365 lines
6.4 KiB
C++
Executable File
365 lines
6.4 KiB
C++
Executable File
/*
|
|
* 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"
|
|
#include "functions.h"
|
|
|
|
|
|
namespace Fun
|
|
{
|
|
|
|
Mv::Mv()
|
|
{
|
|
fun.url = "mv";
|
|
}
|
|
|
|
|
|
bool Mv::MoveCheckAccessFromToDir()
|
|
{
|
|
Item * last;
|
|
Item * last_but_one = 0;
|
|
|
|
last = request->dir_tab[request->dir_tab.size()-1];
|
|
|
|
if( request->dir_tab.size() >= 2 )
|
|
last_but_one = request->dir_tab[request->dir_tab.size()-2];
|
|
|
|
if( request->method != Request::post )
|
|
{
|
|
// used in GET or HEAD
|
|
|
|
if( !system->HasWriteAccess(*last) &&
|
|
(!last_but_one || !system->HasWriteAccess(*last_but_one)) )
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
// used in POST when the moving is performed
|
|
|
|
if( request->IsPostVar("onlycontent") )
|
|
return system->HasWriteAccess(*last);
|
|
else
|
|
if( last_but_one )
|
|
return system->HasWriteAccess(*last_but_one);
|
|
else
|
|
return false; // you cannot move the root directory
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
bool Mv::MoveCheckAccessFrom()
|
|
{
|
|
if( request->is_item )
|
|
{
|
|
// moving a file
|
|
|
|
if( !system->HasWriteAccess(*request->dir_tab.back()) )
|
|
{
|
|
request->status = WINIX_ERR_PERMISSION_DENIED;
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( !MoveCheckAccessFromToDir() )
|
|
{
|
|
request->status = WINIX_ERR_PERMISSION_DENIED;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Mv::MoveCheckAccessTo(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 Mv::MoveCheckMountPoints(long dir_id)
|
|
{
|
|
/*
|
|
Mount * new_mount = system->mounts.CalcMount(dir_id);
|
|
|
|
if( !new_mount )
|
|
{
|
|
if( system->mounts.pmount->type != Mount::cms )
|
|
{
|
|
request->status = WINIX_DIFFERENT_MOUNT_POINTS;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
if( new_mount->type != system->mounts.pmount->type )
|
|
{
|
|
request->status = WINIX_DIFFERENT_MOUNT_POINTS;
|
|
return false;
|
|
}
|
|
*/
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
bool Mv::MoveParseDir(long & dir_id, std::string & dir, std::string & file)
|
|
{
|
|
int res = system->dirs.AnalyzePath(request->PostVar("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 Mv::MoveAuth(Item & item)
|
|
{
|
|
if( !system->MakePath(item, mv_new_path, true) )
|
|
{
|
|
request->status = WINIX_ERR_PERMISSION_DENIED;
|
|
return;
|
|
}
|
|
|
|
if( rename(item.auth_path.c_str(), mv_new_path.c_str()) == 0 )
|
|
{
|
|
log << log1 << "Content: moved 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
|
|
{
|
|
int err = errno;
|
|
|
|
log << log1 << "Content: can't move a file from: " << item.auth_path << ", to: " << mv_new_path << ", ";
|
|
log.SystemErr(err);
|
|
log << logend;
|
|
|
|
request->status = WINIX_ERR_PERMISSION_DENIED;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool Mv::MoveIsTheSameFile(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;
|
|
}
|
|
|
|
|
|
|
|
void Mv::MoveFile(Item & item, bool redirect)
|
|
{
|
|
if( MoveIsTheSameFile(item) )
|
|
return;
|
|
|
|
if( !mv_file.empty() )
|
|
{
|
|
item.url = mv_file;
|
|
functions->PrepareUrl(item);
|
|
}
|
|
|
|
item.parent_id = mv_dir_id;
|
|
request->status = db->EditParentUrlById(item, item.id);
|
|
|
|
if( request->status == WINIX_ERR_OK )
|
|
{
|
|
log << log2 << "Content: the file was moved to: " << mv_dir << item.url << logend;
|
|
|
|
if( item.auth != Item::auth_none )
|
|
MoveAuth(item);
|
|
|
|
if( redirect )
|
|
system->RedirectTo(item);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Mv::MoveContentOfDir()
|
|
{
|
|
Db::ItemQuery iq;
|
|
|
|
iq.sel_parent_id = true;
|
|
iq.sel_type = true;
|
|
iq.sel_url = true;
|
|
iq.sel_auth = true;
|
|
iq.WhereParentId(request->dir_tab.back()->id);
|
|
|
|
db->GetItems(request->item_tab, iq);
|
|
|
|
for(size_t i=0 ; i<request->item_tab.size() ; ++i)
|
|
{
|
|
if( request->item_tab[i].type == Item::dir )
|
|
MoveDir(request->item_tab[i], false);
|
|
else
|
|
MoveFile(request->item_tab[i], false);
|
|
}
|
|
|
|
system->RedirectToLastDir();
|
|
}
|
|
|
|
|
|
|
|
void Mv::MoveAuthPrepareQuery()
|
|
{
|
|
mv_auth_iq.SetAll(false, false);
|
|
|
|
mv_auth_iq.sel_parent_id = true;
|
|
mv_auth_iq.sel_type = true;
|
|
mv_auth_iq.sel_url = true;
|
|
mv_auth_iq.sel_auth = true;
|
|
|
|
mv_auth_iq.WhereType(Item::file);
|
|
mv_auth_iq.WhereAuth(Item::auth_none, false);
|
|
}
|
|
|
|
|
|
|
|
void Mv::MoveAuthContentOfDir(const Item & item)
|
|
{
|
|
DirContainer::ParentIterator i = system->dirs.FindFirstParent(item.id);
|
|
|
|
// go through all directories
|
|
for( ; i != system->dirs.ParentEnd() ; i = system->dirs.NextParent(i) )
|
|
MoveAuthContentOfDir(*(i->second));
|
|
|
|
mv_auth_iq.WhereParentId(item.id);
|
|
|
|
// don't use request->item here (is used in MoveContentOfDir())
|
|
db->GetItems(mv_auth, mv_auth_iq);
|
|
|
|
for(size_t i=0 ; i<mv_auth.size() ; ++i)
|
|
MoveAuth(mv_auth[i]);
|
|
|
|
mv_auth.clear();
|
|
}
|
|
|
|
|
|
|
|
void Mv::MoveDir(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 move directory to inside it" << logend;
|
|
request->status = WINIX_ERR_INCORRECT_DIR;
|
|
return;
|
|
}
|
|
|
|
if( !system->dirs.ChangeParent(item.id, mv_dir_id) )
|
|
{
|
|
request->status = WINIX_ERR_INCORRECT_DIR;
|
|
return;
|
|
}
|
|
|
|
item.parent_id = mv_dir_id;
|
|
|
|
if( !mv_file.empty() )
|
|
{
|
|
item.url = mv_file;
|
|
functions->PrepareUrl(item);
|
|
}
|
|
|
|
request->status = db->EditParentUrlById(item, item.id);
|
|
|
|
if( request->status == WINIX_ERR_OK )
|
|
{
|
|
log << log2 << "Content: the directory was moved to: " << mv_dir << item.url << logend;
|
|
MoveAuthContentOfDir(item);
|
|
|
|
if( redirect )
|
|
system->RedirectToLastDir();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void Mv::MakePost()
|
|
{
|
|
if( MoveCheckAccessFrom() &&
|
|
MoveParseDir(mv_dir_id, mv_dir, mv_file) &&
|
|
MoveCheckAccessTo(mv_dir_id) &&
|
|
MoveCheckMountPoints(mv_dir_id) )
|
|
{
|
|
if( request->is_item )
|
|
{
|
|
MoveFile(request->item);
|
|
}
|
|
else
|
|
{
|
|
MoveAuthPrepareQuery();
|
|
|
|
if( request->IsPostVar("onlycontent") )
|
|
{
|
|
if( mv_file.empty() )
|
|
MoveContentOfDir();
|
|
else
|
|
request->status = WINIX_ERR_INCORRECT_DIR;
|
|
}
|
|
else
|
|
{
|
|
MoveDir(*request->dir_tab.back());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Mv::MakeGet()
|
|
{
|
|
MoveCheckAccessFrom();
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|