123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709 |
- /*
- * Copyright 2005 - 2016 Zarafa and its licensors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- #include <kopano/platform.h>
- #include <algorithm>
- #include <sstream>
- #include <stdexcept>
- #include <string>
- #include <cctype>
- #include <kopano/stringutil.h>
- #include <kopano/charset/convert.h>
- #include <kopano/ECIConv.h>
- #include <openssl/md5.h>
- namespace KC {
- std::string stringify(unsigned int x, bool usehex, bool _signed) {
- char szBuff[33];
- if(usehex)
- sprintf(szBuff, "0x%08X", x);
- else if (_signed)
- sprintf(szBuff, "%d", x);
- else
- sprintf(szBuff, "%u", x);
- return szBuff;
- }
- std::string stringify_int64(int64_t x, bool usehex) {
- std::ostringstream s;
- if (usehex) {
- s.flags(std::ios::showbase);
- s.setf(std::ios::hex, std::ios::basefield); // showbase && basefield: add 0x prefix
- s.setf(std::ios::uppercase);
- }
- s << x;
- return s.str();
- }
- std::string stringify_float(float x) {
- std::ostringstream s;
- s << x;
- return s.str();
- }
- std::string stringify_double(double x, int prec, bool bLocale) {
- std::ostringstream s;
- s.precision(prec);
- s.setf(std::ios::fixed,std::ios::floatfield);
- if (bLocale) {
- try {
- std::locale l("");
- s.imbue(l);
- } catch (std::runtime_error &) {
- // locale not available, print in C
- }
- s << x;
- } else
- s << x;
- return s.str();
- }
- // FIXME support only unsigned int!!!
- std::wstring wstringify(unsigned int x, bool usehex, bool _signed)
- {
- std::wostringstream s;
- if (usehex) {
- s.flags(std::ios::showbase);
- s.setf(std::ios::hex, std::ios::basefield); // showbase && basefield: add 0x prefix
- s.setf(std::ios::uppercase);
- }
- s << x;
- return s.str();
- }
- unsigned int xtoi(const char *lpszHex)
- {
- unsigned int ulHex = 0;
- sscanf(lpszHex, "%X", &ulHex);
- return ulHex;
- }
- int memsubstr(const void* haystack, size_t haystackSize, const void* needle, size_t needleSize)
- {
- size_t pos = 0;
- size_t match = 0;
- auto searchbuf = static_cast<const BYTE *>(needle);
- auto databuf = static_cast<const BYTE *>(haystack);
- if(haystackSize < needleSize)
- return (haystackSize-needleSize);
- while(pos < haystackSize)
- {
- if(*databuf == *searchbuf){
- ++searchbuf;
- ++match;
- if(match == needleSize)
- return 0;
- }else{
- databuf -= match;
- pos -= match;
- searchbuf = (BYTE*)needle;
- match = 0;
- }
- ++databuf;
- ++pos;
- }
- return 1;
- }
- std::string str_storage(uint64_t ulBytes, bool bUnlimited) {
- static double MB = 1024.0 * 1024.0;
- if (ulBytes == 0 && bUnlimited)
- return "unlimited";
- return stringify_double((double)ulBytes / MB, 2) + " MB";
- }
- std::string GetServerNameFromPath(const char *szPath) {
- std::string path = szPath;
- size_t pos = 0;
- pos = path.find("://");
- if (pos != std::string::npos) {
- /* Remove prefixed type information */
- path.erase(0, pos + 3);
- }
- pos = path.find(':');
- if (pos != std::string::npos)
- path.erase(pos, std::string::npos);
- return path;
- }
- std::string GetServerPortFromPath(const char *szPath) {
- std::string path = szPath;
- size_t pos = 0;
- if (strncmp(path.c_str(), "http", 4) != 0)
- return std::string();
- pos = path.rfind(':');
- if (pos == std::string::npos)
- return std::string();
-
- pos += 1; /* Skip ':' */
- /* Remove all leading characters */
- path.erase(0, pos);
- /* Strip additional path */
- pos = path.rfind('/');
- if (pos != std::string::npos)
- path.erase(pos, std::string::npos);
- return path;
- }
- std::string shell_escape(const std::string &str)
- {
- std::string escaped;
- auto start = str.cbegin();
- auto ptr = start;
- while (ptr != str.cend()) {
- while (ptr != str.end() && *ptr != '\'')
- ++ptr;
- escaped += std::string(start, ptr);
- if (ptr == str.end())
- break;
- start = ++ptr; // skip single quote
- escaped += "'\\''"; // shell escape sequence
- }
- return escaped;
- }
- std::string shell_escape(const std::wstring &wstr)
- {
- std::string strLocale = convert_to<std::string>(wstr);
- return shell_escape(strLocale);
- }
- std::vector<std::wstring> tokenize(const std::wstring &strInput, const WCHAR sep, bool bFilterEmpty) {
- const WCHAR *begin, *end = NULL;
- std::vector<std::wstring> vct;
- begin = strInput.c_str();
- while (*begin != '\0') {
- end = wcschr(begin, sep);
- if (!end) {
- vct.push_back(begin);
- break;
- }
- if (!bFilterEmpty || std::distance(begin,end) > 0)
- vct.push_back(std::wstring(begin,end));
- begin = end+1;
- }
- return vct;
- }
- std::vector<std::string> tokenize(const std::string &strInput, const char sep, bool bFilterEmpty) {
- const char *begin, *last, *end = NULL;
- std::vector<std::string> vct;
- begin = strInput.c_str();
- last = begin + strInput.length();
- while (begin < last) {
- end = strchr(begin, sep);
- if (!end) {
- vct.push_back(begin);
- break;
- }
- if (!bFilterEmpty || std::distance(begin,end) > 0)
- vct.push_back(std::string(begin,end));
- begin = end+1;
- }
- return vct;
- }
- std::string trim(const std::string &strInput, const std::string &strTrim)
- {
- std::string s = strInput;
- size_t pos;
- if (s.empty())
- return s;
- pos = s.find_first_not_of(strTrim);
- s.erase(0, pos);
-
- pos = s.find_last_not_of(strTrim);
- if (pos != std::string::npos)
- s.erase(pos + 1, std::string::npos);
-
- return s;
- }
- unsigned char x2b(char c)
- {
- if (c >= '0' && c <= '9')
- // expects sensible input
- return c - '0';
- else if (c >= 'a')
- return c - 'a' + 10;
- return c - 'A' + 10;
- }
- std::string hex2bin(const std::string &input)
- {
- std::string buffer;
- if (input.length() % 2 != 0)
- return buffer;
- buffer.reserve(input.length() / 2);
- for (unsigned int i = 0; i < input.length(); ) {
- unsigned char c;
- c = x2b(input[i++]) << 4;
- c |= x2b(input[i++]);
- buffer += c;
- }
- return buffer;
- }
- std::string hex2bin(const std::wstring &input)
- {
- std::string buffer;
- if (input.length() % 2 != 0)
- return buffer;
- buffer.reserve(input.length() / 2);
- for (unsigned int i = 0; i < input.length(); ) {
- unsigned char c;
- c = x2b((char)input[i++]) << 4;
- c |= x2b((char)input[i++]);
- buffer += c;
- }
- return buffer;
- }
- std::string bin2hex(unsigned int inLength, const unsigned char *input)
- {
- static const char digits[] = "0123456789ABCDEF";
- std::string buffer;
- if (!input)
- return buffer;
- buffer.reserve(inLength * 2);
- for (unsigned int i = 0; i < inLength; ++i) {
- buffer += digits[input[i]>>4];
- buffer += digits[input[i]&0x0F];
- }
- return buffer;
- }
- std::string bin2hex(const std::string &input)
- {
- return bin2hex((unsigned int)input.size(), (const unsigned char*)input.c_str());
- }
- std::wstring bin2hexw(unsigned int inLength, const unsigned char *input)
- {
- static const wchar_t digits[] = L"0123456789ABCDEF";
- std::wstring buffer;
- if (!input)
- return buffer;
- buffer.reserve(inLength * 2);
- for (unsigned int i = 0; i < inLength; ++i) {
- buffer += digits[input[i]>>4];
- buffer += digits[input[i]&0x0F];
- }
- return buffer;
- }
- std::wstring bin2hexw(const std::string &input)
- {
- return bin2hexw((unsigned int)input.size(), (const unsigned char*)input.c_str());
- }
- /**
- * Encodes a string for inclusion into an url.
- *
- * @note this does not encode an url to another more valid url (since / would get encoded!)
- * @note watch the locale of the string, make sure it's the same as the rest of the url.
- *
- * @param[in] input string to encode
- *
- * @return encoded string valid to include in an url
- */
- std::string urlEncode(const std::string &input)
- {
- std::string output;
- static const char digits[] = "0123456789ABCDEF";
- output.reserve(input.length());
- for (size_t i = 0; i < input.length(); ++i) {
- if (static_cast<unsigned char>(input[i]) <= 33 ||
- static_cast<unsigned char>(input[i]) >= 128) {
- output += '%';
- output += digits[input[i] >> 4];
- output += digits[input[i] & 0x0F];
- continue;
- }
- switch (input[i]) {
- case ':':
- case '/':
- case '?':
- case '#':
- case '[':
- case ']':
- case '@':
- case '!':
- case '$':
- case '&':
- case '\'':
- case '(':
- case ')':
- case '*':
- case '+':
- case ',':
- case ';':
- case '=':
- output += '%';
- output += digits[input[i] >> 4];
- output += digits[input[i] & 0x0F];
- break;
- default:
- output += input[i];
- }
- }
- return output;
- }
- /**
- * encode an url part, input in wide char, and destination charset in encoded characters
- *
- * @param[in] input wide string to convert to valid url encoded ascii string
- * @param[in] charset non-ascii characters will be encoded for this charset
- *
- * @return url valid encoded string
- */
- std::string urlEncode(const std::wstring &input, const char* charset)
- {
- return urlEncode(convert_to<std::string>(charset, input, rawsize(input), CHARSET_WCHAR));
- }
- std::string urlEncode(const WCHAR* input, const char* charset)
- {
- return urlEncode(convert_to<std::string>(charset, input, rawsize(input), CHARSET_WCHAR));
- }
- /**
- * replaces %## values by ascii values
- * i.e Amsterdam%2C -> Amsterdam,
- * @note 1. this can take a full url, since it just replaces the %##
- * @note 2. you need to handle the locale of the string yourself!
- *
- * @param[in] input url encoded string
- *
- * @return decoded url in the locale it was encoded in
- */
- std::string urlDecode(const std::string &input)
- {
- std::string output;
- output.reserve(input.length());
- for (size_t i = 0; i < input.length(); ++i) {
- if (input[i] == '%' && input.length() > i + 2)
- {
- unsigned char c;
- c = x2b(input[++i]) << 4;
- c |= x2b(input[++i]);
- output += c;
- }
- else
- output += input[i];
- }
- return output;
- }
- /**
- * Convert a memory buffer with strings with Unix \n enters to DOS
- * \r\n enters.
- *
- * @param[in] size length of the input
- * @param[in] input buffer containing strings with enters to convert
- * @param[out] output buffer with enough space to hold input + extra \r characters
- * @param[out] outsize number of characters written to output
- */
- void BufferLFtoCRLF(size_t size, const char *input, char *output, size_t *outsize) {
- size_t j = 0;
- for (size_t i = 0; i < size; ++i) {
- if (input[i] == '\r') {
- if ((i+1) < size && input[i+1] == '\n') {
- output[j++] = '\r';
- output[j++] = '\n';
- ++i;
- } else {
- output[j++] = '\r';
- output[j++] = '\n';
- }
- } else if (input[i] == '\n') {
- output[j++] = '\r';
- output[j++] = '\n';
- } else {
- output[j++] = input[i];
- }
- }
- output[j] = '\0';
- *outsize = j;
- }
- /**
- * converts Tabs in a string to spaces
- *
- * @param[in] strInput input string to be converted
- * @param[out] strOutput return converted string
- */
- void StringTabtoSpaces(const std::wstring &strInput, std::wstring *lpstrOutput) {
- std::wstring strOutput;
- strOutput.reserve(strInput.length());
- for (auto c : strInput)
- if (c == '\t')
- strOutput.append(4, ' ');
- else
- strOutput.append(1, c);
- lpstrOutput->swap(strOutput);
- }
- /**
- * converts CRLF in a string to LF
- *
- * @param[in] strInput input string to be converted
- * @param[out] strOutput return converted string
- */
- void StringCRLFtoLF(const std::wstring &strInput, std::wstring *lpstrOutput) {
- std::wstring::const_iterator iInput(strInput.begin());
- std::wstring strOutput;
- strOutput.reserve(strInput.length());
- for (; iInput != strInput.end(); ++iInput) {
-
- // skips /r if /r/n found together in the text
- if (*iInput == '\r' && (iInput + 1 != strInput.end() && *(iInput + 1) == '\n'))
- continue;
- else
- strOutput.append(1, *iInput);
-
- }
- lpstrOutput->swap(strOutput);
- }
- /**
- * converts a string inline from \n enters to \r\n
- *
- * @param strInOut string to edit
- */
- void StringLFtoCRLF(std::string &strInOut)
- {
- std::string strOutput;
- std::string::const_iterator i;
- strOutput.reserve(strInOut.size());
- for (i = strInOut.begin(); i != strInOut.end(); ++i)
- if (*i == '\n' && i != strInOut.begin() && *(i-1) != '\r')
- strOutput.append("\r\n");
- else
- strOutput.append(1, *i);
- swap(strInOut, strOutput);
- }
- std::string format(const char *const fmt, ...) {
- char *buffer = NULL;
- va_list ap;
- va_start(ap, fmt);
- (void)vasprintf(&buffer, fmt, ap);
- va_end(ap);
- std::string result = buffer;
- free(buffer);
- return result;
- }
- char *kc_strlcpy(char *dest, const char *src, size_t n)
- {
- strncpy(dest, src, n);
- dest[n-1] = '\0';
- return dest;
- }
- bool kc_starts_with(const std::string &full, const std::string &prefix)
- {
- return full.compare(0, prefix.size(), prefix) == 0;
- }
- bool kc_istarts_with(const std::string &full, const std::string &needle)
- {
- return kc_starts_with(strToLower(full), strToLower(needle));
- }
- bool kc_ends_with(const std::string &full, const std::string &prefix)
- {
- size_t fz = full.size(), pz = prefix.size();
- if (fz < pz)
- return false;
- return full.compare(fz - pz, pz, prefix);
- }
- static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- static inline bool is_base64(unsigned char c)
- {
- return isalnum(c) || c == '+' || c == '/';
- }
- std::string base64_encode(const unsigned char *bytes_to_encode, unsigned int in_len)
- {
- unsigned char char_array_3[3], char_array_4[4];
- int i = 0, j = 0;
- std::string ret;
-
- while (in_len--) {
- char_array_3[i++] = *(bytes_to_encode++);
- if (i != 3)
- continue;
- char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
- char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
- char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
- char_array_4[3] = char_array_3[2] & 0x3f;
- for (i = 0; i < 4; ++i)
- ret += base64_chars[char_array_4[i]];
- i = 0;
- }
- if (i == 0)
- return ret;
- for (j = i; j < 3; ++j)
- char_array_3[j] = '\0';
- char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
- char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
- char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
- char_array_4[3] = char_array_3[2] & 0x3f;
- for (j = 0; j < i + 1; ++j)
- ret += base64_chars[char_array_4[j]];
- while ((i++ < 3))
- ret += '=';
- return ret;
- }
- std::string base64_decode(const std::string &encoded_string)
- {
- int in_len = encoded_string.size(), i = 0, j = 0, in_ = 0;
- unsigned char char_array_4[4], char_array_3[3];
- std::string ret;
- while (in_len-- && encoded_string[in_] != '=' && is_base64(encoded_string[in_])) {
- char_array_4[i++] = encoded_string[in_++];
- if (i != 4)
- continue;
- for (i = 0; i < 4; ++i)
- char_array_4[i] = base64_chars.find(char_array_4[i]);
- char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
- char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
- char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
- for (i = 0; i < 3; ++i)
- ret += char_array_3[i];
- i = 0;
- }
- if (i == 0)
- return ret;
- for (j = i; j < 4; ++j)
- char_array_4[j] = 0;
- for (j = 0; j < 4; ++j)
- char_array_4[j] = base64_chars.find(char_array_4[j]);
- char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
- char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
- char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
- for (j = 0; j < i - 1; ++j)
- ret += char_array_3[j];
- return ret;
- }
- std::string zcp_md5_final_hex(MD5_CTX *ctx)
- {
- static const char hex[] = "0123456789abcdef";
- unsigned char md[MD5_DIGEST_LENGTH];
- std::string s;
- s.reserve(2 * sizeof(md));
- MD5_Final(md, ctx);
- for (size_t z = 0; z < sizeof(md); ++z) {
- s.push_back(hex[(md[z] & 0xF0) >> 4]);
- s.push_back(hex[md[z] & 0xF]);
- }
- return s;
- }
- std::string string_strip_nuls(const std::string &i)
- {
- std::string o;
- std::copy_if(i.cbegin(), i.cend(), std::back_inserter(o),
- [](char c) { return c != '\0'; });
- return o;
- }
- std::wstring string_strip_nuls(const std::wstring &i)
- {
- std::wstring o;
- std::copy_if(i.cbegin(), i.cend(), std::back_inserter(o),
- [](wchar_t c) { return c != L'\0'; });
- return o;
- }
- } /* namespace */
|