4 * Purple is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
24 /* This file is the fullcrap */
27 #include "buddylist.h"
28 #include "conversation.h"
40 #define SECS_BEFORE_RESENDING_AUTORESPONSE 600
41 #define SEX_BEFORE_RESENDING_AUTORESPONSE "Only after you're married"
44 purple_serv_send_typing(PurpleConnection
*gc
, const char *name
, PurpleIMTypingState state
)
46 PurpleProtocol
*protocol
;
49 protocol
= purple_connection_get_protocol(gc
);
50 return purple_protocol_im_iface_send_typing(protocol
, gc
, name
, state
);
56 static GSList
*last_auto_responses
= NULL
;
57 struct last_auto_response
{
64 expire_last_auto_responses(gpointer data
)
67 struct last_auto_response
*lar
;
69 tmp
= last_auto_responses
;
74 lar
= (struct last_auto_response
*)cur
->data
;
76 if ((time(NULL
) - lar
->sent
) > SECS_BEFORE_RESENDING_AUTORESPONSE
) {
77 last_auto_responses
= g_slist_remove(last_auto_responses
, lar
);
82 return FALSE
; /* do not run again */
85 static struct last_auto_response
*
86 get_last_auto_response(PurpleConnection
*gc
, const char *name
)
89 struct last_auto_response
*lar
;
91 /* because we're modifying or creating a lar, schedule the
92 * function to expire them as the pref dictates */
93 g_timeout_add_seconds((SECS_BEFORE_RESENDING_AUTORESPONSE
+ 1), expire_last_auto_responses
, NULL
);
95 tmp
= last_auto_responses
;
98 lar
= (struct last_auto_response
*)tmp
->data
;
100 if (gc
== lar
->gc
&& !strncmp(name
, lar
->name
, sizeof(lar
->name
)))
106 lar
= g_new0(struct last_auto_response
, 1);
107 g_snprintf(lar
->name
, sizeof(lar
->name
), "%s", name
);
110 last_auto_responses
= g_slist_prepend(last_auto_responses
, lar
);
115 int purple_serv_send_im(PurpleConnection
*gc
, PurpleMessage
*msg
)
117 PurpleIMConversation
*im
= NULL
;
118 PurpleAccount
*account
= NULL
;
119 PurplePresence
*presence
= NULL
;
120 PurpleProtocol
*protocol
= NULL
;
122 const gchar
*auto_reply_pref
= NULL
;
123 const gchar
*recipient
;
125 g_return_val_if_fail(gc
!= NULL
, val
);
126 g_return_val_if_fail(msg
!= NULL
, val
);
128 protocol
= purple_connection_get_protocol(gc
);
130 g_return_val_if_fail(protocol
!= NULL
, val
);
131 g_return_val_if_fail(PURPLE_PROTOCOL_HAS_IM_IFACE(protocol
), val
);
133 account
= purple_connection_get_account(gc
);
134 presence
= purple_account_get_presence(account
);
135 recipient
= purple_message_get_recipient(msg
);
137 im
= purple_conversations_find_im_with_account(recipient
, account
);
139 if (PURPLE_PROTOCOL_IMPLEMENTS(protocol
, IM_IFACE
, send
))
140 val
= purple_protocol_im_iface_send(protocol
, gc
, msg
);
143 * XXX - If "only auto-reply when away & idle" is set, then shouldn't
144 * this only reset lar->sent if we're away AND idle?
146 auto_reply_pref
= purple_prefs_get_string("/purple/away/auto_reply");
147 if((purple_connection_get_flags(gc
) & PURPLE_CONNECTION_FLAG_AUTO_RESP
) &&
148 !purple_presence_is_available(presence
) &&
149 !purple_strequal(auto_reply_pref
, "never")) {
151 struct last_auto_response
*lar
;
152 lar
= get_last_auto_response(gc
, recipient
);
153 lar
->sent
= time(NULL
);
156 if(im
&& purple_im_conversation_get_send_typed_timeout(im
))
157 purple_im_conversation_stop_send_typed_timeout(im
);
162 void purple_serv_get_info(PurpleConnection
*gc
, const char *name
)
164 PurpleProtocol
*protocol
;
167 protocol
= purple_connection_get_protocol(gc
);
168 purple_protocol_server_iface_get_info(protocol
, gc
, name
);
172 void purple_serv_set_info(PurpleConnection
*gc
, const char *info
)
174 PurpleProtocol
*protocol
;
175 PurpleAccount
*account
;
178 protocol
= purple_connection_get_protocol(gc
);
180 if (PURPLE_PROTOCOL_IMPLEMENTS(protocol
, SERVER_IFACE
, set_info
)) {
181 account
= purple_connection_get_account(gc
);
183 purple_signal_emit(purple_accounts_get_handle(),
184 "account-setting-info", account
, info
);
186 purple_protocol_server_iface_set_info(protocol
, gc
, info
);
188 purple_signal_emit(purple_accounts_get_handle(),
189 "account-set-info", account
, info
);
195 * Set buddy's alias on server roster/list
197 void purple_serv_alias_buddy(PurpleBuddy
*b
)
199 PurpleAccount
*account
;
200 PurpleConnection
*gc
;
201 PurpleProtocol
*protocol
;
204 account
= purple_buddy_get_account(b
);
207 gc
= purple_account_get_connection(account
);
210 protocol
= purple_connection_get_protocol(gc
);
211 purple_protocol_server_iface_alias_buddy(protocol
, gc
,
212 purple_buddy_get_name(b
),
213 purple_buddy_get_local_alias(b
));
220 purple_serv_got_alias(PurpleConnection
*gc
, const char *who
, const char *alias
)
222 PurpleAccount
*account
;
225 PurpleIMConversation
*im
;
227 account
= purple_connection_get_account(gc
);
228 buddies
= purple_blist_find_buddies(account
, who
);
230 while (buddies
!= NULL
)
232 const char *server_alias
;
235 buddies
= g_slist_delete_link(buddies
, buddies
);
237 server_alias
= purple_buddy_get_server_alias(b
);
239 if (purple_strequal(server_alias
, alias
))
242 purple_buddy_set_server_alias(b
, alias
);
244 im
= purple_conversations_find_im_with_account(purple_buddy_get_name(b
), account
);
245 if (im
!= NULL
&& alias
!= NULL
&& !purple_strequal(alias
, who
))
247 char *escaped
= g_markup_escape_text(who
, -1);
248 char *escaped2
= g_markup_escape_text(alias
, -1);
249 char *tmp
= g_strdup_printf(_("%s is now known as %s.\n"),
252 purple_conversation_write_system_message(
253 PURPLE_CONVERSATION(im
), tmp
,
254 PURPLE_MESSAGE_NO_LINKIFY
);
264 purple_serv_got_private_alias(PurpleConnection
*gc
, const char *who
, const char *alias
)
266 PurpleAccount
*account
= NULL
;
267 GSList
*buddies
= NULL
;
268 PurpleBuddy
*b
= NULL
;
270 account
= purple_connection_get_account(gc
);
271 buddies
= purple_blist_find_buddies(account
, who
);
273 while(buddies
!= NULL
) {
277 buddies
= g_slist_delete_link(buddies
, buddies
);
279 balias
= purple_buddy_get_local_alias(b
);
280 if (purple_strequal(balias
, alias
))
283 purple_buddy_set_local_alias(b
, alias
);
288 PurpleAttentionType
*purple_get_attention_type_from_code(PurpleAccount
*account
, guint type_code
)
290 PurpleProtocol
*protocol
;
291 PurpleAttentionType
* attn
;
293 g_return_val_if_fail(account
!= NULL
, NULL
);
295 protocol
= purple_protocols_find(purple_account_get_protocol_id(account
));
297 /* Lookup the attention type in the protocol's attention_types list, if any. */
298 if (PURPLE_PROTOCOL_IMPLEMENTS(protocol
, ATTENTION_IFACE
, get_types
)) {
299 GList
*attention_types
;
301 attention_types
= purple_protocol_attention_iface_get_types(protocol
, account
);
302 attn
= (PurpleAttentionType
*)g_list_nth_data(attention_types
, type_code
);
312 * Move a buddy from one group to another on server.
314 * Note: For now we'll not deal with changing gc's at the same time, but
315 * it should be possible. Probably needs to be done, someday. Although,
316 * the UI for that would be difficult, because groups are Purple-wide.
318 void purple_serv_move_buddy(PurpleBuddy
*buddy
, PurpleGroup
*orig
, PurpleGroup
*dest
)
320 PurpleAccount
*account
;
321 PurpleConnection
*gc
;
322 PurpleProtocol
*protocol
;
324 g_return_if_fail(buddy
!= NULL
);
325 g_return_if_fail(orig
!= NULL
);
326 g_return_if_fail(dest
!= NULL
);
328 account
= purple_buddy_get_account(buddy
);
329 gc
= purple_account_get_connection(account
);
332 protocol
= purple_connection_get_protocol(gc
);
333 purple_protocol_server_iface_group_buddy(protocol
, gc
, purple_buddy_get_name(buddy
),
334 purple_group_get_name(orig
),
335 purple_group_get_name(dest
));
339 void purple_serv_add_permit(PurpleConnection
*gc
, const char *name
)
341 PurpleProtocol
*protocol
;
344 protocol
= purple_connection_get_protocol(gc
);
345 purple_protocol_privacy_iface_add_permit(protocol
, gc
, name
);
349 void purple_serv_add_deny(PurpleConnection
*gc
, const char *name
)
351 PurpleProtocol
*protocol
;
354 protocol
= purple_connection_get_protocol(gc
);
355 purple_protocol_privacy_iface_add_deny(protocol
, gc
, name
);
359 void purple_serv_rem_permit(PurpleConnection
*gc
, const char *name
)
361 PurpleProtocol
*protocol
;
364 protocol
= purple_connection_get_protocol(gc
);
365 purple_protocol_privacy_iface_rem_permit(protocol
, gc
, name
);
369 void purple_serv_rem_deny(PurpleConnection
*gc
, const char *name
)
371 PurpleProtocol
*protocol
;
374 protocol
= purple_connection_get_protocol(gc
);
375 purple_protocol_privacy_iface_rem_deny(protocol
, gc
, name
);
379 void purple_serv_set_permit_deny(PurpleConnection
*gc
)
381 PurpleProtocol
*protocol
;
384 protocol
= purple_connection_get_protocol(gc
);
387 * this is called when either you import a buddy list, and make lots
388 * of changes that way, or when the user toggles the permit/deny mode
389 * in the prefs. In either case you should probably be resetting and
390 * resending the permit/deny info when you get this.
392 purple_protocol_privacy_iface_set_permit_deny(protocol
, gc
);
396 void purple_serv_join_chat(PurpleConnection
*gc
, GHashTable
*data
)
398 PurpleProtocol
*protocol
;
401 protocol
= purple_connection_get_protocol(gc
);
402 purple_protocol_chat_iface_join(protocol
, gc
, data
);
407 void purple_serv_reject_chat(PurpleConnection
*gc
, GHashTable
*data
)
409 PurpleProtocol
*protocol
;
412 protocol
= purple_connection_get_protocol(gc
);
413 purple_protocol_chat_iface_reject(protocol
, gc
, data
);
417 void purple_serv_chat_invite(PurpleConnection
*gc
, int id
, const char *message
, const char *name
)
419 PurpleProtocol
*protocol
= NULL
;
420 PurpleChatConversation
*chat
;
421 char *buffy
= message
&& *message
? g_strdup(message
) : NULL
;
423 chat
= purple_conversations_find_chat(gc
, id
);
429 protocol
= purple_connection_get_protocol(gc
);
431 purple_signal_emit(purple_conversations_get_handle(), "chat-inviting-user",
435 purple_protocol_chat_iface_invite(protocol
, gc
, id
, buffy
, name
);
437 purple_signal_emit(purple_conversations_get_handle(), "chat-invited-user",
443 /* Ya know, nothing uses this except purple_chat_conversation_finalize(),
444 * I think I'll just merge it into that later...
445 * Then again, something might want to use this, from outside protocol-land
446 * to leave a chat without destroying the conversation.
448 void purple_serv_chat_leave(PurpleConnection
*gc
, int id
)
450 PurpleProtocol
*protocol
;
452 protocol
= purple_connection_get_protocol(gc
);
453 purple_protocol_chat_iface_leave(protocol
, gc
, id
);
456 int purple_serv_chat_send(PurpleConnection
*gc
, int id
, PurpleMessage
*msg
)
458 PurpleProtocol
*protocol
;
459 protocol
= purple_connection_get_protocol(gc
);
461 g_return_val_if_fail(msg
!= NULL
, -EINVAL
);
463 if (PURPLE_PROTOCOL_IMPLEMENTS(protocol
, CHAT_IFACE
, send
))
464 return purple_protocol_chat_iface_send(protocol
, gc
, id
, msg
);
470 * woo. i'm actually going to comment this function. isn't that fun. make
471 * sure to follow along, kids
473 void purple_serv_got_im(PurpleConnection
*gc
, const char *who
, const char *msg
,
474 PurpleMessageFlags flags
, time_t mtime
)
476 PurpleAccount
*account
;
477 PurpleIMConversation
*im
;
478 char *message
, *name
;
483 g_return_if_fail(msg
!= NULL
);
485 account
= purple_connection_get_account(gc
);
488 purple_debug_error("server",
489 "purple_serv_got_im ignoring negative timestamp\n");
490 /* TODO: Would be more appropriate to use a value that indicates
491 that the timestamp is unknown, and surface that in the UI. */
496 * XXX: Should we be setting this here, or relying on protocols to set it?
498 flags
|= PURPLE_MESSAGE_RECV
;
500 if (!purple_account_privacy_check(account
, who
)) {
501 purple_signal_emit(purple_conversations_get_handle(), "blocked-im-msg",
502 account
, who
, msg
, flags
, (unsigned int)mtime
);
507 * We should update the conversation window buttons and menu,
510 im
= purple_conversations_find_im_with_account(who
, purple_connection_get_account(gc
));
513 * Make copies of the message and the sender in case plugins want
514 * to free these strings and replace them with a modifed version.
516 buffy
= g_strdup(msg
);
517 angel
= g_strdup(who
);
519 plugin_return
= GPOINTER_TO_INT(
520 purple_signal_emit_return_1(purple_conversations_get_handle(),
521 "receiving-im-msg", purple_connection_get_account(gc
),
522 &angel
, &buffy
, im
, &flags
));
524 if (!buffy
|| !angel
|| plugin_return
) {
533 purple_signal_emit(purple_conversations_get_handle(), "received-im-msg", purple_connection_get_account(gc
),
534 name
, message
, im
, flags
);
536 /* search for conversation again in case it was created by received-im-msg handler */
538 im
= purple_conversations_find_im_with_account(name
, purple_connection_get_account(gc
));
541 im
= purple_im_conversation_new(account
, name
);
543 pmsg
= purple_message_new_incoming(name
, message
, flags
, mtime
);
544 purple_conversation_write_message(PURPLE_CONVERSATION(im
), pmsg
);
548 * Don't autorespond if:
550 * - it's not supported on this connection
553 * - or we're not idle and the 'only auto respond if idle' pref
556 if (purple_connection_get_flags(gc
) & PURPLE_CONNECTION_FLAG_AUTO_RESP
)
558 PurplePresence
*presence
;
559 PurpleStatus
*status
;
560 PurpleStatusType
*status_type
;
561 PurpleStatusPrimitive primitive
;
562 const gchar
*auto_reply_pref
;
563 const char *away_msg
= NULL
;
564 gboolean mobile
= FALSE
;
566 auto_reply_pref
= purple_prefs_get_string("/purple/away/auto_reply");
568 presence
= purple_account_get_presence(account
);
569 status
= purple_presence_get_active_status(presence
);
570 status_type
= purple_status_get_status_type(status
);
571 primitive
= purple_status_type_get_primitive(status_type
);
572 mobile
= purple_presence_is_status_primitive_active(presence
, PURPLE_STATUS_MOBILE
);
573 if ((primitive
== PURPLE_STATUS_AVAILABLE
) ||
574 (primitive
== PURPLE_STATUS_INVISIBLE
) ||
576 purple_strequal(auto_reply_pref
, "never") ||
577 (!purple_presence_is_idle(presence
) && purple_strequal(auto_reply_pref
, "awayidle")))
583 away_msg
= g_value_get_string(
584 purple_status_get_attr_value(status
, "message"));
586 if ((away_msg
!= NULL
) && (*away_msg
!= '\0')) {
587 struct last_auto_response
*lar
;
588 time_t now
= time(NULL
);
591 * This used to be based on the conversation window. But um, if
592 * you went away, and someone sent you a message and got your
593 * auto-response, and then you closed the window, and then they
594 * sent you another one, they'd get the auto-response back too
595 * soon. Besides that, we need to keep track of this even if we've
596 * got a queue. So the rest of this block is just the auto-response,
599 lar
= get_last_auto_response(gc
, name
);
600 if ((now
- lar
->sent
) >= SECS_BEFORE_RESENDING_AUTORESPONSE
)
603 * We don't want to send an autoresponse in response to the other user's
604 * autoresponse. We do, however, not want to then send one in response to the
605 * _next_ message, so we still set lar->sent to now.
609 if (!(flags
& PURPLE_MESSAGE_AUTO_RESP
))
613 msg
= purple_message_new_outgoing(name
,
614 away_msg
, PURPLE_MESSAGE_AUTO_RESP
);
616 purple_serv_send_im(gc
, msg
);
617 purple_conversation_write_message(PURPLE_CONVERSATION(im
), msg
);
626 void purple_serv_got_typing(PurpleConnection
*gc
, const char *name
, int timeout
,
627 PurpleIMTypingState state
) {
628 PurpleIMConversation
*im
;
630 im
= purple_conversations_find_im_with_account(name
, purple_connection_get_account(gc
));
632 purple_im_conversation_set_typing_state(im
, state
);
636 case PURPLE_IM_TYPING
:
637 purple_signal_emit(purple_conversations_get_handle(),
638 "buddy-typing", purple_connection_get_account(gc
), name
);
640 case PURPLE_IM_TYPED
:
641 purple_signal_emit(purple_conversations_get_handle(),
642 "buddy-typed", purple_connection_get_account(gc
), name
);
644 case PURPLE_IM_NOT_TYPING
:
645 purple_signal_emit(purple_conversations_get_handle(),
646 "buddy-typing-stopped", purple_connection_get_account(gc
), name
);
651 if (im
!= NULL
&& timeout
> 0)
652 purple_im_conversation_start_typing_timeout(im
, timeout
);
655 void purple_serv_got_typing_stopped(PurpleConnection
*gc
, const char *name
) {
657 PurpleIMConversation
*im
;
659 im
= purple_conversations_find_im_with_account(name
, purple_connection_get_account(gc
));
662 if (purple_im_conversation_get_typing_state(im
) == PURPLE_IM_NOT_TYPING
)
665 purple_im_conversation_stop_typing_timeout(im
);
666 purple_im_conversation_set_typing_state(im
, PURPLE_IM_NOT_TYPING
);
670 purple_signal_emit(purple_conversations_get_handle(),
671 "buddy-typing-stopped", purple_connection_get_account(gc
), name
);
675 struct chat_invite_data
{
676 PurpleConnection
*gc
;
677 GHashTable
*components
;
680 static void chat_invite_data_free(struct chat_invite_data
*cid
)
683 g_hash_table_destroy(cid
->components
);
688 static void chat_invite_reject(struct chat_invite_data
*cid
)
690 purple_serv_reject_chat(cid
->gc
, cid
->components
);
691 chat_invite_data_free(cid
);
695 static void chat_invite_accept(struct chat_invite_data
*cid
)
697 purple_serv_join_chat(cid
->gc
, cid
->components
);
698 chat_invite_data_free(cid
);
703 void purple_serv_got_chat_invite(PurpleConnection
*gc
, const char *name
,
704 const char *who
, const char *message
, GHashTable
*data
)
706 PurpleAccount
*account
;
708 struct chat_invite_data
*cid
;
711 g_return_if_fail(name
!= NULL
);
712 g_return_if_fail(who
!= NULL
);
714 account
= purple_connection_get_account(gc
);
715 if (!purple_account_privacy_check(account
, who
)) {
716 purple_signal_emit(purple_conversations_get_handle(), "chat-invite-blocked",
717 account
, who
, name
, message
, data
);
721 cid
= g_new0(struct chat_invite_data
, 1);
723 plugin_return
= GPOINTER_TO_INT(purple_signal_emit_return_1(
724 purple_conversations_get_handle(),
725 "chat-invited", account
, who
, name
, message
, data
));
728 cid
->components
= data
;
730 if (plugin_return
== 0)
734 g_snprintf(buf2
, sizeof(buf2
),
735 _("%s has invited %s to the chat room %s:\n%s"),
736 who
, purple_account_get_username(account
), name
, message
);
739 g_snprintf(buf2
, sizeof(buf2
),
740 _("%s has invited %s to the chat room %s\n"),
741 who
, purple_account_get_username(account
), name
);
744 purple_request_accept_cancel(gc
, NULL
,
745 _("Accept chat invitation?"), buf2
,
746 PURPLE_DEFAULT_ACTION_NONE
,
747 purple_request_cpar_from_connection(gc
), cid
,
748 G_CALLBACK(chat_invite_accept
),
749 G_CALLBACK(chat_invite_reject
));
751 else if (plugin_return
> 0)
752 chat_invite_accept(cid
);
754 chat_invite_reject(cid
);
757 PurpleChatConversation
*purple_serv_got_joined_chat(PurpleConnection
*gc
,
758 int id
, const char *name
)
760 PurpleChatConversation
*chat
;
761 PurpleAccount
*account
;
763 account
= purple_connection_get_account(gc
);
765 g_return_val_if_fail(account
!= NULL
, NULL
);
766 g_return_val_if_fail(name
!= NULL
, NULL
);
768 chat
= purple_chat_conversation_new(account
, name
);
769 g_return_val_if_fail(chat
!= NULL
, NULL
);
771 if (!g_slist_find(purple_connection_get_active_chats(gc
), chat
))
772 _purple_connection_add_active_chat(gc
, chat
);
774 purple_chat_conversation_set_id(chat
, id
);
776 purple_signal_emit(purple_conversations_get_handle(), "chat-joined", chat
);
781 void purple_serv_got_chat_left(PurpleConnection
*g
, int id
)
784 PurpleChatConversation
*chat
= NULL
;
786 for (bcs
= purple_connection_get_active_chats(g
); bcs
!= NULL
; bcs
= bcs
->next
) {
787 if (purple_chat_conversation_get_id(
788 PURPLE_CHAT_CONVERSATION(bcs
->data
)) == id
) {
789 chat
= (PurpleChatConversation
*)bcs
->data
;
797 purple_debug(PURPLE_DEBUG_INFO
, "server", "Leaving room: %s\n",
798 purple_conversation_get_name(PURPLE_CONVERSATION(chat
)));
800 _purple_connection_remove_active_chat(g
, chat
);
802 purple_chat_conversation_leave(chat
);
804 purple_signal_emit(purple_conversations_get_handle(), "chat-left", chat
);
807 void purple_serv_got_join_chat_failed(PurpleConnection
*gc
, GHashTable
*data
)
809 purple_signal_emit(purple_conversations_get_handle(), "chat-join-failed",
813 void purple_serv_got_chat_in(PurpleConnection
*g
, int id
, const char *who
,
814 PurpleMessageFlags flags
, const char *message
, time_t mtime
)
817 PurpleChatConversation
*chat
= NULL
;
822 g_return_if_fail(who
!= NULL
);
823 g_return_if_fail(message
!= NULL
);
826 purple_debug_error("server",
827 "purple_serv_got_chat_in ignoring negative timestamp\n");
828 /* TODO: Would be more appropriate to use a value that indicates
829 that the timestamp is unknown, and surface that in the UI. */
833 for (bcs
= purple_connection_get_active_chats(g
); bcs
!= NULL
; bcs
= bcs
->next
) {
834 if (purple_chat_conversation_get_id(
835 PURPLE_CHAT_CONVERSATION(bcs
->data
)) == id
) {
836 chat
= (PurpleChatConversation
*)bcs
->data
;
844 /* Did I send the message? */
845 if (purple_strequal(purple_chat_conversation_get_nick(chat
),
846 purple_normalize(purple_conversation_get_account(
847 PURPLE_CONVERSATION(chat
)), who
))) {
848 flags
|= PURPLE_MESSAGE_SEND
;
849 flags
&= ~PURPLE_MESSAGE_RECV
; /* Just in case some protocol sets it! */
851 flags
|= PURPLE_MESSAGE_RECV
;
855 * Make copies of the message and the sender in case plugins want
856 * to free these strings and replace them with a modifed version.
858 buffy
= g_strdup(message
);
859 angel
= g_strdup(who
);
861 plugin_return
= GPOINTER_TO_INT(
862 purple_signal_emit_return_1(purple_conversations_get_handle(),
863 "receiving-chat-msg", purple_connection_get_account(g
),
864 &angel
, &buffy
, chat
, &flags
));
866 if (!buffy
|| !angel
|| plugin_return
) {
875 purple_signal_emit(purple_conversations_get_handle(), "received-chat-msg", purple_connection_get_account(g
),
876 who
, message
, chat
, flags
);
878 if (flags
& PURPLE_MESSAGE_RECV
)
879 pmsg
= purple_message_new_incoming(who
, message
, flags
, mtime
);
881 pmsg
= purple_message_new_outgoing(who
, message
, flags
);
882 purple_message_set_time(pmsg
, mtime
);
884 purple_conversation_write_message(PURPLE_CONVERSATION(chat
), pmsg
);
890 void purple_serv_send_file(PurpleConnection
*gc
, const char *who
, const char *file
)
892 PurpleProtocol
*protocol
;
895 protocol
= purple_connection_get_protocol(gc
);
897 if (!PURPLE_PROTOCOL_IMPLEMENTS(protocol
, XFER_IFACE
, can_receive
) ||
898 purple_protocol_xfer_iface_can_receive(protocol
, gc
, who
))
900 purple_protocol_xfer_iface_send(protocol
, gc
, who
, file
);