comparison mcabber/src/xmpp_iqrequest.c @ 1598:a087125d8fc8

Replace libjabber with loudmouth
author franky
date Sun, 11 Oct 2009 15:38:32 +0200
parents mcabber/src/jab_iq.c@8e52ce94eee0
children dcd5d4c75199
comparison
equal deleted inserted replaced
1597:4f59a414217e 1598:a087125d8fc8
1 /* See xmpp.c file for copyright and license details. */
2
3 static LmHandlerResult cb_roster(LmMessageHandler *h, LmConnection *c,
4 LmMessage *m, gpointer user_data);
5 static LmHandlerResult cb_version(LmMessageHandler *h, LmConnection *c,
6 LmMessage *m, gpointer user_data);
7 static LmHandlerResult cb_time(LmMessageHandler *h, LmConnection *c,
8 LmMessage *m, gpointer user_data);
9 static LmHandlerResult cb_last(LmMessageHandler *h, LmConnection *c,
10 LmMessage *m, gpointer user_data);
11 static LmHandlerResult cb_vcard(LmMessageHandler *h, LmConnection *c,
12 LmMessage *m, gpointer user_data);
13
14 static struct IqRequestHandlers
15 {
16 const gchar *xmlns;
17 const gchar *querytag;
18 LmHandleMessageFunction handler;
19 } iq_request_handlers[] = {
20 {NS_ROSTER, "query", &cb_roster},
21 {NS_VERSION,"query", &cb_version},
22 {NS_TIME, "query", &cb_time},
23 {NS_LAST, "query", &cb_last},
24 {NS_VCARD, "vCard", &cb_vcard},
25 {NULL, NULL, NULL}
26 };
27
28 // Enum for vCard attributes
29 enum vcard_attr {
30 vcard_home = 1<<0,
31 vcard_work = 1<<1,
32 vcard_postal = 1<<2,
33 vcard_voice = 1<<3,
34 vcard_fax = 1<<4,
35 vcard_cell = 1<<5,
36 vcard_inet = 1<<6,
37 vcard_pref = 1<<7,
38 };
39
40 // xmlns has to be a namespace from iq_request_handlers[].xmlns
41 void xmpp_iq_request(const char *fulljid, const char *xmlns)
42 {
43 LmMessage *iq;
44 LmMessageNode *query;
45 LmMessageHandler *handler;
46 int i;
47
48 iq = lm_message_new_with_sub_type(fulljid, LM_MESSAGE_TYPE_IQ,
49 LM_MESSAGE_SUB_TYPE_GET);
50 for (i = 0; strcmp(iq_request_handlers[i].xmlns, xmlns) != 0 ; ++i)
51 ;
52 query = lm_message_node_add_child(iq->node,
53 iq_request_handlers[i].querytag,
54 NULL);
55 lm_message_node_set_attribute(query, "xmlns", xmlns);
56 handler = lm_message_handler_new(iq_request_handlers[i].handler,
57 NULL, FALSE);
58 lm_connection_send_with_reply(lconnection, iq, handler, NULL);
59 lm_message_handler_unref(handler);
60 lm_message_unref(iq);
61 }
62
63 // This callback is reached when mcabber receives the first roster update
64 // after the connection.
65 static LmHandlerResult cb_roster(LmMessageHandler *h, LmConnection *c,
66 LmMessage *m, gpointer user_data)
67 {
68 LmMessageNode *x;
69 const char *ns;
70
71 // Only execute the hook if the roster has been successfully retrieved
72 if (lm_message_get_sub_type(m) != LM_MESSAGE_SUB_TYPE_RESULT)
73 return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
74
75 x = lm_message_node_find_child(m->node, "query");
76 if (!x)
77 return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
78
79 ns = lm_message_node_get_attribute(x, "xmlns");
80 if (ns && !strcmp(ns, NS_ROSTER))
81 handle_iq_roster(NULL, c, m, user_data);
82
83 // Post-login stuff
84 hook_execute_internal("hook-post-connect");
85
86 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
87 }
88
89 static LmHandlerResult cb_version(LmMessageHandler *h, LmConnection *c,
90 LmMessage *m, gpointer user_data)
91 {
92 LmMessageNode *ansqry;
93 const char *p, *bjid;
94 char *tmp;
95 char *buf;
96
97 ansqry = lm_message_node_get_child(m->node, "query");
98 if (!ansqry) {
99 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:version result!");
100 return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
101 }
102
103 // Display IQ result sender...
104 p = lm_message_get_from(m);
105 if (!p) {
106 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:version result (no sender name).");
107 return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
108 }
109 bjid = p;
110
111 buf = g_strdup_printf("Received IQ:version result from <%s>", bjid);
112 scr_LogPrint(LPRINT_LOGNORM, "%s", buf);
113
114 // bjid should now really be the "bare JID", let's strip the resource
115 tmp = strchr(bjid, JID_RESOURCE_SEPARATOR);
116 if (tmp) *tmp = '\0';
117
118 scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0);
119 g_free(buf);
120
121 // Get result data...
122 p = lm_message_node_get_child_value(ansqry, "name");
123 if (p) {
124 buf = g_strdup_printf("Name: %s", p);
125 scr_WriteIncomingMessage(bjid, buf,
126 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
127 g_free(buf);
128 }
129 p = lm_message_node_get_child_value(ansqry, "version");
130 if (p) {
131 buf = g_strdup_printf("Version: %s", p);
132 scr_WriteIncomingMessage(bjid, buf,
133 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
134 g_free(buf);
135 }
136 p = lm_message_node_get_child_value(ansqry, "os");
137 if (p) {
138 buf = g_strdup_printf("OS: %s", p);
139 scr_WriteIncomingMessage(bjid, buf,
140 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
141 g_free(buf);
142 }
143 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
144 }
145
146 static LmHandlerResult cb_time(LmMessageHandler *h, LmConnection *c,
147 LmMessage *m, gpointer user_data)
148 {
149 LmMessageNode *ansqry;
150 const char *p, *bjid;
151 char *tmp;
152 char *buf;
153
154 ansqry = lm_message_node_get_child(m->node, "query");
155 if (!ansqry) {
156 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:time result!");
157 return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
158 }
159 // Display IQ result sender...
160 p = lm_message_get_from(m);
161 if (!p) {
162 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:time result (no sender name).");
163 return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
164 }
165 bjid = p;
166
167 buf = g_strdup_printf("Received IQ:time result from <%s>", bjid);
168 scr_LogPrint(LPRINT_LOGNORM, "%s", buf);
169
170 // bjid should now really be the "bare JID", let's strip the resource
171 tmp = strchr(bjid, JID_RESOURCE_SEPARATOR);
172 if (tmp) *tmp = '\0';
173
174 scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0);
175 g_free(buf);
176
177 // Get result data...
178 p = lm_message_node_get_child_value(ansqry, "utc");
179 if (p) {
180 buf = g_strdup_printf("UTC: %s", p);
181 scr_WriteIncomingMessage(bjid, buf,
182 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
183 g_free(buf);
184 }
185 p = lm_message_node_get_child_value(ansqry, "tz");
186 if (p) {
187 buf = g_strdup_printf("TZ: %s", p);
188 scr_WriteIncomingMessage(bjid, buf,
189 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
190 g_free(buf);
191 }
192 p = lm_message_node_get_child_value(ansqry, "display");
193 if (p) {
194 buf = g_strdup_printf("Time: %s", p);
195 scr_WriteIncomingMessage(bjid, buf,
196 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
197 g_free(buf);
198 }
199 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
200 }
201
202 static LmHandlerResult cb_last(LmMessageHandler *h, LmConnection *c,
203 LmMessage *m, gpointer user_data)
204 {
205 LmMessageNode *ansqry;
206 const char *p, *bjid;
207 char *buf, *tmp;
208
209 ansqry = lm_message_node_get_child(m->node, "query");
210 if (!ansqry) {
211 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:last result!");
212 return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
213 }
214 // Display IQ result sender...
215 p = lm_message_get_from(m);
216 if (!p) {
217 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:last result (no sender name).");
218 return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
219 }
220 bjid = p;
221
222 buf = g_strdup_printf("Received IQ:last result from <%s>", bjid);
223 scr_LogPrint(LPRINT_LOGNORM, "%s", buf);
224
225 // bjid should now really be the "bare JID", let's strip the resource
226 tmp = strchr(bjid, JID_RESOURCE_SEPARATOR);
227 if (tmp) *tmp = '\0';
228
229 scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0);
230 g_free(buf);
231
232 // Get result data...
233 p = lm_message_node_get_attribute(ansqry, "seconds");
234 if (p) {
235 long int s;
236 GString *sbuf;
237 sbuf = g_string_new("Idle time: ");
238 s = atol(p);
239 // Days
240 if (s > 86400L) {
241 g_string_append_printf(sbuf, "%ldd ", s/86400L);
242 s %= 86400L;
243 }
244 // hh:mm:ss
245 g_string_append_printf(sbuf, "%02ld:", s/3600L);
246 s %= 3600L;
247 g_string_append_printf(sbuf, "%02ld:%02ld", s/60L, s%60L);
248 scr_WriteIncomingMessage(bjid, sbuf->str,
249 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
250 g_string_free(sbuf, TRUE);
251 } else {
252 scr_WriteIncomingMessage(bjid, "No idle time reported.",
253 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
254 }
255 p = lm_message_node_get_value(ansqry);
256 if (p) {
257 buf = g_strdup_printf("Status message: %s", p);
258 scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0);
259 g_free(buf);
260 }
261 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
262 }
263
264 static void display_vcard_item(const char *bjid, const char *label,
265 enum vcard_attr vcard_attrib, const char *text)
266 {
267 char *buf;
268
269 if (!text || !bjid || !label)
270 return;
271
272 buf = g_strdup_printf("%s: %s%s%s%s%s%s%s%s%s%s", label,
273 (vcard_attrib & vcard_home ? "[home]" : ""),
274 (vcard_attrib & vcard_work ? "[work]" : ""),
275 (vcard_attrib & vcard_postal ? "[postal]" : ""),
276 (vcard_attrib & vcard_voice ? "[voice]" : ""),
277 (vcard_attrib & vcard_fax ? "[fax]" : ""),
278 (vcard_attrib & vcard_cell ? "[cell]" : ""),
279 (vcard_attrib & vcard_inet ? "[inet]" : ""),
280 (vcard_attrib & vcard_pref ? "[pref]" : ""),
281 (vcard_attrib ? " " : ""),
282 text);
283 scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
284 g_free(buf);
285 }
286
287 static void handle_vcard_node(const char *barejid, LmMessageNode *vcardnode)
288 {
289 LmMessageNode *x;
290 const char *p;
291
292 for (x = vcardnode->children ; x; x = x->next) {
293 const char *data;
294 enum vcard_attr vcard_attrib = 0;
295
296 p = x->name;
297 data = lm_message_node_get_value(x);
298 if (!p || !data)
299 continue;
300
301 if (!strcmp(p, "FN"))
302 display_vcard_item(barejid, "Name", vcard_attrib, data);
303 else if (!strcmp(p, "NICKNAME"))
304 display_vcard_item(barejid, "Nickname", vcard_attrib, data);
305 else if (!strcmp(p, "URL"))
306 display_vcard_item(barejid, "URL", vcard_attrib, data);
307 else if (!strcmp(p, "BDAY"))
308 display_vcard_item(barejid, "Birthday", vcard_attrib, data);
309 else if (!strcmp(p, "TZ"))
310 display_vcard_item(barejid, "Timezone", vcard_attrib, data);
311 else if (!strcmp(p, "TITLE"))
312 display_vcard_item(barejid, "Title", vcard_attrib, data);
313 else if (!strcmp(p, "ROLE"))
314 display_vcard_item(barejid, "Role", vcard_attrib, data);
315 else if (!strcmp(p, "DESC"))
316 display_vcard_item(barejid, "Comment", vcard_attrib, data);
317 else if (!strcmp(p, "N")) {
318 data = lm_message_node_get_child_value(x, "FAMILY");
319 display_vcard_item(barejid, "Family Name", vcard_attrib, data);
320 data = lm_message_node_get_child_value(x, "GIVEN");
321 display_vcard_item(barejid, "Given Name", vcard_attrib, data);
322 data = lm_message_node_get_child_value(x, "MIDDLE");
323 display_vcard_item(barejid, "Middle Name", vcard_attrib, data);
324 } else if (!strcmp(p, "ORG")) {
325 data = lm_message_node_get_child_value(x, "ORGNAME");
326 display_vcard_item(barejid, "Organisation name", vcard_attrib, data);
327 data = lm_message_node_get_child_value(x, "ORGUNIT");
328 display_vcard_item(barejid, "Organisation unit", vcard_attrib, data);
329 } else {
330 // The HOME, WORK and PREF attributes are common to the remaining fields
331 // (ADR, TEL & EMAIL)
332 if (lm_message_node_get_child(x, "HOME"))
333 vcard_attrib |= vcard_home;
334 if (lm_message_node_get_child(x, "WORK"))
335 vcard_attrib |= vcard_work;
336 if (lm_message_node_get_child(x, "PREF"))
337 vcard_attrib |= vcard_pref;
338 if (!strcmp(p, "ADR")) { // Address
339 if (lm_message_node_get_child(x, "POSTAL"))
340 vcard_attrib |= vcard_postal;
341 data = lm_message_node_get_child_value(x, "EXTADD");
342 display_vcard_item(barejid, "Addr (ext)", vcard_attrib, data);
343 data = lm_message_node_get_child_value(x, "STREET");
344 display_vcard_item(barejid, "Street", vcard_attrib, data);
345 data = lm_message_node_get_child_value(x, "LOCALITY");
346 display_vcard_item(barejid, "Locality", vcard_attrib, data);
347 data = lm_message_node_get_child_value(x, "REGION");
348 display_vcard_item(barejid, "Region", vcard_attrib, data);
349 data = lm_message_node_get_child_value(x, "PCODE");
350 display_vcard_item(barejid, "Postal code", vcard_attrib, data);
351 data = lm_message_node_get_child_value(x, "CTRY");
352 display_vcard_item(barejid, "Country", vcard_attrib, data);
353 } else if (!strcmp(p, "TEL")) { // Telephone
354 data = lm_message_node_get_child_value(x, "NUMBER");
355 if (data) {
356 if (lm_message_node_get_child(x, "VOICE"))
357 vcard_attrib |= vcard_voice;
358 if (lm_message_node_get_child(x, "FAX"))
359 vcard_attrib |= vcard_fax;
360 if (lm_message_node_get_child(x, "CELL"))
361 vcard_attrib |= vcard_cell;
362 display_vcard_item(barejid, "Phone", vcard_attrib, data);
363 }
364 } else if (!strcmp(p, "EMAIL")) { // Email
365 if (lm_message_node_get_child(x, "INTERNET"))
366 vcard_attrib |= vcard_inet;
367 data = lm_message_node_get_child_value(x, "USERID");
368 display_vcard_item(barejid, "Email", vcard_attrib, data);
369 }
370 }
371 }
372 }
373
374 static LmHandlerResult cb_vcard(LmMessageHandler *h, LmConnection *c,
375 LmMessage *m, gpointer user_data)
376 {
377 LmMessageNode *ansqry;
378 const char *p, *bjid;
379 char *buf, *tmp;
380
381 // Display IQ result sender...
382 p = lm_message_get_from(m);
383 if (!p) {
384 scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:vCard result (no sender name).");
385 return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
386 }
387 bjid = p;
388
389 buf = g_strdup_printf("Received IQ:vCard result from <%s>", bjid);
390 scr_LogPrint(LPRINT_LOGNORM, "%s", buf);
391
392 // Get the vCard node
393 ansqry = lm_message_node_get_child(m->node, "vCard");
394 if (!ansqry) {
395 scr_LogPrint(LPRINT_LOGNORM, "Empty IQ:vCard result!");
396 g_free(buf);
397 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
398 }
399
400 // bjid should really be the "bare JID", let's strip the resource
401 tmp = strchr(bjid, JID_RESOURCE_SEPARATOR);
402 if (tmp) *tmp = '\0';
403
404 scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0);
405 g_free(buf);
406
407 // Get result data...
408 handle_vcard_node(bjid, ansqry);
409 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
410 }
411
412 static void storage_bookmarks_parse_conference(LmMessageNode *node)
413 {
414 const char *fjid, *name, *autojoin;
415 const char *pstatus, *awhois;
416 char *bjid;
417 GSList *room_elt;
418
419 fjid = lm_message_node_get_attribute(node, "jid");
420 if (!fjid)
421 return;
422 name = lm_message_node_get_attribute(node, "name");
423 autojoin = lm_message_node_get_attribute(node, "autojoin");
424 awhois = lm_message_node_get_attribute(node, "autowhois");
425 pstatus = lm_message_node_get_child_value(node, "print_status");
426
427 bjid = jidtodisp(fjid); // Bare jid
428
429 // Make sure this is a room (it can be a conversion user->room)
430 room_elt = roster_find(bjid, jidsearch, 0);
431 if (!room_elt) {
432 room_elt = roster_add_user(bjid, name, NULL, ROSTER_TYPE_ROOM,
433 sub_none, -1);
434 } else {
435 buddy_settype(room_elt->data, ROSTER_TYPE_ROOM);
436 /*
437 // If the name is available, should we use it?
438 // I don't think so, it would be confusing because this item is already
439 // in the roster.
440 if (name)
441 buddy_setname(room_elt->data, name);
442 */
443 }
444
445 // Set the print_status and auto_whois values
446 if (pstatus) {
447 enum room_printstatus i;
448 for (i = status_none; i <= status_all; i++)
449 if (!strcasecmp(pstatus, strprintstatus[i]))
450 break;
451 if (i <= status_all)
452 buddy_setprintstatus(room_elt->data, i);
453 }
454 if (awhois) {
455 enum room_autowhois i = autowhois_default;
456 if (!strcmp(awhois, "1"))
457 i = autowhois_on;
458 else if (!strcmp(awhois, "0"))
459 i = autowhois_off;
460 if (i != autowhois_default)
461 buddy_setautowhois(room_elt->data, i);
462 }
463
464 // Is autojoin set?
465 // If it is, we'll look up for more information (nick? password?) and
466 // try to join the room.
467 if (autojoin && !strcmp(autojoin, "1")) {
468 const char *nick, *passwd;
469 char *tmpnick = NULL;
470 nick = lm_message_node_get_child_value(node, "nick");
471 passwd = lm_message_node_get_child_value(node, "password");
472 if (!nick || !*nick)
473 nick = tmpnick = default_muc_nickname(NULL);
474 // Let's join now
475 scr_LogPrint(LPRINT_LOGNORM, "Auto-join bookmark <%s>", bjid);
476 xmpp_room_join(bjid, nick, passwd);
477 g_free(tmpnick);
478 }
479 g_free(bjid);
480 }
481
482 static LmHandlerResult cb_storage_bookmarks(LmMessageHandler *h,
483 LmConnection *c,
484 LmMessage *m, gpointer user_data)
485 {
486 LmMessageNode *x, *ansqry;
487 char *p;
488
489 if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_ERROR) {
490 // No server support, or no bookmarks?
491 p = m->node->children->name;
492 if (p && !strcmp(p, "item-not-found")) {
493 // item-no-found means the server has Private Storage, but it's
494 // currently empty.
495 if (bookmarks)
496 lm_message_node_unref(bookmarks);
497 bookmarks = lm_message_node_new("storage", "storage:bookmarks");
498 // We return 0 so that the IQ error message be
499 // not displayed, as it isn't a real error.
500 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
501 }
502 return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; // Unhandled error
503 }
504
505 ansqry = lm_message_node_get_child(m->node, "query");
506 ansqry = lm_message_node_get_child(ansqry, "storage");
507 if (!ansqry) {
508 scr_LogPrint(LPRINT_LOG, "Invalid IQ:private result! (storage:bookmarks)");
509 return 0;
510 }
511
512 // Walk through the storage tags
513 for (x = ansqry->children ; x; x = x->next) {
514 // If the current node is a conference item, parse it and update the roster
515 if (x->name && !strcmp(x->name, "conference"))
516 storage_bookmarks_parse_conference(x);
517 }
518 // "Copy" the bookmarks node
519 if (bookmarks)
520 lm_message_node_unref(bookmarks);
521 lm_message_node_deep_ref(ansqry);
522 bookmarks = ansqry;
523 return 0;
524 }
525
526
527 static LmHandlerResult cb_storage_rosternotes(LmMessageHandler *h,
528 LmConnection *c,
529 LmMessage *m, gpointer user_data)
530 {
531 LmMessageNode *ansqry;
532
533 if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_ERROR) {
534 const char *p;
535 // No server support, or no roster notes?
536 p = m->node->children->name;
537 if (p && !strcmp(p, "item-not-found")) {
538 // item-no-found means the server has Private Storage, but it's
539 // currently empty.
540 if (rosternotes)
541 lm_message_node_unref(rosternotes);
542 rosternotes = lm_message_node_new("storage", "storage:rosternotes");
543 // We return 0 so that the IQ error message be
544 // not displayed, as it isn't a real error.
545 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
546 }
547 return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; // Unhandled error
548 }
549
550 ansqry = lm_message_node_get_child(m->node, "query");
551 ansqry = lm_message_node_get_child(ansqry, "storage");
552 if (!ansqry) {
553 scr_LogPrint(LPRINT_LOG, "Invalid IQ:private result! "
554 "(storage:rosternotes)");
555 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
556 }
557 // Copy the rosternotes node
558 if (rosternotes)
559 lm_message_node_unref(rosternotes);
560 lm_message_node_deep_ref(ansqry);
561 rosternotes = ansqry;
562 return 0;
563 }
564
565
566 static struct IqRequestStorageHandlers
567 {
568 const gchar *storagens;
569 LmHandleMessageFunction handler;
570 } iq_request_storage_handlers[] = {
571 {"storage:rosternotes", &cb_storage_rosternotes},
572 {"storage:bookmarks", &cb_storage_bookmarks},
573 {NULL, NULL}
574 };
575
576 void xmpp_request_storage(const gchar *storage)
577 {
578 LmMessage *iq;
579 LmMessageNode *query;
580 LmMessageHandler *handler;
581 int i;
582
583 iq = lm_message_new_with_sub_type(NULL, LM_MESSAGE_TYPE_IQ,
584 LM_MESSAGE_SUB_TYPE_GET);
585 query = lm_message_node_add_child(iq->node, "query", NULL);
586 lm_message_node_set_attribute(query, "xmlns", NS_PRIVATE);
587 lm_message_node_set_attribute(lm_message_node_add_child
588 (query, "storage", NULL),
589 "xmlns", storage);
590
591 for (i = 0;
592 strcmp(iq_request_storage_handlers[i].storagens, storage) != 0;
593 ++i) ;
594
595 handler = lm_message_handler_new(iq_request_storage_handlers[i].handler,
596 NULL, FALSE);
597 lm_connection_send_with_reply(lconnection, iq, handler, NULL);
598 lm_message_handler_unref(handler);
599 lm_message_unref(iq);
600 }