Commit graph

83 commits

Author SHA1 Message Date
Patrick Ohly
3dc7b5fb17 added .gitignore entries for locally created files
This should be enough to keep "git" happy after a compilation inside
the source directory. Kudos to Sascha Peilicke for the original
patch.
2011-04-13 10:34:14 +02:00
Patrick Ohly
4271aa30c4 libgdbus: renamed library to libgdbusyncevo
Fedora now includes a shared libgdbus under /usr/lib. This leads to a
conflict based on the *name* of the library, not just because of
*symbols* (which was resolved earlier).

Therefore this patch renames the version that SyncEvolution depends on
to libgdbusyncevo. All SyncEvolution patches were already sent
upstream, but it is uncertain whether libgdbus will be see further
releases. Patches to make SyncEvolution use a suitable system libgdbus
library are welcome.
2011-03-22 10:35:35 +01:00
Patrick Ohly
7a706b90c3 compiler: fix warnings/errors reported by clang 2.8
clang 2.8 compiles SyncEvolution + Synthesis faster than g++ 4.4.5
(3:40min instead of 4:10min on my laptop) and produces more useful
error reports. This patch fixes the code so that it compiles cleanly
with clang when using "-Wall -Werror -Wno-unknown-pragmas". Note that
clang 2.6 (Debian Squeeze) goes into an infinite recursion compiling
code using gdbus-cxx-bridge.h and dies eventually with a stack
overflow - can't be used.

Changes necessary for clang:
- eptr pointer referencing ambiguous, use *x.get() instead
- boost::intrusive_ptr* must be defined before code using it
- two-phase template checking requires explicitly specifying
  members in base classes
- name clashes with plain C structs (DBusServer, DBusWatch) are
  an error and need to be avoided (done with namespaces GDBusCXX and
  SyncEvo)
- floats cannot be inline constants
- unused methods in local classes are warned about (left() in SyncML.cpp)
2011-02-18 09:22:36 +01:00
Patrick Ohly
94cca8cb5b D-Bus C++: simplified code
A lot of the code was roled out explicitly. This patch replaces
that with an approach similar to iostreams: remember context, then
work on one parameter at a time.

Because the decision what to do with a certain method parameter
depends on the type of the parameter, that type must be used to pick
between Get/Set classes which skip resp. work on the parameter.
2011-02-17 13:27:51 +01:00
Patrick Ohly
502cdec73a gdbus C++: fixed cut-and-paste error
Found this one when adding a method with five parameters. The
boost::bind() call had the wrong number of parameters for that case
and thus compilation failed.
2010-08-25 10:26:49 +02:00
Patrick Ohly
2018114977 gdbus: ensure that header files are included in "make dist"
After commenting out the files, they were no longer considered
by automake.
2010-08-15 21:26:53 +02:00
Patrick Ohly
18dd70a275 Revert "compile fix for FC 13 (and possibly others): use private copy of gdbus (MBC #3556)"
This reverts commit ec7eb74366.

With the symbol prefix renamed from gdbus into bdbus, we can install
the lib into /usr/lib/syncevolution again, to get it shared between
the "syncevolution" and "syncevo-dbus-server" binaries.
2010-08-09 10:46:11 -04:00
Patrick Ohly
4ba42082fa gdbus: avoid name conflict with glib
The previous solution of linking Bluex gdbus statically was not
enough. On Fedora 14, compile errors due to the glib header files
being pulled in indirectly appeared.

