efcd131a7079d9b0ad57ab616f6ea7f4735c6ab4
[ossec-hids.git] / os_xml_access.c
1 /*   $OSSEC, os_xml_access.c, v0.3, 2005/02/11, Daniel B. Cid$   */
2
3 /* Copyright (C) 2009 Trend Micro Inc.
4  * All rights reserved.
5  *
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
9  * Foundation
10  */
11
12 /* os_xml C Library.
13  */
14
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdlib.h>
19
20 #include "os_xml.h"
21 #include "os_xml_internal.h"
22
23
24 /* Internal functions */
25 static char **_GetElements(const OS_XML *_lxml, const char **element_name,XML_TYPE type) __attribute__((nonnull(1)));
26 static char **_GetElementContent(OS_XML *_lxml, const char **element_name, const char *attr) __attribute__((nonnull(1,2)));
27
28
29 /* OS_ElementExist: v1.0: 2005/02/26
30  * Check if a element exists
31  * The element_name must be NULL terminated (last char)
32  */
33 unsigned int OS_ElementExist(const OS_XML *_lxml, const char **element_name)
34 {
35     unsigned int i=0,j=0,matched=0,totalmatch=0;
36
37     if(element_name[0] == NULL)
38         return(0);
39
40     for(i=0,j=0;i<_lxml->cur;i++)
41     {
42         if(element_name[j] == NULL)
43             j=0;
44         if((_lxml->tp[i] == XML_ELEM)&&(_lxml->rl[i] == j))
45         {
46             if(strcmp(_lxml->el[i],element_name[j]) == 0)
47             {
48                 j++;
49                 matched=1;
50                 if(element_name[j] == NULL)
51                 {
52                     j=0;
53                     totalmatch++;
54                 }
55                 continue;
56             }
57         }
58         if((matched == 1) &&(j > _lxml->rl[i])&&
59                 (_lxml->tp[i] == XML_ELEM))
60         {
61             j=0;
62             matched=0;
63         }
64     }
65     return(totalmatch);
66 }
67
68
69 /* RootElementExist: v1.0: 2005/02/26
70  * Check if a root element exists
71  */
72 unsigned int OS_RootElementExist(const OS_XML *_lxml, const char *element_name)
73 {
74     const char *(elements[])={element_name,NULL};
75     return(OS_ElementExist(_lxml,elements));
76 }
77
78
79 /* GetAttributes: v.0.1: 2005/03/01
80  * Get the attributes of the element_name
81  */
82 char **OS_GetAttributes(const OS_XML *_lxml, const char **element_name)
83 {
84     return(_GetElements(_lxml,element_name,XML_ATTR));
85 }
86
87
88
89
90 /* GetElements: v0.1: 2005/03/01
91  * Get the elements children of the element_name
92  */
93 char **OS_GetElements(const OS_XML *_lxml, const char **element_name)
94 {
95     return(_GetElements(_lxml, element_name,XML_ELEM));
96 }
97
98
99
100
101 /* _GetElements: v0.1: 2005/03/01
102  * Get the elements or attributes (internal use)
103  */
104 static char **_GetElements(const OS_XML *_lxml, const char **element_name,XML_TYPE type)
105 {
106     unsigned i=0,j=0,k=0,matched=0,ready=0;
107     char **ret=NULL;
108     char **ret_tmp=NULL;
109
110     if((type == XML_ELEM) && (element_name == NULL))
111         ready=1;
112
113     for(i=0,j=0;i<_lxml->cur;i++)
114     {
115         if((ready != 1) &&(element_name[j] == NULL))
116         {
117             if(matched ==1)
118                 ready=1;
119             else
120                 break;
121         }
122
123         if(j > 16)
124             return(ret);
125
126         if((ready == 1)&&(_lxml->tp[i] == type))
127         {
128             if(((type == XML_ATTR)&&(_lxml->rl[i] == j-1)
129                         &&(_lxml->el[i] != NULL))||
130                     ((type == XML_ELEM)&&(_lxml->rl[i] == j)&&
131                      (_lxml->el[i] != NULL)))
132             {
133                 size_t el_size = strlen(_lxml->el[i])+1;
134                 ret_tmp = (char**)realloc(ret,(k+2)*sizeof(char *));
135                 if(ret_tmp == NULL)
136                     goto fail;
137                 ret = ret_tmp;
138                 ret[k+1] = NULL;
139                 ret[k]=(char*)calloc(el_size,sizeof(char));
140                 if(ret[k] == NULL)
141                 {
142                     goto fail;
143                 }
144                 strncpy(ret[k],_lxml->el[i],el_size-1);
145                 k++;
146             }
147         }
148
149         else if((_lxml->tp[i] == XML_ELEM)&&(_lxml->rl[i] == j)&&
150                 (element_name[j] != NULL))
151         {
152             if(strcmp(_lxml->el[i],element_name[j]) == 0)
153             {
154                 j++;
155                 matched=1;
156                 continue;
157             }
158         }
159
160         if(matched == 1)
161         {
162             if(((_lxml->tp[i]==XML_ATTR)&&(j > _lxml->rl[i]+1))||
163                     ((_lxml->tp[i] == XML_ELEM)&&(j > _lxml->rl[i])))
164             {
165                 j=0;
166                 matched=0;
167                 if(element_name == NULL)
168                     ready=1;
169                 else
170                     ready=0;
171             }
172         }
173     }
174
175     return(ret);
176
177     fail:
178     i = 0;
179     if(ret)
180     {
181         while(ret[i])
182                 free(ret[i++]);
183         free(ret);
184     }
185     return (NULL);
186 }
187
188
189
190 /* OS_GetOneContentforElement: v0.1: 2005/03/01
191  * Get one value for a specific element.
192  */
193 char *OS_GetOneContentforElement(OS_XML *_lxml, const char **element_name)
194 {
195     int i = 1;
196     char *uniqret = NULL;
197     char **ret = NULL;
198
199     _lxml->fol = 0;
200     ret = _GetElementContent(_lxml, element_name, NULL);
201     if(ret == NULL)
202     {
203         return(NULL);
204     }
205
206     if(ret[0] != NULL)
207     {
208         uniqret = ret[0];
209     }
210
211     /* Freeing memory */
212     while(ret[i])
213     {
214         free(ret[i]);
215         ret[i] = NULL;
216         i++;
217     }
218     free(ret);
219
220     return(uniqret);
221 }
222
223
224 /* OS_GetElementContent: v0.1: 2005/03/01
225  * Get all values for a specific element
226  */
227 char **OS_GetElementContent(OS_XML *_lxml, const char **element_name)
228 {
229     _lxml->fol=0;
230     return(_GetElementContent(_lxml, element_name, NULL));
231 }
232
233
234 /* OS_GetContents: v0.1: 2005/03/01
235  * Get the contents for a specific element
236  * Use element_name = NULL to start the state
237  */
238 char **OS_GetContents(OS_XML *_lxml, const char **element_name)
239 {
240     if(element_name == NULL)
241     {
242         _lxml->fol = -1;
243         return(NULL);
244     }
245     return(_GetElementContent(_lxml, element_name, NULL));
246 }
247
248
249
250 /* OS_GetAttributeContent: v0.1: 2005/03/01
251  * Get one value for a specific attribute
252  */
253 char *OS_GetAttributeContent(OS_XML *_lxml, const char **element_name,
254                 const char *attribute_name)
255 {
256     char *uniqret = NULL;
257     char **ret = NULL;
258
259     _lxml->fol=0;
260
261     ret = _GetElementContent(_lxml, element_name,attribute_name);
262
263     if(ret == NULL)
264         return(NULL);
265
266     if(ret[0] != NULL)
267     {
268         uniqret = ret[0];
269     }
270     int i = 1;
271     while(ret[i] != NULL)
272     {
273         free(ret[i++]);
274     }
275     free(ret);
276
277     return(uniqret);
278 }
279
280
281 /* _GetElementContent: v0.1: 2005/03/01
282  *  Get the values for an element or attribute
283  */
284 static char **_GetElementContent(OS_XML *_lxml, const char **element_name, const char *attr)
285 {
286     int i = 0;
287     unsigned int j = 0,k = 0,l = 0,matched = 0;
288     char **ret = NULL;
289     char **ret_tmp;
290
291     if(_lxml->fol >= 0 && (unsigned int)_lxml->fol == _lxml->cur)
292     {
293         _lxml->fol = 0;
294         return(NULL);
295     }
296
297     if(_lxml->fol > 0)
298     {
299         for(i=_lxml->fol;i>=0;i--)
300         {
301             _lxml->fol = i;
302             if(_lxml->rl[i] == 0)
303                 break;
304         }
305         i = _lxml->fol;
306     }
307     else
308     {
309         i = 0;
310     }
311
312     /* Looping through all nodes */
313     for(j=0,l=(unsigned int)i; l<_lxml->cur; l++)
314     {
315         if(element_name[j] == NULL)
316         {
317             if(matched !=1)
318                 break;
319         }
320
321         /* Setting maximum depth of 16. */
322         if(j > 16)
323             goto fail;
324
325
326         /* If the type is not an element and the relation doesn't match,
327          * keep going.
328          */
329         if((_lxml->tp[l] != XML_ELEM) || (_lxml->rl[l] != j))
330         {
331             /* If the node relation is higher than we currently xml
332              * node, zero the position and look at it again (i--).
333              */
334             if(j > _lxml->rl[l])
335             {
336                 j = 0;
337                 matched = 0;
338                 l--;
339             }
340             else
341             {
342                 continue;
343             }
344         }
345
346
347         /* If the element name matches what we are looking for. */
348         else if(element_name[j] != NULL && strcmp(_lxml->el[l], element_name[j]) == 0)
349         {
350             j++;
351             matched = 1;
352
353             /* Get content if we are at the end of the array. */
354             if(element_name[j] == NULL)
355             {
356                 /* If we have an attribute to match. */
357                 if(attr != NULL)
358                 {
359                     unsigned int m=0;
360                     for(m=l+1; m<_lxml->cur; m++)
361                     {
362                         if(_lxml->tp[m] == XML_ELEM)
363                         {
364                             break;
365                         }
366
367                         if(strcmp(attr, _lxml->el[m]) == 0)
368                         {
369                             l = m;
370                             break;
371                         }
372                     }
373                 }
374
375                 if(_lxml->ct[l] != NULL)
376                 {
377                     /* Increasing the size of the array. */
378                     ret_tmp = (char**) realloc(ret,(k+2) * sizeof(char*));
379                     if(ret_tmp == NULL)
380                     {
381                        goto fail;
382                     }
383                     ret = ret_tmp;
384
385                     /* Adding new entry. */
386                     ret[k] = strdup(_lxml->ct[l]);
387                     ret[k + 1] = NULL;
388                     if(ret[k] == NULL)
389                     {
390                         goto fail;
391                     }
392
393                     matched = 1;
394                     k++;
395
396                     if(attr != NULL)
397                     {
398                         break;
399                     }
400
401                     else if(_lxml->fol != 0)
402                     {
403                         _lxml->fol = (int) l+1;
404                         break;
405                     }
406                 }
407
408                 /* Setting new array pointer. */
409                 if((l<_lxml->cur-1) && (_lxml->tp[l+1] == XML_ELEM))
410                 {
411                     j = _lxml->rl[l+1];
412                 }
413             }
414             continue;
415         }
416
417         if(j > _lxml->rl[l])
418         {
419             j = 0;
420             matched = 0;
421         }
422     }
423
424     return(ret);
425
426     fail:
427     i = 0;
428     if(ret)
429     {
430                 while(ret[i])
431                         free(ret[i++]);
432                 free(ret);
433     }
434         return (NULL);
435 }
436
437 /* EOF */