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 2.0
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 #include "dbus-string.h"
00029 
00041 struct DBusAddressEntry
00042 {
00043   DBusString method; 
00045   DBusList *keys;    
00046   DBusList *values;  
00047 };
00048  /* End of internals */
00050 
00051 static void
00052 dbus_address_entry_free (DBusAddressEntry *entry)
00053 {
00054   DBusList *link;
00055   
00056   _dbus_string_free (&entry->method);
00057 
00058   link = _dbus_list_get_first_link (&entry->keys);
00059   while (link != NULL)
00060     {
00061       _dbus_string_free (link->data);
00062       dbus_free (link->data);
00063       
00064       link = _dbus_list_get_next_link (&entry->keys, link);
00065     }
00066   _dbus_list_clear (&entry->keys);
00067   
00068   link = _dbus_list_get_first_link (&entry->values);
00069   while (link != NULL)
00070     {
00071       _dbus_string_free (link->data);
00072       dbus_free (link->data);
00073       
00074       link = _dbus_list_get_next_link (&entry->values, link);
00075     }
00076   _dbus_list_clear (&entry->values);
00077   
00078   dbus_free (entry);
00079 }
00080 
00094 void
00095 dbus_address_entries_free (DBusAddressEntry **entries)
00096 {
00097   int i;
00098   
00099   for (i = 0; entries[i] != NULL; i++)
00100     dbus_address_entry_free (entries[i]);
00101   dbus_free (entries);
00102 }
00103 
00104 static DBusAddressEntry *
00105 create_entry (void)
00106 {
00107   DBusAddressEntry *entry;
00108 
00109   entry = dbus_new0 (DBusAddressEntry, 1);
00110 
00111   if (entry == NULL)
00112     return NULL;
00113 
00114   if (!_dbus_string_init (&entry->method))
00115     {
00116       dbus_free (entry);
00117       return NULL;
00118     }
00119 
00120   return entry;
00121 }
00122 
00130 const char *
00131 dbus_address_entry_get_method (DBusAddressEntry *entry)
00132 {
00133   return _dbus_string_get_const_data (&entry->method);
00134 }
00135 
00143 const char *
00144 dbus_address_entry_get_value (DBusAddressEntry *entry,
00145                               const char       *key)
00146 {
00147   DBusList *values, *keys;
00148 
00149   keys = _dbus_list_get_first_link (&entry->keys);
00150   values = _dbus_list_get_first_link (&entry->values);
00151 
00152   while (keys != NULL)
00153     {
00154       _dbus_assert (values != NULL);
00155 
00156       if (_dbus_string_equal_c_str (keys->data, key))
00157         return _dbus_string_get_const_data (values->data);
00158 
00159       keys = _dbus_list_get_next_link (&entry->keys, keys);
00160       values = _dbus_list_get_next_link (&entry->values, values);
00161     }
00162   
00163   return NULL;
00164 }
00165 
00182 dbus_bool_t
00183 dbus_parse_address (const char         *address,
00184                     DBusAddressEntry ***entry,
00185                     int                *array_len,
00186                     DBusError          *error)
00187 {
00188   DBusString str;
00189   int pos, end_pos, len, i;
00190   DBusList *entries, *link;
00191   DBusAddressEntry **entry_array;
00192 
00193   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00194   
00195   _dbus_string_init_const (&str, address);
00196 
00197   entries = NULL;
00198   pos = 0;
00199   len = _dbus_string_get_length (&str);
00200   
00201   while (pos < len)
00202     {
00203       DBusAddressEntry *entry;
00204 
00205       int found_pos;
00206 
00207       entry = create_entry ();
00208       if (!entry)
00209         {
00210           dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00211 
00212           goto error;
00213         }
00214       
00215       /* Append the entry */
00216       if (!_dbus_list_append (&entries, entry))
00217         {
00218           dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00219           dbus_address_entry_free (entry);
00220           goto error;
00221         }
00222       
00223       /* Look for a semi-colon */
00224       if (!_dbus_string_find (&str, pos, ";", &end_pos))
00225         end_pos = len;
00226       
00227       /* Look for the colon : */
00228       if (!_dbus_string_find_to (&str, pos, end_pos, ":", &found_pos))
00229         {
00230           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, "Address does not contain a colon");
00231           goto error;
00232         }
00233 
00234       if (!_dbus_string_copy_len (&str, pos, found_pos - pos, &entry->method, 0))
00235         {
00236           dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00237           goto error;
00238         }
00239           
00240       pos = found_pos + 1;
00241 
00242       while (pos < end_pos)
00243         {
00244           int comma_pos, equals_pos;
00245 
00246           if (!_dbus_string_find_to (&str, pos, end_pos, ",", &comma_pos))
00247             comma_pos = end_pos;
00248           
00249           if (!_dbus_string_find_to (&str, pos, comma_pos, "=", &equals_pos) ||
00250               equals_pos == pos || equals_pos + 1 == comma_pos)
00251             {
00252               dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00253                               "'=' character not found or has no value following it");
00254               goto error;
00255             }
00256           else
00257             {
00258               DBusString *key;
00259               DBusString *value;
00260 
00261               key = dbus_new0 (DBusString, 1);
00262 
00263               if (!key)
00264                 {
00265                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);             
00266                   goto error;
00267                 }
00268 
00269               value = dbus_new0 (DBusString, 1);
00270               if (!value)
00271                 {
00272                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00273                   dbus_free (key);
00274                   goto error;
00275                 }
00276               
00277               if (!_dbus_string_init (key))
00278                 {
00279                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00280                   dbus_free (key);
00281                   dbus_free (value);
00282                   
00283                   goto error;
00284                 }
00285               
00286               if (!_dbus_string_init (value))
00287                 {
00288                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00289                   _dbus_string_free (key);
00290 
00291                   dbus_free (key);
00292                   dbus_free (value);              
00293                   goto error;
00294                 }
00295 
00296               if (!_dbus_string_copy_len (&str, pos, equals_pos - pos, key, 0))
00297                 {
00298                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00299                   _dbus_string_free (key);
00300                   _dbus_string_free (value);
00301 
00302                   dbus_free (key);
00303                   dbus_free (value);              
00304                   goto error;
00305                 }
00306 
00307               if (!_dbus_string_copy_len (&str, equals_pos + 1, comma_pos - equals_pos - 1, value, 0))
00308                 {
00309                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);             
00310                   _dbus_string_free (key);
00311                   _dbus_string_free (value);
00312 
00313                   dbus_free (key);
00314                   dbus_free (value);              
00315                   goto error;
00316                 }
00317 
00318               if (!_dbus_list_append (&entry->keys, key))
00319                 {
00320                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);             
00321                   _dbus_string_free (key);
00322                   _dbus_string_free (value);
00323 
00324                   dbus_free (key);
00325                   dbus_free (value);              
00326                   goto error;
00327                 }
00328 
00329               if (!_dbus_list_append (&entry->values, value))
00330                 {
00331                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);             
00332                   _dbus_string_free (value);
00333 
00334                   dbus_free (value);
00335                   goto error;             
00336                 }
00337             }
00338 
00339           pos = comma_pos + 1;
00340         }
00341 
00342       pos = end_pos + 1;
00343     }
00344 
00345   *array_len = _dbus_list_get_length (&entries);
00346   
00347   entry_array = dbus_new (DBusAddressEntry *, *array_len + 1);
00348 
00349   if (!entry_array)
00350     {
00351       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00352       
00353       goto error;
00354     }
00355   
00356   entry_array [*array_len] = NULL;
00357 
00358   link = _dbus_list_get_first_link (&entries);
00359   i = 0;
00360   while (link != NULL)
00361     {
00362       entry_array[i] = link->data;
00363       i++;
00364       link = _dbus_list_get_next_link (&entries, link);
00365     }
00366 
00367   _dbus_list_clear (&entries);
00368   *entry = entry_array;
00369 
00370   return TRUE;
00371 
00372  error:
00373   
00374   link = _dbus_list_get_first_link (&entries);
00375   while (link != NULL)
00376     {
00377       dbus_address_entry_free (link->data);
00378       link = _dbus_list_get_next_link (&entries, link);
00379     }
00380 
00381   _dbus_list_clear (&entries);
00382   
00383   return FALSE;
00384   
00385 }
00386 
00387  /* End of public API */
00389 
00390 #ifdef DBUS_BUILD_TESTS
00391 #include "dbus-test.h"
00392 
00393 dbus_bool_t
00394 _dbus_address_test (void)
00395 {
00396   DBusAddressEntry **entries;
00397   int len;  
00398   DBusError error;
00399 
00400   dbus_error_init (&error);
00401   
00402   if (!dbus_parse_address ("unix:path=/tmp/foo;debug:name=test,sliff=sloff;",
00403                            &entries, &len, &error))
00404     _dbus_assert_not_reached ("could not parse address");
00405   _dbus_assert (len == 2);
00406   _dbus_assert (strcmp (dbus_address_entry_get_value (entries[0], "path"), "/tmp/foo") == 0);
00407   _dbus_assert (strcmp (dbus_address_entry_get_value (entries[1], "name"), "test") == 0);
00408   _dbus_assert (strcmp (dbus_address_entry_get_value (entries[1], "sliff"), "sloff") == 0);
00409   
00410   dbus_address_entries_free (entries);
00411 
00412   /* Different possible errors */
00413   if (dbus_parse_address ("foo", &entries, &len, &error))
00414     _dbus_assert_not_reached ("Parsed incorrect address.");
00415   else
00416     dbus_error_free (&error);
00417   
00418   if (dbus_parse_address ("foo:bar", &entries, &len, &error))
00419     _dbus_assert_not_reached ("Parsed incorrect address.");
00420   else
00421     dbus_error_free (&error);
00422   
00423   if (dbus_parse_address ("foo:bar,baz", &entries, &len, &error))
00424     _dbus_assert_not_reached ("Parsed incorrect address.");
00425   else
00426     dbus_error_free (&error);
00427   
00428   if (dbus_parse_address ("foo:bar=foo,baz", &entries, &len, &error))
00429     _dbus_assert_not_reached ("Parsed incorrect address.");
00430   else
00431     dbus_error_free (&error);
00432   
00433   if (dbus_parse_address ("foo:bar=foo;baz", &entries, &len, &error))
00434     _dbus_assert_not_reached ("Parsed incorrect address.");
00435   else
00436     dbus_error_free (&error);
00437   
00438   if (dbus_parse_address ("foo:=foo", &entries, &len, &error))
00439     _dbus_assert_not_reached ("Parsed incorrect address.");
00440   else
00441     dbus_error_free (&error);
00442   
00443   if (dbus_parse_address ("foo:foo=", &entries, &len, &error))
00444     _dbus_assert_not_reached ("Parsed incorrect address.");
00445   else
00446     dbus_error_free (&error);
00447 
00448   if (dbus_parse_address ("foo:foo,bar=baz", &entries, &len, &error))
00449     _dbus_assert_not_reached ("Parsed incorrect address.");
00450   else
00451     dbus_error_free (&error);
00452 
00453   return TRUE;
00454 }
00455 
00456 #endif

Generated on Sun Mar 21 03:52:03 2004 for D-BUS by doxygen 1.3.6-20040222