int xl_parse_format(char *s, xl_elog_p *el) { char *p; int n = 0; xl_elog_p e, e0; 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 'c': p++; switch(*p) { case 't': e->itf = xl_get_contact; break; case 'i': e->itf = xl_get_callid; break; case 's': e->itf = xl_get_cseq; 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 'm': p++; switch(*p) { case 'i': e->itf = xl_get_msgid; break; default: e->itf = xl_get_null; } break; case 'p': p++; switch(*p) { case 'p': e->itf = xl_get_pid; 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; 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; break; case 'f': e->itf = xl_get_timef; break; default: e->itf = xl_get_null; } break; case 'i': p++; switch(*p) { case 's': e->itf = xl_get_srcip; break; default: e->itf = xl_get_null; } break; case '%': e->itf = xl_get_percent; 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; }
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; }