/* * This file is a part of Winix * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2008-2021, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include "misc.h" #include "templates/templates.h" #include "convert/convert.h" namespace Winix { namespace misc_private { // white_chars table should be sorted // we do not treat a new line character (10) as a white character here static const wchar_t white_chars[] = { 0x0009, 0x000B, 0x000C, 0x000D, 0x0020, 0x0085, 0x00A0, 0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x2028, 0x2029, 0x202F, 0x205F, 0x3000 }; pt::WTextStream tmp_qencode; } /* * IMPROVE ME * we ca add our own functions with treat_new_line_as_white flag * and with a pointer pointing after the number * * Toi(const wchar_t * str, const wchar_t ** str_after, bool treat_new_line_as_white); * Toi(const wchar_t * str, bool treat_new_line_as_white); * Toi(const std::wstring & str, bool treat_new_line_as_white); * */ int Toi(const std::string & str, int base) { return Toi(str.c_str(), base); } int Toi(const std::wstring & str, int base) { return Toi(str.c_str(), base); } int Toi(const char * str, int base) { return static_cast(strtol(str, 0, base)); } int Toi(const wchar_t * str, int base) { return static_cast(wcstol(str, 0, base)); } long Tol(const std::string & str, int base) { return Tol(str.c_str(), base); } long Tol(const std::wstring & str, int base) { return Tol(str.c_str(), base); } long Tol(const char * str, int base) { return strtol(str, 0, base); } long Tol(const wchar_t * str, int base) { return wcstol(str, 0, base); } double Tod(const std::string & str) { return strtod(str.c_str(), 0); } double Tod(const std::wstring & str) { return wcstold(str.c_str(), 0); } double Tod(const char * str) { return strtod(str, 0); } double Tod(const wchar_t * str) { return wcstold(str, 0); } const wchar_t * Toa(unsigned int value, int base) { return Toa(static_cast(value), base); } const wchar_t * Toa(unsigned long value, int base) { static wchar_t buffer[50]; size_t len = sizeof(buffer) / sizeof(wchar_t); Toa(value, buffer, len, base); return buffer; } const wchar_t * Toa(int value, int base) { return Toa(static_cast(value), base); } const wchar_t * Toa(long value, int base) { static wchar_t buffer[50]; size_t len = sizeof(buffer) / sizeof(wchar_t); Toa(value, buffer, len, base); return buffer; } void Toa(int value, std::string & res, int base, bool clear) { static char buffer[50]; // !! IMPROVE ME this 'static' is not needed here? size_t len = sizeof(buffer) / sizeof(char); if( clear ) res.clear(); Toa(value, buffer, len, base); res += buffer; } void Toa(long value, std::string & res, int base, bool clear) { static char buffer[50]; // !! IMPROVE ME the same as above size_t len = sizeof(buffer) / sizeof(char); if( clear ) res.clear(); Toa(value, buffer, len, base); res += buffer; } void Toa(int value, std::wstring & res, int base, bool clear) { static wchar_t buffer[50]; // !! size_t len = sizeof(buffer) / sizeof(wchar_t); if( clear ) res.clear(); Toa(value, buffer, len, base); res += buffer; } void Toa(long value, std::wstring & res, int base, bool clear) { static wchar_t buffer[50]; // !! size_t len = sizeof(buffer) / sizeof(wchar_t); if( clear ) res.clear(); Toa(value, buffer, len, base); res += buffer; } void SetNonZeroDigitsAfterComma(char * str, size_t digits) { bool was_comma = false; bool was_not_zero = false; size_t zeroes = 0; size_t not_zeroes = 0; for(size_t i=0 ; str[i] != 0 ; ++i) { if( str[i] == '.' || str[i] == ',' ) { was_comma = true; } else if( was_comma ) { if( str[i] == '0' && !was_not_zero ) { zeroes += 1; } else { was_not_zero = true; not_zeroes += 1; if( not_zeroes >= digits ) { str[i+1] = 0; break; } } } } } bool CorrectUrlChar(wchar_t c) { return (c >= 'a' && c <='z') || (c >= 'A' && c <='Z') || (c >= '0' && c <='9') || c == '(' || c == ')' || c == '.' || c == ',' || c == '_' || c == '-'; } // this function checks how many dots there are in the url // if there are more than one (last) dot then the first dots will be changed into '_' void CorrectUrlDots(std::wstring & url) { size_t i = url.size(); bool was_dot = false; while( i-- > 0 ) { if( url[i] == '.' ) { if( was_dot ) // only one dot is allowed url[i] = '_'; // !! do konfiga was_dot = true; } } } // !! pomyslec o lepszej nazwie void CorrectUrlChars(std::wstring & url) { std::wstring::iterator i; for(i=url.begin(); i != url.end() ; ++i) { if( !CorrectUrlChar(*i) ) { wchar_t c = TemplatesFunctions::locale.UrlSubst(*i); if( CorrectUrlChar(c) ) *i = c; else *i = '_'; // !! dodac do konfiga } } } // !! pomyslec o lepszej nazwie // przerzucic do funkcji - tam gdzie jest PrepareUrl() // bo tutaj nie mamy wskaznika na config void CorrectUrlOnlyAllowedChar(std::wstring & url) { CorrectUrlDots(url); CorrectUrlChars(url); pt::to_lower_emplace(url); Trim(url, '_'); if( url.empty() || url == L"." ) { // !! brakuje config-> //if( config->item_url_empty.empty() ) url = L"unnamed"; //else //{ // url = config->item_url_empty; // CorrectUrlDots(url); // CorrectUrlChars(url); // ToSmall(url); // we don't trim here and the string will not be empty //} } if( url[0] >= '0' && url[0] <= '9' ) // url must begin with a letter url.insert(url.begin(), '_'); } // DEPRECATED now pt::Date can print a month in Roman numerals const wchar_t * DateToStr(int year, int month, int day) { static const wchar_t * month_letter[] = { L"I", L"II", L"III", L"IV", L"V", L"VI", L"VII", L"VIII", L"IX", L"X", L"XI", L"XII" }; static wchar_t buffer[100]; --month; if( month < 0 ) month = 0; if( month > 11 ) month = 11; if( year == 0 ) swprintf(buffer, sizeof(buffer)/sizeof(wchar_t), L"%ls %02d", month_letter[month], day); else swprintf(buffer, sizeof(buffer)/sizeof(wchar_t), L"%02d %ls %02d", year, month_letter[month], day); // warning: not thread safe (we do not use threads) return buffer; } // DEPRECATED now pt::Date can print a month in Roman numerals const wchar_t * DateToStr(int year, int month, int day, int hour, int min, int sec) { static const wchar_t * month_letter[] = { L"I", L"II", L"III", L"IV", L"V", L"VI", L"VII", L"VIII", L"IX", L"X", L"XI", L"XII" }; static wchar_t buffer[100]; --month; if( month < 0 ) month = 0; if( month > 11 ) month = 11; if( year == 0 ) swprintf(buffer, sizeof(buffer)/sizeof(wchar_t), L"%ls %02d %02d:%02d:%02d", month_letter[month], day, hour, min, sec); else swprintf(buffer, sizeof(buffer)/sizeof(wchar_t), L"%02d %ls %02d %02d:%02d:%02d", year, month_letter[month], day, hour, min, sec); // warning: not thread safe (we do not use threads) return buffer; } const wchar_t * DateToStr(const pt::Date & d) { return DateToStr(d.year, d.month, d.day, d.hour, d.min, d.sec); } const wchar_t * DateToStr(time_t t) { pt::Date date = t; return DateToStr(date); } const wchar_t * DateToStrWithoutHours(const pt::Date & d) { return DateToStr(d.year, d.month, d.day); } const wchar_t * DateToStrWithoutHours(time_t t) { pt::Date date = t; return DateToStrWithoutHours(date); } // this format is used with cookies const char * DateToStrCookie(int year, int month, int day, int hour, int min, int sec) { static const char * month_str[]={ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static char buffer[100]; --month; if( month < 0 ) month = 0; if( month > 11 ) month = 11; sprintf(buffer, "%02d-%s-%04d %02d:%02d:%02d", day, month_str[month], year, hour, min, sec); return buffer; } const char * DateToStrCookie(const pt::Date & d) { return DateToStrCookie(d.year, d.month, d.day, d.hour, d.min, d.sec); } const char * DateToStrCookie(time_t t) { pt::Date date = t; return DateToStrCookie(date); } const wchar_t * IpToStr(unsigned int ip_) { static wchar_t buffer[100]; union { unsigned int ip; unsigned char c[4]; } ip; ip.ip = ip_; swprintf(buffer, sizeof(buffer)/sizeof(wchar_t), L"%u.%u.%u.%u", (int)ip.c[0], (int)ip.c[1], (int)ip.c[2], (int)ip.c[3]); return buffer; } pt::WTextStream IPToStr(unsigned int ip) { pt::WTextStream buf; for(int i=0 ; i<4 ; ++i, ip >>= 8) { buf << (ip & 0xff); if( i<3 ) buf << '.'; } return buf; } pt::WTextStream IPToStr(int ip) { return IPToStr(static_cast(ip)); } /* by default we do not treat a new line character (10) as a white character */ bool IsWhite(wchar_t c, bool treat_new_line_as_white) { using misc_private::white_chars; size_t len = sizeof(white_chars) / sizeof(wchar_t); size_t o1 = 0; size_t o2 = len - 1; if( c == 10 ) return treat_new_line_as_white ? true : false; if( c < white_chars[o1] || c > white_chars[o2] ) return false; if( c == white_chars[o1] || c == white_chars[o2] ) return true; while( o1 + 1 < o2 ) { size_t o = (o2 - o1)/2 + o1; if( c == white_chars[o] ) return true; if( c > white_chars[o] ) o1 = o; else o2 = o; } return false; } /* return true if the whole string has only white characters an empty string is treated as white */ bool IsWhite(const wchar_t * str, bool treat_new_line_as_white) { for( ; *str != 0 ; ++str ) { if( !IsWhite(*str, treat_new_line_as_white) ) return false; } return true; } /* return true if the whole string has only white characters */ bool IsWhite(const std::wstring & str, bool treat_new_line_as_white) { return IsWhite(str.c_str(), treat_new_line_as_white); } void TrimWhite(std::wstring & s, bool trim_new_line_too) { size_t i; if( s.empty() ) return; // looking for white characters at the end for(i=s.size()-1 ; i>0 && IsWhite(s[i], trim_new_line_too) ; --i); if( i==0 && IsWhite(s[i], trim_new_line_too) ) { // the whole string has white characters s.clear(); return; } // deleting white characters at the end if( i != s.size() - 1 ) s.erase(i+1, std::wstring::npos); // looking for white characters at the beginning for(i=0 ; i0 && s[i]==c ; --i); if( i==0 && s[i]==c ) { // the whole string has the 'c' characters s.clear(); return; } // deleting 'c' characters at the end if( i != s.size() - 1 ) s.erase(i+1, std::wstring::npos); } void Trim(std::wstring & s, wchar_t c) { if( s.empty() ) return; TrimLast(s, c); TrimFirst(s, c); } bool IsLastSlash(const std::wstring & path) { if( path.empty() ) return false; return path[path.size()-1] == '/'; } bool IsInt(const wchar_t * str, bool treat_new_line_as_white, bool allow_negative_value) { size_t digit = 0; str = SkipWhite(str, treat_new_line_as_white); if( allow_negative_value && *str == '-' ) str += 1; while( *str>='0' && *str<='9' ) { digit += 1; str += 1; } if( digit == 0 ) return false; str = SkipWhite(str, treat_new_line_as_white); if( *str != 0 ) return false; return true; } bool IsInt(const wchar_t * str, bool treat_new_line_as_white) { return IsInt(str, treat_new_line_as_white, true); } bool IsInt(const std::wstring & str, bool treat_new_line_as_white) { return IsInt(str.c_str(), treat_new_line_as_white); } bool IsSize(const wchar_t * str, bool treat_new_line_as_white) { return IsInt(str, treat_new_line_as_white, false); } bool IsSize(const std::wstring & str, bool treat_new_line_as_white) { return IsSize(str.c_str(), treat_new_line_as_white); } bool IsFloat(const wchar_t * str, bool treat_new_line_as_white) { size_t digit = 0; size_t comma = 0; str = SkipWhite(str, treat_new_line_as_white); if( *str == '-' ) str += 1; while( (*str == ',' || *str == '.') || (*str>='0' && *str<='9') ) { if( *str == ',' || *str == '.' ) comma += 1; else digit += 1; str += 1; } if( comma > 1 || digit == 0 ) return false; str = SkipWhite(str, treat_new_line_as_white); if( *str != 0 ) return false; return true; } bool IsFloat(const std::wstring & str, bool treat_new_line_as_white) { return IsFloat(str.c_str(), treat_new_line_as_white); } void Overwrite(std::string & str) { for(char & c : str) c = 0; } void Overwrite(std::wstring & str) { for(wchar_t & c : str) c = 0; } bool IsEmailCorrectChar(wchar_t c) { bool correct = false; const wchar_t * allowed_chars = L"@.!#$%&'*+-/=?^_`{|}~"; if( (c >= 'A' && c<='Z') || (c >= 'a' && c<='z') || (c >= '0' && c<='9') ) { correct = true; } else { for(size_t a=0 ; allowed_chars[a] != 0 ; ++a) { if( c == allowed_chars[a] ) { correct = true; break; } } } return correct; } bool ValidateEmail(const wchar_t * email) { int at = 0; // how many '@' int dots_after_at = 0; // how many dots in the domain part for(size_t i=0 ; email[i] != 0 ; ++i) { if( !IsEmailCorrectChar(email[i]) ) return false; if( email[i] == '@' ) ++at; if( email[i] == '.' && at > 0 ) ++dots_after_at; } if( at != 1 || dots_after_at == 0 ) return false; return true; } bool ValidateEmail(const std::wstring & email) { return ValidateEmail(email.c_str()); } bool IsFile(const wchar_t * file) { struct stat sb; char file_name[WINIX_OS_PATH_SIZE]; if( !wide_to_utf8(file, file_name, WINIX_OS_PATH_SIZE) ) return false; return (stat(file_name, &sb) == 0); } bool IsFile(const std::wstring & file) { return IsFile(file.c_str()); } /* * group can be -1 (it is not used then) */ bool CreateDir(const wchar_t * dir, int priv, int group) { char dir_name[WINIX_OS_PATH_SIZE]; if( !IsFile(dir) ) { if( !wide_to_utf8(dir, dir_name, WINIX_OS_PATH_SIZE) ) return false; if( mkdir(dir_name, 0777) < 0 ) { //log << log1 << "Can't create a directory on fs: " << dir << logend; return false; } return SetPriv(dir, priv, group); } return true; } bool CreateDir(const std::wstring & dir, int priv, int group) { return CreateDir(dir.c_str(), priv, group); } // creating directories (can be more than one) // 'dirs' can begin with a slash (will be skipped) bool CreateDirs(const wchar_t * base_dir, const wchar_t * dirs, int priv, int group, bool skip_last) { static std::wstring temp; // !! IMPROVE ME change to char[WINIX_OS_PATH_SIZE] or just remove 'static' const wchar_t * p = dirs; temp = base_dir; // we start creating from 'base_dir' if( temp.empty() ) return false; if( temp[temp.size()-1] != '/' ) temp += '/'; while( true ) { // skipping slashes for( ; *p=='/' ; ++p ); if( *p == 0 ) break; // taking the name for( ; *p!=0 && *p!='/' ; ++p ) temp += *p; if( !skip_last || *p!=0 ) if( !CreateDir(temp.c_str(), priv, group) ) return false; temp += '/'; } return true; } bool CreateDirs(const std::wstring & base_dir, const std::wstring & dirs, int priv, int group, bool skip_last) { return CreateDirs(base_dir.c_str(), dirs.c_str(), priv, group, skip_last); } int GetGroupId(const wchar_t * name) { struct group gr; struct group * result; char group_name[WINIX_OS_USERNAME_SIZE]; char buffer[512]; if( !wide_to_utf8(name, group_name, WINIX_OS_USERNAME_SIZE) ) return -1; if( getgrnam_r(group_name, &gr, buffer, sizeof(buffer)/sizeof(char), &result) != 0 ) { //log << log1 << "Misc: I cannot get the group_id for group name: " << name << logend; return -1; } /* * there is no such a group in /etc/group */ if( result == 0 ) { //log << log1 << "Misc: There is no a group with name: " << name << logend; return -1; } return gr.gr_gid; } int GetGroupId(const std::wstring & name) { return GetGroupId(name.c_str()); } /* * setting priveleges and a group id on a file or on a directory * group can be -1 (it is not used then) */ bool SetPriv(const wchar_t * name, int priv, int group) { char file_name[WINIX_OS_PATH_SIZE]; if( !wide_to_utf8(name, file_name, WINIX_OS_PATH_SIZE) ) return false; if( chmod(file_name, priv) < 0 ) { //log << log1 << "Misc: Can't set proper fs privileges on: " << name << logend; return false; } if( group != -1 ) { if( chown(file_name, geteuid(), group) < 0 ) { //log << log1 << "Can't set proper fs group on: " << name // << ", group id was: " << group << logend; return false; } } return true; } bool SetPriv(const std::wstring & name, int priv, int group) { return SetPriv(name.c_str(), priv, group); } bool CopyFile(FILE * in, FILE * out) { char buf[1024]; size_t buflen = sizeof(buf)/sizeof(char); size_t len; do { len = fread(buf, 1, buflen, in); if( len > 0 ) fwrite(buf, 1, len, out); if( ferror(in) || ferror(out) ) return false; } while( !feof(in) ); return true; } bool CopyFile(const wchar_t * src, const wchar_t * dst) { char src_name[WINIX_OS_PATH_SIZE]; char dst_name[WINIX_OS_PATH_SIZE]; FILE * in, * out; if( !wide_to_utf8(src, src_name, WINIX_OS_PATH_SIZE) ) return false; if( !wide_to_utf8(dst, dst_name, WINIX_OS_PATH_SIZE) ) return false; in = fopen(src_name, "rb"); if( !in ) return false; out = fopen(dst_name, "wb"); if( !out ) { fclose(in); return false; } bool res = CopyFile(in, out); fclose(in); fclose(out); if( res && ferror(out) ) res = false; if( !res ) remove(dst_name); return res; } bool CopyFile(const std::wstring & src, const std::wstring & dst) { return CopyFile(src.c_str(), dst.c_str()); } bool RemoveFile(const wchar_t * file) { char file_name[WINIX_OS_PATH_SIZE]; if( !wide_to_utf8(file, file_name, WINIX_OS_PATH_SIZE) ) return false; return unlink(file_name) == 0; } bool RemoveFile(const std::wstring & file) { return RemoveFile(file.c_str()); } bool RenameFile(const wchar_t * from, const wchar_t * to) { char from_name[WINIX_OS_PATH_SIZE]; char to_name[WINIX_OS_PATH_SIZE]; if( !wide_to_utf8(from, from_name, WINIX_OS_PATH_SIZE) ) return false; if( !wide_to_utf8(to, to_name, WINIX_OS_PATH_SIZE) ) return false; return rename(from_name, to_name) == 0; } bool RenameFile(const std::wstring & from, const std::wstring & to) { return RenameFile(from.c_str(), to.c_str()); } bool GetUTF8File(const wchar_t * file_path, std::wstring & content, bool clear_content) { char file[WINIX_OS_PATH_SIZE]; std::ifstream get_file_content; if( clear_content ) content.clear(); if( !wide_to_utf8(file_path, file, WINIX_OS_PATH_SIZE) ) return false; get_file_content.open(file, std::ios_base::in | std::ios_base::binary); if( !get_file_content ) return false; /* * we don't report any errors when converting from UTF8 to wide characters here */ pt::utf8_to_wide(get_file_content, content); get_file_content.close(); return true; } bool GetUTF8File(const std::wstring & file_path, std::wstring & content, bool clear_content) { return GetUTF8File(file_path.c_str(), content, clear_content); } bool GetBinaryFile(const wchar_t * file_path, BinaryPage & content, bool clear_content) { char file[WINIX_OS_PATH_SIZE]; char buffer[4096]; size_t buffer_len = sizeof(buffer) / sizeof(char); std::ifstream get_file_content; if( clear_content ) content.clear(); if( !wide_to_utf8(file_path, file, WINIX_OS_PATH_SIZE) ) return false; get_file_content.open(file, std::ios_base::in | std::ios_base::binary); if( !get_file_content ) return false; do { get_file_content.read(buffer, buffer_len); content.write(buffer, get_file_content.gcount()); } while( !get_file_content.eof() && get_file_content.good() ); get_file_content.close(); return true; } bool GetBinaryFile(const std::wstring & file_path, BinaryPage & content, bool clear_content) { return GetBinaryFile(file_path.c_str(), content, clear_content); } // if there is no an extension it returns a pointer to the last '\0' character const wchar_t * GetFileExt(const wchar_t * name) { const wchar_t * dot_ptr = nullptr; for( ; *name != 0 ; ++name) { if( *name == '.' ) { dot_ptr = name; } } return dot_ptr ? dot_ptr + 1 : name; } void PrepareNewFileName(const wchar_t * src, const wchar_t * postfix, std::wstring & res, bool clear_res) { bool has_ext = false; const wchar_t * ext = GetFileExt(src); if( clear_res ) res.clear(); size_t len = ext - src; if( len > 0 ) { if( *(ext-1) == '.' ) { len -= 1; has_ext = true; } } res.append(src, len); res.append(postfix); if( has_ext ) res.append(1, '.'); res.append(ext); } void PrepareNewFileName(const std::wstring & src, const std::wstring & postfix, std::wstring & res, bool clear_res) { return PrepareNewFileName(src.c_str(), postfix.c_str(), res, clear_res); } int SelectFileType(const wchar_t * file_name) { const wchar_t * ext = GetFileExt(file_name); // as an image we're using only those types which can be rendered // by a web browser if( pt::is_equal_nc(ext, L"jpg") || pt::is_equal_nc(ext, L"jpeg") || pt::is_equal_nc(ext, L"jpe") || pt::is_equal_nc(ext, L"pic") || pt::is_equal_nc(ext, L"tga") || pt::is_equal_nc(ext, L"gif") || pt::is_equal_nc(ext, L"bmp") || pt::is_equal_nc(ext, L"png") ) return WINIX_ITEM_FILETYPE_IMAGE; if( pt::is_equal_nc(ext, L"pdf") || pt::is_equal_nc(ext, L"doc") || pt::is_equal_nc(ext, L"xls") || pt::is_equal_nc(ext, L"txt") || pt::is_equal_nc(ext, L"ods") || pt::is_equal_nc(ext, L"odt") ) return WINIX_ITEM_FILETYPE_DOCUMENT; if( pt::is_equal_nc(ext, L"avi") || pt::is_equal_nc(ext, L"mp4") || pt::is_equal_nc(ext, L"flv") || pt::is_equal_nc(ext, L"mpg") || pt::is_equal_nc(ext, L"mpeg") || pt::is_equal_nc(ext, L"mkv") || pt::is_equal_nc(ext, L"wmv") ) return WINIX_ITEM_FILETYPE_VIDEO; return WINIX_ITEM_FILETYPE_UNKNOWN; } int SelectFileType(const std::wstring & file_name) { return SelectFileType(file_name.c_str()); } void UrlEncode(const char * in, std::string & out, bool clear_out) { if( clear_out ) out.clear(); pt::TextStream stream; for(size_t i=0 ; in[i] != 0 ; ++i) { UrlEncode(in[i], stream, true); for(size_t s=0 ; s < stream.size() ; ++s) out += stream[s]; } } void UrlEncode(const std::string & in, std::string & out, bool clear_out) { UrlEncode(in.c_str(), out, clear_out); } //void UrlEncode(const wchar_t * in, std::string & out, bool clear_out) //{ // if( clear_out ) // out.clear(); // // pt::TextStream stream; // // for(size_t i=0 ; in[i] != 0 ; ++i) // { // UrlEncode(in[i], stream, true); // // for(size_t s=0 ; s < stream.size() ++i) // out += stream[s]; // } //} //void UrlEncode(const std::wstring & in, std::string & out, bool clear_out) //{ // UrlEncode(in.c_str(), out, clear_out); //} void UrlEncode(const wchar_t * in, std::wstring & out, bool clear_out) { if( clear_out ) out.clear(); pt::WTextStream stream; for(size_t i=0 ; in[i] != 0 ; ++i) { UrlEncode(in[i], stream, true); for(size_t s=0 ; s < stream.size() ; ++s) out += stream[s]; } } void UrlEncode(const std::wstring & in, std::wstring & out, bool clear_out) { UrlEncode(in.c_str(), out, clear_out); } void UrlEncode(const pt::TextStream & in, pt::TextStream & out, bool clear_out) { if( clear_out ) out.clear(); for(size_t i=0 ; i < in.size() ; ++i) UrlEncode(in.get_char(i), out, false); } void UrlEncode(const pt::WTextStream & in, pt::WTextStream & out, bool clear_out) { if( clear_out ) out.clear(); for(size_t i=0 ; i < in.size() ; ++i) UrlEncode(in.get_wchar(i), out, false); } bool UrlDecodeFromHex(int c, int & out) { if( c>='0' && c<='9' ) { out = c - '0'; return true; } else if( c>='a' && c<='f' ) { out = c - 'a' + 10; return true; } else if( c>='A' && c<='F' ) { out = c - 'A' + 10; return true; } out = 0; return false; } bool UrlDecode(const char * url, std::wstring & out, bool clear_out) { char url_utf8[WINIX_URL_MAX_SIZE]; size_t index = 0; int c1, c2; if( clear_out ) out.clear(); while( *url && index < WINIX_URL_MAX_SIZE-1 ) { if( *url == '%' && *(url+1) && *(url+2) && UrlDecodeFromHex(*(url+1), c1) && UrlDecodeFromHex(*(url+2), c2) ) { url_utf8[index++] = (c1 << 4) + c2; url += 3; } else { url_utf8[index++] = *url; url += 1; } } url_utf8[index] = 0; return pt::utf8_to_wide(url_utf8, out, false); } bool UrlDecode(const std::string & url, std::wstring & out, bool clear_out) { return UrlDecode(url.c_str(), out, clear_out); } void QEncode(const std::wstring & in, std::string & out, bool clear) { using namespace misc_private; tmp_qencode.clear(); QEncode(in, tmp_qencode); tmp_qencode.to_str(out, clear); tmp_qencode.clear(); } /* deleting all post temporary files */ void RemovePostFileTmp(PostFileTab & post_file_tab) { PostFileTab::iterator i = post_file_tab.begin(); for( ; i != post_file_tab.end() ; ++i ) { const std::wstring & tmp_filename = i->second.tmp_filename; if( !tmp_filename.empty() && RemoveFile(tmp_filename) ) { //log << log3 << "Deleted tmp file: " << tmp_filename << logend; } } } void JSONescapeStream(const pt::WTextStream & in, pt::WTextStream & out) { pt::WTextStream::const_iterator i = in.begin(); for( ; i != in.end() ; ++i) { JSONescape(*i, out); } } void JSONescapeStream(const std::wstring & in, pt::WTextStream & out) { std::wstring::const_iterator i = in.begin(); for( ; i != in.end() ; ++i) { JSONescape(*i, out); } } bool wide_to_utf8(const wchar_t * wide_string, char * utf8, size_t utf8_size) { bool res = pt::wide_to_utf8(wide_string, utf8, utf8_size); if( !res ) { /* * either the 'utf8' buffer is too small or there was an error when converting */ //log << log1 << "Misc: I cannot convert from a wide string to an UTF-8 string, original string was: " // << wide_string << logend; } return res; } bool wide_to_utf8(const std::wstring & wide_string, char * utf8, size_t utf8_size) { return wide_to_utf8(wide_string.c_str(), utf8, utf8_size); } void calculate_timespec_diff(timespec & start, timespec & stop, timespec & result) { /* * copied from macro timespecsub(tsp, usp, vsp) which is defined in sys/time.h */ result.tv_sec = stop.tv_sec - start.tv_sec; result.tv_nsec = stop.tv_nsec - start.tv_nsec; if( result.tv_nsec < 0 ) { result.tv_sec--; result.tv_nsec += 1000000000L; } } double timespec_to_double(timespec & val) { double val_double = val.tv_sec + val.tv_nsec / 1000000000.0; return val_double; } void timespec_to_stream(timespec & val, pt::Stream & stream) { char buf[50]; double val_double = timespec_to_double(val); sprintf(buf, "%f", val_double); SetNonZeroDigitsAfterComma(buf, 2); stream << buf; } void timespec_to_stream_with_unit(timespec & val, pt::Stream & stream) { char buf[50]; bool is_ms = false; double val_double = timespec_to_double(val); if( val_double < 0.1 ) { is_ms = true; val_double = val_double * 1000; } sprintf(buf, "%f", val_double); SetNonZeroDigitsAfterComma(buf, 2); stream << buf; if( is_ms ) { stream << "ms"; } else { stream << "s"; } } void slice_by(const std::wstring & str, wchar_t c, std::vector & out) { std::wstring tmp; for(size_t i = 0 ; i < str.size() ; ++i) { if( str[i] == c ) { if( !tmp.empty() ) { out.push_back(tmp); tmp.clear(); } } else { tmp += str[i]; } } if( !tmp.empty() ) { out.push_back(tmp); } } } // namespace Winix