updated build system
This commit is contained in:
		| @@ -48,113 +48,7 @@ | ||||
|  | ||||
| #if defined(__cplusplus) | ||||
| REPERTORY_IGNORE_WARNINGS_ENABLE() | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| #define WINVER 0x0602 | ||||
| #define _WIN32_WINNT WINVER | ||||
| #define WIN32_LEAN_AND_MEAN | ||||
|  | ||||
| #include <winsock2.h> | ||||
| #include <ws2tcpip.h> | ||||
| #include <windows.h> | ||||
| #include <shellapi.h> | ||||
| #include <shlwapi.h> | ||||
| #include <shlobj.h> | ||||
| #include <ciso646> | ||||
| #include <direct.h> | ||||
| #include <fcntl.h> | ||||
| #include <io.h> | ||||
| #include <time.h> | ||||
| #else | ||||
| #include <climits> | ||||
| #include <dirent.h> | ||||
| #include <fcntl.h> | ||||
| #include <grp.h> | ||||
| #include <libgen.h> | ||||
| #include <pwd.h> | ||||
| #include <sys/file.h> | ||||
| #include <sys/stat.h> | ||||
| #if defined(__linux__) | ||||
| #include <sys/statfs.h> | ||||
| #endif | ||||
| #include <unistd.h> | ||||
| #if defined(HAS_SETXATTR) | ||||
| #include <sys/types.h> | ||||
| #include <sys/xattr.h> | ||||
| #endif | ||||
| #if defined(__APPLE__) | ||||
| #include <libproc.h> | ||||
| #include <sys/attr.h> | ||||
| #include <sys/vnode.h> | ||||
| #endif | ||||
| #if defined(__APPLE__) | ||||
| #include <sys/mount.h> | ||||
| #include <sys/statvfs.h> | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <atomic> | ||||
| #include <chrono> | ||||
| #include <codecvt> | ||||
| #include <condition_variable> | ||||
| #include <deque> | ||||
| #include <filesystem> | ||||
| #include <fstream> | ||||
| #include <future> | ||||
| #include <iomanip> | ||||
| #include <iostream> | ||||
| #include <limits> | ||||
| #include <mutex> | ||||
| #include <optional> | ||||
| #include <random> | ||||
| #include <sstream> | ||||
| #include <string> | ||||
| #include <string_view> | ||||
| #include <thread> | ||||
| #include <type_traits> | ||||
| #include <unordered_map> | ||||
| #include <vector> | ||||
|  | ||||
| #include "sodium.h" | ||||
| template <typename data_type> | ||||
| [[nodiscard]] inline auto repertory_rand() -> data_type { | ||||
|   data_type ret{}; | ||||
|   randombytes_buf(&ret, sizeof(ret)); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| #include "boost/archive/text_iarchive.hpp" | ||||
| #include "boost/archive/text_oarchive.hpp" | ||||
| #include "boost/asio.hpp" | ||||
| #include "boost/asio/io_context.hpp" | ||||
| #include "boost/bind/bind.hpp" | ||||
| #include "boost/dynamic_bitset.hpp" | ||||
| #include "boost/dynamic_bitset/serialization.hpp" | ||||
| #include "boost/endian/conversion.hpp" | ||||
| #include "boost/serialization/vector.hpp" | ||||
| #include "curl/curl.h" | ||||
| #include "curl/multi.h" | ||||
| #include "json.hpp" | ||||
| #include "sqlite3.h" | ||||
| #include "uuid.h" | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| #include <sddl.h> | ||||
| #include "winfsp/winfsp.hpp" | ||||
| #else | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
| #include <fuse.h> | ||||
| #include <fuse_lowlevel.h> | ||||
| #else | ||||
| #include <fuse/fuse.h> | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #include "pugixml.hpp" | ||||
|  | ||||
| #include "httplib.h" | ||||
|  | ||||
| #include "utils/config.hpp" | ||||
| REPERTORY_IGNORE_WARNINGS_DISABLE() | ||||
|  | ||||
| using namespace std::chrono_literals; | ||||
| @@ -279,26 +173,6 @@ inline constexpr const auto NANOS_PER_SECOND = 1000000000L; | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #ifndef fstat64 | ||||
| #define fstat64 fstat | ||||
| #endif | ||||
|  | ||||
| #ifndef pread64 | ||||
| #define pread64 pread | ||||
| #endif | ||||
|  | ||||
| #ifndef pwrite64 | ||||
| #define pwrite64 pwrite | ||||
| #endif | ||||
|  | ||||
| #ifndef stat64 | ||||
| #define stat64 stat | ||||
| #endif | ||||
|  | ||||
| #ifndef statfs64 | ||||
| #define statfs64 statfs | ||||
| #endif | ||||
|  | ||||
| #define WINFSP_ALLOCATION_UNIT UINT64(4096U) | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| @@ -409,13 +283,6 @@ using FileInfo = FSP_FSCTL_FILE_INFO; | ||||
|  | ||||
| using namespace Fsp; | ||||
|  | ||||
| namespace { | ||||
| template <class... Ts> struct overloaded : Ts... { | ||||
|   using Ts::operator()...; | ||||
| }; | ||||
| template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>; | ||||
| } // namespace | ||||
|  | ||||
| #define INTERFACE_SETUP(name)                                                  \ | ||||
| public:                                                                        \ | ||||
|   name(const name &) noexcept = delete;                                        \ | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
| #if !defined(_WIN32) | ||||
|  | ||||
| #include "events/event_system.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config; | ||||
|   | ||||
| @@ -32,7 +32,7 @@ | ||||
| #include "types/remote.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/base64.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
|  | ||||
| #define REPERTORY_DIRECTORY_PAGE_SIZE std::size_t(100U) | ||||
|  | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
|  | ||||
| #include "events/event.hpp" | ||||
| #include "events/t_event_system.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/string.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| using event_system = t_event_system<event>; | ||||
|   | ||||
| @@ -23,6 +23,7 @@ | ||||
| #define INCLUDE_EVENTS_T_EVENT_SYSTEM_HPP_ | ||||
|  | ||||
| #include "events/event.hpp" | ||||
| #include "utils/collection.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| @@ -151,14 +152,14 @@ public: | ||||
|  | ||||
|   void release(event_consumer *consumer) { | ||||
|     recur_mutex_lock lock(consumer_mutex_); | ||||
|     auto iter = | ||||
|         std::find_if(event_consumers_.begin(), event_consumers_.end(), | ||||
|                      [&](const auto &item) -> bool { | ||||
|                        return utils::collection_includes(item.second, consumer); | ||||
|                      }); | ||||
|     auto iter = std::find_if(event_consumers_.begin(), event_consumers_.end(), | ||||
|                              [&](const auto &item) -> bool { | ||||
|                                return utils::collection::includes(item.second, | ||||
|                                                                   consumer); | ||||
|                              }); | ||||
|  | ||||
|     if (iter != event_consumers_.end()) { | ||||
|       utils::remove_element_from((*iter).second, consumer); | ||||
|       utils::collection::remove_element((*iter).second, consumer); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -102,6 +102,12 @@ enum class api_error { | ||||
| api_error_to_string(const api_error &error) -> const std::string &; | ||||
|  | ||||
| enum class download_type { direct, fallback, ring_buffer }; | ||||
| [[nodiscard]] auto | ||||
| download_type_from_string(std::string type, | ||||
|                           const download_type &default_type) -> download_type; | ||||
|  | ||||
| [[nodiscard]] auto | ||||
| download_type_to_string(const download_type &type) -> std::string; | ||||
|  | ||||
| enum class exit_code : std::int32_t { | ||||
|   success, | ||||
|   | ||||
| @@ -23,7 +23,7 @@ | ||||
| #define INCLUDE_TYPES_S3_HPP_ | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/string.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
|   | ||||
| @@ -1,170 +0,0 @@ | ||||
| // NOLINTBEGIN | ||||
| #ifndef _MACARON_BASE64_H_ | ||||
| #define _MACARON_BASE64_H_ | ||||
|  | ||||
| /** | ||||
|  * The MIT License (MIT) | ||||
|  * Copyright (c) 2016 tomykaira | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining | ||||
|  * a copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sublicense, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||||
|  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||||
|  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||||
|  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #ifdef __clang__ | ||||
| #pragma clang diagnostic push | ||||
| #pragma clang diagnostic ignored "-Wunknown-warning-option" | ||||
| #endif | ||||
|  | ||||
| #ifdef __GNUC__ | ||||
| #pragma GCC diagnostic push | ||||
| #pragma GCC diagnostic ignored "-Wconversion" | ||||
| #pragma GCC diagnostic ignored "-Wold-style-cast" | ||||
| #pragma GCC diagnostic ignored "-Wuseless-cast" | ||||
| #endif | ||||
|  | ||||
| #include <array> | ||||
| #include <string> | ||||
| #include <vector> | ||||
|  | ||||
| namespace macaron::Base64 { | ||||
| static std::string Encode(const unsigned char *data, std::size_t len) { | ||||
|   static constexpr std::array<unsigned char, 64U> sEncodingTable{ | ||||
|       'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', | ||||
|       'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', | ||||
|       'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', | ||||
|       'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', | ||||
|       '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', | ||||
|   }; | ||||
|  | ||||
|   auto in_len{len}; | ||||
|   std::string ret; | ||||
|   if (in_len > 0) { | ||||
|     std::size_t out_len{4U * ((in_len + 2U) / 3U)}; | ||||
|     ret = std::string(out_len, '\0'); | ||||
|     std::size_t i; | ||||
|     auto *p = reinterpret_cast<unsigned char *>(ret.data()); | ||||
|  | ||||
|     for (i = 0U; i < in_len - 2U; i += 3U) { | ||||
|       *p++ = sEncodingTable[(data[i] >> 2U) & 0x3F]; | ||||
|       *p++ = sEncodingTable[((data[i] & 0x3) << 4U) | | ||||
|                             ((int)(data[i + 1U] & 0xF0) >> 4U)]; | ||||
|       *p++ = sEncodingTable[((data[i + 1] & 0xF) << 2) | | ||||
|                             ((int)(data[i + 2U] & 0xC0) >> 6U)]; | ||||
|       *p++ = sEncodingTable[data[i + 2U] & 0x3F]; | ||||
|     } | ||||
|     if (i < in_len) { | ||||
|       *p++ = sEncodingTable[(data[i] >> 2U) & 0x3F]; | ||||
|       if (i == (in_len - 1U)) { | ||||
|         *p++ = sEncodingTable[((data[i] & 0x3) << 4U)]; | ||||
|         *p++ = '='; | ||||
|       } else { | ||||
|         *p++ = sEncodingTable[((data[i] & 0x3) << 4U) | | ||||
|                               ((int)(data[i + 1U] & 0xF0) >> 4U)]; | ||||
|         *p++ = sEncodingTable[((data[i + 1U] & 0xF) << 2U)]; | ||||
|       } | ||||
|       *p++ = '='; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| [[maybe_unused]] static std::string Encode(std::string_view data) { | ||||
|   return Encode(reinterpret_cast<const unsigned char *>(data.data()), | ||||
|                 data.size()); | ||||
| } | ||||
|  | ||||
| [[maybe_unused]] static std::vector<unsigned char> | ||||
| Decode(std::string_view input) { | ||||
|   static constexpr std::array<unsigned char, 256> kDecodingTable{ | ||||
|       64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||||
|       64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||||
|       64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57, | ||||
|       58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0,  1,  2,  3,  4,  5,  6, | ||||
|       7,  8,  9,  10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, | ||||
|       25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, | ||||
|       37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, | ||||
|       64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||||
|       64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||||
|       64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||||
|       64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||||
|       64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||||
|       64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||||
|       64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||||
|       64, 64, 64, 64, | ||||
|   }; | ||||
|  | ||||
|   std::vector<unsigned char> out; | ||||
|   if (not input.empty()) { | ||||
|     auto in_len{input.size()}; | ||||
|     if (in_len % 4U != 0U) { | ||||
|       throw std::runtime_error("Input data size is not a multiple of 4"); | ||||
|     } | ||||
|  | ||||
|     std::size_t out_len{in_len / 4U * 3U}; | ||||
|     if (input[in_len - 1U] == '=') { | ||||
|       out_len--; | ||||
|     } | ||||
|     if (input[in_len - 2U] == '=') { | ||||
|       out_len--; | ||||
|     } | ||||
|  | ||||
|     out.resize(out_len); | ||||
|  | ||||
|     for (std::size_t i = 0U, j = 0U; i < in_len;) { | ||||
|       std::uint32_t a = input[i] == '=' | ||||
|                             ? 0U & i++ | ||||
|                             : kDecodingTable[static_cast<int>(input[i++])]; | ||||
|       std::uint32_t b = input[i] == '=' | ||||
|                             ? 0U & i++ | ||||
|                             : kDecodingTable[static_cast<int>(input[i++])]; | ||||
|       std::uint32_t c = input[i] == '=' | ||||
|                             ? 0U & i++ | ||||
|                             : kDecodingTable[static_cast<int>(input[i++])]; | ||||
|       std::uint32_t d = input[i] == '=' | ||||
|                             ? 0U & i++ | ||||
|                             : kDecodingTable[static_cast<int>(input[i++])]; | ||||
|  | ||||
|       std::uint32_t triple = | ||||
|           (a << 3U * 6U) + (b << 2U * 6U) + (c << 1U * 6U) + (d << 0U * 6U); | ||||
|  | ||||
|       if (j < out_len) | ||||
|         out[j++] = (triple >> 2U * 8U) & 0xFF; | ||||
|       if (j < out_len) | ||||
|         out[j++] = (triple >> 1U * 8U) & 0xFF; | ||||
|       if (j < out_len) | ||||
|         out[j++] = (triple >> 0U * 8U) & 0xFF; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return out; | ||||
| } | ||||
| } // namespace macaron::Base64 | ||||
|  | ||||
| #ifdef __GNUC__ | ||||
| #pragma GCC diagnostic pop | ||||
| #endif | ||||
|  | ||||
| #ifdef __clang__ | ||||
| #pragma clang diagnostic pop | ||||
| #endif | ||||
|  | ||||
| #endif /* _MACARON_BASE64_H_ */ | ||||
|  | ||||
| // NOLINTEND | ||||
| @@ -1,45 +0,0 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   in the Software without restriction, including without limitation the rights | ||||
|   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|   copies of the Software, and to permit persons to whom the Software is | ||||
|   furnished to do so, subject to the following conditions: | ||||
|  | ||||
|   The above copyright notice and this permission notice shall be included in all | ||||
|   copies or substantial portions of the Software. | ||||
|  | ||||
|   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|   SOFTWARE. | ||||
| */ | ||||
| #ifndef INCLUDE_UTILS_COM_INIT_WRAPPER_HPP_ | ||||
| #define INCLUDE_UTILS_COM_INIT_WRAPPER_HPP_ | ||||
| #if defined(_WIN32) | ||||
|  | ||||
| namespace repertory { | ||||
| class com_init_wrapper { | ||||
| public: | ||||
|   com_init_wrapper() | ||||
|       : uninit_( | ||||
|             SUCCEEDED(::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED))) {} | ||||
|  | ||||
|   ~com_init_wrapper() { | ||||
|     if (uninit_) { | ||||
|       ::CoUninitialize(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| private: | ||||
|   const BOOL uninit_; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // _WIN32 | ||||
| #endif // INCLUDE_UTILS_COM_INIT_WRAPPER_HPP_ | ||||
| @@ -23,6 +23,7 @@ | ||||
| #define INCLUDE_UTILS_ENCRYPT_HPP_ | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/encryption.hpp" | ||||
| #include "utils/encrypting_reader.hpp" | ||||
|  | ||||
| namespace repertory::utils::encryption { | ||||
| @@ -40,122 +41,6 @@ using reader_func = std::function<api_error(data_buffer &cypher_text, | ||||
|                                         const key_type &key, reader_func reader, | ||||
|                                         std::uint64_t total_size, | ||||
|                                         data_buffer &data) -> api_error; | ||||
|  | ||||
| [[nodiscard]] auto generate_key(std::string_view encryption_token) -> key_type; | ||||
|  | ||||
| // Implementations | ||||
| template <typename result> | ||||
| [[nodiscard]] inline auto | ||||
| decrypt_data(const key_type &key, const unsigned char *buffer, | ||||
|              std::size_t buffer_size, result &res) -> bool { | ||||
|   const auto header_size = | ||||
|       static_cast<std::uint32_t>(encrypting_reader::get_header_size()); | ||||
|   if (buffer_size > header_size) { | ||||
|     const std::uint32_t size = | ||||
|         boost::endian::native_to_big(static_cast<std::uint32_t>(buffer_size)); | ||||
|     res.resize(buffer_size - header_size); | ||||
|     return crypto_aead_xchacha20poly1305_ietf_decrypt_detached( | ||||
|                reinterpret_cast<unsigned char *>(res.data()), nullptr, | ||||
|                &buffer[header_size], res.size(), | ||||
|                &buffer[crypto_aead_xchacha20poly1305_IETF_NPUBBYTES], | ||||
|                reinterpret_cast<const unsigned char *>(&size), sizeof(size), | ||||
|                buffer, key.data()) == 0; | ||||
|   } | ||||
|  | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| template <typename buffer, typename result> | ||||
| [[nodiscard]] inline auto decrypt_data(const key_type &key, const buffer &buf, | ||||
|                                        result &res) -> bool { | ||||
|   return decrypt_data<result>( | ||||
|       key, reinterpret_cast<const unsigned char *>(buf.data()), buf.size(), | ||||
|       res); | ||||
| } | ||||
|  | ||||
| template <typename buffer, typename result> | ||||
| [[nodiscard]] inline auto decrypt_data(std::string_view encryption_token, | ||||
|                                        const buffer &buf, result &res) -> bool { | ||||
|   return decrypt_data<buffer, result>(generate_key(encryption_token), buf, res); | ||||
| } | ||||
|  | ||||
| template <typename result> | ||||
| [[nodiscard]] inline auto | ||||
| decrypt_data(std::string_view encryption_token, const unsigned char *buffer, | ||||
|              std::size_t buffer_size, result &res) -> bool { | ||||
|   return decrypt_data<result>(generate_key(encryption_token), buffer, | ||||
|                               buffer_size, res); | ||||
| } | ||||
|  | ||||
| template <typename result> | ||||
| inline void | ||||
| encrypt_data(const std::array<unsigned char, | ||||
|                               crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> &iv, | ||||
|              const key_type &key, const unsigned char *buffer, | ||||
|              std::size_t buffer_size, result &res) { | ||||
|   std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_ABYTES> mac{}; | ||||
|  | ||||
|   const auto header_size = | ||||
|       static_cast<std::uint32_t>(encrypting_reader::get_header_size()); | ||||
|  | ||||
|   const std::uint32_t size = boost::endian::native_to_big( | ||||
|       static_cast<std::uint32_t>(buffer_size + header_size)); | ||||
|  | ||||
|   res.resize(buffer_size + header_size); | ||||
|  | ||||
|   unsigned long long mac_length{}; | ||||
|   if (crypto_aead_xchacha20poly1305_ietf_encrypt_detached( | ||||
|           reinterpret_cast<unsigned char *>(&res[header_size]), mac.data(), | ||||
|           &mac_length, buffer, buffer_size, | ||||
|           reinterpret_cast<const unsigned char *>(&size), sizeof(size), nullptr, | ||||
|           iv.data(), key.data()) != 0) { | ||||
|     throw std::runtime_error("encryption failed"); | ||||
|   } | ||||
|  | ||||
|   std::memcpy(res.data(), iv.data(), iv.size()); | ||||
|   std::memcpy(&res[iv.size()], mac.data(), mac.size()); | ||||
| } | ||||
|  | ||||
| template <typename result> | ||||
| inline void encrypt_data(const key_type &key, const unsigned char *buffer, | ||||
|                          std::size_t buffer_size, result &res) { | ||||
|   std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> iv{}; | ||||
|   randombytes_buf(iv.data(), iv.size()); | ||||
|  | ||||
|   encrypt_data<result>(iv, key, buffer, buffer_size, res); | ||||
| } | ||||
|  | ||||
| template <typename result> | ||||
| inline void encrypt_data(std::string_view encryption_token, | ||||
|                          const unsigned char *buffer, std::size_t buffer_size, | ||||
|                          result &res) { | ||||
|   encrypt_data<result>(generate_key(encryption_token), buffer, buffer_size, | ||||
|                        res); | ||||
| } | ||||
|  | ||||
| template <typename buffer, typename result> | ||||
| inline void encrypt_data(std::string_view encryption_token, const buffer &buf, | ||||
|                          result &res) { | ||||
|   encrypt_data<result>(generate_key(encryption_token), | ||||
|                        reinterpret_cast<const unsigned char *>(buf.data()), | ||||
|                        buf.size(), res); | ||||
| } | ||||
|  | ||||
| template <typename buffer, typename result> | ||||
| inline void encrypt_data(const key_type &key, const buffer &buf, result &res) { | ||||
|   encrypt_data<result>(key, reinterpret_cast<const unsigned char *>(buf.data()), | ||||
|                        buf.size(), res); | ||||
| } | ||||
|  | ||||
| template <typename buffer, typename result> | ||||
| inline void | ||||
| encrypt_data(const std::array<unsigned char, | ||||
|                               crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> &iv, | ||||
|              const key_type &key, const buffer &buf, result &res) { | ||||
|   encrypt_data<result>(iv, key, | ||||
|                        reinterpret_cast<const unsigned char *>(buf.data()), | ||||
|                        buf.size(), res); | ||||
| } | ||||
| } // namespace repertory::utils::encryption | ||||
|  | ||||
| #endif // INCLUDE_UTILS_ENCRYPT_HPP_ | ||||
|   | ||||
| @@ -23,6 +23,7 @@ | ||||
| #define INCLUDE_UTILS_FILE_UTILS_HPP_ | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/file.hpp" | ||||
| #include "utils/native_file.hpp" | ||||
|  | ||||
| namespace repertory::utils::file { | ||||
| @@ -62,16 +63,9 @@ get_free_drive_space(const std::string &path) -> std::uint64_t; | ||||
| [[nodiscard]] auto | ||||
| get_total_drive_space(const std::string &path) -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto get_file_size(std::string_view path, | ||||
|                                  std::uint64_t &file_size) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto get_modified_time(const std::string &path, | ||||
|                                      std::uint64_t &modified) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto is_directory(const std::string &path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto is_file(const std::string &path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto | ||||
| is_modified_date_older_than(const std::string &path, | ||||
|                             const std::chrono::hours &hours) -> bool; | ||||
| @@ -81,16 +75,11 @@ is_modified_date_older_than(const std::string &path, | ||||
| [[nodiscard]] auto | ||||
| read_file_lines(const std::string &path) -> std::vector<std::string>; | ||||
|  | ||||
| [[nodiscard]] auto read_json_file(const std::string &path, json &data) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto reset_modified_time(const std::string &path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto retry_delete_directory(const std::string &dir) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto retry_delete_file(const std::string &file) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto write_json_file(const std::string &path, | ||||
|                                    const json &j) -> bool; | ||||
| } // namespace repertory::utils::file | ||||
|  | ||||
| #endif // INCLUDE_UTILS_FILE_UTILS_HPP_ | ||||
|   | ||||
| @@ -1,66 +0,0 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   in the Software without restriction, including without limitation the rights | ||||
|   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|   copies of the Software, and to permit persons to whom the Software is | ||||
|   furnished to do so, subject to the following conditions: | ||||
|  | ||||
|   The above copyright notice and this permission notice shall be included in all | ||||
|   copies or substantial portions of the Software. | ||||
|  | ||||
|   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|   SOFTWARE. | ||||
| */ | ||||
| #ifndef INCLUDE_UTILS_PATH_UTILS_HPP_ | ||||
| #define INCLUDE_UTILS_PATH_UTILS_HPP_ | ||||
|  | ||||
| namespace repertory::utils::path { | ||||
| #if defined(_WIN32) | ||||
| static const std::string directory_seperator = "\\"; | ||||
| static const std::string not_directory_seperator = "/"; | ||||
| #else | ||||
| static const std::string directory_seperator = "/"; | ||||
| static const std::string not_directory_seperator = "\\"; | ||||
| #endif | ||||
|  | ||||
| // Prototypes | ||||
| [[nodiscard]] auto absolute(std::string path) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto | ||||
| combine(std::string path, const std::vector<std::string> &paths) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto create_api_path(std::string path) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto finalize(std::string path) -> std::string; | ||||
|  | ||||
| auto format_path(std::string &path, const std::string &sep, | ||||
|                  const std::string ¬_sep) -> std::string &; | ||||
|  | ||||
| [[nodiscard]] auto get_parent_api_path(const std::string &path) -> std::string; | ||||
|  | ||||
| #if !defined(_WIN32) | ||||
| [[nodiscard]] auto get_parent_directory(std::string path) -> std::string; | ||||
| #endif | ||||
|  | ||||
| [[nodiscard]] auto is_ads_file_path(const std::string &path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto is_trash_directory(std::string path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto remove_file_name(std::string path) -> std::string; | ||||
|  | ||||
| #if !defined(_WIN32) | ||||
| [[nodiscard]] auto resolve(std::string path) -> std::string; | ||||
| #endif | ||||
|  | ||||
| [[nodiscard]] auto strip_to_file_name(std::string path) -> std::string; | ||||
| } // namespace repertory::utils::path | ||||
|  | ||||
| #endif // INCLUDE_UTILS_PATH_UTILS_HPP_ | ||||
| @@ -1,114 +0,0 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   in the Software without restriction, including without limitation the rights | ||||
|   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|   copies of the Software, and to permit persons to whom the Software is | ||||
|   furnished to do so, subject to the following conditions: | ||||
|  | ||||
|   The above copyright notice and this permission notice shall be included in all | ||||
|   copies or substantial portions of the Software. | ||||
|  | ||||
|   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|   SOFTWARE. | ||||
| */ | ||||
| #ifndef INCLUDE_UTILS_STRING_UTILS_HPP_ | ||||
| #define INCLUDE_UTILS_STRING_UTILS_HPP_ | ||||
|  | ||||
| namespace repertory::utils::string { | ||||
| // Prototypes | ||||
| constexpr auto begins_with(std::string_view str, std::string_view val) -> bool { | ||||
|   return (str.find(val) == 0U); | ||||
| } | ||||
|  | ||||
| constexpr auto contains(std::string_view str, std::string_view search) -> bool { | ||||
|   return (str.find(search) != std::string_view::npos); | ||||
| } | ||||
|  | ||||
| [[nodiscard]] /* constexpr c++20 */ auto | ||||
| ends_with(std::string_view str, std::string_view val) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto from_bool(bool val) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto | ||||
| from_dynamic_bitset(const boost::dynamic_bitset<> &bitset) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto from_utf8(std::string_view str) -> std::wstring; | ||||
|  | ||||
| [[nodiscard]] /* constexpr c++20 */ auto | ||||
| is_numeric(std::string_view str) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto join(const std::vector<std::string> &arr, | ||||
|                         const char &delim) -> std::string; | ||||
|  | ||||
| auto left_trim(std::string &str) -> std::string &; | ||||
|  | ||||
| auto left_trim(std::string &str, const char &trim_ch) -> std::string &; | ||||
|  | ||||
| auto replace(std::string &src, const char &character, | ||||
|              const char &with) -> std::string &; | ||||
|  | ||||
| auto replace(std::string &src, const std::string &find, const std::string &with, | ||||
|              size_t start_pos = 0) -> std::string &; | ||||
|  | ||||
| [[nodiscard]] auto replace_copy(std::string src, const char &character, | ||||
|                                 const char &with) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto replace_copy(std::string src, const std::string &find, | ||||
|                                 const std::string &with, | ||||
|                                 size_t start_pos = 0) -> std::string; | ||||
|  | ||||
| auto right_trim(std::string &str) -> std::string &; | ||||
|  | ||||
| auto right_trim(std::string &str, const char &trim_ch) -> std::string &; | ||||
|  | ||||
| [[nodiscard]] auto split(const std::string &str, const char &delim, | ||||
|                          bool should_trim = true) -> std::vector<std::string>; | ||||
|  | ||||
| [[nodiscard]] auto to_bool(std::string val) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto to_double(const std::string &str) -> double; | ||||
|  | ||||
| [[nodiscard]] auto | ||||
| to_dynamic_bitset(const std::string &val) -> boost::dynamic_bitset<>; | ||||
|  | ||||
| [[nodiscard]] auto to_lower(std::string str) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto to_int32(const std::string &val) -> std::int32_t; | ||||
|  | ||||
| [[nodiscard]] auto to_int64(const std::string &val) -> std::int64_t; | ||||
|  | ||||
| [[nodiscard]] auto to_size_t(const std::string &val) -> std::size_t; | ||||
|  | ||||
| [[nodiscard]] auto to_uint8(const std::string &val) -> std::uint8_t; | ||||
|  | ||||
| [[nodiscard]] auto to_uint16(const std::string &val) -> std::uint16_t; | ||||
|  | ||||
| [[nodiscard]] auto to_uint32(const std::string &val) -> std::uint32_t; | ||||
|  | ||||
| [[nodiscard]] auto to_uint64(const std::string &val) -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto to_upper(std::string str) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto to_utf8(std::string_view str) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto to_utf8(std::wstring_view str) -> std::string; | ||||
|  | ||||
| auto trim(std::string &str) -> std::string &; | ||||
|  | ||||
| auto trim(std::string &str, const char &trim_ch) -> std::string &; | ||||
|  | ||||
| [[nodiscard]] auto trim_copy(std::string str) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto trim_copy(std::string str, | ||||
|                              const char &trim_ch) -> std::string; | ||||
| } // namespace repertory::utils::string | ||||
|  | ||||
| #endif // INCLUDE_UTILS_STRING_UTILS_HPP_ | ||||
| @@ -25,6 +25,7 @@ | ||||
|  | ||||
| #include "types/remote.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/unix.hpp" | ||||
|  | ||||
| namespace repertory::utils { | ||||
| #if defined(__linux__) | ||||
| @@ -35,25 +36,8 @@ inline const std::array<std::string, 4U> attribute_namespaces = { | ||||
|     "user", | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| #if defined(__APPLE__) | ||||
| template <typename t> | ||||
| [[nodiscard]] auto convert_to_uint64(const t *ptr) -> std::uint64_t; | ||||
| #else | ||||
| [[nodiscard]] auto convert_to_uint64(const pthread_t &thread) -> std::uint64_t; | ||||
| #endif | ||||
|  | ||||
| [[nodiscard]] auto from_api_error(const api_error &err) -> int; | ||||
|  | ||||
| [[nodiscard]] auto get_last_error_code() -> int; | ||||
|  | ||||
| [[nodiscard]] auto get_thread_id() -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto is_uid_member_of_group(const uid_t &uid, | ||||
|                                           const gid_t &gid) -> bool; | ||||
|  | ||||
| void set_last_error_code(int error_code); | ||||
|  | ||||
| [[nodiscard]] auto to_api_error(int err) -> api_error; | ||||
|  | ||||
| [[nodiscard]] auto unix_error_to_windows(int err) -> std::int32_t; | ||||
| @@ -61,22 +45,12 @@ void set_last_error_code(int error_code); | ||||
| [[nodiscard]] auto | ||||
| unix_time_to_windows_time(const remote::file_time &file_time) -> UINT64; | ||||
|  | ||||
| void use_getpwuid(uid_t uid, std::function<void(struct passwd *pass)> callback); | ||||
|  | ||||
| void windows_create_to_unix(const UINT32 &create_options, | ||||
|                             const UINT32 &granted_access, std::uint32_t &flags, | ||||
|                             remote::file_mode &mode); | ||||
|  | ||||
| [[nodiscard]] auto | ||||
| windows_time_to_unix_time(std::uint64_t win_time) -> remote::file_time; | ||||
|  | ||||
| // template implementations | ||||
| #if defined(__APPLE__) | ||||
| template <typename t> | ||||
| [[nodiscard]] auto convert_to_uint64(const t *v) -> std::uint64_t { | ||||
|   return static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(v)); | ||||
| } | ||||
| #endif | ||||
| } // namespace repertory::utils | ||||
|  | ||||
| #endif // !_WIN32 | ||||
|   | ||||
| @@ -32,73 +32,19 @@ void calculate_allocation_size(bool directory, std::uint64_t file_size, | ||||
|                                UINT64 allocation_size, | ||||
|                                std::string &allocation_meta_size); | ||||
|  | ||||
| [[nodiscard]] auto calculate_read_size(const uint64_t &total_size, | ||||
|                                        std::size_t read_size, | ||||
|                                        const uint64_t &offset) -> std::size_t; | ||||
|  | ||||
| template <typename t> | ||||
| [[nodiscard]] auto collection_excludes(t collection, | ||||
|                                        const typename t::value_type &val) | ||||
|     -> bool; | ||||
|  | ||||
| template <typename t> | ||||
| [[nodiscard]] auto collection_includes(t collection, | ||||
|                                        const typename t::value_type &val) | ||||
|     -> bool; | ||||
|  | ||||
| [[nodiscard]] auto compare_version_strings(std::string version1, | ||||
|                                            std::string version2) -> int; | ||||
|  | ||||
| [[nodiscard]] auto convert_api_date(const std::string &date) -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto create_curl() -> CURL *; | ||||
|  | ||||
| [[nodiscard]] auto create_uuid_string() -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto create_volume_label(const provider_type &prov) | ||||
|     -> std::string; | ||||
|  | ||||
| template <typename t> | ||||
| [[nodiscard]] auto divide_with_ceiling(const t &n, const t &d) -> t; | ||||
|  | ||||
| [[nodiscard]] auto download_type_from_string(std::string type, | ||||
|                                              const download_type &default_type) | ||||
|     -> download_type; | ||||
|  | ||||
| [[nodiscard]] auto download_type_to_string(const download_type &type) | ||||
|     -> std::string; | ||||
|  | ||||
| template <typename t> | ||||
| [[nodiscard]] auto from_hex_string(const std::string &str, t &val) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto generate_random_string(std::uint16_t length) -> std::string; | ||||
| [[nodiscard]] auto | ||||
| create_volume_label(const provider_type &prov) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto get_attributes_from_meta(const api_meta_map &meta) -> DWORD; | ||||
|  | ||||
| [[nodiscard]] auto get_environment_variable(const std::string &variable) | ||||
|     -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto get_file_time_now() -> std::uint64_t; | ||||
|  | ||||
| void get_local_time_now(struct tm &local_time); | ||||
|  | ||||
| [[nodiscard]] auto get_next_available_port(std::uint16_t first_port, | ||||
|                                            std::uint16_t &available_port) | ||||
|     -> bool; | ||||
|  | ||||
| [[nodiscard]] auto get_time_now() -> std::uint64_t; | ||||
|  | ||||
| template <typename data_type> | ||||
| [[nodiscard]] auto random_between(const data_type &begin, const data_type &end) | ||||
|     -> data_type; | ||||
|  | ||||
| template <typename t> | ||||
| void remove_element_from(t &collection, const typename t::value_type &val); | ||||
|  | ||||
| [[nodiscard]] auto reset_curl(CURL *curl_handle) -> CURL *; | ||||
|  | ||||
| [[nodiscard]] auto retryable_action(const std::function<bool()> &action) | ||||
|     -> bool; | ||||
| [[nodiscard]] auto | ||||
| retryable_action(const std::function<bool()> &action) -> bool; | ||||
|  | ||||
| void spin_wait_for_mutex(std::function<bool()> complete, | ||||
|                          std::condition_variable &cond, std::mutex &mtx, | ||||
| @@ -107,75 +53,6 @@ void spin_wait_for_mutex(std::function<bool()> complete, | ||||
| void spin_wait_for_mutex(bool &complete, std::condition_variable &cond, | ||||
|                          std::mutex &mtx, const std::string &text = ""); | ||||
|  | ||||
| template <typename collection_t> | ||||
| [[nodiscard]] auto to_hex_string(const collection_t &collection) -> std::string; | ||||
|  | ||||
| // template implementations | ||||
| template <typename t> | ||||
| [[nodiscard]] auto collection_excludes(t collection, | ||||
|                                        const typename t::value_type &val) | ||||
|     -> bool { | ||||
|   return std::find(collection.begin(), collection.end(), val) == | ||||
|          collection.end(); | ||||
| } | ||||
|  | ||||
| template <typename t> | ||||
| [[nodiscard]] auto collection_includes(t collection, | ||||
|                                        const typename t::value_type &val) | ||||
|     -> bool { | ||||
|   return std::find(collection.begin(), collection.end(), val) != | ||||
|          collection.end(); | ||||
| } | ||||
|  | ||||
| template <typename t> | ||||
| [[nodiscard]] auto divide_with_ceiling(const t &n, const t &d) -> t { | ||||
|   return n ? (n / d) + (n % d != 0) : 0; | ||||
| } | ||||
|  | ||||
| template <typename t> | ||||
| [[nodiscard]] auto from_hex_string(const std::string &str, t &val) -> bool { | ||||
|   static constexpr const auto base16 = 16; | ||||
|  | ||||
|   val.clear(); | ||||
|   if (not(str.length() % 2U)) { | ||||
|     for (std::size_t i = 0U; i < str.length(); i += 2U) { | ||||
|       val.emplace_back(static_cast<typename t::value_type>( | ||||
|           strtol(str.substr(i, 2U).c_str(), nullptr, base16))); | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| template <typename data_type> | ||||
| [[nodiscard]] auto random_between(const data_type &begin, const data_type &end) | ||||
|     -> data_type { | ||||
|   return begin + repertory_rand<data_type>() % ((end + data_type{1}) - begin); | ||||
| } | ||||
|  | ||||
| template <typename collection_t> | ||||
| void remove_element_from(collection_t &collection, | ||||
|                          const typename collection_t::value_type &value) { | ||||
|   collection.erase(std::remove(collection.begin(), collection.end(), value), | ||||
|                    collection.end()); | ||||
| } | ||||
|  | ||||
| template <typename collection_t> | ||||
| [[nodiscard]] auto to_hex_string(const collection_t &collection) | ||||
|     -> std::string { | ||||
|   static_assert(sizeof(typename collection_t::value_type) == 1U, | ||||
|                 "value_type must be 1 byte in size"); | ||||
|   static constexpr const auto mask = 0xFF; | ||||
|  | ||||
|   std::stringstream stream; | ||||
|   for (const auto &val : collection) { | ||||
|     stream << std::setfill('0') << std::setw(2) << std::hex | ||||
|            << (static_cast<std::uint32_t>(val) & mask); | ||||
|   } | ||||
|  | ||||
|   return stream.str(); | ||||
| } | ||||
| } // namespace repertory::utils | ||||
|  | ||||
| #endif // INCLUDE_UTILS_UTILS_HPP_ | ||||
|   | ||||
| @@ -25,15 +25,9 @@ | ||||
|  | ||||
| #include "types/remote.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/windows.hpp" | ||||
|  | ||||
| namespace repertory::utils { | ||||
| [[nodiscard]] auto | ||||
| filetime_to_unix_time(const FILETIME &ft) -> remote::file_time; | ||||
|  | ||||
| [[nodiscard]] auto get_last_error_code() -> DWORD; | ||||
|  | ||||
| [[nodiscard]] auto get_local_app_data_directory() -> const std::string &; | ||||
|  | ||||
| [[nodiscard]] auto | ||||
| get_accessed_time_from_meta(const api_meta_map &meta) -> std::uint64_t; | ||||
|  | ||||
| @@ -46,29 +40,14 @@ get_creation_time_from_meta(const api_meta_map &meta) -> std::uint64_t; | ||||
| [[nodiscard]] auto | ||||
| get_written_time_from_meta(const api_meta_map &meta) -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto get_thread_id() -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto is_process_elevated() -> bool; | ||||
|  | ||||
| [[nodiscard]] auto run_process_elevated(std::vector<const char *> args) -> int; | ||||
|  | ||||
| void set_last_error_code(DWORD errorCode); | ||||
|  | ||||
| [[nodiscard]] auto from_api_error(const api_error &e) -> NTSTATUS; | ||||
|  | ||||
| auto strptime(const char *s, const char *f, struct tm *tm) -> const char *; | ||||
|  | ||||
| [[nodiscard]] auto unix_access_mask_to_windows(std::int32_t mask) -> int; | ||||
|  | ||||
| [[nodiscard]] auto | ||||
| unix_open_flags_to_flags_and_perms(const remote::file_mode &mode, | ||||
|                                    const remote::open_flags &flags, | ||||
|                                    std::int32_t &perms) -> int; | ||||
|  | ||||
| void unix_time_to_filetime(const remote::file_time &ts, FILETIME &ft); | ||||
|  | ||||
| [[nodiscard]] auto | ||||
| time64_to_unix_time(const __time64_t &t) -> remote::file_time; | ||||
| } // namespace repertory::utils | ||||
|  | ||||
| #endif // _WIN32 | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
| #include "types/startup_exception.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/unix/unix_utils.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
|   | ||||
| @@ -22,8 +22,8 @@ | ||||
| #include "comm/curl/curl_comm.hpp" | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/string.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| const curl_comm::write_callback curl_comm::write_data = | ||||
| @@ -92,8 +92,8 @@ auto curl_comm::construct_url(CURL *curl, const std::string &relative_path, | ||||
|                             relative_path, url); | ||||
| } | ||||
|  | ||||
| auto curl_comm::create_host_config(const s3_config &cfg, bool use_s3_path_style) | ||||
|     -> host_config { | ||||
| auto curl_comm::create_host_config(const s3_config &cfg, | ||||
|                                    bool use_s3_path_style) -> host_config { | ||||
|   host_config host_cfg{}; | ||||
|   host_cfg.api_password = cfg.secret_key; | ||||
|   host_cfg.api_user = cfg.access_key; | ||||
|   | ||||
| @@ -21,7 +21,7 @@ | ||||
| */ | ||||
| #include "comm/curl/requests/http_put_file.hpp" | ||||
|  | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/string.hpp" | ||||
|  | ||||
| namespace repertory::curl::requests { | ||||
| auto http_put_file::set_method(CURL *curl, stop_type &stop_requested) const | ||||
|   | ||||
| @@ -23,6 +23,7 @@ | ||||
|  | ||||
| #include "events/events.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/collection.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/timeout.hpp" | ||||
| #include "version.hpp" | ||||
| @@ -102,7 +103,7 @@ auto packet_client::get_client() -> std::shared_ptr<packet_client::client> { | ||||
|       connect(*ret); | ||||
|     } else { | ||||
|       ret = clients_[0U]; | ||||
|       utils::remove_element_from(clients_, ret); | ||||
|       utils::collection::remove_element(clients_, ret); | ||||
|       clients_lock.unlock(); | ||||
|     } | ||||
|   } | ||||
|   | ||||
| @@ -26,7 +26,7 @@ | ||||
| #include "events/events.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/string.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
|   | ||||
| @@ -23,6 +23,7 @@ | ||||
|  | ||||
| #include "drives/directory_iterator.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/collection.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| @@ -72,7 +73,7 @@ void directory_cache::remove_directory(std::uint64_t handle) { | ||||
|                                             handle) != kv.second.handles.end(); | ||||
|                          }); | ||||
|   if (it != directory_lookup_.end()) { | ||||
|     utils::remove_element_from(it->second.handles, handle); | ||||
|     utils::collection::remove_element(it->second.handles, handle); | ||||
|     if (it->second.handles.empty()) { | ||||
|       directory_lookup_.erase(it); | ||||
|     } | ||||
|   | ||||
| @@ -22,7 +22,7 @@ | ||||
| #include "drives/directory_iterator.hpp" | ||||
|  | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| #if !defined(_WIN32) | ||||
|   | ||||
| @@ -29,9 +29,10 @@ | ||||
| #include "events/events.hpp" | ||||
| #include "initialize.hpp" | ||||
| #include "providers/i_provider.hpp" | ||||
| #include "utils/collection.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/string.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| @@ -615,7 +616,7 @@ auto fuse_base::parse_args(std::vector<std::string> &args) -> int { | ||||
|       force_no_console = true; | ||||
|     } | ||||
|   } | ||||
|   utils::remove_element_from(args, "-nc"); | ||||
|   utils::collection::remove_element(args, "-nc"); | ||||
|  | ||||
|   for (std::size_t i = 1u; i < args.size(); i++) { | ||||
|     if (args[i] == "-f") { | ||||
|   | ||||
| @@ -39,6 +39,7 @@ | ||||
| #include "types/repertory.hpp" | ||||
| #include "types/startup_exception.hpp" | ||||
| #include "utils/base64.hpp" | ||||
| #include "utils/collection.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/polling.hpp" | ||||
| @@ -905,7 +906,7 @@ auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size, | ||||
|   api_meta_map meta; | ||||
|   if ((res = provider_.get_item_meta(api_path, meta)) == api_error::success) { | ||||
|     for (const auto &meta_item : meta) { | ||||
|       if (utils::collection_excludes(META_USED_NAMES, meta_item.first)) { | ||||
|       if (utils::collection::excludes(META_USED_NAMES, meta_item.first)) { | ||||
|         auto attribute_name = meta_item.first; | ||||
| #if defined(__APPLE__) | ||||
|         if (attribute_name != G_KAUTH_FILESEC_XATTR) { | ||||
| @@ -948,7 +949,7 @@ auto fuse_drive::removexattr_impl(std::string api_path, | ||||
|   return check_and_perform( | ||||
|       api_path, X_OK, [&](api_meta_map &meta) -> api_error { | ||||
|         if ((meta.find(name) != meta.end()) && | ||||
|             (utils::collection_excludes(META_USED_NAMES, name))) { | ||||
|             (utils::collection::excludes(META_USED_NAMES, name))) { | ||||
|           return provider_.remove_item_meta(api_path, attribute_name); | ||||
|         } | ||||
|  | ||||
| @@ -988,8 +989,8 @@ auto fuse_drive::setxattr_impl(std::string api_path, const char *name, | ||||
|   if (utils::string::contains(attribute_name, " .") || | ||||
|       utils::string::contains(attribute_name, ". ") | ||||
| #if !defined(__APPLE__) | ||||
|       || utils::collection_excludes(utils::attribute_namespaces, | ||||
|                                     attribute_namespace) | ||||
|       || utils::collection::excludes(utils::attribute_namespaces, | ||||
|                                      attribute_namespace) | ||||
| #endif | ||||
|   ) { | ||||
|     return api_error::not_supported; | ||||
|   | ||||
| @@ -23,7 +23,7 @@ | ||||
|  | ||||
| #include "app_config.hpp" | ||||
| #include "comm/packet/packet.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
|  | ||||
| namespace repertory::remote_fuse { | ||||
| remote_client::remote_client(const app_config &config) | ||||
|   | ||||
| @@ -34,7 +34,7 @@ | ||||
| #include "types/remote.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory::remote_fuse { | ||||
|   | ||||
| @@ -38,7 +38,7 @@ | ||||
| #include "utils/base64.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
|  | ||||
| namespace repertory::remote_fuse { | ||||
| #define RAISE_REMOTE_FUSE_SERVER_EVENT(func, file, ret)                        \ | ||||
|   | ||||
| @@ -23,6 +23,7 @@ | ||||
|  | ||||
| #include "events/event_system.hpp" | ||||
| #include "events/events.hpp" | ||||
| #include "utils/collection.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| @@ -30,7 +31,7 @@ void remote_open_file_table::add_directory(const std::string &client_id, | ||||
|                                            std::uint64_t handle) { | ||||
|   recur_mutex_lock directory_lock(directory_mutex_); | ||||
|   auto &list = directory_lookup_[client_id]; | ||||
|   if (utils::collection_excludes(list, handle)) { | ||||
|   if (utils::collection::excludes(list, handle)) { | ||||
|     directory_lookup_[client_id].emplace_back(handle); | ||||
|   } | ||||
| } | ||||
| @@ -144,7 +145,7 @@ auto remote_open_file_table::has_open_directory(const std::string &client_id, | ||||
|                                                 std::uint64_t handle) -> bool { | ||||
|   recur_mutex_lock directory_lock(directory_mutex_); | ||||
|   auto &list = directory_lookup_[client_id]; | ||||
|   return (utils::collection_includes(list, handle)); | ||||
|   return (utils::collection::includes(list, handle)); | ||||
| } | ||||
|  | ||||
| auto remote_open_file_table::has_compat_open_info( | ||||
| @@ -207,8 +208,8 @@ auto remote_open_file_table::remove_directory(const std::string &client_id, | ||||
|                                               std::uint64_t handle) -> bool { | ||||
|   recur_mutex_lock directory_lock(directory_mutex_); | ||||
|   auto &list = directory_lookup_[client_id]; | ||||
|   if (utils::collection_includes(list, handle)) { | ||||
|     utils::remove_element_from(list, handle); | ||||
|   if (utils::collection::includes(list, handle)) { | ||||
|     utils::collection::remove_element(list, handle); | ||||
|     if (directory_lookup_[client_id].empty()) { | ||||
|       directory_lookup_.erase(client_id); | ||||
|     } | ||||
|   | ||||
| @@ -26,7 +26,7 @@ | ||||
| #include "events/event_system.hpp" | ||||
| #include "events/events.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "version.hpp" | ||||
|  | ||||
| namespace repertory::remote_winfsp { | ||||
|   | ||||
| @@ -37,7 +37,7 @@ | ||||
| #include "types/remote.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
|  | ||||
| #if !defined(_SH_DENYNO) | ||||
| #define _SH_DENYRW 0x10 // deny read/write mode | ||||
|   | ||||
| @@ -29,9 +29,10 @@ | ||||
| #include "events/events.hpp" | ||||
| #include "platform/platform.hpp" | ||||
| #include "rpc/server/server.hpp" | ||||
| #include "utils/collection.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory::remote_winfsp { | ||||
| @@ -232,7 +233,7 @@ auto remote_winfsp_drive::mount(const std::vector<std::string> &drive_args) | ||||
|     -> int { | ||||
|   std::vector<std::string> parsed_drive_args; | ||||
|  | ||||
|   const auto force_no_console = utils::collection_includes(drive_args, "-nc"); | ||||
|   const auto force_no_console = utils::collection::includes(drive_args, "-nc"); | ||||
|  | ||||
|   auto enable_console = false; | ||||
|   for (const auto &arg : drive_args) { | ||||
|   | ||||
| @@ -32,10 +32,11 @@ | ||||
| #include "providers/i_provider.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "types/startup_exception.hpp" | ||||
| #include "utils/collection.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/polling.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/string.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| @@ -560,7 +561,7 @@ auto winfsp_drive::Init(PVOID host) -> NTSTATUS { | ||||
| auto winfsp_drive::mount(const std::vector<std::string> &drive_args) -> int { | ||||
|   std::vector<std::string> parsed_drive_args; | ||||
|  | ||||
|   const auto force_no_console = utils::collection_includes(drive_args, "-nc"); | ||||
|   const auto force_no_console = utils::collection::includes(drive_args, "-nc"); | ||||
|  | ||||
|   auto enable_console = false; | ||||
|   for (const auto &arg : drive_args) { | ||||
|   | ||||
| @@ -25,7 +25,7 @@ | ||||
| #include "spdlog/async.h" | ||||
| #include "spdlog/sinks/rotating_file_sink.h" | ||||
| #include "spdlog/spdlog.h" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| logging_consumer::logging_consumer(event_level level, | ||||
|   | ||||
| @@ -21,7 +21,7 @@ | ||||
| */ | ||||
| #include "events/event.hpp" | ||||
|  | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/string.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| auto event_level_from_string(std::string level) -> event_level { | ||||
|   | ||||
| @@ -32,13 +32,13 @@ | ||||
| #include "utils/encrypting_reader.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/polling.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace { | ||||
| [[nodiscard]] auto create_resume_entry(const repertory::i_open_file &file) | ||||
|     -> json { | ||||
| [[nodiscard]] auto | ||||
| create_resume_entry(const repertory::i_open_file &file) -> json { | ||||
|   return { | ||||
|       {"chunk_size", file.get_chunk_size()}, | ||||
|       {"path", file.get_api_path()}, | ||||
| @@ -439,11 +439,10 @@ auto file_manager::open(const std::string &api_path, bool directory, | ||||
|   return open(api_path, directory, ofd, handle, file, nullptr); | ||||
| } | ||||
|  | ||||
| auto file_manager::open(const std::string &api_path, bool directory, | ||||
|                         const open_file_data &ofd, std::uint64_t &handle, | ||||
|                         std::shared_ptr<i_open_file> &file, | ||||
|                         std::shared_ptr<i_closeable_open_file> closeable_file) | ||||
|     -> api_error { | ||||
| auto file_manager::open( | ||||
|     const std::string &api_path, bool directory, const open_file_data &ofd, | ||||
|     std::uint64_t &handle, std::shared_ptr<i_open_file> &file, | ||||
|     std::shared_ptr<i_closeable_open_file> closeable_file) -> api_error { | ||||
|   const auto create_and_add_handle = | ||||
|       [&](std::shared_ptr<i_closeable_open_file> cur_file) { | ||||
|         handle = get_next_handle(); | ||||
| @@ -696,8 +695,8 @@ auto file_manager::rename_directory(const std::string &from_api_path, | ||||
| } | ||||
|  | ||||
| auto file_manager::rename_file(const std::string &from_api_path, | ||||
|                                const std::string &to_api_path, bool overwrite) | ||||
|     -> api_error { | ||||
|                                const std::string &to_api_path, | ||||
|                                bool overwrite) -> api_error { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   if (not provider_.is_rename_supported()) { | ||||
|   | ||||
| @@ -27,7 +27,7 @@ | ||||
| #include "types/startup_exception.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/unix/unix_utils.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,7 @@ | ||||
| */ | ||||
| #include "file_manager/file_manager.hpp" | ||||
|  | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| file_manager::open_file_base::open_file_base(std::uint64_t chunk_size, | ||||
|   | ||||
| @@ -27,7 +27,7 @@ | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/encrypting_reader.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/unix/unix_utils.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
|   | ||||
| @@ -28,7 +28,7 @@ | ||||
| #include "types/startup_exception.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/unix/unix_utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
|   | ||||
| @@ -29,7 +29,7 @@ | ||||
| #include "events/events.hpp" | ||||
| #include "file_manager/i_file_manager.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/polling.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
|   | ||||
| @@ -29,7 +29,7 @@ | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/encrypting_reader.hpp" | ||||
| #include "utils/encrypt.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/polling.hpp" | ||||
|  | ||||
| namespace { | ||||
|   | ||||
| @@ -26,8 +26,8 @@ | ||||
| #include "database/db_insert.hpp" | ||||
| #include "database/db_select.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/string.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| meta_db::meta_db(const app_config &cfg) { | ||||
| @@ -101,8 +101,8 @@ auto meta_db::get_api_path_list() -> std::vector<std::string> { | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto meta_db::get_item_meta(const std::string &api_path, api_meta_map &meta) | ||||
|     -> api_error { | ||||
| auto meta_db::get_item_meta(const std::string &api_path, | ||||
|                             api_meta_map &meta) -> api_error { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   auto result = db::db_select{*db_, table_name} | ||||
| @@ -283,8 +283,8 @@ auto meta_db::set_item_meta(const std::string &api_path, | ||||
|   return update_item_meta(api_path, existing_meta); | ||||
| } | ||||
|  | ||||
| auto meta_db::update_item_meta(const std::string &api_path, api_meta_map meta) | ||||
|     -> api_error { | ||||
| auto meta_db::update_item_meta(const std::string &api_path, | ||||
|                                api_meta_map meta) -> api_error { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   auto directory = utils::string::to_bool(meta[META_DIRECTORY]); | ||||
|   | ||||
| @@ -32,9 +32,9 @@ | ||||
| #include "utils/encrypting_reader.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/polling.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/string.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| s3_provider::s3_provider(app_config &config, i_http_comm &comm) | ||||
|   | ||||
| @@ -29,9 +29,9 @@ | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/polling.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/string.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
|   | ||||
| @@ -28,7 +28,7 @@ | ||||
| #include "types/repertory.hpp" | ||||
| #include "types/rpc.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| full_server::full_server(app_config &config, i_provider &provider, | ||||
|   | ||||
| @@ -22,8 +22,40 @@ | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| #include "types/startup_exception.hpp" | ||||
| #include "utils/string.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| auto download_type_from_string( | ||||
|     std::string type, const download_type &default_type) -> download_type { | ||||
|   type = utils::string::to_lower(utils::string::trim(type)); | ||||
|   if (type == "direct") { | ||||
|     return download_type::direct; | ||||
|   } | ||||
|  | ||||
|   if (type == "fallback") { | ||||
|     return download_type::fallback; | ||||
|   } | ||||
|  | ||||
|   if (type == "ring_buffer") { | ||||
|     return download_type::ring_buffer; | ||||
|   } | ||||
|  | ||||
|   return default_type; | ||||
| } | ||||
|  | ||||
| auto download_type_to_string(const download_type &type) -> std::string { | ||||
|   switch (type) { | ||||
|   case download_type::direct: | ||||
|     return "direct"; | ||||
|   case download_type::fallback: | ||||
|     return "fallback"; | ||||
|   case download_type::ring_buffer: | ||||
|     return "ring_buffer"; | ||||
|   default: | ||||
|     return "fallback"; | ||||
|   } | ||||
| } | ||||
|  | ||||
| static const std::unordered_map<api_error, std::string> LOOKUP = { | ||||
|     {api_error::success, "success"}, | ||||
|     {api_error::access_denied, "access_denied"}, | ||||
|   | ||||
| @@ -22,9 +22,10 @@ | ||||
| #include "utils/cli_utils.hpp" | ||||
|  | ||||
| #include "app_config.hpp" | ||||
| #include "utils/collection.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/string.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory::utils::cli { | ||||
| @@ -187,14 +188,16 @@ auto parse_drive_options( | ||||
|       if (new_drive_args[i].find("-o") == 0) { | ||||
|         if (new_drive_args[i].size() == 2) { | ||||
|           if ((i + 1) < drive_args.size()) { | ||||
|             utils::remove_element_from(new_drive_args, new_drive_args[i]); | ||||
|             utils::remove_element_from(new_drive_args, new_drive_args[i]); | ||||
|             utils::collection::remove_element(new_drive_args, | ||||
|                                               new_drive_args[i]); | ||||
|             utils::collection::remove_element(new_drive_args, | ||||
|                                               new_drive_args[i]); | ||||
|             i--; | ||||
|           } | ||||
|           continue; | ||||
|         } | ||||
|  | ||||
|         utils::remove_element_from(new_drive_args, new_drive_args[i]); | ||||
|         utils::collection::remove_element(new_drive_args, new_drive_args[i]); | ||||
|         i--; | ||||
|         continue; | ||||
|       } | ||||
|   | ||||
| @@ -65,30 +65,6 @@ auto decrypt_file_name(std::string_view encryption_token, | ||||
|   return api_error::success; | ||||
| } | ||||
|  | ||||
| auto generate_key(std::string_view encryption_token) -> key_type { | ||||
|   crypto_hash_sha256_state state{}; | ||||
|   auto res = crypto_hash_sha256_init(&state); | ||||
|   if (res != 0) { | ||||
|     throw std::runtime_error("failed to initialize sha256|" + | ||||
|                              std::to_string(res)); | ||||
|   } | ||||
|   res = crypto_hash_sha256_update( | ||||
|       &state, reinterpret_cast<const unsigned char *>(encryption_token.data()), | ||||
|       encryption_token.size()); | ||||
|   if (res != 0) { | ||||
|     throw std::runtime_error("failed to update sha256|" + std::to_string(res)); | ||||
|   } | ||||
|  | ||||
|   key_type ret{}; | ||||
|   res = crypto_hash_sha256_final(&state, ret.data()); | ||||
|   if (res != 0) { | ||||
|     throw std::runtime_error("failed to finalize sha256|" + | ||||
|                              std::to_string(res)); | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto read_encrypted_range(const http_range &range, const key_type &key, | ||||
|                           reader_func reader, std::uint64_t total_size, | ||||
|                           data_buffer &data) -> api_error { | ||||
|   | ||||
| @@ -23,8 +23,8 @@ | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/string.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory::utils::file { | ||||
| @@ -483,51 +483,6 @@ auto get_modified_time(const std::string &path, | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto get_file_size(std::string_view path, std::uint64_t &file_size) -> bool { | ||||
|   file_size = 0U; | ||||
|   auto abs_path = utils::path::absolute(std::string{path}); | ||||
|  | ||||
| #if defined(_WIN32) | ||||
|   struct _stat64 st {}; | ||||
|   if (_stat64(abs_path.c_str(), &st) != 0) { | ||||
| #else | ||||
| #if defined(__APPLE__) | ||||
|   struct stat st {}; | ||||
|   if (stat(abs_path.c_str(), &st) != 0) { | ||||
| #else | ||||
|   struct stat64 st {}; | ||||
|   if (stat64(abs_path.c_str(), &st) != 0) { | ||||
| #endif | ||||
| #endif | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   if (st.st_size >= 0) { | ||||
|     file_size = static_cast<std::uint64_t>(st.st_size); | ||||
|   } | ||||
|  | ||||
|   return (st.st_size >= 0); | ||||
| } | ||||
|  | ||||
| auto is_directory(const std::string &path) -> bool { | ||||
| #if defined(_WIN32) | ||||
|   return ::PathIsDirectory(path.c_str()) != 0; | ||||
| #else | ||||
|   struct stat st {}; | ||||
|   return (not stat(path.c_str(), &st) && S_ISDIR(st.st_mode)); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| auto is_file(const std::string &path) -> bool { | ||||
| #if defined(_WIN32) | ||||
|   return (::PathFileExists(path.c_str()) && | ||||
|           not ::PathIsDirectory(path.c_str())); | ||||
| #else | ||||
|   struct stat st {}; | ||||
|   return (not stat(path.c_str(), &st) && not S_ISDIR(st.st_mode)); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| auto is_modified_date_older_than(const std::string &path, | ||||
|                                  const std::chrono::hours &hours) -> bool { | ||||
|   auto ret = false; | ||||
| @@ -580,40 +535,6 @@ auto read_file_lines(const std::string &path) -> std::vector<std::string> { | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto read_json_file(const std::string &path, json &data) -> bool { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   if (not utils::file::is_file(path)) { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   try { | ||||
|     std::ifstream file_stream(path.c_str()); | ||||
|     if (file_stream.is_open()) { | ||||
|       try { | ||||
|         std::stringstream ss; | ||||
|         ss << file_stream.rdbuf(); | ||||
|  | ||||
|         std::string json_text = ss.str(); | ||||
|         if (not json_text.empty()) { | ||||
|           data = json::parse(json_text.c_str()); | ||||
|         } | ||||
|  | ||||
|         file_stream.close(); | ||||
|         return true; | ||||
|       } catch (const std::exception &e) { | ||||
|         file_stream.close(); | ||||
|         throw e; | ||||
|       } | ||||
|     } | ||||
|   } catch (const std::exception &e) { | ||||
|     utils::error::raise_error(function_name, e, path, | ||||
|                               "failed to read json file"); | ||||
|   } | ||||
|  | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| auto reset_modified_time(const std::string &path) -> bool { | ||||
|   auto ret = false; | ||||
| #if defined(_WIN32) | ||||
| @@ -660,24 +581,4 @@ auto retry_delete_file(const std::string &file) -> bool { | ||||
|  | ||||
|   return deleted; | ||||
| } | ||||
|  | ||||
| auto write_json_file(const std::string &path, const json &j) -> bool { | ||||
|   std::string data; | ||||
|   { | ||||
|     std::stringstream ss; | ||||
|     ss << std::setw(2) << j; | ||||
|     data = ss.str(); | ||||
|   } | ||||
|   native_file_ptr nf; | ||||
|   auto ret = (native_file::create_or_open(path, nf) == api_error::success); | ||||
|   if (ret) { | ||||
|     std::size_t bytes_written{0U}; | ||||
|     ret = nf->truncate(0) && | ||||
|           nf->write_bytes(reinterpret_cast<const unsigned char *>(data.data()), | ||||
|                           data.size(), 0U, bytes_written); | ||||
|     nf->close(); | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
| } // namespace repertory::utils::file | ||||
|   | ||||
| @@ -22,7 +22,7 @@ | ||||
| #include "utils/native_file.hpp" | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/string.hpp" | ||||
| #include "utils/unix/unix_utils.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
|   | ||||
| @@ -1,204 +0,0 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   in the Software without restriction, including without limitation the rights | ||||
|   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|   copies of the Software, and to permit persons to whom the Software is | ||||
|   furnished to do so, subject to the following conditions: | ||||
|  | ||||
|   The above copyright notice and this permission notice shall be included in all | ||||
|   copies or substantial portions of the Software. | ||||
|  | ||||
|   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|   SOFTWARE. | ||||
| */ | ||||
| #include "utils/path_utils.hpp" | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory::utils::path { | ||||
| auto absolute(std::string path) -> std::string { | ||||
|   path = finalize(path); | ||||
|  | ||||
| #if defined(_WIN32) | ||||
|   if (not path.empty() && ::PathIsRelative(path.c_str())) { | ||||
|     std::string temp; | ||||
|     temp.resize(MAX_PATH + 1); | ||||
|     path = _fullpath(temp.data(), path.c_str(), MAX_PATH); | ||||
|   } | ||||
| #else | ||||
|   if (not path.empty() && (path[0U] != '/')) { | ||||
|     auto found = false; | ||||
|     auto tmp = path; | ||||
|     do { | ||||
|       auto *res = realpath(&tmp[0U], nullptr); | ||||
|       if (res) { | ||||
|         path = combine(res, {path.substr(tmp.size())}); | ||||
|         free(res); | ||||
|         found = true; | ||||
|       } else if (tmp == ".") { | ||||
|         found = true; | ||||
|       } else { | ||||
|         tmp = dirname(&tmp[0U]); | ||||
|       } | ||||
|     } while (not found); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   return path; | ||||
| } | ||||
|  | ||||
| auto combine(std::string path, | ||||
|              const std::vector<std::string> &paths) -> std::string { | ||||
|   return absolute( | ||||
|       std::accumulate(paths.begin(), paths.end(), path, | ||||
|                       [](std::string next_path, const auto &path_part) { | ||||
|                         if (next_path.empty()) { | ||||
|                           return path_part; | ||||
|                         } | ||||
|                         return next_path + (directory_seperator + path_part); | ||||
|                       })); | ||||
| } | ||||
|  | ||||
| auto create_api_path(std::string path) -> std::string { | ||||
|   if (path.empty() || (path == ".") || (path == "/")) { | ||||
|     return "/"; | ||||
|   } | ||||
|  | ||||
|   format_path(path, "/", "\\"); | ||||
|   if (path.find("./") == 0) { | ||||
|     path = path.substr(1); | ||||
|   } | ||||
|  | ||||
|   if (path[0U] != '/') { | ||||
|     path = "/" + path; | ||||
|   } | ||||
|  | ||||
|   if ((path != "/") && utils::string::ends_with(path, "/")) { | ||||
|     utils::string::right_trim(path, '/'); | ||||
|   } | ||||
|  | ||||
|   return path; | ||||
| } | ||||
|  | ||||
| auto finalize(std::string path) -> std::string { | ||||
|   format_path(path, not_directory_seperator, directory_seperator); | ||||
|   format_path(path, directory_seperator, not_directory_seperator); | ||||
|   if ((path.size() > 1U) && | ||||
|       (path[path.size() - 1U] == directory_seperator[0U])) { | ||||
|     path = path.substr(0U, path.size() - 1U); | ||||
|   } | ||||
|  | ||||
| #if defined(_WIN32) | ||||
|   if ((path.size() >= 2u) && (path[1U] == ':')) { | ||||
|     path[0U] = utils::string::to_lower(std::string(1U, path[0U]))[0U]; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   return path; | ||||
| } | ||||
|  | ||||
| auto format_path(std::string &path, const std::string &sep, | ||||
|                  const std::string ¬_sep) -> std::string & { | ||||
|   std::replace(path.begin(), path.end(), not_sep[0U], sep[0U]); | ||||
|  | ||||
|   while (utils::string::contains(path, sep + sep)) { | ||||
|     utils::string::replace(path, sep + sep, sep); | ||||
|   } | ||||
|  | ||||
|   return path; | ||||
| } | ||||
|  | ||||
| auto get_parent_api_path(const std::string &path) -> std::string { | ||||
|   std::string ret; | ||||
|   if (path != "/") { | ||||
|     ret = path.substr(0, path.rfind('/') + 1); | ||||
|     if (ret != "/") { | ||||
|       ret = utils::string::right_trim(ret, '/'); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| #if !defined(_WIN32) | ||||
| auto get_parent_directory(std::string path) -> std::string { | ||||
|   auto ret = std::string(dirname(&path[0U])); | ||||
|   if (ret == ".") { | ||||
|     ret = "/"; | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| auto is_ads_file_path([[maybe_unused]] const std::string &path) -> bool { | ||||
| #if defined(_WIN32) | ||||
|   return utils::string::contains(path, ":"); | ||||
| #else | ||||
|   return false; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| auto is_trash_directory(std::string path) -> bool { | ||||
|   path = create_api_path(utils::string::to_lower(path)); | ||||
|   if (utils::string::begins_with(path, "/.trash-") || | ||||
|       utils::string::begins_with(path, "/.trashes") || | ||||
|       utils::string::begins_with(path, "/$recycle.bin")) { | ||||
|     return true; | ||||
|   } | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| auto remove_file_name(std::string path) -> std::string { | ||||
|   path = absolute(path); | ||||
|  | ||||
| #if defined(_WIN32) | ||||
|   ::PathRemoveFileSpec(&path[0U]); | ||||
|   path = path.c_str(); | ||||
| #else | ||||
|   if (path != "/") { | ||||
|     auto i = path.size() - 1; | ||||
|     while ((i != 0) && (path[i] != '/')) { | ||||
|       i--; | ||||
|     } | ||||
|  | ||||
|     path = (i > 0) ? absolute(path.substr(0, i)) : "/"; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   return path; | ||||
| } | ||||
|  | ||||
| #if !defined(_WIN32) | ||||
| auto resolve(std::string path) -> std::string { | ||||
|   std::string home{}; | ||||
|   use_getpwuid(getuid(), [&home](struct passwd *pw) { | ||||
|     home = (pw->pw_dir ? pw->pw_dir : ""); | ||||
|     if (home.empty() || ((home == "/") && (getuid() != 0))) { | ||||
|       home = combine("/home", {pw->pw_name}); | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   return absolute(utils::string::replace(path, "~", home)); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| auto strip_to_file_name(std::string path) -> std::string { | ||||
| #if defined(_WIN32) | ||||
|   return ::PathFindFileName(path.c_str()); | ||||
| #else | ||||
|   return utils::string::contains(path, "/") ? basename(&path[0U]) : path; | ||||
| #endif | ||||
| } | ||||
| } // namespace repertory::utils::path | ||||
| @@ -1,230 +0,0 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   in the Software without restriction, including without limitation the rights | ||||
|   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|   copies of the Software, and to permit persons to whom the Software is | ||||
|   furnished to do so, subject to the following conditions: | ||||
|  | ||||
|   The above copyright notice and this permission notice shall be included in all | ||||
|   copies or substantial portions of the Software. | ||||
|  | ||||
|   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|   SOFTWARE. | ||||
| */ | ||||
| #include "utils/string_utils.hpp" | ||||
|  | ||||
| namespace repertory::utils::string { | ||||
| /* constexpr c++20 */ auto ends_with(std::string_view str, | ||||
|                                      std::string_view val) -> bool { | ||||
|   if (val.size() > str.size()) { | ||||
|     return false; | ||||
|   } | ||||
|   return std::equal(val.rbegin(), val.rend(), str.rbegin()); | ||||
| } | ||||
|  | ||||
| auto from_bool(bool val) -> std::string { | ||||
|   return std::to_string(static_cast<int>(val)); | ||||
| } | ||||
|  | ||||
| auto from_dynamic_bitset(const boost::dynamic_bitset<> &bitset) -> std::string { | ||||
|   std::stringstream stream; | ||||
|   boost::archive::text_oarchive archive(stream); | ||||
|   archive << bitset; | ||||
|   return stream.str(); | ||||
| } | ||||
|  | ||||
| auto from_utf8(std::string_view str) -> std::wstring { | ||||
|   return str.empty() | ||||
|              ? L"" | ||||
|              : std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>() | ||||
|                    .from_bytes(std::string{str}); | ||||
| } | ||||
|  | ||||
| /* constexpr c++20 */ auto is_numeric(std::string_view str) -> bool { | ||||
|   if ((str.length() > 1U) && (str[0U] == '+' || str[0U] == '-')) { | ||||
|     str = str.substr(1U); | ||||
|   } | ||||
|  | ||||
|   if (str.empty()) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   auto has_decimal = false; | ||||
|   return std::find_if(str.begin(), str.end(), | ||||
|                       [&has_decimal]( | ||||
|                           const std::string_view::value_type &cur_ch) -> bool { | ||||
|                         if (has_decimal && cur_ch == '.') { | ||||
|                           return true; | ||||
|                         } | ||||
|                         has_decimal = has_decimal || cur_ch == '.'; | ||||
|                         if (has_decimal) { | ||||
|                           return false; | ||||
|                         } | ||||
|                         return std::isdigit(cur_ch) == 0; | ||||
|                       }) == str.end(); | ||||
| } | ||||
|  | ||||
| auto join(const std::vector<std::string> &arr, | ||||
|           const char &delim) -> std::string { | ||||
|   if (arr.empty()) { | ||||
|     return ""; | ||||
|   } | ||||
|  | ||||
|   return std::accumulate( | ||||
|       std::next(arr.begin()), arr.end(), arr[0U], | ||||
|       [&delim](auto str, const auto &cur) { return str + delim + cur; }); | ||||
| } | ||||
|  | ||||
| auto left_trim(std::string &str) -> std::string & { | ||||
|   return left_trim(str, ' '); | ||||
| } | ||||
|  | ||||
| auto left_trim(std::string &str, const char &trim_ch) -> std::string & { | ||||
|   str.erase(0, str.find_first_not_of(trim_ch)); | ||||
|   return str; | ||||
| } | ||||
|  | ||||
| auto replace(std::string &src, const char &character, | ||||
|              const char &with) -> std::string & { | ||||
|   std::replace(src.begin(), src.end(), character, with); | ||||
|   return src; | ||||
| } | ||||
|  | ||||
| auto replace(std::string &src, const std::string &find, const std::string &with, | ||||
|              size_t start_pos) -> std::string & { | ||||
|   if (!src.empty() && (start_pos < src.size())) { | ||||
|     while ((start_pos = src.find(find, start_pos)) != std::string::npos) { | ||||
|       src.replace(start_pos, find.size(), with); | ||||
|       start_pos += with.size(); | ||||
|     } | ||||
|   } | ||||
|   return src; | ||||
| } | ||||
|  | ||||
| auto replace_copy(std::string src, const char &character, | ||||
|                   const char &with) -> std::string { | ||||
|   std::replace(src.begin(), src.end(), character, with); | ||||
|   return src; | ||||
| } | ||||
|  | ||||
| auto replace_copy(std::string src, const std::string &find, | ||||
|                   const std::string &with, size_t start_pos) -> std::string { | ||||
|   return replace(src, find, with, start_pos); | ||||
| } | ||||
|  | ||||
| auto right_trim(std::string &str) -> std::string & { | ||||
|   return right_trim(str, ' '); | ||||
| } | ||||
|  | ||||
| auto right_trim(std::string &str, const char &trim_ch) -> std::string & { | ||||
|   str.erase(str.find_last_not_of(trim_ch) + 1); | ||||
|   return str; | ||||
| } | ||||
|  | ||||
| auto split(const std::string &str, const char &delim, | ||||
|            bool should_trim) -> std::vector<std::string> { | ||||
|   std::vector<std::string> ret; | ||||
|   std::stringstream stream(str); | ||||
|   std::string item; | ||||
|   while (std::getline(stream, item, delim)) { | ||||
|     ret.push_back(should_trim ? trim(item) : item); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto to_bool(std::string val) -> bool { | ||||
|   auto ret = false; | ||||
|  | ||||
|   trim(val); | ||||
|   if (is_numeric(val)) { | ||||
|     if (contains(val, ".")) { | ||||
|       ret = (to_double(val) != 0.0); | ||||
|     } else { | ||||
|       std::istringstream(val) >> ret; | ||||
|     } | ||||
|   } else { | ||||
|     std::istringstream(to_lower(val)) >> std::boolalpha >> ret; | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto to_double(const std::string &str) -> double { return std::stod(str); } | ||||
|  | ||||
| auto to_dynamic_bitset(const std::string &val) -> boost::dynamic_bitset<> { | ||||
|   std::stringstream stream(val); | ||||
|   boost::dynamic_bitset<> bitset; | ||||
|   boost::archive::text_iarchive archive(stream); | ||||
|   archive >> bitset; | ||||
|   return bitset; | ||||
| } | ||||
|  | ||||
| auto to_int32(const std::string &val) -> std::int32_t { return std::stoi(val); } | ||||
|  | ||||
| auto to_int64(const std::string &val) -> std::int64_t { | ||||
|   return std::stoll(val); | ||||
| } | ||||
|  | ||||
| auto to_lower(std::string str) -> std::string { | ||||
|   std::transform(str.begin(), str.end(), str.begin(), ::tolower); | ||||
|   return str; | ||||
| } | ||||
|  | ||||
| auto to_size_t(const std::string &val) -> std::size_t { | ||||
|   return static_cast<std::size_t>(std::stoull(val)); | ||||
| } | ||||
|  | ||||
| auto to_uint8(const std::string &val) -> std::uint8_t { | ||||
|   return static_cast<std::uint8_t>(std::stoul(val)); | ||||
| } | ||||
|  | ||||
| auto to_uint16(const std::string &val) -> std::uint16_t { | ||||
|   return static_cast<std::uint16_t>(std::stoul(val)); | ||||
| } | ||||
|  | ||||
| auto to_uint32(const std::string &val) -> std::uint32_t { | ||||
|   return static_cast<std::uint32_t>(std::stoul(val)); | ||||
| } | ||||
|  | ||||
| auto to_uint64(const std::string &val) -> std::uint64_t { | ||||
|   return std::stoull(val); | ||||
| } | ||||
|  | ||||
| auto to_upper(std::string str) -> std::string { | ||||
|   std::transform(str.begin(), str.end(), str.begin(), ::toupper); | ||||
|   return str; | ||||
| } | ||||
|  | ||||
| auto to_utf8(std::string_view str) -> std::string { return std::string{str}; } | ||||
|  | ||||
| auto to_utf8(std::wstring_view str) -> std::string { | ||||
|   return str.empty() | ||||
|              ? "" | ||||
|              : std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>() | ||||
|                    .to_bytes(std::wstring{str}); | ||||
| } | ||||
|  | ||||
| auto trim(std::string &str) -> std::string & { | ||||
|   return right_trim(left_trim(str)); | ||||
| } | ||||
|  | ||||
| auto trim(std::string &str, const char &trim_ch) -> std::string & { | ||||
|   return right_trim(left_trim(str, trim_ch), trim_ch); | ||||
| } | ||||
|  | ||||
| auto trim_copy(std::string str) -> std::string { | ||||
|   return right_trim(left_trim(str)); | ||||
| } | ||||
|  | ||||
| auto trim_copy(std::string str, const char &trim_ch) -> std::string { | ||||
|   return right_trim(left_trim(str, trim_ch), trim_ch); | ||||
| } | ||||
| } // namespace repertory::utils::string | ||||
| @@ -24,15 +24,8 @@ | ||||
| #include "utils/unix/unix_utils.hpp" | ||||
|  | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory::utils { | ||||
| #if !defined(__APPLE__) | ||||
| auto convert_to_uint64(const pthread_t &thread) -> std::uint64_t { | ||||
|   return static_cast<std::uint64_t>(thread); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| auto from_api_error(const api_error &err) -> int { | ||||
|   switch (err) { | ||||
|   case api_error::access_denied: | ||||
| @@ -100,30 +93,6 @@ auto from_api_error(const api_error &err) -> int { | ||||
|   } | ||||
| } | ||||
|  | ||||
| auto get_last_error_code() -> int { return errno; } | ||||
|  | ||||
| auto get_thread_id() -> std::uint64_t { | ||||
|   return convert_to_uint64(pthread_self()); | ||||
| } | ||||
|  | ||||
| auto is_uid_member_of_group(const uid_t &uid, const gid_t &gid) -> bool { | ||||
|   std::vector<gid_t> groups{}; | ||||
|   use_getpwuid(uid, [&groups](struct passwd *pass) { | ||||
|     int group_count{}; | ||||
|     if (getgrouplist(pass->pw_name, pass->pw_gid, nullptr, &group_count) < 0) { | ||||
|       groups.resize(static_cast<std::size_t>(group_count)); | ||||
| #if defined(__APPLE__) | ||||
|       getgrouplist(pass->pw_name, pass->pw_gid, | ||||
|                    reinterpret_cast<int *>(groups.data()), &group_count); | ||||
| #else | ||||
|       getgrouplist(pass->pw_name, pass->pw_gid, groups.data(), &group_count); | ||||
| #endif | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   return collection_includes(groups, gid); | ||||
| } | ||||
|  | ||||
| auto to_api_error(int err) -> api_error { | ||||
|   switch (abs(err)) { | ||||
|   case 0: | ||||
| @@ -192,8 +161,6 @@ auto to_api_error(int err) -> api_error { | ||||
|   } | ||||
| } | ||||
|  | ||||
| void set_last_error_code(int error_code) { errno = error_code; } | ||||
|  | ||||
| auto unix_error_to_windows(int err) -> std::int32_t { | ||||
|   switch (err) { | ||||
|   case 0: | ||||
| @@ -238,21 +205,6 @@ auto unix_time_to_windows_time(const remote::file_time &file_time) -> UINT64 { | ||||
|   return (file_time / 100ULL) + 116444736000000000ULL; | ||||
| } | ||||
|  | ||||
| void use_getpwuid(uid_t uid, | ||||
|                   std::function<void(struct passwd *pass)> callback) { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   static std::mutex mtx{}; | ||||
|   mutex_lock lock{mtx}; | ||||
|   auto *temp_pw = getpwuid(uid); | ||||
|   if (temp_pw == nullptr) { | ||||
|     utils::error::raise_error(function_name, "'getpwuid' returned nullptr"); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   callback(temp_pw); | ||||
| } | ||||
|  | ||||
| void windows_create_to_unix(const UINT32 &create_options, | ||||
|                             const UINT32 &granted_access, std::uint32_t &flags, | ||||
|                             remote::file_mode &mode) { | ||||
|   | ||||
| @@ -27,9 +27,10 @@ | ||||
| #include "providers/i_provider.hpp" | ||||
| #include "types/startup_exception.hpp" | ||||
| #include "utils/com_init_wrapper.hpp" | ||||
| #include "utils/common.hpp" | ||||
| #include "utils/native_file.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/string.hpp" | ||||
|  | ||||
| namespace repertory::utils { | ||||
| void calculate_allocation_size(bool directory, std::uint64_t file_size, | ||||
| @@ -51,47 +52,6 @@ void calculate_allocation_size(bool directory, std::uint64_t file_size, | ||||
|   allocation_meta_size = std::to_string(allocation_size); | ||||
| } | ||||
|  | ||||
| auto calculate_read_size(const uint64_t &total_size, std::size_t read_size, | ||||
|                          const uint64_t &offset) -> std::size_t { | ||||
|   return static_cast<std::size_t>( | ||||
|       ((offset + read_size) > total_size) | ||||
|           ? ((offset < total_size) ? total_size - offset : 0U) | ||||
|           : read_size); | ||||
| } | ||||
|  | ||||
| auto compare_version_strings(std::string version1, | ||||
|                              std::string version2) -> int { | ||||
|   if (utils::string::contains(version1, "-")) { | ||||
|     version1 = utils::string::split(version1, '-')[0U]; | ||||
|   } | ||||
|  | ||||
|   if (utils::string::contains(version2, "-")) { | ||||
|     version2 = utils::string::split(version2, '-')[0U]; | ||||
|   } | ||||
|  | ||||
|   auto nums1 = utils::string::split(version1, '.'); | ||||
|   auto nums2 = utils::string::split(version2, '.'); | ||||
|  | ||||
|   while (nums1.size() > nums2.size()) { | ||||
|     nums2.emplace_back("0"); | ||||
|   } | ||||
|  | ||||
|   while (nums2.size() > nums1.size()) { | ||||
|     nums1.emplace_back("0"); | ||||
|   } | ||||
|  | ||||
|   for (std::size_t i = 0U; i < nums1.size(); i++) { | ||||
|     const auto int1 = utils::string::to_uint32(nums1[i]); | ||||
|     const auto int2 = utils::string::to_uint32(nums2[i]); | ||||
|     const auto res = std::memcmp(&int1, &int2, sizeof(int1)); | ||||
|     if (res != 0) { | ||||
|       return res; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| auto convert_api_date(const std::string &date) -> std::uint64_t { | ||||
|   // 2009-10-12T17:50:30.000Z | ||||
|   const auto date_parts = utils::string::split(date, '.'); | ||||
| @@ -118,165 +78,14 @@ auto create_curl() -> CURL * { | ||||
|   return reset_curl(curl_easy_init()); | ||||
| } | ||||
|  | ||||
| auto create_uuid_string() -> std::string { | ||||
|   std::random_device random_device; | ||||
|   auto seed_data = std::array<int, std::mt19937::state_size>{}; | ||||
|   std::generate(std::begin(seed_data), std::end(seed_data), | ||||
|                 std::ref(random_device)); | ||||
|   std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); | ||||
|   std::mt19937 generator(seq); | ||||
|   uuids::uuid_random_generator gen{generator}; | ||||
|  | ||||
|   return uuids::to_string(gen()); | ||||
| } | ||||
|  | ||||
| auto create_volume_label(const provider_type &prov) -> std::string { | ||||
|   return "repertory_" + app_config::get_provider_name(prov); | ||||
| } | ||||
|  | ||||
| auto download_type_from_string( | ||||
|     std::string type, const download_type &default_type) -> download_type { | ||||
|   type = utils::string::to_lower(utils::string::trim(type)); | ||||
|   if (type == "direct") { | ||||
|     return download_type::direct; | ||||
|   } | ||||
|  | ||||
|   if (type == "fallback") { | ||||
|     return download_type::fallback; | ||||
|   } | ||||
|  | ||||
|   if (type == "ring_buffer") { | ||||
|     return download_type::ring_buffer; | ||||
|   } | ||||
|  | ||||
|   return default_type; | ||||
| } | ||||
|  | ||||
| auto download_type_to_string(const download_type &type) -> std::string { | ||||
|   switch (type) { | ||||
|   case download_type::direct: | ||||
|     return "direct"; | ||||
|   case download_type::fallback: | ||||
|     return "fallback"; | ||||
|   case download_type::ring_buffer: | ||||
|     return "ring_buffer"; | ||||
|   default: | ||||
|     return "fallback"; | ||||
|   } | ||||
| } | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| // https://www.frenk.com/2009/12/convert-filetime-to-unix-timestamp/ | ||||
| auto filetime_to_unix_time(const FILETIME &ft) -> remote::file_time { | ||||
|   LARGE_INTEGER date{}; | ||||
|   date.HighPart = static_cast<LONG>(ft.dwHighDateTime); | ||||
|   date.LowPart = ft.dwLowDateTime; | ||||
|   date.QuadPart -= 116444736000000000LL; | ||||
|  | ||||
|   return static_cast<remote::file_time>(date.QuadPart) * 100ULL; | ||||
| } | ||||
|  | ||||
| void unix_time_to_filetime(const remote::file_time &ts, FILETIME &ft) { | ||||
|   const auto win_time = (ts / 100ULL) + 116444736000000000ULL; | ||||
|   ft.dwHighDateTime = static_cast<DWORD>(win_time >> 32U); | ||||
|   ft.dwLowDateTime = win_time & 0xFFFFFFFF; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| auto generate_random_string(std::uint16_t length) -> std::string { | ||||
|   std::string ret; | ||||
|   ret.resize(length); | ||||
|   for (std::uint16_t i = 0U; i < length; i++) { | ||||
|     do { | ||||
|       ret[i] = static_cast<char>(repertory_rand<std::uint8_t>() % 74 + 48); | ||||
|     } while (((ret[i] >= 91) && (ret[i] <= 96)) || | ||||
|              ((ret[i] >= 58) && (ret[i] <= 64))); | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto get_attributes_from_meta(const api_meta_map &meta) -> DWORD { | ||||
|   return static_cast<DWORD>(utils::string::to_uint32(meta.at(META_ATTRIBUTES))); | ||||
| } | ||||
|  | ||||
| auto get_environment_variable(const std::string &variable) -> std::string { | ||||
|   static std::mutex mtx{}; | ||||
|   mutex_lock lock{mtx}; | ||||
|  | ||||
|   const auto *val = std::getenv(variable.c_str()); | ||||
|   auto ret = std::string(val == nullptr ? "" : val); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto get_file_time_now() -> std::uint64_t { | ||||
| #if defined(_WIN32) | ||||
|   SYSTEMTIME st{}; | ||||
|   ::GetSystemTime(&st); | ||||
|   FILETIME ft{}; | ||||
|   ::SystemTimeToFileTime(&st, &ft); | ||||
|   return static_cast<std::uint64_t>( | ||||
|       (reinterpret_cast<LARGE_INTEGER *>(&ft))->QuadPart); | ||||
| #else | ||||
|   return get_time_now(); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void get_local_time_now(struct tm &local_time) { | ||||
|   memset(&local_time, 0, sizeof(local_time)); | ||||
|  | ||||
|   const auto now = | ||||
|       std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); | ||||
| #if defined(_WIN32) | ||||
|   localtime_s(&local_time, &now); | ||||
| #else | ||||
|   localtime_r(&now, &local_time); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| auto get_next_available_port(std::uint16_t first_port, | ||||
|                              std::uint16_t &available_port) -> bool { | ||||
|   using namespace boost::asio; | ||||
|   using ip::tcp; | ||||
|  | ||||
|   boost::system::error_code error_code{}; | ||||
|   while (first_port != 0U) { | ||||
|     io_service svc{}; | ||||
|     tcp::acceptor acceptor(svc); | ||||
|     acceptor.open(tcp::v4(), error_code) || | ||||
|         acceptor.bind({tcp::v4(), first_port}, error_code); | ||||
|     if (not error_code) { | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|     ++first_port; | ||||
|   } | ||||
|  | ||||
|   if (not error_code) { | ||||
|     available_port = first_port; | ||||
|   } | ||||
|  | ||||
|   return not error_code; | ||||
| } | ||||
|  | ||||
| auto get_time_now() -> std::uint64_t { | ||||
| #if defined(_WIN32) | ||||
|   return static_cast<std::uint64_t>( | ||||
|       std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())); | ||||
| #else | ||||
| #if defined(__APPLE__) | ||||
|   return std::chrono::nanoseconds( | ||||
|              std::chrono::system_clock::now().time_since_epoch()) | ||||
|       .count(); | ||||
| #else | ||||
|   return static_cast<std::uint64_t>( | ||||
|       std::chrono::nanoseconds( | ||||
|           std::chrono::high_resolution_clock::now().time_since_epoch()) | ||||
|           .count()); | ||||
| #endif | ||||
| #endif | ||||
| } | ||||
|  | ||||
| auto reset_curl(CURL *curl_handle) -> CURL * { | ||||
|   curl_easy_reset(curl_handle); | ||||
| #if defined(__APPLE__) | ||||
|   | ||||
| @@ -25,7 +25,7 @@ | ||||
|  | ||||
| #include "types/startup_exception.hpp" | ||||
| #include "utils/com_init_wrapper.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/string.hpp" | ||||
|  | ||||
| #if !defined(STATUS_DEVICE_INSUFFICIENT_RESOURCES) | ||||
| #define STATUS_DEVICE_INSUFFICIENT_RESOURCES static_cast<NTSTATUS>(0xC0000468L) | ||||
| @@ -232,10 +232,6 @@ auto unix_open_flags_to_flags_and_perms(const remote::file_mode & /*mode*/, | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto time64_to_unix_time(const __time64_t &t) -> remote::file_time { | ||||
|   return static_cast<remote::file_time>(t * NANOS_PER_SECOND); | ||||
| } | ||||
| } // namespace repertory::utils | ||||
|  | ||||
| #endif // _WIN32 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user