source: protocols/purple/purple.c @ db4cd40

Last change on this file since db4cd40 was db4cd40, checked in by Wilmer van der Gaast <wilmer@…>, at 2009-10-11T12:22:23Z

Some valgrind cleaning/type safety fixes.

  • Property mode set to 100644
File size: 10.7 KB
Line 
1/***************************************************************************\
2*                                                                           *
3*  BitlBee - An IRC to IM gateway                                           *
4*  libpurple module - Main file                                             *
5*                                                                           *
6*  Copyright 2009 Wilmer van der Gaast <wilmer@gaast.net>                   *
7*                                                                           *
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.                                      *
12*                                                                           *
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.                             *
17*                                                                           *
18*  You should have received a copy of the GNU General Public License along  *
19*  with this program; if not, write to the Free Software Foundation, Inc.,  *
20*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
21*                                                                           *
22\***************************************************************************/
23
24#include <glib.h>
25#include <purple.h>
26
27#include "bitlbee.h"
28
29GSList *purple_connections;
30
31static struct im_connection *purple_ic_by_pa( PurpleAccount *pa )
32{
33        GSList *i;
34       
35        for( i = purple_connections; i; i = i->next )
36                if( ((struct im_connection *)i->data)->proto_data == pa )
37                        return i->data;
38       
39        return NULL;
40}
41
42static struct im_connection *purple_ic_by_gc( PurpleConnection *gc )
43{
44        return purple_ic_by_pa( purple_connection_get_account( gc ) );
45}
46
47static void purple_init( account_t *acc )
48{
49        /* TODO: Figure out variables to export via set. */
50       
51}
52
53static void purple_login( account_t *acc )
54{
55        struct im_connection *ic = imcb_new( acc );
56        PurpleAccount *pa;
57        //PurpleSavedStatus *ps;
58        //GList *i;
59       
60        /* For now this is needed in the _connected() handlers if using
61           GLib event handling, to make sure we're not handling events
62           on dead connections. */
63        purple_connections = g_slist_prepend( purple_connections, ic );
64       
65        pa = purple_account_new( acc->user, acc->prpl->name );
66        purple_account_set_password( pa, acc->pass );
67       
68        ic->proto_data = pa;
69       
70        purple_account_set_enabled( pa, "BitlBee", TRUE );
71       
72        /*
73        for( i = ((PurplePluginProtocolInfo *)pa->gc->prpl->info->extra_info)->protocol_options; i; i = i->next )
74        {
75                PurpleAccountOption *o = i->data;
76               
77                printf( "%s\n", o->pref_name );
78        }
79        */
80       
81        //ps = purple_savedstatus_new( NULL, PURPLE_STATUS_AVAILABLE );
82        //purple_savedstatus_activate_for_account( ps, pa );
83}
84
85static void purple_logout( struct im_connection *ic )
86{
87        PurpleAccount *pa = ic->proto_data;
88       
89        purple_account_set_enabled( pa, "BitlBee", FALSE );
90        purple_connections = g_slist_remove( purple_connections, ic );
91        purple_account_destroy( pa );
92}
93
94static int purple_buddy_msg( struct im_connection *ic, char *who, char *message, int flags )
95{
96        PurpleConversation *conv;
97       
98        if( ( conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_IM,
99                                                            who, ic->proto_data ) ) == NULL )
100        {
101                conv = purple_conversation_new( PURPLE_CONV_TYPE_IM,
102                                                ic->proto_data, who );
103        }
104       
105        purple_conv_im_send( purple_conversation_get_im_data( conv ), message );
106       
107        return 1;
108}
109
110static GList *purple_away_states( struct im_connection *ic )
111{
112        return NULL;
113}
114
115static void purple_set_away( struct im_connection *ic, char *state_txt, char *message )
116{
117}
118
119static void purple_add_buddy( struct im_connection *ic, char *who, char *group )
120{
121}
122
123static void purple_remove_buddy( struct im_connection *ic, char *who, char *group )
124{
125}
126
127static void purple_keepalive( struct im_connection *ic )
128{
129}
130
131static int purple_send_typing( struct im_connection *ic, char *who, int typing )
132{
133        return 1;
134}
135
136static void purple_ui_init();
137
138static PurpleCoreUiOps bee_core_uiops = 
139{
140        NULL,
141        NULL,
142        purple_ui_init,
143        NULL,
144};
145
146static void prplcb_conn_progress( PurpleConnection *gc, const char *text, size_t step, size_t step_count )
147{
148        struct im_connection *ic = purple_ic_by_gc( gc );
149       
150        imcb_log( ic, "%s", text );
151}
152
153static void prplcb_conn_connected( PurpleConnection *gc )
154{
155        struct im_connection *ic = purple_ic_by_gc( gc );
156       
157        imcb_connected( ic );
158       
159        if( gc->flags & PURPLE_CONNECTION_HTML )
160                ic->flags |= OPT_DOES_HTML;
161}
162
163static void prplcb_conn_disconnected( PurpleConnection *gc )
164{
165        struct im_connection *ic = purple_ic_by_gc( gc );
166       
167        if( ic != NULL )
168                imc_logout( ic, TRUE );
169}
170
171static void prplcb_conn_notice( PurpleConnection *gc, const char *text )
172{
173        struct im_connection *ic = purple_ic_by_gc( gc );
174       
175        if( ic != NULL )
176                imcb_log( ic, "%s", text );
177}
178
179static void prplcb_conn_report_disconnect_reason( PurpleConnection *gc, PurpleConnectionError reason, const char *text )
180{
181        struct im_connection *ic = purple_ic_by_gc( gc );
182       
183        /* PURPLE_CONNECTION_ERROR_NAME_IN_USE means concurrent login,
184           should probably handle that. */
185        if( ic != NULL )
186                imcb_error( ic, "%s", text );
187}
188
189static PurpleConnectionUiOps bee_conn_uiops =
190{
191        prplcb_conn_progress,
192        prplcb_conn_connected,
193        prplcb_conn_disconnected,
194        prplcb_conn_notice,
195        NULL,
196        NULL,
197        NULL,
198        prplcb_conn_report_disconnect_reason,
199};
200
201static void prplcb_blist_new( PurpleBlistNode *node )
202{
203        PurpleBuddy *bud = (PurpleBuddy*) node;
204       
205        if( node->type == PURPLE_BLIST_BUDDY_NODE )
206        {
207                struct im_connection *ic = purple_ic_by_pa( bud->account );
208               
209                if( ic == NULL )
210                        return;
211               
212                imcb_add_buddy( ic, bud->name, NULL );
213                if( bud->server_alias )
214                        imcb_buddy_nick_hint( ic, bud->name, bud->server_alias );
215        }
216}
217
218static void prplcb_blist_update( PurpleBuddyList *list, PurpleBlistNode *node )
219{
220        PurpleBuddy *bud = (PurpleBuddy*) node;
221       
222        if( node->type == PURPLE_BLIST_BUDDY_NODE )
223        {
224                struct im_connection *ic = purple_ic_by_pa( bud->account );
225                PurpleStatus *as;
226                int flags = 0;
227               
228                if( ic == NULL )
229                        return;
230               
231                flags |= purple_presence_is_online( bud->presence ) ? OPT_LOGGED_IN : 0;
232                flags |= purple_presence_is_available( bud->presence ) ? 0 : OPT_AWAY;
233               
234                as = purple_presence_get_active_status( bud->presence );
235               
236                imcb_buddy_status( ic, bud->name, flags, purple_status_get_name( as ),
237                                   purple_status_get_attr_string( as, "message" ) );
238        }
239}
240
241static void prplcb_blist_remove( PurpleBuddyList *list, PurpleBlistNode *node )
242{
243        PurpleBuddy *bud = (PurpleBuddy*) node;
244       
245        if( node->type == PURPLE_BLIST_BUDDY_NODE )
246        {
247                struct im_connection *ic = purple_ic_by_pa( bud->account );
248               
249                if( ic == NULL )
250                        return;
251               
252                imcb_remove_buddy( ic, bud->name, NULL );
253        }
254}
255
256static PurpleBlistUiOps bee_blist_uiops =
257{
258        NULL,
259        prplcb_blist_new,
260        NULL,
261        prplcb_blist_update,
262        prplcb_blist_remove,
263};
264
265static void prplcb_conv_im( PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime )
266{
267        struct im_connection *ic = purple_ic_by_pa( conv->account );
268       
269        /* ..._SEND means it's an outgoing message, no need to echo those. */
270        if( !( flags & PURPLE_MESSAGE_SEND ) )
271                imcb_buddy_msg( ic, (char*) who, (char*) message, 0, mtime );
272}
273
274static PurpleConversationUiOps bee_conv_uiops = 
275{
276        NULL,                      /* create_conversation  */
277        NULL,                      /* destroy_conversation */
278        NULL,                      /* write_chat           */
279        prplcb_conv_im,            /* write_im             */
280        NULL,                      /* write_conv           */
281        NULL,                      /* chat_add_users       */
282        NULL,                      /* chat_rename_user     */
283        NULL,                      /* chat_remove_users    */
284        NULL,                      /* chat_update_user     */
285        NULL,                      /* present              */
286        NULL,                      /* has_focus            */
287        NULL,                      /* custom_smiley_add    */
288        NULL,                      /* custom_smiley_write  */
289        NULL,                      /* custom_smiley_close  */
290        NULL,                      /* send_confirm         */
291        NULL,
292        NULL,
293        NULL,
294        NULL
295};
296
297static void prplcb_debug_print( PurpleDebugLevel level, const char *category, const char *arg_s )
298{
299        printf( "DEBUG %s: %s", category, arg_s );
300}
301
302static PurpleDebugUiOps bee_debug_uiops =
303{
304        prplcb_debug_print,
305};
306
307static guint prplcb_ev_timeout_add( guint interval, GSourceFunc func, gpointer udata )
308{
309        return b_timeout_add( interval, (b_event_handler) func, udata );
310}
311
312static guint prplcb_ev_input_add( int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer udata )
313{
314        return b_input_add( fd, cond | B_EV_FLAG_FORCE_REPEAT, (b_event_handler) func, udata );
315}
316
317static gboolean prplcb_ev_remove( guint id )
318{
319        b_event_remove( (gint) id );
320        return TRUE;
321}
322
323static PurpleEventLoopUiOps glib_eventloops = 
324{
325        prplcb_ev_timeout_add,
326        prplcb_ev_remove,
327        prplcb_ev_input_add,
328        prplcb_ev_remove,
329};
330
331static void purple_ui_init()
332{
333        purple_blist_set_ui_ops( &bee_blist_uiops );
334        purple_connections_set_ui_ops( &bee_conn_uiops );
335        purple_conversations_set_ui_ops( &bee_conv_uiops );
336        //purple_debug_set_ui_ops( &bee_debug_uiops );
337}
338
339void purple_initmodule()
340{
341        GList *prots;
342       
343        if( B_EV_IO_READ != PURPLE_INPUT_READ ||
344            B_EV_IO_WRITE != PURPLE_INPUT_WRITE )
345        {
346                /* FIXME FIXME FIXME FIXME FIXME :-) */
347                exit( 1 );
348        }
349       
350        purple_util_set_user_dir("/tmp");
351        purple_debug_set_enabled(FALSE);
352        purple_core_set_ui_ops(&bee_core_uiops);
353        purple_eventloop_set_ui_ops(&glib_eventloops);
354        if( !purple_core_init( "BitlBee") )
355        {
356                /* Initializing the core failed. Terminate. */
357                fprintf( stderr, "libpurple initialization failed.\n" );
358                abort();
359        }
360       
361        /* This seems like stateful shit we don't want... */
362        purple_set_blist(purple_blist_new());
363        purple_blist_load();
364       
365        /* Meh? */
366        purple_prefs_load();
367       
368        for( prots = purple_plugins_get_protocols(); prots; prots = prots->next )
369        {
370                struct prpl *ret = g_new0( struct prpl, 1 );
371                PurplePlugin *prot = prots->data;
372               
373                ret->name = prot->info->id;
374                ret->login = purple_login;
375                ret->init = purple_init;
376                ret->logout = purple_logout;
377                ret->buddy_msg = purple_buddy_msg;
378                ret->away_states = purple_away_states;
379                ret->set_away = purple_set_away;
380                ret->add_buddy = purple_add_buddy;
381                ret->remove_buddy = purple_remove_buddy;
382                ret->keepalive = purple_keepalive;
383                ret->send_typing = purple_send_typing;
384                ret->handle_cmp = g_strcasecmp;
385               
386                register_protocol( ret );
387        }
388}
Note: See TracBrowser for help on using the repository browser.