Fix some unrelated unit tests when !HAVE_OPENSSL_POLICY_MAPPING.
[wvstreams.git] / dbus / wvdbusmsg.cc
blob8c4c9ed54219983d4eb0bfdff3edf14f7d28206a
1 /* -*- Mode: C++ -*-
2 * Worldvisions Weaver Software:
3 * Copyright (C) 2004-2006 Net Integration Technologies, Inc.
4 *
5 * Pathfinder Software:
6 * Copyright (C) 2007, Carillon Information Security Inc.
8 * This library is licensed under the LGPL, please read LICENSE for details.
10 */
11 #include "wvdbusmsg.h"
12 #include "wvdbusconn.h"
13 #include "wvstrutils.h"
14 #undef interface // windows
15 #include <dbus/dbus.h>
18 class WvDBusReplyMsg : public WvDBusMsg
20 public:
21 /**
22 * Constructs a new reply message (a message intended to be a reply to
23 * an existing D-Bus message).
25 * Don't call this directly. Use WvDBusMsg::reply() instead.
27 WvDBusReplyMsg(DBusMessage *_msg);
29 virtual ~WvDBusReplyMsg() {}
34 WvDBusMsg::Iter::Iter(const WvDBusMsg &_msg)
35 : first(new DBusMessageIter), it(new DBusMessageIter)
37 dbus_message_iter_init(_msg, first);
38 rewind();
42 WvDBusMsg::Iter::Iter(const WvDBusMsg::Iter &_it)
43 : first(new DBusMessageIter), it(new DBusMessageIter)
45 *first = *_it.first;
46 rewind();
50 WvDBusMsg::Iter::Iter(const DBusMessageIter &_first)
51 : first(new DBusMessageIter), it(new DBusMessageIter)
53 *first = _first;
54 rewind();
58 WvDBusMsg::Iter::~Iter()
60 delete first;
61 delete it;
65 void WvDBusMsg::Iter::rewind()
67 rewound = true;
71 bool WvDBusMsg::Iter::next()
73 if (rewound)
74 *it = *first;
75 else if (type() != DBUS_TYPE_INVALID)
76 dbus_message_iter_next(it);
77 rewound = false;
78 return type() != DBUS_TYPE_INVALID;
82 int WvDBusMsg::Iter::type() const
84 return dbus_message_iter_get_arg_type(it);
88 WvDBusMsg::Iter WvDBusMsg::Iter::open() const
90 DBusMessageIter sub;
91 dbus_message_iter_recurse(it, &sub);
92 return Iter(sub);
96 bool WvDBusMsg::Iter::cur() const
98 return !rewound && type() != DBUS_TYPE_INVALID;
102 void WvDBusMsg::Iter::get_all(WvStringList &list)
104 int items = 0;
105 for (rewind(); next() && items < 20; items++)
106 list.append(get_str());
107 if (items == 20)
108 list.append("...");
112 WvString WvDBusMsg::Iter::get_all()
114 WvStringList list;
115 get_all(list);
116 return list.join(",");
120 WvString WvDBusMsg::Iter::get_str() const
122 char *s;
123 double d;
125 switch (type())
127 case DBUS_TYPE_BYTE:
128 return WvString("y%s", get_int());
129 case DBUS_TYPE_BOOLEAN:
130 return WvString("b%s", get_int());
131 case DBUS_TYPE_INT16:
132 case DBUS_TYPE_INT32:
133 case DBUS_TYPE_INT64:
134 return get_int();
135 case DBUS_TYPE_UINT16:
136 case DBUS_TYPE_UINT32:
137 case DBUS_TYPE_UINT64:
138 return get_uint();
139 case DBUS_TYPE_DOUBLE:
140 dbus_message_iter_get_basic(it, &d);
141 return d;
142 case DBUS_TYPE_STRING:
143 dbus_message_iter_get_basic(it, &s);
144 return s;
145 case DBUS_TYPE_VARIANT:
146 return WvString("{%s}", open().getnext().get_str());
147 case DBUS_TYPE_STRUCT:
148 case DBUS_TYPE_ARRAY:
149 return WvString("[%s]", open().get_all());
150 case DBUS_TYPE_INVALID:
151 return WvString();
152 default:
153 return WvString("UNKNOWN_TYPE(%c)", type());
158 int64_t WvDBusMsg::Iter::get_int() const
160 dbus_bool_t b;
161 unsigned char c;
162 dbus_int16_t s;
163 dbus_int32_t i;
164 dbus_int64_t l;
165 char *str;
167 switch (type())
169 case DBUS_TYPE_BYTE:
170 dbus_message_iter_get_basic(it, &c);
171 return c;
173 case DBUS_TYPE_BOOLEAN:
174 dbus_message_iter_get_basic(it, &b);
175 return b;
177 case DBUS_TYPE_INT16:
178 case DBUS_TYPE_UINT16:
179 dbus_message_iter_get_basic(it, &s);
180 return s;
182 case DBUS_TYPE_INT32:
183 case DBUS_TYPE_UINT32:
184 dbus_message_iter_get_basic(it, &i);
185 return i;
187 case DBUS_TYPE_INT64:
188 case DBUS_TYPE_UINT64:
189 dbus_message_iter_get_basic(it, &l);
190 return l;
192 case DBUS_TYPE_STRING:
193 dbus_message_iter_get_basic(it, &str);
194 return WvString(str).num();
196 case DBUS_TYPE_VARIANT:
197 return open().getnext().get_int();
199 default:
200 return 0;
205 uint64_t WvDBusMsg::Iter::get_uint() const
207 dbus_bool_t b;
208 unsigned char c;
209 dbus_uint16_t s;
210 dbus_uint32_t i;
211 dbus_uint64_t l;
212 char *str;
214 switch (type())
216 case DBUS_TYPE_BYTE:
217 dbus_message_iter_get_basic(it, &c);
218 return c;
220 case DBUS_TYPE_BOOLEAN:
221 dbus_message_iter_get_basic(it, &b);
222 return b;
224 case DBUS_TYPE_INT16:
225 case DBUS_TYPE_UINT16:
226 dbus_message_iter_get_basic(it, &s);
227 return s;
229 case DBUS_TYPE_INT32:
230 case DBUS_TYPE_UINT32:
231 dbus_message_iter_get_basic(it, &i);
232 return i;
234 case DBUS_TYPE_INT64:
235 case DBUS_TYPE_UINT64:
236 dbus_message_iter_get_basic(it, &l);
237 return l;
239 case DBUS_TYPE_STRING:
240 dbus_message_iter_get_basic(it, &str);
241 return WvString(str).num();
243 case DBUS_TYPE_VARIANT:
244 return open().getnext().get_uint();
246 default:
247 return 0;
252 double WvDBusMsg::Iter::get_double() const
254 dbus_bool_t b;
255 unsigned char c;
256 dbus_uint16_t s;
257 dbus_uint32_t i;
258 dbus_uint64_t l;
259 char *str;
260 double d;
262 switch (type())
264 case DBUS_TYPE_DOUBLE:
265 dbus_message_iter_get_basic(it, &d);
266 return d;
268 case DBUS_TYPE_BYTE:
269 dbus_message_iter_get_basic(it, &c);
270 return c;
272 case DBUS_TYPE_BOOLEAN:
273 dbus_message_iter_get_basic(it, &b);
274 return b;
276 case DBUS_TYPE_INT16:
277 case DBUS_TYPE_UINT16:
278 dbus_message_iter_get_basic(it, &s);
279 return s;
281 case DBUS_TYPE_INT32:
282 case DBUS_TYPE_UINT32:
283 dbus_message_iter_get_basic(it, &i);
284 return i;
286 case DBUS_TYPE_INT64:
287 case DBUS_TYPE_UINT64:
288 dbus_message_iter_get_basic(it, &l);
289 return l;
291 case DBUS_TYPE_STRING:
292 dbus_message_iter_get_basic(it, &str);
293 return atof(str);
295 case DBUS_TYPE_VARIANT:
296 return open().getnext().get_double();
298 default:
299 return 0;
304 WvString *WvDBusMsg::Iter::ptr() const
306 s = get_str();
307 return &s;
313 static DBusMessageIter *new_append_iter(WvDBusMsg &msg)
315 DBusMessageIter *it = new DBusMessageIter;
316 dbus_message_iter_init_append(msg, it);
317 return it;
321 WvDBusMsg::WvDBusMsg(WvStringParm busname, WvStringParm objectname,
322 WvStringParm interface, WvStringParm method)
324 msg = dbus_message_new_method_call(busname, objectname, interface, method);
325 itlist.prepend(new_append_iter(*this), true);
329 WvDBusMsg::WvDBusMsg(WvDBusMsg &_msg)
331 msg = _msg.msg;
332 dbus_message_ref(msg);
333 itlist.prepend(new_append_iter(*this), true);
337 WvDBusMsg::WvDBusMsg(DBusMessage *_msg)
339 msg = _msg;
340 dbus_message_ref(msg);
341 itlist.prepend(new_append_iter(*this), true);
345 WvDBusMsg::~WvDBusMsg()
347 dbus_message_unref(msg);
351 WvDBusMsg::operator DBusMessage* () const
353 return msg;
357 WvString WvDBusMsg::get_sender() const
359 return dbus_message_get_sender(msg);
363 WvString WvDBusMsg::get_dest() const
365 return dbus_message_get_destination(msg);
369 WvString WvDBusMsg::get_path() const
371 return dbus_message_get_path(msg);
375 WvString WvDBusMsg::get_interface() const
377 return dbus_message_get_interface(msg);
381 WvString WvDBusMsg::get_member() const
383 return dbus_message_get_member(msg);
387 WvString WvDBusMsg::get_error() const
389 if (iserror())
390 return dbus_message_get_error_name(msg);
392 return WvString::null;
395 bool WvDBusMsg::is_reply() const
397 // This used to have a hack to deal with replies to message #0.
398 // But it turns out the first message is #1, so that's not an actual
399 // problem.
400 return get_replyserial() != 0;
404 uint32_t WvDBusMsg::get_serial() const
406 return dbus_message_get_serial(msg);
410 uint32_t WvDBusMsg::get_replyserial() const
412 return dbus_message_get_reply_serial(msg);
416 void WvDBusMsg::get_arglist(WvStringList &list) const
418 Iter(*this).get_all(list);
422 WvString WvDBusMsg::get_argstr() const
424 return Iter(*this).get_all();
428 WvDBusMsg::operator WvString() const
430 if (is_reply())
432 if (iserror())
433 return WvString("ERR#%s(%s)", get_replyserial(), get_argstr());
434 else
435 return WvString("REPLY#%s(%s)", get_replyserial(), get_argstr());
437 else
439 WvString dest(get_dest());
440 if (!dest)
441 dest = "";
442 else
443 dest = WvString("%s:", dest);
444 WvString s("%s%s/%s.%s(%s)#%s",
445 dest,
446 get_path(), get_interface(), get_member(),
447 get_argstr(), get_serial());
448 s = strreplace(s, "org.freedesktop.DBus", "o.f.D");
449 s = strreplace(s, "org/freedesktop/DBus", "o/f/D");
450 return s;
455 WvDBusMsg &WvDBusMsg::append(const char *s)
457 assert(msg);
458 assert(s);
459 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_STRING, &s);
460 return *this;
464 WvDBusMsg &WvDBusMsg::append(bool b)
466 assert(msg);
467 dbus_bool_t bb = b;
468 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_BOOLEAN, &bb);
469 return *this;
473 WvDBusMsg &WvDBusMsg::append(signed char c)
475 assert(msg);
476 dbus_unichar_t cc = c;
477 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_BYTE, &cc);
478 return *this;
482 WvDBusMsg &WvDBusMsg::append(unsigned char c)
484 assert(msg);
485 dbus_unichar_t cc = c;
486 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_BYTE, &cc);
487 return *this;
491 WvDBusMsg &WvDBusMsg::append(int16_t i)
493 assert(msg);
494 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_INT16, &i);
495 return *this;
499 WvDBusMsg &WvDBusMsg::append(uint16_t i)
501 assert(msg);
502 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_UINT16, &i);
503 return *this;
507 WvDBusMsg &WvDBusMsg::append(int32_t i)
509 assert(msg);
510 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_INT32, &i);
511 return *this;
515 WvDBusMsg &WvDBusMsg::append(uint32_t i)
517 assert(msg);
518 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_UINT32, &i);
519 return *this;
523 WvDBusMsg &WvDBusMsg::append(int64_t i)
525 assert(msg);
526 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_INT64, &i);
527 return *this;
531 WvDBusMsg &WvDBusMsg::append(uint64_t i)
533 assert(msg);
534 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_UINT64, &i);
535 return *this;
539 WvDBusMsg &WvDBusMsg::append(double d)
541 assert(msg);
542 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_DOUBLE, &d);
543 return *this;
547 WvDBusMsg &WvDBusMsg::variant_start(WvStringParm element_type)
549 DBusMessageIter *parent = itlist.first();
550 DBusMessageIter *sub = new DBusMessageIter;
551 dbus_message_iter_open_container(parent,
552 DBUS_TYPE_VARIANT, element_type, sub);
553 itlist.prepend(sub, true);
554 return *this;
558 WvDBusMsg &WvDBusMsg::variant_end()
560 assert(itlist.count() >= 2);
562 WvList<DBusMessageIter>::Iter i(itlist);
563 i.rewind(); i.next();
564 DBusMessageIter *sub = i.ptr();
565 i.next();
566 DBusMessageIter *parent = i.ptr();
568 dbus_message_iter_close_container(parent, sub);
569 itlist.unlink_first();
570 return *this;
574 WvDBusMsg &WvDBusMsg::struct_start(WvStringParm element_type)
576 DBusMessageIter *parent = itlist.first();
577 DBusMessageIter *sub = new DBusMessageIter;
578 dbus_message_iter_open_container(parent,
579 DBUS_TYPE_STRUCT, 0, sub);
580 itlist.prepend(sub, true);
581 return *this;
585 WvDBusMsg &WvDBusMsg::struct_end()
587 return array_end(); // same thing
591 WvDBusMsg &WvDBusMsg::array_start(WvStringParm element_type)
593 DBusMessageIter *parent = itlist.first();
594 DBusMessageIter *sub = new DBusMessageIter;
595 dbus_message_iter_open_container(parent,
596 DBUS_TYPE_ARRAY, element_type, sub);
597 itlist.prepend(sub, true);
598 return *this;
602 WvDBusMsg &WvDBusMsg::array_end()
604 return variant_end(); // same thing
608 WvDBusMsg &WvDBusMsg::varray_start(WvStringParm element_type)
610 variant_start(WvString("a%s", element_type));
611 return array_start(element_type);
615 WvDBusMsg &WvDBusMsg::varray_end()
617 assert(itlist.count() >= 3);
618 array_end();
619 return variant_end();
623 WvDBusMsg WvDBusMsg::reply()
625 return WvDBusReplyMsg(*this);
629 bool WvDBusMsg::iserror() const
631 return dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_ERROR;
635 void WvDBusMsg::send(WvDBusConn &conn)
637 conn.send(*this);
641 WvDBusReplyMsg::WvDBusReplyMsg(DBusMessage *_msg)
642 : WvDBusMsg(dbus_message_new_method_return(_msg))
644 dbus_message_unref(msg);
648 WvDBusSignal::WvDBusSignal(WvStringParm objectname, WvStringParm interface,
649 WvStringParm name)
650 : WvDBusMsg(dbus_message_new_signal(objectname, interface, name))
652 dbus_message_unref(msg);
656 DBusMessage *WvDBusError::setup1(WvDBusMsg &in_reply_to,
657 WvStringParm errname, WvStringParm message)
659 return dbus_message_new_error(in_reply_to, errname, message);
662 void WvDBusError::setup2()
664 dbus_message_unref(msg);