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_IS_PROTOCOL_IM(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
, 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
, 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_IS_PROTOCOL_ATTENTION(protocol
)) {
299 GList
*attention_types
;
301 attention_types
= purple_protocol_attention_get_types(
302 PURPLE_PROTOCOL_ATTENTION(protocol
), account
);
303 attn
= (PurpleAttentionType
*)g_list_nth_data(attention_types
, type_code
);
313 * Move a buddy from one group to another on server.
315 * Note: For now we'll not deal with changing gc's at the same time, but
316 * it should be possible. Probably needs to be done, someday. Although,
317 * the UI for that would be difficult, because groups are Purple-wide.
319 void purple_serv_move_buddy(PurpleBuddy
*buddy
, PurpleGroup
*orig
, PurpleGroup
*dest
)
321 PurpleAccount
*account
;
322 PurpleConnection
*gc
;
323 PurpleProtocol
*protocol
;
325 g_return_if_fail(buddy
!= NULL
);
326 g_return_if_fail(orig
!= NULL
);
327 g_return_if_fail(dest
!= NULL
);
329 account
= purple_buddy_get_account(buddy
);
330 gc
= purple_account_get_connection(account
);
333 protocol
= purple_connection_get_protocol(gc
);
334 purple_protocol_server_iface_group_buddy(protocol
, gc
, purple_buddy_get_name(buddy
),
335 purple_group_get_name(orig
),
336 purple_group_get_name(dest
));
340 void purple_serv_add_permit(PurpleConnection
*gc
, const char *name
)
342 PurpleProtocol
*protocol
;
345 protocol
= purple_connection_get_protocol(gc
);
346 purple_protocol_privacy_iface_add_permit(protocol
, gc
, name
);
350 void purple_serv_add_deny(PurpleConnection
*gc
, const char *name
)
352 PurpleProtocol
*protocol
;
355 protocol
= purple_connection_get_protocol(gc
);
356 purple_protocol_privacy_iface_add_deny(protocol
, gc
, name
);
360 void purple_serv_rem_permit(PurpleConnection
*gc
, const char *name
)
362 PurpleProtocol
*protocol
;
365 protocol
= purple_connection_get_protocol(gc
);
366 purple_protocol_privacy_iface_rem_permit(protocol
, gc
, name
);
370 void purple_serv_rem_deny(PurpleConnection
*gc
, const char *name
)
372 PurpleProtocol
*protocol
;
375 protocol
= purple_connection_get_protocol(gc
);
376 purple_protocol_privacy_iface_rem_deny(protocol
, gc
, name
);
380 void purple_serv_set_permit_deny(PurpleConnection
*gc
)
382 PurpleProtocol
*protocol
;
385 protocol
= purple_connection_get_protocol(gc
);
388 * this is called when either you import a buddy list, and make lots
389 * of changes that way, or when the user toggles the permit/deny mode
390 * in the prefs. In either case you should probably be resetting and
391 * resending the permit/deny info when you get this.
393 purple_protocol_privacy_iface_set_permit_deny(protocol
, gc
);
397 void purple_serv_join_chat(PurpleConnection
*gc
, GHashTable
*data
)
399 PurpleProtocol
*protocol
;
402 protocol
= purple_connection_get_protocol(gc
);
403 purple_protocol_chat_iface_join(protocol
, gc
, data
);
408 void purple_serv_reject_chat(PurpleConnection
*gc
, GHashTable
*data
)
410 PurpleProtocol
*protocol
;
413 protocol
= purple_connection_get_protocol(gc
);
414 purple_protocol_chat_iface_reject(protocol
, gc
, data
);
418 void purple_serv_chat_invite(PurpleConnection
*gc
, int id
, const char *message
, const char *name
)
420 PurpleProtocol
*protocol
= NULL
;
421 PurpleChatConversation
*chat
;
424 chat
= purple_conversations_find_chat(gc
, id
);
430 protocol
= purple_connection_get_protocol(gc
);
432 buffy
= message
&& *message
? g_strdup(message
) : NULL
;
433 purple_signal_emit(purple_conversations_get_handle(), "chat-inviting-user",
437 purple_protocol_chat_iface_invite(protocol
, gc
, id
, buffy
, name
);
439 purple_signal_emit(purple_conversations_get_handle(), "chat-invited-user",
445 /* Ya know, nothing uses this except purple_chat_conversation_finalize(),
446 * I think I'll just merge it into that later...
447 * Then again, something might want to use this, from outside protocol-land
448 * to leave a chat without destroying the conversation.
450 void purple_serv_chat_leave(PurpleConnection
*gc
, int id
)
452 PurpleProtocol
*protocol
;
454 protocol
= purple_connection_get_protocol(gc
);
455 purple_protocol_chat_iface_leave(protocol
, gc
, id
);
458 int purple_serv_chat_send(PurpleConnection
*gc
, int id
, PurpleMessage
*msg
)
460 PurpleProtocol
*protocol
;
461 protocol
= purple_connection_get_protocol(gc
);
463 g_return_val_if_fail(msg
!= NULL
, -EINVAL
);
465 if (PURPLE_PROTOCOL_IMPLEMENTS(protocol
, CHAT
, send
))
466 return purple_protocol_chat_iface_send(protocol
, gc
, id
, msg
);
472 * woo. i'm actually going to comment this function. isn't that fun. make
473 * sure to follow along, kids
475 void purple_serv_got_im(PurpleConnection
*gc
, const char *who
, const char *msg
,
476 PurpleMessageFlags flags
, time_t mtime
)
478 PurpleAccount
*account
;
479 PurpleIMConversation
*im
;
480 char *message
, *name
;
485 g_return_if_fail(msg
!= NULL
);
487 account
= purple_connection_get_account(gc
);
490 purple_debug_error("server",
491 "purple_serv_got_im ignoring negative timestamp\n");
492 /* TODO: Would be more appropriate to use a value that indicates
493 that the timestamp is unknown, and surface that in the UI. */
498 * XXX: Should we be setting this here, or relying on protocols to set it?
500 flags
|= PURPLE_MESSAGE_RECV
;
502 if (!purple_account_privacy_check(account
, who
)) {
503 purple_signal_emit(purple_conversations_get_handle(), "blocked-im-msg",
504 account
, who
, msg
, flags
, (unsigned int)mtime
);
509 * We should update the conversation window buttons and menu,
512 im
= purple_conversations_find_im_with_account(who
, purple_connection_get_account(gc
));
515 * Make copies of the message and the sender in case plugins want
516 * to free these strings and replace them with a modifed version.
518 buffy
= g_strdup(msg
);
519 angel
= g_strdup(who
);
521 plugin_return
= GPOINTER_TO_INT(
522 purple_signal_emit_return_1(purple_conversations_get_handle(),
523 "receiving-im-msg", purple_connection_get_account(gc
),
524 &angel
, &buffy
, im
, &flags
));
526 if (!buffy
|| !angel
|| plugin_return
) {
535 purple_signal_emit(purple_conversations_get_handle(), "received-im-msg", purple_connection_get_account(gc
),
536 name
, message
, im
, flags
);
538 /* search for conversation again in case it was created by received-im-msg handler */
540 im
= purple_conversations_find_im_with_account(name
, purple_connection_get_account(gc
));
543 im
= purple_im_conversation_new(account
, name
);
545 pmsg
= purple_message_new_incoming(name
, message
, flags
, mtime
);
546 purple_conversation_write_message(PURPLE_CONVERSATION(im
), pmsg
);
550 * Don't autorespond if:
552 * - it's not supported on this connection
555 * - or we're not idle and the 'only auto respond if idle' pref
558 if (purple_connection_get_flags(gc
) & PURPLE_CONNECTION_FLAG_AUTO_RESP
)
560 PurplePresence
*presence
;
561 PurpleStatus
*status
;
562 PurpleStatusType
*status_type
;
563 PurpleStatusPrimitive primitive
;
564 const gchar
*auto_reply_pref
;
565 const char *away_msg
= NULL
;
566 gboolean mobile
= FALSE
;
568 auto_reply_pref
= purple_prefs_get_string("/purple/away/auto_reply");
570 presence
= purple_account_get_presence(account
);
571 status
= purple_presence_get_active_status(presence
);
572 status_type
= purple_status_get_status_type(status
);
573 primitive
= purple_status_type_get_primitive(status_type
);
574 mobile
= purple_presence_is_status_primitive_active(presence
, PURPLE_STATUS_MOBILE
);
575 if ((primitive
== PURPLE_STATUS_AVAILABLE
) ||
576 (primitive
== PURPLE_STATUS_INVISIBLE
) ||
578 purple_strequal(auto_reply_pref
, "never") ||
579 (!purple_presence_is_idle(presence
) && purple_strequal(auto_reply_pref
, "awayidle")))
585 away_msg
= g_value_get_string(
586 purple_status_get_attr_value(status
, "message"));
588 if ((away_msg
!= NULL
) && (*away_msg
!= '\0')) {
589 struct last_auto_response
*lar
;
590 time_t now
= time(NULL
);
593 * This used to be based on the conversation window. But um, if
594 * you went away, and someone sent you a message and got your
595 * auto-response, and then you closed the window, and then they
596 * sent you another one, they'd get the auto-response back too
597 * soon. Besides that, we need to keep track of this even if we've
598 * got a queue. So the rest of this block is just the auto-response,
601 lar
= get_last_auto_response(gc
, name
);
602 if ((now
- lar
->sent
) >= SECS_BEFORE_RESENDING_AUTORESPONSE
)
605 * We don't want to send an autoresponse in response to the other user's
606 * autoresponse. We do, however, not want to then send one in response to the
607 * _next_ message, so we still set lar->sent to now.
611 if (!(flags
& PURPLE_MESSAGE_AUTO_RESP
))
615 msg
= purple_message_new_outgoing(name
,
616 away_msg
, PURPLE_MESSAGE_AUTO_RESP
);
618 purple_serv_send_im(gc
, msg
);
619 purple_conversation_write_message(PURPLE_CONVERSATION(im
), msg
);
628 void purple_serv_got_typing(PurpleConnection
*gc
, const char *name
, int timeout
,
629 PurpleIMTypingState state
) {
630 PurpleIMConversation
*im
;
632 im
= purple_conversations_find_im_with_account(name
, purple_connection_get_account(gc
));
634 purple_im_conversation_set_typing_state(im
, state
);
638 case PURPLE_IM_TYPING
:
639 purple_signal_emit(purple_conversations_get_handle(),
640 "buddy-typing", purple_connection_get_account(gc
), name
);
642 case PURPLE_IM_TYPED
:
643 purple_signal_emit(purple_conversations_get_handle(),
644 "buddy-typed", purple_connection_get_account(gc
), name
);
646 case PURPLE_IM_NOT_TYPING
:
647 purple_signal_emit(purple_conversations_get_handle(),
648 "buddy-typing-stopped", purple_connection_get_account(gc
), name
);
653 if (im
!= NULL
&& timeout
> 0)
654 purple_im_conversation_start_typing_timeout(im
, timeout
);
657 void purple_serv_got_typing_stopped(PurpleConnection
*gc
, const char *name
) {
659 PurpleIMConversation
*im
;
661 im
= purple_conversations_find_im_with_account(name
, purple_connection_get_account(gc
));
664 if (purple_im_conversation_get_typing_state(im
) == PURPLE_IM_NOT_TYPING
)
667 purple_im_conversation_stop_typing_timeout(im
);
668 purple_im_conversation_set_typing_state(im
, PURPLE_IM_NOT_TYPING
);
672 purple_signal_emit(purple_conversations_get_handle(),
673 "buddy-typing-stopped", purple_connection_get_account(gc
), name
);
677 struct chat_invite_data
{
678 PurpleConnection
*gc
;
679 GHashTable
*components
;
682 static void chat_invite_data_free(struct chat_invite_data
*cid
)
685 g_hash_table_destroy(cid
->components
);
690 static void chat_invite_reject(struct chat_invite_data
*cid
)
692 purple_serv_reject_chat(cid
->gc
, cid
->components
);
693 chat_invite_data_free(cid
);
697 static void chat_invite_accept(struct chat_invite_data
*cid
)
699 purple_serv_join_chat(cid
->gc
, cid
->components
);
700 chat_invite_data_free(cid
);
705 void purple_serv_got_chat_invite(PurpleConnection
*gc
, const char *name
,
706 const char *who
, const char *message
, GHashTable
*data
)
708 PurpleAccount
*account
;
709 struct chat_invite_data
*cid
;
712 g_return_if_fail(name
!= NULL
);
713 g_return_if_fail(who
!= NULL
);
715 account
= purple_connection_get_account(gc
);
716 if (!purple_account_privacy_check(account
, who
)) {
717 purple_signal_emit(purple_conversations_get_handle(), "chat-invite-blocked",
718 account
, who
, name
, message
, data
);
722 cid
= g_new0(struct chat_invite_data
, 1);
724 plugin_return
= GPOINTER_TO_INT(purple_signal_emit_return_1(
725 purple_conversations_get_handle(),
726 "chat-invited", account
, who
, name
, message
, data
));
729 cid
->components
= data
;
731 if (plugin_return
== 0)
737 buf2
= g_strdup_printf(
738 _("%s has invited %s to the chat room %s:\n%s"),
739 who
, purple_account_get_username(account
), name
, message
);
742 buf2
= g_strdup_printf(
743 _("%s has invited %s to the chat room %s\n"),
744 who
, purple_account_get_username(account
), name
);
747 purple_request_accept_cancel(gc
, NULL
,
748 _("Accept chat invitation?"), buf2
,
749 PURPLE_DEFAULT_ACTION_NONE
,
750 purple_request_cpar_from_connection(gc
), cid
,
751 G_CALLBACK(chat_invite_accept
),
752 G_CALLBACK(chat_invite_reject
));
755 else if (plugin_return
> 0)
756 chat_invite_accept(cid
);
758 chat_invite_reject(cid
);
761 PurpleChatConversation
*purple_serv_got_joined_chat(PurpleConnection
*gc
,
762 int id
, const char *name
)
764 PurpleChatConversation
*chat
;
765 PurpleAccount
*account
;
767 account
= purple_connection_get_account(gc
);
769 g_return_val_if_fail(account
!= NULL
, NULL
);
770 g_return_val_if_fail(name
!= NULL
, NULL
);
772 chat
= purple_chat_conversation_new(account
, name
);
773 g_return_val_if_fail(chat
!= NULL
, NULL
);
775 if (!g_slist_find(purple_connection_get_active_chats(gc
), chat
))
776 _purple_connection_add_active_chat(gc
, chat
);
778 purple_chat_conversation_set_id(chat
, id
);
780 purple_signal_emit(purple_conversations_get_handle(), "chat-joined", chat
);
785 void purple_serv_got_chat_left(PurpleConnection
*g
, int id
)
788 PurpleChatConversation
*chat
= NULL
;
790 for (bcs
= purple_connection_get_active_chats(g
); bcs
!= NULL
; bcs
= bcs
->next
) {
791 if (purple_chat_conversation_get_id(
792 PURPLE_CHAT_CONVERSATION(bcs
->data
)) == id
) {
793 chat
= (PurpleChatConversation
*)bcs
->data
;
801 purple_debug(PURPLE_DEBUG_INFO
, "server", "Leaving room: %s\n",
802 purple_conversation_get_name(PURPLE_CONVERSATION(chat
)));
804 _purple_connection_remove_active_chat(g
, chat
);
806 purple_chat_conversation_leave(chat
);
808 purple_signal_emit(purple_conversations_get_handle(), "chat-left", chat
);
811 void purple_serv_got_join_chat_failed(PurpleConnection
*gc
, GHashTable
*data
)
813 purple_signal_emit(purple_conversations_get_handle(), "chat-join-failed",
817 void purple_serv_got_chat_in(PurpleConnection
*g
, int id
, const char *who
,
818 PurpleMessageFlags flags
, const char *message
, time_t mtime
)
821 PurpleChatConversation
*chat
= NULL
;
826 g_return_if_fail(who
!= NULL
);
827 g_return_if_fail(message
!= NULL
);
830 purple_debug_error("server",
831 "purple_serv_got_chat_in ignoring negative timestamp\n");
832 /* TODO: Would be more appropriate to use a value that indicates
833 that the timestamp is unknown, and surface that in the UI. */
837 for (bcs
= purple_connection_get_active_chats(g
); bcs
!= NULL
; bcs
= bcs
->next
) {
838 if (purple_chat_conversation_get_id(
839 PURPLE_CHAT_CONVERSATION(bcs
->data
)) == id
) {
840 chat
= (PurpleChatConversation
*)bcs
->data
;
848 /* Did I send the message? */
849 if (purple_strequal(purple_chat_conversation_get_nick(chat
),
850 purple_normalize(purple_conversation_get_account(
851 PURPLE_CONVERSATION(chat
)), who
))) {
852 flags
|= PURPLE_MESSAGE_SEND
;
853 flags
&= ~PURPLE_MESSAGE_RECV
; /* Just in case some protocol sets it! */
855 flags
|= PURPLE_MESSAGE_RECV
;
859 * Make copies of the message and the sender in case plugins want
860 * to free these strings and replace them with a modifed version.
862 buffy
= g_strdup(message
);
863 angel
= g_strdup(who
);
865 plugin_return
= GPOINTER_TO_INT(
866 purple_signal_emit_return_1(purple_conversations_get_handle(),
867 "receiving-chat-msg", purple_connection_get_account(g
),
868 &angel
, &buffy
, chat
, &flags
));
870 if (!buffy
|| !angel
|| plugin_return
) {
879 purple_signal_emit(purple_conversations_get_handle(), "received-chat-msg", purple_connection_get_account(g
),
880 who
, message
, chat
, flags
);
882 if (flags
& PURPLE_MESSAGE_RECV
)
883 pmsg
= purple_message_new_incoming(who
, message
, flags
, mtime
);
885 pmsg
= purple_message_new_outgoing(who
, message
, flags
);
886 purple_message_set_time(pmsg
, mtime
);
888 purple_conversation_write_message(PURPLE_CONVERSATION(chat
), pmsg
);
894 void purple_serv_send_file(PurpleConnection
*gc
, const char *who
, const char *file
)
896 PurpleProtocol
*protocol
;
899 protocol
= purple_connection_get_protocol(gc
);
901 if(PURPLE_IS_PROTOCOL_XFER(protocol
)) {
902 PurpleProtocolXfer
*xfer
= PURPLE_PROTOCOL_XFER(protocol
);
904 if(purple_protocol_xfer_can_receive(xfer
, gc
, who
)) {
905 purple_protocol_xfer_send_file(xfer
,