winix/core/misc.cpp

660 lines
11 KiB
C++
Executable File

/*
* This file is a part of CMSLU -- Content Management System like Unix
* and is not publicly distributed
*
* Copyright (c) 2008-2009, Tomasz Sowa
* All rights reserved.
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include "misc.h"
#include "log.h"
#include "data.h"
void ToString(std::string & s, int value)
{
static char buffer[50];
sprintf(buffer, "%d", value);
s = buffer;
}
void ToString(std::string & s, long value)
{
static char buffer[50];
sprintf(buffer, "%ld", value);
s = buffer;
}
bool CorrectUrlChar(char c)
{
if( (c >= 'a' && c <='z') ||
(c >= 'A' && c <='Z') ||
(c >= '0' && c <='9') ||
(c == '(' || c == ')' || c == '.' || c == ',' || c == '_' )
)
{
return true;
}
return false;
}
// 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::string & 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] = '_';
was_dot = true;
}
}
}
void CorrectUrlChars(std::string & url)
{
std::string::iterator i;
for(i=url.begin(); i != url.end() ; ++i)
{
if( !CorrectUrlChar(*i) )
{
int c = ChangeLocalChar(*i);
if( CorrectUrlChar(c) )
*i = c;
else
*i = '_';
}
}
}
void CorrectUrlOnlyAllowedChar(std::string & url)
{
CorrectUrlDots(url);
CorrectUrlChars(url);
ToSmall(url);
Trim(url, '_');
if( url.empty() || url == "." )
{
if( data.item_url_empty.empty() )
url = "unnamed";
else
{
url = data.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(), '_');
}
int polish_letters_simple[] =
{ 'a', 'A',
'c', 'C',
's', 'S',
'e', 'E',
'l', 'L',
'o', 'O',
'z', 'Z',
'z', 'Z',
'n', 'N', 0 }; // 0 - terminating
int polish_letters_iso88592[] =
{ 0xb1, 0xa1,
0xe6, 0xc6,
0xb6, 0xa6,
0xea, 0xca,
0xb3, 0xa3,
0xf3, 0xd3,
0xbf, 0xaf,
0xbc, 0xac,
0xf1, 0xd1, 0 };
int ChangeLocalChar(unsigned char c)
{
// if( language == polish_iso88592 )
for(int i = 0 ; polish_letters_iso88592[i] ; ++i)
{
if( polish_letters_simple[i] == 0 )
{
log << log1 << "localization tables don't have the same size" << logend;
return c;
}
if( polish_letters_iso88592[i] == c )
return polish_letters_simple[i];
}
return c;
}
bool HtmlTryChar(std::ostringstream & out, int c)
{
if( c == '<' )
{
out << "&lt;";
return true;
}
else
if( c == '>' )
{
out << "&gt;";
return true;
}
else
if( c == '&' )
{
out << "&amp;";
return true;
}
return false;
}
void HtmlEscape(std::ostringstream & out, const std::string & in)
{
std::string::const_iterator i;
for(i = in.begin() ; i != in.end() ; ++i)
{
if( !HtmlTryChar(out, *i) )
out << *i;
}
}
std::string HtmlEscape(const std::string & in)
{
std::ostringstream out;
HtmlEscape(out, in);
return out.str();
}
void HtmlEscapeFormTxt(std::ostringstream & out, const std::string & in)
{
std::string::const_iterator i;
int was_enter = 0; // how many enteres there were before
if( in.empty() )
return;
out << "<p>";
// skipping first new line characters
for(i = in.begin() ; i != in.end() && (*i==13 || *i==10) ; ++i);
for( ; i != in.end() ; ++i )
{
if( *i == 13 ) // skipping stupid characters (\r\n\ in dos mode)
continue;
if( *i == 10 )
{
++was_enter;
}
else
{
if( was_enter == 1 )
out << "<br>\n";
else
if( was_enter > 1 )
out << "</p>\n<p>";
was_enter = 0;
}
if( !HtmlTryChar(out, *i) )
out << *i;
}
out << "</p>\n";
}
std::string HtmlEscapeFormTxt(const std::string & in)
{
std::ostringstream out;
HtmlEscapeFormTxt(out, in);
return out.str();
}
const char * DateToStr(int year, int month, int day)
{
static const char * month_letter[] = { "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII" };
static char buffer[100];
--month;
if( month < 0 )
month = 0;
if( month > 11 )
month = 11;
if( year == 0 )
sprintf(buffer, "%s %02d", month_letter[month], day);
else
sprintf(buffer, "%02d %s %02d", year, month_letter[month], day);
// warning: not thread safe (we do not use threads)
return buffer;
}
const char * DateToStr(int year, int month, int day, int hour, int min, int sec)
{
static const char * month_letter[] = { "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII" };
static char buffer[100];
--month;
if( month < 0 )
month = 0;
if( month > 11 )
month = 11;
if( year == 0 )
sprintf(buffer, "%s %02d %02d:%02d:%02d", month_letter[month], day, hour, min, sec);
else
sprintf(buffer, "%02d %s %02d %02d:%02d:%02d", year, month_letter[month], day, hour, min, sec);
// warning: not thread safe (we do not use threads)
return buffer;
}
const char * DateToStr(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 char * DateToStr(time_t t)
{
tm * ptm = std::localtime(&t);
return DateToStr(ptm);
}
// 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(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(time_t t)
{
tm * ptm = std::localtime(&t);
return DateToStrCookie(ptm);
}
const char * IpToStr(unsigned int ip_)
{
static char buffer[100];
union
{
unsigned int ip;
unsigned char c[4];
} ip;
ip.ip = ip_;
sprintf(buffer, "%u.%u.%u.%u", (int)ip.c[0], (int)ip.c[1], (int)ip.c[2], (int)ip.c[3]);
return buffer;
}
const char * ToStr(int value)
{
static char buffer[100];
sprintf(buffer, "%d", value);
return buffer;
}
bool IsWhite(int s)
{
if( s==' ' || s=='\t' || s==13 )
return true;
return false;
}
void TrimWhite(std::string & s)
{
std::string::size_type i;
if( s.empty() )
return;
// looking for white characters at the end
for(i=s.size()-1 ; i>0 && IsWhite(s[i]) ; --i);
if( i==0 && IsWhite(s[i]) )
{
// 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::string::npos);
// looking for white characters at the beginning
for(i=0 ; i<s.size() && IsWhite(s[i]) ; ++i);
// deleting white characters at the beginning
if( i != 0 )
s.erase(0, i);
}
void Trim(std::string & s, char c)
{
std::string::size_type 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::string::npos);
// 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);
}
const char * SkipWhite(const char * s)
{
while( IsWhite(*s) )
++s;
return s;
}
int ToSmall(int c)
{
if( c>='A' && c<='Z' )
c = c - 'A' + 'a';
return c;
}
void ToSmall(std::string & s)
{
std::string::size_type i;
for(i=0 ; i<s.size() ; ++i)
s[i] = ToSmall(s[i]);
}
bool IsSubString(const char * short_str, const char * long_str)
{
while( *short_str && *long_str && *short_str == *long_str )
{
++short_str;
++long_str;
}
if( *short_str == 0 )
return true;
return false;
}
bool IsSubStringNoCase(const char * short_str, const char * long_str)
{
while( *short_str && *long_str && ToSmall(*short_str) == ToSmall(*long_str) )
{
++short_str;
++long_str;
}
if( *short_str == 0 )
return true;
return false;
}
bool EqualNoCase(const char * str1, const char * str2)
{
while( *str1 && *str2 && ToSmall(*str1) == ToSmall(*str2) )
{
++str1;
++str2;
}
if( *str1 == 0 && *str2 == 0 )
return true;
return false;
}
bool ValidateEmail(const std::string & email)
{
if( email.empty() )
return false;
bool correct = true;
size_t i;
char allowed_chars[] = "!#$%&'*+-/=?^_`{|}~.@";
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 char * file)
{
struct stat sb;
return (stat(file, &sb) == 0);
}
bool IsFile(const std::string & file)
{
return IsFile(file.c_str());
}
bool CreateDir(const char * dir, int priv)
{
if( !IsFile(dir) )
{
if( mkdir(dir, priv) < 0 )
{
log << log1 << "Can't create a directory on fs: " << dir << logend;
return false;
}
}
return true;
}
bool CreateDir(const std::string & dir, int priv)
{
return CreateDir(dir.c_str(), priv);
}
// if there is not an extension it returns a pointer to the last '\0' character
const char * GetFileExt(const char * 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;
}
Item::StaticAuth SelectFileType(const char * file_name)
{
const char * ext = GetFileExt(file_name);
// as an image we're using only those types which can be rendered
// by a web browser
if( EqualNoCase(ext, "jpg") ||
EqualNoCase(ext, "gif") ||
EqualNoCase(ext, "png") )
return Item::static_image;
if( EqualNoCase(ext, "pdf") ||
EqualNoCase(ext, "doc") ||
EqualNoCase(ext, "xls") ||
EqualNoCase(ext, "txt") ||
EqualNoCase(ext, "ods") ||
EqualNoCase(ext, "odt") )
return Item::static_document;
return Item::static_other;
}