Main Page   Modules   Data Structures   File List   Data Fields   Related Pages  

dbus-address.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-address.c  Server address parser.
00003  *
00004  * Copyright (C) 2003  CodeFactory AB
00005  *
00006  * Licensed under the Academic Free License version 1.2
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00024 #include <config.h>
00025 #include "dbus-address.h"
00026 #include "dbus-internals.h"
00027 #include "dbus-list.h"
00028 
00036 struct DBusAddressEntry
00037 {
00038   DBusString method;
00039 
00040   DBusList *keys;
00041   DBusList *values;
00042 };
00043 
00044 static void
00045 dbus_address_entry_free (DBusAddressEntry *entry)
00046 {
00047   DBusList *link;
00048   
00049   _dbus_string_free (&entry->method);
00050 
00051   link = _dbus_list_get_first_link (&entry->keys);
00052   while (link != NULL)
00053     {
00054       _dbus_string_free (link->data);
00055       dbus_free (link->data);
00056       
00057       link = _dbus_list_get_next_link (&entry->keys, link);
00058     }
00059   _dbus_list_clear (&entry->keys);
00060   
00061   link = _dbus_list_get_first_link (&entry->values);
00062   while (link != NULL)
00063     {
00064       _dbus_string_free (link->data);
00065       dbus_free (link->data);
00066       
00067       link = _dbus_list_get_next_link (&entry->values, link);
00068     }
00069   _dbus_list_clear (&entry->values);
00070   
00071   dbus_free (entry);
00072 }
00073 
00074 
00080 void
00081 dbus_address_entries_free (DBusAddressEntry **entries)
00082 {
00083   int i;
00084   
00085   for (i = 0; entries[i] != NULL; i++)
00086     dbus_address_entry_free (entries[i]);
00087   dbus_free (entries);
00088 }
00089 
00090 static DBusAddressEntry *
00091 create_entry (void)
00092 {
00093   DBusAddressEntry *entry;
00094 
00095   entry = dbus_new0 (DBusAddressEntry, 1);
00096 
00097   if (entry == NULL)
00098     return NULL;
00099 
00100   if (!_dbus_string_init (&entry->method))
00101     {
00102       dbus_free (entry);
00103       return NULL;
00104     }
00105 
00106   return entry;
00107 }
00108 
00116 const char *
00117 dbus_address_entry_get_method (DBusAddressEntry *entry)
00118 {
00119   return _dbus_string_get_const_data (&entry->method);
00120 }
00121 
00129 const char *
00130 dbus_address_entry_get_value (DBusAddressEntry *entry,
00131                               const char       *key)
00132 {
00133   DBusList *values, *keys;
00134 
00135   keys = _dbus_list_get_first_link (&entry->keys);
00136   values = _dbus_list_get_first_link (&entry->values);
00137 
00138   while (keys != NULL)
00139     {
00140       _dbus_assert (values != NULL);
00141 
00142       if (_dbus_string_equal_c_str (keys->data, key))
00143         return _dbus_string_get_const_data (values->data);
00144 
00145       keys = _dbus_list_get_next_link (&entry->keys, keys);
00146       values = _dbus_list_get_next_link (&entry->values, values);
00147     }
00148   
00149   return NULL;
00150 }
00151 
00168 dbus_bool_t
00169 dbus_parse_address (const char         *address,
00170                     DBusAddressEntry ***entry,
00171                     int                *array_len,
00172                     DBusError          *error)
00173 {
00174   DBusString str;
00175   int pos, end_pos, len, i;
00176   DBusList *entries, *link;
00177   DBusAddressEntry **entry_array;
00178 
00179   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00180   
00181   _dbus_string_init_const (&str, address);
00182 
00183   entries = NULL;
00184   pos = 0;
00185   len = _dbus_string_get_length (&str);
00186   
00187   while (pos < len)
00188     {
00189       DBusAddressEntry *entry;
00190 
00191       int found_pos;
00192 
00193       entry = create_entry ();
00194       if (!entry)
00195         {
00196           dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00197 
00198           goto error;
00199         }
00200       
00201       /* Append the entry */
00202       if (!_dbus_list_append (&entries, entry))
00203         {
00204           dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00205           dbus_address_entry_free (entry);
00206           goto error;
00207         }
00208       
00209       /* Look for a semi-colon */
00210       if (!_dbus_string_find (&str, pos, ";", &end_pos))
00211         end_pos = len;
00212       
00213       /* Look for the colon : */
00214       if (!_dbus_string_find_to (&str, pos, end_pos, ":", &found_pos))
00215         {
00216           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, "Address does not contain a colon");
00217           goto error;
00218         }
00219 
00220       if (!_dbus_string_copy_len (&str, pos, found_pos - pos, &entry->method, 0))
00221         {
00222           dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00223           goto error;
00224         }
00225           
00226       pos = found_pos + 1;
00227 
00228       while (pos < end_pos)
00229         {
00230           int comma_pos, equals_pos;
00231 
00232           if (!_dbus_string_find_to (&str, pos, end_pos, ",", &comma_pos))
00233             comma_pos = end_pos;
00234           
00235           if (!_dbus_string_find_to (&str, pos, comma_pos, "=", &equals_pos) ||
00236               equals_pos == pos || equals_pos + 1 == comma_pos)
00237             {
00238               dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00239                               "'=' character not found or has no value following it");
00240               goto error;
00241             }
00242           else
00243             {
00244               DBusString *key;
00245               DBusString *value;
00246 
00247               key = dbus_new0 (DBusString, 1);
00248 
00249               if (!key)
00250                 {
00251                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);             
00252                   goto error;
00253                 }
00254 
00255               value = dbus_new0 (DBusString, 1);
00256               if (!value)
00257                 {
00258                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00259                   dbus_free (key);
00260                   goto error;
00261                 }
00262               
00263               if (!_dbus_string_init (key))
00264                 {
00265                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00266                   dbus_free (key);
00267                   dbus_free (value);
00268                   
00269                   goto error;
00270                 }
00271               
00272               if (!_dbus_string_init (value))
00273                 {
00274                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00275                   _dbus_string_free (key);
00276 
00277                   dbus_free (key);
00278                   dbus_free (value);              
00279                   goto error;
00280                 }
00281 
00282               if (!_dbus_string_copy_len (&str, pos, equals_pos - pos, key, 0))
00283                 {
00284                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00285                   _dbus_string_free (key);
00286                   _dbus_string_free (value);
00287 
00288                   dbus_free (key);
00289                   dbus_free (value);              
00290                   goto error;
00291                 }
00292 
00293               if (!_dbus_string_copy_len (&str, equals_pos + 1, comma_pos - equals_pos - 1, value, 0))
00294                 {
00295                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);             
00296                   _dbus_string_free (key);
00297                   _dbus_string_free (value);
00298 
00299                   dbus_free (key);
00300                   dbus_free (value);              
00301                   goto error;
00302                 }
00303 
00304               if (!_dbus_list_append (&entry->keys, key))
00305                 {
00306                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);             
00307                   _dbus_string_free (key);
00308                   _dbus_string_free (value);
00309 
00310                   dbus_free (key);
00311                   dbus_free (value);              
00312                   goto error;
00313                 }
00314 
00315               if (!_dbus_list_append (&entry->values, value))
00316                 {
00317                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);             
00318                   _dbus_string_free (value);
00319 
00320                   dbus_free (value);
00321                   goto error;             
00322                 }
00323             }
00324 
00325           pos = comma_pos + 1;
00326         }
00327 
00328       pos = end_pos + 1;
00329     }
00330 
00331   *array_len = _dbus_list_get_length (&entries);
00332   
00333   entry_array = dbus_new (DBusAddressEntry *, *array_len + 1);
00334 
00335   if (!entry_array)
00336     {
00337       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00338       
00339       goto error;
00340     }
00341   
00342   entry_array [*array_len] = NULL;
00343 
00344   link = _dbus_list_get_first_link (&entries);
00345   i = 0;
00346   while (link != NULL)
00347     {
00348       entry_array[i] = link->data;
00349       i++;
00350       link = _dbus_list_get_next_link (&entries, link);
00351     }
00352 
00353   _dbus_list_clear (&entries);
00354   *entry = entry_array;
00355 
00356   return TRUE;
00357 
00358  error:
00359   
00360   link = _dbus_list_get_first_link (&entries);
00361   while (link != NULL)
00362     {
00363       dbus_address_entry_free (link->data);
00364       link = _dbus_list_get_next_link (&entries, link);
00365     }
00366 
00367   _dbus_list_clear (&entries);
00368   
00369   return FALSE;
00370   
00371 }
00372 
00373 
00376 #ifdef DBUS_BUILD_TESTS
00377 #include "dbus-test.h"
00378 
00379 dbus_bool_t
00380 _dbus_address_test (void)
00381 {
00382   DBusAddressEntry **entries;
00383   int len;  
00384   DBusError error;
00385 
00386   dbus_error_init (&error);
00387   
00388   if (!dbus_parse_address ("unix:path=/tmp/foo;debug:name=test,sliff=sloff;",
00389                            &entries, &len, &error))
00390     _dbus_assert_not_reached ("could not parse address");
00391   _dbus_assert (len == 2);
00392   _dbus_assert (strcmp (dbus_address_entry_get_value (entries[0], "path"), "/tmp/foo") == 0);
00393   _dbus_assert (strcmp (dbus_address_entry_get_value (entries[1], "name"), "test") == 0);
00394   _dbus_assert (strcmp (dbus_address_entry_get_value (entries[1], "sliff"), "sloff") == 0);
00395   
00396   dbus_address_entries_free (entries);
00397 
00398   /* Different possible errors */
00399   if (dbus_parse_address ("foo", &entries, &len, &error))
00400     _dbus_assert_not_reached ("Parsed incorrect address.");
00401   else
00402     dbus_error_free (&error);
00403   
00404   if (dbus_parse_address ("foo:bar", &entries, &len, &error))
00405     _dbus_assert_not_reached ("Parsed incorrect address.");
00406   else
00407     dbus_error_free (&error);
00408   
00409   if (dbus_parse_address ("foo:bar,baz", &entries, &len, &error))
00410     _dbus_assert_not_reached ("Parsed incorrect address.");
00411   else
00412     dbus_error_free (&error);
00413   
00414   if (dbus_parse_address ("foo:bar=foo,baz", &entries, &len, &error))
00415     _dbus_assert_not_reached ("Parsed incorrect address.");
00416   else
00417     dbus_error_free (&error);
00418   
00419   if (dbus_parse_address ("foo:bar=foo;baz", &entries, &len, &error))
00420     _dbus_assert_not_reached ("Parsed incorrect address.");
00421   else
00422     dbus_error_free (&error);
00423   
00424   if (dbus_parse_address ("foo:=foo", &entries, &len, &error))
00425     _dbus_assert_not_reached ("Parsed incorrect address.");
00426   else
00427     dbus_error_free (&error);
00428   
00429   if (dbus_parse_address ("foo:foo=", &entries, &len, &error))
00430     _dbus_assert_not_reached ("Parsed incorrect address.");
00431   else
00432     dbus_error_free (&error);
00433 
00434   if (dbus_parse_address ("foo:foo,bar=baz", &entries, &len, &error))
00435     _dbus_assert_not_reached ("Parsed incorrect address.");
00436   else
00437     dbus_error_free (&error);
00438 
00439   return TRUE;
00440 }
00441 
00442 #endif

Generated on Wed Oct 22 14:05:00 2003 for D-BUS by doxygen1.3-rc3