novi upstream verzije 2.8.3
[ossec-hids.git] / src / os_xml / os_xml.c
index 9a3f959..d736f20 100755 (executable)
 /* os_xml Library.
  */
 
-
-
-#include "shared.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
 
 #include "os_xml.h"
+#include "os_xml_internal.h"
 
-#define _R_CONFS       '<'
-#define _R_CONFE       '>'
-#define _R_EQUAL       '='
-#define _R_COM         '!'
-#define _R_VAR      '$'
-
-#define OPEN            51
-#define CLOSE           52
-
-#define LEOF           -2
 
 /* Internal functions */
-int _oscomment(FILE *fp);
-int _writecontent(char *str, unsigned int size, int parent, OS_XML *_lxml);
-int _writememory(char *str, short int type, unsigned int size,
-                                        int parent, OS_XML *_lxml);
-int _checkmemory(char *str,OS_XML *_lxml);
-int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml);
-int _getattributes(FILE *fp,int parent,OS_XML *_lxml);
-
-void xml_error(OS_XML *_lxml, const char *msg,...) __attribute__((format(printf, 2, 3)));
+static int _oscomment(FILE *fp) __attribute__((nonnull));
+static int _writecontent(const char *str, size_t size, unsigned int parent, OS_XML *_lxml) __attribute__((nonnull));
+static int _writememory(const char *str, XML_TYPE type, size_t size,
+                                        unsigned int parent, OS_XML *_lxml) __attribute__((nonnull));
+static int _xml_fgetc(FILE *fp) __attribute__((nonnull));
+static int _ReadElem(FILE *fp, unsigned int parent, OS_XML *_lxml) __attribute__((nonnull));
+static int _getattributes(FILE *fp, unsigned int parent,OS_XML *_lxml) __attribute__((nonnull));
+static void xml_error(OS_XML *_lxml, const char *msg,...) __attribute__((format(printf, 2, 3), nonnull));
 
 /* Currently line */
-int _line;
+static unsigned int _line;
 
 /* Local fgetc */
-int _xml_fgetc(FILE *fp)
+static int _xml_fgetc(FILE *fp)
 {
     int c;
     c = fgetc(fp);
@@ -55,9 +47,7 @@ int _xml_fgetc(FILE *fp)
     return(c);
 }
 