This patch does a global search/replace which changes the
"gdbus" (GLib D-Bus) prefix into "bdbus" (Bluez D-Bus). For the
record:
perl -pi 's/g_dbus_/b_dbus_/g; s/GDBus/BDBus/g; s/GDBUS/BDBUS/g' ...
2010-08-09 10:46:03 -04:00
Patrick Ohly
dd5f4b94b0 gdbus: do not install header files
The library was already considered "private",
so no software should need the header files.
2010-08-09 10:45:55 -04:00
Patrick Ohly
ec7eb74366 compile fix for FC 13 (and possibly others): use private copy of gdbus (MBC #3556)
SyncEvolution on FC 13 crashes because it conflicts with a different
system version of the gdbus library. Always linking statically fixes
this.

There never was an official upstream release of gdbus, so sharing the
implementation does not work.
2010-07-16 16:56:11 +02:00
Patrick Ohly
316080d3ff dbus C++ bridge: fix inconsistent CallbackData instantiation
The recent change of the first CallbackData constructor broke
some code which still passed the old type.
2010-04-09 13:55:09 +02:00
Zhu, Yongsheng
bc7de8351d gdbus c++: fix an issue of DBusClientCall exposed by valgrind (MB#10468)
The issue is to access an invalid memory. The reason is that:
DBusClientCall creates a CallbackData for each dbus call. The
CallbackData itself references the DBusClientCall object. This
object is used to get returned value once the dbus call returns.

However, the typical usage is that DBusClientCall object
is a local variable allocated on the stack. So it is invalid after
existing the stack frame. If using this object in the dbus call
handler, cause a severe problem of reading invalid memory.

The solution is to store an always alive connection object in the
CallbackData instead of DBusClientCall object.
2010-04-09 09:52:07 +02:00
Zhu, Yongsheng
dc95612eec cmdline: fix password hang (MB#5043)
When passwords in the config are not set, the daemon asks them from
clients like command line. Command line should react and let
user input passwords and then send responses to the daemon.

Command line listens to 'Server.InfoRequest' signal and only handles
password requests from sessions created for command line in the daemon.

If command line dies in the process of inputting passwords, the daemon
always waits for it so expand current timeout mechanism into this
process. Otherwise, the daemon waits permanently.
2010-04-09 08:52:26 +02:00
Zhu, Yongsheng
b4ebe0c5b0 Cmdline: watch daemon if it has gone (MB #5043)
Add a 'DBusWatch' to watch daemon and exit the process when the
daemon has gone.
Also find that current 'DBusClientCall' related classes are not
efficient and the code is reduntant. Re-design and implement the
inheritance.
2010-04-01 13:21:19 +02:00
Patrick Ohly
781e505c77 command line + D-Bus signal cleanup (MB #5043)
This patch started with the goal of changing the uint level into
a string. The motivation for that was that the numeric constants
would have to be documented (which they weren't) and prevent
us from easily changing the Logger::Level later on.

I did change them once today (see previous commit about reordering the
SHOW level) and really had the problem that a not-restarted
syncevo-dbus-server couldn't talk to a recompiled client.

Using strings avoids that problem.

While changing uint to string I had to make the change twice, once in
an entirely unnecessary new and the pointer definition. Replaced the
shared_ptr with normal members, throughout the code.

Then I wondered about the use of the () operator on these signal
watches.  At the point of use it was not obvious what that did. Turns
out that this activates the watch. In contrast to making a remote
function call or emitting a signal, I find the use of the operator
inappropriate for watches. Replaced with an explicit activate()
method.

While looking at the implementation, I found that this operator and
destructors had been duplicated. Instead of fixing it in all copies, I
moved the common code into a SignalWatch<> base template,
parameterized with the type of callback that it deals with.
2010-03-29 11:01:36 +02:00
Zhu, Yongsheng
3fc7e529ea Cmdline: move cmdline to dbus server (MB#5043)
Implement cmdline with support of dbus server. To enable cmdline
with dbus server, use the option '--use-daemon yes/no' in case that
you enable dbus service when configuration.

In a typical scenario, a new session is created for the purpose of
execution of arguments. It is scheduled with other sessions but with
a highest priority. Once it becomes active, command line call
'Session.Execute', a newly added method to execute command line
arguments.

The config name of a session should be known for dbus clients like
command line. A new property 'configName' is added in the properties
when calling 'Session.GetConfig'.

CTRL-C handling are processed once executing a real sync to dbus
server. It is mapped to invoke 'Session.Suspend' and 'Session.Abort'.

The meaning of '--enable-dbus-service' is expanded accordingly.

'--status' without server means printing all running session in the
dbus server.
'--monitor' could accept an optional config name. If one is given,
only attach to a session of that config, otherwise print an error.
If none is given, pick the first.
2010-03-29 11:01:35 +02:00
Patrick Ohly
3db3e9d916 syncevo-dbus-server: better error message when starting twice (MB #9991)
Now we print
[ERROR] g_dbus_setup_bus() failed - server already running?
instead of just
[ERROR] g_dbus_setup_bus() failed

Starting the server twice was the most common reason for the problem.
Unfortunately we cannot be sure, because g_dbus_setup_bus() doesn't set
an error.
2010-03-03 12:01:12 +01:00
Patrick Ohly
83f25bb14a g_dbus_setup_bus(): call dbus_connection_close() when failing to set up private connection
Calling dbus_connection_unref() alone is not enough for a private
connection, libdbus wants us to call dbus_connection_close() first.
One situation where this was observed was starting the SyncEvolution
D-Bus server twice (MB #9991).

It is the responsibility of the g_dbus_setup_bus() caller to do the
close once the function returns, but inside it, gdbus must do it.
2010-03-03 12:01:12 +01:00
Zhu, Yongsheng
7dbe9d1b44 dbus server: listen to signals sent from bluez
Improvement to add signal receivers for signals sent
from bluez. Thus, syncevo-dbus-server could detect
bluetooth devices changed dynamically.

4 signals from bluez are listened:
org.bluez.Manager: AdapterChanged
org.bluez.adapter: DeviceCreated, DeviceRemoved
org.bluez.device: PropertyChanged

To support listening signals from other services,
add support in gdbus cxx bridge.
2010-02-23 13:10:25 +08:00
Zhu, Yongsheng
d2cd47ba8c DBus server: Implement GetConfigs with device querying(MB#9216)
GetConfigs returns related templates to the paired bluetooth
devices with specific scores:
1)Query against the underlying template system via device names
got from Bluez and create a list of templates for each device. Since
there might be many devices and one template from system might be
for more than one device. Thus the template names returned to clients
have to be changed. So the rule to change these templates is:
Bluetooth_<mac address of device>_<seq number>, where seq number enumerates
the templates created for this device.

2)GetConfig would get the template based the cached templates info.
Each template matched for devices is added 4 properties:
description - the description for the template
score - the calculated score based on the device name and template
deviceName - the device name that the template is for
fingerPrint - the fingerPrint of the template, used for dbus clients
              to re-match with user input device info
Also, the 'syncURL' will be replaced with bluetooth mac address for
these templates.
2010-02-08 13:29:12 +08:00
Chen Congwu
3c46c508c5 gdbus-cxx-bridge: Copy DBusCallObject member to be more safe 2010-02-04 09:32:37 +01:00
Chen Congwu
4be60e7776 gdbus: cxxbridge for asynchronous dbus client call 2010-02-03 12:13:21 +01:00
Patrick Ohly
43126c5c70 some minor language fixes for MB #7711
inteface -> interface
"server would be surprised" => "undefined behavior"
2010-01-26 17:04:59 +01:00
Zhu, Yongsheng
3da11167c0 GDBus C++ binding: changes according to gdbus changes
Add one callback for each interface(DBusObjectHelper):
Each DBusObjectHelper sub-class could register its own
callback function via this parameter. The callback is
eventually called before each method function is called.
2010-01-26 16:17:08 +08:00
Zhu, Yongsheng
283e6ba46c gdbus: add interface-level callback function
A new function pointer 'callback' is added in the InterfaceData.
The callback function is per-interface. It is set together
with the registration of interface. It provides a mechanism to let
gdbus users do something before the registered methods are called.
It must be called *before* any method of an interface is called if set.
The reason is that the method might un-register the interface so
InterfaceData and its user data might be destroyed.
The user data transferred to the callback function is the 'user_data'
member in the InterfaceData set by users of gdbus.
The main purpose of this callback is that it is wanted to track
whether the dbus server is still in use.
2010-01-26 15:21:05 +08:00
Zhu, Yongsheng
6e9b26a212 DBus server: implement InfoRequest and InfoResponse (MB#6376)
Implement the info exchange mechanism when the dbus server wants
any information that only dbus clients can provide.

The dbus server uses the class 'InfoReq' to handle the requested
information from it and get response from dbus clients. The main
processing logic is referred to dbus api document.

To allow multiple info requests, the DBusServer uses a map to manage
all pending info requests and dispatches responses to the corresponding
info request. Also DBusServer.createInfoReq() is provided to create
info requests.

For InfoRequest callers, A series of methods in 'InfoReq' are provided:
check - check whether the required response is gotten
cancel - cancel the info request
wait - wait until timeout, abort or suspend
getResponse - get the response result provided by dbus clients.

All methods here are asynchronous except 'wait', which waits for
response explicitly.
2009-12-25 13:08:12 +08:00
Patrick Ohly
ff145efc1c gdbus: fixed g_dbus_create_error_valist() error handling
Out-of-memory errors were not handled correctly:
- The code using realloc() might have leaked a string.
- A static pointer was used to avoid further memory
  allocation errors, but the caller then would have
  freed it => try strdup() and check result in caller
  instead.
2009-12-09 12:19:44 +01:00
Patrick Ohly
3fc19c58d1 exporting of local changes in gdbus
Importing was already possible, improved README about that.
Exporting is added in this commit.
2009-12-09 11:53:02 +01:00
Patrick Ohly
950fa6857e gdbus: allow using private connection
This change was necessary because it turned out that using
g_dbus_setup_bus() and later dbus_g_bus_get() leads to problems
(assertion about watch data on Moblin 2.1, CRITICAL warning
and possibly other issues on Debian Lenny).

It seems that sharing a DBusConnection between different layers on top
of libdbus is either not supported or incorrectly implemented, at
least in glib-dbus.

The problem was found in SyncEvolution when using a libecal/ebook
which call D-Bus under the hood (Moblin Bugzilla #8460). SyncEvolution
has no control over those calls, therefore making the connection used
by the syncevo-dbus-server private was the easier alternative.
2009-12-04 12:47:47 +01:00
Patrick Ohly
123333d676 gdbus-cxx: header file must be distributed
"make distcheck" failed because it didn't include the new
C++ binding header files. Fixed by including them in the
files which need to be installed in /usr/include, just like
the rest of gdbus does it.
2009-11-30 19:41:00 +01:00
Chen Congwu
aaa6fc915d gdbus: fix a compile error
Need to include stdint for uint
2009-11-16 23:09:24 +01:00
Zhu, Yongsheng
912ddf031d syncevo-dbus-server: add specific exceptions (MB#6548)
Define a DBusCxxException class in gdbus cxx bridge.
It only has 2 virtual functions: getName, getMessage,
which provide the information necessary to generate
a D-Bus error.

Then define a class DBusSyncException deriving from
DBusCxxException and SyncEvo::Exception.
Also 3 classes NoSuchConfig, NoSuchSource,
InvalidCall are based on DBusSyncException.
Turn some errors into these 3 specific errors.

Define a macro to let user have an opportunity to write
its own exception handling function. The SyncEvoHandleException()
logs the error via Exception::handle() and then overrides
the conversion of all exceptions so that they result in
an "org.syncevolution.Exception", unless specified otherwise
when throwing a DBusCXXException or dbus_error.
2009-11-10 13:39:14 +01:00
Patrick Ohly
bb73c2745b gdbus C++: demonstrate how to bind methods in private base classes
Passing the "this" pointer to DBusObjectHelper::add() does not
work in this case because it cannot downcast to the required
base class. However, the caller can do that, which solves the
problem.
2009-10-14 12:28:02 +02:00
Patrick Ohly
fce06ca799 gdbus C++ example: added static and const function callback
The const method does not work at the moment and therefore
is commented out. The underlying problem is that the DBusObjectHelper::add()
call must be able to determine the method pointer type without the
const qualifier. All attempts to write a template function where
"M" is a normal function pointer and "method" a const member pointer
failed with compiler errors or didn't have the desired effect.
2009-10-14 12:28:01 +02:00
Patrick Ohly
7f81e1593a gdbus C++: simplified method declaration
It is no longer necessary to duplicate the list of function parameters
when declaring a D-Bus methods. Instead methods are added to a
DBusObjectHelper instance with the minimum amount of information:
- optional this pointer for methods
- the address of the method, global or static function
- the name of the D-Bus method

The DBusHelper::add() call determines the signature based on the
function pointer. It would have been nice to pass a boost::bind()
result and that way get rid of the special case of method pointers,
but it seems to be impossible to determine the type of all parameters
in the functor returned by boost::bind().

The maximum number of parameters of methods, including the "this"
pointer, is now 9, the maximum supported by boost::bind().

Internally DBusHelper maintains a DBusMethodTable with one pointer to
a boost::function instance for each method. This depends on the new
libgdbus per-method callback data.

Signals are also added with add() and likewise maintained inside the
DBusObjectHelper. This avoids duplicating the signal name.

All strings passed to DBusObjectHelper are copied and freed when no
longer needed.

The old handling of asynchronous method implementations via dedicated
method callbacks was replaced with code that detects when a method ask
for a Result* parameter. This is done via dbus_traits for those
parameter types, similar to the way how Watches were handled. The
compiler can detect this situation at compile time, which should
remove the useless post-method handling of the return values from the
generated code.

The main advantage is that the exponential duplication of code for the
various combinations of n arguments and m asynchronous result values
could be removed. It is nicer for users, too, because the _ASYNC flag
no longer has to be specified manually when registering the method.
2009-10-14 12:28:01 +02:00
Patrick Ohly
92a1dd2f39 gdbus: per-method callback data
The traditional usage of method callbacks is that all callbacks
share the same global data pointer. When composing a D-Bus object
from several independent modules this may be too limited, for
example when using C++.

This patch introduces G_DBUS_METHOD_FLAG_METHOD_DATA and new
fields at the end of GDBusMethodTable. Old code works as before.
New code which sets the flag is passed the new "method_data"
value as its "user_data" pointer.

This implies that the GDBusMethodTable has to be built up dynamically.
It is still owned and managed by the caller of libgdbus. To
simplify this, a new "destroy" callback can be stored inside the
GDBusMethodTable.
2009-10-14 12:28:01 +02:00
Patrick Ohly
d413d1d425 gdbus: add _NONE = 0 enum value for C++
In C++, 0 is not automatically casted into an enum. This patch
adds enum names for the empty bit field, which makes C++ code
using gdbus a bit easier to read.
2009-10-14 12:28:01 +02:00
Patrick Ohly
7b5ae309bf D-Bus C++: added support for structs
Members of structs must be read- and writeable
because the marshaling code accesses them directly.
The dbus_traits then can be defined by deriving
from dbus_struct_traits with template parameters
which describe the struct members.
2009-10-07 16:11:33 +02:00
Patrick Ohly
ecaa53241b D-Bus C++: added support for in-place passing of basic arrays
With V being a basic type, "std::pair<size_t, const V *> &" can
be used to pass an array. The caller owns the array, so this
can be used for method parameters, reply parameters and signals,
but not for return values.

dbus_traits<V> must provide a dbus_type, which is used to
extract and encode the data efficiently via dbus_message_iter_get_fixed_array()
and dbus_message_iter_append_fixed_array().
2009-10-07 16:11:20 +02:00
Patrick Ohly
940383f0b4 D-Bus C++: let app use char and unsigned char for D-BUS BYTE
Strictly speaking, an app has to use uint8_t when it wants
to exchange BYTEs with D-Bus. The extended binding maps both
int8_t and uint8_t to BYTE, so the app can use char and unsigned
char.
2009-10-07 16:11:20 +02:00
Patrick Ohly
b435d87392 D-Bus C++: added the possibility to pass Caller ID string and a watch
Use
    const Caller_t &caller
to get a caller ID string. Caller_t is a class which mimicks a
string, which is necessary to distinguish this parameter
from a std::string parameter passed via D-Bus.

Use
    const boost::shared_ptr<Watch> &watch
to be called with an active watch on the caller.
The callback invoked by the Watch must be set
with setCallback().
2009-10-07 16:11:20 +02:00
Patrick Ohly
0fb5794a21 D-Bus C++: C++ helper classes for libdbus/libgdbus
C++ classes and templates provided by header files simplify
programming in C++ with libdbus and libgdbus. libdbus items are
tracked with Boost shared pointers. Errors are turned into
exceptions. The binding to C++ is done via templates which provide the
C-style callbacks and declarations expected by libgdbus and map to
standard C++ types and STL data structures. Neither code generator nor
library code is required.

Synchronous and asynchronous method implementation are supported.
Asynchronous result deliver is done via a callback object with a
C++ signature that matches the values which have to be returned.

Due to the lack of variadic templates, lots of similar templates have
to be written to cover methods with varying combinations of arguments
and return codes. Not particularly elegant, but the alternative would
be to introduce a code generator, which has its own
drawbacks. Currently up to 10 items per method are supported, where
the number of items include the optional return value, arguments and
retvals.

Setting a Watch (base class) notifies the implementor of an when his
caller disconnects.  This can be used to abort a long-running method
when the consumer of the result goes away.

Callers are identified by their unique Bus ID, represented as Caller_t,
an alias for a plain std::string.

Objects are represented by their path with a DBusObject_t, again a
plain std::string. By default, each path comes with one interface
(DBusObject). It is possible to instantiate multiple DBusObjects with
the same path, which appears on D-Bus as a single object with multiple
interfaces.

The DBusObjectHelper simplifies object handling. It stores the
necessary information and connection reference so that the object can
be unregistered when the DBusObjectHelper is destroyed. The intended
usage is that classes own instances of DBusObjectHelper and activate
those with a method table that points to class methods.

Signals are handled as instances of EmitSignalX templates where X
stands for the number of parameters, pretty much like ResultX
callbacks are handled. The function call operator emits the signal,
with the auxiliary information (D-Bus signal name) set when
instantiating the EmitSignalX object as part of a class. The D-Bus
connection and interface is provided at the time of the signal
emission by the parent DBusObject.

The table entry for the signal is created by a static member function
of the template, which allows building a static table as required by
gdbus. Note that the signal name must be passed into that
function. This slight duplication is necessary because the template
cannot be parameterized with a string constant. Turning
makeSignalEntry() into a normal member function would make it
difficult to build the signal table.

DBusErrorCXX is a helper class for DBusError which automatically
initializes the struct, can be used to check for an error and throws
an exception for it.
2009-10-07 16:11:20 +02:00
Patrick Ohly
914dc8d15e gdbus: fixed segfault in watch disconnect function
If the apps callback function removes the watch that
triggered it, then disconnect_function() used a dangling
data pointer to retrieve the id (first problem) and
g_dbus_remove_watch() used a -1 connection_slot (second
problem, only occurs when the current watch was the
last one).

Fixed by storing the ID in a temporary variable and
adding a connection_slot check to g_dbus_remove_watch(),
similar to the one which was already in g_dbus_remove_all_watches().
2009-10-07 16:11:19 +02:00
Patrick Ohly
962599e5f8 gdbus: allow registering multiple interfaces per object
Apparently this was part of the design (there was a refcount
in ObjectData and a list of interfaces), but the implementation
didn't really use much of that.

Added a check whether there is already an object registered under
a path and reuse that object when adding further interfaces. Only
remove the object when its last interface is gone.
2009-10-07 16:11:19 +02:00
Patrick Ohly
50c7d83636 g_dbus_unregister_object(): fix same invalid memory reuse as for watches
g_dbus_unregister_object() has the same logical flaw as g_dbus_remove_watch():
it left a dangling pointer to its data in the connection slot. This pointer
was found when the slot was reused in the following call sequence:
g_dbus_register_interface()
g_dbus_unregister_interface()
g_dbus_register_interface()

The result was a segfault.
2009-10-07 16:11:19 +02:00
Patrick Ohly
5b71583cd1 g_dbus_create_error(): implemented support for detailed error description
The API had printf-style formatting for a detailed error description,
but that information was ignored. Added a sprintf variant which
allocates the resulting string dynamically, based on vsnprintf().
2009-10-07 16:11:19 +02:00
Patrick Ohly
7e558b23a2 gdbus: compile the gdbus utility library
The library is compiled and installed as a syncevolution utility
library (in other words, as lib/syncevolution/libgdbus), so that
it never conflicts with a copy of the code in another project.
2009-10-07 16:11:02 +02:00
Patrick Ohly
83bf7442d3 watch: call dbus_bus_remove_match() for each dbus_bus_add_match()
Without the remove call the matches would accumulate over time,
which can't be good for the dbus-server.

libgdbus commit ID:
d0084fd7b13b7f4665c223877f77576b08624dbf
2009-10-07 16:07:50 +02:00
Patrick Ohly
b71e1a6fbd fix for ConnectionData handling
g_dbus_remove_watch() decremented the slot ref count and freed
the ConnectionData associated with it if the ref count reached
zero. This left a dangling pointer to the ConnectionData instance
in the slot, which was found and used once the slot got recycled.

The new approach is to clear the data pointer in the slot if
its last user (watch or handler) is gone.

libgdbus commit ID:
3bb0e1e01230f50f66b3004ca385d73c49bff2c6
2009-10-07 16:07:50 +02:00
Marcel Holtmann
55a400b646 Extended GDBusWatchFunction parameter list
libgdbus commit ID:
0ed91c956fb6cf3d94eac17e778c63d5867bcb96
2009-10-07 16:07:49 +02:00