Teaspeak-Server/server/src/client/command_handler/helpers.h

221 lines
10 KiB
C++

#pragma once
/** Permission tests against required values **/
/* use this for any action which will do something with the server */
#define ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(required_permission_type, required_value, cache) \
do { \
if(!permission::v2::permission_granted(required_value, this->calculate_permission(required_permission_type, 0, false, cache))) \
return command_result{required_permission_type}; \
} while(0)
#define ACTION_REQUIRES_GLOBAL_PERMISSION(required_permission_type, required_value) \
ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(required_permission_type, required_value, nullptr)
//TODO: Fixme: Really check for instance permissions!
#define ACTION_REQUIRES_INSTANCE_PERMISSION(required_permission_type, required_value) \
ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(required_permission_type, required_value, nullptr)
/* use this for anything which will do something local in relation to the target channel */
#define ACTION_REQUIRES_PERMISSION(required_permission_type, required_value, channel_id) \
do { \
if(!permission::v2::permission_granted(required_value, this->calculate_permission(required_permission_type, channel_id))) \
return command_result{required_permission_type}; \
} while(0)
/** Permission tests against groups **/
/* use this when testing a permission against a group */
#define ACTION_REQUIRES_GROUP_PERMISSION(group, required_permission_type, own_permission_type, is_required) \
do { \
auto _permission_granted = this->calculate_permission(own_permission_type, 0); \
if(!(group)->permission_granted(required_permission_type, _permission_granted, is_required)) \
return command_result{own_permission_type}; \
} while(0)
/** Permission tests against channels **/
/* use this when testing a permission against a group */
#define ACTION_REQUIRES_CHANNEL_PERMISSION(channel, required_permission_type, own_permission_type, is_required) \
do { \
auto _permission_granted = this->calculate_permission(own_permission_type, channel ? channel->channelId() : 0); \
if(!(channel)->permission_granted(required_permission_type, _permission_granted, is_required)) \
return command_result{own_permission_type}; \
} while(0)
/* Helper methods for channel resolve */
#define RESOLVE_CHANNEL_R(command, force) \
auto channel_tree = this->server ? this->server->channelTree : serverInstance->getChannelTree().get();\
shared_lock channel_tree_read_lock(this->server ? this->server->channel_tree_lock : serverInstance->getChannelTreeLock());\
auto channel_id = command.as<ChannelId>(); \
auto l_channel = channel_id ? channel_tree->findLinkedChannel(command.as<ChannelId>()) : nullptr; \
if (!l_channel && (channel_id != 0 || force)) return command_result{error::channel_invalid_id, "Cant resolve channel"}; \
#define RESOLVE_CHANNEL_W(command, force) \
auto channel_tree = this->server ? this->server->channelTree : serverInstance->getChannelTree().get();\
unique_lock channel_tree_write_lock(this->server ? this->server->channel_tree_lock : serverInstance->getChannelTreeLock());\
auto channel_id = command.as<ChannelId>(); \
auto l_channel = channel_id ? channel_tree->findLinkedChannel(command.as<ChannelId>()) : nullptr; \
if (!l_channel && (channel_id != 0 || force)) return command_result{error::channel_invalid_id, "Cant resolve channel"}; \
//TODO: Map permsid!
#define PARSE_PERMISSION(cmd) \
permission::PermissionType permType = permission::PermissionType::unknown; \
bool grant = false; \
if (cmd[index].has("permid")) { \
permType = cmd[index]["permid"].as<permission::PermissionType>(); \
if ((permType & PERM_ID_GRANT) != 0) { \
grant = true; \
permType &= ~PERM_ID_GRANT; \
} \
} else if (cmd[index].has("permsid")) { \
auto resv = permission::resolvePermissionData(cmd[index]["permsid"].as<string>()); \
permType = resv->type; \
if (resv->grantName() == cmd[index]["permsid"].as<string>()) grant = true; \
} \
if (permission::resolvePermissionData(permType)->type == permission::PermissionType::unknown) { \
if (conOnError) continue; \
return ts::command_result{error::parameter_invalid}; \
}
inline bool permission_require_granted_value(ts::permission::PermissionType type) {
using namespace ts;
/*
switch (type) {
case permission::i_permission_modify_power:
case permission::i_channel_group_member_add_power:
case permission::i_channel_group_member_remove_power:
case permission::i_channel_group_modify_power:
case permission::i_channel_group_needed_member_add_power:
case permission::i_channel_group_needed_member_remove_power:
case permission::i_channel_group_needed_modify_power:
case permission::i_server_group_member_add_power:
case permission::i_server_group_member_remove_power:
case permission::i_server_group_modify_power:
case permission::i_server_group_needed_member_add_power:
case permission::i_server_group_needed_member_remove_power:
case permission::i_server_group_needed_modify_power:
case permission::i_displayed_group_member_add_power:
case permission::i_displayed_group_member_remove_power:
case permission::i_displayed_group_modify_power:
case permission::i_displayed_group_needed_member_add_power:
case permission::i_displayed_group_needed_member_remove_power:
case permission::i_displayed_group_needed_modify_power:
case permission::i_channel_permission_modify_power:
case permission::i_channel_needed_permission_modify_power:
case permission::i_client_permission_modify_power:
case permission::i_client_needed_permission_modify_power:
case permission::i_client_needed_kick_from_server_power:
case permission::i_client_needed_kick_from_channel_power:
case permission::i_client_kick_from_channel_power:
case permission::i_client_kick_from_server_power:
return true;
default:
return false;
}
*/
switch (type) {
case permission::i_icon_id:
case permission::i_max_icon_filesize:
case permission::i_client_max_avatar_filesize:
case permission::i_client_max_channels:
case permission::i_client_max_permanent_channels:
case permission::i_client_max_semi_channels:
case permission::i_client_max_temporary_channels:
case permission::i_channel_max_depth:
case permission::i_channel_min_depth:
case permission::i_client_max_channel_subscriptions:
case permission::i_client_music_create_modify_max_volume:
case permission::i_max_playlist_size:
case permission::i_max_playlists:
case permission::i_client_ban_max_bantime:
case permission::i_client_max_idletime:
case permission::i_group_sort_id:
return false;
default:
return true;
}
}
inline bool permission_is_group_property(ts::permission::PermissionType type) {
using namespace ts;
switch (type) {
case permission::i_icon_id:
case permission::i_group_show_name_in_tree:
case permission::i_group_sort_id:
case permission::b_group_is_permanent:
case permission::i_displayed_group_needed_modify_power:
case permission::i_displayed_group_needed_member_add_power:
case permission::i_displayed_group_needed_member_remove_power:
return true;
default:
return false;
}
}
inline bool permission_is_client_property(ts::permission::PermissionType type) {
using namespace ts;
switch (type) {
case permission::i_icon_id:
case permission::i_client_talk_power:
case permission::i_client_max_idletime:
case permission::i_group_sort_id:
case permission::i_channel_view_power:
case permission::b_channel_ignore_view_power:
case permission::b_client_is_priority_speaker:
return true;
default:
return false;
}
}
inline ssize_t count_characters(const std::string& in) {
size_t index = 0;
size_t count = 0;
while(index < in.length()){
count++;
auto current = (uint8_t) in[index];
if(current >= 128) { //UTF8 check
if(current >= 192 && (current <= 193 || current >= 245)) {
return -1;
} else if(current >= 194 && current <= 223) {
if(in.length() - index <= 1) return -1;
else if((uint8_t) in[index + 1] >= 128 && (uint8_t) in[index + 1] <= 191) index += 1; //Valid
else return -1;
} else if(current >= 224 && current <= 239) {
if(in.length() - index <= 2) return -1;
else if((uint8_t) in[index + 1] >= 128 && (uint8_t) in[index + 1] <= 191 &&
(uint8_t) in[index + 2] >= 128 && (uint8_t) in[index + 2] <= 191) index += 2; //Valid
else return -1;
} else if(current >= 240 && current <= 244) {
if(in.length() - index <= 3) return -1;
else if((uint8_t) in[index + 1] >= 128 && (uint8_t) in[index + 1] <= 191 &&
(uint8_t) in[index + 2] >= 128 && (uint8_t) in[index + 2] <= 191 &&
(uint8_t) in[index + 3] >= 128 && (uint8_t) in[index + 3] <= 191) index += 3; //Valid
else return -1;
} else {
return -1;
}
}
index++;
}
return count;
}