Files
winix/winixd/core/misc.cpp
Tomasz Sowa f7b5ac0dc8 change the way how winix answer is created
Now we can return ezc content and models serialized in the same json structure,
Xml and Csv are not implemented yet.
Ezc frames are returned in 'ezc_frames' field.
Main ezc stream is returned in 'main_stream' field.
Frame url parameter can take more than one frame (names separated by commas).
Honor Accept http header (AcceptParser).

Samples:
--------
http://domain.tld/dir/controller
returns html answer from the main ezc stream

http://domain.tld/dir/controller/container:raw
returns html answer from the main ezc stream (the same as above)

http://domain.tld/dir/controller/frame:abc
returns "abc" frame as html

http://domain.tld/dir/controller/container:json
returns all serialized models to json and no ezc streams

http://domain.tld/dir/controller/container:xml
returns all serialized models to xml and no ezc streams (not implemented yet)

http://domain.tld/dir/controller/container:json/frame:abc,xyz
returns all serialized models to json and two frames in 'ezc_frames' object

http://domain.tld/dir/controller/container:json/all_frames
returns all serialized models to json and all frames in 'ezc_frames' object

http://domain.tld/dir/controller/container:json/main_stream
returns all serialized models and the main ezc stream in 'main_stream' field

http://domain.tld/dir/controller/container:json/main_stream/all_frames
returns all serialized models to json, all frames and the main stream
2022-02-01 18:44:23 +01:00

1637 lines
29 KiB
C++

/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* 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 <sys/types.h>
#include <sys/stat.h>
#include <grp.h>
#include <fstream>
#include <cstdlib>
#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<int>(strtol(str, 0, base));
}
int Toi(const wchar_t * str, int base)
{
return static_cast<int>(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<unsigned long>(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<long>(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<unsigned int>(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 ; i<s.size() && IsWhite(s[i], trim_new_line_too) ; ++i);
// deleting white characters at the beginning
if( i != 0 )
s.erase(0, i);
}
const wchar_t * SkipWhite(const wchar_t * s, bool treat_new_line_as_white)
{
while( IsWhite(*s, treat_new_line_as_white) )
++s;
return s;
}
void TrimFirst(std::wstring & s, wchar_t c)
{
size_t i;
if( s.empty() )
return;
// looking for the 'c' characters at the beginning
for(i=0 ; i<s.size() && s[i]==c ; ++i);
// deleting the 'c' characters at the beginning
if( i != 0 )
s.erase(0, i);
}
void TrimLast(std::wstring & s, wchar_t c)
{
size_t i;
if( s.empty() )
return;
// looking for the 'c' characters at the end
for(i=s.size()-1 ; i>0 && 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<std::wstring> & 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