123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605 |
- /*
- * $Id$
- *
- * 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:
- * [email protected]
- *
- * 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., 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 "../../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 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) {
- 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);
- }
- }
- 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') {
- LOG(L_ERR,"ERROR:cpl_c:encode_string_switch_attr: 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:
- LOG(L_ERR,"ERROR:cpl_c:encode_string_switch_attr: 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:
- LOG(L_ERR,"ERROR:cpl_c:encode_string_attr: 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 = STR_STATIC_INIT("TZ=");
- 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:
- LOG(L_ERR,"ERROR:cpl_c:encode_time_switch_attr: 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[0])
- set_attr_type(p, BYMONTH_ATTR, buf_end, error);
- else if (attr->name[0]=='D' || attr->name[0]=='d')
- set_attr_type(p, BYMONTHDAY_ATTR, buf_end, error);
- else if (attr->name[0]=='e' || attr->name[0]=='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:
- LOG(L_ERR,"ERROR:cpl_c:encode_time_attr: 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) ) {
- LOG(L_ERR,"ERROR:cpl_c:encode_lookup_attr: 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 {
- LOG(L_ERR,"ERROR:cpl_c:encode_lookup_attr: unknown value "
- "<%.*s> for attribute CLEAR\n",val.len,val.s);
- goto error;
- }
- } else if ( !strcasecmp((const char*)attr->name,"timeout") ) {
- LOG(L_WARN,"WARNING:cpl_c:encode_lookup_attr: unsupported param "
- "TIMEOUT; skipping\n");
- } else {
- LOG(L_ERR,"ERROR:cpl_c:encode_lookup_attr: 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) {
- LOG(L_ERR,"ERROR:cpl-c:encrypt_location_attr: <%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:
- LOG(L_ERR,"ERROR:cpl_c:encode_location_attr: unknown attribute "
- "<%s>\n",attr->name);
- goto error;
- }
- }
- return p-p_orig;
- prio_error:
- LOG(L_ERR,"ERROR:cpl_c:encode_location_attr: 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) {
- LOG(L_ERR,"ERROR:cpl-c:encrypt_rmvloc_attr: <%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:
- LOG(L_ERR,"ERROR:cpl_c:encode_rmvloc_attr: 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 {
- LOG(L_ERR,"ERROR:cpl_c:encode_proxy_attr: 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) {
- LOG(L_ERR,"ERROR:cpl_c:encode_proxy_attr: 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:
- LOG(L_ERR,"ERROR:cpl_c:encode_proxy_attr: unknown "
- "value <%s> for attribute ORDERING\n",val.s);
- goto error;
- }
- break;
- default:
- LOG(L_ERR,"ERROR:cpl_c:encode_proxy_attr: 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 {
- LOG(L_ERR,"ERROR:cpl_c:encode_priority_attr: bad "
- "val. <%s> for STATUS\n",val.s);
- goto error;
- }
- } else if (nr<400 || nr>700) {
- LOG(L_ERR,"ERROR:cpl_c:encode_priority_attr: bad "
- "code <%d> for STATUS\n",nr);
- goto error;
- } else {
- append_short_attr(p, nr, buf_end, error);
- }
- break;
- default:
- LOG(L_ERR,"ERROR:cpl_c:encode_priority_attr: 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 {
- LOG(L_ERR,"ERROR:cpl_c:encode_redirect_attr: bad "
- "val. <%s> for PERMANENT\n",val.s);
- goto error;
- }
- } else {
- LOG(L_ERR,"ERROR:cpl_c:encode_redirect_attr: 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:
- LOG(L_ERR,"ERROR:cpl_c:encode_log_attr: 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') {
- LOG(L_ERR,"ERROR:cpl_c:encode_node_attr: 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) {
- LOG(L_ERR,"ERROR:cpl_c:encode_subaction_attr: failed to add "
- "subaction into list -> pkg_malloc failed?\n");
- goto error;
- }
- } else {
- LOG(L_ERR,"ERROR:cpl_c:encode_subaction_attr: 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 ) {
- LOG(L_ERR,"ERROR:cpl_c:encode_sub_attr: 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 ) {
- LOG(L_ERR,"ERROR:cpl_c:encode_sub_attr: 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:
- LOG(L_ERR,"ERROR:cpl-c:encode_node: 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);
- LOG(L_ERR,"ERROR:cpl:encodeCPL:" 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);
- LOG(L_ERR,"ERROR:cpl-c:encodeCPL: " 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);
- LOG(L_ERR,"ERROR:cpl-c:encodeCPL: " 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);
- LOG(L_ERR,"ERROR:cpl-c:encodeCPL: " 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;
- }
- #if 0
- static void err_print(void *ctx, const char *msg, ...)
- {
- va_list ap;
- //char *t;
- va_start( ap, msg);
- LOG(L_ERR,"->>>> my errr <%s>\n",msg);
- //while ( (t=va_arg(ap, char *))!=0) {
- // LOG(L_ERR," -> <%s>\n",t);
- //}
- vfprintf(stderr,msg,ap);
- //append_log( 2, ERR, ERR_LEN, msg, strlen(msg) );
- va_end(ap);
- }
- #endif
- /* 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) {
- LOG(L_ERR,"ERROR:cpl-c:init_CPL_parser: 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;
- }
|