diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..4d62d04 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,62 @@ +--- +# Resons why specific warnings have been turned off: +# +# -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling +# This warns about memcpy and wants us to use memcpy_s, which is not available in our gcc setup. +# +# -cppcoreguidelines-pro-type-vararg +# This forbids using functions like printf, snprintf etc. We would like to use those either way. +# +# -misc-no-recursion +# Recursion with functions can be an elegant way of solving recursive problems +# +# These checks have been disabled to keep compatibility with C++14: +# -modernize-concat-nested-namespaces +# -modernize-use-nodiscard +# + +Checks: "-*, + clang-analyzer-*, + -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling, + + bugprone-*, + -bugprone-easily-swappable-parameters, + -bugprone-implicit-widening-of-multiplication-result, + -bugprone-narrowing-conversions, + + cppcoreguidelines-*, + -cppcoreguidelines-avoid-magic-numbers, + -cppcoreguidelines-macro-usage, + -cppcoreguidelines-narrowing-conversions, + -cppcoreguidelines-non-private-member-variables-in-classes, + -cppcoreguidelines-pro-bounds-array-to-pointer-decay, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-pro-type-vararg, + -cppcoreguidelines-pro-type-reinterpret-cast, + + misc-*, + -misc-non-private-member-variables-in-classes, + -misc-no-recursion, + + modernize-*, + -modernize-pass-by-value, + -modernize-use-trailing-return-type, + -modernize-use-auto, + -modernize-concat-nested-namespaces, + -modernize-return-braced-init-list, + -modernize-use-nodiscard, + -modernize-avoid-bind, + + performance-*, + + readability-*, + -readability-braces-around-statements, + -readability-identifier-length, + -readability-magic-numbers, + -readability-redundant-access-specifiers, + -readability-function-cognitive-complexity, + -readability-else-after-return, +" +WarningsAsErrors: '' +HeaderFilterRegex: '^((?!/thirdparty/|/_deps/).)*$' +FormatStyle: none diff --git a/CMakeWindows.bat b/CMakeWindows.bat index fa787f6..72fec28 100644 --- a/CMakeWindows.bat +++ b/CMakeWindows.bat @@ -1,6 +1,6 @@ mkdir _build cd _build -cmake .. -DCMAKE_INSTALL_PREFIX=_install +cmake .. -DCMAKE_INSTALL_PREFIX=_install -DBUILD_SHARED_LIBS=OFF cd .. pause diff --git a/fineftp-server/CMakeLists.txt b/fineftp-server/CMakeLists.txt index f4fb371..e4e3152 100644 --- a/fineftp-server/CMakeLists.txt +++ b/fineftp-server/CMakeLists.txt @@ -33,6 +33,7 @@ set(sources src/server_impl.cpp src/server_impl.h src/user_database.cpp + src/user_database.h src/win_str_convert.cpp src/win_str_convert.h ) diff --git a/fineftp-server/include/fineftp/permissions.h b/fineftp-server/include/fineftp/permissions.h index 496b272..3c8888b 100644 --- a/fineftp-server/include/fineftp/permissions.h +++ b/fineftp-server/include/fineftp/permissions.h @@ -20,12 +20,12 @@ namespace fineftp None = 0 }; - inline Permission operator~ (Permission a) { return (Permission)~(int)a; } - inline Permission operator| (Permission a, Permission b) { return (Permission)((int)a | (int)b); } - inline Permission operator& (Permission a, Permission b) { return (Permission)((int)a & (int)b); } - inline Permission operator^ (Permission a, Permission b) { return (Permission)((int)a ^ (int)b); } - inline Permission& operator|= (Permission& a, Permission b) { return (Permission&)((int&)a |= (int)b); } - inline Permission& operator&= (Permission& a, Permission b) { return (Permission&)((int&)a &= (int)b); } - inline Permission& operator^= (Permission& a, Permission b) { return (Permission&)((int&)a ^= (int)b); } + inline Permission operator~ (Permission a) { return static_cast(~static_cast(a)); } + inline Permission operator| (Permission a, Permission b) { return static_cast(static_cast(a) | static_cast(b)); } + inline Permission operator& (Permission a, Permission b) { return static_cast(static_cast(a) & static_cast(b)); } + inline Permission operator^ (Permission a, Permission b) { return static_cast(static_cast(a) ^ static_cast(b)); } + inline Permission& operator|= (Permission& a, Permission b) { return reinterpret_cast(reinterpret_cast(a) |= static_cast(b)); } + inline Permission& operator&= (Permission& a, Permission b) { return reinterpret_cast(reinterpret_cast(a) &= static_cast(b)); } + inline Permission& operator^= (Permission& a, Permission b) { return reinterpret_cast(reinterpret_cast(a) ^= static_cast(b)); } -} \ No newline at end of file +} diff --git a/fineftp-server/include/fineftp/server.h b/fineftp-server/include/fineftp/server.h index b305e3c..3b0432b 100644 --- a/fineftp-server/include/fineftp/server.h +++ b/fineftp-server/include/fineftp/server.h @@ -70,6 +70,15 @@ namespace fineftp */ FINEFTP_EXPORT FtpServer(uint16_t port = 21); + // Move + FINEFTP_EXPORT FtpServer(FtpServer&&) noexcept; + FINEFTP_EXPORT FtpServer& operator=(FtpServer&&) noexcept; + + // Non-copyable + FtpServer(const FtpServer&) = delete; + FtpServer& operator=(const FtpServer&) = delete; + + // Destructor FINEFTP_EXPORT ~FtpServer(); /** @@ -93,7 +102,7 @@ namespace fineftp * * @return True if adding the user was successful (i.e. it didn't exit already). */ - FINEFTP_EXPORT bool addUser(const std::string& username, const std::string& password, const std::string& local_root_path, const Permission permissions); + FINEFTP_EXPORT bool addUser(const std::string& username, const std::string& password, const std::string& local_root_path, Permission permissions); /** * @brief Adds the "anonymous" / "ftp" user that FTP clients use to access FTP servers without password @@ -103,7 +112,7 @@ namespace fineftp * * @return True if adding the anonymous user was successful (i.e. it didn't exit already). */ - FINEFTP_EXPORT bool addUserAnonymous(const std::string& local_root_path, const Permission permissions); + FINEFTP_EXPORT bool addUserAnonymous(const std::string& local_root_path, Permission permissions); /** * @brief Starts the FTP Server @@ -148,10 +157,6 @@ namespace fineftp */ FINEFTP_EXPORT std::string getAddress() const; - // Non-copyable - FINEFTP_EXPORT FtpServer(const FtpServer&) = delete; - FINEFTP_EXPORT FtpServer& operator=(const FtpServer&) = delete; - private: std::unique_ptr ftp_server_; /**< Implementation details */ }; diff --git a/fineftp-server/src/filesystem.cpp b/fineftp-server/src/filesystem.cpp index c678cc4..b00743e 100644 --- a/fineftp-server/src/filesystem.cpp +++ b/fineftp-server/src/filesystem.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #ifdef WIN32 @@ -30,9 +31,10 @@ namespace Filesystem FileStatus::FileStatus(const std::string& path) : path_(path) + , file_status_{} { #ifdef WIN32 - std::wstring w_path_ = StrConvert::Utf8ToWide(path); + const std::wstring w_path_ = StrConvert::Utf8ToWide(path); const int error_code = _wstat64(w_path_.c_str(), &file_status_); #else // WIN32 const int error_code = stat(path.c_str(), &file_status_); @@ -40,8 +42,6 @@ namespace Filesystem is_ok_ = (error_code == 0); } - FileStatus::~FileStatus() {} - bool FileStatus::isOk() const { return is_ok_; @@ -107,40 +107,40 @@ namespace Filesystem #ifdef WIN32 // Root - permission_string[0] = (file_status_.st_mode & S_IREAD) ? 'r' : '-'; - permission_string[1] = (file_status_.st_mode & S_IWRITE) ? 'w' : '-'; - permission_string[2] = (file_status_.st_mode & S_IEXEC) ? 'x' : '-'; + permission_string[0] = ((file_status_.st_mode & S_IREAD) != 0) ? 'r' : '-'; + permission_string[1] = ((file_status_.st_mode & S_IWRITE) != 0) ? 'w' : '-'; + permission_string[2] = ((file_status_.st_mode & S_IEXEC) != 0) ? 'x' : '-'; // Group - permission_string[3] = (file_status_.st_mode & S_IREAD) ? 'r' : '-'; - permission_string[4] = (file_status_.st_mode & S_IWRITE) ? 'w' : '-'; - permission_string[5] = (file_status_.st_mode & S_IEXEC) ? 'x' : '-'; + permission_string[3] = ((file_status_.st_mode & S_IREAD) != 0) ? 'r' : '-'; + permission_string[4] = ((file_status_.st_mode & S_IWRITE) != 0) ? 'w' : '-'; + permission_string[5] = ((file_status_.st_mode & S_IEXEC) != 0) ? 'x' : '-'; // Owner - permission_string[6] = (file_status_.st_mode & S_IREAD) ? 'r' : '-'; - permission_string[7] = (file_status_.st_mode & S_IWRITE) ? 'w' : '-'; - permission_string[8] = (file_status_.st_mode & S_IEXEC) ? 'x' : '-'; + permission_string[6] = ((file_status_.st_mode & S_IREAD) != 0) ? 'r' : '-'; + permission_string[7] = ((file_status_.st_mode & S_IWRITE) != 0) ? 'w' : '-'; + permission_string[8] = ((file_status_.st_mode & S_IEXEC) != 0) ? 'x' : '-'; #else // WIN32 // Root - permission_string[0] = (file_status_.st_mode & S_IRUSR) ? 'r' : '-'; - permission_string[1] = (file_status_.st_mode & S_IWUSR) ? 'w' : '-'; - permission_string[2] = (file_status_.st_mode & S_IXUSR) ? 'x' : '-'; + permission_string[0] = ((file_status_.st_mode & S_IRUSR) != 0) ? 'r' : '-'; + permission_string[1] = ((file_status_.st_mode & S_IWUSR) != 0) ? 'w' : '-'; + permission_string[2] = ((file_status_.st_mode & S_IXUSR) != 0) ? 'x' : '-'; // Group - permission_string[3] = (file_status_.st_mode & S_IRGRP) ? 'r' : '-'; - permission_string[4] = (file_status_.st_mode & S_IWGRP) ? 'w' : '-'; - permission_string[5] = (file_status_.st_mode & S_IXGRP) ? 'x' : '-'; + permission_string[3] = ((file_status_.st_mode & S_IRGRP) != 0) ? 'r' : '-'; + permission_string[4] = ((file_status_.st_mode & S_IWGRP) != 0) ? 'w' : '-'; + permission_string[5] = ((file_status_.st_mode & S_IXGRP) != 0) ? 'x' : '-'; // Owner - permission_string[6] = (file_status_.st_mode & S_IROTH) ? 'r' : '-'; - permission_string[7] = (file_status_.st_mode & S_IWOTH) ? 'w' : '-'; - permission_string[8] = (file_status_.st_mode & S_IXOTH) ? 'x' : '-'; + permission_string[6] = ((file_status_.st_mode & S_IROTH) != 0) ? 'r' : '-'; + permission_string[7] = ((file_status_.st_mode & S_IWOTH) != 0) ? 'w' : '-'; + permission_string[8] = ((file_status_.st_mode & S_IXOTH) != 0) ? 'x' : '-'; #endif // WIN32 return permission_string; } - std::string FileStatus::ownerString() const + std::string FileStatus::ownerString() const // NOLINT(readability-convert-member-functions-to-static) Reason: I want being able to extend the stub code here and return an actual owner { return "fineFTP"; } - std::string FileStatus::groupString() const + std::string FileStatus::groupString() const // NOLINT(readability-convert-member-functions-to-static) Reason: I want being able to extend the stub code here and return an actual group { return "fineFTP"; } @@ -164,7 +164,7 @@ namespace Filesystem // https://files.stairways.com/other/ftp-list-specs-info.txt auto now = std::chrono::system_clock::now(); - time_t now_time_t = std::chrono::system_clock::to_time_t(now); + const time_t now_time_t = std::chrono::system_clock::to_time_t(now); //struct tm* now_timeinfo = localtime(&now_time_t); //int current_year = now_timeinfo->tm_year; @@ -192,12 +192,12 @@ namespace Filesystem } #endif - int current_year = now_timeinfo.tm_year; - int file_year = file_timeinfo.tm_year; + const int current_year = now_timeinfo.tm_year; + const int file_year = file_timeinfo.tm_year; // Hardcoded english month names, because returning a localized string by strftime here may break certain FTP clients - static std::string month_names[] = + static const std::array month_names = { "Jan", "Feb", @@ -230,7 +230,7 @@ namespace Filesystem << " " << ( file_timeinfo.tm_year + tm_year_base_year ); } - return month_names[file_timeinfo.tm_mon] + date.str(); + return month_names.at(file_timeinfo.tm_mon) + date.str(); } bool FileStatus::canOpenDir() const @@ -246,9 +246,9 @@ namespace Filesystem std::string find_file_path = path_ + "\\*"; std::replace(find_file_path.begin(), find_file_path.end(), '/', '\\'); - std::wstring w_find_file_path = StrConvert::Utf8ToWide(find_file_path); + const std::wstring w_find_file_path = StrConvert::Utf8ToWide(find_file_path); - HANDLE hFind; + HANDLE hFind = nullptr; WIN32_FIND_DATAW ffd; hFind = FindFirstFileW(w_find_file_path.c_str(), &ffd); if (hFind != INVALID_HANDLE_VALUE) @@ -257,12 +257,12 @@ namespace Filesystem } FindClose(hFind); #else // WIN32 - DIR *dp; - if ((dp = opendir(path_.c_str())) != NULL) + DIR *dp = opendir(path_.c_str()); + if (dp != nullptr) { can_open_dir = true; + closedir(dp); } - closedir(dp); #endif // WIN32 return can_open_dir; @@ -275,9 +275,9 @@ namespace Filesystem std::string find_file_path = path + "\\*"; std::replace(find_file_path.begin(), find_file_path.end(), '/', '\\'); - std::wstring w_find_file_path = StrConvert::Utf8ToWide(find_file_path); + const std::wstring w_find_file_path = StrConvert::Utf8ToWide(find_file_path); - HANDLE hFind; + HANDLE hFind = nullptr; WIN32_FIND_DATAW ffd; hFind = FindFirstFileW(w_find_file_path.c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) @@ -288,20 +288,20 @@ namespace Filesystem do { - std::string file_name = StrConvert::WideToUtf8(std::wstring(ffd.cFileName)); + const std::string file_name = StrConvert::WideToUtf8(std::wstring(ffd.cFileName)); content.emplace(file_name, FileStatus(path + "\\" + file_name)); } while (FindNextFileW(hFind, &ffd) != 0); FindClose(hFind); #else // WIN32 - DIR *dp; - struct dirent *dirp; - if((dp = opendir(path.c_str())) == NULL) + DIR *dp = opendir(path.c_str()); + struct dirent *dirp = nullptr; + if(dp == nullptr) { std::cerr << "Error opening directory: " << strerror(errno) << std::endl; return content; } - while ((dirp = readdir(dp)) != NULL) + while ((dirp = readdir(dp)) != nullptr) { content.emplace(std::string(dirp->d_name), FileStatus(path + "/" + std::string(dirp->d_name))); } @@ -330,8 +330,8 @@ namespace Filesystem * \\Host */ - std::regex win_local_drive("^[a-zA-Z]\\:"); // Local drive - std::regex win_network_drive("^[/\\\\]{2}[^/\\\\]+"); // Network path starting with two slashes or backslashes followed by a hostname + const std::regex win_local_drive(R"(^[a-zA-Z]\:)"); // Local drive + const std::regex win_network_drive(R"(^[/\\]{2}[^/\\]+)"); // Network path starting with two slashes or backslashes followed by a hostname if (std::regex_search(path, win_local_drive)) { @@ -341,7 +341,7 @@ namespace Filesystem else if (std::regex_search(path, win_network_drive)) { // Window network drive, consisting of \\ and hostname - size_t sep_pos = path.find_first_of("/\\", 2); + const size_t sep_pos = path.find_first_of("/\\", 2); absolute_root = path.substr(0, sep_pos); // If no seperator was found, this will return the entire string } } @@ -359,7 +359,8 @@ namespace Filesystem if (path.size() >= (absolute_root.size() + 1)) { - size_t start, end; + size_t start = 0; + size_t end = 0; if (absolute_root.empty()) start = 0; @@ -371,7 +372,7 @@ namespace Filesystem if (windows_path) end = path.find_first_of("/\\", start); else - end = path.find_first_of("/", start); + end = path.find_first_of('/', start); std::string this_component; if (end == std::string::npos) @@ -402,7 +403,7 @@ namespace Filesystem } else { - components.push_back(".."); + components.emplace_back(".."); } } } @@ -419,7 +420,7 @@ namespace Filesystem } while (start < path.size()); // Join the components again - if (components.size() == 0 && absolute_root.empty()) + if (components.empty() && absolute_root.empty()) { return "."; } @@ -450,11 +451,11 @@ namespace Filesystem std::string cleanPathNative(const std::string& path) { #ifdef WIN32 - bool windows_path = true; - char separator = '\\'; + constexpr bool windows_path = true; + constexpr char separator = '\\'; #else // WIN32 - bool windows_path = false; - char separator = '/'; + constexpr bool windows_path = false; + constexpr char separator = '/'; #endif // WIN32 return cleanPath(path, windows_path, separator); } diff --git a/fineftp-server/src/filesystem.h b/fineftp-server/src/filesystem.h index bc8d584..dbfec60 100644 --- a/fineftp-server/src/filesystem.h +++ b/fineftp-server/src/filesystem.h @@ -32,14 +32,11 @@ namespace fineftp public: FileStatus(const std::string& path); - ~FileStatus(); - bool isOk() const; FileType type() const; int64_t fileSize() const; - #ifdef WIN32 bool permissionRootRead() const; bool permissionRootWrite() const; bool permissionRootExecute() const; @@ -49,18 +46,6 @@ namespace fineftp bool permissionOwnerRead() const; bool permissionOwnerWrite() const; bool permissionOwnerExecute() const; - #else // WIN32 - bool permissionRootRead() const; - bool permissionRootWrite() const; - bool permissionRootExecute() const; - bool permissionGroupRead() const; - bool permissionGroupWrite() const; - bool permissionGroupExecute() const; - bool permissionOwnerRead() const; - bool permissionOwnerWrite() const; - bool permissionOwnerExecute() const; - #endif // WIN32 - std::string permissionString() const; @@ -86,8 +71,8 @@ namespace fineftp std::map dirContent(const std::string& path); - std::string cleanPath(const std::string& path, bool windows_path, const char output_separator); + std::string cleanPath(const std::string& path, bool windows_path, char output_separator); std::string cleanPathNative(const std::string& path); } -} \ No newline at end of file +} diff --git a/fineftp-server/src/ftp_message.h b/fineftp-server/src/ftp_message.h index af0737d..618d86c 100644 --- a/fineftp-server/src/ftp_message.h +++ b/fineftp-server/src/ftp_message.h @@ -61,9 +61,6 @@ namespace fineftp , message_(message) {} - ~FtpMessage() - {} - inline FtpReplyCode replyCode() const { return code_; @@ -83,4 +80,4 @@ namespace fineftp FtpReplyCode code_; std::string message_; }; -} \ No newline at end of file +} diff --git a/fineftp-server/src/ftp_session.cpp b/fineftp-server/src/ftp_session.cpp index a23d210..ac1db19 100755 --- a/fineftp-server/src/ftp_session.cpp +++ b/fineftp-server/src/ftp_session.cpp @@ -69,7 +69,7 @@ namespace fineftp { command_write_strand_.post([me = shared_from_this(), raw_message]() { - bool write_in_progress = !me->command_output_queue_.empty(); + const bool write_in_progress = !me->command_output_queue_.empty(); me->command_output_queue_.push_back(raw_message); if (!write_in_progress) { @@ -143,7 +143,7 @@ namespace fineftp std::istream stream (&(me->command_input_stream_)); std::string packet_string(length - 2, ' '); - stream.read(&packet_string[0], length - 2); + stream.read(&packet_string[0], length - 2); // NOLINT(readability-container-data-pointer) Reason: I need a non-const pointer here, As I am directly reading into the buffer, but .data() returns a const pointer. I don't consider a const_cast to be better. Since C++11 this is safe, as strings are stored in contiguous memeory. stream.ignore(2); // Remove the "\r\n" #ifndef NDEBUG @@ -159,7 +159,7 @@ namespace fineftp std::string ftp_command; std::string parameters; - size_t space_index = command.find_first_of(' '); + const size_t space_index = command.find_first_of(' '); ftp_command = command.substr(0, space_index); std::transform(ftp_command.begin(), ftp_command.end(), ftp_command.begin(), [](char c) { return static_cast(std::toupper(static_cast(c))); }); @@ -290,13 +290,11 @@ namespace fineftp void FtpSession::handleFtpCommandACCT(const std::string& /*param*/) { sendFtpMessage(FtpReplyCode::SYNTAX_ERROR_UNRECOGNIZED_COMMAND, "Unsupported command"); - return; } void FtpSession::handleFtpCommandCWD(const std::string& param) { sendFtpMessage(executeCWD(param)); - return; } void FtpSession::handleFtpCommandCDUP(const std::string& /*param*/) @@ -338,14 +336,12 @@ namespace fineftp void FtpSession::handleFtpCommandREIN(const std::string& /*param*/) { sendFtpMessage(FtpReplyCode::COMMAND_NOT_IMPLEMENTED, "Unsupported command"); - return; } void FtpSession::handleFtpCommandQUIT(const std::string& /*param*/) { logged_in_user_ = nullptr; sendFtpMessage(FtpReplyCode::SERVICE_CLOSING_CONTROL_CONNECTION, "Connection shutting down"); - return; } // Transfer parameter commands @@ -353,7 +349,6 @@ namespace fineftp void FtpSession::handleFtpCommandPORT(const std::string& /*param*/) { sendFtpMessage(FtpReplyCode::SYNTAX_ERROR_UNRECOGNIZED_COMMAND, "FTP active mode is not supported by this server"); - return; } void FtpSession::handleFtpCommandPASV(const std::string& /*param*/) @@ -374,7 +369,7 @@ namespace fineftp } } - asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), 0); + const asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), 0); { asio::error_code ec; @@ -388,7 +383,7 @@ namespace fineftp } { asio::error_code ec; - data_acceptor_.bind(endpoint); + data_acceptor_.bind(endpoint, ec); if (ec) { std::cerr << "Error binding data acceptor: " << ec.message() << std::endl; @@ -421,7 +416,6 @@ namespace fineftp stream << ((port >> 8) & 0xff) << "," << (port & 0xff) << ")"; sendFtpMessage(FtpReplyCode::ENTERING_PASSIVE_MODE, "Entering passive mode " + stream.str()); - return; } void FtpSession::handleFtpCommandTYPE(const std::string& param) @@ -457,13 +451,11 @@ namespace fineftp void FtpSession::handleFtpCommandSTRU(const std::string& /*param*/) { sendFtpMessage(FtpReplyCode::SYNTAX_ERROR_UNRECOGNIZED_COMMAND, "Unsupported command"); - return; } void FtpSession::handleFtpCommandMODE(const std::string& /*param*/) { sendFtpMessage(FtpReplyCode::SYNTAX_ERROR_UNRECOGNIZED_COMMAND, "Unsupported command"); - return; } // Ftp service commands @@ -485,10 +477,10 @@ namespace fineftp return; } - std::string local_path = toLocalPath(param); + const std::string local_path = toLocalPath(param); - std::ios::openmode open_mode = (data_type_binary_ ? (std::ios::in | std::ios::binary) : (std::ios::in)); - std::shared_ptr file = std::make_shared(local_path, open_mode); + const std::ios::openmode open_mode = (data_type_binary_ ? (std::ios::in | std::ios::binary) : (std::ios::in)); + const std::shared_ptr file = std::make_shared(local_path, open_mode); if (!file->file_stream_.good()) { @@ -498,7 +490,6 @@ namespace fineftp sendFtpMessage(FtpReplyCode::FILE_STATUS_OK_OPENING_DATA_CONNECTION, "Sending file"); sendFile(file); - return; } void FtpSession::handleFtpCommandSIZE(const std::string& param) @@ -514,9 +505,9 @@ namespace fineftp return; } - std::string local_path = toLocalPath(param); + const std::string local_path = toLocalPath(param); - std::ios::openmode open_mode = + const std::ios::openmode open_mode = std::ios::ate | (data_type_binary_ ? (std::ios::in | std::ios::binary) : (std::ios::in)); #if defined(WIN32) && !defined(__GNUG__) std::ifstream file(StrConvert::Utf8ToWide(local_path), open_mode); @@ -570,7 +561,7 @@ namespace fineftp return; } - std::string local_path = toLocalPath(param); + const std::string local_path = toLocalPath(param); auto existing_file_filestatus = Filesystem::FileStatus(local_path); if (existing_file_filestatus.isOk()) @@ -588,8 +579,8 @@ namespace fineftp } } - std::ios::openmode open_mode = (data_type_binary_ ? (std::ios::out | std::ios::binary) : (std::ios::out)); - std::shared_ptr file = std::make_shared(local_path, open_mode); + const std::ios::openmode open_mode = (data_type_binary_ ? (std::ios::out | std::ios::binary) : (std::ios::out)); + const std::shared_ptr file = std::make_shared(local_path, open_mode); if (!file->file_stream_.good()) { @@ -599,13 +590,11 @@ namespace fineftp sendFtpMessage(FtpReplyCode::FILE_STATUS_OK_OPENING_DATA_CONNECTION, "Receiving file"); receiveFile(file); - return; } void FtpSession::handleFtpCommandSTOU(const std::string& /*param*/) { sendFtpMessage(FtpReplyCode::SYNTAX_ERROR_UNRECOGNIZED_COMMAND, "Command not implemented"); - return; } void FtpSession::handleFtpCommandAPPE(const std::string& param) @@ -626,7 +615,7 @@ namespace fineftp return; } - std::string local_path = toLocalPath(param); + const std::string local_path = toLocalPath(param); auto existing_file_filestatus = Filesystem::FileStatus(local_path); if (!existing_file_filestatus.isOk() @@ -636,8 +625,8 @@ namespace fineftp return; } - std::ios::openmode open_mode = (data_type_binary_ ? (std::ios::out | std::ios::app | std::ios::binary) : (std::ios::out | std::ios::app)); - std::shared_ptr file = std::make_shared(local_path, open_mode); + const std::ios::openmode open_mode = (data_type_binary_ ? (std::ios::out | std::ios::app | std::ios::binary) : (std::ios::out | std::ios::app)); + const std::shared_ptr file = std::make_shared(local_path, open_mode); if (!file->file_stream_.good()) { @@ -647,19 +636,16 @@ namespace fineftp sendFtpMessage(FtpReplyCode::FILE_STATUS_OK_OPENING_DATA_CONNECTION, "Receiving file"); receiveFile(file); - return; } void FtpSession::handleFtpCommandALLO(const std::string& /*param*/) { sendFtpMessage(FtpReplyCode::SYNTAX_ERROR_UNRECOGNIZED_COMMAND, "Command not implemented"); - return; } void FtpSession::handleFtpCommandREST(const std::string& /*param*/) { sendFtpMessage(FtpReplyCode::COMMAND_NOT_IMPLEMENTED, "Command not implemented"); - return; } void FtpSession::handleFtpCommandRNFR(const std::string& param) @@ -710,8 +696,8 @@ namespace fineftp if (is_renamable_error.replyCode() == FtpReplyCode::COMMAND_OK) { - std::string local_from_path = toLocalPath(rename_from_path_); - std::string local_to_path = toLocalPath(param); + const std::string local_from_path = toLocalPath(rename_from_path_); + const std::string local_to_path = toLocalPath(param); // Check if the source file exists already. We simple disallow overwriting a // file be renaming (the bahavior of the native rename command on Windows @@ -757,7 +743,6 @@ namespace fineftp void FtpSession::handleFtpCommandABOR(const std::string& /*param*/) { sendFtpMessage(FtpReplyCode::COMMAND_NOT_IMPLEMENTED, "Command not implemented"); - return; } void FtpSession::handleFtpCommandDELE(const std::string& param) @@ -767,7 +752,7 @@ namespace fineftp sendFtpMessage(FtpReplyCode::NOT_LOGGED_IN, "Not logged in"); return; } - std::string local_path = toLocalPath(param); + const std::string local_path = toLocalPath(param); auto file_status = Filesystem::FileStatus(local_path); @@ -830,7 +815,7 @@ namespace fineftp return; } - std::string local_path = toLocalPath(param); + const std::string local_path = toLocalPath(param); #ifdef WIN32 if (RemoveDirectoryW(StrConvert::Utf8ToWide(local_path).c_str()) != 0) @@ -880,7 +865,7 @@ namespace fineftp auto local_path = toLocalPath(param); #ifdef WIN32 - LPSECURITY_ATTRIBUTES security_attributes = NULL; // => Default security attributes + LPSECURITY_ATTRIBUTES security_attributes = nullptr; // => Default security attributes if (CreateDirectoryW(StrConvert::Utf8ToWide(local_path).c_str(), security_attributes) != 0) { sendFtpMessage(FtpReplyCode::PATHNAME_CREATED, createQuotedFtpPath(toAbsoluteFtpPath(param)) + " Successfully created"); @@ -895,7 +880,7 @@ namespace fineftp return; } #else - mode_t mode = 0755; + const mode_t mode = 0755; if (mkdir(local_path.c_str(), mode) == 0) { sendFtpMessage(FtpReplyCode::PATHNAME_CREATED, createQuotedFtpPath(toAbsoluteFtpPath(param)) + " Successfully created"); @@ -922,7 +907,6 @@ namespace fineftp } sendFtpMessage(FtpReplyCode::PATHNAME_CREATED, createQuotedFtpPath(ftp_working_directory_)); - return; } void FtpSession::handleFtpCommandLIST(const std::string& param) @@ -980,7 +964,7 @@ namespace fineftp path2dst = param; } - std::string local_path = toLocalPath(path2dst); + const std::string local_path = toLocalPath(path2dst); auto dir_status = Filesystem::FileStatus(local_path); if (dir_status.isOk()) @@ -1028,7 +1012,7 @@ namespace fineftp return; } - std::string local_path = toLocalPath(param); + const std::string local_path = toLocalPath(param); auto dir_status = Filesystem::FileStatus(local_path); if (dir_status.isOk()) @@ -1139,7 +1123,7 @@ namespace fineftp } // TODO: close acceptor after connect? // Create a Unix-like file list - std::stringstream stream; + std::stringstream stream; // NOLINT(misc-const-correctness) Reason: False detection, this cannot be made const for (const auto& entry : directory_content) { const std::string& filename(entry.first); @@ -1154,8 +1138,8 @@ namespace fineftp } // Copy the file list into a raw char vector - std::string dir_listing_string = stream.str(); - std::shared_ptr> dir_listing_rawdata = std::make_shared>(); + const std::string dir_listing_string = stream.str(); + const std::shared_ptr> dir_listing_rawdata = std::make_shared>(); dir_listing_rawdata->reserve(dir_listing_string.size()); std::copy(dir_listing_string.begin(), dir_listing_string.end(), std::back_inserter(*dir_listing_rawdata)); @@ -1180,7 +1164,7 @@ namespace fineftp } // Create a file list - std::stringstream stream; + std::stringstream stream; // NOLINT(misc-const-correctness) Reason: False detection, this cannot be made const for (const auto& entry : directory_content) { stream << entry.first; @@ -1188,8 +1172,8 @@ namespace fineftp } // Copy the file list into a raw char vector - std::string dir_listing_string = stream.str(); - std::shared_ptr> dir_listing_rawdata = std::make_shared>(); + const std::string dir_listing_string = stream.str(); + const std::shared_ptr> dir_listing_rawdata = std::make_shared>(); dir_listing_rawdata->reserve(dir_listing_string.size()); std::copy(dir_listing_string.begin(), dir_listing_string.end(), std::back_inserter(*dir_listing_rawdata)); @@ -1199,7 +1183,7 @@ namespace fineftp }); } - void FtpSession::sendFile(std::shared_ptr file) + void FtpSession::sendFile(const std::shared_ptr& file) { auto data_socket = std::make_shared(io_service_); data_socket_weakptr_ = data_socket; @@ -1221,13 +1205,13 @@ namespace fineftp } - void FtpSession::readDataFromFileAndSend(std::shared_ptr file, std::shared_ptr data_socket) + void FtpSession::readDataFromFileAndSend(const std::shared_ptr& file, const std::shared_ptr& data_socket) { file_rw_strand_.post([me = shared_from_this(), file, data_socket]() { if(file->file_stream_.eof()) return; - std::shared_ptr>buffer = std::make_shared>(1024 * 1024 * 1); + const std::shared_ptr> buffer = std::make_shared>(1024 * 1024 * 1); file->file_stream_.read(buffer->data(), static_cast(buffer->size())); auto bytes_read = file->file_stream_.gcount(); buffer->resize(static_cast(bytes_read)); @@ -1244,11 +1228,11 @@ namespace fineftp }); } - void FtpSession::addDataToBufferAndSend(std::shared_ptr> data, std::shared_ptr data_socket, std::function fetch_more) + void FtpSession::addDataToBufferAndSend(const std::shared_ptr>& data, const std::shared_ptr& data_socket, const std::function& fetch_more) { data_buffer_strand_.post([me = shared_from_this(), data, data_socket, fetch_more]() { - bool write_in_progress = (!me->data_buffer_.empty()); + const bool write_in_progress = (!me->data_buffer_.empty()); me->data_buffer_.push_back(data); @@ -1259,7 +1243,7 @@ namespace fineftp }); } - void FtpSession::writeDataToSocket(std::shared_ptr data_socket, std::function fetch_more) + void FtpSession::writeDataToSocket(const std::shared_ptr& data_socket, const std::function& fetch_more) { data_buffer_strand_.post( [me = shared_from_this(), data_socket, fetch_more]() @@ -1304,7 +1288,7 @@ namespace fineftp // FTP data-socket receive //////////////////////////////////////////////////////// - void FtpSession::receiveFile(std::shared_ptr file) + void FtpSession::receiveFile(const std::shared_ptr& file) { auto data_socket = std::make_shared(io_service_); data_socket_weakptr_ = data_socket; @@ -1322,9 +1306,9 @@ namespace fineftp }); } - void FtpSession::receiveDataFromSocketAndWriteToFile(std::shared_ptr file, std::shared_ptr data_socket) + void FtpSession::receiveDataFromSocketAndWriteToFile(const std::shared_ptr& file, const std::shared_ptr& data_socket) { - std::shared_ptr> buffer = std::make_shared>(1024 * 1024 * 1); + const std::shared_ptr> buffer = std::make_shared>(1024 * 1024 * 1); asio::async_read(*data_socket , asio::buffer(*buffer) @@ -1349,7 +1333,7 @@ namespace fineftp } - void FtpSession::writeDataToFile(std::shared_ptr> data, std::shared_ptr file, std::function fetch_more) + void FtpSession::writeDataToFile(const std::shared_ptr>& data, const std::shared_ptr& file, const std::function& fetch_more) { file_rw_strand_.post([me = shared_from_this(), data, file, fetch_more] { @@ -1358,7 +1342,7 @@ namespace fineftp }); } - void FtpSession::endDataReceiving(std::shared_ptr file) + void FtpSession::endDataReceiving(const std::shared_ptr& file) { file_rw_strand_.post([me = shared_from_this(), file] { @@ -1393,19 +1377,19 @@ namespace fineftp assert(logged_in_user_); // First make the ftp path absolute if it isn't already - std::string absolute_ftp_path = toAbsoluteFtpPath(ftp_path); + const std::string absolute_ftp_path = toAbsoluteFtpPath(ftp_path); // Now map it to the local filesystem return fineftp::Filesystem::cleanPathNative(logged_in_user_->local_root_path_ + "/" + absolute_ftp_path); } - std::string FtpSession::createQuotedFtpPath(const std::string& unquoted_ftp_path) const + std::string FtpSession::createQuotedFtpPath(const std::string& unquoted_ftp_path) { std::string output; output.reserve(unquoted_ftp_path.size() * 2 + 2); output.push_back('\"'); - for (char c : unquoted_ftp_path) + for (const char c : unquoted_ftp_path) { output.push_back(c); if (c == '\"') // Escape quote by double-quote @@ -1429,7 +1413,7 @@ namespace fineftp if (file_status.isOk()) { // Calculate required permissions to rename the given resource - Permission required_permissions; + Permission required_permissions = Permission::None; if (file_status.type() == Filesystem::FileType::Dir) { required_permissions = Permission::DirRename; @@ -1489,7 +1473,7 @@ namespace fineftp } auto local_path = toLocalPath(absolute_new_working_dir); - Filesystem::FileStatus file_status(local_path); + const Filesystem::FileStatus file_status(local_path); if (!file_status.isOk()) { @@ -1508,23 +1492,23 @@ namespace fineftp } #ifdef WIN32 - std::string FtpSession::GetLastErrorStr() const + std::string FtpSession::GetLastErrorStr() { - DWORD error = GetLastError(); - if (error) - { - LPVOID lp_msg_buf; - DWORD buf_len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - error, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lp_msg_buf, - 0, NULL ); - if (buf_len) + const DWORD error = GetLastError(); + if (error != 0) + { + LPVOID lp_msg_buf = nullptr; + const DWORD buf_len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, + error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast(&lp_msg_buf), + 0, nullptr ); + if (buf_len != 0) { - LPCSTR lp_msg_str = (LPCSTR)lp_msg_buf; + LPCSTR lp_msg_str = reinterpret_cast(lp_msg_buf); std::string result(lp_msg_str, lp_msg_str + buf_len); result.erase(std::remove_if(result.begin(), result.end(), diff --git a/fineftp-server/src/ftp_session.h b/fineftp-server/src/ftp_session.h index fee1df5..1ef5321 100755 --- a/fineftp-server/src/ftp_session.h +++ b/fineftp-server/src/ftp_session.h @@ -32,6 +32,14 @@ namespace fineftp file_stream_.rdbuf()->pubsetbuf(stream_buffer_.data(), static_cast(stream_buffer_.size())); } + // Copy + IoFile(const IoFile&) = delete; + IoFile& operator=(const IoFile&) = delete; + + // Move disabled (as we are storing the shared_from_this() pointer in lambda captures) + IoFile& operator=(IoFile&&) = delete; + IoFile(IoFile&&) = delete; + ~IoFile() { file_stream_.flush(); @@ -48,6 +56,14 @@ namespace fineftp public: FtpSession(asio::io_service& io_service, const UserDatabase& user_database, const std::function& completion_handler); + // Copy (disabled, as we are inheriting from shared_from_this) + FtpSession(const FtpSession&) = delete; + FtpSession& operator=(const FtpSession&) = delete; + + // Move (disabled, as we are inheriting from shared_from_this) + FtpSession& operator=(FtpSession&&) = delete; + FtpSession(FtpSession&&) = delete; + ~FtpSession(); void start(); @@ -122,32 +138,32 @@ namespace fineftp void sendDirectoryListing (const std::map& directory_content); void sendNameList (const std::map& directory_content); - void sendFile (std::shared_ptr file); + void sendFile (const std::shared_ptr& file); - void readDataFromFileAndSend(std::shared_ptr file - , std::shared_ptr data_socket); + void readDataFromFileAndSend(const std::shared_ptr& file + , const std::shared_ptr& data_socket); - void addDataToBufferAndSend (std::shared_ptr> data - , std::shared_ptr data_socket - , std::function fetch_more = []() {return; }); + void addDataToBufferAndSend (const std::shared_ptr>& data + , const std::shared_ptr& data_socket + , const std::function& fetch_more = []() {return; }); - void writeDataToSocket (std::shared_ptr data_socket - , std::function fetch_more); + void writeDataToSocket (const std::shared_ptr& data_socket + , const std::function& fetch_more); //////////////////////////////////////////////////////// // FTP data-socket receive //////////////////////////////////////////////////////// private: - void receiveFile(std::shared_ptr file); + void receiveFile(const std::shared_ptr& file); - void receiveDataFromSocketAndWriteToFile(std::shared_ptr file - , std::shared_ptr data_socket); + void receiveDataFromSocketAndWriteToFile(const std::shared_ptr& file + , const std::shared_ptr& data_socket); - void writeDataToFile(std::shared_ptr> data - , std::shared_ptr file - , std::function fetch_more = []() {return; }); + void writeDataToFile(const std::shared_ptr>& data + , const std::shared_ptr& file + , const std::function& fetch_more = []() {return; }); - void endDataReceiving(std::shared_ptr file); + void endDataReceiving(const std::shared_ptr& file); //////////////////////////////////////////////////////// // Helpers @@ -155,7 +171,7 @@ namespace fineftp private: std::string toAbsoluteFtpPath(const std::string& rel_or_abs_ftp_path) const; std::string toLocalPath(const std::string& ftp_path) const; - std::string createQuotedFtpPath(const std::string& unquoted_ftp_path) const; + static std::string createQuotedFtpPath(const std::string& unquoted_ftp_path); /** @brief Checks if a path is renamable * @@ -176,7 +192,7 @@ namespace fineftp * @brief Returns Windows' GetLastError() as human readable string * @return The message of the last error */ - std::string GetLastErrorStr() const; + static std::string GetLastErrorStr(); #endif // WIN32 //////////////////////////////////////////////////////// diff --git a/fineftp-server/src/server.cpp b/fineftp-server/src/server.cpp index 0773ddf..24bf1b4 100644 --- a/fineftp-server/src/server.cpp +++ b/fineftp-server/src/server.cpp @@ -13,8 +13,11 @@ namespace fineftp : FtpServer(std::string("0.0.0.0"), port) {} - FtpServer::~FtpServer() - {} + // Move + FtpServer::FtpServer(FtpServer&&) noexcept = default; + FtpServer& FtpServer::operator=(FtpServer&&) noexcept = default; + + FtpServer::~FtpServer() = default; bool FtpServer::addUser(const std::string& username, const std::string& password, const std::string& local_root_path, const Permission permissions) { diff --git a/fineftp-server/src/server_impl.cpp b/fineftp-server/src/server_impl.cpp index e3695ec..c4bc1c8 100644 --- a/fineftp-server/src/server_impl.cpp +++ b/fineftp-server/src/server_impl.cpp @@ -36,7 +36,7 @@ namespace fineftp // set up the acceptor to listen on the tcp port asio::error_code make_address_ec; - asio::ip::tcp::endpoint endpoint(asio::ip::make_address(address_, make_address_ec), port_); + const asio::ip::tcp::endpoint endpoint(asio::ip::make_address(address_, make_address_ec), port_); if (make_address_ec) { std::cerr << "Error creating address from string \"" << address_<< "\": " << make_address_ec.message() << std::endl; @@ -113,7 +113,7 @@ namespace fineftp thread_pool_.clear(); } - void FtpServerImpl::acceptFtpSession(std::shared_ptr ftp_session, asio::error_code const& error) + void FtpServerImpl::acceptFtpSession(const std::shared_ptr& ftp_session, asio::error_code const& error) { if (error) { diff --git a/fineftp-server/src/server_impl.h b/fineftp-server/src/server_impl.h index bc26772..1d30f8e 100644 --- a/fineftp-server/src/server_impl.h +++ b/fineftp-server/src/server_impl.h @@ -19,10 +19,18 @@ namespace fineftp public: FtpServerImpl(const std::string& address, uint16_t port); + // Copy (disabled) + FtpServerImpl(const FtpServerImpl&) = delete; + FtpServerImpl& operator=(const FtpServerImpl&) = delete; + + // Move (disabled, as we are storing the this pointer in lambda captures) + FtpServerImpl& operator=(FtpServerImpl&&) = delete; + FtpServerImpl(FtpServerImpl&&) = delete; + ~FtpServerImpl(); - bool addUser(const std::string& username, const std::string& password, const std::string& local_root_path, const Permission permissions); - bool addUserAnonymous(const std::string& local_root_path, const Permission permissions); + bool addUser(const std::string& username, const std::string& password, const std::string& local_root_path, Permission permissions); + bool addUserAnonymous(const std::string& local_root_path, Permission permissions); bool start(size_t thread_count = 1); @@ -35,7 +43,7 @@ namespace fineftp std::string getAddress(); private: - void acceptFtpSession(std::shared_ptr ftp_session, asio::error_code const& error); + void acceptFtpSession(const std::shared_ptr& ftp_session, asio::error_code const& error); private: UserDatabase ftp_users_; @@ -49,4 +57,4 @@ namespace fineftp std::atomic open_connection_count_; }; -} \ No newline at end of file +} diff --git a/fineftp-server/src/user_database.cpp b/fineftp-server/src/user_database.cpp index 7b370ec..0f4f598 100644 --- a/fineftp-server/src/user_database.cpp +++ b/fineftp-server/src/user_database.cpp @@ -5,15 +5,9 @@ namespace fineftp { - UserDatabase::UserDatabase() - {} - - UserDatabase::~UserDatabase() - {} - bool UserDatabase::addUser(const std::string& username, const std::string& password, const std::string& local_root_path, Permission permissions) { - std::lock_guard database_lock(database_mutex_); + const std::lock_guard database_lock(database_mutex_); if (isUsernameAnonymousUser(username)) { @@ -24,7 +18,7 @@ namespace fineftp } else { - anonymous_user_ = std::shared_ptr(new FtpUser(password, local_root_path, permissions)); + anonymous_user_ = std::make_shared(password, local_root_path, permissions); #ifndef NDEBUG std::cout << "Successfully added anonymous user." << std::endl; #endif // !NDEBUG @@ -36,7 +30,7 @@ namespace fineftp auto user_it = database_.find(username); if (user_it == database_.end()) { - database_.emplace(username, std::shared_ptr(new FtpUser(password, local_root_path, permissions))); + database_.emplace(username, std::make_shared(password, local_root_path, permissions)); #ifndef NDEBUG std::cout << "Successfully added user \"" << username << "\"." << std::endl; #endif // !NDEBUG @@ -52,7 +46,7 @@ namespace fineftp std::shared_ptr UserDatabase::getUser(const std::string& username, const std::string& password) const { - std::lock_guard database_lock(database_mutex_); + const std::lock_guard database_lock(database_mutex_); if (isUsernameAnonymousUser(username)) { @@ -75,11 +69,11 @@ namespace fineftp } } - bool UserDatabase::isUsernameAnonymousUser(const std::string& username) const + bool UserDatabase::isUsernameAnonymousUser(const std::string& username) const // NOLINT(readability-convert-member-functions-to-static) Reason: I don't want to break the API. Otherwise this is a good finding and should be accepted. { return (username.empty() || username == "ftp" || username == "anonymous"); } -} \ No newline at end of file +} diff --git a/fineftp-server/src/user_database.h b/fineftp-server/src/user_database.h index b7d561f..a184554 100644 --- a/fineftp-server/src/user_database.h +++ b/fineftp-server/src/user_database.h @@ -12,9 +12,6 @@ namespace fineftp class UserDatabase { public: - UserDatabase(); - ~UserDatabase(); - bool addUser(const std::string& username, const std::string& password, const std::string& local_root_path, Permission permissions); std::shared_ptr getUser(const std::string& username, const std::string& password) const; diff --git a/fineftp-server/src/win_str_convert.cpp b/fineftp-server/src/win_str_convert.cpp index b6923c3..e176b3e 100644 --- a/fineftp-server/src/win_str_convert.cpp +++ b/fineftp-server/src/win_str_convert.cpp @@ -15,34 +15,34 @@ namespace fineftp #ifdef WIN32 std::string WideToAnsi(const std::wstring& wstr) { - int count = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), static_cast(wstr.length()), NULL, 0, NULL, NULL); - std::string str(count, 0); - WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &str[0], count, NULL, NULL); - return str; + const int count = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), static_cast(wstr.length()), nullptr, 0, nullptr, nullptr); + std::string str(count, 0); + WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &str[0], count, nullptr, nullptr); // NOLINT(readability-container-data-pointer) Reason: I need a non-const pointer here, due to the Raw C API, but .data() returns a const pointer. I don't consider a const_cast to be better. + return str; } std::wstring AnsiToWide(const std::string& str) { - int count = MultiByteToWideChar(CP_ACP, 0, str.c_str(), static_cast(str.length()), NULL, 0); - std::wstring wstr(count, 0); - MultiByteToWideChar(CP_ACP, 0, str.c_str(), static_cast(str.length()), &wstr[0], count); - return wstr; + const int count = MultiByteToWideChar(CP_ACP, 0, str.c_str(), static_cast(str.length()), nullptr, 0); + std::wstring wstr(count, 0); + MultiByteToWideChar(CP_ACP, 0, str.c_str(), static_cast(str.length()), &wstr[0], count); // NOLINT(readability-container-data-pointer) Reason: I need a non-const pointer here, due to the Raw C API, but .data() returns a const pointer. I don't consider a const_cast to be better. + return wstr; } std::string WideToUtf8(const std::wstring& wstr) { - int count = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), static_cast(wstr.length()), NULL, 0, NULL, NULL); - std::string str(count, 0); - WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &str[0], count, NULL, NULL); - return str; + const int count = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), static_cast(wstr.length()), nullptr, 0, nullptr, nullptr); + std::string str(count, 0); + WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &str[0], count, nullptr, nullptr); // NOLINT(readability-container-data-pointer) Reason: I need a non-const pointer here, due to the Raw C API, but .data() returns a const pointer. I don't consider a const_cast to be better. + return str; } std::wstring Utf8ToWide(const std::string& str) { - int count = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), static_cast(str.length()), NULL, 0); - std::wstring wstr(count, 0); - MultiByteToWideChar(CP_UTF8, 0, str.c_str(), static_cast(str.length()), &wstr[0], count); - return wstr; + const int count = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), static_cast(str.length()), nullptr, 0); + std::wstring wstr(count, 0); + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), static_cast(str.length()), &wstr[0], count); // NOLINT(readability-container-data-pointer) Reason: I need a non-const pointer here, due to the Raw C API, but .data() returns a const pointer. I don't consider a const_cast to be better. + return wstr; } std::string AnsiToUtf8(const std::string& str) diff --git a/samples/fineftp_example/src/main.cpp b/samples/fineftp_example/src/main.cpp index 94dbd0e..203fb8f 100644 --- a/samples/fineftp_example/src/main.cpp +++ b/samples/fineftp_example/src/main.cpp @@ -7,9 +7,9 @@ int main() { #ifdef WIN32 - std::string local_root = "C:\\"; // The backslash at the end is necessary! + const std::string local_root = "C:\\"; // The backslash at the end is necessary! #else // WIN32 - std::string local_root = "/"; + const std::string local_root = "/"; #endif // WIN32 // Create an FTP Server on port 2121. We use 2121 instead of the default port