2020-01-26 14:21:34 +01:00
# include <memory>
# include <bitset>
# include <algorithm>
# include "../../build.h"
# include "../ConnectedClient.h"
# include "../InternalClient.h"
# include "../../server/file/FileServer.h"
# include "../voice/VoiceClient.h"
# include "PermissionManager.h"
# include "../../InstanceHandler.h"
# include "../../server/QueryServer.h"
# include "../file/FileClient.h"
# include "../music/MusicClient.h"
# include "../query/QueryClient.h"
# include "../../weblist/WebListManager.h"
# include "../../manager/ConversationManager.h"
# include "../../manager/PermissionNameMapper.h"
# include <cstdint>
# include "helpers.h"
# include <Properties.h>
# include <log/LogUtils.h>
# include <misc/sassert.h>
# include <misc/base64.h>
# include <misc/hex.h>
# include <misc/rnd.h>
# include <bbcode/bbcodes.h>
using namespace std : : chrono ;
using namespace std ;
using namespace ts ;
using namespace ts : : server ;
using namespace ts : : token ;
# define QUERY_PASSWORD_LENGTH 12
command_result ConnectedClient : : handleCommandClientGetVariables ( Command & cmd ) {
CMD_REQ_SERVER ;
2020-02-01 14:32:16 +01:00
ConnectedLockedClient client { this - > server - > find_client_by_id ( cmd [ " clid " ] . as < ClientId > ( ) ) } ;
2020-01-26 14:21:34 +01:00
shared_lock tree_lock ( this - > channel_lock ) ;
2020-02-01 14:32:16 +01:00
if ( ! client | | ( client . client ! = this & & ! this - > isClientVisible ( client . client , false ) ) )
2020-01-26 14:21:34 +01:00
return command_result { error : : client_invalid_id , " " } ;
deque < shared_ptr < property : : PropertyDescription > > props ;
for ( auto & prop : client - > properties ( ) - > list_properties ( property : : FLAG_CLIENT_VARIABLE , this - > getType ( ) = = CLIENT_TEAMSPEAK ? property : : FLAG_NEW : ( uint16_t ) 0 ) ) {
props . push_back ( property : : info ( ( property : : ClientProperties ) prop . type ( ) . property_index ) ) ;
}
2020-02-01 14:32:16 +01:00
this - > notifyClientUpdated ( client . client , props , false ) ;
2020-01-26 14:21:34 +01:00
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientKick ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_CHK_AND_INC_FLOOD_POINTS ( 25 ) ;
2020-02-01 14:32:16 +01:00
ConnectedLockedClient client { this - > server - > find_client_by_id ( cmd [ " clid " ] . as < ClientId > ( ) ) } ;
2020-01-26 14:21:34 +01:00
if ( ! client ) return command_result { error : : client_invalid_id } ;
if ( client - > getType ( ) = = CLIENT_MUSIC ) return command_result { error : : client_invalid_type , " You cant kick a music bot! " } ;
std : : shared_ptr < BasicChannel > targetChannel = nullptr ;
auto type = cmd [ " reasonid " ] . as < ViewReasonId > ( ) ;
if ( type = = ViewReasonId : : VREASON_CHANNEL_KICK ) {
2020-02-01 14:32:16 +01:00
auto channel = client - > getChannel ( ) ;
2020-01-26 14:21:34 +01:00
ACTION_REQUIRES_PERMISSION ( permission : : i_client_kick_from_channel_power , client - > calculate_permission ( permission : : i_client_needed_kick_from_channel_power , client - > getChannelId ( ) ) , client - > getChannelId ( ) ) ;
targetChannel = this - > server - > channelTree - > getDefaultChannel ( ) ;
} else if ( type = = ViewReasonId : : VREASON_SERVER_KICK ) {
2020-02-01 14:32:16 +01:00
auto channel = client - > getChannel ( ) ;
2020-01-26 14:21:34 +01:00
ACTION_REQUIRES_GLOBAL_PERMISSION ( permission : : i_client_kick_from_server_power , client - > calculate_permission ( permission : : i_client_needed_kick_from_server_power , client - > getChannelId ( ) ) ) ;
targetChannel = nullptr ;
} else return command_result { error : : not_implemented } ;
if ( targetChannel ) {
2020-02-01 14:32:16 +01:00
this - > server - > notify_client_kick ( client . client , this - > ref ( ) , cmd [ " reasonmsg " ] . as < std : : string > ( ) , targetChannel ) ;
2020-01-26 14:21:34 +01:00
} else {
2020-02-01 14:32:16 +01:00
this - > server - > notify_client_kick ( client . client , this - > ref ( ) , cmd [ " reasonmsg " ] . as < std : : string > ( ) , nullptr ) ;
client - > close_connection ( system_clock : : now ( ) + seconds ( 1 ) ) ;
2020-01-26 14:21:34 +01:00
}
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientGetIds ( Command & cmd ) {
CMD_REQ_SERVER ;
bool error = false ;
bool found = false ;
auto client_list = this - > server - > getClients ( ) ;
Command notify ( this - > getExternalType ( ) = = CLIENT_TEAMSPEAK ? " notifyclientids " : " " ) ;
int result_index = 0 ;
for ( int index = 0 ; index < cmd . bulkCount ( ) ; index + + ) {
auto unique_id = cmd [ index ] [ " cluid " ] . as < string > ( ) ;
for ( const auto & entry : client_list ) {
if ( entry - > getUid ( ) = = unique_id ) {
if ( ! config : : server : : show_invisible_clients_as_online & & ! this - > channels - > channel_visible ( entry - > currentChannel , nullptr ) )
continue ;
notify [ result_index ] [ " name " ] = entry - > getDisplayName ( ) ;
notify [ result_index ] [ " clid " ] = entry - > getClientId ( ) ;
notify [ result_index ] [ " cluid " ] = entry - > getUid ( ) ;
result_index + + ;
found = true ;
}
}
if ( found ) found = false ;
else error = false ;
}
string uid = cmd [ " cluid " ] ;
if ( result_index > 0 ) {
this - > sendCommand ( notify ) ;
}
if ( error ) {
return command_result { error : : database_empty_result } ;
}
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientMove ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
CMD_CHK_AND_INC_FLOOD_POINTS ( 10 ) ;
shared_lock server_channel_r_lock ( this - > server - > channel_tree_lock ) ;
auto target_client_id = cmd [ " clid " ] . as < ClientId > ( ) ;
2020-02-01 14:32:16 +01:00
ConnectedLockedClient target_client { target_client_id = = 0 ? this - > ref ( ) : this - > server - > find_client_by_id ( target_client_id ) } ;
2020-01-26 14:21:34 +01:00
if ( ! target_client ) {
return command_result { error : : client_invalid_id , " Invalid target clid " } ;
}
2020-02-01 14:32:16 +01:00
if ( ! target_client - > getChannel ( ) ) {
if ( target_client . client ! = this )
2020-01-26 14:21:34 +01:00
return command_result { error : : client_invalid_id , " Invalid target clid " } ;
}
auto channel = this - > server - > channelTree - > findChannel ( cmd [ " cid " ] . as < ChannelId > ( ) ) ;
if ( ! channel ) {
return command_result { error : : channel_invalid_id } ;
}
auto permission_cache = make_shared < CalculateCache > ( ) ;
if ( ! cmd [ 0 ] . has ( " cpw " ) )
cmd [ " cpw " ] = " " ;
if ( ! channel - > passwordMatch ( cmd [ " cpw " ] , true ) )
if ( ! permission : : v2 : : permission_granted ( 1 , this - > calculate_permission ( permission : : b_channel_join_ignore_password , channel - > channelId ( ) ) ) )
return command_result { error : : channel_invalid_password } ;
auto permission_error = this - > calculate_and_get_join_state ( channel ) ;
if ( permission_error ! = permission : : unknown ) return command_result { permission_error } ;
if ( ! channel - > properties ( ) [ property : : CHANNEL_FLAG_MAXCLIENTS_UNLIMITED ] . as < bool > ( ) | | ! channel - > properties ( ) [ property : : CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED ] . as < bool > ( ) ) {
if ( ! permission : : v2 : : permission_granted ( 1 , this - > calculate_permission ( permission : : b_channel_join_ignore_maxclients , channel - > channelId ( ) ) ) ) {
if ( ! channel - > properties ( ) [ property : : CHANNEL_FLAG_MAXCLIENTS_UNLIMITED ] . as < bool > ( ) ) {
auto maxClients = channel - > properties ( ) [ property : : CHANNEL_MAXCLIENTS ] . as < int32_t > ( ) ;
if ( maxClients > = 0 & & maxClients < = this - > server - > getClientsByChannel ( channel ) . size ( ) )
return command_result { error : : channel_maxclients_reached } ;
}
if ( ! channel - > properties ( ) [ property : : CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED ] . as < bool > ( ) ) {
shared_ptr < BasicChannel > family_root ;
if ( channel - > properties ( ) [ property : : CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED ] . as < bool > ( ) ) {
family_root = channel ;
while ( family_root & & family_root - > properties ( ) [ property : : CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED ] . as < bool > ( ) ) family_root = family_root - > parent ( ) ;
}
if ( family_root & & ! family_root - > properties ( ) [ property : : CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED ] ) { //Could not be CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED
auto maxClients = family_root - > properties ( ) [ property : : CHANNEL_MAXFAMILYCLIENTS ] . as < int32_t > ( ) ;
auto clients = 0 ;
for ( const auto & entry : this - > server - > getClientsByChannelRoot ( channel , false ) ) if ( entry . get ( ) ! = this ) clients + + ; //Dont count the client itself
if ( maxClients > = 0 & & maxClients < = clients )
return command_result { error : : channel_maxfamily_reached } ;
}
}
}
}
2020-02-01 14:32:16 +01:00
if ( target_client . client ! = this )
2020-01-26 14:21:34 +01:00
ACTION_REQUIRES_PERMISSION ( permission : : i_client_move_power , target_client - > calculate_permission ( permission : : i_client_needed_move_power , target_client - > getChannelId ( ) ) , target_client - > getChannelId ( ) ) ;
server_channel_r_lock . unlock ( ) ;
unique_lock server_channel_w_lock ( this - > server - > channel_tree_lock ) ;
auto oldChannel = target_client - > getChannel ( ) ;
this - > server - > client_move (
2020-02-01 14:32:16 +01:00
target_client . client ,
2020-01-26 14:21:34 +01:00
channel ,
2020-02-01 14:32:16 +01:00
target_client . client = = this ? nullptr : _this . lock ( ) ,
2020-01-26 14:21:34 +01:00
" " ,
2020-02-01 14:32:16 +01:00
target_client . client = = this ? ViewReasonId : : VREASON_USER_ACTION : ViewReasonId : : VREASON_MOVED ,
2020-01-26 14:21:34 +01:00
true ,
server_channel_w_lock
) ;
if ( oldChannel ) {
if ( ! server_channel_w_lock . owns_lock ( ) )
server_channel_w_lock . lock ( ) ;
if ( oldChannel - > channelType ( ) = = ChannelType : : temporary & & oldChannel - > properties ( ) [ property : : CHANNEL_DELETE_DELAY ] . as < int64_t > ( ) = = 0 )
if ( this - > server - > getClientsByChannelRoot ( oldChannel , false ) . empty ( ) )
this - > server - > delete_channel ( dynamic_pointer_cast < ServerChannel > ( oldChannel ) , this - > ref ( ) , " temporary auto delete " , server_channel_w_lock ) ;
if ( server_channel_w_lock . owns_lock ( ) )
server_channel_w_lock . unlock ( ) ;
}
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientPoke ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
CMD_CHK_AND_INC_FLOOD_POINTS ( 25 ) ;
2020-02-01 14:32:16 +01:00
ConnectedLockedClient client { this - > server - > find_client_by_id ( cmd [ " clid " ] . as < ClientId > ( ) ) } ;
2020-01-26 14:21:34 +01:00
if ( ! client ) return command_result { error : : client_invalid_id } ;
if ( client - > getType ( ) = = CLIENT_MUSIC ) return command_result { error : : client_invalid_type } ;
ACTION_REQUIRES_PERMISSION ( permission : : i_client_poke_power , client - > calculate_permission ( permission : : i_client_needed_poke_power , client - > getChannelId ( ) ) , client - > getChannelId ( ) ) ;
client - > notifyClientPoke ( _this . lock ( ) , cmd [ " msg " ] ) ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientChatComposing ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_CHK_AND_INC_FLOOD_POINTS ( 0 ) ;
2020-02-01 14:32:16 +01:00
ConnectedLockedClient client { this - > server - > find_client_by_id ( cmd [ " clid " ] . as < ClientId > ( ) ) } ;
2020-01-26 14:21:34 +01:00
if ( ! client ) return command_result { error : : client_invalid_id } ;
client - > notifyClientChatComposing ( _this . lock ( ) ) ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientChatClosed ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_CHK_AND_INC_FLOOD_POINTS ( 5 ) ;
2020-02-01 14:32:16 +01:00
ConnectedLockedClient < ConnectedClient > client { this - > server - > find_client_by_id ( cmd [ " clid " ] . as < ClientId > ( ) ) } ;
2020-01-26 14:21:34 +01:00
if ( ! client ) return command_result { error : : client_invalid_id } ;
{
unique_lock channel_lock ( this - > channel_lock ) ;
2020-02-01 14:32:16 +01:00
this - > openChats . erase ( remove_if ( this - > openChats . begin ( ) , this - > openChats . end ( ) , [ & ] ( const weak_ptr < ConnectedClient > & weak ) {
2020-01-26 14:21:34 +01:00
return weak . lock ( ) = = client ;
} ) , this - > openChats . end ( ) ) ;
}
{
2020-02-01 14:32:16 +01:00
unique_lock channel_lock ( client - > get_channel_lock ( ) ) ;
2020-01-26 14:21:34 +01:00
client - > openChats . erase ( remove_if ( client - > openChats . begin ( ) , client - > openChats . end ( ) , [ & ] ( const weak_ptr < ConnectedClient > & weak ) {
return weak . lock ( ) . get ( ) = = this ;
} ) , client - > openChats . end ( ) ) ;
}
client - > notifyClientChatClosed ( _this . lock ( ) ) ;
return command_result { error : : ok } ;
}
//ftgetfilelist cid=1 cpw path=\/ return_code=1:x
//Answer:
//1 .. n
// notifyfilelist cid=1 path=\/ return_code=1:x name=testFile size=35256 datetime=1509459767 type=1|name=testDir size=0 datetime=1509459741 type=0|name=testDir_2 size=0 datetime=1509459763 type=0
//notifyfilelistfinished cid=1 path=\/
inline void cmd_filelist_append_files ( ServerId sid , Command & command , vector < std : : shared_ptr < file : : FileEntry > > files ) {
int index = 0 ;
logTrace ( sid , " Sending file list for path {} " , command [ " path " ] . string ( ) ) ;
for ( const auto & fileEntry : files ) {
logTrace ( sid , " - {} ({}) " , fileEntry - > name , fileEntry - > type = = file : : FileType : : FILE ? " file " : " directory " ) ;
command [ index ] [ " name " ] = fileEntry - > name ;
command [ index ] [ " datetime " ] = std : : chrono : : duration_cast < std : : chrono : : seconds > ( fileEntry - > lastChanged . time_since_epoch ( ) ) . count ( ) ;
command [ index ] [ " type " ] = fileEntry - > type ;
if ( fileEntry - > type = = file : : FileType : : FILE )
command [ index ] [ " size " ] = static_pointer_cast < file : : File > ( fileEntry ) - > fileSize ;
else
command [ index ] [ " size " ] = 0 ;
index + + ;
}
}
# define CMD_REQ_FSERVER if(!serverInstance->getFileServer()) return command_result{error::vs_critical, "file server not started yet!"}
//start=0 duration=10
//pattern=%asd%
struct ClientDbArgs {
2020-01-26 18:04:38 +01:00
shared_ptr < VirtualServer > server ;
2020-01-26 14:21:34 +01:00
int index = 0 ;
int offset = 0 ;
int resultIndex = 0 ;
bool showIp = false ;
bool largeInfo = false ;
Command * result = nullptr ;
} ;
command_result ConnectedClient : : handleCommandClientDbList ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
CMD_CHK_AND_INC_FLOOD_POINTS ( 25 ) ;
ACTION_REQUIRES_GLOBAL_PERMISSION ( permission : : b_virtualserver_client_dblist , 1 ) ;
Command notify ( this - > getExternalType ( ) = = CLIENT_TEAMSPEAK ? " notifyclientdblist " : " " ) ;
if ( ! cmd [ 0 ] . has ( " start " ) )
cmd [ " start " ] = 0 ;
if ( ! cmd [ 0 ] . has ( " duration " ) )
cmd [ " duration " ] = 20 ;
if ( cmd [ 0 ] [ " duration " ] . as < int > ( ) > 2000 ) cmd [ " duration " ] = 2000 ;
if ( cmd [ 0 ] [ " duration " ] . as < int > ( ) < 1 ) cmd [ " duration " ] = 1 ;
auto maxIndex = cmd [ " start " ] . as < uint32_t > ( ) + cmd [ " duration " ] . as < uint32_t > ( ) ;
ClientDbArgs args ;
args . server = this - > server ;
args . offset = cmd [ " start " ] . as < uint32_t > ( ) ;
args . result = & notify ;
args . resultIndex = 0 ;
args . index = 0 ;
args . showIp = permission : : v2 : : permission_granted ( 1 , this - > calculate_permission ( permission : : b_client_remoteaddress_view , 0 ) ) ;
args . largeInfo = cmd . hasParm ( " details " ) ;
( LOG_SQL_CMD ) ( sql : : command ( this - > server - > getSql ( ) , " SELECT * FROM `clients` WHERE `serverId` = :sid ORDER BY `cldbid` ASC " + ( maxIndex > 0 ? " LIMIT " + to_string ( maxIndex ) : " " ) , variable { " :sid " , this - > server - > getServerId ( ) } ) . query (
[ ] ( ClientDbArgs * pArgs , int length , char * * values , char * * column ) {
pArgs - > index + + ;
if ( pArgs - > offset < pArgs - > index ) {
ClientDbId id = 0 ;
string uid , name , ip ;
string created = " 0 " , lastConnected = " 0 " , connections = " 0 " ;
for ( int index = 0 ; index < length ; index + + ) {
string key = column [ index ] ;
if ( key = = " cldbid " )
id = stoll ( values [ index ] ) ;
else if ( key = = " clientUid " )
uid = values [ index ] ;
else if ( key = = " firstConnect " )
created = values [ index ] ;
else if ( key = = " lastConnect " )
lastConnected = values [ index ] ;
else if ( key = = " connections " )
connections = values [ index ] ;
else if ( key = = " lastName " )
name = values [ index ] ;
}
pArgs - > result - > operator [ ] ( pArgs - > resultIndex ) [ " cldbid " ] = id ;
pArgs - > result - > operator [ ] ( pArgs - > resultIndex ) [ " client_unique_identifier " ] = uid ;
pArgs - > result - > operator [ ] ( pArgs - > resultIndex ) [ " client_nickname " ] = name ;
pArgs - > result - > operator [ ] ( pArgs - > resultIndex ) [ " client_created " ] = created ;
pArgs - > result - > operator [ ] ( pArgs - > resultIndex ) [ " client_lastconnected " ] = lastConnected ;
pArgs - > result - > operator [ ] ( pArgs - > resultIndex ) [ " client_totalconnections " ] = connections ;
pArgs - > result - > operator [ ] ( pArgs - > resultIndex ) [ " client_description " ] = " " ;
auto props = serverInstance - > databaseHelper ( ) - > loadClientProperties ( pArgs - > server , id , ClientType : : CLIENT_TEAMSPEAK ) ;
if ( props ) {
pArgs - > result - > operator [ ] ( pArgs - > resultIndex ) [ " client_lastip " ] = ( * props ) [ property : : CONNECTION_CLIENT_IP ] . as < string > ( ) ;
pArgs - > result - > operator [ ] ( pArgs - > resultIndex ) [ " client_description " ] = ( * props ) [ property : : CLIENT_DESCRIPTION ] . as < string > ( ) ;
if ( pArgs - > largeInfo ) {
pArgs - > result - > operator [ ] ( pArgs - > resultIndex ) [ " client_badges " ] = ( * props ) [ property : : CLIENT_BADGES ] . as < string > ( ) ;
pArgs - > result - > operator [ ] ( pArgs - > resultIndex ) [ " client_version " ] = ( * props ) [ property : : CLIENT_VERSION ] . as < string > ( ) ;
pArgs - > result - > operator [ ] ( pArgs - > resultIndex ) [ " client_platform " ] = ( * props ) [ property : : CLIENT_PLATFORM ] . as < string > ( ) ;
pArgs - > result - > operator [ ] ( pArgs - > resultIndex ) [ " client_hwid " ] = ( * props ) [ property : : CLIENT_HARDWARE_ID ] . as < string > ( ) ;
}
}
if ( ! pArgs - > showIp )
pArgs - > result - > operator [ ] ( pArgs - > resultIndex ) [ " client_lastip " ] = " hidden " ;
pArgs - > resultIndex + + ;
}
return 0 ;
} , & args ) ) ;
if ( args . resultIndex = = 0 ) return command_result { error : : database_empty_result } ;
if ( cmd . hasParm ( " count " ) ) {
size_t result = 0 ;
sql : : command ( this - > server - > getSql ( ) , " SELECT COUNT(*) AS `count` FROM `clients` WHERE `serverId` = :sid " , variable { " :sid " , this - > server - > getServerId ( ) } ) . query ( [ ] ( size_t * ptr , int , char * * v , char * * ) {
* ptr = static_cast < size_t > ( stoll ( v [ 0 ] ) ) ;
return 0 ;
} , & result ) ;
notify [ 0 ] [ " count " ] = result ;
}
this - > sendCommand ( notify ) ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientDBEdit ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
CMD_CHK_AND_INC_FLOOD_POINTS ( 5 ) ;
ACTION_REQUIRES_GLOBAL_PERMISSION ( permission : : b_client_modify_dbproperties , 1 ) ;
if ( ! serverInstance - > databaseHelper ( ) - > validClientDatabaseId ( this - > server , cmd [ " cldbid " ] ) ) return command_result { error : : database_empty_result , " invalid cldbid " } ;
auto props = serverInstance - > databaseHelper ( ) - > loadClientProperties ( this - > server , cmd [ " cldbid " ] , ClientType : : CLIENT_TEAMSPEAK ) ;
for ( auto & elm : cmd [ 0 ] . keys ( ) ) {
if ( elm = = " cldbid " ) continue ;
auto info = property : : info < property : : ClientProperties > ( elm ) ;
if ( * info = = property : : CLIENT_UNDEFINED ) {
logError ( this - > getServerId ( ) , " Client " + this - > getDisplayName ( ) + " tried to change someone's db entry, but the entry in unknown: " + elm ) ;
continue ;
}
if ( ! info - > validate_input ( cmd [ elm ] . as < string > ( ) ) ) {
logError ( this - > getServerId ( ) , " Client " + this - > getDisplayName ( ) + " tried to change a property to an invalid value. (Value: ' " + cmd [ elm ] . as < string > ( ) + " ', Property: ' " + info - > name + " ') " ) ;
continue ;
}
( * props ) [ info ] = cmd [ elm ] . string ( ) ;
}
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientEdit ( ts : : Command & cmd ) {
CMD_REQ_SERVER ;
2020-02-01 14:32:16 +01:00
ConnectedLockedClient client { this - > server - > find_client_by_id ( cmd [ " clid " ] . as < ClientId > ( ) ) } ;
2020-01-26 14:21:34 +01:00
if ( ! client ) return command_result { error : : client_invalid_id } ;
2020-02-01 14:32:16 +01:00
return this - > handleCommandClientEdit ( cmd , client . client ) ;
2020-01-26 14:21:34 +01:00
}
command_result ConnectedClient : : handleCommandClientEdit ( Command & cmd , const std : : shared_ptr < ConnectedClient > & client ) {
assert ( client ) ;
auto self = client = = this ;
CMD_CHK_AND_INC_FLOOD_POINTS ( self ? 15 : 25 ) ;
CMD_RESET_IDLE ;
bool update_talk_rights = false ;
unique_ptr < lock_guard < std : : recursive_mutex > > nickname_lock ;
deque < pair < property : : ClientProperties , string > > keys ;
for ( const auto & key : cmd [ 0 ] . keys ( ) ) {
if ( key = = " return_code " ) continue ;
if ( key = = " clid " ) continue ;
const auto & info = property : : info < property : : ClientProperties > ( key ) ;
if ( * info = = property : : CLIENT_UNDEFINED ) {
logError ( this - > getServerId ( ) , R " ([{}] Tried to change a not existing client property for {}. (Key: " { } " , Value: " { } " )) " , CLIENT_STR_LOG_PREFIX , CLIENT_STR_LOG_PREFIX_ ( client ) , key , cmd [ key ] . string ( ) ) ;
continue ;
}
if ( ( info - > flags & property : : FLAG_USER_EDITABLE ) = = 0 ) {
logError ( this - > getServerId ( ) , R " ([{}] Tried to change a not user editable client property for {}. (Key: " { } " , Value: " { } " )) " , CLIENT_STR_LOG_PREFIX , CLIENT_STR_LOG_PREFIX_ ( client ) , key , cmd [ key ] . string ( ) ) ;
continue ;
}
if ( ! info - > validate_input ( cmd [ key ] . as < string > ( ) ) ) {
logError ( this - > getServerId ( ) , R " ([{}] Tried to change a client property to an invalid value for {}. (Key: " { } " , Value: " { } " )) " , CLIENT_STR_LOG_PREFIX , CLIENT_STR_LOG_PREFIX_ ( client ) , key , cmd [ key ] . string ( ) ) ;
continue ;
}
if ( client - > properties ( ) [ info ] . as < string > ( ) = = cmd [ key ] . as < string > ( ) ) continue ;
if ( * info = = property : : CLIENT_DESCRIPTION ) {
if ( self ) {
ACTION_REQUIRES_PERMISSION ( permission : : b_client_modify_own_description , 1 , client - > getChannelId ( ) ) ;
} else if ( client - > getType ( ) = = ClientType : : CLIENT_MUSIC ) {
if ( client - > properties ( ) [ property : : CLIENT_OWNER ] ! = this - > getClientDatabaseId ( ) ) {
ACTION_REQUIRES_PERMISSION ( permission : : i_client_music_modify_power , client - > calculate_permission ( permission : : i_client_music_needed_modify_power , client - > getChannelId ( ) ) , client - > getChannelId ( ) ) ;
}
} else {
ACTION_REQUIRES_PERMISSION ( permission : : b_client_modify_description , 1 , client - > getChannelId ( ) ) ;
}
string value = cmd [ " client_description " ] . string ( ) ;
if ( count_characters ( value ) > 200 ) return command_result { error : : parameter_invalid , " Invalid description length. A maximum of 200 characters is allowed! " } ;
} else if ( * info = = property : : CLIENT_IS_TALKER ) {
ACTION_REQUIRES_PERMISSION ( permission : : b_client_set_flag_talker , 1 , client - > getChannelId ( ) ) ;
cmd [ " client_is_talker " ] = cmd [ " client_is_talker " ] . as < bool > ( ) ;
cmd [ " client_talk_request " ] = 0 ;
update_talk_rights = true ;
keys . emplace_back ( property : : CLIENT_IS_TALKER , " client_is_talker " ) ;
keys . emplace_back ( property : : CLIENT_TALK_REQUEST , " client_talk_request " ) ;
continue ;
} else if ( * info = = property : : CLIENT_NICKNAME ) {
if ( ! self ) {
if ( client - > getType ( ) ! = ClientType : : CLIENT_MUSIC ) return command_result { error : : client_invalid_type } ;
if ( client - > properties ( ) [ property : : CLIENT_OWNER ] ! = this - > getClientDatabaseId ( ) ) {
ACTION_REQUIRES_PERMISSION ( permission : : i_client_music_rename_power , client - > calculate_permission ( permission : : i_client_music_needed_rename_power , client - > getChannelId ( ) ) , client - > getChannelId ( ) ) ;
}
}
string name = cmd [ " client_nickname " ] . string ( ) ;
if ( count_characters ( name ) < 3 ) return command_result { error : : parameter_invalid , " Invalid name length. A minimum of 3 characters is required! " } ;
if ( count_characters ( name ) > 30 ) return command_result { error : : parameter_invalid , " Invalid name length. A maximum of 30 characters is allowed! " } ;
if ( ! permission : : v2 : : permission_granted ( 1 , this - > calculate_permission ( permission : : b_client_ignore_bans , client - > getClientId ( ) ) ) ) {
auto banRecord = serverInstance - > banManager ( ) - > findBanByName ( this - > getServerId ( ) , name ) ;
if ( banRecord )
return command_result { error : : client_nickname_inuse , string ( ) + " This nickname is " + ( banRecord - > serverId = = 0 ? " globally " : " " ) + " banned for the reason: " + banRecord - > reason } ;
}
if ( this - > server ) {
nickname_lock = std : : make_unique < lock_guard < recursive_mutex > > ( this - > server - > client_nickname_lock ) ;
bool self = false ;
for ( const auto & cl : this - > server - > getClients ( ) ) {
if ( cl - > getDisplayName ( ) = = cmd [ " client_nickname " ] . string ( ) ) {
if ( cl = = this )
self = true ;
else
return command_result { error : : client_nickname_inuse , " This nickname is already in use " } ;
}
}
if ( self ) {
nickname_lock . reset ( ) ;
continue ;
}
}
} else if ( * info = = property : : CLIENT_PLAYER_VOLUME ) {
if ( client - > getType ( ) ! = ClientType : : CLIENT_MUSIC ) return command_result { error : : client_invalid_type } ;
if ( client - > properties ( ) [ property : : CLIENT_OWNER ] ! = this - > getClientDatabaseId ( ) ) {
ACTION_REQUIRES_PERMISSION ( permission : : i_client_music_modify_power , client - > calculate_permission ( permission : : i_client_music_needed_modify_power , client - > getChannelId ( ) ) , client - > getChannelId ( ) ) ;
}
auto bot = dynamic_pointer_cast < MusicClient > ( client ) ;
assert ( bot ) ;
auto volume = cmd [ " player_volume " ] . as < float > ( ) ;
auto max_volume = this - > calculate_permission ( permission : : i_client_music_create_modify_max_volume , client - > getClientId ( ) ) ;
if ( max_volume . has_value & & ! permission : : v2 : : permission_granted ( volume * 100 , max_volume ) )
return command_result { permission : : i_client_music_create_modify_max_volume } ;
bot - > volume_modifier ( cmd [ " player_volume " ] ) ;
} else if ( * info = = property : : CLIENT_IS_CHANNEL_COMMANDER ) {
if ( ! self ) {
if ( client - > getType ( ) ! = ClientType : : CLIENT_MUSIC ) return command_result { error : : client_invalid_type } ;
if ( client - > properties ( ) [ property : : CLIENT_OWNER ] ! = this - > getClientDatabaseId ( ) ) {
ACTION_REQUIRES_PERMISSION ( permission : : i_client_music_modify_power , client - > calculate_permission ( permission : : i_client_music_needed_modify_power , client - > getChannelId ( ) ) , client - > getChannelId ( ) ) ;
}
}
if ( cmd [ " client_is_channel_commander " ] . as < bool > ( ) )
ACTION_REQUIRES_PERMISSION ( permission : : b_client_use_channel_commander , 1 , client - > getChannelId ( ) ) ;
} else if ( * info = = property : : CLIENT_IS_PRIORITY_SPEAKER ) {
//FIXME allow other to remove this thing
if ( ! self ) {
if ( client - > getType ( ) ! = ClientType : : CLIENT_MUSIC )
return command_result { error : : client_invalid_type } ;
if ( client - > properties ( ) [ property : : CLIENT_OWNER ] ! = this - > getClientDatabaseId ( ) )
ACTION_REQUIRES_PERMISSION ( permission : : i_client_music_modify_power , client - > calculate_permission ( permission : : i_client_music_needed_modify_power , client - > getClientId ( ) ) , client - > getClientId ( ) ) ;
}
if ( cmd [ " client_is_priority_speaker " ] . as < bool > ( ) )
ACTION_REQUIRES_PERMISSION ( permission : : b_client_use_priority_speaker , 1 , client - > getChannelId ( ) ) ;
} else if ( self & & key = = " client_talk_request " ) {
CMD_CHK_AND_INC_FLOOD_POINTS ( 20 ) ;
ACTION_REQUIRES_PERMISSION ( permission : : b_client_request_talker , 1 , client - > getChannelId ( ) ) ;
if ( cmd [ " client_talk_request " ] . as < bool > ( ) )
cmd [ " client_talk_request " ] = duration_cast < seconds > ( system_clock : : now ( ) . time_since_epoch ( ) ) . count ( ) ;
else
cmd [ " client_talk_request " ] = 0 ;
keys . emplace_back ( property : : CLIENT_TALK_REQUEST , " client_talk_request " ) ;
continue ;
} else if ( self & & key = = " client_badges " ) {
std : : string str = cmd [ key ] ;
size_t index = 0 ;
int badgesTags = 0 ;
do {
index = str . find ( " badges " , index ) ;
if ( index < str . length ( ) ) badgesTags + + ;
index + + ;
} while ( index < str . length ( ) & & index ! = 0 ) ;
if ( badgesTags > = 2 ) {
if ( ! permission : : v2 : : permission_granted ( 1 , this - > calculate_permission ( permission : : b_client_allow_invalid_badges , client - > getClientId ( ) ) ) )
( ( VoiceClient * ) this ) - > disconnect ( VREASON_SERVER_KICK , config : : messages : : kick_invalid_badges , this - > server ? this - > server - > serverAdmin : dynamic_pointer_cast < ConnectedClient > ( serverInstance - > getInitialServerAdmin ( ) ) , true ) ;
return command_result { error : : parameter_invalid , " Invalid badges " } ;
}
//FIXME stuff here
} else if ( ! self & & key = = " client_version " ) {
if ( client - > getType ( ) ! = ClientType : : CLIENT_MUSIC ) return command_result { error : : client_invalid_type } ;
if ( client - > properties ( ) [ property : : CLIENT_OWNER ] ! = this - > getClientDatabaseId ( ) ) {
ACTION_REQUIRES_PERMISSION ( permission : : i_client_music_modify_power , client - > calculate_permission ( permission : : i_client_music_needed_modify_power , client - > getChannelId ( ) ) , client - > getChannelId ( ) ) ;
}
} else if ( ! self & & key = = " client_platform " ) {
if ( client - > getType ( ) ! = ClientType : : CLIENT_MUSIC ) return command_result { error : : client_invalid_type } ;
if ( client - > properties ( ) [ property : : CLIENT_OWNER ] ! = this - > getClientDatabaseId ( ) ) {
ACTION_REQUIRES_PERMISSION ( permission : : i_client_music_modify_power , client - > calculate_permission ( permission : : i_client_music_needed_modify_power , client - > getChannelId ( ) ) , client - > getChannelId ( ) ) ;
}
} else if ( ! self & & key = = " client_country " ) {
if ( client - > getType ( ) ! = ClientType : : CLIENT_MUSIC ) return command_result { error : : client_invalid_type } ;
if ( client - > properties ( ) [ property : : CLIENT_OWNER ] ! = this - > getClientDatabaseId ( ) ) {
ACTION_REQUIRES_PERMISSION ( permission : : i_client_music_modify_power , client - > calculate_permission ( permission : : i_client_music_needed_modify_power , client - > getChannelId ( ) ) , client - > getChannelId ( ) ) ;
}
} else if ( ! self & & ( * info = = property : : CLIENT_FLAG_NOTIFY_SONG_CHANGE /* || *info == property::CLIENT_NOTIFY_SONG_MESSAGE*/ ) ) {
if ( client - > getType ( ) ! = ClientType : : CLIENT_MUSIC ) return command_result { error : : client_invalid_type } ;
if ( client - > properties ( ) [ property : : CLIENT_OWNER ] ! = this - > getClientDatabaseId ( ) ) {
ACTION_REQUIRES_PERMISSION ( permission : : i_client_music_modify_power , client - > calculate_permission ( permission : : i_client_music_needed_modify_power , client - > getChannelId ( ) ) , client - > getChannelId ( ) ) ;
}
} else if ( ! self & & key = = " client_uptime_mode " ) {
if ( client - > getType ( ) ! = ClientType : : CLIENT_MUSIC ) return command_result { error : : client_invalid_type } ;
if ( client - > properties ( ) [ property : : CLIENT_OWNER ] ! = this - > getClientDatabaseId ( ) ) {
ACTION_REQUIRES_PERMISSION ( permission : : i_client_music_modify_power , client - > calculate_permission ( permission : : i_client_music_needed_modify_power , client - > getChannelId ( ) ) , client - > getChannelId ( ) ) ;
}
if ( cmd [ key ] . as < MusicClient : : UptimeMode : : value > ( ) = = MusicClient : : UptimeMode : : TIME_SINCE_SERVER_START ) {
cmd [ " client_lastconnected " ] = duration_cast < seconds > ( this - > server - > startTimestamp . time_since_epoch ( ) ) . count ( ) ;
} else {
string value = client - > properties ( ) [ property : : CLIENT_CREATED ] ;
if ( value . empty ( ) )
value = " 0 " ;
cmd [ " client_lastconnected " ] = value ;
}
keys . emplace_back ( property : : CLIENT_LASTCONNECTED , " client_lastconnected " ) ;
} else if ( ! self & & * info = = property : : CLIENT_BOT_TYPE ) {
ACTION_REQUIRES_PERMISSION ( permission : : i_client_music_modify_power , client - > calculate_permission ( permission : : i_client_music_needed_modify_power , client - > getChannelId ( ) ) , client - > getChannelId ( ) ) ;
auto type = cmd [ " client_bot_type " ] . as < MusicClient : : Type : : value > ( ) ;
if ( type = = MusicClient : : Type : : TEMPORARY ) {
ACTION_REQUIRES_PERMISSION ( permission : : b_client_music_modify_temporary , 1 , client - > getChannelId ( ) ) ;
} else if ( type = = MusicClient : : Type : : SEMI_PERMANENT ) {
ACTION_REQUIRES_PERMISSION ( permission : : b_client_music_modify_semi_permanent , 1 , client - > getChannelId ( ) ) ;
} else if ( type = = MusicClient : : Type : : PERMANENT ) {
ACTION_REQUIRES_PERMISSION ( permission : : b_client_music_modify_permanent , 1 , client - > getChannelId ( ) ) ;
} else
return command_result { error : : parameter_invalid } ;
} else if ( * info = = property : : CLIENT_AWAY_MESSAGE ) {
if ( ! self ) continue ;
if ( cmd [ " client_away_message " ] . string ( ) . length ( ) > 256 )
return command_result { error : : parameter_invalid } ;
} else if ( ! self ) { /* dont edit random properties of other clients. For us self its allowed to edit the rest without permissions */
continue ;
}
keys . emplace_back ( ( property : : ClientProperties ) info - > property_index , key ) ;
}
deque < property : : ClientProperties > updates ;
for ( const auto & key : keys ) {
if ( key . first = = property : : CLIENT_IS_PRIORITY_SPEAKER ) {
client - > clientPermissions - > set_permission ( permission : : b_client_is_priority_speaker , { 1 , 0 } , cmd [ " client_is_priority_speaker " ] . as < bool > ( ) ? permission : : v2 : : PermissionUpdateType : : set_value : permission : : v2 : : PermissionUpdateType : : delete_value , permission : : v2 : : PermissionUpdateType : : do_nothing ) ;
}
client - > properties ( ) [ key . first ] = cmd [ 0 ] [ key . second ] . value ( ) ;
updates . push_back ( key . first ) ;
}
if ( update_talk_rights )
client - > updateTalkRights ( client - > properties ( ) [ property : : CLIENT_TALK_POWER ] ) ;
if ( this - > server )
this - > server - > notifyClientPropertyUpdates ( client , updates ) ;
nickname_lock . reset ( ) ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientUpdate ( Command & cmd ) {
return this - > handleCommandClientEdit ( cmd , _this . lock ( ) ) ;
}
command_result ConnectedClient : : handleCommandClientMute ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
2020-02-01 14:32:16 +01:00
ConnectedLockedClient client { this - > server - > find_client_by_id ( cmd [ " clid " ] . as < ClientId > ( ) ) } ;
2020-01-26 14:21:34 +01:00
if ( ! client | | client - > getClientId ( ) = = this - > getClientId ( ) ) return command_result { error : : client_invalid_id } ;
{
unique_lock channel_lock ( this - > channel_lock ) ;
for ( const auto & weak : this - > mutedClients )
if ( weak . lock ( ) = = client ) return command_result { error : : ok } ;
2020-02-01 14:32:16 +01:00
this - > mutedClients . push_back ( client . client ) ;
2020-01-26 14:21:34 +01:00
}
if ( config : : voice : : notifyMuted )
client - > notifyTextMessage ( ChatMessageMode : : TEXTMODE_PRIVATE , _this . lock ( ) , client - > getClientId ( ) , 0 , system_clock : : now ( ) , config : : messages : : mute_notify_message ) ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientUnmute ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
2020-02-01 14:32:16 +01:00
ConnectedLockedClient client { this - > server - > find_client_by_id ( cmd [ " clid " ] . as < ClientId > ( ) ) } ;
2020-01-26 14:21:34 +01:00
if ( ! client | | client - > getClientId ( ) = = this - > getClientId ( ) ) return command_result { error : : client_invalid_id } ;
{
unique_lock channel_lock ( this - > channel_lock ) ;
2020-02-01 14:32:16 +01:00
this - > mutedClients . erase ( std : : remove_if ( this - > mutedClients . begin ( ) , this - > mutedClients . end ( ) , [ & ] ( const weak_ptr < ConnectedClient > & weak ) {
2020-01-26 14:21:34 +01:00
auto c = weak . lock ( ) ;
return ! c | | c = = client ;
} ) , this - > mutedClients . end ( ) ) ;
}
if ( config : : voice : : notifyMuted )
client - > notifyTextMessage ( ChatMessageMode : : TEXTMODE_PRIVATE , _this . lock ( ) , client - > getClientId ( ) , 0 , system_clock : : now ( ) , config : : messages : : unmute_notify_message ) ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientList ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
bool allow_ip = false ;
if ( cmd . hasParm ( " ip " ) )
allow_ip = permission : : v2 : : permission_granted ( 1 , this - > calculate_permission ( permission : : b_client_remoteaddress_view , 0 ) ) ;
Command result ( " " ) ;
int index = 0 ;
this - > server - > forEachClient ( [ & ] ( shared_ptr < ConnectedClient > client ) {
if ( client - > getType ( ) = = ClientType : : CLIENT_INTERNAL ) return ;
result [ index ] [ " clid " ] = client - > getClientId ( ) ;
if ( client - > getChannel ( ) )
result [ index ] [ " cid " ] = client - > getChannel ( ) - > channelId ( ) ;
else result [ index ] [ " cid " ] = 0 ;
result [ index ] [ " client_database_id " ] = client - > getClientDatabaseId ( ) ;
result [ index ] [ " client_nickname " ] = client - > getDisplayName ( ) ;
result [ index ] [ " client_type " ] = client - > getType ( ) ;
if ( cmd . hasParm ( " uid " ) )
result [ index ] [ " client_unique_identifier " ] = client - > getUid ( ) ;
if ( cmd . hasParm ( " away " ) ) {
result [ index ] [ " client_away " ] = client - > properties ( ) [ property : : CLIENT_AWAY ] . as < string > ( ) ;
result [ index ] [ " client_away_message " ] = client - > properties ( ) [ property : : CLIENT_AWAY_MESSAGE ] . as < string > ( ) ;
}
if ( cmd . hasParm ( " groups " ) ) {
result [ index ] [ " client_channel_group_id " ] = client - > properties ( ) [ property : : CLIENT_CHANNEL_GROUP_ID ] . as < string > ( ) ;
result [ index ] [ " client_servergroups " ] = client - > properties ( ) [ property : : CLIENT_SERVERGROUPS ] . as < string > ( ) ;
result [ index ] [ " client_channel_group_inherited_channel_id " ] = client - > properties ( ) [ property : : CLIENT_CHANNEL_GROUP_INHERITED_CHANNEL_ID ] . as < string > ( ) ;
}
if ( cmd . hasParm ( " times " ) ) {
result [ index ] [ " client_idle_time " ] = duration_cast < milliseconds > ( system_clock : : now ( ) - client - > idleTimestamp ) . count ( ) ;
result [ index ] [ " client_total_online_time " ] = client - > properties ( ) [ property : : CLIENT_TOTAL_ONLINE_TIME ] . as < int64_t > ( ) + duration_cast < seconds > ( system_clock : : now ( ) - client - > lastOnlineTimestamp ) . count ( ) ;
result [ index ] [ " client_month_online_time " ] = client - > properties ( ) [ property : : CLIENT_MONTH_ONLINE_TIME ] . as < int64_t > ( ) + duration_cast < seconds > ( system_clock : : now ( ) - client - > lastOnlineTimestamp ) . count ( ) ;
result [ index ] [ " client_idle_time " ] = duration_cast < milliseconds > ( system_clock : : now ( ) - client - > idleTimestamp ) . count ( ) ;
result [ index ] [ " client_created " ] = client - > properties ( ) [ property : : CLIENT_CREATED ] . as < string > ( ) ;
result [ index ] [ " client_lastconnected " ] = client - > properties ( ) [ property : : CLIENT_LASTCONNECTED ] . as < string > ( ) ;
}
if ( cmd . hasParm ( " info " ) ) {
result [ index ] [ " client_version " ] = client - > properties ( ) [ property : : CLIENT_VERSION ] . as < string > ( ) ;
result [ index ] [ " client_platform " ] = client - > properties ( ) [ property : : CLIENT_PLATFORM ] . as < string > ( ) ;
}
if ( cmd . hasParm ( " badges " ) )
result [ index ] [ " client_badges " ] = client - > properties ( ) [ property : : CLIENT_BADGES ] . as < string > ( ) ;
if ( cmd . hasParm ( " country " ) )
result [ index ] [ " client_country " ] = client - > properties ( ) [ property : : CLIENT_COUNTRY ] . as < string > ( ) ;
if ( cmd . hasParm ( " ip " ) )
result [ index ] [ " connection_client_ip " ] = allow_ip ? client - > properties ( ) [ property : : CONNECTION_CLIENT_IP ] . as < string > ( ) : " hidden " ;
if ( cmd . hasParm ( " icon " ) )
result [ index ] [ " client_icon_id " ] = client - > properties ( ) [ property : : CLIENT_ICON_ID ] . as < string > ( ) ;
if ( cmd . hasParm ( " voice " ) ) {
result [ index ] [ " client_talk_power " ] = client - > properties ( ) [ property : : CLIENT_TALK_POWER ] . as < string > ( ) ;
result [ index ] [ " client_flag_talking " ] = client - > properties ( ) [ property : : CLIENT_FLAG_TALKING ] . as < string > ( ) ;
result [ index ] [ " client_input_muted " ] = client - > properties ( ) [ property : : CLIENT_INPUT_MUTED ] . as < string > ( ) ;
result [ index ] [ " client_output_muted " ] = client - > properties ( ) [ property : : CLIENT_OUTPUT_MUTED ] . as < string > ( ) ;
result [ index ] [ " client_input_hardware " ] = client - > properties ( ) [ property : : CLIENT_INPUT_HARDWARE ] . as < string > ( ) ;
result [ index ] [ " client_output_hardware " ] = client - > properties ( ) [ property : : CLIENT_OUTPUT_HARDWARE ] . as < string > ( ) ;
result [ index ] [ " client_is_talker " ] = client - > properties ( ) [ property : : CLIENT_IS_TALKER ] . as < string > ( ) ;
result [ index ] [ " client_is_priority_speaker " ] = client - > properties ( ) [ property : : CLIENT_IS_PRIORITY_SPEAKER ] . as < string > ( ) ;
result [ index ] [ " client_is_recording " ] = client - > properties ( ) [ property : : CLIENT_IS_RECORDING ] . as < string > ( ) ;
result [ index ] [ " client_is_channel_commander " ] = client - > properties ( ) [ property : : CLIENT_IS_CHANNEL_COMMANDER ] . as < string > ( ) ;
}
index + + ;
} ) ;
this - > sendCommand ( result ) ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientGetDBIDfromUID ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
deque < string > unique_ids ;
for ( int index = 0 ; index < cmd . bulkCount ( ) ; index + + )
unique_ids . push_back ( cmd [ index ] [ " cluid " ] . as < string > ( ) ) ;
auto res = serverInstance - > databaseHelper ( ) - > queryDatabaseInfoByUid ( this - > server , unique_ids ) ;
if ( res . empty ( ) ) return command_result { error : : database_empty_result } ;
Command result ( this - > getExternalType ( ) = = CLIENT_TEAMSPEAK ? " notifyclientdbidfromuid " : " " ) ;
int result_index = 0 ;
for ( auto & info : res ) {
result [ result_index ] [ " cluid " ] = info - > uniqueId ;
result [ result_index ] [ " cldbid " ] = info - > cldbid ;
result_index + + ;
}
this - > sendCommand ( result ) ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientGetNameFromDBID ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
deque < ClientDbId > dbids ;
for ( int index = 0 ; index < cmd . bulkCount ( ) ; index + + )
dbids . push_back ( cmd [ index ] [ " cldbid " ] . as < ClientDbId > ( ) ) ;
auto res = serverInstance - > databaseHelper ( ) - > queryDatabaseInfo ( this - > server , dbids ) ;
if ( res . empty ( ) ) return command_result { error : : database_empty_result } ;
Command result ( this - > getExternalType ( ) = = CLIENT_TEAMSPEAK ? " notifyclientgetnamefromdbid " : " " ) ;
int result_index = 0 ;
for ( auto & info : res ) {
result [ result_index ] [ " cluid " ] = info - > uniqueId ;
result [ result_index ] [ " cldbid " ] = info - > cldbid ;
result [ result_index ] [ " name " ] = info - > lastName ;
result [ result_index ] [ " clname " ] = info - > lastName ;
result_index + + ;
}
this - > sendCommand ( result ) ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientGetNameFromUid ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
deque < string > unique_ids ;
for ( int index = 0 ; index < cmd . bulkCount ( ) ; index + + )
unique_ids . push_back ( cmd [ index ] [ " cluid " ] . as < string > ( ) ) ;
auto res = serverInstance - > databaseHelper ( ) - > queryDatabaseInfoByUid ( this - > server , unique_ids ) ;
if ( res . empty ( ) ) return command_result { error : : database_empty_result } ;
Command result ( this - > getExternalType ( ) = = CLIENT_TEAMSPEAK ? " notifyclientnamefromuid " : " " ) ;
int result_index = 0 ;
for ( auto & info : res ) {
result [ result_index ] [ " cluid " ] = info - > uniqueId ;
result [ result_index ] [ " cldbid " ] = info - > cldbid ;
result [ result_index ] [ " name " ] = info - > lastName ;
result [ result_index ] [ " clname " ] = info - > lastName ;
result_index + + ;
}
this - > sendCommand ( result ) ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientGetUidFromClid ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
bool error = false ;
bool found = false ;
auto client_list = this - > server - > getClients ( ) ;
Command notify ( this - > getExternalType ( ) = = CLIENT_TEAMSPEAK ? " notifyclientgetuidfromclid " : " " ) ;
int result_index = 0 ;
for ( int index = 0 ; index < cmd . bulkCount ( ) ; index + + ) {
auto client_id = cmd [ index ] [ " clid " ] . as < ClientId > ( ) ;
for ( const auto & entry : client_list ) {
if ( entry - > getClientId ( ) = = client_id ) {
notify [ result_index ] [ " clname " ] = entry - > getDisplayName ( ) ;
notify [ result_index ] [ " clid " ] = entry - > getClientId ( ) ;
notify [ result_index ] [ " cluid " ] = entry - > getUid ( ) ;
notify [ result_index ] [ " cldbid " ] = entry - > getClientDatabaseId ( ) ;
result_index + + ;
found = true ;
}
}
if ( found ) found = false ;
else error = false ;
}
if ( result_index > 0 )
this - > sendCommand ( notify ) ;
if ( error )
return command_result { error : : database_empty_result } ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientAddPerm ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
CMD_CHK_AND_INC_FLOOD_POINTS ( 5 ) ;
auto cldbid = cmd [ " cldbid " ] . as < ClientDbId > ( ) ;
if ( ! serverInstance - > databaseHelper ( ) - > validClientDatabaseId ( this - > server , cldbid ) )
return command_result { error : : client_invalid_id } ;
auto mgr = serverInstance - > databaseHelper ( ) - > loadClientPermissionManager ( this - > server , cldbid ) ;
ACTION_REQUIRES_GLOBAL_PERMISSION ( permission : : i_client_permission_modify_power , this - > server - > calculate_permission ( permission : : i_client_needed_permission_modify_power , cldbid , ClientType : : CLIENT_TEAMSPEAK , 0 ) ) ;
auto max_value = this - > calculate_permission ( permission : : i_permission_modify_power , 0 , true ) ;
if ( ! max_value . has_value ) return command_result { permission : : i_permission_modify_power } ;
auto ignore_granted_values = permission : : v2 : : permission_granted ( 1 , this - > calculate_permission ( permission : : b_permission_modify_power_ignore , 0 ) ) ;
bool conOnError = cmd [ 0 ] . has ( " continueonerror " ) ;
auto update_channels = false ;
for ( int index = 0 ; index < cmd . bulkCount ( ) ; index + + ) {
PARSE_PERMISSION ( cmd ) ;
auto val = cmd [ index ] [ " permvalue " ] . as < permission : : PermissionValue > ( ) ;
if ( permission_require_granted_value ( permType ) & & ! permission : : v2 : : permission_granted ( val , max_value ) ) {
if ( conOnError ) continue ;
return command_result { permission : : i_permission_modify_power } ;
}
if ( ! ignore_granted_values & & ! permission : : v2 : : permission_granted ( val , this - > calculate_permission ( permType , 0 , true ) ) ) {
if ( conOnError ) continue ;
return command_result { permission : : i_permission_modify_power } ;
}
if ( grant ) {
mgr - > set_permission ( permType , { 0 , cmd [ index ] [ " permvalue " ] } , permission : : v2 : : do_nothing , permission : : v2 : : set_value ) ;
} else {
mgr - > set_permission ( permType , { cmd [ index ] [ " permvalue " ] , 0 } , permission : : v2 : : set_value , permission : : v2 : : do_nothing , cmd [ index ] [ " permskip " ] ? 1 : 0 , cmd [ index ] [ " permnegated " ] ? 1 : 0 ) ;
update_channels | = permission_is_client_property ( permType ) ;
}
}
serverInstance - > databaseHelper ( ) - > saveClientPermissions ( this - > server , cldbid , mgr ) ;
auto onlineClients = this - > server - > findClientsByCldbId ( cldbid ) ;
if ( ! onlineClients . empty ( ) )
for ( const auto & elm : onlineClients ) {
if ( elm - > update_cached_permissions ( ) ) /* update cached calculated permissions */
elm - > sendNeededPermissions ( false ) ; /* cached permissions had changed, notify the client */
if ( update_channels )
elm - > updateChannelClientProperties ( true , true ) ;
elm - > join_state_id + + ; /* join permission may changed, all channels need to be recalculate dif needed */
}
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientDelPerm ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
CMD_CHK_AND_INC_FLOOD_POINTS ( 5 ) ;
auto cldbid = cmd [ " cldbid " ] . as < ClientDbId > ( ) ;
if ( ! serverInstance - > databaseHelper ( ) - > validClientDatabaseId ( this - > server , cldbid ) )
return command_result { error : : client_invalid_id } ;
auto mgr = serverInstance - > databaseHelper ( ) - > loadClientPermissionManager ( this - > server , cldbid ) ;
ACTION_REQUIRES_GLOBAL_PERMISSION ( permission : : i_client_permission_modify_power , this - > server - > calculate_permission ( permission : : i_client_needed_permission_modify_power , cldbid , ClientType : : CLIENT_TEAMSPEAK , 0 ) ) ;
auto ignore_granted_values = permission : : v2 : : permission_granted ( 1 , this - > calculate_permission ( permission : : b_permission_modify_power_ignore , 0 ) ) ;
bool conOnError = cmd [ 0 ] . has ( " continueonerror " ) ;
auto onlineClients = this - > server - > findClientsByCldbId ( cmd [ " cldbid " ] ) ;
auto update_channel = false ;
for ( int index = 0 ; index < cmd . bulkCount ( ) ; index + + ) {
PARSE_PERMISSION ( cmd )
if ( ! ignore_granted_values & & ! permission : : v2 : : permission_granted ( 0 , this - > calculate_permission ( permType , 0 , true ) ) ) {
if ( conOnError ) continue ;
return command_result { permission : : i_permission_modify_power } ;
}
if ( grant ) {
mgr - > set_permission ( permType , permission : : v2 : : empty_permission_values , permission : : v2 : : do_nothing , permission : : v2 : : delete_value ) ;
} else {
mgr - > set_permission ( permType , permission : : v2 : : empty_permission_values , permission : : v2 : : delete_value , permission : : v2 : : do_nothing ) ;
update_channel | = permission_is_client_property ( permType ) ;
}
}
serverInstance - > databaseHelper ( ) - > saveClientPermissions ( this - > server , cldbid , mgr ) ;
if ( ! onlineClients . empty ( ) )
for ( const auto & elm : onlineClients ) {
if ( elm - > update_cached_permissions ( ) ) /* update cached calculated permissions */
elm - > sendNeededPermissions ( false ) ; /* cached permissions had changed, notify the client */
if ( update_channel )
elm - > updateChannelClientProperties ( true , true ) ;
elm - > join_state_id + + ; /* join permission may changed, all channels need to be recalculate dif needed */
}
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientPermList ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
CMD_CHK_AND_INC_FLOOD_POINTS ( 5 ) ;
ACTION_REQUIRES_GLOBAL_PERMISSION ( permission : : b_virtualserver_client_permission_list , 1 ) ;
if ( ! serverInstance - > databaseHelper ( ) - > validClientDatabaseId ( this - > server , cmd [ " cldbid " ] ) ) return command_result { error : : client_invalid_id } ;
auto mgr = serverInstance - > databaseHelper ( ) - > loadClientPermissionManager ( this - > server , cmd [ " cldbid " ] ) ;
if ( ! this - > notifyClientPermList ( cmd [ " cldbid " ] , mgr , cmd . hasParm ( " permsid " ) ) ) return command_result { error : : database_empty_result } ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientDbInfo ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
CMD_CHK_AND_INC_FLOOD_POINTS ( 5 ) ;
ACTION_REQUIRES_GLOBAL_PERMISSION ( permission : : b_virtualserver_client_dbinfo , 1 ) ;
deque < ClientDbId > cldbids ;
for ( int index = 0 ; index < cmd . bulkCount ( ) ; index + + )
cldbids . push_back ( cmd [ index ] [ " cldbid " ] ) ;
auto basic = serverInstance - > databaseHelper ( ) - > queryDatabaseInfo ( this - > server , cldbids ) ;
if ( basic . empty ( ) ) return command_result { error : : database_empty_result } ;
auto allow_ip = permission : : v2 : : permission_granted ( 1 , this - > calculate_permission ( permission : : b_client_remoteaddress_view , 0 ) ) ;
Command res ( this - > getExternalType ( ) = = ClientType : : CLIENT_TEAMSPEAK ? " notifyclientdbinfo " : " " ) ;
size_t index = 0 ;
for ( const auto & info : basic ) {
res [ index ] [ " client_base64HashClientUID " ] = hex : : hex ( base64 : : validate ( info - > uniqueId ) ? base64 : : decode ( info - > uniqueId ) : info - > uniqueId , ' a ' , ' q ' ) ;
res [ index ] [ " client_unique_identifier " ] = info - > uniqueId ;
res [ index ] [ " client_nickname " ] = info - > lastName ;
res [ index ] [ " client_database_id " ] = info - > cldbid ;
res [ index ] [ " client_created " ] = chrono : : duration_cast < chrono : : seconds > ( info - > created . time_since_epoch ( ) ) . count ( ) ;
res [ index ] [ " client_lastconnected " ] = chrono : : duration_cast < chrono : : seconds > ( info - > lastjoin . time_since_epoch ( ) ) . count ( ) ;
res [ index ] [ " client_totalconnections " ] = info - > connections ;
res [ index ] [ " client_database_id " ] = info - > cldbid ;
auto props = serverInstance - > databaseHelper ( ) - > loadClientProperties ( this - > server , info - > cldbid , ClientType : : CLIENT_TEAMSPEAK ) ;
if ( allow_ip )
res [ index ] [ " client_lastip " ] = ( * props ) [ property : : CONNECTION_CLIENT_IP ] . as < string > ( ) ;
else
res [ index ] [ " client_lastip " ] = " hidden " ;
res [ index ] [ " client_icon_id " ] = ( * props ) [ property : : CLIENT_ICON_ID ] . as < string > ( ) ;
res [ index ] [ " client_badges " ] = ( * props ) [ property : : CLIENT_BADGES ] . as < string > ( ) ;
res [ index ] [ " client_version " ] = ( * props ) [ property : : CLIENT_VERSION ] . as < string > ( ) ;
res [ index ] [ " client_platform " ] = ( * props ) [ property : : CLIENT_PLATFORM ] . as < string > ( ) ;
res [ index ] [ " client_hwid " ] = ( * props ) [ property : : CLIENT_HARDWARE_ID ] . as < string > ( ) ;
res [ index ] [ " client_total_bytes_downloaded " ] = ( * props ) [ property : : CLIENT_TOTAL_BYTES_DOWNLOADED ] . as < string > ( ) ;
res [ index ] [ " client_total_bytes_uploaded " ] = ( * props ) [ property : : CLIENT_TOTAL_BYTES_UPLOADED ] . as < string > ( ) ;
res [ index ] [ " client_month_bytes_downloaded " ] = ( * props ) [ property : : CLIENT_MONTH_BYTES_DOWNLOADED ] . as < string > ( ) ;
res [ index ] [ " client_month_bytes_uploaded " ] = ( * props ) [ property : : CLIENT_MONTH_BYTES_DOWNLOADED ] . as < string > ( ) ;
res [ index ] [ " client_description " ] = ( * props ) [ property : : CLIENT_DESCRIPTION ] . as < string > ( ) ;
res [ index ] [ " client_flag_avatar " ] = ( * props ) [ property : : CLIENT_FLAG_AVATAR ] . as < string > ( ) ;
res [ index ] [ " client_month_online_time " ] = ( * props ) [ property : : CLIENT_MONTH_ONLINE_TIME ] . as < string > ( ) ;
res [ index ] [ " client_total_online_time " ] = ( * props ) [ property : : CLIENT_TOTAL_ONLINE_TIME ] . as < string > ( ) ;
index + + ;
}
this - > sendCommand ( res ) ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientDBDelete ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
CMD_CHK_AND_INC_FLOOD_POINTS ( 5 ) ;
ACTION_REQUIRES_GLOBAL_PERMISSION ( permission : : b_client_delete_dbproperties , 1 ) ;
ClientDbId id = cmd [ " cldbid " ] ;
if ( ! serverInstance - > databaseHelper ( ) - > validClientDatabaseId ( this - > server , id ) ) return command_result { error : : database_empty_result } ;
serverInstance - > databaseHelper ( ) - > deleteClient ( this - > server , id ) ;
return command_result { error : : ok } ;
}
struct DBFindArgs {
int index = 0 ;
bool full = false ;
bool ip = false ;
Command cmd { " " } ;
} ;
command_result ConnectedClient : : handleCommandClientDBFind ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
CMD_CHK_AND_INC_FLOOD_POINTS ( 5 ) ;
ACTION_REQUIRES_GLOBAL_PERMISSION ( permission : : b_virtualserver_client_dbsearch , 1 ) ;
bool uid = cmd . hasParm ( " uid " ) ;
string pattern = cmd [ " pattern " ] ;
DBFindArgs args { } ;
args . cmd = Command ( this - > getType ( ) = = CLIENT_QUERY ? " " : " notifyclientdbfind " ) ;
args . full = cmd . hasParm ( " details " ) ;
args . ip = permission : : v2 : : permission_granted ( 1 , this - > calculate_permission ( permission : : b_client_remoteaddress_view , 0 ) ) ;
auto res = sql : : command ( this - > sql , string ( ) + " SELECT * FROM `clients` WHERE `serverId` = :sid AND ` " + ( uid ? " clientUid " : " lastName " ) + " ` LIKE ' " + pattern + " ' LIMIT 50 " , variable { " :sid " , this - > server - > getServerId ( ) } ) . query (
[ & ] ( DBFindArgs * ptr , int len , char * * values , char * * names ) {
for ( int index = 0 ; index < len ; index + + )
if ( strcmp ( names [ index ] , " cldbid " ) = = 0 )
ptr - > cmd [ ptr - > index ] [ " cldbid " ] = values [ index ] ;
else if ( strcmp ( names [ index ] , " clientUid " ) = = 0 & & ptr - > full )
ptr - > cmd [ ptr - > index ] [ " client_unique_identifier " ] = values [ index ] ;
else if ( strcmp ( names [ index ] , " lastConnect " ) = = 0 & & ptr - > full )
ptr - > cmd [ ptr - > index ] [ " client_lastconnected " ] = values [ index ] ;
else if ( strcmp ( names [ index ] , " connections " ) = = 0 & & ptr - > full )
ptr - > cmd [ ptr - > index ] [ " client_totalconnections " ] = values [ index ] ;
else if ( strcmp ( names [ index ] , " lastName " ) = = 0 & & ptr - > full )
ptr - > cmd [ ptr - > index ] [ " client_nickname " ] = values [ index ] ;
if ( ptr - > full ) {
auto props = serverInstance - > databaseHelper ( ) - > loadClientProperties ( this - > server , ptr - > cmd [ ptr - > index ] [ " cldbid " ] , ClientType : : CLIENT_TEAMSPEAK ) ;
if ( props ) {
if ( ptr - > ip ) {
ptr - > cmd [ ptr - > index ] [ " client_lastip " ] = ( * props ) [ property : : CONNECTION_CLIENT_IP ] . as < string > ( ) ;
} else {
ptr - > cmd [ ptr - > index ] [ " client_lastip " ] = " hidden " ;
}
ptr - > cmd [ ptr - > index ] [ " client_badges " ] = ( * props ) [ property : : CLIENT_BADGES ] . as < string > ( ) ;
ptr - > cmd [ ptr - > index ] [ " client_version " ] = ( * props ) [ property : : CLIENT_VERSION ] . as < string > ( ) ;
ptr - > cmd [ ptr - > index ] [ " client_platform " ] = ( * props ) [ property : : CLIENT_PLATFORM ] . as < string > ( ) ;
ptr - > cmd [ ptr - > index ] [ " client_hwid " ] = ( * props ) [ property : : CLIENT_HARDWARE_ID ] . as < string > ( ) ;
}
}
ptr - > index + + ;
return 0 ;
} , & args ) ;
auto pf = LOG_SQL_CMD ;
pf ( res ) ;
if ( args . index = = 0 ) return command_result { error : : database_empty_result } ;
this - > sendCommand ( args . cmd ) ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientInfo ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_RESET_IDLE ;
Command res ( this - > getExternalType ( ) = = ClientType : : CLIENT_TEAMSPEAK ? " notifyclientinfo " : " " ) ;
bool trigger_error = false ;
bool view_remote = permission : : v2 : : permission_granted ( 1 , this - > calculate_permission ( permission : : b_client_remoteaddress_view , 0 ) ) ;
int result_index = 0 ;
for ( int index = 0 ; index < cmd . bulkCount ( ) ; index + + ) {
auto client_id = cmd [ index ] [ " clid " ] . as < ClientId > ( ) ;
if ( client_id = = 0 ) continue ;
2020-02-01 14:32:16 +01:00
ConnectedLockedClient client { this - > server - > find_client_by_id ( client_id ) } ;
2020-01-26 14:21:34 +01:00
if ( ! client ) {
trigger_error = true ;
continue ;
}
for ( const auto & key : client - > properties ( ) - > list_properties ( property : : FLAG_CLIENT_VIEW | property : : FLAG_CLIENT_VARIABLE | property : : FLAG_CLIENT_INFO , this - > getType ( ) = = CLIENT_TEAMSPEAK ? property : : FLAG_NEW : ( uint16_t ) 0 ) )
res [ result_index ] [ key . type ( ) . name ] = key . value ( ) ;
if ( view_remote )
res [ result_index ] [ " connection_client_ip " ] = client - > properties ( ) [ property : : CONNECTION_CLIENT_IP ] . as < string > ( ) ;
else
res [ result_index ] [ " connection_client_ip " ] = " hidden " ;
res [ result_index ] [ " client_idle_time " ] = duration_cast < milliseconds > ( system_clock : : now ( ) - client - > idleTimestamp ) . count ( ) ;
res [ result_index ] [ " connection_connected_time " ] = duration_cast < milliseconds > ( system_clock : : now ( ) - client - > connectTimestamp ) . count ( ) ;
{
auto channel = client - > currentChannel ;
if ( channel )
res [ result_index ] [ " cid " ] = channel - > channelId ( ) ;
else
res [ result_index ] [ " cid " ] = 0 ;
}
result_index + + ;
}
if ( result_index > 0 ) {
this - > sendCommand ( res ) ;
}
if ( trigger_error | | result_index = = 0 )
return command_result { error : : client_invalid_id } ;
else
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientFind ( Command & cmd ) {
CMD_REQ_SERVER ;
CMD_CHK_AND_INC_FLOOD_POINTS ( 5 ) ;
string pattern = cmd [ " pattern " ] ;
std : : transform ( pattern . begin ( ) , pattern . end ( ) , pattern . begin ( ) , : : tolower ) ;
Command res ( " " ) ;
int index = 0 ;
for ( const auto & cl : this - > server - > getClients ( ) ) {
string name = cl - > getDisplayName ( ) ;
std : : transform ( name . begin ( ) , name . end ( ) , name . begin ( ) , : : tolower ) ;
if ( name . find ( pattern ) ! = std : : string : : npos ) {
res [ index ] [ " clid " ] = cl - > getClientId ( ) ;
res [ index ] [ " client_nickname " ] = cl - > getDisplayName ( ) ;
index + + ;
}
}
if ( index = = 0 ) return command_result { error : : database_empty_result } ;
this - > sendCommand ( res ) ;
return command_result { error : : ok } ;
}
command_result ConnectedClient : : handleCommandClientSetServerQueryLogin ( Command & cmd ) {
ACTION_REQUIRES_GLOBAL_PERMISSION ( permission : : b_client_create_modify_serverquery_login , 1 ) ;
if ( ! cmd [ 0 ] . has ( " client_login_password " ) ) cmd [ " client_login_password " ] = " " ;
std : : string password = cmd [ " client_login_password " ] ;
if ( password . empty ( ) )
password = rnd_string ( QUERY_PASSWORD_LENGTH ) ;
auto old = serverInstance - > getQueryServer ( ) - > find_query_account_by_name ( cmd [ " client_login_name " ] ) ;
if ( old ) {
if ( old - > unique_id = = this - > getUid ( ) ) {
serverInstance - > getQueryServer ( ) - > change_query_password ( old , password ) ;
} else {
return command_result { error : : client_not_logged_in } ;
}
} else {
serverInstance - > getQueryServer ( ) - > create_query_account ( cmd [ " client_login_name " ] , this - > getServerId ( ) , this - > getUid ( ) , password ) ;
}
Command res ( this - > notify_response_command ( " notifyclientserverqueryloginpassword " ) ) ;
res [ " client_login_password " ] = password ;
this - > sendCommand ( res ) ;
return command_result { error : : ok } ;
}