Accept options for the server and IDs used.
[cascardo/pubsub-bot.git] / status.c
1 /*
2  *  Copyright (C) 2009  Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
3  *
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.
8  *
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.
13  *
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.
17  */
18
19
20 #include <iksemel.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 static char * server = "vespa.holoscopio.com";
27 static char * username = "pubsub";
28 static char * password = "pubsub";
29 static char * pbservice = "pubsub.vespa.holoscopio.com";
30 static char * authed_jid = "vespa";
31
32 iks *
33 createiq (char *type, char *to, char *qnam, char *xmlns, iks **query)
34 {
35   static int id = 0;
36   char sid[32];;
37   iks *iq;
38   snprintf (sid, 32, "ps%d", id++);
39   iq = iks_new ("iq");
40   iks_insert_attrib (iq, "type", type);
41   iks_insert_attrib (iq, "to", to);
42   iks_insert_attrib (iq, "id", sid);
43   *query = iks_insert (iq, qnam);
44   iks_insert_attrib (*query, "xmlns", xmlns);
45   return iq;
46 }
47
48 void
49 catnode (iksparser *parser, char *node)
50 {
51   iks *iq;
52   iks *query;
53   iq = createiq ("get", pbservice, "query",
54                  "http://jabber.org/protocol/disco#info", &query);
55   if (node != NULL)
56     iks_insert_attrib (query, "node", node);
57   iks_send (parser, iq);
58   iks_delete (iq);
59 }
60
61 void
62 listnode (iksparser *parser, char *node)
63 {
64   iks *iq;
65   iks *query;
66   iq = createiq ("get", pbservice, "query",
67                  "http://jabber.org/protocol/disco#items", &query);
68   if (node != NULL)
69     iks_insert_attrib (query, "node", node);
70   iks_send (parser, iq);
71   iks_delete (iq);
72 }
73
74 void
75 createnode (iksparser *parser, char *node)
76 {
77   iks *iq;
78   iks *query;
79   iq = createiq ("set", pbservice, "pubsub",
80                  "http://jabber.org/protocol/pubsub", &query);
81   iks_insert_attrib (iks_insert (query, "create"), "node", node);
82   iks_send (parser, iq);
83   iks_delete (iq);
84 }
85
86 void
87 getnode (iksparser *parser, char *node)
88 {
89   iks *iq;
90   iks *query;
91   iq = createiq ("get", pbservice, "pubsub",
92                  "http://jabber.org/protocol/pubsub", &query);
93   iks_insert_attrib (iks_insert (query, "items"), "node", node);
94   iks_send (parser, iq);
95   iks_delete (iq);
96 }
97
98 void
99 vcard (iksparser *parser)
100 {
101   iks *iq;
102   iks *query;
103   iq = createiq ("get", pbservice, "vCard", "vcard-temp", &query);
104   iks_send (parser, iq);
105   iks_delete (iq);
106 }
107
108 iks *
109 createmood (char *line)
110 {
111   iks *mood;
112   mood = iks_new ("mood");
113   iks_insert_attrib (mood, "xmlns", "http://jabber.org/protocol/mood");
114   iks_insert (mood, line);
115   return mood;
116 }
117
118 void
119 pushmood (iksparser *parser, char *node, char *line)
120 {
121   iks *iq;
122   iks *query;
123   iks *publish;
124   iks *item;
125   iks *mood;
126   iq = createiq ("set", pbservice, "pubsub",
127                  "http://jabber.org/protocol/pubsub", &query);
128   publish = iks_insert (query, "publish");
129   iks_insert_attrib (publish, "node", node);
130   item = iks_insert (publish, "item");
131   mood = createmood (line);
132   iks_insert_node (item, mood);
133   iks_send (parser, iq);
134   iks_delete (iq);
135 }
136
137 void
138 process_mood (iksparser *parser, char *cmdline)
139 {
140   char *cmd;
141   char *orig_cmdline;
142   orig_cmdline = cmdline = strdup (cmdline);
143   cmd = strsep (&cmdline, " ");
144   if (!strcmp (cmd, "ls"))
145     listnode (parser, cmdline);
146   else if (!strcmp (cmd, "cat"))
147     catnode (parser, cmdline);
148   else if (!strcmp (cmd, "vcard"))
149     vcard (parser);
150   else if (!strcmp (cmd, "create"))
151     createnode (parser, cmdline);
152   else if (!strcmp (cmd, "get"))
153     getnode (parser, cmdline);
154   else if (!strcmp (cmd, "push"))
155     {
156       char *node;
157       node = strsep (&cmdline, " ");
158       pushmood (parser, node, cmdline);
159     }
160   free (orig_cmdline);
161 }
162
163 int
164 xmpp_session_hook (iksparser *parser, iks *node)
165 {
166   iks *iq;
167   iq = iks_new ("iq");
168   iks_insert_attrib (iq, "type", "set");
169   iks_insert_attrib (iq, "id", "session1");
170   iks_insert_attrib (iks_insert (iq, "session"),
171                      "xmlns", "urn:ietf:params:xml:ns:xmpp-session");
172   iks_send (parser, iq);
173   iks_delete (iq);
174   return 0;
175 }
176
177 int
178 xmpp_initial_presence_hook (iksparser *parser, iks *node)
179 {
180   iks *pres;
181   pres = iks_make_pres (IKS_SHOW_AVAILABLE, "Microblogging here!");
182   iks_send (parser, pres);
183   iks_delete (pres);
184   return 0;
185 }
186
187 int
188 xmpp_id_hook (iksparser *parser, iks *node, char *id)
189 {
190   if (!iks_strcmp (id, "bind1"))
191     {
192       xmpp_session_hook (parser, node);
193       return 0;
194     }
195   else if (!iks_strcmp (id, "session1"))
196     {
197       xmpp_initial_presence_hook (parser, node);
198       return 0;
199     }
200   else if (!iks_strncmp (id, "ps", 2))
201     {
202       printf ("%s\n", iks_string (iks_stack (node), node));
203     }
204   return 1;
205 }
206
207 int
208 xmpp_ns_hook (iksparser *parser, iks *node, char *ns)
209 {
210   return 1;
211 }
212
213 int
214 xmpp_iq_error (iksparser *parser, iks *node)
215 {
216   iks *enode;
217   char *to;
218   char *from;
219   if (!iks_strcmp (iks_find_attrib (node, "type"), "error"))
220     return 1;
221   to = iks_find_attrib (node, "to");
222   from = iks_find_attrib (node, "from");
223   if (to)
224     iks_insert_attrib (node, "from", to);
225   else
226     iks_insert_attrib (node, "from", NULL);
227   if (from)
228     iks_insert_attrib (node, "to", from);
229   else
230     iks_insert_attrib (node, "to", NULL);
231   iks_insert_attrib (node, "type", "error");
232   enode = iks_insert (node, "error");
233   iks_insert_attrib (enode, "type", "cancel");
234   iks_insert_attrib (iks_insert (enode, "feature-not-implemented"),
235                      "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas");
236   iks_send (parser, node);
237   return 0;
238 }
239
240 int
241 xmpp_tls_hook (iksparser *parser, iks *node)
242 {
243   iks_start_tls (parser);
244   return 0;
245 }
246
247 int
248 xmpp_sasl_hook (iksparser *parser, iks* node)
249 {
250   iks_start_sasl (parser, IKS_SASL_DIGEST_MD5, username, password);
251   return 0;
252 }
253
254 int
255 xmpp_bind_hook (iksparser *parser, iks *node)
256 {
257   iks *iq;
258   iq = iks_new ("iq");
259   iks_insert_attrib (iq, "type", "set");
260   iks_insert_attrib (iq, "id", "bind1");
261   iks_insert_attrib (iks_insert (iq, "bind"),
262                      "xmlns", "urn:ietf:params:xml:ns:xmpp-bind");
263   iks_send (parser, iq);
264   iks_delete (iq);
265   return 0;
266 }
267
268 int
269 xmpp_features_hook (iksparser *parser, iks *node)
270 {
271   iks *feat;
272   char *ns;
273   for (feat = iks_child (node); feat != NULL; feat = iks_next (feat))
274     {
275       ns = iks_find_attrib (feat, "xmlns");
276       if (!iks_strcmp (ns, "urn:ietf:params:xml:ns:xmpp-tls"))
277         {
278           xmpp_tls_hook (parser, node);
279           return 0;
280         }
281       else if (!iks_strcmp (ns, "urn:ietf:params:xml:ns:xmpp-sasl"))
282         {
283           xmpp_sasl_hook (parser, node);
284           return 0;
285         }
286       else if (!iks_strcmp (ns, "urn:ietf:params:xml:ns:xmpp-bind"))
287         {
288           xmpp_bind_hook (parser, node);
289           return 0;
290         }
291     }
292   return 1;
293 }
294
295 int
296 xmpp_other_hook (iksparser *parser, iks *node, char *ns)
297 {
298   if (!iks_strcmp (ns, "urn:ietf:params:xml:ns:xmpp-sasl"))
299     {
300       if (!iks_strcmp (iks_name (node), "success"))
301         iks_send_header (parser, server);
302       else if (!iks_strcmp (iks_name (node), "failure"))
303         printf ("failture to authenticate: %s\n",
304                 iks_string (iks_stack (node), node));
305       return 0;
306     }
307   return 1;
308 }
309
310
311 static int
312 hook (void *data, int type, iks *node)
313 {
314   char *name;
315   char *id;
316   char *ns;
317   char *iqns;
318   iksparser *parser;
319   parser = *(iksparser **) data;
320   name = iks_name (node);
321   id = iks_find_attrib (node, "id");
322   ns = iks_find_attrib (node, "xmlns"); 
323   iqns = iks_find_attrib (iks_child (node), "xmlns"); 
324   if (!iks_strcmp (name, "message"))
325     {
326       char *from;
327       from = iks_find_attrib (node, "from");
328       if (!iks_strncmp (from, authed_jid, iks_strlen (authed_jid)))
329         {
330           char *body = iks_find_cdata (node, "body");
331           if (body != NULL)
332             process_mood (parser, body);
333         }
334       else
335         {
336           printf ("%s is not authorized\n", from);
337         }
338       return IKS_OK;
339     }
340   else if (!iks_strcmp (name, "presence"))
341     {
342       char *from;
343       from = iks_find_attrib (node, "from");
344       printf ("I sense a disturbance in the force: %s!\n", from);
345     }
346   else if (!iks_strcmp (name, "iq"))
347     {
348       if (xmpp_id_hook (parser, node, id) == 0)
349         return IKS_OK;
350       if (xmpp_ns_hook (parser, node, iqns) == 0)
351         return IKS_OK;
352       xmpp_iq_error (parser, node);
353     }
354   else if (!iks_strcmp (name, "stream:features"))
355     {
356       if (xmpp_features_hook (parser, node) == 0)
357         return IKS_OK;
358     }
359   else if (!iks_strcmp (name, "stream:error"))
360     {
361       printf ("streamerror: %s\n", iks_string (iks_stack (node), node));
362     }
363   else
364     {
365       if (xmpp_other_hook (parser, node, ns) == 0)
366         return IKS_OK;
367       printf ("No no: %s\n", name);
368     }
369   return IKS_OK;
370 }
371
372 int
373 main (int argc, char **argv)
374 {
375   iksparser *parser;
376   int c;
377   while ((c = getopt (argc, argv, "s:u:p:i:a:")) != -1)
378     {
379       switch (c)
380         {
381         case 's':
382           server = optarg;
383           break;
384         case 'u':
385           username = optarg;
386           break;
387         case 'p':
388           password = optarg;
389           break;
390         case 'i':
391           pbservice = optarg;
392           break;
393         case 'a':
394           authed_jid = optarg;
395           break;
396         }
397     }
398   parser = iks_stream_new ("jabber:client", &parser, hook);
399   iks_connect_tcp (parser, server, 5222);
400   while (1)
401     iks_recv (parser, -1);
402   return 0;
403 }