/* Misc utils for strings. Copyright (c) 2006-2023 Pandora FMS. Written by Esteban Sanchez. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pandora.h" #include "pandora_strutils.h" #include #include #include #include #include // for strchr #include #include using namespace Pandora; /** * Removes heading and tailing blank spaces from a string. * * The blank spaces removed are " ", "\t", "\r" and "\n". * * @param str String to be trimmed. * * @return The trimmed string. */ string Pandora_Strutils::trim (const string str) { const char * delims = " \t\r\n"; string result = str; string::size_type index = result.find_last_not_of (delims); if (index != string::npos) { result.erase (++index); } index = result.find_first_not_of (delims); if (index != std::string::npos) { result.erase (0, index); } else { result.erase (); } return result; } /** * Encode the given string to base64. * Based on: https://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64 * * @param str String to be encoded. * * @return The base64 encoded string. */ string Pandora_Strutils::base64Encode(string str) { string base64_str; std::uint32_t temp; const static char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::vector buffer(begin(str), end(str)); base64_str.reserve(((buffer.size() / 3) + (buffer.size() % 3 > 0)) * 4); std::vector::iterator cursor = buffer.begin(); for(size_t idx = 0; idx < buffer.size() / 3; idx++) { temp = (*cursor++) << 16; temp += (*cursor++) << 8; temp += (*cursor++); base64_str.append(1, alphabet[(temp & 0x00FC0000) >> 18]); base64_str.append(1, alphabet[(temp & 0x0003F000) >> 12]); base64_str.append(1, alphabet[(temp & 0x00000FC0) >> 6]); base64_str.append(1, alphabet[(temp & 0x0000003F)]); } switch(buffer.size() % 3){ case 1: temp = (*cursor++) << 16; base64_str.append(1, alphabet[(temp & 0x00FC0000) >> 18]); base64_str.append(1, alphabet[(temp & 0x0003F000) >> 12]); base64_str.append(2, '='); break; case 2: temp = (*cursor++) << 16; temp += (*cursor++) << 8; base64_str.append(1, alphabet[(temp & 0x00FC0000) >> 18]); base64_str.append(1, alphabet[(temp & 0x0003F000) >> 12]); base64_str.append(1, alphabet[(temp & 0x00000FC0) >> 6]); base64_str.append(1, '='); break; } return base64_str; } /** * Convert an unicode string to a ANSI string. * * @param s String to convert * * @return String converted into ANSI code */ string Pandora_Strutils::strUnicodeToAnsi (LPCWSTR s) { string output; if (s == NULL) return NULL; int cw = lstrlenW (s); if (cw == 0) { return output; } int cc = WideCharToMultiByte (CP_ACP,0, s, cw, NULL, 0, NULL, NULL); if (cc==0) { return output; } CHAR *psz = new CHAR[cc+1]; cc = WideCharToMultiByte (CP_ACP, 0, s, cw, psz, cc, NULL, NULL); if (cc == 0) { delete[] psz; return output; } psz[cc]='\0'; output = psz; delete[] psz; return output; } /** * Convert an ANSI string to a unicode string. Do not forget to * delete the returned string! * * @param s String to convert * * @return String converted to Unicode */ wstring Pandora_Strutils::strAnsiToUnicode (LPCSTR s) { LPWSTR output; wstring w_output; int lenW = MultiByteToWideChar(CP_ACP, 0, s, -1, NULL, 0); if (lenW <= 0) { return NULL; } output = new wchar_t[lenW]; MultiByteToWideChar(CP_ACP, 0, s, -1, output, lenW); w_output = output; delete[] output; return w_output; } /** * Transform an integer variable into a string. * * @param i Integer to transform. * * @return A string with the integer value. */ string Pandora_Strutils::inttostr (const int i) { return longtostr (i); } /** * Transform a long variable into a string. * * @param i Long variable to transform * * @return A string with the long value. */ string Pandora_Strutils::longtostr (const long i) { std::ostringstream o; o << i; return o.str(); } /** * Transform a long variable into hexadecimal. * * @param i Long variable to transform. * * @return The hexadecimal value of the long variable. */ string Pandora_Strutils::longtohex (const long i) { std::ostringstream o; o << std::hex << i; return o.str(); } /** * Tranform a string into a integer. * * @param str String to convert. * * @return The integer value of the string. * * @exception Invalid_Conversion throwed if the string has non- * decimal values. */ int Pandora_Strutils::strtoint (const string str) { int result; if (! std::sscanf (str.c_str (), "%d", &result)) { throw Invalid_Conversion (); } return result; } /** * Returns the double precision floating-point value of a given string. * * @param str The string. * * @return The double precision floating-point value of the string. * * @exception Invalid_Conversion thrown on error. */ double Pandora_Strutils::strtodouble (const string str) { double result; if (! std::sscanf (str.c_str (), "%le", &result)) { throw Invalid_Conversion (); } return result; } /** * Tranform a string into a long integer. * * @param str String to convert. * * @return The long integer value of the string. * * @exception Invalid_Conversion throwed if the string has non- * decimal values. */ unsigned long long Pandora_Strutils::strtoulong (const string str) { unsigned long long result; if (! std::sscanf (str.c_str (), "%I64d", &result)) { throw Invalid_Conversion (); } return result; } /** * Replace every occurence of a pattern in a string with other substring. * * @param in Objective string. * @param pattern Pattern to be replaced. * @param rep Substring that replace every occurence of the pattern. * * @return The input string with all pattern occurence replaced. */ string Pandora_Strutils::strreplace (string in, string pattern, string rep) { int i = in.find (pattern); int j; if (i < 0) { return in; } int plen = pattern.length (); int rlen = rep.length (); do { in.replace(i, plen, rep); i += rlen; string rest = in.substr (i, in.length () - i); j = rest.find (pattern); i += j; } while (j >= 0); return in; } inline bool isseparator (char c, char const * const wstr) { return (strchr (wstr, c) != NULL); } /** * Split a string into diferent tokens, divided by one or many * field separators. * * @param l Returned string list with every tokens. Must be initialized * before calling the function. * @param s Input string. * @param separators Field separators string. I.e. " \t" will separate * with every " " and "\t". Can be ommited and will be " \t\n". */ void Pandora_Strutils::stringtok (list &l, string const &s, char const * const separators) { const string::size_type strsize = s.size(); string::size_type i = 0; while (i < strsize) { /* eat leading whitespace */ while ((i < strsize) && (isseparator (s[i], separators))) { i++; } if (i == strsize) { return; /* nothing left but WS */ } /* find end of word */ string::size_type j = i + 1; while ((j < strsize) && (!isseparator (s[j], separators))) { j++; } /* add word */ l.push_back (s.substr (i, j - i)); /* set up for next loop */ i = j + 1; } }