| 1 | #include "mtxclient/utils.hpp" |
|---|---|
| 2 | |
| 3 | #include <algorithm> |
| 4 | #include <cstdint> |
| 5 | #include <iomanip> |
| 6 | #include <random> |
| 7 | #include <sstream> |
| 8 | #include <string> |
| 9 | #include <utility> |
| 10 | |
| 11 | mtx::client::utils::MxcUrl |
| 12 | mtx::client::utils::parse_mxc_url(const std::string &url) |
| 13 | { |
| 14 | constexpr auto mxc_uri_protocol = "mxc://"; |
| 15 | MxcUrl res; |
| 16 | |
| 17 | if (url.find(s: mxc_uri_protocol) != 0) |
| 18 | return res; |
| 19 | |
| 20 | auto str_left = url.substr(pos: 6); |
| 21 | |
| 22 | std::vector<std::string> parts; |
| 23 | |
| 24 | size_t pos = 0; |
| 25 | while ((pos = str_left.find(c: '/')) != std::string_view::npos) { |
| 26 | parts.push_back(x: std::string(str_left.substr(pos: 0, n: pos))); |
| 27 | str_left = str_left.substr(pos: pos + 1); |
| 28 | } |
| 29 | parts.emplace_back(args&: str_left); |
| 30 | |
| 31 | if (parts.size() != 2) { |
| 32 | res.server = parts.at(n: 0); |
| 33 | return res; |
| 34 | } |
| 35 | |
| 36 | res.server = parts.at(n: 0); |
| 37 | res.media_id = parts.at(n: 1); |
| 38 | |
| 39 | return res; |
| 40 | } |
| 41 | |
| 42 | bool |
| 43 | mtx::client::utils::is_number(const std::string &s) |
| 44 | { |
| 45 | return !s.empty() && |
| 46 | std::find_if(first: s.begin(), last: s.end(), pred: [](char c) { return !std::isdigit(c); }) == s.end(); |
| 47 | } |
| 48 | |
| 49 | std::string |
| 50 | mtx::client::utils::random_token(uint8_t len, bool with_symbols) noexcept |
| 51 | { |
| 52 | std::string symbols = "!@#$%^&*()"; |
| 53 | std::string alphanumberic("abcdefghijklmnopqrstuvwxyz" |
| 54 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
| 55 | "1234567890"); |
| 56 | |
| 57 | const auto chars = with_symbols ? alphanumberic + symbols : alphanumberic; |
| 58 | |
| 59 | thread_local std::random_device rng; |
| 60 | std::uniform_int_distribution<> index_dist(0, (int)chars.size() - 1); |
| 61 | |
| 62 | std::string token; |
| 63 | token.reserve(res: len); |
| 64 | |
| 65 | for (uint8_t i = 0; i < len; ++i) |
| 66 | token.push_back(c: chars[index_dist(rng)]); |
| 67 | |
| 68 | return token; |
| 69 | } |
| 70 | |
| 71 | std::string |
| 72 | mtx::client::utils::query_params(const std::map<std::string, std::string> ¶ms) noexcept |
| 73 | { |
| 74 | if (params.empty()) |
| 75 | return ""; |
| 76 | |
| 77 | auto pb = params.cbegin(); |
| 78 | auto pe = params.cend(); |
| 79 | |
| 80 | std::string data = pb->first + "="+ url_encode(s: pb->second); |
| 81 | ++pb; |
| 82 | |
| 83 | if (pb == pe) |
| 84 | return data; |
| 85 | |
| 86 | for (; pb != pe; ++pb) |
| 87 | data += "&"+ pb->first + "="+ url_encode(s: pb->second); |
| 88 | |
| 89 | return data; |
| 90 | } |
| 91 | |
| 92 | std::string |
| 93 | mtx::client::utils::url_encode(const std::string &value) noexcept |
| 94 | { |
| 95 | // https: // stackoverflow.com/questions/154536/encode-decode-urls-in-c |
| 96 | std::ostringstream escaped; |
| 97 | escaped.fill(ch: '0'); |
| 98 | escaped << std::hex; |
| 99 | |
| 100 | for (char c : value) { |
| 101 | // Keep alphanumeric and other accepted characters intact |
| 102 | if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') { |
| 103 | escaped << c; |
| 104 | continue; |
| 105 | } |
| 106 | |
| 107 | // Any other characters are percent-encoded |
| 108 | escaped << std::uppercase; |
| 109 | escaped << '%' << std::setw(2) << int((unsigned char)c); |
| 110 | escaped << std::nouppercase; |
| 111 | } |
| 112 | |
| 113 | return escaped.str(); |
| 114 | } |
| 115 |