etqw-sdk/source/game/rules/UserGroup.cpp
2008-05-29 00:00:00 +00:00

613 lines
14 KiB
C++

// Copyright (C) 2007 Id Software, Inc.
//
#include "../precompiled.h"
#pragma hdrstop
#if defined( _DEBUG ) && !defined( ID_REDIRECT_NEWDELETE )
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "UserGroup.h"
#include "../Player.h"
#include "../guis/UIList.h"
typedef sdPair< const char*, userPermissionFlags_t > permissionName_t;
permissionName_t permissionNames[] = {
permissionName_t( "adminKick", PF_ADMIN_KICK ),
permissionName_t( "adminBan", PF_ADMIN_BAN ),
permissionName_t( "adminSetTeam", PF_ADMIN_SETTEAM ),
permissionName_t( "adminChangeCampaign", PF_ADMIN_CHANGE_CAMPAIGN ),
permissionName_t( "adminChangeMap", PF_ADMIN_CHANGE_MAP ),
permissionName_t( "adminGlobalMute", PF_ADMIN_GLOBAL_MUTE ),
permissionName_t( "adminGlobalVOIPMute", PF_ADMIN_GLOBAL_MUTE_VOIP ),
permissionName_t( "adminPlayerMute", PF_ADMIN_PLAYER_MUTE ),
permissionName_t( "adminPlayerVOIPMute", PF_ADMIN_PLAYER_MUTE_VOIP ),
permissionName_t( "adminWarn", PF_ADMIN_WARN ),
permissionName_t( "adminRestartMap", PF_ADMIN_RESTART_MAP ),
permissionName_t( "adminRestartCampaign", PF_ADMIN_RESTART_CAMPAIGN ),
permissionName_t( "adminStartMatch", PF_ADMIN_START_MATCH ),
permissionName_t( "adminExecConfig", PF_ADMIN_EXEC_CONFIG ),
permissionName_t( "adminShuffleTeams", PF_ADMIN_SHUFFLE_TEAMS ),
permissionName_t( "adminAddBot", PF_ADMIN_ADD_BOT ),
permissionName_t( "adminAdjustBots", PF_ADMIN_ADJUST_BOTS ),
permissionName_t( "adminDisableProficiency", PF_ADMIN_DISABLE_PROFICIENCY ),
permissionName_t( "adminSetTimeLimit", PF_ADMIN_SET_TIMELIMIT ),
permissionName_t( "adminSetTeamDamage", PF_ADMIN_SET_TEAMDAMAGE ),
permissionName_t( "adminSetTeamBalance", PF_ADMIN_SET_TEAMBALANCE ),
permissionName_t( "noBan", PF_NO_BAN ),
permissionName_t( "noKick", PF_NO_KICK ),
permissionName_t( "noMute", PF_NO_MUTE ),
permissionName_t( "noMuteVOIP", PF_NO_MUTE_VOIP ),
permissionName_t( "noWarn", PF_NO_WARN ),
permissionName_t( "quietLogin", PF_QUIET_LOGIN )
};
int numPermissionNames = _arraycount( permissionNames );
/*
===============================================================================
sdUserGroup
===============================================================================
*/
/*
============
sdUserGroup::sdUserGroup
============
*/
sdUserGroup::sdUserGroup( void ) : superUser( false ), voteLevel( -1 ), needsLogin( false ) {
}
/*
============
sdUserGroup::Write
============
*/
void sdUserGroup::Write( idBitMsg& msg ) const {
msg.WriteString( GetName() );
for ( int i = 0; i < flags.Size(); i++ ) {
msg.WriteLong( flags.GetDirect()[ i ] );
}
msg.WriteLong( controlGroups.Num() );
for ( int i = 0; i < controlGroups.Num(); i++ ) {
msg.WriteLong( controlGroups[ i ].second );
}
msg.WriteLong( voteLevel );
msg.WriteBool( needsLogin );
}
/*
============
sdUserGroup::Read
============
*/
void sdUserGroup::Read( const idBitMsg& msg ) {
char buffer[ 512 ];
msg.ReadString( buffer, sizeof( buffer ) );
SetName( buffer );
for ( int i = 0; i < flags.Size(); i++ ) {
flags.GetDirect()[ i ] = msg.ReadLong();
}
controlGroups.SetNum( msg.ReadLong() );
for ( int i = 0; i < controlGroups.Num(); i++ ) {
controlGroups[ i ].second = msg.ReadLong();
}
voteLevel = msg.ReadLong();
needsLogin = msg.ReadBool();
}
/*
============
sdUserGroup::Write
============
*/
void sdUserGroup::Write( idFile* file ) const {
file->WriteString( GetName() );
for ( int i = 0; i < flags.Size(); i++ ) {
file->WriteInt( flags.GetDirect()[ i ] );
}
file->WriteInt( controlGroups.Num() );
for ( int i = 0; i < controlGroups.Num(); i++ ) {
file->WriteInt( controlGroups[ i ].second );
}
file->WriteInt( voteLevel );
file->WriteBool( needsLogin );
}
/*
============
sdUserGroup::Read
============
*/
void sdUserGroup::Read( idFile* file ) {
file->ReadString( name );
for ( int i = 0; i < flags.Size(); i++ ) {
file->ReadInt( flags.GetDirect()[ i ] );
}
int count;
file->ReadInt( count );
controlGroups.SetNum( count );
for ( int i = 0; i < controlGroups.Num(); i++ ) {
file->ReadInt( controlGroups[ i ].second );
}
file->ReadInt( voteLevel );
file->ReadBool( needsLogin );
}
/*
============
sdUserGroup::ParseControl
============
*/
bool sdUserGroup::ParseControl( idLexer& src ) {
if ( !src.ExpectTokenString( "{" ) ) {
return false;
}
idToken token;
while ( true ) {
if ( !src.ReadToken( &token ) ) {
src.Warning( "Unexpected end of file" );
return false;
}
if ( token == "}" ) {
break;
}
sdPair< idStr, int >& control = controlGroups.Alloc();
control.first = token;
control.second = -1;
}
return true;
}
/*
============
sdUserGroup::Parse
============
*/
bool sdUserGroup::Parse( idLexer& src ) {
idToken token;
if ( !src.ReadToken( &token ) ) {
src.Warning( "No Name Specified" );
return false;
}
SetName( token );
if ( !src.ExpectTokenString( "{" ) ) {
return false;
}
while ( true ) {
if ( !src.ReadToken( &token ) ) {
src.Warning( "Unexpected end of file" );
return false;
}
if ( token == "}" ) {
break;
}
if ( token.Icmp( "password" ) == 0 ) {
if ( !src.ReadToken( &token ) ) {
src.Warning( "Unexpected end of file" );
return false;
}
// Gordon: The example file will have password set to password, this should never be a valid password
if ( token.Icmp( "password" ) != 0 ) {
SetPassword( token );
}
continue;
}
if ( token.Icmp( "control" ) == 0 ) {
if ( !ParseControl( src ) ) {
src.Warning( "Failed to parse control groups" );
return false;
}
continue;
}
if ( token.Icmp( "voteLevel" ) == 0 ) {
if ( !src.ReadToken( &token ) ) {
src.Warning( "Failed to parse voteLevel" );
return false;
}
voteLevel = token.GetIntValue();
continue;
}
int i;
for ( i = 0; i < numPermissionNames; i++ ) {
if ( idStr::Icmp( permissionNames[ i ].first, token ) ) {
continue;
}
GivePermission( permissionNames[ i ].second );
break;
}
if ( i != numPermissionNames ) {
continue;
}
src.Warning( "Unexpected token '%s'", token.c_str() );
return false;
}
return true;
}
/*
============
sdUserGroup::Parse
============
*/
void sdUserGroup::PostParseFixup( void ) {
sdUserGroupManagerLocal& groupManager = sdUserGroupManager::GetInstance();
for ( int i = 0; i < controlGroups.Num(); i++ ) {
sdPair< idStr, int >& control = controlGroups[ i ];
control.second = groupManager.FindGroup( control.first );
if ( control.second == -1 ) {
gameLocal.Warning( "sdUserGroup::PostParseFixup Control Group '%s' not found", control.first.c_str() );
}
}
}
/*
============
sdUserGroup::CanControl
============
*/
bool sdUserGroup::CanControl( const sdUserGroup& group ) const {
if ( superUser ) {
return true;
}
sdUserGroupManagerLocal& groupManager = sdUserGroupManager::GetInstance();
for ( int i = 0; i < controlGroups.Num(); i++ ) {
int index = controlGroups[ i ].second;
if ( index == -1 ) {
continue;
}
if ( &groupManager.GetGroup( index ) == &group ) {
return true;
}
}
return false;
}
/*
===============================================================================
sdUserGroupManagerLocal
===============================================================================
*/
/*
============
sdUserGroupManagerLocal::sdUserGroupManagerLocal
============
*/
sdUserGroupManagerLocal::sdUserGroupManagerLocal( void ) {
consoleGroup.SetName( "<CONSOLE>" ); // users coming from the console will use this user group which has full permissions
consoleGroup.MakeSuperUser();
defaultGroup = -1;
}
/*
============
sdUserGroupManagerLocal::sdUserGroupManagerLocal
============
*/
sdUserGroupManagerLocal::~sdUserGroupManagerLocal( void ) {
}
/*
============
sdUserGroupManagerLocal::Init
============
*/
void sdUserGroupManagerLocal::Init( void ) {
idStr groupNames[ MAX_CLIENTS ];
for ( int i = 0; i < MAX_CLIENTS; i++ ) {
nextLoginTime[ i ] = 0;
idPlayer* player = gameLocal.GetClient( i );
if ( !player ) {
continue;
}
groupNames[ i ] = GetGroup( player->GetUserGroup() ).GetName();
}
userGroups.Clear();
userGroups.Alloc().SetName( "<DEFAULT>" );
configs.Clear();
votes.Clear();
// load user groups
idLexer src( LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT | LEXFL_NOFATALERRORS );
src.LoadFile( "usergroups.dat" );
if ( !src.IsLoaded() ) {
return;
}
idToken token;
while ( true ) {
if ( !src.ReadToken( &token ) ) {
break;
}
if ( !token.Icmp( "group" ) ) {
sdUserGroup& group = userGroups.Alloc();
if ( !group.Parse( src ) ) {
src.Warning( "Error Parsing Group" );
break;
}
} else if ( !token.Icmp( "configs" ) ) {
if ( !configs.Parse( src ) ) {
src.Warning( "Error Parsing configs" );
break;
}
} else if ( !token.Icmp( "votes" ) ) {
if ( !votes.Parse( src ) ) {
src.Warning( "Error Parsing votes" );
break;
}
} else {
src.Warning( "Invalid Token '%s'", token.c_str() );
break;
}
}
defaultGroup = FindGroup( "default" );
if ( defaultGroup == -1 ) {
defaultGroup = 0;
}
for ( int i = 0; i < MAX_CLIENTS; i++ ) {
idPlayer* player = gameLocal.GetClient( i );
if ( !player ) {
continue;
}
player->SetUserGroup( FindGroup( groupNames[ i ] ) );
}
for ( int i = 0; i < userGroups.Num(); i++ ) {
userGroups[ i ].PostParseFixup();
}
if ( gameLocal.isServer ) {
WriteNetworkData( sdReliableMessageClientInfoAll() );
}
}
/*
============
sdUserGroupManagerLocal::FindGroup
============
*/
int sdUserGroupManagerLocal::FindGroup( const char* name ) {
for ( int i = 0; i < userGroups.Num(); i++ ) {
if ( idStr::Icmp( userGroups[ i ].GetName(), name ) ) {
continue;
}
return i;
}
return -1;
}
/*
============
sdUserGroupManagerLocal::Login
============
*/
bool sdUserGroupManagerLocal::Login( idPlayer* player, const char* password ) {
int now = MS2SEC( sys->Milliseconds() );
if ( now < nextLoginTime[ player->entityNumber ] ) {
return false;
}
nextLoginTime[ player->entityNumber ] = now + 5; // Gordon: limit password brute forcing
for ( int i = 0; i < userGroups.Num(); i++ ) {
if ( !userGroups[ i ].CheckPassword( password ) ) {
continue;
}
player->SetUserGroup( i );
return true;
}
return false;
}
/*
============
sdUserGroupManagerLocal::CanLogin
============
*/
bool sdUserGroupManagerLocal::CanLogin() const {
for ( int i = 0; i < userGroups.Num(); i++ ) {
if( userGroups[ i ].HasPassword() ) {
return true;
}
}
return false;
}
/*
============
sdUserGroupManagerLocal::ReadNetworkData
============
*/
void sdUserGroupManagerLocal::ReadNetworkData( const idBitMsg& msg ) {
userGroups.Clear();
userGroups.Alloc().SetName( "<DEFAULT>" );
int count = msg.ReadLong();
for ( int i = 0; i < count; i++ ) {
sdUserGroup& group = userGroups.Alloc();
group.Read( msg );
}
msg.ReadDeltaDict( configs, NULL );
msg.ReadDeltaDict( votes, NULL );
defaultGroup = FindGroup( "default" );
if ( defaultGroup == -1 ) {
defaultGroup = 0;
}
}
/*
============
sdUserGroupManagerLocal::WriteNetworkData
============
*/
void sdUserGroupManagerLocal::WriteNetworkData( const sdReliableMessageClientInfoBase& target ) {
sdReliableServerMessage msg( GAME_RELIABLE_SMESSAGE_USERGROUPS );
msg.WriteLong( userGroups.Num() - 1 );
for ( int i = 1; i < userGroups.Num(); i++ ) {
sdUserGroup& group = userGroups[ i ];
group.Write( msg );
}
msg.WriteDeltaDict( configs, NULL );
msg.WriteDeltaDict( votes, NULL );
msg.Send( target );
}
/*
============
sdUserGroupManagerLocal::CreateUserGroupList
============
*/
void sdUserGroupManagerLocal::CreateUserGroupList( sdUIList* list ) {
sdUIList::ClearItems( list );
idPlayer* localPlayer = gameLocal.GetLocalPlayer();
if ( !localPlayer ) {
return;
}
const sdUserGroup& localGroup = gameLocal.isClient ? GetGroup( localPlayer->GetUserGroup() ) : GetConsoleGroup();
int index = 0;
for ( int i = 1; i < userGroups.Num(); i++ ) {
if ( !localGroup.CanControl( userGroups[ i ] ) ) {
continue;
}
sdUIList::InsertItem( list, va( L"%hs", userGroups[ i ].GetName() ), index, 0 );
index++;
}
/*
for ( int i = 1; i < userGroups.Num(); i++ ) {
sdUIList::InsertItem( list, va( L"%hs", userGroups[ i ].GetName() ), i - 1, 0 );
}
*/
}
/*
============
sdUserGroupManagerLocal::CreateServerConfigList
============
*/
void sdUserGroupManagerLocal::CreateServerConfigList( sdUIList* list ) {
sdUIList::ClearItems( list );
for ( int i = 0; i < configs.GetNumKeyVals(); i++ ) {
const idKeyValue* kv = configs.GetKeyVal( i );
sdUIList::InsertItem( list, va( L"%hs", kv->GetKey().c_str() ), i, 0 );
}
}
/*
============
sdUserGroupManagerLocal::Write
============
*/
void sdUserGroupManagerLocal::Write( idFile* file ) const {
file->WriteInt( userGroups.Num() - 1 );
for ( int i = 1; i < userGroups.Num(); i++ ) {
const sdUserGroup& group = userGroups[ i ];
group.Write( file );
}
configs.WriteToFileHandle( file );
votes.WriteToFileHandle( file );
}
/*
============
sdUserGroupManagerLocal::Read
============
*/
void sdUserGroupManagerLocal::Read( idFile* file ) {
userGroups.Clear();
userGroups.Alloc().SetName( "<DEFAULT>" );
int count;
file->ReadInt( count );
for ( int i = 0; i < count; i++ ) {
sdUserGroup& group = userGroups.Alloc();
group.Read( file );
}
configs.ReadFromFileHandle( file );
votes.ReadFromFileHandle( file );
defaultGroup = FindGroup( "default" );
if ( defaultGroup == -1 ) {
defaultGroup = 0;
}
}
/*
============
sdUserGroupManagerLocal::GetVoteLevel
============
*/
int sdUserGroupManagerLocal::GetVoteLevel( const char* voteName ) {
return votes.GetInt( voteName, "-1" );
}