source: nick.c @ f06894d

Last change on this file since f06894d was 5b52a48, checked in by Wilmer van der Gaast <wilmer@…>, at 2006-07-03T21:22:45Z

Implemented per-account nick lists instead of per-protocol nick lists.
nick_t is dead, instead nicks are just saves in a per-account_t GLib
hash table. While doing this, the import_buddies command finally died
and text_save() disappeared, because the old file format can't handle
most of the new features in this branch anyway.

Still have to implement support for the new nick lists in text_load()!

  • Property mode set to 100644
File size: 6.1 KB
Line 
1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2006 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, const char *realname )
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                /* All-digit handles (mainly ICQ UINs) aren't cool, try to
80                   use the realname instead. */
81                for( s = nick; *s && isdigit( *s ); s ++ );
82                if( !*s && realname && *realname )
83                        g_snprintf( nick, MAX_NICK_LENGTH, "%s", realname );
84               
85                nick_strip( nick );
86                if( set_getbool( &acc->irc->set, "lcnicks" ) )
87                        nick_lc( nick );
88        }
89        g_free( store_handle );
90       
91        /* Now, find out if the nick is already in use at the moment, and make
92           subtle changes to make it unique. */
93        while( !nick_ok( nick ) || user_find( acc->irc, nick ) )
94        {
95                if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) )
96                {
97                        nick[strlen(nick)+1] = 0;
98                        nick[strlen(nick)] = '_';
99                }
100                else
101                {
102                        nick[0] ++;
103                }
104               
105                if( inf_protection-- == 0 )
106                {
107                        int i;
108                       
109                        irc_usermsg( acc->irc, "WARNING: Almost had an infinite loop in nick_get()! "
110                                               "This used to be a fatal BitlBee bug, but we tried to fix it. "
111                                               "This message should *never* appear anymore. "
112                                               "If it does, please *do* send us a bug report! "
113                                               "Please send all the following lines in your report:" );
114                       
115                        irc_usermsg( acc->irc, "Trying to get a sane nick for handle %s", handle );
116                        for( i = 0; i < MAX_NICK_LENGTH; i ++ )
117                                irc_usermsg( acc->irc, "Char %d: %c/%d", i, nick[i], nick[i] );
118                       
119                        irc_usermsg( acc->irc, "FAILED. Returning an insane nick now. Things might break. "
120                                               "Good luck, and please don't forget to paste the lines up here "
121                                               "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" );
122                       
123                        g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() );
124                       
125                        break;
126                }
127        }
128       
129        return nick;
130}
131
132void nick_del( account_t *acc, const char *handle )
133{
134        g_hash_table_remove( acc->nicks, handle );
135}
136
137
138/* Character maps, _lc_[x] == _uc_[x] (but uppercase), according to the RFC's.
139   With one difference, we allow dashes. */
140
141static char *nick_lc_chars = "0123456789abcdefghijklmnopqrstuvwxyz{}^-_|";
142static char *nick_uc_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[]~-_\\";
143
144void nick_strip( char * nick )
145{
146        int i, j;
147       
148        for( i = j = 0; nick[i] && j < MAX_NICK_LENGTH; i++ )
149        {
150                if( strchr( nick_lc_chars, nick[i] ) || 
151                    strchr( nick_uc_chars, nick[i] ) )
152                {
153                        nick[j] = nick[i];
154                        j++;
155                }
156        }
157        while( j <= MAX_NICK_LENGTH )
158                nick[j++] = '\0';
159}
160
161int nick_ok( const char *nick )
162{
163        const char *s;
164       
165        /* Empty/long nicks are not allowed */
166        if( !*nick || strlen( nick ) > MAX_NICK_LENGTH )
167                return( 0 );
168       
169        for( s = nick; *s; s ++ )
170                if( !strchr( nick_lc_chars, *s ) && !strchr( nick_uc_chars, *s ) )
171                        return( 0 );
172       
173        return( 1 );
174}
175
176int nick_lc( char *nick )
177{
178        static char tab[256] = { 0 };
179        int i;
180       
181        if( tab['A'] == 0 )
182                for( i = 0; nick_lc_chars[i]; i ++ )
183                {
184                        tab[(int)nick_uc_chars[i]] = nick_lc_chars[i];
185                        tab[(int)nick_lc_chars[i]] = nick_lc_chars[i];
186                }
187       
188        for( i = 0; nick[i]; i ++ )
189        {
190                if( !tab[(int)nick[i]] )
191                        return( 0 );
192               
193                nick[i] = tab[(int)nick[i]];
194        }
195       
196        return( 1 );
197}
198
199int nick_uc( char *nick )
200{
201        static char tab[128] = { 0 };
202        int i;
203       
204        if( tab['A'] == 0 )
205                for( i = 0; nick_lc_chars[i]; i ++ )
206                {
207                        tab[(int)nick_uc_chars[i]] = nick_uc_chars[i];
208                        tab[(int)nick_lc_chars[i]] = nick_uc_chars[i];
209                }
210       
211        for( i = 0; nick[i]; i ++ )
212        {
213                if( !tab[(int)nick[i]] )
214                        return( 0 );
215               
216                nick[i] = tab[(int)nick[i]];
217        }
218       
219        return( 1 );
220}
221
222int nick_cmp( const char *a, const char *b )
223{
224        char aa[1024] = "", bb[1024] = "";
225       
226        strncpy( aa, a, sizeof( aa ) - 1 );
227        strncpy( bb, b, sizeof( bb ) - 1 );
228        if( nick_lc( aa ) && nick_lc( bb ) )
229        {
230                return( strcmp( aa, bb ) );
231        }
232        else
233        {
234                return( -1 );   /* Hmm... Not a clear answer.. :-/ */
235        }
236}
237
238char *nick_dup( const char *nick )
239{
240        return g_strndup( nick, MAX_NICK_LENGTH );
241}
Note: See TracBrowser for help on using the repository browser.