source: nick.c @ b1f818b

Last change on this file since b1f818b was b1f818b, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-07-11T12:21:59Z

Use bee_user structs in all nick_* functions. Prepare for a nick_get() with
more flexible nickname generation.

  • Property mode set to 100644
File size: 6.8 KB
Line 
1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2010 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_raw( 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        store_nick[MAX_NICK_LENGTH] = '\0';
50        strncpy( store_nick, nick, MAX_NICK_LENGTH );
51        nick_strip( store_nick );
52       
53        g_hash_table_replace( acc->nicks, store_handle, store_nick );
54}
55
56void nick_set( bee_user_t *bu, const char *nick )
57{
58        nick_set_raw( bu->ic->acc, bu->handle, nick );
59}
60
61char *nick_get( bee_user_t *bu )
62{
63        static char nick[MAX_NICK_LENGTH+1];
64        char *store_handle, *found_nick;
65       
66        memset( nick, 0, MAX_NICK_LENGTH + 1 );
67       
68        store_handle = clean_handle( bu->handle );
69        /* Find out if we stored a nick for this person already. If not, try
70           to generate a sane nick automatically. */
71        if( ( found_nick = g_hash_table_lookup( bu->ic->acc->nicks, store_handle ) ) )
72        {
73                strncpy( nick, found_nick, MAX_NICK_LENGTH );
74        }
75        else
76        {
77                char *s;
78               
79                g_snprintf( nick, MAX_NICK_LENGTH, "%s", bu->handle );
80                if( ( s = strchr( nick, '@' ) ) )
81                        while( *s )
82                                *(s++) = 0;
83               
84                nick_strip( nick );
85                if( set_getbool( &bu->bee->set, "lcnicks" ) )
86                        nick_lc( nick );
87        }
88        g_free( store_handle );
89       
90        /* Make sure the nick doesn't collide with an existing one by adding
91           underscores and that kind of stuff, if necessary. */
92        nick_dedupe( bu, nick );
93       
94        return nick;
95}
96
97char *nick_gen( bee_user_t *bu )
98{
99        return NULL;
100}
101
102void nick_dedupe( bee_user_t *bu, char nick[MAX_NICK_LENGTH+1] )
103{
104        irc_t *irc = (irc_t*) bu->bee->ui_data;
105        int inf_protection = 256;
106       
107        /* Now, find out if the nick is already in use at the moment, and make
108           subtle changes to make it unique. */
109        while( !nick_ok( nick ) || irc_user_by_name( irc, nick ) )
110        {
111                if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) )
112                {
113                        nick[strlen(nick)+1] = 0;
114                        nick[strlen(nick)] = '_';
115                }
116                else
117                {
118                        nick[0] ++;
119                }
120               
121                if( inf_protection-- == 0 )
122                {
123                        int i;
124                       
125                        irc_usermsg( irc, "Warning: Almost had an infinite loop in nick_get()! "
126                                          "This used to be a fatal BitlBee bug, but we tried to fix it. "
127                                          "This message should *never* appear anymore. "
128                                          "If it does, please *do* send us a bug report! "
129                                          "Please send all the following lines in your report:" );
130                       
131                        irc_usermsg( irc, "Trying to get a sane nick for handle %s", bu->handle );
132                        for( i = 0; i < MAX_NICK_LENGTH; i ++ )
133                                irc_usermsg( irc, "Char %d: %c/%d", i, nick[i], nick[i] );
134                       
135                        irc_usermsg( irc, "FAILED. Returning an insane nick now. Things might break. "
136                                          "Good luck, and please don't forget to paste the lines up here "
137                                          "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" );
138                       
139                        g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() );
140                       
141                        break;
142                }
143        }
144}
145
146/* Just check if there is a nickname set for this buddy or if we'd have to
147   generate one. */
148int nick_saved( bee_user_t *bu )
149{
150        char *store_handle, *found;
151       
152        store_handle = clean_handle( bu->handle );
153        found = g_hash_table_lookup( bu->ic->acc->nicks, store_handle );
154        g_free( store_handle );
155       
156        return found != NULL;
157}
158
159void nick_del( bee_user_t *bu )
160{
161        g_hash_table_remove( bu->ic->acc->nicks, bu->handle );
162}
163
164
165/* Character maps, _lc_[x] == _uc_[x] (but uppercase), according to the RFC's.
166   With one difference, we allow dashes. */
167
168static char *nick_lc_chars = "0123456789abcdefghijklmnopqrstuvwxyz{}^`-_|";
169static char *nick_uc_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[]~`-_\\";
170
171void nick_strip( char *nick )
172{
173        int i, j;
174       
175        for( i = j = 0; nick[i] && j < MAX_NICK_LENGTH; i++ )
176        {
177                if( strchr( nick_lc_chars, nick[i] ) || 
178                    strchr( nick_uc_chars, nick[i] ) )
179                {
180                        nick[j] = nick[i];
181                        j++;
182                }
183        }
184        if( isdigit( nick[0] ) )
185        {
186                char *orig;
187               
188                orig = g_strdup( nick );
189                g_snprintf( nick, MAX_NICK_LENGTH, "_%s", orig );
190                g_free( orig );
191                j ++;
192        }
193        while( j <= MAX_NICK_LENGTH )
194                nick[j++] = '\0';
195}
196
197int nick_ok( const char *nick )
198{
199        const char *s;
200       
201        /* Empty/long nicks are not allowed, nor numbers at [0] */
202        if( !*nick || isdigit( nick[0] ) || strlen( nick ) > MAX_NICK_LENGTH )
203                return( 0 );
204       
205        for( s = nick; *s; s ++ )
206                if( !strchr( nick_lc_chars, *s ) && !strchr( nick_uc_chars, *s ) )
207                        return( 0 );
208       
209        return( 1 );
210}
211
212int nick_lc( char *nick )
213{
214        static char tab[128] = { 0 };
215        int i;
216       
217        if( tab['A'] == 0 )
218                for( i = 0; nick_lc_chars[i]; i ++ )
219                {
220                        tab[(int)nick_uc_chars[i]] = nick_lc_chars[i];
221                        tab[(int)nick_lc_chars[i]] = nick_lc_chars[i];
222                }
223       
224        for( i = 0; nick[i]; i ++ )
225        {
226                if( !tab[(int)nick[i]] )
227                        return( 0 );
228               
229                nick[i] = tab[(int)nick[i]];
230        }
231       
232        return( 1 );
233}
234
235int nick_uc( char *nick )
236{
237        static char tab[128] = { 0 };
238        int i;
239       
240        if( tab['A'] == 0 )
241                for( i = 0; nick_lc_chars[i]; i ++ )
242                {
243                        tab[(int)nick_uc_chars[i]] = nick_uc_chars[i];
244                        tab[(int)nick_lc_chars[i]] = nick_uc_chars[i];
245                }
246       
247        for( i = 0; nick[i]; i ++ )
248        {
249                if( !tab[(int)nick[i]] )
250                        return( 0 );
251               
252                nick[i] = tab[(int)nick[i]];
253        }
254       
255        return( 1 );
256}
257
258int nick_cmp( const char *a, const char *b )
259{
260        char aa[1024] = "", bb[1024] = "";
261       
262        strncpy( aa, a, sizeof( aa ) - 1 );
263        strncpy( bb, b, sizeof( bb ) - 1 );
264        if( nick_lc( aa ) && nick_lc( bb ) )
265        {
266                return( strcmp( aa, bb ) );
267        }
268        else
269        {
270                return( -1 );   /* Hmm... Not a clear answer.. :-/ */
271        }
272}
273
274char *nick_dup( const char *nick )
275{
276        return g_strndup( nick, MAX_NICK_LENGTH );
277}
Note: See TracBrowser for help on using the repository browser.