Incoming statuses with characters 0x80-0xFF were double-escaped.
[thrasher.git] / thconversations.c
blob831f3660cc6eaa290f165b0bace55ec921e75db9
1 /*
2 * Thrasher Bird - XMPP transport via libpurple
3 * Copyright (C) 2008 Barracuda Networks, Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with Thrasher Bird; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
20 #include <glib.h>
21 #include "thrasher.h"
22 #include "thperl.h"
24 #include <purple.h>
26 #include "thconversations.h"
28 static void
29 thrasher_destroy_conversation(PurpleConversation *conv) {
30 purple_debug_info("thrasher", "destroy conversation\n");
33 PurpleConversation*
34 thrasher_find_conversation_with_account(PurpleAccount* pa,
35 const char* who) {
36 PurpleConversation *conv;
38 /* For testing and the initial build we're recreating a
39 * conversation *every time*
41 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, pa);
43 /* If not, create a new one */
44 if (conv == NULL) {
45 conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, pa, who);
48 return conv;
52 static void
53 thrasher_write_conv(PurpleConversation *conv,
54 const char *who,
55 const char *alias,
56 const char *message,
57 PurpleMessageFlags flags,
58 time_t mtime) {
59 PurpleAccount *account;
60 account = purple_conversation_get_account(conv);
62 /* libpurple throws write_conv on every recv and send */
63 if (! (flags & PURPLE_MESSAGE_RECV))
64 return;
66 purple_debug_info("thrasher",
67 "Incoming message:\n");
69 thrasher_wrapper_incoming_msg(thrasher_account_get_jid(account),
70 who,
71 alias,
72 message,
73 flags);
75 #ifdef TH_DEBUG
76 purple_debug_info("thrasher",
77 "(%s) %s %s: %s\n",
78 purple_conversation_get_name(conv),
79 purple_utf8_strftime("(%H:%M:%S)", localtime(&mtime)),
80 who,
81 message);
82 #endif /* TH_DEBUG */
85 gboolean
86 thrasher_outgoing_chatstate(PurpleAccount* pa,
87 char* recipient,
88 PurpleTypingState chatstate) {
89 g_return_val_if_fail(pa != NULL, FALSE);
90 g_return_val_if_fail(recipient != NULL, FALSE);
92 PurpleConversation *conv
93 = thrasher_find_conversation_with_account(pa, recipient);
94 g_return_val_if_fail(conv != NULL, FALSE);
96 PurpleConnection *gc = purple_conversation_get_gc(conv);
97 if (gc == NULL) {
98 return FALSE;
101 unsigned int timeout = serv_send_typing(gc, recipient, chatstate);
102 if (chatstate == PURPLE_TYPING) {
103 /* TODO: if the prpl requests the typing notification be resent
104 * after timeout, "normal" UIs can check get_type_again() each
105 * keystroke. Should Thrasher add a event loop timeout? (and rm it
106 * if the conv ended or the state was no longer typing...)
108 PurpleConvIm *im = PURPLE_CONV_IM(conv);
109 purple_conv_im_set_type_again(im, timeout);
111 return TRUE;
114 /* incoming_chatstate_cb(pa, who):
116 * Account "pa" got a typing notification state change from the contact "who".
118 static void
119 incoming_chatstate_cb(PurpleAccount *pa,
120 const char *who) {
121 PurpleConversation *conv
122 = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
123 who,
124 pa);
125 if (! conv
126 || purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_IM) {
127 return;
130 PurpleConvIm *im = PURPLE_CONV_IM(conv);
131 if (! im) {
132 return;
135 thrasher_wrapper_incoming_chatstate(pa,
136 who,
137 purple_conv_im_get_typing_state(im));
140 static gpointer
141 thrasher_conversations_get_handle() {
142 static int handle;
143 return &handle;
146 static PurpleConversationUiOps thrasher_conv_uiops =
148 NULL, /* create_conversation */
149 thrasher_destroy_conversation, /* destroy_conversation */
150 NULL, /* write_chat */
151 NULL, /* write_im */
152 thrasher_write_conv, /* write_conv */
153 NULL, /* chat_add_users */
154 NULL, /* chat_rename_user */
155 NULL, /* chat_remove_users */
156 NULL, /* chat_update_user */
157 NULL, /* present */
158 NULL, /* has_focus */
159 NULL, /* custom_smiley_add */
160 NULL, /* custom_smiley_write */
161 NULL, /* custom_smiley_close */
162 NULL, /* send_confirm */
163 NULL,
164 NULL,
165 NULL,
166 NULL
169 void
170 thrasher_conversations_init(void) {
171 purple_conversations_set_ui_ops(&thrasher_conv_uiops);
173 purple_signal_connect(purple_conversations_get_handle(),
174 "buddy-typing",
175 thrasher_conversations_get_handle(),
176 PURPLE_CALLBACK(incoming_chatstate_cb),
177 NULL);
178 purple_signal_connect(purple_conversations_get_handle(),
179 "buddy-typing-stopped",
180 thrasher_conversations_get_handle(),
181 PURPLE_CALLBACK(incoming_chatstate_cb),
182 NULL);