source: protocols/nogaim.c @ da44b08

Last change on this file since da44b08 was 748bcdd, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-11-21T15:23:54Z

Time out if logging in takes too long (2m for now). Except for Twitter
OAuth login, which requires user action. This mostly solves problems with
OSCAR login silently failing, but may also be useful in other places.

  • Property mode set to 100644
File size: 16.6 KB
RevLine 
[b7d3cc34]1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
[58adb7e]4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
[b7d3cc34]5  \********************************************************************/
6
7/*
8 * nogaim
9 *
10 * Gaim without gaim - for BitlBee
11 *
12 * This file contains functions called by the Gaim IM-modules. It's written
13 * from scratch for BitlBee and doesn't contain any code from Gaim anymore
14 * (except for the function names).
15 */
16
17/*
18  This program is free software; you can redistribute it and/or modify
19  it under the terms of the GNU General Public License as published by
20  the Free Software Foundation; either version 2 of the License, or
21  (at your option) any later version.
22
23  This program is distributed in the hope that it will be useful,
24  but WITHOUT ANY WARRANTY; without even the implied warranty of
25  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  GNU General Public License for more details.
27
28  You should have received a copy of the GNU General Public License with
29  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
30  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
31  Suite 330, Boston, MA  02111-1307  USA
32*/
33
34#define BITLBEE_CORE
35#include <ctype.h>
36
[4cf80bb]37#include "nogaim.h"
38
[b7d3cc34]39GSList *connections;
40
[65e2ce1]41#ifdef WITH_PLUGINS
[7b23afd]42gboolean load_plugin(char *path)
43{
44        void (*init_function) (void);
45       
46        GModule *mod = g_module_open(path, G_MODULE_BIND_LAZY);
47
48        if(!mod) {
[8ad90fb]49                log_message(LOGLVL_ERROR, "Can't find `%s', not loading (%s)\n", path, g_module_error());
[7b23afd]50                return FALSE;
51        }
52
53        if(!g_module_symbol(mod,"init_plugin",(gpointer *) &init_function)) {
54                log_message(LOGLVL_WARNING, "Can't find function `init_plugin' in `%s'\n", path);
55                return FALSE;
56        }
57
58        init_function();
59
60        return TRUE;
61}
[b7d3cc34]62
[65e2ce1]63void load_plugins(void)
64{
65        GDir *dir;
66        GError *error = NULL;
67
[4bfca70]68        dir = g_dir_open(global.conf->plugindir, 0, &error);
[65e2ce1]69
70        if (dir) {
71                const gchar *entry;
72                char *path;
73
74                while ((entry = g_dir_read_name(dir))) {
[4bfca70]75                        path = g_build_filename(global.conf->plugindir, entry, NULL);
[65e2ce1]76                        if(!path) {
77                                log_message(LOGLVL_WARNING, "Can't build path for %s\n", entry);
78                                continue;
79                        }
80
81                        load_plugin(path);
82
83                        g_free(path);
84                }
85
86                g_dir_close(dir);
87        }
88}
89#endif
[b7d3cc34]90
[7b23afd]91GList *protocols = NULL;
92 
93void register_protocol (struct prpl *p)
94{
[90cd6c4]95        int i;
96        gboolean refused = global.conf->protocols != NULL;
97 
98        for (i = 0; global.conf->protocols && global.conf->protocols[i]; i++)
99        {
100                if (g_strcasecmp(p->name, global.conf->protocols[i]) == 0)
101                        refused = FALSE;
102        }
103
104        if (refused)
105                log_message(LOGLVL_WARNING, "Protocol %s disabled\n", p->name);
106        else
107                protocols = g_list_append(protocols, p);
[7b23afd]108}
109
110struct prpl *find_protocol(const char *name)
111{
112        GList *gl;
[e248c7f]113       
114        for( gl = protocols; gl; gl = gl->next )
[7b23afd]115        {
116                struct prpl *proto = gl->data;
[e248c7f]117               
118                if( g_strcasecmp( proto->name, name ) == 0 )
[7b23afd]119                        return proto;
120        }
[e248c7f]121       
[7b23afd]122        return NULL;
123}
124
[b7d3cc34]125void nogaim_init()
126{
[0da65d5]127        extern void msn_initmodule();
128        extern void oscar_initmodule();
129        extern void byahoo_initmodule();
130        extern void jabber_initmodule();
[1b221e0]131        extern void twitter_initmodule();
[796da03]132        extern void purple_initmodule();
[7b23afd]133
[b7d3cc34]134#ifdef WITH_MSN
[0da65d5]135        msn_initmodule();
[b7d3cc34]136#endif
137
138#ifdef WITH_OSCAR
[0da65d5]139        oscar_initmodule();
[b7d3cc34]140#endif
141       
142#ifdef WITH_YAHOO
[0da65d5]143        byahoo_initmodule();
[b7d3cc34]144#endif
145       
146#ifdef WITH_JABBER
[0da65d5]147        jabber_initmodule();
[b7d3cc34]148#endif
[7b23afd]149
[1b221e0]150#ifdef WITH_TWITTER
151        twitter_initmodule();
152#endif
153
[796da03]154#ifdef WITH_PURPLE
155        purple_initmodule();
156#endif
[7b23afd]157
[65e2ce1]158#ifdef WITH_PLUGINS
159        load_plugins();
[b7d3cc34]160#endif
161}
162
163GSList *get_connections() { return connections; }
164
[84b045d]165struct im_connection *imcb_new( account_t *acc )
[b7d3cc34]166{
[0da65d5]167        struct im_connection *ic;
[b7d3cc34]168       
[0da65d5]169        ic = g_new0( struct im_connection, 1 );
[b7d3cc34]170       
[81e04e1]171        ic->bee = acc->bee;
[0da65d5]172        ic->acc = acc;
173        acc->ic = ic;
[b7d3cc34]174       
[0da65d5]175        connections = g_slist_append( connections, ic );
[b7d3cc34]176       
[0da65d5]177        return( ic );
[b7d3cc34]178}
179
[aef4828]180void imc_free( struct im_connection *ic )
[b7d3cc34]181{
182        account_t *a;
183       
184        /* Destroy the pointer to this connection from the account list */
[81e04e1]185        for( a = ic->bee->accounts; a; a = a->next )
[0da65d5]186                if( a->ic == ic )
[b7d3cc34]187                {
[0da65d5]188                        a->ic = NULL;
[b7d3cc34]189                        break;
190                }
191       
[0da65d5]192        connections = g_slist_remove( connections, ic );
193        g_free( ic );
[b7d3cc34]194}
195
[aef4828]196static void serv_got_crap( struct im_connection *ic, char *format, ... )
[b7d3cc34]197{
198        va_list params;
[e27661d]199        char *text;
[dfde8e0]200        account_t *a;
[b7d3cc34]201       
202        va_start( params, format );
[e27661d]203        text = g_strdup_vprintf( format, params );
[b7d3cc34]204        va_end( params );
205
[81e04e1]206        if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) ||
207            ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) )
[e27661d]208                strip_html( text );
[b7d3cc34]209       
[dfde8e0]210        /* Try to find a different connection on the same protocol. */
[81e04e1]211        for( a = ic->bee->accounts; a; a = a->next )
[0da65d5]212                if( a->prpl == ic->acc->prpl && a->ic != ic )
[dfde8e0]213                        break;
214       
[e27661d]215        /* If we found one, include the screenname in the message. */
[dfde8e0]216        if( a )
[81e04e1]217                /* FIXME(wilmer): ui_log callback or so */
218                irc_usermsg( ic->bee->ui_data, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text );
[dfde8e0]219        else
[81e04e1]220                irc_usermsg( ic->bee->ui_data, "%s - %s", ic->acc->prpl->name, text );
[7b07dc6]221       
[e27661d]222        g_free( text );
[b7d3cc34]223}
224
[84b045d]225void imcb_log( struct im_connection *ic, char *format, ... )
[aef4828]226{
227        va_list params;
228        char *text;
229       
230        va_start( params, format );
231        text = g_strdup_vprintf( format, params );
232        va_end( params );
233       
234        if( ic->flags & OPT_LOGGED_IN )
235                serv_got_crap( ic, "%s", text );
236        else
237                serv_got_crap( ic, "Logging in: %s", text );
238       
239        g_free( text );
240}
241
[84b045d]242void imcb_error( struct im_connection *ic, char *format, ... )
[aef4828]243{
244        va_list params;
245        char *text;
246       
247        va_start( params, format );
248        text = g_strdup_vprintf( format, params );
249        va_end( params );
250       
251        if( ic->flags & OPT_LOGGED_IN )
252                serv_got_crap( ic, "Error: %s", text );
253        else
[02bb9db]254                serv_got_crap( ic, "Login error: %s", text );
[aef4828]255       
256        g_free( text );
257}
258
[ba9edaa]259static gboolean send_keepalive( gpointer d, gint fd, b_input_condition cond )
[b7d3cc34]260{
[0da65d5]261        struct im_connection *ic = d;
[b7d3cc34]262       
[0da65d5]263        if( ic->acc->prpl->keepalive )
264                ic->acc->prpl->keepalive( ic );
[b7d3cc34]265       
266        return TRUE;
267}
268
[84b045d]269void imcb_connected( struct im_connection *ic )
[b7d3cc34]270{
271        /* MSN servers sometimes redirect you to a different server and do
[84c1a0a]272           the whole login sequence again, so these "late" calls to this
[b7d3cc34]273           function should be handled correctly. (IOW, ignored) */
[0da65d5]274        if( ic->flags & OPT_LOGGED_IN )
[b7d3cc34]275                return;
276       
[84b045d]277        imcb_log( ic, "Logged in" );
[b7d3cc34]278       
[748bcdd]279        b_event_remove( ic->keepalive );
[0da65d5]280        ic->keepalive = b_timeout_add( 60000, send_keepalive, ic );
281        ic->flags |= OPT_LOGGED_IN;
[b7d3cc34]282       
[58adb7e]283        /* Necessary to send initial presence status, even if we're not away. */
284        imc_away_send_update( ic );
[280e655]285       
286        /* Apparently we're connected successfully, so reset the
287           exponential backoff timer. */
288        ic->acc->auto_reconnect_delay = 0;
[3611717]289       
[5c7b45c]290        if( ic->bee->ui->imc_connected )
291                ic->bee->ui->imc_connected( ic );
[b7d3cc34]292}
293
[ba9edaa]294gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond )
[b7d3cc34]295{
296        account_t *a = data;
297       
298        a->reconnect = 0;
[81e04e1]299        account_on( a->bee, a );
[b7d3cc34]300       
301        return( FALSE );        /* Only have to run the timeout once */
302}
303
304void cancel_auto_reconnect( account_t *a )
305{
[c98be00]306        b_event_remove( a->reconnect );
[b7d3cc34]307        a->reconnect = 0;
308}
309
[c2fb3809]310void imc_logout( struct im_connection *ic, int allow_reconnect )
[b7d3cc34]311{
[81e04e1]312        bee_t *bee = ic->bee;
[b7d3cc34]313        account_t *a;
[81e04e1]314        GSList *l;
[4230221]315        int delay;
[b7d3cc34]316       
[8d74291]317        /* Nested calls might happen sometimes, this is probably the best
318           place to catch them. */
[0da65d5]319        if( ic->flags & OPT_LOGGING_OUT )
[8d74291]320                return;
[66f783f]321        else
[0da65d5]322                ic->flags |= OPT_LOGGING_OUT;
[8d74291]323       
[5c7b45c]324        if( ic->bee->ui->imc_disconnected )
325                ic->bee->ui->imc_disconnected( ic );
326       
[84b045d]327        imcb_log( ic, "Signing off.." );
[fb62f81f]328       
[eabc9d2]329        for( l = bee->users; l; )
[b7d3cc34]330        {
[81e04e1]331                bee_user_t *bu = l->data;
[eabc9d2]332                GSList *next = l->next;
[81e04e1]333               
334                if( bu->ic == ic )
[eabc9d2]335                        bee_user_free( bee, bu );
336               
337                l = next;
[b7d3cc34]338        }
339       
[be7a180]340        b_event_remove( ic->keepalive );
341        ic->keepalive = 0;
342        ic->acc->prpl->logout( ic );
343        b_event_remove( ic->inpa );
344       
345        g_free( ic->away );
346        ic->away = NULL;
347       
[3663bb3]348        query_del_by_conn( (irc_t*) ic->bee->ui_data, ic );
[b7d3cc34]349       
[81e04e1]350        for( a = bee->accounts; a; a = a->next )
[0da65d5]351                if( a->ic == ic )
[b7d3cc34]352                        break;
353       
354        if( !a )
355        {
356                /* Uhm... This is very sick. */
357        }
[81e04e1]358        else if( allow_reconnect && set_getbool( &bee->set, "auto_reconnect" ) &&
[4230221]359                 set_getbool( &a->set, "auto_reconnect" ) &&
360                 ( delay = account_reconnect_delay( a ) ) > 0 )
[b7d3cc34]361        {
[84b045d]362                imcb_log( ic, "Reconnecting in %d seconds..", delay );
[c98be00]363                a->reconnect = b_timeout_add( delay * 1000, auto_reconnect, a );
[b7d3cc34]364        }
365       
[aef4828]366        imc_free( ic );
[b7d3cc34]367}
368
[9143aeb]369void imcb_ask( struct im_connection *ic, char *msg, void *data,
370               query_callback doit, query_callback dont )
[b7d3cc34]371{
[1e52e1f]372        query_add( (irc_t *) ic->bee->ui_data, ic, msg, doit, dont, g_free, data );
[b7d3cc34]373}
374
[d0527c1]375void imcb_ask_with_free( struct im_connection *ic, char *msg, void *data,
376                         query_callback doit, query_callback dont, query_callback myfree )
377{
378        query_add( (irc_t *) ic->bee->ui_data, ic, msg, doit, dont, myfree, data );
379}
380
[c6ca3ee]381void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group )
[b7d3cc34]382{
[81e04e1]383        bee_user_t *bu;
384        bee_t *bee = ic->bee;
[8b61469]385        bee_group_t *oldg;
[b7d3cc34]386       
[4e608d6]387        if( !( bu = bee_user_by_handle( bee, ic, handle ) ) )
[ad404ab]388                bu = bee_user_new( bee, ic, handle, 0 );
[b7d3cc34]389       
[8b61469]390        oldg = bu->group;
[7aadd71]391        bu->group = bee_group_by_name( bee, group, TRUE );
[7e83e8e4]392       
[8b61469]393        if( bee->ui->user_group && bu->group != oldg )
[7e83e8e4]394                bee->ui->user_group( bee, bu );
[b7d3cc34]395}
396
[1d39159]397void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *fullname )
[b7d3cc34]398{
[1d39159]399        bee_t *bee = ic->bee;
400        bee_user_t *bu = bee_user_by_handle( bee, ic, handle );
[b7d3cc34]401       
[1d39159]402        if( !bu || !fullname ) return;
[b7d3cc34]403       
[17a6ee9]404        if( !bu->fullname || strcmp( bu->fullname, fullname ) != 0 )
[b7d3cc34]405        {
[1d39159]406                g_free( bu->fullname );
407                bu->fullname = g_strdup( fullname );
[b7d3cc34]408               
[1d39159]409                if( bee->ui->user_fullname )
410                        bee->ui->user_fullname( bee, bu );
[b7d3cc34]411        }
412}
413
[c6ca3ee]414void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group )
[998b103]415{
[eabc9d2]416        bee_user_free( ic->bee, bee_user_by_handle( ic->bee, ic, handle ) );
[998b103]417}
418
[d06eabf]419/* Mainly meant for ICQ (and now also for Jabber conferences) to allow IM
420   modules to suggest a nickname for a handle. */
[fb00989]421void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick )
[d06eabf]422{
[6ef9065]423        bee_t *bee = ic->bee;
424        bee_user_t *bu = bee_user_by_handle( bee, ic, handle );
[d06eabf]425       
[6ef9065]426        if( !bu || !nick ) return;
427       
[69b896b]428        g_free( bu->nick );
429        bu->nick = g_strdup( nick );
430       
[6ef9065]431        if( bee->ui->user_nick_hint )
432                bee->ui->user_nick_hint( bee, bu, nick );
[d06eabf]433}
[b7d3cc34]434
435
[fa295e36]436struct imcb_ask_cb_data
[7bf0f5f0]437{
[0da65d5]438        struct im_connection *ic;
[7bf0f5f0]439        char *handle;
440};
441
[fa295e36]442static void imcb_ask_auth_cb_no( void *data )
[7bf0f5f0]443{
[fa295e36]444        struct imcb_ask_cb_data *cbd = data;
445       
446        cbd->ic->acc->prpl->auth_deny( cbd->ic, cbd->handle );
447       
448        g_free( cbd->handle );
449        g_free( cbd );
450}
451
452static void imcb_ask_auth_cb_yes( void *data )
453{
454        struct imcb_ask_cb_data *cbd = data;
455       
456        cbd->ic->acc->prpl->auth_allow( cbd->ic, cbd->handle );
457       
458        g_free( cbd->handle );
459        g_free( cbd );
460}
461
462void imcb_ask_auth( struct im_connection *ic, const char *handle, const char *realname )
463{
464        struct imcb_ask_cb_data *data = g_new0( struct imcb_ask_cb_data, 1 );
465        char *s, *realname_ = NULL;
466       
467        if( realname != NULL )
468                realname_ = g_strdup_printf( " (%s)", realname );
469       
470        s = g_strdup_printf( "The user %s%s wants to add you to his/her buddy list.",
[daae10f]471                             handle, realname_ ? realname_ : "" );
[fa295e36]472       
473        g_free( realname_ );
474       
475        data->ic = ic;
476        data->handle = g_strdup( handle );
[e00da63]477        query_add( (irc_t *) ic->bee->ui_data, ic, s,
[1e52e1f]478                   imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, g_free, data );
[fa295e36]479}
480
481
482static void imcb_ask_add_cb_no( void *data )
483{
484        g_free( ((struct imcb_ask_cb_data*)data)->handle );
[7bf0f5f0]485        g_free( data );
486}
487
[fa295e36]488static void imcb_ask_add_cb_yes( void *data )
[7bf0f5f0]489{
[fa295e36]490        struct imcb_ask_cb_data *cbd = data;
[7bf0f5f0]491       
[fa295e36]492        cbd->ic->acc->prpl->add_buddy( cbd->ic, cbd->handle, NULL );
[9143aeb]493       
[daae10f]494        imcb_ask_add_cb_no( data );
[7bf0f5f0]495}
496
[fa295e36]497void imcb_ask_add( struct im_connection *ic, const char *handle, const char *realname )
[b7d3cc34]498{
[fa295e36]499        struct imcb_ask_cb_data *data = g_new0( struct imcb_ask_cb_data, 1 );
[7bf0f5f0]500        char *s;
501       
502        /* TODO: Make a setting for this! */
[e00da63]503        if( bee_user_by_handle( ic->bee, ic, handle ) != NULL )
[7bf0f5f0]504                return;
505       
506        s = g_strdup_printf( "The user %s is not in your buddy list yet. Do you want to add him/her now?", handle );
507       
[0da65d5]508        data->ic = ic;
[7bf0f5f0]509        data->handle = g_strdup( handle );
[e00da63]510        query_add( (irc_t *) ic->bee->ui_data, ic, s,
[1e52e1f]511                   imcb_ask_add_cb_yes, imcb_ask_add_cb_no, g_free, data );
[b7d3cc34]512}
513
[81e04e1]514struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle )
515{
516        return bee_user_by_handle( ic->bee, ic, handle );
[b7d3cc34]517}
518
[226fce1]519/* The plan is to not allow straight calls to prpl functions anymore, but do
520   them all from some wrappers. We'll start to define some down here: */
521
[84b045d]522int imc_chat_msg( struct groupchat *c, char *msg, int flags )
[b7d3cc34]523{
[e27661d]524        char *buf = NULL;
[b7d3cc34]525       
[6bbb939]526        if( ( c->ic->flags & OPT_DOES_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) )
[e27661d]527        {
528                buf = escape_html( msg );
[b7d3cc34]529                msg = buf;
530        }
531       
[f6c963b]532        c->ic->acc->prpl->chat_msg( c, msg, flags );
[e27661d]533        g_free( buf );
534       
[0da65d5]535        return 1;
[b7d3cc34]536}
[226fce1]537
[34fbbf9]538static char *imc_away_state_find( GList *gcm, char *away, char **message );
[226fce1]539
[58adb7e]540int imc_away_send_update( struct im_connection *ic )
[226fce1]541{
[3e1ef92c]542        char *away, *msg = NULL;
[226fce1]543       
[91cec2f]544        if( ic->acc->prpl->away_states == NULL ||
545            ic->acc->prpl->set_away == NULL )
546                return 0;
547       
[58adb7e]548        away = set_getstr( &ic->acc->set, "away" ) ?
[81e04e1]549             : set_getstr( &ic->bee->set, "away" );
[34fbbf9]550        if( away && *away )
[226fce1]551        {
[34fbbf9]552                GList *m = ic->acc->prpl->away_states( ic );
[58adb7e]553                msg = ic->acc->flags & ACC_FLAG_AWAY_MESSAGE ? away : NULL;
554                away = imc_away_state_find( m, away, &msg ) ? : m->data;
555        }
556        else if( ic->acc->flags & ACC_FLAG_STATUS_MESSAGE )
557        {
558                away = NULL;
559                msg = set_getstr( &ic->acc->set, "status" ) ?
[81e04e1]560                    : set_getstr( &ic->bee->set, "status" );
[226fce1]561        }
562       
[58adb7e]563        ic->acc->prpl->set_away( ic, away, msg );
[226fce1]564       
[34fbbf9]565        return 1;
[226fce1]566}
567
[84b045d]568static char *imc_away_alias_list[8][5] =
[226fce1]569{
570        { "Away from computer", "Away", "Extended away", NULL },
571        { "NA", "N/A", "Not available", NULL },
572        { "Busy", "Do not disturb", "DND", "Occupied", NULL },
573        { "Be right back", "BRB", NULL },
574        { "On the phone", "Phone", "On phone", NULL },
575        { "Out to lunch", "Lunch", "Food", NULL },
576        { "Invisible", "Hidden" },
577        { NULL }
578};
579
[34fbbf9]580static char *imc_away_state_find( GList *gcm, char *away, char **message )
[226fce1]581{
582        GList *m;
583        int i, j;
584       
[34fbbf9]585        for( m = gcm; m; m = m->next )
586                if( g_strncasecmp( m->data, away, strlen( m->data ) ) == 0 )
587                {
588                        /* At least the Yahoo! module works better if message
589                           contains no data unless it adds something to what
590                           we have in state already. */
591                        if( strlen( m->data ) == strlen( away ) )
592                                *message = NULL;
593                       
594                        return m->data;
595                }
596       
[84b045d]597        for( i = 0; *imc_away_alias_list[i]; i ++ )
[226fce1]598        {
[34fbbf9]599                int keep_message;
600               
[84b045d]601                for( j = 0; imc_away_alias_list[i][j]; j ++ )
602                        if( g_strncasecmp( away, imc_away_alias_list[i][j], strlen( imc_away_alias_list[i][j] ) ) == 0 )
[34fbbf9]603                        {
604                                keep_message = strlen( away ) != strlen( imc_away_alias_list[i][j] );
[226fce1]605                                break;
[34fbbf9]606                        }
[226fce1]607               
[84b045d]608                if( !imc_away_alias_list[i][j] )        /* If we reach the end, this row */
[226fce1]609                        continue;                       /* is not what we want. Next!    */
610               
611                /* Now find an entry in this row which exists in gcm */
[84b045d]612                for( j = 0; imc_away_alias_list[i][j]; j ++ )
[226fce1]613                {
[34fbbf9]614                        for( m = gcm; m; m = m->next )
[84b045d]615                                if( g_strcasecmp( imc_away_alias_list[i][j], m->data ) == 0 )
[34fbbf9]616                                {
617                                        if( !keep_message )
618                                                *message = NULL;
619                                       
620                                        return imc_away_alias_list[i][j];
621                                }
[226fce1]622                }
[34fbbf9]623               
624                /* No need to look further, apparently this state doesn't
625                   have any good alias for this protocol. */
626                break;
[226fce1]627        }
628       
[34fbbf9]629        return NULL;
[226fce1]630}
[da3b536]631
[84b045d]632void imc_add_allow( struct im_connection *ic, char *handle )
[da3b536]633{
[0da65d5]634        if( g_slist_find_custom( ic->permit, handle, (GCompareFunc) ic->acc->prpl->handle_cmp ) == NULL )
[da3b536]635        {
[0da65d5]636                ic->permit = g_slist_prepend( ic->permit, g_strdup( handle ) );
[da3b536]637        }
638       
[0da65d5]639        ic->acc->prpl->add_permit( ic, handle );
[da3b536]640}
641
[84b045d]642void imc_rem_allow( struct im_connection *ic, char *handle )
[da3b536]643{
644        GSList *l;
645       
[0da65d5]646        if( ( l = g_slist_find_custom( ic->permit, handle, (GCompareFunc) ic->acc->prpl->handle_cmp ) ) )
[da3b536]647        {
648                g_free( l->data );
[0da65d5]649                ic->permit = g_slist_delete_link( ic->permit, l );
[da3b536]650        }
651       
[0da65d5]652        ic->acc->prpl->rem_permit( ic, handle );
[da3b536]653}
654
[84b045d]655void imc_add_block( struct im_connection *ic, char *handle )
[da3b536]656{
[0da65d5]657        if( g_slist_find_custom( ic->deny, handle, (GCompareFunc) ic->acc->prpl->handle_cmp ) == NULL )
[da3b536]658        {
[0da65d5]659                ic->deny = g_slist_prepend( ic->deny, g_strdup( handle ) );
[da3b536]660        }
661       
[0da65d5]662        ic->acc->prpl->add_deny( ic, handle );
[da3b536]663}
664
[84b045d]665void imc_rem_block( struct im_connection *ic, char *handle )
[da3b536]666{
667        GSList *l;
668       
[0da65d5]669        if( ( l = g_slist_find_custom( ic->deny, handle, (GCompareFunc) ic->acc->prpl->handle_cmp ) ) )
[da3b536]670        {
671                g_free( l->data );
[0da65d5]672                ic->deny = g_slist_delete_link( ic->deny, l );
[da3b536]673        }
674       
[0da65d5]675        ic->acc->prpl->rem_deny( ic, handle );
[da3b536]676}
[85023c6]677
678void imcb_clean_handle( struct im_connection *ic, char *handle )
679{
680        /* Accepts a handle and does whatever is necessary to make it
681           BitlBee-friendly. Currently this means removing everything
682           outside 33-127 (ASCII printable excl spaces), @ (only one
683           is allowed) and ! and : */
684        char out[strlen(handle)+1];
685        int s, d;
686       
687        s = d = 0;
688        while( handle[s] )
689        {
690                if( handle[s] > ' ' && handle[s] != '!' && handle[s] != ':' &&
691                    ( handle[s] & 0x80 ) == 0 )
692                {
693                        if( handle[s] == '@' )
694                        {
695                                /* See if we got an @ already? */
696                                out[d] = 0;
697                                if( strchr( out, '@' ) )
698                                        continue;
699                        }
700                       
701                        out[d++] = handle[s];
702                }
703                s ++;
704        }
705        out[d] = handle[s];
706       
707        strcpy( handle, out );
708}
Note: See TracBrowser for help on using the repository browser.