1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086 |
- /*
- * $Id$
- *
- * Copyright (C) 2006 iptelorg GmbH
- *
- * This file is part of ser, a free SIP server.
- *
- * ser 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
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- * [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <ctype.h>
- #include "../../route.h"
- #include "../../sr_module.h"
- #include "../../mem/mem.h"
- #include "../../str.h"
- #include "../../error.h"
- #include "../../config.h"
- #include "../../trim.h"
- #include "../../select.h"
- #include "../../ut.h"
- #include "../../modules/xprint/xp_lib.h"
- #include "../../select_buf.h"
- #include "../../globals.h"
- #include "../../route.h"
- #include "../../parser/msg_parser.h"
- #include "../../action.h"
- #include "../../script_cb.h"
- #include "../../dset.h"
- #include "../../usr_avp.h"
- MODULE_VERSION
- #define MODULE_NAME "eval"
- enum {evtVoid=0, evtInt, evtStr};
- struct eval_str {
- str s;
- int cnt;
- };
- struct eval_value {
- union {
- long n;
- struct eval_str *s;
- } u;
- int type;
- };
- struct register_item {
- char *name;
- struct eval_value value;
- struct register_item *next;
- };
- struct stack_item {
- struct eval_value value;
- struct stack_item *prev;
- struct stack_item *next;
- };
- static int stack_no = 0;
- static struct stack_item *stack_head = 0;
- static struct stack_item *stack_tail = 0;
- static struct register_item* registers = 0;
- #define destroy_value(val) { \
- if ((val).type == evtStr && (val).u.s && (val).u.s->cnt > 0) { \
- (val).u.s->cnt--; \
- if ((val).u.s->cnt == 0) \
- pkg_free((val).u.s); \
- } \
- (val).type = evtVoid; \
- }
- #define assign_value(dest, src) { \
- if (&(dest) != &(src)) { \
- destroy_value(dest); \
- dest = src; \
- if ((dest).type == evtStr && (dest).u.s && (dest).u.s->cnt > 0) \
- (dest).u.s->cnt++; \
- } \
- }
- static int get_as_int(struct eval_value *value, long* val) {
- switch (value->type) {
- case evtInt:
- *val = value->u.n;
- return 1;
- case evtStr:
- if (value->u.s->s.s && value->u.s->s.len && value->u.s->s.len <= 25) {
- char *err;
- char buf[25+1];
- memcpy(buf, value->u.s->s.s, value->u.s->s.len);
- buf[value->u.s->s.len] = '\0';
- *val = strtol(buf, &err, 10);
- if (*err == 0)
- return 1;
- }
- ERR(MODULE_NAME": cannot convert '%.*s' as int\n", value->u.s->s.len, value->u.s->s.s);
- return -1;
- default:
- BUG("Bad value type %d\n", value->type);
- return -1;
- }
- }
- static void get_as_str(struct eval_value *value, str *s) {
- static char buf[25];
- switch (value->type) {
- case evtInt:
- s->len = snprintf(buf, sizeof(buf)-1, "%ld", value->u.n);
- s->s = buf;
- break;
- case evtStr:
- *s = value->u.s->s;
- break;
- default:
- s->s = 0;
- s->len = 0;
- break;
- }
- }
- static int get_as_bool(struct eval_value *value) {
- switch (value->type) {
- case evtVoid:
- return 0;
- case evtInt:
- return value->u.n != 0;
- case evtStr:
- return (value->u.s->s.s && value->u.s->s.len > 0);
- default:
- BUG("Bad value type %d\n", value->type);
- return -1;
- }
- }
- static struct eval_str* eval_str_malloc(str* s) {
- struct eval_str* p;
- p = pkg_malloc(sizeof(*p)+s->len);
- if (p) {
- p->s.s = (char*)p+sizeof(*p);
- if (s->len && s->s != 0)
- memcpy(p->s.s, s->s, s->len);
- if (s->s == 0 && s->len)
- s->s = p->s.s;
- p->s.len = s->len;
- p->cnt = 1;
- }
- return p;
- }
- /* taken from modules/textops */
- #define is_space(_p) ((_p) == '\t' || (_p) == '\n' || (_p) == '\r' || (_p) == ' ')
- static void get_uri_and_skip_until_params(str *param_area, str *uri) {
- int i, quoted, uri_pos, uri_done;
- uri->len = 0;
- uri->s = 0;
- uri_done = 0;
- for (i=0; i<param_area->len && param_area->s[i]!=';'; ) { /* [ *(token LSW)/quoted-string ] "<" addr-spec ">" | addr-spec */
- /* skip name */
- for (quoted=0, uri_pos=i; i<param_area->len; i++) {
- if (!quoted) {
- if (param_area->s[i] == '\"') {
- quoted = 1;
- uri_pos = -1;
- }
- else if (param_area->s[i] == '<' || param_area->s[i] == ';' || is_space(param_area->s[i])) break;
- }
- else if (param_area->s[i] == '\"' && param_area->s[i-1] != '\\') quoted = 0;
- }
- if (uri_pos >= 0 && !uri_done) {
- uri->s = param_area->s+uri_pos;
- uri->len = param_area->s+i-uri->s;
- }
- /* skip uri */
- while (i<param_area->len && is_space(param_area->s[i])) i++;
- if (i<param_area->len && param_area->s[i]=='<') {
- uri->s = param_area->s+i;
- uri->len = 0;
- for (quoted=0; i<param_area->len; i++) {
- if (!quoted) {
- if (param_area->s[i] == '\"') quoted = 1;
- else if (param_area->s[i] == '>') {
- uri->len = param_area->s+i-uri->s+1;
- uri_done = 1;
- break;
- }
- }
- else if (param_area->s[i] == '\"' && param_area->s[i-1] != '\\') quoted = 0;
- }
- }
- }
- param_area->s+= i;
- param_area->len-= i;
- }
- static int find_next_value(char** start, char* end, str* val, str* lump_val) {
- int quoted = 0;
- lump_val->s = *start;
- while (*start < end && is_space(**start) ) (*start)++;
- val->s = *start;
- while ( *start < end && (**start != ',' || quoted) ) {
- if (**start == '\"' && (!quoted || (*start)[-1]!='\\') )
- quoted = ~quoted;
- (*start)++;
- }
- val->len = *start - val->s;
- while (val->len > 0 && is_space(val->s[val->len-1])) val->len--;
- /* we cannot automatically strip quotes!!! an example why: "name" <sip:ssss>;param="bar"
- if (val->len >= 2 && val->s[0] == '\"' && val->s[val->len-1] == '\"') {
- val->s++;
- val->len -= 2;
- }
- */
- while (*start < end && **start != ',') (*start)++;
- if (*start < end) {
- (*start)++;
- }
- lump_val->len = *start - lump_val->s;
- return (*start < end);
- }
- #define MAX_HF_VALUES 30
- static int parse_hf_values(str s, int* n, str** vals) {
- static str values[MAX_HF_VALUES];
- char *start, *end;
- str lump_val;
- *n = 0;
- *vals = values;
- if (!s.s) return 1;
- start = s.s;
- end = start+s.len;
- while (start < end) {
- find_next_value(&start, end, &values[*n], &lump_val);
- if (*n >= MAX_HF_VALUES) {
- ERR(MODULE_NAME": too many values\n");
- return -1;
- }
- (*n)++;
- }
- return 1;
- }
- static void destroy_stack() {
- struct stack_item *p;
- while (stack_head) {
- destroy_value(stack_head->value);
- p = stack_head;
- stack_head = stack_head->next;
- pkg_free(p);
- }
- stack_tail = stack_head;
- stack_no = 0;
- }
- static void destroy_register_values() {
- struct register_item *p;
- for (p=registers; p; p=p->next) {
- destroy_value(p->value);
- }
- }
- static void remove_stack_item(struct stack_item *s) {
- if (s->prev)
- s->prev->next = s->next;
- else
- stack_head = s->next;
- if (s->next)
- s->next->prev = s->prev;
- else
- stack_tail = s->prev;
- destroy_value(s->value);
- pkg_free(s);
- stack_no--;
- }
- static void insert_stack_item(struct stack_item *s, struct stack_item *pivot, int behind) {
- if (stack_head == NULL) {
- s->prev = s->next = 0;
- }
- else if (behind) {
- if (pivot) {
- s->next = pivot->next;
- s->prev = pivot;
- }
- else {
- s->next = 0;
- s->prev = stack_tail; /* bottom (tail) */
- }
- }
- else {
- if (pivot) {
- s->prev = pivot->prev;
- s->next = pivot;
- }
- else {
- s->next = stack_head; /* top (head) */
- s->prev = 0;
- }
- }
- if (!s->prev)
- stack_head = s;
- else
- s->prev->next = s;
- if (!s->next)
- stack_tail = s;
- else
- s->next->prev = s;
- stack_no++;
- }
- static int declare_register(modparam_t type, char* param) {
- struct register_item **p;
- char *c;
- for (c=param; *c; c++) {
- if ( (*c >= 'a' && *c <= 'z') ||
- (*c >= 'A' && *c <= 'Z') ||
- (*c >= '0' && *c <= '9') ||
- (*c == '_') ) {
- ;
- } else {
- ERR(MODULE_NAME": illegal register name\n");
- return E_CFG;
- }
- }
- for (p = ®isters; *p!= 0; p = &(*p)->next);
- *p = pkg_malloc(sizeof(**p));
- if (!*p) return E_OUT_OF_MEM;
- memset(*p, 0, sizeof(**p));
- (*p)->name = param;
- return 0;
- }
- static int mod_pre_script_cb(struct sip_msg *msg, unsigned int flags, void *param) {
- destroy_stack();
- destroy_register_values();
- return 1;
- }
- static struct register_item* find_register(char* s, int len) {
- struct register_item *p;
- for (p=registers; p; p=p->next) {
- if (strlen(p->name) == len && strncasecmp(p->name, s, len) == 0)
- break;
- }
- return p;
- }
- static struct stack_item* find_stack_item(int n) {
- struct stack_item *p;
- if ((n >= 0 && n >= stack_no) || (n<0 && -n > stack_no)) {
- return NULL;
- }
- p = NULL;
- if (n >= 0) {
- for (p = stack_head; p && n>0; p=p->next, n--);
- }
- else {
- for (p = stack_tail, n=-n-1; p && n>0; p=p->prev, n--);
- }
- return p;
- }
- /* module exported functions */
- static void print_eval_value(struct eval_value* v) {
- switch (v->type) {
- case evtStr:
- if (v->u.s)
- fprintf(stderr, "s:'%.*s', cnt:%d\n", v->u.s->s.len, v->u.s->s.s, v->u.s->cnt);
- else
- fprintf(stderr, "s:<null>\n");
- break;
- case evtInt:
- fprintf(stderr, "i:%ld\n", v->u.n);
- break;
- default:;
- fprintf(stderr, "type:%d\n", v->type);
- break;
- }
- }
- static int eval_dump_func(struct sip_msg *msg, char *param1, char *param2) {
- struct stack_item *si;
- struct register_item *ri;
- int i;
- fprintf(stderr, "Stack (no=%d):\n", stack_no);
- for (si=stack_head, i=0; si; si=si->next, i++) {
- fprintf(stderr, "# %.2d ", i);
- print_eval_value(&si->value);
- }
- for (si=stack_tail, i=-1; si; si=si->prev, i--) {
- fprintf(stderr, "#%.2d ", i);
- print_eval_value(&si->value);
- }
- fprintf(stderr, "Registers:\n");
- for (ri=registers; ri; ri=ri->next) {
- fprintf(stderr, "%s: ", ri->name);
- print_eval_value(&ri->value);
- }
- return 1;
- }
- static int xlbuf_size = 4096;
- static xl_print_log_f* xl_print = NULL;
- static xl_parse_format_f* xl_parse = NULL;
- #define NO_SCRIPT -1
- enum {esotAdd, esotInsert, esotXchg, esotPut, esotGet, esotPop, esotAddValue, esotInsertValue};
- enum {esovtInt, esovtStr, esovtAvp, esovtXStr, esovtRegister, esovtFunc, esovtSelect};
- enum {esofNone=0, esofTime, esofUuid, esofStackNo};
- struct eval_location_func {
- int type;
- char *name;
- };
- static struct eval_location_func loc_functions[] = {
- {esofTime, "time"},
- {esofUuid, "uuid"},
- {esofStackNo, "stackno"},
- {esofNone, NULL}
- };
- struct eval_location {
- int value_type;
- union {
- int n;
- struct eval_str s;
- xl_elog_t* xl;
- struct register_item *reg;
- avp_ident_t avp;
- select_t* select;
- struct eval_location_func *func;
- } u;
- };
- struct eval_stack_oper {
- int oper_type;
- struct eval_location loc;
- };
- static int parse_location(str s, struct eval_location *p) {
- if (s.len >= 2 && s.s[1] == ':') {
- switch (s.s[0]) {
- case 'r':
- p->u.reg = find_register(s.s+2, s.len-2);
- if (!p->u.reg) {
- ERR(MODULE_NAME": register '%.*s' not found\n", s.len-2, s.s+2);
- return E_CFG;
- }
- p->value_type = esovtRegister;
- break;
- case 'x':
- if (!xl_print) {
- xl_print=(xl_print_log_f*)find_export("xprint", NO_SCRIPT, 0);
- if (!xl_print) {
- ERR(MODULE_NAME": cannot find \"xprint\", is module xprint loaded?\n");
- return E_UNSPEC;
- }
- }
- if (!xl_parse) {
- xl_parse=(xl_parse_format_f*)find_export("xparse", NO_SCRIPT, 0);
- if (!xl_parse) {
- ERR(MODULE_NAME": cannot find \"xparse\", is module xprint loaded?\n");
- return E_UNSPEC;
- }
- }
- if(xl_parse(s.s+2, &p->u.xl) < 0) {
- ERR(MODULE_NAME": wrong xl_lib format '%s'\n", s.s+2);
- return E_UNSPEC;
- }
- p->value_type = esovtXStr;
- break;
- case 'f': {
- struct eval_location_func* f;
- s.s += 2;
- s.len -= 2;
- for (f=loc_functions; f->type != esofNone; f++) {
- if (strlen(f->name)==s.len && strncasecmp(s.s, f->name, s.len) == 0) {
- p->value_type = esovtFunc;
- p->u.func = f;
- break;
- }
- }
- if (!f) {
- ERR(MODULE_NAME": unknown function '%.*s'\n", s.len, s.s);
- return E_CFG;
- }
- break;
- }
- case 's':
- s.s += 2;
- s.len -= 2;
- /* no break */
- default:
- p->u.s.s = s;
- p->u.s.cnt = 0;
- p->value_type = esovtStr;
- break;
- }
- }
- else {
- char *err;
- if (s.len > 1 && s.s[0]=='$') {
- s.s++;
- s.len--;
- if (parse_avp_ident(&s, &p->u.avp) == 0) {
- if (p->u.avp.flags & AVP_NAME_RE) {
- ERR(MODULE_NAME": avp regex not allowed\n");
- return E_CFG;
- }
- p->value_type = esovtAvp;
- return 1;
- }
- s.s--;
- s.len++;
- }
- else if (s.len > 1 && s.s[0]=='@') {
- if (parse_select(&s.s, &p->u.select) >= 0) {
- p->value_type = esovtSelect;
- return 1;
- }
- }
- p->u.n = strtol(s.s, &err, 10);
- if (*err) {
- p->u.s.s = s;
- p->u.s.cnt = 0;
- p->value_type = esovtStr;
- }
- else {
- p->value_type = esovtInt;
- }
- }
- return 1;
- }
- static int eval_xl(struct sip_msg *msg, xl_elog_t* xl, str* s) {
- static char *xlbuf=NULL;
- int xllen = 0;
- if (!xlbuf) {
- xlbuf = (char*) pkg_malloc((xlbuf_size+1)*sizeof(char));
- if (!xlbuf) {
- ERR(MODULE_NAME": eval_xl: No memory left for format buffer\n");
- return E_OUT_OF_MEM;
- }
- }
- xllen = xlbuf_size;
- if (xl_print(msg, xl, xlbuf, &xllen) < 0) {
- ERR(MODULE_NAME": eval_xl: Error while formatting result\n");
- return E_UNSPEC;
- }
- s->s = xlbuf;
- s->len = xllen;
- return 1;
- }
- SELECT_F(select_sys_unique)
- static int eval_location(struct sip_msg *msg, struct eval_location* so, struct eval_value* v, int get_static_str) {
- static struct eval_str ss;
- v->type = evtVoid;
- switch (so->value_type) {
- case esovtInt:
- v->type = evtInt;
- v->u.n = so->u.n;
- break;
- case esovtStr:
- v->type = evtStr;
- v->u.s = &so->u.s;
- break;
- case esovtXStr: {
- str s;
- int ret;
- ret = eval_xl(msg, so->u.xl, &s);
- if (ret < 0) return ret;
- if (get_static_str) {
- ss.s = s;
- ss.cnt = 0;
- v->u.s = &ss;
- }
- else {
- v->u.s = eval_str_malloc(&s);
- if (!v->u.s) {
- ERR(MODULE_NAME": out of memory to allocate xl string\n");
- return E_OUT_OF_MEM;
- }
- }
- v->type = evtStr;
- break;
- }
- case esovtRegister:
- if (get_static_str)
- *v = so->u.reg->value; /* do not incement cnt */
- else
- assign_value(*v, so->u.reg->value);
- break;
- case esovtAvp: {
- avp_t* avp;
- avp_value_t val;
- if (so->u.avp.flags & AVP_INDEX_ALL)
- avp = search_first_avp(so->u.avp.flags & ~AVP_INDEX_ALL, so->u.avp.name, &val, NULL);
- else
- avp = search_avp_by_index(so->u.avp.flags, so->u.avp.name, &val, so->u.avp.index);
- if (!avp) {
- ERR(MODULE_NAME": avp '%.*s'[%d] not found\n", so->u.avp.name.s.len, so->u.avp.name.s.s, so->u.avp.index);
- return -1;
- }
- if (avp->flags & AVP_VAL_STR) {
- if (get_static_str) {
- ss.s = val.s;
- ss.cnt = 0;
- v->u.s = &ss;
- }
- else {
- v->u.s = eval_str_malloc(&val.s);
- if (!v->u.s) {
- ERR(MODULE_NAME": out of memory to allocate avp string\n");
- return E_OUT_OF_MEM;
- }
- }
- v->type = evtStr;
- }
- else {
- v->type = evtInt;
- v->u.n = val.n;
- }
- break;
- }
- case esovtSelect: {
- str s;
- int ret = run_select(&s, so->u.select, msg);
- if (ret < 0 || ret > 0) return -1;
- if (get_static_str) {
- ss.s = s;
- ss.cnt = 0;
- v->u.s = &ss;
- }
- else {
- v->u.s = eval_str_malloc(&s);
- if (!v->u.s) {
- ERR(MODULE_NAME": out of memory to allocate select string\n");
- return E_OUT_OF_MEM;
- }
- }
- v->type = evtStr;
- break;
- }
- case esovtFunc: {
- switch (so->u.func->type) {
- case esofTime: {
- time_t stamp;
- stamp = time(NULL);
- v->type = evtInt;
- v->u.n = stamp;
- break;
- }
- case esofUuid: {
- str s;
- select_sys_unique(&s, 0, msg);
- if (get_static_str) {
- ss.s = s;
- ss.cnt = 0;
- v->u.s = &ss;
- }
- else {
- v->u.s = eval_str_malloc(&s);
- if (!v->u.s) {
- ERR(MODULE_NAME": out of memory to allocate uuid string\n");
- return E_OUT_OF_MEM;
- }
- }
- v->type = evtStr;
- break;
- }
- case esofStackNo:
- v->type = evtInt;
- v->u.n = stack_no;
- break;
- default:
- BUG("bad func type (%d)\n", so->u.func->type);
- return -1;
- }
- break;
- }
- default:
- BUG("Bad value type (%d)\n", so->value_type);
- return -1;
- }
- return 1;
- }
- static int fixup_location_12( void** param, int param_no) {
- struct eval_location *so;
- str s;
- s.s = *param;
- s.len = strlen(s.s);
- so = pkg_malloc(sizeof(*so));
- if (!so) return E_OUT_OF_MEM;
- if (parse_location(s, so) < 0) {
- ERR(MODULE_NAME": parse location error '%s'\n", s.s);
- return E_CFG;
- }
- *param = so;
- return 0;
- }
- static int fixup_stack_oper(void **param, int param_no, int oper_type) {
- str s;
- struct eval_stack_oper *p;
- int ret;
- if (param_no == 2) {
- return fixup_location_12(param, param_no);
- }
- p = pkg_malloc(sizeof(*p));
- if (!p) return E_OUT_OF_MEM;
- p->oper_type = oper_type;
- s.s = *param;
- s.len = strlen(s.s);
- *param = p;
- ret = parse_location(s, &p->loc);
- if (ret < 0) return ret;
- switch (p->oper_type) {
- case esotXchg:
- if (p->loc.value_type == esovtAvp || p->loc.value_type == esovtSelect) {
- ERR(MODULE_NAME": avp non supported for xchg\n");
- return E_CFG;
- }
- /* no break */
- case esotPop:
- case esotGet:
- if (p->loc.value_type != esovtRegister && p->loc.value_type != esovtAvp) {
- ERR(MODULE_NAME": non supported read only location\n");
- return E_CFG;
- }
- break;
- default:;
- }
- return 0;
- }
- static int eval_stack_oper_func(struct sip_msg *msg, char *param1, char *param2) {
- int ret, idx;
- struct stack_item *pivot;
- struct eval_stack_oper *so;
- struct run_act_ctx ra_ctx;
- so = (struct eval_stack_oper *)param1;
- if (param2) {
- long l;
- struct eval_value v;
- eval_location(msg, (struct eval_location*) param2, &v, 1);
- ret = get_as_int(&v, &l);
- if (ret < 0) return ret;
- idx = l;
- }
- else {
- switch (so->oper_type) { /* default values */
- case esotAdd:
- case esotAddValue:
- idx = -1;
- break;
- default:
- idx = 0;
- break;
- }
- }
- pivot = find_stack_item(idx);
- if ( !(pivot!=NULL || ((so->oper_type == esotAdd || so->oper_type == esotAddValue) && idx == -1) || ((so->oper_type == esotInsert || so->oper_type == esotInsertValue) && idx == 0)) )
- return -1;
- switch (so->oper_type) {
- case esotGet:
- case esotPop:
- switch (so->loc.value_type) {
- case esovtRegister:
- assign_value(so->loc.u.reg->value, pivot->value);
- if (so->oper_type == esotPop)
- remove_stack_item(pivot);
- return 1;
- case esovtAvp: {
- struct action a;
- avp_spec_t attr;
- a.type = ASSIGN_T;
- a.count = 2;
- a.val[0].type = AVP_ST;
- attr.type = so->loc.u.avp.flags;
- attr.name = so->loc.u.avp.name;
- attr.index = so->loc.u.avp.index;
- a.val[0].u.attr = &attr;
- switch (pivot->value.type) {
- case evtInt:
- a.val[1].type = NUMBER_ST;
- a.val[1].u.number = pivot->value.u.n;
- break;
- case evtStr:
- if (pivot->value.u.s)
- a.val[1].u.str = pivot->value.u.s->s;
- else
- a.val[1].u.str.len = 0;
- a.val[1].type = STRING_ST;
- break;
- default:
- return -1;
- }
- a.next = 0;
- init_run_actions_ctx(&ra_ctx);
- ret = do_action(&ra_ctx, &a, msg);
- if (so->oper_type == esotPop)
- remove_stack_item(pivot);
- return ret<0?-1:1;
- }
- default:
- BUG("Bad value type (%d) for get/pop\n", so->loc.value_type);
- return -1;
- }
- break;
- case esotXchg:
- switch (so->loc.value_type) {
- case esovtRegister: {
- struct eval_value v;
- v = so->loc.u.reg->value;
- so->loc.u.reg->value = pivot->value;
- pivot->value = v;
- return 1;
- }
- default:
- BUG("Bad value type (%d) for xchg\n", so->loc.value_type);
- return -1;
- }
- break;
- case esotInsert:
- case esotAdd:
- case esotPut: {
- struct eval_value v;
- eval_location(msg, &so->loc, &v, 0);
- if (so->oper_type == esotInsert || so->oper_type == esotAdd) {
- struct stack_item *si;
- si = pkg_malloc(sizeof(*si));
- if (!si) {
- ERR(MODULE_NAME": out of memory\n");
- destroy_value(v);
- return -1;
- }
- si->value = v;
- insert_stack_item(si, pivot, so->oper_type == esotAdd);
- return 1;
- }
- else {
- destroy_value(pivot->value);
- pivot->value = v;
- return 1;
- }
- break;
- }
- case esotInsertValue:
- case esotAddValue: {
- struct eval_value v;
- str s, *vals;
- int i, n;
- struct eval_str* es;
- struct stack_item *si;
- eval_location(msg, &so->loc, &v, 0);
- get_as_str(&v, &s);
- if ((parse_hf_values(s, &n, &vals) < 0) || n == 0) {
- destroy_value(v);
- return -1;
- }
- si = pkg_malloc(sizeof(*si));
- if (!si) {
- ERR(MODULE_NAME": out of memory\n");
- destroy_value(v);
- return -1;
- }
- si->value.type = evtInt;
- si->value.u.n = n;
- insert_stack_item(si, pivot, so->oper_type == esotAddValue);
- pivot = si;
- for (i=0; i<n; i++) {
- si = pkg_malloc(sizeof(*si));
- if (!si) {
- ERR(MODULE_NAME": out of memory\n");
- destroy_value(v);
- return -1;
- }
- es = eval_str_malloc(vals+i);
- if (!es) {
- ERR(MODULE_NAME": out of memory\n");
- destroy_value(v);
- return -1;
- }
- si->value.type = evtStr;
- si->value.u.s = es;
- insert_stack_item(si, pivot, 1);
- pivot = si;
- }
- destroy_value(v);
- return 1;
- }
- default:
- BUG("Unexpected operation (%d)\n", so->oper_type);
- return -1;
- }
- }
- static int eval_add_fixup( void** param, int param_no) {
- return fixup_stack_oper(param, param_no, esotAdd);
- }
- static int eval_insert_fixup( void** param, int param_no) {
- return fixup_stack_oper(param, param_no, esotInsert);
- }
- static int eval_put_fixup( void** param, int param_no) {
- return fixup_stack_oper(param, param_no, esotPut);
- }
- static int eval_get_fixup( void** param, int param_no) {
- return fixup_stack_oper(param, param_no, esotGet);
- }
- static int eval_pop_fixup( void** param, int param_no) {
- return fixup_stack_oper(param, param_no, esotPop);
- }
- static int eval_xchg_fixup( void** param, int param_no) {
- return fixup_stack_oper(param, param_no, esotXchg);
- }
- static int eval_add_value_fixup( void** param, int param_no) {
- return fixup_stack_oper(param, param_no, esotAddValue);
- }
- static int eval_insert_value_fixup( void** param, int param_no) {
- return fixup_stack_oper(param, param_no, esotInsertValue);
- }
- static int eval_remove_func(struct sip_msg *msg, char *param1, char *param2) {
- struct stack_item *p, *p2;
- int ret, len, start;
- struct eval_value v;
- if (param1) {
- long l;
- eval_location(msg, (struct eval_location*) param1, &v, 1);
- ret = get_as_int(&v, &l);
- if (ret < 0) return ret;
- start = l;
- }
- else
- start = 0;
- p = find_stack_item(start);
- if (p) {
- if (param2) {
- long l;
- eval_location(msg, (struct eval_location*) param2, &v, 1);
- ret = get_as_int(&v, &l);
- if (ret < 0) return ret;
- len = l;
- }
- else
- len = 1;
- if (start < 0) {
- start = stack_no + start;
- if (start < 0) start = 0;
- }
- else {
- if (start > stack_no) start = stack_no;
- }
- if (len < 0) {
- len = stack_no - start + len;
- if (len < 0)
- len = 0;
- }
- else {
- if (start + len > stack_no)
- len = stack_no - start;
- }
- for (; len > 0 && p; len--) {
- p2 = p;
- p = p->next;
- remove_stack_item(p2);
- }
- return 1;
- }
- else
- return -1;
- }
- static int eval_clear_func(struct sip_msg *msg, char *param1, char *param2) {
- int n;
- if (get_int_fparam(&n, msg, (fparam_t*)param1)<0) {
- ERR(MODULE_NAME": eval_clear: Invalid number specified\n");
- return -1;
- }
- if (n & 1)
- destroy_stack();
- if (n & 2)
- destroy_register_values();
- return 1;
- }
- enum {esftNone=0, esftAdd, esftSub, esftMultiplication, esftDivision, esftModulo, esftNeg, esftAbs, esftSgn, esftDec, esftInc,
- esftConcat, esftSubstr, esftStrLen, esftStrStr, esftStrDel, esftStrUpper, esftStrLower,
- esftCastAsInt, esftCastAsStr,
- esftValueAt, esftValueUris, esftValueRev, esftSubValue, esftValueCount, esftValueConcat, esftStrValueAt,
- esftGetUri,
- esftAnd, esftOr, esftNot, esftBitAnd, esftBitOr, esftBitNot, esftBitXor, esftEQ, esftNE, esftGT, esftGE, esftLW, esftLE};
- struct eval_function_def {
- int type;
- char *name;
- int arg_no;
- };
- static struct eval_function_def eval_functions[] = {
- {esftAdd, "+", 2},
- {esftSub, "-", 2},
- {esftMultiplication, "*", 2},
- {esftDivision, "/", 2},
- {esftModulo, "%", 2},
- {esftNeg, "neg", 1},
- {esftAbs, "abs", 1},
- {esftDec, "dec", 1},
- {esftInc, "inc", 1},
- {esftSgn, "sgn", 1},
- {esftConcat, "concat", 2},
- {esftSubstr, "substr", 3},
- {esftStrLen, "strlen", 1},
- {esftStrStr, "strstr", 2},
- {esftStrDel, "strdel", 3},
- {esftStrUpper, "strupper", 1},
- {esftStrLower, "strlower", 1},
- {esftCastAsInt, "(int)", 1},
- {esftCastAsStr, "(str)", 1},
- {esftValueAt, "valat", 2},
- {esftValueUris, "valuris", 1},
- {esftValueRev, "valrev", 1},
- {esftSubValue, "subval", 3},
- {esftValueCount, "valcount", 1},
- {esftValueConcat, "valconcat", 1},
- {esftStrValueAt, "strvalat", 2},
- {esftGetUri, "geturi", 1},
- {esftAnd, "&&", 2},
- {esftOr, "||", 2},
- {esftNot, "!", 1},
- {esftBitAnd, "&", 2},
- {esftBitOr, "|", 2},
- {esftBitNot, "~", 1},
- {esftBitXor, "^", 2},
- {esftEQ, "==", 2},
- {esftNE, "!=", 2},
- {esftGT, ">", 2},
- {esftGE, ">=", 2},
- {esftLW, "<", 2},
- {esftLE, "<=", 2},
- {esftNone, NULL}
- };
- struct eval_function {
- int resolved; /* is oper.d valid ? */
- union {
- struct eval_function_def *d;
- struct eval_location loc;
- } oper;
- struct eval_function* next;
- };
- static int eval_stack_func_fixup( void** param, int param_no) {
- char *c, *c2;
- struct eval_function_def* d;
- struct eval_function **p, *head;
- if (param_no == 2) {
- return fixup_location_12(param, param_no);
- }
- head = 0;
- p = &head;
- c = *param;
- while (*c) {
- str s;
- struct eval_location so;
- while( (*c<=' ' || *c == ',') && *c ) c++;
- if (*c == '\0')
- break;
- c2 = c;
- while (*c && *c!=',') c++;
- while (c > c2 && *(c-1) <= ' ') c--;
- s.s = c2;
- s.len = c-c2;
- if (parse_location(s, &so) < 0) {
- ERR(MODULE_NAME": parse operation error near '%s'\n", c2);
- return E_CFG;
- }
- *p = pkg_malloc(sizeof(**p));
- if (!*p) return E_OUT_OF_MEM;
- (*p)->next = 0;
- switch (so.value_type) {
- case esovtStr:
- for (d=eval_functions; d->type; d++) {
- if (strlen(d->name) == so.u.s.s.len && strncasecmp(d->name, so.u.s.s.s, so.u.s.s.len)==0) {
- (*p)->oper.d = d;
- break;
- }
- }
- if (!d->type) {
- ERR(MODULE_NAME": unknown eval function near '%s'\n", so.u.s.s.s);
- return E_CFG;
- }
- (*p)->resolved = 1;
- break;
- case esovtAvp:
- case esovtXStr:
- case esovtRegister:
- case esovtSelect:
- case esovtFunc:
- (*p)->oper.loc = so;
- (*p)->resolved = 0;
- break;
- default:
- ERR(MODULE_NAME": location %d not allowed\n", so.value_type);
- return E_CFG;
- }
- p = &(*p)->next;
- }
- *param = head;
- return 0;
- }
- #ifndef _GNU_SOURCE
- void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);
- #endif
- static int eval_stack_func_func(struct sip_msg *msg, char *param1, char *param2) {
- struct eval_function *f;
- struct stack_item *pivot;
- struct eval_function_def *d;
- int stack_idx = 0;
- int ret = -1;
- if (param2) {
- long l;
- int ret;
- struct eval_value v;
- eval_location(msg, (struct eval_location*) param2, &v, 1);
- ret = get_as_int(&v, &l);
- if (ret < 0) return ret;
- stack_idx = l;
- }
- for (f = (struct eval_function*) param1; f; f=f->next, ret = 1) {
- if (f->resolved) {
- d = f->oper.d;
- }
- else {
- str fn;
- struct eval_value v;
- eval_location(msg, &f->oper.loc, &v, 1);
- get_as_str(&v, &fn);
- for (d=eval_functions; d->type; d++) {
- if (strlen(d->name) == fn.len && strncasecmp(d->name, fn.s, fn.len)==0) {
- break;
- }
- }
- if (!d->type) {
- ERR(MODULE_NAME": unknown eval function '%.*s'\n", fn.len, fn.s);
- return -1;
- }
- }
- DEBUG(MODULE_NAME": eval_oper: %s, stack_idx: %d, stack_no: %d\n", d->name, stack_idx, stack_no);
- if ( ((stack_idx >= 0) && (stack_idx+d->arg_no > stack_no)) ||
- ((stack_idx < 0) && (stack_no+stack_idx < 0 || stack_no+stack_idx+d->arg_no > stack_no)) ) {
- ERR(MODULE_NAME": operation out of stack range\n");
- return -1;
- }
- pivot = find_stack_item(stack_idx);
- if (!pivot) {
- BUG("stack test error\n");
- return -1;
- }
- switch (d->type) {
- case esftAdd:
- case esftSub:
- case esftMultiplication:
- case esftDivision:
- case esftModulo:
- case esftAnd:
- case esftOr:
- case esftBitAnd:
- case esftBitOr:
- case esftBitXor: {
- long a, b;
- if (get_as_int(&pivot->value, &a) < 0) return -1;
- if (get_as_int(&pivot->next->value, &b) < 0) return -1;
- switch (d->type) {
- case esftAdd:
- a = a + b;
- break;
- case esftSub:
- a = a - b;
- break;
- case esftMultiplication:
- a = a * b;
- break;
- case esftDivision:
- if (b == 0) {
- ERR(MODULE_NAME": division by zero\n");
- return -1;
- }
- a = a / b;
- break;
- case esftModulo:
- if (b == 0) {
- ERR(MODULE_NAME": division by zero\n");
- return -1;
- }
- a = a % b;
- break;
- case esftAnd:
- a = a && b;
- break;
- case esftOr:
- a = a || b;
- break;
- case esftBitAnd:
- a = a & b;
- break;
- case esftBitOr:
- a = a | b;
- break;
- case esftBitXor:
- a = a ^ b;
- break;
- }
- destroy_value(pivot->value);
- pivot->value.type = evtInt;
- pivot->value.u.n = a;
- remove_stack_item(pivot->next);
- break;
- }
- case esftNeg:
- case esftAbs:
- case esftSgn:
- case esftDec:
- case esftInc:
- case esftNot:
- case esftBitNot:
- case esftCastAsInt: {
- long a;
- if (get_as_int(&pivot->value, &a) < 0) return -1;
- switch (d->type) {
- case esftNeg:
- a = -a;
- break;
- case esftAbs:
- a = abs(a);
- break;
- case esftSgn:
- if (a < 0)
- a = -1;
- else if (a > 0)
- a = 1;
- else
- a = 0;
- break;
- case esftDec:
- a--;
- break;
- case esftInc:
- a++;
- break;
- case esftNot:
- a = !a;
- break;
- case esftBitNot:
- a = ~a;
- break;
- case esftCastAsInt:
- break;
- }
- destroy_value(pivot->value);
- pivot->value.type = evtInt;
- pivot->value.u.n = a;
- break;
- }
- case esftCastAsStr:
- if (pivot->value.type != evtStr) {
- str s;
- get_as_str(&pivot->value, &s);
- destroy_value(pivot->value);
- pivot->value.u.s = eval_str_malloc(&s);
- if (!pivot->value.u.s) {
- ERR(MODULE_NAME": out of memory\n");
- return -1;
- }
- pivot->value.type = evtStr;
- }
- break;
- case esftEQ:
- case esftNE:
- case esftGT:
- case esftGE:
- case esftLW:
- case esftLE: {
- long a;
- if (pivot->value.type == evtStr || pivot->next->value.type == evtStr) {
- str s1, s2;
- int l;
- get_as_str(&pivot->value, &s1);
- get_as_str(&pivot->next->value, &s2);
- l = (s1.len < s2.len)?s1.len:s2.len;
- if (l > 0)
- a = strncasecmp(s1.s, s2.s, l);
- else
- a = 0;
- switch (d->type) {
- case esftEQ:
- a = a == 0 && s1.len == s2.len;
- break;
- case esftNE:
- a = a != 0 || s1.len != s2.len;
- break;
- case esftGT:
- a = a > 0 || (a == 0 && s1.len > s2.len);
- break;
- case esftGE:
- a = a > 0 || (a == 0 && s1.len >= s2.len);
- break;
- case esftLW:
- a = a < 0 || (a == 0 && s1.len < s2.len);
- break;
- case esftLE:
- a = a < 0 || (a == 0 && s1.len <= s2.len);
- break;
- }
- }
- else {
- long b;
- if (get_as_int(&pivot->value, &a) < 0) return -1;
- if (get_as_int(&pivot->next->value, &b) < 0) return -1;
- switch (d->type) {
- case esftEQ:
- a = a == b;
- break;
- case esftNE:
- a = a != b;
- break;
- case esftGT:
- a = a > b;
- break;
- case esftGE:
- a = a >= b;
- break;
- case esftLW:
- a = a < b;
- break;
- case esftLE:
- a = a <= b;
- break;
- }
- }
- destroy_value(pivot->value);
- pivot->value.type = evtInt;
- pivot->value.u.n = a;
- remove_stack_item(pivot->next);
- break;
- }
- case esftConcat: {
- char buf[25];
- str s, s1, s2;
- struct eval_str* es;
- get_as_str(&pivot->value, &s1);
- if (pivot->value.type == evtInt && pivot->next->value.type == evtInt) {
- memcpy(buf, s1.s, s1.len); /* result in static buffer */
- s1.s = buf;
- }
- get_as_str(&pivot->next->value, &s2);
- s.len = s1.len + s2.len;
- s.s = 0;
- es = eval_str_malloc(&s);
- if (!es) {
- ERR(MODULE_NAME": out of memory\n");
- return -1;
- }
- memcpy(s.s, s1.s, s1.len);
- memcpy(s.s+s1.len, s2.s, s2.len);
- destroy_value(pivot->value);
- pivot->value.type = evtStr;
- pivot->value.u.s = es;
- remove_stack_item(pivot->next);
- break;
- }
- case esftSubstr: {
- long start, len;
- str s1;
- struct eval_str* es;
- get_as_str(&pivot->value, &s1);
- if (get_as_int(&pivot->next->value, &start) < 0) return -1;
- if (get_as_int(&pivot->next->next->value, &len) < 0) return -1;
- if (start < 0) {
- start = s1.len + start;
- if (start < 0) start = 0;
- }
- else {
- if (start > s1.len) start = s1.len;
- }
- if (len < 0) {
- len = s1.len - start + len;
- if (len < 0)
- len = 0;
- }
- else {
- if (start + len > s1.len)
- len = s1.len - start;
- }
- s1.s += start;
- s1.len = len;
- es = eval_str_malloc(&s1);
- if (!es) {
- ERR(MODULE_NAME": out of memory\n");
- return -1;
- }
- destroy_value(pivot->value);
- pivot->value.type = evtStr;
- pivot->value.u.s = es;
- remove_stack_item(pivot->next);
- remove_stack_item(pivot->next);
- break;
- }
- case esftStrLen: {
- long len;
- str s1;
- get_as_str(&pivot->value, &s1);
- len = s1.len;
- destroy_value(pivot->value);
- pivot->value.type = evtInt;
- pivot->value.u.n = len;
- break;
- }
- case esftStrStr: {
- char buf[25], *p;
- str s1, s2;
- get_as_str(&pivot->value, &s1);
- if (pivot->value.type == evtInt && pivot->next->value.type == evtInt) {
- memcpy(buf, s1.s, s1.len); /* result in static buffer */
- s1.s = buf;
- }
- get_as_str(&pivot->next->value, &s2);
- p = (char *) memmem(s1.s, s1.len, s2.s, s2.len);
- destroy_value(pivot->value);
- pivot->value.type = evtInt;
- pivot->value.u.n = p?p-s1.s:-1;
- remove_stack_item(pivot->next);
- break;
- }
- case esftStrDel: {
- long start, len;
- str s1, s;
- struct eval_str* es;
- get_as_str(&pivot->value, &s1);
- if (get_as_int(&pivot->next->value, &start) < 0) return -1;
- if (get_as_int(&pivot->next->next->value, &len) < 0) return -1;
- if (start < 0) {
- start = s1.len + start;
- if (start < 0) start = 0;
- }
- else {
- if (start > s1.len) start = s1.len;
- }
- if (len < 0) {
- len = s1.len - start + len;
- if (len < 0)
- len = 0;
- }
- else {
- if (start + len > s1.len)
- len = s1.len - start;
- }
- s.s = 0;
- s.len = s1.len - len;
- es = eval_str_malloc(&s);
- if (!es) {
- ERR(MODULE_NAME": out of memory\n");
- return -1;
- }
- if (start > 0)
- memcpy(s.s, s1.s, start);
- memcpy(s.s+start, s1.s+start+len, s1.len-(start+len));
- destroy_value(pivot->value);
- pivot->value.type = evtStr;
- pivot->value.u.s = es;
- remove_stack_item(pivot->next);
- remove_stack_item(pivot->next);
- break;
- }
- case esftStrUpper:
- case esftStrLower: {
- str s1;
- int i;
- struct eval_str* es;
- get_as_str(&pivot->value, &s1);
- es = eval_str_malloc(&s1);
- if (!es) {
- ERR(MODULE_NAME": out of memory\n");
- return -1;
- }
- for (i=0; i<es->s.len; i++)
- es->s.s[i] = (d->type == esftStrUpper) ? toupper(es->s.s[i]) : tolower(es->s.s[i]);
- destroy_value(pivot->value);
- pivot->value.type = evtStr;
- pivot->value.u.s = es;
- break;
- }
- case esftValueAt: {
- str s1, *vals;
- long idx;
- int n;
- struct eval_str* es;
- get_as_str(&pivot->value, &s1);
- if (get_as_int(&pivot->next->value, &idx) < 0) return -1;
- if (parse_hf_values(s1, &n, &vals) < 0) return -1;
- if (idx < 0|| idx >= n) {
- ERR(MODULE_NAME": index (%ld) of of range (%d)\n", idx, n);
- return -1;
- }
- es = eval_str_malloc(vals+idx);
- if (!es) {
- ERR(MODULE_NAME": out of memory\n");
- return -1;
- }
- destroy_value(pivot->value);
- pivot->value.type = evtStr;
- pivot->value.u.s = es;
- remove_stack_item(pivot->next);
- break;
- }
- case esftStrValueAt: {
- char buf[25];
- str s1, s2, *vals;
- int i, n;
- get_as_str(&pivot->value, &s1);
- if (pivot->value.type == evtInt && pivot->next->value.type == evtInt) {
- memcpy(buf, s1.s, s1.len); /* result in static buffer */
- s1.s = buf;
- }
- get_as_str(&pivot->next->value, &s2);
- if (parse_hf_values(s1, &n, &vals) < 0) return -1;
- for (i=0; i<n; i++) {
- if (s2.len == vals[i].len && strncmp(s2.s, vals[i].s, s2.len) == 0)
- break;
- }
- destroy_value(pivot->value);
- pivot->value.type = evtInt;
- pivot->value.u.n = (i>=n)?-1:i;
- remove_stack_item(pivot->next);
- break;
- }
- case esftValueCount: {
- str s1, *vals;
- int n;
- get_as_str(&pivot->value, &s1);
- if (parse_hf_values(s1, &n, &vals) < 0) return -1;
- destroy_value(pivot->value);
- pivot->value.type = evtInt;
- pivot->value.u.n = n;
- break;
- }
- case esftSubValue: {
- long start, len;
- int i, n, pos;
- str s1, s, *vals;
- struct eval_str* es;
- get_as_str(&pivot->value, &s1);
- if (get_as_int(&pivot->next->value, &start) < 0) return -1;
- if (get_as_int(&pivot->next->next->value, &len) < 0) return -1;
- if (parse_hf_values(s1, &n, &vals) < 0) return -1;
- if (start < 0) {
- start = n + start;
- if (start < 0) start = 0;
- }
- else {
- if (start > n) start = n;
- }
- if (len < 0) {
- len = n - start + len;
- if (len < 0)
- len = 0;
- }
- else {
- if (start + len > n)
- len = n - start;
- }
- s.len = 0;
- for (i=0; i<len; i++) {
- s.len += vals[start+i].len+1/*delim*/;
- }
- if (s.len)
- s.len--;
- s.s = 0;
- es = eval_str_malloc(&s);
- if (!es) {
- ERR(MODULE_NAME": out of memory\n");
- return -1;
- }
- for (i=0, pos=0; i<len; i++) {
- if (pos > 0)
- s.s[pos++] = ',';
- memcpy(s.s+pos, vals[start+i].s, vals[start+i].len);
- pos += vals[start+i].len;
- }
- destroy_value(pivot->value);
- pivot->value.type = evtStr;
- pivot->value.u.s = es;
- remove_stack_item(pivot->next);
- remove_stack_item(pivot->next);
- break;
- }
- case esftValueConcat: {
- long n;
- int i, pos;
- str s1, s;
- struct eval_str* es;
- struct stack_item *si;
- if (get_as_int(&pivot->value, &n) < 0) return -1;
- for (si=pivot->next, s.len=0, i=0; i<n && si; i++, si=si->next) {
- get_as_str(&si->value, &s1);
- s.len += s1.len+1;
- }
- if (s.len)
- s.len--;
- s.s = 0;
- es = eval_str_malloc(&s);
- if (!es) {
- ERR(MODULE_NAME": out of memory\n");
- return -1;
- }
- for (si=pivot->next, i=0, pos=0; i<n && si; i++, si=si->next) {
- if (pos > 0)
- s.s[pos++] = ',';
- get_as_str(&si->value, &s1);
- memcpy(s.s+pos, s1.s, s1.len);
- pos += s1.len;
- }
- destroy_value(pivot->value);
- pivot->value.type = evtStr;
- pivot->value.u.s = es;
- for (si=pivot->next, i=0; i<n && si; i++) {
- struct stack_item *si2;
- si2 = si;
- si=si->next;
- remove_stack_item(si2);
- }
- break;
- }
- case esftValueRev: {
- int i, n, pos;
- str s1, s, *vals;
- struct eval_str* es;
- get_as_str(&pivot->value, &s1);
- if (parse_hf_values(s1, &n, &vals) < 0) return -1;
- s.len = 0;
- for (i=0; i<n; i++) {
- s.len += vals[i].len+1/*delim*/;
- }
- if (s.len)
- s.len--;
- s.s = 0;
- es = eval_str_malloc(&s);
- if (!es) {
- ERR(MODULE_NAME": out of memory\n");
- return -1;
- }
- for (i=n-1, pos=0; i>=0; i--) {
- if (pos > 0)
- s.s[pos++] = ',';
- memcpy(s.s+pos, vals[i].s, vals[i].len);
- pos += vals[i].len;
- }
- destroy_value(pivot->value);
- pivot->value.type = evtStr;
- pivot->value.u.s = es;
- break;
- }
- case esftValueUris: {
- int i, n, pos;
- str s1, s, *vals;
- struct eval_str* es;
- get_as_str(&pivot->value, &s1);
- if (parse_hf_values(s1, &n, &vals) < 0) return -1;
- s.len = 0;
- for (i=0; i<n; i++) {
- s.len += vals[i].len+1/*delim*/;
- }
- if (s.len)
- s.len--;
- s.s = 0;
- es = eval_str_malloc(&s);
- if (!es) {
- ERR(MODULE_NAME": out of memory\n");
- return -1;
- }
- for (i=0, pos=0; i<n; i++) {
- str hval1, huri;
- if (pos > 0)
- s.s[pos++] = ',';
- hval1 = *(vals+i);
- get_uri_and_skip_until_params(&hval1, &huri);
- if (huri.len) {
- /* TODO: normalize uri, lowercase except quoted params */
- memcpy(s.s+pos, huri.s, huri.len);
- pos += huri.len;
- }
- }
- es->s.len = pos;
- destroy_value(pivot->value);
- pivot->value.type = evtStr;
- pivot->value.u.s = es;
- break;
- }
- case esftGetUri: {
- str s1, huri;
- struct eval_str* es;
- get_as_str(&pivot->value, &s1);
- get_uri_and_skip_until_params(&s1, &huri);
- if (huri.len && *(huri.s) == '<') {
- huri.s++; /* strip < & > */
- huri.len-=2;
- }
- es = eval_str_malloc(&huri);
- if (!es) {
- ERR(MODULE_NAME": out of memory\n");
- return -1;
- }
- destroy_value(pivot->value);
- pivot->value.type = evtStr;
- pivot->value.u.s = es;
- break;
- }
- default:
- BUG("Bad operation %d\n", d->type);
- return -1;
- }
- }
- return ret;
- }
- static int eval_while_fixup(void **param, int param_no) {
- if (param_no == 2) {
- return fixup_location_12(param, param_no);
- }
- else if (param_no == 1) {
- int n;
- n = route_get(&main_rt, (char*) *param);
- if (n == -1) {
- ERR(MODULE_NAME": eval_while: bad route\n");
- return E_CFG;
- }
- pkg_free(*param);
- *param=(void*) (intptr_t) n;
- }
- return 0;
- }
- static int eval_while_func(struct sip_msg *msg, char *route_no, char *param2) {
- int ret, idx;
- struct stack_item *pivot;
- struct run_act_ctx ra_ctx;
- if (param2) {
- long l;
- struct eval_value v;
- eval_location(msg, (struct eval_location*) param2, &v, 1);
- ret = get_as_int(&v, &l);
- if (ret < 0) return ret;
- idx = l;
- }
- else {
- idx = 0; /* default values */
- }
- ret = -1;
- while (1) {
- pivot = find_stack_item(idx);
- if (!pivot) break;
- if (get_as_bool(&pivot->value) <= 0) break;
- if ((intptr_t)route_no >= main_rt.idx) {
- BUG("invalid routing table number #%d of %d\n", (int)(intptr_t) route_no, main_rt.idx);
- return -1;
- }
- if (!main_rt.rlist[(intptr_t) route_no]) {
- WARN(MODULE_NAME": route not declared (hash:%d)\n", (int)(intptr_t) route_no);
- return -1;
- }
- /* exec the routing script */
- init_run_actions_ctx(&ra_ctx);
- ret = run_actions(&ra_ctx, main_rt.rlist[(intptr_t) route_no], msg);
- if (ret <= 0) break;
- }
- return ret;
- }
- static int eval_while_stack_func(struct sip_msg *msg, char *route_no, char *param2) {
- int ret, count;
- struct run_act_ctx ra_ctx;
-
- if (param2) {
- long l;
- struct eval_value v;
- eval_location(msg, (struct eval_location*) param2, &v, 1);
- ret = get_as_int(&v, &l);
- if (ret < 0) return ret;
- count = l;
- }
- else {
- count = 0; /* default values */
- }
- ret = -1;
- while ((count >= 0 && stack_no > count) || (count < 0 && stack_no < -count)) {
- if ((intptr_t)route_no >= main_rt.idx) {
- BUG("invalid routing table number #%d of %d\n", (int)(intptr_t) route_no, main_rt.idx);
- return -1;
- }
- if (!main_rt.rlist[(intptr_t) route_no]) {
- WARN(MODULE_NAME": route not declared (hash:%d)\n", (int)(intptr_t) route_no);
- return -1;
- }
- /* exec the routing script */
- init_run_actions_ctx(&ra_ctx);
- ret = run_actions(&ra_ctx, main_rt.rlist[(intptr_t) route_no], msg);
- if (ret <= 0) break;
- }
- return ret;
- }
- /* select functions */
- static int sel_value2str(str* res, struct eval_value *v, int force_copy) {
- res->len = 0;
- switch (v->type) {
- case evtInt: {
- char buf[30];
- res->len = snprintf(buf, sizeof(buf)-1, "%ld", v->u.n);
- res->s = get_static_buffer(res->len);
- if (res->s)
- memcpy(res->s, buf, res->len);
- else
- res->len = 0;
- break;
- }
- case evtStr:
- if (v->u.s) {
- *res = v->u.s->s;
- if (force_copy && res->len) {
- res->s = get_static_buffer(res->len);
- if (res->s)
- memcpy(res->s, v->u.s->s.s, res->len);
- else
- res->len = 0;
- }
- }
- break;
- }
- return 0;
- }
- static int sel_eval(str* res, select_t* s, struct sip_msg* msg) { /* dummy */
- return 0;
- }
- static int sel_register(str* res, select_t* s, struct sip_msg* msg) {
- if (msg == 0) {
- struct register_item *p = find_register(s->params[2].v.s.s, s->params[2].v.s.len);
- if (p == 0) {
- ERR(MODULE_NAME": select: register '%.*s' not found\n", s->params[2].v.s.len, s->params[2].v.s.s);
- return E_CFG;
- }
- s->params[2].v.p = p;
- s->params[2].type = SEL_PARAM_PTR;
- }
- else {
- return sel_value2str(res, &((struct register_item *)s->params[2].v.p)->value, 0);
- }
- return 0;
- }
- static int sel_get_and_remove(str* res, select_t* s, struct sip_msg* msg) {
- struct stack_item* p;
- res->len = 0;
- p = find_stack_item(s->params[2].v.i);
- if (p) {
- sel_value2str(res, &p->value, 1);
- remove_stack_item(p);
- }
- return 0;
- }
- static int sel_get(str* res, select_t* s, struct sip_msg* msg) {
- struct stack_item* p;
- res->len = 0;
- p = find_stack_item(s->params[2].v.i);
- if (p) {
- sel_value2str(res, &p->value, 0);
- }
- return 0;
- }
- SELECT_F(select_any_nameaddr)
- SELECT_F(select_any_uri)
- SELECT_F(select_anyheader_params)
- select_row_t sel_declaration[] = {
- { NULL, SEL_PARAM_STR, STR_STATIC_INIT(MODULE_NAME), sel_eval, SEL_PARAM_EXPECTED},
- { sel_eval, SEL_PARAM_STR, STR_STATIC_INIT("pop"), sel_get_and_remove, CONSUME_NEXT_INT },
- { sel_eval, SEL_PARAM_STR, STR_STATIC_INIT("get"), sel_get, CONSUME_NEXT_INT },
- { sel_eval, SEL_PARAM_STR, STR_STATIC_INIT("reg"), sel_register, CONSUME_NEXT_STR|FIXUP_CALL },
- { sel_get, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"), select_any_nameaddr, NESTED | CONSUME_NEXT_STR},
- { sel_get, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_any_uri, NESTED | CONSUME_NEXT_STR},
- { sel_get, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_anyheader_params, NESTED},
- { sel_register, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"), select_any_nameaddr, NESTED | CONSUME_NEXT_STR},
- { sel_register, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_any_uri, NESTED | CONSUME_NEXT_STR},
- { sel_register, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_anyheader_params, NESTED},
- /* for backward compatability only, use @sys.unique */
- { sel_eval, SEL_PARAM_STR, STR_STATIC_INIT("uuid"), select_sys_unique, 0},
- { NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
- };
- static int mod_init() {
- register_script_cb(mod_pre_script_cb, REQUEST_CB | ONREPLY_CB | PRE_SCRIPT_CB, 0);
- register_select_table(sel_declaration);
- return 0;
- }
- static int child_init(int rank) {
- return 0;
- }
- static void destroy_mod(void) {
- struct register_item *p;
- destroy_stack();
- destroy_register_values();
- while (registers) {
- p = registers;
- registers = registers->next;
- pkg_free(p);
- }
- }
- /*
- * Exported functions
- */
- static cmd_export_t cmds[] = {
- {MODULE_NAME"_add", eval_stack_oper_func, 2, eval_add_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_add", eval_stack_oper_func, 1, eval_add_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_push", eval_stack_oper_func, 2, eval_add_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_push", eval_stack_oper_func, 1, eval_add_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_insert", eval_stack_oper_func, 2, eval_insert_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_insert", eval_stack_oper_func, 1, eval_insert_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_xchg", eval_stack_oper_func, 2, eval_xchg_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_xchg", eval_stack_oper_func, 1, eval_xchg_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_get", eval_stack_oper_func, 2, eval_get_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_get", eval_stack_oper_func, 1, eval_get_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_put", eval_stack_oper_func, 2, eval_put_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_put", eval_stack_oper_func, 1, eval_put_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_pop", eval_stack_oper_func, 2, eval_pop_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_pop", eval_stack_oper_func, 1, eval_pop_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_add_value", eval_stack_oper_func, 2, eval_add_value_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_add_value", eval_stack_oper_func, 1, eval_add_value_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_insert_value", eval_stack_oper_func, 2, eval_insert_value_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_insert_value", eval_stack_oper_func, 1, eval_insert_value_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_remove", eval_remove_func, 0, fixup_location_12, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_remove", eval_remove_func, 1, fixup_location_12, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_remove", eval_remove_func, 2, fixup_location_12, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_clear", eval_clear_func, 1, fixup_int_12, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_oper", eval_stack_func_func, 2, eval_stack_func_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_oper", eval_stack_func_func, 1, eval_stack_func_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_while", eval_while_func, 1, eval_while_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_while", eval_while_func, 2, eval_while_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_while_stack", eval_while_stack_func, 1, eval_while_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_while_stack", eval_while_stack_func, 2, eval_while_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {MODULE_NAME"_dump", eval_dump_func, 0, 0, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
- {0, 0, 0, 0, 0}
- };
- /*
- * Exported parameters
- */
- static param_export_t params[] = {
- {"declare_register", PARAM_STRING|PARAM_USE_FUNC, (void*) declare_register},
- {"xlbuf_size", PARAM_INT, &xlbuf_size},
- {0, 0, 0}
- };
- struct module_exports exports = {
- MODULE_NAME,
- cmds, /* Exported commands */
- 0, /* RPC */
- params, /* Exported parameters */
- mod_init, /* module initialization function */
- 0, /* response function*/
- destroy_mod, /* destroy function */
- 0, /* oncancel function */
- child_init /* per-child init function */
- };
|