comparison mcabber/src/xmpp.c @ 1600:c5ee395fbc8c

Updated Entity Capabilities support (XEP-0115)
author franky
date Tue, 23 Sep 2008 10:59:25 +0200
parents dcd5d4c75199
children f4a2c6f767d1
comparison
equal deleted inserted replaced
1599:dcd5d4c75199 1600:c5ee395fbc8c
23 */ 23 */
24 #include <stdlib.h> 24 #include <stdlib.h>
25 #include <string.h> 25 #include <string.h>
26 #include <sys/utsname.h> 26 #include <sys/utsname.h>
27 27
28 #include "caps.h"
28 #include "commands.h" 29 #include "commands.h"
29 #include "events.h" 30 #include "events.h"
30 #include "histolog.h" 31 #include "histolog.h"
31 #include "hooks.h" 32 #include "hooks.h"
32 #include "logprint.h" 33 #include "logprint.h"
1251 } 1252 }
1252 1253
1253 return LM_HANDLER_RESULT_REMOVE_MESSAGE; 1254 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
1254 } 1255 }
1255 1256
1257 static LmHandlerResult cb_caps(LmMessageHandler *h, LmConnection *c,
1258 LmMessage *m, gpointer user_data)
1259 {
1260 char *ver = user_data;
1261
1262 if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_ERROR) {
1263 display_server_error(lm_message_node_get_child(m->node, "error"));
1264 } else if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_RESULT) {
1265 LmMessageNode *info;
1266 LmMessageNode *query = lm_message_node_get_child(m->node, "query");
1267
1268 caps_add(ver);
1269 info = lm_message_node_get_child(query, "identity");
1270 if (info)
1271 caps_set_identity(ver, lm_message_node_get_attribute(info, "category"),
1272 lm_message_node_get_attribute(info, "name"),
1273 lm_message_node_get_attribute(info, "type"));
1274 info = lm_message_node_get_child(query, "feature");
1275 while (info) {
1276 if (!g_strcmp0(info->name, "feature"))
1277 caps_add_feature(ver, lm_message_node_get_attribute(info, "var"));
1278 info = info->next;
1279 }
1280 }
1281 g_free(ver);
1282 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
1283 }
1284
1256 static LmHandlerResult handle_presence(LmMessageHandler *handler, 1285 static LmHandlerResult handle_presence(LmMessageHandler *handler,
1257 LmConnection *connection, 1286 LmConnection *connection,
1258 LmMessage *m, gpointer user_data) 1287 LmMessage *m, gpointer user_data)
1259 { 1288 {
1260 char *r; 1289 char *r;
1261 const char *from, *rname, *p=NULL, *ustmsg=NULL; 1290 const char *from, *rname, *p=NULL, *ustmsg=NULL;
1262 enum imstatus ust; 1291 enum imstatus ust;
1263 char bpprio; 1292 char bpprio;
1264 time_t timestamp = 0L; 1293 time_t timestamp = 0L;
1265 LmMessageNode *muc_packet; 1294 LmMessageNode *muc_packet, *caps;
1266 1295
1267 //Check for MUC presence packet 1296 //Check for MUC presence packet
1268 muc_packet = lm_message_node_find_xmlns 1297 muc_packet = lm_message_node_find_xmlns
1269 (m->node, "http://jabber.org/protocol/muc#user"); 1298 (m->node, "http://jabber.org/protocol/muc#user");
1270 1299
1341 // Presence signature processing 1370 // Presence signature processing
1342 if (!ustmsg) 1371 if (!ustmsg)
1343 ustmsg = ""; // Some clients omit the <status/> element :-( 1372 ustmsg = ""; // Some clients omit the <status/> element :-(
1344 check_signature(r, rname, lm_message_node_find_xmlns(m->node, NS_SIGNED), 1373 check_signature(r, rname, lm_message_node_find_xmlns(m->node, NS_SIGNED),
1345 ustmsg); 1374 ustmsg);
1375 }
1376
1377 //XEP-0115 Entity Capabilities
1378 caps = lm_message_node_find_xmlns(m->node, NS_CAPS);
1379 if (caps) {
1380 const char *ver = lm_message_node_get_attribute(caps, "ver");
1381 GSList *sl_buddy = NULL;
1382 if (rname)
1383 sl_buddy = roster_find(r, jidsearch, ROSTER_TYPE_USER);
1384 //only cache the caps if the user is on the roster
1385 if (sl_buddy && buddy_getonserverflag(sl_buddy->data)) {
1386 buddy_resource_setcaps(sl_buddy->data, rname, ver);
1387
1388 if (!caps_has_hash(ver)) {
1389 char *node;
1390 LmMessageHandler *handler;
1391 LmMessage *iq = lm_message_new_with_sub_type(from, LM_MESSAGE_TYPE_IQ,
1392 LM_MESSAGE_SUB_TYPE_GET);
1393 node = g_strdup_printf("%s#%s",
1394 lm_message_node_get_attribute(caps, "node"),
1395 ver);
1396 lm_message_node_set_attributes
1397 (lm_message_node_add_child(iq->node, "query", NULL),
1398 "xmlns", NS_DISCO_INFO,
1399 "node", node,
1400 NULL);
1401 g_free(node);
1402 handler = lm_message_handler_new(cb_caps, g_strdup(ver), NULL);
1403 lm_connection_send_with_reply(connection, iq, handler, NULL);
1404 lm_message_unref(iq);
1405 lm_message_handler_unref(handler);
1406 }
1407 }
1346 } 1408 }
1347 1409
1348 g_free(r); 1410 g_free(r);
1349 return LM_HANDLER_RESULT_REMOVE_MESSAGE; 1411 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
1350 } 1412 }
1691 } 1753 }
1692 } 1754 }
1693 1755
1694 // insert_entity_capabilities(presence_stanza) 1756 // insert_entity_capabilities(presence_stanza)
1695 // Entity Capabilities (XEP-0115) 1757 // Entity Capabilities (XEP-0115)
1696 static void insert_entity_capabilities(LmMessageNode * x) 1758 static void insert_entity_capabilities(LmMessageNode *x, enum imstatus status)
1697 { 1759 {
1698 LmMessageNode *y; 1760 LmMessageNode *y;
1699 const char *ver = entity_version(); 1761 const char *ver = entity_version(status);
1700 char *exts, *exts2;
1701
1702 exts = NULL;
1703 1762
1704 y = lm_message_node_add_child(x, "c", NULL); 1763 y = lm_message_node_add_child(x, "c", NULL);
1705 lm_message_node_set_attribute(y, "xmlns", NS_CAPS); 1764 lm_message_node_set_attribute(y, "xmlns", NS_CAPS);
1765 lm_message_node_set_attribute(y, "hash", "sha-1");
1706 lm_message_node_set_attribute(y, "node", MCABBER_CAPS_NODE); 1766 lm_message_node_set_attribute(y, "node", MCABBER_CAPS_NODE);
1707 lm_message_node_set_attribute(y, "ver", ver); 1767 lm_message_node_set_attribute(y, "ver", ver);
1708 #ifdef JEP0085
1709 if (!chatstates_disabled) {
1710 exts2 = g_strjoin(" ", "csn", exts, NULL);
1711 g_free(exts);
1712 exts = exts2;
1713 }
1714 #endif
1715 if (!settings_opt_get_int("iq_last_disable")) {
1716 exts2 = g_strjoin(" ", "iql", exts, NULL);
1717 g_free(exts);
1718 exts = exts2;
1719 }
1720 if (exts) {
1721 lm_message_node_set_attribute(y, "ext", exts);
1722 g_free(exts);
1723 }
1724 } 1768 }
1725 1769
1726 void xmpp_disconnect(void) 1770 void xmpp_disconnect(void)
1727 { 1771 {
1728 if (!lconnection || !lm_connection_is_authenticated(lconnection)) 1772 if (!lconnection || !lm_connection_is_authenticated(lconnection))
1763 // (But we want to update internal status even when disconnected, 1807 // (But we want to update internal status even when disconnected,
1764 // in order to avoid some problems during network failures) 1808 // in order to avoid some problems during network failures)
1765 if (lm_connection_is_authenticated(lconnection)) { 1809 if (lm_connection_is_authenticated(lconnection)) {
1766 const char *s_msg = (st != invisible ? msg : NULL); 1810 const char *s_msg = (st != invisible ? msg : NULL);
1767 m = lm_message_new_presence(st, recipient, s_msg); 1811 m = lm_message_new_presence(st, recipient, s_msg);
1768 insert_entity_capabilities(m->node); // Entity Capabilities (XEP-0115) 1812 insert_entity_capabilities(m->node, st); // Entity Capabilities (XEP-0115)
1769 #ifdef HAVE_GPGME 1813 #ifdef HAVE_GPGME
1770 if (!do_not_sign && gpg_enabled()) { 1814 if (!do_not_sign && gpg_enabled()) {
1771 char *signature; 1815 char *signature;
1772 signature = gpg_sign(s_msg ? s_msg : ""); 1816 signature = gpg_sign(s_msg ? s_msg : "");
1773 if (signature) { 1817 if (signature) {