1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24: #include "config-parser.h"
25: #include <dbus/dbus-internals.h>
26: #include <expat.h>
27:
28: static XML_Memory_Handling_Suite memsuite =
29: {
30: dbus_malloc,
31: dbus_realloc,
32: dbus_free
33: };
34:
35: typedef struct
36: {
37: BusConfigParser *parser;
38: const char *filename;
39: DBusString content;
40: DBusError *error;
41: dbus_bool_t failed;
42: } ExpatParseContext;
43:
44: static dbus_bool_t
45: process_content (ExpatParseContext *context)
46: {
47: if (context->failed)
48: return FALSE;
49:
50: if (_dbus_string_get_length (&context->content) > 0)
51: {
52: if (!bus_config_parser_content (context->parser,
53: &context->content,
54: context->error))
55: {
56: context->failed = TRUE;
57: return FALSE;
58: }
59: _dbus_string_set_length (&context->content, 0);
60: }
61:
62: return TRUE;
63: }
64:
65: static void
66: expat_StartElementHandler (void *userData,
67: const XML_Char *name,
68: const XML_Char **atts)
69: {
70: ExpatParseContext *context = userData;
71: int i;
72: char **names;
73: char **values;
74:
75:
76:
77:
78: if (context->failed)
79: return;
80:
81: if (!process_content (context))
82: return;
83:
84:
85: for (i = 0; atts[i] != NULL; ++i)
86: ;
87:
88: _dbus_assert (i % 2 == 0);
89: names = dbus_new0 (char *, i / 2 + 1);
90: values = dbus_new0 (char *, i / 2 + 1);
91:
92: if (names == NULL || values == NULL)
93: {
94: dbus_set_error (context->error, DBUS_ERROR_NO_MEMORY, NULL);
95: context->failed = TRUE;
96: dbus_free (names);
97: dbus_free (values);
98: return;
99: }
100:
101: i = 0;
102: while (atts[i] != NULL)
103: {
104: _dbus_assert (i % 2 == 0);
105: names [i / 2] = (char*) atts[i];
106: values[i / 2] = (char*) atts[i+1];
107:
108: i += 2;
109: }
110:
111: if (!bus_config_parser_start_element (context->parser,
112: name,
113: (const char **) names,
114: (const char **) values,
115: context->error))
116: {
117: dbus_free (names);
118: dbus_free (values);
119: context->failed = TRUE;
120: return;
121: }
122:
123: dbus_free (names);
124: dbus_free (values);
125: }
126:
127: static void
128: expat_EndElementHandler (void *userData,
129: const XML_Char *name)
130: {
131: ExpatParseContext *context = userData;
132:
133: if (!process_content (context))
134: return;
135:
136: if (!bus_config_parser_end_element (context->parser,
137: name,
138: context->error))
139: {
140: context->failed = TRUE;
141: return;
142: }
143: }
144:
145:
146: static void
147: expat_CharacterDataHandler (void *userData,
148: const XML_Char *s,
149: int len)
150: {
151: ExpatParseContext *context = userData;
152: if (context->failed)
153: return;
154:
155: if (!_dbus_string_append_len (&context->content,
156: s, len))
157: {
158: dbus_set_error (context->error, DBUS_ERROR_NO_MEMORY, NULL);
159: context->failed = TRUE;
160: return;
161: }
162: }
163:
164:
165: BusConfigParser*
166: bus_config_load (const DBusString *file,
167: dbus_bool_t is_toplevel,
168: const BusConfigParser *parent,
169: DBusError *error)
170: {
171: XML_Parser expat;
172: const char *filename;
173: BusConfigParser *parser;
174: ExpatParseContext context;
175: DBusString dirname;
176:
177: _DBUS_ASSERT_ERROR_IS_CLEAR (error);
178:
179: parser = NULL;
180: expat = NULL;
181: context.error = error;
182: context.failed = FALSE;
183:
184: filename = _dbus_string_get_const_data (file);
185:
186: if (!_dbus_string_init (&context.content))
187: {
188: dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
189: return NULL;
190: }
191:
192: if (!_dbus_string_init (&dirname))
193: {
194: dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
195: _dbus_string_free (&context.content);
196: return NULL;
197: }
198:
199: expat = XML_ParserCreate_MM ("UTF-8", &memsuite, NULL);
200: if (expat == NULL)
201: {
202: dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
203: goto failed;
204: }
205:
206: if (!_dbus_string_get_dirname (file, &dirname))
207: {
208: dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
209: goto failed;
210: }
211:
212: parser = bus_config_parser_new (&dirname, is_toplevel, parent);
213: if (parser == NULL)
214: {
215: dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
216: goto failed;
217: }
218: context.parser = parser;
219:
220: XML_SetUserData (expat, &context);
221: XML_SetElementHandler (expat,
222: expat_StartElementHandler,
223: expat_EndElementHandler);
224: XML_SetCharacterDataHandler (expat,
225: expat_CharacterDataHandler);
226:
227: {
228: DBusString data;
229: const char *data_str;
230:
231: if (!_dbus_string_init (&data))
232: {
233: dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
234: goto failed;
235: }
236:
237: if (!_dbus_file_get_contents (&data, file, error))
238: {
239: _dbus_string_free (&data);
240: goto failed;
241: }
242:
243: data_str = _dbus_string_get_const_data (&data);
244:
245: if (!XML_Parse (expat, data_str, _dbus_string_get_length (&data), TRUE))
246: {
247: if (context.error != NULL &&
248: !dbus_error_is_set (context.error))
249: {
250: enum XML_Error e;
251:
252: e = XML_GetErrorCode (expat);
253: if (e == XML_ERROR_NO_MEMORY)
254: dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
255: else
256: dbus_set_error (error, DBUS_ERROR_FAILED,
257: "Error in file %s, line %d, column %d: %s\n",
258: filename,
259: XML_GetCurrentLineNumber (expat),
260: XML_GetCurrentColumnNumber (expat),
261: XML_ErrorString (e));
262: }
263:
264: _dbus_string_free (&data);
265: goto failed;
266: }
267:
268: _dbus_string_free (&data);
269:
270: if (context.failed)
271: goto failed;
272: }
273:
274: if (!bus_config_parser_finished (parser, error))
275: goto failed;
276:
277: _dbus_string_free (&dirname);
278: _dbus_string_free (&context.content);
279: XML_ParserFree (expat);
280:
281: _DBUS_ASSERT_ERROR_IS_CLEAR (error);
282: return parser;
283:
284: failed:
285: _DBUS_ASSERT_ERROR_IS_SET (error);
286:
287: _dbus_string_free (&dirname);
288: _dbus_string_free (&context.content);
289: if (expat)
290: XML_ParserFree (expat);
291: if (parser)
292: bus_config_parser_unref (parser);
293: return NULL;
294: }