2 * Copyright (C) 2009 Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <dbus/dbus.h>
28 #include <dbus/dbus-glib-lowlevel.h>
30 static char * server = "vespa.holoscopio.com";
31 static char * username = "pubsub";
32 static char * password = NULL;
33 static char * pbservice = "pubsub@vespa.holoscopio.com";
34 static char * authed_jid = "vespa";
37 createiq (char *type, char *to, char *qnam, char *xmlns, iks **query)
42 snprintf (sid, 32, "ps%d", id++);
44 iks_insert_attrib (iq, "type", type);
45 iks_insert_attrib (iq, "to", to);
46 iks_insert_attrib (iq, "id", sid);
47 *query = iks_insert (iq, qnam);
48 iks_insert_attrib (*query, "xmlns", xmlns);
53 catnode (iksparser *parser, char *node)
57 iq = createiq ("get", pbservice, "query",
58 "http://jabber.org/protocol/disco#info", &query);
60 iks_insert_attrib (query, "node", node);
61 iks_send (parser, iq);
66 listnode (iksparser *parser, char *node)
70 iq = createiq ("get", pbservice, "query",
71 "http://jabber.org/protocol/disco#items", &query);
73 iks_insert_attrib (query, "node", node);
74 iks_send (parser, iq);
79 createnode (iksparser *parser, char *node)
83 iq = createiq ("set", pbservice, "pubsub",
84 "http://jabber.org/protocol/pubsub", &query);
85 iks_insert_attrib (iks_insert (query, "create"), "node", node);
86 iks_send (parser, iq);
91 getnode (iksparser *parser, char *node)
95 iq = createiq ("get", pbservice, "pubsub",
96 "http://jabber.org/protocol/pubsub", &query);
97 iks_insert_attrib (iks_insert (query, "items"), "node", node);
98 iks_send (parser, iq);
103 vcard (iksparser *parser)
107 iq = createiq ("get", pbservice, "vCard", "vcard-temp", &query);
108 iks_send (parser, iq);
113 createmood (char *line)
116 mood = iks_new ("mood");
117 iks_insert_attrib (mood, "xmlns", "http://jabber.org/protocol/mood");
118 iks_insert (mood, line);
123 pushmood (iksparser *parser, char *node, char *line)
130 iq = createiq ("set", pbservice, "pubsub",
131 "http://jabber.org/protocol/pubsub", &query);
132 publish = iks_insert (query, "publish");
133 iks_insert_attrib (publish, "node", node);
134 item = iks_insert (publish, "item");
135 mood = createmood (line);
136 iks_insert_node (item, mood);
137 iks_send (parser, iq);
142 createtune (char *line)
145 tune = iks_new ("tune");
146 iks_insert_attrib (tune, "xmlns", "http://jabber.org/protocol/tune");
147 iks_insert_cdata (iks_insert (tune, "artist"), line, 0);
152 pushtune (iksparser *parser, char *node, iks *tune)
158 iq = createiq ("set", pbservice, "pubsub",
159 "http://jabber.org/protocol/pubsub", &query);
160 publish = iks_insert (query, "publish");
161 iks_insert_attrib (publish, "node", node);
162 item = iks_insert (publish, "item");
163 iks_insert_node (item, tune);
164 printf ("debug: %s\n", iks_string (iks_stack (iq), iq));
165 iks_send (parser, iq);
171 process_mood (iksparser *parser, char *cmdline)
175 orig_cmdline = cmdline = strdup (cmdline);
176 cmd = strsep (&cmdline, " ");
177 if (!strcmp (cmd, "ls"))
178 listnode (parser, cmdline);
179 else if (!strcmp (cmd, "cat"))
180 catnode (parser, cmdline);
181 else if (!strcmp (cmd, "vcard"))
183 else if (!strcmp (cmd, "create"))
184 createnode (parser, cmdline);
185 else if (!strcmp (cmd, "get"))
186 getnode (parser, cmdline);
187 else if (!strcmp (cmd, "mood"))
190 node = "http://jabber.org/protocol/mood";
191 pushmood (parser, node, cmdline);
193 else if (!strcmp (cmd, "tune"))
197 node = "http://jabber.org/protocol/tune";
198 tune = createtune (cmdline);
199 pushtune (parser, node, tune);
205 xmpp_session_hook (iksparser *parser, iks *node)
209 iks_insert_attrib (iq, "type", "set");
210 iks_insert_attrib (iq, "id", "session1");
211 iks_insert_attrib (iks_insert (iq, "session"),
212 "xmlns", "urn:ietf:params:xml:ns:xmpp-session");
213 iks_send (parser, iq);
219 xmpp_initial_presence_hook (iksparser *parser, iks *node)
222 pres = iks_make_pres (IKS_SHOW_AVAILABLE, "Microblogging here!");
223 iks_insert_cdata (iks_insert (pres, "priority"), "-1", 2);
224 iks_send (parser, pres);
230 xmpp_id_hook (iksparser *parser, iks *node, char *id)
232 if (!iks_strcmp (id, "bind1"))
234 xmpp_session_hook (parser, node);
237 else if (!iks_strcmp (id, "session1"))
239 xmpp_initial_presence_hook (parser, node);
242 else if (!iks_strncmp (id, "ps", 2))
244 printf ("%s\n", iks_string (iks_stack (node), node));
250 xmpp_ns_hook (iksparser *parser, iks *node, char *ns)
256 xmpp_iq_error (iksparser *parser, iks *node)
261 if (!iks_strcmp (iks_find_attrib (node, "type"), "error"))
263 to = iks_find_attrib (node, "to");
264 from = iks_find_attrib (node, "from");
266 iks_insert_attrib (node, "from", to);
268 iks_insert_attrib (node, "from", NULL);
270 iks_insert_attrib (node, "to", from);
272 iks_insert_attrib (node, "to", NULL);
273 iks_insert_attrib (node, "type", "error");
274 enode = iks_insert (node, "error");
275 iks_insert_attrib (enode, "type", "cancel");
276 iks_insert_attrib (iks_insert (enode, "feature-not-implemented"),
277 "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas");
278 iks_send (parser, node);
283 xmpp_tls_hook (iksparser *parser, iks *node)
285 iks_start_tls (parser);
290 xmpp_sasl_hook (iksparser *parser, iks* node)
292 if (password == NULL)
294 iks_start_sasl (parser, IKS_SASL_DIGEST_MD5, username, password);
299 xmpp_bind_hook (iksparser *parser, iks *node)
304 memset (password, 0, sysconf (_SC_PASS_MAX));
309 iks_insert_attrib (iq, "type", "set");
310 iks_insert_attrib (iq, "id", "bind1");
311 iks_insert_attrib (iks_insert (iq, "bind"),
312 "xmlns", "urn:ietf:params:xml:ns:xmpp-bind");
313 iks_send (parser, iq);
319 xmpp_features_hook (iksparser *parser, iks *node)
323 for (feat = iks_child (node); feat != NULL; feat = iks_next (feat))
325 ns = iks_find_attrib (feat, "xmlns");
326 if (!iks_strcmp (ns, "urn:ietf:params:xml:ns:xmpp-tls"))
328 xmpp_tls_hook (parser, node);
331 else if (!iks_strcmp (ns, "urn:ietf:params:xml:ns:xmpp-sasl"))
333 xmpp_sasl_hook (parser, node);
336 else if (!iks_strcmp (ns, "urn:ietf:params:xml:ns:xmpp-bind"))
338 xmpp_bind_hook (parser, node);
346 xmpp_other_hook (iksparser *parser, iks *node, char *ns)
348 if (!iks_strcmp (ns, "urn:ietf:params:xml:ns:xmpp-sasl"))
350 if (!iks_strcmp (iks_name (node), "success"))
351 iks_send_header (parser, server);
352 else if (!iks_strcmp (iks_name (node), "failure"))
353 printf ("failture to authenticate: %s\n",
354 iks_string (iks_stack (node), node));
362 hook (void *data, int type, iks *node)
369 parser = *(iksparser **) data;
370 name = iks_name (node);
371 id = iks_find_attrib (node, "id");
372 ns = iks_find_attrib (node, "xmlns");
373 iqns = iks_find_attrib (iks_child (node), "xmlns");
374 if (!iks_strcmp (name, "message"))
377 from = iks_find_attrib (node, "from");
378 if (!iks_strncmp (from, authed_jid, iks_strlen (authed_jid)))
380 char *body = iks_find_cdata (node, "body");
382 process_mood (parser, body);
386 printf ("%s is not authorized\n", from);
390 else if (!iks_strcmp (name, "presence"))
393 from = iks_find_attrib (node, "from");
394 printf ("I sense a disturbance in the force: %s!\n", from);
396 else if (!iks_strcmp (name, "iq"))
398 if (xmpp_id_hook (parser, node, id) == 0)
400 if (xmpp_ns_hook (parser, node, iqns) == 0)
402 xmpp_iq_error (parser, node);
404 else if (!iks_strcmp (name, "stream:features"))
406 if (xmpp_features_hook (parser, node) == 0)
409 else if (!iks_strcmp (name, "stream:error"))
411 printf ("streamerror: %s\n", iks_string (iks_stack (node), node));
415 if (xmpp_other_hook (parser, node, ns) == 0)
417 printf ("No no: %s\n", name);
423 handler (GIOChannel *channel, GIOCondition cond, gpointer data)
425 iksparser *parser = data;
426 iks_recv (parser, 0);
431 { char * key; char * val; } keymaps[] =
433 { "artist", "artist" },
434 { "duration", "length" },
435 { "album", "source" },
436 { "title", "title" },
437 { "track-number", "track" },
438 { "location", "uri" },
446 for (i = 0; keymaps[i].key != NULL; i++)
447 if (strcmp (orig, keymaps[i].key) == 0)
448 return keymaps[i].val;
453 tune_add_dbus_arg (iks *tune, DBusMessageIter *args)
455 DBusMessageIter entry;
459 dbus_message_iter_recurse (args, &entry);
460 if (dbus_message_iter_get_arg_type (&entry) == DBUS_TYPE_STRING)
462 dbus_message_iter_get_basic (&entry, &strkey);
463 dbus_message_iter_next (&entry);
464 if (dbus_message_iter_get_arg_type (&entry) == DBUS_TYPE_VARIANT)
466 dbus_message_iter_recurse (&entry, &var);
467 if (dbus_message_iter_get_arg_type (&var) == DBUS_TYPE_STRING)
469 dbus_message_iter_get_basic (&var, &strval);
474 printf ("%c\n", dbus_message_iter_get_arg_type (&entry));
475 strkey = map_key (strkey);
476 if (strkey && strval)
478 iks_insert_cdata (iks_insert (tune, strkey), strval, 0);
483 tune_from_dbus (DBusMessage *msg)
485 DBusMessageIter args;
487 tune = iks_new ("tune");
488 iks_insert_attrib (tune, "xmlns", "http://jabber.org/protocol/tune");
489 dbus_message_iter_init (msg, &args);
490 if (dbus_message_iter_get_arg_type (&args) == DBUS_TYPE_ARRAY)
492 DBusMessageIter dict;
493 dbus_message_iter_recurse (&args, &dict);
494 while (dbus_message_iter_get_arg_type (&dict) ==
495 DBUS_TYPE_DICT_ENTRY)
497 tune_add_dbus_arg (tune, &dict);
498 dbus_message_iter_next (&dict);
504 static DBusHandlerResult
505 gettune (DBusConnection *conn, DBusMessage *msg, void *data)
508 if (dbus_message_is_signal (msg, "org.MetaPlayer.tag", "playing"))
510 printf("publishing tune\n");
511 tune = tune_from_dbus (msg);
512 pushtune (data, "http://jabber.org/protocol/tune", tune);
513 return DBUS_HANDLER_RESULT_HANDLED;
515 else if (dbus_message_is_signal (msg, "org.MetaPlayer.player", "stop"))
517 printf("tune stopped\n");
518 tune = iks_new ("tune");
519 iks_insert_attrib (tune, "xmlns", "http://jabber.org/protocol/tune");
520 pushtune (data, "http://jabber.org/protocol/tune", tune);
521 return DBUS_HANDLER_RESULT_HANDLED;
524 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
528 prepare_dbus (gpointer parser)
530 DBusConnection *conn;
531 conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
532 dbus_bus_register (conn, NULL);
533 dbus_bus_add_match (conn,
534 "type='signal'", NULL);
535 dbus_connection_flush (conn);
536 dbus_connection_setup_with_g_main (conn, g_main_context_default ());
537 dbus_connection_add_filter (conn, gettune, parser, NULL);
541 loop (iksparser *parser)
544 channel = g_io_channel_unix_new (iks_fd (parser));
545 g_io_add_watch (channel, G_IO_IN, handler, parser);
546 prepare_dbus (parser);
547 g_main_loop_run (g_main_loop_new (g_main_context_default (), TRUE));
551 main (int argc, char **argv)
556 char *passwd = strdup ("pubsub");
557 while ((c = getopt (argc, argv, "s:u:p:i:a:w")) != -1)
569 passwd = strdup (optarg);
583 passwd = getpass ("Type password: ");
584 password = malloc (sysconf (_SC_PASS_MAX));
585 strcpy (password, passwd);
586 memset (passwd, 0, strlen (passwd));
592 parser = iks_stream_new ("jabber:client", &parser, hook);
593 iks_connect_tcp (parser, server, 5222);