/* =========== G_ClientCleanName ============ */ static void G_ClientCleanName( const char *in, char *out, int outSize ) { int len, colorlessLen; char *p; int spaces; qboolean escaped; qboolean invalid = qfalse; //save room for trailing null byte outSize--; len = 0; colorlessLen = 0; p = out; *p = 0; spaces = 0; for( ; *in; in++ ) { // don't allow leading spaces if( colorlessLen == 0 && *in == ' ' ) continue; // don't allow nonprinting characters or (dead) console keys if( *in < ' ' || *in > '}' || *in == '`' ) continue; // check colors if( Q_IsColorString( in ) ) { in++; // make sure room in dest for both chars if( len > outSize - 2 ) break; *out++ = Q_COLOR_ESCAPE; *out++ = *in; len += 2; continue; } else if( !g_emoticonsAllowedInNames.integer && G_IsEmoticon( in, &escaped ) ) { // make sure room in dest for both chars if( len > outSize - 2 ) break; *out++ = '['; *out++ = '['; len += 2; if( escaped ) in++; continue; } // don't allow too many consecutive spaces if( *in == ' ' ) { spaces++; if( spaces > 3 ) continue; } else spaces = 0; if( len > outSize - 1 ) break; *out++ = *in; colorlessLen++; len++; } *out = 0; // don't allow names beginning with "[skipnotify]" because it messes up /ignore-related code if( !Q_stricmpn( p, "[skipnotify]", 12 ) ) invalid = qtrue; // don't allow comment-beginning strings because it messes up various parsers if( strstr( p, "//" ) || strstr( p, "/*" ) ) invalid = qtrue; // don't allow empty names if( *p == 0 || colorlessLen == 0 ) invalid = qtrue; // if something made the name bad, put them back to UnnamedPlayer if( invalid ) Q_strncpyz( p, "UnnamedPlayer", outSize ); }
/* =========== G_ClientCleanName ============ */ static void G_ClientCleanName( const char *in, char *out, int outSize ) { int len, colorlessLen; char *p; int spaces; qboolean escaped; //save room for trailing null byte outSize--; len = 0; colorlessLen = 0; p = out; *p = 0; spaces = 0; for( ; *in; in++ ) { // don't allow leading spaces if( colorlessLen == 0 && *in == ' ' ) continue; // check colors if( Q_IsColorString( in ) ) { in++; // don't allow black in a name, period if( ColorIndex( *in ) == 0 ) continue; // make sure room in dest for both chars if( len > outSize - 2 ) break; *out++ = Q_COLOR_ESCAPE; *out++ = *in; len += 2; continue; } else if( !g_emoticonsAllowedInNames.integer && G_IsEmoticon( in, &escaped ) ) { // make sure room in dest for both chars if( len > outSize - 2 ) break; *out++ = '['; *out++ = '['; len += 2; if( escaped ) in++; continue; } // don't allow too many consecutive spaces if( *in == ' ' ) { spaces++; if( spaces > 3 ) continue; } else spaces = 0; if( len > outSize - 1 ) break; *out++ = *in; colorlessLen++; len++; } *out = 0; // don't allow empty names if( *p == 0 || colorlessLen == 0 ) Q_strncpyz( p, "UnnamedPlayer", outSize ); }
/* =========== G_ClientCleanName ============ */ static void G_ClientCleanName( const char *in, char *out, int outSize, gclient_t *client ) { --outSize; bool has_visible_characters = false; std::string out_string; bool hasletter = false; int spaces = 0; for ( const auto& token : Color::Parser( in ) ) { if ( out_string.size() + token.Size() > outSize ) { break; } if ( token.Type() == Color::Token::TokenType::CHARACTER ) { int cp = Q_UTF8_CodePoint(token.Begin()); // don't allow leading spaces // TODO: use a Unicode-aware isspace if ( !has_visible_characters && Str::cisspace( cp ) ) { continue; } // don't allow nonprinting characters or (dead) console keys // but do allow UTF-8 (unvalidated) if ( cp >= 0 && cp < ' ' ) { continue; } bool escaped_emote = false; // single trailing ^ will mess up some things if ( cp == Color::Constants::ESCAPE && !*token.End() ) { if ( out_string.size() + 2 > outSize ) { break; } out_string += Color::Constants::ESCAPE; } else if ( !g_emoticonsAllowedInNames.integer && G_IsEmoticon( in, &escaped_emote ) ) { if ( out_string.size() + 2 + token.Size() > outSize ) { break; } out_string += "[["; if ( escaped_emote ) { continue; } } if ( Q_Unicode_IsAlphaOrIdeo( cp ) ) { hasletter = true; } // don't allow too many consecutive spaces // TODO: use a Unicode-aware isspace if ( Str::cisspace( cp ) ) { spaces++; if ( spaces > 3 ) { continue; } } else { spaces = 0; has_visible_characters = true; } } else if ( token.Type() == Color::Token::TokenType::ESCAPE ) { has_visible_characters = true; } out_string.append(token.Begin(), token.Size()); } bool invalid = false; // don't allow names beginning with S_SKIPNOTIFY because it messes up /ignore-related code if ( !out_string.compare( 0, 12, S_SKIPNOTIFY ) ) { invalid = true; } // don't allow comment-beginning strings because it messes up various parsers if ( out_string.find( "//" ) != std::string::npos || out_string.find( "/*" ) != std::string::npos ) { out_string.erase( std::remove( out_string.begin(), out_string.end(), '/' ) ); } // don't allow empty names if ( out_string.empty() || !hasletter ) { invalid = true; } // don't allow names beginning with digits else if ( Str::cisdigit( out_string[0] ) ) { out_string.erase( out_string.begin(), std::find_if_not( out_string.begin(), out_string.end(), Str::cisdigit ) ); } // if something made the name bad, put them back to UnnamedPlayer if ( invalid ) { Q_strncpyz( out, G_UnnamedClientName( client ), outSize ); } else { Q_strncpyz( out, out_string.c_str(), outSize ); } }
/* =========== G_ClientCleanName ============ */ static void G_ClientCleanName( const char *in, char *out, int outSize, gclient_t *client ) { int len, colorlessLen; char *p; int spaces; qboolean escaped; qboolean invalid = qfalse; qboolean hasletter = qfalse; //save room for trailing null byte outSize--; len = 0; colorlessLen = 0; p = out; *p = 0; spaces = 0; for ( ; *in; in++ ) { int cp, w; // don't allow leading spaces if ( colorlessLen == 0 && *in == ' ' ) { continue; } // don't allow nonprinting characters or (dead) console keys // but do allow UTF-8 (unvalidated) if ( *in >= 0 && *in < ' ' ) { continue; } // check colors if ( Q_IsColorString( in ) ) { in++; // make sure room in dest for both chars if ( len > outSize - 2 ) { break; } *out++ = Q_COLOR_ESCAPE; *out++ = *in; len += 2; continue; } else if ( !g_emoticonsAllowedInNames.integer && G_IsEmoticon( in, &escaped ) ) { // make sure room in dest for both chars if ( len > outSize - 2 ) { break; } *out++ = '['; *out++ = '['; len += 2; if ( escaped ) { in++; } continue; } cp = Q_UTF8_CodePoint( in ); if ( Q_Unicode_IsAlphaOrIdeo( cp ) ) { hasletter = qtrue; } // don't allow too many consecutive spaces if ( *in == ' ' ) { spaces++; if ( spaces > 3 ) { continue; } } else { spaces = 0; } w = Q_UTF8_WidthCP( cp ); if ( len > outSize - w ) { break; } memcpy( out, in, w ); colorlessLen++; len += w; out += w; in += w - 1; // allow for loop increment } *out = 0; // don't allow names beginning with S_SKIPNOTIFY because it messes up /ignore-related code if ( !Q_strnicmp( p, S_SKIPNOTIFY, 12 ) ) { invalid = qtrue; } // don't allow comment-beginning strings because it messes up various parsers if ( strstr( p, "//" ) || strstr( p, "/*" ) ) { invalid = qtrue; } // don't allow empty names if ( *p == 0 || colorlessLen == 0 ) { invalid = qtrue; } // limit no. of code points if ( Q_UTF8_PrintStrlen( p ) > MAX_NAME_LENGTH_CP ) { invalid = qtrue; } // if something made the name bad, put them back to UnnamedPlayer if ( invalid || !hasletter ) { Q_strncpyz( p, G_UnnamedClientName( client ), outSize ); } }