| 44 feature = xmlnode_new_child(query, "feature"); \ |
44 feature = xmlnode_new_child(query, "feature"); \ |
| 45 xmlnode_set_attrib(feature, "var", x); \ |
45 xmlnode_set_attrib(feature, "var", x); \ |
| 46 } |
46 } |
| 47 |
47 |
| 48 static void |
48 static void |
| 49 jabber_disco_bytestream_server_cb(JabberStream *js, xmlnode *packet, gpointer data) { |
49 jabber_disco_bytestream_server_cb(JabberStream *js, const char *from, |
| |
50 JabberIqType type, const char *id, |
| |
51 xmlnode *packet, gpointer data) |
| |
52 { |
| 50 JabberBytestreamsStreamhost *sh = data; |
53 JabberBytestreamsStreamhost *sh = data; |
| 51 const char *from = xmlnode_get_attrib(packet, "from"); |
|
| 52 xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", |
54 xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", |
| 53 "http://jabber.org/protocol/bytestreams"); |
55 "http://jabber.org/protocol/bytestreams"); |
| 54 |
56 |
| 55 if (from && !strcmp(from, sh->jid) && query != NULL) { |
57 if (from && !strcmp(from, sh->jid) && query != NULL) { |
| 56 xmlnode *sh_node = xmlnode_get_child(query, "streamhost"); |
58 xmlnode *sh_node = xmlnode_get_child(query, "streamhost"); |
| 84 js->bs_proxies = g_list_remove(js->bs_proxies, sh); |
86 js->bs_proxies = g_list_remove(js->bs_proxies, sh); |
| 85 } |
87 } |
| 86 } |
88 } |
| 87 |
89 |
| 88 |
90 |
| 89 void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) { |
91 void jabber_disco_info_parse(JabberStream *js, const char *from, |
| 90 const char *from = xmlnode_get_attrib(packet, "from"); |
92 JabberIqType type, const char *id, |
| 91 const char *type = xmlnode_get_attrib(packet, "type"); |
93 xmlnode *in_query) |
| 92 |
94 { |
| 93 if(!from || !type) |
95 |
| 94 return; |
96 if(!from) |
| 95 |
97 return; |
| 96 if(!strcmp(type, "get")) { |
98 |
| |
99 if(type == JABBER_IQ_GET) { |
| 97 xmlnode *query, *identity, *feature; |
100 xmlnode *query, *identity, *feature; |
| 98 JabberIq *iq; |
101 JabberIq *iq; |
| 99 |
102 const char *node = xmlnode_get_attrib(in_query, "node"); |
| 100 xmlnode *in_query; |
|
| 101 const char *node = NULL; |
|
| 102 char *node_uri = NULL; |
103 char *node_uri = NULL; |
| 103 |
104 |
| 104 /* create custom caps node URI */ |
105 /* create custom caps node URI */ |
| 105 node_uri = g_strconcat(CAPS0115_NODE, "#", jabber_caps_get_own_hash(js), NULL); |
106 node_uri = g_strconcat(CAPS0115_NODE, "#", jabber_caps_get_own_hash(js), NULL); |
| 106 |
107 |
| 107 if((in_query = xmlnode_get_child(packet, "query"))) { |
|
| 108 node = xmlnode_get_attrib(in_query, "node"); |
|
| 109 } |
|
| 110 |
|
| 111 |
|
| 112 iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, |
108 iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, |
| 113 "http://jabber.org/protocol/disco#info"); |
109 "http://jabber.org/protocol/disco#info"); |
| 114 |
110 |
| 115 jabber_iq_set_id(iq, xmlnode_get_attrib(packet, "id")); |
111 jabber_iq_set_id(iq, id); |
| 116 |
112 |
| 117 xmlnode_set_attrib(iq->node, "to", from); |
113 xmlnode_set_attrib(iq->node, "to", from); |
| 118 query = xmlnode_get_child(iq->node, "query"); |
114 query = xmlnode_get_child(iq->node, "query"); |
| 119 |
115 |
| 120 if(node) |
116 if(node) |
| 144 for(features = jabber_features; features; features = features->next) { |
140 for(features = jabber_features; features; features = features->next) { |
| 145 JabberFeature *feat = (JabberFeature*)features->data; |
141 JabberFeature *feat = (JabberFeature*)features->data; |
| 146 if (!feat->is_enabled || feat->is_enabled(js, feat->namespace)) { |
142 if (!feat->is_enabled || feat->is_enabled(js, feat->namespace)) { |
| 147 feature = xmlnode_new_child(query, "feature"); |
143 feature = xmlnode_new_child(query, "feature"); |
| 148 xmlnode_set_attrib(feature, "var", feat->namespace); |
144 xmlnode_set_attrib(feature, "var", feat->namespace); |
| 149 } |
145 } |
| 150 } |
146 } |
| 151 #ifdef USE_VV |
147 #ifdef USE_VV |
| 152 } else if (g_str_equal(node, CAPS0115_NODE "#" "voice-v1")) { |
148 } else if (g_str_equal(node, CAPS0115_NODE "#" "voice-v1")) { |
| 153 /* |
149 /* |
| 154 * HUGE HACK! We advertise this ext (see jabber_presence_create_js |
150 * HUGE HACK! We advertise this ext (see jabber_presence_create_js |
| 175 inf = xmlnode_new_child(error, "item-not-found"); |
171 inf = xmlnode_new_child(error, "item-not-found"); |
| 176 xmlnode_set_namespace(inf, "urn:ietf:params:xml:ns:xmpp-stanzas"); |
172 xmlnode_set_namespace(inf, "urn:ietf:params:xml:ns:xmpp-stanzas"); |
| 177 } |
173 } |
| 178 g_free(node_uri); |
174 g_free(node_uri); |
| 179 jabber_iq_send(iq); |
175 jabber_iq_send(iq); |
| 180 } else if(!strcmp(type, "result")) { |
176 } else if(type == JABBER_IQ_RESULT) { |
| 181 xmlnode *query = xmlnode_get_child(packet, "query"); |
|
| 182 xmlnode *child; |
177 xmlnode *child; |
| 183 JabberID *jid; |
178 JabberID *jid; |
| 184 JabberBuddy *jb; |
179 JabberBuddy *jb; |
| 185 JabberBuddyResource *jbr = NULL; |
180 JabberBuddyResource *jbr = NULL; |
| 186 JabberCapabilities capabilities = JABBER_CAP_NONE; |
181 JabberCapabilities capabilities = JABBER_CAP_NONE; |
| 193 } |
188 } |
| 194 |
189 |
| 195 if(jbr) |
190 if(jbr) |
| 196 capabilities = jbr->capabilities; |
191 capabilities = jbr->capabilities; |
| 197 |
192 |
| 198 for(child = query->child; child; child = child->next) { |
193 for(child = in_query->child; child; child = child->next) { |
| 199 if(child->type != XMLNODE_TYPE_TAG) |
194 if(child->type != XMLNODE_TYPE_TAG) |
| 200 continue; |
195 continue; |
| 201 |
196 |
| 202 if(!strcmp(child->name, "identity")) { |
197 if(!strcmp(child->name, "identity")) { |
| 203 const char *category = xmlnode_get_attrib(child, "category"); |
198 const char *category = xmlnode_get_attrib(child, "category"); |
| 243 capabilities |= JABBER_CAP_BYTESTREAMS; |
238 capabilities |= JABBER_CAP_BYTESTREAMS; |
| 244 else if(!strcmp(var, "jabber:iq:search")) |
239 else if(!strcmp(var, "jabber:iq:search")) |
| 245 capabilities |= JABBER_CAP_IQ_SEARCH; |
240 capabilities |= JABBER_CAP_IQ_SEARCH; |
| 246 else if(!strcmp(var, "jabber:iq:register")) |
241 else if(!strcmp(var, "jabber:iq:register")) |
| 247 capabilities |= JABBER_CAP_IQ_REGISTER; |
242 capabilities |= JABBER_CAP_IQ_REGISTER; |
| 248 else if(!strcmp(var, "http://www.xmpp.org/extensions/xep-0199.html#ns")) |
243 else if(!strcmp(var, "urn:xmpp:ping")) |
| 249 capabilities |= JABBER_CAP_PING; |
244 capabilities |= JABBER_CAP_PING; |
| 250 else if(!strcmp(var, "http://jabber.org/protocol/commands")) { |
245 else if(!strcmp(var, "http://jabber.org/protocol/commands")) { |
| 251 capabilities |= JABBER_CAP_ADHOC; |
246 capabilities |= JABBER_CAP_ADHOC; |
| 252 } |
247 } |
| 253 else if(!strcmp(var, "http://jabber.org/protocol/ibb")) { |
248 else if(!strcmp(var, "http://jabber.org/protocol/ibb")) { |
| 264 |
259 |
| 265 if((jdicd = g_hash_table_lookup(js->disco_callbacks, from))) { |
260 if((jdicd = g_hash_table_lookup(js->disco_callbacks, from))) { |
| 266 jdicd->callback(js, from, capabilities, jdicd->data); |
261 jdicd->callback(js, from, capabilities, jdicd->data); |
| 267 g_hash_table_remove(js->disco_callbacks, from); |
262 g_hash_table_remove(js->disco_callbacks, from); |
| 268 } |
263 } |
| 269 } else if(!strcmp(type, "error")) { |
264 } else if(type == JABBER_IQ_ERROR) { |
| 270 JabberID *jid; |
265 JabberID *jid; |
| 271 JabberBuddy *jb; |
266 JabberBuddy *jb; |
| 272 JabberBuddyResource *jbr = NULL; |
267 JabberBuddyResource *jbr = NULL; |
| 273 JabberCapabilities capabilities = JABBER_CAP_NONE; |
268 JabberCapabilities capabilities = JABBER_CAP_NONE; |
| 274 struct _jabber_disco_info_cb_data *jdicd; |
269 struct _jabber_disco_info_cb_data *jdicd; |
| 288 jdicd->callback(js, from, capabilities, jdicd->data); |
283 jdicd->callback(js, from, capabilities, jdicd->data); |
| 289 g_hash_table_remove(js->disco_callbacks, from); |
284 g_hash_table_remove(js->disco_callbacks, from); |
| 290 } |
285 } |
| 291 } |
286 } |
| 292 |
287 |
| 293 void jabber_disco_items_parse(JabberStream *js, xmlnode *packet) { |
288 void jabber_disco_items_parse(JabberStream *js, const char *from, |
| 294 const char *from = xmlnode_get_attrib(packet, "from"); |
289 JabberIqType type, const char *id, |
| 295 const char *type = xmlnode_get_attrib(packet, "type"); |
290 xmlnode *query) |
| 296 |
291 { |
| 297 if(type && !strcmp(type, "get")) { |
292 if(type == JABBER_IQ_GET) { |
| 298 JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, |
293 JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, |
| 299 "http://jabber.org/protocol/disco#items"); |
294 "http://jabber.org/protocol/disco#items"); |
| 300 |
295 |
| 301 /* preserve node */ |
296 /* preserve node */ |
| 302 xmlnode *iq_query = xmlnode_get_child_with_namespace(iq->node,"query","http://jabber.org/protocol/disco#items"); |
297 xmlnode *iq_query = xmlnode_get_child(iq->node, "query"); |
| 303 if(iq_query) { |
298 const char *node = xmlnode_get_attrib(query, "node"); |
| 304 xmlnode *query = xmlnode_get_child_with_namespace(packet,"query","http://jabber.org/protocol/disco#items"); |
299 if(node) |
| 305 if(query) { |
300 xmlnode_set_attrib(iq_query,"node",node); |
| 306 const char *node = xmlnode_get_attrib(query,"node"); |
301 |
| 307 if(node) |
302 jabber_iq_set_id(iq, id); |
| 308 xmlnode_set_attrib(iq_query,"node",node); |
303 |
| 309 } |
304 if (from) |
| 310 } |
305 xmlnode_set_attrib(iq->node, "to", from); |
| 311 |
|
| 312 jabber_iq_set_id(iq, xmlnode_get_attrib(packet, "id")); |
|
| 313 |
|
| 314 xmlnode_set_attrib(iq->node, "to", from); |
|
| 315 jabber_iq_send(iq); |
306 jabber_iq_send(iq); |
| 316 } |
307 } |
| 317 } |
308 } |
| 318 |
309 |
| 319 static void |
310 static void |
| 371 } |
362 } |
| 372 |
363 |
| 373 } |
364 } |
| 374 |
365 |
| 375 static void |
366 static void |
| 376 jabber_disco_server_info_result_cb(JabberStream *js, xmlnode *packet, gpointer data) |
367 jabber_disco_server_info_result_cb(JabberStream *js, const char *from, |
| |
368 JabberIqType type, const char *id, |
| |
369 xmlnode *packet, gpointer data) |
| 377 { |
370 { |
| 378 xmlnode *query, *child; |
371 xmlnode *query, *child; |
| 379 const char *from = xmlnode_get_attrib(packet, "from"); |
372 |
| 380 const char *type = xmlnode_get_attrib(packet, "type"); |
373 if (!from || strcmp(from, js->user->domain)) { |
| 381 |
|
| 382 if((!from || !type) || |
|
| 383 (strcmp(from, js->user->domain))) { |
|
| 384 jabber_disco_finish_server_info_result_cb(js); |
374 jabber_disco_finish_server_info_result_cb(js); |
| 385 return; |
375 return; |
| 386 } |
376 } |
| 387 |
377 |
| 388 if(strcmp(type, "result")) { |
378 if (type == JABBER_IQ_ERROR) { |
| 389 /* A common way to get here is for the server not to support xmlns http://jabber.org/protocol/disco#info */ |
379 /* A common way to get here is for the server not to support xmlns http://jabber.org/protocol/disco#info */ |
| 390 jabber_disco_finish_server_info_result_cb(js); |
380 jabber_disco_finish_server_info_result_cb(js); |
| 391 return; |
381 return; |
| 392 } |
382 } |
| 393 |
383 |
| 449 |
439 |
| 450 jabber_disco_finish_server_info_result_cb(js); |
440 jabber_disco_finish_server_info_result_cb(js); |
| 451 } |
441 } |
| 452 |
442 |
| 453 static void |
443 static void |
| 454 jabber_disco_server_items_result_cb(JabberStream *js, xmlnode *packet, gpointer data) |
444 jabber_disco_server_items_result_cb(JabberStream *js, const char *from, |
| |
445 JabberIqType type, const char *id, |
| |
446 xmlnode *packet, gpointer data) |
| 455 { |
447 { |
| 456 xmlnode *query, *child; |
448 xmlnode *query, *child; |
| 457 const char *from = xmlnode_get_attrib(packet, "from"); |
449 |
| 458 const char *type = xmlnode_get_attrib(packet, "type"); |
450 if (!from || strcmp(from, js->user->domain) != 0) |
| 459 |
451 return; |
| 460 if(!from || !type) |
452 |
| 461 return; |
453 if (type == JABBER_IQ_ERROR) |
| 462 |
|
| 463 if(strcmp(from, js->user->domain)) |
|
| 464 return; |
|
| 465 |
|
| 466 if(strcmp(type, "result")) |
|
| 467 return; |
454 return; |
| 468 |
455 |
| 469 while(js->chat_servers) { |
456 while(js->chat_servers) { |
| 470 g_free(js->chat_servers->data); |
457 g_free(js->chat_servers->data); |
| 471 js->chat_servers = g_list_delete_link(js->chat_servers, js->chat_servers); |
458 js->chat_servers = g_list_delete_link(js->chat_servers, js->chat_servers); |