X-Git-Url: http://git.cascardo.eti.br/?p=cascardo%2Fpubsub-bot.git;a=blobdiff_plain;f=status.c;h=0ff93ef8577f233f39f560be17f94c0b4ee00d24;hp=78ccd6f3454589d5c08da0c6dcc1acfe74189f1b;hb=HEAD;hpb=97f54e8d8bbceb7b38996d64dc91755397267da2 diff --git a/status.c b/status.c index 78ccd6f..0ff93ef 100644 --- a/status.c +++ b/status.c @@ -17,82 +17,581 @@ */ +#include #include #include +#include +#include +#include +#include +#include +#include -struct udata +static char * server = "vespa.holoscopio.com"; +static char * username = "pubsub"; +static char * password = NULL; +static char * pbservice = "pubsub@vespa.holoscopio.com"; +static char * authed_jid = "vespa"; + +static iks * +createiq (char *type, char *to, char *qnam, char *xmlns, iks **query) { - iksparser *parser; - int auth; -}; + static int id = 0; + char sid[32];; + iks *iq; + snprintf (sid, 32, "ps%d", id++); + iq = iks_new ("iq"); + iks_insert_attrib (iq, "type", type); + iks_insert_attrib (iq, "to", to); + iks_insert_attrib (iq, "id", sid); + *query = iks_insert (iq, qnam); + iks_insert_attrib (*query, "xmlns", xmlns); + return iq; +} -enum +static void +catnode (iksparser *parser, char *node) { - AUTH_NONE, - AUTH_TLS, - AUTH_SASL, - AUTH_BIND, - AUTH_SESSION -} AUTH_STATE; + iks *iq; + iks *query; + iq = createiq ("get", pbservice, "query", + "http://jabber.org/protocol/disco#info", &query); + if (node != NULL) + iks_insert_attrib (query, "node", node); + iks_send (parser, iq); + iks_delete (iq); +} + +static void +listnode (iksparser *parser, char *node) +{ + iks *iq; + iks *query; + iq = createiq ("get", pbservice, "query", + "http://jabber.org/protocol/disco#items", &query); + if (node != NULL) + iks_insert_attrib (query, "node", node); + iks_send (parser, iq); + iks_delete (iq); +} + +static void +createnode (iksparser *parser, char *node) +{ + iks *iq; + iks *query; + iq = createiq ("set", pbservice, "pubsub", + "http://jabber.org/protocol/pubsub", &query); + iks_insert_attrib (iks_insert (query, "create"), "node", node); + iks_insert (query, "configure"); + iks_send (parser, iq); + iks_delete (iq); +} + +static void +getnode (iksparser *parser, char *node) +{ + iks *iq; + iks *query; + iq = createiq ("get", pbservice, "pubsub", + "http://jabber.org/protocol/pubsub", &query); + iks_insert_attrib (iks_insert (query, "items"), "node", node); + iks_send (parser, iq); + iks_delete (iq); +} + +static void +vcard (iksparser *parser) +{ + iks *iq; + iks *query; + iq = createiq ("get", pbservice, "vCard", "vcard-temp", &query); + iks_send (parser, iq); + iks_delete (iq); +} + +static iks * +createmood (char *line) +{ + iks *mood; + mood = iks_new ("mood"); + iks_insert_attrib (mood, "xmlns", "http://jabber.org/protocol/mood"); + iks_insert (mood, line); + return mood; +} + +static void +pushmood (iksparser *parser, char *node, char *line) +{ + iks *iq; + iks *query; + iks *publish; + iks *item; + iks *mood; + iq = createiq ("set", pbservice, "pubsub", + "http://jabber.org/protocol/pubsub", &query); + publish = iks_insert (query, "publish"); + iks_insert_attrib (publish, "node", node); + item = iks_insert (publish, "item"); + mood = createmood (line); + iks_insert_node (item, mood); + iks_send (parser, iq); + iks_delete (iq); +} + +static iks * +createtune (char *line) +{ + iks *tune; + tune = iks_new ("tune"); + iks_insert_attrib (tune, "xmlns", "http://jabber.org/protocol/tune"); + iks_insert_cdata (iks_insert (tune, "artist"), line, 0); + return tune; +} + +static void +pushtune (iksparser *parser, char *node, iks *tune) +{ + iks *iq; + iks *query; + iks *publish; + iks *item; + iq = createiq ("set", pbservice, "pubsub", + "http://jabber.org/protocol/pubsub", &query); + publish = iks_insert (query, "publish"); + iks_insert_attrib (publish, "node", node); + item = iks_insert (publish, "item"); + iks_insert_node (item, tune); + printf ("debug: %s\n", iks_string (iks_stack (iq), iq)); + iks_send (parser, iq); + iks_delete (iq); +} + + +static void +process_mood (iksparser *parser, char *cmdline) +{ + char *cmd; + char *orig_cmdline; + orig_cmdline = cmdline = strdup (cmdline); + cmd = strsep (&cmdline, " "); + if (!strcmp (cmd, "ls")) + listnode (parser, cmdline); + else if (!strcmp (cmd, "cat")) + catnode (parser, cmdline); + else if (!strcmp (cmd, "vcard")) + vcard (parser); + else if (!strcmp (cmd, "create")) + createnode (parser, cmdline); + else if (!strcmp (cmd, "get")) + getnode (parser, cmdline); + else if (!strcmp (cmd, "mood")) + { + char *node; + node = "http://jabber.org/protocol/mood"; + pushmood (parser, node, cmdline); + } + else if (!strcmp (cmd, "tune")) + { + char *node; + iks *tune; + node = "http://jabber.org/protocol/tune"; + tune = createtune (cmdline); + pushtune (parser, node, tune); + } + free (orig_cmdline); +} static int -hook (void *data, int type, iks *node) +xmpp_session_hook (iksparser *parser, iks *node) +{ + iks *iq; + iq = iks_new ("iq"); + iks_insert_attrib (iq, "type", "set"); + iks_insert_attrib (iq, "id", "session1"); + iks_insert_attrib (iks_insert (iq, "session"), + "xmlns", "urn:ietf:params:xml:ns:xmpp-session"); + iks_send (parser, iq); + iks_delete (iq); + return 0; +} + +static int +xmpp_initial_presence_hook (iksparser *parser, iks *node) +{ + iks *pres; + pres = iks_make_pres (IKS_SHOW_AVAILABLE, "Microblogging here!"); + iks_insert_cdata (iks_insert (pres, "priority"), "-1", 2); + iks_send (parser, pres); + iks_delete (pres); + return 0; +} + +static int +xmpp_id_hook (iksparser *parser, iks *node, char *id) +{ + if (!iks_strcmp (id, "bind1")) + { + xmpp_session_hook (parser, node); + return 0; + } + else if (!iks_strcmp (id, "session1")) + { + xmpp_initial_presence_hook (parser, node); + return 0; + } + else if (!iks_strncmp (id, "ps", 2)) + { + printf ("%s\n", iks_string (iks_stack (node), node)); + } + return 1; +} + +static int +xmpp_ns_hook (iksparser *parser, iks *node, char *ns) +{ + return 1; +} + +static int +xmpp_iq_error (iksparser *parser, iks *node) +{ + iks *enode; + char *to; + char *from; + if (!iks_strcmp (iks_find_attrib (node, "type"), "error")) + return 1; + to = iks_find_attrib (node, "to"); + from = iks_find_attrib (node, "from"); + if (to) + iks_insert_attrib (node, "from", to); + else + iks_insert_attrib (node, "from", NULL); + if (from) + iks_insert_attrib (node, "to", from); + else + iks_insert_attrib (node, "to", NULL); + iks_insert_attrib (node, "type", "error"); + enode = iks_insert (node, "error"); + iks_insert_attrib (enode, "type", "cancel"); + iks_insert_attrib (iks_insert (enode, "feature-not-implemented"), + "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); + iks_send (parser, node); + return 0; +} + +static int +xmpp_tls_hook (iksparser *parser, iks *node) +{ + iks_start_tls (parser); + return 0; +} + +static int +xmpp_sasl_hook (iksparser *parser, iks* node) +{ + if (password == NULL) + return -1; + iks_start_sasl (parser, IKS_SASL_DIGEST_MD5, username, password); + return 0; +} + +static int +xmpp_bind_hook (iksparser *parser, iks *node) +{ + iks *iq; + if (password) + { + memset (password, 0, sysconf (_SC_PASS_MAX)); + free (password); + password = NULL; + } + iq = iks_new ("iq"); + iks_insert_attrib (iq, "type", "set"); + iks_insert_attrib (iq, "id", "bind1"); + iks_insert_attrib (iks_insert (iq, "bind"), + "xmlns", "urn:ietf:params:xml:ns:xmpp-bind"); + iks_send (parser, iq); + iks_delete (iq); + return 0; +} + +static int +xmpp_features_hook (iksparser *parser, iks *node) { - iks *sub; - struct udata *udata; - udata = (struct udata *) data; - if (type == IKS_NODE_START) + iks *feat; + char *ns; + for (feat = iks_child (node); feat != NULL; feat = iks_next (feat)) { - if (!iks_is_secure (udata->parser) || udata->auth == AUTH_NONE) + ns = iks_find_attrib (feat, "xmlns"); + if (!iks_strcmp (ns, "urn:ietf:params:xml:ns:xmpp-tls")) { - iks_start_tls (udata->parser); - udata->auth = AUTH_TLS; + xmpp_tls_hook (parser, node); + return 0; } - else if (udata->auth == AUTH_TLS) + else if (!iks_strcmp (ns, "urn:ietf:params:xml:ns:xmpp-sasl")) { - iks_start_sasl (udata->parser, IKS_SASL_PLAIN, "pubsub", "pubsub"); + xmpp_sasl_hook (parser, node); + return 0; } - else if (udata->auth == AUTH_SASL) + else if (!iks_strcmp (ns, "urn:ietf:params:xml:ns:xmpp-bind")) { - iks_send_raw (udata->parser, ""); + xmpp_bind_hook (parser, node); + return 0; } } - else + return 1; +} + +static int +xmpp_other_hook (iksparser *parser, iks *node, char *ns) +{ + if (!iks_strcmp (ns, "urn:ietf:params:xml:ns:xmpp-sasl")) + { + if (!iks_strcmp (iks_name (node), "success")) + iks_send_header (parser, server); + else if (!iks_strcmp (iks_name (node), "failure")) + printf ("failture to authenticate: %s\n", + iks_string (iks_stack (node), node)); + return 0; + } + return 1; +} + + +static int +hook (void *data, int type, iks *node) +{ + char *name; + char *id; + char *ns; + char *iqns; + iksparser *parser; + parser = *(iksparser **) data; + name = iks_name (node); + id = iks_find_attrib (node, "id"); + ns = iks_find_attrib (node, "xmlns"); + iqns = iks_find_attrib (iks_child (node), "xmlns"); + if (!iks_strcmp (name, "message")) { - if (!iks_strcmp (iks_find_attrib (node, "id"), "boo")) + char *from; + from = iks_find_attrib (node, "from"); + if (!iks_strncmp (from, authed_jid, iks_strlen (authed_jid))) { - udata->auth = AUTH_BIND; - iks_send_raw (udata->parser, ""); + char *body = iks_find_cdata (node, "body"); + if (body != NULL) + process_mood (parser, body); } - else if (!iks_strcmp (iks_find_attrib (node, "id"), "goo")) + else { - printf ("goooooo\n"); - sub = iks_make_s10n (IKS_TYPE_SUBSCRIBED, "cascardo@jabber-br.org", ""); - iks_send (udata->parser, sub); - iks_delete (sub); - sub = iks_make_pres (IKS_SHOW_AVAILABLE, "here"); - iks_insert_attrib (sub, "to", "cascardo@jabber-br.org"); - iks_send (udata->parser, sub); - iks_delete (sub); + printf ("%s is not authorized\n", from); } - if (!iks_strcmp (iks_name (node), "success")) + return IKS_OK; + } + else if (!iks_strcmp (name, "presence")) + { + char *from; + from = iks_find_attrib (node, "from"); + printf ("I sense a disturbance in the force: %s!\n", from); + } + else if (!iks_strcmp (name, "iq")) + { + if (xmpp_id_hook (parser, node, id) == 0) + return IKS_OK; + if (xmpp_ns_hook (parser, node, iqns) == 0) + return IKS_OK; + xmpp_iq_error (parser, node); + } + else if (!iks_strcmp (name, "stream:features")) + { + if (xmpp_features_hook (parser, node) == 0) + return IKS_OK; + } + else if (!iks_strcmp (name, "stream:error")) + { + printf ("streamerror: %s\n", iks_string (iks_stack (node), node)); + } + else + { + if (xmpp_other_hook (parser, node, ns) == 0) + return IKS_OK; + printf ("No no: %s\n", name); + } + return IKS_OK; +} + +static gboolean +handler (GIOChannel *channel, GIOCondition cond, gpointer data) +{ + iksparser *parser = data; + iks_recv (parser, 0); + return TRUE; +} + +struct + { char * key; char * val; } keymaps[] = +{ + { "artist", "artist" }, + { "duration", "length" }, + { "album", "source" }, + { "title", "title" }, + { "track-number", "track" }, + { "location", "uri" }, + { NULL, NULL } +}; + +static char * +map_key (char *orig) +{ + int i; + for (i = 0; keymaps[i].key != NULL; i++) + if (strcmp (orig, keymaps[i].key) == 0) + return keymaps[i].val; + return NULL; +} + +static void +tune_add_dbus_arg (iks *tune, DBusMessageIter *args) +{ + DBusMessageIter entry; + DBusMessageIter var; + char *strkey = NULL; + char *strval = NULL; + dbus_message_iter_recurse (args, &entry); + if (dbus_message_iter_get_arg_type (&entry) == DBUS_TYPE_STRING) + { + dbus_message_iter_get_basic (&entry, &strkey); + dbus_message_iter_next (&entry); + if (dbus_message_iter_get_arg_type (&entry) == DBUS_TYPE_VARIANT) { - iks_send_header (udata->parser, "jabber-br.org"); - udata->auth = AUTH_SASL; + dbus_message_iter_recurse (&entry, &var); + if (dbus_message_iter_get_arg_type (&var) == DBUS_TYPE_STRING) + { + dbus_message_iter_get_basic (&var, &strval); + } } - printf ("%s\n", iks_string (iks_stack (node), node)); } - return IKS_OK; + else + printf ("%c\n", dbus_message_iter_get_arg_type (&entry)); + strkey = map_key (strkey); + if (strkey && strval) + { + iks_insert_cdata (iks_insert (tune, strkey), strval, 0); + } +} + +static iks * +tune_from_dbus (DBusMessage *msg) +{ + DBusMessageIter args; + iks *tune; + tune = iks_new ("tune"); + iks_insert_attrib (tune, "xmlns", "http://jabber.org/protocol/tune"); + dbus_message_iter_init (msg, &args); + if (dbus_message_iter_get_arg_type (&args) == DBUS_TYPE_ARRAY) + { + DBusMessageIter dict; + dbus_message_iter_recurse (&args, &dict); + while (dbus_message_iter_get_arg_type (&dict) == + DBUS_TYPE_DICT_ENTRY) + { + tune_add_dbus_arg (tune, &dict); + dbus_message_iter_next (&dict); + } + } + return tune; +} + +static DBusHandlerResult +gettune (DBusConnection *conn, DBusMessage *msg, void *data) +{ + iks *tune; + if (dbus_message_is_signal (msg, "org.MetaPlayer.tag", "playing")) + { + printf("publishing tune\n"); + tune = tune_from_dbus (msg); + pushtune (data, "http://jabber.org/protocol/tune", tune); + return DBUS_HANDLER_RESULT_HANDLED; + } + else if (dbus_message_is_signal (msg, "org.MetaPlayer.player", "stop")) + { + printf("tune stopped\n"); + tune = iks_new ("tune"); + iks_insert_attrib (tune, "xmlns", "http://jabber.org/protocol/tune"); + pushtune (data, "http://jabber.org/protocol/tune", tune); + return DBUS_HANDLER_RESULT_HANDLED; + } + else + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static void +prepare_dbus (gpointer parser) +{ + DBusConnection *conn; + conn = dbus_bus_get (DBUS_BUS_SESSION, NULL); + dbus_bus_register (conn, NULL); + dbus_bus_add_match (conn, + "type='signal'", NULL); + dbus_connection_flush (conn); + dbus_connection_setup_with_g_main (conn, g_main_context_default ()); + dbus_connection_add_filter (conn, gettune, parser, NULL); +} + +static void +loop (iksparser *parser) +{ + GIOChannel *channel; + channel = g_io_channel_unix_new (iks_fd (parser)); + g_io_add_watch (channel, G_IO_IN, handler, parser); + prepare_dbus (parser); + g_main_loop_run (g_main_loop_new (g_main_context_default (), TRUE)); } int main (int argc, char **argv) { - struct udata udata; - udata.auth = 0; - udata.parser = iks_stream_new ("jabber:client", &udata, hook); - iks_connect_tcp (udata.parser, "jabber-br.org", 5222); - while (1) - iks_recv (udata.parser, -1); + iksparser *parser; + int c; + int askpasswd = 0; + char *passwd = strdup ("pubsub"); + while ((c = getopt (argc, argv, "s:u:p:i:a:w")) != -1) + { + switch (c) + { + case 's': + server = optarg; + break; + case 'u': + username = optarg; + break; + case 'p': + free (passwd); + passwd = strdup (optarg); + break; + case 'i': + pbservice = optarg; + break; + case 'a': + authed_jid = optarg; + break; + case 'w': + askpasswd = 1; + break; + } + } + if (askpasswd) + passwd = getpass ("Type password: "); + password = malloc (sysconf (_SC_PASS_MAX)); + strcpy (password, passwd); + memset (passwd, 0, strlen (passwd)); + if (!askpasswd) + { + free (passwd); + passwd = NULL; + } + parser = iks_stream_new ("jabber:client", &parser, hook); + iks_connect_tcp (parser, server, 5222); + loop (parser); return 0; }