~ubuntu-branches/ubuntu/raring/workrave/raring-proposed

« back to all changes in this revision

Viewing changes to .pc/fix-format-security.patch/common/src/DBus-gio.cc

  • Committer: Package Import Robot
  • Author(s): Michael Terry
  • Date: 2013-01-24 11:04:41 UTC
  • mfrom: (1.2.10)
  • Revision ID: package-import@ubuntu.com-20130124110441-rbrq0e0y6p71asoc
Tags: 1.10-0ubuntu1
* New upstream release
* debian/control, debian/rules, debian/workrave.install:
  - Enable support for an indicator in Unity (LP: #796824)
* debian/patches/fix-format-security.patch:
  - Fix FTBFS due to -Werror=format-security

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// DBus-gio.c
 
2
//
 
3
// Copyright (C) 2011, 2012, 2013 Rob Caelers <robc@krandor.nl>
 
4
// All rights reserved.
 
5
//
 
6
// This program is free software: you can redistribute it and/or modify
 
7
// it under the terms of the GNU General Public License as published by
 
8
// the Free Software Foundation, either version 3 of the License, or
 
9
// (at your option) any later version.
 
10
//
 
11
// This program 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
 
14
// GNU General Public License for more details.
 
15
//
 
16
// You should have received a copy of the GNU General Public License
 
17
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
//
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
#include "config.h"
 
22
#endif
 
23
 
 
24
#include "DBus-gio.hh"
 
25
#include "debug.hh"
 
26
 
 
27
#include <string>
 
28
#include <list>
 
29
#include <map>
 
30
 
 
31
#include <gio/gio.h>
 
32
 
 
33
#include "DBusException.hh"
 
34
#include "DBusBinding-gio.hh"
 
35
 
 
36
using namespace std;
 
37
using namespace workrave;
 
38
 
 
39
const GDBusInterfaceVTable DBus::interface_vtable =
 
40
{
 
41
  &DBus::on_method_call,
 
42
  &DBus::on_get_property,
 
43
  &DBus::on_set_property,
 
44
  NULL,
 
45
};
 
46
 
 
47
//! Construct a new D-BUS bridge
 
48
DBus::DBus()
 
49
  : connection(NULL)
 
50
{
 
51
}
 
52
 
 
53
 
 
54
//! Destruct the D-BUS bridge
 
55
DBus::~DBus()
 
56
{
 
57
  for (ServicesCIter i = services.begin(); i != services.end(); i++)
 
58
    {
 
59
      g_bus_unown_name(i->second);
 
60
    }
 
61
 
 
62
  for (ObjectIter object_it = objects.begin();object_it != objects.end(); object_it++)
 
63
    {
 
64
      for (InterfaceIter interface_it = object_it->second.interfaces.begin();
 
65
           interface_it != object_it->second.interfaces.end();
 
66
           interface_it++)
 
67
        {
 
68
          if (interface_it->second.registration_id != 0)
 
69
            {
 
70
              g_dbus_connection_unregister_object(connection, interface_it->second.registration_id);
 
71
            }
 
72
 
 
73
          if (interface_it->second.introspection_data != NULL)
 
74
            {
 
75
              g_dbus_node_info_unref(interface_it->second.introspection_data);
 
76
            }
 
77
        }
 
78
    }
 
79
}
 
80
 
 
81
 
 
82
//! Initialize D-BUS bridge
 
83
void
 
84
DBus::init()
 
85
{
 
86
}
 
87
 
 
88
 
 
89
//! Registers the specified service
 
90
void
 
91
DBus::register_service(const std::string &service_name)
 
92
{
 
93
  guint owner_id;
 
94
 
 
95
  owner_id = g_bus_own_name(G_BUS_TYPE_SESSION,
 
96
                            service_name.c_str(),
 
97
                            G_BUS_NAME_OWNER_FLAGS_NONE,
 
98
                            &DBus::on_bus_acquired,
 
99
                            NULL, //&DBus::on_name_acquired,
 
100
                            NULL, //&DBus::on_name_lost,
 
101
                            this,
 
102
                            NULL);
 
103
 
 
104
  services[service_name] = owner_id;
 
105
}
 
106
 
 
107
 
 
108
//! Registers the specified object path
 
109
void
 
110
DBus::register_object_path(const string &object_path)
 
111
{
 
112
  objects[object_path].registered = true;
 
113
}
 
114
 
 
115
 
 
116
void
 
117
DBus::update_object_registration(InterfaceData &data)
 
118
{
 
119
  TRACE_ENTER_MSG("DBus::update_object_registration", data.object_path);
 
120
  if (connection == NULL)
 
121
    {
 
122
      TRACE_RETURN("No Connection");
 
123
      return;
 
124
    }
 
125
  
 
126
  if (data.registration_id != 0)
 
127
    {
 
128
      g_dbus_connection_unregister_object(connection, data.registration_id);
 
129
    }
 
130
      
 
131
  string introspection_xml = get_introspect(data.object_path, data.interface_name);
 
132
  TRACE_MSG("Intro: %s" << introspection_xml);
 
133
 
 
134
  GError *error = NULL;
 
135
  data.introspection_data = g_dbus_node_info_new_for_xml(introspection_xml.c_str(), &error);
 
136
 
 
137
  if (error != NULL)
 
138
    {
 
139
      TRACE_MSG("Error: " << error->message);
 
140
      g_error_free(error);
 
141
    }
 
142
  
 
143
  data.registration_id = g_dbus_connection_register_object(connection,
 
144
                                                           data.object_path.c_str(),
 
145
                                                           data.introspection_data->interfaces[0],
 
146
                                                           &interface_vtable,
 
147
                                                           this, NULL, NULL);
 
148
 
 
149
  TRACE_EXIT();
 
150
}
 
151
 
 
152
 
 
153
//! Connect a D-DBUS object/interface to a C object
 
154
void
 
155
DBus::connect(const std::string &object_path, const std::string &interface_name, void *object)
 
156
{
 
157
  DBusBindingBase *binding = find_binding(interface_name);
 
158
  if (binding == NULL)
 
159
    {
 
160
      throw DBusSystemException("No such interface");
 
161
    }
 
162
 
 
163
  ObjectIter oit = objects.find(object_path);
 
164
  if (oit == objects.end())
 
165
    {
 
166
      objects[object_path].registered = false;
 
167
    }
 
168
 
 
169
  ObjectData &object_data = objects[object_path];
 
170
 
 
171
  InterfaceIter iit =  object_data.interfaces.find(interface_name);
 
172
  if (iit != object_data.interfaces.end())
 
173
    {
 
174
      throw DBusSystemException("Interface already registered");
 
175
    }
 
176
 
 
177
  InterfaceData &interface_data = object_data.interfaces[interface_name];
 
178
  interface_data.object_path = object_path;
 
179
  interface_data.interface_name = interface_name;
 
180
  interface_data.object = object;
 
181
 
 
182
  if (object_data.registered)
 
183
    {
 
184
      update_object_registration(interface_data);
 
185
    }
 
186
}
 
187
 
 
188
 
 
189
//! Disconnect a D-DBUS object/interface to a C object
 
190
void
 
191
DBus::disconnect(const std::string &object_path, const std::string &interface_name)
 
192
{
 
193
  ObjectIter it = objects.find(object_path);
 
194
  if (it != objects.end())
 
195
    {
 
196
      Interfaces &interfaces = it->second.interfaces;
 
197
 
 
198
      if (interfaces[interface_name].registration_id != 0)
 
199
        {
 
200
          g_dbus_connection_unregister_object(connection, interfaces[interface_name].registration_id);
 
201
        }
 
202
 
 
203
      if (interfaces[interface_name].introspection_data != NULL)
 
204
        {
 
205
          g_dbus_node_info_unref(interfaces[interface_name].introspection_data);
 
206
        }
 
207
      
 
208
      interfaces.erase(interface_name);
 
209
    }
 
210
}
 
211
 
 
212
 
 
213
//! Register an interface binding
 
214
void
 
215
DBus::register_binding(const std::string &name, DBusBindingBase *interface)
 
216
{
 
217
  bindings[name] = interface;
 
218
}
 
219
 
 
220
 
 
221
//! Find an interface binding
 
222
DBusBindingBase *
 
223
DBus::find_binding(const std::string &interface_name) const
 
224
{
 
225
  DBusBindingBase *ret = NULL;
 
226
 
 
227
  BindingCIter it = bindings.find(interface_name);
 
228
  if (it != bindings.end())
 
229
    {
 
230
      ret = it->second;
 
231
    }
 
232
 
 
233
  return ret;
 
234
}
 
235
 
 
236
 
 
237
void *
 
238
DBus::find_object(const std::string &path, const std::string &interface_name) const
 
239
{
 
240
  void *object = NULL;
 
241
 
 
242
  ObjectCIter object_it = objects.find(path);
 
243
  if (object_it != objects.end())
 
244
    {
 
245
      InterfaceCIter interface_it = object_it->second.interfaces.find(interface_name);
 
246
 
 
247
      if (interface_it != object_it->second.interfaces.end())
 
248
        {
 
249
          object = interface_it->second.object;
 
250
        }
 
251
    }
 
252
 
 
253
  return object;
 
254
}
 
255
 
 
256
 
 
257
bool
 
258
DBus::is_running(const std::string &name) const
 
259
{
 
260
  TRACE_ENTER("DBus::is_owner");
 
261
        GError *error = NULL;
 
262
        gboolean running = FALSE;
 
263
 
 
264
  GDBusProxy *proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SESSION,
 
265
                                                    G_DBUS_PROXY_FLAGS_NONE,
 
266
                                                    NULL,
 
267
                                                    "org.freedesktop.DBus",
 
268
                                                    "/org/freedesktop/DBus",
 
269
                                                    "org.freedesktop.DBus",
 
270
                                                    NULL,
 
271
                                                    &error);
 
272
 
 
273
  if (error != NULL)
 
274
    {
 
275
      TRACE_MSG("Error: " << error->message);
 
276
      g_error_free(error);
 
277
    }
 
278
 
 
279
  if (error == NULL && proxy != NULL)
 
280
    {
 
281
      GVariant *result = g_dbus_proxy_call_sync(proxy,
 
282
                                                "NameHasOwner",
 
283
                                                g_variant_new("(s)", name.c_str()),
 
284
                                                G_DBUS_CALL_FLAGS_NONE,
 
285
                                                -1,
 
286
                                                NULL,
 
287
                                                &error);
 
288
 
 
289
      if (error != NULL)
 
290
        {
 
291
          TRACE_MSG("Error: " << error->message);
 
292
          g_error_free(error);
 
293
        }
 
294
      else
 
295
        {
 
296
          GVariant *first = g_variant_get_child_value(result, 0);
 
297
          running = g_variant_get_boolean(first);
 
298
          g_variant_unref(first);
 
299
          g_variant_unref(result);
 
300
        }
 
301
    }
 
302
 
 
303
  TRACE_RETURN(running);
 
304
        return running;
 
305
}
 
