winix/functions/functions.cpp

578 lines
11 KiB
C++
Raw Normal View History

/*
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010, Tomasz Sowa
* All rights reserved.
*
*/
#include "functions.h"
#include "core/log.h"
#include "core/misc.h"
#include "core/plugin.h"
#include "templates/templates.h"
void Functions::SetConfig(Config * pconfig)
{
config = pconfig;
}
void Functions::SetRequest(Request * prequest)
{
request = prequest;
}
void Functions::SetDb(Db * pdb)
{
db = pdb;
}
void Functions::SetSystem(System * psystem)
{
system = psystem;
}
void Functions::SetTemplates(Templates * ptemplates)
{
templates = ptemplates;
}
void Functions::SetSynchro(Synchro * psynchro)
{
synchro = psynchro;
}
size_t Functions::FunctionsSize()
{
return table.size();
}
Functions::Iterator Functions::Begin()
{
return table.begin();
}
Functions::Iterator Functions::End()
{
return table.end();
}
FunctionBase * Functions::Find(const std::wstring & function_name)
{
Table::iterator i = table.find(function_name);
if( i == table.end() )
return 0;
return i->second;
}
void Functions::PrepareUrl(Item & item)
{
TrimWhite(item.url);
if( item.url.empty() )
item.url = item.subject; // if the subject is empty then the url will be corrected by CorrectUrlOnlyAllowedChar()
CorrectUrlOnlyAllowedChar(item.url);
if( Find(item.url) )
{
// the name provided by an user is the same as a name of a function
// we add one underscore character at the beginning
// names of functions should not begin with an underscore '_'
// and we can simply add one '_' at the beginning
// and the name will be unique
item.url.insert(item.url.begin(), '_');
}
}
Error Functions::CheckSpecialFile(const Item & item)
{
static std::wstring fstab = L"fstab";
Item * etc = system->dirs.GetEtcDir();
if( !etc )
return WINIX_NOTHING_TO_DO;
if( item.parent_id != etc->id )
return WINIX_NOTHING_TO_DO;
if( item.url == fstab )
{
log << log3 << "Functions: reloading mount points" << logend;
Error status = system->mounts.ReadMounts(item.content);
templates->ReadNewIndexTemplates();
return status;
}
return WINIX_NOTHING_TO_DO;
}
void Functions::SetObjects(FunctionBase * fun)
{
fun->SetConfig(config);
fun->SetRequest(request);
fun->SetDb(db);
fun->SetSystem(system);
fun->SetFunctions(this);
fun->SetTemplates(templates);
fun->SetSynchro(synchro);
}
void Functions::Add(FunctionBase * fun)
{
if( Find(fun->fun.url) )
{
log << log1 << "Functions: function " << fun->fun.url
<< " already exists (skipped)" << logend;
return;
}
fun->id = table.size();
SetObjects(fun);
table[fun->fun.url] = fun;
}
void Functions::Add(FunctionBase & fun)
{
Add(&fun);
}
void Functions::CreateFunctions()
{
Add(fun_adduser);
Add(fun_cat);
Add(fun_chmod);
Add(fun_chown);
Add(fun_ckeditor);
Add(fun_cp);
Add(fun_default);
Add(fun_download);
Add(fun_emacs);
Add(fun_last);
Add(fun_login);
Add(fun_logout);
Add(fun_ln);
Add(fun_ls);
Add(fun_mkdir);
Add(fun_mv);
Add(fun_node);
Add(fun_priv);
Add(fun_reload);
Add(fun_rm);
Add(fun_run);
Add(fun_special_default);
Add(fun_stat);
Add(fun_subject);
Add(fun_template);
Add(fun_tinymce);
Add(fun_uname);
Add(fun_upload);
Add(fun_uptime);
Add(fun_who);
Add(fun_vim);
plugin.Call(WINIX_CREATE_FUNCTIONS);
}
void Functions::InitFunctions()
{
Table::iterator i = table.begin();
for( ; i!=table.end() ; ++i)
i->second->Init();
}
void Functions::Init()
{
CreateFunctions();
InitFunctions();
}
void Functions::Parse()
{
function_parser.Parse(request, db, this, system);
}
void Functions::SetDefaultFunctionForFile()
{
if( request->item.file_type != WINIX_ITEM_FILETYPE_NONE )
request->function = &fun_download;
else
if( system->HasReadExecAccess(request->item) )
request->function = &fun_run;
else
request->function = &fun_cat;
log << log3 << "Functions: default function: " << request->function->fun.url << logend;
}
void Functions::SetDefaultFunctionForDir()
{
// !! nie potrzebne
// if( system->mounts.pmount->type == system->mounts.MountTypeThread() )
// request->function = &fun_thread;
// else
request->function = &fun_ls;
log << log3 << "Functions: default function: " << request->function->fun.url << logend;
}
void Functions::SetDefaultFunction()
{
request->function = 0;
plugin.Call(WINIX_SELECT_DEFAULT_FUNCTION);
if( request->function )
{
log << log3 << "Functions: default function: " << request->function->fun.url
<< " (set by a plugin)" << logend;
return;
}
if( request->is_item )
SetDefaultFunctionForFile();
else
SetDefaultFunctionForDir();
}
void Functions::CheckFunctionFollowDir(bool was_default_function)
{
// directory with 'default' flag
if( was_default_function )
{
if( request->dir_tab.back()->link_redirect == 1 )
{
system->RedirectTo(request->dir_tab.back()->link_to);
}
else
{
if( system->FollowAllLinks(request->dir_tab.back()->link_to, true, true) )
SetDefaultFunction();
}
}
}
void Functions::CheckFunctionFollowSymlink(bool was_default_function)
{
if( request->item.link_redirect == 1 )
{
if( was_default_function )
system->RedirectTo(request->item.link_to);
else
system->RedirectWithFunctionAndParamsTo(request->item.link_to);
}
else
if( system->FollowAllLinks(request->item.link_to, true, true) )
{
if( was_default_function )
SetDefaultFunction();
if( request->status == WINIX_ERR_OK && !request->redirect_to.empty() && !was_default_function && request->function )
{
// !! nie jestem pewny dodania tej nowej funkcji do redirecta... (sprawdzic to)
request->redirect_to += '/';
request->redirect_to += request->function->fun.url;
system->AddParams(request->param_tab, request->redirect_to, false);
}
}
}
// making a proper redirection from a directory with 'default' flag
// or from a symlink (or just loading it if there is no redirection flag set)
void Functions::CheckFunctionAndSymlink()
{
bool was_default_function = false;
if( !request->function || request->function == &fun_special_default )
{
was_default_function = true;
SetDefaultFunction();
}
if( request->status != WINIX_ERR_OK || !request->redirect_to.empty() )
return;
if( !request->is_item && !request->dir_tab.back()->link_to.empty() )
CheckFunctionFollowDir(was_default_function);
else
if( request->is_item && request->item.type == Item::symlink && request->function && request->function->follow_symlinks )
CheckFunctionFollowSymlink(was_default_function);
}
void Functions::MakeFunction()
{
if( !request->function )
{
request->status = WINIX_ERR_NO_FUNCTION;
log << log1 << "Functions: no function (neither cat nor ls)" << logend;
return;
}
if( !system->DirsHaveReadExecPerm() ||
!system->HasReadExecAccess(request->function->fun) ||
!request->function->HasAccess() )
{
request->status = WINIX_ERR_PERMISSION_DENIED;
return;
}
if( request->method == Request::get )
{
if( request->redirect_to.empty() )
request->function->MakeGet();
}
else
if( request->method == Request::post )
{
// we don't use post with redirecting (the post variables would be lost)
if( request->redirect_to.empty() )
request->function->MakePost();
else
request->status = WINIX_ERR_PERMISSION_DENIED;
}
else
if( request->method == Request::head )
{
// do nothing
}
else
log << log1 << "Functions: unknown request method (skipping)" << logend;
}
void Functions::CheckGetPostTimes(time_t difference)
{
time_t now = std::time(0);
if( request->session->puser )
return;
if( request->method != Request::post )
return;
if( now - request->session->last_time_get >= (time_t)difference )
return;
if( request->AllPostVarEmpty() )
return;
request->session->spam_score += 1;
log << log1 << "Functions: spam +1: POST after GET sent too fast" << logend;
}
// !!uwaga zwracana warto<74><6F> zmieniona (true/false)
bool Functions::CheckAbuse()
{
if( !system->rebus.CheckRebus() )
{
request->status = WINIX_ERR_INCORRECT_REBUS;
return true;
}
CheckGetPostTimes();
if( request->session->spam_score > 0 )
{
request->status = WINIX_ERR_SPAM;
log << log1 << "Functions: ignoring due to suspected spamming" << logend;
return true;
}
return false;
}
// returning true if the 'url' has to be changed
void Functions::ReadItemUrlSubject(Item & item, Item::Type item_type)
{
std::wstring * new_subject = request->PostVarp(L"subject");
std::wstring * new_url = request->PostVarp(L"url");
if( new_subject )
item.subject = *new_subject;
if( item.subject.empty() )
{
item.subject = request->dir_tab.back()->subject;
item.subject += L"_msg_";
added: uptime winix function prints how many sessions there are changed: functions for text/numbers conversions int Toi(const std::string & str, int base = 10); int Toi(const std::wstring & str, int base = 10); int Toi(const char * str, int base = 10); int Toi(const wchar_t * str, int base = 10); long Tol(const std::string & str, int base = 10); long Tol(const std::wstring & str, int base = 10); long Tol(const char * str, int base = 10); long Tol(const wchar_t * str, int base = 10); template<class CharType> bool Toa(unsigned long value, CharType * buffer, size_t buf_len, int base = 10); template<class CharType> bool Toa(long value, CharType * buffer, size_t buf_len, int base = 10); template<class CharType> bool Toa(unsigned int value, CharType * buffer, size_t buf_len, int base = 10); template<class CharType> bool Toa(int value, CharType * buffer, size_t buf_len, int base = 10); const wchar_t * Toa(unsigned int value, int base = 10); const wchar_t * Toa(unsigned long value, int base = 10); const wchar_t * Toa(int value, int base = 10); const wchar_t * Toa(long value, int base = 10); void Toa(int value, std::string & res, int base = 10, bool clear = true); void Toa(long value, std::string & res, int base = 10, bool clear = true); void Toa(int value, std::wstring & res, int base = 10, bool clear = true); void Toa(long value, std::wstring & res, int base = 10, bool clear = true); added: HtmlTextStream class (files htmltextstream.cpp htmltextstream.h in templates) this is a special stream for automatically escaping html tags git-svn-id: svn://ttmath.org/publicrep/winix/trunk@682 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-11-25 02:34:46 +01:00
Toa(db->Size(request->dir_tab.back()->id, Item::file), item.subject, 10, false);
}
if( new_url )
item.url = *new_url;
// if item.url is empty then it will be set from item.subject
PrepareUrl(item);
}
void Functions::ReadItemFilterHtml(Item & item)
{
html_filter.BreakLines(0);
html_filter.TrimWhite(false);
html_filter.InsertTabs(0);
html_filter.CheckOrphans(HTMLFilter::lang_none);
html_filter.SafeMode(true);
html_filter.Filter(request->PostVar(L"itemcontent"), item.content);
}
void Functions::ReadItemContent(Item & item, const std::wstring & content_type)
{
bool is_root = request->session->puser && request->session->puser->super_user;
bool filter_html = (content_type == L"2") && config->editors_html_safe_mode;
if( filter_html && is_root && config->editors_html_safe_mode_skip_root )
filter_html = false;
if( filter_html )
ReadItemFilterHtml(item);
else
request->PostVar(L"itemcontent", item.content);
}
void Functions::ReadItemContentWithType(Item & item)
{
item.content_type = Item::ct_formatted_text; // default is formatted text
request->PostVar(L"contenttype", temp);
ReadItemContent(item, temp);
// ct_text and ct_formatted_text can use everyone
if( temp == L"0" )
item.content_type = Item::ct_text;
else
if( temp == L"1" )
item.content_type = Item::ct_formatted_text;
// those below need special privileges
if( !request->session->puser )
return;
long user_id = request->session->puser->id;
if( temp == L"2" )
{
if( system->CanUseHtml(user_id) )
item.content_type = Item::ct_html;
}
else
if( temp == L"3" )
{
if( system->CanUseBBCode(user_id) )
item.content_type = Item::ct_bbcode;
}
else
if( temp == L"4" )
{
if( system->CanUseRaw(user_id) )
item.content_type = Item::ct_raw;
}
}
// item_type - the type of an item you are expecting to read
// returns true if the url has to be changed
// at the moment this is only checked for Item::file - for Item::dir it returns always true
// !! zmienic nazwe na ReadUrlSubjectContent
void Functions::ReadItem(Item & item, Item::Type item_type)
{
if( item_type == Item::none )
return;
item.type = item_type;
item.parent_id = request->dir_tab.back()->id; // !! moze to dac jako parametr?
ReadItemUrlSubject(item, item_type);
if( item_type == Item::file )
ReadItemContentWithType(item);
}
void Functions::SetUser(Item & item)
{
if( request->session && request->session->puser )
{
item.user_id = request->session->puser->id;
item.guest_name.clear();
}
else
{
item.user_id = -1;
request->PostVar(L"guestname", item.guest_name);
}
item.group_id = request->dir_tab.back()->group_id;
}