Mercurial > pidgin.yaz
annotate src/protocols/jabber/message.c @ 9584:fe35f55ee984
[gaim-migrate @ 10427]
" When joining a jabber conference many jabber servers
send a recap of the last 20 or so messages. If you
have sounds enabled, this will result in either 20
sounds in row, or worse if mixing is available, a
horrible mix of 20 overlapping sounds. These recap
messages can be identifed be the presence of the
"jabber:x:delay". This patch identifies delayed
messages, passes that information through flags from
the prpl to the core, and then on to the gui. Detailed
changes:
Add GAIM_MESSAGE_DELAYED to GaimMessageFlags to
indicate a delayed message.
Change gtkconv.c to not play sounds when either
GAIM_MESSAGE_DELAYED or GAIM_MESSAGE_SYSTEM are set.
Add GaimConvChatFlags, parallel to GaimConvImFlags, to
pass flags from protocols to core. Currently contains
two flags:
GAIM_CONV_CHAT_WHISPER
GAIM_CONV_CHAT_DELAYED
Change fourth arg of serv_got_chat_in() from "int
whisper" to "GaimConvChatFlags chatflags".
Change jabber prpl to set delayed flag when the
"jabber:x:delay" element is present. Change toc
protocol since it uses the whisper flag." --Nathan Fredrickson
Date: 2004-07-24 00:49
Sender: marv_sfAccepting Donations
Logged In: YES
user_id=790708
I'm not sure I like naming the flags "DELAYED". I mean
that's okay inside jabber since that's what the jabber
protocol refers to it as, but for the the GAIM_*_DELAYED
flags, I think they should be named something else.
I thought about NOSOUND, but I decided that was wrong,
because the flag should say what kind of message it is, not
what to do with it, that's up to the UI to decide.
What's up with not playing sounds on GAIM_MESSAGE_SYSTEM?
This sounds unrelated to this. Are there times when we want
to play sounds on system messages?
Date: 2004-07-24 09:13
Sender: noif
Logged In: YES
user_id=365548
I purposely did not use a name that implied what the UI
should do with the flag. The only characteristic that makes
these messages unique is that they've been stored in the
server for some period of time and are not current. I'm
open to a better flag name than "DELAYED"... I thought about
"RECAP", but that seemed less generalized than "DELAYED".
As for not playing sounds on GAIM_MESSAGE_SYSTEM, that can
be removed if it's controversial. I think I slipped that
in since the setting of the topic was still playing a sound
every time you joined a jabber conference.
I think we can change the flag name ourselves if something else is better.
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Sat, 24 Jul 2004 15:18:32 +0000 |
parents | 933a19e3a6b3 |
children | 3f97624e7753 |
rev | line source |
---|---|
7014 | 1 /* |
2 * gaim - Jabber Protocol Plugin | |
3 * | |
4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 * | |
20 */ | |
21 #include "internal.h" | |
22 | |
23 #include "debug.h" | |
24 #include "notify.h" | |
25 #include "server.h" | |
7095
c8bf2da398e3
[gaim-migrate @ 7660]
Christian Hammond <chipx86@chipx86.com>
parents:
7014
diff
changeset
|
26 #include "util.h" |
7014 | 27 |
28 #include "buddy.h" | |
29 #include "chat.h" | |
30 #include "message.h" | |
31 #include "xmlnode.h" | |
32 | |
33 #define JABBER_TYPING_NOTIFY_INT 15 | |
34 | |
35 void jabber_message_free(JabberMessage *jm) | |
36 { | |
37 if(jm->from) | |
38 g_free(jm->from); | |
39 if(jm->to) | |
40 g_free(jm->to); | |
41 if(jm->subject) | |
42 g_free(jm->subject); | |
43 if(jm->body) | |
44 g_free(jm->body); | |
45 if(jm->xhtml) | |
46 g_free(jm->xhtml); | |
47 if(jm->password) | |
48 g_free(jm->password); | |
7145 | 49 if(jm->etc) |
50 g_list_free(jm->etc); | |
7014 | 51 |
52 g_free(jm); | |
53 } | |
54 | |
7145 | 55 static void handle_chat(JabberMessage *jm) |
7014 | 56 { |
57 JabberID *jid = jabber_id_new(jm->from); | |
58 char *from; | |
59 | |
60 JabberBuddy *jb; | |
61 JabberBuddyResource *jbr; | |
62 | |
7310 | 63 if(!jid) |
64 return; | |
65 | |
7014 | 66 jb = jabber_buddy_find(jm->js, jm->from, TRUE); |
7306 | 67 jbr = jabber_buddy_find_resource(jb, jid->resource); |
7014 | 68 |
8043 | 69 if(jabber_find_unnormalized_conv(jm->from, jm->js->gc->account)) { |
7014 | 70 from = g_strdup(jm->from); |
7258 | 71 } else if(jid->node) { |
72 GaimConversation *conv; | |
73 | |
7014 | 74 from = g_strdup_printf("%s@%s", jid->node, jid->domain); |
8043 | 75 conv = jabber_find_unnormalized_conv(from, jm->js->gc->account); |
7258 | 76 if(conv) |
77 gaim_conversation_set_name(conv, jm->from); | |
78 g_free(from); | |
79 from = g_strdup(jm->from); | |
80 } else { | |
7014 | 81 from = g_strdup(jid->domain); |
7258 | 82 } |
7014 | 83 |
84 if(!jm->xhtml && !jm->body) { | |
85 if(jm->events & JABBER_MESSAGE_EVENT_COMPOSING) | |
86 serv_got_typing(jm->js->gc, from, 0, GAIM_TYPING); | |
87 else | |
88 serv_got_typing_stopped(jm->js->gc, from); | |
89 } else { | |
8400 | 90 if(jbr) { |
91 if(jm->events & JABBER_MESSAGE_EVENT_COMPOSING) | |
92 jbr->capabilities |= JABBER_CAP_COMPOSING; | |
93 if(jbr->thread_id) | |
94 g_free(jbr->thread_id); | |
95 jbr->thread_id = g_strdup(jbr->thread_id); | |
96 } | |
7014 | 97 serv_got_im(jm->js->gc, from, jm->xhtml ? jm->xhtml : jm->body, 0, |
98 jm->sent); | |
99 } | |
100 | |
101 g_free(from); | |
102 jabber_id_free(jid); | |
103 } | |
104 | |
7145 | 105 static void handle_headline(JabberMessage *jm) |
106 { | |
107 char *title; | |
108 GString *body = g_string_new(""); | |
109 GList *etc; | |
110 | |
111 title = g_strdup_printf(_("Message from %s"), jm->from); | |
112 | |
113 if(jm->xhtml) | |
114 g_string_append(body, jm->xhtml); | |
115 else if(jm->body) | |
116 g_string_append(body, jm->body); | |
117 | |
118 for(etc = jm->etc; etc; etc = etc->next) { | |
119 xmlnode *x = etc->data; | |
120 const char *xmlns = xmlnode_get_attrib(x, "xmlns"); | |
121 if(xmlns && !strcmp(xmlns, "jabber:x:oob")) { | |
122 xmlnode *url, *desc; | |
123 char *urltxt, *desctxt; | |
124 | |
125 url = xmlnode_get_child(x, "url"); | |
126 desc = xmlnode_get_child(x, "desc"); | |
127 | |
128 if(!url || !desc) | |
129 continue; | |
130 | |
131 urltxt = xmlnode_get_data(url); | |
132 desctxt = xmlnode_get_data(desc); | |
133 | |
134 /* I'm all about ugly hacks */ | |
135 if(body->len && !strcmp(body->str, jm->body)) | |
136 g_string_printf(body, "<a href='%s'>%s</a>", | |
137 urltxt, desctxt); | |
138 else | |
139 g_string_append_printf(body, "<br/><a href='%s'>%s</a>", | |
140 urltxt, desctxt); | |
141 | |
142 g_free(urltxt); | |
143 g_free(desctxt); | |
144 } | |
145 } | |
146 | |
147 gaim_notify_formatted(jm->js->gc, title, jm->subject ? jm->subject : title, | |
148 NULL, body->str, NULL, NULL); | |
149 | |
150 g_free(title); | |
151 g_string_free(body, TRUE); | |
152 } | |
153 | |
154 static void handle_groupchat(JabberMessage *jm) | |
7014 | 155 { |
156 JabberID *jid = jabber_id_new(jm->from); | |
7310 | 157 JabberChat *chat; |
158 | |
159 if(!jid) | |
160 return; | |
161 | |
162 chat = jabber_chat_find(jm->js, jid->node, jid->domain); | |
7014 | 163 |
164 if(!chat) | |
165 return; | |
166 | |
7971 | 167 if(jm->subject) { |
7183 | 168 gaim_conv_chat_set_topic(GAIM_CONV_CHAT(chat->conv), jid->resource, |
169 jm->subject); | |
7971 | 170 if(!jm->xhtml && !jm->body) { |
171 char *msg; | |
172 if(jid->resource) | |
173 msg = g_strdup_printf(_("%s has set the topic to: %s"), jid->resource, jm->subject); | |
174 else | |
175 msg = g_strdup_printf(_("The topic is: %s"), jm->subject); | |
176 gaim_conv_chat_write(GAIM_CONV_CHAT(chat->conv), "", msg, GAIM_MESSAGE_SYSTEM, jm->sent); | |
177 g_free(msg); | |
178 } | |
179 } | |
7014 | 180 |
7630 | 181 if(jm->xhtml || jm->body) { |
182 if(jid->resource) | |
9584 | 183 serv_got_chat_in(jm->js->gc, chat->id, jid->resource, |
184 jm->delayed ? GAIM_CONV_CHAT_DELAYED : 0, | |
7630 | 185 jm->xhtml ? jm->xhtml : jm->body, jm->sent); |
186 else if(chat->muc) | |
187 gaim_conv_chat_write(GAIM_CONV_CHAT(chat->conv), "", | |
188 jm->xhtml ? jm->xhtml : jm->body, | |
189 GAIM_MESSAGE_SYSTEM, jm->sent); | |
190 } | |
191 | |
7014 | 192 jabber_id_free(jid); |
193 } | |
194 | |
7145 | 195 static void handle_groupchat_invite(JabberMessage *jm) |
7014 | 196 { |
7310 | 197 GHashTable *components; |
7014 | 198 JabberID *jid = jabber_id_new(jm->to); |
8537 | 199 char *stripped; |
7014 | 200 |
7310 | 201 if(!jid) |
202 return; | |
203 | |
204 components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | |
205 | |
7332 | 206 g_hash_table_replace(components, g_strdup("room"), g_strdup(jid->node)); |
7448 | 207 g_hash_table_replace(components, g_strdup("server"), g_strdup(jid->domain)); |
7332 | 208 g_hash_table_replace(components, g_strdup("handle"), |
209 g_strdup(jm->js->user->node)); | |
210 g_hash_table_replace(components, g_strdup("password"), | |
211 g_strdup(jm->password)); | |
7014 | 212 |
213 jabber_id_free(jid); | |
8537 | 214 stripped = gaim_markup_strip_html(jm->body); |
215 serv_got_chat_invite(jm->js->gc, jm->to, jm->from, stripped, components); | |
216 g_free(stripped); | |
7014 | 217 } |
218 | |
7145 | 219 static void handle_error(JabberMessage *jm) |
7014 | 220 { |
221 char *buf; | |
222 | |
223 if(!jm->body) | |
224 return; | |
225 | |
226 buf = g_strdup_printf(_("Message delivery to %s failed: %s"), | |
227 jm->from, jm->error); | |
228 | |
7944 | 229 gaim_notify_formatted(jm->js->gc, _("Jabber Message Error"), _("Jabber Message Error"), buf, |
230 jm->xhtml ? jm->xhtml : jm->body, NULL, NULL); | |
7014 | 231 |
232 g_free(buf); | |
233 } | |
234 | |
235 void jabber_message_parse(JabberStream *js, xmlnode *packet) | |
236 { | |
237 JabberMessage *jm; | |
238 const char *type; | |
239 xmlnode *child; | |
240 | |
241 if(strcmp(packet->name, "message")) | |
242 return; | |
243 | |
244 jm = g_new0(JabberMessage, 1); | |
245 jm->js = js; | |
246 jm->sent = time(NULL); | |
9584 | 247 jm->delayed = FALSE; |
7014 | 248 |
249 type = xmlnode_get_attrib(packet, "type"); | |
250 | |
251 if(type) { | |
252 if(!strcmp(type, "normal")) | |
253 jm->type = JABBER_MESSAGE_NORMAL; | |
254 else if(!strcmp(type, "chat")) | |
255 jm->type = JABBER_MESSAGE_CHAT; | |
256 else if(!strcmp(type, "groupchat")) | |
257 jm->type = JABBER_MESSAGE_GROUPCHAT; | |
258 else if(!strcmp(type, "headline")) | |
259 jm->type = JABBER_MESSAGE_HEADLINE; | |
260 else if(!strcmp(type, "error")) | |
261 jm->type = JABBER_MESSAGE_ERROR; | |
262 else | |
263 jm->type = JABBER_MESSAGE_OTHER; | |
264 } else { | |
265 jm->type = JABBER_MESSAGE_NORMAL; | |
266 } | |
267 | |
268 jm->from = g_strdup(xmlnode_get_attrib(packet, "from")); | |
269 jm->to = g_strdup(xmlnode_get_attrib(packet, "to")); | |
270 | |
271 for(child = packet->child; child; child = child->next) { | |
8135 | 272 if(child->type != XMLNODE_TYPE_TAG) |
7014 | 273 continue; |
274 | |
275 if(!strcmp(child->name, "subject")) { | |
276 if(!jm->subject) | |
277 jm->subject = xmlnode_get_data(child); | |
8400 | 278 } else if(!strcmp(child->name, "thread")) { |
279 if(!jm->thread_id) | |
280 jm->thread_id = xmlnode_get_data(child); | |
7014 | 281 } else if(!strcmp(child->name, "body")) { |
282 if(!jm->body) | |
7894 | 283 jm->body = xmlnode_to_str(child, NULL); |
7241 | 284 } else if(!strcmp(child->name, "html")) { |
285 if(!jm->xhtml) | |
7642 | 286 jm->xhtml = xmlnode_to_str(child, NULL); |
7014 | 287 } else if(!strcmp(child->name, "error")) { |
288 const char *code = xmlnode_get_attrib(child, "code"); | |
289 char *code_txt = NULL; | |
290 char *text = xmlnode_get_data(child); | |
291 | |
292 if(code) | |
293 code_txt = g_strdup_printf(_(" (Code %s)"), code); | |
294 | |
295 if(!jm->error) | |
296 jm->error = g_strdup_printf("%s%s", text ? text : "", | |
297 code_txt ? code_txt : ""); | |
298 | |
299 g_free(code_txt); | |
300 g_free(text); | |
301 } else if(!strcmp(child->name, "x")) { | |
302 const char *xmlns = xmlnode_get_attrib(child, "xmlns"); | |
303 if(xmlns && !strcmp(xmlns, "jabber:x:event")) { | |
304 if(xmlnode_get_child(child, "composing")) | |
305 jm->events |= JABBER_MESSAGE_EVENT_COMPOSING; | |
306 } else if(xmlns && !strcmp(xmlns, "jabber:x:delay")) { | |
307 const char *timestamp = xmlnode_get_attrib(child, "stamp"); | |
9584 | 308 jm->delayed = TRUE; |
7014 | 309 if(timestamp) |
8577 | 310 jm->sent = gaim_str_to_time(timestamp, TRUE); |
7014 | 311 } else if(xmlns && !strcmp(xmlns, "jabber:x:conference") && |
312 jm->type != JABBER_MESSAGE_GROUPCHAT_INVITE) { | |
313 const char *jid = xmlnode_get_attrib(child, "jid"); | |
314 if(jid) { | |
315 jm->type = JABBER_MESSAGE_GROUPCHAT_INVITE; | |
316 g_free(jm->to); | |
317 jm->to = g_strdup(jid); | |
318 } | |
319 } else if(xmlns && !strcmp(xmlns, | |
320 "http://jabber.org/protocol/muc#user")) { | |
321 xmlnode *invite = xmlnode_get_child(child, "invite"); | |
322 if(invite) { | |
323 xmlnode *reason, *password; | |
7968 | 324 const char *jid = xmlnode_get_attrib(invite, "from"); |
7014 | 325 g_free(jm->to); |
326 jm->to = jm->from; | |
327 jm->from = g_strdup(jid); | |
328 if((reason = xmlnode_get_child(invite, "reason"))) { | |
329 g_free(jm->body); | |
330 jm->body = xmlnode_get_data(reason); | |
331 } | |
332 if((password = xmlnode_get_child(invite, "password"))) | |
333 jm->password = xmlnode_get_data(password); | |
334 | |
335 jm->type = JABBER_MESSAGE_GROUPCHAT_INVITE; | |
336 } | |
7145 | 337 } else { |
338 jm->etc = g_list_append(jm->etc, child); | |
7014 | 339 } |
340 } | |
341 } | |
342 | |
343 switch(jm->type) { | |
344 case JABBER_MESSAGE_NORMAL: | |
345 case JABBER_MESSAGE_CHAT: | |
7145 | 346 handle_chat(jm); |
347 break; | |
7014 | 348 case JABBER_MESSAGE_HEADLINE: |
7145 | 349 handle_headline(jm); |
7014 | 350 break; |
351 case JABBER_MESSAGE_GROUPCHAT: | |
352 handle_groupchat(jm); | |
353 break; | |
354 case JABBER_MESSAGE_GROUPCHAT_INVITE: | |
355 handle_groupchat_invite(jm); | |
356 break; | |
357 case JABBER_MESSAGE_ERROR: | |
358 handle_error(jm); | |
359 break; | |
360 case JABBER_MESSAGE_OTHER: | |
361 gaim_debug(GAIM_DEBUG_INFO, "jabber", | |
362 "Received message of unknown type: %s\n", type); | |
363 break; | |
364 } | |
365 jabber_message_free(jm); | |
366 } | |
367 | |
368 void jabber_message_send(JabberMessage *jm) | |
369 { | |
370 xmlnode *message, *child; | |
371 const char *type = NULL; | |
372 | |
373 message = xmlnode_new("message"); | |
374 | |
375 switch(jm->type) { | |
376 case JABBER_MESSAGE_NORMAL: | |
377 type = "normal"; | |
378 break; | |
379 case JABBER_MESSAGE_CHAT: | |
380 case JABBER_MESSAGE_GROUPCHAT_INVITE: | |
381 type = "chat"; | |
382 break; | |
383 case JABBER_MESSAGE_HEADLINE: | |
384 type = "headline"; | |
385 break; | |
386 case JABBER_MESSAGE_GROUPCHAT: | |
387 type = "groupchat"; | |
388 break; | |
389 case JABBER_MESSAGE_ERROR: | |
390 type = "error"; | |
391 break; | |
392 case JABBER_MESSAGE_OTHER: | |
393 type = NULL; | |
394 break; | |
395 } | |
396 | |
397 if(type) | |
398 xmlnode_set_attrib(message, "type", type); | |
399 | |
400 xmlnode_set_attrib(message, "to", jm->to); | |
401 | |
8400 | 402 if(jm->thread_id) { |
403 child = xmlnode_new_child(message, "thread"); | |
404 xmlnode_insert_data(child, jm->thread_id, -1); | |
405 } | |
406 | |
7971 | 407 if(jm->events || (!jm->body && !jm->xhtml && !jm->subject)) { |
7014 | 408 child = xmlnode_new_child(message, "x"); |
409 xmlnode_set_attrib(child, "xmlns", "jabber:x:event"); | |
410 if(jm->events & JABBER_MESSAGE_EVENT_COMPOSING) | |
411 xmlnode_new_child(child, "composing"); | |
412 } | |
413 | |
414 if(jm->subject) { | |
415 child = xmlnode_new_child(message, "subject"); | |
416 xmlnode_insert_data(child, jm->subject, -1); | |
417 } | |
418 | |
419 if(jm->body) { | |
420 child = xmlnode_new_child(message, "body"); | |
421 xmlnode_insert_data(child, jm->body, -1); | |
422 } | |
423 | |
424 if(jm->xhtml) { | |
425 child = xmlnode_from_str(jm->xhtml, -1); | |
426 if(child) { | |
427 xmlnode_insert_child(message, child); | |
428 } else { | |
429 gaim_debug(GAIM_DEBUG_ERROR, "jabber", | |
430 "XHTML translation/validation failed, returning: %s\n", | |
431 jm->xhtml); | |
432 } | |
433 } | |
434 | |
435 jabber_send(jm->js, message); | |
436 | |
437 xmlnode_free(message); | |
438 } | |
439 | |
440 int jabber_message_send_im(GaimConnection *gc, const char *who, const char *msg, | |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
7095
diff
changeset
|
441 GaimConvImFlags flags) |
7014 | 442 { |
443 JabberMessage *jm; | |
444 JabberBuddy *jb; | |
445 JabberBuddyResource *jbr; | |
446 char *buf; | |
7135 | 447 char *xhtml; |
7306 | 448 char *resource; |
7014 | 449 |
450 if(!who || !msg) | |
451 return 0; | |
452 | |
7306 | 453 resource = jabber_get_resource(who); |
454 | |
7014 | 455 jb = jabber_buddy_find(gc->proto_data, who, TRUE); |
7306 | 456 jbr = jabber_buddy_find_resource(jb, resource); |
457 | |
458 g_free(resource); | |
7014 | 459 |
460 jm = g_new0(JabberMessage, 1); | |
461 jm->js = gc->proto_data; | |
462 jm->type = JABBER_MESSAGE_CHAT; | |
463 jm->events = JABBER_MESSAGE_EVENT_COMPOSING; | |
464 jm->to = g_strdup(who); | |
8400 | 465 if(jbr && jbr->thread_id) |
466 jm->thread_id = jbr->thread_id; | |
7014 | 467 |
7773 | 468 buf = g_strdup_printf("<html xmlns='http://jabber.org/protocol/xhtml-im'><body xmlns='http://www.w3.org/1999/xhtml'>%s</body></html>", msg); |
7014 | 469 |
7135 | 470 gaim_markup_html_to_xhtml(buf, &xhtml, &jm->body); |
7014 | 471 g_free(buf); |
472 | |
473 if(!jbr || jbr->capabilities & JABBER_CAP_XHTML) | |
474 jm->xhtml = xhtml; | |
475 else | |
476 g_free(xhtml); | |
477 | |
478 jabber_message_send(jm); | |
479 jabber_message_free(jm); | |
480 return 1; | |
481 } | |
482 | |
7345 | 483 int jabber_message_send_chat(GaimConnection *gc, int id, const char *msg) |
7014 | 484 { |
485 JabberChat *chat; | |
486 JabberMessage *jm; | |
8042 | 487 JabberStream *js; |
9130 | 488 char *buf; |
7014 | 489 |
8042 | 490 if(!msg || !gc) |
7014 | 491 return 0; |
492 | |
8042 | 493 js = gc->proto_data; |
7014 | 494 chat = jabber_chat_find_by_id(js, id); |
495 | |
8043 | 496 if(!chat) |
497 return 0; | |
498 | |
9130 | 499 jm = g_new0(JabberMessage, 1); |
500 jm->js = gc->proto_data; | |
501 jm->type = JABBER_MESSAGE_GROUPCHAT; | |
502 jm->to = g_strdup_printf("%s@%s", chat->room, chat->server); | |
503 | |
8858 | 504 buf = g_strdup_printf("<html xmlns='http://jabber.org/protocol/xhtml-im'><body xmlns='http://www.w3.org/1999/xhtml'>%s</body></html>", msg); |
9130 | 505 gaim_markup_html_to_xhtml(buf, &jm->xhtml, &jm->body); |
8858 | 506 g_free(buf); |
507 | |
9130 | 508 if(!chat->xhtml) { |
509 g_free(jm->xhtml); | |
510 jm->xhtml = NULL; | |
7923 | 511 } |
512 | |
9130 | 513 jabber_message_send(jm); |
514 jabber_message_free(jm); | |
515 | |
7014 | 516 return 1; |
517 } | |
518 | |
519 int jabber_send_typing(GaimConnection *gc, const char *who, int typing) | |
520 { | |
521 JabberMessage *jm; | |
522 JabberBuddy *jb; | |
523 JabberBuddyResource *jbr; | |
7306 | 524 char *resource = jabber_get_resource(who); |
7014 | 525 |
526 jb = jabber_buddy_find(gc->proto_data, who, TRUE); | |
7306 | 527 jbr = jabber_buddy_find_resource(jb, resource); |
528 | |
529 g_free(resource); | |
7014 | 530 |
7187 | 531 if(!jbr || !(jbr->capabilities & JABBER_CAP_COMPOSING)) |
7014 | 532 return 0; |
533 | |
534 jm = g_new0(JabberMessage, 1); | |
535 jm->js = gc->proto_data; | |
536 jm->type = JABBER_MESSAGE_CHAT; | |
537 jm->to = g_strdup(who); | |
538 | |
539 if(typing == GAIM_TYPING) | |
540 jm->events = JABBER_MESSAGE_EVENT_COMPOSING; | |
541 | |
542 jabber_message_send(jm); | |
543 jabber_message_free(jm); | |
544 | |
545 return JABBER_TYPING_NOTIFY_INT; | |
546 } | |
547 |