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
);
53 static void no_dot_purple_no_op(void*);
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 static PurpleBlistUiOps thrasher_blist_uiops
= {
96 /* request_add_buddy */
98 /* request_add_chat */
100 /* request_add_group */
103 (void(*)(PurpleBlistNode
*)) no_dot_purple_no_op
,
105 (void(*)(PurpleBlistNode
*)) no_dot_purple_no_op
,
107 (void(*)(PurpleAccount
*)) no_dot_purple_no_op
,
112 struct _PurpleStatusType
114 PurpleStatusPrimitive primitive
;
118 char *primary_attr_id
;
121 gboolean user_settable
;
122 gboolean independent
;
130 struct _PurpleStatusType
*type
;
131 PurplePresence
*presence
;
137 GHashTable
*attr_values
;
141 * @brief This is the callback for the buddy-status-changed signal
142 * @param buddy PurpleBuddy struct
143 * @param old (unused)
144 * @param new @buddy new PurpleStatus
146 void thrasher_buddy_status_changed (PurpleBuddy
*buddy
,
151 const char *group_name
= NULL
;
152 const char *alias
= NULL
;
154 g_return_if_fail(buddy
!= NULL
);
155 g_return_if_fail(new != NULL
);
157 group
= purple_buddy_get_group(buddy
);
160 group_name
= purple_group_get_name(group
);
162 alias
= purple_buddy_get_alias_only(buddy
);
164 char* message
= status_text_for_buddy(buddy
, new);
166 message
= g_strdup(purple_status_get_attr_string(new, "message"));
169 thrasher_wrapper_presence_in(thrasher_account_get_jid(buddy
->account
),
170 purple_buddy_get_name(buddy
),
173 purple_status_type_get_primitive(new->type
),
178 /* Returns a string that becomes owned by the caller or NULL. */
180 status_text_for_buddy(PurpleBuddy
*buddy
,
181 PurpleStatus
*status
) {
185 if (! buddy
->account
->gc
) {
189 const char *prpl_id
= purple_account_get_protocol_id(buddy
->account
);
191 PurplePlugin
*prpl
= purple_find_prpl(prpl_id
);
193 PurplePluginProtocolInfo
*prpl_info
194 = PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
195 if (prpl_info
&& prpl_info
->status_text
) {
196 char* status_text
= prpl_info
->status_text(buddy
);
197 if (status
&& status_text
198 && purple_status_is_available(status
)
199 && 0 == strcmp(prpl_id
, "prpl-icq")
200 && 0 == strcmp(status_text
,
201 purple_status_get_name(status
))) {
202 /* The oscar prpl's status_text tries to suppress
203 * a redundant "Available" message, but won't if
204 * it's in the message attribute instead of the
205 * status name. libpurple's initial log on does
206 * not set this in the message, but subsequent
207 * status changes will.
209 status_text
= g_strdup("");
217 void thrasher_buddy_authorize (const char *jid
,
218 const char *legacy_username
) {
219 g_return_if_fail(jid
);
220 g_return_if_fail(legacy_username
);
222 PurpleAccount
*account
= thrasher_get_account_by_jid(jid
);
223 g_return_if_fail(account
);
225 PurpleConnection
*gc
=
226 thrasher_get_connection_by_account(account
);
227 g_return_if_fail(gc
);
229 purple_debug_info("thrasher", "Authorizing %s for jid %s (%s)\n",
230 legacy_username
, jid
,
231 purple_account_get_username(account
));
233 // defensive; probably only add_permit is necesary
234 serv_rem_deny(gc
, legacy_username
);
236 serv_add_permit(gc
, legacy_username
);
239 void thrasher_buddy_deauthorize (const char *jid
,
240 const char *legacy_username
) {
241 g_return_if_fail(jid
);
242 g_return_if_fail(legacy_username
);
244 PurpleAccount
*account
= thrasher_get_account_by_jid(jid
);
245 g_return_if_fail(account
);
247 PurpleConnection
*gc
=
248 thrasher_get_connection_by_account(account
);
249 g_return_if_fail(gc
);
251 purple_debug_info("thrasher", "Deauthorizing %s for jid %s\n",
252 legacy_username
, jid
);
254 // no corresponding deny, we don't have a reperesentation for that
255 serv_rem_permit(gc
, legacy_username
);
258 void thrasher_buddy_signed_on (PurpleBuddy
*buddy
)
260 PurplePresence
*presence
;
262 presence
= purple_buddy_get_presence(buddy
);
267 // libpurple uses this to populate some stuff about the
268 // buddy, particularly useful for XMPP file transfers but
269 // probably the cause of random other errors if we don't fill this
271 PurpleAccount
* account
= buddy
->account
;
272 g_return_if_fail(account
);
273 PurpleConnection
* connection
= thrasher_connection_for_account(account
);
274 g_return_if_fail(connection
);
276 purple_debug_info("thblist",
277 "getting server info for %s\n\n---------\n\n",
279 serv_get_info(connection
, buddy
->name
);
281 /* Currently active status may be PURPLE_STATUS_UNAVAILABLE
282 * (translates XMPP dnd) instead of just "available".
284 PurpleStatus
*status
= purple_presence_get_active_status(presence
);
286 thrasher_buddy_status_changed(buddy
,
291 void thrasher_buddy_signed_off (PurpleBuddy
*buddy
)
293 PurplePresence
*presence
;
295 presence
= purple_buddy_get_presence(buddy
);
300 thrasher_buddy_status_changed(buddy
,
302 purple_presence_get_status(presence
, "offline"));
305 struct auth_request_cb_data
{
306 PurpleAccount
*account
;
310 PurpleAccountRequestAuthorizationCb authorize_cb
;
314 static void * thrasher_buddy_request_authorize
315 (PurpleAccount
*account
,
316 const char *remote_user
,
321 PurpleAccountRequestAuthorizationCb authorize_cb
,
322 PurpleAccountRequestAuthorizationCb deny_cb
,
324 purple_debug_info("thrasher", "%s request_authorize from %s reached cb0\n",
326 thrasher_account_get_jid(account
));
328 struct auth_request_cb_data
*data
329 = g_malloc(sizeof(struct auth_request_cb_data
));
330 data
->account
= account
;
331 data
->remote_user
= g_strdup(remote_user
);
332 data
->alias
= g_strdup(alias
);
333 data
->message
= g_strdup(message
);
334 data
->authorize_cb
= authorize_cb
;
335 data
->user_data
= user_data
;
336 purple_timeout_add_seconds(2,
337 thrasher_buddy_request_authorize_cb1
,
340 void *uihandle
= NULL
;
345 thrasher_buddy_request_authorize_cb1(gpointer data_in
) {
346 struct auth_request_cb_data
*data
= data_in
;
347 purple_debug_info("thrasher", "%s request_authorize from %s reached cb1\n",
349 thrasher_account_get_jid(data
->account
));
350 if (data
->authorize_cb
) {
351 data
->authorize_cb(data
->user_data
);
354 /* FIXME: I don't think this actually happens? Any more? */
355 purple_debug_info("thrasher", "authorize_cb sometimes NULL?!?\n");
357 purple_timeout_add_seconds(2,
358 thrasher_buddy_request_authorize_cb2
,
364 thrasher_buddy_request_authorize_cb2(gpointer data_in
) {
365 struct auth_request_cb_data
*data
= data_in
;
366 purple_debug_info("thrasher", "%s request_authorize from %s reached cb2\n",
368 thrasher_account_get_jid(data
->account
));
369 /* FIXME: call through purple_blist_request_add_buddy() and blist ui_ops. */
370 thrasher_buddy_add_request(data
->account
,
375 g_free(data
->remote_user
);
377 g_free(data
->message
);
382 /* thrasher_buddy_add_request
384 * Triggered on a buddy-added signal, this allows us to push new subscriptions.
387 void thrasher_buddy_added (PurpleBuddy
*buddy
) {
388 PurplePresence
*presence
= purple_buddy_get_presence(buddy
);
389 PurpleStatus
*status
= purple_presence_get_active_status(presence
);
390 PurpleStatusType
*type
= purple_status_get_type(status
);
392 const char *jid
= thrasher_account_get_jid(buddy
->account
);
393 const char *sender
= purple_buddy_get_name(buddy
);
394 const guint status_int
= purple_status_type_get_primitive(type
);
396 purple_debug_info("thrasher",
397 "buddy added to %s: %s\n",
400 thrasher_wrapper_subscription_add(jid
, sender
, status_int
);
404 void thrasher_buddy_add_request (PurpleAccount
*account
, const char *remote_user
,
405 const char *id
, const char *alias
,
408 const char *jid
= thrasher_account_get_jid(account
);
412 purple_debug_info("thrasher",
413 "legacy user %s aka %s added %s to roster\n",
414 remote_user
, alias
, jid
);
415 thrasher_wrapper_legacy_user_add_user(jid
, remote_user
);
419 void thrasher_buddy_removed (PurpleBuddy
*buddy
)
421 /* printf("Removed buddy:\t[%s]\t[%s]\n", purple_buddy_get_name(buddy),
422 * purple_status_get_name( purple_presence_get_active_status( purple_buddy_get_presence(buddy) ) )
425 PurplePresence *presence = purple_buddy_get_presence(buddy);
426 PurpleStatus *status = purple_presence_get_active_status(presence);
427 PurpleStatusType *type = purple_status_get_type(status);
428 PurpleGroup *group = purple_buddy_get_group(buddy);
430 * Need to fire jid, sender, group_name, alias, and status back to perl */
432 // jid = thrasher_account_get_jid(buddy->account)
433 // sender = purple_buddy_get_name(buddy)
434 // group_name = purple_group_get_name(group)
435 // alias = purple_buddy_get_alias_only(buddy)
436 // status = purple_status_type_get_primitive(type)
441 thrasher_blist_get_handle ()
448 no_dot_purple_no_op(void *nope_not_here
) {}
450 void thrasher_blist_init()
452 purple_accounts_set_ui_ops(&thrasher_account_uiops
);
454 purple_blist_set_ui_ops(&thrasher_blist_uiops
);
456 purple_signal_connect(purple_blist_get_handle(),
457 "buddy-status-changed",
458 thrasher_blist_get_handle(),
459 PURPLE_CALLBACK(thrasher_buddy_status_changed
),
462 purple_signal_connect(purple_blist_get_handle(),
464 thrasher_blist_get_handle(),
465 PURPLE_CALLBACK(thrasher_buddy_signed_on
),
468 purple_signal_connect(purple_blist_get_handle(),
470 thrasher_blist_get_handle(),
471 PURPLE_CALLBACK(thrasher_buddy_signed_off
),
474 // It looks like this only comes in for things already on our roster.
475 purple_signal_connect(purple_blist_get_handle(),
477 thrasher_blist_get_handle(),
478 PURPLE_CALLBACK(thrasher_buddy_added
),
482 purple_signal_connect(purple_blist_get_handle(),
484 thrasher_blist_get_handle(),
485 PURPLE_CALLBACK(thrasher_buddy_removed),