306
 
 
307
 
 
308
bool
 
309
DBus::is_available() const
 
310
{
 
311
  return true;
 
312
}
 
313
 
 
314
void
 
315
DBus::on_bus_name_appeared(GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data)
 
316
{
 
317
  (void) connection;
 
318
  (void) name_owner;
 
319
  DBus *dbus = (DBus *)user_data;
 
320
  dbus->watched[name].seen = true;
 
321
  dbus->bus_name_presence(name, true);
 
322
}
 
323
 
 
324
void
 
325
DBus::on_bus_name_vanished(GDBusConnection *connection, const gchar *name, gpointer user_data)
 
326
{
 
327
  (void) connection;
 
328
  DBus *dbus = (DBus *)user_data;
 
329
  if (dbus->watched[name].seen)
 
330
    {
 
331
      dbus->bus_name_presence(name, false);
 
332
    }
 
333
}
 
334
 
 
335
void
 
336
DBus::bus_name_presence(const std::string &name, bool present)
 
337
{
 
338
  if (watched.find(name) != watched.end())
 
339
    {
 
340
      watched[name].callback->bus_name_presence(name, present);
 
341
    }
 
342
}
 
343
 
 
344
void
 
345
DBus::watch(const std::string &name, IDBusWatch *cb)
 
346
{
 
347
  guint id = g_bus_watch_name_on_connection(connection,
 
348
                                            name.c_str(),
 
349
                                            G_BUS_NAME_WATCHER_FLAGS_NONE,
 
350
                                            on_bus_name_appeared,
 
351
                                            on_bus_name_vanished,
 
352
                                            this,
 
353
                                            NULL);
 
354
  watched[name].id = id;
 
355
  watched[name].callback = cb;
 
356
  watched[name].seen = false;
 
357
}
 
