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
29 void thrasher_buddy_status_changed (PurpleBuddy
*buddy
, PurpleStatus
*old
,
31 void thrasher_buddy_signed_on (PurpleBuddy
*buddy
);
32 void thrasher_buddy_signed_off (PurpleBuddy
*buddy
);
33 void thrasher_buddy_added (PurpleBuddy
*buddy
);
34 void thrasher_buddy_add_request (PurpleAccount
*account
, const char *remote_user
,
35 const char *id
, const char *alias
,
37 static void * thrasher_buddy_request_authorize
38 (PurpleAccount
*account
,
39 const char *remote_user
,
44 PurpleAccountRequestAuthorizationCb authorize_cb
,
45 PurpleAccountRequestAuthorizationCb deny_cb
,
47 void thrasher_buddy_removed (PurpleBuddy
*buddy
);
48 static gpointer
thrasher_blist_get_handle (void);
49 static char* status_text_for_buddy(PurpleBuddy
*buddy
, PurpleStatus
*status
);
51 static gboolean
thrasher_buddy_request_authorize_cb1(gpointer data_in
);
52 static gboolean
thrasher_buddy_request_authorize_cb2(gpointer data_in
);
55 static PurpleAccountUiOps thrasher_account_uiops
=
58 thrasher_buddy_add_request
,
64 thrasher_buddy_add_request
,
67 thrasher_buddy_request_authorize
,
69 // close_account_request
81 struct _PurpleStatusType
83 PurpleStatusPrimitive primitive
;
87 char *primary_attr_id
;
90 gboolean user_settable
;
99 struct _PurpleStatusType
*type
;
100 PurplePresence
*presence
;
106 GHashTable
*attr_values
;
110 * @brief This is the callback for the buddy-status-changed signal
111 * @param buddy PurpleBuddy struct
112 * @param old (unused)
113 * @param new @buddy new PurpleStatus
115 void thrasher_buddy_status_changed (PurpleBuddy
*buddy
,
120 const char *group_name
= NULL
;
121 const char *alias
= NULL
;
123 g_return_if_fail(buddy
!= NULL
);
124 g_return_if_fail(new != NULL
);
126 group
= purple_buddy_get_group(buddy
);
129 group_name
= purple_group_get_name(group
);
131 alias
= purple_buddy_get_alias_only(buddy
);
133 char* message
= status_text_for_buddy(buddy
, new);
135 message
= g_strdup(purple_status_get_attr_string(new, "message"));
138 thrasher_wrapper_presence_in(thrasher_account_get_jid(buddy
->account
),
139 purple_buddy_get_name(buddy
),
142 purple_status_type_get_primitive(new->type
),
147 /* Returns a string that becomes owned by the caller or NULL. */
149 status_text_for_buddy(PurpleBuddy
*buddy
,
150 PurpleStatus
*status
) {
154 if (! buddy
->account
->gc
) {
158 const char *prpl_id
= purple_account_get_protocol_id(buddy
->account
);
160 PurplePlugin
*prpl
= purple_find_prpl(prpl_id
);
162 PurplePluginProtocolInfo
*prpl_info
163 = PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
164 if (prpl_info
&& prpl_info
->status_text
) {
165 char* status_text
= prpl_info
->status_text(buddy
);
166 if (status
&& status_text
167 && purple_status_is_available(status
)
168 && 0 == strcmp(prpl_id
, "prpl-icq")
169 && 0 == strcmp(status_text
,
170 purple_status_get_name(status
))) {
171 /* The oscar prpl's status_text tries to suppress
172 * a redundant "Available" message, but won't if
173 * it's in the message attribute instead of the
174 * status name. libpurple's initial log on does
175 * not set this in the message, but subsequent
176 * status changes will.
178 status_text
= g_strdup("");
186 void thrasher_buddy_authorize (const char *jid
,
187 const char *legacy_username
) {
188 g_return_if_fail(jid
);
189 g_return_if_fail(legacy_username
);
191 PurpleAccount
*account
= thrasher_get_account_by_jid(jid
);
192 g_return_if_fail(account
);
194 PurpleConnection
*gc
=
195 thrasher_get_connection_by_account(account
);
196 g_return_if_fail(gc
);
198 purple_debug_info("thrasher", "Authorizing %s for jid %s (%s)\n",
199 legacy_username
, jid
,
200 purple_account_get_username(account
));
202 // defensive; probably only add_permit is necesary
203 serv_rem_deny(gc
, legacy_username
);
205 serv_add_permit(gc
, legacy_username
);
208 void thrasher_buddy_deauthorize (const char *jid
,
209 const char *legacy_username
) {
210 g_return_if_fail(jid
);
211 g_return_if_fail(legacy_username
);
213 PurpleAccount
*account
= thrasher_get_account_by_jid(jid
);
214 g_return_if_fail(account
);
216 PurpleConnection
*gc
=
217 thrasher_get_connection_by_account(account
);
218 g_return_if_fail(gc
);
220 purple_debug_info("thrasher", "Deauthorizing %s for jid %s\n",
221 legacy_username
, jid
);
223 // no corresponding deny, we don't have a reperesentation for that
224 serv_rem_permit(gc
, legacy_username
);
227 void thrasher_buddy_signed_on (PurpleBuddy
*buddy
)
229 PurplePresence
*presence
;
231 presence
= purple_buddy_get_presence(buddy
);
236 // libpurple uses this to populate some stuff about the
237 // buddy, particularly useful for XMPP file transfers but
238 // probably the cause of random other errors if we don't fill this
240 PurpleAccount
* account
= buddy
->account
;
241 g_return_if_fail(account
);
242 PurpleConnection
* connection
= thrasher_connection_for_account(account
);
243 g_return_if_fail(connection
);
245 purple_debug_info("thblist",
246 "getting server info for %s\n\n---------\n\n",
248 serv_get_info(connection
, buddy
->name
);
250 /* Currently active status may be PURPLE_STATUS_UNAVAILABLE
251 * (translates XMPP dnd) instead of just "available".
253 PurpleStatus
*status
= purple_presence_get_active_status(presence
);
255 thrasher_buddy_status_changed(buddy
,
260 void thrasher_buddy_signed_off (PurpleBuddy
*buddy
)
262 PurplePresence
*presence
;
264 presence
= purple_buddy_get_presence(buddy
);
269 thrasher_buddy_status_changed(buddy
,
271 purple_presence_get_status(presence
, "offline"));
274 struct auth_request_cb_data
{
275 PurpleAccount
*account
;
279 PurpleAccountRequestAuthorizationCb authorize_cb
;
283 static void * thrasher_buddy_request_authorize
284 (PurpleAccount
*account
,
285 const char *remote_user
,
290 PurpleAccountRequestAuthorizationCb authorize_cb
,
291 PurpleAccountRequestAuthorizationCb deny_cb
,
293 purple_debug_info("thrasher", "%s request_authorize from %s reached cb0\n",
295 thrasher_account_get_jid(account
));
297 struct auth_request_cb_data
*data
298 = g_malloc(sizeof(struct auth_request_cb_data
));
299 data
->account
= account
;
300 data
->remote_user
= g_strdup(remote_user
);
301 data
->alias
= g_strdup(alias
);
302 data
->message
= g_strdup(message
);
303 data
->authorize_cb
= authorize_cb
;
304 data
->user_data
= user_data
;
305 purple_timeout_add_seconds(2,
306 thrasher_buddy_request_authorize_cb1
,
309 void *uihandle
= NULL
;
314 thrasher_buddy_request_authorize_cb1(gpointer data_in
) {
315 struct auth_request_cb_data
*data
= data_in
;
316 purple_debug_info("thrasher", "%s request_authorize from %s reached cb1\n",
318 thrasher_account_get_jid(data
->account
));
319 if (data
->authorize_cb
) {
320 data
->authorize_cb(data
->user_data
);
323 /* FIXME: I don't think this actually happens? Any more? */
324 purple_debug_info("thrasher", "authorize_cb sometimes NULL?!?\n");
326 purple_timeout_add_seconds(2,
327 thrasher_buddy_request_authorize_cb2
,
333 thrasher_buddy_request_authorize_cb2(gpointer data_in
) {
334 struct auth_request_cb_data
*data
= data_in
;
335 purple_debug_info("thrasher", "%s request_authorize from %s reached cb2\n",
337 thrasher_account_get_jid(data
->account
));
338 /* FIXME: call through purple_blist_request_add_buddy() and blist ui_ops. */
339 thrasher_buddy_add_request(data
->account
,
344 g_free(data
->remote_user
);
346 g_free(data
->message
);
351 /* thrasher_buddy_add_request
353 * Triggered on a buddy-added signal, this allows us to push new subscriptions.
356 void thrasher_buddy_added (PurpleBuddy
*buddy
) {
357 PurplePresence
*presence
= purple_buddy_get_presence(buddy
);
358 PurpleStatus
*status
= purple_presence_get_active_status(presence
);
359 PurpleStatusType
*type
= purple_status_get_type(status
);
361 const char *jid
= thrasher_account_get_jid(buddy
->account
);
362 const char *sender
= purple_buddy_get_name(buddy
);
363 const guint status_int
= purple_status_type_get_primitive(type
);
365 purple_debug_info("thrasher",
366 "buddy added to %s: %s\n",
369 thrasher_wrapper_subscription_add(jid
, sender
, status_int
);
373 void thrasher_buddy_add_request (PurpleAccount
*account
, const char *remote_user
,
374 const char *id
, const char *alias
,
377 const char *jid
= thrasher_account_get_jid(account
);
381 purple_debug_info("thrasher",
382 "legacy user %s aka %s added %s to roster\n",
383 remote_user
, alias
, jid
);
384 thrasher_wrapper_legacy_user_add_user(jid
, remote_user
);
388 void thrasher_buddy_removed (PurpleBuddy
*buddy
)
390 /* printf("Removed buddy:\t[%s]\t[%s]\n", purple_buddy_get_name(buddy),
391 * purple_status_get_name( purple_presence_get_active_status( purple_buddy_get_presence(buddy) ) )
394 PurplePresence *presence = purple_buddy_get_presence(buddy);
395 PurpleStatus *status = purple_presence_get_active_status(presence);
396 PurpleStatusType *type = purple_status_get_type(status);
397 PurpleGroup *group = purple_buddy_get_group(buddy);
399 * Need to fire jid, sender, group_name, alias, and status back to perl */
401 // jid = thrasher_account_get_jid(buddy->account)
402 // sender = purple_buddy_get_name(buddy)
403 // group_name = purple_group_get_name(group)
404 // alias = purple_buddy_get_alias_only(buddy)
405 // status = purple_status_type_get_primitive(type)
410 thrasher_blist_get_handle ()
417 void thrasher_blist_init()
419 purple_accounts_set_ui_ops(&thrasher_account_uiops
);
421 purple_signal_connect(purple_blist_get_handle(),
422 "buddy-status-changed",
423 thrasher_blist_get_handle(),
424 PURPLE_CALLBACK(thrasher_buddy_status_changed
),
427 purple_signal_connect(purple_blist_get_handle(),
429 thrasher_blist_get_handle(),
430 PURPLE_CALLBACK(thrasher_buddy_signed_on
),
433 purple_signal_connect(purple_blist_get_handle(),
435 thrasher_blist_get_handle(),
436 PURPLE_CALLBACK(thrasher_buddy_signed_off
),
439 // It looks like this only comes in for things already on our roster.
440 purple_signal_connect(purple_blist_get_handle(),
442 thrasher_blist_get_handle(),
443 PURPLE_CALLBACK(thrasher_buddy_added
),
447 purple_signal_connect(purple_blist_get_handle(),
449 thrasher_blist_get_handle(),
450 PURPLE_CALLBACK(thrasher_buddy_removed),