comparison mcabber/src/jab_iq.c @ 1215:80c095886fb5

Entity Capabilities support (XEP-0115)
author Mikael Berthe <mikael@lilotux.net>
date Tue, 08 May 2007 10:00:32 +0200
parents 4a7db2870685
children 21226969d59a
comparison
equal deleted inserted replaced
1214:9f5c5f176953 1215:80c095886fb5
32 #include "screen.h" 32 #include "screen.h"
33 #include "settings.h" 33 #include "settings.h"
34 #include "hbuf.h" 34 #include "hbuf.h"
35 #include "commands.h" 35 #include "commands.h"
36 36
37 #ifdef ENABLE_HGCSET
38 # include "hgcset.h"
39 #endif
40
37 41
38 // Bookmarks for IQ:private storage 42 // Bookmarks for IQ:private storage
39 xmlnode bookmarks; 43 xmlnode bookmarks;
40 // Roster notes for IQ:private storage 44 // Roster notes for IQ:private storage
41 xmlnode rosternotes; 45 xmlnode rosternotes;
95 {"dnd", "Do not disturb", "dnd"}, 99 {"dnd", "Do not disturb", "dnd"},
96 {"invisible", "Invisible", "invisible"}, 100 {"invisible", "Invisible", "invisible"},
97 {"offline", "Offline", "offline"}, 101 {"offline", "Offline", "offline"},
98 {NULL, NULL, NULL}, 102 {NULL, NULL, NULL},
99 }; 103 };
104
105 // entity_version()
106 // Return a static version string for Entity Capabilities.
107 // It should be specific to the client version, so we'll append
108 // a random string if it's a dev version and there's no changeset, or
109 // if it's been modified locally.
110 const char *entity_version(void)
111 {
112 static char *ver;
113 char *tver;
114
115 if (ver)
116 return ver;
117
118 #ifdef HGCSET
119 tver = g_strdup_printf("%s-%s", PACKAGE_VERSION, HGCSET);
120 if (strlen(HGCSET) == 12)
121 ver = tver;
122 #else
123 tver = g_strdup(PACKAGE_VERSION);
124 if (!strcasestr(PACKAGE_VERSION, "-dev"))
125 ver = tver; // Official release
126 #endif
127
128 // If this isn't an official release, or if the changeset shows the source
129 // code has been modified locally, we alter the release id.
130 if (!ver) {
131 unsigned int n;
132 srand(time(NULL));
133 n = (1U + (unsigned int)rand()) >> 8;
134 ver = g_strdup_printf("%s~%x", tver, n);
135 g_free(tver);
136 }
137 return ver;
138 }
100 139
101 // iqs_new(type, namespace, prefix, timeout) 140 // iqs_new(type, namespace, prefix, timeout)
102 // Create a query (GET, SET) IQ structure. This function should not be used 141 // Create a query (GET, SET) IQ structure. This function should not be used
103 // for RESULT packets. 142 // for RESULT packets.
104 eviqs *iqs_new(guint8 type, const char *ns, const char *prefix, time_t tmout) 143 eviqs *iqs_new(guint8 type, const char *ns, const char *prefix, time_t tmout)
1256 // not sure about this one 1295 // not sure about this one
1257 send_iq_not_implemented(conn, from, xmldata); 1296 send_iq_not_implemented(conn, from, xmldata);
1258 } 1297 }
1259 } 1298 }
1260 1299
1300 // disco_info_set_ext(ansquery, ext)
1301 // Add features attributes to ansquery for extension ext.
1302 static void disco_info_set_ext(xmlnode ansquery, const char *ext)
1303 {
1304 char *nodename;
1305 nodename = g_strdup_printf("%s#%s", MCABBER_CAPS_NODE, ext);
1306 xmlnode_put_attrib(ansquery, "node", nodename);
1307 g_free(nodename);
1308 if (!strcasecmp(ext, "csn")) {
1309 // I guess it's ok to send this even if it's not compiled in.
1310 xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"),
1311 "var", NS_CHATSTATES);
1312 }
1313 }
1314
1315 // disco_info_set_default(ansquery, entitycaps)
1316 // Add features attributes to ansquery. If entitycaps is TRUE, assume
1317 // that we're answering an Entity Caps request (if not, the request was
1318 // a basic discovery query).
1319 static void disco_info_set_default(xmlnode ansquery, guint entitycaps)
1320 {
1321 xmlnode y;
1322 char *eversion;
1323
1324 eversion = g_strdup_printf("%s#%s", MCABBER_CAPS_NODE, entity_version());
1325 xmlnode_put_attrib(ansquery, "node", eversion);
1326 g_free(eversion);
1327
1328 y = xmlnode_insert_tag(ansquery, "identity");
1329 xmlnode_put_attrib(y, "category", "client");
1330 xmlnode_put_attrib(y, "type", "pc");
1331 xmlnode_put_attrib(y, "name", PACKAGE_NAME);
1332
1333 xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"),
1334 "var", NS_DISCO_INFO);
1335 xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"),
1336 "var", NS_MUC);
1337 #ifdef JEP0085
1338 // Advertise ChatStates only if we're not using Entity Capabilities
1339 if (!entitycaps)
1340 xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"),
1341 "var", NS_CHATSTATES);
1342 #endif
1343 xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"),
1344 "var", NS_TIME);
1345 xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"),
1346 "var", NS_VERSION);
1347 xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"),
1348 "var", NS_PING);
1349 xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"),
1350 "var", NS_COMMANDS);
1351 }
1352
1261 static void handle_iq_disco_info(jconn conn, char *from, const char *id, 1353 static void handle_iq_disco_info(jconn conn, char *from, const char *id,
1262 xmlnode xmldata) 1354 xmlnode xmldata)
1263 { 1355 {
1264 xmlnode x, y; 1356 xmlnode x;
1265 xmlnode myquery; 1357 xmlnode myquery;
1358 char *node;
1266 1359
1267 x = jutil_iqnew(JPACKET__RESULT, NS_DISCO_INFO); 1360 x = jutil_iqnew(JPACKET__RESULT, NS_DISCO_INFO);
1268 xmlnode_put_attrib(x, "id", id); 1361 xmlnode_put_attrib(x, "id", id);
1269 xmlnode_put_attrib(x, "to", xmlnode_get_attrib(xmldata, "from")); 1362 xmlnode_put_attrib(x, "to", xmlnode_get_attrib(xmldata, "from"));
1270 myquery = xmlnode_get_tag(x, "query"); 1363 myquery = xmlnode_get_tag(x, "query");
1271 1364
1272 y = xmlnode_insert_tag(myquery, "identity"); 1365 node = xmlnode_get_attrib(xmlnode_get_tag(xmldata, "query"), "node");
1273 xmlnode_put_attrib(y, "category", "client"); 1366 if (node && startswith(node, MCABBER_CAPS_NODE "#", FALSE)) {
1274 xmlnode_put_attrib(y, "type", "pc"); 1367 const char *param = node+strlen(MCABBER_CAPS_NODE)+1;
1275 xmlnode_put_attrib(y, "name", PACKAGE_NAME); 1368 if (!strcmp(param, entity_version()))
1276 1369 disco_info_set_default(myquery, TRUE); // client#version
1277 xmlnode_put_attrib(xmlnode_insert_tag(myquery, "feature"), 1370 else
1278 "var", NS_DISCO_INFO); 1371 disco_info_set_ext(myquery, param); // client#extension
1279 xmlnode_put_attrib(xmlnode_insert_tag(myquery, "feature"), 1372 } else {
1280 "var", NS_MUC); 1373 // Basic discovery request
1281 xmlnode_put_attrib(xmlnode_insert_tag(myquery, "feature"), 1374 disco_info_set_default(myquery, FALSE);
1282 "var", NS_CHATSTATES); 1375 }
1283 xmlnode_put_attrib(xmlnode_insert_tag(myquery, "feature"), 1376
1284 "var", NS_TIME);
1285 xmlnode_put_attrib(xmlnode_insert_tag(myquery, "feature"),
1286 "var", NS_VERSION);
1287 xmlnode_put_attrib(xmlnode_insert_tag(myquery, "feature"),
1288 "var", NS_PING);
1289 xmlnode_put_attrib(xmlnode_insert_tag(myquery, "feature"),
1290 "var", NS_COMMANDS);
1291 jab_send(jc, x); 1377 jab_send(jc, x);
1292 xmlnode_free(x); 1378 xmlnode_free(x);
1293 } 1379 }
1294 1380
1295 static void handle_iq_ping(jconn conn, char *from, const char *id, 1381 static void handle_iq_ping(jconn conn, char *from, const char *id,