/* * 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 "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::Init() { dirs.SetDb(db); dirs.SetRequest(request); dirs.ReadDirs(); mounts.SetDirs(&dirs); mounts.SetDb(db); mounts.SetRequest(request); mounts.CreateMounts(); mounts.ReadMounts(); users.SetRequest(request); users.ReadUsers(db); users.SetTimeZoneOffset(config->time_zone_offset); 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 wchar_t * 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 wchar_t * postfix) { 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_tab (zrobic sobie lokalny tutaj) db->GetItem(request->item_tab, item_id); if( !request->item_tab.empty() ) { if( !dirs.MakePath(request->item_tab[0].parent_id, path) ) log << log1 << "Content: Can't redirect: no dirs for item id: " << request->item_tab[0].id << ", requested directory id: " << request->item_tab[0].parent_id << logend; request->redirect_to += path + request->item_tab[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() { if( !request->dir_tab.empty() ) RedirectTo( *request->dir_tab.back() ); } void System::RedirectToLastItem() { if( request->last_item ) RedirectTo( *request->last_item ); } 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_tab.begin() ; i!=request->dir_tab.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_tab) { size_t i = 0; while( i < item_tab.size() ) { if( !HasReadAccess(item_tab[i]) ) { item_tab.erase(item_tab.begin() + i); } else { i += 1; } } } bool System::CanUseHtml(long user_id) { return IsMemberOfGroup(user_id, L"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, L"allow_raw"); } bool System::IsMemberOfGroup(long user_id, const wchar_t * group_name) { User * puser = users.GetUser(user_id); if( !puser ) return false; if( puser->super_user ) return true; // !! ?? zakladamy ze administrator jest czlonkiem wszystkich grup? dlaczego? long group = groups.GetGroupId(group_name); if( group == -1 ) // there is no such a group return false; return puser->IsMemberOf(group); } bool System::MakePathSimpleFs(std::wstring & 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::wstring & path, long id, bool create_dir) { wchar_t buffer[50]; wchar_t * hash = buffer; size_t buffer_len = sizeof(buffer)/sizeof(wchar_t); // get 'id' as hexadecimal buffer[0] = '0'; swprintf(buffer+1, buffer_len, L"%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( (wcslen(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::wstring & path, bool create_dir) { bool res; Mount * pmount = mounts.CalcMount(item.parent_id); if( !pmount || pmount->fs == mounts.MountFsSimplefs() ) { 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, bool notify) { 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; if( notify ) request->notify_code |= WINIX_NOTIFY_ITEM_ADD; } return status; } Error System::EditFile(Item & item, bool with_url, bool notify) { 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; if( notify ) request->notify_code |= WINIX_NOTIFY_ITEM_EDIT; } return status; } time_t System::LocalTime(time_t gmt_time) { int time_offset; if( request->session && request->session->puser ) time_offset = request->session->puser->time_zone_offset; else time_offset = config->time_zone_offset_guest; return gmt_time + (time_t)time_offset; } tm System::LocalTime(const tm * ptm) { time_t t; tm rtm; t = Time(ptm); t = LocalTime(t); rtm = Time(t); return rtm; } tm System::LocalTime(const tm & ptm) { return LocalTime(&ptm); }