1 /* $OSSEC, os_xml.c, v0.3, 2005/02/11, Daniel B. Cid$ */
3 /* Copyright (C) 2009 Trend Micro Inc.
6 * This program is a free software; you can redistribute it
7 * and/or modify it under the terms of the GNU General Public
8 * License (version 2) as published by the FSF - Free Software
22 #include "os_xml_internal.h"
25 /* Internal functions */
26 static int _oscomment(FILE *fp) __attribute__((nonnull));
27 static int _writecontent(const char *str, size_t size, unsigned int parent, OS_XML *_lxml) __attribute__((nonnull));
28 static int _writememory(const char *str, XML_TYPE type, size_t size,
29 unsigned int parent, OS_XML *_lxml) __attribute__((nonnull));
30 static int _xml_fgetc(FILE *fp) __attribute__((nonnull));
31 static int _ReadElem(FILE *fp, unsigned int parent, OS_XML *_lxml) __attribute__((nonnull));
32 static int _getattributes(FILE *fp, unsigned int parent,OS_XML *_lxml) __attribute__((nonnull));
33 static void xml_error(OS_XML *_lxml, const char *msg,...) __attribute__((format(printf, 2, 3), nonnull));
36 static unsigned int _line;
39 static int _xml_fgetc(FILE *fp)
44 if(c == '\n') /* add new line */
50 static void xml_error(OS_XML *_lxml, const char *msg,...)
63 fprintf(stderr,"%d/%d/%d %d:%d:%d (LINE: %u)",p->tm_year+1900,p->tm_mon,
64 p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec,_line);
65 vfprintf(stderr, msg, args);
66 fprintf(stderr, "\n\n");
69 memset(_lxml->err,'\0', XML_ERR_LENGTH);
70 vsnprintf(_lxml->err,XML_ERR_LENGTH-1,msg,args);
72 _lxml->err_line = _line;
78 * Clear the memory used by the XML
80 void OS_ClearXML(OS_XML *_lxml)
83 for(i=0;i<_lxml->cur;i++)
110 memset(_lxml->err,'\0', XML_ERR_LENGTH);
115 * Read a XML file and generate the necessary structs.
117 int OS_ReadXML(const char *file, OS_XML *_lxml)
123 /* init xml strcuture */
134 memset(_lxml->err,'\0',XML_ERR_LENGTH);
136 fp = fopen(file,"r");
139 xml_error(_lxml, "XMLERR: File '%s' not found.",file);
143 /* Zeroing the line */
146 if((r = _ReadElem(fp,0,_lxml)) < 0) /* First position */
155 for(i=0;i<_lxml->cur;i++)
157 if(_lxml->ck[i] == 0)
159 xml_error(_lxml,"XMLERR: Element '%s' not closed.", _lxml->el[i]);
170 static int _oscomment(FILE *fp)
173 if((c = fgetc(fp)) == _R_COM)
175 while((c=_xml_fgetc(fp)) != EOF)
179 if((c=fgetc(fp)) == _R_CONFE)
183 else if(c == '-') /* W3C way of finish comments */
185 if((c = _xml_fgetc(fp)) == '-')
187 if((c = fgetc(fp)) == _R_CONFE)
204 static int _ReadElem(FILE *fp, unsigned int parent, OS_XML *_lxml)
207 unsigned int count = 0;
208 unsigned int _currentlycont = 0;
209 short int location = -1;
212 char elem[XML_MAXSIZE +1];
213 char cont[XML_MAXSIZE +1];
214 char closedelem[XML_MAXSIZE +1];
218 memset(elem,'\0',XML_MAXSIZE +1);
219 memset(cont,'\0',XML_MAXSIZE +1);
220 memset(closedelem,'\0',XML_MAXSIZE +1);
222 while((c=_xml_fgetc(fp)) != EOF)
226 else if(prevv == '\\')
234 if(count >= XML_MAXSIZE)
236 xml_error(_lxml,"XMLERR: String overflow.");
241 /* Checking for comments */
245 if((r = _oscomment(fp)) < 0)
247 xml_error(_lxml,"XMLERR: Comment not closed.");
255 if((location == -1) && (prevv == 0))
259 if((c=fgetc(fp)) == '/')
261 xml_error(_lxml,"XMLERR: Element not opened.");
272 else if((location == 0) && ((c == _R_CONFE) || isspace(c)))
278 /* Removing the / at the end of the element name */
279 if(count > 0 && elem[count -1] == '/')
282 elem[count -1] = '\0';
285 if(_writememory(elem, XML_ELEM, count+1, parent, _lxml) < 0)
289 _currentlycont=_lxml->cur-1;
292 if((_ga = _getattributes(fp,parent,_lxml)) < 0)
296 /* If the element is closed already (finished in />) */
297 if((_ge == '/') || (_ga == '/'))
299 if(_writecontent("\0", 2, _currentlycont,_lxml) < 0)
303 _lxml->ck[_currentlycont] = 1;
308 memset(elem,'\0',XML_MAXSIZE);
309 memset(closedelem,'\0',XML_MAXSIZE);
310 memset(cont,'\0',XML_MAXSIZE);
322 else if((location == 2) &&(c == _R_CONFE))
324 closedelem[count]='\0';
325 if(strcmp(closedelem,elem) != 0)
327 xml_error(_lxml,"XMLERR: Element '%s' not closed.",elem);
330 if(_writecontent(cont,strlen(cont)+1,_currentlycont,_lxml) < 0)
334 _lxml->ck[_currentlycont]=1;
335 memset(elem,'\0',XML_MAXSIZE);
336 memset(closedelem,'\0',XML_MAXSIZE);
337 memset(cont,'\0',XML_MAXSIZE);
344 else if((location == 1) && (c == _R_CONFS) && (prevv == 0))
346 if((c=fgetc(fp)) == '/')
357 if(_ReadElem(fp,parent+1,_lxml)< 0)
367 elem[count++] = (char) c;
368 else if(location == 1)
369 cont[count++] = (char) c;
370 else if(location == 2)
371 closedelem[count++] = (char) c;
373 if((_R_CONFS == c) && (prevv != 0))
382 xml_error(_lxml,"XMLERR: End of file and some elements were not closed.");
386 static int _writememory(const char *str, XML_TYPE type, size_t size,
387 unsigned int parent, OS_XML *_lxml)
394 /* Allocating for the element */
395 tmp = (char **)realloc(_lxml->el,(_lxml->cur+1)*sizeof(char *));
401 _lxml->el[_lxml->cur]=(char *)calloc(size,sizeof(char));
402 if(_lxml->el[_lxml->cur] == NULL)
406 strncpy(_lxml->el[_lxml->cur],str,size-1);
408 /* Allocating for the content */
409 tmp = (char **)realloc(_lxml->ct,(_lxml->cur+1)*sizeof(char *));
415 _lxml->ct[_lxml->cur] = NULL;
417 /* Allocating for the type */
418 tmp4 = (XML_TYPE *) realloc(_lxml->tp,(_lxml->cur+1)*sizeof(XML_TYPE));
424 _lxml->tp[_lxml->cur] = type;
426 /* Allocating for the relation */
427 tmp3 = (unsigned int *) realloc(_lxml->rl,(_lxml->cur+1)*sizeof(unsigned int));
433 _lxml->rl[_lxml->cur] = parent;
435 /* Allocating for the "check" */
436 tmp2 = (int *) realloc(_lxml->ck,(_lxml->cur+1)*sizeof(int));
442 _lxml->ck[_lxml->cur] = 0;
444 /* Allocating for the line */
445 tmp3 = (unsigned int *) realloc(_lxml->ln,(_lxml->cur+1)*sizeof(unsigned int));
451 _lxml->ln[_lxml->cur] = _line;
453 /* Attributes does not need to be closed */
455 _lxml->ck[_lxml->cur] = 1;
457 /* Checking if it is a variable */
458 if(strcasecmp(XML_VAR,str) == 0)
460 _lxml->tp[_lxml->cur] = XML_VARIABLE_BEGIN;
467 snprintf(_lxml->err, XML_ERR_LENGTH, "XMLERR: Memory error.");
471 static int _writecontent(const char *str, size_t size, unsigned int parent, OS_XML *_lxml)
473 _lxml->ct[parent]=(char *)calloc(size,sizeof(char));
474 if( _lxml->ct[parent] == NULL)
476 snprintf(_lxml->err, XML_ERR_LENGTH, "XMLERR: Memory error.");
479 strncpy(_lxml->ct[parent],str,size-1);
485 /* getattributes (Internal function): v0.1: 2005/03/03
486 * Read the attributes of an element
488 static int _getattributes(FILE *fp, unsigned int parent,OS_XML *_lxml)
491 unsigned int count = 0;
495 char attr[XML_MAXSIZE+1];
496 char value[XML_MAXSIZE+1];
498 memset(attr,'\0',XML_MAXSIZE+1);
499 memset(value,'\0',XML_MAXSIZE+1);
501 while((c=_xml_fgetc(fp)) != EOF)
503 if(count >= XML_MAXSIZE)
505 attr[count-1] = '\0';
507 "XMLERR: Overflow attempt at attribute '%.20s'.",attr);
511 else if((c == _R_CONFE) || ((location == 0) && (c == '/')))
515 xml_error(_lxml, "XMLERR: Attribute '%s' not closed.",
519 else if((location == 0)&&(count > 0))
521 xml_error(_lxml, "XMLERR: Attribute '%s' has no value.",
530 else if((location == 0)&&(c == '='))
534 /* check for already existent attribute with same name */
535 unsigned int i = _lxml->cur - 1;
536 /* search attributes backwards in same parent */
537 while(_lxml->rl[i] == parent && _lxml->tp[i] == XML_ATTR)
539 if(strcmp(_lxml->el[i], attr) == 0)
541 xml_error(_lxml, "XMLERR: Attribute '%s' already defined.", attr);
545 /* continue with previous element */
554 if((c != '"')&&(c != '\''))
556 unsigned short int _err=1;
559 while((c=_xml_fgetc(fp))!= EOF)
563 else if((c == '"')||(c == '\''))
574 "XMLERR: Attribute '%s' not followed by a \" or \'."
583 else if((location == 0)&&(isspace(c)))
591 xml_error(_lxml, "XMLERR: Attribute '%s' has no value.", attr);
595 else if((location == 1)&&(c == c_to_match))
604 if(_writememory(attr, XML_ATTR, strlen(attr)+1,
609 if(_writecontent(value,count+1,_lxml->cur-1,_lxml) < 0)
615 return(_getattributes(fp,parent,_lxml));
616 else if(c == _R_CONFE)
622 "XMLERR: Bad attribute closing for '%s'='%s'.",
626 else if(location == 0)
627 attr[count++] = (char) c;
628 else if(location == 1)
629 value[count++] = (char) c;
633 xml_error(_lxml, "XMLERR: End of file while reading an attribute.");