source: nick.c @ c737ba7

Last change on this file since c737ba7 was d323394c, checked in by Wilmer van der Gaast <wilmer@…>, at 2007-04-20T04:49:30Z

New code to use nicknames stored in ICQ contact lists.

  • Property mode set to 100644
File size: 6.2 KB
Line 
1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2007 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* Some stuff to fetch, save and handle nicknames for your buddies      */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23  Suite 330, Boston, MA  02111-1307  USA
24*/
25
26#define BITLBEE_CORE
27#include "bitlbee.h"
28
29/* Store handles in lower case and strip spaces, because AIM is braindead. */
30static char *clean_handle( const char *orig )
31{
32        char *new = g_malloc( strlen( orig ) + 1 );
33        int i = 0;
34       
35        do {
36                if (*orig != ' ')
37                        new[i++] = tolower( *orig );
38        }
39        while (*(orig++));
40       
41        return new;
42}
43
44void nick_set( account_t *acc, const char *handle, const char *nick )
45{
46        char *store_handle, *store_nick = g_malloc( MAX_NICK_LENGTH + 1 );
47       
48        store_handle = clean_handle( handle );
49        strncpy( store_nick, nick, MAX_NICK_LENGTH );
50        nick_strip( store_nick );
51       
52        g_hash_table_replace( acc->nicks, store_handle, store_nick );
53}
54
55char *nick_get( account_t *acc, const char *handle )
56{
57        static char nick[MAX_NICK_LENGTH+1];
58        char *store_handle, *found_nick;
59        int inf_protection = 256;
60       
61        memset( nick, 0, MAX_NICK_LENGTH + 1 );
62       
63        store_handle = clean_handle( handle );
64        /* Find out if we stored a nick for this person already. If not, try
65           to generate a sane nick automatically. */
66        if( ( found_nick = g_hash_table_lookup( acc->nicks, store_handle ) ) )
67        {
68                strncpy( nick, found_nick, MAX_NICK_LENGTH );
69        }
70        else
71        {
72                char *s;
73               
74                g_snprintf( nick, MAX_NICK_LENGTH, "%s", handle );
75                if( ( s = strchr( nick, '@' ) ) )
76                        while( *s )
77                                *(s++) = 0;
78               
79                nick_strip( nick );
80                if( set_getbool( &acc->irc->set, "lcnicks" ) )
81                        nick_lc( nick );
82        }
83        g_free( store_handle );
84       
85        /* Now, find out if the nick is already in use at the moment, and make
86           subtle changes to make it unique. */
87        while( !nick_ok( nick ) || user_find( acc->irc, nick ) )
88        {
89                if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) )
90                {
91                        nick[strlen(nick)+1] = 0;
92                        nick[strlen(nick)] = '_';
93                }
94                else
95                {
96                        nick[0] ++;
97                }
98               
99                if( inf_protection-- == 0 )
100                {
101                        int i;
102                       
103                        irc_usermsg( acc->irc, "WARNING: Almost had an infinite loop in nick_get()! "
104                                               "This used to be a fatal BitlBee bug, but we tried to fix it. "
105                                               "This message should *never* appear anymore. "
106                                               "If it does, please *do* send us a bug report! "
107                                               "Please send all the following lines in your report:" );
108                       
109                        irc_usermsg( acc->irc, "Trying to get a sane nick for handle %s", handle );
110                        for( i = 0; i < MAX_NICK_LENGTH; i ++ )
111                                irc_usermsg( acc->irc, "Char %d: %c/%d", i, nick[i], nick[i] );
112                       
113                        irc_usermsg( acc->irc, "FAILED. Returning an insane nick now. Things might break. "
114                                               "Good luck, and please don't forget to paste the lines up here "
115                                               "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" );
116                       
117                        g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() );
118                       
119                        break;
120                }
121        }
122       
123        return nick;
124}
125
126/* Just check if there is a nickname set for this buddy or if we'd have to
127   generate one. */
128int nick_saved( account_t *acc, const char *handle )
129{
130        char *store_handle, *found;
131       
132        store_handle = clean_handle( handle );
133        found = g_hash_table_lookup( acc->nicks, store_handle );
134        g_free( store_handle );
135       
136        return found != NULL;
137}
138
139void nick_del( account_t *acc, const char *handle )
140{
141        g_hash_table_remove( acc->nicks, handle );
142}
143
144
145/* Character maps, _lc_[x] == _uc_[x] (but uppercase), according to the RFC's.
146   With one difference, we allow dashes. */
147
148static char *nick_lc_chars = "0123456789abcdefghijklmnopqrstuvwxyz{}^-_|";
149static char *nick_uc_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[]~-_\\";
150
151void nick_strip( char * nick )
152{
153        int i, j;
154       
155        for( i = j = 0; nick[i] && j < MAX_NICK_LENGTH; i++ )
156        {
157                if( strchr( nick_lc_chars, nick[i] ) || 
158                    strchr( nick_uc_chars, nick[i] ) )
159                {
160                        nick[j] = nick[i];
161                        j++;
162                }
163        }
164        while( j <= MAX_NICK_LENGTH )
165                nick[j++] = '\0';
166}
167
168int nick_ok( const char *nick )
169{
170        const char *s;
171       
172        /* Empty/long nicks are not allowed */
173        if( !*nick || strlen( nick ) > MAX_NICK_LENGTH )
174                return( 0 );
175       
176        for( s = nick; *s; s ++ )
177                if( !strchr( nick_lc_chars, *s ) && !strchr( nick_uc_chars, *s ) )
178                        return( 0 );
179       
180        return( 1 );
181}
182
183int nick_lc( char *nick )
184{
185        static char tab[128] = { 0 };
186        int i;
187       
188        if( tab['A'] == 0 )
189                for( i = 0; nick_lc_chars[i]; i ++ )
190                {
191                        tab[(int)nick_uc_chars[i]] = nick_lc_chars[i];
192                        tab[(int)nick_lc_chars[i]] = nick_lc_chars[i];
193                }
194       
195        for( i = 0; nick[i]; i ++ )
196        {
197                if( !tab[(int)nick[i]] )
198                        return( 0 );
199               
200                nick[i] = tab[(int)nick[i]];
201        }
202       
203        return( 1 );
204}
205
206int nick_uc( char *nick )
207{
208        static char tab[128] = { 0 };
209        int i;
210       
211        if( tab['A'] == 0 )
212                for( i = 0; nick_lc_chars[i]; i ++ )
213                {
214                        tab[(int)nick_uc_chars[i]] = nick_uc_chars[i];
215                        tab[(int)nick_lc_chars[i]] = nick_uc_chars[i];
216                }
217       
218        for( i = 0; nick[i]; i ++ )
219        {
220                if( !tab[(int)nick[i]] )
221                        return( 0 );
222               
223                nick[i] = tab[(int)nick[i]];
224        }
225       
226        return( 1 );
227}
228
229int nick_cmp( const char *a, const char *b )
230{
231        char aa[1024] = "", bb[1024] = "";
232       
233        strncpy( aa, a, sizeof( aa ) - 1 );
234        strncpy( bb, b, sizeof( bb ) - 1 );
235        if( nick_lc( aa ) && nick_lc( bb ) )
236        {
237                return( strcmp( aa, bb ) );
238        }
239        else
240        {
241                return( -1 );   /* Hmm... Not a clear answer.. :-/ */
242        }
243}
244
245char *nick_dup( const char *nick )
246{
247        return g_strndup( nick, MAX_NICK_LENGTH );
248}
Note: See TracBrowser for help on using the repository browser.