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
00032
00033
00034
00035
00036
00037
00038
00039 #include "dprint.h"
00040 #include "mem/mem.h"
00041 #include "re.h"
00042
00043 #include <string.h>
00044
00045
00046
00047 void subst_expr_free(struct subst_expr* se)
00048 {
00049 if (se->replacement.s) pkg_free(se->replacement.s);
00050 if (se->re) { regfree(se->re); pkg_free(se->re); };
00051 pkg_free(se);
00052 }
00053
00054
00055
00056
00057 void replace_lst_free(struct replace_lst* l)
00058 {
00059 struct replace_lst* t;
00060
00061 while (l){
00062 t=l;
00063 l=l->next;
00064 if (t->rpl.s) pkg_free(t->rpl.s);
00065 pkg_free(t);
00066 }
00067 }
00068
00069 #define MAX_REPLACE_WITH 100
00070 int parse_repl(struct replace_with * rw, char ** begin,
00071 char * end, int *max_token_nb, int with_sep)
00072 {
00073
00074 char* p0;
00075 char * repl;
00076 str s;
00077 int token_nb;
00078 int escape;
00079 int max_pmatch;
00080 char *p, c;
00081
00082
00083 p = *begin;
00084 c = *p;
00085 if(with_sep)
00086 p++;
00087 repl= p;
00088 token_nb=0;
00089 max_pmatch=0;
00090 escape=0;
00091 for(;p<end; p++){
00092 if (escape){
00093 escape=0;
00094 switch (*p){
00095
00096 case '\\':
00097 rw[token_nb].size=2;
00098 rw[token_nb].offset=(p-1)-repl;
00099 rw[token_nb].type=REPLACE_CHAR;
00100 rw[token_nb].u.c='\\';
00101 break;
00102 case 'n':
00103 rw[token_nb].size=2;
00104 rw[token_nb].offset=(p-1)-repl;
00105 rw[token_nb].type=REPLACE_CHAR;
00106 rw[token_nb].u.c='\n';
00107 break;
00108 case 'r':
00109 rw[token_nb].size=2;
00110 rw[token_nb].offset=(p-1)-repl;
00111 rw[token_nb].type=REPLACE_CHAR;
00112 rw[token_nb].u.c='\r';
00113 break;
00114 case 't':
00115 rw[token_nb].size=2;
00116 rw[token_nb].offset=(p-1)-repl;
00117 rw[token_nb].type=REPLACE_CHAR;
00118 rw[token_nb].u.c='\t';
00119 break;
00120 case PV_MARKER:
00121 rw[token_nb].size=2;
00122 rw[token_nb].offset=(p-1)-repl;
00123 rw[token_nb].type=REPLACE_CHAR;
00124 rw[token_nb].u.c=PV_MARKER;
00125 break;
00126
00127 case 'u':
00128 rw[token_nb].size=2;
00129 rw[token_nb].offset=(p-1)-repl;
00130 rw[token_nb].type=REPLACE_URI;
00131 break;
00132
00133 case '0':
00134 case '1':
00135 case '2':
00136 case '3':
00137 case '4':
00138 case '5':
00139 case '6':
00140 case '7':
00141 case '8':
00142 case '9':
00143 rw[token_nb].size=2;
00144 rw[token_nb].offset=(p-1)-repl;
00145 rw[token_nb].type=REPLACE_NMATCH;
00146 rw[token_nb].u.nmatch=(*p)-'0';
00147
00148 if (max_pmatch<rw[token_nb].u.nmatch)
00149 max_pmatch=rw[token_nb].u.nmatch;
00150 break;
00151 default:
00152 if (*p!=c){
00153 LM_WARN("\\%c unknown escape in %s\n", *p, *begin);
00154 }
00155 rw[token_nb].size=2;
00156 rw[token_nb].offset=(p-1)-repl;
00157 rw[token_nb].type=REPLACE_CHAR;
00158 rw[token_nb].u.c=*p;
00159 break;
00160 }
00161
00162 token_nb++;
00163
00164 if (token_nb>=MAX_REPLACE_WITH){
00165 LM_ERR("too many escapes in the replace part %s\n", *begin);
00166 goto error;
00167 }
00168 }else if (*p=='\\') {
00169 escape=1;
00170 }else if (*p==PV_MARKER) {
00171 s.s = p;
00172 s.len = end - s.s;
00173 p0 = pv_parse_spec(&s, &rw[token_nb].u.spec);
00174 if(p0==NULL)
00175 {
00176 LM_ERR("bad specifier in replace part %s\n", *begin);
00177 goto error;
00178 }
00179 rw[token_nb].size=p0-p;
00180 rw[token_nb].offset=p-repl;
00181 rw[token_nb].type=REPLACE_SPEC;
00182 token_nb++;
00183 p=p0-1;
00184 }else if (*p==c && with_sep){
00185 goto found_repl;
00186 }
00187 }
00188 if(with_sep){
00189
00190 LM_ERR("missing separator: %s\n", *begin);
00191 goto error;
00192 }
00193
00194 found_repl:
00195
00196 *max_token_nb = max_pmatch;
00197 *begin = p;
00198 return token_nb;
00199
00200 error:
00201 return -1;
00202 }
00203
00204
00205
00206
00207 struct subst_expr* subst_parser(str* subst)
00208 {
00209 char c;
00210 char* end;
00211 char* p;
00212 char* re;
00213 char* re_end;
00214 char* repl;
00215 char* repl_end;
00216 struct replace_with rw[MAX_REPLACE_WITH];
00217 int rw_no;
00218
00219 int cflags;
00220 int replace_all;
00221 struct subst_expr* se;
00222 regex_t* regex;
00223 int max_pmatch;
00224 int r;
00225
00226
00227 se=0;
00228 regex=0;
00229 cflags=REG_EXTENDED | REG_NEWLINE;
00230 replace_all=0;
00231 if (subst->len<3){
00232 LM_ERR("expression is too short: %.*s\n", subst->len, subst->s);
00233 goto error;
00234 }
00235
00236 p=subst->s;
00237 end=subst->s+subst->len;
00238
00239 c=*p;
00240 if (c=='\\'){
00241 LM_ERR("invalid separator char <%c> in %.*s\n", c,
00242 subst->len, subst->s);
00243 goto error;
00244 }
00245 p++;
00246
00247
00248 re=p;
00249 for (;p<end;p++){
00250
00251 if ((*p==c) && (*(p-1)!='\\')) goto found_re;
00252 }
00253 LM_ERR("no separator found: %.*s\n", subst->len, subst->s);
00254 goto error;
00255 found_re:
00256 re_end=p;
00257 if(end< (p+2) ){
00258 LM_ERR("string too short\n");
00259 goto error;
00260 }
00261 repl=p+1;
00262 if((rw_no = parse_repl(rw, &p, end, &max_pmatch, WITH_SEP))< 0)
00263 goto error;
00264
00265
00266 repl_end=p;
00267 p++;
00268
00269 for(;p<end; p++){
00270 switch(*p){
00271 case 'i':
00272 cflags|=REG_ICASE;
00273 break;
00274 case 's':
00275 cflags&=(~REG_NEWLINE);
00276 break;
00277 case 'g':
00278 replace_all=1;
00279 break;
00280 default:
00281 LM_ERR("unknown flag %c in %.*s\n", *p, subst->len, subst->s);
00282 goto error;
00283 }
00284 }
00285
00286
00287 if ((regex=pkg_malloc(sizeof(regex_t)))==0){
00288 LM_ERR("out of pkg memory (re)\n");
00289 goto error;
00290 }
00291 c=*re_end;
00292 *re_end=0;
00293 if (regcomp(regex, re, cflags)!=0){
00294 pkg_free(regex);
00295 *re_end=c;
00296 LM_ERR("bad regular expression %.*s in %.*s\n",
00297 (int)(re_end-re), re, subst->len, subst->s);
00298 goto error;
00299 }
00300 *re_end=c;
00301
00302 se=pkg_malloc(sizeof(struct subst_expr)+
00303 ((rw_no)?(rw_no-1)*sizeof(struct replace_with):0));
00304
00305 if (se==0){
00306 LM_ERR("out of pkg memory (subst_expr)\n");
00307 goto error;
00308 }
00309 memset((void*)se, 0, sizeof(struct subst_expr));
00310
00311 se->replacement.len=repl_end-repl;
00312 if ((se->replacement.s=pkg_malloc(se->replacement.len))==0){
00313 LM_ERR("out of pkg memory (replacement)\n");
00314 goto error;
00315 }
00316
00317
00318 memcpy(se->replacement.s, repl, se->replacement.len);
00319 se->re=regex;
00320 se->replace_all=replace_all;
00321 se->n_escapes=rw_no;
00322 se->max_pmatch=max_pmatch;
00323 for (r=0; r<rw_no; r++) se->replace[r]=rw[r];
00324 LM_DBG("ok, se is %p\n", se);
00325 return se;
00326
00327 error:
00328 if (se) { subst_expr_free(se); regex=0; }
00329 if (regex) { regfree (regex); pkg_free(regex); }
00330 return 0;
00331 }
00332
00333
00334 #if 0
00335 static int replace_len(const char* match, int nmatch, regmatch_t* pmatch,
00336 struct subst_expr* se, struct sip_msg* msg)
00337 {
00338 int r;
00339 int len;
00340 str* uri;
00341
00342 len=se->replacement.len;
00343 for (r=0; r<se->n_escapes; r++){
00344 switch(se->replace[r].type){
00345 case REPLACE_NMATCH:
00346 len-=se->replace[r].size;
00347 if ((se->replace[r].u.nmatch<nmatch)&&(
00348 pmatch[se->replace[r].u.nmatch].rm_so!=-1)){
00349
00350 len+=pmatch[se->replace[r].u.nmatch].rm_eo-
00351 pmatch[se->replace[r].u.nmatch].rm_so;
00352 };
00353 break;
00354 case REPLACE_CHAR:
00355 len-=(se->replace[r].size-1);
00356 break;
00357 case REPLACE_URI:
00358 len-=se->replace[r].size;
00359 if (msg->first_line.type!=SIP_REQUEST){
00360 LM_CRIT("uri substitution on a reply\n");
00361 break;
00362 }
00363 uri= (msg->new_uri.s)?(&msg->new_uri):
00364 (&msg->first_line.u.request.uri);
00365 len+=uri->len;
00366 break;
00367 default:
00368 LM_CRIT("unknown type %d\n", se->replace[r].type);
00369
00370 }
00371 }
00372 return len;
00373 }
00374
00375 #endif
00376
00377
00378
00379
00380 static int replace_build(const char* match, int nmatch, regmatch_t* pmatch,
00381 struct subst_expr* se, struct sip_msg* msg, str* rpl)
00382 {
00383 int r;
00384 str* uri;
00385 pv_value_t sv;
00386 char* p;
00387 char* dest;
00388 char* end;
00389 int size;
00390 #define REPLACE_BUFFER_SIZE 1024
00391 static char rbuf[REPLACE_BUFFER_SIZE];
00392
00393 #if 0
00394
00395 rpl->len=replace_len(match, nmatch, pmatch, se, msg);
00396 if (rpl->len==0){
00397 rpl->s=0;
00398 return 0;
00399 }
00400 rpl->s=pkg_malloc(rpl->len);
00401 if (rpl->s==0){
00402 LM_ERR("out of pkg mem (rpl)\n");
00403 goto error;
00404 }
00405 #endif
00406
00407 p=se->replacement.s;
00408 end=p+se->replacement.len;
00409 dest=rbuf;
00410 for (r=0; r<se->n_escapes; r++){
00411
00412 size=se->replacement.s+se->replace[r].offset-p;
00413 if(dest-rbuf+size>=REPLACE_BUFFER_SIZE-1){
00414 LM_ERR("overflow\n");
00415 goto error;
00416 }
00417 memcpy(dest, p, size);
00418 p+=size+se->replace[r].size;
00419 dest+=size;
00420 switch(se->replace[r].type){
00421 case REPLACE_NMATCH:
00422 if ((se->replace[r].u.nmatch<nmatch)&&(
00423 pmatch[se->replace[r].u.nmatch].rm_so!=-1)){
00424
00425 size=pmatch[se->replace[r].u.nmatch].rm_eo-
00426 pmatch[se->replace[r].u.nmatch].rm_so;
00427 if(dest-rbuf+size>=REPLACE_BUFFER_SIZE-1){
00428 LM_ERR("overflow\n");
00429 goto error;
00430 }
00431 memcpy(dest,
00432 match+pmatch[se->replace[r].u.nmatch].rm_so,
00433 size);
00434 dest+=size;
00435 };
00436 break;
00437 case REPLACE_CHAR:
00438 if(dest-rbuf+1>=REPLACE_BUFFER_SIZE-1){
00439 LM_ERR("overflow\n");
00440 goto error;
00441 }
00442 *dest=se->replace[r].u.c;
00443 dest++;
00444 break;
00445 case REPLACE_URI:
00446 if (msg->first_line.type!=SIP_REQUEST){
00447 LM_CRIT("uri substitution on a reply\n");
00448 break;
00449 }
00450 uri= (msg->new_uri.s)?(&msg->new_uri):
00451 (&msg->first_line.u.request.uri);
00452 if(dest-rbuf+uri->len>=REPLACE_BUFFER_SIZE-1){
00453 LM_ERR("overflow\n");
00454 goto error;
00455 }
00456 memcpy(dest, uri->s, uri->len);
00457 dest+=uri->len;
00458 break;
00459 case REPLACE_SPEC:
00460 if(pv_get_spec_value(msg, &se->replace[r].u.spec, &sv)!=0)
00461 {
00462 LM_CRIT("item substitution returned error\n");
00463 break;
00464 }
00465 if(dest-rbuf+sv.rs.len>=REPLACE_BUFFER_SIZE-1){
00466 LM_ERR("overflow\n");
00467 goto error;
00468 }
00469 memcpy(dest, sv.rs.s, sv.rs.len);
00470 dest+=sv.rs.len;
00471 break;
00472 default:
00473 LM_CRIT("unknown type %d\n", se->replace[r].type);
00474
00475 }
00476 }
00477 memcpy(dest, p, end-p);
00478
00479 rpl->len = (dest-rbuf)+(end-p);
00480 rpl->s=pkg_malloc(rpl->len);
00481 if (rpl->s==0){
00482 LM_ERR("out of pkg mem (rpl)\n");
00483 goto error;
00484 }
00485 memcpy(rpl->s, rbuf, rpl->len);
00486
00487 return 0;
00488 error:
00489 return -1;
00490 }
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 struct replace_lst* subst_run(struct subst_expr* se, const char* input,
00501 struct sip_msg* msg, int* count)
00502 {
00503 struct replace_lst *head;
00504 struct replace_lst **crt;
00505 const char *p;
00506 int r;
00507 regmatch_t* pmatch;
00508 int nmatch;
00509 int eflags;
00510 int cnt;
00511
00512
00513
00514 head=0;
00515 cnt=0;
00516 crt=&head;
00517 p=input;
00518 nmatch=se->max_pmatch+1;
00519
00520 pmatch=pkg_malloc(nmatch*sizeof(regmatch_t));
00521 if (pmatch==0){
00522 LM_ERR("out of pkg mem. (pmatch)\n");
00523 goto error;
00524 }
00525 eflags=0;
00526 do{
00527 r=regexec(se->re, p, nmatch, pmatch, eflags);
00528 LM_DBG("running. r=%d\n", r);
00529
00530 if (r==0){
00531
00532 if (pmatch[0].rm_so==-1){
00533 LM_ERR("unknown offset?\n");
00534 goto error;
00535 }
00536 if (pmatch[0].rm_so==pmatch[0].rm_eo){
00537 LM_ERR("matched string is empty... invalid regexp?\n");
00538 goto error;
00539 }
00540 *crt=pkg_malloc(sizeof(struct replace_lst));
00541 if (*crt==0){
00542 LM_ERR("out of pkg mem (crt)\n");
00543 goto error;
00544 }
00545 memset(*crt, 0, sizeof(struct replace_lst));
00546 (*crt)->offset=pmatch[0].rm_so+(int)(p-input);
00547 (*crt)->size=pmatch[0].rm_eo-pmatch[0].rm_so;
00548 LM_DBG("matched (%d, %d): [%.*s]\n",
00549 (*crt)->offset, (*crt)->size,
00550 (*crt)->size, input+(*crt)->offset);
00551
00552
00553 if (replace_build(p, nmatch, pmatch, se, msg, &((*crt)->rpl))<0){
00554 goto error;
00555 }
00556 crt=&((*crt)->next);
00557 p+=pmatch[0].rm_eo;
00558
00559 if (*(p-1)=='\n' || *(p-1)=='\r')
00560 eflags&=~REG_NOTBOL;
00561 else
00562 eflags|=REG_NOTBOL;
00563 cnt++;
00564 }
00565 }while((r==0) && se->replace_all);
00566 pkg_free(pmatch);
00567 if (count)*count=cnt;
00568 return head;
00569 error:
00570 if (head) replace_lst_free(head);
00571 if (pmatch) pkg_free(pmatch);
00572 if (count) *count=-1;
00573 return 0;
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583 str* subst_str(const char *input, struct sip_msg* msg, struct subst_expr* se,
00584 int* count)
00585 {
00586 str* res;
00587 struct replace_lst *lst;
00588 struct replace_lst* l;
00589 int len;
00590 int size;
00591 const char* p;
00592 char* dest;
00593 const char* end;
00594
00595
00596
00597 len=strlen(input);
00598 end=input+len;
00599 lst=subst_run(se, input, msg, count);
00600 if (lst==0){
00601 LM_DBG("no match\n");
00602 return 0;
00603 }
00604 for (l=lst; l; l=l->next)
00605 len+=(int)(l->rpl.len)-l->size;
00606 res=pkg_malloc(sizeof(str));
00607 if (res==0){
00608 LM_ERR("out of pkg memory\n");
00609 goto error;
00610 }
00611 res->s=pkg_malloc(len+1);
00612 if (res->s==0){
00613 LM_ERR("out of pkg memory (res->s)\n");
00614 goto error;
00615 }
00616 res->s[len]=0;
00617 res->len=len;
00618
00619
00620 dest=res->s;
00621 p=input;
00622 for(l=lst; l; l=l->next){
00623 size=l->offset+input-p;
00624 memcpy(dest, p, size);
00625 p+=size + l->size;
00626 dest+=size;
00627 if (l->rpl.len){
00628 memcpy(dest, l->rpl.s, l->rpl.len);
00629 dest+=l->rpl.len;
00630 }
00631 }
00632 memcpy(dest, p, end-p);
00633 if(lst) replace_lst_free(lst);
00634 return res;
00635 error:
00636 if (lst) replace_lst_free(lst);
00637 if (res){
00638 if (res->s) pkg_free(res->s);
00639 pkg_free(res);
00640 }
00641 if (count) *count=-1;
00642 return 0;
00643 }