Mercurial > ~mikael > mcabber > hg
annotate mcabber/src/xmpp_iq.c @ 1598:a087125d8fc8
Replace libjabber with loudmouth
author | franky |
---|---|
date | Sun, 11 Oct 2009 15:38:32 +0200 |
parents | mcabber/src/jabglue.c@1802b926e3fa |
children | dcd5d4c75199 |
rev | line source |
---|---|
1598 | 1 /* See xmpp.c file for copyright and license details. */ |
2 | |
3 static LmHandlerResult handle_iq_command_set_status(LmMessageHandler *h, | |
4 LmConnection *c, | |
5 LmMessage *m, | |
6 gpointer ud); | |
29 | 7 |
1598 | 8 static LmHandlerResult handle_iq_command_leave_groupchats(LmMessageHandler *h, |
9 LmConnection *c, | |
10 LmMessage *m, | |
11 gpointer ud); | |
29 | 12 |
1598 | 13 inline double seconds_since_last_use(void); |
29 | 14 |
1598 | 15 struct adhoc_command { |
16 char *name; | |
17 char *description; | |
18 bool only_for_self; | |
19 LmHandleMessageFunction callback; | |
1378 | 20 }; |
21 | |
1598 | 22 const struct adhoc_command adhoc_command_list[] = { |
23 { "http://jabber.org/protocol/rc#set-status", | |
24 "Change client status", | |
25 1, | |
26 &handle_iq_command_set_status }, | |
27 { "http://jabber.org/protocol/rc#leave-groupchats", | |
28 "Leave groupchat(s)", | |
29 1, | |
30 &handle_iq_command_leave_groupchats }, | |
31 { NULL, NULL, 0, NULL }, | |
32 }; | |
1383 | 33 |
1598 | 34 struct adhoc_status { |
35 char *name; // the name used by adhoc | |
36 char *description; | |
37 char *status; // the string, used by setstus | |
38 }; | |
39 // It has to match imstatus of roster.h! | |
40 const struct adhoc_status adhoc_status_list[] = { | |
41 {"offline", "Offline", "offline"}, | |
42 {"online", "Online", "avail"}, | |
43 {"chat", "Chat", "free"}, | |
44 {"dnd", "Do not disturb", "dnd"}, | |
45 {"xd", "Extended away", "notavail"}, | |
46 {"away", "Away", "away"}, | |
47 {"invisible", "Invisible", "invisible"}, | |
48 {NULL, NULL, NULL}, | |
49 }; | |
298
35cda94e570d
Add /connect and /disconnect commands
Mikael Berthe <mikael@lilotux.net>
parents:
294
diff
changeset
|
50 |
1598 | 51 static char *generate_session_id(char *prefix) |
29 | 52 { |
1598 | 53 char *result; |
54 static int counter = 0; | |
55 counter++; | |
56 // TODO better use timestamp? | |
57 result = g_strdup_printf("%s-%i", prefix, counter); | |
58 return result; | |
29 | 59 } |
60 | |
1598 | 61 static LmMessage *lm_message_new_iq_error(LmMessage *m, guint error) |
29 | 62 { |
1598 | 63 LmMessage *r; |
64 LmMessageNode *err; | |
65 int i; | |
66 | |
67 for (i = 0; xmpp_errors[i].code; ++i) | |
68 if (xmpp_errors[i].code == error) | |
69 break; | |
70 g_return_val_if_fail(xmpp_errors[i].code > 0, NULL); | |
298
35cda94e570d
Add /connect and /disconnect commands
Mikael Berthe <mikael@lilotux.net>
parents:
294
diff
changeset
|
71 |
1598 | 72 r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_ERROR); |
73 err = lm_message_node_add_child(r->node, "error", NULL); | |
74 lm_message_node_set_attribute(err, "code", xmpp_errors[i].code_str); | |
75 lm_message_node_set_attribute(err, "type", xmpp_errors[i].type); | |
76 lm_message_node_set_attribute | |
77 (lm_message_node_add_child(err, | |
78 xmpp_errors[i].condition, NULL), | |
79 "xmlns", NS_XMPP_STANZAS); | |
634
f3c05d5fe459
Send "</stream:stream>" when disconnecting from the server
Mikael Berthe <mikael@lilotux.net>
parents:
633
diff
changeset
|
80 |
1598 | 81 return r; |
436 | 82 } |
83 | |
1598 | 84 static void send_iq_error(LmConnection *c, LmMessage *m, guint error) |
1001
dff25377c11f
Auto-reconnect after a network/server failure
Mikael Berthe <mikael@lilotux.net>
parents:
999
diff
changeset
|
85 { |
1598 | 86 LmMessage *r; |
87 r = lm_message_new_iq_error(m, error); | |
88 lm_connection_send(c, r, NULL); | |
89 lm_message_unref(r); | |
1001
dff25377c11f
Auto-reconnect after a network/server failure
Mikael Berthe <mikael@lilotux.net>
parents:
999
diff
changeset
|
90 } |
dff25377c11f
Auto-reconnect after a network/server failure
Mikael Berthe <mikael@lilotux.net>
parents:
999
diff
changeset
|
91 |
1598 | 92 static void lm_message_node_add_dataform_result(LmMessageNode *node, |
93 const char *message) | |
29 | 94 { |
1598 | 95 LmMessageNode *x, *field; |
939
12fa2ae6445d
Get rid of "busy-waiting" (Christof Meerwald)
Mikael Berthe <mikael@lilotux.net>
parents:
924
diff
changeset
|
96 |
1598 | 97 x = lm_message_node_add_child(node, "x", NULL); |
98 lm_message_node_set_attributes(x, | |
99 "type", "result", | |
100 "xmlns", "jabber:x:data", | |
101 NULL); | |
102 field = lm_message_node_add_child(x, "field", NULL); | |
103 lm_message_node_set_attributes(field, | |
104 "type", "text-single", | |
105 "var", "message", | |
106 NULL); | |
107 lm_message_node_add_child(field, "value", message); | |
108 } | |
1439
fd09c95bc2b5
Wake up less often when not connected to the server
Mikael Berthe <mikael@lilotux.net>
parents:
1435
diff
changeset
|
109 |
1598 | 110 static LmHandlerResult handle_iq_commands_list(LmMessageHandler *h, |
111 LmConnection *c, | |
112 LmMessage *m, gpointer ud) | |
113 { | |
114 LmMessage *iq; | |
115 LmMessageNode *query; | |
116 const char *requester_jid; | |
117 const struct adhoc_command *command; | |
118 const char *node; | |
119 gboolean from_self; | |
940 | 120 |
1598 | 121 iq = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); |
122 query = lm_message_node_add_child(iq->node, "query", NULL); | |
123 node = lm_message_node_get_attribute | |
124 (lm_message_node_get_child(m->node, "query"), | |
125 "node"); | |
126 if (node) | |
127 lm_message_node_set_attribute(query, "node", node); | |
29 | 128 |
1598 | 129 requester_jid = lm_message_get_from(m); |
130 from_self = jid_equal(lm_connection_get_jid(c), requester_jid); | |
686
98de2d166a11
Use the new IQ system for authentication
Mikael Berthe <mikael@lilotux.net>
parents:
684
diff
changeset
|
131 |
1598 | 132 for (command = adhoc_command_list ; command->name ; command++) { |
133 if (!command->only_for_self || from_self) { | |
134 lm_message_node_set_attributes | |
135 (lm_message_node_add_child(query, "item", NULL), | |
136 "node", command->name, | |
137 "name", command->description, | |
138 "jid", lm_connection_get_jid(c), | |
139 NULL); | |
29 | 140 } |
141 } | |
142 | |
1598 | 143 lm_connection_send(c, iq, NULL); |
144 lm_message_unref(iq); | |
145 return LM_HANDLER_RESULT_REMOVE_MESSAGE; | |
534 | 146 } |
147 | |
1598 | 148 static LmHandlerResult handle_iq_command_set_status(LmMessageHandler *h, |
149 LmConnection *c, | |
150 LmMessage *m, gpointer ud) | |
988
6e2bfd1ffded
Add ids to message stanzas if needed
Mikael Berthe <mikael@lilotux.net>
parents:
987
diff
changeset
|
151 { |
1598 | 152 const char *action, *node; |
153 char *sessionid; | |
154 LmMessage *iq; | |
155 LmMessageNode *command, *x, *y; | |
156 const struct adhoc_status *s; | |
157 | |
158 x = lm_message_node_get_child(m->node, "command"); | |
159 action = lm_message_node_get_attribute(x, "action"); | |
160 node = lm_message_node_get_attribute(x, "node"); | |
161 sessionid = (char *)lm_message_node_get_attribute(x, "sessionid"); | |
162 | |
163 iq = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); | |
164 command = lm_message_node_add_child(iq->node, "command", NULL); | |
165 lm_message_node_set_attribute(command, "node", node); | |
166 lm_message_node_set_attribute(command, "xmlns", NS_COMMANDS); | |
167 | |
168 if (!sessionid) { | |
169 sessionid = generate_session_id("set-status"); | |
170 lm_message_node_set_attribute(command, "sessionid", sessionid); | |
171 g_free(sessionid); | |
172 sessionid = NULL; | |
173 lm_message_node_set_attribute(command, "status", "executing"); | |
988
6e2bfd1ffded
Add ids to message stanzas if needed
Mikael Berthe <mikael@lilotux.net>
parents:
987
diff
changeset
|
174 |
1598 | 175 x = lm_message_node_add_child(command, "x", NULL); |
176 lm_message_node_set_attribute(x, "type", "form"); | |
177 lm_message_node_set_attribute(x, "xmlns", "jabber:x:data"); | |
178 | |
179 lm_message_node_add_child(x, "title", "Change Status"); | |
180 | |
181 lm_message_node_add_child(x, "instructions", | |
182 "Choose the status and status message"); | |
447
03bb57383cea
Initial Multi-User Chat support
Mikael Berthe <mikael@lilotux.net>
parents:
444
diff
changeset
|
183 |
1598 | 184 // TODO see if factorisation is possible |
185 y = lm_message_node_add_child(x, "field", NULL); | |
186 lm_message_node_set_attribute(y, "type", "hidden"); | |
187 lm_message_node_set_attribute(y, "var", "FORM_TYPE"); | |
188 | |
189 lm_message_node_add_child(y, "value", "http://jabber.org/protocol/rc"); | |
1055
6eb1efea75d0
PGP: Visual encryption flag
Mikael Berthe <mikael@lilotux.net>
parents:
1053
diff
changeset
|
190 |
1598 | 191 y = lm_message_node_add_child(x, "field", NULL); |
192 lm_message_node_set_attributes(y, | |
193 "type", "list-single", | |
194 "var", "status", | |
195 "label", "Status", | |
196 NULL); | |
197 lm_message_node_add_child(y, "required", NULL); | |
472
75442262c082
Disable some commands when not connected
Mikael Berthe <mikael@lilotux.net>
parents:
470
diff
changeset
|
198 |
1598 | 199 // XXX: ugly |
200 lm_message_node_add_child(y, "value", | |
201 adhoc_status_list[xmpp_getstatus()].name); | |
202 for (s = adhoc_status_list; s->name; s++) { | |
203 LmMessageNode *option = lm_message_node_add_child(y, "option", NULL); | |
204 lm_message_node_add_child(option, "value", s->name); | |
205 lm_message_node_set_attribute(option, "label", s->description); | |
1299
3b338a5c01fc
OTR support
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1290
diff
changeset
|
206 } |
1598 | 207 // TODO add priority ? |
208 // I do not think this is useful, user should not have to care of the | |
209 // priority like gossip and gajim do (misc) | |
210 lm_message_node_set_attributes | |
211 (lm_message_node_add_child(x, "field", NULL), | |
212 "type", "text-multi", | |
213 "var", "status-message", | |
214 "label", "Message", | |
215 NULL); | |
216 } else if (action && !strcmp(action, "cancel")) { | |
217 lm_message_node_set_attribute(command, "status", "canceled"); | |
218 } else { // (if sessionid and not canceled) | |
219 y = lm_message_node_find_xmlns(x, "jabber:x:data"); //x?xmlns=jabber:x:data | |
220 if (y) { | |
221 const char *value=NULL, *message=NULL; | |
222 LmMessageNode *fields, *field; | |
223 field = fields = lm_message_node_get_child(y, "field"); //field?var=status | |
224 while (field && strcmp("status", | |
225 lm_message_node_get_attribute(field, "var"))) | |
226 field = field->next; | |
227 field = lm_message_node_get_child(field, "value"); | |
228 if (field) | |
229 value = lm_message_node_get_value(field); | |
230 field = fields; //field?var=status-message | |
231 while (field && strcmp("status-message", | |
232 lm_message_node_get_attribute(field, "var"))) | |
233 field = field->next; | |
234 field = lm_message_node_get_child(field, "value"); | |
235 if (field) | |
236 message = lm_message_node_get_value(field); | |
237 if (value) { | |
238 for (s = adhoc_status_list; !s->name || strcmp(s->name, value); s++); | |
239 if (s->name) { | |
240 char *status = g_strdup_printf("%s %s", s->status, | |
241 message ? message : ""); | |
242 cmd_setstatus(NULL, status); | |
243 g_free(status); | |
244 lm_message_node_set_attribute(command, "status", "completed"); | |
245 lm_message_node_add_dataform_result(command, | |
246 "Status has been changed"); | |
1197 | 247 } |
1067
a5dc85fdebde
Add key comparison for signatures & use user-provided PGP keys for encryption
Mikael Berthe <mikael@lilotux.net>
parents:
1065
diff
changeset
|
248 } |
1065
230dca34dbea
Extand pgp_data structure
Mikael Berthe <mikael@lilotux.net>
parents:
1058
diff
changeset
|
249 } |
1044
52cfe9bf9840
Encryption support for outgoing messages
Mikael Berthe <mikael@lilotux.net>
parents:
1043
diff
changeset
|
250 } |
1598 | 251 if (sessionid) |
252 lm_message_node_set_attribute(command, "sessionid", sessionid); | |
253 lm_connection_send(c, iq, NULL); | |
254 lm_message_unref(iq); | |
255 return LM_HANDLER_RESULT_REMOVE_MESSAGE; | |
256 } | |
1067
a5dc85fdebde
Add key comparison for signatures & use user-provided PGP keys for encryption
Mikael Berthe <mikael@lilotux.net>
parents:
1065
diff
changeset
|
257 |
1598 | 258 static void _callback_foreach_buddy_groupchat(gpointer rosterdata, void *param) |
259 { | |
260 LmMessageNode *field, *value, *option; | |
261 const char *room_jid, *nickname; | |
262 char *desc; | |
263 | |
264 room_jid = buddy_getjid(rosterdata); | |
265 if (!room_jid) return; | |
266 nickname = buddy_getnickname(rosterdata); | |
267 if (!nickname) return; | |
268 field = param; | |
1044
52cfe9bf9840
Encryption support for outgoing messages
Mikael Berthe <mikael@lilotux.net>
parents:
1043
diff
changeset
|
269 |
1598 | 270 option = lm_message_node_add_child(field, "option", NULL); |
271 value = lm_message_node_add_child(option, "value", room_jid); | |
272 desc = g_strdup_printf("%s on %s", nickname, room_jid); | |
273 lm_message_node_set_attribute(option, "label", desc); | |
274 g_free(desc); | |
275 } | |
1044
52cfe9bf9840
Encryption support for outgoing messages
Mikael Berthe <mikael@lilotux.net>
parents:
1043
diff
changeset
|
276 |
1598 | 277 static LmHandlerResult handle_iq_command_leave_groupchats(LmMessageHandler *h, |
278 LmConnection *c, | |
279 LmMessage *m, | |
280 gpointer ud) | |
281 { | |
282 const char *action, *node; | |
283 char *sessionid; | |
284 LmMessage *iq; | |
285 LmMessageNode *command, *x; | |
1044
52cfe9bf9840
Encryption support for outgoing messages
Mikael Berthe <mikael@lilotux.net>
parents:
1043
diff
changeset
|
286 |
1598 | 287 x = lm_message_node_get_child(m->node, "command"); |
288 action = lm_message_node_get_attribute(x, "action"); | |
289 node = lm_message_node_get_attribute(x, "node"); | |
290 sessionid = (char*)lm_message_node_get_attribute(x, "sessionid"); | |
291 | |
292 iq = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); | |
293 command = lm_message_node_add_child(iq->node, "command", NULL); | |
294 lm_message_node_set_attributes(command, | |
295 "node", node, | |
296 "xmlns", NS_COMMANDS, | |
297 NULL); | |
298 | |
299 if (!sessionid) { | |
300 LmMessageNode *field; | |
986
ed697234bd39
Chat states receival (Alexis Hildebrandt)
Mikael Berthe <mikael@lilotux.net>
parents:
977
diff
changeset
|
301 |
1598 | 302 sessionid = generate_session_id("leave-groupchats"); |
303 lm_message_node_set_attribute(command, "sessionid", sessionid); | |
304 g_free(sessionid); | |
305 sessionid = NULL; | |
306 lm_message_node_set_attribute(command, "status", "executing"); | |
307 | |
308 x = lm_message_node_add_child(command, "x", NULL); | |
309 lm_message_node_set_attributes(x, | |
310 "type", "form", | |
311 "xmlns", "jabber:x:data", | |
312 NULL); | |
313 | |
314 lm_message_node_add_child(x, "title", "Leave groupchat(s)"); | |
315 | |
316 lm_message_node_add_child(x, "instructions", | |
317 "What groupchats do you want to leave?"); | |
318 | |
319 field = lm_message_node_add_child(x, "field", NULL); | |
320 lm_message_node_set_attributes(field, | |
321 "type", "hidden", | |
322 "var", "FORM_TYPE", | |
323 NULL); | |
324 | |
325 lm_message_node_add_child(field, "value", | |
326 "http://jabber.org/protocol/rc"); | |
988
6e2bfd1ffded
Add ids to message stanzas if needed
Mikael Berthe <mikael@lilotux.net>
parents:
987
diff
changeset
|
327 |
1598 | 328 field = lm_message_node_add_child(x, "field", NULL); |
329 lm_message_node_set_attributes(field, | |
330 "type", "list-multi", | |
331 "var", "groupchats", | |
332 "label", "Groupchats: ", | |
333 NULL); | |
334 lm_message_node_add_child(field, "required", NULL); | |
335 | |
336 foreach_buddy(ROSTER_TYPE_ROOM, &_callback_foreach_buddy_groupchat, field); | |
337 //TODO: return an error if we are not connected to groupchats | |
338 } else if (action && !strcmp(action, "cancel")) { | |
339 lm_message_node_set_attribute(command, "status", "canceled"); | |
340 } else { // (if sessionid and not canceled) | |
341 LmMessageNode *form = lm_message_node_find_xmlns(x, "jabber:x:data");//TODO | |
342 if (form) { | |
343 LmMessageNode *field; | |
990
35e7913affb7
Send events/chatstates notifications (JEP-22/JEP-85)
Mikael Berthe <mikael@lilotux.net>
parents:
989
diff
changeset
|
344 |
1598 | 345 lm_message_node_set_attribute(command, "status", "completed"); |
346 //TODO: implement sth. like "field?var=groupchats" in xmlnode... | |
347 field = lm_message_node_get_child(form, "field"); | |
348 while (field && strcmp("groupchats", | |
349 lm_message_node_get_attribute(field, "var"))) | |
350 field = field->next; | |
351 | |
352 for (x = field->children ; x ; x = x->next) | |
353 { | |
354 LmMessageNode *to_leave = lm_message_node_get_child(x, "value"); | |
355 if (to_leave) { | |
356 GList* b = buddy_search_jid(lm_message_node_get_value(to_leave)); | |
357 if (b) | |
358 cmd_room_leave(b->data, "Requested by remote command"); | |
359 } | |
989
859ab76e5093
Send JEP-22 delivered messages
Mikael Berthe <mikael@lilotux.net>
parents:
988
diff
changeset
|
360 } |
1598 | 361 lm_message_node_add_dataform_result(command, |
362 "Groupchats have been left"); | |
988
6e2bfd1ffded
Add ids to message stanzas if needed
Mikael Berthe <mikael@lilotux.net>
parents:
987
diff
changeset
|
363 } |
987
f47e312560af
Improve JEP22 + JEP85 support
Mikael Berthe <mikael@lilotux.net>
parents:
986
diff
changeset
|
364 } |
1598 | 365 if (sessionid) |
366 lm_message_node_set_attribute(command, "sessionid", sessionid); | |
367 lm_connection_send(c, iq, NULL); | |
368 lm_message_unref(iq); | |
369 return LM_HANDLER_RESULT_REMOVE_MESSAGE; | |
370 } | |
986
ed697234bd39
Chat states receival (Alexis Hildebrandt)
Mikael Berthe <mikael@lilotux.net>
parents:
977
diff
changeset
|
371 |
1598 | 372 static LmHandlerResult handle_iq_commands(LmMessageHandler *h, |
373 LmConnection *c, | |
374 LmMessage *m, gpointer ud) | |
375 { | |
376 const char *requester_jid = NULL; | |
377 LmMessageNode *cmd; | |
378 const struct adhoc_command *command; | |
379 | |
380 // mcabber has only partial XEP-0146 support... | |
381 if (LM_MESSAGE_SUB_TYPE_SET != lm_message_get_sub_type(m)) | |
382 return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; | |
383 | |
384 requester_jid = lm_message_get_from(m); | |
988
6e2bfd1ffded
Add ids to message stanzas if needed
Mikael Berthe <mikael@lilotux.net>
parents:
987
diff
changeset
|
385 |
1598 | 386 cmd = lm_message_node_get_child(m->node, "command"); |
387 if (jid_equal(lm_connection_get_jid(c), requester_jid)) { | |
388 const char *action, *node; | |
389 action = lm_message_node_get_attribute(cmd, "action"); | |
390 node = lm_message_node_get_attribute(cmd, "node"); | |
391 // action can be NULL, in which case it seems to take the default, | |
392 // ie execute | |
393 if (!action || !strcmp(action, "execute") || !strcmp(action, "cancel") | |
394 || !strcmp(action, "next") || !strcmp(action, "complete")) { | |
395 for (command = adhoc_command_list; command->name; command++) { | |
396 if (!strcmp(node, command->name)) | |
397 command->callback(h, c, m, ud); | |
398 } | |
399 // "prev" action will get there, as we do not implement it, | |
400 // and do not authorize it | |
401 } else { | |
402 LmMessage *r; | |
403 LmMessageNode *err; | |
404 r = lm_message_new_iq_error(m, XMPP_ERROR_BAD_REQUEST); | |
405 err = lm_message_node_get_child(r->node, "error"); | |
406 lm_message_node_set_attribute | |
407 (lm_message_node_add_child(err, "malformed-action", NULL), | |
408 "xmlns", NS_COMMANDS); | |
409 lm_connection_send(c, r, NULL); | |
410 lm_message_unref(r); | |
411 } | |
412 } else { | |
413 send_iq_error(c, m, XMPP_ERROR_FORBIDDEN); | |
414 } | |
415 return LM_HANDLER_RESULT_REMOVE_MESSAGE; | |
35 | 416 } |
417 | |
990
35e7913affb7
Send events/chatstates notifications (JEP-22/JEP-85)
Mikael Berthe <mikael@lilotux.net>
parents:
989
diff
changeset
|
418 |
1598 | 419 static LmHandlerResult handle_iq_disco_items(LmMessageHandler *h, |
420 LmConnection *c, | |
421 LmMessage *m, gpointer ud) | |
990
35e7913affb7
Send events/chatstates notifications (JEP-22/JEP-85)
Mikael Berthe <mikael@lilotux.net>
parents:
989
diff
changeset
|
422 { |
1598 | 423 LmMessageNode *query; |
424 const char *node; | |
425 query = lm_message_node_get_child(m->node, "query"); | |
426 node = lm_message_node_get_attribute(query, "node"); | |
427 if (node) { | |
428 if (!strcmp(node, NS_COMMANDS)) { | |
429 return handle_iq_commands_list(NULL, c, m, ud); | |
430 } else { | |
431 send_iq_error(c, m, XMPP_ERROR_NOT_IMPLEMENTED); | |
1091
10f9d6fcfeab
JEP85: Reset composing/paused state when a resource with higher prio comes up
Mikael Berthe <mikael@lilotux.net>
parents:
1072
diff
changeset
|
432 } |
1598 | 433 } else { |
434 // not sure about this one | |
435 send_iq_error(c, m, XMPP_ERROR_NOT_IMPLEMENTED); | |
205 | 436 } |
1598 | 437 return LM_HANDLER_RESULT_REMOVE_MESSAGE; |
1395
d431cd75eb53
Use bookmarked nickname when manually joining a room
Mikael Berthe <mikael@lilotux.net>
parents:
1385
diff
changeset
|
438 } |
d431cd75eb53
Use bookmarked nickname when manually joining a room
Mikael Berthe <mikael@lilotux.net>
parents:
1385
diff
changeset
|
439 |
d431cd75eb53
Use bookmarked nickname when manually joining a room
Mikael Berthe <mikael@lilotux.net>
parents:
1385
diff
changeset
|
440 |
1598 | 441 // disco_info_set_ext(ansquery, ext) |
442 // Add features attributes to ansquery for extension ext. | |
443 static void disco_info_set_ext(LmMessageNode *ansquery, const char *ext) | |
1163
2913310a7be6
Make /roster bookmark in the status buffer show all bookmarks
Mikael Berthe <mikael@lilotux.net>
parents:
1161
diff
changeset
|
444 { |
1598 | 445 char *nodename = g_strdup_printf("%s#%s", MCABBER_CAPS_NODE, ext); |
446 lm_message_node_set_attribute(ansquery, "node", nodename); | |
447 g_free(nodename); | |
448 if (!strcasecmp(ext, "csn")) { | |
449 // I guess it's ok to send this even if it's not compiled in. | |
450 lm_message_node_set_attribute(lm_message_node_add_child(ansquery, | |
451 "feature", NULL), | |
452 "var", NS_CHATSTATES); | |
1008
bbf53cd43fbb
Functions to update room bookmarks
Mikael Berthe <mikael@lilotux.net>
parents:
1003
diff
changeset
|
453 } |
1598 | 454 if (!strcasecmp(ext, "iql")) { |
455 // I guess it's ok to send this even if it's not compiled in. | |
456 lm_message_node_set_attribute(lm_message_node_add_child(ansquery, | |
457 "feature", NULL), | |
458 "var", NS_LAST); | |
1008
bbf53cd43fbb
Functions to update room bookmarks
Mikael Berthe <mikael@lilotux.net>
parents:
1003
diff
changeset
|
459 } |
1016 | 460 } |
461 | |
1598 | 462 // disco_info_set_default(ansquery, entitycaps) |
463 // Add features attributes to ansquery. If entitycaps is TRUE, assume | |
464 // that we're answering an Entity Caps request (if not, the request was | |
465 // a basic discovery query). | |
466 // Please change the entity version string if you modify mcabber disco | |
467 // source code, so that it doesn't conflict with the upstream client. | |
468 static void disco_info_set_default(LmMessageNode *ansquery, guint entitycaps) | |
1016 | 469 { |
1598 | 470 LmMessageNode *y; |
471 char *eversion; | |
1016 | 472 |
1598 | 473 eversion = g_strdup_printf("%s#%s", MCABBER_CAPS_NODE, entity_version()); |
474 lm_message_node_set_attribute(ansquery, "node", eversion); | |
475 g_free(eversion); | |
476 | |
477 y = lm_message_node_add_child(ansquery, "identity", NULL); | |
1016 | 478 |
1598 | 479 lm_message_node_set_attributes(y, |
480 "category", "client", | |
481 "type", "pc", | |
482 "name", PACKAGE_NAME, | |
483 NULL); | |
1016 | 484 |
1598 | 485 lm_message_node_set_attribute |
486 (lm_message_node_add_child(ansquery, "feature", NULL), | |
487 "var", NS_DISCO_INFO); | |
488 lm_message_node_set_attribute | |
489 (lm_message_node_add_child(ansquery, "feature", NULL), | |
490 "var", NS_MUC); | |
491 #ifdef JEP0085 | |
492 // Advertise ChatStates only if we're not using Entity Capabilities | |
493 if (!entitycaps) | |
494 lm_message_node_set_attribute | |
495 (lm_message_node_add_child(ansquery, "feature", NULL), | |
496 "var", NS_CHATSTATES); | |
497 #endif | |
498 lm_message_node_set_attribute | |
499 (lm_message_node_add_child(ansquery, "feature", NULL), | |
500 "var", NS_TIME); | |
501 lm_message_node_set_attribute | |
502 (lm_message_node_add_child(ansquery, "feature", NULL), | |
503 "var", NS_XMPP_TIME); | |
504 lm_message_node_set_attribute | |
505 (lm_message_node_add_child(ansquery, "feature", NULL), | |
506 "var", NS_VERSION); | |
507 lm_message_node_set_attribute | |
508 (lm_message_node_add_child(ansquery, "feature", NULL), | |
509 "var", NS_PING); | |
510 lm_message_node_set_attribute | |
511 (lm_message_node_add_child(ansquery, "feature", NULL), | |
512 "var", NS_COMMANDS); | |
513 if (!entitycaps) | |
514 lm_message_node_set_attribute | |
515 (lm_message_node_add_child(ansquery, "feature", NULL), | |
516 "var", NS_LAST); | |
1016 | 517 } |
518 | |
1598 | 519 static LmHandlerResult handle_iq_disco_info(LmMessageHandler *h, |
520 LmConnection *c, | |
521 LmMessage *m, gpointer ud) | |
1043
ebbde723614b
Store contacts PGP keys
Mikael Berthe <mikael@lilotux.net>
parents:
1042
diff
changeset
|
522 { |
1598 | 523 LmMessage *r; |
524 LmMessageNode *query, *tmp; | |
525 const char *node = NULL; | |
1043
ebbde723614b
Store contacts PGP keys
Mikael Berthe <mikael@lilotux.net>
parents:
1042
diff
changeset
|
526 |
1598 | 527 r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); |
528 query = lm_message_node_add_child(r->node, "query", NULL); | |
529 lm_message_node_set_attribute(query, "xmlns", NS_DISCO_INFO); | |
530 tmp = lm_message_node_find_child(m->node, "query"); | |
531 if (tmp) | |
532 node = lm_message_node_get_attribute(tmp, "node"); | |
533 if (node && startswith(node, MCABBER_CAPS_NODE "#", FALSE)) { | |
534 const char *param = node+strlen(MCABBER_CAPS_NODE)+1; | |
535 if (!strcmp(param, entity_version())) | |
536 disco_info_set_default(query, TRUE); // client#version | |
1484
7b36b91a4388
New UI message flag (O) when OTR is used
Mikael Berthe <mikael@lilotux.net>
parents:
1476
diff
changeset
|
537 else |
1598 | 538 disco_info_set_ext(query, param); // client#extension |
819
c2d7d9dd4193
New option 'block_unsubscribed'
Mikael Berthe <mikael@lilotux.net>
parents:
818
diff
changeset
|
539 } else { |
1598 | 540 // Basic discovery request |
541 disco_info_set_default(query, FALSE); | |
819
c2d7d9dd4193
New option 'block_unsubscribed'
Mikael Berthe <mikael@lilotux.net>
parents:
818
diff
changeset
|
542 } |
1347
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1344
diff
changeset
|
543 |
1598 | 544 lm_connection_send(c, r, NULL); |
545 lm_message_unref(r); | |
546 return LM_HANDLER_RESULT_REMOVE_MESSAGE; | |
625
028c01940490
Show presence timestamps in "/info" and "/room whois"
Mikael Berthe <mikael@lilotux.net>
parents:
624
diff
changeset
|
547 } |
028c01940490
Show presence timestamps in "/info" and "/room whois"
Mikael Berthe <mikael@lilotux.net>
parents:
624
diff
changeset
|
548 |
1598 | 549 static LmHandlerResult handle_iq_roster(LmMessageHandler *h, LmConnection *c, |
550 LmMessage *m, gpointer ud) | |
579
0c67755e0fa7
Introduce a handle_presence_muc() function
Mikael Berthe <mikael@lilotux.net>
parents:
578
diff
changeset
|
551 { |
1598 | 552 LmMessageNode *y; |
553 const char *fjid, *name, *group, *sub, *ask; | |
554 char *cleanalias; | |
555 enum subscr esub; | |
556 int need_refresh = FALSE; | |
557 guint roster_type; | |
581
ad07c868ff43
Tell the user when he or she has been kicked/banned
Mikael Berthe <mikael@lilotux.net>
parents:
580
diff
changeset
|
558 |
1598 | 559 for (y = lm_message_node_find_child(lm_message_node_find_xmlns |
560 (m->node, NS_ROSTER), | |
561 "item"); | |
562 y; | |
563 y = y->next) { | |
564 char *name_tmp = NULL; | |
864
a7b3409df6bc
MUC: Work around user server restart
Mikael Berthe <mikael@lilotux.net>
parents:
862
diff
changeset
|
565 |
1598 | 566 fjid = lm_message_node_get_attribute(y, "jid"); |
567 name = lm_message_node_get_attribute(y, "name"); | |
568 sub = lm_message_node_get_attribute(y, "subscription"); | |
569 ask = lm_message_node_get_attribute(y, "ask"); | |
581
ad07c868ff43
Tell the user when he or she has been kicked/banned
Mikael Berthe <mikael@lilotux.net>
parents:
580
diff
changeset
|
570 |
1598 | 571 if (lm_message_node_find_child(y, "group")) |
572 group = lm_message_node_get_value(lm_message_node_find_child(y, "group")); | |
573 else | |
574 group = NULL; | |
1396
8f9928839a36
Automatically unlock new rooms (suggested by Michael Weiser)
Mikael Berthe <mikael@lilotux.net>
parents:
1395
diff
changeset
|
575 |
1598 | 576 if (!fjid) |
577 continue; | |
578 | |
579 cleanalias = jidtodisp(fjid); | |
579
0c67755e0fa7
Introduce a handle_presence_muc() function
Mikael Berthe <mikael@lilotux.net>
parents:
578
diff
changeset
|
580 |
1598 | 581 esub = sub_none; |
582 if (sub) { | |
583 if (!strcmp(sub, "to")) esub = sub_to; | |
584 else if (!strcmp(sub, "from")) esub = sub_from; | |
585 else if (!strcmp(sub, "both")) esub = sub_both; | |
586 else if (!strcmp(sub, "remove")) esub = sub_remove; | |
583
32ae027a3238
MUC: clean up departure message code
Mikael Berthe <mikael@lilotux.net>
parents:
581
diff
changeset
|
587 } |
581
ad07c868ff43
Tell the user when he or she has been kicked/banned
Mikael Berthe <mikael@lilotux.net>
parents:
580
diff
changeset
|
588 |
1598 | 589 if (esub == sub_remove) { |
590 roster_del_user(cleanalias); | |
591 scr_LogPrint(LPRINT_LOGNORM, "Buddy <%s> has been removed " | |
592 "from the roster", cleanalias); | |
593 g_free(cleanalias); | |
594 need_refresh = TRUE; | |
595 continue; | |
596 } | |
583
32ae027a3238
MUC: clean up departure message code
Mikael Berthe <mikael@lilotux.net>
parents:
581
diff
changeset
|
597 |
1598 | 598 if (ask && !strcmp(ask, "subscribe")) |
599 esub |= sub_pending; | |
600 | |
601 if (!name) { | |
602 if (!settings_opt_get_int("roster_hide_domain")) { | |
603 name = cleanalias; | |
583
32ae027a3238
MUC: clean up departure message code
Mikael Berthe <mikael@lilotux.net>
parents:
581
diff
changeset
|
604 } else { |
1598 | 605 char *p; |
606 name = name_tmp = g_strdup(cleanalias); | |
607 p = strchr(name_tmp, JID_DOMAIN_SEPARATOR); | |
608 if (p) *p = '\0'; | |
581
ad07c868ff43
Tell the user when he or she has been kicked/banned
Mikael Berthe <mikael@lilotux.net>
parents:
580
diff
changeset
|
609 } |
583
32ae027a3238
MUC: clean up departure message code
Mikael Berthe <mikael@lilotux.net>
parents:
581
diff
changeset
|
610 } |
32ae027a3238
MUC: clean up departure message code
Mikael Berthe <mikael@lilotux.net>
parents:
581
diff
changeset
|
611 |
1598 | 612 // Tricky... :-\ My guess is that if there is no JID_DOMAIN_SEPARATOR, |
613 // this is an agent. | |
614 if (strchr(cleanalias, JID_DOMAIN_SEPARATOR)) | |
615 roster_type = ROSTER_TYPE_USER; | |
616 else | |
617 roster_type = ROSTER_TYPE_AGENT; | |
1377
cd9182f0b5c7
Add /room setopt {print_status,auto_whois}
Mikael Berthe <mikael@lilotux.net>
parents:
1365
diff
changeset
|
618 |
1598 | 619 roster_add_user(cleanalias, name, group, roster_type, esub, 1); |
579
0c67755e0fa7
Introduce a handle_presence_muc() function
Mikael Berthe <mikael@lilotux.net>
parents:
578
diff
changeset
|
620 |
1598 | 621 g_free(name_tmp); |
622 g_free(cleanalias); | |
1446
49c8be874344
Add option 'ignore_self_presence'
Mikael Berthe <mikael@lilotux.net>
parents:
1439
diff
changeset
|
623 } |
49c8be874344
Add option 'ignore_self_presence'
Mikael Berthe <mikael@lilotux.net>
parents:
1439
diff
changeset
|
624 |
1598 | 625 buddylist_build(); |
626 update_roster = TRUE; | |
627 if (need_refresh) | |
628 scr_UpdateBuddyWindow(); | |
629 return LM_HANDLER_RESULT_REMOVE_MESSAGE; | |
630 } | |
644
68fb0c1dfb15
MUC: better nickname check when entering a room
Mikael Berthe <mikael@lilotux.net>
parents:
643
diff
changeset
|
631 |
1598 | 632 static LmHandlerResult handle_iq_ping(LmMessageHandler *h, LmConnection *c, |
633 LmMessage *m, gpointer ud) | |
634 { | |
635 LmMessage *r; | |
644
68fb0c1dfb15
MUC: better nickname check when entering a room
Mikael Berthe <mikael@lilotux.net>
parents:
643
diff
changeset
|
636 |
1598 | 637 r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); |
638 lm_connection_send(c, r, NULL); | |
639 lm_message_unref(r); | |
640 return LM_HANDLER_RESULT_REMOVE_MESSAGE; | |
641 } | |
642 | |
643 double seconds_since_last_use(void) | |
644 { | |
645 return difftime(time(NULL), iqlast); | |
646 } | |
644
68fb0c1dfb15
MUC: better nickname check when entering a room
Mikael Berthe <mikael@lilotux.net>
parents:
643
diff
changeset
|
647 |
1598 | 648 static LmHandlerResult handle_iq_last(LmMessageHandler *h, LmConnection *c, |
649 LmMessage *m, gpointer ud) | |
650 { | |
651 LmMessage *r; | |
652 LmMessageNode *query; | |
653 char *seconds; | |
547
1df26ff0ed8c
Break packethandler() out
Mikael Berthe <mikael@lilotux.net>
parents:
539
diff
changeset
|
654 |
1598 | 655 if (!settings_opt_get_int("iq_hide_requests")) { |
656 scr_LogPrint(LPRINT_LOGNORM, "Received an IQ last time request from <%s>", | |
657 lm_message_get_from(m)); | |
547
1df26ff0ed8c
Break packethandler() out
Mikael Berthe <mikael@lilotux.net>
parents:
539
diff
changeset
|
658 } |
1df26ff0ed8c
Break packethandler() out
Mikael Berthe <mikael@lilotux.net>
parents:
539
diff
changeset
|
659 |
1598 | 660 if (settings_opt_get_int("iq_last_disable") || |
661 (settings_opt_get_int("iq_last_disable_when_notavail") && | |
662 xmpp_getstatus() == notavail)) | |
663 { | |
664 send_iq_error(c, m, XMPP_ERROR_SERVICE_UNAVAILABLE); | |
665 return LM_HANDLER_RESULT_REMOVE_MESSAGE; | |
547
1df26ff0ed8c
Break packethandler() out
Mikael Berthe <mikael@lilotux.net>
parents:
539
diff
changeset
|
666 } |
1df26ff0ed8c
Break packethandler() out
Mikael Berthe <mikael@lilotux.net>
parents:
539
diff
changeset
|
667 |
1598 | 668 r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); |
669 query = lm_message_node_add_child(r->node, "query", NULL); | |
670 seconds = g_strdup_printf("%.0f", seconds_since_last_use()); | |
671 lm_message_node_set_attribute(query, "seconds", seconds); | |
672 g_free(seconds); | |
1236
f7b35b1c343d
Fix a roster bug when receiving a MUC invitation
Mikael Berthe <mikael@lilotux.net>
parents:
1215
diff
changeset
|
673 |
1598 | 674 lm_connection_send(c, r, NULL); |
675 lm_message_unref(r); | |
676 return LM_HANDLER_RESULT_REMOVE_MESSAGE; | |
1128 | 677 } |
678 | |
1598 | 679 static LmHandlerResult handle_iq_version(LmMessageHandler *h, LmConnection *c, |
680 LmMessage *m, gpointer ud) | |
1128 | 681 { |
1598 | 682 LmMessage *r; |
683 LmMessageNode *query; | |
684 char *os = NULL; | |
685 char *ver = mcabber_version(); | |
1128 | 686 |
1598 | 687 if (!settings_opt_get_int("iq_hide_requests")) { |
688 scr_LogPrint(LPRINT_LOGNORM, "Received an IQ version request from <%s>", | |
689 lm_message_get_from(m)); | |
690 } | |
691 if (!settings_opt_get_int("iq_version_hide_os")) { | |
692 struct utsname osinfo; | |
693 uname(&osinfo); | |
694 os = g_strdup_printf("%s %s %s", osinfo.sysname, osinfo.release, | |
695 osinfo.machine); | |
1128 | 696 } |
1598 | 697 |
698 r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); | |
699 | |
700 query = lm_message_node_add_child(r->node, "query", NULL); | |
701 | |
702 lm_message_node_add_child(query, "name", PACKAGE_NAME); | |
703 lm_message_node_add_child(query, "version", ver); | |
704 if (os) { | |
705 lm_message_node_add_child(query, "os", os); | |
706 g_free(os); | |
707 } | |
708 | |
709 g_free(ver); | |
710 lm_connection_send(c, r, NULL); | |
711 lm_message_unref(r); | |
712 return LM_HANDLER_RESULT_REMOVE_MESSAGE; | |
1128 | 713 } |
714 | |
1598 | 715 // This function borrows some code from the Pidgin project |
716 static LmHandlerResult handle_iq_time(LmMessageHandler *h, LmConnection *c, | |
717 LmMessage *m, gpointer ud) | |
547
1df26ff0ed8c
Break packethandler() out
Mikael Berthe <mikael@lilotux.net>
parents:
539
diff
changeset
|
718 { |
1598 | 719 LmMessage *r; |
720 LmMessageNode *query; | |
721 char *buf, *utf8_buf; | |
722 time_t now_t; | |
723 struct tm *now; | |
1528
4b4b3948420c
MUC fix: the topic couldn't be cleared
Mikael Berthe <mikael@lilotux.net>
parents:
1525
diff
changeset
|
724 |
1598 | 725 time(&now_t); |
726 | |
727 if (!settings_opt_get_int("iq_hide_requests")) { | |
728 scr_LogPrint(LPRINT_LOGNORM, "Received an IQ time request from <%s>", | |
729 lm_message_get_from(m)); | |
547
1df26ff0ed8c
Break packethandler() out
Mikael Berthe <mikael@lilotux.net>
parents:
539
diff
changeset
|
730 } |
1df26ff0ed8c
Break packethandler() out
Mikael Berthe <mikael@lilotux.net>
parents:
539
diff
changeset
|
731 |
1598 | 732 buf = g_new0(char, 512); |
733 | |
734 r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); | |
735 query = lm_message_node_add_child(r->node, "query", NULL); | |
547
1df26ff0ed8c
Break packethandler() out
Mikael Berthe <mikael@lilotux.net>
parents:
539
diff
changeset
|
736 |
1598 | 737 now = gmtime(&now_t); |
1128 | 738 |
1598 | 739 strftime(buf, 512, "%Y%m%dT%T", now); |
740 lm_message_node_add_child(query, "utc", buf); | |
547
1df26ff0ed8c
Break packethandler() out
Mikael Berthe <mikael@lilotux.net>
parents:
539
diff
changeset
|
741 |
1598 | 742 now = localtime(&now_t); |
987
f47e312560af
Improve JEP22 + JEP85 support
Mikael Berthe <mikael@lilotux.net>
parents:
986
diff
changeset
|
743 |
1598 | 744 strftime(buf, 512, "%Z", now); |
745 if ((utf8_buf = to_utf8(buf))) { | |
746 lm_message_node_add_child(query, "tz", utf8_buf); | |
747 g_free(utf8_buf); | |
748 } | |
987
f47e312560af
Improve JEP22 + JEP85 support
Mikael Berthe <mikael@lilotux.net>
parents:
986
diff
changeset
|
749 |
1598 | 750 strftime(buf, 512, "%d %b %Y %T", now); |
751 if ((utf8_buf = to_utf8(buf))) { | |
752 lm_message_node_add_child(query, "display", utf8_buf); | |
753 g_free(utf8_buf); | |
987
f47e312560af
Improve JEP22 + JEP85 support
Mikael Berthe <mikael@lilotux.net>
parents:
986
diff
changeset
|
754 } |
986
ed697234bd39
Chat states receival (Alexis Hildebrandt)
Mikael Berthe <mikael@lilotux.net>
parents:
977
diff
changeset
|
755 |
1598 | 756 lm_connection_send(c, r, NULL); |
757 lm_message_unref(r); | |
758 g_free(buf); | |
759 return LM_HANDLER_RESULT_REMOVE_MESSAGE; | |
760 } | |
986
ed697234bd39
Chat states receival (Alexis Hildebrandt)
Mikael Berthe <mikael@lilotux.net>
parents:
977
diff
changeset
|
761 |
1598 | 762 // This function borrows some code from the Pidgin project |
763 static LmHandlerResult handle_iq_time202(LmMessageHandler *h, LmConnection *c, | |
764 LmMessage *m, gpointer ud) | |
765 { | |
766 LmMessage *r; | |
767 LmMessageNode *query; | |
768 char *buf, *utf8_buf; | |
769 time_t now_t; | |
770 struct tm *now; | |
771 char const *sign; | |
772 int diff = 0; | |
987
f47e312560af
Improve JEP22 + JEP85 support
Mikael Berthe <mikael@lilotux.net>
parents:
986
diff
changeset
|
773 |
1598 | 774 time(&now_t); |
775 | |
776 if (!settings_opt_get_int("iq_hide_requests")) { | |
777 scr_LogPrint(LPRINT_LOGNORM, "Received an IQ time request from <%s>", | |
778 lm_message_get_from(m)); | |
986
ed697234bd39
Chat states receival (Alexis Hildebrandt)
Mikael Berthe <mikael@lilotux.net>
parents:
977
diff
changeset
|
779 } |
ed697234bd39
Chat states receival (Alexis Hildebrandt)
Mikael Berthe <mikael@lilotux.net>
parents:
977
diff
changeset
|
780 |
1598 | 781 buf = g_new0(char, 512); |
987
f47e312560af
Improve JEP22 + JEP85 support
Mikael Berthe <mikael@lilotux.net>
parents:
986
diff
changeset
|
782 |
1598 | 783 r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); |
784 query = lm_message_node_add_child(r->node, "time", NULL); | |
785 lm_message_node_set_attribute(query, "xmlns", NS_XMPP_TIME); | |
987
f47e312560af
Improve JEP22 + JEP85 support
Mikael Berthe <mikael@lilotux.net>
parents:
986
diff
changeset
|
786 |
1598 | 787 now = localtime(&now_t); |
987
f47e312560af
Improve JEP22 + JEP85 support
Mikael Berthe <mikael@lilotux.net>
parents:
986
diff
changeset
|
788 |
1598 | 789 if (now->tm_isdst >= 0) { |
790 #if defined HAVE_TM_GMTOFF | |
791 diff = now->tm_gmtoff; | |
792 #elif defined HAVE_TIMEZONE | |
793 tzset(); | |
794 diff = -timezone; | |
989
859ab76e5093
Send JEP-22 delivered messages
Mikael Berthe <mikael@lilotux.net>
parents:
988
diff
changeset
|
795 #endif |
986
ed697234bd39
Chat states receival (Alexis Hildebrandt)
Mikael Berthe <mikael@lilotux.net>
parents:
977
diff
changeset
|
796 } |
ed697234bd39
Chat states receival (Alexis Hildebrandt)
Mikael Berthe <mikael@lilotux.net>
parents:
977
diff
changeset
|
797 |
1598 | 798 if (diff < 0) { |
799 sign = "-"; | |
800 diff = -diff; | |
749
6c633adaae10
Use events system for subscription requests
Mikael Berthe <mikael@lilotux.net>
parents:
745
diff
changeset
|
801 } else { |
1598 | 802 sign = "+"; |
749
6c633adaae10
Use events system for subscription requests
Mikael Berthe <mikael@lilotux.net>
parents:
745
diff
changeset
|
803 } |
1598 | 804 diff /= 60; |
805 snprintf(buf, 512, "%c%02d:%02d", *sign, diff / 60, diff % 60); | |
806 if ((utf8_buf = to_utf8(buf))) { | |
807 lm_message_node_add_child(query, "tzo", utf8_buf); | |
808 g_free(utf8_buf); | |
1128 | 809 } |
810 | |
1598 | 811 now = gmtime(&now_t); |
818
55cd45481a07
Fix a buddylist bug when receiving a subscription request
Mikael Berthe <mikael@lilotux.net>
parents:
793
diff
changeset
|
812 |
1598 | 813 strftime(buf, 512, "%Y-%m-%dT%TZ", now); |
814 lm_message_node_add_child(query, "utc", buf); | |
611
ad737139a144
Improve subscription management
Mikael Berthe <mikael@lilotux.net>
parents:
610
diff
changeset
|
815 |
1598 | 816 lm_connection_send(c, r, NULL); |
817 lm_message_unref(r); | |
818 g_free(buf); | |
819 return LM_HANDLER_RESULT_REMOVE_MESSAGE; | |
547
1df26ff0ed8c
Break packethandler() out
Mikael Berthe <mikael@lilotux.net>
parents:
539
diff
changeset
|
820 } |