winix/content/mv.cpp

362 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 "content.h"
#include "../core/request.h"
#include "../core/data.h"
bool Content::MoveCheckAccessFromToDir()
{
Item * last;
Item * last_but_one = 0;
last = request.dir_table[request.dir_table.size()-1];
if( request.dir_table.size() >= 2 )
last_but_one = request.dir_table[request.dir_table.size()-2];
if( request.method != Request::post )
{
// used in GET (HEAD in the future?)
if( !request.HasWriteAccess(*last) &&
(!last_but_one || !request.HasWriteAccess(*last_but_one)) )
return false;
}
else
{
// used in POST when the moving is performed
if( request.IsPostVar("onlycontent") )
return request.HasWriteAccess(*last);
else
if( last_but_one )
return request.HasWriteAccess(*last_but_one);
else
return false; // you cannot move the root directory
}
return true;
}
bool Content::MoveCheckAccessFrom()
{
if( request.is_item )
{
// moving a file
if( !request.HasWriteAccess(*request.dir_table.back()) )
{
request.status = WINIX_ERR_PERMISSION_DENIED;
return false;
}
}
else
{
if( !MoveCheckAccessFromToDir() )
{
request.status = WINIX_ERR_PERMISSION_DENIED;
return false;
}
}
return true;
}
bool Content::MoveCheckAccessTo(long dir_id)
{
Item * pdir = data.dirs.GetDir(dir_id);
if( !pdir )
{
request.status = WINIX_ERR_INCORRECT_DIR;
return false;
}
if( !request.HasReadExecAccessToPath(dir_id) || !request.HasWriteAccess(*pdir) )
{
request.status = WINIX_ERR_PERMISSION_DENIED;
return false;
}
return true;
}
bool Content::MoveCheckMountPoints(long dir_id)
{
/*
Mount * new_mount = data.mounts.CalcMount(dir_id);
if( !new_mount )
{
if( data.mounts.pmount->type != Mount::cms )
{
request.status = WINIX_DIFFERENT_MOUNT_POINTS;
return false;
}
return true;
}
if( new_mount->type != data.mounts.pmount->type )
{
request.status = WINIX_DIFFERENT_MOUNT_POINTS;
return false;
}
*/
return true;
}
bool Content::MoveParseDir(long & dir_id, std::string & dir, std::string & file)
{
std::string * move_to = request.PostVar("moveto");
if( !move_to )
{
request.status = WINIX_ERR_PERMISSION_DENIED;
return false;
}
int res = data.dirs.AnalyzePath(*move_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 Content::MoveAuth(Item & item)
{
if( !request.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 Content::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 Content::MoveFile(Item & item, bool redirect)
{
if( MoveIsTheSameFile(item) )
return;
if( !mv_file.empty() )
{
item.url = mv_file;
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 )
RedirectTo(item);
}
}
void Content::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_table.back()->id);
db.GetItems(request.item_table, iq);
for(size_t i=0 ; i<request.item_table.size() ; ++i)
{
if( request.item_table[i].type == Item::dir )
MoveDir(request.item_table[i], false);
else
MoveFile(request.item_table[i], false);
}
RedirectToLastDir();
}
void Content::MoveAuthPrepareQuery()
{
mv_auth_iq.SetAll(true, 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 Content::MoveAuthContentOfDir(const Item & item)
{
DirContainer::ParentIterator i = data.dirs.FindFirstParent(item.id);
// go through all directories
for( ; i != data.dirs.ParentEnd() ; i = data.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]);
}
void Content::MoveDir(Item & item, bool redirect)
{
if( mv_file.empty() && mv_dir_id == item.id )
return; // nothing to do
if( mv_dir_id == item.id || data.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( !data.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;
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 )
RedirectToLastDir();
}
}
void Content::PostFunMv()
{
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_table.back());
}
}
}
}
void Content::FunMv()
{
MoveCheckAccessFrom();
}