/* returns the substitution result in a str, input must be 0 term * 0 on no match or malloc error */ str* subst_str(char *input, struct sip_msg* msg, struct subst_expr* se) { str* res; struct replace_lst *lst; struct replace_lst* l; int len; int size; char* p; char* dest; char* end; /* compute the len */ len=strlen(input); end=input+len; lst=subst_run(se, input, msg); if (lst==0){ DBG("subst_str: no match\n"); return 0; } for (l=lst; l; l=l->next) len+=(int)(l->rpl.len)-l->size; res=pkg_malloc(sizeof(str)); if (res==0){ LOG(L_ERR, "ERROR: subst_str: mem. allocation error\n"); goto error; } res->s=pkg_malloc(len+1); /* space for null termination */ res->s[len]=0; if (res->s==0){ LOG(L_ERR, "ERROR: subst_str: mem. allocation error (res->s)\n"); goto error; } res->len=len; /* replace */ dest=res->s; p=input; for(l=lst; l; l=l->next){ size=l->offset+input-p; memcpy(dest, p, size); /* copy till offset */ p+=size + l->size; /* skip l->size bytes */ dest+=size; if (l->rpl.len){ memcpy(dest, l->rpl.s, l->rpl.len); dest+=l->rpl.len; } } memcpy(dest, p, end-p); if(lst) replace_lst_free(lst); return res; error: if (lst) replace_lst_free(lst); if (res){ if (res->s) pkg_free(res->s); pkg_free(res); } return 0; }
/* sed-perl style re: s/regular expression/replacement/flags */ static int subst_body_f(struct sip_msg* msg, char* subst, char* ignored) { struct lump* l; struct replace_lst* lst; struct replace_lst* rpl; char* begin; struct subst_expr* se; int off; int ret; int nmatches; str body; if ( get_body(msg,&body)!=0 || body.len==0) { LM_DBG("message body has zero length\n"); return -1; } se=(struct subst_expr*)subst; begin=body.s; off=begin-msg->buf; ret=-1; if ((lst=subst_run(se, begin, msg, &nmatches))==0) goto error; /* not found */ for (rpl=lst; rpl; rpl=rpl->next){ LM_DBG("%s replacing at offset %d [%.*s] with [%.*s]\n", exports.name, rpl->offset+off, rpl->size, rpl->offset+off+msg->buf, rpl->rpl.len, rpl->rpl.s); if ((l=del_lump(msg, rpl->offset+off, rpl->size, 0))==0) goto error; /* hack to avoid re-copying rpl, possible because both * replace_lst & lumps use pkg_malloc */ if (insert_new_lump_after(l, rpl->rpl.s, rpl->rpl.len, 0)==0){ LM_ERR("%s could not insert new lump\n", exports.name); goto error; } /* hack continued: set rpl.s to 0 so that replace_lst_free will * not free it */ rpl->rpl.s=0; rpl->rpl.len=0; } ret=1; error: LM_DBG("lst was %p\n", lst); if (lst) replace_lst_free(lst); if (nmatches<0) LM_ERR("%s subst_run failed\n", exports.name); return ret; }
/* sed-perl style re: s/regular expression/replacement/flags */ static int subst_f(struct sip_msg* msg, char* subst, char* ignored) { struct lump* l; struct replace_lst* lst; struct replace_lst* rpl; char* begin; struct subst_expr* se; int off; int ret; int nmatches; se=(struct subst_expr*)subst; begin=get_header(msg); /* start after first line to avoid replacing the uri */ off=begin-msg->buf; ret=-1; if ((lst=subst_run(se, begin, msg, &nmatches))==0) goto error; /* not found */ for (rpl=lst; rpl; rpl=rpl->next){ DBG(" %s: subst_f: replacing at offset %d [%.*s] with [%.*s]\n", exports.name, rpl->offset+off, rpl->size, rpl->offset+off+msg->buf, rpl->rpl.len, rpl->rpl.s); if ((l=del_lump(msg, rpl->offset+off, rpl->size, 0))==0) goto error; /* hack to avoid re-copying rpl, possible because both * replace_lst & lumps use pkg_malloc */ if (insert_new_lump_after(l, rpl->rpl.s, rpl->rpl.len, 0)==0){ LOG(L_ERR, "ERROR: %s: subst_f: could not insert new lump\n", exports.name); goto error; } /* hack continued: set rpl.s to 0 so that replace_lst_free will * not free it */ rpl->rpl.s=0; rpl->rpl.len=0; } ret=1; error: DBG("subst_f: lst was %p\n", lst); if (lst) replace_lst_free(lst); if (nmatches<0) LOG(L_ERR, "ERROR: %s: subst_run failed\n", exports.name); return ret; }
/* WARNING: input must be 0 terminated! */ struct replace_lst* subst_run(struct subst_expr* se, char* input, struct sip_msg* msg) { struct replace_lst *head; struct replace_lst **crt; char *p; int r; regmatch_t* pmatch; int nmatch; int eflags; /* init */ head=0; crt=&head; p=input; nmatch=se->max_pmatch+1; /* no of () referenced + 1 for the whole string: pmatch[0] */ pmatch=pkg_malloc(nmatch*sizeof(regmatch_t)); if (pmatch==0){ LOG(L_ERR, "ERROR: subst_run_ out of mem. (pmatch)\n"); goto error; } eflags=0; do{ r=regexec(se->re, p, nmatch, pmatch, eflags); DBG("subst_run: running. r=%d\n", r); /* subst */ if (r==0){ /* != REG_NOMATCH */ /* change eflags, not to match any more at string start */ eflags|=REG_NOTBOL; *crt=pkg_malloc(sizeof(struct replace_lst)); if (*crt==0){ LOG(L_ERR, "ERROR: subst_run: out of mem (crt)\n"); goto error; } memset(*crt, 0, sizeof(struct replace_lst)); if (pmatch[0].rm_so==-1){ LOG(L_ERR, "ERROR: subst_run: unknown offset?\n"); goto error; } (*crt)->offset=pmatch[0].rm_so+(int)(p-input); (*crt)->size=pmatch[0].rm_eo-pmatch[0].rm_so; DBG("subst_run: matched (%d, %d): [%.*s]\n", (*crt)->offset, (*crt)->size, (*crt)->size, input+(*crt)->offset); /* create subst. string */ /* construct the string from replace[] */ if (replace_build(p, nmatch, pmatch, se, msg, &((*crt)->rpl))<0){ goto error; } crt=&((*crt)->next); p+=pmatch[0].rm_eo; } }while((r==0) && se->replace_all); pkg_free(pmatch); return head; error: if (head) replace_lst_free(head); if (pmatch) pkg_free(pmatch); return 0; }
/*! \brief run substitutions * \return 0 if no match or error, or subst result; if count!=0 * it will be set to 0 (no match), the number of matches * or -1 (error). * \note WARNING: input must be 0 terminated! */ struct replace_lst* subst_run(struct subst_expr* se, const char* input, struct sip_msg* msg, int* count) { struct replace_lst *head; struct replace_lst **crt; const char *p; int r; regmatch_t* pmatch; int nmatch; int eflags; int cnt; /* init */ head=0; cnt=0; crt=&head; p=input; nmatch=se->max_pmatch+1; /* no of () referenced + 1 for the whole string: pmatch[0] */ pmatch=pkg_malloc(nmatch*sizeof(regmatch_t)); if (pmatch==0){ LM_ERR("out of pkg mem. (pmatch)\n"); goto error; } eflags=0; do{ r=regexec(se->re, p, nmatch, pmatch, eflags); LM_DBG("running. r=%d\n", r); /* subst */ if (r==0){ /* != REG_NOMATCH */ /* some checks */ if (pmatch[0].rm_so==-1){ LM_ERR("unknown offset?\n"); goto error; } if (pmatch[0].rm_so==pmatch[0].rm_eo){ LM_ERR("matched string is empty... invalid regexp?\n"); goto error; } *crt=pkg_malloc(sizeof(struct replace_lst)); if (*crt==0){ LM_ERR("out of pkg mem (crt)\n"); goto error; } memset(*crt, 0, sizeof(struct replace_lst)); (*crt)->offset=pmatch[0].rm_so+(int)(p-input); (*crt)->size=pmatch[0].rm_eo-pmatch[0].rm_so; LM_DBG("matched (%d, %d): [%.*s]\n", (*crt)->offset, (*crt)->size, (*crt)->size, input+(*crt)->offset); /* create subst. string */ /* construct the string from replace[] */ if (replace_build(p, nmatch, pmatch, se, msg, &((*crt)->rpl))<0){ goto error; } crt=&((*crt)->next); p+=pmatch[0].rm_eo; /* is it still a string start? */ if (*(p-1)=='\n' || *(p-1)=='\r') eflags&=~REG_NOTBOL; else eflags|=REG_NOTBOL; cnt++; } }while((r==0) && se->replace_all); pkg_free(pmatch); if (count)*count=cnt; return head; error: if (head) replace_lst_free(head); if (pmatch) pkg_free(pmatch); if (count) *count=-1; return 0; }