#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(); \ auto l_channel = channel_id ? channel_tree->findLinkedChannel(command.as()) : 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(); \ auto l_channel = channel_id ? channel_tree->findLinkedChannel(command.as()) : 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(); \ 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()); \ permType = resv->type; \ if (resv->grantName() == cmd[index]["permsid"].as()) 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; }