358
 
 
359
void
 
360
DBus::unwatch(const std::string &name)
 
361
{
 
362
  guint id = watched[name].id;
 
363
  g_bus_unwatch_name(id);
 
364
  watched.erase(name);
 
365
}
 
366
 
 
367
 
 
368
string
 
369
DBus::get_introspect(const string &object_path, const string &interface_name)
 
370
{
 
371
  TRACE_ENTER_MSG("DBus::get_introspect", object_path);
 
372
        string str;
 
373
 
 
374
  str += "<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN' 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>\n";
 
375
  str += "<node name='" + object_path + "'>\n";
 
376
 
 
377
  ObjectCIter object_it = objects.find(object_path);
 
378
  if (object_it != objects.end())
 
379
    {
 
380
      InterfaceCIter interface_it = object_it->second.interfaces.find(interface_name);
 
381
      if (interface_it != object_it->second.interfaces.end())
 
382
        {
 
383
          DBusBindingBase *binding = find_binding(interface_it->first);
 
384
          if (binding == NULL)
 
385
            {
 
386
              throw DBusSystemException("Internal error, unknown interface");
 
387
            }
 
388
 
 
389
          const char *interface_introspect = binding->get_interface_introspect();
 
390
          str += string(interface_introspect);
 
391
        }
 
392
    }
 
393
 
 
394
  str += "</node>\n";
 
395
  TRACE_RETURN(str);
 
396
  return str;
 
397
}
 
