1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-address.c Server address parser.
4 * Copyright (C) 2003 CodeFactory AB
5 * Copyright (C) 2004 Red Hat, Inc.
7 * Licensed under the Academic Free License version 2.1
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "dbus-address.h"
27 #include "dbus-internals.h"
28 #include "dbus-list.h"
29 #include "dbus-string.h"
30 #include "dbus-protocol.h"
33 * @defgroup DBusAddressInternals Address parsing
34 * @ingroup DBusInternals
35 * @brief Implementation of parsing addresses of D-BUS servers.
41 * Internals of DBusAddressEntry
43 struct DBusAddressEntry
45 DBusString method; /**< The address type (unix, tcp, etc.) */
47 DBusList *keys; /**< List of keys */
48 DBusList *values; /**< List of values */
51 /** @} */ /* End of internals */
54 dbus_address_entry_free (DBusAddressEntry *entry)
58 _dbus_string_free (&entry->method);
60 link = _dbus_list_get_first_link (&entry->keys);
63 _dbus_string_free (link->data);
64 dbus_free (link->data);
66 link = _dbus_list_get_next_link (&entry->keys, link);
68 _dbus_list_clear (&entry->keys);
70 link = _dbus_list_get_first_link (&entry->values);
73 _dbus_string_free (link->data);
74 dbus_free (link->data);
76 link = _dbus_list_get_next_link (&entry->values, link);
78 _dbus_list_clear (&entry->values);
84 * @defgroup DBusAddress Address parsing
86 * @brief Parsing addresses of D-BUS servers.
92 * Frees a #NULL-terminated array of address entries.
94 * @param entries the array.
97 dbus_address_entries_free (DBusAddressEntry **entries)
101 for (i = 0; entries[i] != NULL; i++)
102 dbus_address_entry_free (entries[i]);
106 static DBusAddressEntry *
109 DBusAddressEntry *entry;
111 entry = dbus_new0 (DBusAddressEntry, 1);
116 if (!_dbus_string_init (&entry->method))
126 * Returns the method string of an address entry.
128 * @param entry the entry.
129 * @returns a string describing the method. This string
133 dbus_address_entry_get_method (DBusAddressEntry *entry)
135 return _dbus_string_get_const_data (&entry->method);
139 * Returns a value from a key of an entry.
141 * @param entry the entry.
142 * @param key the key.
143 * @returns the key value. This string must not be fred.
146 dbus_address_entry_get_value (DBusAddressEntry *entry,
149 DBusList *values, *keys;
151 keys = _dbus_list_get_first_link (&entry->keys);
152 values = _dbus_list_get_first_link (&entry->values);
156 _dbus_assert (values != NULL);
158 if (_dbus_string_equal_c_str (keys->data, key))
159 return _dbus_string_get_const_data (values->data);
161 keys = _dbus_list_get_next_link (&entry->keys, keys);
162 values = _dbus_list_get_next_link (&entry->values, values);
169 * Parses an address string of the form:
171 * method:key=value,key=value;method:key=value
173 * @todo document address format in the specification
175 * @todo need to be able to escape ';' and ',' in the
176 * key values, and the parsing needs to handle that.
178 * @param address the address.
179 * @param entry return location to an array of entries.
180 * @param array_len return location for array length.
181 * @param error address where an error can be returned.
182 * @returns #TRUE on success, #FALSE otherwise.
185 dbus_parse_address (const char *address,
186 DBusAddressEntry ***entry,
191 int pos, end_pos, len, i;
192 DBusList *entries, *link;
193 DBusAddressEntry **entry_array;
195 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
197 _dbus_string_init_const (&str, address);
201 len = _dbus_string_get_length (&str);
205 DBusAddressEntry *entry;
209 entry = create_entry ();
212 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
217 /* Append the entry */
218 if (!_dbus_list_append (&entries, entry))
220 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
221 dbus_address_entry_free (entry);
225 /* Look for a semi-colon */
226 if (!_dbus_string_find (&str, pos, ";", &end_pos))
229 /* Look for the colon : */
230 if (!_dbus_string_find_to (&str, pos, end_pos, ":", &found_pos))
232 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, "Address does not contain a colon");
236 if (!_dbus_string_copy_len (&str, pos, found_pos - pos, &entry->method, 0))
238 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
244 while (pos < end_pos)
246 int comma_pos, equals_pos;
248 if (!_dbus_string_find_to (&str, pos, end_pos, ",", &comma_pos))
251 if (!_dbus_string_find_to (&str, pos, comma_pos, "=", &equals_pos) ||
252 equals_pos == pos || equals_pos + 1 == comma_pos)
254 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
255 "'=' character not found or has no value following it");
263 key = dbus_new0 (DBusString, 1);
267 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
271 value = dbus_new0 (DBusString, 1);
274 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
279 if (!_dbus_string_init (key))
281 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
288 if (!_dbus_string_init (value))
290 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
291 _dbus_string_free (key);
298 if (!_dbus_string_copy_len (&str, pos, equals_pos - pos, key, 0))
300 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
301 _dbus_string_free (key);
302 _dbus_string_free (value);
309 if (!_dbus_string_copy_len (&str, equals_pos + 1, comma_pos - equals_pos - 1, value, 0))
311 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
312 _dbus_string_free (key);
313 _dbus_string_free (value);
320 if (!_dbus_list_append (&entry->keys, key))
322 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
323 _dbus_string_free (key);
324 _dbus_string_free (value);
331 if (!_dbus_list_append (&entry->values, value))
333 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
334 _dbus_string_free (value);
347 *array_len = _dbus_list_get_length (&entries);
349 entry_array = dbus_new (DBusAddressEntry *, *array_len + 1);
353 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
358 entry_array [*array_len] = NULL;
360 link = _dbus_list_get_first_link (&entries);
364 entry_array[i] = link->data;
366 link = _dbus_list_get_next_link (&entries, link);
369 _dbus_list_clear (&entries);
370 *entry = entry_array;
376 link = _dbus_list_get_first_link (&entries);
379 dbus_address_entry_free (link->data);
380 link = _dbus_list_get_next_link (&entries, link);
383 _dbus_list_clear (&entries);
390 /** @} */ /* End of public API */
392 #ifdef DBUS_BUILD_TESTS
393 #include "dbus-test.h"
396 _dbus_address_test (void)
398 DBusAddressEntry **entries;
402 dbus_error_init (&error);
404 if (!dbus_parse_address ("unix:path=/tmp/foo;debug:name=test,sliff=sloff;",
405 &entries, &len, &error))
406 _dbus_assert_not_reached ("could not parse address");
407 _dbus_assert (len == 2);
408 _dbus_assert (strcmp (dbus_address_entry_get_value (entries[0], "path"), "/tmp/foo") == 0);
409 _dbus_assert (strcmp (dbus_address_entry_get_value (entries[1], "name"), "test") == 0);
410 _dbus_assert (strcmp (dbus_address_entry_get_value (entries[1], "sliff"), "sloff") == 0);
412 dbus_address_entries_free (entries);
414 /* Different possible errors */
415 if (dbus_parse_address ("foo", &entries, &len, &error))
416 _dbus_assert_not_reached ("Parsed incorrect address.");
418 dbus_error_free (&error);
420 if (dbus_parse_address ("foo:bar", &entries, &len, &error))
421 _dbus_assert_not_reached ("Parsed incorrect address.");
423 dbus_error_free (&error);
425 if (dbus_parse_address ("foo:bar,baz", &entries, &len, &error))
426 _dbus_assert_not_reached ("Parsed incorrect address.");
428 dbus_error_free (&error);
430 if (dbus_parse_address ("foo:bar=foo,baz", &entries, &len, &error))
431 _dbus_assert_not_reached ("Parsed incorrect address.");
433 dbus_error_free (&error);
435 if (dbus_parse_address ("foo:bar=foo;baz", &entries, &len, &error))
436 _dbus_assert_not_reached ("Parsed incorrect address.");
438 dbus_error_free (&error);
440 if (dbus_parse_address ("foo:=foo", &entries, &len, &error))
441 _dbus_assert_not_reached ("Parsed incorrect address.");
443 dbus_error_free (&error);
445 if (dbus_parse_address ("foo:foo=", &entries, &len, &error))
446 _dbus_assert_not_reached ("Parsed incorrect address.");
448 dbus_error_free (&error);
450 if (dbus_parse_address ("foo:foo,bar=baz", &entries, &len, &error))
451 _dbus_assert_not_reached ("Parsed incorrect address.");
453 dbus_error_free (&error);