/* * G_SanitizeUserString */ static int G_SanitizeUserString( char *string, size_t size ) { static char *colorless = NULL; static size_t colorless_size = 0; int i, c_ascii; // life is hard, UTF-8 will have to go strip_highchars( string ); COM_SanitizeColorString( va( "%s", string ), string, size, -1, COLOR_WHITE ); Q_trim( string ); if( colorless_size < strlen( string ) + 1 ) { colorless_size = strlen( string ) + 1; G_Free( colorless ); colorless = ( char * )G_Malloc( colorless_size ); } Q_strncpyz( colorless, COM_RemoveColorTokens( string ), colorless_size ); // require at least one non-whitespace ascii char in the string // (this will upset people who would like to have a name entirely in a non-latin // script, but it makes damn sure you can't get an empty name by exploiting some // utf-8 decoder quirk) c_ascii = 0; for( i = 0; colorless[i]; i++ ) if( colorless[i] > 32 && colorless[i] < 127 ) c_ascii++; return c_ascii; }
/* * G_SetClan */ static void G_SetClan( edict_t *ent, const char *original_clan ) { const char *invalid_values[] = { "console", "spec", "bot", "coach", "tv", NULL }; char clan[MAX_CLANNAME_BYTES]; char colorless[MAX_CLANNAME_BYTES]; int i; int c_ascii; int maxchars; if( !ent->r.client ) return; // we allow NULL to be passed for clan name if( ent->r.svflags & SVF_FAKECLIENT ) original_clan = "BOT"; else if( !original_clan ) original_clan = ""; Q_strncpyz( clan, original_clan, sizeof( clan ) ); COM_Compress( clan ); c_ascii = G_SanitizeUserString( clan, sizeof( clan ) ); if( !c_ascii ) clan[0] = colorless[0] = '\0'; else Q_strncpyz( colorless, COM_RemoveColorTokens( clan ), sizeof( colorless ) ); if( !( ent->r.svflags & SVF_FAKECLIENT ) ) { for( i = 0; invalid_values[i] != NULL; i++ ) { if( !Q_strnicmp( colorless, invalid_values[i], strlen( invalid_values[i] ) ) ) { clan[0] = colorless[0] = '\0'; break; } } } // clan names can not contain spaces Q_chrreplace( clan, ' ', '_' ); // clan names can not start with an ampersand { char *t; int len; t = clan; while( *t == '&' ) t++; len = strlen( clan ) - (t - clan); if( clan != t ) memmove( clan, t, len + 1 ); } maxchars = MAX_CLANNAME_CHARS; // Limit the name to MAX_NAME_CHARS printable characters // (non-ascii utf-8 sequences are currently counted as 2 or more each, sorry) COM_SanitizeColorString( va( "%s", clan ), clan, sizeof( clan ), maxchars, COLOR_WHITE ); Q_strncpyz( ent->r.client->clanname, clan, sizeof( ent->r.client->clanname ) ); }
/* * G_SetName */ static void G_SetName( edict_t *ent, const char *original_name ) { const char *invalid_prefixes[] = { "console", "[team]", "[spec]", "[bot]", "[coach]", "[tv]", NULL }; edict_t *other; char name[MAX_NAME_BYTES]; char colorless[MAX_NAME_BYTES]; int i, trynum, trylen; int c_ascii; int maxchars; if( !ent->r.client ) return; // we allow NULL to be passed for name if( !original_name ) original_name = ""; Q_strncpyz( name, original_name, sizeof( name ) ); c_ascii = G_SanitizeUserString( name, sizeof( name ) ); if( !c_ascii ) Q_strncpyz( name, "Player", sizeof( name ) ); Q_strncpyz( colorless, COM_RemoveColorTokens( name ), sizeof( colorless ) ); if( !( ent->r.svflags & SVF_FAKECLIENT ) ) { for( i = 0; invalid_prefixes[i] != NULL; i++ ) { if( !Q_strnicmp( colorless, invalid_prefixes[i], strlen( invalid_prefixes[i] ) ) ) { Q_strncpyz( name, "Player", sizeof( name ) ); Q_strncpyz( colorless, COM_RemoveColorTokens( name ), sizeof( colorless ) ); break; } } } maxchars = MAX_NAME_CHARS; if( ent->r.client->isTV ) maxchars = min( maxchars + 10, MAX_NAME_BYTES-1 ); // Limit the name to MAX_NAME_CHARS printable characters // (non-ascii utf-8 sequences are currently counted as 2 or more each, sorry) COM_SanitizeColorString( va( "%s", name ), name, sizeof( name ), maxchars, COLOR_WHITE ); Q_strncpyz( colorless, COM_RemoveColorTokens( name ), sizeof( colorless ) ); trynum = 1; do { for( i = 0; i < gs.maxclients; i++ ) { other = game.edicts + 1 + i; if( !other->r.inuse || !other->r.client || other == ent ) continue; // if nick is already in use, try with (number) appended if( !Q_stricmp( colorless, COM_RemoveColorTokens( other->r.client->netname ) ) ) { if( trynum != 1 ) // remove last try name[strlen( name ) - strlen( va( "%s(%i)", S_COLOR_WHITE, trynum-1 ) )] = 0; // make sure there is enough space for the postfix trylen = strlen( va( "%s(%i)", S_COLOR_WHITE, trynum ) ); if( (int)strlen( colorless ) + trylen > maxchars ) { COM_SanitizeColorString( va( "%s", name ), name, sizeof( name ), maxchars - trylen, COLOR_WHITE ); Q_strncpyz( colorless, COM_RemoveColorTokens( name ), sizeof( colorless ) ); } // add the postfix Q_strncatz( name, va( "%s(%i)", S_COLOR_WHITE, trynum ), sizeof( name ) ); Q_strncpyz( colorless, COM_RemoveColorTokens( name ), sizeof( colorless ) ); // go trough all clients again trynum++; break; } } } while( i != gs.maxclients && trynum <= MAX_CLIENTS ); Q_strncpyz( ent->r.client->netname, name, sizeof( ent->r.client->netname ) ); }
/* * TV_Downstream_FixName * * Make name valid, so it's not used by anyone else or so. See G_SetName * Client can be given, so conflict with that client's name won't matter * The returned value will be overwritten by the next call to this function */ char *TV_Downstream_FixName( const char *original_name, client_t *client ) { const char *invalid_prefixes[] = { "console", "[team]", "[spec]", "[bot]", "[coach]", "[tv]", NULL }; client_t *other; static char name[MAX_NAME_BYTES]; char colorless[MAX_NAME_BYTES]; int i, trynum, trylen; int c_ascii; int maxchars; // we allow NULL to be passed for name if( !original_name ) original_name = ""; Q_strncpyz( name, original_name, sizeof( name ) ); // life is hard, UTF-8 will have to go strip_highchars( name ); COM_SanitizeColorString( va( "%s", name ), name, sizeof( name ), -1, COLOR_WHITE ); // remove leading whitespace while( name[0] == ' ' ) memmove( name, name + 1, strlen( name ) ); // remove trailing whitespace while( strlen( name ) && name[strlen(name)-1] == ' ' ) name[strlen(name)-1] = '\0'; Q_strncpyz( colorless, COM_RemoveColorTokens( name ), sizeof( colorless ) ); maxchars = MAX_NAME_CHARS; if( client && client->tv ) maxchars = min( maxchars + 10, MAX_NAME_BYTES-1 ); // require at least one non-whitespace ascii char in the name // (this will upset people who would like to have a name entirely in a non-latin // script, but it makes damn sure you can't get an empty name by exploiting some // utf-8 decoder quirk) c_ascii = 0; for( i = 0; colorless[i]; i++ ) if( colorless[i] > 32 && colorless[i] < 127 ) c_ascii++; if( !c_ascii ) { Q_strncpyz( name, "Player", sizeof( name ) ); Q_strncpyz( colorless, COM_RemoveColorTokens( name ), sizeof( colorless ) ); } for( i = 0; invalid_prefixes[i] != NULL; i++ ) { if( !Q_strnicmp( colorless, invalid_prefixes[i], strlen( invalid_prefixes[i] ) ) ) { Q_strncpyz( name, "Player", sizeof( name ) ); Q_strncpyz( colorless, COM_RemoveColorTokens( name ), sizeof( colorless ) ); } } trynum = 1; do { for( i = 0, other = tvs.clients; i < tv_maxclients->integer; i++, other++ ) { if( ( client && other == client ) || other->state == CS_FREE || other->state == CS_ZOMBIE ) continue; // if nick is already in use, try with (number) appended if( !Q_stricmp( colorless, COM_RemoveColorTokens( other->name ) ) ) { if( trynum != 1 ) // remove last try name[strlen( name ) - strlen( va( "%s(%i)", S_COLOR_WHITE, trynum-1 ) )] = 0; // make sure there is enough space for the postfix trylen = strlen( va( "%s(%i)", S_COLOR_WHITE, trynum ) ); if( (int)strlen( colorless ) + trylen > maxchars ) { COM_SanitizeColorString( va( "%s", name ), name, sizeof( name ), maxchars - trylen, COLOR_WHITE ); Q_strncpyz( colorless, COM_RemoveColorTokens( name ), sizeof( colorless ) ); } // add the postfix Q_strncatz( name, va( "%s(%i)", S_COLOR_WHITE, trynum ), sizeof( name ) ); Q_strncpyz( colorless, COM_RemoveColorTokens( name ), sizeof( colorless ) ); // go trough all clients again trynum++; break; } } } while( i != tv_maxclients->integer && trynum <= MAX_CLIENTS ); return name; }