1 Star 0 Fork 0

souhoiryo/opensips

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
transformations.c 68.05 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051
/*
* $Id$
*
* Copyright (C) 2007 voice-system.ro
*
* This file is part of opensips, a free SIP server.
*
* opensips 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
*
* opensips 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/*! \file
* \brief Support for transformations
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include "dprint.h"
#include "mem/mem.h"
#include "ut.h"
#include "trim.h"
#include "dset.h"
#include "usr_avp.h"
#include "errinfo.h"
#include "resolve.h"
#include "ip_addr.h"
#include "parser/parse_param.h"
#include "parser/parse_uri.h"
#include "parser/parse_via.h"
#include "parser/parse_to.h"
#include "parser/sdp/sdp_helpr_funcs.h"
#include "strcommon.h"
#include "transformations.h"
#include "re.h"
#define TR_BUFFER_SIZE 65536
/* structure for CSV transformation */
typedef struct csv {
str body;
struct csv* next;
} csv_t;
static char _tr_buffer[TR_BUFFER_SIZE];
int run_transformations(struct sip_msg *msg, trans_t *tr, pv_value_t *val)
{
trans_t *it;
int ret = 0;
if(tr==NULL || val==NULL){
LM_DBG("null pointer\n");
return -1;
}
it = tr;
while(it)
{
ret = (*it->trf)(msg, it->params, it->subtype, val);
if(ret!=0)
return ret;
it = it->next;
}
return 0;
}
int tr_eval_string(struct sip_msg *msg, tr_param_t *tp, int subtype,
pv_value_t *val)
{
int i, j;
char *p, *s;
str st;
pv_value_t v;
if(val==NULL || val->flags&PV_VAL_NULL)
return -1;
switch(subtype)
{
case TR_S_LEN:
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
val->ri = val->rs.len;
val->rs.s = int2str(val->ri, &val->rs.len);
break;
case TR_S_INT:
if(!(val->flags&PV_VAL_INT))
{
if(str2sint(&val->rs, &val->ri)!=0)
return -1;
} else {
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
}
val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
break;
case TR_S_MD5:
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
compute_md5(_tr_buffer, val->rs.s, val->rs.len);
_tr_buffer[MD5_LEN] = '\0';
val->flags = PV_VAL_STR;
val->ri = 0;
val->rs.s = _tr_buffer;
val->rs.len = MD5_LEN;
break;
case TR_S_CRC32:
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
unsigned int crc_val;
int length = 10;
crc32_uint(&val->rs,&crc_val);
val->rs.len = length;
val->rs.s = int2str(crc_val,&length);
val->flags = PV_VAL_STR;
break;
case TR_S_ENCODEHEXA:
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
if(val->rs.len>TR_BUFFER_SIZE/2-1)
return -1;
j = 0;
for(i=0; i<val->rs.len; i++)
{
_tr_buffer[j++] = fourbits2char[(unsigned char)val->rs.s[i] >> 4];
_tr_buffer[j++] = fourbits2char[(unsigned char)val->rs.s[i] & 0xf];
}
_tr_buffer[j] = '\0';
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
val->rs.s = _tr_buffer;
val->rs.len = j;
break;
case TR_S_DECODEHEXA:
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
if(val->rs.len>TR_BUFFER_SIZE*2-1)
return -1;
for(i=0; i<val->rs.len/2; i++)
{
if(val->rs.s[2*i]>='0'&&val->rs.s[2*i]<='9')
_tr_buffer[i] = (val->rs.s[2*i]-'0') << 4;
else if(val->rs.s[2*i]>='a'&&val->rs.s[2*i]<='f')
_tr_buffer[i] = (val->rs.s[2*i]-'a'+10) << 4;
else if(val->rs.s[2*i]>='A'&&val->rs.s[2*i]<='F')
_tr_buffer[i] = (val->rs.s[2*i]-'A'+10) << 4;
else return -1;
if(val->rs.s[2*i+1]>='0'&&val->rs.s[2*i+1]<='9')
_tr_buffer[i] += val->rs.s[2*i+1]-'0';
else if(val->rs.s[2*i+1]>='a'&&val->rs.s[2*i+1]<='f')
_tr_buffer[i] += val->rs.s[2*i+1]-'a'+10;
else if(val->rs.s[2*i+1]>='A'&&val->rs.s[2*i+1]<='F')
_tr_buffer[i] += val->rs.s[2*i+1]-'A'+10;
else return -1;
}
_tr_buffer[i] = '\0';
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
val->rs.s = _tr_buffer;
val->rs.len = i;
break;
case TR_S_HEX2DEC:
if(val->flags&PV_VAL_INT)
break; /* already converted */
s = NULL;
if (hexstr2int(val->rs.s, val->rs.len, (unsigned int *)&i) < 0)
return -1;
val->rs.s = int2str(i, &val->rs.len);
val->ri = i;
val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
break;
case TR_S_DEC2HEX:
if(!(val->flags&PV_VAL_INT))
{
if(str2sint(&val->rs, &val->ri)!=0)
return -1;
}
val->rs.len = snprintf(_tr_buffer, TR_BUFFER_SIZE, "%x", val->ri);
if (val->rs.len < 0 || val->rs.len > TR_BUFFER_SIZE)
return -1;
val->ri = 0;
val->rs.s = _tr_buffer;
val->flags = PV_VAL_STR;
break;
case TR_S_ESCAPECOMMON:
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
if(val->rs.len>TR_BUFFER_SIZE/2-1)
return -1;
i = escape_common(_tr_buffer, val->rs.s, val->rs.len);
_tr_buffer[i] = '\0';
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
val->rs.s = _tr_buffer;
val->rs.len = i;
break;
case TR_S_UNESCAPECOMMON:
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
if(val->rs.len>TR_BUFFER_SIZE-1)
return -1;
i = unescape_common(_tr_buffer, val->rs.s, val->rs.len);
_tr_buffer[i] = '\0';
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
val->rs.s = _tr_buffer;
val->rs.len = i;
break;
case TR_S_ESCAPEUSER:
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
if(val->rs.len>TR_BUFFER_SIZE/2-1)
return -1;
st.s = _tr_buffer;
st.len = TR_BUFFER_SIZE;
if (escape_user(&val->rs, &st))
return -1;
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
val->rs = st;
break;
case TR_S_UNESCAPEUSER:
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
if(val->rs.len>TR_BUFFER_SIZE-1)
return -1;
st.s = _tr_buffer;
st.len = TR_BUFFER_SIZE;
if (unescape_user(&val->rs, &st))
return -1;
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
val->rs = st;
break;
case TR_S_ESCAPEPARAM:
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
if(val->rs.len>TR_BUFFER_SIZE/2-1)
return -1;
st.s = _tr_buffer;
st.len = TR_BUFFER_SIZE;
if (escape_param(&val->rs, &st) < 0)
return -1;
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
val->rs = st;
break;
case TR_S_UNESCAPEPARAM:
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
if(val->rs.len>TR_BUFFER_SIZE-1)
return -1;
st.s = _tr_buffer;
st.len = TR_BUFFER_SIZE;
if (unescape_param(&val->rs, &st) < 0)
return -1;
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
val->rs = st;
break;
case TR_S_SUBSTR:
if(tp==NULL || tp->next==NULL)
{
LM_ERR("substr invalid parameters\n");
return -1;
}
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
if(tp->type==TR_PARAM_NUMBER)
{
i = tp->v.n;
} else {
if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
|| (!(v.flags&PV_VAL_INT)))
{
LM_ERR("substr cannot get p1\n");
return -1;
}
i = v.ri;
}
if(tp->next->type==TR_PARAM_NUMBER)
{
j = tp->next->v.n;
} else {
if(pv_get_spec_value(msg, (pv_spec_p)tp->next->v.data, &v)!=0
|| (!(v.flags&PV_VAL_INT)))
{
LM_ERR("substr cannot get p2\n");
return -1;
}
j = v.ri;
}
LM_DBG("i=%d j=%d\n", i, j);
if(j<0)
{
LM_ERR("substr negative offset\n");
return -1;
}
val->flags = PV_VAL_STR;
val->ri = 0;
if(i>=0)
{
if(i>=val->rs.len)
{
LM_ERR("substr out of range\n");
return -1;
}
if(i+j>=val->rs.len) j=0;
if(j==0)
{ /* to end */
val->rs.s += i;
val->rs.len -= i;
break;
}
val->rs.s += i;
val->rs.len = j;
break;
}
i = -i;
if(i>val->rs.len)
{
LM_ERR("substr out of range\n");
return -1;
}
if(i<j) j=0;
if(j==0)
{ /* to end */
val->rs.s += val->rs.len-i;
val->rs.len = i;
break;
}
val->rs.s += val->rs.len-i;
val->rs.len = j;
break;
case TR_S_SELECT:
if(tp==NULL || tp->next==NULL)
{
LM_ERR("select invalid parameters\n");
return -1;
}
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
if(tp->type==TR_PARAM_NUMBER)
{
i = tp->v.n;
} else {
if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
|| (!(v.flags&PV_VAL_INT)))
{
LM_ERR("select cannot get p1\n");
return -1;
}
i = v.ri;
}
val->flags = PV_VAL_STR;
val->ri = 0;
if(i<0)
{
s = val->rs.s+val->rs.len-1;
p = s;
i = -i;
i--;
while(p>=val->rs.s)
{
if(*p==tp->next->v.s.s[0])
{
if(i==0)
break;
s = p-1;
i--;
}
p--;
}
if(i==0)
{
val->rs.s = p+1;
val->rs.len = s-p;
} else {
val->rs.s = "";
val->rs.len = 0;
}
} else {
s = val->rs.s;
p = s;
while(p<val->rs.s+val->rs.len)
{
if(*p==tp->next->v.s.s[0])
{
if(i==0)
break;
s = p + 1;
i--;
}
p++;
}
if(i==0)
{
val->rs.s = s;
val->rs.len = p-s;
} else {
val->rs.s = "";
val->rs.len = 0;
}
}
break;
case TR_S_TOLOWER:
if(!(val->flags&PV_VAL_STR))
{
val->rs.s = int2str(val->ri, &val->rs.len);
val->flags |= PV_VAL_STR;
break;
}
if(val->rs.len>TR_BUFFER_SIZE-1)
return -1;
st.s = _tr_buffer;
st.len = val->rs.len;
for (i=0; i<st.len; i++)
st.s[i]=(val->rs.s[i]>='A' && val->rs.s[i]<='Z')
?('a' + val->rs.s[i] -'A'):val->rs.s[i];
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
val->rs = st;
break;
case TR_S_TOUPPER:
if(!(val->flags&PV_VAL_STR))
{
val->rs.s = int2str(val->ri, &val->rs.len);
val->flags |= PV_VAL_STR;
break;
}
if(val->rs.len>TR_BUFFER_SIZE-1)
return -1;
st.s = _tr_buffer;
st.len = val->rs.len;
for (i=0; i<st.len; i++)
st.s[i]=(val->rs.s[i]>='a' && val->rs.s[i]<='z')
?('A' + val->rs.s[i] -'a'):val->rs.s[i];
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
val->rs = st;
break;
case TR_S_INDEX:
case TR_S_RINDEX:
/* Ensure it is in string format */
if(!(val->flags&PV_VAL_STR))
{
val->rs.s = int2str(val->ri, &val->rs.len);
val->flags |= PV_VAL_STR;
}
/* Needle to look for in haystack */
if(tp->type==TR_PARAM_STRING)
{
st = tp->v.s;
} else {
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("index/rindex cannot get p1\n");
return -1;
}
st = v.rs;
}
/* User supplied starting position */
if (tp->next != NULL) {
if(tp->next->type==TR_PARAM_NUMBER)
{
i = tp->next->v.n;
} else {
if(pv_get_spec_value(msg, (pv_spec_p)tp->next->v.data, &v)!=0
|| (!(v.flags&PV_VAL_INT)))
{
LM_ERR("index/rindex cannot get p2\n");
return -1;
}
i = v.ri;
}
} else {
/* Default start positions: 0 for index, end of str for rindex */
i = (subtype == TR_S_INDEX ? 0 : (val->rs.len - 1));
}
/* If start is negative base it off end of string
e.g -2 on 10 char str start of 8. */
if (i < 0 ){
if ( val->rs.len > 0 ) {
/* Support wrapping on negative index
e.g -2 and -12 index are same on strlen of 10 */
i = ( (i * -1) % val->rs.len );
/* No remainder means we start at 0
otherwise take remainder off the end */
if ( i > 0) {
i = (val->rs.len - i);
}
} else {
/* Case of searching through an empty string is caught later */
i = 0;
}
}
/* Index */
if (subtype == TR_S_INDEX) {
/* If start index is beyond end of string or
Needle is bigger than haystack return -1 */
if ( i >= val->rs.len || st.len > (val->rs.len - i)) {
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
val->ri = -1;
val->rs.s = int2str(val->ri, &val->rs.len);
break;
}
/* Iterate through string starting at index
After j there are no longer enough characters left to match the needle */
j = (val->rs.len - st.len);
while (i <= j) {
if (val->rs.s[i] == st.s[0]) {
/* First character matches, do a full comparison
shortcut for single character lookups */
if (st.len == 1 || strncmp(val->rs.s + i, st.s, st.len) == 0) {
/* Bingo, found it */
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
val->ri = i;
val->rs.s = int2str(val->ri, &val->rs.len);
return 0;
}
}
i++;
}
/* Rindex */
} else {
/* Needle bigger than haystack */
if ( st.len > val->rs.len ) {
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
val->ri = -1;
val->rs.s = int2str(val->ri, &val->rs.len);
break;
}
/* Incase of RINDEX clamp index to end of string */
if (i >= val->rs.len) {
i = (val->rs.len - 1);
}
/* Start position does not leave enough characters to match needle, jump ahead */
if ( st.len > (val->rs.len - i) ) {
/* Minimum start position allowing for matches */
i = (val->rs.len - st.len);
}
/* Iterate through string starting at index and going backwards */
while (i >= 0) {
if (val->rs.s[i] == st.s[0]) {
/* First character matches, do a full comparison
shortcut for single character lookups */
if (st.len == 1 || strncmp(val->rs.s + i, st.s, st.len) == 0) {
/* Bingo, found it */
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
val->ri = i;
val->rs.s = int2str(val->ri, &val->rs.len);
return 0;
}
}
i--;
}
}
/* Not found */
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
val->ri = -1;
val->rs.s = int2str(val->ri, &val->rs.len);
break;
default:
LM_ERR("unknown subtype %d\n",
subtype);
return -1;
}
return 0;
}
static str _tr_empty = { "", 0 };
static str _tr_uri = {0, 0};
static struct sip_uri _tr_parsed_uri;
static param_t* _tr_uri_params = NULL;
int tr_eval_uri(struct sip_msg *msg, tr_param_t *tp, int subtype,
pv_value_t *val)
{
pv_value_t v;
str sv;
param_hooks_t phooks;
param_t *pit=NULL;
if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
return -1;
if(_tr_uri.len==0 || _tr_uri.len!=val->rs.len ||
strncmp(_tr_uri.s, val->rs.s, val->rs.len)!=0)
{
if(val->rs.len>_tr_uri.len)
{
if(_tr_uri.s) pkg_free(_tr_uri.s);
_tr_uri.s = (char*)pkg_malloc((val->rs.len+1)*sizeof(char));
if(_tr_uri.s==NULL)
{
LM_ERR("no more private memory\n");
if(_tr_uri_params != NULL)
{
free_params(_tr_uri_params);
_tr_uri_params = 0;
}
memset(&_tr_uri, 0, sizeof(str));
memset(&_tr_parsed_uri, 0, sizeof(struct sip_uri));
return -1;
}
}
_tr_uri.len = val->rs.len;
memcpy(_tr_uri.s, val->rs.s, val->rs.len);
_tr_uri.s[_tr_uri.len] = '\0';
/* reset old values */
memset(&_tr_parsed_uri, 0, sizeof(struct sip_uri));
if(_tr_uri_params != NULL)
{
free_params(_tr_uri_params);
_tr_uri_params = 0;
}
/* parse uri -- params only when requested */
if(parse_uri(_tr_uri.s, _tr_uri.len, &_tr_parsed_uri)!=0)
{
LM_ERR("invalid uri [%.*s]\n", val->rs.len,
val->rs.s);
if(_tr_uri_params != NULL)
{
free_params(_tr_uri_params);
_tr_uri_params = 0;
}
pkg_free(_tr_uri.s);
memset(&_tr_uri, 0, sizeof(str));
memset(&_tr_parsed_uri, 0, sizeof(struct sip_uri));
return -1;
}
}
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
switch(subtype)
{
case TR_URI_USER:
val->rs = (_tr_parsed_uri.user.s)?_tr_parsed_uri.user:_tr_empty;
break;
case TR_URI_HOST:
val->rs = (_tr_parsed_uri.host.s)?_tr_parsed_uri.host:_tr_empty;
break;
case TR_URI_PASSWD:
val->rs = (_tr_parsed_uri.passwd.s)?_tr_parsed_uri.passwd:_tr_empty;
break;
case TR_URI_PORT:
val->flags |= PV_TYPE_INT|PV_VAL_INT;
val->rs = (_tr_parsed_uri.port.s)?_tr_parsed_uri.port:_tr_empty;
val->ri = _tr_parsed_uri.port_no;
break;
case TR_URI_PARAMS:
val->rs = (_tr_parsed_uri.params.s)?_tr_parsed_uri.params:_tr_empty;
break;
case TR_URI_PARAM:
if(tp==NULL)
{
LM_ERR("param invalid parameters\n");
return -1;
}
if(_tr_parsed_uri.params.len<=0)
{
val->rs = _tr_empty;
val->flags = PV_VAL_STR;
val->ri = 0;
break;
}
if(_tr_uri_params == NULL)
{
sv = _tr_parsed_uri.params;
if (parse_params(&sv, CLASS_ANY, &phooks, &_tr_uri_params)<0)
return -1;
}
if(tp->type==TR_PARAM_STRING)
{
sv = tp->v.s;
} else {
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("param cannot get p1\n");
return -1;
}
sv = v.rs;
}
for (pit = _tr_uri_params; pit; pit=pit->next)
{
if (pit->name.len==sv.len
&& strncasecmp(pit->name.s, sv.s, sv.len)==0)
{
val->rs = pit->body;
goto done;
}
}
val->rs = _tr_empty;
break;
case TR_URI_HEADERS:
val->rs = (_tr_parsed_uri.headers.s)?_tr_parsed_uri.headers:
_tr_empty;
break;
case TR_URI_TRANSPORT:
val->rs = (_tr_parsed_uri.transport_val.s)?
_tr_parsed_uri.transport_val:_tr_empty;
break;
case TR_URI_TTL:
val->rs = (_tr_parsed_uri.ttl_val.s)?
_tr_parsed_uri.ttl_val:_tr_empty;
break;
case TR_URI_UPARAM:
val->rs = (_tr_parsed_uri.user_param_val.s)?
_tr_parsed_uri.user_param_val:_tr_empty;
break;
case TR_URI_MADDR:
val->rs = (_tr_parsed_uri.maddr_val.s)?
_tr_parsed_uri.maddr_val:_tr_empty;
break;
case TR_URI_METHOD:
val->rs = (_tr_parsed_uri.method_val.s)?
_tr_parsed_uri.method_val:_tr_empty;
break;
case TR_URI_LR:
val->rs = (_tr_parsed_uri.lr_val.s)?
_tr_parsed_uri.lr_val:_tr_empty;
break;
case TR_URI_R2:
val->rs = (_tr_parsed_uri.r2_val.s)?
_tr_parsed_uri.r2_val:_tr_empty;
break;
default:
LM_ERR("unknown subtype %d\n",
subtype);
return -1;
}
done:
return 0;
}
/* last via string */
static str _tr_via = {0, 0};
/* the actual len of the allocated buffer (to hold the via) */
static int _tr_via_buf_len = 0;
/* holder for the parsed via */
static struct via_body *_tr_parsed_via = 0;
int tr_eval_via(struct sip_msg *msg, tr_param_t *tp, int subtype,
pv_value_t *val)
{
pv_value_t v;
str sv;
struct via_param *pit;
// WATCHOUT: need at least 2 chars so \r\n check wont segfault
if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=2)
return -1;
if(_tr_via_buf_len==0 || _tr_via.len!=val->rs.len ||
strncmp(_tr_via.s, val->rs.s, val->rs.len)!=0
|| _tr_parsed_via==0)
{
if (val->rs.len+4 > _tr_via_buf_len)
{
if(_tr_via.s) pkg_free(_tr_via.s);
_tr_via.s = (char*)pkg_malloc((val->rs.len+4)*sizeof(char));
if(_tr_via.s==NULL)
{
_tr_via_buf_len = 0;
LM_ERR("no more private memory\n");
goto error;
}
_tr_via_buf_len = val->rs.len+4;
}
_tr_via.len = val->rs.len;
memcpy(_tr_via.s, val->rs.s, val->rs.len);
// $hdr PV strips off the terminating CRLR
// parse_via wants to parse a full message (including
// multiple vias), not just a header line. Fake this
_tr_via.s[_tr_via.len+0] = '\r';
_tr_via.s[_tr_via.len+1] = '\n';
_tr_via.s[_tr_via.len+2] = 'A'; // anything other than V
_tr_via.s[_tr_via.len+3] = '\0';
/* reset old values */
free_via_list(_tr_parsed_via);
if ( (_tr_parsed_via=pkg_malloc(sizeof(struct via_body))) == NULL ) {
LM_ERR("no more private memory\n");
goto error;
}
memset(_tr_parsed_via, 0, sizeof(struct via_body));
parse_via(_tr_via.s, _tr_via.s+_tr_via.len+4, _tr_parsed_via);
if(_tr_parsed_via->error != PARSE_OK) {
LM_ERR("invalid via [%.*s]\n", val->rs.len,
val->rs.s);
goto error;
}
}
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
switch(subtype)
{
case TR_VIA_NAME:
val->rs = (_tr_parsed_via->name.s)?_tr_parsed_via->name:_tr_empty;
break;
case TR_VIA_VERSION:
val->rs = (_tr_parsed_via->version.s)?_tr_parsed_via->version:_tr_empty;
break;
case TR_VIA_TRANSPORT:
val->rs = (_tr_parsed_via->transport.s)?_tr_parsed_via->transport:_tr_empty;
break;
case TR_VIA_HOST:
val->rs = (_tr_parsed_via->host.s)?_tr_parsed_via->host:_tr_empty;
break;
case TR_VIA_PORT:
val->flags |= PV_TYPE_INT|PV_VAL_INT;
val->rs = (_tr_parsed_via->port_str.s)?_tr_parsed_via->port_str:_tr_empty;
val->ri = _tr_parsed_via->port;
break;
case TR_VIA_PARAMS:
val->rs = (_tr_parsed_via->params.s)?_tr_parsed_via->params:_tr_empty;
break;
case TR_VIA_COMMENT:
val->rs = (_tr_parsed_via->comment.s)?_tr_parsed_via->comment:_tr_empty;
break;
case TR_VIA_PARAM: // param by name
if(tp==NULL)
{
LM_ERR("param invalid parameters\n");
return -1;
}
if(_tr_parsed_via->params.len<=0)
{
val->rs = _tr_empty;
val->flags = PV_VAL_STR;
val->ri = 0;
break;
}
if(tp->type==TR_PARAM_STRING)
{
sv = tp->v.s;
} else {
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("param cannot get p1\n");
return -1;
}
sv = v.rs;
}
for (pit = _tr_parsed_via->param_lst; pit; pit=pit->next)
{
if (pit->name.len==sv.len
&& strncasecmp(pit->name.s, sv.s, sv.len)==0)
{
val->rs = pit->value;
goto done;
}
}
val->rs = _tr_empty;
break;
case TR_VIA_BRANCH:
val->rs = (_tr_parsed_via->branch&&_tr_parsed_via->branch->value.s)?_tr_parsed_via->branch->value: _tr_empty;
break;
case TR_VIA_RECEIVED:
val->rs = (_tr_parsed_via->received&&_tr_parsed_via->received->value.s)?_tr_parsed_via->received->value: _tr_empty;
break;
case TR_VIA_RPORT:
val->rs = (_tr_parsed_via->rport&&_tr_parsed_via->rport->value.s)?_tr_parsed_via->rport->value: _tr_empty;
break;
default:
LM_ERR("unknown subtype %d\n",
subtype);
return -1;
}
done:
return 0;
error:
if ( _tr_via.s ) {
pkg_free(_tr_via.s);
}
memset(&_tr_via, 0, sizeof(str));
if ( _tr_parsed_via ) {
free_via_list(_tr_parsed_via);
_tr_parsed_via = 0;
}
return -1;
}
static str _tr_csv_str = {0,0};
static csv_t* _tr_csv_list = NULL;
static int init_csv(csv_t **t,char *s,int len)
{
*t = (csv_t *)pkg_malloc(sizeof(csv_t));
if (*t == NULL)
{
return -1;
}
memset(*t,0,sizeof(csv_t));
(*t)->body.s = s;
(*t)->body.len = len;
return 0;
}
void free_csv_list(csv_t *list)
{
csv_t *cit;
for (cit=list;cit;cit=cit->next)
pkg_free(cit);
}
static int parse_csv(str *s,csv_t **list)
{
csv_t *t = NULL;
csv_t *last = NULL;
char *string,*limit,*aux;
int len;
if (!s || !list)
{
LM_ERR("Invalid parameter values\n");
return -1;
}
last = NULL;
*list = 0;
if (!s->s)
{
LM_DBG("empty csv params, skipping\n");
return 0;
}
LM_DBG("Parsing csv for : [%.*s]\n",s->len,s->s);
string = s->s;
limit = string+s->len;
while (*string)
{
t = NULL;
/* quoted token */
if (*string == '\"')
{
aux = string+1;
search:
/* find coresponding quote */
while (*aux != '\"') aux++;
if ( *(aux+1) != '\"')
{
/* end of current token, also skip the following comma */
len = aux-string+1;
if (init_csv(&t,string,len) < 0)
{
LM_ERR("no more memory");
goto error;
}
string +=len+1;
if (string > limit)
{
/* again, end of string */
if (last) { last->next = t;} else {*list = t;}
return 0;
}
}
else
{
/* quoted string inside token */
aux +=2;
/* keep searching for final double quote*/
goto search;
}
}
else
{
/* non quoted csv , find comma */
aux = strchr(string,',');
if (aux == NULL)
{
len = strlen(string);
if (init_csv(&t,string,len) < 0)
{
LM_ERR("no more memory");
goto error;
}
/* should be end of string ! */
if (last) { last->next = t;} else {*list = t;}
return 0;
}
else
{
len = aux - string;
if (init_csv(&t,string,len) < 0)
{
LM_ERR("no more memory");
goto error;
}
string +=len+1;
}
}
if (last) { last->next = t;} else {*list = t;}
last = t;
}
return 0;
error:
if (t) pkg_free(t);
free_csv_list(*list);
*list = NULL;
return -1;
}
int tr_eval_csv(struct sip_msg *msg, tr_param_t *tp,int subtype,
pv_value_t *val)
{
str sv;
csv_t *cit=NULL;
int n,i,list_size=0;
pv_value_t v;
if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
{
return -1;
}
if(_tr_csv_str.len==0 || _tr_csv_str.len!=val->rs.len ||
strncmp(_tr_csv_str.s, val->rs.s, val->rs.len)!=0)
{
if(val->rs.len>_tr_csv_str.len)
{
if(_tr_csv_str.s) pkg_free(_tr_csv_str.s);
_tr_csv_str.s = (char*)pkg_malloc((val->rs.len+1));
if(_tr_csv_str.s==NULL)
{
LM_ERR("no more private memory\n");
memset(&_tr_csv_str, 0, sizeof(str));
if(_tr_csv_list != NULL)
{
free_csv_list(_tr_csv_list);
_tr_csv_list = 0;
}
return -1;
}
}
_tr_csv_str.len = val->rs.len;
memcpy(_tr_csv_str.s, val->rs.s, val->rs.len);
_tr_csv_str.s[_tr_csv_str.len] = '\0';
/* reset old values */
if(_tr_csv_list != NULL)
{
free_csv_list(_tr_csv_list);
_tr_csv_list = 0;
}
/* parse csv */
sv = _tr_csv_str;
if (parse_csv(&sv,&_tr_csv_list)<0)
return -1;
}
if (_tr_csv_list == NULL)
return -1;
switch(subtype)
{
case TR_CSV_COUNT:
val->ri = 0;
for (cit=_tr_csv_list;cit;cit=cit->next)
val->ri++;
val->rs.s = int2str(val->ri, &val->rs.len);
val->flags = PV_VAL_INT | PV_VAL_STR | PV_TYPE_INT;
break;
case TR_CSV_VALUEAT:
if(tp==NULL)
{
LM_ERR("csv invalid parameters\n");
return -1;
}
if(tp->type==TR_PARAM_NUMBER)
{
n = tp->v.n;
} else {
if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
|| (!(v.flags&PV_VAL_INT)))
{
LM_ERR("cannot get parameter\n");
return -1;
}
n = v.ri;
}
if (n<0)
{
for (cit=_tr_csv_list;cit;cit=cit->next)
list_size++;
n = list_size + n;
if (n<0)
{
LM_ERR("Too large negative index\n");
return -1;
}
}
cit = _tr_csv_list;
for (i=0;i<n;i++)
{
cit=cit->next;
if (!cit)
{
LM_ERR("Index out of bounds\n");
return -1;
}
}
val->rs = cit->body;
val->flags = PV_VAL_STR;
break;
default:
LM_ERR("unknown subtype %d\n",subtype);
return -1;
}
return 0;
}
static str _tr_sdp_str = {0,0};
int tr_eval_sdp(struct sip_msg *msg, tr_param_t *tp,int subtype,
pv_value_t *val)
{
char *bodylimit;
char *answer;
char *answerEnd;
char searchLine;
int entryNo,i;
pv_value_t v;
if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
return -1;
if (!tp || !tp->next)
return -1;
if(_tr_sdp_str.len==0 || _tr_sdp_str.len!=val->rs.len ||
strncmp(_tr_sdp_str.s, val->rs.s, val->rs.len)!=0)
{
if(val->rs.len>_tr_sdp_str.len)
{
if(_tr_sdp_str.s) pkg_free(_tr_sdp_str.s);
_tr_sdp_str.s = (char*)pkg_malloc((val->rs.len+1));
if(_tr_sdp_str.s==NULL)
{
LM_ERR("no more private memory\n");
memset(&_tr_sdp_str, 0, sizeof(str));
return -1;
}
}
_tr_sdp_str.len = val->rs.len;
memcpy(_tr_sdp_str.s, val->rs.s, val->rs.len);
_tr_sdp_str.s[_tr_sdp_str.len] = '\0';
}
switch (subtype)
{
case TR_SDP_LINEAT:
bodylimit = _tr_sdp_str.s + _tr_sdp_str.len;
searchLine = *(tp->v.s.s);
if(tp->next->type==TR_PARAM_NUMBER)
entryNo = tp->next->v.n;
else
{
if(pv_get_spec_value(msg, (pv_spec_p)tp->next->v.data, &v)!=0
|| (!(v.flags&PV_VAL_INT)))
{
LM_ERR("cannot get parameter\n");
return -1;
}
entryNo = v.ri;
}
if (entryNo < 0)
{
LM_ERR("negative index provided for sdp.lineat\n");
return -1;
}
answer = find_sdp_line(_tr_sdp_str.s, bodylimit, searchLine);
if (!answer) {
LM_DBG("No such line [%c=]\n", searchLine);
return pv_get_null(NULL, NULL, val);
}
for (i=1;i<=entryNo;i++)
{
answer = find_next_sdp_line(answer,bodylimit,searchLine,bodylimit);
if (!answer || answer == bodylimit)
{
val->flags = PV_VAL_STR;
val->rs.s = "";
val->rs.len = 0;
LM_DBG("No such line [%c] nr %d in SDP body. Max fields = %d\n",
searchLine,entryNo,i);
return 0;
}
}
/* find CR */
answerEnd = strchr(answer,13);
if (answerEnd == NULL)
{
LM_ERR("malformed SDP body\n");
return -1;
}
val->flags = PV_VAL_STR;
val->rs.s = answer;
val->rs.len = answerEnd - answer;
break;
default:
LM_ERR("unknown subtype %d\n",subtype);
return -1;
}
return 0;
}
int tr_eval_ip(struct sip_msg *msg, tr_param_t *tp,int subtype,
pv_value_t *val)
{
char *buffer;
struct ip_addr *binary_ip;
str inet = str_init("INET");
str inet6 = str_init("INET6");
struct hostent *server;
struct ip_addr ip;
if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
return -1;
switch (subtype)
{
case TR_IP_FAMILY:
if (val->rs.len == 4)
{
memcpy(val->rs.s,inet.s,inet.len);
val->rs.len = inet.len;
}
else if (val->rs.len == 16)
{
memcpy(val->rs.s,inet6.s,inet6.len);
val->rs.len = inet6.len;
}
else
{
LM_ERR("Invalid ip address provided for ip.family. Binary format expected !\n");
return -1;
}
val->flags = PV_VAL_STR;
break;
case TR_IP_NTOP:
if (val->rs.len == 4)
ip.af = AF_INET;
else if (val->rs.len == 16)
ip.af = AF_INET6;
else
{
LM_ERR("Invalid ip address provided for ip.ntop. Binary format expected !\n");
return -1;
}
memcpy(ip.u.addr,val->rs.s,val->rs.len);
ip.len = val->rs.len;
buffer = ip_addr2a(&ip);
val->rs.s = buffer;
val->rs.len = strlen(buffer);
val->flags = PV_VAL_STR;
break;
case TR_IP_ISIP:
if(!(val->flags&PV_VAL_STR))
val->rs.s = int2str(val->ri, &val->rs.len);
if ( str2ip(&(val->rs)) || str2ip6(&(val->rs)) )
val->ri = 1;
else
val->ri = 0;
val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
val->rs.s = int2str(val->ri, &val->rs.len);
break;
case TR_IP_PTON:
binary_ip = str2ip(&(val->rs));
if (!binary_ip)
{
binary_ip = str2ip6(&(val->rs));
if (!binary_ip)
{
LM_ERR("pton transformation applied to invalid IP\n");
return -1;
}
}
val->rs.s = (char *)binary_ip->u.addr;
val->rs.len = binary_ip->len;
val->flags = PV_VAL_STR;
break;
case TR_IP_RESOLVE:
val->flags = PV_VAL_STR;
server = resolvehost(val->rs.s,0);
if (!server || !server->h_addr)
{
val->rs.s = "";
val->rs.len = 0;
return 0;
}
if (server->h_addrtype == AF_INET)
{
memcpy(ip.u.addr,server->h_addr,4);
ip.len = 4;
ip.af = AF_INET;
}
else if (server->h_addrtype == AF_INET6)
{
memcpy(ip.u.addr,server->h_addr,16);
ip.len = 16;
ip.af = AF_INET6;
}
else
{
LM_ERR("Unexpected IP address type \n");
val->rs.s = "";
val->rs.len = 0;
return 0;
}
buffer = ip_addr2a(&ip);
val->rs.s = buffer;
val->rs.len = strlen(buffer);
break;
default:
LM_ERR("unknown subtype %d\n",subtype);
return -1;
}
return 0;
}
#define RE_MAX_SIZE 1024
static char reg_input_buf[RE_MAX_SIZE];
static struct subst_expr *subst_re = NULL;
static char reg_buf[RE_MAX_SIZE];
static int reg_buf_len = -1;
int tr_eval_re(struct sip_msg *msg, tr_param_t *tp, int subtype,
pv_value_t *val)
{
int match_no=0;
pv_value_t v;
str *result;
str sv;
if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
return -1;
switch (subtype) {
case TR_RE_SUBST:
if (tp->type == TR_PARAM_STRING) {
sv = tp->v.s;
} else {
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("cannot get value from spec\n");
return -1;
}
sv = v.rs;
}
LM_DBG("Trying to apply regexp [%.*s] on : [%.*s]\n",
sv.len,sv.s,val->rs.len, val->rs.s);
if (reg_buf_len != sv.len || memcmp(reg_buf,sv.s,sv.len) != 0) {
LM_DBG("we must compile the regexp\n");
if (subst_re != NULL) {
LM_DBG("freeing prev regexp\n");
subst_expr_free(subst_re);
}
subst_re=subst_parser(&sv);
if (subst_re==0) {
LM_ERR("Can't compile regexp\n");
return -1;
}
reg_buf_len = sv.len;
memcpy(reg_buf,sv.s,sv.len);
} else
LM_DBG("yay, we can use the pre-compile regexp\n");
memcpy(reg_input_buf,val->rs.s,val->rs.len);
reg_input_buf[val->rs.len]=0;
result=subst_str(reg_input_buf, msg, subst_re, &match_no);
if (result == NULL) {
if (match_no == 0) {
LM_DBG("no match for subst expression\n");
break;
} else if (match_no < 0) {
LM_ERR("subst failed\n");
return -1;
}
}
memcpy(reg_input_buf,result->s,result->len);
reg_input_buf[result->len]=0;
val->flags = PV_VAL_STR;
val->rs.s = reg_input_buf;
val->rs.len = result->len;
pkg_free(result->s);
pkg_free(result);
return 0;
default:
LM_ERR("Unexpected subtype for RE : %d\n",subtype);
return -1;
}
return 0;
}
static str _tr_params_str = {0, 0};
static param_t* _tr_params_list = NULL;
int tr_eval_paramlist(struct sip_msg *msg, tr_param_t *tp, int subtype,
pv_value_t *val)
{
pv_value_t v;
str sv;
int n, i;
param_hooks_t phooks;
param_t *pit=NULL;
if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
return -1;
if(_tr_params_str.len==0 || _tr_params_str.len!=val->rs.len ||
strncmp(_tr_params_str.s, val->rs.s, val->rs.len)!=0)
{
if(val->rs.len>_tr_params_str.len)
{
if(_tr_params_str.s) pkg_free(_tr_params_str.s);
_tr_params_str.s = (char*)pkg_malloc((val->rs.len+1)*sizeof(char));
if(_tr_params_str.s==NULL)
{
LM_ERR("no more private memory\n");
memset(&_tr_params_str, 0, sizeof(str));
if(_tr_params_list != NULL)
{
free_params(_tr_params_list);
_tr_params_list = 0;
}
return -1;
}
}
_tr_params_str.len = val->rs.len;
memcpy(_tr_params_str.s, val->rs.s, val->rs.len);
_tr_params_str.s[_tr_params_str.len] = '\0';
/* reset old values */
if(_tr_params_list != NULL)
{
free_params(_tr_params_list);
_tr_params_list = 0;
}
/* parse params */
sv = _tr_params_str;
if (parse_params(&sv, CLASS_ANY, &phooks, &_tr_params_list)<0)
return -1;
}
if(_tr_params_list==NULL)
return -1;
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
switch(subtype)
{
case TR_PL_VALUE:
if(tp==NULL)
{
LM_ERR("value invalid parameters\n");
return -1;
}
if(tp->type==TR_PARAM_STRING)
{
sv = tp->v.s;
} else {
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("value cannot get p1\n");
return -1;
}
sv = v.rs;
}
for (pit = _tr_params_list; pit; pit=pit->next)
{
if (pit->name.len==sv.len
&& strncasecmp(pit->name.s, sv.s, sv.len)==0)
{
val->rs = pit->body;
goto done;
}
}
val->rs = _tr_empty;
break;
case TR_PL_VALUEAT:
if(tp==NULL)
{
LM_ERR("name invalid parameters\n");
return -1;
}
if(tp->type==TR_PARAM_NUMBER)
{
n = tp->v.n;
} else {
if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
|| (!(v.flags&PV_VAL_INT)))
{
LM_ERR("name cannot get p1\n");
return -1;
}
n = v.ri;
}
if(n<0)
{
n = -n;
n--;
for (pit = _tr_params_list; pit; pit=pit->next)
{
if(n==0)
{
val->rs = pit->body;
goto done;
}
n--;
}
} else {
/* ugly hack -- params are in reverse order
* - first count then find */
i = 0;
for (pit = _tr_params_list; pit; pit=pit->next)
i++;
if(n<i)
{
n = i - n - 1;
for (pit = _tr_params_list; pit; pit=pit->next)
{
if(n==0)
{
val->rs = pit->body;
goto done;
}
n--;
}
}
}
val->rs = _tr_empty;
break;
case TR_PL_NAME:
if(tp==NULL)
{
LM_ERR("name invalid parameters\n");
return -1;
}
if(tp->type==TR_PARAM_NUMBER)
{
n = tp->v.n;
} else {
if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
|| (!(v.flags&PV_VAL_INT)))
{
LM_ERR("name cannot get p1\n");
return -1;
}
n = v.ri;
}
if(n<0)
{
n = -n;
n--;
for (pit = _tr_params_list; pit; pit=pit->next)
{
if(n==0)
{
val->rs = pit->name;
goto done;
}
n--;
}
} else {
/* ugly hack -- params are in reverse order
* - first count then find */
i = 0;
for (pit = _tr_params_list; pit; pit=pit->next)
i++;
if(n<i)
{
n = i - n - 1;
for (pit = _tr_params_list; pit; pit=pit->next)
{
if(n==0)
{
val->rs = pit->name;
goto done;
}
n--;
}
}
}
val->rs = _tr_empty;
break;
case TR_PL_COUNT:
val->ri = 0;
for (pit = _tr_params_list; pit; pit=pit->next)
val->ri++;
val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
val->rs.s = int2str(val->ri, &val->rs.len);
break;
case TR_PL_EXIST:
if(tp==NULL)
{
LM_ERR("value invalid parameters\n");
return -1;
}
if(tp->type==TR_PARAM_STRING)
{
sv = tp->v.s;
} else {
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("value cannot get p1\n");
return -1;
}
sv = v.rs;
}
val->ri = 0;
for (pit = _tr_params_list; pit; pit=pit->next)
{
if (pit->name.len==sv.len
&& strncasecmp(pit->name.s, sv.s, sv.len)==0)
{
val->ri = 1;
break;
}
}
val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
val->rs.s = int2str(val->ri, &val->rs.len);
goto done;
default:
LM_ERR("unknown subtype %d\n",
subtype);
return -1;
}
done:
return 0;
}
static str nameaddr_str = {0, 0};
static struct to_body *nameaddr_to_body = NULL;
int tr_eval_nameaddr(struct sip_msg *msg, tr_param_t *tp, int subtype,
pv_value_t *val)
{
struct to_param* topar;
if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
return -1;
LM_DBG("String to transform %.*s\n", val->rs.len, val->rs.s);
if(nameaddr_str.len==0 || nameaddr_str.len!=val->rs.len ||
strncmp(nameaddr_str.s, val->rs.s, val->rs.len)!=0)
{
/* copy the value in the global variable */
if(val->rs.len+CRLF_LEN > nameaddr_str.len)
{
if(nameaddr_str.s) pkg_free(nameaddr_str.s);
nameaddr_str.s =
(char*)pkg_malloc((val->rs.len+CRLF_LEN+1)*sizeof(char));
if(nameaddr_str.s==NULL)
{
LM_ERR("no more private memory\n");
memset(&nameaddr_str, 0, sizeof(str));
return -1;
}
}
nameaddr_str.len = val->rs.len + CRLF_LEN;
memcpy(nameaddr_str.s, val->rs.s, val->rs.len);
memcpy(nameaddr_str.s + val->rs.len, CRLF, CRLF_LEN);
nameaddr_str.s[nameaddr_str.len] = '\0';
/* reset old values */
if (nameaddr_to_body) {
free_to(nameaddr_to_body);
nameaddr_to_body = NULL;
}
/* parse TO hdr + params */
nameaddr_to_body = (struct to_body*)pkg_malloc(sizeof(struct to_body));
if(nameaddr_to_body==NULL)
{
LM_ERR("no more private memory\n");
/* keep the buffer, but flush the content to force the realloc
next time */
nameaddr_str.s[0] = 0;
return -1;
}
parse_to(nameaddr_str.s, nameaddr_str.s + nameaddr_str.len,
nameaddr_to_body);
}
if (nameaddr_to_body->error == PARSE_ERROR)
{
LM_ERR("Wrong syntax. It must have the To header format\n");
return -1;
}
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
switch(subtype)
{
case TR_NA_URI:
val->rs =(nameaddr_to_body->uri.s)?nameaddr_to_body->uri:_tr_empty;
break;
case TR_NA_LEN:
val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
val->ri = nameaddr_to_body->body.len;
val->rs.s = int2str(val->ri, &val->rs.len);
break;
case TR_NA_NAME:
val->rs = (nameaddr_to_body->display.s)?
nameaddr_to_body->display:_tr_empty;
break;
case TR_NA_PARAM:
if(tp->type != TR_PARAM_STRING)
{
LM_ERR("Wrong type for parameter, it must string\n");
return -1;
}
topar = nameaddr_to_body->param_lst;
/* search the parameter */
while(topar)
{
if(topar->name.len == tp->v.s.len &&
strncmp(topar->name.s, tp->v.s.s, topar->name.len)== 0)
break;
topar = topar->next;
}
val->rs = (topar)?topar->value:_tr_empty;
break;
case TR_NA_PARAMS:
topar = nameaddr_to_body->param_lst;
if (!topar) {
LM_DBG("no params\n");
val->rs = _tr_empty;
}
else {
LM_DBG("We have params\n");
val->rs.s = topar->name.s;
if (nameaddr_to_body->last_param->value.s==NULL) {
val->rs.len = nameaddr_to_body->last_param->name.s +
nameaddr_to_body->last_param->name.len - val->rs.s;
} else {
val->rs.len = nameaddr_to_body->last_param->value.s +
nameaddr_to_body->last_param->value.len - val->rs.s;
/* compensate the len if the value of the last param is
* a quoted value (include the closing quote in the len) */
if ( (val->rs.s+val->rs.len<nameaddr_str.len+nameaddr_str.s) &&
(val->rs.s[val->rs.len]=='"' || val->rs.s[val->rs.len]=='\'' ) )
val->rs.len++;
}
}
break;
default:
LM_ERR("unknown subtype %d\n", subtype);
return -1;
}
return 0;
}
#define is_in_str(p, in) (p<in->s+in->len && *p)
char* parse_transformation(str *in, trans_t **tr)
{
char *p;
char *p0;
str tclass;
trans_t *t = NULL;
trans_t *t0 = NULL;
str s;
if(in==NULL || in->s==NULL || tr==NULL)
return NULL;
p = in->s;
do {
while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p != TR_LBRACKET)
break;
p++;
t = (trans_t*)pkg_malloc(sizeof(trans_t));
if(t == NULL)
{
LM_ERR("no more private memory\n");
return NULL;
}
memset(t, 0, sizeof(trans_t));
if(t0==NULL)
*tr = t;
else
t0->next = t;
t0 = t;
/* find transformation class */
tclass.s = p;
while(is_in_str(p, in) && *p!=TR_CLASS_MARKER) p++;
if(*p!=TR_CLASS_MARKER || tclass.s == p)
{
LM_ERR("invalid transformation: %.*s (%c)!\n", in->len, in->s, *p);
goto error;
}
tclass.len = p - tclass.s;
p++;
if(tclass.len==1 && (*tclass.s=='s' || *tclass.s=='S'))
{
t->type = TR_STRING;
t->trf = tr_eval_string;
s.s = p; s.len = in->s + in->len - p;
p0 = tr_parse_string(&s, t);
if(p0==NULL)
goto error;
p = p0;
} else if(tclass.len==3 && strncasecmp(tclass.s, "uri", 3)==0) {
t->type = TR_URI;
t->trf = tr_eval_uri;
s.s = p; s.len = in->s + in->len - p;
p0 = tr_parse_uri(&s, t);
if(p0==NULL)
goto error;
p = p0;
} else if(tclass.len==3 && strncasecmp(tclass.s, "via", 3)==0) {
t->type = TR_VIA;
t->trf = tr_eval_via;
s.s = p; s.len = in->s + in->len - p;
p0 = tr_parse_via(&s, t);
if(p0==NULL)
goto error;
p = p0;
} else if(tclass.len==5 && strncasecmp(tclass.s, "param", 5)==0) {
t->type = TR_PARAMLIST;
t->trf = tr_eval_paramlist;
s.s = p; s.len = in->s + in->len - p;
p0 = tr_parse_paramlist(&s, t);
if(p0==NULL)
goto error;
p = p0;
} else if(tclass.len==8 && strncasecmp(tclass.s, "nameaddr", 8)==0) {
t->type = TR_NAMEADDR;
t->trf = tr_eval_nameaddr;
s.s = p; s.len = in->s + in->len - p;
p0 = tr_parse_nameaddr(&s, t);
if(p0==NULL)
goto error;
p = p0;
}
else if (tclass.len==3 && strncasecmp(tclass.s, "csv", 3) == 0) {
t->type = TR_CSV;
t->trf = tr_eval_csv;
s.s = p; s.len = in->s + in->len - p;
p0 = tr_parse_csv(&s,t);
if (p0==NULL)
goto error;
p = p0;
}
else if (tclass.len==3 && strncasecmp(tclass.s,"sdp",3) == 0) {
t->type = TR_SDP;
t->trf = tr_eval_sdp;
s.s = p; s.len = in->s + in->len - p;
p0 = tr_parse_sdp(&s,t);
if (p0==NULL)
goto error;
p = p0;
}
else if (tclass.len==2 && strncasecmp(tclass.s,"ip",2) == 0) {
t->type = TR_IP;
t->trf = tr_eval_ip;
s.s = p; s.len = in->s + in->len - p;
p0 = tr_parse_ip(&s,t);
if (p0==NULL)
goto error;
p = p0;
} else if (tclass.len==2 && strncasecmp(tclass.s,"re",2) == 0) {
t->type = TR_RE;
t->trf = tr_eval_re;
s.s = p; s.len = in->s + in->len - p;
p0 = tr_parse_re(&s,t);
if (p0==NULL)
goto error;
p = p0;
}
else {
LM_ERR("unknown transformation: [%.*s] in [%.*s]\n",
tclass.len, tclass.s, in->len, in->s);
goto error;
}
if(*p != TR_RBRACKET)
{
LM_ERR("invalid transformation: %.*s | %c !!\n", in->len, in->s, *p);
goto error;
}
p++;
if(!is_in_str(p, in))
break;
} while(1);
return p;
error:
LM_ERR("error parsing [%.*s]\n", in->len, in->s);
t = *tr;
while(t)
{
t0 = t;
t = t->next;
destroy_transformation(t0);
pkg_free(t0);
}
return NULL;
}
#define _tr_parse_nparam(_p, _p0, _tp, _spec, _n, _sign, _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 { \
if(*_p=='+' || *_p=='-' || (*_p>='0' && *_p<='9')) \
{ /* number */ \
_sign = 1; \
if(*_p=='-') { \
_p++; \
_sign = -1; \
} else if(*_p=='+') _p++; \
_n = 0; \
while(is_in_str(_p, _in) && (*_p==' ' || *_p=='\t' || *_p=='\n')) \
_p++; \
while(is_in_str(_p, _in) && *_p>='0' && *_p<='9') \
{ \
_n = _n*10 + *_p - '0'; \
_p++; \
} \
_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_NUMBER; \
_tp->v.n = sign*n; \
} else { \
LM_ERR("tinvalid param in transformation: %.*s!!\n", \
_in->len, _in->s); \
goto error; \
} \
}
#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 */ \
while(is_in_str(_p, _in) && (*_p==' ' || *_p=='\t' || *_p=='\n')) \
_p++; \
_ps = _p; \
while(is_in_str(_p, _in) && *_p!=' ' && *_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_parse_string(str* in, trans_t *t)
{
char *p;
char *p0;
char *ps;
str name;
str s;
pv_spec_t *spec = NULL;
int n;
int sign;
tr_param_t *tp = NULL;
if(in==NULL || t==NULL)
return NULL;
p = in->s;
name.s = in->s;
/* find next token */
while(is_in_str(p, in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
if(*p=='\0')
{
LM_ERR("invalid transformation: %.*s\n",
in->len, in->s);
goto error;
}
name.len = p - name.s;
trim(&name);
if(name.len==3 && strncasecmp(name.s, "len", 3)==0)
{
t->subtype = TR_S_LEN;
return p;
} else if(name.len==3 && strncasecmp(name.s, "int", 3)==0) {
t->subtype = TR_S_INT;
return p;
} else if(name.len==3 && strncasecmp(name.s, "md5", 3)==0) {
t->subtype = TR_S_MD5;
return p;
} else if(name.len==5 && strncasecmp(name.s, "crc32", 5)==0) {
t->subtype = TR_S_CRC32;
return p;
} else if(name.len==7 && strncasecmp(name.s, "tolower", 7)==0) {
t->subtype = TR_S_TOLOWER;
return p;
} else if(name.len==7 && strncasecmp(name.s, "toupper", 7)==0) {
t->subtype = TR_S_TOUPPER;
return p;
} else if(name.len==11 && strncasecmp(name.s, "encode.hexa", 11)==0) {
t->subtype = TR_S_ENCODEHEXA;
return p;
} else if(name.len==11 && strncasecmp(name.s, "decode.hexa", 11)==0) {
t->subtype = TR_S_DECODEHEXA;
return p;
} else if(name.len==7 && strncasecmp(name.s, "hex2dec", 7)==0) {
t->subtype = TR_S_HEX2DEC;
return p;
} else if(name.len==7 && strncasecmp(name.s, "dec2hex", 7)==0) {
t->subtype = TR_S_DEC2HEX;
return p;
} else if(name.len==13 && strncasecmp(name.s, "escape.common", 13)==0) {
t->subtype = TR_S_ESCAPECOMMON;
return p;
} else if(name.len==15 && strncasecmp(name.s, "unescape.common", 15)==0) {
t->subtype = TR_S_UNESCAPECOMMON;
return p;
} else if(name.len==11 && strncasecmp(name.s, "escape.user", 11)==0) {
t->subtype = TR_S_ESCAPEUSER;
return p;
} else if(name.len==13 && strncasecmp(name.s, "unescape.user", 13)==0) {
t->subtype = TR_S_UNESCAPEUSER;
return p;
} else if(name.len==12 && strncasecmp(name.s, "escape.param", 12)==0) {
t->subtype = TR_S_ESCAPEPARAM;
return p;
} else if(name.len==14 && strncasecmp(name.s, "unescape.param", 14)==0) {
t->subtype = TR_S_UNESCAPEPARAM;
return p;
} else if(name.len==5 && strncasecmp(name.s, "index", 5)==0) {
t->subtype = TR_S_INDEX;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid index transformation: %.*s!\n", in->len, in->s);
goto error;
}
p++;
_tr_parse_sparam(p, p0, tp, spec, ps, in, s);
t->params = tp;
tp = 0;
while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_PARAM_MARKER && *p!=TR_RBRACKET)
{
LM_ERR("invalid index transformation: %.*s!\n",
in->len, in->s);
goto error;
}
if (*p!=TR_RBRACKET) {
p++;
_tr_parse_nparam(p, p0, tp, spec, n, sign, in, s);
t->params->next = tp;
} else {
t->params->next = NULL;
}
tp = 0;
while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_RBRACKET)
{
LM_ERR("invalid index transformation: %.*s!!\n",
in->len, in->s);
goto error;
}
return p;
} else if(name.len==6 && strncasecmp(name.s, "rindex", 6)==0) {
t->subtype = TR_S_RINDEX;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid rindex transformation: %.*s!\n", in->len, in->s);
goto error;
}
p++;
_tr_parse_sparam(p, p0, tp, spec, ps, in, s);
t->params = tp;
tp = 0;
while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_PARAM_MARKER && *p!=TR_RBRACKET)
{
LM_ERR("invalid rindex transformation: %.*s!\n",
in->len, in->s);
goto error;
}
if (*p!=TR_RBRACKET) {
p++;
_tr_parse_nparam(p, p0, tp, spec, n, sign, in, s);
t->params->next = tp;
} else {
t->params->next = NULL;
}
tp = 0;
while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_RBRACKET)
{
LM_ERR("invalid rindex transformation: %.*s!!\n",
in->len, in->s);
goto error;
}
return p;
} else if(name.len==6 && strncasecmp(name.s, "substr", 6)==0) {
t->subtype = TR_S_SUBSTR;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid substr transformation: %.*s!\n", in->len, in->s);
goto error;
}
p++;
_tr_parse_nparam(p, p0, tp, spec, n, sign, in, s);
t->params = tp;
tp = 0;
while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid substr transformation: %.*s!\n",
in->len, in->s);
goto error;
}
p++;
_tr_parse_nparam(p, p0, tp, spec, n, sign, in, s);
if(tp->type==TR_PARAM_NUMBER && tp->v.n<0)
{
LM_ERR("substr negative offset\n");
goto error;
}
t->params->next = tp;
tp = 0;
while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_RBRACKET)
{
LM_ERR("invalid substr transformation: %.*s!!\n",
in->len, in->s);
goto error;
}
return p;
} else if(name.len==6 && strncasecmp(name.s, "select", 6)==0) {
t->subtype = TR_S_SELECT;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid select transformation: %.*s!\n",
in->len, in->s);
goto error;
}
p++;
_tr_parse_nparam(p, p0, tp, spec, n, sign, in, s);
t->params = tp;
tp = 0;
while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_PARAM_MARKER || *(p+1)=='\0')
{
LM_ERR("invalid select transformation: %.*s!\n", in->len, in->s);
goto error;
}
p++;
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 = p;
tp->v.s.len = 1;
t->params->next = tp;
tp = 0;
p++;
while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_RBRACKET)
{
LM_ERR("invalid select transformation: %.*s!!\n",
in->len, in->s);
goto error;
}
return p;
}
LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
name.len, name.s, name.len);
error:
if(tp)
free_tr_param(tp);
if(spec)
pv_spec_free(spec);
return NULL;
}
char* tr_parse_uri(str* in, trans_t *t)
{
char *p;
char *p0;
char *ps;
str name;
str s;
pv_spec_t *spec = NULL;
tr_param_t *tp = NULL;
if(in==NULL || in->s==NULL || t==NULL)
return NULL;
p = in->s;
name.s = in->s;
/* find next token */
while(*p && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
if(*p=='\0')
{
LM_ERR("invalid transformation: %.*s\n", in->len, in->s);
goto error;
}
name.len = p - name.s;
trim(&name);
if(name.len==4 && strncasecmp(name.s, "user", 4)==0)
{
t->subtype = TR_URI_USER;
return p;
} else if((name.len==4 && strncasecmp(name.s, "host", 4)==0)
|| (name.len==6 && strncasecmp(name.s, "domain", 6)==0)) {
t->subtype = TR_URI_HOST;
return p;
} else if(name.len==6 && strncasecmp(name.s, "passwd", 6)==0) {
t->subtype = TR_URI_PASSWD;
return p;
} else if(name.len==4 && strncasecmp(name.s, "port", 4)==0) {
t->subtype = TR_URI_PORT;
return p;
} else if(name.len==6 && strncasecmp(name.s, "params", 6)==0) {
t->subtype = TR_URI_PARAMS;
return p;
} else if(name.len==5 && strncasecmp(name.s, "param", 5)==0) {
t->subtype = TR_URI_PARAM;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid param transformation: %.*s\n", in->len, in->s);
goto error;
}
p++;
_tr_parse_sparam(p, p0, tp, spec, ps, in, s);
t->params = tp;
tp = 0;
while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_RBRACKET)
{
LM_ERR("invalid param transformation: %.*s!\n", in->len, in->s);
goto error;
}
return p;
} else if(name.len==9 && strncasecmp(name.s, "transport", 9)==0) {
t->subtype = TR_URI_TRANSPORT;
return p;
} else if(name.len==7 && strncasecmp(name.s, "headers", 7)==0) {
t->subtype = TR_URI_HEADERS;
return p;
} else if(name.len==3 && strncasecmp(name.s, "ttl", 3)==0) {
t->subtype = TR_URI_TTL;
return p;
} else if(name.len==6 && strncasecmp(name.s, "uparam", 6)==0) {
t->subtype = TR_URI_UPARAM;
return p;
} else if(name.len==5 && strncasecmp(name.s, "maddr", 5)==0) {
t->subtype = TR_URI_MADDR;
return p;
} else if(name.len==6 && strncasecmp(name.s, "method", 6)==0) {
t->subtype = TR_URI_METHOD;
return p;
} else if(name.len==2 && strncasecmp(name.s, "lr", 2)==0) {
t->subtype = TR_URI_LR;
return p;
} else if(name.len==2 && strncasecmp(name.s, "r2", 2)==0) {
t->subtype = TR_URI_R2;
return p;
}
LM_ERR("unknown transformation: %.*s/%.*s!\n", in->len,
in->s, name.len, name.s);
error:
if(tp)
free_tr_param(tp);
if(spec)
pv_spec_free(spec);
return NULL;
}
char* tr_parse_via(str* in, trans_t *t)
{
char *p;
char *p0;
char *ps;
str name;
str s;
pv_spec_t *spec = NULL;
tr_param_t *tp = NULL;
if(in==NULL || in->s==NULL || t==NULL)
return NULL;
p = in->s;
name.s = in->s;
/* find next token */
while(*p && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
if(*p=='\0')
{
LM_ERR("invalid transformation: %.*s\n", in->len, in->s);
goto error;
}
name.len = p - name.s;
trim(&name);
if(name.len==4 && strncasecmp(name.s, "name", 4)==0)
{
t->subtype = TR_VIA_NAME;
return p;
} else if(name.len==7 && strncasecmp(name.s, "version", 7)==0)
{
t->subtype = TR_VIA_VERSION;
return p;
} else if(name.len==9 && strncasecmp(name.s, "transport", 9)==0) {
t->subtype = TR_VIA_TRANSPORT;
return p;
} else if((name.len==4 && strncasecmp(name.s, "host", 4)==0)
|| (name.len==6 && strncasecmp(name.s, "domain", 6)==0)) {
t->subtype = TR_VIA_HOST;
return p;
} else if(name.len==4 && strncasecmp(name.s, "port", 4)==0) {
t->subtype = TR_VIA_PORT;
return p;
} else if(name.len==6 && strncasecmp(name.s, "params", 6)==0) {
t->subtype = TR_VIA_PARAMS;
return p;
} else if(name.len==5 && strncasecmp(name.s, "param", 5)==0) {
t->subtype = TR_VIA_PARAM;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid param transformation: %.*s\n", in->len, in->s);
goto error;
}
p++;
_tr_parse_sparam(p, p0, tp, spec, ps, in, s);
t->params = tp;
tp = 0;
while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_RBRACKET)
{
LM_ERR("invalid param transformation: %.*s!\n", in->len, in->s);
goto error;
}
return p;
} else if(name.len==7 && strncasecmp(name.s, "comment", 7)==0) {
t->subtype = TR_VIA_COMMENT;
return p;
} else if(name.len==6 && strncasecmp(name.s, "branch", 6)==0) {
t->subtype = TR_VIA_BRANCH;
return p;
} else if(name.len==8 && strncasecmp(name.s, "received", 8)==0) {
t->subtype = TR_VIA_RECEIVED;
return p;
} else if(name.len==5 && strncasecmp(name.s, "rport", 5)==0) {
t->subtype = TR_VIA_RPORT;
return p;
}
LM_ERR("unknown transformation: %.*s/%.*s!\n", in->len,
in->s, name.len, name.s);
error:
if(tp)
free_tr_param(tp);
if(spec)
pv_spec_free(spec);
return NULL;
}
char* tr_parse_paramlist(str* in, trans_t *t)
{
char *p;
char *p0;
char *ps;
str s;
str name;
int n;
int sign;
pv_spec_t *spec = NULL;
tr_param_t *tp = NULL;
if(in==NULL || in->s==NULL || t==NULL)
return NULL;
p = in->s;
name.s = in->s;
/* find next token */
while(is_in_str(p, in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
if(*p=='\0')
{
LM_ERR("invalid transformation: %.*s\n",
in->len, in->s);
goto error;
}
name.len = p - name.s;
trim(&name);
if(name.len==5 && strncasecmp(name.s, "value", 5)==0)
{
t->subtype = TR_PL_VALUE;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid value transformation: %.*s\n",
in->len, in->s);
goto error;
}
p++;
_tr_parse_sparam(p, p0, tp, spec, ps, in, s);
t->params = tp;
tp = 0;
while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_RBRACKET)
{
LM_ERR("invalid value transformation: %.*s!\n",
in->len, in->s);
goto error;
}
return p;
} else if(name.len==5 && strncasecmp(name.s, "exist", 5)==0) {
t->subtype = TR_PL_EXIST;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid value transformation: %.*s\n",
in->len, in->s);
goto error;
}
p++;
_tr_parse_sparam(p, p0, tp, spec, ps, in, s);
t->params = tp;
tp = 0;
while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_RBRACKET)
{
LM_ERR("invalid value transformation: %.*s!\n",
in->len, in->s);
goto error;
}
return p;
} else if(name.len==7 && strncasecmp(name.s, "valueat", 7)==0) {
t->subtype = TR_PL_VALUEAT;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid name transformation: %.*s\n",
in->len, in->s);
goto error;
}
p++;
_tr_parse_nparam(p, p0, tp, spec, n, sign, in, s)
t->params = tp;
tp = 0;
while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_RBRACKET)
{
LM_ERR("invalid name transformation: %.*s!\n",
in->len, in->s);
goto error;
}
return p;
} else if(name.len==4 && strncasecmp(name.s, "name", 4)==0) {
t->subtype = TR_PL_NAME;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid name transformation: %.*s\n",
in->len, in->s);
goto error;
}
p++;
_tr_parse_nparam(p, p0, tp, spec, n, sign, in, s)
t->params = tp;
tp = 0;
while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_RBRACKET)
{
LM_ERR("invalid name transformation: %.*s!\n",
in->len, in->s);
goto error;
}
return p;
} else if(name.len==5 && strncasecmp(name.s, "count", 5)==0) {
t->subtype = TR_PL_COUNT;
return p;
}
LM_ERR("unknown transformation: %.*s/%.*s!\n",
in->len, in->s, name.len, name.s);
error:
if(tp)
free_tr_param(tp);
if(spec)
pv_spec_free(spec);
return NULL;
}
char* tr_parse_nameaddr(str* in, trans_t *t)
{
char *p;
str name;
char *p0;
char *ps;
str s;
pv_spec_t *spec = NULL;
tr_param_t *tp = NULL;
if(in==NULL || t==NULL)
return NULL;
p = in->s;
name.s = in->s;
/* find next token */
while(is_in_str(p, in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
if(*p=='\0')
{
LM_ERR("invalid transformation: %.*s\n",
in->len, in->s);
goto error;
}
name.len = p - name.s;
trim(&name);
if(name.len==3 && strncasecmp(name.s, "uri", 3)==0)
{
t->subtype = TR_NA_URI;
return p;
} else if(name.len==3 && strncasecmp(name.s, "len", 3)==0)
{
t->subtype = TR_NA_LEN;
return p;
} else if(name.len==4 && strncasecmp(name.s, "name", 4)==0) {
t->subtype = TR_NA_NAME;
return p;
} else if(name.len==5 && strncasecmp(name.s, "param", 5)==0) {
t->subtype = TR_NA_PARAM;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid value transformation: %.*s\n",
in->len, in->s);
goto error;
}
p++;
_tr_parse_sparam(p, p0, tp, spec, ps, in, s);
t->params = tp;
tp = 0;
while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_RBRACKET)
{
LM_ERR("invalid value transformation: %.*s!\n",
in->len, in->s);
goto error;
}
return p;
} else if(name.len==6 && strncasecmp(name.s, "params", 6)==0) {
t->subtype = TR_NA_PARAMS;
return p;
}
LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
name.len, name.s, name.len);
error:
return NULL;
}
char * tr_parse_csv(str *in, trans_t *t)
{
char *p;
str name;
pv_spec_t *spec = NULL;
tr_param_t *tp = NULL;
char *p0;
str s;
int n;
int sign;
if (in == NULL || t == NULL)
return NULL;
p = in->s;
name.s = in->s;
/* find next token */
while (is_in_str(p,in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
if (*p == '\0')
{
LM_ERR("invalid transformation: %.*s\n",in->len,in->s);
return NULL;
}
name.len = p - name.s;
trim(&name);
if (name.len==5 && strncasecmp(name.s,"count",5)==0)
{
t->subtype = TR_CSV_COUNT;
return p;
}
else if (name.len==5 && strncasecmp(name.s,"value",5)==0)
{
t->subtype = TR_CSV_VALUEAT;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid name transformation: %.*s\n",
in->len, in->s);
goto error;
}
p++;
_tr_parse_nparam(p, p0, tp, spec, n, sign, in, s)
t->params = tp;
tp = 0;
while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_RBRACKET)
{
LM_ERR("invalid name transformation: %.*s!\n",
in->len, in->s);
goto error;
}
return p;
}
LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
name.len, name.s, name.len);
error:
return NULL;
}
char * tr_parse_sdp(str *in, trans_t *t)
{
char *p;
char *p0;
char *ps;
str name;
pv_spec_t *spec = NULL;
tr_param_t *tp = NULL;
str s;
int n;
int sign;
if (in == NULL || t == NULL)
return NULL;
p = in->s;
name.s = in->s;
/* find next token */
while (is_in_str(p,in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
if (*p == '\0')
{
LM_ERR("invalid transformation: %.*s\n",in->len,in->s);
return NULL;
}
name.len = p - name.s;
trim(&name);
if (name.len==4 && strncasecmp(name.s,"line",4)==0)
{
t->subtype = TR_SDP_LINEAT;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid lineat transformation: %.*s!\n", in->len, in->s);
goto error;
}
p++;
_tr_parse_sparam(p, p0, tp, spec,ps, in, s);
t->params = tp;
tp = 0;
while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_PARAM_MARKER)
{
/* lineat has only one parameter */
tp = (tr_param_t*)pkg_malloc(sizeof(tr_param_t));
if (!tp)
{
LM_ERR("no more pkg memory\n");
goto error;
}
memset(tp, 0, sizeof(tr_param_t));
tp->type = TR_PARAM_NUMBER;
tp->v.n = 0;
t->params->next = tp;
LM_DBG("sdp.lineat with only one parameter. default = 1\n");
return p;
}
p++;
if (spec)
{
pkg_free(spec);
spec = NULL;
}
_tr_parse_nparam(p, p0, tp, spec,n,sign, in, s);
if(tp->type==TR_PARAM_NUMBER && tp->v.n<0)
{
LM_ERR("lineat negative argument\n");
goto error;
}
t->params->next = tp;
tp = 0;
while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_RBRACKET)
{
LM_ERR("invalid lineat transformation: %.*s!!\n",
in->len, in->s);
goto error;
}
return p;
}
LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
name.len, name.s, name.len);
error:
return NULL;
}
char * tr_parse_ip(str *in, trans_t *t)
{
char *p;
str name;
if (in == NULL || t == NULL)
return NULL;
p = in->s;
name.s = in->s;
/* find next token */
while (is_in_str(p,in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
if (*p == '\0')
{
LM_ERR("invalid transformation: %.*s\n",in->len,in->s);
goto error;
}
name.len = p - name.s;
trim(&name);
if (name.len==6 && strncasecmp(name.s,"family",6)==0)
{
t->subtype = TR_IP_FAMILY;
return p;
}
else if (name.len==4 && strncasecmp(name.s,"ntop",4)==0)
{
t->subtype = TR_IP_NTOP;
return p;
}
else if (name.len == 4 && strncasecmp(name.s,"isip",4) == 0) {
t->subtype = TR_IP_ISIP;
return p;
} else if (name.len == 4 && strncasecmp(name.s,"pton",4) == 0) {
t->subtype = TR_IP_PTON;
return p;
} else if (name.len == 7 && strncasecmp(name.s,"resolve",7) == 0) {
t->subtype = TR_IP_RESOLVE;
return p;
}
LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
name.len, name.s, name.len);
error:
return NULL;
}
char* tr_parse_re(str *in,trans_t *t)
{
char *p,*p0,*ps;
str name,s;
pv_spec_t *spec = NULL;
tr_param_t *tp = NULL;
if (in == NULL || t == NULL)
return NULL;
p = in->s;
name.s = in->s;
/* find next token */
while (is_in_str(p,in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
if (*p == '\0')
{
LM_ERR("invalid transformation: %.*s\n",in->len,in->s);
goto error;
}
name.len = p - name.s;
trim(&name);
if (name.len==5 && strncasecmp(name.s,"subst",5)==0)
{
t->subtype = TR_RE_SUBST;
if(*p!=TR_PARAM_MARKER)
{
LM_ERR("invalid value transformation: %.*s\n",
in->len, in->s);
goto error;
}
p++;
LM_INFO("preparing to parse param\n");
_tr_parse_sparam(p, p0, tp, spec, ps, in, s);
t->params = tp;
tp = 0;
while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
if(*p!=TR_RBRACKET)
{
LM_ERR("invalid value transformation: %.*s!\n",
in->len, in->s);
goto error;
}
return p;
}
LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
name.len, name.s, name.len);
error:
return NULL;
}
void destroy_transformation(trans_t *t)
{
tr_param_t *tp;
tr_param_t *tp0;
if(t==NULL) return;
tp = t->params;
while(tp)
{
tp0 = tp;
tp = tp->next;
free_tr_param(tp0);
}
memset(t, 0, sizeof(trans_t));
}
void free_transformation(trans_t *t)
{
trans_t *t0;
while(t)
{
t0 = t;
t = t->next;
destroy_transformation(t0);
pkg_free(t0);
}
}
void free_tr_param(tr_param_t *tp)
{
tr_param_t *tp0;
if(tp==NULL) return;
while(tp)
{
tp0 = tp;
tp = tp->next;
if(tp0->type==TR_PARAM_SPEC)
pv_spec_free((pv_spec_t*)tp0->v.data);
pkg_free(tp0);
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/maplerain/opensips.git
git@gitee.com:maplerain/opensips.git
maplerain
opensips
opensips
master

搜索帮助

23e8dbc6 1850385 7e0993f3 1850385