winix/functions/mv.cpp

365 lines
6.3 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 = L"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(L"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 != system->mounts.MountTypeCms() )
{
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::wstring & dir, std::wstring & file)
{
int res = system->dirs.AnalyzePath(request->PostVar(L"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( RenameFile(item.auth_path, mv_new_path) )
{
log << log1 << "Mv: 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 << "Mv: 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 << "Mv: 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()
{
DbItemQuery 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 << "Mv: 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 << "Mv: 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(L"onlycontent") )
{
if( mv_file.empty() )
MoveContentOfDir();
else
request->status = WINIX_ERR_INCORRECT_DIR;
}
else
{
MoveDir(*request->dir_tab.back());
}
}
}
}
void Mv::MakeGet()
{
MoveCheckAccessFrom();
}
} // namespace