2003-03-27 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / bus / config-loader-libxml.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* config-loader-libxml.c  libxml2 XML loader
3  *
4  * Copyright (C) 2003 Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 1.2
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "config-parser.h"
25 #include <dbus/dbus-internals.h>
26 #include <libxml/xmlreader.h>
27 #include <libxml/parser.h>
28 #include <libxml/globals.h>
29 #include <libxml/xmlmemory.h>
30 #include <errno.h>
31 #include <string.h>
32
33 static void*
34 libxml_malloc (size_t size)
35 {
36   return dbus_malloc (size);
37 }
38
39 static void*
40 libxml_realloc (void *ptr, size_t size)
41 {
42   return dbus_realloc (ptr, size);
43 }
44
45 static void
46 libxml_free (void *ptr)
47 {
48   dbus_free (ptr);
49 }
50
51 static char*
52 libxml_strdup (const char *str)
53 {
54   return _dbus_strdup (str);
55 }
56
57 static void
58 xml_text_reader_error (void                   *arg,
59                        const char             *msg,
60                        xmlParserSeverities     severity,
61                        xmlTextReaderLocatorPtr locator)
62 {
63   DBusError *error = arg;
64   
65   if (!dbus_error_is_set (error))
66     {
67       dbus_set_error (error, DBUS_ERROR_FAILED,
68                       "Error loading config file: %s",
69                       msg);
70     }
71 }
72
73 BusConfigParser*
74 bus_config_load (const DBusString *file,
75                  DBusError        *error)
76 {
77   xmlTextReader *reader;
78   const char *filename;
79   BusConfigParser *parser;
80   DBusError tmp_error;
81   int ret;
82   
83   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
84   
85   _dbus_string_get_const_data (file, &filename);
86   parser = NULL;
87   reader = NULL;
88   dbus_error_init (&tmp_error);
89
90   if (xmlMemSetup (libxml_free,
91                    libxml_malloc,
92                    libxml_realloc,
93                    libxml_strdup) != 0)
94     {
95       /* Current libxml can't possibly fail here, but just being
96        * paranoid; don't really know why xmlMemSetup() returns an
97        * error code, assuming some version of libxml had a reason.
98        */
99       dbus_set_error (error, DBUS_ERROR_FAILED,
100                       "xmlMemSetup() didn't work for some reason\n");
101       return NULL;
102     }
103   
104   parser = bus_config_parser_new ();
105   if (parser == NULL)
106     {
107       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
108       return NULL;
109     }
110   
111   errno = 0;
112   reader = xmlNewTextReaderFilename (filename);
113
114   if (reader == NULL)
115     {
116       dbus_set_error (error, DBUS_ERROR_FAILED,
117                       "Failed to load configuration file %s: %s\n",
118                       filename,
119                       errno != 0 ? strerror (errno) : "Unknown error");
120         
121       goto failed;
122     }
123
124   xmlTextReaderSetErrorHandler (reader, xml_text_reader_error, &tmp_error);
125
126   while ((ret = xmlTextReaderRead (reader)) == 1)
127     {
128       int type;
129       
130       if (dbus_error_is_set (&tmp_error))
131         goto reader_out;
132       
133       /* "enum" anyone? http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html for
134        * the magic numbers
135        */
136       type = xmlTextReaderNodeType (reader);
137       if (dbus_error_is_set (&tmp_error))
138         goto reader_out;
139
140       /* FIXME I don't really know exactly what I need to do to
141        * resolve all entities and so on to get the full content of a
142        * node or attribute value. I'm worried about whether I need to
143        * manually handle stuff like &lt;
144        */
145     }
146
147   if (ret == -1)
148     {
149       if (!dbus_error_is_set (&tmp_error))
150         dbus_set_error (&tmp_error,
151                         DBUS_ERROR_FAILED,
152                         "Unknown failure loading configuration file");
153     }
154   
155  reader_out:
156   xmlFreeTextReader (reader);
157   reader = NULL;
158   if (dbus_error_is_set (&tmp_error))
159     {
160       dbus_move_error (&tmp_error, error);
161       goto failed;
162     }
163   
164   if (!bus_config_parser_finished (parser, error))
165     goto failed;
166
167   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
168   return parser;
169   
170  failed:
171   _DBUS_ASSERT_ERROR_IS_SET (error);
172   if (parser)
173     bus_config_parser_unref (parser);
174   _dbus_assert (reader == NULL); /* must go to reader_out first */
175   return NULL;
176 }