/* * This file is a part of Winix * and is not publicly distributed * * Copyright (c) 2010, Tomasz Sowa * All rights reserved. * */ #include "system.h" #include "misc.h" #include "error.h" #include "notify.h" #include "functions/functions.h" #include "templates/templates.h" void System::SetRequest(Request * prequest) { request = prequest; } void System::SetConfig(Config * pconfig) { config = pconfig; } void System::SetDb(Db * pdb) { db = pdb; } void System::SetFunctions(Functions * pfunctions) { functions = pfunctions; } void System::SetTemplates(Templates * ptemplates) { templates = ptemplates; } void System::Init() { dirs.SetDb(db); dirs.SetRequest(request); dirs.ReadDirs(); mounts.SetDirs(&dirs); mounts.SetDb(db); mounts.SetRequest(request); mounts.ReadMounts(); users.SetRequest(request); users.ReadUsers(db); groups.ReadGroups(db); // !! chwilowe przekazanie argumentu, db bedzie zmienione rebus.SetRequest(request); rebus.Init(); } // !! mozna zrobic jakas obsluge kiedy nie mozemy sie redirectnac, np gdy wystapil blad // !! moze zwracac jakas wartosc? void System::RedirectTo(const Item & item, const char * postfix) { request->redirect_to = config->base_url; if( item.type == Item::dir ) { // item_id is pointing to a directory dirs.MakePath(item.id, path); request->redirect_to += path; } else { if( !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; } if( postfix ) request->redirect_to += postfix; } void System::RedirectTo(long item_id, const char * postfix) { std::string path; Item * pdir; request->redirect_to = config->base_url; pdir = dirs.GetDir(item_id); if( pdir ) { // item_id is pointing to a directory dirs.MakePath(pdir->id, path); request->redirect_to += path; } else { // !! zrobic nowy interfejs // !! GetItem pozamieniac na GetFile // !! i nie uzywac request->item_table (zrobic sobie lokalny tutaj) db->GetItem(request->item_table, item_id); if( !request->item_table.empty() ) { if( !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; } } if( postfix ) request->redirect_to += postfix; } void System::RedirectToLastDir() { // !! dac sprawdzenie czy istnieje RedirectTo( *request->dir_table.back() ); } void System::RedirectToLastItem() { if( request->is_item ) RedirectTo(request->item); else RedirectTo( *request->dir_table.back() );// !! dac sprawdzenie czy istnieje } void System::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( functions->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(), '_'); } } bool System::CanChangeUser(const Item & item, long new_user_id) { if( !request->session ) // session must be set return false; if( request->session->puser && request->session->puser->super_user ) // super user is allowed everything return true; if( item.user_id != new_user_id ) // only super user can change the owner of an item return false; return true; } bool System::CanChangeGroup(const Item & item, long new_group_id) { if( !request->session ) // session must be set return false; if( request->session->puser && request->session->puser->super_user ) // super user is allowed everything return true; if( item.group_id != new_group_id ) { // user is allowed to change the group only if he is an owner of the item // he can change only into a group in which he is a member of, or into a 'no_group' if( !request->session->puser ) return false; if( request->session->puser->id != item.user_id ) return false; if( new_group_id == -1 ) return true; if( !request->session->puser->IsMemberOf(new_group_id) ) return false; // is logged, is the owner of the item, is the member of the new group } return true; } bool System::CanChangePrivileges(const Item & item, int new_priv) { if( !request->session ) // session must be set return false; if( request->session->puser && request->session->puser->super_user ) // super user is allowed everything return true; if( item.privileges != new_priv ) { // the owner of an item is allowed to change the privileges if( !request->session->puser ) return false; if( request->session->puser->id != item.user_id ) return false; } return true; } bool System::HasAccess(const Item & item, int mask) { if( !request->session ) // session must be set return false; if( request->session->puser && request->session->puser->super_user ) // super user is allowed everything return true; if( request->session->puser && request->session->puser->id == item.user_id ) { // the owner return ((item.privileges >> 6) & mask) == mask; } if( request->session->puser && request->session->puser->IsMemberOf(item.group_id) ) { // group return ((item.privileges >> 3) & mask) == mask; } // others return (item.privileges & mask) == mask; } bool System::HasReadAccess(const Item & item) { return HasAccess(item, 4); } bool System::HasWriteAccess(const Item & item) { return HasAccess(item, 2); } bool System::HasReadWriteAccess(const Item & item) { return HasAccess(item, 6); // r+w } bool System::HasReadExecAccess(const Item & item) { if( request->session && request->session->puser && request->session->puser->super_user ) { // there must be at least one 'x' (for the root) return (item.privileges & 0111) != 0; } return HasAccess(item, 5); // r+x } bool System::HasReadExecAccessToPath(long dir_id) { while( true ) { Item * pdir = dirs.GetDir(dir_id); if( !pdir ) return false; if( !HasReadExecAccess(*pdir) ) return false; dir_id = pdir->parent_id; if( dir_id == -1 ) return true; } } bool System::DirsHaveReadExecPerm() { std::vector::iterator i; for(i = request->dir_table.begin() ; i!=request->dir_table.end() ; ++i) { if( !HasReadExecAccess(**i) ) return false; } return true; } // if we don't have access we only remove the item from the table void System::CheckAccessToItems(std::vector & item_table) { size_t i = 0; while( i < item_table.size() ) { if( !HasReadAccess(item_table[i]) ) { item_table.erase(item_table.begin() + i); } else { i += 1; } } } bool System::CanUseHtml(long user_id) { return IsMemberOfGroup(user_id, "allow_html"); } bool System::CanUseBBCode(long user_id) { // logged users can use bbcode return (user_id != -1); } bool System::CanUseRaw(long user_id) { return IsMemberOfGroup(user_id, "allow_raw"); } bool System::IsMemberOfGroup(long user_id, const char * group_name) { User * puser = users.GetUser(user_id); if( !puser ) return false; if( puser->super_user ) return true; long group = groups.GetGroupId(group_name); if( group == -1 ) // there is no such a group return false; if( puser->IsMemberOf(group) ) return true; return false; } bool System::MakePathSimpleFs(std::string & path, long dir_id, bool create_dir) { if( config->auth_simplefs_dir.empty() ) { log << log1 << "System: auth_simplefs_dir is not set in the config file" << logend; return false; } if( !dirs.MakePath(dir_id, path) ) return false; if( create_dir && !CreateDirs(config->auth_simplefs_dir, path, 0755) ) return false; path.insert(0, config->auth_simplefs_dir); return true; } // the path depends on id bool System::MakePathHashFs(std::string & path, long id, bool create_dir) { char buffer[50]; char * hash = buffer; // get 'id' as hexadecimal buffer[0] = '0'; sprintf(buffer+1, "%lx", (unsigned long)id); path = config->auth_hashfs_dir; if( path.empty() ) { log << log1 << "System: auth_hashfs_dir is not set in the config file" << logend; return false; } path += '/'; // make sure that the length is even if( (strlen(hash) & 1) != 0 ) hash = buffer + 1; // the first character was zero // creating dirs without the last part // the last part is a part of a file for(size_t i=0 ; hash[i] != 0 ; i+=2) { path += hash[i]; path += hash[i+1]; if( hash[i+2] != 0 ) { if( create_dir && !CreateDir(path, 0755) ) return false; path += '/'; } } // one character more to make sure the path is unique // (we can have a directory without the character) path += "_"; return true; } // making a complete path to a static file bool System::MakePath(const Item & item, std::string & path, bool create_dir) { bool res; Mount * pmount = mounts.CalcMount(item.parent_id); if( !pmount || pmount->fs == Mount::simplefs ) { res = MakePathSimpleFs(path, item.parent_id, create_dir); } else { res = MakePathHashFs(path, item.id, create_dir); } if( res ) path += item.url; else path.clear(); return res; } bool System::MakePath(Item & item, bool create_dir) { return MakePath(item, item.auth_path, create_dir); } Error System::AddFile(Item & item) { if( item.type == Item::dir ) return WINIX_ERR_FILE_EXPECTED; Error status = db->AddItem(item); if( status == WINIX_ERR_OK ) { log << log2 << "System: added a new file, url: " << item.url << ", id: " << item.id << ", parent_id: " << item.parent_id << logend; request->notify_code |= WINIX_NOTIFY_ITEM_ADD; } return status; } Error System::EditFile(Item & item, bool with_url) { if( item.type == Item::dir ) return WINIX_ERR_FILE_EXPECTED; if( request->session && request->session->puser ) request->item.modification_user_id = request->session->puser->id; else request->item.modification_user_id = -1; item.SetDateModifyToNow(); Error status = db->EditItemById(item, with_url); if( status == WINIX_ERR_OK ) { TemplatesFunctions::pattern_cacher.UpdatePattern(item); log << log2 << "System: modified an item" << logend; request->notify_code |= WINIX_NOTIFY_ITEM_EDIT; } return status; } Error System::CheckSpecialFile(const Item & item) { static std::string fstab = "fstab"; Item * etc = 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 << "System: reloading mount points" << logend; Error status = mounts.ReadMounts(item.content); templates->ReadNewIndexTemplates(); return status; } return WINIX_NOTHING_TO_DO; }