/* * 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::SetNotify(Notify * pnotify) { notify = pnotify; } 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::string & 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::string fstab = "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->SetNotify(notify); } 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::Create() { Add(fun_adduser); Add(fun_cat); Add(fun_chmod); Add(fun_chown); Add(fun_ckeditor); Add(fun_cp); Add(fun_createthread); Add(fun_default); Add(fun_download); Add(fun_emacs); Add(fun_last); Add(fun_login); Add(fun_logout); 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_subject); Add(fun_template); Add(fun_thread); Add(fun_tinymce); Add(fun_uname); Add(fun_upload); Add(fun_uptime); Add(fun_who); plugin.Call(WINIX_CREATE_FUNCTIONS); } void Functions::Parse() { function_parser.Parse(request, db, this, system); } void Functions::SetDefaultFunctionForFile() { if( request->item.auth != Item::auth_none ) request->function = &fun_download; else if( system->HasReadExecAccess(request->item) ) request->function = &fun_run; else request->function = &fun_cat; log << log3 << "Content: default function: " << request->function->fun.url << logend; } void Functions::SetDefaultFunctionForDir() { long default_item = request->dir_tab.back()->default_item; if( default_item != -1 ) { log << log3 << "Content: Default item: id: " << default_item << logend; system->RedirectTo(default_item); } else { if( system->mounts.pmount->type == system->mounts.MountTypeThread() ) request->function = &fun_thread; else request->function = &fun_ls; log << log3 << "Content: default function: " << request->function->fun.url << logend; } } void Functions::SetDefaultFunction() { plugin.Call(WINIX_SELECT_DEFAULT_FUNCTION); if( request->function ) { log << log3 << "Functions: default function: " << request->function->fun.url << logend; return; } if( request->is_item ) SetDefaultFunctionForFile(); else SetDefaultFunctionForDir(); } void Functions::MakeGet() { if( request->role == Request::authorizer ) { // in authorizer mode only cat function is available // (and must be default) if( request->function ) { request->status = WINIX_ERR_NO_ITEM; log << log1 << "Content: in authorizer mode only 'cat' funtion is available and must " "be default (not in the url)" << logend; return; } request->function = &fun_cat; } if( !request->function ) SetDefaultFunction(); if( !request->redirect_to.empty() ) return; if( !request->function ) { request->status = WINIX_ERR_NO_FUNCTION; log << log1 << "Functions: no function (neither cat nor ls)" << logend; return; } if( !system->HasReadExecAccess(request->function->fun) || !request->function->HasAccess() ) { request->status = WINIX_ERR_PERMISSION_DENIED; return; } request->function->MakeGet(); } void Functions::MakePost() { if( request->role == Request::authorizer ) { request->status = WINIX_ERR_PERMISSION_DENIED; return; } if( !request->function ) SetDefaultFunction(); if( !request->function ) { request->status = WINIX_ERR_NO_FUNCTION; log << log1 << "Functions: MakePost: no function" << logend; return; } if( !system->HasReadExecAccess(request->function->fun) || !request->function->HasAccess() ) { request->status = WINIX_ERR_PERMISSION_DENIED; return; } request->function->MakePost(); } 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; } // returning true if the 'url' has to be changed void Functions::ReadItemUrlSubject(Item & item, Item::Type item_type) { std::string * new_subject = request->PostVarp("subject"); std::string * new_url = request->PostVarp("url"); if( new_subject ) item.subject = *new_subject; if( item.subject.empty() ) { item.subject = request->dir_tab.back()->subject; item.subject += "_msg_"; item.subject += ToStr(db->Size(request->dir_tab.back()->id, Item::file)); } 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("itemcontent"), item.content); } void Functions::ReadItemContent(Item & item, const std::string & content_type) { bool is_root = request->session->puser && request->session->puser->super_user; bool filter_html = (content_type == "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("itemcontent", item.content); } void Functions::ReadItemContentWithType(Item & item) { item.content_type = Item::ct_formatted_text; // default is formatted text request->PostVar("contenttype", temp); ReadItemContent(item, temp); // ct_text and ct_formatted_text can use everyone if( temp == "0" ) item.content_type = Item::ct_text; else if( temp == "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 == "2" ) { if( system->CanUseHtml(user_id) ) item.content_type = Item::ct_html; } else if( temp == "3" ) { if( system->CanUseBBCode(user_id) ) item.content_type = Item::ct_bbcode; } else if( temp == "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 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("guestname", item.guest_name); } item.group_id = request->dir_tab.back()->group_id; }