/* * This file is a part of Winix * and is not publicly distributed * * Copyright (c) 2008-2010, Tomasz Sowa * All rights reserved. * */ #include #include "mv.h" #include "functions.h" namespace Fun { Mv::Mv() { fun.url = L"mv"; follow_symlinks = false; } bool Mv::HasAccess() { return CheckAccessFrom(); } bool Mv::CheckAccessFromToDir() { Item * last; Item * last_but_one = 0; size_t dir_tab_size; last = cur->request->dir_tab.back(); dir_tab_size = cur->request->dir_tab.size(); if( dir_tab_size <= 1 ) return false; // you cannot move the root directory last_but_one = cur->request->dir_tab[dir_tab_size - 2]; if( cur->request->method != Request::post ) { // used in GET or HEAD // we don't now whether we move the last directory or the last but one // it depends on the 'onlycontent' parameter if( !system->HasWriteAccess(*last) && !system->HasWriteAccess(*last_but_one) ) return false; } else { // used in POST when the moving is performed if( cur->request->IsPostVar(L"onlycontent") ) return system->HasWriteAccess(*last); else return system->HasWriteAccess(*last_but_one); } return true; } bool Mv::CheckAccessFrom() { if( cur->request->is_item ) { // moving a file if( !system->HasWriteAccess(*cur->request->dir_tab.back()) ) { cur->request->status = WINIX_ERR_PERMISSION_DENIED; return false; } } else { if( !CheckAccessFromToDir() ) { cur->request->status = WINIX_ERR_PERMISSION_DENIED; return false; } } return true; } bool Mv::CheckAccessTo() { if( dir_tab.empty() || !system->HasReadExecAccessToPath(dir_tab) || !system->HasWriteAccess(*dir_tab.back()) ) { cur->request->status = WINIX_ERR_PERMISSION_DENIED; return false; } return true; } bool Mv::ParseDir() { const std::wstring & new_dir = cur->request->PostVar(L"to"); int res = system->dirs.FollowLink(cur->request->dir_tab, new_dir, dir_tab, file); if( res == 3 ) cur->request->status = WINIX_ERR_NO_ROOT_DIR; else if( res != 0 && res != 1 ) cur->request->status = WINIX_ERR_INCORRECT_DIR; return res == 0 || res == 1; } bool Mv::MoveStaticFile(const std::wstring & from, const std::wstring & to) { if( from == to ) { log << log3 << "Mv: the same path to a static file: " << to << " (skipped)" << logend; return true; } if( RenameFile(from, to) ) { log << log2 << "Mv: moved static file from: " << from << ", to: " << to << logend; return true; } else { log << log1 << "Mv: can't move a file from: " << from << ", to: " << to << logend; cur->request->status = WINIX_ERR_PERMISSION_DENIED; return false; } } void Mv::MoveStaticFile(Item & item) { bool res1, res2, res3, res4, res5; res1 = system->MakeFilePath(item, old_path, false); res2 = !item.has_thumb || system->MakeFilePath(item, old_path_thumb, true); res3 = system->CreateNewFile(item); res4 = system->MakeFilePath(item, new_path, false, true, config->upload_dirs_chmod); res5 = !item.has_thumb || system->MakeFilePath(item, new_path_thumb, true, true, config->upload_dirs_chmod); if( !res1 || !res2 || !res3 || !res4 || !res5 ) { cur->request->status = WINIX_ERR_PERMISSION_DENIED; return; } if( MoveStaticFile(old_path, new_path) ) { cur->request->status = db->EditFileById(item, item.id); if( item.has_thumb ) MoveStaticFile(old_path_thumb, new_path_thumb); } } void Mv::MoveFileOrSymlink(Item & item) { old_url = item.url; if( !file.empty() ) { item.url = file; functions->PrepareUrl(item); file.clear(); } item.parent_id = dir_tab.back()->id; cur->request->status = db->EditParentUrlById(item, item.id); if( cur->request->status == WINIX_ERR_OK ) { if( item.type == Item::file ) log << log3 << "Mv: file: "; else log << log3 << "Mv: symlink: "; log << old_url << " was moved to: "; system->dirs.LogDir(dir_tab); log << item.url << logend; if( item.file_type != WINIX_ITEM_FILETYPE_NONE ) MoveStaticFile(item); } } void Mv::MoveDirContent(const Item & dir) { content_dir_iq.WhereParentId(dir.id); db->GetItems(item_tab, content_dir_iq); for(size_t i=0 ; idirs.FindFirstChild(dir.id); // go through all directories for( ; i != system->dirs.ParentEnd() ; i = system->dirs.NextChild(i) ) MoveStaticFilesTree(*(i->second)); static_iq.WhereParentId(dir.id); db->GetItems(static_item_tab, static_iq); for(size_t i=0 ; iid; old_url = dir.url; if( dst_dir_id == dir.id || system->dirs.HasParent(dst_dir_id, dir.id) ) { log << log1 << "Mv: cannot move directory to inside it" << logend; cur->request->status = WINIX_ERR_INCORRECT_DIR; return; } if( !system->dirs.ChangeParent(dir.id, dst_dir_id) ) { cur->request->status = WINIX_ERR_INCORRECT_DIR; return; } dir.parent_id = dst_dir_id; if( !file.empty() ) { dir.url = file; functions->PrepareUrl(dir); file.clear(); } cur->request->status = db->EditParentUrlById(dir, dir.id); if( cur->request->status == WINIX_ERR_OK ) { log << log3 << "Mv: directory: " << old_url << " was moved to: "; system->dirs.LogDir(dir_tab); log << dir.url << logend; MoveStaticFilesTree(dir); } } bool Mv::IsTheSameFile(const Item & item) { if( file.empty() ) { if( item.parent_id == dir_tab.back()->id ) return true; // nothing to do } else { if( item.parent_id == dir_tab.back()->id && item.url == file ) return true; // nothing to do } return false; } void Mv::PostMoveFile() { if( IsTheSameFile(cur->request->item) ) return; MoveFileOrSymlink(cur->request->item); if( cur->request->status == WINIX_ERR_OK ) system->RedirectTo(cur->request->item); } void Mv::PostMoveDirContent() { if( !file.empty() ) { cur->request->status = WINIX_ERR_INCORRECT_DIR; return; } if( cur->request->dir_tab.back()->id == dir_tab.back()->id ) return; // nothing to do MoveDirContent(*cur->request->dir_tab.back()); system->RedirectToLastDir(); } void Mv::PostMoveDir() { Item & last_dir = *cur->request->dir_tab.back(); Item & new_dir = *dir_tab.back(); if( file.empty() && new_dir.id == last_dir.id ) return; // nothing to do MoveDir(last_dir); if( cur->request->status == WINIX_ERR_OK ) system->RedirectToLastDir(); } void Mv::MakePost() { if( CheckAccessFrom() && ParseDir() && CheckAccessTo() ) { Prepare(); if( cur->request->is_item ) { PostMoveFile(); } else { if( cur->request->IsPostVar(L"onlycontent") ) PostMoveDirContent(); else PostMoveDir(); } Clear(); } } } // namespace