X Tutup
 #include "Utils.h" #include #include #include #include #include #include #include namespace Utils { void toLower(std::string &str, const std::locale &loc) { for (auto &c : str) { c = std::tolower(c, loc); } } void trim(std::string &str) { static const std::array whitespace { " \t\n\v\f\r" }; const size_t last = str.find_last_not_of(whitespace.data() ); if (std::string::npos == last) { return str.clear(); } str.assign(str.cbegin() + str.find_first_not_of(whitespace.data() ), str.cbegin() + last + 1); } std::vector explode(const std::string &str, const char sep) { std::vector values; for (size_t pos = 0; std::string::npos != pos;) { size_t delimiter = str.find(sep, pos); std::string value = str.substr(pos, delimiter); trim(value); values.emplace_back(std::move(value) ); pos = delimiter; if (std::string::npos != pos) { ++pos; } } return values; } std::string encodeHtmlSymbols(const std::string &str) { std::string buf; buf.reserve(str.length() ); for (size_t pos = 0; pos < str.length(); ++pos) { switch (str[pos]) { case '&': buf.append("&"); break; case '\"': buf.append("""); break; case '\'': buf.append("'"); break; case '<': buf.append("<"); break; case '>': buf.append(">"); break; default: buf.push_back(str[pos]); break; } } return buf; } std::string binToHexString(const void *binData, const size_t dataSize) { std::string str(dataSize * 2, 0); const uint8_t *bin = reinterpret_cast(binData); static const std::array hexDigits { "0123456789abcdef" }; for (size_t i = dataSize - 1; std::numeric_limits::max() != i; --i) { str[i * 2 + 0] = hexDigits[bin[i] >> 4]; str[i * 2 + 1] = hexDigits[bin[i] & 0x0F]; } return str; } static unsigned char hexStringToBinEncodeSymbol(const char c) { if (c >= '0' && c <= '9') { return c - 0x30; } else if (c >= 'a' && c <= 'f') { return c - 0x57; } else if (c >= 'A' && c <= 'F') { return c - 0x37; } return 0; } std::string hexStringToBin(const std::string &hexStr) { std::string bin(hexStr.length() / 2, 0); for (size_t i = 0; i < bin.length(); ++i) { const char a = hexStr[i * 2 + 0]; const char b = hexStr[i * 2 + 1]; bin[i] = ( (hexStringToBinEncodeSymbol(a) << 4) | hexStringToBinEncodeSymbol(b) ); } return bin; } unsigned long long htonll(const unsigned long long src) { enum Endianness { INIT = 0, LITE = 1, BIGE = 2 }; static int endian = Endianness::INIT; union { unsigned long long ull; unsigned char c[8]; } x; if (endian == Endianness::INIT) { x.ull = 0x01; endian = (x.c[7] == 0x01ULL) ? Endianness::BIGE : Endianness::LITE; } if (endian == Endianness::BIGE) { return src; } x.ull = src; unsigned char c; c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c; c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c; c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c; c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c; return x.ull; } std::string getUniqueName() { size_t time = std::chrono::high_resolution_clock::now().time_since_epoch().count(); time = htonll(time); return binToHexString(&time, sizeof(time) ); } char *stlStringToPChar(const std::string &str) { const size_t length = str.length(); char *s = nullptr; if (length) { s = new char[length + 1]; #ifdef WIN32 ::strcpy_s(s, length + 1, str.c_str() ); #elif POSIX ::strcpy(s, str.c_str() ); s[length] = '\0'; #else #error "Undefine platform" #endif } return s; } void filesIncomingToRawFilesInfo(Utils::raw_fileinfo *raw[], const std::unordered_multimap &map) { if (raw && map.size() ) { raw_fileinfo *arr = new raw_fileinfo[map.size()]; *raw = arr; size_t i = 0; for (auto it = map.cbegin(); map.cend() != it; ++it, ++i) { arr[i].key = stlStringToPChar(it->first); const HttpServer::FileIncoming &file = it->second; arr[i].file_name = stlStringToPChar(file.getName() ); arr[i].file_type = stlStringToPChar(file.getType() ); arr[i].file_size = file.getSize(); } } } void rawFilesInfoToFilesIncoming(std::unordered_multimap &map, const Utils::raw_fileinfo raw[], const size_t count) { for (size_t i = 0; i < count; ++i) { map.emplace(raw[i].key ? raw[i].key : "", HttpServer::FileIncoming(raw[i].file_name, raw[i].file_type, raw[i].file_size) ); } } void destroyRawPairs(Utils::raw_pair raw[], const size_t count) { if (raw) { for (size_t i = 0; i < count; ++i) { raw_pair &cur = raw[i]; delete[] cur.key; delete[] cur.value; } delete[] raw; } } void destroyRawFilesInfo(Utils::raw_fileinfo raw[], const size_t count) { if (raw) { for (size_t i = 0; i < count; ++i) { raw_fileinfo &cur = raw[i]; delete[] cur.key; delete[] cur.file_name; delete[] cur.file_type; } delete[] raw; } } time_t stringTimeToTimestamp(const std::string &strTime) { static const std::unordered_map map_months { {"Jan", 0}, {"Feb", 1}, {"Mar", 2}, {"Apr", 3}, {"May", 4}, {"Jun", 5}, {"Jul", 6}, {"Aug", 7}, {"Sep", 8}, {"Oct", 9}, {"Nov", 10}, {"Dec", 11} }; if (strTime.length() > 64) { return ~0; } const size_t str_mon_length = 64; std::vector s_mon(str_mon_length); struct ::tm tc = {}; // Parse RFC 822 #ifdef WIN32 if (~0 != ::sscanf_s(strTime.c_str(), "%*s %d %3s %d %d:%d:%d", &tc.tm_mday, s_mon.data(), static_cast(s_mon.size() ), &tc.tm_year, &tc.tm_hour, &tc.tm_min, &tc.tm_sec) ) #else if (~0 != ::sscanf(strTime.c_str(), "%*s %d %3s %d %d:%d:%d", &tc.tm_mday, s_mon.data(), &tc.tm_year, &tc.tm_hour, &tc.tm_min, &tc.tm_sec) ) #endif { tc.tm_year -= 1900; auto const it_mon = map_months.find(s_mon.data() ); if (map_months.cend() != it_mon) { tc.tm_mon = it_mon->second; } } tc.tm_isdst = -1; return ::mktime(&tc); } std::string getDatetimeAsString(const ::time_t tTime, const bool isGmtTime) { std::array buf; ::time_t cur_time = tTime; if (tTime == ~0) { ::time(&cur_time); } #ifdef WIN32 struct ::tm stm = {}; isGmtTime ? ::localtime_s(&stm, &cur_time) : ::gmtime_s(&stm, &cur_time); // RFC 822 ::strftime(buf.data(), buf.size(), "%a, %d %b %Y %H:%M:%S GMT", &stm); #else struct ::tm stm = {}; isGmtTime ? ::localtime_r(&cur_time, &stm) : ::gmtime_r(&cur_time, &stm); // RFC 822 ::strftime(buf.data(), buf.size(), "%a, %d %b %G %H:%M:%S GMT", &stm); #endif return std::string(buf.data() ); } size_t getNumberLength(const size_t number) { size_t length = 0; size_t n = number; do { ++length; n /= 10; } while (n); return length; } bool parseCookies(const std::string &cookieHeader, std::unordered_multimap &cookies) { if (cookieHeader.empty() ) { return true; } for (size_t cur_pos = 0, next_value; std::string::npos != cur_pos; cur_pos = next_value) { next_value = cookieHeader.find(';', cur_pos); size_t delimiter = cookieHeader.find('=', cur_pos); if (std::string::npos == delimiter || delimiter > next_value) { return false; } std::string key = cookieHeader.substr(cur_pos, delimiter - cur_pos); trim(key); key = urlDecode(key); ++delimiter; std::string value = cookieHeader.substr(delimiter, std::string::npos != next_value ? next_value - delimiter : next_value); trim(value); value = urlDecode(value); cookies.emplace(std::move(key), std::move(value) ); if (std::string::npos != next_value) { ++next_value; } } return true; } static inline bool isCharUrlAllowed(const char c) { return c == '-' || c == '_' || c == '.' || c == '~'; } std::string urlEncode(const std::string &str) { std::string encoded; static const std::array hexDigits { "0123456789ABCDEF" }; for (size_t i = 0; i < str.length(); ++i) { const unsigned char c = str[i]; if (std::isalnum(c) || isCharUrlAllowed(c) ) { encoded.push_back(c); } else if (' ' == c) { encoded.push_back('+'); } else { const uint8_t a = c >> 4; const uint8_t b = c & 0x0F; encoded.push_back('%'); encoded.push_back(hexDigits[a]); encoded.push_back(hexDigits[b]); } } return encoded; } std::string urlDecode(const std::string &str) { std::string decoded; for (size_t i = 0; i < str.length(); ++i) { unsigned char c = str[i]; if ('%' == c) { if (i + 2 < str.length() ) { const char a = str[++i]; const char b = str[++i]; c = ( (hexStringToBinEncodeSymbol(a) << 4) | hexStringToBinEncodeSymbol(b) ); } } else if ('+' == c) { c = ' '; } decoded.push_back(c); } return decoded; } };
X Tutup