winix/functions/rm.cpp

292 lines
5.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 <cstdio>
#include <errno.h>
#include "rm.h"
#include "core/plugin.h"
#include "core/misc.h"
#include "templates/templates.h"
namespace Fun
{
Rm::Rm()
{
fun.url = L"rm";
follow_symlinks = false;
}
bool Rm::HasAccess(const Item & item)
{
// !! temporarily (we're waiting for the sticky bit to be implemented)
// not logged users cannot remove anything
if( !request->session->puser )
return false;
if( item.parent_id == -1 )
{
// we can only remove the content of the root directory
// and here we check only access the the root dir
// "onlycontent" parameter should be check in post method
if( !system->HasWriteAccess(item) )
return false;
}
else
{
Item * last_but_one_dir = system->dirs.GetDir(item.parent_id);
if( !last_but_one_dir )
// ops, there is no a parent dir
return false;
if( !system->HasWriteAccess(*last_but_one_dir) )
return false;
}
if( system->mounts.pmount->IsPar(system->mounts.MountParOnlyRootRemove()) )
if( !request->session->puser || !request->session->puser->super_user )
return false;
return true;
}
bool Rm::HasAccess()
{
if( !request->is_item )
return HasAccess(*request->dir_tab.back());
else
return HasAccess(request->item);
return true;
}
void Rm::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;
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);
}
bool Rm::RemoveStaticFile(const std::wstring & path)
{
if( ::RemoveFile(path) )
{
log << log2 << "Rm: removed static file: " << path << logend;
return true;
}
else
{
log << log1 << "Rm: can't remove a file: " << path << logend;
request->status = WINIX_ERR_PERMISSION_DENIED;
return false;
}
}
void Rm::RemoveStaticFile(Item & item)
{
if( system->MakeFilePath(item, path, false) )
{
if( RemoveStaticFile(path) )
{
if( item.has_thumb && system->MakeFilePath(item, path, true) )
{
RemoveStaticFile(path);
item.has_thumb = false;
}
// we don't store it to db (it will be removed or is removed already)
item.file_path.clear();
item.file_type = WINIX_ITEM_FILETYPE_NONE;
}
}
else
{
request->status = WINIX_ERR_PERMISSION_DENIED;
}
}
void Rm::RemoveFileOrSymlink(Item & item)
{
if( db->DelItem(item) == WINIX_ERR_OK )
{
if( item.type == Item::file )
log << log2 << "Rm: deleted file ";
else
log << log2 << "Rm: deleted symlink ";
log << item.url << logend;
TemplatesFunctions::pattern_cacher.DeletePattern(item);
plugin.Call(WINIX_FILE_REMOVED, item.id);
// !! nie potrzebne
//db->EditThreadRemoveItem(item.parent_id);
if( item.file_type != WINIX_ITEM_FILETYPE_NONE )
RemoveStaticFile(item);
}
else
{
// request->status = WINIX_ERR_NO_ITEM;
}
}
void Rm::RemoveDirTree(long dir_id)
{
DirContainer::ParentIterator pnext, p = system->dirs.FindFirstChild(dir_id);
for( ; p != system->dirs.ParentEnd() ; p = pnext )
{
// this iterator p will be deleted by the next DeleteDir(p->second->id)
// (the next iterator we must calculate beforehand)
pnext = system->dirs.NextChild(p);
RemoveDirTree(p->second->id);
}
plugin.Call(WINIX_DIR_PREPARE_TO_REMOVE, dir_id);
static_iq.WhereParentId(dir_id);
db->GetItems(static_item_tab, static_iq);
for(size_t i=0 ; i<static_item_tab.size() ; ++i)
RemoveStaticFile(static_item_tab[i]);
if( db->DelDirById(dir_id) == WINIX_ERR_OK )
{
system->dirs.DelDir(dir_id);
// !! nie potrzebne
//db->RemoveThread(dir_id);
plugin.Call(WINIX_DIR_REMOVED, dir_id);
}
}
void Rm::RemoveDir(const Item & dir)
{
old_url = dir.url;
RemoveDirTree(dir.id);
if( request->status == WINIX_ERR_OK )
log << log3 << "Rm: removed directory " << old_url << logend;
}
void Rm::RemoveFile()
{
RemoveFileOrSymlink(request->item);
if( request->status == WINIX_ERR_OK )
system->RedirectToLastDir();
}
void Rm::RemoveDirContent()
{
if( !request->IsParam(L"r") )
{
request->status = WINIX_ERR_PERMISSION_DENIED;
return;
}
content_dir_iq.WhereParentId(request->dir_tab.back()->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 )
RemoveDir(item_tab[i]);
else
RemoveFileOrSymlink(item_tab[i]);
}
if( request->status == WINIX_ERR_OK )
system->RedirectToLastDir();
}
void Rm::RemoveDir()
{
if( !request->IsParam(L"r") || request->dir_tab.size() <= 1 )
{
// we cannot remove the root directory (dir_tab.size()==1)
request->status = WINIX_ERR_PERMISSION_DENIED;
return;
}
RemoveDir(*request->dir_tab.back());
request->dir_tab.erase(--request->dir_tab.end());
if( request->status == WINIX_ERR_OK )
system->RedirectToLastDir();
}
void Rm::Clear()
{
static_item_tab.clear();
item_tab.clear();
}
void Rm::MakePost()
{
Prepare();
if( request->is_item )
{
RemoveFile();
}
else
{
if( request->IsPostVar(L"onlycontent") )
RemoveDirContent();
else
RemoveDir();
}
Clear();
}
} // namespace