2010-08-10 18:12:50 +02:00
|
|
|
/*
|
|
|
|
* This file is a part of Winix
|
|
|
|
* and is not publicly distributed
|
|
|
|
*
|
|
|
|
* Copyright (c) 2008-2010, Tomasz Sowa
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include "mv.h"
|
2010-08-12 21:10:12 +02:00
|
|
|
#include "functions.h"
|
2010-08-10 18:12:50 +02:00
|
|
|
|
|
|
|
|
|
|
|
namespace Fun
|
|
|
|
{
|
|
|
|
|
|
|
|
Mv::Mv()
|
|
|
|
{
|
2010-11-21 01:19:17 +01:00
|
|
|
fun.url = L"mv";
|
2011-01-05 22:24:11 +01:00
|
|
|
follow_symlinks = false;
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
bool Mv::HasAccess()
|
|
|
|
{
|
|
|
|
return CheckAccessFrom();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Mv::CheckAccessFromToDir()
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
|
|
|
Item * last;
|
|
|
|
Item * last_but_one = 0;
|
2011-01-05 22:24:11 +01:00
|
|
|
size_t dir_tab_size;
|
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
last = cur->request->dir_tab.back();
|
|
|
|
dir_tab_size = cur->request->dir_tab.size();
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( dir_tab_size <= 1 )
|
|
|
|
return false; // you cannot move the root directory
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
last_but_one = cur->request->dir_tab[dir_tab_size - 2];
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->method != Request::post )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2010-08-12 21:10:12 +02:00
|
|
|
// used in GET or HEAD
|
2011-01-05 22:24:11 +01:00
|
|
|
// we don't now whether we move the last directory or the last but one
|
|
|
|
// it depends on the 'onlycontent' parameter
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( !system->HasWriteAccess(*last) && !system->HasWriteAccess(*last_but_one) )
|
2010-08-10 18:12:50 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// used in POST when the moving is performed
|
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->IsPostVar(L"onlycontent") )
|
2010-08-10 18:12:50 +02:00
|
|
|
return system->HasWriteAccess(*last);
|
|
|
|
else
|
|
|
|
return system->HasWriteAccess(*last_but_one);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
|
|
|
|
bool Mv::CheckAccessFrom()
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->is_item )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
|
|
|
// moving a file
|
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( !system->HasWriteAccess(*cur->request->dir_tab.back()) )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
2010-08-10 18:12:50 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
if( !CheckAccessFromToDir() )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
2010-08-10 18:12:50 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
bool Mv::CheckAccessTo()
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
if( dir_tab.empty() ||
|
|
|
|
!system->HasReadExecAccessToPath(dir_tab) ||
|
|
|
|
!system->HasWriteAccess(*dir_tab.back()) )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
2010-08-10 18:12:50 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
bool Mv::ParseDir()
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
const std::wstring & new_dir = cur->request->PostVar(L"to");
|
|
|
|
int res = system->dirs.FollowLink(cur->request->dir_tab, new_dir, dir_tab, file);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( res == 3 )
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_NO_ROOT_DIR;
|
2010-08-10 18:12:50 +02:00
|
|
|
else
|
2011-01-05 22:24:11 +01:00
|
|
|
if( res != 0 && res != 1 )
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_INCORRECT_DIR;
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
return res == 0 || res == 1;
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
bool Mv::MoveStaticFile(const std::wstring & from, const std::wstring & to)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
if( from == to )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
log << log3 << "Mv: the same path to a static file: " << to << " (skipped)" << logend;
|
|
|
|
return true;
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( RenameFile(from, to) )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
log << log2 << "Mv: moved static file from: " << from << ", to: " << to << logend;
|
|
|
|
return true;
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
log << log1 << "Mv: can't move a file from: " << from << ", to: " << to << logend;
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
2011-01-05 22:24:11 +01:00
|
|
|
return false;
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
void Mv::MoveStaticFile(Item & item)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
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 )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
2011-01-05 22:24:11 +01:00
|
|
|
return;
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
2011-01-05 22:24:11 +01:00
|
|
|
|
|
|
|
if( MoveStaticFile(old_path, new_path) )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = db->EditFileById(item, item.id);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( item.has_thumb )
|
|
|
|
MoveStaticFile(old_path_thumb, new_path_thumb);
|
|
|
|
}
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
|
|
|
|
void Mv::MoveFileOrSymlink(Item & item)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
old_url = item.url;
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( !file.empty() )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
item.url = file;
|
2010-08-12 21:10:12 +02:00
|
|
|
functions->PrepareUrl(item);
|
2011-01-05 22:24:11 +01:00
|
|
|
file.clear();
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
item.parent_id = dir_tab.back()->id;
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = db->EditParentUrlById(item, item.id);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->status == WINIX_ERR_OK )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
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;
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2010-12-10 22:07:01 +01:00
|
|
|
if( item.file_type != WINIX_ITEM_FILETYPE_NONE )
|
|
|
|
MoveStaticFile(item);
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
void Mv::MoveDirContent(const Item & dir)
|
|
|
|
{
|
|
|
|
content_dir_iq.WhereParentId(dir.id);
|
|
|
|
db->GetItems(item_tab, content_dir_iq);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
for(size_t i=0 ; i<item_tab.size() ; ++i)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
if( item_tab[i].type == Item::dir )
|
|
|
|
MoveDir(item_tab[i]);
|
2010-08-10 18:12:50 +02:00
|
|
|
else
|
2011-01-05 22:24:11 +01:00
|
|
|
MoveFileOrSymlink(item_tab[i]);
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
|
|
|
|
void Mv::Prepare()
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
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;
|
|
|
|
|
|
|
|
static_iq.SetAll(false, false);
|
|
|
|
static_iq.sel_parent_id = true;
|
|
|
|
static_iq.sel_type = true;
|
|
|
|
static_iq.sel_url = true;
|
|
|
|
static_iq.sel_file = true;
|
|
|
|
|
|
|
|
static_iq.WhereType(Item::file);
|
|
|
|
static_iq.WhereFileType(WINIX_ITEM_FILETYPE_NONE, false);
|
|
|
|
}
|
2010-08-10 18:12:50 +02:00
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
void Mv::Clear()
|
|
|
|
{
|
|
|
|
dir_tab.clear();
|
|
|
|
static_item_tab.clear();
|
|
|
|
item_tab.clear();
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
void Mv::MoveStaticFilesTree(const Item & dir)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
DirContainer::ParentIterator i = system->dirs.FindFirstChild(dir.id);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
|
|
|
// go through all directories
|
2011-01-05 22:24:11 +01:00
|
|
|
for( ; i != system->dirs.ParentEnd() ; i = system->dirs.NextChild(i) )
|
|
|
|
MoveStaticFilesTree(*(i->second));
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
static_iq.WhereParentId(dir.id);
|
|
|
|
db->GetItems(static_item_tab, static_iq);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
for(size_t i=0 ; i<static_item_tab.size() ; ++i)
|
|
|
|
MoveStaticFile(static_item_tab[i]);
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
void Mv::MoveDir(Item & dir)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
long dst_dir_id = dir_tab.back()->id;
|
|
|
|
old_url = dir.url;
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( dst_dir_id == dir.id || system->dirs.HasParent(dst_dir_id, dir.id) )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2010-11-21 01:19:17 +01:00
|
|
|
log << log1 << "Mv: cannot move directory to inside it" << logend;
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_INCORRECT_DIR;
|
2010-08-10 18:12:50 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( !system->dirs.ChangeParent(dir.id, dst_dir_id) )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_INCORRECT_DIR;
|
2010-08-10 18:12:50 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
dir.parent_id = dst_dir_id;
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( !file.empty() )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
dir.url = file;
|
|
|
|
functions->PrepareUrl(dir);
|
|
|
|
file.clear();
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = db->EditParentUrlById(dir, dir.id);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->status == WINIX_ERR_OK )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
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()
|
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
if( IsTheSameFile(cur->request->item) )
|
2011-01-05 22:24:11 +01:00
|
|
|
return;
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
MoveFileOrSymlink(cur->request->item);
|
2011-01-05 22:24:11 +01:00
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->status == WINIX_ERR_OK )
|
|
|
|
system->RedirectTo(cur->request->item);
|
2011-01-05 22:24:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Mv::PostMoveDirContent()
|
|
|
|
{
|
|
|
|
if( !file.empty() )
|
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_INCORRECT_DIR;
|
2011-01-05 22:24:11 +01:00
|
|
|
return;
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
2011-01-05 22:24:11 +01:00
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->dir_tab.back()->id == dir_tab.back()->id )
|
2011-01-05 22:24:11 +01:00
|
|
|
return; // nothing to do
|
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
MoveDirContent(*cur->request->dir_tab.back());
|
2011-01-05 22:24:11 +01:00
|
|
|
system->RedirectToLastDir();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Mv::PostMoveDir()
|
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
Item & last_dir = *cur->request->dir_tab.back();
|
2011-01-05 22:24:11 +01:00
|
|
|
Item & new_dir = *dir_tab.back();
|
|
|
|
|
|
|
|
if( file.empty() && new_dir.id == last_dir.id )
|
|
|
|
return; // nothing to do
|
|
|
|
|
|
|
|
MoveDir(last_dir);
|
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->status == WINIX_ERR_OK )
|
2011-01-05 22:24:11 +01:00
|
|
|
system->RedirectToLastDir();
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Mv::MakePost()
|
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
if( CheckAccessFrom() &&
|
|
|
|
ParseDir() &&
|
|
|
|
CheckAccessTo() )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
Prepare();
|
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->is_item )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
PostMoveFile();
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->IsPostVar(L"onlycontent") )
|
2011-01-05 22:24:11 +01:00
|
|
|
PostMoveDirContent();
|
2010-08-10 18:12:50 +02:00
|
|
|
else
|
2011-01-05 22:24:11 +01:00
|
|
|
PostMoveDir();
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
2011-01-05 22:24:11 +01:00
|
|
|
|
|
|
|
Clear();
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace
|