diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fbce4f..39853ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,6 @@ find_package(DataPipes REQUIRED) include_directories(${DataPipes_INCLUDE_DIR}) find_package(Ed25519 REQUIRED) -include_directories(${ed25519_INCLUDE_DIR}) set(TARGET_LIBRARIES) set(FEATURE_LOGGING ON) @@ -236,6 +235,7 @@ add_library(TeaSpeak STATIC ${SOURCE_FILES} ${HEADER_FILES}) target_link_libraries(TeaSpeak PUBLIC tomcrypt::static tommath::static + ed25519::static ${OPENSSL_LIBRARIES} ${TARGET_LIBRARIES} dl @@ -246,7 +246,7 @@ if (TEASPEAK_SERVER) message("Found MySQL") target_link_libraries(TeaSpeak PUBLIC mysql::client::static - ) + ) target_compile_options(TeaSpeak PRIVATE "-Wall" "-DHAVE_MYSQL_H") target_link_libraries(TeaSpeak PUBLIC CXXTerminal::static) diff --git a/src/BasicChannel.cpp b/src/BasicChannel.cpp index 8c63ea4..b82ec3f 100644 --- a/src/BasicChannel.cpp +++ b/src/BasicChannel.cpp @@ -125,15 +125,26 @@ void BasicChannel::setChannelType(ChannelType::ChannelType type) { properties()[property::CHANNEL_FLAG_SEMI_PERMANENT] = type == ChannelType::semipermanent; } -bool BasicChannel::passwordMatch(std::string password, bool hashed) { - if (!this->properties()[property::CHANNEL_FLAG_PASSWORD].as_unchecked() || this->properties()[property::CHANNEL_PASSWORD].value().empty()) return true; - if (password.empty()) return false; - - if(this->properties()[property::CHANNEL_PASSWORD].as_unchecked() == password) +bool BasicChannel::verify_password(const std::optional &password, bool password_hashed) { + if(!this->properties()[property::CHANNEL_FLAG_PASSWORD].as_unchecked()) { return true; + } - password = base64::encode(digest::sha1(password)); - return this->properties()[property::CHANNEL_PASSWORD].as_unchecked() == password; + auto channel_password = this->properties()[property::CHANNEL_PASSWORD].value(); + if(channel_password.empty()) { + return true; + } + + if(!password.has_value()) { + return false; + } + + if(password_hashed) { + return *password == channel_password; + } + + /* We might have supplied the raw password */ + return base64::encode(digest::sha1(*password)) == channel_password; } int64_t BasicChannel::emptySince() { diff --git a/src/BasicChannel.h b/src/BasicChannel.h index 573f049..08fd2a8 100644 --- a/src/BasicChannel.h +++ b/src/BasicChannel.h @@ -52,7 +52,8 @@ namespace ts { ChannelType::ChannelType channelType(); void setChannelType(ChannelType::ChannelType); - bool passwordMatch(std::string password, bool hashed = false); + [[nodiscard]] bool verify_password(const std::optional&, bool /* password already hashed */); + bool defaultChannel() { return (*this->_properties)[property::CHANNEL_FLAG_DEFAULT]; } int64_t emptySince(); diff --git a/src/PermissionManager.h b/src/PermissionManager.h index e188cfa..5c0312c 100644 --- a/src/PermissionManager.h +++ b/src/PermissionManager.h @@ -825,6 +825,13 @@ namespace ts { [[nodiscard]] constexpr bool has_power() const { return this->has_value && (this->value > 0 || this->value == -1); } [[nodiscard]] constexpr bool has_infinite_power() const { return this->has_value && this->value == -1; } + constexpr bool clear_flag_on_zero() { + if(this->has_value && this->value == 0) { + this->has_value = false; + return true; + } + return false; + } inline bool operator==(const PermissionFlaggedValue& other) const { return other.value == this->value && other.has_value == this->has_value; } inline bool operator!=(const PermissionFlaggedValue& other) const { return !(*this == other); } @@ -832,9 +839,10 @@ namespace ts { static constexpr PermissionFlaggedValue empty_permission_flagged_value{0, false}; - static constexpr bool permission_granted(const PermissionFlaggedValue& required, const PermissionFlaggedValue& given, bool requires_given = true) { + static constexpr bool permission_granted(const PermissionFlaggedValue& required, const PermissionFlaggedValue& given) { if(!required.has_value) { - return !requires_given || given.has_power(); + /* The target permission hasn't been set so just check if we've not negated the target */ + return !given.has_value || given.value >= 0; } else if(!given.has_power()) { return false; } else if(given.has_infinite_power()) { @@ -845,8 +853,8 @@ namespace ts { return given.value >= required.value; } } - static constexpr bool permission_granted(const PermissionValue& required, const PermissionFlaggedValue& given, bool requires_given = true) { - return permission_granted({required, true}, given, requires_given); + static constexpr bool permission_granted(const PermissionValue& required, const PermissionFlaggedValue& given) { + return permission_granted({required, true}, given); } class PermissionManager { diff --git a/src/log/LogSinks.cpp b/src/log/LogSinks.cpp index 2997684..ef76cb0 100644 --- a/src/log/LogSinks.cpp +++ b/src/log/LogSinks.cpp @@ -16,20 +16,25 @@ namespace logger { #ifdef HAVE_CXX_TERMINAL if (terminal::active()) { //Split the string at new lines - size_t index{0}, found{0}; + size_t index{0}, found; do { found = message.find('\n', index); const auto length = (found == -1 ? message.length() : found) - index; const auto line = message.substr(index, length); index = found; - if(length == 0) continue; + if(length == 0) { + continue; + } - terminal::instance()->writeMessage(std::string{line}); + terminal::instance()->writeMessage(std::to_string(length) + "_" + std::to_string(index) + ": " + std::string{line}); } while(++index); - } else - #endif + } else { cout << message << std::flush; + } +#else + cout << message << std::flush; +#endif } void TerminalSink::flush_() { diff --git a/src/log/LogUtils.cpp b/src/log/LogUtils.cpp index ecef5bc..7f474f1 100644 --- a/src/log/LogUtils.cpp +++ b/src/log/LogUtils.cpp @@ -1,6 +1,5 @@ #include "LogUtils.h" #include "LogSinks.h" -#include #include #include #ifdef WIN32 diff --git a/src/misc/sassert.h b/src/misc/sassert.h index 8cd0e4e..8593ebb 100644 --- a/src/misc/sassert.h +++ b/src/misc/sassert.h @@ -15,4 +15,5 @@ __FILE__, __LINE__, #exp); \ } \ } while(0) + #undef S #endif \ No newline at end of file diff --git a/src/query/Command.h b/src/query/Command.h index 633d314..06ff028 100644 --- a/src/query/Command.h +++ b/src/query/Command.h @@ -96,19 +96,36 @@ operator type() { ValueList(const ValueList& ref) : key(ref.key), bulkList(ref.bulkList) {} variable operator[](int index){ - while(index >= bulkList.size()) bulkList.push_back(ParameterBulk()); + while(index >= bulkList.size()) { + bulkList.push_back(ParameterBulk{}); + } + return bulkList[index][key]; } variable first() const { - int index = 0; - while(index < bulkList.size() && !bulkList[index].has(key)) index++; - if(index < bulkList.size()) return bulkList[index][key]; + auto value = this->optional_first(); + if(value.has_value()) { + return std::move(*value); + } return variable{this->key, "", VariableType::VARTYPE_NULL}; throw std::invalid_argument("could not find key [" + key + "]"); } + std::optional optional_first() const { + int index = 0; + while(index < bulkList.size() && !bulkList[index].has(key)) { + index++; + } + + if(index < bulkList.size()) { + return std::make_optional(bulkList[index][key]); + } + + return std::nullopt; + } + size_t size(){ size_t count = 0; for(const auto& blk : this->bulkList) @@ -134,6 +151,15 @@ operator type() { std::string string() const { return as(); } + std::optional optional_string() const { + auto value = this->optional_first(); + if(value.has_value()) { + return std::make_optional(value->string()); + } + + return std::nullopt; + } + friend std::ostream& operator<<(std::ostream&, const ValueList&); private: ValueList(std::string key, std::deque& bulkList) : key{std::move(key)}, bulkList(bulkList) {}