1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* config-loader-expat.c expat XML loader
4 * Copyright (C) 2003 Red Hat, Inc.
6 * Licensed under the Academic Free License version 2.1
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "config-parser.h"
26 #include <dbus/dbus-internals.h>
29 static XML_Memory_Handling_Suite memsuite =
38 BusConfigParser *parser;
46 process_content (ExpatParseContext *context)
51 if (_dbus_string_get_length (&context->content) > 0)
53 if (!bus_config_parser_content (context->parser,
57 context->failed = TRUE;
60 _dbus_string_set_length (&context->content, 0);
67 expat_StartElementHandler (void *userData,
69 const XML_Char **atts)
71 ExpatParseContext *context = userData;
76 /* Expat seems to suck and can't abort the parse if we
77 * throw an error. Expat 2.0 is supposed to fix this.
82 if (!process_content (context))
85 /* "atts" is key, value, key, value, NULL */
86 for (i = 0; atts[i] != NULL; ++i)
89 _dbus_assert (i % 2 == 0);
90 names = dbus_new0 (char *, i / 2 + 1);
91 values = dbus_new0 (char *, i / 2 + 1);
93 if (names == NULL || values == NULL)
95 dbus_set_error (context->error, DBUS_ERROR_NO_MEMORY, NULL);
96 context->failed = TRUE;
103 while (atts[i] != NULL)
105 _dbus_assert (i % 2 == 0);
106 names [i / 2] = (char*) atts[i];
107 values[i / 2] = (char*) atts[i+1];
112 if (!bus_config_parser_start_element (context->parser,
114 (const char **) names,
115 (const char **) values,
120 context->failed = TRUE;
129 expat_EndElementHandler (void *userData,
130 const XML_Char *name)
132 ExpatParseContext *context = userData;
134 if (!process_content (context))
137 if (!bus_config_parser_end_element (context->parser,
141 context->failed = TRUE;
146 /* s is not 0 terminated. */
148 expat_CharacterDataHandler (void *userData,
152 ExpatParseContext *context = userData;
156 if (!_dbus_string_append_len (&context->content,
159 dbus_set_error (context->error, DBUS_ERROR_NO_MEMORY, NULL);
160 context->failed = TRUE;
167 bus_config_load (const DBusString *file,
168 dbus_bool_t is_toplevel,
169 const BusConfigParser *parent,
173 const char *filename;
174 BusConfigParser *parser;
175 ExpatParseContext context;
178 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
182 context.error = error;
183 context.failed = FALSE;
185 filename = _dbus_string_get_const_data (file);
187 if (!_dbus_string_init (&context.content))
189 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
193 if (!_dbus_string_init (&dirname))
195 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
196 _dbus_string_free (&context.content);
200 expat = XML_ParserCreate_MM ("UTF-8", &memsuite, NULL);
203 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
207 if (!_dbus_string_get_dirname (file, &dirname))
209 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
213 parser = bus_config_parser_new (&dirname, is_toplevel, parent);
216 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
219 context.parser = parser;
221 XML_SetUserData (expat, &context);
222 XML_SetElementHandler (expat,
223 expat_StartElementHandler,
224 expat_EndElementHandler);
225 XML_SetCharacterDataHandler (expat,
226 expat_CharacterDataHandler);
230 const char *data_str;
232 if (!_dbus_string_init (&data))
234 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
238 if (!_dbus_file_get_contents (&data, file, error))
240 _dbus_string_free (&data);
244 data_str = _dbus_string_get_const_data (&data);
246 if (!XML_Parse (expat, data_str, _dbus_string_get_length (&data), TRUE))
248 if (context.error != NULL &&
249 !dbus_error_is_set (context.error))
253 e = XML_GetErrorCode (expat);
254 if (e == XML_ERROR_NO_MEMORY)
255 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
257 dbus_set_error (error, DBUS_ERROR_FAILED,
258 "Error in file %s, line %d, column %d: %s\n",
260 XML_GetCurrentLineNumber (expat),
261 XML_GetCurrentColumnNumber (expat),
262 XML_ErrorString (e));
265 _dbus_string_free (&data);
269 _dbus_string_free (&data);
275 if (!bus_config_parser_finished (parser, error))
278 _dbus_string_free (&dirname);
279 _dbus_string_free (&context.content);
280 XML_ParserFree (expat);
282 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
286 _DBUS_ASSERT_ERROR_IS_SET (error);
288 _dbus_string_free (&dirname);
289 _dbus_string_free (&context.content);
291 XML_ParserFree (expat);
293 bus_config_parser_unref (parser);