| 160 |
160 |
| 161 static void |
161 static void |
| 162 xmpp_disco_info_do(PurpleConnection *pc, gpointer cbdata, const char *jid, |
162 xmpp_disco_info_do(PurpleConnection *pc, gpointer cbdata, const char *jid, |
| 163 const char *node, XmppIqCallback cb) |
163 const char *node, XmppIqCallback cb) |
| 164 { |
164 { |
| 165 xmlnode *iq, *query; |
165 PurpleXmlNode *iq, *query; |
| 166 char *id = generate_next_id(); |
166 char *id = generate_next_id(); |
| 167 |
167 |
| 168 iq = xmlnode_new("iq"); |
168 iq = purple_xmlnode_new("iq"); |
| 169 xmlnode_set_attrib(iq, "type", "get"); |
169 purple_xmlnode_set_attrib(iq, "type", "get"); |
| 170 xmlnode_set_attrib(iq, "to", jid); |
170 purple_xmlnode_set_attrib(iq, "to", jid); |
| 171 xmlnode_set_attrib(iq, "id", id); |
171 purple_xmlnode_set_attrib(iq, "id", id); |
| 172 |
172 |
| 173 query = xmlnode_new_child(iq, "query"); |
173 query = purple_xmlnode_new_child(iq, "query"); |
| 174 xmlnode_set_namespace(query, NS_DISCO_INFO); |
174 purple_xmlnode_set_namespace(query, NS_DISCO_INFO); |
| 175 if (node) |
175 if (node) |
| 176 xmlnode_set_attrib(query, "node", node); |
176 purple_xmlnode_set_attrib(query, "node", node); |
| 177 |
177 |
| 178 /* Steals id */ |
178 /* Steals id */ |
| 179 xmpp_iq_register_callback(pc, id, cbdata, cb); |
179 xmpp_iq_register_callback(pc, id, cbdata, cb); |
| 180 |
180 |
| 181 purple_signal_emit(purple_connection_get_protocol(pc), "jabber-sending-xmlnode", |
181 purple_signal_emit(purple_connection_get_protocol(pc), "jabber-sending-xmlnode", |
| 182 pc, &iq); |
182 pc, &iq); |
| 183 if (iq != NULL) |
183 if (iq != NULL) |
| 184 xmlnode_free(iq); |
184 purple_xmlnode_free(iq); |
| 185 } |
185 } |
| 186 |
186 |
| 187 static void |
187 static void |
| 188 xmpp_disco_items_do(PurpleConnection *pc, gpointer cbdata, const char *jid, |
188 xmpp_disco_items_do(PurpleConnection *pc, gpointer cbdata, const char *jid, |
| 189 const char *node, XmppIqCallback cb) |
189 const char *node, XmppIqCallback cb) |
| 190 { |
190 { |
| 191 xmlnode *iq, *query; |
191 PurpleXmlNode *iq, *query; |
| 192 char *id = generate_next_id(); |
192 char *id = generate_next_id(); |
| 193 |
193 |
| 194 iq = xmlnode_new("iq"); |
194 iq = purple_xmlnode_new("iq"); |
| 195 xmlnode_set_attrib(iq, "type", "get"); |
195 purple_xmlnode_set_attrib(iq, "type", "get"); |
| 196 xmlnode_set_attrib(iq, "to", jid); |
196 purple_xmlnode_set_attrib(iq, "to", jid); |
| 197 xmlnode_set_attrib(iq, "id", id); |
197 purple_xmlnode_set_attrib(iq, "id", id); |
| 198 |
198 |
| 199 query = xmlnode_new_child(iq, "query"); |
199 query = purple_xmlnode_new_child(iq, "query"); |
| 200 xmlnode_set_namespace(query, NS_DISCO_ITEMS); |
200 purple_xmlnode_set_namespace(query, NS_DISCO_ITEMS); |
| 201 if (node) |
201 if (node) |
| 202 xmlnode_set_attrib(query, "node", node); |
202 purple_xmlnode_set_attrib(query, "node", node); |
| 203 |
203 |
| 204 /* Steals id */ |
204 /* Steals id */ |
| 205 xmpp_iq_register_callback(pc, id, cbdata, cb); |
205 xmpp_iq_register_callback(pc, id, cbdata, cb); |
| 206 |
206 |
| 207 purple_signal_emit(purple_connection_get_protocol(pc), "jabber-sending-xmlnode", |
207 purple_signal_emit(purple_connection_get_protocol(pc), "jabber-sending-xmlnode", |
| 208 pc, &iq); |
208 pc, &iq); |
| 209 if (iq != NULL) |
209 if (iq != NULL) |
| 210 xmlnode_free(iq); |
210 purple_xmlnode_free(iq); |
| 211 } |
211 } |
| 212 |
212 |
| 213 static XmppDiscoServiceType |
213 static XmppDiscoServiceType |
| 214 disco_service_type_from_identity(xmlnode *identity) |
214 disco_service_type_from_identity(PurpleXmlNode *identity) |
| 215 { |
215 { |
| 216 const char *category, *type; |
216 const char *category, *type; |
| 217 |
217 |
| 218 if (!identity) |
218 if (!identity) |
| 219 return XMPP_DISCO_SERVICE_TYPE_OTHER; |
219 return XMPP_DISCO_SERVICE_TYPE_OTHER; |
| 220 |
220 |
| 221 category = xmlnode_get_attrib(identity, "category"); |
221 category = purple_xmlnode_get_attrib(identity, "category"); |
| 222 type = xmlnode_get_attrib(identity, "type"); |
222 type = purple_xmlnode_get_attrib(identity, "type"); |
| 223 |
223 |
| 224 if (!category) |
224 if (!category) |
| 225 return XMPP_DISCO_SERVICE_TYPE_OTHER; |
225 return XMPP_DISCO_SERVICE_TYPE_OTHER; |
| 226 |
226 |
| 227 if (g_str_equal(category, "conference")) |
227 if (g_str_equal(category, "conference")) |
| 273 return str; |
273 return str; |
| 274 } |
274 } |
| 275 |
275 |
| 276 static void |
276 static void |
| 277 got_info_cb(PurpleConnection *pc, const char *type, const char *id, |
277 got_info_cb(PurpleConnection *pc, const char *type, const char *id, |
| 278 const char *from, xmlnode *iq, gpointer data) |
278 const char *from, PurpleXmlNode *iq, gpointer data) |
| 279 { |
279 { |
| 280 struct item_data *item_data = data; |
280 struct item_data *item_data = data; |
| 281 PidginDiscoList *list = item_data->list; |
281 PidginDiscoList *list = item_data->list; |
| 282 xmlnode *query; |
282 PurpleXmlNode *query; |
| 283 |
283 |
| 284 --list->fetch_count; |
284 --list->fetch_count; |
| 285 |
285 |
| 286 if (!list->in_progress) |
286 if (!list->in_progress) |
| 287 goto out; |
287 goto out; |
| 288 |
288 |
| 289 if (g_str_equal(type, "result") && |
289 if (g_str_equal(type, "result") && |
| 290 (query = xmlnode_get_child(iq, "query"))) { |
290 (query = purple_xmlnode_get_child(iq, "query"))) { |
| 291 xmlnode *identity = xmlnode_get_child(query, "identity"); |
291 PurpleXmlNode *identity = purple_xmlnode_get_child(query, "identity"); |
| 292 XmppDiscoService *service; |
292 XmppDiscoService *service; |
| 293 xmlnode *feature; |
293 PurpleXmlNode *feature; |
| 294 |
294 |
| 295 service = g_new0(XmppDiscoService, 1); |
295 service = g_new0(XmppDiscoService, 1); |
| 296 service->list = item_data->list; |
296 service->list = item_data->list; |
| 297 purple_debug_info("xmppdisco", "parent for %s is %p\n", from, item_data->parent); |
297 purple_debug_info("xmppdisco", "parent for %s is %p\n", from, item_data->parent); |
| 298 service->parent = item_data->parent; |
298 service->parent = item_data->parent; |
| 320 |
320 |
| 321 if (item_data->name) { |
321 if (item_data->name) { |
| 322 service->description = item_data->name; |
322 service->description = item_data->name; |
| 323 item_data->name = NULL; |
323 item_data->name = NULL; |
| 324 } else if (identity) |
324 } else if (identity) |
| 325 service->description = g_strdup(xmlnode_get_attrib(identity, "name")); |
325 service->description = g_strdup(purple_xmlnode_get_attrib(identity, "name")); |
| 326 |
326 |
| 327 /* TODO: Overlap with service->name a bit */ |
327 /* TODO: Overlap with service->name a bit */ |
| 328 service->jid = g_strdup(from); |
328 service->jid = g_strdup(from); |
| 329 |
329 |
| 330 for (feature = xmlnode_get_child(query, "feature"); feature; |
330 for (feature = purple_xmlnode_get_child(query, "feature"); feature; |
| 331 feature = xmlnode_get_next_twin(feature)) { |
331 feature = purple_xmlnode_get_next_twin(feature)) { |
| 332 const char *var; |
332 const char *var; |
| 333 if (!(var = xmlnode_get_attrib(feature, "var"))) |
333 if (!(var = purple_xmlnode_get_attrib(feature, "var"))) |
| 334 continue; |
334 continue; |
| 335 |
335 |
| 336 if (g_str_equal(var, NS_REGISTER)) |
336 if (g_str_equal(var, NS_REGISTER)) |
| 337 service->flags |= XMPP_DISCO_REGISTER; |
337 service->flags |= XMPP_DISCO_REGISTER; |
| 338 else if (g_str_equal(var, NS_DISCO_ITEMS)) |
338 else if (g_str_equal(var, NS_DISCO_ITEMS)) |
| 360 pidgin_disco_list_unref(list); |
360 pidgin_disco_list_unref(list); |
| 361 } |
361 } |
| 362 |
362 |
| 363 static void |
363 static void |
| 364 got_items_cb(PurpleConnection *pc, const char *type, const char *id, |
364 got_items_cb(PurpleConnection *pc, const char *type, const char *id, |
| 365 const char *from, xmlnode *iq, gpointer data) |
365 const char *from, PurpleXmlNode *iq, gpointer data) |
| 366 { |
366 { |
| 367 struct item_data *item_data = data; |
367 struct item_data *item_data = data; |
| 368 PidginDiscoList *list = item_data->list; |
368 PidginDiscoList *list = item_data->list; |
| 369 xmlnode *query; |
369 PurpleXmlNode *query; |
| 370 gboolean has_items = FALSE; |
370 gboolean has_items = FALSE; |
| 371 |
371 |
| 372 --list->fetch_count; |
372 --list->fetch_count; |
| 373 |
373 |
| 374 if (!list->in_progress) |
374 if (!list->in_progress) |
| 375 goto out; |
375 goto out; |
| 376 |
376 |
| 377 if (g_str_equal(type, "result") && |
377 if (g_str_equal(type, "result") && |
| 378 (query = xmlnode_get_child(iq, "query"))) { |
378 (query = purple_xmlnode_get_child(iq, "query"))) { |
| 379 xmlnode *item; |
379 PurpleXmlNode *item; |
| 380 |
380 |
| 381 for (item = xmlnode_get_child(query, "item"); item; |
381 for (item = purple_xmlnode_get_child(query, "item"); item; |
| 382 item = xmlnode_get_next_twin(item)) { |
382 item = purple_xmlnode_get_next_twin(item)) { |
| 383 const char *jid = xmlnode_get_attrib(item, "jid"); |
383 const char *jid = purple_xmlnode_get_attrib(item, "jid"); |
| 384 const char *name = xmlnode_get_attrib(item, "name"); |
384 const char *name = purple_xmlnode_get_attrib(item, "name"); |
| 385 const char *node = xmlnode_get_attrib(item, "node"); |
385 const char *node = purple_xmlnode_get_attrib(item, "node"); |
| 386 |
386 |
| 387 has_items = TRUE; |
387 has_items = TRUE; |
| 388 |
388 |
| 389 if (item_data->parent->type == XMPP_DISCO_SERVICE_TYPE_CHAT) { |
389 if (item_data->parent->type == XMPP_DISCO_SERVICE_TYPE_CHAT) { |
| 390 /* This is a hacky first-order approximation. Any MUC |
390 /* This is a hacky first-order approximation. Any MUC |
| 430 pidgin_disco_list_unref(list); |
430 pidgin_disco_list_unref(list); |
| 431 } |
431 } |
| 432 |
432 |
| 433 static void |
433 static void |
| 434 server_items_cb(PurpleConnection *pc, const char *type, const char *id, |
434 server_items_cb(PurpleConnection *pc, const char *type, const char *id, |
| 435 const char *from, xmlnode *iq, gpointer data) |
435 const char *from, PurpleXmlNode *iq, gpointer data) |
| 436 { |
436 { |
| 437 struct item_data *cb_data = data; |
437 struct item_data *cb_data = data; |
| 438 PidginDiscoList *list = cb_data->list; |
438 PidginDiscoList *list = cb_data->list; |
| 439 xmlnode *query; |
439 PurpleXmlNode *query; |
| 440 |
440 |
| 441 g_free(cb_data); |
441 g_free(cb_data); |
| 442 --list->fetch_count; |
442 --list->fetch_count; |
| 443 |
443 |
| 444 if (g_str_equal(type, "result") && |
444 if (g_str_equal(type, "result") && |
| 445 (query = xmlnode_get_child(iq, "query"))) { |
445 (query = purple_xmlnode_get_child(iq, "query"))) { |
| 446 xmlnode *item; |
446 PurpleXmlNode *item; |
| 447 |
447 |
| 448 for (item = xmlnode_get_child(query, "item"); item; |
448 for (item = purple_xmlnode_get_child(query, "item"); item; |
| 449 item = xmlnode_get_next_twin(item)) { |
449 item = purple_xmlnode_get_next_twin(item)) { |
| 450 const char *jid = xmlnode_get_attrib(item, "jid"); |
450 const char *jid = purple_xmlnode_get_attrib(item, "jid"); |
| 451 const char *name = xmlnode_get_attrib(item, "name"); |
451 const char *name = purple_xmlnode_get_attrib(item, "name"); |
| 452 const char *node = xmlnode_get_attrib(item, "node"); |
452 const char *node = purple_xmlnode_get_attrib(item, "node"); |
| 453 struct item_data *item_data; |
453 struct item_data *item_data; |
| 454 |
454 |
| 455 if (!jid) |
455 if (!jid) |
| 456 continue; |
456 continue; |
| 457 |
457 |
| 472 pidgin_disco_list_unref(list); |
472 pidgin_disco_list_unref(list); |
| 473 } |
473 } |
| 474 |
474 |
| 475 static void |
475 static void |
| 476 server_info_cb(PurpleConnection *pc, const char *type, const char *id, |
476 server_info_cb(PurpleConnection *pc, const char *type, const char *id, |
| 477 const char *from, xmlnode *iq, gpointer data) |
477 const char *from, PurpleXmlNode *iq, gpointer data) |
| 478 { |
478 { |
| 479 struct item_data *cb_data = data; |
479 struct item_data *cb_data = data; |
| 480 PidginDiscoList *list = cb_data->list; |
480 PidginDiscoList *list = cb_data->list; |
| 481 xmlnode *query; |
481 PurpleXmlNode *query; |
| 482 xmlnode *error; |
482 PurpleXmlNode *error; |
| 483 gboolean items = FALSE; |
483 gboolean items = FALSE; |
| 484 |
484 |
| 485 --list->fetch_count; |
485 --list->fetch_count; |
| 486 |
486 |
| 487 if (g_str_equal(type, "result") && |
487 if (g_str_equal(type, "result") && |
| 488 (query = xmlnode_get_child(iq, "query"))) { |
488 (query = purple_xmlnode_get_child(iq, "query"))) { |
| 489 xmlnode *feature; |
489 PurpleXmlNode *feature; |
| 490 |
490 |
| 491 for (feature = xmlnode_get_child(query, "feature"); feature; |
491 for (feature = purple_xmlnode_get_child(query, "feature"); feature; |
| 492 feature = xmlnode_get_next_twin(feature)) { |
492 feature = purple_xmlnode_get_next_twin(feature)) { |
| 493 const char *var = xmlnode_get_attrib(feature, "var"); |
493 const char *var = purple_xmlnode_get_attrib(feature, "var"); |
| 494 if (purple_strequal(var, NS_DISCO_ITEMS)) { |
494 if (purple_strequal(var, NS_DISCO_ITEMS)) { |
| 495 items = TRUE; |
495 items = TRUE; |
| 496 break; |
496 break; |
| 497 } |
497 } |
| 498 } |
498 } |
| 565 service->expanded = TRUE; |
565 service->expanded = TRUE; |
| 566 } |
566 } |
| 567 |
567 |
| 568 void xmpp_disco_service_register(XmppDiscoService *service) |
568 void xmpp_disco_service_register(XmppDiscoService *service) |
| 569 { |
569 { |
| 570 xmlnode *iq, *query; |
570 PurpleXmlNode *iq, *query; |
| 571 char *id = generate_next_id(); |
571 char *id = generate_next_id(); |
| 572 |
572 |
| 573 iq = xmlnode_new("iq"); |
573 iq = purple_xmlnode_new("iq"); |
| 574 xmlnode_set_attrib(iq, "type", "get"); |
574 purple_xmlnode_set_attrib(iq, "type", "get"); |
| 575 xmlnode_set_attrib(iq, "to", service->jid); |
575 purple_xmlnode_set_attrib(iq, "to", service->jid); |
| 576 xmlnode_set_attrib(iq, "id", id); |
576 purple_xmlnode_set_attrib(iq, "id", id); |
| 577 |
577 |
| 578 query = xmlnode_new_child(iq, "query"); |
578 query = purple_xmlnode_new_child(iq, "query"); |
| 579 xmlnode_set_namespace(query, NS_REGISTER); |
579 purple_xmlnode_set_namespace(query, NS_REGISTER); |
| 580 |
580 |
| 581 purple_signal_emit(purple_connection_get_protocol(service->list->pc), |
581 purple_signal_emit(purple_connection_get_protocol(service->list->pc), |
| 582 "jabber-sending-xmlnode", service->list->pc, &iq); |
582 "jabber-sending-xmlnode", service->list->pc, &iq); |
| 583 if (iq != NULL) |
583 if (iq != NULL) |
| 584 xmlnode_free(iq); |
584 purple_xmlnode_free(iq); |
| 585 g_free(id); |
585 g_free(id); |
| 586 } |
586 } |
| 587 |
587 |
| 588 static void |
588 static void |
| 589 create_dialog(PurplePluginAction *action) |
589 create_dialog(PurplePluginAction *action) |