From 006fd6ebec86977391bfd479cfb15488e19eb184 Mon Sep 17 00:00:00 2001
From: WolverinDEV <git@teaspeak.de>
Date: Wed, 10 Jun 2020 18:17:32 +0200
Subject: [PATCH] Some minor changes

---
 file/local_server/LocalFileProvider.cpp    |  2 +-
 git-teaspeak                               |  2 +-
 server/CMakeLists.txt                      |  2 +-
 server/src/FileServerHandler.cpp           | 14 +++-
 server/src/client/command_handler/file.cpp | 83 ++++++++++++++++------
 server/src/lincense/LicenseService.cpp     |  2 +-
 shared                                     |  2 +-
 7 files changed, 79 insertions(+), 28 deletions(-)

diff --git a/file/local_server/LocalFileProvider.cpp b/file/local_server/LocalFileProvider.cpp
index 48ca4a7..9250b2f 100644
--- a/file/local_server/LocalFileProvider.cpp
+++ b/file/local_server/LocalFileProvider.cpp
@@ -47,7 +47,7 @@ bool LocalFileServer::initialize(std::string &error) {
 
         auto& iaddr = *(sockaddr_in*) &binding->address;
         iaddr.sin_family = AF_INET;
-        iaddr.sin_port = htons(1112);
+        iaddr.sin_port = htons(30303);
         iaddr.sin_addr.s_addr = INADDR_ANY;
 
         bindings.push_back(std::move(binding));
diff --git a/git-teaspeak b/git-teaspeak
index a04e7b6..7ef9198 160000
--- a/git-teaspeak
+++ b/git-teaspeak
@@ -1 +1 @@
-Subproject commit a04e7b6399a66dbc72f0ac53cd6d77d2c8b2e273
+Subproject commit 7ef91982ac92d87e2d35bfa576fa794c9763788a
diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt
index b5cd879..ed287dd 100644
--- a/server/CMakeLists.txt
+++ b/server/CMakeLists.txt
@@ -241,7 +241,7 @@ target_link_libraries(PermMapHelper
 
 SET(CPACK_PACKAGE_VERSION_MAJOR "1")
 SET(CPACK_PACKAGE_VERSION_MINOR "4")
-SET(CPACK_PACKAGE_VERSION_PATCH "14")
+SET(CPACK_PACKAGE_VERSION_PATCH "15")
 if (BUILD_TYPE_NAME EQUAL OFF)
     SET(CPACK_PACKAGE_VERSION_DATA "beta")
 elseif (BUILD_TYPE_NAME STREQUAL "")
diff --git a/server/src/FileServerHandler.cpp b/server/src/FileServerHandler.cpp
index 7b92e92..670f098 100644
--- a/server/src/FileServerHandler.cpp
+++ b/server/src/FileServerHandler.cpp
@@ -4,10 +4,12 @@
 
 #include <files/FileServer.h>
 #include <log/LogUtils.h>
+#include <files/Config.h>
 
 #include "./client/ConnectedClient.h"
 #include "FileServerHandler.h"
 
+using namespace ts::server;
 using namespace ts::server::file;
 
 FileServerHandler::FileServerHandler(ts::server::InstanceHandler *instance) : instance_{instance} {}
@@ -22,6 +24,10 @@ bool FileServerHandler::initialize(std::string &error) {
     if(!file::initialize(error))
         return false;
 
+    file::config::ssl_option_supplier = [&]{
+        return this->instance_->sslManager()->web_ssl_options();
+    };
+
     auto server = file::server();
     assert(server);
 
@@ -158,7 +164,7 @@ void FileServerHandler::callback_transfer_statistics(const std::shared_ptr<trans
     }
 
     ts::command_builder notify{"notifyfiletransferprogress"};
-    notify.put_unchecked(0, "clientftid", transfer->client_transfer_id);
+    notify.put_unchecked(0, "clientftfid", transfer->client_transfer_id);
 
     notify.put_unchecked(0, "file_bytes_transferred", statistics.file_bytes_transferred);
     notify.put_unchecked(0, "network_bytes_send", statistics.network_bytes_send);
@@ -167,6 +173,10 @@ void FileServerHandler::callback_transfer_statistics(const std::shared_ptr<trans
     notify.put_unchecked(0, "file_start_offset", statistics.file_start_offset);
     notify.put_unchecked(0, "file_current_offset", statistics.file_current_offset);
     notify.put_unchecked(0, "file_total_size", statistics.file_total_size);
+
+    notify.put_unchecked(0, "network_current_speed", statistics.current_speed);
+    notify.put_unchecked(0, "network_average_speed", statistics.average_speed);
+
     client->sendCommand(notify);
 }
 
@@ -179,7 +189,7 @@ void FileServerHandler::callback_transfer_started(const std::shared_ptr<transfer
 
 
     ts::command_builder notify{"notifyfiletransferstarted"};
-    notify.put_unchecked(0, "clientftid", transfer->client_transfer_id);
+    notify.put_unchecked(0, "clientftfid", transfer->client_transfer_id);
     client->sendCommand(notify);
 }
 
diff --git a/server/src/client/command_handler/file.cpp b/server/src/client/command_handler/file.cpp
index cd4fa60..4c5c61b 100644
--- a/server/src/client/command_handler/file.cpp
+++ b/server/src/client/command_handler/file.cpp
@@ -152,6 +152,7 @@ command_result ConnectedClient::handleCommandFTGetFileList(Command &cmd) {
 
             bulk.put_unchecked("name", file.name);
             bulk.put_unchecked("size", file.size);
+            bulk.put_unchecked("empty", file.empty);
             bulk.put_unchecked("datetime", std::chrono::duration_cast<std::chrono::seconds>(file.modified_at.time_since_epoch()).count());
             if(bulk_index >= 16) {
                 this->sendCommand(notify_file_list);
@@ -249,7 +250,7 @@ command_result ConnectedClient::handleCommandFTDeleteFile(Command &cmd) {
         std::vector<std::string> delete_files{};
         delete_files.reserve(cmd.bulkCount());
         for(size_t index{0}; index < cmd.bulkCount(); index++)
-            delete_files.push_back(cmd[index]["name"].string());
+            delete_files.push_back(file_path + "/" + cmd[index]["name"].string());
 
         delete_response = file_system.delete_channel_files(virtual_file_server, channel->channelId(), delete_files);
     } else {
@@ -400,7 +401,7 @@ command_result ConnectedClient::handleCommandFTGetFileInfo(ts::Command &cmd) {
 
     CMD_RESET_IDLE;
     CMD_REQ_SERVER;
-    CMD_CHK_AND_INC_FLOOD_POINTS(5);
+    CMD_CHK_AND_INC_FLOOD_POINTS(25);
 
     auto virtual_file_server = file::server()->find_virtual_server(this->getServerId());
     if(!virtual_file_server) return command_result{error::file_virtual_server_not_registered};
@@ -412,22 +413,47 @@ command_result ConnectedClient::handleCommandFTGetFileInfo(ts::Command &cmd) {
     auto file_path = cmd["path"].string();
     std::shared_ptr<file::ExecuteResponse<file::filesystem::FileInfoError, file::filesystem::FileInfoResponse>> info_response{};
     if (cmd[0].has("cid") && cmd["cid"] != 0) {
-        auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
-        if (!channel)
-            return command_result{error::channel_invalid_id};
+        std::shared_ptr<BasicChannel> currentChannel{};
+        error::type error_error{error::ok};
+        permission::PermissionType permission_error{permission::ok};
 
-        if (!channel->passwordMatch(cmd["cpw"]) && !permission::v2::permission_granted(1, this->calculate_permission(permission::b_ft_ignore_password, channel->channelId())))
-            return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
+        std::vector<std::tuple<ChannelId, std::string>> info_files{};
+        info_files.reserve(cmd.bulkCount());
 
-        if(!channel->permission_granted(permission::i_ft_needed_file_browse_power, this->calculate_permission(permission::i_ft_file_browse_power, channel->channelId()), true))
-            return command_result{permission::i_ft_file_browse_power};
+        for(size_t index{0}; index < cmd.bulkCount(); index++) {
+            if(cmd[index].has("cid")) {
+                error_error = error::ok;
+                permission_error = permission::ok;
 
-        std::vector<std::string> delete_files{};
-        delete_files.reserve(cmd.bulkCount());
-        for(size_t index{0}; index < cmd.bulkCount(); index++)
-            delete_files.push_back(cmd[index]["name"].string());
+                currentChannel = this->server->channelTree->findChannel(cmd[index]["cid"].as<ChannelId>());
+                if(currentChannel) {
+                    const auto password = cmd[index]["cpw"].string();
+                    if (!currentChannel->passwordMatch(password) && !permission::v2::permission_granted(1, this->calculate_permission(permission::b_ft_ignore_password, currentChannel->channelId()))) {
+                        if(password.empty())
+                            error_error = error::channel_invalid_password;
+                        else
+                            permission_error = permission::b_ft_ignore_password;
+                    } else if(!currentChannel->permission_granted(permission::i_ft_needed_file_browse_power, this->calculate_permission(permission::i_ft_file_browse_power, currentChannel->channelId()), true)) {
+                        permission_error = permission::i_ft_file_browse_power;
+                    }
+                } else {
+                    error_error = error::channel_invalid_id;
+                }
+            }
 
-        info_response = file_system.query_channel_info(virtual_file_server, channel->channelId(), delete_files);
+            if(error_error != error::ok) {
+                response.set_result(index, ts::command_result{error_error});
+                continue;
+            }
+
+            if(permission_error != permission::ok) {
+                response.set_result(index, ts::command_result{permission_error});
+                continue;
+            }
+            info_files.emplace_back(currentChannel->channelId(), cmd[index]["name"].string());
+        }
+
+        info_response = file_system.query_channel_info(virtual_file_server, info_files);
     } else {
         auto first_entry_name = cmd["name"].string();
         if (first_entry_name.find("/icon_") == 0 && file_path.empty()) {
@@ -492,6 +518,7 @@ command_result ConnectedClient::handleCommandFTGetFileInfo(ts::Command &cmd) {
         }
     }
 
+    const auto as_list = cmd.hasParm("as-list");
     const auto& file_status = info_response->response();
     size_t bulk_index{0};
 
@@ -521,6 +548,10 @@ command_result ConnectedClient::handleCommandFTGetFileInfo(ts::Command &cmd) {
                 break;
         }
         bulk_index++;
+        if(notify_index == 0) {
+            notify_file_info.reset();
+            notify_file_info.put_unchecked(0, "return_code", cmd["return_code"].string());
+        }
 
         auto bulk = notify_file_info.bulk(notify_index++);
         switch(file.info.type) {
@@ -540,10 +571,21 @@ command_result ConnectedClient::handleCommandFTGetFileInfo(ts::Command &cmd) {
 
         bulk.put_unchecked("name", file.info.name);
         bulk.put_unchecked("size", file.info.size);
+        bulk.put_unchecked("empty", file.info.empty);
         bulk.put_unchecked("datetime", std::chrono::duration_cast<std::chrono::seconds>(file.info.modified_at.time_since_epoch()).count());
+
+        if(notify_index > 20 && as_list) {
+            this->sendCommand(notify_file_info);
+            notify_index = 0;
+        }
     }
     if(notify_index > 0)
         this->sendCommand(notify_file_info);
+    if(as_list && this->getExternalType() == ClientType::CLIENT_TEAMSPEAK) {
+        ts::command_builder notify{this->notify_response_command("notifyfileinfofinished")};
+        notify.put_unchecked(0, "return_code", cmd["return_code"].string());
+        this->sendCommand(notify);
+    }
 
     while(response.length() > bulk_index && response.response(bulk_index).type() == command_result_type::error && response.response(bulk_index).error_code() != error::ok)
         bulk_index++;
@@ -611,7 +653,7 @@ command_result ConnectedClient::handleCommandFTInitUpload(ts::Command &cmd) {
         ACTION_REQUIRES_CHANNEL_PERMISSION(channel, permission::i_ft_needed_file_upload_power, permission::i_ft_file_upload_power, true);
         transfer_response = file::server()->file_transfer().initialize_channel_transfer(file::transfer::Transfer::DIRECTION_UPLOAD, virtual_file_server, channel->channelId(), info);
     } else {
-        if (cmd["path"].string().empty() && cmd["name"].string().starts_with("/icon_") == 0) {
+        if (cmd["path"].string().empty() && cmd["name"].string().starts_with("/icon_")) {
             auto max_size = this->calculate_permission(permission::i_max_icon_filesize, 0);
             if(max_size.has_value && !max_size.has_infinite_power() && (max_size.value < 0 || max_size.value < cmd["size"].as<size_t>()))
                 return command_result{permission::i_max_icon_filesize};
@@ -717,7 +759,7 @@ command_result ConnectedClient::handleCommandFTInitDownload(ts::Command &cmd) {
         if(client_quota.has_value) {
             if(client_quota.value > 0) {
                 if((size_t) client_quota.value * 1024 * 1024 <= client_used_quota)
-                    return command_result{error::file_transfer_server_quota_exceeded};
+                    return command_result{error::file_transfer_client_quota_exceeded};
                 info.download_client_quota_limit = client_quota.value * 1024 * 1024 - client_used_quota;
             } else if(client_quota.value != -1) {
                 return command_result{error::file_transfer_client_quota_exceeded};
@@ -734,7 +776,7 @@ command_result ConnectedClient::handleCommandFTInitDownload(ts::Command &cmd) {
 
     info.file_offset = cmd["seekpos"].as<size_t>();
     info.override_exiting = false;
-    info.file_path = cmd["name"].string();
+    info.file_path = cmd["path"].string() + "/" + cmd["name"].string();
     info.client_unique_id = this->getUid();
     info.client_id = this->getClientId();
     info.max_concurrent_transfers = kMaxClientTransfers;
@@ -750,10 +792,9 @@ command_result ConnectedClient::handleCommandFTInitDownload(ts::Command &cmd) {
         ACTION_REQUIRES_CHANNEL_PERMISSION(channel, permission::i_ft_needed_file_download_power, permission::i_ft_file_download_power, true);
         transfer_response = file::server()->file_transfer().initialize_channel_transfer(file::transfer::Transfer::DIRECTION_DOWNLOAD, virtual_file_server, channel->channelId(), info);
     } else {
-        if (cmd["path"].as<std::string>().empty() && cmd["name"].string().find("/icon_") == 0) {
+        if (cmd["path"].as<std::string>().empty() && cmd["name"].string().starts_with("/icon_")) {
             transfer_response = file::server()->file_transfer().initialize_icon_transfer(file::transfer::Transfer::DIRECTION_DOWNLOAD, virtual_file_server, info);
-        } else if (cmd["path"].as<std::string>().empty() && cmd["name"].string() == "/avatar") {
-            info.file_path = "/avatar_" + this->getAvatarId();
+        } else if (cmd["path"].as<std::string>().empty() && cmd["name"].string().starts_with("/avatar")) {
             transfer_response = file::server()->file_transfer().initialize_avatar_transfer(file::transfer::Transfer::DIRECTION_DOWNLOAD, virtual_file_server, info);
         } else {
             return command_result{error::parameter_invalid, "name"};
@@ -766,7 +807,7 @@ command_result ConnectedClient::handleCommandFTInitDownload(ts::Command &cmd) {
     if(!transfer_response->succeeded()) {
         using ErrorType = file::transfer::TransferInitError;
 
-        debugMessage(this->getServerId(), "{} Failed to initialize file download: {} / {}", CLIENT_STR_LOG_PREFIX, (int) transfer_response->error().error_type, transfer_response->error().error_message);
+        debugMessage(this->getServerId(), "{} Failed to initialize file download: {}/{}", CLIENT_STR_LOG_PREFIX, (int) transfer_response->error().error_type, transfer_response->error().error_message);
         switch(transfer_response->error().error_type) {
             case ErrorType::UNKNOWN: {
                 auto error_detail = std::to_string((int) transfer_response->error().error_type);
diff --git a/server/src/lincense/LicenseService.cpp b/server/src/lincense/LicenseService.cpp
index ae8ce15..a96cc43 100644
--- a/server/src/lincense/LicenseService.cpp
+++ b/server/src/lincense/LicenseService.cpp
@@ -112,7 +112,7 @@ void LicenseService::execute_dns_request() {
             auto license_host = gethostbyname(strobf("license.teaspeak.de").c_str());
 #endif
             if(!license_host) {
-                error = strobf("result is null").string();
+                error = strobf("resolve error occurred: ").string() + hstrerror(h_errno);
                 goto handle_result;
             }
             if(!license_host->h_addr){
diff --git a/shared b/shared
index 246e57e..9b41ca5 160000
--- a/shared
+++ b/shared
@@ -1 +1 @@
-Subproject commit 246e57e69d61d25d92e76c2af0368eac18536ac1
+Subproject commit 9b41ca5dcacd30f69228d71fcb9ed05be8b542d8