mi_parser.c

Go to the documentation of this file.
00001 /*
00002  * $Id: mi_parser.c 5514 2009-01-26 12:33:24Z henningw $
00003  *
00004  * Copyright (C) 2006 Voice Sistem SRL
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  * History:
00024  * ---------
00025  *  2006-09-25  first version (bogdan)
00026  */
00027 
00028 /*!
00029  * \file
00030  * \brief MI Fifo :: Parser
00031  * \ingroup mi
00032  */
00033 
00034 
00035 #include <stdio.h>
00036 #include <string.h>
00037 #include <ctype.h>
00038 
00039 #include "../../str.h"
00040 #include "../../dprint.h"
00041 #include "../../mi/mi.h"
00042 #include "../../mem/mem.h"
00043 #include "fifo_fnc.h"
00044 #include "mi_fifo.h"
00045 #include "mi_parser.h"
00046 
00047 static char *mi_parse_buffer = 0;
00048 static unsigned int mi_parse_buffer_len = 0;
00049 
00050 
00051 int mi_parser_init( unsigned int size )
00052 {
00053    mi_parse_buffer_len = size;
00054    mi_parse_buffer = pkg_malloc(size);
00055 
00056    if(!mi_parse_buffer){
00057       LM_ERR("pkg_malloc cannot allocate any more memory!\n");
00058       return -1;
00059    }
00060 
00061    return 0;
00062 }
00063 
00064 
00065 
00066 /* returns -1 = error
00067  *          0 = ok
00068  *          1 = end of stream
00069  */
00070 static inline int mi_parse_node( FILE *stream, str *buf, str *name, str *value)
00071 {
00072    char *p, *pmax;
00073    char *start;
00074    char *mark_nsp;
00075    int line_len;
00076 
00077    /* read one line */
00078    do {
00079       if (mi_read_line( buf->s, buf->len, stream, &line_len)<0) {
00080          LM_ERR("failed to read from fifo\n");
00081          return -1;
00082       }
00083       if (line_len == 1){
00084          LM_DBG("end of fifo input tree\n");
00085          return 1;
00086       }
00087 
00088       start = buf->s;
00089       pmax = buf->s + line_len - 1;
00090 
00091       /* remove leading spaces */
00092       for( ; start<pmax && isspace((int)*start) ; start++ );
00093    } while ( start==pmax );
00094 
00095    /* init */
00096    name->s = value->s = 0;
00097    name->len = value->len = 0;
00098 
00099    mark_nsp = 0;
00100 
00101    /* start parsing */
00102    if (*start!='"') {
00103       /* look for the atribute name */
00104       p = mark_nsp = start;
00105       while ( p!=pmax && ( (p[0]!=MI_ATTR_VAL_SEP1) || (p+1==pmax)
00106       || p[1]!=MI_ATTR_VAL_SEP2) ) {
00107          if (!isspace((int)*p)) {
00108             if (*p=='"')
00109                goto parse_err;
00110             mark_nsp = p;
00111          }
00112          p++;
00113       }
00114 
00115       if (p!=pmax) {
00116          /* we have found the separator */
00117          if (p==start) {
00118             /* empty attr name */
00119          } else {
00120             name->s = start;
00121             name->len = mark_nsp - start + 1;
00122          }
00123 
00124          p += 2; /* for separator */
00125 
00126          LM_DBG("attr name <%.*s> found\n",
00127             name->len, name->s);
00128 
00129          /* consume the trailing spaces */
00130          for( ; p!=pmax && isspace((int)*p) ; p++);
00131 
00132          if (p==pmax) {
00133             /* empty value.....we are done */
00134             goto done;
00135          }
00136 
00137          /* value (only if not quoted ) */
00138          if (*p!='"') {
00139             for( start=p ; p!=pmax ; p++ ) {
00140                if (!isspace((int)*p)) {
00141                   if (*p=='"')
00142                      goto parse_err;
00143                   mark_nsp = p;
00144                }
00145             }
00146             value->s = start;
00147             value->len = mark_nsp + 1  - start;
00148             goto done;
00149          }
00150          /* quoted value....continue */
00151       } else {
00152          /* we have an empty name ... and we read a non-quoted value */
00153          value->s = start;
00154          value->len = mark_nsp + 1 - start;
00155          goto done;
00156       }
00157    } else {
00158       p = start;
00159    }
00160 
00161    start = p+1;
00162    value->s = start;
00163 
00164    do {
00165       p = start;
00166       /* parse the buffer and look for " */
00167       while (p<pmax) {
00168          if (*p=='"') {
00169             if (start+1!=p && *(p-1)=='\\') {
00170                /* skip current char */
00171                memmove( p-1, p, pmax-p);
00172                pmax--;
00173             } else {
00174                /* end of value */
00175                value->len = p - value->s;
00176                /* is the line ending propely (only spaces) ? */
00177                for( p++ ; p!=pmax && isspace((int)*p) ; p++);
00178                if (p!=pmax)
00179                   goto parse_err;
00180                /* found! */
00181                goto done;
00182             }
00183          } else {
00184             p++;
00185          }
00186       }
00187 
00188       /* adjust input buffer */
00189       p++;
00190       buf->len -= p - buf->s;
00191       buf->s = p;
00192 
00193       /*read one more line */
00194       if (mi_read_line( buf->s, buf->len, stream, &line_len)<0) {
00195          LM_ERR("failed to re-read from fifo\n");
00196          return -1;
00197       }
00198       if (line_len == 1) {
00199          LM_DBG("end of fifo input tree\n");
00200          return -2;
00201       }
00202 
00203       start = buf->s;
00204       pmax = buf->s + line_len - 1;
00205    } while(1);
00206 
00207 done:
00208    buf->len -= p - buf->s;
00209    buf->s = p;
00210    return 0;
00211 parse_err:
00212    LM_ERR("parse error around %c\n",*p);
00213    return -1;
00214 }
00215 
00216 
00217 
00218 struct mi_root * mi_parse_tree(FILE *stream) {
00219    struct mi_root *root;
00220    struct mi_node *node;
00221    str name;
00222    str value;
00223    str buf;
00224    int ret;
00225 
00226    buf.s = mi_parse_buffer;
00227    buf.len= mi_parse_buffer_len;
00228 
00229    root = init_mi_tree(0,0,0);
00230    if (!root) {
00231       LM_ERR("the MI tree cannot be initialized!\n");
00232       goto error;
00233    }
00234    node = &root->node;
00235 
00236    name.s = value.s = 0;
00237    name.len = value.len = 0;
00238 
00239    /* every tree for a command ends with a \n that is alone on its line */
00240    while ( (ret=mi_parse_node(stream, &buf, &name, &value))>=0 ) {
00241       if (ret==1)
00242          return root;
00243 
00244       LM_DBG("adding node <%.*s> ; val <%.*s>\n",
00245          name.len,name.s, value.len,value.s);
00246 
00247       if(!add_mi_node_child(node,0,name.s,name.len,value.s,value.len)){
00248          LM_ERR("cannot add the child node to the MI tree\n");
00249          goto error;
00250       }
00251    }
00252 
00253    LM_ERR("Parse error!\n");
00254    if (ret==-1) {
00255       /* consume the rest of the fifo request */
00256       do {
00257          mi_read_line(mi_parse_buffer,mi_parse_buffer_len,stream,&ret);
00258       }while(ret>1);
00259    }
00260 
00261 error:
00262    if (root)
00263       free_mi_tree(root);
00264    return 0;
00265 }
00266 
00267 

Generated on Wed May 23 20:00:27 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6