Imported Upstream version 2.5.1
[ossec-hids.git] / src / os_xml / os_xml_writer.c
1 /* @(#) $Id$ */
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 Library.
13  * Available at http://www.ossec.net/
14  */
15
16
17
18 #include "shared.h"
19
20 #include "os_xml_writer.h"
21 //#include "os_xml.h"
22
23 #define _R_CONFS        '<'
24 #define _R_CONFE        '>'
25 #define _R_EQUAL        '='
26 #define _R_COM          '!'
27 #define _R_VAR      '$'
28
29 #define OPEN            51
30 #define CLOSE           52
31
32 #define LEOF            -2
33
34 /* Internal functions */
35 int _oswcomment(FILE *fp_in, FILE *fp_out);
36 int _WReadElem(FILE *fp_in, FILE *fp_out, int position, int parent, 
37                char **node, char *value, int node_pos);
38
39
40 /* Currently line */
41 int _line;
42
43
44 /* Local fgetc */
45 int _xml_wfgetc(FILE *fp_in, FILE *fp_out)
46 {
47     int c;
48
49     /* Putting on fp_out, whatever we read */
50     c = fgetc(fp_in);
51     if(c != EOF)
52     {
53         fputc(c, fp_out);
54     }
55
56     if(c == '\n') /* add new line */
57         _line++;
58     
59     return(c);    
60 }
61
62 #define FWGETC(fp_in, fp_out) _xml_wfgetc(fp_in, fp_out)
63
64
65
66 /* OS_WriteXML
67  * Write an XML file, based on the input and values to change.
68  */
69 int OS_WriteXML(char *infile, char *outfile, char **nodes, char *attr,
70                 char *oldval, char *newval,  int type)
71 {
72     int r = 0;
73     int node_pos = 0;
74     FILE *fp_in;
75     FILE *fp_out;
76
77
78     /* Nodes and newval must be set. */
79     if(!nodes || !newval)
80     {
81         return(XMLW_ERROR);
82     }
83
84     /* Opening infile */
85     fp_in = fopen(infile,"r");
86     if(!fp_in)
87     {
88         return(XMLW_NOIN);
89     }
90
91
92     /* Opening out file */
93     fp_out = fopen(outfile,"w");
94     if(!fp_out)
95     {
96         fclose(fp_in);
97         return(XMLW_NOOUT);
98     }
99
100
101     if((r = _WReadElem(fp_in, fp_out, 0, 0,
102                        nodes, newval, node_pos)) < 0) /* First position */
103     {
104         fclose(fp_in);
105         fclose(fp_out);
106         return(XMLW_ERROR);
107     }
108
109     /* We didn't find an entry, add at the end. */
110     if(!oldval && r == 0)
111     {
112         int r = 0;
113         int rwidth = 0;
114         
115         fseek(fp_out, 0, SEEK_END);
116         fprintf(fp_out, "\n");
117         
118         /* Printing each node. */
119         while(nodes[r])
120         {
121             fprintf(fp_out, "%*c<%s>", rwidth, ' ', nodes[r]);
122             r++;
123             rwidth += 3;
124
125             if(nodes[r])
126                 fprintf(fp_out, "\n");
127         }
128     
129         /* Printing val. */
130         r--;
131         rwidth -=6;
132         fprintf(fp_out, "%s</%s>\n", newval, nodes[r]);
133         r--;
134         
135
136         /* Closing each node. */
137         while(r >= 0)
138         {
139             fprintf(fp_out, "%*c</%s>\n", rwidth, ' ', nodes[r]);
140             r--;
141             rwidth -= 3;
142         }
143     }
144     
145     fclose(fp_in);
146     fclose(fp_out);
147     return(0);
148 }
149
150
151
152 /* Getting comments */
153 int _oswcomment(FILE *fp_in, FILE *fp_out)
154 {
155     int c;
156     if((c = fgetc(fp_in)) == _R_COM)
157     {
158         fputc(c, fp_out);
159         while((c = FWGETC(fp_in, fp_out)) != EOF)
160         {
161             if(c == _R_COM)
162             {
163                 if((c=fgetc(fp_in)) == _R_CONFE)
164                 {
165                     fputc(c, fp_out);
166                     return(1);
167                 }
168                 ungetc(c,fp_in);
169             }
170             else if(c == '-')       /* W3C way of finish comments */
171             {
172                 if((c = fgetc(fp_in)) == '-')
173                 {
174                     fputc(c, fp_out);
175                     if((c = fgetc(fp_in)) == _R_CONFE)
176                     {
177                         fputc(c, fp_out);
178                         return(1);
179                     }
180                     ungetc(c,fp_in);
181                 }
182                 else
183                 {
184                     ungetc(c,fp_in);
185                 }
186             }
187             else
188             {
189                 continue;
190             }
191         }
192         return(-1);
193     }
194     else
195     {
196         ungetc(c,fp_in);
197     }
198
199     return(0);
200 }
201
202
203
204 int _WReadElem(FILE *fp_in, FILE *fp_out, 
205               int position, int parent, char **nodes, char *val, int node_pos)
206 {
207     int c;
208     int ret_code = 0;
209     unsigned int count = 0;
210     short int location = -1;
211
212     char elem[XML_MAXSIZE +1];
213     char cont[XML_MAXSIZE +1];
214     char closedelem[XML_MAXSIZE +1];
215
216     memset(elem,'\0',XML_MAXSIZE +1);
217     memset(cont,'\0',XML_MAXSIZE +1);
218     memset(closedelem,'\0',XML_MAXSIZE +1);
219
220
221     while((c = FWGETC(fp_in, fp_out)) != EOF)
222     {
223         /* Max size */
224         if(count >= XML_MAXSIZE)
225         {
226             return(-1);
227         }
228
229         /* Checking for comments */
230         if(c == _R_CONFS)
231         {
232             int r = 0;
233             if((r = _oswcomment(fp_in, fp_out)) < 0)
234             {
235                 return(-1);
236             }
237             else if(r == 1)
238             {
239                 continue;
240             }
241         }
242         
243         
244         /* Real checking */
245         if(location == -1)
246         {
247             /* Must be the opening element */
248             if(c == _R_CONFS)
249             {
250                 if((c = fgetc(fp_in)) == '/')
251                 {
252                     return(-1);
253                 }
254                 else
255                 {
256                     ungetc(c,fp_in);
257                 }
258                 location = 0;
259             }
260             else
261             {
262                 continue;
263             }
264         }
265         
266
267         /* Looking for the closure */
268         else if((location == 0) && ((c == _R_CONFE) || (c == ' ')))
269         {
270             int _ge = 0;
271             elem[count] = '\0';
272
273
274             /* Removing the / at the end of the element name */
275             if(elem[count -1] == '/')
276             {
277                 _ge = '/';
278                 elem[count -1] = '\0';
279             }
280             
281
282             /* If we may have more attributes */
283             if(c == ' ')
284             {
285                 /* Writing the attributes */
286                 while((c = FWGETC(fp_in, fp_out)) != EOF)
287                 {
288                     if(c == _R_CONFE)
289                     {
290                         break;
291                     }
292                 }
293             }
294
295
296             /* If the element is closed already (finished in />) */
297             if(_ge == '/')
298             {
299                 count = 0;
300                 location = -1;
301              
302                 memset(elem,'\0',XML_MAXSIZE);
303                 memset(closedelem,'\0',XML_MAXSIZE);
304                 memset(cont,'\0',XML_MAXSIZE);
305                 
306                 if(parent > 0)
307                 {
308                     return(ret_code);
309                 }
310             }
311             /* Location == means we are getting the content */
312             else
313             {
314                 count = 0;
315                 location = 1;
316             }    
317
318
319             /* Checking position of the node */
320             if(node_pos > position)
321             {
322                 node_pos = 0;
323             }
324
325             /* Checking if the element name matches */
326             if(node_pos == position && 
327                nodes[node_pos] && strcmp(elem, nodes[node_pos]) == 0)
328             {
329                 node_pos++;
330
331                 /* Latest node, printint value */
332                 if(!nodes[node_pos])
333                 {
334                     ret_code = 1;
335                     fprintf(fp_out, "%s", val);
336
337                     while((c = fgetc(fp_in)) != EOF)
338                     {
339                         if(c == _R_CONFS)
340                         {
341                             ungetc(c,fp_in);
342                             break;
343                         }
344                     }
345                 }
346             }
347         }
348         
349         else if((location == 2) &&(c == _R_CONFE))
350         {
351             closedelem[count]='\0';
352             if(strcmp(closedelem,elem) != 0)
353             {
354                 return(-1);
355             }
356
357             memset(elem,'\0',XML_MAXSIZE);
358             memset(closedelem,'\0',XML_MAXSIZE);
359             memset(cont,'\0',XML_MAXSIZE);
360             
361             count = 0;  
362             location = -1;
363             if(parent > 0)
364             {
365                 return(ret_code);
366             }
367         }
368
369         /* If we are reading the element */
370         else if((location == 1) &&(c == _R_CONFS))
371         {
372             if((c=fgetc(fp_in)) == '/')
373             {
374                 fputc(c, fp_out);
375
376                 cont[count] = '\0';
377                 count = 0;
378                 location = 2;
379             }   
380             else
381             {
382                 int wret_code;
383                 ungetc(c,fp_in);
384                 ungetc(_R_CONFS,fp_in);
385                 fseek(fp_out, -1, SEEK_CUR);
386
387                 if((wret_code = _WReadElem(fp_in, fp_out, position+1, parent+1,
388                              nodes, val, node_pos))< 0)
389                 {
390                     return(-1);
391                 }
392
393                 /* Setting final return code. */
394                 if(wret_code == 1)
395                 {
396                     ret_code = 1;
397                 }
398                 
399                 count = 0;
400             }
401         }
402         else
403         {
404             if(location == 0)
405             {
406                 elem[count++] = c;
407             }
408             else if(location == 1)
409             {
410                 cont[count++] = c;
411             }
412             else if(location == 2)
413             {
414                 closedelem[count++] = c;
415             }
416         }
417     }
418     
419     if(location == -1)
420     {
421         return(ret_code);
422     }
423
424
425     return(-1);
426 }                               
427
428
429
430
431 /* EOF */