/* * This file is a part of Winix * and is not publicly distributed * * Copyright (c) 2008-2010, Tomasz Sowa * All rights reserved. * */ #include "content.h" #include "../core/request.h" #include "../core/error.h" #include "../core/db.h" #include "../core/data.h" bool Content::PrivCheckAccess() { // we do not check permissions here // permissions depends on the user, group, and privileges // but we cannot use parameter 'r' on files // and only logged users can change permissions if( !request.session->puser || (request.is_item && request.IsParam("r")) ) { request.status = WINIX_ERR_PERMISSION_DENIED; return false; } return true; } bool Content::ChangeOwner(Item & item, long user_id, long group_id) { if( user_id!=item.user_id || group_id!=item.group_id ) { if( !request.CanChangeUser(item, user_id) ) { log << log3 << "Content: can't change the user" << logend; return false; } if( !request.CanChangeGroup(item, group_id) ) { log << log3 << "Content: can't change the group" << logend; return false; } } item.user_id = user_id; item.group_id = group_id; return true; } bool Content::ChangePrivileges(Item & item, int privileges) { if( privileges != item.privileges ) { if( !request.CanChangePrivileges(item, privileges) ) { log << log3 << "Content: can't change privileges" << logend; return false; } } item.privileges = privileges; return true; } void Content::ChangePriv(Item & item, long user_id, long group_id, int privileges) { if( change_owner ) { if( !ChangeOwner(item, user_id, group_id) ) return; } if( change_priv ) { if( !ChangePrivileges(item, privileges) ) return; } request.status = db.EditPrivById(item, item.id); } void Content::PrivLogStart(const char * what, long user, long group, int priv) { log << log2 << what; if( change_owner ) { User * puser = data.users.GetUser(user); Group * pgroup = data.groups.GetGroup(group); log << "new user: "; if( puser ) log << puser->name; else log << "id: " << user; log << ", new group: "; if( pgroup ) log << pgroup->name; else log << "id: " << group; if( change_priv ) log << ", "; } if( change_priv ) { char buf[30]; sprintf(buf, "0%o", priv); log << "privileges: " << buf; } log << logend; } void Content::PrivLog(const char * what, long id, const std::string & url) { Item * root = 0; if( id != -1 ) root = data.dirs.GetRootDir(); log << log3 << "Content: " << what; if( root && root->id == id ) log << "(root)"; else log << url; log << logend; } void Content::PrivFilesInDir(long parent_id) { Db::ItemQuery iq; iq.SetAll(false, false); iq.sel_user_id = iq.sel_group_id = iq.sel_guest_name = iq.sel_privileges = true; iq.WhereParentId(parent_id); iq.WhereType(Item::file); db.GetItems(request.item_table, iq); std::vector::iterator i = request.item_table.begin(); for( ; i != request.item_table.end() ; ++i) { PrivLog("changed file: ", -1, i->url); ChangePriv(*i, user_id_file, group_id_file, priv_file); } } // recurrence void Content::PrivDir(long parent_id) { PrivFilesInDir(parent_id); DirContainer::ParentIterator i = data.dirs.FindFirstParent(parent_id); for( ; i != data.dirs.ParentEnd() ; i = data.dirs.NextParent(i) ) { PrivLog("changed dir: ", -1, i->second->url); ChangePriv(*(i->second), user_id_dir, group_id_dir, priv_dir); if( subdirectories ) PrivDir(i->second->id); } } bool Content::ReadPriv(const char * user_in, const char * group_in, const char * priv_in, long & user_id, long & group_id, int & priv) { std::string * user_str = request.PostVar(user_in); std::string * group_str = request.PostVar(group_in); std::string * priv_str = request.PostVar(priv_in); if( change_owner && (!user_str || !group_str) ) { log << log1 << "Content: PostFunPriv: there is no some post variables for changing the owner" << logend; return false; } if( change_priv && !priv_str ) { log << log1 << "Content: PostFunPriv: there is no some post variables for changing privileges" << logend; return false; } if( change_owner ) { user_id = data.users.GetUserId( *user_str ); group_id = data.groups.GetGroupId( *group_str ); } if( change_priv ) priv = strtol( priv_str->c_str() , 0, 8); return true; } void Content::PrivDir() { if( !ReadPriv("userfile", "groupfile", "privilegesfile", user_id_file, group_id_file, priv_file) ) return; if( !ReadPriv("userdir", "groupdir", "privilegesdir", user_id_dir, group_id_dir, priv_dir) ) return; PrivLogStart("Content: changes for files: ", user_id_file, group_id_file, priv_file); PrivLogStart("Content: changes for dirs: ", user_id_dir, group_id_dir, priv_dir); if( request.IsPostVar("changecurrentdir") ) { Item & last_dir = *request.dir_table.back(); PrivLog("changed dir: ", last_dir.id, last_dir.url); ChangePriv(*request.dir_table.back(), user_id_dir, group_id_dir, priv_dir); } subdirectories = request.IsPostVar("changesubdirs"); // go through all directories PrivDir(request.dir_table.back()->id); RedirectToLastDir(); } // changing only one item (either a dir or file) void Content::PrivOneItem() { if( !ReadPriv("user", "group", "privileges", user_id_file, group_id_file, priv_file) ) return; PrivLogStart("Content: changes: ", user_id_file, group_id_file, priv_file); if( request.is_item ) { ChangePriv(request.item, user_id_file, group_id_file, priv_file); RedirectTo(request.item); } else { ChangePriv(*request.dir_table.back(), user_id_file, group_id_file, priv_file); RedirectToLastDir(); } } void Content::PostFunPriv() { if( !PrivCheckAccess() ) return; change_owner = (request.pfunction->code == FUN_PRIV || request.pfunction->code == FUN_CHOWN); change_priv = (request.pfunction->code == FUN_PRIV || request.pfunction->code == FUN_CHMOD); if( request.IsParam("r") ) { PrivDir(); } else { PrivOneItem(); } data.dirs.CheckRootDir(); } void Content::FunPriv() { PrivCheckAccess(); }