Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
/**
 *	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;
}
Ejemplo n.º 3
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;
	}

	/* 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;
}
Ejemplo n.º 4
0
/**
 * 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);
}
Ejemplo n.º 5
0
/*
 * 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;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
/* 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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
0
/* 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;
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
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;
}