static inline str* extract_mangled_fromuri(str *mangled_from_hdr) { struct to_body from_b; struct hdr_field hdr; char *tmp,*end; if (mangled_from_hdr->len == 0 || mangled_from_hdr->s == NULL) return NULL; end = mangled_from_hdr->s+mangled_from_hdr->len; tmp=parse_hname2(mangled_from_hdr->s,end,&hdr); if (hdr.type==HDR_ERROR_T) { LM_ERR("bad from header\n"); return NULL; } tmp=eat_lws_end(tmp, end); if (tmp >= end) { LM_ERR("empty header\n"); return NULL; } parse_to(tmp,end,&from_b); if (from_b.error == PARSE_ERROR) { LM_ERR("bad from header [%.*s]\n",mangled_from_hdr->len,mangled_from_hdr->s); return NULL; } extracted_from_uri = from_b.uri; free_to_params(&from_b); LM_DBG("extracted from uri [%.*s]\n",extracted_from_uri.len,extracted_from_uri.s); return &extracted_from_uri; }
/** * Parse SPT for SIP Header. * @param doc - the XML document * @param node - the current node * @param sh - structure to fill * @returns 1 on success, 0 on failure */ static int parse_sip_header(xmlDocPtr doc,xmlNodePtr node,ims_sip_header *sh) { xmlNodePtr child; xmlChar *x; char c[256]; int len; struct hdr_field hf; sh->header.s=NULL;sh->header.len=0; sh->content.s=NULL;sh->content.len=0; for(child=node->children ; child ; child=child->next) if (child->type==XML_ELEMENT_NODE) switch (child->name[0]) { case 'H':case 'h': //Header x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); len = strlen((char*)x); memcpy(c,x,len); c[len++]=':'; c[len]=0; space_trim_dup(&(sh->header),(char*)x); parse_hname2(c,c+(len<4?4:len),&hf); sh->type=(short)hf.type; //LOG(L_CRIT,"[%.*s(%d)]\n",sh->header.len,sh->header.s,sh->type); xmlFree(x); break; case 'C':case 'c': //Content x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); space_quotes_trim_dup(&(sh->content),(char*)x); xmlFree(x); break; } return 1; }
/* returns pointer to next header line, and fill hdr_f ; * if at end of header returns pointer to the last crlf (always buf)*/ char* get_sdp_hdr_field(char* buf, char* end, struct hdr_field* hdr) { char* tmp; char *match; if ((*buf)=='\n' || (*buf)=='\r'){ /* double crlf or lflf or crcr */ hdr->type=HDR_EOH_T; return buf; } tmp=parse_hname2(buf, end, hdr); if (hdr->type==HDR_ERROR_T){ LM_ERR("bad header\n"); goto error; } /* eliminate leading whitespace */ tmp=eat_lws_end(tmp, end); if (tmp>=end) { LM_ERR("hf empty\n"); goto error; } /* just skip over it */ hdr->body.s=tmp; /* find end of header */ /* find lf */ do{ match=memchr(tmp, '\n', end-tmp); if (match){ match++; }else { LM_ERR("bad body for <%s>(%d)\n", hdr->name.s, hdr->type); tmp=end; goto error; } tmp=match; }while( match<end &&( (*match==' ')||(*match=='\t') ) ); tmp=match; hdr->body.len=match-hdr->body.s; /* jku: if \r covered by current length, shrink it */ trim_r( hdr->body ); hdr->len=tmp-hdr->name.s; return tmp; error: LM_DBG("error exit\n"); hdr->type=HDR_ERROR_T; hdr->len=tmp-hdr->name.s; return tmp; }
/** * parse_hname2_short() - safer version to parse header name stored in short buffers * - parse_hanem2() reads 4 bytes at once, expecting to walk through a buffer * that contains more than the header name (e.g., sip msg buf, full header buf * with name and body) */ char* parse_hname2_short(char* const begin, const char* const end, struct hdr_field* const hdr) { #define HBUF_MAX_SIZE 256 char hbuf[HBUF_MAX_SIZE]; char *p; if(end-begin>=HBUF_MAX_SIZE-4) { p = q_memchr(begin, ':', end - begin); if(p && p-4> begin) { /* header name termination char found and enough space in buffer after it */ return parse_hname2(begin, end, hdr); } /* not enough space */ return NULL; } /* pad with whitespace - tipycal char after the ':' of the header name */ memset(hbuf, ' ', HBUF_MAX_SIZE); memcpy(hbuf, begin, end-begin); p = parse_hname2(hbuf, hbuf + 4 + (end-begin), hdr); if(!p) return NULL; return begin + (p-hbuf); }
/* * Convert char* header_name to str* parameter */ static int hname_fixup(void** param, int param_no) { str* s; char c; struct hdr_field hdr; s = (str*)pkg_malloc(sizeof(str)); if (!s) { LOG(L_ERR, "textops:hname_fixup: No memory left\n"); return E_UNSPEC; } s->s = (char*)*param; s->len = strlen(s->s); if(s->len==0) { LOG(L_ERR,"textops:hname_fixup: empty header name parameter\n"); pkg_free(s); return E_UNSPEC; } c = s->s[s->len]; s->s[s->len] = ':'; s->len++; if (parse_hname2(s->s, s->s + ((s->len<4)?4:s->len), &hdr)==0) { LOG(L_ERR,"textops:hname_fixup: error parsing header name\n"); pkg_free(s); return E_UNSPEC; } s->len--; s->s[s->len] = c; if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T) { LOG(L_INFO,"INFO:textops:hname_fixup: using " "hdr type (%d) instead of <%.*s>\n", hdr.type, s->len, s->s); pkg_free(s->s); s->s = NULL; s->len = hdr.type; } else { LOG(L_INFO,"INFO:textops:hname_fixup: using " "hdr type name <%.*s>\n", s->len, s->s); } *param = (void*)s; return 0; }
/* returns pointer to next header line, and fill hdr_f ; * if at end of header returns pointer to the last crlf (always buf)*/ char* get_sdp_hdr_field(char* buf, char* end, struct hdr_field* hdr) { char* tmp; char *match; if ((*buf)=='\n' || (*buf)=='\r'){ /* double crlf or lflf or crcr */ hdr->type=HDR_EOH_T; return buf; } tmp=parse_hname2(buf, end, hdr); if (hdr->type==HDR_ERROR_T){ LM_ERR("bad header\n"); goto error; } /* eliminate leading whitespace */ tmp=eat_lws_end(tmp, end); if (tmp>=end) { LM_ERR("hf empty\n"); goto error; } /* if header-field well-known, parse it, find its end otherwise ; * after leaving the hdr->type switch, tmp should be set to the * next header field */ switch(hdr->type){ case HDR_CONTENTTYPE_T: case HDR_CONTENTDISPOSITION_T: /* just skip over it */ hdr->body.s=tmp; /* find end of header */ /* find lf */ do{ match=q_memchr(tmp, '\n', end-tmp); if (match){ match++; }else { LM_ERR("bad body for <%s>(%d)\n", hdr->name.s, hdr->type); tmp=end; goto error; } tmp=match; }while( match<end &&( (*match==' ')||(*match=='\t') ) ); tmp=match; hdr->body.len=match-hdr->body.s; break; default: LM_CRIT("unknown header type %d\n", hdr->type); goto error; } /* jku: if \r covered by current length, shrink it */ trim_r( hdr->body ); hdr->len=tmp-hdr->name.s; return tmp; error: LM_DBG("error exit\n"); hdr->type=HDR_ERROR_T; hdr->len=tmp-hdr->name.s; return tmp; }
/* parse: hname [ ([] | [*] | [number]) ] [ "." param ] */ static int fixup_hname_param(char *hname, struct hname_data** h) { struct hdr_field hdr; char *savep, savec; *h = pkg_malloc(sizeof(**h)); if (!*h) return E_OUT_OF_MEM; memset(*h, 0, sizeof(**h)); memset(&hdr, 0, sizeof(hdr)); eat_spaces(hname); (*h)->hname.s = hname; savep = hname; eat_while_alphanum(hname); (*h)->hname.len = hname - (*h)->hname.s; savec = *hname; *hname = ':'; parse_hname2((*h)->hname.s, (*h)->hname.s+(*h)->hname.len+3, &hdr); *hname = savec; if (hdr.type == HDR_ERROR_T) goto err; (*h)->htype = hdr.type; eat_spaces(hname); savep = hname; if (*hname == '[') { hname++; eat_spaces(hname); savep = hname; (*h)->flags |= HNF_IDX; if (*hname == '*') { (*h)->flags |= HNF_ALL; hname++; } else if (*hname != ']') { char* c; (*h)->idx = strtol(hname, &c, 10); if (hname == c) goto err; hname = c; } eat_spaces(hname); savep = hname; if (*hname != ']') goto err; hname++; } eat_spaces(hname); savep = hname; if (*hname == '.') { hname++; eat_spaces(hname); savep = hname; (*h)->param.s = hname; eat_while_alphanum(hname); (*h)->param.len = hname-(*h)->param.s; if ((*h)->param.len == 0) goto err; } else { (*h)->param.s = hname; } savep = hname; if (*hname != '\0') goto err; (*h)->hname.s[(*h)->hname.len] = '\0'; (*h)->param.s[(*h)->param.len] = '\0'; return 0; err: pkg_free(*h); LOG(L_ERR, "ERROR: textops: cannot parse header near '%s'\n", savep); return E_CFG; }
static int sel_hf_value_name(str* res, select_t* s, struct sip_msg* msg) { struct hname_data* hname; struct hdr_field* hf; str val, hval1, hval2, huri, dummy_name; int r; if (!msg) { struct hdr_field hdr; char buf[50]; int i, n; if (s->params[1].type == SEL_PARAM_STR) { hname = pkg_malloc(sizeof(*hname)); if (!hname) return E_OUT_OF_MEM; memset(hname, 0, sizeof(*hname)); for (i=s->params[1].v.s.len-1; i>0; i--) { if (s->params[1].v.s.s[i]=='_') s->params[1].v.s.s[i]='-'; } i = snprintf(buf, sizeof(buf)-1, "%.*s: X\n", s->params[1].v.s.len, s->params[1].v.s.s); buf[i] = 0; hname->hname = s->params[1].v.s; parse_hname2(buf, buf+i, &hdr); if (hdr.type == HDR_ERROR_T) return E_CFG; hname->htype = hdr.type; s->params[1].v.p = hname; s->params[1].type = SEL_PARAM_PTR; } else { hname = s->params[1].v.p; } n = s->param_offset[select_level+1] - s->param_offset[select_level]; /* number of values before NESTED */ if (n > 2 && s->params[2].type == SEL_PARAM_INT) { hname->idx = s->params[2].v.i; hname->flags |= HNF_IDX; if (hname->idx < -MAX_HF_VALUE_STACK) { LOG(L_ERR, "ERROR: textops: index cannot be lower than %d\n", -MAX_HF_VALUE_STACK); return E_CFG; } if (hname->idx == 0) hname->idx = 1; i = 3; } else { i = 2; hname->idx = 1; } if (n > i && s->params[i].type == SEL_PARAM_STR) { hname->param = s->params[i].v.s; for (i=hname->param.len-1; i>0; i--) { if (hname->param.s[i]=='_') hname->param.s[i]='-'; } } s->params[1].v.p = hname; s->params[1].type = SEL_PARAM_PTR; hname->oper = hnoGetValue; return 0; } res->len = 0; res->s = 0; hname = s->params[1].v.p; switch (hname->oper) { case hnoGetValueUri: if (hname->flags & HNF_ALL || (hname->flags & HNF_IDX) == 0) { char *buf = NULL; int buf_len = 0; hf = 0; do { r = find_next_hf(msg, hname, &hf); if (r < 0) break; if (hf) { char *p; str huri; hval2.len = 0; p = hf->body.s; do { r = find_next_value(&p, hf->body.s+hf->body.len, &hval1, &hval2); get_uri_and_skip_until_params(&hval1, &dummy_name, &huri); if (huri.len) { /* TODO: normalize uri, lowercase except quoted params, add/strip < > */ if (*huri.s == '<') { huri.s++; huri.len -= 2; } } if (res->len == 0) { *res = huri; /* first value, if is also last value then we don't need any buffer */ } else { if (buf) { if (res->len+huri.len+1 > buf_len) { buf_len = res->len+huri.len+1+_ALLOC_INC_SIZE; res->s = pkg_realloc(buf, buf_len); if (!res->s) { pkg_free(buf); LOG(L_ERR, "ERROR: textops: cannot realloc buffer\n"); res->len = 0; return E_OUT_OF_MEM; } buf = res->s; } } else { /* 2nd value */ buf_len = res->len+huri.len+1+_ALLOC_INC_SIZE; buf = pkg_malloc(buf_len); if (!buf) { LOG(L_ERR, "ERROR: testops: out of memory\n"); res->len = 0; return E_OUT_OF_MEM; } /* copy 1st value */ memcpy(buf, res->s, res->len); res->s = buf; } res->s[res->len] = ','; res->len++; if (huri.len) { memcpy(res->s+res->len, huri.s, huri.len); res->len += huri.len; } } } while (r); } } while (hf); if (buf) { res->s = get_static_buffer(res->len); if (!res->s) { pkg_free(buf); res->len = 0; LOG(L_ERR, "ERROR: testops: cannot allocate static buffer\n"); return E_OUT_OF_MEM; } memcpy(res->s, buf, res->len); pkg_free(buf); } } else { r = find_hf_value_idx(msg, hname, &hf, &hval1, &hval2); if (r > 0) { get_uri_and_skip_until_params(&hval1, &dummy_name, res); if (res->len && *res->s == '<') { res->s++; /* strip < & > */ res->len-=2; } } } break; case hnoGetValueName: if ((hname->flags & HNF_ALL) == 0) { r = find_hf_value_idx(msg, hname, &hf, &hval1, &hval2); if (r > 0) { get_uri_and_skip_until_params(&hval1, res, &dummy_name); if (res->len >= 2 && res->s[0] == '\"' && res->s[res->len-1]=='\"' ) { res->s++; /* strip quotes */ res->len-=2; } } } break; case hnoGetValue: if (hname->flags & HNF_ALL || (hname->flags & HNF_IDX) == 0) { char *buf = NULL; int buf_len = 0; hf = 0; do { r = find_next_hf(msg, hname, &hf); if (r < 0) break; if (hf) { char *p; hval2.len = 0; p = hf->body.s; do { r = find_next_value(&p, hf->body.s+hf->body.len, &hval1, &hval2); if (res->len == 0) { *res = hval1; /* first value, if is also last value then we don't need any buffer */ } else { if (buf) { if (res->len+hval1.len+1 > buf_len) { buf_len = res->len+hval1.len+1+_ALLOC_INC_SIZE; res->s = pkg_realloc(buf, buf_len); if (!res->s) { pkg_free(buf); LOG(L_ERR, "ERROR: textops: cannot realloc buffer\n"); res->len = 0; return E_OUT_OF_MEM; } buf = res->s; } } else { /* 2nd value */ buf_len = res->len+hval1.len+1+_ALLOC_INC_SIZE; buf = pkg_malloc(buf_len); if (!buf) { LOG(L_ERR, "ERROR: testops: out of memory\n"); res->len = 0; return E_OUT_OF_MEM; } /* copy 1st value */ memcpy(buf, res->s, res->len); res->s = buf; } res->s[res->len] = ','; res->len++; if (hval1.len) { memcpy(res->s+res->len, hval1.s, hval1.len); res->len += hval1.len; } } } while (r); } } while (hf); if (buf) { res->s = get_static_buffer(res->len); if (!res->s) { pkg_free(buf); res->len = 0; LOG(L_ERR, "ERROR: testops: cannot allocate static buffer\n"); return E_OUT_OF_MEM; } memcpy(res->s, buf, res->len); pkg_free(buf); } } else { r = find_hf_value_idx(msg, hname, &hf, &hval1, &hval2); if (r > 0) { if (hname->param.len) { str d1, d2; get_uri_and_skip_until_params(&hval1, &dummy_name, &huri); if (find_hf_value_param(hname, &hval1, &val, &d1, &d2)) { *res = val; } } else { *res = hval1; } } } break; case hnoGetValue2: r = find_hf_value_idx(msg, hname, &hf, 0, 0); if (r > 0) { if (hname->param.len) { str d1, d2; char c; if (find_hf_value2_param(hname, &hf->body, &val, &d1, &d2, &c)) { *res = val; } } else { *res = hf->body; } } break; default: break; } return 0; }
static int fixup_write_avp(void** param, int param_no) { struct hdr_field hdr; struct fis_param *ap; int flags; int len; char *s; char *p; flags=0; s = (char*)*param; ap = 0 ; if (param_no==1) { if ( *s=='$' ) { /* is variable */ if ((++s)==0) { LOG(L_ERR,"ERROR:avops:fixup_write_avp: bad param 1; " "expected : $[from|to|ruri|hdr] or int/str value\n"); return E_UNSPEC; } if ( (p=strchr(s,'/'))!=0) *(p++) = 0; if ( (!strcasecmp( "from", s) && (flags|=AVPOPS_USE_FROM)) || (!strcasecmp( "to", s) && (flags|=AVPOPS_USE_TO)) || (!strcasecmp( "ruri", s) && (flags|=AVPOPS_USE_RURI)) || (!strcasecmp( "src_ip", s) && (flags|=AVPOPS_USE_SRC_IP)) || (!strcasecmp( "dst_ip", s) && (flags|=AVPOPS_USE_DST_IP)) || (!strncasecmp( "hdr", s, 3) && (flags|=AVPOPS_USE_HDRREQ)) ) { ap = (struct fis_param*)pkg_malloc(sizeof(struct fis_param)); if (ap==0) { LOG(L_ERR,"ERROR:avpops:fixup_write_avp: no more " "pkg mem\n"); return E_OUT_OF_MEM; } memset( ap, 0, sizeof(struct fis_param)); /* any falgs ? */ if(p && !((flags& (AVPOPS_USE_SRC_IP|AVPOPS_USE_DST_IP|AVPOPS_USE_HDRREQ))==0 && ((!strcasecmp("username",p) && (flags|=AVPOPS_FLAG_USER)) || (!strcasecmp("domain", p) && (flags|=AVPOPS_FLAG_DOMAIN)))) ) { LOG(L_ERR,"ERROR:avpops:fixup_write_avp: flag \"%s\"" " unknown!\n", p); return E_UNSPEC; } if (flags&AVPOPS_USE_HDRREQ) { len = strlen(s); if (len<6 || s[3]!='[' || s[len-1]!=']') { LOG(L_ERR,"ERROR:avpops:fixup_write_avp: invalid hdr " "specificatoin \"%s\"\n",s); return E_UNSPEC; } s[len-1] = ':'; /* parse header name */ if (parse_hname2( s+4, s+len, &hdr)==0) { LOG(L_ERR,"BUG:avpops:fixup_write_avp: parse header " "failed\n"); return E_UNSPEC; } if (hdr.type==HDR_OTHER_T) { /* duplicate hdr name */ len -= 5; /*hdr[]*/ ap->val.s.s = pkg_malloc(len+1); if (ap->val.s.s==0) { LOG(L_ERR,"ERROR:avpops:fixup_write_avp: no more " "pkg mem\n"); return E_OUT_OF_MEM; } ap->val.s.len = len; memcpy( ap->val.s.s, s+4, len); ap->val.s.s[len] = 0; DBG("DEBUF:avpops:fixup_write_avp: hdr=<%s>\n", ap->val.s.s); } else { ap->val.n = hdr.type; flags |= AVPOPS_VAL_INT; } } ap->flags = flags|AVPOPS_VAL_NONE; } else { LOG(L_ERR,"ERROR:avpops:fixup_write_avp: source \"%s\"" " unknown!\n", s); return E_UNSPEC; } } else { /* is value */ if ( (ap=parse_intstr_value(s,strlen(s)))==0 ) { LOG(L_ERR,"ERROR:avops:fixup_write_avp: bad param 1; " "expected : $[from|to|ruri] or int/str value\n"); return E_UNSPEC; } } } else if (param_no==2) { if ( (ap=get_attr_or_alias(s))==0 ) { LOG(L_ERR,"ERROR:avpops:fixup_write_avp: bad attribute name" "/alias <%s>\n", s); return E_UNSPEC; } /* attr name is mandatory */ if (ap->flags&AVPOPS_VAL_NONE) { LOG(L_ERR,"ERROR:avpops:fixup_write_avp: you must specify " "a name for the AVP\n"); return E_UNSPEC; } } pkg_free(*param); *param=(void*)ap; return 0; }
int xl_parse_format(char *s, xl_elog_p *el) { char *p, c; int n = 0; xl_elog_p e, e0; struct hdr_field hdr; str name; int avp_flags, avp_index; int_str avp_name; select_t *sel; if(s==NULL || el==NULL) return -1; DBG("XLOG: xl_parse_format: parsing [%s]\n", s); p = s; *el = NULL; e = e0 = NULL; while(*p) { e0 = e; e = pkg_malloc(sizeof(xl_elog_t)); if(!e) goto error; memset(e, 0, sizeof(xl_elog_t)); n++; if(*el == NULL) *el = e; if(e0) e0->next = e; e->text.s = p; while(*p && *p!='%') p++; e->text.len = p - e->text.s; if(*p == '\0') break; p++; switch(*p) { case 'b': p++; switch(*p) { case 'r': e->itf = xl_get_branch; break; case 'R': e->itf = xl_get_branches; break; default: e->itf = xl_get_null; } break; case 'c': p++; switch(*p) { case 'i': e->itf = xl_get_callid; break; case 's': e->itf = xl_get_cseq; break; case 't': e->itf = xl_get_contact; break; default: e->itf = xl_get_null; } break; case 'C': p++; e->hparam.s = p; /* foreground */ switch(*p) { case 'x': case 's': case 'r': case 'g': case 'y': case 'b': case 'p': case 'c': case 'w': case 'S': case 'R': case 'G': case 'Y': case 'B': case 'P': case 'C': case 'W': break; default: e->itf = xl_get_empty; goto error; } p++; /* background */ switch(*p) { case 'x': case 's': case 'r': case 'g': case 'y': case 'b': case 'p': case 'c': case 'w': break; default: e->itf = xl_get_empty; goto error; } /* end */ e->hparam.len = 2; e->itf = xl_get_color; break; case 'd': p++; switch(*p) { case 's': e->itf = xl_get_dset; break; default: e->itf = xl_get_null; } break; case 'f': p++; switch(*p) { case 'u': e->itf = xl_get_from; break; case 't': e->itf = xl_get_from_tag; break; default: e->itf = xl_get_null; } break; case 'H': p++; e->itf = xl_get_host; switch(*p) { case 'n': e->hindex = XL_HOST_NAME; break; case 'd': e->hindex = XL_HOST_DOMAIN; break; case 'f': e->hindex = XL_HOST_FULL; break; case 'i': e->hindex = XL_HOST_IPADDR; break; default: e->hindex = XL_HOST_NULL; break; } break; case 'm': p++; switch(*p) { case 'b': e->itf = xl_get_msg_buf; break; case 'f': e->itf = xl_get_flags; break; case 'i': e->itf = xl_get_msgid; e->hindex = 10; break; case 'l': e->itf = xl_get_msg_len; break; case 'x': e->itf = xl_get_msgid; e->hindex = 16; break; default: e->itf = xl_get_null; } break; case 'n': p++; switch(*p) { case 'h': e->itf = xl_get_nexthop; break; default: e->itf = xl_get_null; } break; case 'p': p++; switch(*p) { case 'p': e->itf = xl_get_pid; e->hindex = 10; break; case 'x': e->itf = xl_get_pid; e->hindex = 16; break; default: e->itf = xl_get_null; } break; case 'r': p++; switch(*p) { case 'm': e->itf = xl_get_method; break; case 'u': e->itf = xl_get_ruri; break; case 's': e->itf = xl_get_status; break; case 'r': e->itf = xl_get_reason; break; case 't': e->itf = xl_get_refer_to; break; default: e->itf = xl_get_null; } break; case 'R': p++; switch(*p) { case 'i': e->itf = xl_get_rcvip; break; case 'p': e->itf = xl_get_rcvport; break; default: e->itf = xl_get_null; } break; case 's': p++; switch(*p) { case 'i': e->itf = xl_get_srcip; break; case 'p': e->itf = xl_get_srcport; break; default: e->itf = xl_get_null; } break; case 't': p++; switch(*p) { case 'u': e->itf = xl_get_to; break; case 't': e->itf = xl_get_to_tag; break; default: e->itf = xl_get_null; } break; case 'T': p++; switch(*p) { case 's': e->itf = xl_get_times; e->hindex = 10; break; case 'f': e->itf = xl_get_timef; break; case 'x': e->itf = xl_get_times; e->hindex = 16; break; default: e->itf = xl_get_null; } break; case 'u': p++; switch(*p) { case 'a': e->itf = xl_get_useragent; break; case 'q': e->itf = xl_get_unique; break; default: e->itf = xl_get_null; } break; case '{': p++; /* we expect a letter */ if((*p < 'A' || *p > 'Z') && (*p < 'a' || *p > 'z')) { LOG(L_ERR, "xlog: xl_parse_format: error parsing format" " [%s] pos [%d]\n", s, (int)(p-s)); goto error; } e->hparam.s = p; while(*p && *p!='}' && *p!='[') p++; if(*p == '\0') { LOG(L_ERR, "xlog: xl_parse_format: error parsing format" " [%s] expecting '}' after position [%d]\n", s, (int)(e->hparam.s-s)); goto error; } e->hparam.len = p - e->hparam.s; /* check if we have index */ if(*p == '[') { p++; if(*p=='-') { p++; if(*p!='1') { LOG(L_ERR, "xlog: xl_parse_format: error" " parsing format [%s] -- only -1 is accepted" " as a negative index\n", s); goto error; } e->hindex = XLOG_PRINT_LAST; p++; } else if (*p=='*') { e->hindex = XLOG_PRINT_ALL; p++; } else { while(*p>='0' && *p<='9') { e->hindex = e->hindex * 10 + *p - '0'; p++; } } if(*p != ']') { LOG(L_ERR, "xlog: xl_parse_format: error parsing format" " [%s] expecting ']' after position [%d]\n", s, (int)(e->hparam.s - s + e->hparam.len)); goto error; } p++; } if(*p != '}') { LOG(L_ERR, "xlog: xl_parse_format: error parsing format" " [%s] expecting '}' after position [%d]!\n", s, (int)(e->hparam.s-s)); goto error; } DBG("xlog: xl_parse_format: header name [%.*s] index [%d]\n", e->hparam.len, e->hparam.s, e->hindex); /* optimize for known headers -- fake header name */ c = e->hparam.s[e->hparam.len]; e->hparam.s[e->hparam.len] = ':'; e->hparam.len++; /* ugly hack for compact header names -- !!fake length!! * -- parse_hname2 expects name buffer length >= 4 */ if (parse_hname2(e->hparam.s, e->hparam.s + ((e->hparam.len<4)?4:e->hparam.len), &hdr)==0) { LOG(L_ERR,"xlog: xl_parse_format: strange error\n"); goto error; } e->hparam.len--; e->hparam.s[e->hparam.len] = c; if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T) { LOG(L_INFO,"INFO:xlog: xl_parse_format: using " "hdr type (%d) instead of <%.*s>\n", hdr.type, e->hparam.len, e->hparam.s); e->hparam.len = hdr.type; e->hparam.s = NULL; } e->itf = xl_get_header; break; case '<': p++; /* we expect a letter */ if((*p < 'A' || *p > 'Z') && (*p < 'a' || *p > 'z')) { LOG(L_ERR, "xlog: xl_parse_format: error parsing format" " [%s] pos [%d]\n", s, (int)(p-s)); goto error; } e->hparam.s = p; while(*p && *p!='>' && *p!='[') p++; if(*p == '\0') { LOG(L_ERR, "xlog: xl_parse_format: error parsing format" " [%s] expecting '>' after position [%d]\n", s, (int)(e->hparam.s-s)); goto error; } e->hparam.len = p - e->hparam.s; /* check if we have index */ if(*p == '[') { p++; if(*p=='-') { p++; if(*p!='1') { LOG(L_ERR, "xlog: xl_parse_format: error" " parsing format [%s] -- only -1 is accepted" " as a negative index\n", s); goto error; } e->hindex = -1; p++; } else { while(*p>='0' && *p<='9') { e->hindex = e->hindex * 10 + *p - '0'; p++; } } if(*p != ']') { LOG(L_ERR, "xlog: xl_parse_format: error parsing format" " [%s] expecting ']' after position [%d]\n", s, (int)(e->hparam.s - s + e->hparam.len)); goto error; } p++; } if(*p != '>') { LOG(L_ERR, "xlog: xl_parse_format: error parsing format" " [%s] expecting '>' after position [%d]!\n", s, (int)(e->hparam.s-s)); goto error; } DBG("xlog: xl_parse_format: AVP [%.*s] index [%d]\n", e->hparam.len, e->hparam.s, e->hindex); e->itf = xl_get_avp; break; case '$': p++; name.s=p; while ( (*p>='a' && *p<='z') || (*p>='A' && *p<='Z') || (*p>='0' && *p<='9') || (*p=='_') || (*p=='+') || (*p=='-') || (*p=='[') || (*p==']') || (*p=='.') ) p++; name.len=p-name.s; p--; if (parse_avp_name(&name, &avp_flags, &avp_name, &avp_index) < 0) { ERR("error while parsing AVP name\n"); goto error; } e->itf = xl_get_avp; e->hflags=avp_flags; e->hparam.s=name.s; e->hparam.len=name.len; e->hindex=avp_index; DBG("flags %x name %.*s index %d\n", avp_flags, avp_name.s.len, avp_name.s.s, avp_index); break; case '@': /* fill select structure and call resolve_select */ DBG("xlog: xl_parse_format: @\n"); n=parse_select(&p, &sel); if (n<0) { ERR("xlog: xl_parse_format: parse_select returned error\n"); goto error; } e->itf = xl_get_select; e->hparam.s = (char*)sel; p--; break; case '%': e->itf = xl_get_percent; break; case ' ': /* enables spaceless terminating of avp, e.g. "blah%$avp% text goes on" */ case '|': e->itf = xl_get_empty; break; default: e->itf = xl_get_null; } if(*p == '\0') break; p++; } DBG("XLOG: xl_parse_format: format parsed OK: [%d] items\n", n); return 0; error: xl_elog_free_all(*el); *el = NULL; return -1; }
/* Parse an xl-formatted string pointed by s. * el points to the resulted linked list that is allocated * in shared memory when shm==1 otherwise in pkg memory. * If parse_cb is not NULL then regular expression back references * are passed to the parse_cb function that is supposed to farther parse * the back reference and fill in the xl_elog_t structure. * * Return value: * 0: success * -1: error */ static int _xl_parse_format(char *s, xl_elog_p *el, int shm, xl_parse_cb parse_cb) { char *p, c; int n = 0; xl_elog_p e, e0; struct hdr_field hdr; str name; int avp_flags, avp_index; int_str avp_name; select_t *sel; int *range; if(s==NULL || el==NULL) return -1; DBG("XLOG: xl_parse_format: parsing [%s]\n", s); p = s; *el = NULL; e = e0 = NULL; range = NULL; while(*p) { e0 = e; if (shm) e = shm_malloc(sizeof(xl_elog_t)); else e = pkg_malloc(sizeof(xl_elog_t)); if(!e) goto error; memset(e, 0, sizeof(xl_elog_t)); n++; if(*el == NULL) *el = e; if(e0) e0->next = e; e->text.s = p; while(*p && *p!='%' && *p!='\\' && !range) p++; e->text.len = p - e->text.s; if(*p == '\0') break; if ((*p == '\\') && !range) { p++; switch(*p) { case '\\': e->itf = xl_get_special; e->hindex = '\\'; break; case 'r': e->itf = xl_get_special; e->hindex = '\r'; break; case 'n': e->itf = xl_get_special; e->hindex = '\n'; break; case 't': e->itf = xl_get_special; e->hindex = '\t'; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* Regular expression back reference found */ if (!parse_cb) { /* There is no callback function, hence the * result will be written as it is. */ e->itf = xl_get_special; e->hindex = *p; break; } name.s = p; /* eat all the numeric characters */ while ((*(p+1) >= '0') && (*(p+1) <= '9')) p++; name.len = p - name.s + 1; if (parse_cb(&name, shm, e)) { ERR("xprint: xl_parse_format: failed to parse '%.*s'\n", name.len, name.s); goto error; } break; default: /* not a special character, it will be just written to the result as it is */ e->itf = xl_get_special; e->hindex = *p; } goto cont; } if (range) range = NULL; else p++; switch(*p) { case 'b': p++; switch(*p) { case 'r': e->itf = xl_get_branch; break; case 'R': e->itf = xl_get_branches; break; default: e->itf = xl_get_null; } break; case 'c': p++; switch(*p) { case 'i': e->itf = xl_get_callid; break; case 's': e->itf = xl_get_cseq; break; case 't': e->itf = xl_get_contact; break; default: e->itf = xl_get_null; } break; case 'C': p++; e->hparam.s = p; /* foreground */ switch(*p) { case 'x': case 's': case 'r': case 'g': case 'y': case 'b': case 'p': case 'c': case 'w': case 'S': case 'R': case 'G': case 'Y': case 'B': case 'P': case 'C': case 'W': break; default: e->itf = xl_get_empty; goto error; } p++; /* background */ switch(*p) { case 'x': case 's': case 'r': case 'g': case 'y': case 'b': case 'p': case 'c': case 'w': break; default: e->itf = xl_get_empty; goto error; } /* end */ e->hparam.len = 2; e->itf = xl_get_color; break; case 'd': p++; switch(*p) { case 's': e->itf = xl_get_dset; break; default: e->itf = xl_get_null; } break; case 'f': p++; switch(*p) { case 'u': e->itf = xl_get_from; break; case 't': e->itf = xl_get_from_tag; break; default: e->itf = xl_get_null; } break; case 'H': p++; e->itf = xl_get_host; switch(*p) { case 'n': e->hindex = XL_HOST_NAME; break; case 'd': e->hindex = XL_HOST_DOMAIN; break; case 'f': e->hindex = XL_HOST_FULL; break; case 'i': e->hindex = XL_HOST_IPADDR; break; default: e->hindex = XL_HOST_NULL; break; } break; case 'm': p++; switch(*p) { case 'b': e->itf = xl_get_msg_buf; break; case 'f': e->itf = xl_get_flags; break; case 'i': e->itf = xl_get_msgid; e->hindex = 10; break; case 'l': e->itf = xl_get_msg_len; break; case 'x': e->itf = xl_get_msgid; e->hindex = 16; break; default: e->itf = xl_get_null; } break; case 'n': p++; switch(*p) { case 'h': e->itf = xl_get_nexthop; break; default: e->itf = xl_get_null; } break; case 'p': p++; switch(*p) { case 'p': e->itf = xl_get_pid; e->hindex = 10; break; case 'x': e->itf = xl_get_pid; e->hindex = 16; break; default: e->itf = xl_get_null; } break; case 'r': p++; switch(*p) { case 'm': e->itf = xl_get_method; break; case 'u': e->itf = xl_get_ruri; break; case 's': e->itf = xl_get_status; break; case 'r': e->itf = xl_get_reason; break; case 't': e->itf = xl_get_refer_to; break; default: e->itf = xl_get_null; } break; case 'R': p++; switch(*p) { case 'i': e->itf = xl_get_rcvip; break; case 'p': e->itf = xl_get_rcvport; break; default: e->itf = xl_get_null; } break; case 's': p++; switch(*p) { case 'i': e->itf = xl_get_srcip; break; case 'p': e->itf = xl_get_srcport; break; default: e->itf = xl_get_null; } break; case 't': p++; switch(*p) { case 'u': e->itf = xl_get_to; break; case 't': e->itf = xl_get_to_tag; break; default: e->itf = xl_get_null; } break; case 'T': p++; switch(*p) { case 's': e->itf = xl_get_times; e->hindex = 10; break; case 'f': e->itf = xl_get_timef; break; case 'x': e->itf = xl_get_times; e->hindex = 16; break; default: e->itf = xl_get_null; } break; case 'u': p++; switch(*p) { case 'a': e->itf = xl_get_useragent; break; case 'q': e->itf = xl_get_unique; break; default: e->itf = xl_get_null; } break; case '{': p++; /* we expect a letter */ if((*p < 'A' || *p > 'Z') && (*p < 'a' || *p > 'z')) { LOG(L_ERR, "xprint: xl_parse_format: error parsing format" " [%s] pos [%d]\n", s, (int)(p-s)); goto error; } e->hparam.s = p; while(*p && *p!='}' && *p!='[') p++; if(*p == '\0') { LOG(L_ERR, "xprint: xl_parse_format: error parsing format" " [%s] expecting '}' after position [%d]\n", s, (int)(e->hparam.s-s)); goto error; } e->hparam.len = p - e->hparam.s; /* check if we have index */ if(*p == '[') { p++; if(*p=='-') { p++; if(*p!='1') { LOG(L_ERR, "xprint: xl_parse_format: error" " parsing format [%s] -- only -1 is accepted" " as a negative index\n", s); goto error; } e->hindex = XLOG_PRINT_LAST; p++; } else if (*p=='*') { e->hindex = XLOG_PRINT_ALL; p++; } else { while(*p>='0' && *p<='9') { e->hindex = e->hindex * 10 + *p - '0'; p++; } } if(*p != ']') { LOG(L_ERR, "xprint: xl_parse_format: error parsing format" " [%s] expecting ']' after position [%d]\n", s, (int)(e->hparam.s - s + e->hparam.len)); goto error; } p++; } if(*p != '}') { LOG(L_ERR, "xprint: xl_parse_format: error parsing format" " [%s] expecting '}' after position [%d]!\n", s, (int)(e->hparam.s-s)); goto error; } DBG("xprint: xl_parse_format: header name [%.*s] index [%d]\n", e->hparam.len, e->hparam.s, e->hindex); /* optimize for known headers -- fake header name */ c = e->hparam.s[e->hparam.len]; e->hparam.s[e->hparam.len] = ':'; e->hparam.len++; /* ugly hack for compact header names -- !!fake length!! * -- parse_hname2 expects name buffer length >= 4 */ if (parse_hname2(e->hparam.s, e->hparam.s + ((e->hparam.len<4)?4:e->hparam.len), &hdr)==0) { LOG(L_ERR,"xprint: xl_parse_format: strange error\n"); goto error; } e->hparam.len--; e->hparam.s[e->hparam.len] = c; if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T) { LOG(L_INFO,"INFO:xprint: xl_parse_format: using " "hdr type (%d) instead of <%.*s>\n", hdr.type, e->hparam.len, e->hparam.s); e->hparam.len = hdr.type; e->hparam.s = NULL; } e->itf = xl_get_header; break; case '<': p++; /* we expect a letter */ if((*p < 'A' || *p > 'Z') && (*p < 'a' || *p > 'z')) { LOG(L_ERR, "xprint: xl_parse_format: error parsing format" " [%s] pos [%d]\n", s, (int)(p-s)); goto error; } e->hparam.s = p; while(*p && *p!='>' && *p!='[') p++; if(*p == '\0') { LOG(L_ERR, "xprint: xl_parse_format: error parsing format" " [%s] expecting '>' after position [%d]\n", s, (int)(e->hparam.s-s)); goto error; } e->hparam.len = p - e->hparam.s; /* check if we have index */ if(*p == '[') { p++; if(*p=='-') { p++; if(*p!='1') { LOG(L_ERR, "xprint: xl_parse_format: error" " parsing format [%s] -- only -1 is accepted" " as a negative index\n", s); goto error; } e->hindex = -1; p++; } else { while(*p>='0' && *p<='9') { e->hindex = e->hindex * 10 + *p - '0'; p++; } } if(*p != ']') { LOG(L_ERR, "xprint: xl_parse_format: error parsing format" " [%s] expecting ']' after position [%d]\n", s, (int)(e->hparam.s - s + e->hparam.len)); goto error; } p++; } if(*p != '>') { LOG(L_ERR, "xprint: xl_parse_format: error parsing format" " [%s] expecting '>' after position [%d]!\n", s, (int)(e->hparam.s-s)); goto error; } DBG("xprint: xl_parse_format: AVP [%.*s] index [%d]\n", e->hparam.len, e->hparam.s, e->hindex); e->itf = xl_get_avp; break; case '$': p++; name.s=p; while ( (*p>='a' && *p<='z') || (*p>='A' && *p<='Z') || (*p>='0' && *p<='9') || (*p=='_') || (*p=='+') || (*p=='-') || (*p=='[') || (*p==']') || (*p=='.') ) p++; name.len=p-name.s; p--; if (parse_avp_name(&name, &avp_flags, &avp_name, &avp_index) < 0) { ERR("error while parsing AVP name\n"); goto error; } e->itf = xl_get_avp; e->hflags=avp_flags; e->hparam.s=name.s; e->hparam.len=name.len; e->hindex=avp_index; DBG("flags %x name %.*s index %d\n", avp_flags, avp_name.s.len, avp_name.s.s, avp_index); break; case '@': /* fill select structure and call resolve_select */ DBG("xprint: xl_parse_format: @\n"); if (shm) n=shm_parse_select(&p, &sel); else n=parse_select(&p, &sel); if (n<0) { ERR("xprint: xl_parse_format: parse_select returned error\n"); goto error; } e->itf = xl_get_select; e->hparam.s = (char*)sel; e->free_f = (shm) ? xl_shm_free_select : xl_free_select; p--; break; case '%': e->itf = xl_get_percent; break; case ' ': /* enables spaceless terminating of avp, e.g. "blah%$avp% text goes on" */ case '|': e->itf = xl_get_empty; break; case '[': range = &e->hindex; e->itf = xl_get_range; while (1) { p++; if (((*p) >= '0') && ((*p) <= '9')) { (*range) *= 10; (*range) += (*p) - '0'; } else if ((*p) == '-') { if (range == &e->hindex) { range = &e->hflags; } else { ERR("xprint: xl_parse_format: syntax error in the range specification\n"); goto error; } } else if ((*p) == ']') { if (range == &e->hindex) { /* no range, only a single number */ e->hflags = e->hindex; } else if (e->hflags == 0) { /* only the left side is defined */ e->hflags = -1; } else if (e->hindex > e->hflags) { ERR("xprint: xl_parse_format: syntax error in the range specification\n"); goto error; } break; } else { ERR("xprint: xl_parse_format: syntax error in the range specification\n"); goto error; } } break; default: e->itf = xl_get_null; } cont: if(*p == '\0') break; p++; } DBG("XLOG: xl_parse_format: format parsed OK: [%d] items\n", n); return 0; error: _xl_elog_free_all(*el, shm); *el = NULL; return -1; }
int select_anyheader(str* res, select_t* s, struct sip_msg* msg) { struct hdr_field *hf, *hf0; int hi; char c; struct hdr_field hdr; if(msg==NULL) { if (res!=NULL) return -1; /* "fixup" call, res & msg are NULL */ if (s->n <3) return -1; if (s->params[2].type==SEL_PARAM_STR) { /* replace _ with - (for P-xxx headers) */ for (hi=s->params[2].v.s.len-1; hi>0; hi--) if (s->params[2].v.s.s[hi]=='_') s->params[2].v.s.s[hi]='-'; /* if header name is parseable, parse it and set SEL_PARAM_DIV */ c=s->params[2].v.s.s[s->params[2].v.s.len]; s->params[2].v.s.s[s->params[2].v.s.len]=':'; if (parse_hname2(s->params[2].v.s.s,s->params[2].v.s.s+(s->params[2].v.s.len<3?4:s->params[2].v.s.len+1), &hdr)==0) { ERR("select_anyhdr:fixup_call:parse error\n"); return -1; } s->params[2].v.s.s[s->params[2].v.s.len]=c; if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T) { /* pkg_free(s->params[1].v.s.s); */ /* don't free it (the mem can leak only once at startup) * the parsed string can live inside larger string block * e.g. when xlog's select is parsed */ s->params[2].type = SEL_PARAM_DIV; s->params[2].v.i = hdr.type; } } return 1; } hf0 = NULL; /* extract header index if present */ if (s->param_offset[s->lvl+1] == 4) { if (s->params[3].type == SEL_PARAM_INT) { hi = s->params[3].v.i; } else { hi = -1; } } else { hi = 1; } /* we need to be sure we have parsed all headers */ if (!msg->eoh && (parse_headers(msg,HDR_EOH_F,0)==-1 || !msg->eoh)) { ERR("bad msg while parsing to EOH \n"); return -1; } for (hf=msg->headers; hf; hf=hf->next) { if(s->params[2].type==SEL_PARAM_DIV) { if (s->params[2].v.i!=hf->type) continue; } else if(s->params[2].type==SEL_PARAM_STR) { if (s->params[2].v.s.len!=hf->name.len) continue; if (strncasecmp(s->params[2].v.s.s, hf->name.s, hf->name.len)!=0) continue; } hf0 = hf; hi--; if (!hi) break; } if(hf0==NULL || hi>0) return 1; res->s = hf0->body.s; res->len = hf0->body.len; trim(res); return 0; }
/* tw_append syntax: * tw_append = name:element[;element] * element = [title=]value * value = avp[avp_spec] | hdr[hdr_name] | msg[body] */ int parse_tw_append( modparam_t type, void* val) { struct hdr_field hdr; struct hdr_avp *last; struct hdr_avp *ha; struct tw_append *app; int_str avp_name; char *s; char bar; str foo; int n; int index; if (val==0 || ((char*)val)[0]==0) return 0; s = (char*)val; /* start parsing - first the name */ while( *s && isspace((int)*s) ) s++; if ( !*s || *s==':') goto parse_error; foo.s = s; while ( *s && *s!=':' && !isspace((int)*s) ) s++; if ( !*s || foo.s==s ) goto parse_error; foo.len = s - foo.s; /* parse separator */ while( *s && isspace((int)*s) ) s++; if ( !*s || *s!=':') goto parse_error; s++; while( *s && isspace((int)*s) ) s++; if ( !*s ) goto parse_error; /* check for name duplication */ for(app=tw_appends;app;app=app->next) if (app->name.len==foo.len && !strncasecmp(app->name.s,foo.s,foo.len)){ LOG(L_ERR,"ERROR:tm:parse_tw_append: duplicated tw_append name " "<%.*s>\n",foo.len,foo.s); goto error; } /* new tw_append structure */ app = (struct tw_append*)pkg_malloc( sizeof(struct tw_append) ); if (app==0) { LOG(L_ERR,"ERROR:tm:parse_tw_append: no more pkg memory\n"); goto error; } app->name.s = (char*)pkg_malloc( foo.len+1 ); if (app->name.s==0) { LOG(L_ERR,"ERROR:tm:parse_tw_append: no more pkg memory\n"); goto error; } memcpy( app->name.s, foo.s, foo.len); app->name.len = foo.len; app->name.s[app->name.len] = 0; last = app->elems = 0; app->next = tw_appends; tw_appends = app; /* parse the elements */ while (*s) { /* parse element title or element type */ foo.s = s; while( *s && *s!='[' && *s!='=' && *s!=';' && !isspace((int)*s) ) s++; if ( !*s || foo.s==s) goto parse_error; foo.len = s - foo.s; /* new hdr_avp structure */ ha = (struct hdr_avp*)pkg_malloc( sizeof(struct hdr_avp) ); if (ha==0) { LOG(L_ERR,"ERROR:tm:parse_tw_append: no more pkg memory\n"); goto error; } memset( ha, 0, sizeof(struct hdr_avp)); if (*s!='[') { /* foo must by title or some error -> parse separator */ while( *s && isspace((int)*s) ) s++; if ( !*s || *s!='=') goto parse_error; s++; while( *s && isspace((int)*s) ) s++; if ( !*s ) goto parse_error; /* set the title */ ha->title.s = (char*)pkg_malloc( foo.len+1 ); if (ha->title.s==0) { LOG(L_ERR,"ERROR:tm:parse_tw_append: no more pkg memory\n"); goto error; } memcpy( ha->title.s, foo.s, foo.len); ha->title.len = foo.len; ha->title.s[ha->title.len] = 0; /* parse the type now */ foo.s = s; while( *s && *s!='[' && *s!=']' && *s!=';' && !isspace((int)*s) ) s++; if ( *s!='[' || foo.s==s) goto parse_error; foo.len = s - foo.s; } /* foo containes the elemet type */ if ( foo.len==ELEM_TYPE_AVP_LEN && !strncasecmp( foo.s, ELEM_TYPE_AVP, foo.len) ) { ha->type = ELEM_IS_AVP; } else if ( foo.len==ELEM_TYPE_HDR_LEN && !strncasecmp( foo.s, ELEM_TYPE_HDR, foo.len) ) { ha->type = ELEM_IS_HDR; } else if ( foo.len==ELEM_TYPE_MSG_LEN && !strncasecmp( foo.s, ELEM_TYPE_MSG, foo.len) ) { ha->type = ELEM_IS_MSG; } else { LOG(L_ERR,"ERROR:tm:parse_tw_append: unknown type <%.*s>\n", foo.len, foo.s); goto error; } /* parse the element name */ s++; foo.s = s; while( *s && *s!=']' && *s!=';' && !isspace((int)*s) ) s++; if ( *s!=']' || foo.s==s ) goto parse_error; foo.len = s - foo.s; s++; /* process and optimize the element name */ if (ha->type==ELEM_IS_AVP) { /* element is AVP */ if ( parse_avp_spec( &foo, &n, &avp_name, &index)!=0 ) { LOG(L_ERR,"ERROR:tm:parse_tw_append: bad alias spec " "<%.*s>\n",foo.len, foo.s); goto error; } if (n&AVP_NAME_STR) { /* string name */ ha->sval.s = (char*)pkg_malloc(avp_name.s.len+1); if (ha->sval.s==0) { LOG(L_ERR,"ERROR:tm:parse_tw_append: no more pkg mem\n"); goto error; } memcpy( ha->sval.s, avp_name.s.s, avp_name.s.len); ha->sval.len = avp_name.s.len; ha->sval.s[ha->sval.len] = 0; if (ha->title.s==0) ha->title = ha->sval; } else { /* ID name - if title is missing, convert the ID to * string and us it a title */ ha->ival = avp_name.n; if (ha->title.s==0) { foo.s=int2str((unsigned long)ha->ival, &foo.len); ha->title.s = (char*)pkg_malloc( n+1 ); if (ha->title.s==0) { LOG(L_ERR,"ERROR:tm:parse_tw_append: no more pkg " "memory\n"); goto error; } memcpy( ha->title.s, foo.s, foo.len); ha->title.len = foo.len; ha->title.s[ha->title.len] = 0; } } } else if (ha->type==ELEM_IS_HDR) { /* element is HDR - try to get it's coded type if defined */ bar = foo.s[foo.len]; foo.s[foo.len] = ':'; /* parse header name */ if (parse_hname2( foo.s, foo.s+foo.len+1, &hdr)==0) { LOG(L_ERR,"BUG:tm_parse_tw_append: parse header failed\n"); goto error; } foo.s[foo.len] = bar; ha->ival = hdr.type; if (hdr.type==HDR_OTHER_T || ha->title.s==0) { /* duplicate hdr name */ ha->sval.s = (char*)pkg_malloc(foo.len+1); if (ha->sval.s==0) { LOG(L_ERR,"ERROR:tm:parse_tw_append: no more pkg mem\n"); goto error; } memcpy( ha->sval.s, foo.s, foo.len); ha->sval.len = foo.len; ha->sval.s[ha->sval.len] = 0; if (ha->title.s==0) ha->title = ha->sval; } } else { /* element is MSG */ if ( !(foo.len==ELEM_VAL_BODY_LEN && !strncasecmp(ELEM_VAL_BODY,foo.s,foo.len)) ) { LOG(L_ERR,"ERROR:tm:parse_tw_append: unsupported value <%.*s>" " for msg type\n",foo.len,foo.s); goto error; } app->add_body = 1; pkg_free( ha ); ha = 0; } /* parse the element separator, if present */ while( *s && isspace((int)*s) ) s++; if ( *s && *s!=';') goto parse_error; if (*s==';') { s++; while( *s && isspace((int)*s) ) s++; if (!*s) goto parse_error; } /* link the element to tw_append structure */ if (ha) { if (last==0) { last = app->elems = ha; } else { last->next = ha; last = ha; } } } /* end while */ print_tw_append( app ); /* free the old string */ pkg_free(val); return 0; parse_error: LOG(L_ERR,"ERROR:tm:parse_tw_append: parse error in <%s> around " "position %ld\n", (char*)val, (long)(s-(char*)val)); error: return -1; }