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