/* Copyright (C) 2005-2009 Michel de Boer 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 of the License, 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, see . */ #include #include #include #include #include #include #include #include #include #include #include "util.h" #include "twinkle_config.h" string month_abbrv[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; string month_full[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; string day_abbrv[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; string random_token(int length) { string s; for (int i = 0; i < length; i++) { s += char(rand() % 26 + 97); } return s; } string random_hexstr(int length) { string s; int x; for (int i = 0; i < length; i++) { x = rand() % 16; if (x <= 9) s += '0' + x; else s += 'a' + x - 10; } return s; } string float2str(float f, int precision) { ostringstream s; // Force the locale to POSIX, such that a dot is used for // the decimal point. s.imbue(locale("POSIX")); s.setf(ios::fixed,ios::floatfield); s.precision(precision); s << f; return s.str(); } string int2str(int i, const char *format) { char buf[32]; snprintf(buf, 32, format, i); return string(buf); } string int2str(int i) { return int2str(i, "%d"); } string ulong2str(unsigned long i, const char *format) { char buf[32]; snprintf(buf, 32, format, i); return string(buf); } string ulong2str(unsigned long i) { return ulong2str(i, "%u"); } string ptr2str(void *p) { char buf[32]; snprintf(buf, 32, "%p", p); return string(buf); } string bool2str(bool b) { return (b ? "true" : "false"); } string time2str(time_t t, const char *format) { struct tm tm; char buf[64]; localtime_r(&t, &tm); strftime(buf, 64, format, &tm); return string(buf); } string current_time2str(const char *format) { struct timeval t; gettimeofday(&t, NULL); return time2str(t.tv_sec, format); } string weekday2str(int wkday) { if (wkday >= 0 && wkday <= 6) return day_abbrv[wkday]; return "XXX"; } string month2str(int month) { if (month >= 0 && month <= 11) return month_abbrv[month]; return "XXX"; } int str2month_full(const string &month) { for (int i = 0; i < 12; i++) { if (cmp_nocase(month_full[i], month) == 0) { return i; } } return 0; } string duration2str(unsigned long seconds) { string result; long remainder, h, m, s; h = seconds / 3600; remainder = seconds % 3600; m = remainder / 60; s = remainder % 60; if (h > 0) { result = ulong2str(h); result += "h "; } if (!result.empty() || m > 0) { result += ulong2str(m); result += "m "; } result += ulong2str(s); result += "s"; return result; } string timer2str(unsigned long seconds) { string result; unsigned long remainder, h, m, s; h = seconds / 3600; remainder = seconds % 3600; m = remainder / 60; s = remainder % 60; char buf[16]; snprintf(buf, 16, "%01lu:%02lu:%02lu", h, m, s); return string(buf); } static uint8 hexdig2value(char hexdig) { uint8 val = 0; if (hexdig >= '0' && hexdig <= '9') val = hexdig - '0'; else if (hexdig >= 'a' && hexdig <= 'f') val = hexdig - 'a' + 10; else if (hexdig >= 'A' && hexdig <= 'F') val = hexdig - 'A' + 10; return val; } static char value2hexdig(uint8 val) { char c = '0'; if (val <= 9) { c = '0' + val; } else if (val <= 15) { c = 'a' + val - 10; } return c; } unsigned long hex2int(const string &h) { unsigned long u = 0; int power = 1; for (string::const_reverse_iterator i = h.rbegin(); i != h.rend(); ++i) { u += hexdig2value(*i) * power; power = power * 16; } return u; } void hex2binary(const string &h, uint8 *buf) { uint8 *p = buf; bool hi_nibble = true; for (string::const_iterator i = h.begin() ; i != h.end(); ++i) { if (hi_nibble) { *p = hexdig2value(*i) << 4; } else { *(p++) |= hexdig2value(*i); } hi_nibble = !hi_nibble; } } string binary2hex(uint8 *buf, unsigned long len) { string s; for (uint8 *p = buf; p < buf + len; ++p) { s += value2hexdig((*p >> 4) & 0xf); s += value2hexdig(*p & 0xf); } return s; } string tolower(const string &s) { string result; for (string::const_iterator i = s.begin(); i != s.end(); ++i) { result += tolower(*i); } return result; } string toupper(const string &s) { string result; for (string::const_iterator i = s.begin(); i != s.end(); ++i) { result += toupper(*i); } return result; } string rtrim(const string &s) { string::size_type i; i = s.find_last_not_of(' '); if (i == string::npos) return ""; if (i == s.size()-1) return s; return s.substr(0, i+1); } string ltrim(const string &s) { string::size_type i; i = s.find_first_not_of(' '); if (i == string::npos) return ""; if (i == 0) return s; return s.substr(i, s.size()-i+1); } string trim(const string &s) { return ltrim(rtrim(s)); } string padleft(const string &s, char c, unsigned long len) { string result(c, len); result += s; return result.substr(result.size() - len); } int cmp_nocase(const string &s1, const string &s2) { string::const_iterator i1 = s1.begin(); string::const_iterator i2 = s2.begin(); while (i1 != s1.end() && i2 != s2.end()) { if (toupper(*i1) != toupper(*i2)) { return (toupper(*i1) < toupper(*i2)) ? -1 : 1; } ++i1; ++i2; } if (s1.size() == s2.size()) return 0; if (s1.size() < s2.size()) return -1; return 1; } bool must_quote(const string &s) { string special("()<>@,;:\\\"/[]?={} \t"); if (s.size() == 0) return true; return (s.find_first_of(special) != string::npos); } string escape(const string &s, char c) { string result; for (string::size_type i = 0; i < s.size(); i++) { if (s[i] == '\\' || s[i] == c) { result += '\\'; } result += s[i]; } return result; } string unescape(const string &s) { string result; for (string::size_type i = 0; i < s.size(); i++) { if (s[i] == '\\' && i < s.size() - 1) { i++; } result += s[i]; } return result; } string escape_hex(const string &s, const string &unreserved) { string result; for (string::size_type i = 0; i < s.size(); i++) { if (unreserved.find(s[i], 0) != string::npos) { // Unreserved symbol result += s[i]; } else { // Reserved symbol result += int2str((int)s[i], "%%%02x"); } } return result; } string unescape_hex(const string &s) { string result; for (string::size_type i = 0; i < s.size(); i++) { if (s[i] == '%' && i < s.size() - 2 && isxdigit(s[i+1]) && isxdigit(s[i+2])) { // Escaped hex-value string hexval = s.substr(i+1, 2); result += static_cast(hex2int(hexval)); i += 2; } else { result += s[i]; } } return result; } string replace_char(const string &s, char from, char to) { string result = s; for (string::size_type i = 0; i < result.size(); i++) { if (result[i] == from) result[i] = to; } return result; } string replace_first(const string &s, const string &from, const string &to) { string result = s; string::size_type i = result.find(from, 0); if (i != string::npos) { result.replace(i, from.size(), to); } return result; } vector split(const string &s, char c) { string::size_type i; string::size_type j = 0; vector l; while (true) { i = s.find(c, j); if (i == string::npos) { l.push_back(s.substr(j)); return l; } if (i == j) l.push_back(""); else l.push_back(s.substr(j, i-j)); j = i+1; if (j == s.size()) { l.push_back(""); return l; } } } vector split(const string &s, const string& separator) { string::size_type i; string::size_type j = 0; vector l; while (true) { i = s.find(separator, j); if (i == string::npos) { l.push_back(s.substr(j)); return l; } if (i == j) l.push_back(""); else l.push_back(s.substr(j, i-j)); j = i + separator.size(); if (j == s.size()) { l.push_back(""); return l; } } } vector split_linebreak(const string &s) { if (s.find("\r\n") != string::npos) { return split(s, "\r\n"); } else if (s.find("\r") != string::npos) { return split(s, "\r"); } return split(s, "\n"); } vector split_on_first(const string &s, char c) { vector l; string::size_type i = s.find(c); if (i == string::npos) { l.push_back(s); } else { if (i == 0) { l.push_back(""); } else { l.push_back(s.substr(0, i)); } if (i == s.size() - 1) { l.push_back(""); } else { l.push_back(s.substr(i + 1)); } } return l; } vector split_on_last(const string &s, char c) { vector l; string::size_type i = s.find_last_of(c); if (i == string::npos) { l.push_back(s); } else { if (i == 0) { l.push_back(""); } else { l.push_back(s.substr(0, i)); } if (i == s.size() - 1) { l.push_back(""); } else { l.push_back(s.substr(i + 1)); } } return l; } vector split_escaped(const string &s, char c) { vector l; string::size_type start_pos = 0; for (string::size_type i = 0; i < s.size(); i++) { if (s[i] == '\\') { // Skip escaped character if (i < s.size()) i++; continue; } if (s[i] == c) { l.push_back(unescape(s.substr(start_pos, i - start_pos))); start_pos = i + 1; } } if (start_pos < s.size()) { l.push_back(unescape(s.substr(start_pos, s.size() - start_pos))); } else if (start_pos == s.size()) { l.push_back(""); } return l; } vector split_ws(const string &s, bool quote_sensitive) { vector l; bool in_quotes = false; string::size_type start_pos = 0; for (string::size_type i = 0; i < s.size(); i++ ) { if (quote_sensitive && s[i] == '"') { in_quotes = !in_quotes; continue; } if (in_quotes) continue; if (s[i] == ' ' || s[i] == '\t') { // Skip consecutive white space if (start_pos != i) { l.push_back(s.substr(start_pos, i - start_pos)); } start_pos = i + 1; } } if (start_pos < s.size()) { l.push_back(s.substr(start_pos, s.size() - start_pos)); } return l; } string join_strings(const vector &v, const string &separator) { string text; for (vector::const_iterator it = v.begin(); it != v.end(); ++it) { if (it != v.begin()) { text += separator; } text += *it; } return text; } string unquote(const string &s) { if (s.size() <= 1) return s; if (s[0] == '"' && s[s.size() - 1] == '"') return s.substr(1, s.size() - 2); return s; } bool is_number(const string &s) { if (s.empty()) return false; for (string::size_type i = 0; i < s.size(); i++ ) { if (!isdigit(s[i])) return false; } return true; } bool is_ipaddr(const string &s) { vector l = split(s, '.'); if (l.size() != 4) return false; for (vector::iterator i = l.begin(); i != l.end(); ++i) { if (!is_number(*i) || atoi(i->c_str()) > 255) return false; } return true; } bool yesno2bool(const string &yesno) { return (yesno == "yes" ? true : false); } string bool2yesno(bool b) { return (b ? "yes" : "no"); } string str2dtmf(const string &s) { string result; string to_convert = tolower(s); for (string::size_type i = 0; i < to_convert.size(); i++) { switch (to_convert[i]) { case '1': result += '1'; break; case '2': case 'a': case 'b': case 'c': result += '2'; break; case '3': case 'd': case 'e': case 'f': result += '3'; break; case '4': case 'g': case 'h': case 'i': result += '4'; break; case '5': case 'j': case 'k': case 'l': result += '5'; break; case '6': case 'm': case 'n': case 'o': result += '6'; break; case '7': case 'p': case 'q': case 'r': case 's': result += '7'; break; case '8': case 't': case 'u': case 'v': result += '8'; break; case '9': case 'w': case 'x': case 'y': case 'z': result += '9'; break; case '0': case ' ': result += '0'; break; case '#': case '*': result += to_convert[i]; break; } } return result; } bool looks_like_phone(const string &s, const string &special_symbols) { string phone_symbols= special_symbols + "0123456789*#+ \t"; string t; for (string::const_iterator i = s.begin(); i != s.end(); ++i) { if (phone_symbols.find(*i) == string::npos) return false; } return true; } string remove_symbols(const string &s, const string &special_symbols) { string result; for (string::const_iterator i = s.begin(); i != s.end(); ++i) { if (special_symbols.find(*i) == string::npos) { result += *i; } } return result; } string remove_white_space(const string &s) { string result; for (string::const_iterator i = s.begin(); i != s.end(); ++i) { if (*i != ' ' && *i != '\t') { result += *i; } } return result; } string dotted_truncate(const string &s, string::size_type len) { if (len >= s.size()) return s; return s.substr(0, len) + "..."; } string to_printable(const string &s) { string result; for (string::const_iterator i = s.begin(); i != s.end(); ++i) { if (isprint(*i) || *i == '\n' || *i == '\r') { result += *i; } else { result += '.'; } } return result; } string get_error_str(int errnum) { #if HAVE_STRERROR_R char buf[81]; memset(buf, 0, sizeof(buf)); #if STRERROR_R_CHAR_P string errmsg(strerror_r(errnum, buf, sizeof(buf)-1)); #else string errmsg; if (strerror_r(errnum, buf, sizeof(buf)-1) == 0) { errmsg = buf; } else { errmsg = "unknown error: "; errmsg += int2str(errnum); } #endif #else string errmsg("strerror_r is not available: "); errmsg += int2str(errnum); #endif return errmsg; }