Home | History | Annotate | Download | only in bus
      1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
      2 /* signals.c  Bus signal connection implementation
      3  *
      4  * Copyright (C) 2003, 2005  Red Hat, Inc.
      5  *
      6  * Licensed under the Academic Free License version 2.1
      7  *
      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.
     12  *
     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.
     17  *
     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
     21  *
     22  */
     23 
     24 #include <config.h>
     25 #include "signals.h"
     26 #include "services.h"
     27 #include "utils.h"
     28 #include <dbus/dbus-marshal-validate.h>
     29 
     30 struct BusMatchRule
     31 {
     32   int refcount;       /**< reference count */
     33 
     34   DBusConnection *matches_go_to; /**< Owner of the rule */
     35 
     36   unsigned int flags; /**< BusMatchFlags */
     37 
     38   int   message_type;
     39   char *interface;
     40   char *member;
     41   char *sender;
     42   char *destination;
     43   char *path;
     44 
     45   unsigned int *arg_lens;
     46   char **args;
     47   int args_len;
     48 };
     49 
     50 #define BUS_MATCH_ARG_NAMESPACE   0x4000000u
     51 #define BUS_MATCH_ARG_IS_PATH  0x8000000u
     52 
     53 #define BUS_MATCH_ARG_FLAGS (BUS_MATCH_ARG_NAMESPACE | BUS_MATCH_ARG_IS_PATH)
     54 
     55 BusMatchRule*
     56 bus_match_rule_new (DBusConnection *matches_go_to)
     57 {
     58   BusMatchRule *rule;
     59 
     60   rule = dbus_new0 (BusMatchRule, 1);
     61   if (rule == NULL)
     62     return NULL;
     63 
     64   rule->refcount = 1;
     65   rule->matches_go_to = matches_go_to;
     66 
     67 #ifndef DBUS_BUILD_TESTS
     68   _dbus_assert (rule->matches_go_to != NULL);
     69 #endif
     70 
     71   return rule;
     72 }
     73 
     74 BusMatchRule *
     75 bus_match_rule_ref (BusMatchRule *rule)
     76 {
     77   _dbus_assert (rule->refcount > 0);
     78 
     79   rule->refcount += 1;
     80 
     81   return rule;
     82 }
     83 
     84 void
     85 bus_match_rule_unref (BusMatchRule *rule)
     86 {
     87   _dbus_assert (rule->refcount > 0);
     88 
     89   rule->refcount -= 1;
     90   if (rule->refcount == 0)
     91     {
     92       dbus_free (rule->interface);
     93       dbus_free (rule->member);
     94       dbus_free (rule->sender);
     95       dbus_free (rule->destination);
     96       dbus_free (rule->path);
     97       dbus_free (rule->arg_lens);
     98 
     99       /* can't use dbus_free_string_array() since there
    100        * are embedded NULL
    101        */
    102       if (rule->args)
    103         {
    104           int i;
    105 
    106           i = 0;
    107           while (i < rule->args_len)
    108             {
    109               if (rule->args[i])
    110                 dbus_free (rule->args[i]);
    111               ++i;
    112             }
    113 
    114           dbus_free (rule->args);
    115         }
    116 
    117       dbus_free (rule);
    118     }
    119 }
    120 
    121 #ifdef DBUS_ENABLE_VERBOSE_MODE
    122 /* Note this function does not do escaping, so it's only
    123  * good for debug spew at the moment
    124  */
    125 static char*
    126 match_rule_to_string (BusMatchRule *rule)
    127 {
    128   DBusString str;
    129   char *ret;
    130 
    131   if (!_dbus_string_init (&str))
    132     {
    133       char *s;
    134       while ((s = _dbus_strdup ("nomem")) == NULL)
    135         ; /* only OK for debug spew... */
    136       return s;
    137     }
    138 
    139   if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
    140     {
    141       if (!_dbus_string_append_printf (&str, "type='%s'",
    142             dbus_message_type_to_string (rule->message_type)))
    143         goto nomem;
    144     }
    145 
    146   if (rule->flags & BUS_MATCH_INTERFACE)
    147     {
    148       if (_dbus_string_get_length (&str) > 0)
    149         {
    150           if (!_dbus_string_append (&str, ","))
    151             goto nomem;
    152         }
    153 
    154       if (!_dbus_string_append_printf (&str, "interface='%s'", rule->interface))
    155         goto nomem;
    156     }
    157 
    158   if (rule->flags & BUS_MATCH_MEMBER)
    159     {
    160       if (_dbus_string_get_length (&str) > 0)
    161         {
    162           if (!_dbus_string_append (&str, ","))
    163             goto nomem;
    164         }
    165 
    166       if (!_dbus_string_append_printf (&str, "member='%s'", rule->member))
    167         goto nomem;
    168     }
    169 
    170   if (rule->flags & BUS_MATCH_PATH)
    171     {
    172       if (_dbus_string_get_length (&str) > 0)
    173         {
    174           if (!_dbus_string_append (&str, ","))
    175             goto nomem;
    176         }
    177 
    178       if (!_dbus_string_append_printf (&str, "path='%s'", rule->path))
    179         goto nomem;
    180     }
    181 
    182   if (rule->flags & BUS_MATCH_PATH_NAMESPACE)
    183     {
    184       if (_dbus_string_get_length (&str) > 0)
    185         {
    186           if (!_dbus_string_append (&str, ","))
    187             goto nomem;
    188         }
    189 
    190       if (!_dbus_string_append_printf (&str, "path_namespace='%s'", rule->path))
    191         goto nomem;
    192     }
    193 
    194   if (rule->flags & BUS_MATCH_SENDER)
    195     {
    196       if (_dbus_string_get_length (&str) > 0)
    197         {
    198           if (!_dbus_string_append (&str, ","))
    199             goto nomem;
    200         }
    201 
    202       if (!_dbus_string_append_printf (&str, "sender='%s'", rule->sender))
    203         goto nomem;
    204     }
    205 
    206   if (rule->flags & BUS_MATCH_DESTINATION)
    207     {
    208       if (_dbus_string_get_length (&str) > 0)
    209         {
    210           if (!_dbus_string_append (&str, ","))
    211             goto nomem;
    212         }
    213 
    214       if (!_dbus_string_append_printf (&str, "destination='%s'", rule->destination))
    215         goto nomem;
    216     }
    217 
    218   if (rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING)
    219     {
    220       if (_dbus_string_get_length (&str) > 0)
    221         {
    222           if (!_dbus_string_append (&str, ","))
    223             goto nomem;
    224         }
    225 
    226       if (!_dbus_string_append_printf (&str, "eavesdrop='%s'",
    227             (rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING) ?
    228             "true" : "false"))
    229         goto nomem;
    230     }
    231 
    232   if (rule->flags & BUS_MATCH_ARGS)
    233     {
    234       int i;
    235 
    236       _dbus_assert (rule->args != NULL);
    237 
    238       i = 0;
    239       while (i < rule->args_len)
    240         {
    241           if (rule->args[i] != NULL)
    242             {
    243               dbus_bool_t is_path, is_namespace;
    244 
    245               if (_dbus_string_get_length (&str) > 0)
    246                 {
    247                   if (!_dbus_string_append (&str, ","))
    248                     goto nomem;
    249                 }
    250 
    251               is_path = (rule->arg_lens[i] & BUS_MATCH_ARG_IS_PATH) != 0;
    252               is_namespace = (rule->arg_lens[i] & BUS_MATCH_ARG_NAMESPACE) != 0;
    253 
    254               if (!_dbus_string_append_printf (&str,
    255                                                "arg%d%s='%s'",
    256                                                i,
    257                                                is_path ? "path" :
    258                                                is_namespace ? "namespace" : "",
    259                                                rule->args[i]))
    260                 goto nomem;
    261             }
    262 
    263           ++i;
    264         }
    265     }
    266 
    267   if (!_dbus_string_steal_data (&str, &ret))
    268     goto nomem;
    269 
    270   _dbus_string_free (&str);
    271   return ret;
    272 
    273  nomem:
    274   _dbus_string_free (&str);
    275   {
    276     char *s;
    277     while ((s = _dbus_strdup ("nomem")) == NULL)
    278       ;  /* only OK for debug spew... */
    279     return s;
    280   }
    281 }
    282 #endif /* DBUS_ENABLE_VERBOSE_MODE */
    283 
    284 dbus_bool_t
    285 bus_match_rule_set_message_type (BusMatchRule *rule,
    286                                  int           type)
    287 {
    288   rule->flags |= BUS_MATCH_MESSAGE_TYPE;
    289 
    290   rule->message_type = type;
    291 
    292   return TRUE;
    293 }
    294 
    295 dbus_bool_t
    296 bus_match_rule_set_interface (BusMatchRule *rule,
    297                               const char   *interface)
    298 {
    299   char *new;
    300 
    301   _dbus_assert (interface != NULL);
    302 
    303   new = _dbus_strdup (interface);
    304   if (new == NULL)
    305     return FALSE;
    306 
    307   rule->flags |= BUS_MATCH_INTERFACE;
    308   dbus_free (rule->interface);
    309   rule->interface = new;
    310 
    311   return TRUE;
    312 }
    313 
    314 dbus_bool_t
    315 bus_match_rule_set_member (BusMatchRule *rule,
    316                            const char   *member)
    317 {
    318   char *new;
    319 
    320   _dbus_assert (member != NULL);
    321 
    322   new = _dbus_strdup (member);
    323   if (new == NULL)
    324     return FALSE;
    325 
    326   rule->flags |= BUS_MATCH_MEMBER;
    327   dbus_free (rule->member);
    328   rule->member = new;
    329 
    330   return TRUE;
    331 }
    332 
    333 dbus_bool_t
    334 bus_match_rule_set_sender (BusMatchRule *rule,
    335                            const char   *sender)
    336 {
    337   char *new;
    338 
    339   _dbus_assert (sender != NULL);
    340 
    341   new = _dbus_strdup (sender);
    342   if (new == NULL)
    343     return FALSE;
    344 
    345   rule->flags |= BUS_MATCH_SENDER;
    346   dbus_free (rule->sender);
    347   rule->sender = new;
    348 
    349   return TRUE;
    350 }
    351 
    352 dbus_bool_t
    353 bus_match_rule_set_destination (BusMatchRule *rule,
    354                                 const char   *destination)
    355 {
    356   char *new;
    357 
    358   _dbus_assert (destination != NULL);
    359 
    360   new = _dbus_strdup (destination);
    361   if (new == NULL)
    362     return FALSE;
    363 
    364   rule->flags |= BUS_MATCH_DESTINATION;
    365   dbus_free (rule->destination);
    366   rule->destination = new;
    367 
    368   return TRUE;
    369 }
    370 
    371 void
    372 bus_match_rule_set_client_is_eavesdropping (BusMatchRule *rule,
    373                                             dbus_bool_t is_eavesdropping)
    374 {
    375   if (is_eavesdropping)
    376     rule->flags |= BUS_MATCH_CLIENT_IS_EAVESDROPPING;
    377   else
    378     rule->flags &= ~(BUS_MATCH_CLIENT_IS_EAVESDROPPING);
    379 }
    380 
    381 dbus_bool_t
    382 bus_match_rule_set_path (BusMatchRule *rule,
    383                          const char   *path,
    384                          dbus_bool_t   is_namespace)
    385 {
    386   char *new;
    387 
    388   _dbus_assert (path != NULL);
    389 
    390   new = _dbus_strdup (path);
    391   if (new == NULL)
    392     return FALSE;
    393 
    394   rule->flags &= ~(BUS_MATCH_PATH|BUS_MATCH_PATH_NAMESPACE);
    395 
    396   if (is_namespace)
    397     rule->flags |= BUS_MATCH_PATH_NAMESPACE;
    398   else
    399     rule->flags |= BUS_MATCH_PATH;
    400 
    401   dbus_free (rule->path);
    402   rule->path = new;
    403 
    404   return TRUE;
    405 }
    406 
    407 dbus_bool_t
    408 bus_match_rule_set_arg (BusMatchRule     *rule,
    409                         int                arg,
    410                         const DBusString *value,
    411                         dbus_bool_t       is_path,
    412                         dbus_bool_t       is_namespace)
    413 {
    414   int length;
    415   char *new;
    416 
    417   _dbus_assert (value != NULL);
    418 
    419   /* args_len is the number of args not including null termination
    420    * in the char**
    421    */
    422   if (arg >= rule->args_len)
    423     {
    424       unsigned int *new_arg_lens;
    425       char **new_args;
    426       int new_args_len;
    427       int i;
    428 
    429       new_args_len = arg + 1;
    430 
    431       /* add another + 1 here for null termination */
    432       new_args = dbus_realloc (rule->args,
    433                                sizeof (char *) * (new_args_len + 1));
    434       if (new_args == NULL)
    435         return FALSE;
    436 
    437       /* NULL the new slots */
    438       i = rule->args_len;
    439       while (i <= new_args_len) /* <= for null termination */
    440         {
    441           new_args[i] = NULL;
    442           ++i;
    443         }
    444 
    445       rule->args = new_args;
    446 
    447       /* and now add to the lengths */
    448       new_arg_lens = dbus_realloc (rule->arg_lens,
    449                                    sizeof (int) * (new_args_len + 1));
    450 
    451       if (new_arg_lens == NULL)
    452         return FALSE;
    453 
    454       /* zero the new slots */
    455       i = rule->args_len;
    456       while (i <= new_args_len) /* <= for null termination */
    457         {
    458           new_arg_lens[i] = 0;
    459           ++i;
    460         }
    461 
    462       rule->arg_lens = new_arg_lens;
    463       rule->args_len = new_args_len;
    464     }
    465 
    466   length = _dbus_string_get_length (value);
    467   if (!_dbus_string_copy_data (value, &new))
    468     return FALSE;
    469 
    470   rule->flags |= BUS_MATCH_ARGS;
    471 
    472   dbus_free (rule->args[arg]);
    473   rule->arg_lens[arg] = length;
    474   rule->args[arg] = new;
    475 
    476   if (is_path)
    477     rule->arg_lens[arg] |= BUS_MATCH_ARG_IS_PATH;
    478 
    479   if (is_namespace)
    480     rule->arg_lens[arg] |= BUS_MATCH_ARG_NAMESPACE;
    481 
    482   /* NULL termination didn't get busted */
    483   _dbus_assert (rule->args[rule->args_len] == NULL);
    484   _dbus_assert (rule->arg_lens[rule->args_len] == 0);
    485 
    486   return TRUE;
    487 }
    488 
    489 #define ISWHITE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r'))
    490 
    491 static dbus_bool_t
    492 find_key (const DBusString *str,
    493           int               start,
    494           DBusString       *key,
    495           int              *value_pos,
    496           DBusError        *error)
    497 {
    498   const char *p;
    499   const char *s;
    500   const char *key_start;
    501   const char *key_end;
    502 
    503   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
    504 
    505   s = _dbus_string_get_const_data (str);
    506 
    507   p = s + start;
    508 
    509   while (*p && ISWHITE (*p))
    510     ++p;
    511 
    512   key_start = p;
    513 
    514   while (*p && *p != '=' && !ISWHITE (*p))
    515     ++p;
    516 
    517   key_end = p;
    518 
    519   while (*p && ISWHITE (*p))
    520     ++p;
    521 
    522   if (key_start == key_end)
    523     {
    524       /* Empty match rules or trailing whitespace are OK */
    525       *value_pos = p - s;
    526       return TRUE;
    527     }
    528 
    529   if (*p != '=')
    530     {
    531       dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    532                       "Match rule has a key with no subsequent '=' character");
    533       return FALSE;
    534     }
    535   ++p;
    536 
    537   if (!_dbus_string_append_len (key, key_start, key_end - key_start))
    538     {
    539       BUS_SET_OOM (error);
    540       return FALSE;
    541     }
    542 
    543   *value_pos = p - s;
    544 
    545   return TRUE;
    546 }
    547 
    548 static dbus_bool_t
    549 find_value (const DBusString *str,
    550             int               start,
    551             const char       *key,
    552             DBusString       *value,
    553             int              *value_end,
    554             DBusError        *error)
    555 {
    556   const char *p;
    557   const char *s;
    558   char quote_char;
    559   int orig_len;
    560 
    561   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
    562 
    563   orig_len = _dbus_string_get_length (value);
    564 
    565   s = _dbus_string_get_const_data (str);
    566 
    567   p = s + start;
    568 
    569   quote_char = '\0';
    570 
    571   while (*p)
    572     {
    573       if (quote_char == '\0')
    574         {
    575           switch (*p)
    576             {
    577             case '\0':
    578               goto done;
    579 
    580             case '\'':
    581               quote_char = '\'';
    582               goto next;
    583 
    584             case ',':
    585               ++p;
    586               goto done;
    587 
    588             case '\\':
    589               quote_char = '\\';
    590               goto next;
    591 
    592             default:
    593               if (!_dbus_string_append_byte (value, *p))
    594                 {
    595                   BUS_SET_OOM (error);
    596                   goto failed;
    597                 }
    598             }
    599         }
    600       else if (quote_char == '\\')
    601         {
    602           /* \ only counts as an escape if escaping a quote mark */
    603           if (*p != '\'')
    604             {
    605               if (!_dbus_string_append_byte (value, '\\'))
    606                 {
    607                   BUS_SET_OOM (error);
    608                   goto failed;
    609                 }
    610             }
    611 
    612           if (!_dbus_string_append_byte (value, *p))
    613             {
    614               BUS_SET_OOM (error);
    615               goto failed;
    616             }
    617 
    618           quote_char = '\0';
    619         }
    620       else
    621         {
    622           _dbus_assert (quote_char == '\'');
    623 
    624           if (*p == '\'')
    625             {
    626               quote_char = '\0';
    627             }
    628           else
    629             {
    630               if (!_dbus_string_append_byte (value, *p))
    631                 {
    632                   BUS_SET_OOM (error);
    633                   goto failed;
    634                 }
    635             }
    636         }
    637 
    638     next:
    639       ++p;
    640     }
    641 
    642  done:
    643 
    644   if (quote_char == '\\')
    645     {
    646       if (!_dbus_string_append_byte (value, '\\'))
    647         {
    648           BUS_SET_OOM (error);
    649           goto failed;
    650         }
    651     }
    652   else if (quote_char == '\'')
    653     {
    654       dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    655                       "Unbalanced quotation marks in match rule");
    656       goto failed;
    657     }
    658   else
    659     _dbus_assert (quote_char == '\0');
    660 
    661   /* Zero-length values are allowed */
    662 
    663   *value_end = p - s;
    664 
    665   return TRUE;
    666 
    667  failed:
    668   _DBUS_ASSERT_ERROR_IS_SET (error);
    669   _dbus_string_set_length (value, orig_len);
    670   return FALSE;
    671 }
    672 
    673 /* duplicates aren't allowed so the real legitimate max is only 6 or
    674  * so. Leaving extra so we don't have to bother to update it.
    675  * FIXME this is sort of busted now with arg matching, but we let
    676  * you match on up to 10 args for now
    677  */
    678 #define MAX_RULE_TOKENS 16
    679 
    680 /* this is slightly too high level to be termed a "token"
    681  * but let's not be pedantic.
    682  */
    683 typedef struct
    684 {
    685   char *key;
    686   char *value;
    687 } RuleToken;
    688 
    689 static dbus_bool_t
    690 tokenize_rule (const DBusString *rule_text,
    691                RuleToken         tokens[MAX_RULE_TOKENS],
    692                DBusError        *error)
    693 {
    694   int i;
    695   int pos;
    696   DBusString key;
    697   DBusString value;
    698   dbus_bool_t retval;
    699 
    700   retval = FALSE;
    701 
    702   if (!_dbus_string_init (&key))
    703     {
    704       BUS_SET_OOM (error);
    705       return FALSE;
    706     }
    707 
    708   if (!_dbus_string_init (&value))
    709     {
    710       _dbus_string_free (&key);
    711       BUS_SET_OOM (error);
    712       return FALSE;
    713     }
    714 
    715   i = 0;
    716   pos = 0;
    717   while (i < MAX_RULE_TOKENS &&
    718          pos < _dbus_string_get_length (rule_text))
    719     {
    720       _dbus_assert (tokens[i].key == NULL);
    721       _dbus_assert (tokens[i].value == NULL);
    722 
    723       if (!find_key (rule_text, pos, &key, &pos, error))
    724         goto out;
    725 
    726       if (_dbus_string_get_length (&key) == 0)
    727         goto next;
    728 
    729       if (!_dbus_string_steal_data (&key, &tokens[i].key))
    730         {
    731           BUS_SET_OOM (error);
    732           goto out;
    733         }
    734 
    735       if (!find_value (rule_text, pos, tokens[i].key, &value, &pos, error))
    736         goto out;
    737 
    738       if (!_dbus_string_steal_data (&value, &tokens[i].value))
    739         {
    740           BUS_SET_OOM (error);
    741           goto out;
    742         }
    743 
    744     next:
    745       ++i;
    746     }
    747 
    748   retval = TRUE;
    749 
    750  out:
    751   if (!retval)
    752     {
    753       i = 0;
    754       while (tokens[i].key || tokens[i].value)
    755         {
    756           dbus_free (tokens[i].key);
    757           dbus_free (tokens[i].value);
    758           tokens[i].key = NULL;
    759           tokens[i].value = NULL;
    760           ++i;
    761         }
    762     }
    763 
    764   _dbus_string_free (&key);
    765   _dbus_string_free (&value);
    766 
    767   return retval;
    768 }
    769 
    770 static dbus_bool_t
    771 bus_match_rule_parse_arg_match (BusMatchRule     *rule,
    772                                 const char       *key,
    773                                 const DBusString *value,
    774                                 DBusError        *error)
    775 {
    776   dbus_bool_t is_path = FALSE;
    777   dbus_bool_t is_namespace = FALSE;
    778   DBusString key_str;
    779   unsigned long arg;
    780   int length;
    781   int end;
    782 
    783   /* For now, arg0='foo' always implies that 'foo' is a
    784    * DBUS_TYPE_STRING. Someday we could add an arg0type='int32' thing
    785    * if we wanted, which would specify another type, in which case
    786    * arg0='5' would have the 5 parsed as an int rather than string.
    787    */
    788 
    789   /* First we need to parse arg0 = 0, arg27 = 27 */
    790 
    791   _dbus_string_init_const (&key_str, key);
    792   length = _dbus_string_get_length (&key_str);
    793 
    794   if (_dbus_string_get_length (&key_str) < 4)
    795     {
    796       dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    797                       "Key '%s' in match rule starts with 'arg' but lacks an arg number. Should be 'arg0' or 'arg7' for example.\n", key);
    798       goto failed;
    799     }
    800 
    801   if (!_dbus_string_parse_uint (&key_str, 3, &arg, &end))
    802     {
    803       dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    804                       "Key '%s' in match rule starts with 'arg' but could not parse arg number. Should be 'arg0' or 'arg7' for example.\n", key);
    805       goto failed;
    806     }
    807 
    808   if (end != length)
    809     {
    810       if ((end + strlen ("path")) == length &&
    811           _dbus_string_ends_with_c_str (&key_str, "path"))
    812         {
    813           is_path = TRUE;
    814         }
    815       else if (_dbus_string_equal_c_str (&key_str, "arg0namespace"))
    816         {
    817           int value_len = _dbus_string_get_length (value);
    818 
    819           is_namespace = TRUE;
    820 
    821           if (!_dbus_validate_bus_namespace (value, 0, value_len))
    822             {
    823               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    824                   "arg0namespace='%s' is not a valid prefix of a bus name",
    825                   _dbus_string_get_const_data (value));
    826               goto failed;
    827             }
    828         }
    829       else
    830         {
    831           dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    832               "Key '%s' in match rule contains junk after argument number (%u). Only 'arg%upath' (for example) or 'arg0namespace' are valid", key, arg, arg);
    833           goto failed;
    834         }
    835     }
    836 
    837   /* If we didn't check this we could allocate a huge amount of RAM */
    838   if (arg > DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER)
    839     {
    840       dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    841                       "Key '%s' in match rule has arg number %lu but the maximum is %d.\n", key, (unsigned long) arg, DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER);
    842       goto failed;
    843     }
    844 
    845   if ((rule->flags & BUS_MATCH_ARGS) &&
    846       rule->args_len > (int) arg &&
    847       rule->args[arg] != NULL)
    848     {
    849       dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    850                       "Argument %d matched more than once in match rule\n", key);
    851       goto failed;
    852     }
    853 
    854   if (!bus_match_rule_set_arg (rule, arg, value, is_path, is_namespace))
    855     {
    856       BUS_SET_OOM (error);
    857       goto failed;
    858     }
    859 
    860   return TRUE;
    861 
    862  failed:
    863   _DBUS_ASSERT_ERROR_IS_SET (error);
    864   return FALSE;
    865 }
    866 
    867 /*
    868  * The format is comma-separated with strings quoted with single quotes
    869  * as for the shell (to escape a literal single quote, use '\'').
    870  *
    871  * type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='Foo',
    872  * path='/bar/foo',destination=':452345.34'
    873  *
    874  */
    875 BusMatchRule*
    876 bus_match_rule_parse (DBusConnection   *matches_go_to,
    877                       const DBusString *rule_text,
    878                       DBusError        *error)
    879 {
    880   BusMatchRule *rule;
    881   RuleToken tokens[MAX_RULE_TOKENS+1]; /* NULL termination + 1 */
    882   int i;
    883 
    884   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
    885 
    886   if (_dbus_string_get_length (rule_text) > DBUS_MAXIMUM_MATCH_RULE_LENGTH)
    887     {
    888       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
    889                       "Match rule text is %d bytes, maximum is %d",
    890                       _dbus_string_get_length (rule_text),
    891                       DBUS_MAXIMUM_MATCH_RULE_LENGTH);
    892       return NULL;
    893     }
    894 
    895   memset (tokens, '\0', sizeof (tokens));
    896 
    897   rule = bus_match_rule_new (matches_go_to);
    898   if (rule == NULL)
    899     {
    900       BUS_SET_OOM (error);
    901       goto failed;
    902     }
    903 
    904   if (!tokenize_rule (rule_text, tokens, error))
    905     goto failed;
    906 
    907   i = 0;
    908   while (tokens[i].key != NULL)
    909     {
    910       DBusString tmp_str;
    911       int len;
    912       const char *key = tokens[i].key;
    913       const char *value = tokens[i].value;
    914 
    915       _dbus_string_init_const (&tmp_str, value);
    916       len = _dbus_string_get_length (&tmp_str);
    917 
    918       if (strcmp (key, "type") == 0)
    919         {
    920           int t;
    921 
    922           if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
    923             {
    924               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    925                               "Key %s specified twice in match rule\n", key);
    926               goto failed;
    927             }
    928 
    929           t = dbus_message_type_from_string (value);
    930 
    931           if (t == DBUS_MESSAGE_TYPE_INVALID)
    932             {
    933               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    934                               "Invalid message type (%s) in match rule\n", value);
    935               goto failed;
    936             }
    937 
    938           if (!bus_match_rule_set_message_type (rule, t))
    939             {
    940               BUS_SET_OOM (error);
    941               goto failed;
    942             }
    943         }
    944       else if (strcmp (key, "sender") == 0)
    945         {
    946           if (rule->flags & BUS_MATCH_SENDER)
    947             {
    948               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    949                               "Key %s specified twice in match rule\n", key);
    950               goto failed;
    951             }
    952 
    953           if (!_dbus_validate_bus_name (&tmp_str, 0, len))
    954             {
    955               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    956                               "Sender name '%s' is invalid\n", value);
    957               goto failed;
    958             }
    959 
    960           if (!bus_match_rule_set_sender (rule, value))
    961             {
    962               BUS_SET_OOM (error);
    963               goto failed;
    964             }
    965         }
    966       else if (strcmp (key, "interface") == 0)
    967         {
    968           if (rule->flags & BUS_MATCH_INTERFACE)
    969             {
    970               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    971                               "Key %s specified twice in match rule\n", key);
    972               goto failed;
    973             }
    974 
    975           if (!_dbus_validate_interface (&tmp_str, 0, len))
    976             {
    977               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    978                               "Interface name '%s' is invalid\n", value);
    979               goto failed;
    980             }
    981 
    982           if (!bus_match_rule_set_interface (rule, value))
    983             {
    984               BUS_SET_OOM (error);
    985               goto failed;
    986             }
    987         }
    988       else if (strcmp (key, "member") == 0)
    989         {
    990           if (rule->flags & BUS_MATCH_MEMBER)
    991             {
    992               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
    993                               "Key %s specified twice in match rule\n", key);
    994               goto failed;
    995             }
    996 
    997           if (!_dbus_validate_member (&tmp_str, 0, len))
    998             {
    999               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
   1000                               "Member name '%s' is invalid\n", value);
   1001               goto failed;
   1002             }
   1003 
   1004           if (!bus_match_rule_set_member (rule, value))
   1005             {
   1006               BUS_SET_OOM (error);
   1007               goto failed;
   1008             }
   1009         }
   1010       else if (strcmp (key, "path") == 0 ||
   1011           strcmp (key, "path_namespace") == 0)
   1012         {
   1013           dbus_bool_t is_namespace = (strcmp (key, "path_namespace") == 0);
   1014 
   1015           if (rule->flags & (BUS_MATCH_PATH | BUS_MATCH_PATH_NAMESPACE))
   1016             {
   1017               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
   1018                               "path or path_namespace specified twice in match rule\n");
   1019               goto failed;
   1020             }
   1021 
   1022           if (!_dbus_validate_path (&tmp_str, 0, len))
   1023             {
   1024               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
   1025                               "Path '%s' is invalid\n", value);
   1026               goto failed;
   1027             }
   1028 
   1029           if (!bus_match_rule_set_path (rule, value, is_namespace))
   1030             {
   1031               BUS_SET_OOM (error);
   1032               goto failed;
   1033             }
   1034         }
   1035       else if (strcmp (key, "destination") == 0)
   1036         {
   1037           if (rule->flags & BUS_MATCH_DESTINATION)
   1038             {
   1039               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
   1040                               "Key %s specified twice in match rule\n", key);
   1041               goto failed;
   1042             }
   1043 
   1044           if (!_dbus_validate_bus_name (&tmp_str, 0, len))
   1045             {
   1046               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
   1047                               "Destination name '%s' is invalid\n", value);
   1048               goto failed;
   1049             }
   1050 
   1051           if (!bus_match_rule_set_destination (rule, value))
   1052             {
   1053               BUS_SET_OOM (error);
   1054               goto failed;
   1055             }
   1056         }
   1057       else if (strcmp (key, "eavesdrop") == 0)
   1058         {
   1059           /* do not detect "eavesdrop" being used more than once in rule:
   1060            * 1) it's not possible, it's only in the flags
   1061            * 2) it might be used twice to disable eavesdropping when it's
   1062            * automatically added (eg dbus-monitor/bustle) */
   1063 
   1064           /* we accept only "true|false" as possible values */
   1065           if ((strcmp (value, "true") == 0))
   1066             {
   1067               bus_match_rule_set_client_is_eavesdropping (rule, TRUE);
   1068             }
   1069           else if (strcmp (value, "false") == 0)
   1070             {
   1071               bus_match_rule_set_client_is_eavesdropping (rule, FALSE);
   1072             }
   1073           else
   1074             {
   1075               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
   1076                               "eavesdrop='%s' is invalid, "
   1077                               "it should be 'true' or 'false'\n",
   1078                               value);
   1079               goto failed;
   1080             }
   1081         }
   1082       else if (strncmp (key, "arg", 3) == 0)
   1083         {
   1084           if (!bus_match_rule_parse_arg_match (rule, key, &tmp_str, error))
   1085             goto failed;
   1086         }
   1087       else
   1088         {
   1089           dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
   1090                           "Unknown key \"%s\" in match rule",
   1091                           key);
   1092           goto failed;
   1093         }
   1094 
   1095       ++i;
   1096     }
   1097 
   1098 
   1099   goto out;
   1100 
   1101  failed:
   1102   _DBUS_ASSERT_ERROR_IS_SET (error);
   1103   if (rule)
   1104     {
   1105       bus_match_rule_unref (rule);
   1106       rule = NULL;
   1107     }
   1108 
   1109  out:
   1110 
   1111   i = 0;
   1112   while (tokens[i].key || tokens[i].value)
   1113     {
   1114       _dbus_assert (i < MAX_RULE_TOKENS);
   1115       dbus_free (tokens[i].key);
   1116       dbus_free (tokens[i].value);
   1117       ++i;
   1118     }
   1119 
   1120   return rule;
   1121 }
   1122 
   1123 typedef struct RulePool RulePool;
   1124 struct RulePool
   1125 {
   1126   /* Maps non-NULL interface names to non-NULL (DBusList **)s */
   1127   DBusHashTable *rules_by_iface;
   1128 
   1129   /* List of BusMatchRules which don't specify an interface */
   1130   DBusList *rules_without_iface;
   1131 };
   1132 
   1133 struct BusMatchmaker
   1134 {
   1135   int refcount;
   1136 
   1137   /* Pools of rules, grouped by the type of message they match. 0
   1138    * (DBUS_MESSAGE_TYPE_INVALID) represents rules that do not specify a message
   1139    * type.
   1140    */
   1141   RulePool rules_by_type[DBUS_NUM_MESSAGE_TYPES];
   1142 };
   1143 
   1144 static void
   1145 rule_list_free (DBusList **rules)
   1146 {
   1147   while (*rules != NULL)
   1148     {
   1149       BusMatchRule *rule;
   1150 
   1151       rule = (*rules)->data;
   1152       bus_match_rule_unref (rule);
   1153       _dbus_list_remove_link (rules, *rules);
   1154     }
   1155 }
   1156 
   1157 static void
   1158 rule_list_ptr_free (DBusList **list)
   1159 {
   1160   /* We have to cope with NULL because the hash table frees the "existing"
   1161    * value (which is NULL) when creating a new table entry...
   1162    */
   1163   if (list != NULL)
   1164     {
   1165       rule_list_free (list);
   1166       dbus_free (list);
   1167     }
   1168 }
   1169 
   1170 BusMatchmaker*
   1171 bus_matchmaker_new (void)
   1172 {
   1173   BusMatchmaker *matchmaker;
   1174   int i;
   1175 
   1176   matchmaker = dbus_new0 (BusMatchmaker, 1);
   1177   if (matchmaker == NULL)
   1178     return NULL;
   1179 
   1180   matchmaker->refcount = 1;
   1181 
   1182   for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
   1183     {
   1184       RulePool *p = matchmaker->rules_by_type + i;
   1185 
   1186       p->rules_by_iface = _dbus_hash_table_new (DBUS_HASH_STRING,
   1187           dbus_free, (DBusFreeFunction) rule_list_ptr_free);
   1188 
   1189       if (p->rules_by_iface == NULL)
   1190         goto nomem;
   1191     }
   1192 
   1193   return matchmaker;
   1194 
   1195  nomem:
   1196   for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
   1197     {
   1198       RulePool *p = matchmaker->rules_by_type + i;
   1199 
   1200       if (p->rules_by_iface == NULL)
   1201         break;
   1202       else
   1203         _dbus_hash_table_unref (p->rules_by_iface);
   1204     }
   1205   dbus_free (matchmaker);
   1206 
   1207   return NULL;
   1208 }
   1209 
   1210 static DBusList **
   1211 bus_matchmaker_get_rules (BusMatchmaker *matchmaker,
   1212                           int            message_type,
   1213                           const char    *interface,
   1214                           dbus_bool_t    create)
   1215 {
   1216   RulePool *p;
   1217 
   1218   _dbus_assert (message_type >= 0);
   1219   _dbus_assert (message_type < DBUS_NUM_MESSAGE_TYPES);
   1220 
   1221   _dbus_verbose ("Looking up rules for message_type %d, interface %s\n",
   1222                  message_type,
   1223                  interface != NULL ? interface : "<null>");
   1224 
   1225   p = matchmaker->rules_by_type + message_type;
   1226 
   1227   if (interface == NULL)
   1228     {
   1229       return &p->rules_without_iface;
   1230     }
   1231   else
   1232     {
   1233       DBusList **list;
   1234 
   1235       list = _dbus_hash_table_lookup_string (p->rules_by_iface, interface);
   1236 
   1237       if (list == NULL && create)
   1238         {
   1239           char *dupped_interface;
   1240 
   1241           list = dbus_new0 (DBusList *, 1);
   1242           if (list == NULL)
   1243             return NULL;
   1244 
   1245           dupped_interface = _dbus_strdup (interface);
   1246           if (dupped_interface == NULL)
   1247             {
   1248               dbus_free (list);
   1249               return NULL;
   1250             }
   1251 
   1252           _dbus_verbose ("Adding list for type %d, iface %s\n", message_type,
   1253                          interface);
   1254 
   1255           if (!_dbus_hash_table_insert_string (p->rules_by_iface,
   1256                                                dupped_interface, list))
   1257             {
   1258               dbus_free (list);
   1259               dbus_free (dupped_interface);
   1260               return NULL;
   1261             }
   1262         }
   1263 
   1264       return list;
   1265     }
   1266 }
   1267 
   1268 static void
   1269 bus_matchmaker_gc_rules (BusMatchmaker *matchmaker,
   1270                          int            message_type,
   1271                          const char    *interface,
   1272                          DBusList     **rules)
   1273 {
   1274   RulePool *p;
   1275 
   1276   if (interface == NULL)
   1277     return;
   1278 
   1279   if (*rules != NULL)
   1280     return;
   1281 
   1282   _dbus_verbose ("GCing HT entry for message_type %u, interface %s\n",
   1283                  message_type, interface);
   1284 
   1285   p = matchmaker->rules_by_type + message_type;
   1286 
   1287   _dbus_assert (_dbus_hash_table_lookup_string (p->rules_by_iface, interface)
   1288       == rules);
   1289 
   1290   _dbus_hash_table_remove_string (p->rules_by_iface, interface);
   1291 }
   1292 
   1293 BusMatchmaker *
   1294 bus_matchmaker_ref (BusMatchmaker *matchmaker)
   1295 {
   1296   _dbus_assert (matchmaker->refcount > 0);
   1297 
   1298   matchmaker->refcount += 1;
   1299 
   1300   return matchmaker;
   1301 }
   1302 
   1303 void
   1304 bus_matchmaker_unref (BusMatchmaker *matchmaker)
   1305 {
   1306   _dbus_assert (matchmaker->refcount > 0);
   1307 
   1308   matchmaker->refcount -= 1;
   1309   if (matchmaker->refcount == 0)
   1310     {
   1311       int i;
   1312 
   1313       for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
   1314         {
   1315           RulePool *p = matchmaker->rules_by_type + i;
   1316 
   1317           _dbus_hash_table_unref (p->rules_by_iface);
   1318           rule_list_free (&p->rules_without_iface);
   1319         }
   1320 
   1321       dbus_free (matchmaker);
   1322     }
   1323 }
   1324 
   1325 /* The rule can't be modified after it's added. */
   1326 dbus_bool_t
   1327 bus_matchmaker_add_rule (BusMatchmaker   *matchmaker,
   1328                          BusMatchRule    *rule)
   1329 {
   1330   DBusList **rules;
   1331 
   1332   _dbus_assert (bus_connection_is_active (rule->matches_go_to));
   1333 
   1334   _dbus_verbose ("Adding rule with message_type %d, interface %s\n",
   1335                  rule->message_type,
   1336                  rule->interface != NULL ? rule->interface : "<null>");
   1337 
   1338   rules = bus_matchmaker_get_rules (matchmaker, rule->message_type,
   1339                                     rule->interface, TRUE);
   1340 
   1341   if (rules == NULL)
   1342     return FALSE;
   1343 
   1344   if (!_dbus_list_append (rules, rule))
   1345     return FALSE;
   1346 
   1347   if (!bus_connection_add_match_rule (rule->matches_go_to, rule))
   1348     {
   1349       _dbus_list_remove_last (rules, rule);
   1350       bus_matchmaker_gc_rules (matchmaker, rule->message_type,
   1351                                rule->interface, rules);
   1352       return FALSE;
   1353     }
   1354 
   1355   bus_match_rule_ref (rule);
   1356 
   1357 #ifdef DBUS_ENABLE_VERBOSE_MODE
   1358   {
   1359     char *s = match_rule_to_string (rule);
   1360 
   1361     _dbus_verbose ("Added match rule %s to connection %p\n",
   1362                    s, rule->matches_go_to);
   1363     dbus_free (s);
   1364   }
   1365 #endif
   1366 
   1367   return TRUE;
   1368 }
   1369 
   1370 static dbus_bool_t
   1371 match_rule_equal (BusMatchRule *a,
   1372                   BusMatchRule *b)
   1373 {
   1374   if (a->flags != b->flags)
   1375     return FALSE;
   1376 
   1377   if (a->matches_go_to != b->matches_go_to)
   1378     return FALSE;
   1379 
   1380   if ((a->flags & BUS_MATCH_MESSAGE_TYPE) &&
   1381       a->message_type != b->message_type)
   1382     return FALSE;
   1383 
   1384   if ((a->flags & BUS_MATCH_MEMBER) &&
   1385       strcmp (a->member, b->member) != 0)
   1386     return FALSE;
   1387 
   1388   if ((a->flags & BUS_MATCH_PATH) &&
   1389       strcmp (a->path, b->path) != 0)
   1390     return FALSE;
   1391 
   1392   if ((a->flags & BUS_MATCH_INTERFACE) &&
   1393       strcmp (a->interface, b->interface) != 0)
   1394     return FALSE;
   1395 
   1396   if ((a->flags & BUS_MATCH_SENDER) &&
   1397       strcmp (a->sender, b->sender) != 0)
   1398     return FALSE;
   1399 
   1400   if ((a->flags & BUS_MATCH_DESTINATION) &&
   1401       strcmp (a->destination, b->destination) != 0)
   1402     return FALSE;
   1403 
   1404   /* we already compared the value of flags, and
   1405    * BUS_MATCH_CLIENT_IS_EAVESDROPPING does not have another struct member */
   1406 
   1407   if (a->flags & BUS_MATCH_ARGS)
   1408     {
   1409       int i;
   1410 
   1411       if (a->args_len != b->args_len)
   1412         return FALSE;
   1413 
   1414       i = 0;
   1415       while (i < a->args_len)
   1416         {
   1417           int length;
   1418 
   1419           if ((a->args[i] != NULL) != (b->args[i] != NULL))
   1420             return FALSE;
   1421 
   1422           if (a->arg_lens[i] != b->arg_lens[i])
   1423             return FALSE;
   1424 
   1425           length = a->arg_lens[i] & ~BUS_MATCH_ARG_FLAGS;
   1426 
   1427           if (a->args[i] != NULL)
   1428             {
   1429               _dbus_assert (b->args[i] != NULL);
   1430               if (memcmp (a->args[i], b->args[i], length) != 0)
   1431                 return FALSE;
   1432             }
   1433 
   1434           ++i;
   1435         }
   1436     }
   1437 
   1438   return TRUE;
   1439 }
   1440 
   1441 static void
   1442 bus_matchmaker_remove_rule_link (DBusList       **rules,
   1443                                  DBusList        *link)
   1444 {
   1445   BusMatchRule *rule = link->data;
   1446 
   1447   bus_connection_remove_match_rule (rule->matches_go_to, rule);
   1448   _dbus_list_remove_link (rules, link);
   1449 
   1450 #ifdef DBUS_ENABLE_VERBOSE_MODE
   1451   {
   1452     char *s = match_rule_to_string (rule);
   1453 
   1454     _dbus_verbose ("Removed match rule %s for connection %p\n",
   1455                    s, rule->matches_go_to);
   1456     dbus_free (s);
   1457   }
   1458 #endif
   1459 
   1460   bus_match_rule_unref (rule);
   1461 }
   1462 
   1463 void
   1464 bus_matchmaker_remove_rule (BusMatchmaker   *matchmaker,
   1465                             BusMatchRule    *rule)
   1466 {
   1467   DBusList **rules;
   1468 
   1469   _dbus_verbose ("Removing rule with message_type %d, interface %s\n",
   1470                  rule->message_type,
   1471                  rule->interface != NULL ? rule->interface : "<null>");
   1472 
   1473   bus_connection_remove_match_rule (rule->matches_go_to, rule);
   1474 
   1475   rules = bus_matchmaker_get_rules (matchmaker, rule->message_type,
   1476                                     rule->interface, FALSE);
   1477 
   1478   /* We should only be asked to remove a rule by identity right after it was
   1479    * added, so there should be a list for it.
   1480    */
   1481   _dbus_assert (rules != NULL);
   1482 
   1483   _dbus_list_remove (rules, rule);
   1484   bus_matchmaker_gc_rules (matchmaker, rule->message_type, rule->interface,
   1485       rules);
   1486 
   1487 #ifdef DBUS_ENABLE_VERBOSE_MODE
   1488   {
   1489     char *s = match_rule_to_string (rule);
   1490 
   1491     _dbus_verbose ("Removed match rule %s for connection %p\n",
   1492                    s, rule->matches_go_to);
   1493     dbus_free (s);
   1494   }
   1495 #endif
   1496 
   1497   bus_match_rule_unref (rule);
   1498 }
   1499 
   1500 /* Remove a single rule which is equal to the given rule by value */
   1501 dbus_bool_t
   1502 bus_matchmaker_remove_rule_by_value (BusMatchmaker   *matchmaker,
   1503                                      BusMatchRule    *value,
   1504                                      DBusError       *error)
   1505 {
   1506   DBusList **rules;
   1507   DBusList *link = NULL;
   1508 
   1509   _dbus_verbose ("Removing rule by value with message_type %d, interface %s\n",
   1510                  value->message_type,
   1511                  value->interface != NULL ? value->interface : "<null>");
   1512 
   1513   rules = bus_matchmaker_get_rules (matchmaker, value->message_type,
   1514       value->interface, FALSE);
   1515 
   1516   if (rules != NULL)
   1517     {
   1518       /* we traverse backward because bus_connection_remove_match_rule()
   1519        * removes the most-recently-added rule
   1520        */
   1521       link = _dbus_list_get_last_link (rules);
   1522       while (link != NULL)
   1523         {
   1524           BusMatchRule *rule;
   1525           DBusList *prev;
   1526 
   1527           rule = link->data;
   1528           prev = _dbus_list_get_prev_link (rules, link);
   1529 
   1530           if (match_rule_equal (rule, value))
   1531             {
   1532               bus_matchmaker_remove_rule_link (rules, link);
   1533               break;
   1534             }
   1535 
   1536           link = prev;
   1537         }
   1538     }
   1539 
   1540   if (link == NULL)
   1541     {
   1542       dbus_set_error (error, DBUS_ERROR_MATCH_RULE_NOT_FOUND,
   1543                       "The given match rule wasn't found and can't be removed");
   1544       return FALSE;
   1545     }
   1546 
   1547   bus_matchmaker_gc_rules (matchmaker, value->message_type, value->interface,
   1548       rules);
   1549 
   1550   return TRUE;
   1551 }
   1552 
   1553 static void
   1554 rule_list_remove_by_connection (DBusList       **rules,
   1555                                 DBusConnection  *connection)
   1556 {
   1557   DBusList *link;
   1558 
   1559   link = _dbus_list_get_first_link (rules);
   1560   while (link != NULL)
   1561     {
   1562       BusMatchRule *rule;
   1563       DBusList *next;
   1564 
   1565       rule = link->data;
   1566       next = _dbus_list_get_next_link (rules, link);
   1567 
   1568       if (rule->matches_go_to == connection)
   1569         {
   1570           bus_matchmaker_remove_rule_link (rules, link);
   1571         }
   1572       else if (((rule->flags & BUS_MATCH_SENDER) && *rule->sender == ':') ||
   1573                ((rule->flags & BUS_MATCH_DESTINATION) && *rule->destination == ':'))
   1574         {
   1575           /* The rule matches to/from a base service, see if it's the
   1576            * one being disconnected, since we know this service name
   1577            * will never be recycled.
   1578            */
   1579           const char *name;
   1580 
   1581           name = bus_connection_get_name (connection);
   1582           _dbus_assert (name != NULL); /* because we're an active connection */
   1583 
   1584           if (((rule->flags & BUS_MATCH_SENDER) &&
   1585                strcmp (rule->sender, name) == 0) ||
   1586               ((rule->flags & BUS_MATCH_DESTINATION) &&
   1587                strcmp (rule->destination, name) == 0))
   1588             {
   1589               bus_matchmaker_remove_rule_link (rules, link);
   1590             }
   1591         }
   1592 
   1593       link = next;
   1594     }
   1595 }
   1596 
   1597 void
   1598 bus_matchmaker_disconnected (BusMatchmaker   *matchmaker,
   1599                              DBusConnection  *connection)
   1600 {
   1601   int i;
   1602 
   1603   /* FIXME
   1604    *
   1605    * This scans all match rules on the bus. We could avoid that
   1606    * for the rules belonging to the connection, since we keep
   1607    * a list of those; but for the rules that just refer to
   1608    * the connection we'd need to do something more elaborate.
   1609    */
   1610 
   1611   _dbus_assert (bus_connection_is_active (connection));
   1612 
   1613   _dbus_verbose ("Removing all rules for connection %p\n", connection);
   1614 
   1615   for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
   1616     {
   1617       RulePool *p = matchmaker->rules_by_type + i;
   1618       DBusHashIter iter;
   1619 
   1620       rule_list_remove_by_connection (&p->rules_without_iface, connection);
   1621 
   1622       _dbus_hash_iter_init (p->rules_by_iface, &iter);
   1623       while (_dbus_hash_iter_next (&iter))
   1624         {
   1625           DBusList **items = _dbus_hash_iter_get_value (&iter);
   1626 
   1627           rule_list_remove_by_connection (items, connection);
   1628 
   1629           if (*items == NULL)
   1630             _dbus_hash_iter_remove_entry (&iter);
   1631         }
   1632     }
   1633 }
   1634 
   1635 static dbus_bool_t
   1636 connection_is_primary_owner (DBusConnection *connection,
   1637                              const char     *service_name)
   1638 {
   1639   BusService *service;
   1640   DBusString str;
   1641   BusRegistry *registry;
   1642 
   1643   _dbus_assert (connection != NULL);
   1644 
   1645   registry = bus_connection_get_registry (connection);
   1646 
   1647   _dbus_string_init_const (&str, service_name);
   1648   service = bus_registry_lookup (registry, &str);
   1649 
   1650   if (service == NULL)
   1651     return FALSE; /* Service doesn't exist so connection can't own it. */
   1652 
   1653   return bus_service_get_primary_owners_connection (service) == connection;
   1654 }
   1655 
   1656 static dbus_bool_t
   1657 str_has_prefix (const char *str, const char *prefix)
   1658 {
   1659   size_t prefix_len;
   1660   prefix_len = strlen (prefix);
   1661   if (strncmp (str, prefix, prefix_len) == 0)
   1662     return TRUE;
   1663   else
   1664     return FALSE;
   1665 }
   1666 
   1667 static dbus_bool_t
   1668 match_rule_matches (BusMatchRule    *rule,
   1669                     DBusConnection  *sender,
   1670                     DBusConnection  *addressed_recipient,
   1671                     DBusMessage     *message,
   1672                     BusMatchFlags    already_matched)
   1673 {
   1674   dbus_bool_t wants_to_eavesdrop = FALSE;
   1675   int flags;
   1676 
   1677   /* All features of the match rule are AND'd together,
   1678    * so FALSE if any of them don't match.
   1679    */
   1680 
   1681   /* sender/addressed_recipient of #NULL may mean bus driver,
   1682    * or for addressed_recipient may mean a message with no
   1683    * specific recipient (i.e. a signal)
   1684    */
   1685 
   1686   /* Don't bother re-matching features we've already checked implicitly. */
   1687   flags = rule->flags & (~already_matched);
   1688 
   1689   if (flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING)
   1690     wants_to_eavesdrop = TRUE;
   1691 
   1692   if (flags & BUS_MATCH_MESSAGE_TYPE)
   1693     {
   1694       _dbus_assert (rule->message_type != DBUS_MESSAGE_TYPE_INVALID);
   1695 
   1696       if (rule->message_type != dbus_message_get_type (message))
   1697         return FALSE;
   1698     }
   1699 
   1700   if (flags & BUS_MATCH_INTERFACE)
   1701     {
   1702       const char *iface;
   1703 
   1704       _dbus_assert (rule->interface != NULL);
   1705 
   1706       iface = dbus_message_get_interface (message);
   1707       if (iface == NULL)
   1708         return FALSE;
   1709 
   1710       if (strcmp (iface, rule->interface) != 0)
   1711         return FALSE;
   1712     }
   1713 
   1714   if (flags & BUS_MATCH_MEMBER)
   1715     {
   1716       const char *member;
   1717 
   1718       _dbus_assert (rule->member != NULL);
   1719 
   1720       member = dbus_message_get_member (message);
   1721       if (member == NULL)
   1722         return FALSE;
   1723 
   1724       if (strcmp (member, rule->member) != 0)
   1725         return FALSE;
   1726     }
   1727 
   1728   if (flags & BUS_MATCH_SENDER)
   1729     {
   1730       _dbus_assert (rule->sender != NULL);
   1731 
   1732       if (sender == NULL)
   1733         {
   1734           if (strcmp (rule->sender,
   1735                       DBUS_SERVICE_DBUS) != 0)
   1736             return FALSE;
   1737         }
   1738       else
   1739         {
   1740           if (!connection_is_primary_owner (sender, rule->sender))
   1741             return FALSE;
   1742         }
   1743     }
   1744 
   1745   /* Note: this part is relevant for eavesdropper rules:
   1746    * Two cases:
   1747    * 1) rule has a destination to be matched
   1748    *   (flag BUS_MATCH_DESTINATION present). Rule will match if:
   1749    *   - rule->destination matches the addressed_recipient
   1750    *   AND
   1751    *   - wants_to_eavesdrop=TRUE
   1752    *
   1753    *   Note: (the case in which addressed_recipient is the actual rule owner
   1754    *   is handled elsewere in dispatch.c:bus_dispatch_matches().
   1755    *
   1756    * 2) rule has no destination. Rule will match if:
   1757    *    - message has no specified destination (ie broadcasts)
   1758    *      (Note: this will rule out unicast method calls and unicast signals,
   1759    *      fixing FDO#269748)
   1760    *    OR
   1761    *    - wants_to_eavesdrop=TRUE (destination-catch-all situation)
   1762    */
   1763   if (flags & BUS_MATCH_DESTINATION)
   1764     {
   1765       const char *destination;
   1766 
   1767       _dbus_assert (rule->destination != NULL);
   1768 
   1769       destination = dbus_message_get_destination (message);
   1770       if (destination == NULL)
   1771         /* broadcast, but this rule specified a destination: no match */
   1772         return FALSE;
   1773 
   1774       /* rule owner does not intend to eavesdrop: we'll deliver only msgs
   1775        * directed to it, NOT MATCHING */
   1776       if (!wants_to_eavesdrop)
   1777         return FALSE;
   1778 
   1779       if (addressed_recipient == NULL)
   1780         {
   1781           if (strcmp (rule->destination,
   1782                       DBUS_SERVICE_DBUS) != 0)
   1783             return FALSE;
   1784         }
   1785       else
   1786         {
   1787           if (!connection_is_primary_owner (addressed_recipient, rule->destination))
   1788             return FALSE;
   1789         }
   1790     } else { /* no destination in rule */
   1791         dbus_bool_t msg_is_broadcast;
   1792 
   1793         _dbus_assert (rule->destination == NULL);
   1794 
   1795         msg_is_broadcast = (dbus_message_get_destination (message) == NULL);
   1796 
   1797         if (!wants_to_eavesdrop && !msg_is_broadcast)
   1798           return FALSE;
   1799 
   1800         /* if we are here rule owner intends to eavesdrop
   1801          * OR
   1802          * message is being broadcasted */
   1803     }
   1804 
   1805   if (flags & BUS_MATCH_PATH)
   1806     {
   1807       const char *path;
   1808 
   1809       _dbus_assert (rule->path != NULL);
   1810 
   1811       path = dbus_message_get_path (message);
   1812       if (path == NULL)
   1813         return FALSE;
   1814 
   1815       if (strcmp (path, rule->path) != 0)
   1816         return FALSE;
   1817     }
   1818 
   1819   if (flags & BUS_MATCH_PATH_NAMESPACE)
   1820     {
   1821       const char *path;
   1822       int len;
   1823 
   1824       _dbus_assert (rule->path != NULL);
   1825 
   1826       path = dbus_message_get_path (message);
   1827       if (path == NULL)
   1828         return FALSE;
   1829 
   1830       if (!str_has_prefix (path, rule->path))
   1831         return FALSE;
   1832 
   1833       len = strlen (rule->path);
   1834 
   1835       /* Check that the actual argument is within the expected
   1836        * namespace, rather than just starting with that string,
   1837        * by checking that the matched prefix is followed by a '/'
   1838        * or the end of the path.
   1839        */
   1840       if (path[len] != '\0' && path[len] != '/')
   1841         return FALSE;
   1842     }
   1843 
   1844   if (flags & BUS_MATCH_ARGS)
   1845     {
   1846       int i;
   1847       DBusMessageIter iter;
   1848 
   1849       _dbus_assert (rule->args != NULL);
   1850 
   1851       dbus_message_iter_init (message, &iter);
   1852 
   1853       i = 0;
   1854       while (i < rule->args_len)
   1855         {
   1856           int current_type;
   1857           const char *expected_arg;
   1858           int expected_length;
   1859           dbus_bool_t is_path, is_namespace;
   1860 
   1861           expected_arg = rule->args[i];
   1862           expected_length = rule->arg_lens[i] & ~BUS_MATCH_ARG_FLAGS;
   1863           is_path = (rule->arg_lens[i] & BUS_MATCH_ARG_IS_PATH) != 0;
   1864           is_namespace = (rule->arg_lens[i] & BUS_MATCH_ARG_NAMESPACE) != 0;
   1865 
   1866           current_type = dbus_message_iter_get_arg_type (&iter);
   1867 
   1868           if (expected_arg != NULL)
   1869             {
   1870               const char *actual_arg;
   1871               int actual_length;
   1872 
   1873               if (current_type != DBUS_TYPE_STRING &&
   1874                   (!is_path || current_type != DBUS_TYPE_OBJECT_PATH))
   1875                 return FALSE;
   1876 
   1877               actual_arg = NULL;
   1878               dbus_message_iter_get_basic (&iter, &actual_arg);
   1879               _dbus_assert (actual_arg != NULL);
   1880 
   1881               actual_length = strlen (actual_arg);
   1882 
   1883               if (is_path)
   1884                 {
   1885                   if (actual_length < expected_length &&
   1886                       actual_arg[actual_length - 1] != '/')
   1887                     return FALSE;
   1888 
   1889                   if (expected_length < actual_length &&
   1890                       expected_arg[expected_length - 1] != '/')
   1891                     return FALSE;
   1892 
   1893                   if (memcmp (actual_arg, expected_arg,
   1894                               MIN (actual_length, expected_length)) != 0)
   1895                     return FALSE;
   1896                 }
   1897               else if (is_namespace)
   1898                 {
   1899                   if (expected_length > actual_length)
   1900                     return FALSE;
   1901 
   1902                   /* If the actual argument doesn't start with the expected
   1903                    * namespace, then we don't match.
   1904                    */
   1905                   if (memcmp (expected_arg, actual_arg, expected_length) != 0)
   1906                     return FALSE;
   1907 
   1908                   if (expected_length < actual_length)
   1909                     {
   1910                       /* Check that the actual argument is within the expected
   1911                        * namespace, rather than just starting with that string,
   1912                        * by checking that the matched prefix ends in a '.'.
   1913                        *
   1914                        * This doesn't stop "foo.bar." matching "foo.bar..baz"
   1915                        * which is an invalid namespace, but at some point the
   1916                        * daemon can't cover up for broken services.
   1917                        */
   1918                       if (actual_arg[expected_length] != '.')
   1919                         return FALSE;
   1920                     }
   1921                   /* otherwise we had an exact match. */
   1922                 }
   1923               else
   1924                 {
   1925                   if (expected_length != actual_length ||
   1926                       memcmp (expected_arg, actual_arg, expected_length) != 0)
   1927                     return FALSE;
   1928                 }
   1929 
   1930             }
   1931 
   1932           if (current_type != DBUS_TYPE_INVALID)
   1933             dbus_message_iter_next (&iter);
   1934 
   1935           ++i;
   1936         }
   1937     }
   1938 
   1939   return TRUE;
   1940 }
   1941 
   1942 static dbus_bool_t
   1943 get_recipients_from_list (DBusList       **rules,
   1944                           DBusConnection  *sender,
   1945                           DBusConnection  *addressed_recipient,
   1946                           DBusMessage     *message,
   1947                           DBusList       **recipients_p)
   1948 {
   1949   DBusList *link;
   1950 
   1951   if (rules == NULL)
   1952     return TRUE;
   1953 
   1954   link = _dbus_list_get_first_link (rules);
   1955   while (link != NULL)
   1956     {
   1957       BusMatchRule *rule;
   1958 
   1959       rule = link->data;
   1960 
   1961 #ifdef DBUS_ENABLE_VERBOSE_MODE
   1962       {
   1963         char *s = match_rule_to_string (rule);
   1964 
   1965         _dbus_verbose ("Checking whether message matches rule %s for connection %p\n",
   1966                        s, rule->matches_go_to);
   1967         dbus_free (s);
   1968       }
   1969 #endif
   1970 
   1971       if (match_rule_matches (rule,
   1972                               sender, addressed_recipient, message,
   1973                               BUS_MATCH_MESSAGE_TYPE | BUS_MATCH_INTERFACE))
   1974         {
   1975           _dbus_verbose ("Rule matched\n");
   1976 
   1977           /* Append to the list if we haven't already */
   1978           if (bus_connection_mark_stamp (rule->matches_go_to))
   1979             {
   1980               if (!_dbus_list_append (recipients_p, rule->matches_go_to))
   1981                 return FALSE;
   1982             }
   1983 #ifdef DBUS_ENABLE_VERBOSE_MODE
   1984           else
   1985             {
   1986               _dbus_verbose ("Connection already receiving this message, so not adding again\n");
   1987             }
   1988 #endif /* DBUS_ENABLE_VERBOSE_MODE */
   1989         }
   1990 
   1991       link = _dbus_list_get_next_link (rules, link);
   1992     }
   1993 
   1994   return TRUE;
   1995 }
   1996 
   1997 dbus_bool_t
   1998 bus_matchmaker_get_recipients (BusMatchmaker   *matchmaker,
   1999                                BusConnections  *connections,
   2000                                DBusConnection  *sender,
   2001                                DBusConnection  *addressed_recipient,
   2002                                DBusMessage     *message,
   2003                                DBusList       **recipients_p)
   2004 {
   2005   int type;
   2006   const char *interface;
   2007   DBusList **neither, **just_type, **just_iface, **both;
   2008 
   2009   _dbus_assert (*recipients_p == NULL);
   2010 
   2011   /* This avoids sending same message to the same connection twice.
   2012    * Purpose of the stamp instead of a bool is to avoid iterating over
   2013    * all connections resetting the bool each time.
   2014    */
   2015   bus_connections_increment_stamp (connections);
   2016 
   2017   /* addressed_recipient is already receiving the message, don't add to list.
   2018    * NULL addressed_recipient means either bus driver, or this is a signal
   2019    * and thus lacks a specific addressed_recipient.
   2020    */
   2021   if (addressed_recipient != NULL)
   2022     bus_connection_mark_stamp (addressed_recipient);
   2023 
   2024   type = dbus_message_get_type (message);
   2025   interface = dbus_message_get_interface (message);
   2026 
   2027   neither = bus_matchmaker_get_rules (matchmaker, DBUS_MESSAGE_TYPE_INVALID,
   2028       NULL, FALSE);
   2029   just_type = just_iface = both = NULL;
   2030 
   2031   if (interface != NULL)
   2032     just_iface = bus_matchmaker_get_rules (matchmaker,
   2033         DBUS_MESSAGE_TYPE_INVALID, interface, FALSE);
   2034 
   2035   if (type > DBUS_MESSAGE_TYPE_INVALID && type < DBUS_NUM_MESSAGE_TYPES)
   2036     {
   2037       just_type = bus_matchmaker_get_rules (matchmaker, type, NULL, FALSE);
   2038 
   2039       if (interface != NULL)
   2040         both = bus_matchmaker_get_rules (matchmaker, type, interface, FALSE);
   2041     }
   2042 
   2043   if (!(get_recipients_from_list (neither, sender, addressed_recipient,
   2044                                   message, recipients_p) &&
   2045         get_recipients_from_list (just_iface, sender, addressed_recipient,
   2046                                   message, recipients_p) &&
   2047         get_recipients_from_list (just_type, sender, addressed_recipient,
   2048                                   message, recipients_p) &&
   2049         get_recipients_from_list (both, sender, addressed_recipient,
   2050                                   message, recipients_p)))
   2051     {
   2052       _dbus_list_clear (recipients_p);
   2053       return FALSE;
   2054     }
   2055 
   2056   return TRUE;
   2057 }
   2058 
   2059 #ifdef DBUS_BUILD_TESTS
   2060 #include "test.h"
   2061 #include <stdlib.h>
   2062 
   2063 static BusMatchRule*
   2064 check_parse (dbus_bool_t should_succeed,
   2065              const char *text)
   2066 {
   2067   BusMatchRule *rule;
   2068   DBusString str;
   2069   DBusError error;
   2070 
   2071   dbus_error_init (&error);
   2072 
   2073   _dbus_string_init_const (&str, text);
   2074 
   2075   rule = bus_match_rule_parse (NULL, &str, &error);
   2076   if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
   2077     {
   2078       dbus_error_free (&error);
   2079       return NULL;
   2080     }
   2081 
   2082   if (should_succeed && rule == NULL)
   2083     {
   2084       _dbus_warn ("Failed to parse: %s: %s: \"%s\"\n",
   2085                   error.name, error.message,
   2086                   _dbus_string_get_const_data (&str));
   2087       exit (1);
   2088     }
   2089 
   2090   if (!should_succeed && rule != NULL)
   2091     {
   2092       _dbus_warn ("Failed to fail to parse: \"%s\"\n",
   2093                   _dbus_string_get_const_data (&str));
   2094       exit (1);
   2095     }
   2096 
   2097   dbus_error_free (&error);
   2098 
   2099   return rule;
   2100 }
   2101 
   2102 static void
   2103 assert_large_rule (BusMatchRule *rule)
   2104 {
   2105   _dbus_assert (rule->flags & BUS_MATCH_MESSAGE_TYPE);
   2106   _dbus_assert (rule->flags & BUS_MATCH_SENDER);
   2107   _dbus_assert (rule->flags & BUS_MATCH_INTERFACE);
   2108   _dbus_assert (rule->flags & BUS_MATCH_MEMBER);
   2109   _dbus_assert (rule->flags & BUS_MATCH_DESTINATION);
   2110   _dbus_assert (rule->flags & BUS_MATCH_PATH);
   2111 
   2112   _dbus_assert (rule->message_type == DBUS_MESSAGE_TYPE_SIGNAL);
   2113   _dbus_assert (rule->interface != NULL);
   2114   _dbus_assert (rule->member != NULL);
   2115   _dbus_assert (rule->sender != NULL);
   2116   _dbus_assert (rule->destination != NULL);
   2117   _dbus_assert (rule->path != NULL);
   2118 
   2119   _dbus_assert (strcmp (rule->interface, "org.freedesktop.DBusInterface") == 0);
   2120   _dbus_assert (strcmp (rule->sender, "org.freedesktop.DBusSender") == 0);
   2121   _dbus_assert (strcmp (rule->member, "Foo") == 0);
   2122   _dbus_assert (strcmp (rule->path, "/bar/foo") == 0);
   2123   _dbus_assert (strcmp (rule->destination, ":452345.34") == 0);
   2124 }
   2125 
   2126 static dbus_bool_t
   2127 test_parsing (void *data)
   2128 {
   2129   BusMatchRule *rule;
   2130 
   2131   rule = check_parse (TRUE, "type='signal',sender='org.freedesktop.DBusSender',interface='org.freedesktop.DBusInterface',member='Foo',path='/bar/foo',destination=':452345.34'");
   2132   if (rule != NULL)
   2133     {
   2134       assert_large_rule (rule);
   2135       bus_match_rule_unref (rule);
   2136     }
   2137 
   2138   /* With extra whitespace and useless quotes */
   2139   rule = check_parse (TRUE, "    type='signal',  \tsender='org.freedes''ktop.DBusSender',   interface='org.freedesktop.DBusInterface''''', \tmember='Foo',path='/bar/foo',destination=':452345.34'''''");
   2140   if (rule != NULL)
   2141     {
   2142       assert_large_rule (rule);
   2143       bus_match_rule_unref (rule);
   2144     }
   2145 
   2146 
   2147   /* A simple signal connection */
   2148   rule = check_parse (TRUE, "type='signal',path='/foo',interface='org.Bar'");
   2149   if (rule != NULL)
   2150     {
   2151       _dbus_assert (rule->flags & BUS_MATCH_MESSAGE_TYPE);
   2152       _dbus_assert (rule->flags & BUS_MATCH_INTERFACE);
   2153       _dbus_assert (rule->flags & BUS_MATCH_PATH);
   2154 
   2155       _dbus_assert (rule->message_type == DBUS_MESSAGE_TYPE_SIGNAL);
   2156       _dbus_assert (rule->interface != NULL);
   2157       _dbus_assert (rule->path != NULL);
   2158 
   2159       _dbus_assert (strcmp (rule->interface, "org.Bar") == 0);
   2160       _dbus_assert (strcmp (rule->path, "/foo") == 0);
   2161 
   2162       bus_match_rule_unref (rule);
   2163     }
   2164 
   2165   /* argN */
   2166   rule = check_parse (TRUE, "arg0='foo'");
   2167   if (rule != NULL)
   2168     {
   2169       _dbus_assert (rule->flags == BUS_MATCH_ARGS);
   2170       _dbus_assert (rule->args != NULL);
   2171       _dbus_assert (rule->args_len == 1);
   2172       _dbus_assert (rule->args[0] != NULL);
   2173       _dbus_assert (rule->args[1] == NULL);
   2174       _dbus_assert (strcmp (rule->args[0], "foo") == 0);
   2175 
   2176       bus_match_rule_unref (rule);
   2177     }
   2178 
   2179   rule = check_parse (TRUE, "arg1='foo'");
   2180   if (rule != NULL)
   2181     {
   2182       _dbus_assert (rule->flags == BUS_MATCH_ARGS);
   2183       _dbus_assert (rule->args != NULL);
   2184       _dbus_assert (rule->args_len == 2);
   2185       _dbus_assert (rule->args[0] == NULL);
   2186       _dbus_assert (rule->args[1] != NULL);
   2187       _dbus_assert (rule->args[2] == NULL);
   2188       _dbus_assert (strcmp (rule->args[1], "foo") == 0);
   2189 
   2190       bus_match_rule_unref (rule);
   2191     }
   2192 
   2193   rule = check_parse (TRUE, "arg2='foo'");
   2194   if (rule != NULL)
   2195     {
   2196       _dbus_assert (rule->flags == BUS_MATCH_ARGS);
   2197       _dbus_assert (rule->args != NULL);
   2198       _dbus_assert (rule->args_len == 3);
   2199       _dbus_assert (rule->args[0] == NULL);
   2200       _dbus_assert (rule->args[1] == NULL);
   2201       _dbus_assert (rule->args[2] != NULL);
   2202       _dbus_assert (rule->args[3] == NULL);
   2203       _dbus_assert (strcmp (rule->args[2], "foo") == 0);
   2204 
   2205       bus_match_rule_unref (rule);
   2206     }
   2207 
   2208   rule = check_parse (TRUE, "arg40='foo'");
   2209   if (rule != NULL)
   2210     {
   2211       _dbus_assert (rule->flags == BUS_MATCH_ARGS);
   2212       _dbus_assert (rule->args != NULL);
   2213       _dbus_assert (rule->args_len == 41);
   2214       _dbus_assert (rule->args[0] == NULL);
   2215       _dbus_assert (rule->args[1] == NULL);
   2216       _dbus_assert (rule->args[40] != NULL);
   2217       _dbus_assert (rule->args[41] == NULL);
   2218       _dbus_assert (strcmp (rule->args[40], "foo") == 0);
   2219 
   2220       bus_match_rule_unref (rule);
   2221     }
   2222 
   2223   rule = check_parse (TRUE, "arg63='foo'");
   2224   if (rule != NULL)
   2225     {
   2226       _dbus_assert (rule->flags == BUS_MATCH_ARGS);
   2227       _dbus_assert (rule->args != NULL);
   2228       _dbus_assert (rule->args_len == 64);
   2229       _dbus_assert (rule->args[0] == NULL);
   2230       _dbus_assert (rule->args[1] == NULL);
   2231       _dbus_assert (rule->args[63] != NULL);
   2232       _dbus_assert (rule->args[64] == NULL);
   2233       _dbus_assert (strcmp (rule->args[63], "foo") == 0);
   2234 
   2235       bus_match_rule_unref (rule);
   2236     }
   2237 
   2238   rule = check_parse (TRUE, "arg7path='/foo'");
   2239   if (rule != NULL)
   2240     {
   2241       _dbus_assert (rule->flags = BUS_MATCH_ARGS);
   2242       _dbus_assert (rule->args != NULL);
   2243       _dbus_assert (rule->args_len == 8);
   2244       _dbus_assert (rule->args[7] != NULL);
   2245       _dbus_assert (rule->args[8] == NULL);
   2246       _dbus_assert (strcmp (rule->args[7], "/foo") == 0);
   2247       _dbus_assert ((rule->arg_lens[7] & BUS_MATCH_ARG_IS_PATH)
   2248           == BUS_MATCH_ARG_IS_PATH);
   2249 
   2250       bus_match_rule_unref (rule);
   2251     }
   2252 
   2253   /* Arg 0 namespace matches */
   2254   rule = check_parse (TRUE, "arg0namespace='foo'");
   2255   if (rule != NULL)
   2256     {
   2257       _dbus_assert (rule->flags == BUS_MATCH_ARGS);
   2258       _dbus_assert (rule->args != NULL);
   2259       _dbus_assert (rule->args_len == 1);
   2260       _dbus_assert (strcmp (rule->args[0], "foo") == 0);
   2261       _dbus_assert ((rule->arg_lens[0] & BUS_MATCH_ARG_NAMESPACE)
   2262           == BUS_MATCH_ARG_NAMESPACE);
   2263 
   2264       bus_match_rule_unref (rule);
   2265     }
   2266 
   2267   rule = check_parse (TRUE, "arg0namespace='foo.bar'");
   2268   if (rule != NULL)
   2269     {
   2270       _dbus_assert (rule->flags == BUS_MATCH_ARGS);
   2271       _dbus_assert (rule->args != NULL);
   2272       _dbus_assert (rule->args_len == 1);
   2273       _dbus_assert (strcmp (rule->args[0], "foo.bar") == 0);
   2274       _dbus_assert ((rule->arg_lens[0] & BUS_MATCH_ARG_NAMESPACE)
   2275           == BUS_MATCH_ARG_NAMESPACE);
   2276 
   2277       bus_match_rule_unref (rule);
   2278     }
   2279 
   2280   /* Only arg0namespace is supported. */
   2281   rule = check_parse (FALSE, "arg1namespace='foo'");
   2282   _dbus_assert (rule == NULL);
   2283 
   2284   /* An empty string isn't a valid namespace prefix (you should just not
   2285    * specify this key at all).
   2286    */
   2287   rule = check_parse (FALSE, "arg0namespace=''");
   2288   _dbus_assert (rule == NULL);
   2289 
   2290   /* Trailing periods aren't allowed (earlier versions of the arg0namespace
   2291    * spec allowed a single trailing period, which altered the semantics) */
   2292   rule = check_parse (FALSE, "arg0namespace='foo.'");
   2293   _dbus_assert (rule == NULL);
   2294 
   2295   rule = check_parse (FALSE, "arg0namespace='foo.bar.'");
   2296   _dbus_assert (rule == NULL);
   2297 
   2298   rule = check_parse (FALSE, "arg0namespace='foo..'");
   2299   _dbus_assert (rule == NULL);
   2300 
   2301   rule = check_parse (FALSE, "arg0namespace='foo.bar..'");
   2302   _dbus_assert (rule == NULL);
   2303 
   2304   /* Too-large argN */
   2305   rule = check_parse (FALSE, "arg300='foo'");
   2306   _dbus_assert (rule == NULL);
   2307   rule = check_parse (FALSE, "arg64='foo'");
   2308   _dbus_assert (rule == NULL);
   2309 
   2310   /* No N in argN */
   2311   rule = check_parse (FALSE, "arg='foo'");
   2312   _dbus_assert (rule == NULL);
   2313   rule = check_parse (FALSE, "argv='foo'");
   2314   _dbus_assert (rule == NULL);
   2315   rule = check_parse (FALSE, "arg3junk='foo'");
   2316   _dbus_assert (rule == NULL);
   2317   rule = check_parse (FALSE, "argument='foo'");
   2318   _dbus_assert (rule == NULL);
   2319 
   2320   /* Reject duplicates */
   2321   rule = check_parse (FALSE, "type='signal',type='method_call'");
   2322   _dbus_assert (rule == NULL);
   2323 
   2324   rule = check_parse (TRUE, "path_namespace='/foo/bar'");
   2325   if (rule != NULL)
   2326     {
   2327       _dbus_assert (rule->flags == BUS_MATCH_PATH_NAMESPACE);
   2328       _dbus_assert (rule->path != NULL);
   2329       _dbus_assert (strcmp (rule->path, "/foo/bar") == 0);
   2330 
   2331       bus_match_rule_unref (rule);
   2332     }
   2333 
   2334   /* Almost a duplicate */
   2335   rule = check_parse (FALSE, "path='/foo',path_namespace='/foo'");
   2336   _dbus_assert (rule == NULL);
   2337 
   2338   /* Trailing / was supported in the initial proposal, but now isn't */
   2339   rule = check_parse (FALSE, "path_namespace='/foo/'");
   2340   _dbus_assert (rule == NULL);
   2341 
   2342   /* Duplicates with the argN code */
   2343   rule = check_parse (FALSE, "arg0='foo',arg0='bar'");
   2344   _dbus_assert (rule == NULL);
   2345   rule = check_parse (FALSE, "arg3='foo',arg3='bar'");
   2346   _dbus_assert (rule == NULL);
   2347   rule = check_parse (FALSE, "arg30='foo',arg30='bar'");
   2348   _dbus_assert (rule == NULL);
   2349 
   2350   /* Reject broken keys */
   2351   rule = check_parse (FALSE, "blah='signal'");
   2352   _dbus_assert (rule == NULL);
   2353 
   2354   /* Reject broken values */
   2355   rule = check_parse (FALSE, "type='chouin'");
   2356   _dbus_assert (rule == NULL);
   2357   rule = check_parse (FALSE, "interface='abc@def++'");
   2358   _dbus_assert (rule == NULL);
   2359   rule = check_parse (FALSE, "service='youpi'");
   2360   _dbus_assert (rule == NULL);
   2361 
   2362   /* Allow empty rule */
   2363   rule = check_parse (TRUE, "");
   2364   if (rule != NULL)
   2365     {
   2366       _dbus_assert (rule->flags == 0);
   2367 
   2368       bus_match_rule_unref (rule);
   2369     }
   2370 
   2371   /* All-whitespace rule is the same as empty */
   2372   rule = check_parse (TRUE, "    \t");
   2373   if (rule != NULL)
   2374     {
   2375       _dbus_assert (rule->flags == 0);
   2376 
   2377       bus_match_rule_unref (rule);
   2378     }
   2379 
   2380   /* But with non-whitespace chars and no =value, it's not OK */
   2381   rule = check_parse (FALSE, "type");
   2382   _dbus_assert (rule == NULL);
   2383 
   2384   return TRUE;
   2385 }
   2386 
   2387 static struct {
   2388   const char *first;
   2389   const char *second;
   2390 } equality_tests[] = {
   2391   { "type='signal'", "type='signal'" },
   2392   { "type='signal',interface='foo.bar'", "interface='foo.bar',type='signal'" },
   2393   { "type='signal',member='bar'", "member='bar',type='signal'" },
   2394   { "type='method_call',sender=':1.0'", "sender=':1.0',type='method_call'" },
   2395   { "type='method_call',destination=':1.0'", "destination=':1.0',type='method_call'" },
   2396   { "type='method_call',path='/foo/bar'", "path='/foo/bar',type='method_call'" },
   2397   { "type='method_call',arg0='blah'", "arg0='blah',type='method_call'" },
   2398   { "type='method_call',arg0='boo'", "arg0='boo',type='method_call'" },
   2399   { "type='method_call',arg0='blah',arg1='baz'", "arg0='blah',arg1='baz',type='method_call'" },
   2400   { "type='method_call',arg3='foosh'", "arg3='foosh',type='method_call'" },
   2401   { "arg3='fool'", "arg3='fool'" },
   2402   { "arg0namespace='fool'", "arg0namespace='fool'" },
   2403   { "member='food'", "member='food'" }
   2404 };
   2405 
   2406 static void
   2407 test_equality (void)
   2408 {
   2409   int i;
   2410 
   2411   i = 0;
   2412   while (i < _DBUS_N_ELEMENTS (equality_tests))
   2413     {
   2414       BusMatchRule *first;
   2415       BusMatchRule *second;
   2416       int j;
   2417 
   2418       first = check_parse (TRUE, equality_tests[i].first);
   2419       _dbus_assert (first != NULL);
   2420       second = check_parse (TRUE, equality_tests[i].second);
   2421       _dbus_assert (second != NULL);
   2422 
   2423       if (!match_rule_equal (first, second))
   2424         {
   2425           _dbus_warn ("rule %s and %s should have been equal\n",
   2426                       equality_tests[i].first,
   2427                       equality_tests[i].second);
   2428           exit (1);
   2429         }
   2430 
   2431       bus_match_rule_unref (second);
   2432 
   2433       /* Check that the rule is not equal to any of the
   2434        * others besides its pair match
   2435        */
   2436       j = 0;
   2437       while (j < _DBUS_N_ELEMENTS (equality_tests))
   2438         {
   2439           if (i != j)
   2440             {
   2441               second = check_parse (TRUE, equality_tests[j].second);
   2442 
   2443               if (match_rule_equal (first, second))
   2444                 {
   2445                   _dbus_warn ("rule %s and %s should not have been equal\n",
   2446                               equality_tests[i].first,
   2447                               equality_tests[j].second);
   2448                   exit (1);
   2449                 }
   2450 
   2451               bus_match_rule_unref (second);
   2452             }
   2453 
   2454           ++j;
   2455         }
   2456 
   2457       bus_match_rule_unref (first);
   2458 
   2459       ++i;
   2460     }
   2461 }
   2462 
   2463 static const char*
   2464 should_match_message_1[] = {
   2465   "type='signal'",
   2466   "member='Frobated'",
   2467   "arg0='foobar'",
   2468   "type='signal',member='Frobated'",
   2469   "type='signal',member='Frobated',arg0='foobar'",
   2470   "member='Frobated',arg0='foobar'",
   2471   "type='signal',arg0='foobar'",
   2472   /* The definition of argXpath matches says: "As with normal argument matches,
   2473    * if the argument is exactly equal to the string given in the match rule
   2474    * then the rule is satisfied." So this should match (even though the
   2475    * argument is not a valid path)!
   2476    */
   2477   "arg0path='foobar'",
   2478   "arg0namespace='foobar'",
   2479   NULL
   2480 };
   2481 
   2482 static const char*
   2483 should_not_match_message_1[] = {
   2484   "type='method_call'",
   2485   "type='error'",
   2486   "type='method_return'",
   2487   "type='signal',member='Oopsed'",
   2488   "arg0='blah'",
   2489   "arg1='foobar'",
   2490   "arg2='foobar'",
   2491   "arg3='foobar'",
   2492   "arg0='3'",
   2493   "arg1='3'",
   2494   "arg0='foobar',arg1='abcdef'",
   2495   "arg0='foobar',arg1='abcdef',arg2='abcdefghi',arg3='abcdefghi',arg4='abcdefghi'",
   2496   "arg0='foobar',arg1='abcdef',arg4='abcdefghi',arg3='abcdefghi',arg2='abcdefghi'",
   2497   "arg0path='foo'",
   2498   "arg0path='foobar/'",
   2499   "arg1path='3'",
   2500   "arg0namespace='foo'",
   2501   "arg0namespace='foo',arg1='abcdef'",
   2502   "arg0namespace='moo'",
   2503   NULL
   2504 };
   2505 
   2506 #define EXAMPLE_NAME "com.example.backend.foo"
   2507 
   2508 static const char *
   2509 should_match_message_2[] = {
   2510   /* EXAMPLE_NAME is in all of these namespaces */
   2511   "arg0namespace='com.example.backend'",
   2512   "arg0namespace='com.example'",
   2513   "arg0namespace='com'",
   2514 
   2515   /* If the client specifies the name exactly, with no trailing period, then
   2516    * it should match.
   2517    */
   2518   "arg0namespace='com.example.backend.foo'",
   2519 
   2520   NULL
   2521 };
   2522 
   2523 static const char *
   2524 should_not_match_message_2[] = {
   2525   /* These are not even prefixes */
   2526   "arg0namespace='com.example.backend.foo.bar'",
   2527   "arg0namespace='com.example.backend.foobar'",
   2528 
   2529   /* These are prefixes, but they're not parent namespaces. */
   2530   "arg0namespace='com.example.backend.fo'",
   2531   "arg0namespace='com.example.backen'",
   2532   "arg0namespace='com.exampl'",
   2533   "arg0namespace='co'",
   2534 
   2535   NULL
   2536 };
   2537 
   2538 static void
   2539 check_matches (dbus_bool_t  expected_to_match,
   2540                int          number,
   2541                DBusMessage *message,
   2542                const char  *rule_text)
   2543 {
   2544   BusMatchRule *rule;
   2545   dbus_bool_t matched;
   2546 
   2547   rule = check_parse (TRUE, rule_text);
   2548   _dbus_assert (rule != NULL);
   2549 
   2550   /* We can't test sender/destination rules since we pass NULL here */
   2551   matched = match_rule_matches (rule, NULL, NULL, message, 0);
   2552 
   2553   if (matched != expected_to_match)
   2554     {
   2555       _dbus_warn ("Expected rule %s to %s message %d, failed\n",
   2556                   rule_text, expected_to_match ?
   2557                   "match" : "not match", number);
   2558       exit (1);
   2559     }
   2560 
   2561   bus_match_rule_unref (rule);
   2562 }
   2563 
   2564 static void
   2565 check_matching (DBusMessage *message,
   2566                 int          number,
   2567                 const char **should_match,
   2568                 const char **should_not_match)
   2569 {
   2570   int i;
   2571 
   2572   i = 0;
   2573   while (should_match[i] != NULL)
   2574     {
   2575       check_matches (TRUE, number, message, should_match[i]);
   2576       ++i;
   2577     }
   2578 
   2579   i = 0;
   2580   while (should_not_match[i] != NULL)
   2581     {
   2582       check_matches (FALSE, number, message, should_not_match[i]);
   2583       ++i;
   2584     }
   2585 }
   2586 
   2587 static void
   2588 test_matching (void)
   2589 {
   2590   DBusMessage *message1, *message2;
   2591   const char *v_STRING;
   2592   dbus_int32_t v_INT32;
   2593 
   2594   message1 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
   2595   _dbus_assert (message1 != NULL);
   2596   if (!dbus_message_set_member (message1, "Frobated"))
   2597     _dbus_assert_not_reached ("oom");
   2598 
   2599   v_STRING = "foobar";
   2600   v_INT32 = 3;
   2601   if (!dbus_message_append_args (message1,
   2602                                  DBUS_TYPE_STRING, &v_STRING,
   2603                                  DBUS_TYPE_INT32, &v_INT32,
   2604                                  NULL))
   2605     _dbus_assert_not_reached ("oom");
   2606 
   2607   check_matching (message1, 1,
   2608                   should_match_message_1,
   2609                   should_not_match_message_1);
   2610 
   2611   dbus_message_unref (message1);
   2612 
   2613   message2 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
   2614   _dbus_assert (message2 != NULL);
   2615   if (!dbus_message_set_member (message2, "NameOwnerChanged"))
   2616     _dbus_assert_not_reached ("oom");
   2617 
   2618   /* Obviously this isn't really a NameOwnerChanged signal. */
   2619   v_STRING = EXAMPLE_NAME;
   2620   if (!dbus_message_append_args (message2,
   2621                                  DBUS_TYPE_STRING, &v_STRING,
   2622                                  NULL))
   2623     _dbus_assert_not_reached ("oom");
   2624 
   2625   check_matching (message2, 2,
   2626                   should_match_message_2,
   2627                   should_not_match_message_2);
   2628 
   2629   dbus_message_unref (message2);
   2630 }
   2631 
   2632 #define PATH_MATCH_RULE "arg0path='/aa/bb/'"
   2633 
   2634 /* This is a list of paths that should be matched by PATH_MATCH_RULE, taken
   2635  * from the specification. Notice that not all of them are actually legal D-Bus
   2636  * paths.
   2637  *
   2638  * The author of this test takes no responsibility for the semantics of
   2639  * this match rule key.
   2640  */
   2641 static const char *paths_that_should_be_matched[] = {
   2642     "/aa/",
   2643     "/aa/bb/",
   2644     "/aa/bb/cc/",
   2645 #define FIRST_VALID_PATH_WHICH_SHOULD_MATCH 3
   2646     "/",
   2647     "/aa/bb/cc",
   2648     NULL
   2649 };
   2650 
   2651 /* These paths should not be matched by PATH_MATCH_RULE. */
   2652 static const char *paths_that_should_not_be_matched[] = {
   2653     "/aa/b",
   2654     "/aa",
   2655     /* or even... */
   2656     "/aa/bb",
   2657     NULL
   2658 };
   2659 
   2660 static void
   2661 test_path_match (int type,
   2662                  const char   *path,
   2663                  const char   *rule_text,
   2664                  BusMatchRule *rule,
   2665                  dbus_bool_t   should_match)
   2666 {
   2667   DBusMessage *message = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
   2668   dbus_bool_t matched;
   2669 
   2670   _dbus_assert (message != NULL);
   2671   if (!dbus_message_set_member (message, "Foo"))
   2672     _dbus_assert_not_reached ("oom");
   2673 
   2674   if (!dbus_message_append_args (message,
   2675                                  type, &path,
   2676                                  NULL))
   2677     _dbus_assert_not_reached ("oom");
   2678 
   2679   matched = match_rule_matches (rule, NULL, NULL, message, 0);
   2680 
   2681   if (matched != should_match)
   2682     {
   2683       _dbus_warn ("Expected rule %s to %s message "
   2684                   "with first arg %s of type '%c', failed\n",
   2685                   rule_text,
   2686                   should_match ? "match" : "not match",
   2687                   path,
   2688                   (char) type);
   2689       exit (1);
   2690     }
   2691 
   2692   dbus_message_unref (message);
   2693 }
   2694 
   2695 static void
   2696 test_path_matching (void)
   2697 {
   2698   BusMatchRule *rule;
   2699   const char **s;
   2700 
   2701   rule = check_parse (TRUE, PATH_MATCH_RULE);
   2702   _dbus_assert (rule != NULL);
   2703 
   2704   for (s = paths_that_should_be_matched; *s != NULL; s++)
   2705     test_path_match (DBUS_TYPE_STRING, *s, PATH_MATCH_RULE, rule, TRUE);
   2706 
   2707   for (s = paths_that_should_be_matched + FIRST_VALID_PATH_WHICH_SHOULD_MATCH;
   2708        *s != NULL; s++)
   2709     test_path_match (DBUS_TYPE_OBJECT_PATH, *s, PATH_MATCH_RULE, rule, TRUE);
   2710 
   2711   for (s = paths_that_should_not_be_matched; *s != NULL; s++)
   2712     {
   2713       test_path_match (DBUS_TYPE_STRING, *s, PATH_MATCH_RULE, rule, FALSE);
   2714       test_path_match (DBUS_TYPE_OBJECT_PATH, *s, PATH_MATCH_RULE, rule, FALSE);
   2715     }
   2716 
   2717   bus_match_rule_unref (rule);
   2718 }
   2719 
   2720 static const char*
   2721 path_namespace_should_match_message_1[] = {
   2722   "type='signal',path_namespace='/foo'",
   2723   "type='signal',path_namespace='/foo/TheObjectManager'",
   2724   NULL
   2725 };
   2726 
   2727 static const char*
   2728 path_namespace_should_not_match_message_1[] = {
   2729   "type='signal',path_namespace='/bar'",
   2730   "type='signal',path_namespace='/bar/TheObjectManager'",
   2731   NULL
   2732 };
   2733 
   2734 static const char*
   2735 path_namespace_should_match_message_2[] = {
   2736   "type='signal',path_namespace='/foo/TheObjectManager'",
   2737   NULL
   2738 };
   2739 
   2740 static const char*
   2741 path_namespace_should_not_match_message_2[] = {
   2742   NULL
   2743 };
   2744 
   2745 static const char*
   2746 path_namespace_should_match_message_3[] = {
   2747   NULL
   2748 };
   2749 
   2750 static const char*
   2751 path_namespace_should_not_match_message_3[] = {
   2752   "type='signal',path_namespace='/foo/TheObjectManager'",
   2753   NULL
   2754 };
   2755 
   2756 static void
   2757 test_matching_path_namespace (void)
   2758 {
   2759   DBusMessage *message1;
   2760   DBusMessage *message2;
   2761   DBusMessage *message3;
   2762 
   2763   message1 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
   2764   _dbus_assert (message1 != NULL);
   2765   if (!dbus_message_set_path (message1, "/foo/TheObjectManager"))
   2766     _dbus_assert_not_reached ("oom");
   2767 
   2768   message2 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
   2769   _dbus_assert (message2 != NULL);
   2770   if (!dbus_message_set_path (message2, "/foo/TheObjectManager/child_object"))
   2771     _dbus_assert_not_reached ("oom");
   2772 
   2773   message3 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
   2774   _dbus_assert (message3 != NULL);
   2775   if (!dbus_message_set_path (message3, "/foo/TheObjectManagerOther"))
   2776     _dbus_assert_not_reached ("oom");
   2777 
   2778   check_matching (message1, 1,
   2779                   path_namespace_should_match_message_1,
   2780                   path_namespace_should_not_match_message_1);
   2781   check_matching (message2, 2,
   2782                   path_namespace_should_match_message_2,
   2783                   path_namespace_should_not_match_message_2);
   2784   check_matching (message3, 3,
   2785                   path_namespace_should_match_message_3,
   2786                   path_namespace_should_not_match_message_3);
   2787 
   2788   dbus_message_unref (message3);
   2789   dbus_message_unref (message2);
   2790   dbus_message_unref (message1);
   2791 }
   2792 
   2793 dbus_bool_t
   2794 bus_signals_test (const DBusString *test_data_dir)
   2795 {
   2796   BusMatchmaker *matchmaker;
   2797 
   2798   matchmaker = bus_matchmaker_new ();
   2799   bus_matchmaker_ref (matchmaker);
   2800   bus_matchmaker_unref (matchmaker);
   2801   bus_matchmaker_unref (matchmaker);
   2802 
   2803   if (!_dbus_test_oom_handling ("parsing match rules", test_parsing, NULL))
   2804     _dbus_assert_not_reached ("Parsing match rules test failed");
   2805 
   2806   test_equality ();
   2807   test_matching ();
   2808   test_path_matching ();
   2809   test_matching_path_namespace ();
   2810 
   2811   return TRUE;
   2812 }
   2813 
   2814 #endif /* DBUS_BUILD_TESTS */
   2815 
   2816