- Timestamp:
- 2015-02-20T22:50:54Z (9 years ago)
- Branches:
- master
- Children:
- 0b9daac, 3d45471, 7733b8c
- Parents:
- af359b4
- git-author:
- Indent <please@…> (19-02-15 05:47:20)
- git-committer:
- dequis <dx@…> (20-02-15 22:50:54)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
nick.c
raf359b4 r5ebff60 1 1 /********************************************************************\ 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * … … 34 34 35 35 /* Store handles in lower case and strip spaces, because AIM is braindead. */ 36 static char *clean_handle( const char *orig)37 { 38 char *new = g_malloc( strlen( orig ) + 1);36 static char *clean_handle(const char *orig) 37 { 38 char *new = g_malloc(strlen(orig) + 1); 39 39 int i = 0; 40 40 41 41 do { 42 if (*orig != ' ') 43 new[i++] = g_ascii_tolower( *orig);44 }45 while (*(orig++));46 42 if (*orig != ' ') { 43 new[i++] = g_ascii_tolower(*orig); 44 } 45 } while (*(orig++)); 46 47 47 return new; 48 48 } 49 49 50 void nick_set_raw( account_t *acc, const char *handle, const char *nick)51 { 52 char *store_handle, *store_nick = g_malloc( MAX_NICK_LENGTH + 1);50 void nick_set_raw(account_t *acc, const char *handle, const char *nick) 51 { 52 char *store_handle, *store_nick = g_malloc(MAX_NICK_LENGTH + 1); 53 53 irc_t *irc = (irc_t *) acc->bee->ui_data; 54 55 store_handle = clean_handle( handle);54 55 store_handle = clean_handle(handle); 56 56 store_nick[MAX_NICK_LENGTH] = '\0'; 57 strncpy( store_nick, nick, MAX_NICK_LENGTH);58 nick_strip( irc, store_nick);59 60 g_hash_table_replace( acc->nicks, store_handle, store_nick);61 } 62 63 void nick_set( bee_user_t *bu, const char *nick)64 { 65 nick_set_raw( bu->ic->acc, bu->handle, nick);66 } 67 68 char *nick_get( bee_user_t *bu)69 { 70 static char nick[MAX_NICK_LENGTH +1];57 strncpy(store_nick, nick, MAX_NICK_LENGTH); 58 nick_strip(irc, store_nick); 59 60 g_hash_table_replace(acc->nicks, store_handle, store_nick); 61 } 62 63 void nick_set(bee_user_t *bu, const char *nick) 64 { 65 nick_set_raw(bu->ic->acc, bu->handle, nick); 66 } 67 68 char *nick_get(bee_user_t *bu) 69 { 70 static char nick[MAX_NICK_LENGTH + 1]; 71 71 char *store_handle, *found_nick; 72 72 irc_t *irc = (irc_t *) bu->bee->ui_data; 73 74 memset( nick, 0, MAX_NICK_LENGTH + 1);75 76 store_handle = clean_handle( bu->handle);73 74 memset(nick, 0, MAX_NICK_LENGTH + 1); 75 76 store_handle = clean_handle(bu->handle); 77 77 /* Find out if we stored a nick for this person already. If not, try 78 78 to generate a sane nick automatically. */ 79 if( ( found_nick = g_hash_table_lookup( bu->ic->acc->nicks, store_handle ) ) ) 80 { 81 strncpy( nick, found_nick, MAX_NICK_LENGTH ); 82 } 83 else if( ( found_nick = nick_gen( bu ) ) ) 84 { 85 strncpy( nick, found_nick, MAX_NICK_LENGTH ); 86 g_free( found_nick ); 87 } 88 else 89 { 79 if ((found_nick = g_hash_table_lookup(bu->ic->acc->nicks, store_handle))) { 80 strncpy(nick, found_nick, MAX_NICK_LENGTH); 81 } else if ((found_nick = nick_gen(bu))) { 82 strncpy(nick, found_nick, MAX_NICK_LENGTH); 83 g_free(found_nick); 84 } else { 90 85 /* Keep this fallback since nick_gen() can return NULL in some cases. */ 91 86 char *s; 92 93 g_snprintf( nick, MAX_NICK_LENGTH, "%s", bu->handle);94 if ( ( s = strchr( nick, '@' ) ) )95 while ( *s )87 88 g_snprintf(nick, MAX_NICK_LENGTH, "%s", bu->handle); 89 if ((s = strchr(nick, '@'))) { 90 while (*s) { 96 91 *(s++) = 0; 97 98 nick_strip( irc, nick ); 99 if( set_getbool( &bu->bee->set, "lcnicks" ) ) 100 nick_lc( irc, nick ); 101 } 102 g_free( store_handle ); 103 92 } 93 } 94 95 nick_strip(irc, nick); 96 if (set_getbool(&bu->bee->set, "lcnicks")) { 97 nick_lc(irc, nick); 98 } 99 } 100 g_free(store_handle); 101 104 102 /* Make sure the nick doesn't collide with an existing one by adding 105 103 underscores and that kind of stuff, if necessary. */ 106 nick_dedupe( bu, nick);107 104 nick_dedupe(bu, nick); 105 108 106 return nick; 109 107 } 110 108 111 char *nick_gen( bee_user_t *bu)109 char *nick_gen(bee_user_t *bu) 112 110 { 113 111 gboolean ok = FALSE; /* Set to true once the nick contains something unique. */ 114 GString *ret = g_string_sized_new( MAX_NICK_LENGTH + 1);112 GString *ret = g_string_sized_new(MAX_NICK_LENGTH + 1); 115 113 char *rets; 116 114 irc_t *irc = (irc_t *) bu->bee->ui_data; 117 char *fmt = set_getstr( &bu->ic->acc->set, "nick_format" ) ? : 118 set_getstr( &bu->bee->set, "nick_format" ); 119 120 while( fmt && *fmt && ret->len < MAX_NICK_LENGTH ) 121 { 115 char *fmt = set_getstr(&bu->ic->acc->set, "nick_format") ? : 116 set_getstr(&bu->bee->set, "nick_format"); 117 118 while (fmt && *fmt && ret->len < MAX_NICK_LENGTH) { 122 119 char *part = NULL, chop = '\0', *asc = NULL, *s; 123 120 int len = INT_MAX; 124 125 if( *fmt != '%' ) 126 { 127 g_string_append_c( ret, *fmt ); 128 fmt ++; 121 122 if (*fmt != '%') { 123 g_string_append_c(ret, *fmt); 124 fmt++; 129 125 continue; 130 126 } 131 132 fmt ++; 133 while( *fmt ) 134 { 127 128 fmt++; 129 while (*fmt) { 135 130 /* -char means chop off everything from char */ 136 if( *fmt == '-' ) 137 { 131 if (*fmt == '-') { 138 132 chop = fmt[1]; 139 if( chop == '\0' ) 140 { 141 g_string_free( ret, TRUE ); 133 if (chop == '\0') { 134 g_string_free(ret, TRUE); 142 135 return NULL; 143 136 } 144 137 fmt += 2; 145 } 146 else if( g_ascii_isdigit( *fmt ) ) 147 { 138 } else if (g_ascii_isdigit(*fmt)) { 148 139 len = 0; 149 140 /* Grab a number. */ 150 while( g_ascii_isdigit( *fmt ) ) 151 len = len * 10 + ( *(fmt++) - '0' ); 152 } 153 else if( g_strncasecmp( fmt, "nick", 4 ) == 0 ) 154 { 141 while (g_ascii_isdigit(*fmt)) { 142 len = len * 10 + (*(fmt++) - '0'); 143 } 144 } else if (g_strncasecmp(fmt, "nick", 4) == 0) { 155 145 part = bu->nick ? : bu->handle; 156 146 fmt += 4; 157 147 ok |= TRUE; 158 148 break; 159 } 160 else if( g_strncasecmp( fmt, "handle", 6 ) == 0 ) 161 { 149 } else if (g_strncasecmp(fmt, "handle", 6) == 0) { 162 150 part = bu->handle; 163 151 fmt += 6; 164 152 ok |= TRUE; 165 153 break; 166 } 167 else if( g_strncasecmp( fmt, "full_name", 9 ) == 0 ) 168 { 154 } else if (g_strncasecmp(fmt, "full_name", 9) == 0) { 169 155 part = bu->fullname; 170 156 fmt += 9; 171 157 ok |= part && *part; 172 158 break; 173 } 174 else if( g_strncasecmp( fmt, "first_name", 10 ) == 0 ) 175 { 159 } else if (g_strncasecmp(fmt, "first_name", 10) == 0) { 176 160 part = bu->fullname; 177 161 fmt += 10; … … 179 163 chop = ' '; 180 164 break; 181 } 182 else if( g_strncasecmp( fmt, "group", 5 ) == 0 ) 183 { 165 } else if (g_strncasecmp(fmt, "group", 5) == 0) { 184 166 part = bu->group ? bu->group->name : NULL; 185 167 fmt += 5; 186 168 break; 187 } 188 else if( g_strncasecmp( fmt, "account", 7 ) == 0 ) 189 { 169 } else if (g_strncasecmp(fmt, "account", 7) == 0) { 190 170 part = bu->ic->acc->tag; 191 171 fmt += 7; 192 172 break; 193 } 194 else 195 { 196 g_string_free( ret, TRUE ); 173 } else { 174 g_string_free(ret, TRUE); 197 175 return NULL; 198 176 } 199 177 } 200 201 if ( !part )178 179 if (!part) { 202 180 continue; 203 181 } 182 204 183 /* Credits to Josay_ in #bitlbee for this idea. //TRANSLIT 205 184 should do lossy/approximate conversions, so letters with 206 185 accents don't just get stripped. Note that it depends on 207 186 LC_CTYPE being set to something other than C/POSIX. */ 208 if( !( irc && irc->status & IRC_UTF8_NICKS ) ) 209 part = asc = g_convert_with_fallback( part, -1, "ASCII//TRANSLIT", 210 "UTF-8", "", NULL, NULL, NULL ); 211 212 if( part && chop && ( s = strchr( part, chop ) ) ) 213 len = MIN( len, s - part ); 214 215 if( part ) 216 { 217 if( len < INT_MAX ) 218 g_string_append_len( ret, part, len ); 219 else 220 g_string_append( ret, part ); 221 } 222 g_free( asc ); 223 } 224 225 rets = g_string_free( ret, FALSE ); 226 if( ok && rets && *rets ) 227 { 228 nick_strip( irc, rets ); 229 truncate_utf8( rets, MAX_NICK_LENGTH ); 187 if (!(irc && irc->status & IRC_UTF8_NICKS)) { 188 part = asc = g_convert_with_fallback(part, -1, "ASCII//TRANSLIT", 189 "UTF-8", "", NULL, NULL, NULL); 190 } 191 192 if (part && chop && (s = strchr(part, chop))) { 193 len = MIN(len, s - part); 194 } 195 196 if (part) { 197 if (len < INT_MAX) { 198 g_string_append_len(ret, part, len); 199 } else { 200 g_string_append(ret, part); 201 } 202 } 203 g_free(asc); 204 } 205 206 rets = g_string_free(ret, FALSE); 207 if (ok && rets && *rets) { 208 nick_strip(irc, rets); 209 truncate_utf8(rets, MAX_NICK_LENGTH); 230 210 return rets; 231 211 } 232 g_free( rets);212 g_free(rets); 233 213 return NULL; 234 214 } 235 215 236 void nick_dedupe( bee_user_t *bu, char nick[MAX_NICK_LENGTH+1])237 { 238 irc_t *irc = (irc_t *) bu->bee->ui_data;216 void nick_dedupe(bee_user_t *bu, char nick[MAX_NICK_LENGTH + 1]) 217 { 218 irc_t *irc = (irc_t *) bu->bee->ui_data; 239 219 int inf_protection = 256; 240 220 irc_user_t *iu; 241 221 242 222 /* Now, find out if the nick is already in use at the moment, and make 243 223 subtle changes to make it unique. */ 244 while( !nick_ok( irc, nick ) || 245 ( ( iu = irc_user_by_name( irc, nick ) ) && iu->bu != bu ) ) 246 { 247 if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) ) 248 { 249 nick[strlen(nick)+1] = 0; 224 while (!nick_ok(irc, nick) || 225 ((iu = irc_user_by_name(irc, nick)) && iu->bu != bu)) { 226 if (strlen(nick) < (MAX_NICK_LENGTH - 1)) { 227 nick[strlen(nick) + 1] = 0; 250 228 nick[strlen(nick)] = '_'; 251 } 252 else 253 { 229 } else { 254 230 /* We've got no more space for underscores, 255 231 so truncate it and replace the last three 256 232 chars with a random "_XX" suffix */ 257 int len = truncate_utf8( nick, MAX_NICK_LENGTH - 3);233 int len = truncate_utf8(nick, MAX_NICK_LENGTH - 3); 258 234 nick[len] = '_'; 259 g_snprintf(nick + len + 1, 3, "%2x", rand() ); 260 } 261 262 if( inf_protection-- == 0 ) 263 { 264 g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() ); 265 266 irc_rootmsg( irc, "Warning: Something went wrong while trying " 267 "to generate a nickname for contact %s on %s.", 268 bu->handle, bu->ic->acc->tag ); 269 irc_rootmsg( irc, "This might be a bug in BitlBee, or the result " 270 "of a faulty nick_format setting. Will use %s " 271 "instead.", nick ); 272 235 g_snprintf(nick + len + 1, 3, "%2x", rand()); 236 } 237 238 if (inf_protection-- == 0) { 239 g_snprintf(nick, MAX_NICK_LENGTH + 1, "xx%x", rand()); 240 241 irc_rootmsg(irc, "Warning: Something went wrong while trying " 242 "to generate a nickname for contact %s on %s.", 243 bu->handle, bu->ic->acc->tag); 244 irc_rootmsg(irc, "This might be a bug in BitlBee, or the result " 245 "of a faulty nick_format setting. Will use %s " 246 "instead.", nick); 247 273 248 break; 274 249 } … … 278 253 /* Just check if there is a nickname set for this buddy or if we'd have to 279 254 generate one. */ 280 int nick_saved( bee_user_t *bu)255 int nick_saved(bee_user_t *bu) 281 256 { 282 257 char *store_handle, *found; 283 284 store_handle = clean_handle( bu->handle);285 found = g_hash_table_lookup( bu->ic->acc->nicks, store_handle);286 g_free( store_handle);287 258 259 store_handle = clean_handle(bu->handle); 260 found = g_hash_table_lookup(bu->ic->acc->nicks, store_handle); 261 g_free(store_handle); 262 288 263 return found != NULL; 289 264 } 290 265 291 void nick_del( bee_user_t *bu)292 { 293 g_hash_table_remove( bu->ic->acc->nicks, bu->handle);294 } 295 296 297 void nick_strip( irc_t *irc, char *nick)266 void nick_del(bee_user_t *bu) 267 { 268 g_hash_table_remove(bu->ic->acc->nicks, bu->handle); 269 } 270 271 272 void nick_strip(irc_t *irc, char *nick) 298 273 { 299 274 int len = 0; 300 301 if( irc && ( irc->status & IRC_UTF8_NICKS ) ) 302 { 275 276 if (irc && (irc->status & IRC_UTF8_NICKS)) { 303 277 gunichar c; 304 char *p = nick, *n, tmp[strlen(nick)+1]; 305 306 while( p && *p ) 307 { 308 c = g_utf8_get_char_validated( p, -1 ); 309 n = g_utf8_find_next_char( p, NULL ); 310 311 if( ( c < 0x7f && !( strchr( nick_lc_chars, c ) || 312 strchr( nick_uc_chars, c ) ) ) || 313 !g_unichar_isgraph( c ) ) 314 { 315 strcpy( tmp, n ); 316 strcpy( p, tmp ); 317 } 318 else 278 char *p = nick, *n, tmp[strlen(nick) + 1]; 279 280 while (p && *p) { 281 c = g_utf8_get_char_validated(p, -1); 282 n = g_utf8_find_next_char(p, NULL); 283 284 if ((c < 0x7f && !(strchr(nick_lc_chars, c) || 285 strchr(nick_uc_chars, c))) || 286 !g_unichar_isgraph(c)) { 287 strcpy(tmp, n); 288 strcpy(p, tmp); 289 } else { 319 290 p = n; 320 } 321 if( p ) 291 } 292 } 293 if (p) { 322 294 len = p - nick; 323 } 324 else 325 { 295 } 296 } else { 326 297 int i; 327 328 for( i = len = 0; nick[i] && len < MAX_NICK_LENGTH; i++ ) 329 { 330 if( strchr( nick_lc_chars, nick[i] ) || 331 strchr( nick_uc_chars, nick[i] ) ) 332 { 298 299 for (i = len = 0; nick[i] && len < MAX_NICK_LENGTH; i++) { 300 if (strchr(nick_lc_chars, nick[i]) || 301 strchr(nick_uc_chars, nick[i])) { 333 302 nick[len] = nick[i]; 334 303 len++; … … 336 305 } 337 306 } 338 if( g_ascii_isdigit( nick[0] ) ) 339 { 307 if (g_ascii_isdigit(nick[0])) { 340 308 char *orig; 341 309 342 310 /* First character of a nick can't be a digit, so insert an 343 311 underscore if necessary. */ 344 orig = g_strdup( nick);345 g_snprintf( nick, MAX_NICK_LENGTH, "_%s", orig);346 g_free( orig);347 len 348 } 349 while ( len <= MAX_NICK_LENGTH )312 orig = g_strdup(nick); 313 g_snprintf(nick, MAX_NICK_LENGTH, "_%s", orig); 314 g_free(orig); 315 len++; 316 } 317 while (len <= MAX_NICK_LENGTH) { 350 318 nick[len++] = '\0'; 351 } 352 353 gboolean nick_ok( irc_t *irc, const char *nick ) 319 } 320 } 321 322 gboolean nick_ok(irc_t *irc, const char *nick) 354 323 { 355 324 const char *s; 356 325 357 326 /* Empty/long nicks are not allowed, nor numbers at [0] */ 358 if ( !*nick || g_ascii_isdigit( nick[0] ) || strlen( nick ) > MAX_NICK_LENGTH )327 if (!*nick || g_ascii_isdigit(nick[0]) || strlen(nick) > MAX_NICK_LENGTH) { 359 328 return 0; 360 361 if( irc && ( irc->status & IRC_UTF8_NICKS ) ) 362 {329 } 330 331 if (irc && (irc->status & IRC_UTF8_NICKS)) { 363 332 gunichar c; 364 333 const char *p = nick, *n; 365 366 while( p && *p ) 367 { 368 c = g_utf8_get_char_validated( p, -1 ); 369 n = g_utf8_find_next_char( p, NULL ); 370 371 if( ( c < 0x7f && !( strchr( nick_lc_chars, c ) || 372 strchr( nick_uc_chars, c ) ) ) || 373 !g_unichar_isgraph( c ) ) 374 { 334 335 while (p && *p) { 336 c = g_utf8_get_char_validated(p, -1); 337 n = g_utf8_find_next_char(p, NULL); 338 339 if ((c < 0x7f && !(strchr(nick_lc_chars, c) || 340 strchr(nick_uc_chars, c))) || 341 !g_unichar_isgraph(c)) { 375 342 return FALSE; 376 343 } 377 344 p = n; 378 345 } 379 } 380 else 381 { 382 for( s = nick; *s; s ++ ) 383 if( !strchr( nick_lc_chars, *s ) && !strchr( nick_uc_chars, *s ) ) 346 } else { 347 for (s = nick; *s; s++) { 348 if (!strchr(nick_lc_chars, *s) && !strchr(nick_uc_chars, *s)) { 384 349 return FALSE; 385 } 386 350 } 351 } 352 } 353 387 354 return TRUE; 388 355 } 389 356 390 int nick_lc( irc_t *irc, char *nick)357 int nick_lc(irc_t *irc, char *nick) 391 358 { 392 359 static char tab[128] = { 0 }; 393 360 int i; 394 395 if ( tab['A'] == 0 )396 for ( i = 0; nick_lc_chars[i]; i ++ )397 {398 tab[(int) nick_uc_chars[i]] = nick_lc_chars[i];399 tab[(int)nick_lc_chars[i]] = nick_lc_chars[i];400 401 402 if ( irc && ( irc->status & IRC_UTF8_NICKS ) )403 {404 gchar *down = g_utf8_strdown( nick, -1 );405 if( strlen( down ) > strlen( nick ) )406 {407 truncate_utf8( down, strlen( nick ));408 }409 strcpy( nick, down );410 g_free( down ); 411 }412 413 for( i = 0; nick[i]; i ++ )414 if( ((guchar)nick[i]) < 0x7f )415 nick[i] = tab[(guchar)nick[i]];416 417 return nick_ok( irc, nick);418 } 419 420 int nick_cmp( irc_t *irc, const char *a, const char *b)361 362 if (tab['A'] == 0) { 363 for (i = 0; nick_lc_chars[i]; i++) { 364 tab[(int) nick_uc_chars[i]] = nick_lc_chars[i]; 365 tab[(int) nick_lc_chars[i]] = nick_lc_chars[i]; 366 } 367 } 368 369 if (irc && (irc->status & IRC_UTF8_NICKS)) { 370 gchar *down = g_utf8_strdown(nick, -1); 371 if (strlen(down) > strlen(nick)) { 372 truncate_utf8(down, strlen(nick)); 373 } 374 strcpy(nick, down); 375 g_free(down); 376 } 377 378 for (i = 0; nick[i]; i++) { 379 if (((guchar) nick[i]) < 0x7f) { 380 nick[i] = tab[(guchar) nick[i]]; 381 } 382 } 383 384 return nick_ok(irc, nick); 385 } 386 387 int nick_cmp(irc_t *irc, const char *a, const char *b) 421 388 { 422 389 char aa[1024] = "", bb[1024] = ""; 423 424 strncpy( aa, a, sizeof( aa ) - 1 ); 425 strncpy( bb, b, sizeof( bb ) - 1 ); 426 if( nick_lc( irc, aa ) && nick_lc( irc, bb ) ) 427 { 428 return( strcmp( aa, bb ) ); 429 } 430 else 431 { 432 return( -1 ); /* Hmm... Not a clear answer.. :-/ */ 433 } 434 } 390 391 strncpy(aa, a, sizeof(aa) - 1); 392 strncpy(bb, b, sizeof(bb) - 1); 393 if (nick_lc(irc, aa) && nick_lc(irc, bb)) { 394 return(strcmp(aa, bb)); 395 } else { 396 return(-1); /* Hmm... Not a clear answer.. :-/ */ 397 } 398 }
Note: See TracChangeset
for help on using the changeset viewer.