⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpl_parser.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * $Id: cpl_parser.c,v 1.32 2004/08/24 08:58:26 janakj Exp $ * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of ser, a free SIP server. * * ser is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * For a license to use the ser software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: *    info@iptel.org * * ser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 "../../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)/* right and left space trimming */#define trimlr(_s_) \	do{\		for(;(_s_).s[(_s_).len-1]==' ';(_s_).s[--(_s_).len]=0);\		for(;(_s_).s[0]==' ';(_s_).s=(_s_).s+1,(_s_).len--);\	}while(0);#define check_overflow(_p_,_offset_,_end_,_error_) \	do{\		if ((_p_)+(_offset_)>=(_end_)) { \			LOG(L_ERR,"ERROR:cpl-c:%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 */\		trimlr( (_val_) );\		if ((_val_).len==0) {\			LOG(L_ERR,"ERROR:cpl_c:%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 32static 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) {				LOG(L_ERR, "ERROR:cpl_c:decode_mail_url: 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) {							LOG(L_ERR,"ERROR:cpl_c:decode_mail_url: 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:						DBG("DEBUG:cpl_c:decode_mail_url: 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 {							DBG("DEBUG:cpl_c:decode_mail_url: 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) {							LOG(L_ERR,"ERROR:cpl_c:decode_mail_url: 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))) {							DBG("DEBUG:cpl_c:decode_mail_url: 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:	LOG(L_ERR,"ERROR:cpl_c:decode_mail_url: 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:				LOG(L_ERR,"ERROR:cpl_c:encode_address_attr: 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 {					LOG(L_ERR,"ERROR:cpl_c:encode_address_switch_attr: 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:						LOG(L_ERR,"ERROR:cpl_c:encode_address_switch_attr: "							"unknown value <%s> for SUBFIELD attr\n",val.s);						goto error;				}				break;			default:				LOG(L_ERR,"ERROR:cpl_c:encode_address_switch_attr: 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') {			LOG(L_ERR,"ERROR:cpl_c:encode_lang_attr: 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)++;			/*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:	LOG(L_ERR,"ERROR:cpl-c:encode_lang_attr: 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:				LOG(L_ERR,"ERROR:cpl_c:encode_priority_attr: 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);		}	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -