Mercurial > hg
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, |