/* * 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 "content.h" #include "../core/request.h" #include "../core/error.h" #include "../core/db.h" #include "../core/data.h" #include "../core/misc.h" #include "../core/plugin.h" bool Content::Init() { templates.ReadTemplates(); templates.CreateFunctions(); return true; } bool Content::DirsHaveReadExecPerm() { std::vector::iterator i; for(i = request.dir_table.begin() ; i!=request.dir_table.end() ; ++i) { if( !request.HasReadExecAccess(**i) ) return false; } return true; } void Content::SetDefaultFunctionForFile() { if( request.HasReadExecAccess(request.item) ) request.pfunction = data.functions.GetFunction(FUN_RUN); else request.pfunction = data.functions.GetFunction(FUN_CAT); if( request.pfunction ) log << log3 << "Content: default function: " << request.pfunction->item.url << logend; } void Content::SetDefaultFunctionForDir() { long default_item = request.dir_table.back()->default_item; if( default_item != -1 ) { request.session->IncrementTimersIfExist(); log << log3 << "Content: Default item: id: " << default_item << logend; RedirectTo(default_item); return; } if( data.mounts.CurrentMountType() == Mount::thread ) { request.pfunction = data.functions.GetFunction(FUN_THREAD); if( request.pfunction ) log << log3 << "Content: default function: " << request.pfunction->item.url << logend; } else { // cms request.pfunction = data.functions.GetFunction(FUN_LS); if( request.pfunction ) log << log3 << "Content: default function: " << request.pfunction->item.url << logend; } } void Content::SetDefaultFunction() { if( request.is_item ) { SetDefaultFunctionForFile(); } else { SetDefaultFunctionForDir(); } } void Content::MakeStandardFunction() { if( !request.pfunction ) SetDefaultFunction(); if( !request.redirect_to.empty() ) return; if( !request.pfunction ) { log << log1 << "Content: no function (neither cat nor ls)" << logend; return; } if( request.pfunction->code == FUN_LOGOUT ) FunLogout(); else if( request.pfunction->code == FUN_CAT ) FunCat(); else if( request.pfunction->code == FUN_LS ) FunLs(); else if( request.pfunction->code == FUN_EMACS ) FunEmacs(); else if( request.pfunction->code == FUN_MKDIR ) FunMkdir(); else if( request.pfunction->code == FUN_DEFAULT ) FunDefault(); else if( request.pfunction->code == FUN_PRIV ) FunPriv(); else if( request.pfunction->code == FUN_RM ) FunRm(); else if( request.pfunction->code == FUN_RUN ) FunRun(); else if( request.pfunction->code == FUN_NODE ) FunNode(); else if( request.pfunction->code == FUN_WHO ) FunWho(); else if( request.pfunction->code == FUN_LAST ) FunLast(); else if( request.pfunction->code == FUN_THREAD ) FunThread(); else if( request.pfunction->code == FUN_RELOAD ) FunReload(); else if( request.pfunction->code == FUN_CREATETHREAD ) FunCreateThread(); else request.status = Error::permision_denied; } void Content::MakePost() { if( !request.pfunction ) SetDefaultFunction(); if( !request.pfunction ) { log << log1 << "Content: MakePost: no function" << logend; request.status = Error::no_function; return; } switch( request.pfunction->code ) { case FUN_RUN: PostFunRun(); break; case FUN_EMACS: PostFunEmacs(); break; case FUN_MKDIR: PostFunMkdir(); break; case FUN_DEFAULT: PostFunDefault(); break; case FUN_PRIV: PostFunPriv(); break; case FUN_LOGIN: PostFunLogin(); break; case FUN_CREATETHREAD: PostFunCreateThread(); break; default: log << log1 << "Content: unknown post function" << logend; break; } } void Content::Make() { if( request.dir_table.empty() ) { log << log1 << "Content: there is no a root dir (dir_table is empty)" << logend; return; } // request.status can be changed by function_parser if( request.status == Error::ok ) { if( DirsHaveReadExecPerm() ) { if( request.method == Request::post ) MakePost(); if( request.redirect_to.empty() && request.status == Error::ok ) MakeStandardFunction(); } else request.status = Error::permision_denied; } if( request.session->spam_score > 0 ) log << log1 << "Content: spam score: " << request.session->spam_score << logend; if( !request.redirect_to.empty() ) return; if( request.dir_table.empty() ) { log << log1 << "Content: there is no a root dir (dir_table is empty -- after calling some standard functions)" << logend; return; } plugin.Call(CMSLU_CONTENT_MAKE); templates.Generate(); //request.PrintGetTable(); //request.PrintEnv(); //request.PrintIn(); } // !! mozna zrobic jakas obsluge kiedy nie mozemy sie redirectnac, np gdy wystapil blad // !! moze zwracac jakas wartosc? void Content::RedirectTo(const Item & item) { std::string path; request.redirect_to = data.base_url; if( item.type == Item::dir ) { // item_id is pointing to a directory data.dirs.MakePath(item.id, path); request.redirect_to += path; } else { if( !data.dirs.MakePath(item.parent_id, path) ) log << log1 << "Content: Can't redirect: no dirs for item id: " << item.id << logend; request.redirect_to += path; request.redirect_to += item.url; } } void Content::RedirectTo(long item_id) { std::string path; Item * pdir; request.redirect_to = data.base_url; pdir = data.dirs.GetDir(item_id); if( pdir ) { // item_id is pointing to a directory data.dirs.MakePath(pdir->id, path); request.redirect_to += path; } else { // !! zrobic nowy interfejs // !! GetItem pozamieniac na GetFile db.GetItem(request.item_table, item_id); if( !request.item_table.empty() ) { if( !data.dirs.MakePath(request.item_table[0].parent_id, path) ) log << log1 << "Content: Can't redirect: no dirs for item id: " << request.item_table[0].id << ", requested directory id: " << request.item_table[0].parent_id << logend; request.redirect_to += path + request.item_table[0].url; } else { log << log1 << "Content: Can't redirect: no such item: id: " << item_id << logend; } } } void Content::ReadAdditionalInfo() { if( request.dir_table.empty() ) return; if( data.mounts.CurrentMountType() == Mount::thread ) { if( db.GetThreadByDirId(request.dir_table.back()->id, request.thread) == Error::ok ) request.is_thread = true; } } void Content::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 CorrectUrl() CorrectUrl(item); if( data.functions.GetFunction(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(), '_'); } } bool Content::CheckRebus() { if( request.session->puser ) // logged user don't have to use the rebus return true; if( request.session->rebus_checked ) return true; request.session->rebus_checked = true; if( !request.session->rebus_item ) { log << log1 << "Content: rebus not set" << logend; return false; } try { std::string * answer = request.PostVar("rebus"); if( answer && data.rebus.IsAnswerOk(request.session->rebus_item, *answer) ) return true; } catch(const Error &) { } log << log1 << "Content: rebus has an incorrect answer" << logend; // don't add request.session->spam_score when the rebus has incorrect answer // a user could have made a mistake return false; } void Content::SetUser(Item & item) { if( 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); } } void Content::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 << "Content: spam +1: POST after GET sent too fast" << logend; }