398
 
 
399
 
 
400
void
 
401
DBus::on_method_call(GDBusConnection       *connection,
 
402
                     const gchar           *sender,
 
403
                     const gchar           *object_path,
 
404
                     const gchar           *interface_name,
 
405
                     const gchar           *method_name,
 
406
                     GVariant              *parameters,
 
407
                     GDBusMethodInvocation *invocation,
 
408
                     gpointer               user_data)
 
409
{
 
410
  (void) connection;
 
411
  (void) sender;
 
412
  
 
413
  try
 
414
    {
 
415
      DBus *self = (DBus *) user_data;
 
416
 
 
417
      void *object = self->find_object(object_path, interface_name);
 
418
      if (object == NULL)
 
419
        {
 
420
          throw DBusUsageException(string("No such object: ") + object_path + " " + interface_name );
 
421
        }
 
422
 
 
423
      DBusBindingBase *binding = self->find_binding(interface_name);
 
424
      if (binding == NULL)
 
425
        {
 
426
          throw DBusSystemException(string("No such binding: ") + interface_name );
 
427
        }
 
428
 
 
429
      binding->call(method_name, object, invocation, sender, parameters);
 
430
    }
 
431
  catch (DBusException &e)
 
432
    {
 
433
      g_dbus_method_invocation_return_error (invocation,
 
434
                                             G_IO_ERROR,
 
435
                                             G_IO_ERROR_FAILED_HANDLED,
 
436
                                             e.details().c_str());
 
437
    }
 
438
}
 
439
 
 
440
 
 
441
GVariant *
 
442
DBus::on_get_property(GDBusConnection  *connection,
 
443
                      const gchar      *sender,
 
444
                      const gchar      *object_path,
 
445
                      const gchar      *interface_name,
 
446
                      const gchar      *property_name,
 
447
                      GError          **error,
 
448
                      gpointer          user_data)
 
449
{
 
450
  (void) connection;
 
451
  (void) sender;
 
452
  (void) object_path;
 
453
  (void) interface_name;
 
454
  (void) property_name;
 
455
  (void) error;
 
456
  (void) user_data;
 
457
 
 
458
  return NULL;
 
459
}
 
460
 
 
461
 
 
462
gboolean
 
463
DBus::on_set_property(GDBusConnection  *connection,
 
464
                      const gchar      *sender,
 
465
                      const gchar      *object_path,
 
466
                      const gchar      *interface_name,
 
467
                      const gchar      *property_name,
 
468
                      GVariant         *value,
 
469
                      GError          **error,
 
470
                      gpointer          user_data)
 
471
{
 
472
  (void) connection;
 
473
  (void) sender;
 
474
  (void) object_path;
 
475
  (void) interface_name;
 
476
  (void) property_name;
 
477
  (void) value;
 
478
  (void) error;
 
479
  (void) user_data;
 
480
 
 
481
  return FALSE;
 
482
}
 
483
 
 
484
 
 
485
void
 
486
DBus::on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
 
487
{
 
488
  (void) name;
 
489
  TRACE_ENTER_MSG("DBus::on_bus_acquired", name);
 
490
 
 
491
  DBus *self = (DBus *) user_data;
 
492
  self->connection = connection;
 
493
  
 
494
  for (ObjectIter object_it = self->objects.begin();object_it != self->objects.end(); object_it++)
 
495
    {
 
496
      for (InterfaceIter interface_it = object_it->second.interfaces.begin();
 
497
           interface_it != object_it->second.interfaces.end();
 
498
           interface_it++)
 
499
        {
 
500
          self->update_object_registration(interface_it->second);
 
501
        }
 
502
    }
 
503
  TRACE_EXIT();
 
504
}
 
505
 
 
506
 
 
507
void
 
508
DBus::on_name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
 
509
{
 
510
  (void) connection;
 
511
  (void) name;
 
512
  (void) user_data;
 
513
  TRACE_ENTER_MSG("DBus::on_name_acquired", name);
 
514
  TRACE_EXIT();
 
515
}
 
516
 
 
517
 
 
518
void
 
519
DBus::on_name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data)
 
520
{
 
521
  (void) connection;
 
522
  (void) name;
 
523
  (void) user_data;
 
524
  TRACE_ENTER_MSG("DBus::on_name_lost", name);
 
525
  TRACE_EXIT();
 
526
}