diff options
| author | Jelmer Vernooij <jelmer@samba.org> | 2008-04-02 16:22:57 +0200 | 
|---|---|---|
| committer | Jelmer Vernooij <jelmer@samba.org> | 2008-04-02 16:22:57 +0200 | 
| commit | 85d7b857fb8ca8e3c03d4abb3368a0966760630c (patch) | |
| tree | a16163e557bcae3af41bde7d2d771d64ca248a97 /nick.c | |
| parent | 875ad4201402b1a8f80ba22a6cdcdb152c6e5510 (diff) | |
| parent | dd345753c1742905c9f81aa71d8b09109fbc5456 (diff) | |
Merge trunk.
Diffstat (limited to 'nick.c')
| -rw-r--r-- | nick.c | 165 | 
1 files changed, 86 insertions, 79 deletions
| @@ -1,7 +1,7 @@    /********************************************************************\    * BitlBee -- An IRC to other IM-networks gateway                     *    *                                                                    * -  * Copyright 2002-2004 Wilmer van der Gaast and others                * +  * Copyright 2002-2007 Wilmer van der Gaast and others                *    \********************************************************************/  /* Some stuff to fetch, save and handle nicknames for your buddies      */ @@ -26,50 +26,47 @@  #define BITLBEE_CORE  #include "bitlbee.h" -void nick_set( irc_t *irc, const char *handle, struct prpl *proto, const char *nick ) +/* Store handles in lower case and strip spaces, because AIM is braindead. */ +static char *clean_handle( const char *orig )  { -	nick_t *m = NULL, *n = irc->nicks; +	char *new = g_malloc( strlen( orig ) + 1 ); +	int i = 0; -	while( n ) -	{ -		if( ( g_strcasecmp( n->handle, handle ) == 0 ) && n->proto == proto ) -		{ -			g_free( n->nick ); -			n->nick = nick_dup( nick ); -			nick_strip( n->nick ); -			 -			return; -		} -		n = ( m = n )->next;	// :-P +	do { +		if (*orig != ' ') +			new[i++] = tolower( *orig );  	} +	while (*(orig++)); -	if( m ) -		n = m->next = g_new0( nick_t, 1 ); -	else -		n = irc->nicks = g_new0( nick_t, 1 ); +	return new; +} + +void nick_set( account_t *acc, const char *handle, const char *nick ) +{ +	char *store_handle, *store_nick = g_malloc( MAX_NICK_LENGTH + 1 ); -	n->handle = g_strdup( handle ); -	n->proto = proto; -	n->nick = nick_dup( nick ); +	store_handle = clean_handle( handle ); +	strncpy( store_nick, nick, MAX_NICK_LENGTH ); +	nick_strip( store_nick ); -	nick_strip( n->nick ); +	g_hash_table_replace( acc->nicks, store_handle, store_nick );  } -char *nick_get( irc_t *irc, const char *handle, struct prpl *proto, const char *realname ) +char *nick_get( account_t *acc, const char *handle )  {  	static char nick[MAX_NICK_LENGTH+1]; -	nick_t *n = irc->nicks; -	int inf_protection = 256; +	char *store_handle, *found_nick;  	memset( nick, 0, MAX_NICK_LENGTH + 1 ); -	while( n && !*nick ) -		if( ( n->proto == proto ) && ( g_strcasecmp( n->handle, handle ) == 0 ) ) -			strcpy( nick, n->nick ); -		else -			n = n->next; -	 -	if( !n ) +	store_handle = clean_handle( handle ); +	/* Find out if we stored a nick for this person already. If not, try +	   to generate a sane nick automatically. */ +	if( ( found_nick = g_hash_table_lookup( acc->nicks, store_handle ) ) ) +	{ +		strncpy( nick, found_nick, MAX_NICK_LENGTH ); +	} +	else  	{  		char *s; @@ -78,18 +75,26 @@ char *nick_get( irc_t *irc, const char *handle, struct prpl *proto, const char *  			while( *s )  				*(s++) = 0; -		/* All-digit handles (mainly ICQ UINs) aren't cool, try to -		   use the realname instead. */ -		for( s = nick; *s && isdigit( *s ); s ++ ); -		if( !*s && realname && *realname ) -			g_snprintf( nick, MAX_NICK_LENGTH, "%s", realname ); -		  		nick_strip( nick ); -		if (set_getint(irc, "lcnicks"))  +		if( set_getbool( &acc->irc->set, "lcnicks" ) )  			nick_lc( nick );  	} +	g_free( store_handle ); -	while( !nick_ok( nick ) || user_find( irc, nick ) ) +	/* Make sure the nick doesn't collide with an existing one by adding +	   underscores and that kind of stuff, if necessary. */ +	nick_dedupe( acc, handle, nick ); +	 +	return nick; +} + +void nick_dedupe( account_t *acc, const char *handle, char nick[MAX_NICK_LENGTH+1] ) +{ +	int inf_protection = 256; +	 +	/* Now, find out if the nick is already in use at the moment, and make +	   subtle changes to make it unique. */ +	while( !nick_ok( nick ) || user_find( acc->irc, nick ) )  	{  		if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) )  		{ @@ -105,64 +110,57 @@ char *nick_get( irc_t *irc, const char *handle, struct prpl *proto, const char *  		{  			int i; -			irc_usermsg( irc, "WARNING: Almost had an infinite loop in nick_get()! " -			                  "This used to be a fatal BitlBee bug, but we tried to fix it. " -			                  "This message should *never* appear anymore. " -			                  "If it does, please *do* send us a bug report! " -			                  "Please send all the following lines in your report:" ); +			irc_usermsg( acc->irc, "Warning: Almost had an infinite loop in nick_get()! " +			                       "This used to be a fatal BitlBee bug, but we tried to fix it. " +			                       "This message should *never* appear anymore. " +			                       "If it does, please *do* send us a bug report! " +			                       "Please send all the following lines in your report:" ); -			irc_usermsg( irc, "Trying to get a sane nick for handle %s", handle ); +			irc_usermsg( acc->irc, "Trying to get a sane nick for handle %s", handle );  			for( i = 0; i < MAX_NICK_LENGTH; i ++ ) -				irc_usermsg( irc, "Char %d: %c/%d", i, nick[i], nick[i] ); +				irc_usermsg( acc->irc, "Char %d: %c/%d", i, nick[i], nick[i] ); -			irc_usermsg( irc, "FAILED. Returning an insane nick now. Things might break. " -			                  "Good luck, and please don't forget to paste the lines up here " -			                  "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" ); +			irc_usermsg( acc->irc, "FAILED. Returning an insane nick now. Things might break. " +			                       "Good luck, and please don't forget to paste the lines up here " +			                       "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" );  			g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() );  			break;  		}  	} -	 -	return( nick );  } -void nick_del( irc_t *irc, const char *nick ) +/* Just check if there is a nickname set for this buddy or if we'd have to +   generate one. */ +int nick_saved( account_t *acc, const char *handle )  { -	nick_t *l = NULL, *n = irc->nicks; +	char *store_handle, *found; -	while( n ) -	{ -		if( g_strcasecmp( n->nick, nick ) == 0 ) -		{ -			if( l ) -				l->next = n->next; -			else -				irc->nicks = n->next; -			 -			g_free( n->handle ); -			g_free( n->nick ); -			g_free( n ); -			 -			break; -		} -		n = (l=n)->next; -	} +	store_handle = clean_handle( handle ); +	found = g_hash_table_lookup( acc->nicks, store_handle ); +	g_free( store_handle ); +	 +	return found != NULL; +} + +void nick_del( account_t *acc, const char *handle ) +{ +	g_hash_table_remove( acc->nicks, handle );  }  /* Character maps, _lc_[x] == _uc_[x] (but uppercase), according to the RFC's.     With one difference, we allow dashes. */ -static char *nick_lc_chars = "0123456789abcdefghijklmnopqrstuvwxyz{}^-_|"; -static char *nick_uc_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[]~-_\\"; +static char *nick_lc_chars = "0123456789abcdefghijklmnopqrstuvwxyz{}^`-_|"; +static char *nick_uc_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[]~`-_\\"; -void nick_strip( char * nick ) +void nick_strip( char *nick )  {  	int i, j; -	for( i = j = 0; nick[i] && i < MAX_NICK_LENGTH; i++ ) +	for( i = j = 0; nick[i] && j < MAX_NICK_LENGTH; i++ )  	{  		if( strchr( nick_lc_chars, nick[i] ) ||   		    strchr( nick_uc_chars, nick[i] ) ) @@ -171,7 +169,16 @@ void nick_strip( char * nick )  			j++;  		}  	} -	while( j < MAX_NICK_LENGTH ) +	if( isdigit( nick[0] ) ) +	{ +		char *orig; +		 +		orig = g_strdup( nick ); +		g_snprintf( nick, MAX_NICK_LENGTH, "_%s", orig ); +		g_free( orig ); +		j ++; +	} +	while( j <= MAX_NICK_LENGTH )  		nick[j++] = '\0';  } @@ -179,8 +186,8 @@ int nick_ok( const char *nick )  {  	const char *s; -	/* Empty/long nicks are not allowed */ -	if( !*nick || strlen( nick ) > MAX_NICK_LENGTH ) +	/* Empty/long nicks are not allowed, nor numbers at [0] */ +	if( !*nick || isdigit( nick[0] ) || strlen( nick ) > MAX_NICK_LENGTH )  		return( 0 );  	for( s = nick; *s; s ++ ) @@ -192,7 +199,7 @@ int nick_ok( const char *nick )  int nick_lc( char *nick )  { -	static char tab[256] = { 0 }; +	static char tab[128] = { 0 };  	int i;  	if( tab['A'] == 0 ) | 
