/* * This file is a part of Winix * and is not publicly distributed * * Copyright (c) 2008-2010, Tomasz Sowa * All rights reserved. * */ #include #include "cp.h" #include "core/misc.h" namespace Fun { Cp::Cp() { fun.url = "cp"; } bool Cp::CpCheckAccessFrom() { if( request->is_item ) { if( !system->HasReadAccess(request->item) ) { request->status = WINIX_ERR_PERMISSION_DENIED; return false; } } else if( !request->IsParam("r") ) { // directories need 'r' parameter request->status = WINIX_ERR_PERMISSION_DENIED; } return true; } bool Cp::CheckAccessTo(long dir_id) { Item * pdir = system->dirs.GetDir(dir_id); if( !pdir ) { request->status = WINIX_ERR_INCORRECT_DIR; return false; } if( !system->HasReadExecAccessToPath(dir_id) || !system->HasWriteAccess(*pdir) ) { request->status = WINIX_ERR_PERMISSION_DENIED; return false; } return true; } bool Cp::ParseDir(long & dir_id, std::string & dir, std::string & file) { std::string * move_to = request->PostVar("to"); if( !move_to ) { request->status = WINIX_ERR_PERMISSION_DENIED; return false; } int res = system->dirs.AnalyzePath(*move_to, dir_id, dir, file); if( res == 1 ) request->status = WINIX_ERR_NO_ROOT_DIR; else if( res != 0 ) request->status = WINIX_ERR_INCORRECT_DIR; return res == 0; } void Cp::CpAuth(Item & item) { if( !system->MakePath(item, mv_new_path, true) ) { request->status = WINIX_ERR_PERMISSION_DENIED; return; } if( CopyFile(item.auth_path, mv_new_path) ) { log << log1 << "Content: copied static file from: " << item.auth_path << ", to: " << mv_new_path << logend; item.auth_path = mv_new_path; request->status = db->EditAuthById(item, item.id); } else { log << log1 << "Content: can't copy a file from: " << item.auth_path << ", to: " << mv_new_path << logend; request->status = WINIX_ERR_PERMISSION_DENIED; } } void Cp::CpSetNewAttributes(Item & item) { item.user_id = cp_new_user; item.group_id = cp_new_group; item.SetDateModifyToNow(); } void Cp::CpItem(Item & item, long dst_dir_id) { if( !system->HasReadAccess(item) ) return; // !! w przyszlosci bedziemy dodawac komunikaty do specjalnej tablicy (narazie nie zaimplementowane) item.parent_id = dst_dir_id; if( !cp_preserve_attr ) CpSetNewAttributes(item); request->status = system->AddFile(item); if( request->status == WINIX_ERR_OK ) { if( item.auth != Item::auth_none ) CpAuth(item); } } void Cp::CpPrepare() { cp_iq.SetAll(true, false); cp_iq.WhereType(Item::file); cp_new_user = -1; cp_new_group = -1; if( request->session->puser ) cp_new_user = request->session->puser->id; Item * pdir = system->dirs.GetDir(mv_dir_id); if( pdir ) cp_new_group = pdir->group_id; } void Cp::CpFilesInDir(const Item & dir, long dst_dir_id) { cp_iq.WhereParentId(dir.id); db->GetItems(request->item_table, cp_iq); for(size_t i=0 ; iitem_table.size() ; ++i) CpItem(request->item_table[i], dst_dir_id); } void Cp::CpContentOfDir(const Item & item, long dst_dir_id) { DirContainer::ParentIterator i = system->dirs.FindFirstParent(item.id); // go through all directories for( ; i != system->dirs.ParentEnd() ; i = system->dirs.NextParent(i) ) CpDir(*(i->second), dst_dir_id); CpFilesInDir(item, dst_dir_id); } // we shouldn't change 'item' because we have references to our app.dirs objects long Cp::CpDir(const Item & item, long dst_dir_id) { cp_temp = item; cp_temp.parent_id = dst_dir_id; if( !mv_file.empty() ) { cp_temp.url = mv_file; mv_file.clear(); system->PrepareUrl(cp_temp); } if( !cp_preserve_attr ) CpSetNewAttributes(cp_temp); if( cp_remove_defaults ) cp_temp.default_item = -1; request->status = system->dirs.AddDirectory(cp_temp); long new_dir_id = cp_temp.id; // remember the new dir_id if( system->HasReadExecAccess(item) ) CpContentOfDir(item, cp_temp.id); return new_dir_id; // and return it } bool Cp::IsTheSameFile(const Item & item) { if( mv_file.empty() ) { if( item.parent_id == mv_dir_id ) return true; // nothing to do } else { if( item.parent_id == mv_dir_id && item.url == mv_file ) return true; // nothing to do } return false; } // here 'item' can be changed in place void Cp::CpItemCheck(Item & item, bool redirect) { if( IsTheSameFile(item) ) return; if( !mv_file.empty() ) { item.url = mv_file; system->PrepareUrl(item); } CpItem(item, mv_dir_id); if( request->status==WINIX_ERR_OK && redirect ) system->RedirectTo(item); } void Cp::CpContentOfDirCheck(const Item & item, bool redirect) { if( !mv_file.empty() ) { request->status = WINIX_ERR_INCORRECT_DIR; return; } if( mv_dir_id == item.id ) return; // nothing to do if( system->dirs.HasParent(mv_dir_id, item.id) ) { log << log1 << "Content: cannot copy directory to inside it" << logend; request->status = WINIX_ERR_INCORRECT_DIR; return; } CpContentOfDir(item, mv_dir_id); if( request->status==WINIX_ERR_OK && redirect ) system->RedirectTo(mv_dir_id); } void Cp::CpDirCheck(const Item & item, bool redirect) { if( mv_file.empty() && mv_dir_id == item.id ) return; // nothing to do if( mv_dir_id == item.id || system->dirs.HasParent(mv_dir_id, item.id) ) { log << log1 << "Content: cannot copy directory to inside it" << logend; request->status = WINIX_ERR_INCORRECT_DIR; return; } long new_dir_id = CpDir(item, mv_dir_id); if( request->status==WINIX_ERR_OK && redirect ) system->RedirectTo(new_dir_id); } void Cp::MakePost() { if( CpCheckAccessFrom() && ParseDir(mv_dir_id, mv_dir, mv_file) && CheckAccessTo(mv_dir_id) ) { CpPrepare(); cp_preserve_attr = request->IsPostVar("preserveattr"); if( request->is_item ) { CpItemCheck(request->item); } else { cp_remove_defaults = request->IsPostVar("removedefaults"); if( request->IsPostVar("onlycontent") ) CpContentOfDirCheck(*request->dir_table.back()); else CpDirCheck(*request->dir_table.back()); } } } void Cp::MakeGet() { CpCheckAccessFrom(); } } // namespace