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