winix/core/misc.cpp

1095 lines
18 KiB
C++
Executable File

/*
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2011, Tomasz Sowa
* All rights reserved.
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fstream>
#include "misc.h"
#include "log.h"
#include "templates/templates.h"
#include "utf8.h"
namespace misc_private
{
std::ifstream get_file_content;
std::string get_file_content_ansi;
}
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);
}
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];
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];
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 AssignString(const char * src, size_t len, std::wstring & dst, bool clear)
{
if( clear )
dst.clear();
if( dst.capacity() < dst.size() + len )
dst.reserve(dst.size() + len + 128);
for(size_t i=0 ; i<len ; ++i )
dst += static_cast<unsigned char>(src[i]);
}
void AssignString(const char * src, std::wstring & dst, bool clear)
{
size_t len;
for(len=0 ; src[len] ; ++len){}
AssignString(src, len, dst, clear);
}
void AssignString(const std::string & src, std::wstring & dst, bool clear)
{
AssignString(src.c_str(), src.size(), dst, clear);
}
void AssignString(const wchar_t * src, size_t len, std::string & dst, bool clear)
{
if( clear )
dst.clear();
if( dst.capacity() < dst.size() + len )
dst.reserve(dst.size() + len + 128);
for(size_t i=0 ; i<len ; ++i)
dst += static_cast<char>(src[i]);
}
void AssignString(const wchar_t * src, std::string & dst, bool clear)
{
size_t len;
for(len=0 ; src[len] ; ++len){}
AssignString(src, len, dst, clear);
}
void AssignString(const std::wstring & src, std::string & dst, bool clear)
{
AssignString(src.c_str(), src.size(), dst, clear);
}
void AssignString(const char * src, size_t len, std::string & dst, bool clear)
{
if( clear )
dst.clear();
// we suppose that append is smart enough and we don't have to use reserve()
dst.append(src, len);
}
void AssignString(const char * src, std::string & dst, bool clear)
{
size_t len;
for(len=0 ; src[len] ; ++len){}
AssignString(src, len, dst, clear);
}
void AssignString(const std::string & src, std::string & dst, bool clear)
{
if( clear )
dst.clear();
dst.append(src);
}
void AssignString(const wchar_t * src, size_t len, std::wstring & dst, bool clear)
{
if( clear )
dst.clear();
// we suppose that append is smart enough and we don't have to use reserve()
dst.append(src, len);
}
void AssignString(const wchar_t * src, std::wstring & dst, bool clear)
{
size_t len;
for(len=0 ; src[len] ; ++len){}
AssignString(src, len, dst, clear);
}
void AssignString(const std::wstring & src, std::wstring & dst, bool clear)
{
if( clear )
dst.clear();
dst.append(src);
}
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.Subst(*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);
ToSmall(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(), '_');
}
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;
}
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 tm * ptm)
{
return DateToStr(ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
}
const wchar_t * DateToStr(const tm & rtm)
{
return DateToStr(rtm.tm_year + 1900, rtm.tm_mon+1, rtm.tm_mday, rtm.tm_hour, rtm.tm_min, rtm.tm_sec);
}
const wchar_t * DateToStr(time_t t)
{
tm rtm = Time(t);
return DateToStr(rtm);
}
const wchar_t * DateToStrWithoutHours(const tm * ptm)
{
return DateToStr(ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday);
}
const wchar_t * DateToStrWithoutHours(const tm & rtm)
{
return DateToStr(rtm.tm_year + 1900, rtm.tm_mon+1, rtm.tm_mday);
}
const wchar_t * DateToStrWithoutHours(time_t t)
{
tm rtm = Time(t);
return DateToStrWithoutHours(rtm);
}
// 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 tm * ptm)
{
return DateToStrCookie(ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
}
const char * DateToStrCookie(const tm & rtm)
{
return DateToStrCookie(rtm.tm_year + 1900, rtm.tm_mon+1, rtm.tm_mday, rtm.tm_hour, rtm.tm_min, rtm.tm_sec);
}
const char * DateToStrCookie(time_t t)
{
tm rtm = Time(t);
return DateToStrCookie(rtm);
}
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;
}
bool IsWhite(wchar_t s)
{
if( s==' ' || s=='\t' || s==13 || s==160 )
return true;
return false;
}
const char * SkipWhite(const char * s)
{
while( IsWhite(*s) )
++s;
return s;
}
const wchar_t * SkipWhite(const wchar_t * s)
{
while( IsWhite(*s) )
++s;
return s;
}
wchar_t ToSmall(wchar_t c)
{
if( c>='A' && c<='Z' )
c = c - 'A' + 'a';
return c;
}
void ToSmall(std::wstring & s)
{
std::wstring::size_type i;
for(i=0 ; i<s.size() ; ++i)
s[i] = ToSmall(s[i]);
}
bool ValidateEmail(const std::wstring & email)
{
if( email.empty() )
return false;
bool correct = true;
size_t i;
wchar_t allowed_chars[] = L"!#$%&'*+-/=?^_`{|}~.@";
int at = 0;
for(i=0 ; i<email.length() && correct ; ++i)
{
correct = false;
if( (email[i] >= 'A' && email[i]<='Z') ||
(email[i] >= 'a' && email[i]<='z') ||
(email[i] >= '0' && email[i]<='9') )
{
correct = true;
}
else
{
for(size_t a=0 ; a < sizeof(allowed_chars)-1 ; ++a)
{
if( email[i] == allowed_chars[a] )
{
correct = true;
break;
}
}
}
if( email[i] == '@' )
++at;
}
if( at != 1 )
return false;
return correct;
}
bool IsFile(const wchar_t * file)
{
struct stat sb;
static std::string afile;
Ezc::WideToUTF8(file, afile);
return (stat(afile.c_str(), &sb) == 0);
}
bool IsFile(const std::wstring & file)
{
return IsFile(file.c_str());
}
bool CreateDir(const wchar_t * dir, int priv)
{
static std::string adir;
if( !IsFile(dir) )
{
Ezc::WideToUTF8(dir, adir);
if( mkdir(adir.c_str(), priv) < 0 )
{
log << log1 << "Can't create a directory on fs: " << adir << logend;
return false;
}
}
return true;
}
bool CreateDir(const std::wstring & dir, int priv)
{
return CreateDir(dir.c_str(), priv);
}
// 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, bool skip_last)
{
static std::wstring temp;
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) )
return false;
temp += '/';
}
return true;
}
bool CreateDirs(const std::wstring & base_dir, const std::wstring & dirs, int priv, bool skip_last)
{
return CreateDirs(base_dir.c_str(), dirs.c_str(), priv, skip_last);
}
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)
{
static std::string asrc, adst;
FILE * in, * out;
Ezc::WideToUTF8(src, asrc);
Ezc::WideToUTF8(dst, adst);
in = fopen(asrc.c_str(), "rb");
if( !in )
return false;
out = fopen(adst.c_str(), "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(adst.c_str());
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)
{
static std::string afile;
Ezc::WideToUTF8(file, afile);
return unlink(afile.c_str()) == 0;
}
bool RemoveFile(const std::wstring & file)
{
return RemoveFile(file.c_str());
}
bool RenameFile(const wchar_t * from, const wchar_t * to)
{
static std::string afrom, ato;
Ezc::WideToUTF8(from, afrom);
Ezc::WideToUTF8(to, ato);
return rename(afrom.c_str(), ato.c_str()) == 0;
}
bool RenameFile(const std::wstring & from, const std::wstring & to)
{
return RenameFile(from.c_str(), to.c_str());
}
bool GetUTF8File(const char * file_path, std::wstring & content, bool clear_content)
{
using namespace misc_private;
if( clear_content )
content.clear();
get_file_content.clear();
get_file_content.open(file_path, std::ios_base::in | std::ios_base::binary);
if( !get_file_content )
return false;
Ezc::UTF8ToWide(get_file_content, content);
get_file_content.close();
return true;
}
bool GetUTF8File(const wchar_t * file_path, std::wstring & content, bool clear_content)
{
using namespace misc_private;
Ezc::WideToUTF8(file_path, get_file_content_ansi);
return GetUTF8File(get_file_content_ansi.c_str(), content, clear_content);
}
bool GetUTF8File(const std::string & file_path, std::wstring & content, bool clear_content)
{
return GetUTF8File(file_path.c_str(), content, clear_content);
}
bool GetUTF8File(const std::wstring & file_path, std::wstring & content, bool clear_content)
{
return GetUTF8File(file_path.c_str(), content, clear_content);
}
// if there is not an extension it returns a pointer to the last '\0' character
const wchar_t * GetFileExt(const wchar_t * name)
{
size_t i, ilast;
// looking for the end of the name
for(i=0 ; name[i] != 0 ; ++i);
if( i == 0 )
return name; // ops, the name is empty
// remember the end of the string
ilast = i;
// looking for the last dot
for(--i ; i>0 && name[i] != '.' ; --i);
if( name[i] != '.' )
return name + ilast; // ops, there is not a dot
// the extensions starts from i+1
// and can be empty (if the last character is a dot)
return name + i + 1;
}
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( EqualNoCase(ext, L"jpg") ||
EqualNoCase(ext, L"jpeg") ||
EqualNoCase(ext, L"jpe") ||
EqualNoCase(ext, L"pic") ||
EqualNoCase(ext, L"tga") ||
EqualNoCase(ext, L"gif") ||
EqualNoCase(ext, L"bmp") ||
EqualNoCase(ext, L"png") )
return WINIX_ITEM_FILETYPE_IMAGE;
if( EqualNoCase(ext, L"pdf") ||
EqualNoCase(ext, L"doc") ||
EqualNoCase(ext, L"xls") ||
EqualNoCase(ext, L"txt") ||
EqualNoCase(ext, L"ods") ||
EqualNoCase(ext, L"odt") )
return WINIX_ITEM_FILETYPE_DOCUMENT;
return WINIX_ITEM_FILETYPE_UNKNOWN;
}
int SelectFileType(const std::wstring & file_name)
{
return SelectFileType(file_name.c_str());
}
time_t Time(const tm & par)
{
tm t;
memset(&t, 0, sizeof(t));
t.tm_year = par.tm_year;
t.tm_mon = par.tm_mon;
t.tm_mday = par.tm_mday;
t.tm_hour = par.tm_hour;
t.tm_min = par.tm_min;
t.tm_sec = par.tm_sec;
return timegm(&t);
}
time_t Time(const tm * par)
{
return Time(*par);
}
tm Time(time_t par)
{
tm * ptm = gmtime(&par);
tm res;
memset(&res, 0, sizeof(res));
if( ptm )
{
res.tm_year = ptm->tm_year;
res.tm_mon = ptm->tm_mon;
res.tm_mday = ptm->tm_mday;
res.tm_hour = ptm->tm_hour;
res.tm_min = ptm->tm_min;
res.tm_sec = ptm->tm_sec;
}
return res;
}
void UrlEncode(const std::string & in, std::string & out, bool clear_out)
{
char buffer[10];
if( clear_out )
out.clear();
for(size_t i=0 ; i<in.size() ; ++i)
{
if( (in[i] >= 'a' && in[i] <= 'z') ||
(in[i] >= 'A' && in[i] <= 'Z') ||
(in[i] >= '0' && in[i] <= '9') ||
in[i] == '.' || in[i] == ',' || in[i] == '/' || in[i] == ':' || in[i] == '#' ||
in[i] == '-' || in[i] == '_' || in[i] == '(' || in[i] == ')' )
{
out += in[i];
}
else
{
Toa(static_cast<unsigned char>(in[i]), buffer, 10, 16);
out += '%';
if( buffer[1] == 0 )
out += '0'; // there is only one characters in the buffer
out += buffer;
}
}
}
void UrlEncode(const std::wstring & in, std::string & out, bool clear_out)
{
static std::string ain;
Ezc::WideToUTF8(in, ain);
UrlEncode(ain, out, clear_out);
}
void QEncodeAddChar(wchar_t c, std::string & out)
{
if( (c>='A' && c<='Z') ||
(c>='a' && c<='z') ||
(c>='0' && c<='9') )
{
out += char(c);
}
else
{
char buf1[10];
char buf2[10];
size_t len1 = sizeof(buf1) / sizeof(char);
size_t len2 = sizeof(buf2) / sizeof(char);
size_t len = Ezc::IntToUTF8(int(c), buf1, len1);
for(size_t i=0 ; i<len ; ++i)
{
// make sure that it produces *capital* letters (ABC...)
Toa((unsigned long)(unsigned char)buf1[i], buf2, len2, 16);
out += '=';
out += buf2;
}
}
}
/*
this encoding is used in mails headers
encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
http://www.faqs.org/rfcs/rfc1522.html
we have:
charset = UTF-8
encoding = Q
current limitation:
we do not support checking the maximum length:
"An encoded-word may not be more than 75 characters long, including
charset, encoding, encoded-text, and delimiters."
*/
void QEncode(const std::wstring & in, std::string & out, bool clear)
{
if( clear )
out.clear();
out += "=?UTF-8?Q?";
for(size_t i=0 ; i<in.size() ; ++i)
QEncodeAddChar(in[i], out);
out += "?=";
}
/*
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;
else
if( !tmp_filename.empty() )
log << "swinka" << logend; //!!usunac
}
}