LCOV - code coverage report
Current view: top level - glib/gio - gdbusdaemon.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 0 740 0.0 %
Date: 2024-04-16 05:15:53 Functions: 0 60 0.0 %
Branches: 0 374 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright © 2012 Red Hat, Inc.
       3                 :            :  *
       4                 :            :  * SPDX-License-Identifier: LGPL-2.1-or-later
       5                 :            :  *
       6                 :            :  * This library is free software; you can redistribute it and/or
       7                 :            :  * modify it under the terms of the GNU Lesser General Public
       8                 :            :  * License as published by the Free Software Foundation; either
       9                 :            :  * version 2.1 of the License, or (at your option) any later version.
      10                 :            :  *
      11                 :            :  * This library is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14                 :            :  * Lesser General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU Lesser General
      17                 :            :  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      18                 :            :  *
      19                 :            :  * Authors: Alexander Larsson <alexl@redhat.com>
      20                 :            :  */
      21                 :            : 
      22                 :            : #include "config.h"
      23                 :            : 
      24                 :            : #include <string.h>
      25                 :            : #include <stdlib.h>
      26                 :            : 
      27                 :            : #include <gstdio.h>
      28                 :            : #include <gio/gio.h>
      29                 :            : #include <gio/gunixsocketaddress.h>
      30                 :            : #include "gdbusdaemon.h"
      31                 :            : #include "glibintl.h"
      32                 :            : 
      33                 :            : #include "gdbus-daemon-generated.h"
      34                 :            : 
      35                 :            : #define DBUS_SERVICE_NAME  "org.freedesktop.DBus"
      36                 :            : 
      37                 :            : /* Owner flags */
      38                 :            : #define DBUS_NAME_FLAG_ALLOW_REPLACEMENT 0x1 /**< Allow another service to become the primary owner if requested */
      39                 :            : #define DBUS_NAME_FLAG_REPLACE_EXISTING  0x2 /**< Request to replace the current primary owner */
      40                 :            : #define DBUS_NAME_FLAG_DO_NOT_QUEUE      0x4 /**< If we can not become the primary owner do not place us in the queue */
      41                 :            : 
      42                 :            : /* Replies to request for a name */
      43                 :            : #define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER  1 /**< Service has become the primary owner of the requested name */
      44                 :            : #define DBUS_REQUEST_NAME_REPLY_IN_QUEUE       2 /**< Service could not become the primary owner and has been placed in the queue */
      45                 :            : #define DBUS_REQUEST_NAME_REPLY_EXISTS         3 /**< Service is already in the queue */
      46                 :            : #define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER  4 /**< Service is already the primary owner */
      47                 :            : 
      48                 :            : /* Replies to releasing a name */
      49                 :            : #define DBUS_RELEASE_NAME_REPLY_RELEASED        1 /**< Service was released from the given name */
      50                 :            : #define DBUS_RELEASE_NAME_REPLY_NON_EXISTENT    2 /**< The given name does not exist on the bus */
      51                 :            : #define DBUS_RELEASE_NAME_REPLY_NOT_OWNER       3 /**< Service is not an owner of the given name */
      52                 :            : 
      53                 :            : /* Replies to service starts */
      54                 :            : #define DBUS_START_REPLY_SUCCESS         1 /**< Service was auto started */
      55                 :            : #define DBUS_START_REPLY_ALREADY_RUNNING 2 /**< Service was already running */
      56                 :            : 
      57                 :            : #define IDLE_TIMEOUT_MSEC 3000
      58                 :            : 
      59                 :            : struct _GDBusDaemon
      60                 :            : {
      61                 :            :   _GFreedesktopDBusSkeleton parent_instance;
      62                 :            : 
      63                 :            :   gchar *address;
      64                 :            :   guint timeout;
      65                 :            :   gchar *tmpdir;
      66                 :            :   GDBusServer *server;
      67                 :            :   gchar *guid;
      68                 :            :   GHashTable *clients;
      69                 :            :   GHashTable *names;
      70                 :            :   guint32 next_major_id;
      71                 :            :   guint32 next_minor_id;
      72                 :            : };
      73                 :            : 
      74                 :            : struct _GDBusDaemonClass
      75                 :            : {
      76                 :            :   _GFreedesktopDBusSkeletonClass parent_class;
      77                 :            : };
      78                 :            : 
      79                 :            : enum {
      80                 :            :   PROP_0,
      81                 :            :   PROP_ADDRESS,
      82                 :            : };
      83                 :            : 
      84                 :            : enum
      85                 :            : {
      86                 :            :   SIGNAL_IDLE_TIMEOUT,
      87                 :            :   NR_SIGNALS
      88                 :            : };
      89                 :            : 
      90                 :            : static guint g_dbus_daemon_signals[NR_SIGNALS];
      91                 :            : 
      92                 :            : 
      93                 :            : static void initable_iface_init      (GInitableIface         *initable_iface);
      94                 :            : static void g_dbus_daemon_iface_init (_GFreedesktopDBusIface *iface);
      95                 :            : 
      96                 :            : #define g_dbus_daemon_get_type _g_dbus_daemon_get_type
      97   [ #  #  #  #  :          0 : G_DEFINE_TYPE_WITH_CODE (GDBusDaemon, g_dbus_daemon, _G_TYPE_FREEDESKTOP_DBUS_SKELETON,
                   #  # ]
      98                 :            :                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
      99                 :            :                          G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS, g_dbus_daemon_iface_init))
     100                 :            : 
     101                 :            : typedef struct {
     102                 :            :   GDBusDaemon *daemon;
     103                 :            :   char *id;
     104                 :            :   GDBusConnection *connection;
     105                 :            :   GList *matches;
     106                 :            : } Client;
     107                 :            : 
     108                 :            : typedef struct {
     109                 :            :   Client *client;
     110                 :            :   guint32 flags;
     111                 :            : } NameOwner;
     112                 :            : 
     113                 :            : typedef struct {
     114                 :            :   int refcount;
     115                 :            : 
     116                 :            :   char *name;
     117                 :            :   GDBusDaemon *daemon;
     118                 :            : 
     119                 :            :   NameOwner *owner;
     120                 :            :   GList *queue;
     121                 :            : } Name;
     122                 :            : 
     123                 :            : enum {
     124                 :            :   MATCH_ELEMENT_TYPE,
     125                 :            :   MATCH_ELEMENT_SENDER,
     126                 :            :   MATCH_ELEMENT_INTERFACE,
     127                 :            :   MATCH_ELEMENT_MEMBER,
     128                 :            :   MATCH_ELEMENT_PATH,
     129                 :            :   MATCH_ELEMENT_PATH_NAMESPACE,
     130                 :            :   MATCH_ELEMENT_DESTINATION,
     131                 :            :   MATCH_ELEMENT_ARG0NAMESPACE,
     132                 :            :   MATCH_ELEMENT_EAVESDROP,
     133                 :            :   MATCH_ELEMENT_ARGN,
     134                 :            :   MATCH_ELEMENT_ARGNPATH,
     135                 :            : };
     136                 :            : 
     137                 :            : typedef struct {
     138                 :            :   guint16 type;
     139                 :            :   guint16 arg;
     140                 :            :   char *value;
     141                 :            : } MatchElement;
     142                 :            : 
     143                 :            : typedef struct {
     144                 :            :   gboolean eavesdrop;
     145                 :            :   GDBusMessageType type;
     146                 :            :   int n_elements;
     147                 :            :   MatchElement *elements;
     148                 :            : } Match;
     149                 :            : 
     150                 :            : static GDBusMessage *filter_function   (GDBusConnection *connection,
     151                 :            :                                         GDBusMessage    *message,
     152                 :            :                                         gboolean         incoming,
     153                 :            :                                         gpointer         user_data);
     154                 :            : static void          connection_closed (GDBusConnection *connection,
     155                 :            :                                         gboolean         remote_peer_vanished,
     156                 :            :                                         GError          *error,
     157                 :            :                                         Client          *client);
     158                 :            : 
     159                 :            : static NameOwner *
     160                 :          0 : name_owner_new (Client *client, guint32 flags)
     161                 :            : {
     162                 :            :   NameOwner *owner;
     163                 :            : 
     164                 :          0 :   owner = g_new0 (NameOwner, 1);
     165                 :          0 :   owner->client = client;
     166                 :          0 :   owner->flags = flags;
     167                 :          0 :   return owner;
     168                 :            : }
     169                 :            : 
     170                 :            : static void
     171                 :          0 : name_owner_free (NameOwner *owner)
     172                 :            : {
     173                 :          0 :   g_free (owner);
     174                 :          0 : }
     175                 :            : 
     176                 :            : static Name *
     177                 :          0 : name_new (GDBusDaemon *daemon, const char *str)
     178                 :            : {
     179                 :            :   Name *name;
     180                 :            : 
     181                 :          0 :   name = g_new0 (Name, 1);
     182                 :          0 :   name->refcount = 1;
     183                 :          0 :   name->daemon = daemon;
     184                 :          0 :   name->name = g_strdup (str);
     185                 :            : 
     186                 :          0 :   g_hash_table_insert (daemon->names, name->name, name);
     187                 :            : 
     188                 :          0 :   return name;
     189                 :            : }
     190                 :            : 
     191                 :            : static Name *
     192                 :          0 : name_ref (Name *name)
     193                 :            : {
     194                 :          0 :   g_assert (name->refcount > 0);
     195                 :          0 :   name->refcount++;
     196                 :          0 :   return name;
     197                 :            : }
     198                 :            : 
     199                 :            : static void
     200                 :          0 : name_unref (Name *name)
     201                 :            : {
     202                 :          0 :   g_assert (name->refcount > 0);
     203         [ #  # ]:          0 :   if (--name->refcount == 0)
     204                 :            :     {
     205                 :          0 :       g_hash_table_remove (name->daemon->names, name->name);
     206                 :          0 :       g_free (name->name);
     207                 :          0 :       g_free (name);
     208                 :            :     }
     209                 :          0 : }
     210                 :            : 
     211                 :            : static Name *
     212                 :          0 : name_ensure (GDBusDaemon *daemon, const char *str)
     213                 :            : {
     214                 :            :   Name *name;
     215                 :            : 
     216                 :          0 :   name = g_hash_table_lookup (daemon->names, str);
     217                 :            : 
     218         [ #  # ]:          0 :   if (name != NULL)
     219                 :          0 :     return name_ref (name);
     220                 :          0 :   return name_new (daemon, str);
     221                 :            : }
     222                 :            : 
     223                 :            : static Name *
     224                 :          0 : name_lookup (GDBusDaemon *daemon, const char *str)
     225                 :            : {
     226                 :          0 :   return g_hash_table_lookup (daemon->names, str);
     227                 :            : }
     228                 :            : 
     229                 :            : static gboolean
     230                 :          0 : is_key (const char *key_start, const char *key_end, const char *value)
     231                 :            : {
     232                 :          0 :   gsize len = strlen (value);
     233                 :            : 
     234                 :          0 :   g_assert (key_end >= key_start);
     235         [ #  # ]:          0 :   if (len != (gsize) (key_end - key_start))
     236                 :          0 :     return FALSE;
     237                 :            : 
     238                 :          0 :   return strncmp (key_start, value, len) == 0;
     239                 :            : }
     240                 :            : 
     241                 :            : static gboolean
     242                 :          0 : parse_key (MatchElement *element, const char *key_start, const char *key_end)
     243                 :            : {
     244                 :          0 :   gboolean res = TRUE;
     245                 :            : 
     246         [ #  # ]:          0 :   if (is_key (key_start, key_end, "type"))
     247                 :            :     {
     248                 :          0 :       element->type = MATCH_ELEMENT_TYPE;
     249                 :            :     }
     250         [ #  # ]:          0 :   else if (is_key (key_start, key_end, "sender"))
     251                 :            :     {
     252                 :          0 :       element->type = MATCH_ELEMENT_SENDER;
     253                 :            :     }
     254         [ #  # ]:          0 :   else if (is_key (key_start, key_end, "interface"))
     255                 :            :     {
     256                 :          0 :       element->type = MATCH_ELEMENT_INTERFACE;
     257                 :            :     }
     258         [ #  # ]:          0 :   else if (is_key (key_start, key_end, "member"))
     259                 :            :     {
     260                 :          0 :       element->type = MATCH_ELEMENT_MEMBER;
     261                 :            :     }
     262         [ #  # ]:          0 :   else if (is_key (key_start, key_end, "path"))
     263                 :            :     {
     264                 :          0 :       element->type = MATCH_ELEMENT_PATH;
     265                 :            :     }
     266         [ #  # ]:          0 :   else if (is_key (key_start, key_end, "path_namespace"))
     267                 :            :     {
     268                 :          0 :       element->type = MATCH_ELEMENT_PATH_NAMESPACE;
     269                 :            :     }
     270         [ #  # ]:          0 :   else if (is_key (key_start, key_end, "destination"))
     271                 :            :     {
     272                 :          0 :       element->type = MATCH_ELEMENT_DESTINATION;
     273                 :            :     }
     274         [ #  # ]:          0 :   else if (is_key (key_start, key_end, "arg0namespace"))
     275                 :            :     {
     276                 :          0 :       element->type = MATCH_ELEMENT_ARG0NAMESPACE;
     277                 :            :     }
     278         [ #  # ]:          0 :   else if (is_key (key_start, key_end, "eavesdrop"))
     279                 :            :     {
     280                 :          0 :       element->type = MATCH_ELEMENT_EAVESDROP;
     281                 :            :     }
     282   [ #  #  #  # ]:          0 :   else if (key_end - key_start > 3 && is_key (key_start, key_start + 3, "arg"))
     283                 :          0 :     {
     284                 :          0 :       const char *digits = key_start + 3;
     285                 :          0 :       const char *end_digits = digits;
     286                 :            : 
     287   [ #  #  #  # ]:          0 :       while (end_digits < key_end && g_ascii_isdigit (*end_digits))
     288                 :          0 :         end_digits++;
     289                 :            : 
     290         [ #  # ]:          0 :       if (end_digits == key_end) /* argN */
     291                 :            :         {
     292                 :          0 :           element->type = MATCH_ELEMENT_ARGN;
     293                 :          0 :           element->arg = atoi (digits);
     294                 :            :         }
     295         [ #  # ]:          0 :       else if (is_key (end_digits, key_end, "path")) /* argNpath */
     296                 :            :         {
     297                 :          0 :           element->type = MATCH_ELEMENT_ARGNPATH;
     298                 :          0 :           element->arg = atoi (digits);
     299                 :            :         }
     300                 :            :       else
     301                 :          0 :         res = FALSE;
     302                 :            :     }
     303                 :            :   else
     304                 :          0 :     res = FALSE;
     305                 :            : 
     306                 :          0 :   return res;
     307                 :            : }
     308                 :            : 
     309                 :            : static const char *
     310                 :          0 : parse_value (MatchElement *element, const char *s)
     311                 :            : {
     312                 :            :   char quote_char;
     313                 :            :   GString *value;
     314                 :            : 
     315                 :          0 :   value = g_string_new ("");
     316                 :            : 
     317                 :          0 :   quote_char = 0;
     318                 :            : 
     319         [ #  # ]:          0 :   for (;*s; s++)
     320                 :            :     {
     321         [ #  # ]:          0 :       if (quote_char == 0)
     322                 :            :         {
     323   [ #  #  #  # ]:          0 :           switch (*s)
     324                 :            :             {
     325                 :          0 :             case '\'':
     326                 :          0 :               quote_char = '\'';
     327                 :          0 :               break;
     328                 :            : 
     329                 :          0 :             case ',':
     330                 :          0 :               s++;
     331                 :          0 :               goto out;
     332                 :            : 
     333                 :          0 :             case '\\':
     334                 :          0 :               quote_char = '\\';
     335                 :          0 :               break;
     336                 :            : 
     337                 :          0 :             default:
     338         [ #  # ]:          0 :               g_string_append_c (value, *s);
     339                 :          0 :               break;
     340                 :            :             }
     341                 :            :         }
     342         [ #  # ]:          0 :       else if (quote_char == '\\')
     343                 :            :         {
     344                 :            :           /* \ only counts as an escape if escaping a quote mark */
     345         [ #  # ]:          0 :           if (*s != '\'')
     346                 :            :             g_string_append_c (value, '\\');
     347                 :            : 
     348         [ #  # ]:          0 :           g_string_append_c (value, *s);
     349                 :          0 :           quote_char = 0;
     350                 :            :         }
     351                 :            :       else /* quote_char == ' */
     352                 :            :         {
     353         [ #  # ]:          0 :           if (*s == '\'')
     354                 :          0 :             quote_char = 0;
     355                 :            :           else
     356         [ #  # ]:          0 :             g_string_append_c (value, *s);
     357                 :            :         }
     358                 :            :     }
     359                 :            : 
     360                 :          0 :  out:
     361                 :            : 
     362         [ #  # ]:          0 :   if (quote_char == '\\')
     363                 :            :     g_string_append_c (value, '\\');
     364         [ #  # ]:          0 :   else if (quote_char == '\'')
     365                 :            :     {
     366                 :          0 :       g_string_free (value, TRUE);
     367                 :          0 :       return NULL;
     368                 :            :     }
     369                 :            : 
     370                 :          0 :   element->value = g_string_free (value, FALSE);
     371                 :          0 :   return s;
     372                 :            : }
     373                 :            : 
     374                 :            : static Match *
     375                 :          0 : match_new (const char *str)
     376                 :            : {
     377                 :            :   Match *match;
     378                 :            :   GArray *elements;
     379                 :            :   const char *p;
     380                 :            :   const char *key_start;
     381                 :            :   const char *key_end;
     382                 :            :   MatchElement element;
     383                 :            :   gboolean eavesdrop;
     384                 :            :   GDBusMessageType type;
     385                 :            :   gsize i;
     386                 :            : 
     387                 :          0 :   eavesdrop = FALSE;
     388                 :          0 :   type = G_DBUS_MESSAGE_TYPE_INVALID;
     389                 :          0 :   elements = g_array_new (TRUE, TRUE, sizeof (MatchElement));
     390                 :            : 
     391                 :          0 :   p = str;
     392                 :            : 
     393         [ #  # ]:          0 :   while (*p != 0)
     394                 :            :     {
     395                 :          0 :       memset (&element, 0, sizeof (element));
     396                 :            : 
     397                 :            :       /* Skip initial whitespace */
     398   [ #  #  #  # ]:          0 :       while (*p && g_ascii_isspace (*p))
     399                 :          0 :         p++;
     400                 :            : 
     401                 :          0 :       key_start = p;
     402                 :            : 
     403                 :            :       /* Read non-whitespace non-equals chars */
     404   [ #  #  #  #  :          0 :       while (*p && *p != '=' && !g_ascii_isspace (*p))
                   #  # ]
     405                 :          0 :         p++;
     406                 :            : 
     407                 :          0 :       key_end = p;
     408                 :            : 
     409                 :            :       /* Skip any whitespace after key */
     410   [ #  #  #  # ]:          0 :       while (*p && g_ascii_isspace (*p))
     411                 :          0 :         p++;
     412                 :            : 
     413         [ #  # ]:          0 :       if (key_start == key_end)
     414                 :          0 :         continue; /* Allow trailing whitespace */
     415                 :            : 
     416         [ #  # ]:          0 :       if (*p != '=')
     417                 :          0 :         goto error;
     418                 :            : 
     419                 :          0 :       ++p;
     420                 :            : 
     421         [ #  # ]:          0 :       if (!parse_key (&element, key_start, key_end))
     422                 :          0 :         goto error;
     423                 :            : 
     424                 :          0 :       p = parse_value (&element, p);
     425         [ #  # ]:          0 :       if (p == NULL)
     426                 :          0 :         goto error;
     427                 :            : 
     428         [ #  # ]:          0 :       if (element.type == MATCH_ELEMENT_EAVESDROP)
     429                 :            :         {
     430         [ #  # ]:          0 :           if (strcmp (element.value, "true") == 0)
     431                 :          0 :             eavesdrop = TRUE;
     432         [ #  # ]:          0 :           else if (strcmp (element.value, "false") == 0)
     433                 :          0 :             eavesdrop = FALSE;
     434                 :            :           else
     435                 :            :             {
     436                 :          0 :               g_free (element.value);
     437                 :          0 :               goto error;
     438                 :            :             }
     439                 :          0 :           g_free (element.value);
     440                 :            :         }
     441         [ #  # ]:          0 :       else if (element.type == MATCH_ELEMENT_TYPE)
     442                 :            :         {
     443         [ #  # ]:          0 :           if (strcmp (element.value, "signal") == 0)
     444                 :          0 :             type = G_DBUS_MESSAGE_TYPE_SIGNAL;
     445         [ #  # ]:          0 :           else if (strcmp (element.value, "method_call") == 0)
     446                 :          0 :             type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
     447         [ #  # ]:          0 :           else if (strcmp (element.value, "method_return") == 0)
     448                 :          0 :             type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
     449         [ #  # ]:          0 :           else if (strcmp (element.value, "error") == 0)
     450                 :          0 :             type = G_DBUS_MESSAGE_TYPE_ERROR;
     451                 :            :           else
     452                 :            :             {
     453                 :          0 :               g_free (element.value);
     454                 :          0 :               goto error;
     455                 :            :             }
     456                 :          0 :           g_free (element.value);
     457                 :            :         }
     458                 :            :       else
     459                 :          0 :         g_array_append_val (elements, element);
     460                 :            :     }
     461                 :            : 
     462                 :          0 :   match = g_new0 (Match, 1);
     463                 :          0 :   match->n_elements = elements->len;
     464                 :          0 :   match->elements = (MatchElement *)g_array_free (elements, FALSE);
     465                 :          0 :   match->eavesdrop = eavesdrop;
     466                 :          0 :   match->type = type;
     467                 :            : 
     468                 :          0 :   return match;
     469                 :            : 
     470                 :          0 :  error:
     471         [ #  # ]:          0 :   for (i = 0; i < elements->len; i++)
     472                 :          0 :     g_free (g_array_index (elements, MatchElement, i).value);
     473                 :          0 :   g_array_free (elements, TRUE);
     474                 :          0 :   return NULL;
     475                 :            : }
     476                 :            : 
     477                 :            : static void
     478                 :          0 : match_free (Match *match)
     479                 :            : {
     480                 :            :   int i;
     481         [ #  # ]:          0 :   for (i = 0; i < match->n_elements; i++)
     482                 :          0 :     g_free (match->elements[i].value);
     483                 :          0 :   g_free (match->elements);
     484                 :          0 :   g_free (match);
     485                 :          0 : }
     486                 :            : 
     487                 :            : static gboolean
     488                 :          0 : match_equal (Match *a, Match *b)
     489                 :            : {
     490                 :            :   int i;
     491                 :            : 
     492         [ #  # ]:          0 :   if (a->eavesdrop != b->eavesdrop)
     493                 :          0 :     return FALSE;
     494         [ #  # ]:          0 :   if (a->type != b->type)
     495                 :          0 :     return FALSE;
     496         [ #  # ]:          0 :  if (a->n_elements != b->n_elements)
     497                 :          0 :     return FALSE;
     498         [ #  # ]:          0 :   for (i = 0; i < a->n_elements; i++)
     499                 :            :     {
     500         [ #  # ]:          0 :       if (a->elements[i].type != b->elements[i].type ||
     501         [ #  # ]:          0 :           a->elements[i].arg != b->elements[i].arg ||
     502         [ #  # ]:          0 :           strcmp (a->elements[i].value, b->elements[i].value) != 0)
     503                 :          0 :         return FALSE;
     504                 :            :     }
     505                 :          0 :   return TRUE;
     506                 :            : }
     507                 :            : 
     508                 :            : static const gchar *
     509                 :          0 : message_get_argN (GDBusMessage *message, int n, gboolean allow_path)
     510                 :            : {
     511                 :            :   const gchar *ret;
     512                 :            :   GVariant *body;
     513                 :            : 
     514                 :          0 :   ret = NULL;
     515                 :            : 
     516                 :          0 :   body = g_dbus_message_get_body (message);
     517                 :            : 
     518   [ #  #  #  # ]:          0 :   if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE))
     519                 :            :     {
     520                 :            :       GVariant *item;
     521                 :          0 :       item = g_variant_get_child_value (body, n);
     522   [ #  #  #  # ]:          0 :       if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING) ||
     523         [ #  # ]:          0 :           (allow_path && g_variant_is_of_type (item, G_VARIANT_TYPE_OBJECT_PATH)))
     524                 :          0 :         ret = g_variant_get_string (item, NULL);
     525                 :          0 :       g_variant_unref (item);
     526                 :            :     }
     527                 :            : 
     528                 :          0 :   return ret;
     529                 :            : }
     530                 :            : 
     531                 :            : enum {
     532                 :            :   CHECK_TYPE_STRING,
     533                 :            :   CHECK_TYPE_NAME,
     534                 :            :   CHECK_TYPE_PATH_PREFIX,
     535                 :            :   CHECK_TYPE_PATH_RELATED,
     536                 :            :   CHECK_TYPE_NAMESPACE_PREFIX
     537                 :            : };
     538                 :            : 
     539                 :            : static gboolean
     540                 :          0 : match_matches (GDBusDaemon *daemon,
     541                 :            :                Match *match, GDBusMessage *message,
     542                 :            :                gboolean has_destination)
     543                 :            : {
     544                 :            :   MatchElement *element;
     545                 :            :   Name *name;
     546                 :            :   int i, len, len2;
     547                 :            :   const char *value;
     548                 :            :   int check_type;
     549                 :            : 
     550   [ #  #  #  # ]:          0 :   if (has_destination && !match->eavesdrop)
     551                 :          0 :     return FALSE;
     552                 :            : 
     553         [ #  # ]:          0 :   if (match->type != G_DBUS_MESSAGE_TYPE_INVALID &&
     554         [ #  # ]:          0 :       g_dbus_message_get_message_type (message) != match->type)
     555                 :          0 :     return FALSE;
     556                 :            : 
     557         [ #  # ]:          0 :   for (i = 0; i < match->n_elements; i++)
     558                 :            :     {
     559                 :          0 :       element = &match->elements[i];
     560                 :          0 :       check_type = CHECK_TYPE_STRING;
     561   [ #  #  #  #  :          0 :       switch (element->type)
          #  #  #  #  #  
                      # ]
     562                 :            :         {
     563                 :          0 :         case MATCH_ELEMENT_SENDER:
     564                 :          0 :           check_type = CHECK_TYPE_NAME;
     565                 :          0 :           value = g_dbus_message_get_sender (message);
     566         [ #  # ]:          0 :           if (value == NULL)
     567                 :          0 :             value = DBUS_SERVICE_NAME;
     568                 :          0 :           break;
     569                 :          0 :         case MATCH_ELEMENT_DESTINATION:
     570                 :          0 :           check_type = CHECK_TYPE_NAME;
     571                 :          0 :           value = g_dbus_message_get_destination (message);
     572                 :          0 :           break;
     573                 :          0 :         case MATCH_ELEMENT_INTERFACE:
     574                 :          0 :           value = g_dbus_message_get_interface (message);
     575                 :          0 :           break;
     576                 :          0 :         case MATCH_ELEMENT_MEMBER:
     577                 :          0 :           value = g_dbus_message_get_member (message);
     578                 :          0 :           break;
     579                 :          0 :         case MATCH_ELEMENT_PATH:
     580                 :          0 :           value = g_dbus_message_get_path (message);
     581                 :          0 :           break;
     582                 :          0 :         case MATCH_ELEMENT_PATH_NAMESPACE:
     583                 :          0 :           check_type = CHECK_TYPE_PATH_PREFIX;
     584                 :          0 :           value = g_dbus_message_get_path (message);
     585                 :          0 :           break;
     586                 :          0 :         case MATCH_ELEMENT_ARG0NAMESPACE:
     587                 :          0 :           check_type = CHECK_TYPE_NAMESPACE_PREFIX;
     588                 :          0 :           value = message_get_argN (message, 0, FALSE);
     589                 :          0 :           break;
     590                 :          0 :         case MATCH_ELEMENT_ARGN:
     591                 :          0 :           value = message_get_argN (message, element->arg, FALSE);
     592                 :          0 :           break;
     593                 :          0 :         case MATCH_ELEMENT_ARGNPATH:
     594                 :          0 :           check_type = CHECK_TYPE_PATH_RELATED;
     595                 :          0 :           value = message_get_argN (message, element->arg, TRUE);
     596                 :          0 :           break;
     597                 :          0 :         default:
     598                 :            :         case MATCH_ELEMENT_TYPE:
     599                 :            :         case MATCH_ELEMENT_EAVESDROP:
     600                 :            :           g_assert_not_reached ();
     601                 :            :         }
     602                 :            : 
     603         [ #  # ]:          0 :       if (value == NULL)
     604                 :          0 :         return FALSE;
     605                 :            : 
     606   [ #  #  #  #  :          0 :       switch (check_type)
                   #  # ]
     607                 :            :         {
     608                 :          0 :         case CHECK_TYPE_STRING:
     609         [ #  # ]:          0 :           if (strcmp (element->value, value) != 0)
     610                 :          0 :             return FALSE;
     611                 :          0 :           break;
     612                 :          0 :         case CHECK_TYPE_NAME:
     613                 :          0 :           name = name_lookup (daemon, element->value);
     614   [ #  #  #  # ]:          0 :           if (name != NULL && name->owner != NULL)
     615                 :            :             {
     616         [ #  # ]:          0 :               if (strcmp (name->owner->client->id, value) != 0)
     617                 :          0 :                 return FALSE;
     618                 :            :             }
     619         [ #  # ]:          0 :           else if (strcmp (element->value, value) != 0)
     620                 :          0 :             return FALSE;
     621                 :          0 :           break;
     622                 :          0 :         case CHECK_TYPE_PATH_PREFIX:
     623                 :          0 :           len = strlen (element->value);
     624                 :            : 
     625                 :            :           /* Make sure to handle the case of element->value == '/'. */
     626         [ #  # ]:          0 :           if (len == 1)
     627                 :          0 :             break;
     628                 :            : 
     629                 :            :           /* Fail if there's no prefix match, or if the prefix match doesn't
     630                 :            :            * finish at the end of or at a separator in the @value. */
     631         [ #  # ]:          0 :           if (!g_str_has_prefix (value, element->value))
     632                 :          0 :             return FALSE;
     633   [ #  #  #  # ]:          0 :           if (value[len] != 0 && value[len] != '/')
     634                 :          0 :             return FALSE;
     635                 :            : 
     636                 :          0 :           break;
     637                 :          0 :         case CHECK_TYPE_PATH_RELATED:
     638                 :          0 :           len = strlen (element->value);
     639                 :          0 :           len2 = strlen (value);
     640                 :            : 
     641   [ #  #  #  #  :          0 :           if (!(strcmp (value, element->value) == 0 ||
                   #  # ]
     642   [ #  #  #  # ]:          0 :                 (len2 > 0 && value[len2-1] == '/' && g_str_has_prefix (element->value, value)) ||
     643   [ #  #  #  # ]:          0 :                 (len > 0 && element->value[len-1] == '/' && g_str_has_prefix (value, element->value))))
     644                 :          0 :             return FALSE;
     645                 :          0 :           break;
     646                 :          0 :         case CHECK_TYPE_NAMESPACE_PREFIX:
     647                 :          0 :           len = strlen (element->value);
     648         [ #  # ]:          0 :           if (!(g_str_has_prefix (value, element->value) &&
     649   [ #  #  #  # ]:          0 :                 (value[len] == 0 || value[len] == '.')))
     650                 :          0 :             return FALSE;
     651                 :          0 :           break;
     652                 :          0 :         default:
     653                 :            :           g_assert_not_reached ();
     654                 :            :         }
     655                 :            :     }
     656                 :            : 
     657                 :          0 :   return TRUE;
     658                 :            : }
     659                 :            : 
     660                 :            : static void
     661                 :          0 : broadcast_message (GDBusDaemon *daemon,
     662                 :            :                    GDBusMessage *message,
     663                 :            :                    gboolean has_destination,
     664                 :            :                    gboolean preserve_serial,
     665                 :            :                    Client *not_to)
     666                 :            : {
     667                 :            :   GList *clients, *l, *ll;
     668                 :            :   GDBusMessage *copy;
     669                 :            : 
     670                 :          0 :   clients = g_hash_table_get_values (daemon->clients);
     671         [ #  # ]:          0 :   for (l = clients; l != NULL; l = l->next)
     672                 :            :     {
     673                 :          0 :       Client *client = l->data;
     674                 :            : 
     675         [ #  # ]:          0 :       if (client == not_to)
     676                 :          0 :         continue;
     677                 :            : 
     678         [ #  # ]:          0 :       for (ll = client->matches; ll != NULL; ll = ll->next)
     679                 :            :         {
     680                 :          0 :           Match *match = ll->data;
     681                 :            : 
     682         [ #  # ]:          0 :           if (match_matches (daemon, match, message, has_destination))
     683                 :          0 :             break;
     684                 :            :         }
     685                 :            : 
     686         [ #  # ]:          0 :       if (ll != NULL)
     687                 :            :         {
     688                 :          0 :           copy = g_dbus_message_copy (message, NULL);
     689         [ #  # ]:          0 :           if (copy)
     690                 :            :             {
     691                 :          0 :               g_dbus_connection_send_message (client->connection, copy,
     692                 :            :                                               preserve_serial?G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL:0, NULL, NULL);
     693                 :          0 :               g_object_unref (copy);
     694                 :            :             }
     695                 :            :         }
     696                 :            :     }
     697                 :            : 
     698                 :          0 :   g_list_free (clients);
     699                 :          0 : }
     700                 :            : 
     701                 :            : static void
     702                 :          0 : send_name_owner_changed (GDBusDaemon *daemon,
     703                 :            :                          const char *name,
     704                 :            :                          const char *old_owner,
     705                 :            :                          const char *new_owner)
     706                 :            : {
     707                 :            :   GDBusMessage *signal_message;
     708                 :            : 
     709                 :          0 :   signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
     710                 :            :                                               "org.freedesktop.DBus",
     711                 :            :                                               "NameOwnerChanged");
     712   [ #  #  #  # ]:          0 :   g_dbus_message_set_body (signal_message,
     713                 :            :                            g_variant_new ("(sss)",
     714                 :            :                                           name,
     715                 :            :                                           old_owner ? old_owner : "",
     716                 :            :                                           new_owner ? new_owner : ""));
     717                 :            : 
     718                 :          0 :   broadcast_message (daemon, signal_message, FALSE, FALSE, NULL);
     719                 :          0 :   g_object_unref (signal_message);
     720                 :            : 
     721                 :          0 : }
     722                 :            : 
     723                 :            : static gboolean
     724                 :          0 : name_unqueue_owner (Name *name, Client *client)
     725                 :            : {
     726                 :            :   GList *l;
     727                 :            : 
     728         [ #  # ]:          0 :   for (l = name->queue; l != NULL; l = l->next)
     729                 :            :     {
     730                 :          0 :       NameOwner *other = l->data;
     731                 :            : 
     732         [ #  # ]:          0 :       if (other->client == client)
     733                 :            :         {
     734                 :          0 :           name->queue = g_list_delete_link (name->queue, l);
     735                 :          0 :           name_unref (name);
     736                 :          0 :           name_owner_free (other);
     737                 :          0 :           return TRUE;
     738                 :            :         }
     739                 :            :     }
     740                 :            : 
     741                 :          0 :   return FALSE;
     742                 :            : }
     743                 :            : 
     744                 :            : static void
     745                 :          0 : name_replace_owner (Name *name, NameOwner *owner)
     746                 :            : {
     747                 :          0 :   GDBusDaemon *daemon = name->daemon;
     748                 :            :   NameOwner *old_owner;
     749                 :          0 :   char *old_name = NULL, *new_name = NULL;
     750                 :          0 :   Client *new_client = NULL;
     751                 :            : 
     752         [ #  # ]:          0 :   if (owner)
     753                 :          0 :     new_client = owner->client;
     754                 :            : 
     755                 :          0 :   name_ref (name);
     756                 :            : 
     757                 :          0 :   old_owner = name->owner;
     758         [ #  # ]:          0 :   if (old_owner)
     759                 :            :     {
     760                 :          0 :       Client *old_client = old_owner->client;
     761                 :            : 
     762                 :          0 :       g_assert (old_owner->client != new_client);
     763                 :            : 
     764                 :          0 :       g_dbus_connection_emit_signal (old_client->connection,
     765                 :            :                                      NULL, "/org/freedesktop/DBus",
     766                 :            :                                      "org.freedesktop.DBus", "NameLost",
     767                 :            :                                      g_variant_new ("(s)",
     768                 :            :                                                     name->name), NULL);
     769                 :            : 
     770                 :          0 :       old_name = g_strdup (old_client->id);
     771         [ #  # ]:          0 :       if (old_owner->flags & DBUS_NAME_FLAG_DO_NOT_QUEUE)
     772                 :            :         {
     773                 :          0 :           name_unref (name);
     774                 :          0 :           name_owner_free (old_owner);
     775                 :            :         }
     776                 :            :       else
     777                 :          0 :         name->queue = g_list_prepend (name->queue, old_owner);
     778                 :            :     }
     779                 :            : 
     780                 :          0 :   name->owner = owner;
     781         [ #  # ]:          0 :   if (owner)
     782                 :            :     {
     783                 :          0 :       name_unqueue_owner (name, owner->client);
     784                 :          0 :       name_ref (name);
     785                 :          0 :       new_name = new_client->id;
     786                 :            : 
     787                 :          0 :       g_dbus_connection_emit_signal (new_client->connection,
     788                 :            :                                      NULL, "/org/freedesktop/DBus",
     789                 :            :                                      "org.freedesktop.DBus", "NameAcquired",
     790                 :            :                                      g_variant_new ("(s)",
     791                 :            :                                                     name->name), NULL);
     792                 :            :     }
     793                 :            : 
     794                 :          0 :   send_name_owner_changed (daemon, name->name, old_name, new_name);
     795                 :            : 
     796                 :          0 :   g_free (old_name);
     797                 :            : 
     798                 :          0 :   name_unref (name);
     799                 :          0 : }
     800                 :            : 
     801                 :            : static void
     802                 :          0 : name_release_owner (Name *name)
     803                 :            : {
     804                 :          0 :   NameOwner *next_owner = NULL;
     805                 :            : 
     806                 :          0 :   name_ref (name);
     807                 :            : 
     808                 :            :   /* Will someone else take over? */
     809         [ #  # ]:          0 :   if (name->queue)
     810                 :            :     {
     811                 :          0 :       next_owner = name->queue->data;
     812                 :          0 :       name_unref (name);
     813                 :          0 :       name->queue = g_list_delete_link (name->queue, name->queue);
     814                 :            :     }
     815                 :            : 
     816                 :          0 :   name->owner->flags |= DBUS_NAME_FLAG_DO_NOT_QUEUE;
     817                 :          0 :   name_replace_owner (name, next_owner);
     818                 :            : 
     819                 :          0 :   name_unref (name);
     820                 :          0 : }
     821                 :            : 
     822                 :            : static void
     823                 :          0 : name_queue_owner (Name *name, NameOwner *owner)
     824                 :            : {
     825                 :            :   GList *l;
     826                 :            : 
     827         [ #  # ]:          0 :   for (l = name->queue; l != NULL; l = l->next)
     828                 :            :     {
     829                 :          0 :       NameOwner *other = l->data;
     830                 :            : 
     831         [ #  # ]:          0 :       if (other->client == owner->client)
     832                 :            :         {
     833                 :          0 :           other->flags = owner->flags;
     834                 :          0 :           name_owner_free (owner);
     835                 :          0 :           return;
     836                 :            :         }
     837                 :            :     }
     838                 :            : 
     839                 :          0 :   name->queue = g_list_append (name->queue, owner);
     840                 :          0 :   name_ref (name);
     841                 :            : }
     842                 :            : 
     843                 :            : static Client *
     844                 :          0 : client_new (GDBusDaemon *daemon, GDBusConnection *connection)
     845                 :            : {
     846                 :            :   Client *client;
     847                 :          0 :   GError *error = NULL;
     848                 :            : 
     849                 :          0 :   client = g_new0 (Client, 1);
     850                 :          0 :   client->daemon = daemon;
     851                 :          0 :   client->id = g_strdup_printf (":%d.%d", daemon->next_major_id, daemon->next_minor_id);
     852                 :          0 :   client->connection = g_object_ref (connection);
     853                 :            : 
     854         [ #  # ]:          0 :   if (daemon->next_minor_id == G_MAXUINT32)
     855                 :            :     {
     856                 :          0 :       daemon->next_minor_id = 0;
     857                 :          0 :       daemon->next_major_id++;
     858                 :            :     }
     859                 :            :   else
     860                 :          0 :     daemon->next_minor_id++;
     861                 :            : 
     862                 :          0 :   g_object_set_data (G_OBJECT (connection), "client", client);
     863                 :          0 :   g_hash_table_insert (daemon->clients, client->id, client);
     864                 :            : 
     865                 :          0 :   g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon), connection,
     866                 :            :                                     "/org/freedesktop/DBus", &error);
     867                 :          0 :   g_assert_no_error (error);
     868                 :            : 
     869                 :          0 :   g_signal_connect (connection, "closed", G_CALLBACK (connection_closed), client);
     870                 :          0 :   g_dbus_connection_add_filter (connection,
     871                 :            :                                 filter_function,
     872                 :            :                                 client, NULL);
     873                 :            : 
     874                 :          0 :   send_name_owner_changed (daemon, client->id, NULL, client->id);
     875                 :            : 
     876                 :          0 :   return client;
     877                 :            : }
     878                 :            : 
     879                 :            : static void
     880                 :          0 : client_free (Client *client)
     881                 :            : {
     882                 :          0 :   GDBusDaemon *daemon = client->daemon;
     883                 :            :   GList *l, *names;
     884                 :            : 
     885                 :          0 :   g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (daemon),
     886                 :            :                                                       client->connection);
     887                 :            : 
     888                 :          0 :   g_hash_table_remove (daemon->clients, client->id);
     889                 :            : 
     890                 :          0 :   names = g_hash_table_get_values (daemon->names);
     891         [ #  # ]:          0 :   for (l = names; l != NULL; l = l->next)
     892                 :            :     {
     893                 :          0 :       Name *name = l->data;
     894                 :            : 
     895                 :          0 :       name_ref (name);
     896                 :            : 
     897   [ #  #  #  # ]:          0 :       if (name->owner && name->owner->client == client)
     898                 :            :         {
     899                 :            :           /* Help static analysers with the refcount at this point. */
     900                 :          0 :           g_assert (name->refcount >= 2);
     901                 :          0 :           name_release_owner (name);
     902                 :            :         }
     903                 :            : 
     904                 :          0 :       name_unqueue_owner (name, client);
     905                 :            : 
     906                 :          0 :       name_unref (name);
     907                 :            :     }
     908                 :          0 :   g_list_free (names);
     909                 :            : 
     910                 :          0 :   send_name_owner_changed (daemon, client->id, client->id, NULL);
     911                 :            : 
     912                 :          0 :   g_object_unref (client->connection);
     913                 :            : 
     914         [ #  # ]:          0 :   for (l = client->matches; l != NULL; l = l->next)
     915                 :          0 :     match_free (l->data);
     916                 :          0 :   g_list_free (client->matches);
     917                 :            : 
     918                 :          0 :   g_free (client->id);
     919                 :          0 :   g_free (client);
     920                 :          0 : }
     921                 :            : 
     922                 :            : static gboolean
     923                 :          0 : idle_timeout_cb (gpointer user_data)
     924                 :            : {
     925                 :          0 :   GDBusDaemon *daemon = user_data;
     926                 :            : 
     927                 :          0 :   daemon->timeout = 0;
     928                 :            : 
     929                 :          0 :   g_signal_emit (daemon,
     930                 :            :                  g_dbus_daemon_signals[SIGNAL_IDLE_TIMEOUT],
     931                 :            :                  0);
     932                 :            : 
     933                 :          0 :   return G_SOURCE_REMOVE;
     934                 :            : }
     935                 :            : 
     936                 :            : static void
     937                 :          0 : connection_closed (GDBusConnection *connection,
     938                 :            :                    gboolean remote_peer_vanished,
     939                 :            :                    GError *error,
     940                 :            :                    Client *client)
     941                 :            : {
     942                 :          0 :   GDBusDaemon *daemon = client->daemon;
     943                 :            : 
     944                 :          0 :   client_free (client);
     945                 :            : 
     946         [ #  # ]:          0 :   if (g_hash_table_size (daemon->clients) == 0)
     947                 :          0 :     daemon->timeout = g_timeout_add (IDLE_TIMEOUT_MSEC,
     948                 :            :                                      idle_timeout_cb,
     949                 :            :                                      daemon);
     950                 :          0 : }
     951                 :            : 
     952                 :            : static gboolean
     953                 :          0 : handle_add_match (_GFreedesktopDBus *object,
     954                 :            :                   GDBusMethodInvocation *invocation,
     955                 :            :                   const gchar *arg_rule)
     956                 :            : {
     957                 :          0 :   Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
     958                 :            :   Match *match;
     959                 :            : 
     960                 :          0 :   match = match_new (arg_rule);
     961                 :            : 
     962         [ #  # ]:          0 :   if (match == NULL)
     963                 :          0 :     g_dbus_method_invocation_return_error (invocation,
     964                 :            :                                            G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_INVALID,
     965                 :            :                                            "Invalid rule: %s", arg_rule);
     966                 :            :   else
     967                 :            :     {
     968                 :          0 :       client->matches = g_list_prepend (client->matches, match);
     969                 :          0 :       _g_freedesktop_dbus_complete_add_match (object, invocation);
     970                 :            :     }
     971                 :          0 :   return TRUE;
     972                 :            : }
     973                 :            : 
     974                 :            : static gboolean
     975                 :          0 : handle_get_connection_selinux_security_context (_GFreedesktopDBus *object,
     976                 :            :                                                 GDBusMethodInvocation *invocation,
     977                 :            :                                                 const gchar *arg_name)
     978                 :            : {
     979                 :          0 :   g_dbus_method_invocation_return_error (invocation,
     980                 :            :                                          G_DBUS_ERROR, G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
     981                 :            :                                          "selinux context not supported");
     982                 :          0 :   _g_freedesktop_dbus_complete_get_connection_selinux_security_context (object, invocation, "");
     983                 :          0 :   return TRUE;
     984                 :            : }
     985                 :            : 
     986                 :            : static gboolean
     987                 :          0 : handle_get_connection_unix_process_id (_GFreedesktopDBus *object,
     988                 :            :                                        GDBusMethodInvocation *invocation,
     989                 :            :                                        const gchar *arg_name)
     990                 :            : {
     991                 :          0 :   g_dbus_method_invocation_return_error (invocation,
     992                 :            :                                          G_DBUS_ERROR, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
     993                 :            :                                          "connection pid not supported");
     994                 :          0 :   return TRUE;
     995                 :            : }
     996                 :            : 
     997                 :            : static gboolean
     998                 :          0 : handle_get_connection_unix_user (_GFreedesktopDBus *object,
     999                 :            :                                  GDBusMethodInvocation *invocation,
    1000                 :            :                                  const gchar *arg_name)
    1001                 :            : {
    1002                 :          0 :   g_dbus_method_invocation_return_error (invocation,
    1003                 :            :                                          G_DBUS_ERROR, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
    1004                 :            :                                          "connection user not supported");
    1005                 :          0 :   return TRUE;
    1006                 :            : }
    1007                 :            : 
    1008                 :            : static gboolean
    1009                 :          0 : handle_get_id (_GFreedesktopDBus *object,
    1010                 :            :                GDBusMethodInvocation *invocation)
    1011                 :            : {
    1012                 :          0 :   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
    1013                 :          0 :   _g_freedesktop_dbus_complete_get_id (object, invocation,
    1014                 :          0 :                                        daemon->guid);
    1015                 :          0 :   return TRUE;
    1016                 :            : }
    1017                 :            : 
    1018                 :            : static gboolean
    1019                 :          0 : handle_get_name_owner (_GFreedesktopDBus *object,
    1020                 :            :                        GDBusMethodInvocation *invocation,
    1021                 :            :                        const gchar *arg_name)
    1022                 :            : {
    1023                 :          0 :   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
    1024                 :            :   Name *name;
    1025                 :            : 
    1026         [ #  # ]:          0 :   if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
    1027                 :            :     {
    1028                 :          0 :       _g_freedesktop_dbus_complete_get_name_owner (object, invocation, DBUS_SERVICE_NAME);
    1029                 :          0 :       return TRUE;
    1030                 :            :     }
    1031                 :            : 
    1032         [ #  # ]:          0 :   if (arg_name[0] == ':')
    1033                 :            :     {
    1034         [ #  # ]:          0 :       if (g_hash_table_lookup (daemon->clients, arg_name) == NULL)
    1035                 :          0 :         g_dbus_method_invocation_return_error (invocation,
    1036                 :            :                                                G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
    1037                 :            :                                                "Could not get owner of name '%s': no such name", arg_name);
    1038                 :            :       else
    1039                 :          0 :         _g_freedesktop_dbus_complete_get_name_owner (object, invocation, arg_name);
    1040                 :          0 :       return TRUE;
    1041                 :            :     }
    1042                 :            : 
    1043                 :          0 :   name = name_lookup (daemon, arg_name);
    1044   [ #  #  #  # ]:          0 :   if (name == NULL || name->owner == NULL)
    1045                 :            :     {
    1046                 :          0 :       g_dbus_method_invocation_return_error (invocation,
    1047                 :            :                                              G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
    1048                 :            :                                              "Could not get owner of name '%s': no such name", arg_name);
    1049                 :          0 :       return TRUE;
    1050                 :            :     }
    1051                 :            : 
    1052                 :          0 :   _g_freedesktop_dbus_complete_get_name_owner (object, invocation, name->owner->client->id);
    1053                 :          0 :   return TRUE;
    1054                 :            : }
    1055                 :            : 
    1056                 :            : static gboolean
    1057                 :          0 : handle_hello (_GFreedesktopDBus *object,
    1058                 :            :               GDBusMethodInvocation *invocation)
    1059                 :            : {
    1060                 :          0 :   Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
    1061                 :          0 :   _g_freedesktop_dbus_complete_hello (object, invocation, client->id);
    1062                 :            : 
    1063                 :          0 :   g_dbus_connection_emit_signal (client->connection,
    1064                 :            :                                  NULL, "/org/freedesktop/DBus",
    1065                 :            :                                  "org.freedesktop.DBus", "NameAcquired",
    1066                 :            :                                  g_variant_new ("(s)",
    1067                 :            :                                                 client->id), NULL);
    1068                 :            : 
    1069                 :          0 :   return TRUE;
    1070                 :            : }
    1071                 :            : 
    1072                 :            : static gboolean
    1073                 :          0 : handle_list_activatable_names (_GFreedesktopDBus *object,
    1074                 :            :                                GDBusMethodInvocation *invocation)
    1075                 :            : {
    1076                 :          0 :   const char *names[] = { NULL };
    1077                 :            : 
    1078                 :          0 :   _g_freedesktop_dbus_complete_list_activatable_names (object,
    1079                 :            :                                                        invocation,
    1080                 :            :                                                        names);
    1081                 :          0 :   return TRUE;
    1082                 :            : }
    1083                 :            : 
    1084                 :            : static gboolean
    1085                 :          0 : handle_list_names (_GFreedesktopDBus *object,
    1086                 :            :                    GDBusMethodInvocation *invocation)
    1087                 :            : {
    1088                 :          0 :   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
    1089                 :            :   GPtrArray *array;
    1090                 :            :   GPtrArray *clients, *names;
    1091                 :            : 
    1092                 :          0 :   clients = g_hash_table_get_values_as_ptr_array (daemon->clients);
    1093                 :          0 :   array = g_steal_pointer (&clients);
    1094                 :            : 
    1095                 :          0 :   names = g_hash_table_get_values_as_ptr_array (daemon->names);
    1096                 :          0 :   g_ptr_array_extend_and_steal (array, g_steal_pointer (&names));
    1097                 :            : 
    1098                 :          0 :   g_ptr_array_add (array, NULL);
    1099                 :            : 
    1100                 :          0 :   _g_freedesktop_dbus_complete_list_names (object,
    1101                 :            :                                            invocation,
    1102                 :          0 :                                            (const gchar * const*)array->pdata);
    1103                 :          0 :   g_ptr_array_free (array, TRUE);
    1104                 :          0 :   return TRUE;
    1105                 :            : }
    1106                 :            : 
    1107                 :            : static gboolean
    1108                 :          0 : handle_list_queued_owners (_GFreedesktopDBus *object,
    1109                 :            :                            GDBusMethodInvocation *invocation,
    1110                 :            :                            const gchar *arg_name)
    1111                 :            : {
    1112                 :          0 :   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
    1113                 :            :   GPtrArray *array;
    1114                 :            :   Name *name;
    1115                 :            :   GList *l;
    1116                 :            : 
    1117                 :          0 :   array = g_ptr_array_new ();
    1118                 :            : 
    1119                 :          0 :   name = name_lookup (daemon, arg_name);
    1120   [ #  #  #  # ]:          0 :   if (name && name->owner)
    1121                 :            :     {
    1122         [ #  # ]:          0 :       for (l = name->queue; l != NULL; l = l->next)
    1123                 :            :         {
    1124                 :          0 :           Client *client = l->data;
    1125                 :            : 
    1126                 :          0 :           g_ptr_array_add (array, client->id);
    1127                 :            :         }
    1128                 :            :     }
    1129                 :            : 
    1130                 :          0 :   g_ptr_array_add (array, NULL);
    1131                 :            : 
    1132                 :          0 :   _g_freedesktop_dbus_complete_list_queued_owners (object,
    1133                 :            :                                                    invocation,
    1134                 :          0 :                                                    (const gchar * const*)array->pdata);
    1135                 :          0 :   g_ptr_array_free (array, TRUE);
    1136                 :          0 :   return TRUE;
    1137                 :            : }
    1138                 :            : 
    1139                 :            : static gboolean
    1140                 :          0 : handle_name_has_owner (_GFreedesktopDBus *object,
    1141                 :            :                        GDBusMethodInvocation *invocation,
    1142                 :            :                        const gchar *arg_name)
    1143                 :            : {
    1144                 :          0 :   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
    1145                 :            :   Name *name;
    1146                 :            :   Client *client;
    1147                 :            : 
    1148                 :          0 :   name = name_lookup (daemon, arg_name);
    1149                 :          0 :   client = g_hash_table_lookup (daemon->clients, arg_name);
    1150                 :            : 
    1151   [ #  #  #  # ]:          0 :   _g_freedesktop_dbus_complete_name_has_owner (object, invocation,
    1152                 :            :                                                name != NULL || client != NULL);
    1153                 :          0 :   return TRUE;
    1154                 :            : }
    1155                 :            : 
    1156                 :            : static gboolean
    1157                 :          0 : handle_release_name (_GFreedesktopDBus *object,
    1158                 :            :                      GDBusMethodInvocation *invocation,
    1159                 :            :                      const gchar *arg_name)
    1160                 :            : {
    1161                 :          0 :   Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
    1162                 :          0 :   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
    1163                 :            :   Name *name;
    1164                 :            :   guint32 result;
    1165                 :            : 
    1166         [ #  # ]:          0 :   if (!g_dbus_is_name (arg_name))
    1167                 :            :     {
    1168                 :          0 :       g_dbus_method_invocation_return_error (invocation,
    1169                 :            :                                              G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
    1170                 :            :                                              "Given bus name \"%s\" is not valid", arg_name);
    1171                 :          0 :       return TRUE;
    1172                 :            :     }
    1173                 :            : 
    1174         [ #  # ]:          0 :   if (*arg_name == ':')
    1175                 :            :     {
    1176                 :          0 :       g_dbus_method_invocation_return_error (invocation,
    1177                 :            :                                              G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
    1178                 :            :                                              "Cannot release a service starting with ':' such as \"%s\"", arg_name);
    1179                 :          0 :       return TRUE;
    1180                 :            :     }
    1181                 :            : 
    1182         [ #  # ]:          0 :   if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
    1183                 :            :     {
    1184                 :          0 :       g_dbus_method_invocation_return_error (invocation,
    1185                 :            :                                              G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
    1186                 :            :                                              "Cannot release a service named " DBUS_SERVICE_NAME ", because that is owned by the bus");
    1187                 :          0 :       return TRUE;
    1188                 :            :     }
    1189                 :            : 
    1190                 :          0 :   name = name_lookup (daemon, arg_name);
    1191                 :            : 
    1192         [ #  # ]:          0 :   if (name == NULL)
    1193                 :          0 :     result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
    1194   [ #  #  #  # ]:          0 :   else if (name->owner && name->owner->client == client)
    1195                 :            :     {
    1196                 :          0 :       name_release_owner (name);
    1197                 :          0 :       result = DBUS_RELEASE_NAME_REPLY_RELEASED;
    1198                 :            :     }
    1199         [ #  # ]:          0 :   else if (name_unqueue_owner (name, client))
    1200                 :          0 :     result = DBUS_RELEASE_NAME_REPLY_RELEASED;
    1201                 :            :   else
    1202                 :          0 :     result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
    1203                 :            : 
    1204                 :          0 :   _g_freedesktop_dbus_complete_release_name (object, invocation, result);
    1205                 :          0 :   return TRUE;
    1206                 :            : }
    1207                 :            : 
    1208                 :            : static gboolean
    1209                 :          0 : handle_reload_config (_GFreedesktopDBus *object,
    1210                 :            :                       GDBusMethodInvocation *invocation)
    1211                 :            : {
    1212                 :          0 :   _g_freedesktop_dbus_complete_reload_config (object, invocation);
    1213                 :          0 :   return TRUE;
    1214                 :            : }
    1215                 :            : 
    1216                 :            : static gboolean
    1217                 :          0 : handle_update_activation_environment (_GFreedesktopDBus *object,
    1218                 :            :                                       GDBusMethodInvocation *invocation,
    1219                 :            :                                       GVariant *arg_environment)
    1220                 :            : {
    1221                 :          0 :   g_dbus_method_invocation_return_error (invocation,
    1222                 :            :                                          G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
    1223                 :            :                                          "UpdateActivationEnvironment not implemented");
    1224                 :          0 :   return TRUE;
    1225                 :            : }
    1226                 :            : 
    1227                 :            : static gboolean
    1228                 :          0 : handle_remove_match (_GFreedesktopDBus *object,
    1229                 :            :                      GDBusMethodInvocation *invocation,
    1230                 :            :                      const gchar *arg_rule)
    1231                 :            : {
    1232                 :          0 :   Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
    1233                 :            :   Match *match, *other_match;
    1234                 :            :   GList *l;
    1235                 :            : 
    1236                 :          0 :   match = match_new (arg_rule);
    1237                 :            : 
    1238         [ #  # ]:          0 :   if (match == NULL)
    1239                 :          0 :     g_dbus_method_invocation_return_error (invocation,
    1240                 :            :                                            G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_INVALID,
    1241                 :            :                                            "Invalid rule: %s", arg_rule);
    1242                 :            :   else
    1243                 :            :     {
    1244         [ #  # ]:          0 :       for (l = client->matches; l != NULL; l = l->next)
    1245                 :            :         {
    1246                 :          0 :           other_match = l->data;
    1247         [ #  # ]:          0 :           if (match_equal (match, other_match))
    1248                 :            :             {
    1249                 :          0 :               match_free (other_match);
    1250                 :          0 :               client->matches = g_list_delete_link (client->matches, l);
    1251                 :          0 :               break;
    1252                 :            :             }
    1253                 :            :         }
    1254                 :            : 
    1255         [ #  # ]:          0 :       if (l == NULL)
    1256                 :          0 :         g_dbus_method_invocation_return_error (invocation,
    1257                 :            :                                                G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_NOT_FOUND,
    1258                 :            :                                                "The given match rule wasn't found and can't be removed");
    1259                 :            :       else
    1260                 :          0 :         _g_freedesktop_dbus_complete_remove_match (object, invocation);
    1261                 :            :     }
    1262         [ #  # ]:          0 :   if (match)    
    1263                 :          0 :     match_free (match);
    1264                 :            : 
    1265                 :          0 :   return TRUE;
    1266                 :            : }
    1267                 :            : 
    1268                 :            : static gboolean
    1269                 :          0 : handle_request_name (_GFreedesktopDBus *object,
    1270                 :            :                      GDBusMethodInvocation *invocation,
    1271                 :            :                      const gchar *arg_name,
    1272                 :            :                      guint flags)
    1273                 :            : {
    1274                 :          0 :   Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
    1275                 :          0 :   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
    1276                 :            :   Name *name;
    1277                 :            :   NameOwner *owner;
    1278                 :            :   guint32 result;
    1279                 :            : 
    1280         [ #  # ]:          0 :   if (!g_dbus_is_name (arg_name))
    1281                 :            :     {
    1282                 :          0 :       g_dbus_method_invocation_return_error (invocation,
    1283                 :            :                                              G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
    1284                 :            :                                              "Requested bus name \"%s\" is not valid", arg_name);
    1285                 :          0 :       return TRUE;
    1286                 :            :     }
    1287                 :            : 
    1288         [ #  # ]:          0 :   if (*arg_name == ':')
    1289                 :            :     {
    1290                 :          0 :       g_dbus_method_invocation_return_error (invocation,
    1291                 :            :                                              G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
    1292                 :            :                                              "Cannot acquire a service starting with ':' such as \"%s\"", arg_name);
    1293                 :          0 :       return TRUE;
    1294                 :            :     }
    1295                 :            : 
    1296         [ #  # ]:          0 :   if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
    1297                 :            :     {
    1298                 :          0 :       g_dbus_method_invocation_return_error (invocation,
    1299                 :            :                                              G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
    1300                 :            :                                              "Cannot acquire a service named " DBUS_SERVICE_NAME ", because that is reserved");
    1301                 :          0 :       return TRUE;
    1302                 :            :     }
    1303                 :            : 
    1304                 :          0 :   name = name_ensure (daemon, arg_name);
    1305         [ #  # ]:          0 :   if (name->owner == NULL)
    1306                 :            :     {
    1307                 :          0 :       owner = name_owner_new (client, flags);
    1308                 :          0 :       name_replace_owner (name, owner);
    1309                 :            : 
    1310                 :          0 :       result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
    1311                 :            :     }
    1312   [ #  #  #  # ]:          0 :   else if (name->owner && name->owner->client == client)
    1313                 :            :     {
    1314                 :          0 :       name->owner->flags = flags;
    1315                 :          0 :       result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
    1316                 :            :     }
    1317         [ #  # ]:          0 :   else if ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
    1318         [ #  # ]:          0 :            (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
    1319         [ #  # ]:          0 :             !(name->owner->flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)))
    1320                 :            :     {
    1321                 :            :       /* Unqueue if queued */
    1322                 :          0 :       name_unqueue_owner (name, client);
    1323                 :          0 :       result = DBUS_REQUEST_NAME_REPLY_EXISTS;
    1324                 :            :     }
    1325         [ #  # ]:          0 :   else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
    1326         [ #  # ]:          0 :            (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
    1327         [ #  # ]:          0 :             !(name->owner->flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)))
    1328                 :            :     {
    1329                 :            :       /* Queue the connection */
    1330                 :          0 :       owner = name_owner_new (client, flags);
    1331                 :          0 :       name_queue_owner (name, owner);
    1332                 :          0 :       result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
    1333                 :            :     }
    1334                 :            :   else
    1335                 :            :     {
    1336                 :            :       /* Replace the current owner */
    1337                 :            : 
    1338                 :          0 :       owner = name_owner_new (client, flags);
    1339                 :          0 :       name_replace_owner (name, owner);
    1340                 :            : 
    1341                 :          0 :       result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
    1342                 :            :     }
    1343                 :            : 
    1344                 :          0 :   name_unref (name);
    1345                 :            : 
    1346                 :          0 :   _g_freedesktop_dbus_complete_request_name (object, invocation, result);
    1347                 :          0 :   return TRUE;
    1348                 :            : }
    1349                 :            : 
    1350                 :            : static gboolean
    1351                 :          0 : handle_start_service_by_name (_GFreedesktopDBus *object,
    1352                 :            :                               GDBusMethodInvocation *invocation,
    1353                 :            :                               const gchar *arg_name,
    1354                 :            :                               guint arg_flags)
    1355                 :            : {
    1356                 :          0 :   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
    1357                 :            :   Name *name;
    1358                 :            : 
    1359                 :          0 :   name = name_lookup (daemon, arg_name);
    1360         [ #  # ]:          0 :   if (name)
    1361                 :          0 :     _g_freedesktop_dbus_complete_start_service_by_name (object, invocation,
    1362                 :            :                                                         DBUS_START_REPLY_ALREADY_RUNNING);
    1363                 :            :   else
    1364                 :          0 :     g_dbus_method_invocation_return_error (invocation,
    1365                 :            :                                            G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
    1366                 :            :                                            "No support for activation for name: %s", arg_name);
    1367                 :            : 
    1368                 :          0 :   return TRUE;
    1369                 :            : }
    1370                 :            : 
    1371                 :            : G_GNUC_PRINTF(5, 6)
    1372                 :            : static void
    1373                 :          0 : return_error (Client *client, GDBusMessage *message,
    1374                 :            :               GQuark                 domain,
    1375                 :            :               gint                   code,
    1376                 :            :               const gchar           *format,
    1377                 :            :               ...)
    1378                 :            : {
    1379                 :            :   GDBusMessage *reply;
    1380                 :            :   va_list var_args;
    1381                 :            :   char *error_message;
    1382                 :            :   GError *error;
    1383                 :            :   gchar *dbus_error_name;
    1384                 :            : 
    1385                 :          0 :   va_start (var_args, format);
    1386                 :          0 :   error_message = g_strdup_vprintf (format, var_args);
    1387                 :          0 :   va_end (var_args);
    1388                 :            : 
    1389                 :          0 :   error = g_error_new_literal (domain, code, "");
    1390                 :          0 :   dbus_error_name = g_dbus_error_encode_gerror (error);
    1391                 :            : 
    1392                 :          0 :   reply = g_dbus_message_new_method_error_literal (message,
    1393                 :            :                                                    dbus_error_name,
    1394                 :            :                                                    error_message);
    1395                 :            : 
    1396                 :          0 :   g_error_free (error);
    1397                 :          0 :   g_free (dbus_error_name);
    1398                 :          0 :   g_free (error_message);
    1399                 :            : 
    1400         [ #  # ]:          0 :   if (!g_dbus_connection_send_message (client->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL))
    1401                 :          0 :       g_warning ("Error sending reply");
    1402                 :          0 :   g_object_unref (reply);
    1403                 :          0 : }
    1404                 :            : 
    1405                 :            : static GDBusMessage *
    1406                 :          0 : route_message (Client *source_client, GDBusMessage *message)
    1407                 :            : {
    1408                 :            :   const char *dest;
    1409                 :            :   Client *dest_client;
    1410                 :            :   GDBusDaemon *daemon;
    1411                 :            : 
    1412                 :          0 :   daemon = source_client->daemon;
    1413                 :            : 
    1414                 :          0 :   dest_client = NULL;
    1415                 :          0 :   dest = g_dbus_message_get_destination (message);
    1416   [ #  #  #  # ]:          0 :   if (dest != NULL && strcmp (dest, DBUS_SERVICE_NAME) != 0)
    1417                 :            :     {
    1418                 :          0 :       dest_client = g_hash_table_lookup (daemon->clients, dest);
    1419                 :            : 
    1420         [ #  # ]:          0 :       if (dest_client == NULL)
    1421                 :            :         {
    1422                 :            :           Name *name;
    1423                 :          0 :           name = name_lookup (daemon, dest);
    1424   [ #  #  #  # ]:          0 :           if (name && name->owner)
    1425                 :          0 :             dest_client = name->owner->client;
    1426                 :            :         }
    1427                 :            : 
    1428         [ #  # ]:          0 :       if (dest_client == NULL)
    1429                 :            :         {
    1430         [ #  # ]:          0 :           if (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL)
    1431                 :          0 :             return_error (source_client, message,
    1432                 :            :                           G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
    1433                 :            :                           "The name %s is unknown", dest);
    1434                 :            :         }
    1435                 :            :       else
    1436                 :            :         {
    1437                 :          0 :           GError *error = NULL;
    1438                 :            : 
    1439         [ #  # ]:          0 :           if (!g_dbus_connection_send_message (dest_client->connection, message, G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL, NULL, &error))
    1440                 :            :             {
    1441                 :          0 :               g_warning ("Error forwarding message: %s", error->message);
    1442                 :          0 :               g_error_free (error);
    1443                 :            :             }
    1444                 :            :         }
    1445                 :            :     }
    1446                 :            : 
    1447                 :          0 :   broadcast_message (daemon, message, dest_client != NULL, TRUE, dest_client);
    1448                 :            : 
    1449                 :            :   /* Swallow messages not for the bus */
    1450   [ #  #  #  # ]:          0 :   if (dest == NULL || strcmp (dest, DBUS_SERVICE_NAME) != 0)
    1451                 :            :     {
    1452                 :          0 :       g_object_unref (message);
    1453                 :          0 :       message = NULL;
    1454                 :            :     }
    1455                 :            : 
    1456                 :          0 :   return message;
    1457                 :            : }
    1458                 :            : 
    1459                 :            : static GDBusMessage *
    1460                 :          0 : copy_if_locked (GDBusMessage *message)
    1461                 :            : {
    1462         [ #  # ]:          0 :   if (g_dbus_message_get_locked (message))
    1463                 :            :     {
    1464                 :          0 :       GDBusMessage *copy = g_dbus_message_copy (message, NULL);
    1465                 :          0 :       g_object_unref (message);
    1466                 :          0 :       message = copy;
    1467                 :            :     }
    1468                 :          0 :   return message;
    1469                 :            : }
    1470                 :            : 
    1471                 :            : static GDBusMessage *
    1472                 :          0 : filter_function (GDBusConnection *connection,
    1473                 :            :                  GDBusMessage    *message,
    1474                 :            :                  gboolean         incoming,
    1475                 :            :                  gpointer         user_data)
    1476                 :            : {
    1477                 :          0 :   Client *client = user_data;
    1478                 :            : 
    1479                 :            :   if (0)
    1480                 :            :     {
    1481                 :            :       const char *types[] = {"invalid", "method_call", "method_return", "error", "signal" };
    1482                 :            :       g_printerr ("%s%s %s %d(%d) sender: %s destination: %s %s %s.%s\n",
    1483                 :            :                 client->id,
    1484                 :            :                 incoming? "->" : "<-",
    1485                 :            :                 types[g_dbus_message_get_message_type (message)],
    1486                 :            :                 g_dbus_message_get_serial (message),
    1487                 :            :                 g_dbus_message_get_reply_serial (message),
    1488                 :            :                 g_dbus_message_get_sender (message),
    1489                 :            :                 g_dbus_message_get_destination (message),
    1490                 :            :                 g_dbus_message_get_path (message),
    1491                 :            :                 g_dbus_message_get_interface (message),
    1492                 :            :                 g_dbus_message_get_member (message));
    1493                 :            :     }
    1494                 :            : 
    1495         [ #  # ]:          0 :   if (incoming)
    1496                 :            :     {
    1497                 :            :       /* Ensure its not locked so we can set the sender */
    1498                 :          0 :       message = copy_if_locked (message);
    1499         [ #  # ]:          0 :       if (message == NULL)
    1500                 :            :         {
    1501                 :          0 :           g_warning ("Failed to copy incoming message");
    1502                 :          0 :           return NULL;
    1503                 :            :         }
    1504                 :          0 :       g_dbus_message_set_sender (message, client->id);
    1505                 :            : 
    1506                 :          0 :       return route_message (client, message);
    1507                 :            :     }
    1508                 :            :   else
    1509                 :            :     {
    1510   [ #  #  #  # ]:          0 :       if (g_dbus_message_get_sender (message) == NULL ||
    1511                 :          0 :           g_dbus_message_get_destination (message) == NULL)
    1512                 :            :         {
    1513                 :          0 :           message = copy_if_locked (message);
    1514         [ #  # ]:          0 :           if (message == NULL)
    1515                 :            :             {
    1516                 :          0 :               g_warning ("Failed to copy outgoing message");
    1517                 :          0 :               return NULL;
    1518                 :            :             }
    1519                 :            :         }
    1520                 :            : 
    1521         [ #  # ]:          0 :       if (g_dbus_message_get_sender (message) == NULL)
    1522                 :          0 :         g_dbus_message_set_sender (message, DBUS_SERVICE_NAME);
    1523         [ #  # ]:          0 :       if (g_dbus_message_get_destination (message) == NULL)
    1524                 :          0 :         g_dbus_message_set_destination (message, client->id);
    1525                 :            :     }
    1526                 :            : 
    1527                 :          0 :   return message;
    1528                 :            : }
    1529                 :            : 
    1530                 :            : static gboolean
    1531                 :          0 : on_new_connection (GDBusServer *server,
    1532                 :            :                    GDBusConnection *connection,
    1533                 :            :                    gpointer user_data)
    1534                 :            : {
    1535                 :          0 :   GDBusDaemon *daemon = user_data;
    1536                 :            : 
    1537                 :          0 :   g_dbus_connection_set_exit_on_close (connection, FALSE);
    1538                 :            : 
    1539         [ #  # ]:          0 :   if (daemon->timeout)
    1540                 :            :     {
    1541                 :          0 :       g_source_remove (daemon->timeout);
    1542                 :          0 :       daemon->timeout = 0;
    1543                 :            :     }
    1544                 :            : 
    1545                 :          0 :   client_new (daemon, connection);
    1546                 :            : 
    1547                 :          0 :   return TRUE;
    1548                 :            : }
    1549                 :            : 
    1550                 :            : static void
    1551                 :          0 : g_dbus_daemon_finalize (GObject *object)
    1552                 :            : {
    1553                 :          0 :   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
    1554                 :            :   GList *clients, *l;
    1555                 :            : 
    1556         [ #  # ]:          0 :   if (daemon->timeout)
    1557                 :          0 :     g_source_remove (daemon->timeout);
    1558                 :            : 
    1559                 :          0 :   clients = g_hash_table_get_values (daemon->clients);
    1560         [ #  # ]:          0 :   for (l = clients; l != NULL; l = l->next)
    1561                 :          0 :     client_free (l->data);
    1562                 :          0 :   g_list_free (clients);
    1563                 :            : 
    1564                 :          0 :   g_assert (g_hash_table_size (daemon->clients) == 0);
    1565                 :          0 :   g_assert (g_hash_table_size (daemon->names) == 0);
    1566                 :            : 
    1567                 :          0 :   g_hash_table_destroy (daemon->clients);
    1568                 :          0 :   g_hash_table_destroy (daemon->names);
    1569                 :            : 
    1570                 :          0 :   g_object_unref (daemon->server);
    1571                 :            : 
    1572         [ #  # ]:          0 :   if (daemon->tmpdir)
    1573                 :            :     {
    1574                 :          0 :       g_rmdir (daemon->tmpdir);
    1575                 :          0 :       g_free (daemon->tmpdir);
    1576                 :            :     }
    1577                 :            : 
    1578                 :          0 :   g_free (daemon->guid);
    1579                 :          0 :   g_free (daemon->address);
    1580                 :            : 
    1581                 :          0 :   G_OBJECT_CLASS (g_dbus_daemon_parent_class)->finalize (object);
    1582                 :          0 : }
    1583                 :            : 
    1584                 :            : static void
    1585                 :          0 : g_dbus_daemon_init (GDBusDaemon *daemon)
    1586                 :            : {
    1587                 :          0 :   daemon->next_major_id = 1;
    1588                 :          0 :   daemon->clients = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
    1589                 :          0 :   daemon->names = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
    1590                 :          0 :   daemon->guid = g_dbus_generate_guid ();
    1591                 :          0 : }
    1592                 :            : 
    1593                 :            : static gboolean
    1594                 :          0 : initable_init (GInitable     *initable,
    1595                 :            :                GCancellable  *cancellable,
    1596                 :            :                GError       **error)
    1597                 :            : {
    1598                 :          0 :   GDBusDaemon *daemon = G_DBUS_DAEMON (initable);
    1599                 :            :   GDBusServerFlags flags;
    1600                 :            : 
    1601                 :          0 :   flags = G_DBUS_SERVER_FLAGS_NONE;
    1602         [ #  # ]:          0 :   if (daemon->address == NULL)
    1603                 :            :     {
    1604                 :            : #ifdef G_OS_UNIX
    1605                 :          0 :       daemon->tmpdir = g_dir_make_tmp ("gdbus-daemon-XXXXXX", NULL);
    1606                 :          0 :       daemon->address = g_strdup_printf ("unix:tmpdir=%s", daemon->tmpdir);
    1607                 :          0 :       flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER;
    1608                 :            : #else
    1609                 :            :       /* Don’t require authentication on Windows as that hasn’t been
    1610                 :            :        * implemented yet. */
    1611                 :            :       daemon->address = g_strdup ("nonce-tcp:");
    1612                 :            :       flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
    1613                 :            : #endif
    1614                 :            :     }
    1615                 :            : 
    1616                 :          0 :   daemon->server = g_dbus_server_new_sync (daemon->address,
    1617                 :            :                                            flags,
    1618                 :          0 :                                            daemon->guid,
    1619                 :            :                                            NULL,
    1620                 :            :                                            cancellable,
    1621                 :            :                                            error);
    1622         [ #  # ]:          0 :   if (daemon->server == NULL)
    1623                 :          0 :     return FALSE;
    1624                 :            : 
    1625                 :            : 
    1626                 :          0 :   g_dbus_server_start (daemon->server);
    1627                 :            : 
    1628                 :          0 :   g_signal_connect (daemon->server, "new-connection",
    1629                 :            :                     G_CALLBACK (on_new_connection),
    1630                 :            :                     daemon);
    1631                 :            : 
    1632                 :          0 :   return TRUE;
    1633                 :            : }
    1634                 :            : 
    1635                 :            : static void
    1636                 :          0 : g_dbus_daemon_set_property (GObject      *object,
    1637                 :            :                             guint         prop_id,
    1638                 :            :                             const GValue *value,
    1639                 :            :                             GParamSpec   *pspec)
    1640                 :            : {
    1641                 :          0 :   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
    1642                 :            : 
    1643         [ #  # ]:          0 :   switch (prop_id)
    1644                 :            :     {
    1645                 :          0 :     case PROP_ADDRESS:
    1646                 :          0 :       g_free (daemon->address);
    1647                 :          0 :       daemon->address = g_value_dup_string (value);
    1648                 :          0 :       break;
    1649                 :            : 
    1650                 :          0 :     default:
    1651                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    1652                 :            :     }
    1653                 :          0 : }
    1654                 :            : 
    1655                 :            : static void
    1656                 :          0 : g_dbus_daemon_get_property (GObject    *object,
    1657                 :            :                             guint       prop_id,
    1658                 :            :                             GValue     *value,
    1659                 :            :                             GParamSpec *pspec)
    1660                 :            : {
    1661                 :          0 :   GDBusDaemon *daemon = G_DBUS_DAEMON (object);
    1662                 :            : 
    1663         [ #  # ]:          0 :   switch (prop_id)
    1664                 :            :     {
    1665                 :          0 :       case PROP_ADDRESS:
    1666                 :          0 :         g_value_set_string (value, daemon->address);
    1667                 :          0 :         break;
    1668                 :            : 
    1669                 :          0 :     default:
    1670                 :          0 :         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    1671                 :            :     }
    1672                 :          0 : }
    1673                 :            : 
    1674                 :            : static void
    1675                 :          0 : g_dbus_daemon_class_init (GDBusDaemonClass *klass)
    1676                 :            : {
    1677                 :            :   GObjectClass *gobject_class;
    1678                 :            : 
    1679                 :          0 :   gobject_class = G_OBJECT_CLASS (klass);
    1680                 :          0 :   gobject_class->finalize = g_dbus_daemon_finalize;
    1681                 :          0 :   gobject_class->set_property = g_dbus_daemon_set_property;
    1682                 :          0 :   gobject_class->get_property = g_dbus_daemon_get_property;
    1683                 :            : 
    1684                 :          0 :   g_dbus_daemon_signals[SIGNAL_IDLE_TIMEOUT] =
    1685                 :          0 :     g_signal_new (I_("idle-timeout"),
    1686                 :            :                   G_TYPE_DBUS_DAEMON,
    1687                 :            :                   G_SIGNAL_RUN_LAST,
    1688                 :            :                   0,
    1689                 :            :                   NULL, NULL,
    1690                 :            :                   NULL,
    1691                 :            :                   G_TYPE_NONE, 0);
    1692                 :            : 
    1693                 :          0 :   g_object_class_install_property (gobject_class,
    1694                 :            :                                    PROP_ADDRESS,
    1695                 :            :                                    g_param_spec_string ("address", NULL, NULL,
    1696                 :            :                                                         NULL,
    1697                 :            :                                                         G_PARAM_READWRITE |
    1698                 :            :                                                         G_PARAM_CONSTRUCT_ONLY |
    1699                 :            :                                                         G_PARAM_STATIC_STRINGS));
    1700                 :          0 : }
    1701                 :            : 
    1702                 :            : static void
    1703                 :          0 : g_dbus_daemon_iface_init (_GFreedesktopDBusIface *iface)
    1704                 :            : {
    1705                 :          0 :   iface->handle_add_match = handle_add_match;
    1706                 :          0 :   iface->handle_get_connection_selinux_security_context = handle_get_connection_selinux_security_context;
    1707                 :          0 :   iface->handle_get_connection_unix_process_id = handle_get_connection_unix_process_id;
    1708                 :          0 :   iface->handle_get_connection_unix_user = handle_get_connection_unix_user;
    1709                 :          0 :   iface->handle_get_id = handle_get_id;
    1710                 :          0 :   iface->handle_get_name_owner = handle_get_name_owner;
    1711                 :          0 :   iface->handle_hello = handle_hello;
    1712                 :          0 :   iface->handle_list_activatable_names = handle_list_activatable_names;
    1713                 :          0 :   iface->handle_list_names = handle_list_names;
    1714                 :          0 :   iface->handle_list_queued_owners = handle_list_queued_owners;
    1715                 :          0 :   iface->handle_name_has_owner = handle_name_has_owner;
    1716                 :          0 :   iface->handle_release_name = handle_release_name;
    1717                 :          0 :   iface->handle_reload_config = handle_reload_config;
    1718                 :          0 :   iface->handle_update_activation_environment = handle_update_activation_environment;
    1719                 :          0 :   iface->handle_remove_match = handle_remove_match;
    1720                 :          0 :   iface->handle_request_name = handle_request_name;
    1721                 :          0 :   iface->handle_start_service_by_name = handle_start_service_by_name;
    1722                 :          0 : }
    1723                 :            : 
    1724                 :            : static void
    1725                 :          0 : initable_iface_init (GInitableIface *initable_iface)
    1726                 :            : {
    1727                 :          0 :   initable_iface->init = initable_init;
    1728                 :          0 : }
    1729                 :            : 
    1730                 :            : GDBusDaemon *
    1731                 :          0 : _g_dbus_daemon_new (const char *address,
    1732                 :            :                     GCancellable *cancellable,
    1733                 :            :                     GError **error)
    1734                 :            : {
    1735                 :          0 :   return g_initable_new (G_TYPE_DBUS_DAEMON,
    1736                 :            :                          cancellable,
    1737                 :            :                          error,
    1738                 :            :                          "address", address,
    1739                 :            :                          NULL);
    1740                 :            : }
    1741                 :            : 
    1742                 :            : const char *
    1743                 :          0 : _g_dbus_daemon_get_address (GDBusDaemon *daemon)
    1744                 :            : {
    1745                 :          0 :   return g_dbus_server_get_client_address (daemon->server);
    1746                 :            : }

Generated by: LCOV version 1.14