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 3) as published by the FSF - Free Software
32 /* Internal functions */
33 int _oscomment(FILE *fp);
34 int _writecontent(char *str, unsigned int size, int parent, OS_XML *_lxml);
35 int _writememory(char *str, short int type, unsigned int size,
36 int parent, OS_XML *_lxml);
37 int _checkmemory(char *str,OS_XML *_lxml);
38 int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml);
39 int _getattributes(FILE *fp,int parent,OS_XML *_lxml);
41 void xml_error(OS_XML *_lxml, const char *msg,...) __attribute__((format(printf, 2, 3)));
47 int _xml_fgetc(FILE *fp)
52 if(c == '\n') /* add new line */
58 #define FGETC(fp) _xml_fgetc(fp)
60 void xml_error(OS_XML *_lxml, const char *msg,...)
73 fprintf(stderr,"%d/%d/%d %d:%d:%d (LINE: %d)",p->tm_year+1900,p->tm_mon,
74 p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec,_line);
75 vfprintf(stderr, msg, args);
76 fprintf(stderr, "\n\n");
79 memset(_lxml->err,'\0', 128);
80 vsnprintf(_lxml->err,127,msg,args);
82 _lxml->err_line = _line;
88 * Clear the memory used by the XML
90 void OS_ClearXML(OS_XML *_lxml)
93 for(i=0;i<_lxml->cur;i++)
108 memset(_lxml->err,'\0', 128);
116 * Read a XML file and generate the necessary structs.
118 int OS_ReadXML(char *file, OS_XML *_lxml)
123 fp = fopen(file,"r");
126 xml_error(_lxml, "XMLERR: File '%s' not found.",file);
140 memset(_lxml->err,'\0',128);
142 /* Zeroing the line */
145 if((r = _ReadElem(fp,0,0,_lxml)) < 0) /* First position */
154 for(i=0;i<_lxml->cur;i++)
156 if(_lxml->ck[i] == 0)
158 xml_error(_lxml,"XMLERR: Element '%s' not closed\n", _lxml->el[i]);
169 int _oscomment(FILE *fp)
172 if((c = fgetc(fp)) == _R_COM)
174 while((c=FGETC(fp)) != EOF)
178 if((c=fgetc(fp)) == _R_CONFE)
182 else if(c == '-') /* W3C way of finish comments */
184 if((c = FGETC(fp)) == '-')
186 if((c = fgetc(fp)) == _R_CONFE)
203 int _ReadElem(FILE *fp, int position, int parent, OS_XML *_lxml)
206 unsigned int count = 0;
207 unsigned int _currentlycont = 0;
208 short int location = -1;
211 char elem[XML_MAXSIZE +1];
212 char cont[XML_MAXSIZE +1];
213 char closedelem[XML_MAXSIZE +1];
217 memset(elem,'\0',XML_MAXSIZE +1);
218 memset(cont,'\0',XML_MAXSIZE +1);
219 memset(closedelem,'\0',XML_MAXSIZE +1);
221 while((c=FGETC(fp)) != EOF)
225 else if(prevv == '\\')
233 if(count >= XML_MAXSIZE)
235 xml_error(_lxml,"XML ERR: String overflow. Exiting.");
240 /* Checking for comments */
244 if((r = _oscomment(fp)) < 0)
246 xml_error(_lxml,"XML ERR: Comment not closed. Bad XML.");
254 if((location == -1) && (prevv == 0))
258 if((c=fgetc(fp)) == '/')
260 xml_error(_lxml,"XML ERR: Bad formed XML. Element "
272 else if((location == 0) && ((c == _R_CONFE) || (c == ' ')))
278 /* Removing the / at the end of the element name */
279 if(elem[count -1] == '/')
282 elem[count -1] = '\0';
285 _writememory(elem, XML_ELEM, count+1, parent, _lxml);
286 _currentlycont=_lxml->cur-1;
289 if((_ga = _getattributes(fp,parent,_lxml)) < 0)
293 /* If the element is closed already (finished in />) */
294 if((_ge == '/') || (_ga == '/'))
296 _writecontent("\0", 2, _currentlycont,_lxml);
297 _lxml->ck[_currentlycont] = 1;
302 memset(elem,'\0',XML_MAXSIZE);
303 memset(closedelem,'\0',XML_MAXSIZE);
304 memset(cont,'\0',XML_MAXSIZE);
316 else if((location == 2) &&(c == _R_CONFE))
318 closedelem[count]='\0';
319 if(strcmp(closedelem,elem) != 0)
321 xml_error(_lxml,"XML ERR: Element not closed: %s",elem);
324 _writecontent(cont,strlen(cont)+1,_currentlycont,_lxml);
325 _lxml->ck[_currentlycont]=1;
326 memset(elem,'\0',XML_MAXSIZE);
327 memset(closedelem,'\0',XML_MAXSIZE);
328 memset(cont,'\0',XML_MAXSIZE);
335 else if((location == 1) && (c == _R_CONFS) && (prevv == 0))
337 if((c=fgetc(fp)) == '/')
348 if(_ReadElem(fp,position+1,parent+1,_lxml)< 0)
359 else if(location == 1)
361 else if(location == 2)
362 closedelem[count++] = c;
364 if((_R_CONFS == c) && (prevv != 0))
373 xml_error(_lxml,"XML ERR: End of file and some elements were not closed");
377 int _writememory(char *str, short int type, unsigned int size,
378 int parent, OS_XML *_lxml)
380 /* Allocating for the element */
381 _lxml->el = (char **)realloc(_lxml->el,(_lxml->cur+1)*sizeof(char *));
382 _lxml->el[_lxml->cur]=(char *)calloc(size,sizeof(char));
383 strncpy(_lxml->el[_lxml->cur],str,size-1);
385 /* Allocating for the content */
386 _lxml->ct = (char **)realloc(_lxml->ct,(_lxml->cur+1)*sizeof(char *));
388 /* Allocating for the type */
389 _lxml->tp = realloc(_lxml->tp,(_lxml->cur+1)*sizeof(int));
390 _lxml->tp[_lxml->cur] = type;
392 /* Allocating for the relation */
393 _lxml->rl = realloc(_lxml->rl,(_lxml->cur+1)*sizeof(int));
394 _lxml->rl[_lxml->cur] = parent;
396 /* Allocating for the "check" */
397 _lxml->ck = realloc(_lxml->ck,(_lxml->cur+1)*sizeof(int));
398 _lxml->ck[_lxml->cur] = 0;
400 /* Allocating for the line */
401 _lxml->ln = realloc(_lxml->ln,(_lxml->cur+1)*sizeof(int));
402 _lxml->ln[_lxml->cur] = _line;
404 /* Attributes does not need to be closed */
406 _lxml->ck[_lxml->cur] = 1;
408 /* Checking if it is a variable */
409 if(strcasecmp(XML_VAR,str) == 0)
411 _lxml->tp[_lxml->cur] = XML_VARIABLE_BEGIN;
418 int _writecontent(char *str, unsigned int size, int parent, OS_XML *_lxml)
420 _lxml->ct[parent]=(char *)calloc(size,sizeof(char));
421 strncpy(_lxml->ct[parent],str,size-1);
427 int _checkmemory(char *str,OS_XML *_lxml)
430 for(i=0;i<_lxml->cur;i++)
432 if(_lxml->ck[i] == 0)
434 if(strcmp(str,_lxml->el[i]) == 0)
446 /* getattributes (Internal function): v0.1: 2005/03/03
447 * Read the attributes of an element
449 int _getattributes(FILE *fp,int parent,OS_XML *_lxml)
456 char attr[XML_MAXSIZE+1];
457 char value[XML_MAXSIZE+1];
459 memset(attr,'\0',XML_MAXSIZE+1);
460 memset(value,'\0',XML_MAXSIZE+1);
462 while((c=FGETC(fp)) != EOF)
464 if(count >= XML_MAXSIZE)
466 attr[count-1] = '\0';
468 "XMLERR: Overflow attempt at attribute '%s'.",attr);
472 else if((c == _R_CONFE) || (c == '/'))
474 if((location == 1)||((location == 0)&&(count > 0)))
476 xml_error(_lxml, "XMLERR: Attribute '%s' not closed.",
485 else if((location == 0)&&(c == '='))
489 if((c != '"')&&(c != '\''))
491 unsigned short int _err=1;
494 while((c=FGETC(fp))!= EOF)
498 else if((c == '"')||(c == '\''))
509 "XMLERR: Attribute '%s' not followed by a \" or \'."
518 else if((location == 0)&&(c == ' '))
521 else if((location == 1)&&(c == c_to_match))
528 _writememory(attr, XML_ATTR, strlen(attr)+1,
530 _writecontent(value,count+1,_lxml->cur-1,_lxml);
533 return(_getattributes(fp,parent,_lxml));
534 else if(c == _R_CONFE)
539 "XMLERR: Bad attribute closing for '%s'='%s'.",
545 else if(location == 0)
547 else if(location == 1)
552 xml_error(_lxml, "XMLERR: End of file while reading an attribute.");