added: now we have a fourth part in permissions (guests)
e.g.: 07555 means:
7 for owner
5 for group
5 for others
5 for guests (not logged users)
added: the sticky bit for directories
e.g. permissions to a directory with a sticky bit set
can be set to: 017555
rewritten: rm/mv winix functions to correctly understand the sticky bit
added: Dir::FollowLink() recognizes ".." and "." now
consequently System::FollowAllLinks recognizes it too
added: umask -- calculating privileges for new files/directories
all users have their own umask (in meta)
and there is one in the config
(for guests and when a user has not definied its own one)
removed: mount option: only_root_remove
git-svn-id: svn://ttmath.org/publicrep/winix/trunk@801 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
747
functions/mv.cpp
747
functions/mv.cpp
@@ -2,7 +2,7 @@
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -21,73 +21,131 @@ Mv::Mv()
|
||||
{
|
||||
fun.url = L"mv";
|
||||
follow_symlinks = false;
|
||||
|
||||
Prepare();
|
||||
}
|
||||
|
||||
|
||||
// !! CHECK ME
|
||||
// check if everywhere correct messages are sent (prepare_to, modified item/dir)
|
||||
|
||||
|
||||
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()) )
|
||||
if( !system->CanRemoveRenameChild(*cur->request->dir_tab.back(), cur->request->item.user_id) )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool only_content = (cur->request->IsParam(L"c") || cur->request->IsPostVar(L"c"));
|
||||
|
||||
if( !CheckAccessFromToDir(*cur->request->dir_tab.back(), only_content) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Mv::CheckAccessFromToDir(const Item & dir, bool only_content)
|
||||
{
|
||||
if( dir.parent_id == -1 )
|
||||
{
|
||||
if( !only_content )
|
||||
{
|
||||
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
||||
// the root directory cannot be moved anywhere
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
if( only_content )
|
||||
{
|
||||
if( !CheckAccessFromToDir() )
|
||||
{
|
||||
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
||||
// sticky bit for a specified child will be checked later
|
||||
if( !system->HasWriteAccess(dir) )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Item * last_but_one_dir = system->dirs.GetDir(dir.parent_id);
|
||||
|
||||
if( !last_but_one_dir )
|
||||
// ops, there is no a parent dir
|
||||
return false;
|
||||
|
||||
if( !system->CanRemoveRenameChild(*last_but_one_dir, dir.user_id) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// !! IMPROVE ME: may a better name?
|
||||
void Mv::Prepare()
|
||||
{
|
||||
content_dir_iq.SetAll(false, false);
|
||||
content_dir_iq.sel_parent_id = true;
|
||||
content_dir_iq.sel_type = true;
|
||||
content_dir_iq.sel_url = true;
|
||||
content_dir_iq.sel_file = true;
|
||||
content_dir_iq.sel_user_id = true;
|
||||
content_dir_iq.sel_group_id = true;
|
||||
content_dir_iq.sel_privileges = true;
|
||||
content_dir_iq.sel_meta = true;
|
||||
|
||||
files_iq.SetAll(false, false);
|
||||
files_iq.sel_parent_id = true;
|
||||
files_iq.sel_type = true;
|
||||
files_iq.sel_url = true;
|
||||
files_iq.sel_file = true;
|
||||
files_iq.sel_user_id = true;
|
||||
files_iq.sel_group_id = true;
|
||||
files_iq.sel_privileges = true;
|
||||
files_iq.sel_meta = true;
|
||||
files_iq.WhereType(Item::dir, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Mv::Clear()
|
||||
{
|
||||
out_dir_tab.clear();
|
||||
out_item.Clear();
|
||||
out_filename.clear();
|
||||
files_item_tab.clear();
|
||||
item_tab.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Mv::ParseDirCheckLastName()
|
||||
{
|
||||
if( out_has_file )
|
||||
{
|
||||
log << log1 << "Mv: incorrent path" << logend;
|
||||
slog << logerror << T("mv_incorrect_path") << logend;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Item * dir = system->dirs.GetDir(out_filename, out_dir_tab.back()->id);
|
||||
|
||||
if( dir )
|
||||
{
|
||||
out_dir_tab.push_back(dir);
|
||||
out_filename.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( db->GetItem(out_dir_tab.back()->id, out_filename, out_item) == WINIX_ERR_OK )
|
||||
{
|
||||
out_has_file = true;
|
||||
out_filename.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,13 +153,48 @@ return true;
|
||||
}
|
||||
|
||||
|
||||
bool Mv::CheckAccessTo()
|
||||
bool Mv::ParseDir(const std::wstring & dst_path, bool check_access)
|
||||
{
|
||||
if( dir_tab.empty() ||
|
||||
!system->HasReadExecAccessToPath(dir_tab) ||
|
||||
!system->HasWriteAccess(*dir_tab.back()) )
|
||||
if( dst_path.empty() )
|
||||
return false;
|
||||
|
||||
// first we should remove the last name from the dst_path
|
||||
// (it may not exist in current file system and FollowAllLinks will fail)
|
||||
size_t last_slash = dst_path.find_last_of('/');
|
||||
out_path = dst_path;
|
||||
out_filename.clear();
|
||||
|
||||
if( last_slash != std::wstring::npos && last_slash + 1 < dst_path.size() )
|
||||
{
|
||||
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
||||
out_path.erase(last_slash + 1); // leaving the slash at the end
|
||||
out_filename = dst_path.c_str() + last_slash + 1;
|
||||
}
|
||||
|
||||
int res = system->FollowAllLinks(cur->request->dir_tab, out_path, out_dir_tab, out_item, false, false, check_access);
|
||||
|
||||
if( res != 0 && res != 1 )
|
||||
{
|
||||
slog << logerror << T("mv_incorrect_dst_path") << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
out_has_file = (res == 1);
|
||||
|
||||
if( !out_filename.empty() )
|
||||
return ParseDirCheckLastName();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Mv::CanRemoveRenameChild(const Item & child)
|
||||
{
|
||||
Item * parent_dir = system->dirs.GetDir(child.parent_id);
|
||||
|
||||
if( !parent_dir || !system->CanRemoveRenameChild(*parent_dir, child.user_id) )
|
||||
{
|
||||
log << log1 << "Mv: permission denied to: " << child.url << logend;
|
||||
slog << logerror << T("mv_permission_denied_to") << ": " << child.url << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -109,25 +202,6 @@ 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 )
|
||||
@@ -143,8 +217,8 @@ bool Mv::MoveStaticFile(const std::wstring & from, const std::wstring & to)
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "Mv: can't move a file from: " << from << ", to: " << to << logend;
|
||||
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
||||
log << log1 << "Mv: cannot move a static file from: " << from << ", to: " << to << logend;
|
||||
slog << logerror << T("internal_error") << logend;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -155,124 +229,44 @@ 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);
|
||||
res1 = system->MakeFilePath(item, old_static_path, false);
|
||||
res2 = !item.has_thumb || system->MakeFilePath(item, old_static_thumb_path, 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);
|
||||
res4 = system->MakeFilePath(item, new_static_path, false, true, config->upload_dirs_chmod);
|
||||
res5 = !item.has_thumb || system->MakeFilePath(item, new_static_thumb_path, true, true, config->upload_dirs_chmod);
|
||||
|
||||
if( !res1 || !res2 || !res3 || !res4 || !res5 )
|
||||
{
|
||||
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
||||
log << log1 << "Mv: cannot create a static path" << logend;
|
||||
slog << logerror << T("internal_error") << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
if( MoveStaticFile(old_path, new_path) )
|
||||
if( MoveStaticFile(old_static_path, new_static_path) )
|
||||
{
|
||||
cur->request->status = db->EditFileById(item, item.id);
|
||||
if( db->EditFileById(item, item.id) != WINIX_ERR_OK )
|
||||
{
|
||||
log << log1 << "Mv: cannot move static file (database problem)" << logend;
|
||||
slog << logerror << T("internal_error") << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
if( item.has_thumb )
|
||||
MoveStaticFile(old_path_thumb, new_path_thumb);
|
||||
MoveStaticFile(old_static_thumb_path, new_static_thumb_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Mv::MoveFileOrSymlink(Item & item)
|
||||
void Mv::MoveFilesPrepareTreeGo(const Item & src_dir)
|
||||
{
|
||||
plugin.Call(WINIX_FILE_PREPARE_TO_MOVE, &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);
|
||||
|
||||
plugin.Call(WINIX_FILE_MOVED, &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 ; i<item_tab.size() ; ++i)
|
||||
{
|
||||
if( item_tab[i].type == Item::dir )
|
||||
MoveDir(item_tab[i]);
|
||||
else
|
||||
MoveFileOrSymlink(item_tab[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Mv::Prepare()
|
||||
{
|
||||
content_dir_iq.SetAll(false, false);
|
||||
content_dir_iq.sel_parent_id = true;
|
||||
content_dir_iq.sel_type = true;
|
||||
content_dir_iq.sel_url = true;
|
||||
content_dir_iq.sel_file = true;
|
||||
|
||||
files_iq.SetAll(false, false);
|
||||
files_iq.sel_parent_id = true;
|
||||
files_iq.sel_type = true;
|
||||
files_iq.sel_url = true;
|
||||
files_iq.sel_file = true;
|
||||
files_iq.WhereType(Item::dir, false);
|
||||
}
|
||||
|
||||
|
||||
void Mv::Clear()
|
||||
{
|
||||
dir_tab.clear();
|
||||
files_item_tab.clear();
|
||||
item_tab.clear();
|
||||
}
|
||||
|
||||
|
||||
void Mv::MoveFilesPrepareTree(const Item & dir)
|
||||
{
|
||||
// we only calling plugins here
|
||||
// so if there is no WINIX_FILE_PREPARE_TO_MOVE message
|
||||
// we can immediately return and the database will not be bothered
|
||||
if( !plugin.HasMessage(WINIX_FILE_PREPARE_TO_MOVE) )
|
||||
return;
|
||||
|
||||
DirContainer::ParentIterator i = system->dirs.FindFirstChild(dir.id);
|
||||
DirContainer::ParentIterator i = system->dirs.FindFirstChild(src_dir.id);
|
||||
|
||||
// go through all directories
|
||||
for( ; i != system->dirs.ParentEnd() ; i = system->dirs.NextChild(i) )
|
||||
MoveFilesPrepareTree(*(i->second));
|
||||
|
||||
files_iq.WhereParentId(dir.id);
|
||||
files_iq.WhereParentId(src_dir.id);
|
||||
db->GetItems(files_item_tab, files_iq);
|
||||
|
||||
for(size_t i=0 ; i<files_item_tab.size() ; ++i)
|
||||
@@ -280,6 +274,20 @@ void Mv::MoveFilesPrepareTree(const Item & dir)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Mv::MoveFilesPrepareTree(const Item & src_dir)
|
||||
{
|
||||
// we only calling plugins here
|
||||
// so if there is no WINIX_FILE_PREPARE_TO_MOVE message
|
||||
// we can immediately return and the database will not be bothered
|
||||
if( plugin.HasMessage(WINIX_FILE_PREPARE_TO_MOVE) )
|
||||
{
|
||||
MoveFilesPrepareTree(src_dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Mv::MoveFilesTree(const Item & dir)
|
||||
{
|
||||
DirContainer::ParentIterator i = system->dirs.FindFirstChild(dir.id);
|
||||
@@ -294,69 +302,193 @@ void Mv::MoveFilesTree(const Item & dir)
|
||||
for(size_t i=0 ; i<files_item_tab.size() ; ++i)
|
||||
{
|
||||
if( files_item_tab[i].file_type != WINIX_ITEM_FILETYPE_NONE )
|
||||
{
|
||||
plugin.Call(WINIX_FILE_PREPARE_TO_MOVE, &files_item_tab[i]);
|
||||
MoveStaticFile(files_item_tab[i]);
|
||||
|
||||
plugin.Call(WINIX_FILE_MOVED, &files_item_tab[i]);
|
||||
plugin.Call(WINIX_FILE_MOVED, &files_item_tab[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Mv::MoveDir(Item & dir)
|
||||
{
|
||||
long dst_dir_id = dir_tab.back()->id;
|
||||
old_url = dir.url;
|
||||
|
||||
if( dst_dir_id == dir.id || system->dirs.HasParent(dst_dir_id, dir.id) )
|
||||
|
||||
// private
|
||||
// uses: out_dir_tab, out_filename
|
||||
bool Mv::MoveDir(Item & src_dir, std::vector<Item*> & dst_dir_tab, const std::wstring & dst_name)
|
||||
{
|
||||
long dst_dir_id = dst_dir_tab.back()->id;
|
||||
old_url = src_dir.url;
|
||||
|
||||
if( dst_dir_id == src_dir.id || system->dirs.HasParent(dst_dir_id, src_dir.id) )
|
||||
{
|
||||
log << log1 << "Mv: cannot move directory to inside it" << logend;
|
||||
cur->request->status = WINIX_ERR_INCORRECT_DIR;
|
||||
return;
|
||||
slog << logerror << T("mv_cannot_move_to_inside");
|
||||
return false;
|
||||
}
|
||||
|
||||
MoveFilesPrepareTree(dir);
|
||||
MoveFilesPrepareTree(src_dir);
|
||||
|
||||
if( !system->dirs.ChangeParent(dir.id, dst_dir_id) )
|
||||
if( !system->dirs.ChangeParent(src_dir.id, dst_dir_id) )
|
||||
return false;
|
||||
|
||||
src_dir.parent_id = dst_dir_id;
|
||||
old_url = src_dir.url;
|
||||
|
||||
if( !dst_name.empty() )
|
||||
{
|
||||
cur->request->status = WINIX_ERR_INCORRECT_DIR;
|
||||
return;
|
||||
src_dir.url = dst_name;
|
||||
functions->PrepareUrl(src_dir);
|
||||
}
|
||||
|
||||
dir.parent_id = dst_dir_id;
|
||||
Error status = db->EditParentUrlById(src_dir, src_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 )
|
||||
if( status == WINIX_ERR_OK )
|
||||
{
|
||||
log << log3 << "Mv: directory: " << old_url << " was moved to: ";
|
||||
system->dirs.LogDir(dir_tab);
|
||||
log << dir.url << logend;
|
||||
system->dirs.LogDir(dst_dir_tab);
|
||||
log << src_dir.url << logend;
|
||||
|
||||
MoveFilesTree(dir);
|
||||
MoveFilesTree(src_dir);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// public
|
||||
bool Mv::MoveDir(Item & src_dir, long dst_dir_id, const std::wstring & new_url, bool check_access)
|
||||
{
|
||||
bool res = MoveDir2(src_dir, dst_dir_id, new_url, check_access);
|
||||
Clear();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// private
|
||||
bool Mv::MoveDir2(Item & src_dir, long dst_dir_id, const std::wstring & new_url, bool check_access)
|
||||
{
|
||||
if( src_dir.type != Item::dir )
|
||||
{
|
||||
log << "Mv: a directory required" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( src_dir.parent_id == -1 )
|
||||
{
|
||||
log << log1 << "Mv: the root directory cannot be moved anywhere" << logend;
|
||||
slog << logerror << T("mv_cant_move_root_dir") << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( check_access && !CanRemoveRenameChild(src_dir) )
|
||||
return false;
|
||||
|
||||
if( src_dir.id == dst_dir_id )
|
||||
{
|
||||
if( new_url.empty() || src_dir.url == new_url )
|
||||
return true; // the same directory -- there is nothing to do
|
||||
}
|
||||
|
||||
if( !system->dirs.CreateDirTab(dst_dir_id, out_dir_tab) )
|
||||
{
|
||||
log << log1 << "Mv: incorrect directory" << logend;
|
||||
slog << logerror << T("mv_incorrect_dir") << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
return MoveDir(src_dir, out_dir_tab, new_url);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// public
|
||||
bool Mv::MoveDir(Item & src_dir, const std::wstring & dst_path, bool check_access)
|
||||
{
|
||||
bool res = MoveDir2(src_dir, dst_path, check_access);
|
||||
Clear();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// private
|
||||
bool Mv::MoveDir2(Item & src_dir, const std::wstring & dst_path, bool check_access)
|
||||
{
|
||||
if( src_dir.type != Item::dir )
|
||||
{
|
||||
log << "Mv: a directory required" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( src_dir.parent_id == -1 )
|
||||
{
|
||||
log << log1 << "Mv: the root directory cannot be moved anywhere" << logend;
|
||||
slog << logerror << T("mv_cant_move_root_dir") << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( check_access && !CanRemoveRenameChild(src_dir) )
|
||||
return false;
|
||||
|
||||
if( !ParseDir(dst_path, check_access) )
|
||||
return false;
|
||||
|
||||
if( out_has_file )
|
||||
{
|
||||
log << log1 << "Mv: directory can be moved only to a directory" << logend;
|
||||
slog << logerror << T("mv_dir_can_be_moved_to_dir") << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( src_dir.id == out_dir_tab.back()->id )
|
||||
{
|
||||
if( out_filename.empty() || src_dir.url == out_filename )
|
||||
return true; // the same directory -- there is nothing to do
|
||||
}
|
||||
|
||||
return MoveDir(src_dir, out_dir_tab, out_filename);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool Mv::IsTheSameFile(const Item & item)
|
||||
|
||||
// private
|
||||
bool Mv::MoveFileOrSymlink(Item & src_file, std::vector<Item*> & dst_dir_tab, const std::wstring & new_url)
|
||||
{
|
||||
if( file.empty() )
|
||||
plugin.Call(WINIX_FILE_PREPARE_TO_MOVE, &src_file);
|
||||
|
||||
old_url = src_file.url;
|
||||
|
||||
if( !new_url.empty() )
|
||||
{
|
||||
if( item.parent_id == dir_tab.back()->id )
|
||||
return true; // nothing to do
|
||||
src_file.url = new_url;
|
||||
functions->PrepareUrl(src_file);
|
||||
}
|
||||
else
|
||||
|
||||
src_file.parent_id = dst_dir_tab.back()->id;
|
||||
Error status = db->EditParentUrlById(src_file, src_file.id);
|
||||
|
||||
if( status == WINIX_ERR_OK )
|
||||
{
|
||||
if( item.parent_id == dir_tab.back()->id && item.url == file )
|
||||
return true; // nothing to do
|
||||
if( src_file.type == Item::file )
|
||||
log << log3 << "Mv: file: ";
|
||||
else
|
||||
log << log3 << "Mv: symlink: ";
|
||||
|
||||
log << old_url << " was moved to: ";
|
||||
system->dirs.LogDir(dst_dir_tab);
|
||||
log << src_file.url << logend;
|
||||
|
||||
if( src_file.file_type != WINIX_ITEM_FILETYPE_NONE )
|
||||
MoveStaticFile(src_file);
|
||||
|
||||
plugin.Call(WINIX_FILE_MOVED, &src_file);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -364,48 +496,164 @@ return false;
|
||||
|
||||
|
||||
|
||||
void Mv::PostMoveFile()
|
||||
// public
|
||||
bool Mv::MoveFileOrSymlink(Item & src_file, long dst_dir_id, const std::wstring & new_url, bool check_access)
|
||||
{
|
||||
if( IsTheSameFile(cur->request->item) )
|
||||
return;
|
||||
bool res = MoveFileOrSymlink2(src_file, dst_dir_id, new_url, check_access);
|
||||
Clear();
|
||||
|
||||
MoveFileOrSymlink(cur->request->item);
|
||||
return res;
|
||||
}
|
||||
|
||||
if( cur->request->status == WINIX_ERR_OK )
|
||||
system->RedirectTo(cur->request->item);
|
||||
|
||||
// private
|
||||
bool Mv::MoveFileOrSymlink2(Item & src_file, long dst_dir_id, const std::wstring & new_url, bool check_access)
|
||||
{
|
||||
if( src_file.type == Item::dir )
|
||||
{
|
||||
log << "Mv: a file/symlink required" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( check_access && !CanRemoveRenameChild(src_file) )
|
||||
return false;
|
||||
|
||||
if( src_file.parent_id == dst_dir_id )
|
||||
{
|
||||
if( new_url.empty() || src_file.url == new_url )
|
||||
return true; // the same file -- there is nothing to do
|
||||
}
|
||||
|
||||
if( !system->dirs.CreateDirTab(dst_dir_id, out_dir_tab) )
|
||||
return false;
|
||||
|
||||
return MoveFileOrSymlink(src_file, out_dir_tab, new_url);
|
||||
}
|
||||
|
||||
|
||||
// public
|
||||
bool Mv::MoveFileOrSymlink(Item & src_file, const std::wstring & dst_path, bool check_access)
|
||||
{
|
||||
bool res = MoveFileOrSymlink2(src_file, dst_path, check_access);
|
||||
Clear();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// private
|
||||
bool Mv::MoveFileOrSymlink2(Item & src_file, const std::wstring & dst_path, bool check_access)
|
||||
{
|
||||
if( src_file.type == Item::dir )
|
||||
{
|
||||
log << "Mv: a file/symlink required" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( check_access && !CanRemoveRenameChild(src_file) )
|
||||
return false;
|
||||
|
||||
if( !ParseDir(dst_path, check_access) )
|
||||
return false;
|
||||
|
||||
if( src_file.parent_id == out_dir_tab.back()->id )
|
||||
{
|
||||
// actually out_filename is here empty
|
||||
// because ParseDir() have been read it to out_item
|
||||
if( out_filename.empty() || src_file.url == out_filename )
|
||||
return true; // the same file -- there is nothing to do
|
||||
}
|
||||
|
||||
return MoveFileOrSymlink(src_file, out_dir_tab, out_filename);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Mv::PostMoveDirContent()
|
||||
// private
|
||||
void Mv::MoveAllFilesFromDir(Item & src_dir, std::vector<Item*> & dst_dir_tab, bool check_access)
|
||||
{
|
||||
if( !file.empty() )
|
||||
content_dir_iq.WhereParentId(src_dir.id);
|
||||
db->GetItems(item_tab, content_dir_iq);
|
||||
out_filename.clear();
|
||||
|
||||
for(size_t i=0 ; i<item_tab.size() ; ++i)
|
||||
{
|
||||
cur->request->status = WINIX_ERR_INCORRECT_DIR;
|
||||
if( check_access && !system->CanRemoveRenameChild(src_dir, item_tab[i].user_id) )
|
||||
{
|
||||
log << log1 << "Mv: permission denied to: " << src_dir.url << logend;
|
||||
slog << logerror << T("mv_permission_denied_to") << ": " << src_dir.url << logend;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( item_tab[i].type == Item::dir )
|
||||
MoveDir(item_tab[i], dst_dir_tab, out_filename);
|
||||
else
|
||||
MoveFileOrSymlink(item_tab[i], dst_dir_tab, out_filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// public
|
||||
void Mv::MoveDirContent(Item & src_dir, long dst_dir_id, bool check_access)
|
||||
{
|
||||
MoveDirContent2(src_dir, dst_dir_id, check_access);
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// private
|
||||
void Mv::MoveDirContent2(Item & src_dir, long dst_dir_id, bool check_access)
|
||||
{
|
||||
if( src_dir.type != Item::dir )
|
||||
{
|
||||
log << "Mv: a directory required" << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
if( cur->request->dir_tab.back()->id == dir_tab.back()->id )
|
||||
return; // nothing to do
|
||||
if( src_dir.parent_id == -1 )
|
||||
{
|
||||
log << log1 << "Mv: the root directory cannot be moved anywhere" << logend;
|
||||
slog << logerror << T("mv_cant_move_root_dir") << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
MoveDirContent(*cur->request->dir_tab.back());
|
||||
system->RedirectToLastDir();
|
||||
if( !system->dirs.CreateDirTab(dst_dir_id, out_dir_tab) )
|
||||
{
|
||||
log << log1 << "Mv: incorrect directory" << logend;
|
||||
slog << logerror << T("mv_incorrect_dir") << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
MoveAllFilesFromDir(src_dir, out_dir_tab, check_access);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Mv::PostMoveDir()
|
||||
// public
|
||||
void Mv::MoveDirContent(Item & src_dir, const std::wstring & dst_dir, bool check_access)
|
||||
{
|
||||
Item & last_dir = *cur->request->dir_tab.back();
|
||||
Item & new_dir = *dir_tab.back();
|
||||
MoveDirContent2(src_dir, dst_dir, check_access);
|
||||
Clear();
|
||||
}
|
||||
|
||||
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();
|
||||
// private
|
||||
void Mv::MoveDirContent2(Item & src_dir, const std::wstring & dst_dir, bool check_access)
|
||||
{
|
||||
if( !ParseDir(dst_dir, check_access) )
|
||||
return;
|
||||
|
||||
if( out_has_file || !out_filename.empty() )
|
||||
{
|
||||
log << log1 << "Mv: directory content can be moved only to a directory" << logend;
|
||||
slog << logerror << T("mv_dir_content_can_be_moved_to_dir") << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
MoveDirContent2(src_dir, out_dir_tab.back()->id, check_access);
|
||||
}
|
||||
|
||||
|
||||
@@ -413,26 +661,23 @@ void Mv::PostMoveDir()
|
||||
|
||||
void Mv::MakePost()
|
||||
{
|
||||
if( CheckAccessFrom() &&
|
||||
ParseDir() &&
|
||||
CheckAccessTo() )
|
||||
const std::wstring & dst_path = cur->request->PostVar(L"dst_path");
|
||||
bool ok = true;
|
||||
|
||||
if( cur->request->is_item )
|
||||
{
|
||||
Prepare();
|
||||
|
||||
if( cur->request->is_item )
|
||||
{
|
||||
PostMoveFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( cur->request->IsPostVar(L"onlycontent") )
|
||||
PostMoveDirContent();
|
||||
else
|
||||
PostMoveDir();
|
||||
}
|
||||
|
||||
Clear();
|
||||
ok = MoveFileOrSymlink(cur->request->item, dst_path, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( cur->request->IsParam(L"c") || cur->request->IsPostVar(L"c") )
|
||||
MoveDirContent(*cur->request->dir_tab.back(), dst_path, true);
|
||||
else
|
||||
ok = MoveDir(*cur->request->dir_tab.back(), dst_path, true);
|
||||
}
|
||||
|
||||
if( ok )
|
||||
system->RedirectToLastItem();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user