-#define FGETC(fp) _xml_fgetc(fp)
-
-void xml_error(OS_XML *_lxml, const char *msg,...)
+static void xml_error(OS_XML *_lxml, const char *msg,...)
 {
 #ifdef DEBUG
     time_t tm;
@@ -67,17 +57,17 @@ void xml_error(OS_XML *_lxml, const char *msg,...)
     va_list args;
     va_start(args,msg);
 
-#ifdef DEBUG   
+#ifdef DEBUG
     tm = time(NULL);
     p = localtime(&tm);
-    fprintf(stderr,"%d/%d/%d %d:%d:%d (LINE: %d)",p->tm_year+1900,p->tm_mon,
+    fprintf(stderr,"%d/%d/%d %d:%d:%d (LINE: %u)",p->tm_year+1900,p->tm_mon,
             p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec,_line);
     vfprintf(stderr, msg, args);
     fprintf(stderr, "\n\n");
 #endif
 
-    memset(_lxml->err,'\0', 128);
-    vsnprintf(_lxml->err,127,msg,args);
+    memset(_lxml->err,'\0', XML_ERR_LENGTH);
+    vsnprintf(_lxml->err,XML_ERR_LENGTH-1,msg,args);
     va_end(args);
     _lxml->err_line = _line;
 }
@@ -89,37 +79,60 @@ void xml_error(OS_XML *_lxml, const char *msg,...)
  */
 void OS_ClearXML(OS_XML *_lxml)
 {
-    int i;
+    unsigned int i;
     for(i=0;i<_lxml->cur;i++)
     {
-        if(_lxml->el[i])
-            free(_lxml->el[i]);
-        if(_lxml->ct[i])
-            free(_lxml->ct[i]);
+        free(_lxml->el[i]);
+        free(_lxml->ct[i]);
     }
     _lxml->cur = 0;
+    _lxml->fol = 0;
     _lxml->err_line = 0;
+
     free(_lxml->el);
+    _lxml->el = NULL;
+
     free(_lxml->ct);
+    _lxml->ct = NULL;
+
     free(_lxml->rl);
+    _lxml->rl = NULL;
+
     free(_lxml->tp);
+    _lxml->tp = NULL;
+
     free(_lxml->ck);
-    free(_lxml->ln);
-    memset(_lxml->err,'\0', 128);
+    _lxml->ck = NULL;
 
-    return;    
+    free(_lxml->ln);
+    _lxml->ln = NULL;
 
+    memset(_lxml->err,'\0', XML_ERR_LENGTH);
 }
 
 
 /* OS_ReadXML v0.1
  * Read a XML file and generate the necessary structs.
  */
-int OS_ReadXML(char *file, OS_XML *_lxml)
+int OS_ReadXML(const char *file, OS_XML *_lxml)
 {
-    int r,i;
+    int r;
+    unsigned int i;
     FILE *fp;
 
+    /* init xml strcuture */
+    _lxml->cur = 0;
+       _lxml->fol = 0;
+       _lxml->el = NULL;
+       _lxml->ct = NULL;
+       _lxml->tp = NULL;
+       _lxml->rl = NULL;
+       _lxml->ck = NULL;
+       _lxml->ln = NULL;
+
+       _lxml->err_line = 0;
+       memset(_lxml->err,'\0',XML_ERR_LENGTH);
+
     fp = fopen(file,"r");
     if(!fp)
     {
@@ -127,22 +140,10 @@ int OS_ReadXML(char *file, OS_XML *_lxml)
         return(-2);
     }
 
-    _lxml->cur = 0;
-    _lxml->fol = 0;
-    _lxml->el = NULL;
-    _lxml->ct = NULL;
-    _lxml->tp = NULL;
-    _lxml->rl = NULL;
-    _lxml->ck = NULL;
-    _lxml->ln = NULL;
-
-    _lxml->err_line = 0;
-    memset(_lxml->err,'\0',128);
-
     /* Zeroing the line */
     _line = 1;
 
-    if((r = _ReadElem(fp,0,0,_lxml)) < 0) /* First position */
+    if((r = _ReadElem(fp,0,_lxml)) < 0) /* First position */
     {
         if(r != LEOF)
         {
@@ -155,7 +156,7 @@ int OS_ReadXML(char *file, OS_XML *_lxml)
     {
         if(_lxml->ck[i] == 0)
         {
-            xml_error(_lxml,"XMLERR: Element '%s' not closed\n", _lxml->el[i]);
+            xml_error(_lxml,"XMLERR: Element '%s' not closed.", _lxml->el[i]);
             fclose(fp);
             return(-1);
         }
@@ -166,12 +167,12 @@ int OS_ReadXML(char *file, OS_XML *_lxml)
 }
 
 
-int _oscomment(FILE *fp)
+static int _oscomment(FILE *fp)
 {
     int c;
     if((c = fgetc(fp)) == _R_COM)
     {
-        while((c=FGETC(fp)) != EOF)
+        while((c=_xml_fgetc(fp)) != EOF)
         {
             if(c == _R_COM)
             {
@@ -181,7 +182,7 @@ int _oscomment(FILE *fp)
             }
             else if(c == '-')       /* W3C way of finish comments */
             {
-                if((c = FGETC(fp)) == '-')
+                if((c = _xml_fgetc(fp)) == '-')
                 {
                     if((c = fgetc(fp)) == _R_CONFE)
                         return(1);
@@ -200,14 +201,14 @@ int _oscomment(FILE *fp)
 }
 
 
-int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml)
+static int _ReadElem(FILE *fp, unsigned int parent, OS_XML *_lxml)
 {
     int c;
     unsigned int count = 0;
     unsigned int _currentlycont = 0;
     short int location = -1;
 
-    char prevv = 0;
+    int prevv = 0;
     char elem[XML_MAXSIZE +1];
     char cont[XML_MAXSIZE +1];
     char closedelem[XML_MAXSIZE +1];
@@ -218,7 +219,7 @@ int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml)
     memset(cont,'\0',XML_MAXSIZE +1);
     memset(closedelem,'\0',XML_MAXSIZE +1);
 
-    while((c=FGETC(fp)) != EOF)
+    while((c=_xml_fgetc(fp)) != EOF)
     {
         if(c == '\\')
             prevv = c;
@@ -232,7 +233,7 @@ int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml)
         /* Max size */
         if(count >= XML_MAXSIZE)
         {
-            xml_error(_lxml,"XML ERR: String overflow. Exiting.");
+            xml_error(_lxml,"XMLERR: String overflow.");
             return(-1);
         }
 
@@ -243,7 +244,7 @@ int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml)
             int r = 0;
             if((r = _oscomment(fp)) < 0)
             {
-                xml_error(_lxml,"XML ERR: Comment not closed. Bad XML.");
+                xml_error(_lxml,"XMLERR: Comment not closed.");
                 return(-1);
             }
             else if(r == 1)
@@ -257,8 +258,7 @@ int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml)
             {
                 if((c=fgetc(fp)) == '/')
                 {
-                    xml_error(_lxml,"XML ERR: Bad formed XML. Element "
-                                    "not opened");
+                    xml_error(_lxml,"XMLERR: Element not opened.");
                     return(-1);
                 }
                 else
@@ -269,22 +269,25 @@ int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml)
                 continue;
         }
 
-        else if((location == 0) && ((c == _R_CONFE) || (c == ' ')))
+        else if((location == 0) && ((c == _R_CONFE) || isspace(c)))
         {
             int _ge = 0;
             int _ga = 0;
             elem[count]='\0';
 
             /* Removing the / at the end of the element name */
-            if(elem[count -1] == '/')
+            if(count > 0 && elem[count -1] == '/')
             {
                 _ge = '/';
                 elem[count -1] = '\0';
             }
 
-            _writememory(elem, XML_ELEM, count+1, parent, _lxml);
+            if(_writememory(elem, XML_ELEM, count+1, parent, _lxml) < 0)
+            {
+                return(-1);
+            }
             _currentlycont=_lxml->cur-1;
-            if(c == ' ')
+            if(isspace(c))
             {
                 if((_ga = _getattributes(fp,parent,_lxml)) < 0)
                     return(-1);
@@ -293,7 +296,10 @@ int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml)
             /* If the element is closed already (finished in />) */
             if((_ge == '/') || (_ga == '/'))
             {
-                _writecontent("\0", 2, _currentlycont,_lxml);
+                if(_writecontent("\0", 2, _currentlycont,_lxml) < 0)
+                {
+                    return(-1);
+                }
                 _lxml->ck[_currentlycont] = 1;
                 _currentlycont = 0;
                 count = 0;
@@ -318,16 +324,19 @@ int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml)
             closedelem[count]='\0';
             if(strcmp(closedelem,elem) != 0)
             {
-                xml_error(_lxml,"XML ERR: Element not closed: %s",elem);
+                xml_error(_lxml,"XMLERR: Element '%s' not closed.",elem);
                 return(-1);
             }
-            _writecontent(cont,strlen(cont)+1,_currentlycont,_lxml);
-            _lxml->ck[_currentlycont]=1;       
+            if(_writecontent(cont,strlen(cont)+1,_currentlycont,_lxml) < 0)
+            {
+                return(-1);
+            }
+            _lxml->ck[_currentlycont]=1;
             memset(elem,'\0',XML_MAXSIZE);
             memset(closedelem,'\0',XML_MAXSIZE);
             memset(cont,'\0',XML_MAXSIZE);
             _currentlycont = 0;
-            count = 0; 
+            count = 0;
             location = -1;
             if(parent > 0)
                 return(0);
@@ -339,13 +348,13 @@ int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml)
                 cont[count] = '\0';
                 count = 0;
                 location = 2;
-            }  
+            }
             else
             {
                 ungetc(c,fp);
                 ungetc(_R_CONFS,fp);
 
-                if(_ReadElem(fp,position+1,parent+1,_lxml)< 0)
+                if(_ReadElem(fp,parent+1,_lxml)< 0)
                 {
                     return(-1);
                 }
@@ -355,11 +364,11 @@ int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml)
         else
         {
             if(location == 0)
-                elem[count++] = c;
+                elem[count++] = (char) c;
             else if(location == 1)
-                cont[count++] = c;
+                cont[count++] = (char) c;
             else if(location == 2)
-                closedelem[count++] = c;
+                closedelem[count++] = (char) c;
 
             if((_R_CONFS == c) && (prevv != 0))
             {
@@ -370,35 +379,75 @@ int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml)
     if(location == -1)
         return(LEOF);
 
-    xml_error(_lxml,"XML ERR: End of file and some elements were not closed");
+    xml_error(_lxml,"XMLERR: End of file and some elements were not closed.");
     return(-1);
-}                              
+}
 
-int _writememory(char *str, short int type, unsigned int size,
-                                        int parent, OS_XML *_lxml)
+static int _writememory(const char *str, XML_TYPE type, size_t size,
+                                        unsigned int parent, OS_XML *_lxml)
 {
+    char **tmp;
+    int *tmp2;
+    unsigned int *tmp3;
+    XML_TYPE *tmp4;
+
     /* Allocating for the element */
-    _lxml->el = (char **)realloc(_lxml->el,(_lxml->cur+1)*sizeof(char *));
+    tmp = (char **)realloc(_lxml->el,(_lxml->cur+1)*sizeof(char *));
+    if(tmp == NULL)
+    {
+        goto fail;
+    }
+    _lxml->el = tmp;
     _lxml->el[_lxml->cur]=(char *)calloc(size,sizeof(char));
+    if(_lxml->el[_lxml->cur] == NULL)
+    {
+        goto fail;
+    }
     strncpy(_lxml->el[_lxml->cur],str,size-1);
 
-    /* Allocating for the content */   
-    _lxml->ct = (char **)realloc(_lxml->ct,(_lxml->cur+1)*sizeof(char *));
+    /* Allocating for the content */
+    tmp = (char **)realloc(_lxml->ct,(_lxml->cur+1)*sizeof(char *));
+    if(tmp == NULL)
+    {
+        goto fail;
+    }
+    _lxml->ct = tmp;
+    _lxml->ct[_lxml->cur] = NULL;
 
     /* Allocating for the type */
-    _lxml->tp = realloc(_lxml->tp,(_lxml->cur+1)*sizeof(int));
-    _lxml->tp[_lxml->cur] = type;      
+    tmp4 = (XML_TYPE *) realloc(_lxml->tp,(_lxml->cur+1)*sizeof(XML_TYPE));
+    if(tmp4 == NULL)
+    {
+        goto fail;
+    }
+    _lxml->tp = tmp4;
+    _lxml->tp[_lxml->cur] = type;
 
     /* Allocating for the relation */
-    _lxml->rl = realloc(_lxml->rl,(_lxml->cur+1)*sizeof(int));
+    tmp3 = (unsigned int *) realloc(_lxml->rl,(_lxml->cur+1)*sizeof(unsigned int));
+    if(tmp3 == NULL)
+    {
+        goto fail;
+    }
+    _lxml->rl = tmp3;
     _lxml->rl[_lxml->cur] = parent;
 
     /* Allocating for the "check" */
-    _lxml->ck = realloc(_lxml->ck,(_lxml->cur+1)*sizeof(int));
+    tmp2 = (int *) realloc(_lxml->ck,(_lxml->cur+1)*sizeof(int));
+    if(tmp2 == NULL)
+    {
+        goto fail;
+    }
+    _lxml->ck = tmp2;
     _lxml->ck[_lxml->cur] = 0;
 
     /* Allocating for the line */
-    _lxml->ln = realloc(_lxml->ln,(_lxml->cur+1)*sizeof(int));
+    tmp3 = (unsigned int *) realloc(_lxml->ln,(_lxml->cur+1)*sizeof(unsigned int));
+    if(tmp3 == NULL)
+    {
+        goto fail;
+    }
+    _lxml->ln = tmp3;
     _lxml->ln[_lxml->cur] = _line;
 
     /* Attributes does not need to be closed */
@@ -413,43 +462,33 @@ int _writememory(char *str, short int type, unsigned int size,
 
     _lxml->cur++;
     return(0);
+
+    fail:
+    snprintf(_lxml->err, XML_ERR_LENGTH, "XMLERR: Memory error.");
+    return(-1);
 }
 
-int _writecontent(char *str, unsigned int size, int parent, OS_XML *_lxml)
+static int _writecontent(const char *str, size_t size, unsigned int parent, OS_XML *_lxml)
 {
     _lxml->ct[parent]=(char *)calloc(size,sizeof(char));
+    if( _lxml->ct[parent] == NULL)
+    {
+        snprintf(_lxml->err, XML_ERR_LENGTH, "XMLERR: Memory error.");
+        return(-1);
+    }
     strncpy(_lxml->ct[parent],str,size-1);
 
     return(0);
 }
 
 
-int _checkmemory(char *str,OS_XML *_lxml)
-{
-    int i;
-    for(i=0;i<_lxml->cur;i++)
-    {
-        if(_lxml->ck[i] == 0)
-        {
-            if(strcmp(str,_lxml->el[i]) == 0)
-            {
-                _lxml->ck[i] = 1;
-                return(0);
-            }
-            else
-                continue;
-        }
-    }
-    return(-1);
-}
-
 /* getattributes (Internal function): v0.1: 2005/03/03
  * Read the attributes of an element
  */
-int _getattributes(FILE *fp,int parent,OS_XML *_lxml)
+static int _getattributes(FILE *fp, unsigned int parent,OS_XML *_lxml)
 {
     int location = 0;
-    int count = 0;
+    unsigned int count = 0;
     int c;
     int c_to_match = 0;
 
@@ -459,41 +498,67 @@ int _getattributes(FILE *fp,int parent,OS_XML *_lxml)
     memset(attr,'\0',XML_MAXSIZE+1);
     memset(value,'\0',XML_MAXSIZE+1);
 
-    while((c=FGETC(fp)) != EOF)
+    while((c=_xml_fgetc(fp)) != EOF)
     {
         if(count >= XML_MAXSIZE)
         {
             attr[count-1] = '\0';
             xml_error(_lxml,
-                    "XMLERR: Overflow attempt at attribute '%s'.",attr);
+                    "XMLERR: Overflow attempt at attribute '%.20s'.",attr);
             return(-1);
         }
 
-        else if((c == _R_CONFE) || (c == '/'))
+        else if((c == _R_CONFE) || ((location == 0) && (c == '/')))
         {
-            if((location == 1)||((location == 0)&&(count > 0)))
+            if(location == 1)
             {
                 xml_error(_lxml, "XMLERR: Attribute '%s' not closed.",
                                  attr);
                 return(-1);
             }
+            else if((location == 0)&&(count > 0))
+            {
+                xml_error(_lxml, "XMLERR: Attribute '%s' has no value.",
+                                                 attr);
+                                return(-1);
+            }
             else if(c == '/')
                 return(c);
             else
                 return(0);
-        }      
+        }
         else if((location == 0)&&(c == '='))
         {
             attr[count]='\0';
-            c = FGETC(fp);
+
+            /* check for already existent attribute with same name */
+            unsigned int i = _lxml->cur - 1;
+            /* search attributes backwards in same parent */
+            while(_lxml->rl[i] == parent && _lxml->tp[i] == XML_ATTR)
+            {
+                if(strcmp(_lxml->el[i], attr) == 0)
+                {
+                    xml_error(_lxml, "XMLERR: Attribute '%s' already defined.", attr);
+                    return(-1);
+                }
+
+                /* continue with previous element */
+                if(i==0)
+                {
+                    break;
+                }
+                i--;
+            }
+
+            c = _xml_fgetc(fp);
             if((c != '"')&&(c != '\''))
             {
                 unsigned short int _err=1;
-                if(c == ' ')
+                if(isspace(c))
                 {
-                    while((c=FGETC(fp))!= EOF)
+                    while((c=_xml_fgetc(fp))!= EOF)
                     {
-                        if(c == ' ')
+                        if(isspace(c))
                             continue;
                         else if((c == '"')||(c == '\''))
                         {
@@ -515,37 +580,53 @@ int _getattributes(FILE *fp,int parent,OS_XML *_lxml)
             location = 1;
             count = 0;
         }
-        else if((location == 0)&&(c == ' '))
-            continue;
-
+        else if((location == 0)&&(isspace(c)))
+        {
+            if(count == 0)
+            {
+                continue;
+            }
+            else
+            {
+                xml_error(_lxml, "XMLERR: Attribute '%s' has no value.", attr);
+                return(-1);
+            }
+        }
         else if((location == 1)&&(c == c_to_match))
         {
             value[count]='\0';
 
-            location = 0;
-            c_to_match = 0;
+            /* dead code:
+             * location = 0;
+             * c_to_match = 0;
+             */
 
-            _writememory(attr, XML_ATTR, strlen(attr)+1,
-                    parent, _lxml);    
-            _writecontent(value,count+1,_lxml->cur-1,_lxml);
-            c = FGETC(fp);
-            if(c == ' ')
-                return(_getattributes(fp,parent,_lxml));
-            else if(c == _R_CONFE)
-                return(0);
-            else
+            if(_writememory(attr, XML_ATTR, strlen(attr)+1,
+                    parent, _lxml) < 0)
             {
-                xml_error(_lxml,
-                        "XMLERR: Bad attribute closing for '%s'='%s'.",
-                        attr,value);
                 return(-1);
             }
-            count = 0;
+            if(_writecontent(value,count+1,_lxml->cur-1,_lxml) < 0)
+            {
+                return(-1);
+            }
+            c = _xml_fgetc(fp);
+            if(isspace(c))
+                return(_getattributes(fp,parent,_lxml));
+            else if(c == _R_CONFE)
+                return(0);
+            else if(c == '/')
+               return (c);
+
+            xml_error(_lxml,
+                "XMLERR: Bad attribute closing for '%s'='%s'.",
+                attr,value);
+            return(-1);
         }
         else if(location == 0)
-            attr[count++]=c;
+            attr[count++] = (char) c;
         else if(location == 1)
-            value[count++]=c;
+            value[count++] = (char) c;
 
     }