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