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