cpl_parser.c

Go to the documentation of this file.
00001 /*
00002  * $Id: cpl_parser.c 4518 2008-07-28 15:39:28Z henningw $
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  */
00022 
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <stdlib.h>
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 #include <fcntl.h>
00029 #include <errno.h>
00030 #include <unistd.h>
00031 #include <libxml/xmlmemory.h>
00032 #include <libxml/parser.h>
00033 
00034 #include "../../parser/parse_uri.h"
00035 #include "../../dprint.h"
00036 #include "../../str.h"
00037 #include "../../ut.h"
00038 #include "CPL_tree.h"
00039 #include "sub_list.h"
00040 #include "cpl_log.h"
00041 
00042 
00043 
00044 static struct node *list = 0;
00045 static xmlDtdPtr     dtd;     /* DTD file */
00046 static xmlValidCtxt  cvp;     /* validating context */
00047 
00048 
00049 typedef unsigned short length_type ;
00050 typedef length_type*   length_type_ptr;
00051 
00052 enum {EMAIL_TO,EMAIL_HDR_NAME,EMAIL_KNOWN_HDR_BODY,EMAIL_UNKNOWN_HDR_BODY};
00053 
00054 
00055 #define ENCONDING_BUFFER_SIZE 65536
00056 
00057 #define FOR_ALL_ATTR(_node,_attr) \
00058    for( (_attr)=(_node)->properties ; (_attr) ; (_attr)=(_attr)->next)
00059 
00060 #define check_overflow(_p_,_offset_,_end_,_error_) \
00061    do{\
00062       if ((_p_)+(_offset_)>=(_end_)) { \
00063          LM_ERR("%s:%d: overflow -> buffer to small\n",\
00064             __FILE__,__LINE__);\
00065          goto _error_;\
00066       }\
00067    }while(0)\
00068 
00069 #define set_attr_type(_p_,_type_,_end_,_error_) \
00070    do{\
00071       check_overflow(_p_,sizeof(length_type),_end_,_error_);\
00072       *((length_type_ptr)(_p_)) = htons((length_type)(_type_));\
00073       (_p_) += sizeof(length_type);\
00074    }while(0)\
00075 
00076 #define append_short_attr(_p_,_n_,_end_,_error_) \
00077    do{\
00078       check_overflow(_p_,sizeof(length_type),_end_,_error_);\
00079       *((length_type_ptr)(_p_)) = htons((length_type)(_n_));\
00080       (_p_) += sizeof(length_type);\
00081    }while(0)
00082 
00083 #define append_str_attr(_p_,_s_,_end_,_error_) \
00084    do{\
00085       check_overflow(_p_,(_s_).len + 1*((((_s_).len)&0x0001)==1),\
00086          _end_,_error_);\
00087       *((length_type_ptr)(_p_)) = htons((length_type)(_s_).len);\
00088       (_p_) += sizeof(length_type);\
00089       memcpy( (_p_), (_s_).s, (_s_).len);\
00090       (_p_) += (_s_).len + 1*((((_s_).len)&0x0001)==1);\
00091    }while(0)
00092 
00093 #define append_double_str_attr(_p_,_s1_,_s2_,_end_,_error_) \
00094    do{\
00095       check_overflow(_p_,(_s1_).len + (_s2_).len +\
00096          1*((((_s2_).len+(_s2_).len)&0x0001)==1), _end_, _error_);\
00097       *((length_type_ptr)(_p_))=htons((length_type)((_s1_).len)+(_s2_).len);\
00098       (_p_) += sizeof(length_type);\
00099       memcpy( (_p_), (_s1_).s, (_s1_).len);\
00100       (_p_) += (_s1_).len;\
00101       memcpy( (_p_), (_s2_).s, (_s2_).len);\
00102       (_p_) += (_s2_).len + 1*((((_s1_).len+(_s2_).len)&0x0001)==1);\
00103    }while(0)
00104 
00105 #define get_attr_val(_attr_name_,_val_,_error_) \
00106    do { \
00107       (_val_).s = (char*)xmlGetProp(node,(_attr_name_));\
00108       (_val_).len = strlen((_val_).s);\
00109       /* remove all spaces from begin and end */\
00110       trim_spaces_lr( (_val_) );\
00111       if ((_val_).len==0) {\
00112          LM_ERR("%s:%d: attribute <%s> has an "\
00113             "empty value\n",__FILE__,__LINE__,(_attr_name_));\
00114          goto _error_;\
00115       }\
00116    }while(0)\
00117 
00118 
00119 
00120 #define MAX_EMAIL_HDR_SIZE   7 /*we are looking only for SUBJECT and BODY ;-)*/
00121 #define MAX_EMAIL_BODY_SIZE    512
00122 #define MAX_EMAIL_SUBJECT_SIZE 32
00123 
00124 static inline char *decode_mail_url(char *p, char *p_end, char *url,
00125                                           unsigned char *nr_attr)
00126 {
00127    static char buf[ MAX_EMAIL_HDR_SIZE ];
00128    char c;
00129    char foo;
00130    unsigned short hdr_len;
00131    unsigned short *len;
00132    int max_len;
00133    int status;
00134 
00135    /* init */
00136    hdr_len = 0;
00137    max_len = 0;
00138    status = EMAIL_TO;
00139    (*nr_attr) ++;
00140    set_attr_type(p, TO_ATTR, p_end, error); /* attr type */
00141    len = ((unsigned short*)(p));  /* attr val's len */
00142    *len = 0; /* init the len */
00143    p += 2;
00144 
00145    /* parse the whole url */
00146    do {
00147       /* extract a char from the encoded url */
00148       if (*url=='+') {
00149          /* substitute a blank for a plus */
00150          c=' ';
00151          url++;
00152       /* Look for a hex encoded character */
00153       } else if ( (*url=='%') && *(url+1) && *(url+2) ) {
00154          /* hex encoded - convert to a char */
00155          c = hex2int(url[1]);
00156          foo = hex2int(url[2]);
00157          if (c==-1 || foo==-1) {
00158             LM_ERR("non-ASCII escaped "
00159                "character in mail url [%.*s]\n", 3, url);
00160             goto error;
00161          }
00162          c = c<<4 | foo;
00163          url += 3;
00164       } else {
00165          /* normal character - just copy it without changing */
00166          c = *url;
00167          url++;
00168       }
00169 
00170       /* finally we got a character !! */
00171       switch (c) {
00172          case '?':
00173             switch (status) {
00174                case EMAIL_TO:
00175                   if (*len==0) {
00176                      LM_ERR("empty TO "
00177                         "address found in MAIL node!\n");
00178                      goto error;
00179                   }
00180                   if (((*len)&0x0001)==1) p++;
00181                   *len = htons(*len);
00182                   hdr_len = 0;
00183                   status = EMAIL_HDR_NAME;
00184                   break;
00185                default: goto parse_error;
00186             }
00187             break;
00188          case '=':
00189             switch (status) {
00190                case EMAIL_HDR_NAME:
00191                   LM_DBG("hdr [%.*s] found\n",
00192                      hdr_len,buf);
00193                   if ( hdr_len==BODY_EMAILHDR_LEN &&
00194                   strncasecmp(buf,BODY_EMAILHDR_STR,hdr_len)==0 ) {
00195                      /* BODY hdr found */
00196                      set_attr_type( p, BODY_ATTR, p_end, error);
00197                      max_len = MAX_EMAIL_BODY_SIZE;
00198                   } else if ( hdr_len==SUBJECT_EMAILHDR_LEN &&
00199                   strncasecmp(buf,SUBJECT_EMAILHDR_STR,hdr_len)==0 ) {
00200                      /* SUBJECT hdr found */
00201                      set_attr_type( p, SUBJECT_ATTR, p_end, error);
00202                      max_len = MAX_EMAIL_SUBJECT_SIZE;
00203                   } else {
00204                      LM_DBG("unknown hdr -> ignoring\n");
00205                      status = EMAIL_UNKNOWN_HDR_BODY;
00206                      break;
00207                   }
00208                   (*nr_attr) ++;
00209                   len = ((unsigned short*)(p));  /* attr val's len */
00210                   *len = 0; /* init the len */
00211                   p += 2;
00212                   status = EMAIL_KNOWN_HDR_BODY;
00213                   break;
00214                default: goto parse_error;
00215             }
00216             break;
00217          case '&':
00218             switch (status) {
00219                case EMAIL_KNOWN_HDR_BODY:
00220                   if (((*len)&0x0001)==1) p++;
00221                   *len = htons(*len);
00222                case EMAIL_UNKNOWN_HDR_BODY:
00223                   hdr_len = 0;
00224                   status = EMAIL_HDR_NAME;
00225                   break;
00226                default: goto parse_error;
00227             }
00228             break;
00229          case 0:
00230             switch (status) {
00231                case EMAIL_TO:
00232                   if (*len==0) {
00233                      LM_ERR("empty TO "
00234                         "address found in MAIL node!\n");
00235                      goto error;
00236                   }
00237                case EMAIL_KNOWN_HDR_BODY:
00238                   if (((*len)&0x0001)==1) p++;
00239                   *len = htons(*len);
00240                case EMAIL_UNKNOWN_HDR_BODY:
00241                   break;
00242                default: goto parse_error;
00243             }
00244             break;
00245          default:
00246             switch (status) {
00247                case EMAIL_TO:
00248                   (*len)++;
00249                   *(p++) = c;
00250                   if (*len==URL_MAILTO_LEN &&
00251                   !strncasecmp(p-(*len),URL_MAILTO_STR,(*len))) {
00252                      LM_DBG("MAILTO: found at"
00253                         " the beginning of TO -> removed\n");
00254                      p -= (*len);
00255                      *len = 0;
00256                   }
00257                   break;
00258                case EMAIL_KNOWN_HDR_BODY:
00259                   if ((*len)<max_len) (*len)++;
00260                   *(p++) = c;
00261                   break;
00262                case EMAIL_HDR_NAME:
00263                   if (hdr_len<MAX_EMAIL_HDR_SIZE) hdr_len++;
00264                   buf[hdr_len-1] = c;
00265                   break;
00266                case EMAIL_UNKNOWN_HDR_BODY:
00267                   /* do nothing */
00268                   break;
00269                default : goto parse_error;
00270             }
00271       }
00272    }while(c!=0);
00273 
00274    return p;
00275 parse_error:
00276    LM_ERR("unexpected char [%c] in state %d"
00277       " in email url \n",*url,status);
00278 error:
00279    return 0;
00280 }
00281 
00282 
00283 
00284 /* Attr. encoding for ADDRESS node:
00285  *   | attr_t(2) attr_len(2) attr_val(2*x) |  IS/CONTAINS/SUBDOMAIN_OF attr (NT)
00286  */
00287 static inline int encode_address_attr(xmlNodePtr  node, char *node_ptr, char *buf_end)
00288 {
00289    xmlAttrPtr     attr;
00290    char           *p, *p_orig;
00291    unsigned char  *nr_attr;
00292    str            val;
00293 
00294    nr_attr = &(NR_OF_ATTR(node_ptr));
00295    *nr_attr = 0;
00296    p = p_orig = ATTR_PTR(node_ptr);
00297 
00298    FOR_ALL_ATTR(node,attr) {
00299       (*nr_attr)++;
00300       switch (attr->name[0]) {
00301          case 'i': case 'I':
00302             set_attr_type(p, IS_ATTR, buf_end, error);
00303             break;
00304          case 'c': case 'C':
00305             set_attr_type(p, CONTAINS_ATTR, buf_end, error);
00306             break;
00307          case 's': case 'S':
00308             set_attr_type(p, SUBDOMAIN_OF_ATTR, buf_end, error);
00309             break;
00310          default:
00311             LM_ERR("unknown attribute "
00312                "<%s>\n",attr->name);
00313             goto error;
00314       }
00315       /* get the value of the attribute */
00316       get_attr_val( attr->name , val, error);
00317       /* copy also the \0 from the end of string */
00318       val.len++;
00319       append_str_attr(p, val, buf_end, error);
00320    }
00321 
00322    return p-p_orig;
00323 error:
00324    return -1;
00325 }
00326 
00327 
00328 
00329 /* Attr. encoding for ADDRESS_SWITCH node:
00330  *   | attr1_t(2) attr1_val(2) |                FIELD attr
00331  *  [| attr2_t(2) attr2_val(2) |]?              SUBFILED attr
00332  */
00333 static inline int encode_address_switch_attr(xmlNodePtr node, char *node_ptr,
00334                                                 char *buf_end)
00335 {
00336    xmlAttrPtr     attr;
00337    char           *p, *p_orig;
00338    unsigned char  *nr_attr;
00339    str            val;
00340 
00341    nr_attr = &(NR_OF_ATTR(node_ptr));
00342    *nr_attr = 0;
00343    p = p_orig = ATTR_PTR(node_ptr);
00344 
00345    FOR_ALL_ATTR(node,attr) {
00346       (*nr_attr)++;
00347       /* get the value of the attribute */
00348       get_attr_val( attr->name , val, error);
00349       switch(attr->name[0]) {
00350          case 'F': case 'f':
00351             set_attr_type(p, FIELD_ATTR, buf_end, error);
00352             if (val.s[0]=='D' || val.s[0]=='d')
00353                append_short_attr(p, DESTINATION_VAL, buf_end, error);
00354             else if (val.s[6]=='A' || val.s[6]=='a')
00355                append_short_attr(p,ORIGINAL_DESTINATION_VAL,buf_end,error);
00356             else if (!val.s[6])
00357                append_short_attr(p, ORIGIN_VAL, buf_end, error);
00358             else {
00359                LM_ERR("unknown"
00360                   " value <%s> for FIELD attr\n",val.s);
00361                goto error;
00362             };
00363             break;
00364          case 'S': case 's':
00365             set_attr_type(p, SUBFIELD_ATTR, buf_end, error);
00366             switch (val.s[0]) {
00367                case 'u': case 'U':
00368                   append_short_attr(p, USER_VAL, buf_end, error);
00369                   break;
00370                case 'h': case 'H':
00371                   append_short_attr(p, HOST_VAL, buf_end, error);
00372                   break;
00373                case 'p': case 'P':
00374                   append_short_attr(p, PORT_VAL, buf_end, error);
00375                   break;
00376                case 't': case 'T':
00377                   append_short_attr(p, TEL_VAL, buf_end, error);
00378                   break;
00379                case 'd': case 'D':
00380                   /*append_short_attr(p, DISPLAY_VAL, buf_end, error);
00381                   break;*/  /* NOT YET SUPPORTED BY INTERPRETER */
00382                case 'a': case 'A':
00383                   /*append_short_attr(p, ADDRESS_TYPE_VAL, buf_end,error);
00384                   break;*/  /* NOT YET SUPPORTED BY INTERPRETER */
00385                default:
00386                   LM_ERR("unknown value <%s> for SUBFIELD attr\n",val.s);
00387                   goto error;
00388             }
00389             break;
00390          default:
00391             LM_ERR("unknown attribute <%s>\n",attr->name);
00392             goto error;
00393       }
00394    }
00395 
00396    return p-p_orig;
00397 error:
00398    return -1;
00399 }
00400 
00401 
00402 
00403 /* Attr. encoding for LANGUAGE node:
00404  *   | attr_t(2) attr_len(2) attr_val(2*x) |              MATCHES attr  (NNT)
00405  */
00406 static inline int encode_lang_attr(xmlNodePtr  node, char *node_ptr, char *buf_end)
00407 
00408 {
00409    xmlAttrPtr     attr;
00410    char           *p, *p_orig;
00411    unsigned char  *nr_attr;
00412    char           *end;
00413    char           *val_bk;
00414    str            val;
00415 
00416    nr_attr = &(NR_OF_ATTR(node_ptr));
00417    *nr_attr = 0;
00418    p = p_orig = ATTR_PTR(node_ptr);
00419 
00420    FOR_ALL_ATTR(node,attr) {
00421       /* there is only one attribute -> MATCHES */
00422       if (attr->name[0]!='M' && attr->name[0]!='m') {
00423          LM_ERR("unknown attribute "
00424             "<%s>\n",attr->name);
00425          goto error;
00426       }
00427       val.s = val_bk = (char*)xmlGetProp(node,attr->name);
00428       /* parse the language-tag */
00429       for(end=val.s,val.len=0;;end++) {
00430          /* trim all spaces from the beginning of the tag */
00431          if (!val.len && (*end==' ' || *end=='\t')) continue;
00432          /* we cannot have more than 2 attrs - LANG_TAG and LANG_SUBTAG */
00433          if ((*nr_attr)>=2) goto lang_error;
00434          if (((*end)|0x20)>='a' && ((*end)|0x20)<='z') {
00435             val.len++; continue;
00436          } else if (*end=='*' && val.len==0 && (*nr_attr)==0 &&
00437          (*end==' '|| *end=='\t' || *end==0)) {
00438             val.len++;
00439             set_attr_type(p, MATCHES_TAG_ATTR, buf_end, error);
00440          } else if (val.len && (*nr_attr)==0 && *end=='-' ) {
00441             set_attr_type(p, MATCHES_TAG_ATTR, buf_end, error);
00442          } else if (val.len && ((*nr_attr)==0 || (*nr_attr)==1) &&
00443          (*end==' '|| *end=='\t' || *end==0)) {
00444             set_attr_type(p,
00445                (!(*nr_attr))?MATCHES_TAG_ATTR:MATCHES_SUBTAG_ATTR,
00446                buf_end, error );
00447          } else goto lang_error;
00448          (*nr_attr)++;
00449          /*LM_DBG("----> language tag=%d; %d [%.*s]\n",*(p-1),
00450             val.len,val.len,end-val.len);*/
00451          val.s = end-val.len;
00452          append_str_attr(p, val, buf_end, error);
00453          val.len = 0;
00454          if (*end==0) break;
00455       }
00456    }
00457 
00458    return p-p_orig;
00459 lang_error:
00460    LM_ERR("bad value for language_tag <%s>\n",val_bk);
00461 error:
00462    return -1;
00463 }
00464 
00465 
00466 
00467 /* Attr. encoding for PRIORITY node:
00468  *   | attr1_t(2) attr1_val(2) |                  LESS/GREATER/EQUAL attr
00469  *  [| attr2_t(2) attr2_len(2) attr_val(2*x) |]?  PRIOSTR attr (NT)
00470  */
00471 static inline int encode_priority_attr(xmlNodePtr  node, char *node_ptr, char *buf_end)
00472 {
00473    xmlAttrPtr     attr;
00474    char  *p, *p_orig;
00475    unsigned char  *nr_attr;
00476    str            val;
00477 
00478    nr_attr = &(NR_OF_ATTR(node_ptr));
00479    *nr_attr = 0;
00480    p = p_orig = ATTR_PTR(node_ptr);
00481 
00482    FOR_ALL_ATTR(node,attr) {
00483       (*nr_attr)++;
00484       /* attribute's name */
00485       switch(attr->name[0]) {
00486          case 'L': case 'l':
00487             set_attr_type(p, LESS_ATTR, buf_end, error);
00488             break;
00489          case 'G': case 'g':
00490             set_attr_type(p, GREATER_ATTR, buf_end, error);
00491             break;
00492          case 'E': case 'e':
00493             set_attr_type(p, EQUAL_ATTR, buf_end, error);
00494             break;
00495          default:
00496             LM_ERR("unknown attribute <%s>\n",attr->name);
00497             goto error;
00498       }
00499       /* attribute's encoded value */
00500       get_attr_val( attr->name , val, error);
00501       if ( val.len==EMERGENCY_STR_LEN &&
00502       !strncasecmp(val.s,EMERGENCY_STR,val.len) ) {
00503          append_short_attr(p, EMERGENCY_VAL, buf_end, error);
00504       } else if ( val.len==URGENT_STR_LEN &&
00505       !strncasecmp(val.s,URGENT_STR,val.len) ) {
00506          append_short_attr(p, URGENT_VAL, buf_end, error);
00507       } else if ( val.len==NORMAL_STR_LEN &&
00508       !strncasecmp(val.s,NORMAL_STR,val.len) ) {
00509          append_short_attr(p, NORMAL_VAL, buf_end, error);
00510       } else if ( val.len==NON_URGENT_STR_LEN &&
00511       !strncasecmp(val.s,NON_URGENT_STR,val.len) ) {
00512          append_short_attr(p, NON_URGENT_VAL, buf_end, error);
00513       } else {
00514          append_short_attr(p, UNKNOWN_PRIO_VAL, buf_end, error);
00515          set_attr_type(p, PRIOSTR_ATTR, buf_end, error);
00516          val.len++; /* append \0 also */
00517          append_str_attr(p, val, buf_end, error);
00518       }
00519    }
00520 
00521    return p-p_orig;
00522 error:
00523    return -1;
00524 }
00525 
00526 
00527 
00528 /* Attr. encoding for STRING_SWITCH node:
00529  *  [| attr1_t(2) attr1_len(2) attr_val(2*x) |]?  IS attr  (NT)
00530  *  [| attr2_t(2) attr2_len(2) attr_val(2*x) |]?  CONTAINS attr (NT)
00531  */
00532 static inline int encode_string_switch_attr(xmlNodePtr  node, char *node_ptr,
00533                                                 char *buf_end)
00534 {
00535    xmlAttrPtr     attr;
00536    char           *p, *p_orig;
00537    unsigned char  *nr_attr;
00538    str            val;
00539 
00540    nr_attr = &(NR_OF_ATTR(node_ptr));
00541    *nr_attr = 0;
00542    p = p_orig = ATTR_PTR(node_ptr);
00543 
00544    FOR_ALL_ATTR(node,attr) {
00545       (*nr_attr)++;
00546       /* there is only one attribute -> MATCHES */
00547       if (attr->name[0]!='F' && attr->name[0]!='f') {
00548          LM_ERR("unknown attribute <%s>\n",attr->name);
00549          goto error;
00550       }
00551       set_attr_type(p, FIELD_ATTR, buf_end, error);
00552       /* attribute's encoded value */
00553       get_attr_val( attr->name , val, error);
00554       switch (val.s[0]) {
00555          case 'S': case 's':
00556             append_short_attr(p, SUBJECT_VAL, buf_end, error);
00557             break;
00558          case 'O': case 'o':
00559             append_short_attr(p, ORGANIZATION_VAL, buf_end, error);
00560             break;
00561          case 'U': case 'u':
00562             append_short_attr(p, USER_AGENT_VAL, buf_end, error);
00563             break;
00564          case 'D': case 'd':
00565             append_short_attr(p, DISPLAY_VAL, buf_end, error);
00566             break;
00567          default:
00568             LM_ERR("unknown "
00569                "value <%s> for FIELD\n",attr->name);
00570             goto error;
00571       }
00572    }
00573 
00574    return p-p_orig;
00575 error:
00576    return -1;
00577 }
00578 
00579 
00580 
00581 /* Attr. encoding for STRING node:
00582  *  [| attr1_t(2) attr1_len(2) attr_val(2*x) |]?  IS attr  (NT)
00583  *  [| attr2_t(2) attr2_len(2) attr_val(2*x) |]?  CONTAINS attr (NT)
00584  */
00585 static inline int encode_string_attr(xmlNodePtr  node, char *node_ptr, char *buf_end)
00586 {
00587    xmlAttrPtr     attr;
00588    char  *p, *p_orig;
00589    unsigned char  *nr_attr;
00590    str            val;
00591 
00592    nr_attr = &(NR_OF_ATTR(node_ptr));
00593    *nr_attr = 0;
00594    p = p_orig = ATTR_PTR(node_ptr);
00595 
00596    FOR_ALL_ATTR(node,attr) {
00597       (*nr_attr)++;
00598       switch(attr->name[0]) {
00599          case 'I': case 'i':
00600             set_attr_type(p, IS_ATTR, buf_end, error);
00601             break;
00602          case 'C': case 'c':
00603             set_attr_type(p, CONTAINS_ATTR, buf_end, error);
00604             break;
00605          default:
00606             LM_ERR("unknown "
00607                "attribute <%s>\n",attr->name);
00608             goto error;
00609       }
00610       /* attribute's encoded value */
00611       get_attr_val( attr->name , val, error);
00612       val.len++; /* grab also the \0 */
00613       append_str_attr(p,val, buf_end, error);
00614    }
00615 
00616    return p-p_orig;
00617 error:
00618    return -1;
00619 }
00620 
00621 
00622 
00623 /* Attr. encoding for TIME_SWITCH node:
00624  *  [| attr1_t(2) attr1_len(2) attr_val(2*x) |]?  TZID attr  (NT)
00625  *  [| attr2_t(2) attr2_len(2) attr_val(2*x) |]?  TZURL attr (NT)
00626  */
00627 static inline int encode_time_switch_attr(xmlNodePtr  node, char *node_ptr,
00628                                                 char *buf_end)
00629 {
00630    static str     tz_str = {"TZ=",3};
00631    xmlAttrPtr     attr;
00632    char           *p, *p_orig;
00633    unsigned char  *nr_attr;
00634    str            val;
00635 
00636    nr_attr = &(NR_OF_ATTR(node_ptr));
00637    *nr_attr = 0;
00638    p = p_orig = ATTR_PTR(node_ptr);
00639 
00640    FOR_ALL_ATTR(node,attr) {
00641       (*nr_attr)++;
00642       switch(attr->name[2]) {
00643          case 'I': case 'i':
00644             set_attr_type(p, TZID_ATTR, buf_end, error);
00645             /* attribute's encoded value */
00646             get_attr_val( attr->name , val, error);
00647             val.len++; /* grab also the \0 */
00648             append_double_str_attr(p,tz_str,val, buf_end, error);
00649             break;
00650          case 'U': case 'u':
00651             /* set_attr_type(p, TZURL_ATTR, buf_end, error);
00652              * is a waste of space to copy the url - the interpreter doesn't
00653              * use it at all ;-) */
00654             break;
00655          default:
00656             LM_ERR("unknown attribute <%s>\n",attr->name);
00657             goto error;
00658       }
00659    }
00660 
00661    return p-p_orig;
00662 error:
00663    return -1;
00664 }
00665 
00666 
00667 
00668 /* Attr. encoding for TIME node:
00669  *   | attr1_t(2) attr1_len(2) attr1_val(2*x) |       DSTART attr  (NT)
00670  *  [| attr2_t(2) attr2_len(2) attr2_val(2*x) |]?     DTEND attr (NT)
00671  *  [| attr3_t(2) attr3_len(2) attr3_val(2*x) |]?     DURATION attr (NT)
00672  *  [| attr4_t(2) attr4_len(2) attr4_val(2*x) |]?     FREQ attr (NT)
00673  *  [| attr5_t(2) attr5_len(2) attr5_val(2*x) |]?     WKST attr (NT)
00674  *  [| attr6_t(2) attr6_len(2) attr6_val(2*x) |]?     BYYEARDAY attr (NT)
00675  *  [| attr7_t(2) attr7_len(2) attr7_val(2*x) |]?     COUNT attr (NT)
00676  *  [| attr8_t(2) attr8_len(2) attr8_val(2*x) |]?     BYSETPOS attr (NT)
00677  *  [| attr9_t(2) attr9_len(2) attr9_val(2*x) |]?     BYMONTH attr (NT)
00678  *  [| attr10_t(2) attr10_len(2) attr_val10(2*x) |]?  BYMONTHDAY attr (NT)
00679  *  [| attr11_t(2) attr11_len(2) attr_val11(2*x) |]?  BYMINUTE attr (NT)
00680  *  [| attr12_t(2) attr12_len(2) attr_val12(2*x) |]?  INTERVAL attr (NT)
00681  *  [| attr13_t(2) attr13_len(2) attr_val13(2*x) |]?  UNTIL attr (NT)
00682  *  [| attr14_t(2) attr14_len(2) attr_val14(2*x) |]?  BYSECOND attr (NT)
00683  *  [| attr15_t(2) attr15_len(2) attr_val15(2*x) |]?  BYHOUR attr (NT)
00684  *  [| attr16_t(2) attr16_len(2) attr_val16(2*x) |]?  BYDAY attr (NT)
00685  *  [| attr17_t(2) attr17_len(2) attr_val17(2*x) |]?  BYWEEKNO attr (NT)
00686  */
00687 static inline int encode_time_attr(xmlNodePtr  node, char *node_ptr,
00688                                                 char *buf_end)
00689 {
00690    xmlAttrPtr     attr;
00691    char           *p, *p_orig;
00692    unsigned char  *nr_attr;
00693    str            val;
00694 
00695    nr_attr = &(NR_OF_ATTR(node_ptr));
00696    *nr_attr = 0;
00697    p = p_orig = ATTR_PTR(node_ptr);
00698 
00699    FOR_ALL_ATTR(node,attr) {
00700       (*nr_attr)++;
00701       switch (attr->name[4]) {
00702          case 0:
00703             if (attr->name[0]=='F' || attr->name[0]=='f')
00704                set_attr_type(p, FREQ_ATTR, buf_end, error);
00705             else if (attr->name[0]=='W' || attr->name[0]=='w')
00706                set_attr_type(p, WKST_ATTR, buf_end, error);
00707             break;
00708          case 'a': case 'A':
00709             if (attr->name[0]=='D' || attr->name[0]=='d')
00710                set_attr_type(p, DTSTART_ATTR, buf_end, error);
00711             else if (attr->name[0]=='B' || attr->name[0]=='b')
00712                set_attr_type(p, BYYEARDAY_ATTR, buf_end, error);
00713             break;
00714          case 't': case 'T':
00715             if (attr->name[0]=='D' || attr->name[0]=='d')
00716                set_attr_type(p, DURATION_ATTR, buf_end, error);
00717             else if (attr->name[0]=='C' || attr->name[0]=='c')
00718                set_attr_type(p, COUNT_ATTR, buf_end, error);
00719             else if (attr->name[0]=='B' || attr->name[0]=='b')
00720                set_attr_type(p, BYSETPOS_ATTR, buf_end, error);
00721             break;
00722          case 'n': case 'N':
00723             if (!attr->name[7])
00724                set_attr_type(p, BYMONTH_ATTR, buf_end, error);
00725             else if (attr->name[7]=='D' || attr->name[7]=='d')
00726                set_attr_type(p, BYMONTHDAY_ATTR, buf_end, error);
00727             else if (attr->name[7]=='e' || attr->name[7]=='E')
00728                set_attr_type(p, BYMINUTE_ATTR, buf_end, error);
00729             break;
00730          case 'd': case 'D':
00731             set_attr_type(p, DTEND_ATTR, buf_end, error);
00732             break;
00733          case 'r': case 'R':
00734             set_attr_type(p, INTERVAL_ATTR, buf_end, error);
00735             break;
00736          case 'l': case 'L':
00737             set_attr_type(p, UNTIL_ATTR, buf_end, error);
00738             break;
00739          case 'c': case 'C':
00740             set_attr_type(p, BYSECOND_ATTR, buf_end, error);
00741             break;
00742          case 'u': case 'U':
00743             set_attr_type(p, BYHOUR_ATTR, buf_end, error);
00744             break;
00745          case 'y': case 'Y':
00746             set_attr_type(p, BYDAY_ATTR, buf_end, error);
00747             break;
00748          case 'e': case 'E':
00749             set_attr_type(p, BYWEEKNO_ATTR, buf_end, error);
00750             break;
00751          default:
00752             LM_ERR("unknown attribute <%s>\n",attr->name);
00753             goto error;
00754       }
00755       /* attribute's encoded value */
00756       get_attr_val( attr->name , val, error);
00757       val.len++; /* grab also the \0 */
00758       append_str_attr(p,val, buf_end, error);
00759    }
00760 
00761    return p-p_orig;
00762 error:
00763    return -1;
00764 }
00765 
00766 
00767 
00768 /* Attr. encoding for LOOKUP node:
00769  *  | attr1_t(2) attr1_len(2) attr1_val(2*x) |      SOURCE attr  (NT)
00770  * [| attr2_t(2) attr2_val(2) |]?                   CLEAR attr
00771  */
00772 static inline int encode_lookup_attr(xmlNodePtr  node, char *node_ptr,
00773                                                 char *buf_end)
00774 {
00775    xmlAttrPtr     attr;
00776    char           *p, *p_orig;
00777    unsigned char  *nr_attr;
00778    str            val;
00779 
00780    nr_attr = &(NR_OF_ATTR(node_ptr));
00781    *nr_attr = 0;
00782    p = p_orig = ATTR_PTR(node_ptr);
00783 
00784    FOR_ALL_ATTR(node,attr) {
00785       /* get attribute's value */
00786       get_attr_val( attr->name , val, error);
00787       if ( !strcasecmp((const char*)attr->name,"source") ) {
00788          /* this param will not be copied, since it has only one value ;-)*/
00789          if ( val.len!=SOURCE_REG_STR_LEN ||
00790          strncasecmp( val.s, SOURCE_REG_STR, val.len) ) {
00791             LM_ERR("unsupported value"
00792                " <%.*s> in SOURCE param\n",val.len,val.s);
00793             goto error;
00794          }
00795       } else if ( !strcasecmp((const char*)attr->name,"clear") ) {
00796          (*nr_attr)++;
00797          set_attr_type(p, CLEAR_ATTR, buf_end, error);
00798          if ( val.len==3 && !strncasecmp(val.s,"yes",3) )
00799             append_short_attr(p, YES_VAL, buf_end, error);
00800          else if ( val.len==2 && !strncasecmp(val.s,"no",2) )
00801             append_short_attr(p, NO_VAL, buf_end, error);
00802          else {
00803             LM_ERR("unknown value "
00804                "<%.*s> for attribute CLEAR\n",val.len,val.s);
00805             goto error;
00806          }
00807       } else if ( !strcasecmp((const char*)attr->name,"timeout") ) {
00808          LM_WARN("unsupported param TIMEOUT; skipping\n");
00809       } else {
00810          LM_ERR("unknown attribute <%s>\n",attr->name);
00811          goto error;
00812       }
00813    }
00814 
00815    return p-p_orig;
00816 error:
00817    return -1;
00818 }
00819 
00820 
00821 
00822 
00823 /* Attr. encoding for LOCATION node:
00824  *  | attr1_t(2) attr1_len(2) attr1_val(2*x) |      URL attr  (NT)
00825  * [| attr2_t(2) attr2_val(2) |]?                   PRIORITY attr
00826  * [| attr3_t(2) attr3_val(2) |]?                   CLEAR attr
00827  */
00828 static inline int encode_location_attr(xmlNodePtr  node, char *node_ptr,
00829                                                 char *buf_end)
00830 {
00831    struct sip_uri uri;
00832    xmlAttrPtr     attr;
00833    char           *p, *p_orig;
00834    unsigned char  *nr_attr;
00835    unsigned short nr;
00836    str            val;
00837 
00838    nr_attr = &(NR_OF_ATTR(node_ptr));
00839    *nr_attr = 0;
00840    p = p_orig = ATTR_PTR(node_ptr);
00841 
00842    FOR_ALL_ATTR(node,attr) {
00843       (*nr_attr)++;
00844       /* get attribute's value */
00845       get_attr_val( attr->name , val, error);
00846       switch(attr->name[0]) {
00847          case 'U': case 'u':
00848             set_attr_type(p, URL_ATTR, buf_end, error);
00849             /* check if it's a valid SIP URL -> just call
00850              * parse uri function and see if returns error ;-) */
00851             if (parse_uri( val.s, val.len, &uri)!=0) {
00852                LM_ERR("<%s> is not a valid SIP URL\n",val.s);
00853                goto error;
00854             }
00855             val.len++; /*copy also the \0 */
00856             append_str_attr(p,val, buf_end, error);
00857             break;
00858          case 'P': case 'p':
00859             set_attr_type(p, PRIORITY_ATTR, buf_end, error);
00860             if (val.s[0]=='0') nr=0;
00861             else if (val.s[0]=='1') nr=10;
00862             else goto prio_error;
00863             if (val.s[1]!='.') goto prio_error;
00864             if (val.s[2]<'0' || val.s[2]>'9') goto prio_error;
00865             nr += val.s[2] - '0';
00866             if (nr>10)
00867                goto prio_error;
00868             append_short_attr(p, nr, buf_end, error);
00869             break;
00870          case 'C': case 'c':
00871             set_attr_type(p, CLEAR_ATTR, buf_end, error);
00872             if (val.s[0]=='y' || val.s[0]=='Y')
00873                append_short_attr(p, YES_VAL, buf_end, error);
00874             else
00875                append_short_attr(p, NO_VAL, buf_end, error);
00876             break;
00877          default:
00878             LM_ERR("unknown attribute <%s>\n",attr->name);
00879             goto error;
00880       }
00881    }
00882 
00883    return p-p_orig;
00884 prio_error:
00885    LM_ERR("invalid priority <%s>\n",val.s);
00886 error:
00887    return -1;
00888 }
00889 
00890 
00891 
00892 /* Attr. encoding for REMOVE_LOCATION node:
00893  * [| attr1_t(2) attr1_len(2) attr1_val(2*x) |]?    LOCATION attr  (NT)
00894  */
00895 static inline int encode_rmvloc_attr(xmlNodePtr  node, char *node_ptr, char *buf_end)
00896 {
00897    struct sip_uri uri;
00898    xmlAttrPtr     attr;
00899    char           *p, *p_orig;
00900    unsigned char  *nr_attr;
00901    str            val;
00902 
00903    nr_attr = &(NR_OF_ATTR(node_ptr));
00904    *nr_attr = 0;
00905    p = p_orig = ATTR_PTR(node_ptr);
00906 
00907    FOR_ALL_ATTR(node,attr) {
00908       (*nr_attr)++;
00909       switch(attr->name[0]) {
00910          case 'L': case 'l':
00911             set_attr_type(p, LOCATION_ATTR, buf_end, error);
00912             /* get the value of the attribute */
00913             get_attr_val( attr->name , val, error);
00914             /* check if it's a valid SIP URL -> just call
00915              * parse uri function and see if returns error ;-) */
00916             if (parse_uri( val.s, val.len, &uri)!=0) {
00917                LM_ERR("<%s> is not a valid SIP URL\n",val.s);
00918                goto error;
00919             }
00920             val.len++; /*copy also the \0 */
00921             append_str_attr(p,val, buf_end, error);
00922             break;
00923          case 'P': case 'p':
00924          case 'V': case 'v':
00925             /* as the interpreter ignores PARAM and VALUE attributes, we will
00926              * do the same ;-) */
00927             break;
00928          default:
00929             LM_ERR("unknown attribute <%s>\n",attr->name);
00930             goto error;
00931       }
00932    }
00933 
00934    return p-p_orig;
00935 error:
00936    return -1;
00937 }
00938 
00939 
00940 
00941 /* Attr. encoding for PROXY node:
00942  * [| attr1_t(2) attr1_val(2) |]?                   RECURSE attr
00943  * [| attr2_t(2) attr2_val(2) |]?                   TIMEOUT attr
00944  * [| attr3_t(2) attr3_val(2) |]?                   ORDERING attr
00945  */
00946 static inline int encode_proxy_attr(xmlNodePtr  node, char *node_ptr,
00947                                                 char *buf_end)
00948 {
00949    xmlAttrPtr     attr;
00950    char           *p, *p_orig;
00951    unsigned char  *nr_attr;
00952    unsigned int   nr;
00953    str            val;
00954 
00955    nr_attr = &(NR_OF_ATTR(node_ptr));
00956    *nr_attr = 0;
00957    p = p_orig = ATTR_PTR(node_ptr);
00958 
00959    FOR_ALL_ATTR(node,attr) {
00960       (*nr_attr)++;
00961       /* get the value of the attribute */
00962       get_attr_val( attr->name , val, error);
00963       switch(attr->name[0]) {
00964          case 'R': case 'r':
00965             set_attr_type(p, RECURSE_ATTR, buf_end, error);
00966             if (val.s[0]=='y' || val.s[0]=='Y')
00967                append_short_attr(p, YES_VAL, buf_end, error);
00968             else if (val.s[0]=='n' || val.s[0]=='N')
00969                append_short_attr(p, NO_VAL, buf_end, error);
00970             else {
00971                LM_ERR("unknown value "
00972                   "<%s> for attribute RECURSE\n",val.s);
00973                goto error;
00974             }
00975             break;
00976          case 'T': case 't':
00977             set_attr_type(p, TIMEOUT_ATTR, buf_end, error);
00978             if (str2int(&val,&nr)==-1) {
00979                LM_ERR("bad value <%.*s>"
00980                   " for attribute TIMEOUT\n",val.len,val.s);
00981                goto error;
00982             }
00983             append_short_attr(p, (unsigned short)nr, buf_end, error);
00984             break;
00985          case 'O': case 'o':
00986             set_attr_type(p, ORDERING_ATTR, buf_end, error);
00987             switch (val.s[0]) {
00988                case 'p': case'P':
00989                   append_short_attr(p, PARALLEL_VAL, buf_end, error);
00990                   break;
00991                case 'S': case 's':
00992                   append_short_attr(p, SEQUENTIAL_VAL, buf_end, error);
00993                   break;
00994                case 'F': case 'f':
00995                   append_short_attr(p, FIRSTONLY_VAL, buf_end, error);
00996                   break;
00997                default:
00998                   LM_ERR("unknown "
00999                      "value <%s> for attribute ORDERING\n",val.s);
01000                   goto error;
01001             }
01002             break;
01003          default:
01004             LM_ERR("unknown attribute <%s>\n",attr->name);
01005             goto error;
01006       }
01007    }
01008 
01009    return p-p_orig;
01010 error:
01011    return -1;
01012 }
01013 
01014 
01015 
01016 /* Attr. encoding for REJECT node:
01017  *  | attr1_t(2) attr1_val(2) |                      STATUS attr
01018  * [| attr2_t(2) attr2_len(2) attr2_val(2*x)|]?      REASON attr (NT)
01019  */
01020 static inline int encode_reject_attr(xmlNodePtr  node, char *node_ptr, char *buf_end)
01021 {
01022    xmlAttrPtr     attr;
01023    char           *p, *p_orig;
01024    unsigned char  *nr_attr;
01025    unsigned int   nr;
01026    str            val;
01027 
01028    nr_attr = &(NR_OF_ATTR(node_ptr));
01029    *nr_attr = 0;
01030    p = p_orig = ATTR_PTR(node_ptr);
01031 
01032    FOR_ALL_ATTR(node,attr) {
01033       (*nr_attr)++;
01034       /* get the value of the attribute */
01035       get_attr_val( attr->name , val, error);
01036       switch(attr->name[0]) {
01037          case 'R': case 'r':
01038             set_attr_type(p, REASON_ATTR, buf_end, error);
01039             val.len++; /* grab also the /0 */
01040             append_str_attr(p, val, buf_end, error);
01041             break;
01042          case 'S': case 's':
01043             set_attr_type(p, STATUS_ATTR, buf_end, error);
01044             if (str2int(&val,&nr)==-1) {
01045                /*it was a non numeric value */
01046                if (val.len==BUSY_STR_LEN &&
01047                !strncasecmp(val.s,BUSY_STR,val.len)) {
01048                   append_short_attr(p, BUSY_VAL, buf_end, error);
01049                } else if (val.len==NOTFOUND_STR_LEN &&
01050                !strncasecmp(val.s,NOTFOUND_STR,val.len)) {
01051                   append_short_attr(p, NOTFOUND_VAL, buf_end, error);
01052                } else if (val.len==ERROR_STR_LEN &&
01053                !strncasecmp(val.s,ERROR_STR,val.len)) {
01054                   append_short_attr(p, ERROR_VAL, buf_end, error);
01055                } else if (val.len==REJECT_STR_LEN &&
01056                !strncasecmp(val.s,REJECT_STR,val.len)) {
01057                   append_short_attr(p, REJECT_VAL, buf_end, error);
01058                } else {
01059                   LM_ERR("bad val. <%s> for STATUS\n",val.s);
01060                   goto error;
01061                }
01062             } else if (nr<400 || nr>700) {
01063                LM_ERR("bad code <%d> for STATUS\n",nr);
01064                goto error;
01065             } else {
01066                append_short_attr(p, nr, buf_end, error);
01067             }
01068             break;
01069          default:
01070             LM_ERR("unknown attribute <%s>\n",attr->name);
01071             goto error;
01072       }
01073    }
01074 
01075    return p-p_orig;
01076 error:
01077    return -1;
01078 }
01079 
01080 
01081 
01082 /* Attr. encoding for REDIRECT node:
01083  *  | attr1_t(2) attr1_val(2) |                      STATUS attr
01084  * [| attr2_t(2) attr2_len(2) attr2_val(2*x)|]?      REASON attr (NT)
01085  */
01086 static inline int encode_redirect_attr(xmlNodePtr  node, char *node_ptr, char *buf_end)
01087 {
01088    xmlAttrPtr     attr;
01089    char           *p, *p_orig;
01090    unsigned char  *nr_attr;
01091    str            val;
01092 
01093    nr_attr = &(NR_OF_ATTR(node_ptr));
01094    *nr_attr = 0;
01095    p = p_orig = ATTR_PTR(node_ptr);
01096 
01097    FOR_ALL_ATTR(node,attr) {
01098       (*nr_attr)++;
01099       if (attr->name[0]=='p' || attr->name[0]=='P') {
01100          set_attr_type(p, PERMANENT_ATTR, buf_end, error);
01101          /* get the value */
01102          get_attr_val( attr->name , val, error);
01103          if (val.s[0]=='y' || val.s[0]=='Y')
01104             append_short_attr( p, YES_VAL, buf_end, error);
01105          else if (val.s[0]=='n' || val.s[0]=='N')
01106             append_short_attr( p, NO_VAL, buf_end, error);
01107          else {
01108             LM_ERR("bad val. <%s> for PERMANENT\n",val.s);
01109             goto error;
01110          }
01111       } else {
01112          LM_ERR("unknown attribute <%s>\n",attr->name);
01113          goto error;
01114       }
01115    }
01116 
01117    return p-p_orig;
01118 error:
01119    return -1;
01120 }
01121 
01122 
01123 
01124 /* Attr. encoding for LOG node:
01125  *  [| attr1_t(2) attr1_len(2) attr1_val(2*x) |]?       NAME attr  (NT)
01126  *  [| attr2_t(2) attr2_len(2) attr2_val(2*x) |]?       COMMENT attr (NT)
01127  */
01128 static inline int encode_log_attr(xmlNodePtr  node, char *node_ptr, char *buf_end)
01129 {
01130    xmlAttrPtr     attr;
01131    char           *p, *p_orig;
01132    unsigned char  *nr_attr;
01133    str            val;
01134 
01135    nr_attr = &(NR_OF_ATTR(node_ptr));
01136    *nr_attr = 0;
01137    p = p_orig = ATTR_PTR(node_ptr);
01138 
01139    FOR_ALL_ATTR(node,attr) {
01140       (*nr_attr)++;
01141       /* get the value of the attribute */
01142       get_attr_val( attr->name , val, error);
01143       switch (attr->name[0] ) {
01144          case 'n': case 'N':
01145             if (val.len>MAX_NAME_SIZE) val.len=MAX_NAME_SIZE;
01146             set_attr_type(p, NAME_ATTR, buf_end, error);
01147             break;
01148          case 'c': case 'C':
01149             if (val.len>MAX_COMMENT_SIZE) val.len=MAX_COMMENT_SIZE;
01150             set_attr_type(p, COMMENT_ATTR, buf_end, error);
01151             break;
01152          default:
01153             LM_ERR("unknown attribute <%s>\n",attr->name);
01154                goto error;
01155       }
01156       /* be sure there is a \0 at the end of string */
01157       val.s[val.len++]=0;
01158       append_str_attr(p,val, buf_end, error);
01159    }
01160 
01161    return p-p_orig;
01162 error:
01163    return -1;
01164 }
01165 
01166 
01167 
01168 /* Attr. encoding for MAIL node:
01169  *   | attr1_t(2) attr1_len(2) attr1_val(2*x) |        TO_ATTR attr  (NNT)
01170  *  [| attr2_t(2) attr2_len(2) attr2_val(2*x) |]?      SUBJECT_ATTR attr (NNT)
01171  *  [| attr3_t(2) attr3_len(2) attr3_val(2*x) |]?      BODY_ATTR attr (NNT)
01172  */
01173 static inline int encode_mail_attr(xmlNodePtr  node, char *node_ptr, char *buf_end)
01174 {
01175    xmlAttrPtr     attr;
01176    char           *p, *p_orig;
01177    unsigned char  *nr_attr;
01178 
01179    nr_attr = &(NR_OF_ATTR(node_ptr));
01180    *nr_attr = 0;
01181    p = p_orig = ATTR_PTR(node_ptr);
01182 
01183    FOR_ALL_ATTR(node,attr) {
01184       /* there is only one attribute -> URL */
01185       if (attr->name[0]!='u' && attr->name[0]!='U') {
01186          LM_ERR("unknown attribute <%s>\n",attr->name);
01187          goto error;
01188       }
01189       p = decode_mail_url( p, buf_end,
01190          (char*)xmlGetProp(node,attr->name), nr_attr);
01191       if (p==0)
01192          goto error;
01193    }
01194 
01195    return p-p_orig;
01196 error:
01197    return -1;
01198 }
01199 
01200 
01201 
01202 /* Attr. encoding for SUBACTION node:
01203  */
01204 static inline int encode_subaction_attr(xmlNodePtr  node, char *node_ptr,
01205                                                 char *buf_end)
01206 {
01207    xmlAttrPtr     attr;
01208    str            val;
01209 
01210    FOR_ALL_ATTR(node,attr) {
01211       /* there is only one attribute -> ID */
01212       if ((attr->name[0]|0x20)=='i' && ((attr->name[1]|0x20)=='d') &&
01213       attr->name[2]==0 ) {
01214          /* get the value of the attribute */
01215          get_attr_val( attr->name , val, error);
01216          if ((list = append_to_list(list, node_ptr,val.s))==0) {
01217             LM_ERR("failed to add "
01218                "subaction into list -> pkg_malloc failed?\n");
01219             goto error;
01220          }
01221       } else {
01222          LM_ERR("unknown attribute <%s>\n",attr->name);
01223          goto error;
01224       }
01225    }
01226 
01227    return 0;
01228 error:
01229    return -1;
01230 }
01231 
01232 
01233 
01234 /* Attr. encoding for SUB node:
01235  *   | attr1_t(2) attr1_val(2) |              REF_ATTR attr
01236  */
01237 static inline int encode_sub_attr(xmlNodePtr  node, char *node_ptr, char *buf_end)
01238 {
01239    xmlAttrPtr     attr;
01240    char           *p, *p_orig;
01241    unsigned char  *nr_attr;
01242    char           *sub_ptr;
01243    str            val;
01244 
01245    nr_attr = &(NR_OF_ATTR(node_ptr));
01246    *nr_attr = 0;
01247    p = p_orig = ATTR_PTR(node_ptr);
01248 
01249    FOR_ALL_ATTR(node,attr) {
01250       (*nr_attr)++;
01251       /* there is only one attribute -> REF */
01252       if ( strcasecmp("ref",(char*)attr->name)!=0 ) {
01253          LM_ERR("unknown attribute <%s>\n",attr->name);
01254          goto error;
01255       }
01256       set_attr_type(p, REF_ATTR, buf_end, error);
01257       /* get the value of the attribute */
01258       get_attr_val( attr->name , val, error);
01259       if ( (sub_ptr=search_the_list(list, val.s))==0 ) {
01260          LM_ERR("unable to find declaration "
01261             "of subaction <%s>\n",val.s);
01262          goto error;
01263       }
01264       append_short_attr(p,(unsigned short)(node_ptr-sub_ptr),buf_end,error);
01265    }
01266 
01267    return p-p_orig;
01268 error:
01269    return -1;
01270 }
01271 
01272 
01273 
01274 /* Returns :  -1 - error
01275  *            >0 - subtree size of the given node
01276  */
01277 int encode_node( xmlNodePtr node, char *p, char *p_end)
01278 {
01279    xmlNodePtr kid;
01280    unsigned short sub_tree_size;
01281    int attr_size;
01282    int kid_size;
01283    int foo;
01284 
01285    /* counting the kids */
01286    for(kid=node->children,foo=0;kid;kid=kid->next)
01287       if (kid->type==XML_ELEMENT_NODE) foo++;
01288    check_overflow(p,GET_NODE_SIZE(foo),p_end,error);
01289    NR_OF_KIDS(p) = foo;
01290 
01291    /* size of the encoded attributes */
01292    attr_size = 0;
01293 
01294    /* init the number of attributes */
01295    NR_OF_ATTR(p) = 0;
01296 
01297    /* encode node name */
01298    switch (node->name[0]) {
01299       case 'a':case 'A':
01300          switch (node->name[7]) {
01301             case 0:
01302                NODE_TYPE(p) = ADDRESS_NODE;
01303                attr_size = encode_address_attr( node, p, p_end);
01304                break;
01305             case '-':
01306                NODE_TYPE(p) = ADDRESS_SWITCH_NODE;
01307                attr_size = encode_address_switch_attr( node, p, p_end);
01308                break;
01309             default:
01310                NODE_TYPE(p) = ANCILLARY_NODE;
01311                break;
01312          }
01313          break;
01314       case 'B':case 'b':
01315          NODE_TYPE(p) = BUSY_NODE;
01316          break;
01317       case 'c':case 'C':
01318          NODE_TYPE(p) = CPL_NODE;
01319          break;
01320       case 'd':case 'D':
01321          NODE_TYPE(p) = DEFAULT_NODE;
01322          break;
01323       case 'f':case 'F':
01324          NODE_TYPE(p) = FAILURE_NODE;
01325          break;
01326       case 'i':case 'I':
01327          NODE_TYPE(p) = INCOMING_NODE;
01328          break;
01329       case 'l':case 'L':
01330          switch (node->name[2]) {
01331             case 'g':case 'G':
01332                NODE_TYPE(p) = LOG_NODE;
01333                attr_size = encode_log_attr( node, p, p_end);
01334                break;
01335             case 'o':case 'O':
01336                NODE_TYPE(p) = LOOKUP_NODE;
01337                attr_size = encode_lookup_attr( node, p, p_end);
01338                break;
01339             case 'c':case 'C':
01340                NODE_TYPE(p) = LOCATION_NODE;
01341                attr_size = encode_location_attr( node, p, p_end);
01342                break;
01343             default:
01344                if (node->name[8]) {
01345                   NODE_TYPE(p) = LANGUAGE_SWITCH_NODE;
01346                } else {
01347                   NODE_TYPE(p) = LANGUAGE_NODE;
01348                   attr_size = encode_lang_attr( node, p, p_end);
01349                }
01350                break;
01351          }
01352          break;
01353       case 'm':case 'M':
01354          NODE_TYPE(p) =  MAIL_NODE;
01355          attr_size = encode_mail_attr( node, p, p_end);
01356          break;
01357       case 'n':case 'N':
01358          switch (node->name[3]) {
01359             case 'F':case 'f':
01360                NODE_TYPE(p) = NOTFOUND_NODE;
01361                break;
01362             case 'N':case 'n':
01363                NODE_TYPE(p) = NOANSWER_NODE;
01364                break;
01365             default:
01366                NODE_TYPE(p) = NOT_PRESENT_NODE;
01367                break;
01368          }
01369          break;
01370       case 'o':case 'O':
01371          if (node->name[1]=='t' || node->name[1]=='T') {
01372             NODE_TYPE(p) = OTHERWISE_NODE;
01373          } else {
01374             NODE_TYPE(p) = OUTGOING_NODE;
01375          }
01376          break;
01377       case 'p':case 'P':
01378          if (node->name[2]=='o' || node->name[2]=='O') {
01379             NODE_TYPE(p) = PROXY_NODE;
01380             attr_size = encode_proxy_attr( node, p, p_end);
01381          } else if (node->name[8]) {
01382             NODE_TYPE(p) = PRIORITY_SWITCH_NODE;
01383          } else {
01384             NODE_TYPE(p) = PRIORITY_NODE;
01385             attr_size = encode_priority_attr( node, p, p_end);
01386          }
01387          break;
01388       case 'r':case 'R':
01389          switch (node->name[2]) {
01390             case 'j':case 'J':
01391                NODE_TYPE(p) = REJECT_NODE;
01392                attr_size = encode_reject_attr( node, p, p_end);
01393                break;
01394             case 'm':case 'M':
01395                NODE_TYPE(p) = REMOVE_LOCATION_NODE;
01396                attr_size = encode_rmvloc_attr( node, p, p_end);
01397                break;
01398             default:
01399                if (node->name[8]) {
01400                   NODE_TYPE(p) = REDIRECTION_NODE;
01401                } else {
01402                   NODE_TYPE(p) = REDIRECT_NODE;
01403                   attr_size = encode_redirect_attr( node, p, p_end);
01404                }
01405                break;
01406          }
01407          break;
01408       case 's':case 'S':
01409          switch (node->name[3]) {
01410             case 0:
01411                NODE_TYPE(p) = SUB_NODE;
01412                attr_size = encode_sub_attr( node, p, p_end);
01413                break;
01414             case 'c':case 'C':
01415                NODE_TYPE(p) = SUCCESS_NODE;
01416                break;
01417             case 'a':case 'A':
01418                NODE_TYPE(p) = SUBACTION_NODE;
01419                attr_size = encode_subaction_attr( node, p, p_end);
01420                break;
01421             default:
01422                if (node->name[6]) {
01423                   NODE_TYPE(p) = STRING_SWITCH_NODE;
01424                   attr_size = encode_string_switch_attr( node, p, p_end);
01425                } else {
01426                   NODE_TYPE(p) = STRING_NODE;
01427                   attr_size = encode_string_attr( node, p, p_end);
01428                }
01429                break;
01430          }
01431          break;
01432       case 't':case 'T':
01433          if (node->name[4]) {
01434             NODE_TYPE(p) = TIME_SWITCH_NODE;
01435             attr_size = encode_time_switch_attr( node, p, p_end);
01436          } else {
01437             NODE_TYPE(p) = TIME_NODE;
01438             attr_size = encode_time_attr( node, p, p_end);
01439          }
01440          break;
01441       default:
01442          LM_ERR("unknown node <%s>\n",node->name);
01443          goto error;
01444    }
01445 
01446    /* compute the total length of the node (including attributes) */
01447    if (attr_size<0)
01448       goto error;
01449    sub_tree_size =  SIMPLE_NODE_SIZE(p) + (unsigned short)attr_size;
01450 
01451    /* encrypt all the kids */
01452    for(kid = node->children,foo=0;kid;kid=kid->next) {
01453       if (kid->type!=XML_ELEMENT_NODE) continue;
01454       SET_KID_OFFSET( p, foo, sub_tree_size);
01455       kid_size = encode_node( kid, p+sub_tree_size, p_end);
01456       if (kid_size<=0)
01457          goto error;
01458       sub_tree_size += (unsigned short)kid_size;
01459       foo++;
01460    }
01461 
01462    return sub_tree_size;
01463 error:
01464    return -1;
01465 }
01466 
01467 
01468 
01469 #define BAD_XML       "CPL script is not a valid XML document"
01470 #define BAD_XML_LEN   (sizeof(BAD_XML)-1)
01471 #define BAD_CPL       "CPL script doesn't respect CPL grammar"
01472 #define BAD_CPL_LEN   (sizeof(BAD_CPL)-1)
01473 #define NULL_CPL      "Empty CPL script"
01474 #define NULL_CPL_LEN  (sizeof(NULL_CPL)-1)
01475 #define ENC_ERR       "Encoding of the CPL script failed"
01476 #define ENC_ERR_LEN   (sizeof(ENC_ERR)-1)
01477 
01478 int encodeCPL( str *xml, str *bin, str *log)
01479 {
01480    static char buf[ENCONDING_BUFFER_SIZE];
01481    xmlDocPtr  doc;
01482    xmlNodePtr cur;
01483 
01484    doc  = 0;
01485    list = 0;
01486 
01487    /* reset all the logs (if any) to catch some possible err/warn/notice
01488     * from the parser/validater/encoder */
01489    reset_logs();
01490 
01491    /* parse the xml */
01492    doc = xmlParseDoc( (unsigned char*)xml->s );
01493    if (!doc) {
01494       append_log( 1, ERR BAD_XML LF, ERR_LEN+BAD_XML_LEN+LF_LEN);
01495       LM_ERR( BAD_XML "\n");
01496       goto error;
01497    }
01498 
01499    /* check the xml against dtd */
01500    if (xmlValidateDtd(&cvp, doc, dtd)!=1) {
01501       append_log( 1, ERR BAD_CPL LF, ERR_LEN+BAD_CPL_LEN+LF_LEN);
01502       LM_ERR( BAD_CPL "\n");
01503       goto error;
01504    }
01505 
01506    cur = xmlDocGetRootElement(doc);
01507    if (!cur) {
01508       append_log( 1, ERR NULL_CPL LF, ERR_LEN+NULL_CPL_LEN+LF_LEN);
01509       LM_ERR( NULL_CPL "\n");
01510       goto error;
01511    }
01512 
01513    bin->len = encode_node( cur, buf, buf+ENCONDING_BUFFER_SIZE);
01514    if (bin->len<0) {
01515       append_log( 1, ERR ENC_ERR LF, ERR_LEN+ENC_ERR_LEN+LF_LEN);
01516       LM_ERR( ENC_ERR "\n");
01517       goto error;
01518    }
01519 
01520    xmlFreeDoc(doc);
01521    if (list) delete_list(list);
01522    /* compile the log buffer */
01523    compile_logs( log );
01524    bin->s = buf;
01525    return 1;
01526 error:
01527    if (doc) xmlFreeDoc(doc);
01528    if (list) delete_list(list);
01529    /* compile the log buffer */
01530    compile_logs( log );
01531    return 0;
01532 }
01533 
01534 
01535 
01536 /* loads and parse the dtd file; a validating context is created */
01537 int init_CPL_parser( char* DTD_filename )
01538 {
01539    dtd = xmlParseDTD( NULL, (unsigned char*)DTD_filename);
01540    if (!dtd) {
01541       LM_ERR("DTD not parsed successfully\n");
01542       return -1;
01543    }
01544    cvp.userData = (void *) stderr;
01545    cvp.error    = (xmlValidityErrorFunc) /*err_print*/ fprintf;
01546    cvp.warning  = (xmlValidityWarningFunc) /*err_print*/ fprintf;
01547 
01548    return 1;
01549 }
01550 

Generated on Mon May 21 18:00:25 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6