You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/modules/cpl-c/cpl_parser.c

1552 lines
41 KiB

/*
* $Id$
*
* Copyright (C) 2001-2003 FhG Fokus
*
* This file is part of Kamailio, a free SIP server.
*
* Kamailio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* Kamailio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include "../../parser/parse_uri.h"
#include "../../trim.h"
#include "../../dprint.h"
#include "../../str.h"
#include "../../ut.h"
#include "CPL_tree.h"
#include "sub_list.h"
#include "cpl_log.h"
static struct node *list = 0;
static xmlDtdPtr dtd; /* DTD file */
static xmlValidCtxt cvp; /* validating context */
typedef unsigned short length_type ;
typedef length_type* length_type_ptr;
enum {EMAIL_TO,EMAIL_HDR_NAME,EMAIL_KNOWN_HDR_BODY,EMAIL_UNKNOWN_HDR_BODY};
#define ENCONDING_BUFFER_SIZE 65536
#define FOR_ALL_ATTR(_node,_attr) \
for( (_attr)=(_node)->properties ; (_attr) ; (_attr)=(_attr)->next)
#define check_overflow(_p_,_offset_,_end_,_error_) \
do{\
if ((_p_)+(_offset_)>=(_end_)) { \
LM_ERR("%s:%d: overflow -> buffer to small\n",\
__FILE__,__LINE__);\
goto _error_;\
}\
}while(0)\
#define set_attr_type(_p_,_type_,_end_,_error_) \
do{\
check_overflow(_p_,sizeof(length_type),_end_,_error_);\
*((length_type_ptr)(_p_)) = htons((length_type)(_type_));\
(_p_) += sizeof(length_type);\
}while(0)\
#define append_short_attr(_p_,_n_,_end_,_error_) \
do{\
check_overflow(_p_,sizeof(length_type),_end_,_error_);\
*((length_type_ptr)(_p_)) = htons((length_type)(_n_));\
(_p_) += sizeof(length_type);\
}while(0)
#define append_str_attr(_p_,_s_,_end_,_error_) \
do{\
check_overflow(_p_,(_s_).len + 1*((((_s_).len)&0x0001)==1),\
_end_,_error_);\
*((length_type_ptr)(_p_)) = htons((length_type)(_s_).len);\
(_p_) += sizeof(length_type);\
memcpy( (_p_), (_s_).s, (_s_).len);\
(_p_) += (_s_).len + 1*((((_s_).len)&0x0001)==1);\
}while(0)
#define append_double_str_attr(_p_,_s1_,_s2_,_end_,_error_) \
do{\
check_overflow(_p_,(_s1_).len + (_s2_).len +\
1*((((_s2_).len+(_s2_).len)&0x0001)==1), _end_, _error_);\
*((length_type_ptr)(_p_))=htons((length_type)((_s1_).len)+(_s2_).len);\
(_p_) += sizeof(length_type);\
memcpy( (_p_), (_s1_).s, (_s1_).len);\
(_p_) += (_s1_).len;\
memcpy( (_p_), (_s2_).s, (_s2_).len);\
(_p_) += (_s2_).len + 1*((((_s1_).len+(_s2_).len)&0x0001)==1);\
}while(0)
#define get_attr_val(_attr_name_,_val_,_error_) \
do { \
(_val_).s = (char*)xmlGetProp(node,(_attr_name_));\
(_val_).len = strlen((_val_).s);\
/* remove all spaces from begin and end */\
trim_spaces_lr( (_val_) );\
if ((_val_).len==0) {\
LM_ERR("%s:%d: attribute <%s> has an "\
"empty value\n",__FILE__,__LINE__,(_attr_name_));\
goto _error_;\
}\
}while(0)\
#define MAX_EMAIL_HDR_SIZE 7 /*we are looking only for SUBJECT and BODY ;-)*/
#define MAX_EMAIL_BODY_SIZE 512
#define MAX_EMAIL_SUBJECT_SIZE 32
static inline char *decode_mail_url(char *p, char *p_end, char *url,
unsigned char *nr_attr)
{
static char buf[ MAX_EMAIL_HDR_SIZE ];
char c;
char foo;
unsigned short hdr_len;
unsigned short *len;
int max_len;
int status;
/* init */
hdr_len = 0;
max_len = 0;
status = EMAIL_TO;
(*nr_attr) ++;
set_attr_type(p, TO_ATTR, p_end, error); /* attr type */
len = ((unsigned short*)(p)); /* attr val's len */
*len = 0; /* init the len */
p += 2;
/* parse the whole url */
do {
/* extract a char from the encoded url */
if (*url=='+') {
/* substitute a blank for a plus */
c=' ';
url++;
/* Look for a hex encoded character */
} else if ( (*url=='%') && *(url+1) && *(url+2) ) {
/* hex encoded - convert to a char */
c = hex2int(url[1]);
foo = hex2int(url[2]);
if (c==-1 || foo==-1) {
LM_ERR("non-ASCII escaped "
"character in mail url [%.*s]\n", 3, url);
goto error;
}
c = c<<4 | foo;
url += 3;
} else {
/* normal character - just copy it without changing */
c = *url;
url++;
}
/* finally we got a character !! */
switch (c) {
case '?':
switch (status) {
case EMAIL_TO:
if (*len==0) {
LM_ERR("empty TO "
"address found in MAIL node!\n");
goto error;
}
if (((*len)&0x0001)==1) p++;
*len = htons(*len);
hdr_len = 0;
status = EMAIL_HDR_NAME;
break;
default: goto parse_error;
}
break;
case '=':
switch (status) {
case EMAIL_HDR_NAME:
LM_DBG("hdr [%.*s] found\n",
hdr_len,buf);
if ( hdr_len==BODY_EMAILHDR_LEN &&
strncasecmp(buf,BODY_EMAILHDR_STR,hdr_len)==0 ) {
/* BODY hdr found */
set_attr_type( p, BODY_ATTR, p_end, error);
max_len = MAX_EMAIL_BODY_SIZE;
} else if ( hdr_len==SUBJECT_EMAILHDR_LEN &&
strncasecmp(buf,SUBJECT_EMAILHDR_STR,hdr_len)==0 ) {
/* SUBJECT hdr found */
set_attr_type( p, SUBJECT_ATTR, p_end, error);
max_len = MAX_EMAIL_SUBJECT_SIZE;
} else {
LM_DBG("unknown hdr -> ignoring\n");
status = EMAIL_UNKNOWN_HDR_BODY;
break;
}
(*nr_attr) ++;
len = ((unsigned short*)(p)); /* attr val's len */
*len = 0; /* init the len */
p += 2;
status = EMAIL_KNOWN_HDR_BODY;
break;
default: goto parse_error;
}
break;
case '&':
switch (status) {
case EMAIL_KNOWN_HDR_BODY:
if (((*len)&0x0001)==1) p++;
*len = htons(*len);
case EMAIL_UNKNOWN_HDR_BODY:
hdr_len = 0;
status = EMAIL_HDR_NAME;
break;
default: goto parse_error;
}
break;
case 0:
switch (status) {
case EMAIL_TO:
if (*len==0) {
LM_ERR("empty TO "
"address found in MAIL node!\n");
goto error;
}
case EMAIL_KNOWN_HDR_BODY:
if (((*len)&0x0001)==1) p++;
*len = htons(*len);
case EMAIL_UNKNOWN_HDR_BODY:
break;
default: goto parse_error;
}
break;
default:
switch (status) {
case EMAIL_TO:
(*len)++;
*(p++) = c;
if (*len==URL_MAILTO_LEN &&
!strncasecmp(p-(*len),URL_MAILTO_STR,(*len))) {
LM_DBG("MAILTO: found at"
" the beginning of TO -> removed\n");
p -= (*len);
*len = 0;
}
break;
case EMAIL_KNOWN_HDR_BODY:
if ((*len)<max_len) (*len)++;
*(p++) = c;
break;
case EMAIL_HDR_NAME:
if (hdr_len<MAX_EMAIL_HDR_SIZE) hdr_len++;
buf[hdr_len-1] = c;
break;
case EMAIL_UNKNOWN_HDR_BODY:
/* do nothing */
break;
default : goto parse_error;
}
}
}while(c!=0);
return p;
parse_error:
LM_ERR("unexpected char [%c] in state %d"
" in email url \n",*url,status);
error:
return 0;
}
/* Attr. encoding for ADDRESS node:
* | attr_t(2) attr_len(2) attr_val(2*x) | IS/CONTAINS/SUBDOMAIN_OF attr (NT)
*/
static inline int encode_address_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
{
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
(*nr_attr)++;
switch (attr->name[0]) {
case 'i': case 'I':
set_attr_type(p, IS_ATTR, buf_end, error);
break;
case 'c': case 'C':
set_attr_type(p, CONTAINS_ATTR, buf_end, error);
break;
case 's': case 'S':
set_attr_type(p, SUBDOMAIN_OF_ATTR, buf_end, error);
break;
default:
LM_ERR("unknown attribute "
"<%s>\n",attr->name);
goto error;
}
/* get the value of the attribute */
get_attr_val( attr->name , val, error);
/* copy also the \0 from the end of string */
val.len++;
append_str_attr(p, val, buf_end, error);
}
return p-p_orig;
error:
return -1;
}
/* Attr. encoding for ADDRESS_SWITCH node:
* | attr1_t(2) attr1_val(2) | FIELD attr
* [| attr2_t(2) attr2_val(2) |]? SUBFILED attr
*/
static inline int encode_address_switch_attr(xmlNodePtr node, char *node_ptr,
char *buf_end)
{
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
(*nr_attr)++;
/* get the value of the attribute */
get_attr_val( attr->name , val, error);
switch(attr->name[0]) {
case 'F': case 'f':
set_attr_type(p, FIELD_ATTR, buf_end, error);
if (val.s[0]=='D' || val.s[0]=='d')
append_short_attr(p, DESTINATION_VAL, buf_end, error);
else if (val.s[6]=='A' || val.s[6]=='a')
append_short_attr(p,ORIGINAL_DESTINATION_VAL,buf_end,error);
else if (!val.s[6])
append_short_attr(p, ORIGIN_VAL, buf_end, error);
else {
LM_ERR("unknown"
" value <%s> for FIELD attr\n",val.s);
goto error;
};
break;
case 'S': case 's':
set_attr_type(p, SUBFIELD_ATTR, buf_end, error);
switch (val.s[0]) {
case 'u': case 'U':
append_short_attr(p, USER_VAL, buf_end, error);
break;
case 'h': case 'H':
append_short_attr(p, HOST_VAL, buf_end, error);
break;
case 'p': case 'P':
append_short_attr(p, PORT_VAL, buf_end, error);
break;
case 't': case 'T':
append_short_attr(p, TEL_VAL, buf_end, error);
break;
case 'd': case 'D':
/*append_short_attr(p, DISPLAY_VAL, buf_end, error);
break;*/ /* NOT YET SUPPORTED BY INTERPRETER */
case 'a': case 'A':
/*append_short_attr(p, ADDRESS_TYPE_VAL, buf_end,error);
break;*/ /* NOT YET SUPPORTED BY INTERPRETER */
default:
LM_ERR("unknown value <%s> for SUBFIELD attr\n",val.s);
goto error;
}
break;
default:
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
}
return p-p_orig;
error:
return -1;
}
/* Attr. encoding for LANGUAGE node:
* | attr_t(2) attr_len(2) attr_val(2*x) | MATCHES attr (NNT)
*/
static inline int encode_lang_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
{
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
char *end;
char *val_bk;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
/* there is only one attribute -> MATCHES */
if (attr->name[0]!='M' && attr->name[0]!='m') {
LM_ERR("unknown attribute "
"<%s>\n",attr->name);
goto error;
}
val.s = val_bk = (char*)xmlGetProp(node,attr->name);
/* parse the language-tag */
for(end=val.s,val.len=0;;end++) {
/* trim all spaces from the beginning of the tag */
if (!val.len && (*end==' ' || *end=='\t')) continue;
/* we cannot have more than 2 attrs - LANG_TAG and LANG_SUBTAG */
if ((*nr_attr)>=2) goto lang_error;
if (((*end)|0x20)>='a' && ((*end)|0x20)<='z') {
val.len++; continue;
} else if (*end=='*' && val.len==0 && (*nr_attr)==0 &&
(*end==' '|| *end=='\t' || *end==0)) {
val.len++;
set_attr_type(p, MATCHES_TAG_ATTR, buf_end, error);
} else if (val.len && (*nr_attr)==0 && *end=='-' ) {
set_attr_type(p, MATCHES_TAG_ATTR, buf_end, error);
} else if (val.len && ((*nr_attr)==0 || (*nr_attr)==1) &&
(*end==' '|| *end=='\t' || *end==0)) {
set_attr_type(p,
(!(*nr_attr))?MATCHES_TAG_ATTR:MATCHES_SUBTAG_ATTR,
buf_end, error );
} else goto lang_error;
(*nr_attr)++;
/*LM_DBG("----> language tag=%d; %d [%.*s]\n",*(p-1),
val.len,val.len,end-val.len);*/
val.s = end-val.len;
append_str_attr(p, val, buf_end, error);
val.len = 0;
if (*end==0) break;
}
}
return p-p_orig;
lang_error:
LM_ERR("bad value for language_tag <%s>\n",val_bk);
error:
return -1;
}
/* Attr. encoding for PRIORITY node:
* | attr1_t(2) attr1_val(2) | LESS/GREATER/EQUAL attr
* [| attr2_t(2) attr2_len(2) attr_val(2*x) |]? PRIOSTR attr (NT)
*/
static inline int encode_priority_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
{
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
(*nr_attr)++;
/* attribute's name */
switch(attr->name[0]) {
case 'L': case 'l':
set_attr_type(p, LESS_ATTR, buf_end, error);
break;
case 'G': case 'g':
set_attr_type(p, GREATER_ATTR, buf_end, error);
break;
case 'E': case 'e':
set_attr_type(p, EQUAL_ATTR, buf_end, error);
break;
default:
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
/* attribute's encoded value */
get_attr_val( attr->name , val, error);
if ( val.len==EMERGENCY_STR_LEN &&
!strncasecmp(val.s,EMERGENCY_STR,val.len) ) {
append_short_attr(p, EMERGENCY_VAL, buf_end, error);
} else if ( val.len==URGENT_STR_LEN &&
!strncasecmp(val.s,URGENT_STR,val.len) ) {
append_short_attr(p, URGENT_VAL, buf_end, error);
} else if ( val.len==NORMAL_STR_LEN &&
!strncasecmp(val.s,NORMAL_STR,val.len) ) {
append_short_attr(p, NORMAL_VAL, buf_end, error);
} else if ( val.len==NON_URGENT_STR_LEN &&
!strncasecmp(val.s,NON_URGENT_STR,val.len) ) {
append_short_attr(p, NON_URGENT_VAL, buf_end, error);
} else {
append_short_attr(p, UNKNOWN_PRIO_VAL, buf_end, error);
set_attr_type(p, PRIOSTR_ATTR, buf_end, error);
val.len++; /* append \0 also */
append_str_attr(p, val, buf_end, error);
}
}
return p-p_orig;
error:
return -1;
}
/* Attr. encoding for STRING_SWITCH node:
* [| attr1_t(2) attr1_len(2) attr_val(2*x) |]? IS attr (NT)
* [| attr2_t(2) attr2_len(2) attr_val(2*x) |]? CONTAINS attr (NT)
*/
static inline int encode_string_switch_attr(xmlNodePtr node, char *node_ptr,
char *buf_end)
{
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
(*nr_attr)++;
/* there is only one attribute -> MATCHES */
if (attr->name[0]!='F' && attr->name[0]!='f') {
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
set_attr_type(p, FIELD_ATTR, buf_end, error);
/* attribute's encoded value */
get_attr_val( attr->name , val, error);
switch (val.s[0]) {
case 'S': case 's':
append_short_attr(p, SUBJECT_VAL, buf_end, error);
break;
case 'O': case 'o':
append_short_attr(p, ORGANIZATION_VAL, buf_end, error);
break;
case 'U': case 'u':
append_short_attr(p, USER_AGENT_VAL, buf_end, error);
break;
case 'D': case 'd':
append_short_attr(p, DISPLAY_VAL, buf_end, error);
break;
default:
LM_ERR("unknown "
"value <%s> for FIELD\n",attr->name);
goto error;
}
}
return p-p_orig;
error:
return -1;
}
/* Attr. encoding for STRING node:
* [| attr1_t(2) attr1_len(2) attr_val(2*x) |]? IS attr (NT)
* [| attr2_t(2) attr2_len(2) attr_val(2*x) |]? CONTAINS attr (NT)
*/
static inline int encode_string_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
{
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
(*nr_attr)++;
switch(attr->name[0]) {
case 'I': case 'i':
set_attr_type(p, IS_ATTR, buf_end, error);
break;
case 'C': case 'c':
set_attr_type(p, CONTAINS_ATTR, buf_end, error);
break;
default:
LM_ERR("unknown "
"attribute <%s>\n",attr->name);
goto error;
}
/* attribute's encoded value */
get_attr_val( attr->name , val, error);
val.len++; /* grab also the \0 */
append_str_attr(p,val, buf_end, error);
}
return p-p_orig;
error:
return -1;
}
/* Attr. encoding for TIME_SWITCH node:
* [| attr1_t(2) attr1_len(2) attr_val(2*x) |]? TZID attr (NT)
* [| attr2_t(2) attr2_len(2) attr_val(2*x) |]? TZURL attr (NT)
*/
static inline int encode_time_switch_attr(xmlNodePtr node, char *node_ptr,
char *buf_end)
{
static str tz_str = {"TZ=",3};
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
(*nr_attr)++;
switch(attr->name[2]) {
case 'I': case 'i':
set_attr_type(p, TZID_ATTR, buf_end, error);
/* attribute's encoded value */
get_attr_val( attr->name , val, error);
val.len++; /* grab also the \0 */
append_double_str_attr(p,tz_str,val, buf_end, error);
break;
case 'U': case 'u':
/* set_attr_type(p, TZURL_ATTR, buf_end, error);
* is a waste of space to copy the url - the interpreter doesn't
* use it at all ;-) */
break;
default:
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
}
return p-p_orig;
error:
return -1;
}
/* Attr. encoding for TIME node:
* | attr1_t(2) attr1_len(2) attr1_val(2*x) | DSTART attr (NT)
* [| attr2_t(2) attr2_len(2) attr2_val(2*x) |]? DTEND attr (NT)
* [| attr3_t(2) attr3_len(2) attr3_val(2*x) |]? DURATION attr (NT)
* [| attr4_t(2) attr4_len(2) attr4_val(2*x) |]? FREQ attr (NT)
* [| attr5_t(2) attr5_len(2) attr5_val(2*x) |]? WKST attr (NT)
* [| attr6_t(2) attr6_len(2) attr6_val(2*x) |]? BYYEARDAY attr (NT)
* [| attr7_t(2) attr7_len(2) attr7_val(2*x) |]? COUNT attr (NT)
* [| attr8_t(2) attr8_len(2) attr8_val(2*x) |]? BYSETPOS attr (NT)
* [| attr9_t(2) attr9_len(2) attr9_val(2*x) |]? BYMONTH attr (NT)
* [| attr10_t(2) attr10_len(2) attr_val10(2*x) |]? BYMONTHDAY attr (NT)
* [| attr11_t(2) attr11_len(2) attr_val11(2*x) |]? BYMINUTE attr (NT)
* [| attr12_t(2) attr12_len(2) attr_val12(2*x) |]? INTERVAL attr (NT)
* [| attr13_t(2) attr13_len(2) attr_val13(2*x) |]? UNTIL attr (NT)
* [| attr14_t(2) attr14_len(2) attr_val14(2*x) |]? BYSECOND attr (NT)
* [| attr15_t(2) attr15_len(2) attr_val15(2*x) |]? BYHOUR attr (NT)
* [| attr16_t(2) attr16_len(2) attr_val16(2*x) |]? BYDAY attr (NT)
* [| attr17_t(2) attr17_len(2) attr_val17(2*x) |]? BYWEEKNO attr (NT)
*/
static inline int encode_time_attr(xmlNodePtr node, char *node_ptr,
char *buf_end)
{
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
(*nr_attr)++;
switch (attr->name[4]) {
case 0:
if (attr->name[0]=='F' || attr->name[0]=='f')
set_attr_type(p, FREQ_ATTR, buf_end, error);
else if (attr->name[0]=='W' || attr->name[0]=='w')
set_attr_type(p, WKST_ATTR, buf_end, error);
break;
case 'a': case 'A':
if (attr->name[0]=='D' || attr->name[0]=='d')
set_attr_type(p, DTSTART_ATTR, buf_end, error);
else if (attr->name[0]=='B' || attr->name[0]=='b')
set_attr_type(p, BYYEARDAY_ATTR, buf_end, error);
break;
case 't': case 'T':
if (attr->name[0]=='D' || attr->name[0]=='d')
set_attr_type(p, DURATION_ATTR, buf_end, error);
else if (attr->name[0]=='C' || attr->name[0]=='c')
set_attr_type(p, COUNT_ATTR, buf_end, error);
else if (attr->name[0]=='B' || attr->name[0]=='b')
set_attr_type(p, BYSETPOS_ATTR, buf_end, error);
break;
case 'n': case 'N':
if (!attr->name[7])
set_attr_type(p, BYMONTH_ATTR, buf_end, error);
else if (attr->name[7]=='D' || attr->name[7]=='d')
set_attr_type(p, BYMONTHDAY_ATTR, buf_end, error);
else if (attr->name[7]=='e' || attr->name[7]=='E')
set_attr_type(p, BYMINUTE_ATTR, buf_end, error);
break;
case 'd': case 'D':
set_attr_type(p, DTEND_ATTR, buf_end, error);
break;
case 'r': case 'R':
set_attr_type(p, INTERVAL_ATTR, buf_end, error);
break;
case 'l': case 'L':
set_attr_type(p, UNTIL_ATTR, buf_end, error);
break;
case 'c': case 'C':
set_attr_type(p, BYSECOND_ATTR, buf_end, error);
break;
case 'u': case 'U':
set_attr_type(p, BYHOUR_ATTR, buf_end, error);
break;
case 'y': case 'Y':
set_attr_type(p, BYDAY_ATTR, buf_end, error);
break;
case 'e': case 'E':
set_attr_type(p, BYWEEKNO_ATTR, buf_end, error);
break;
default:
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
/* attribute's encoded value */
get_attr_val( attr->name , val, error);
val.len++; /* grab also the \0 */
append_str_attr(p,val, buf_end, error);
}
return p-p_orig;
error:
return -1;
}
/* Attr. encoding for LOOKUP node:
* | attr1_t(2) attr1_len(2) attr1_val(2*x) | SOURCE attr (NT)
* [| attr2_t(2) attr2_val(2) |]? CLEAR attr
*/
static inline int encode_lookup_attr(xmlNodePtr node, char *node_ptr,
char *buf_end)
{
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
/* get attribute's value */
get_attr_val( attr->name , val, error);
if ( !strcasecmp((const char*)attr->name,"source") ) {
/* this param will not be copied, since it has only one value ;-)*/
if ( val.len!=SOURCE_REG_STR_LEN ||
strncasecmp( val.s, SOURCE_REG_STR, val.len) ) {
LM_ERR("unsupported value"
" <%.*s> in SOURCE param\n",val.len,val.s);
goto error;
}
} else if ( !strcasecmp((const char*)attr->name,"clear") ) {
(*nr_attr)++;
set_attr_type(p, CLEAR_ATTR, buf_end, error);
if ( val.len==3 && !strncasecmp(val.s,"yes",3) )
append_short_attr(p, YES_VAL, buf_end, error);
else if ( val.len==2 && !strncasecmp(val.s,"no",2) )
append_short_attr(p, NO_VAL, buf_end, error);
else {
LM_ERR("unknown value "
"<%.*s> for attribute CLEAR\n",val.len,val.s);
goto error;
}
} else if ( !strcasecmp((const char*)attr->name,"timeout") ) {
LM_WARN("unsupported param TIMEOUT; skipping\n");
} else {
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
}
return p-p_orig;
error:
return -1;
}
/* Attr. encoding for LOCATION node:
* | attr1_t(2) attr1_len(2) attr1_val(2*x) | URL attr (NT)
* [| attr2_t(2) attr2_val(2) |]? PRIORITY attr
* [| attr3_t(2) attr3_val(2) |]? CLEAR attr
*/
static inline int encode_location_attr(xmlNodePtr node, char *node_ptr,
char *buf_end)
{
struct sip_uri uri;
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
unsigned short nr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
(*nr_attr)++;
/* get attribute's value */
get_attr_val( attr->name , val, error);
switch(attr->name[0]) {
case 'U': case 'u':
set_attr_type(p, URL_ATTR, buf_end, error);
/* check if it's a valid SIP URL -> just call
* parse uri function and see if returns error ;-) */
if (parse_uri( val.s, val.len, &uri)!=0) {
LM_ERR("<%s> is not a valid SIP URL\n",val.s);
goto error;
}
val.len++; /*copy also the \0 */
append_str_attr(p,val, buf_end, error);
break;
case 'P': case 'p':
set_attr_type(p, PRIORITY_ATTR, buf_end, error);
if (val.s[0]=='0') nr=0;
else if (val.s[0]=='1') nr=10;
else goto prio_error;
if (val.s[1]!='.') goto prio_error;
if (val.s[2]<'0' || val.s[2]>'9') goto prio_error;
nr += val.s[2] - '0';
if (nr>10)
goto prio_error;
append_short_attr(p, nr, buf_end, error);
break;
case 'C': case 'c':
set_attr_type(p, CLEAR_ATTR, buf_end, error);
if (val.s[0]=='y' || val.s[0]=='Y')
append_short_attr(p, YES_VAL, buf_end, error);
else
append_short_attr(p, NO_VAL, buf_end, error);
break;
default:
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
}
return p-p_orig;
prio_error:
LM_ERR("invalid priority <%s>\n",val.s);
error:
return -1;
}
/* Attr. encoding for REMOVE_LOCATION node:
* [| attr1_t(2) attr1_len(2) attr1_val(2*x) |]? LOCATION attr (NT)
*/
static inline int encode_rmvloc_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
{
struct sip_uri uri;
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
(*nr_attr)++;
switch(attr->name[0]) {
case 'L': case 'l':
set_attr_type(p, LOCATION_ATTR, buf_end, error);
/* get the value of the attribute */
get_attr_val( attr->name , val, error);
/* check if it's a valid SIP URL -> just call
* parse uri function and see if returns error ;-) */
if (parse_uri( val.s, val.len, &uri)!=0) {
LM_ERR("<%s> is not a valid SIP URL\n",val.s);
goto error;
}
val.len++; /*copy also the \0 */
append_str_attr(p,val, buf_end, error);
break;
case 'P': case 'p':
case 'V': case 'v':
/* as the interpreter ignores PARAM and VALUE attributes, we will
* do the same ;-) */
break;
default:
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
}
return p-p_orig;
error:
return -1;
}
/* Attr. encoding for PROXY node:
* [| attr1_t(2) attr1_val(2) |]? RECURSE attr
* [| attr2_t(2) attr2_val(2) |]? TIMEOUT attr
* [| attr3_t(2) attr3_val(2) |]? ORDERING attr
*/
static inline int encode_proxy_attr(xmlNodePtr node, char *node_ptr,
char *buf_end)
{
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
unsigned int nr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
(*nr_attr)++;
/* get the value of the attribute */
get_attr_val( attr->name , val, error);
switch(attr->name[0]) {
case 'R': case 'r':
set_attr_type(p, RECURSE_ATTR, buf_end, error);
if (val.s[0]=='y' || val.s[0]=='Y')
append_short_attr(p, YES_VAL, buf_end, error);
else if (val.s[0]=='n' || val.s[0]=='N')
append_short_attr(p, NO_VAL, buf_end, error);
else {
LM_ERR("unknown value "
"<%s> for attribute RECURSE\n",val.s);
goto error;
}
break;
case 'T': case 't':
set_attr_type(p, TIMEOUT_ATTR, buf_end, error);
if (str2int(&val,&nr)==-1) {
LM_ERR("bad value <%.*s>"
" for attribute TIMEOUT\n",val.len,val.s);
goto error;
}
append_short_attr(p, (unsigned short)nr, buf_end, error);
break;
case 'O': case 'o':
set_attr_type(p, ORDERING_ATTR, buf_end, error);
switch (val.s[0]) {
case 'p': case'P':
append_short_attr(p, PARALLEL_VAL, buf_end, error);
break;
case 'S': case 's':
append_short_attr(p, SEQUENTIAL_VAL, buf_end, error);
break;
case 'F': case 'f':
append_short_attr(p, FIRSTONLY_VAL, buf_end, error);
break;
default:
LM_ERR("unknown "
"value <%s> for attribute ORDERING\n",val.s);
goto error;
}
break;
default:
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
}
return p-p_orig;
error:
return -1;
}
/* Attr. encoding for REJECT node:
* | attr1_t(2) attr1_val(2) | STATUS attr
* [| attr2_t(2) attr2_len(2) attr2_val(2*x)|]? REASON attr (NT)
*/
static inline int encode_reject_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
{
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
unsigned int nr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
(*nr_attr)++;
/* get the value of the attribute */
get_attr_val( attr->name , val, error);
switch(attr->name[0]) {
case 'R': case 'r':
set_attr_type(p, REASON_ATTR, buf_end, error);
val.len++; /* grab also the /0 */
append_str_attr(p, val, buf_end, error);
break;
case 'S': case 's':
set_attr_type(p, STATUS_ATTR, buf_end, error);
if (str2int(&val,&nr)==-1) {
/*it was a non numeric value */
if (val.len==BUSY_STR_LEN &&
!strncasecmp(val.s,BUSY_STR,val.len)) {
append_short_attr(p, BUSY_VAL, buf_end, error);
} else if (val.len==NOTFOUND_STR_LEN &&
!strncasecmp(val.s,NOTFOUND_STR,val.len)) {
append_short_attr(p, NOTFOUND_VAL, buf_end, error);
} else if (val.len==ERROR_STR_LEN &&
!strncasecmp(val.s,ERROR_STR,val.len)) {
append_short_attr(p, ERROR_VAL, buf_end, error);
} else if (val.len==REJECT_STR_LEN &&
!strncasecmp(val.s,REJECT_STR,val.len)) {
append_short_attr(p, REJECT_VAL, buf_end, error);
} else {
LM_ERR("bad val. <%s> for STATUS\n",val.s);
goto error;
}
} else if (nr<400 || nr>700) {
LM_ERR("bad code <%d> for STATUS\n",nr);
goto error;
} else {
append_short_attr(p, nr, buf_end, error);
}
break;
default:
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
}
return p-p_orig;
error:
return -1;
}
/* Attr. encoding for REDIRECT node:
* | attr1_t(2) attr1_val(2) | STATUS attr
* [| attr2_t(2) attr2_len(2) attr2_val(2*x)|]? REASON attr (NT)
*/
static inline int encode_redirect_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
{
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
(*nr_attr)++;
if (attr->name[0]=='p' || attr->name[0]=='P') {
set_attr_type(p, PERMANENT_ATTR, buf_end, error);
/* get the value */
get_attr_val( attr->name , val, error);
if (val.s[0]=='y' || val.s[0]=='Y')
append_short_attr( p, YES_VAL, buf_end, error);
else if (val.s[0]=='n' || val.s[0]=='N')
append_short_attr( p, NO_VAL, buf_end, error);
else {
LM_ERR("bad val. <%s> for PERMANENT\n",val.s);
goto error;
}
} else {
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
}
return p-p_orig;
error:
return -1;
}
/* Attr. encoding for LOG node:
* [| attr1_t(2) attr1_len(2) attr1_val(2*x) |]? NAME attr (NT)
* [| attr2_t(2) attr2_len(2) attr2_val(2*x) |]? COMMENT attr (NT)
*/
static inline int encode_log_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
{
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
(*nr_attr)++;
/* get the value of the attribute */
get_attr_val( attr->name , val, error);
switch (attr->name[0] ) {
case 'n': case 'N':
if (val.len>MAX_NAME_SIZE) val.len=MAX_NAME_SIZE;
set_attr_type(p, NAME_ATTR, buf_end, error);
break;
case 'c': case 'C':
if (val.len>MAX_COMMENT_SIZE) val.len=MAX_COMMENT_SIZE;
set_attr_type(p, COMMENT_ATTR, buf_end, error);
break;
default:
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
/* be sure there is a \0 at the end of string */
val.s[val.len++]=0;
append_str_attr(p,val, buf_end, error);
}
return p-p_orig;
error:
return -1;
}
/* Attr. encoding for MAIL node:
* | attr1_t(2) attr1_len(2) attr1_val(2*x) | TO_ATTR attr (NNT)
* [| attr2_t(2) attr2_len(2) attr2_val(2*x) |]? SUBJECT_ATTR attr (NNT)
* [| attr3_t(2) attr3_len(2) attr3_val(2*x) |]? BODY_ATTR attr (NNT)
*/
static inline int encode_mail_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
{
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
/* there is only one attribute -> URL */
if (attr->name[0]!='u' && attr->name[0]!='U') {
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
p = decode_mail_url( p, buf_end,
(char*)xmlGetProp(node,attr->name), nr_attr);
if (p==0)
goto error;
}
return p-p_orig;
error:
return -1;
}
/* Attr. encoding for SUBACTION node:
*/
static inline int encode_subaction_attr(xmlNodePtr node, char *node_ptr,
char *buf_end)
{
xmlAttrPtr attr;
str val;
FOR_ALL_ATTR(node,attr) {
/* there is only one attribute -> ID */
if ((attr->name[0]|0x20)=='i' && ((attr->name[1]|0x20)=='d') &&
attr->name[2]==0 ) {
/* get the value of the attribute */
get_attr_val( attr->name , val, error);
if ((list = append_to_list(list, node_ptr,val.s))==0) {
LM_ERR("failed to add "
"subaction into list -> pkg_malloc failed?\n");
goto error;
}
} else {
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
}
return 0;
error:
return -1;
}
/* Attr. encoding for SUB node:
* | attr1_t(2) attr1_val(2) | REF_ATTR attr
*/
static inline int encode_sub_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
{
xmlAttrPtr attr;
char *p, *p_orig;
unsigned char *nr_attr;
char *sub_ptr;
str val;
nr_attr = &(NR_OF_ATTR(node_ptr));
*nr_attr = 0;
p = p_orig = ATTR_PTR(node_ptr);
FOR_ALL_ATTR(node,attr) {
(*nr_attr)++;
/* there is only one attribute -> REF */
if ( strcasecmp("ref",(char*)attr->name)!=0 ) {
LM_ERR("unknown attribute <%s>\n",attr->name);
goto error;
}
set_attr_type(p, REF_ATTR, buf_end, error);
/* get the value of the attribute */
get_attr_val( attr->name , val, error);
if ( (sub_ptr=search_the_list(list, val.s))==0 ) {
LM_ERR("unable to find declaration "
"of subaction <%s>\n",val.s);
goto error;
}
append_short_attr(p,(unsigned short)(node_ptr-sub_ptr),buf_end,error);
}
return p-p_orig;
error:
return -1;
}
/* Returns : -1 - error
* >0 - subtree size of the given node
*/
int encode_node( xmlNodePtr node, char *p, char *p_end)
{
xmlNodePtr kid;
unsigned short sub_tree_size;
int attr_size;
int kid_size;
int foo;
/* counting the kids */
for(kid=node->children,foo=0;kid;kid=kid->next)
if (kid->type==XML_ELEMENT_NODE) foo++;
check_overflow(p,GET_NODE_SIZE(foo),p_end,error);
NR_OF_KIDS(p) = foo;
/* size of the encoded attributes */
attr_size = 0;
/* init the number of attributes */
NR_OF_ATTR(p) = 0;
/* encode node name */
switch (node->name[0]) {
case 'a':case 'A':
switch (node->name[7]) {
case 0:
NODE_TYPE(p) = ADDRESS_NODE;
attr_size = encode_address_attr( node, p, p_end);
break;
case '-':
NODE_TYPE(p) = ADDRESS_SWITCH_NODE;
attr_size = encode_address_switch_attr( node, p, p_end);
break;
default:
NODE_TYPE(p) = ANCILLARY_NODE;
break;
}
break;
case 'B':case 'b':
NODE_TYPE(p) = BUSY_NODE;
break;
case 'c':case 'C':
NODE_TYPE(p) = CPL_NODE;
break;
case 'd':case 'D':
NODE_TYPE(p) = DEFAULT_NODE;
break;
case 'f':case 'F':
NODE_TYPE(p) = FAILURE_NODE;
break;
case 'i':case 'I':
NODE_TYPE(p) = INCOMING_NODE;
break;
case 'l':case 'L':
switch (node->name[2]) {
case 'g':case 'G':
NODE_TYPE(p) = LOG_NODE;
attr_size = encode_log_attr( node, p, p_end);
break;
case 'o':case 'O':
NODE_TYPE(p) = LOOKUP_NODE;
attr_size = encode_lookup_attr( node, p, p_end);
break;
case 'c':case 'C':
NODE_TYPE(p) = LOCATION_NODE;
attr_size = encode_location_attr( node, p, p_end);
break;
default:
if (node->name[8]) {
NODE_TYPE(p) = LANGUAGE_SWITCH_NODE;
} else {
NODE_TYPE(p) = LANGUAGE_NODE;
attr_size = encode_lang_attr( node, p, p_end);
}
break;
}
break;
case 'm':case 'M':
NODE_TYPE(p) = MAIL_NODE;
attr_size = encode_mail_attr( node, p, p_end);
break;
case 'n':case 'N':
switch (node->name[3]) {
case 'F':case 'f':
NODE_TYPE(p) = NOTFOUND_NODE;
break;
case 'N':case 'n':
NODE_TYPE(p) = NOANSWER_NODE;
break;
default:
NODE_TYPE(p) = NOT_PRESENT_NODE;
break;
}
break;
case 'o':case 'O':
if (node->name[1]=='t' || node->name[1]=='T') {
NODE_TYPE(p) = OTHERWISE_NODE;
} else {
NODE_TYPE(p) = OUTGOING_NODE;
}
break;
case 'p':case 'P':
if (node->name[2]=='o' || node->name[2]=='O') {
NODE_TYPE(p) = PROXY_NODE;
attr_size = encode_proxy_attr( node, p, p_end);
} else if (node->name[8]) {
NODE_TYPE(p) = PRIORITY_SWITCH_NODE;
} else {
NODE_TYPE(p) = PRIORITY_NODE;
attr_size = encode_priority_attr( node, p, p_end);
}
break;
case 'r':case 'R':
switch (node->name[2]) {
case 'j':case 'J':
NODE_TYPE(p) = REJECT_NODE;
attr_size = encode_reject_attr( node, p, p_end);
break;
case 'm':case 'M':
NODE_TYPE(p) = REMOVE_LOCATION_NODE;
attr_size = encode_rmvloc_attr( node, p, p_end);
break;
default:
if (node->name[8]) {
NODE_TYPE(p) = REDIRECTION_NODE;
} else {
NODE_TYPE(p) = REDIRECT_NODE;
attr_size = encode_redirect_attr( node, p, p_end);
}
break;
}
break;
case 's':case 'S':
switch (node->name[3]) {
case 0:
NODE_TYPE(p) = SUB_NODE;
attr_size = encode_sub_attr( node, p, p_end);
break;
case 'c':case 'C':
NODE_TYPE(p) = SUCCESS_NODE;
break;
case 'a':case 'A':
NODE_TYPE(p) = SUBACTION_NODE;
attr_size = encode_subaction_attr( node, p, p_end);
break;
default:
if (node->name[6]) {
NODE_TYPE(p) = STRING_SWITCH_NODE;
attr_size = encode_string_switch_attr( node, p, p_end);
} else {
NODE_TYPE(p) = STRING_NODE;
attr_size = encode_string_attr( node, p, p_end);
}
break;
}
break;
case 't':case 'T':
if (node->name[4]) {
NODE_TYPE(p) = TIME_SWITCH_NODE;
attr_size = encode_time_switch_attr( node, p, p_end);
} else {
NODE_TYPE(p) = TIME_NODE;
attr_size = encode_time_attr( node, p, p_end);
}
break;
default:
LM_ERR("unknown node <%s>\n",node->name);
goto error;
}
/* compute the total length of the node (including attributes) */
if (attr_size<0)
goto error;
sub_tree_size = SIMPLE_NODE_SIZE(p) + (unsigned short)attr_size;
/* encrypt all the kids */
for(kid = node->children,foo=0;kid;kid=kid->next) {
if (kid->type!=XML_ELEMENT_NODE) continue;
SET_KID_OFFSET( p, foo, sub_tree_size);
kid_size = encode_node( kid, p+sub_tree_size, p_end);
if (kid_size<=0)
goto error;
sub_tree_size += (unsigned short)kid_size;
foo++;
}
return sub_tree_size;
error:
return -1;
}
#define BAD_XML "CPL script is not a valid XML document"
#define BAD_XML_LEN (sizeof(BAD_XML)-1)
#define BAD_CPL "CPL script doesn't respect CPL grammar"
#define BAD_CPL_LEN (sizeof(BAD_CPL)-1)
#define NULL_CPL "Empty CPL script"
#define NULL_CPL_LEN (sizeof(NULL_CPL)-1)
#define ENC_ERR "Encoding of the CPL script failed"
#define ENC_ERR_LEN (sizeof(ENC_ERR)-1)
int encodeCPL( str *xml, str *bin, str *log)
{
static char buf[ENCONDING_BUFFER_SIZE];
xmlDocPtr doc;
xmlNodePtr cur;
doc = 0;
list = 0;
/* reset all the logs (if any) to catch some possible err/warn/notice
* from the parser/validater/encoder */
reset_logs();
/* parse the xml */
doc = xmlParseDoc( (unsigned char*)xml->s );
if (!doc) {
append_log( 1, MSG_ERR BAD_XML LF, MSG_ERR_LEN+BAD_XML_LEN+LF_LEN);
LM_ERR( BAD_XML "\n");
goto error;
}
/* check the xml against dtd */
if (xmlValidateDtd(&cvp, doc, dtd)!=1) {
append_log( 1, MSG_ERR BAD_CPL LF, MSG_ERR_LEN+BAD_CPL_LEN+LF_LEN);
LM_ERR( BAD_CPL "\n");
goto error;
}
cur = xmlDocGetRootElement(doc);
if (!cur) {
append_log( 1, MSG_ERR NULL_CPL LF, MSG_ERR_LEN+NULL_CPL_LEN+LF_LEN);
LM_ERR( NULL_CPL "\n");
goto error;
}
bin->len = encode_node( cur, buf, buf+ENCONDING_BUFFER_SIZE);
if (bin->len<0) {
append_log( 1, MSG_ERR ENC_ERR LF, MSG_ERR_LEN+ENC_ERR_LEN+LF_LEN);
LM_ERR( ENC_ERR "\n");
goto error;
}
xmlFreeDoc(doc);
if (list) delete_list(list);
/* compile the log buffer */
compile_logs( log );
bin->s = buf;
return 1;
error:
if (doc) xmlFreeDoc(doc);
if (list) delete_list(list);
/* compile the log buffer */
compile_logs( log );
return 0;
}
/* loads and parse the dtd file; a validating context is created */
int init_CPL_parser( char* DTD_filename )
{
dtd = xmlParseDTD( NULL, (unsigned char*)DTD_filename);
if (!dtd) {
LM_ERR("DTD not parsed successfully\n");
return -1;
}
cvp.userData = (void *) stderr;
cvp.error = (xmlValidityErrorFunc) /*err_print*/ fprintf;
cvp.warning = (xmlValidityWarningFunc) /*err_print*/ fprintf;
return 1;
}