added: now we have a fourth part in permissions (guests)

e.g.: 07555 means:
           7 for owner
           5 for group
           5 for others
           5 for guests (not logged users)
added:     the sticky bit for directories
           e.g. permissions to a directory with a sticky bit set
           can be set to: 017555
rewritten: rm/mv winix functions to correctly understand the sticky bit
added:     Dir::FollowLink() recognizes ".." and "." now
           consequently System::FollowAllLinks recognizes it too
added:     umask -- calculating privileges for new files/directories
           all users have their own umask (in meta)
           and there is one in the config
           (for guests and when a user has not definied its own one)
removed:   mount option: only_root_remove



git-svn-id: svn://ttmath.org/publicrep/winix/trunk@801 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
2012-01-24 23:03:36 +00:00
parent 5aaab89cd8
commit 6e2d00bc5b
34 changed files with 1109 additions and 557 deletions

View File

@@ -29,7 +29,12 @@ adduser.o: ../templates/htmltextstream.h ../core/mounts.h
adduser.o: ../core/mountparser.h ../core/crypt.h ../core/users.h
adduser.o: ../core/groups.h ../core/group.h ../core/loadavg.h ../core/image.h
adduser.o: ../core/basethread.h ../core/threadmanager.h ../core/synchro.h
adduser.o: ../core/slog.h
adduser.o: ../core/slog.h ../core/plugin.h ../core/pluginmsg.h
adduser.o: ../core/system.h ../core/sessionmanager.h
adduser.o: ../core/sessioncontainer.h ../functions/functions.h
adduser.o: ../templates/templates.h ../templates/patterncacher.h
adduser.o: ../templates/indexpatterns.h ../templates/patterns.h
adduser.o: ../templates/changepatterns.h ../core/sessionmanager.h
cat.o: cat.h functionbase.h ../core/item.h ../db/db.h ../db/dbbase.h
cat.o: ../db/dbconn.h ../db/dbtextstream.h ../core/textstream.h
cat.o: ../core/misc.h ../core/item.h ../core/requesttypes.h ../core/error.h

View File

@@ -9,6 +9,7 @@
#include "adduser.h"
#include "core/slog.h"
#include "core/plugin.h"
@@ -112,10 +113,14 @@ void AddUser::MakePost()
{
if( system->users.AddUser(user) )
{
if( !cur->session->puser )
system->users.LoginUser(user.id, false);
log << log2 << "AddUser: added a new user: " << user.name << logend;
if( !cur->session->puser )
{
system->users.LoginUser(user.id, false);
log << log2 << "AddUser: now logged as: " << user.name << logend;
plugin.Call(WINIX_USER_LOGGED);
}
}
else
{

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2010, Tomasz Sowa
* Copyright (c) 2008-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -125,9 +125,9 @@ void Emacs::MakePost()
if( adding )
{
cur->request->is_item = true; // !! moze lepiej nie ustawiac is_item? (bo jak wystapi blad np dodania do bazy danych
// to formularz edycji zmieni sie z 'dodaj' na 'edytuj'
cur->request->item.privileges = 0644; // !! tymczasowo, bedzie uzyte umask
cur->request->is_item = true; // !! moze lepiej nie ustawiac is_item? (bo jak wystapi blad np dodania do bazy danych
// to formularz edycji zmieni sie z 'dodaj' na 'edytuj'
cur->request->item.privileges = system->NewFilePrivileges();
cur->request->status = system->AddFile(cur->request->item, NotifyCodeAdd());
}
else

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010-2011, Tomasz Sowa
* Copyright (c) 2010-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -19,8 +19,8 @@ FunctionBase::FunctionBase()
fun.user_id = -1;
fun.group_id = -1;
fun.privileges = 0755;
fun.parent_id = -1; // !! temporarily doesn't matter
fun.privileges = 07555;
fun.parent_id = -1;
fun.id = -1;
fun.type = Item::file;
}

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010, Tomasz Sowa
* Copyright (c) 2010-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -37,7 +37,7 @@ void Ln::CreateSymbolicLink(const std::wstring & link_to)
item.url = cur->request->PostVar(L"url");
item.link_to = link_to;
item.link_redirect = cur->request->IsPostVar(L"makeredirect") ? 1 : 0;
item.privileges = 0644; // !! tymczasowo, bedzie uzyte umask
item.privileges = system->NewFilePrivileges();
functions->SetUser(item);
functions->PrepareUrl(item);
@@ -64,7 +64,7 @@ void Ln::CreateHardLink(const std::wstring & link_to)
item.type = Item::file;
item.parent_id = cur->request->dir_tab.back()->id;
item.url = cur->request->PostVar(L"url");
item.privileges = 0644; // !! tymczasowo, bedzie uzyte umask
item.privileges = system->NewFilePrivileges();
functions->SetUser(item);
functions->PrepareUrl(item);
cur->request->status = db->AddHardLink(item);

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2010, Tomasz Sowa
* Copyright (c) 2008-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -79,7 +79,7 @@ void Mkdir::PostFunMkdir(bool add_to_dir_tab, int privileges)
void Mkdir::MakePost()
{
PostFunMkdir(false, 0755);
PostFunMkdir(false, system->NewDirPrivileges());
}

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2011, Tomasz Sowa
* Copyright (c) 2008-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -21,73 +21,131 @@ Mv::Mv()
{
fun.url = L"mv";
follow_symlinks = false;
Prepare();
}
// !! CHECK ME
// check if everywhere correct messages are sent (prepare_to, modified item/dir)
bool Mv::HasAccess()
{
return CheckAccessFrom();
}
bool Mv::CheckAccessFromToDir()
{
Item * last;
Item * last_but_one = 0;
size_t dir_tab_size;
last = cur->request->dir_tab.back();
dir_tab_size = cur->request->dir_tab.size();
if( dir_tab_size <= 1 )
return false; // you cannot move the root directory
last_but_one = cur->request->dir_tab[dir_tab_size - 2];
if( cur->request->method != Request::post )
{
// used in GET or HEAD
// we don't now whether we move the last directory or the last but one
// it depends on the 'onlycontent' parameter
if( !system->HasWriteAccess(*last) && !system->HasWriteAccess(*last_but_one) )
return false;
}
else
{
// used in POST when the moving is performed
if( cur->request->IsPostVar(L"onlycontent") )
return system->HasWriteAccess(*last);
else
return system->HasWriteAccess(*last_but_one);
}
return true;
}
bool Mv::CheckAccessFrom()
{
if( cur->request->is_item )
{
// moving a file
if( !system->HasWriteAccess(*cur->request->dir_tab.back()) )
if( !system->CanRemoveRenameChild(*cur->request->dir_tab.back(), cur->request->item.user_id) )
return false;
}
else
{
bool only_content = (cur->request->IsParam(L"c") || cur->request->IsPostVar(L"c"));
if( !CheckAccessFromToDir(*cur->request->dir_tab.back(), only_content) )
return false;
}
return true;
}
bool Mv::CheckAccessFromToDir(const Item & dir, bool only_content)
{
if( dir.parent_id == -1 )
{
if( !only_content )
{
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
// the root directory cannot be moved anywhere
return false;
}
}
else
if( only_content )
{
if( !CheckAccessFromToDir() )
{
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
// sticky bit for a specified child will be checked later
if( !system->HasWriteAccess(dir) )
return false;
}
else
{
Item * last_but_one_dir = system->dirs.GetDir(dir.parent_id);
if( !last_but_one_dir )
// ops, there is no a parent dir
return false;
if( !system->CanRemoveRenameChild(*last_but_one_dir, dir.user_id) )
return false;
}
return true;
}
// !! IMPROVE ME: may a better name?
void Mv::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;
content_dir_iq.sel_user_id = true;
content_dir_iq.sel_group_id = true;
content_dir_iq.sel_privileges = true;
content_dir_iq.sel_meta = true;
files_iq.SetAll(false, false);
files_iq.sel_parent_id = true;
files_iq.sel_type = true;
files_iq.sel_url = true;
files_iq.sel_file = true;
files_iq.sel_user_id = true;
files_iq.sel_group_id = true;
files_iq.sel_privileges = true;
files_iq.sel_meta = true;
files_iq.WhereType(Item::dir, false);
}
void Mv::Clear()
{
out_dir_tab.clear();
out_item.Clear();
out_filename.clear();
files_item_tab.clear();
item_tab.clear();
}
bool Mv::ParseDirCheckLastName()
{
if( out_has_file )
{
log << log1 << "Mv: incorrent path" << logend;
slog << logerror << T("mv_incorrect_path") << logend;
return false;
}
else
{
Item * dir = system->dirs.GetDir(out_filename, out_dir_tab.back()->id);
if( dir )
{
out_dir_tab.push_back(dir);
out_filename.clear();
}
else
{
if( db->GetItem(out_dir_tab.back()->id, out_filename, out_item) == WINIX_ERR_OK )
{
out_has_file = true;
out_filename.clear();
}
}
}
@@ -95,13 +153,48 @@ return true;
}
bool Mv::CheckAccessTo()
bool Mv::ParseDir(const std::wstring & dst_path, bool check_access)
{
if( dir_tab.empty() ||
!system->HasReadExecAccessToPath(dir_tab) ||
!system->HasWriteAccess(*dir_tab.back()) )
if( dst_path.empty() )
return false;
// first we should remove the last name from the dst_path
// (it may not exist in current file system and FollowAllLinks will fail)
size_t last_slash = dst_path.find_last_of('/');
out_path = dst_path;
out_filename.clear();
if( last_slash != std::wstring::npos && last_slash + 1 < dst_path.size() )
{
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
out_path.erase(last_slash + 1); // leaving the slash at the end
out_filename = dst_path.c_str() + last_slash + 1;
}
int res = system->FollowAllLinks(cur->request->dir_tab, out_path, out_dir_tab, out_item, false, false, check_access);
if( res != 0 && res != 1 )
{
slog << logerror << T("mv_incorrect_dst_path") << logend;
return false;
}
out_has_file = (res == 1);
if( !out_filename.empty() )
return ParseDirCheckLastName();
return true;
}
bool Mv::CanRemoveRenameChild(const Item & child)
{
Item * parent_dir = system->dirs.GetDir(child.parent_id);
if( !parent_dir || !system->CanRemoveRenameChild(*parent_dir, child.user_id) )
{
log << log1 << "Mv: permission denied to: " << child.url << logend;
slog << logerror << T("mv_permission_denied_to") << ": " << child.url << logend;
return false;
}
@@ -109,25 +202,6 @@ return true;
}
bool Mv::ParseDir()
{
const std::wstring & new_dir = cur->request->PostVar(L"to");
int res = system->dirs.FollowLink(cur->request->dir_tab, new_dir, dir_tab, file);
if( res == 3 )
cur->request->status = WINIX_ERR_NO_ROOT_DIR;
else
if( res != 0 && res != 1 )
cur->request->status = WINIX_ERR_INCORRECT_DIR;
return res == 0 || res == 1;
}
bool Mv::MoveStaticFile(const std::wstring & from, const std::wstring & to)
{
if( from == to )
@@ -143,8 +217,8 @@ bool Mv::MoveStaticFile(const std::wstring & from, const std::wstring & to)
}
else
{
log << log1 << "Mv: can't move a file from: " << from << ", to: " << to << logend;
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
log << log1 << "Mv: cannot move a static file from: " << from << ", to: " << to << logend;
slog << logerror << T("internal_error") << logend;
return false;
}
}
@@ -155,124 +229,44 @@ void Mv::MoveStaticFile(Item & item)
{
bool res1, res2, res3, res4, res5;
res1 = system->MakeFilePath(item, old_path, false);
res2 = !item.has_thumb || system->MakeFilePath(item, old_path_thumb, true);
res1 = system->MakeFilePath(item, old_static_path, false);
res2 = !item.has_thumb || system->MakeFilePath(item, old_static_thumb_path, 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);
res4 = system->MakeFilePath(item, new_static_path, false, true, config->upload_dirs_chmod);
res5 = !item.has_thumb || system->MakeFilePath(item, new_static_thumb_path, true, true, config->upload_dirs_chmod);
if( !res1 || !res2 || !res3 || !res4 || !res5 )
{
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
log << log1 << "Mv: cannot create a static path" << logend;
slog << logerror << T("internal_error") << logend;
return;
}
if( MoveStaticFile(old_path, new_path) )
if( MoveStaticFile(old_static_path, new_static_path) )
{
cur->request->status = db->EditFileById(item, item.id);
if( db->EditFileById(item, item.id) != WINIX_ERR_OK )
{
log << log1 << "Mv: cannot move static file (database problem)" << logend;
slog << logerror << T("internal_error") << logend;
return;
}
if( item.has_thumb )
MoveStaticFile(old_path_thumb, new_path_thumb);
MoveStaticFile(old_static_thumb_path, new_static_thumb_path);
}
}
void Mv::MoveFileOrSymlink(Item & item)
void Mv::MoveFilesPrepareTreeGo(const Item & src_dir)
{
plugin.Call(WINIX_FILE_PREPARE_TO_MOVE, &item);
old_url = item.url;
if( !file.empty() )
{
item.url = file;
functions->PrepareUrl(item);
file.clear();
}
item.parent_id = dir_tab.back()->id;
cur->request->status = db->EditParentUrlById(item, item.id);
if( cur->request->status == WINIX_ERR_OK )
{
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;
if( item.file_type != WINIX_ITEM_FILETYPE_NONE )
MoveStaticFile(item);
plugin.Call(WINIX_FILE_MOVED, &item);
}
}
void Mv::MoveDirContent(const Item & dir)
{
content_dir_iq.WhereParentId(dir.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 )
MoveDir(item_tab[i]);
else
MoveFileOrSymlink(item_tab[i]);
}
}
void Mv::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;
files_iq.SetAll(false, false);
files_iq.sel_parent_id = true;
files_iq.sel_type = true;
files_iq.sel_url = true;
files_iq.sel_file = true;
files_iq.WhereType(Item::dir, false);
}
void Mv::Clear()
{
dir_tab.clear();
files_item_tab.clear();
item_tab.clear();
}
void Mv::MoveFilesPrepareTree(const Item & dir)
{
// we only calling plugins here
// so if there is no WINIX_FILE_PREPARE_TO_MOVE message
// we can immediately return and the database will not be bothered
if( !plugin.HasMessage(WINIX_FILE_PREPARE_TO_MOVE) )
return;
DirContainer::ParentIterator i = system->dirs.FindFirstChild(dir.id);
DirContainer::ParentIterator i = system->dirs.FindFirstChild(src_dir.id);
// go through all directories
for( ; i != system->dirs.ParentEnd() ; i = system->dirs.NextChild(i) )
MoveFilesPrepareTree(*(i->second));
files_iq.WhereParentId(dir.id);
files_iq.WhereParentId(src_dir.id);
db->GetItems(files_item_tab, files_iq);
for(size_t i=0 ; i<files_item_tab.size() ; ++i)
@@ -280,6 +274,20 @@ void Mv::MoveFilesPrepareTree(const Item & dir)
}
void Mv::MoveFilesPrepareTree(const Item & src_dir)
{
// we only calling plugins here
// so if there is no WINIX_FILE_PREPARE_TO_MOVE message
// we can immediately return and the database will not be bothered
if( plugin.HasMessage(WINIX_FILE_PREPARE_TO_MOVE) )
{
MoveFilesPrepareTree(src_dir);
}
}
void Mv::MoveFilesTree(const Item & dir)
{
DirContainer::ParentIterator i = system->dirs.FindFirstChild(dir.id);
@@ -294,69 +302,193 @@ void Mv::MoveFilesTree(const Item & dir)
for(size_t i=0 ; i<files_item_tab.size() ; ++i)
{
if( files_item_tab[i].file_type != WINIX_ITEM_FILETYPE_NONE )
{
plugin.Call(WINIX_FILE_PREPARE_TO_MOVE, &files_item_tab[i]);
MoveStaticFile(files_item_tab[i]);
plugin.Call(WINIX_FILE_MOVED, &files_item_tab[i]);
plugin.Call(WINIX_FILE_MOVED, &files_item_tab[i]);
}
}
}
void Mv::MoveDir(Item & dir)
{
long dst_dir_id = dir_tab.back()->id;
old_url = dir.url;
if( dst_dir_id == dir.id || system->dirs.HasParent(dst_dir_id, dir.id) )
// private
// uses: out_dir_tab, out_filename
bool Mv::MoveDir(Item & src_dir, std::vector<Item*> & dst_dir_tab, const std::wstring & dst_name)
{
long dst_dir_id = dst_dir_tab.back()->id;
old_url = src_dir.url;
if( dst_dir_id == src_dir.id || system->dirs.HasParent(dst_dir_id, src_dir.id) )
{
log << log1 << "Mv: cannot move directory to inside it" << logend;
cur->request->status = WINIX_ERR_INCORRECT_DIR;
return;
slog << logerror << T("mv_cannot_move_to_inside");
return false;
}
MoveFilesPrepareTree(dir);
MoveFilesPrepareTree(src_dir);
if( !system->dirs.ChangeParent(dir.id, dst_dir_id) )
if( !system->dirs.ChangeParent(src_dir.id, dst_dir_id) )
return false;
src_dir.parent_id = dst_dir_id;
old_url = src_dir.url;
if( !dst_name.empty() )
{
cur->request->status = WINIX_ERR_INCORRECT_DIR;
return;
src_dir.url = dst_name;
functions->PrepareUrl(src_dir);
}
dir.parent_id = dst_dir_id;
Error status = db->EditParentUrlById(src_dir, src_dir.id);
if( !file.empty() )
{
dir.url = file;
functions->PrepareUrl(dir);
file.clear();
}
cur->request->status = db->EditParentUrlById(dir, dir.id);
if( cur->request->status == WINIX_ERR_OK )
if( status == WINIX_ERR_OK )
{
log << log3 << "Mv: directory: " << old_url << " was moved to: ";
system->dirs.LogDir(dir_tab);
log << dir.url << logend;
system->dirs.LogDir(dst_dir_tab);
log << src_dir.url << logend;
MoveFilesTree(dir);
MoveFilesTree(src_dir);
return true;
}
return false;
}
// public
bool Mv::MoveDir(Item & src_dir, long dst_dir_id, const std::wstring & new_url, bool check_access)
{
bool res = MoveDir2(src_dir, dst_dir_id, new_url, check_access);
Clear();
return res;
}
// private
bool Mv::MoveDir2(Item & src_dir, long dst_dir_id, const std::wstring & new_url, bool check_access)
{
if( src_dir.type != Item::dir )
{
log << "Mv: a directory required" << logend;
return false;
}
if( src_dir.parent_id == -1 )
{
log << log1 << "Mv: the root directory cannot be moved anywhere" << logend;
slog << logerror << T("mv_cant_move_root_dir") << logend;
return false;
}
if( check_access && !CanRemoveRenameChild(src_dir) )
return false;
if( src_dir.id == dst_dir_id )
{
if( new_url.empty() || src_dir.url == new_url )
return true; // the same directory -- there is nothing to do
}
if( !system->dirs.CreateDirTab(dst_dir_id, out_dir_tab) )
{
log << log1 << "Mv: incorrect directory" << logend;
slog << logerror << T("mv_incorrect_dir") << logend;
return false;
}
return MoveDir(src_dir, out_dir_tab, new_url);
}
// public
bool Mv::MoveDir(Item & src_dir, const std::wstring & dst_path, bool check_access)
{
bool res = MoveDir2(src_dir, dst_path, check_access);
Clear();
return res;
}
// private
bool Mv::MoveDir2(Item & src_dir, const std::wstring & dst_path, bool check_access)
{
if( src_dir.type != Item::dir )
{
log << "Mv: a directory required" << logend;
return false;
}
if( src_dir.parent_id == -1 )
{
log << log1 << "Mv: the root directory cannot be moved anywhere" << logend;
slog << logerror << T("mv_cant_move_root_dir") << logend;
return false;
}
if( check_access && !CanRemoveRenameChild(src_dir) )
return false;
if( !ParseDir(dst_path, check_access) )
return false;
if( out_has_file )
{
log << log1 << "Mv: directory can be moved only to a directory" << logend;
slog << logerror << T("mv_dir_can_be_moved_to_dir") << logend;
return false;
}
if( src_dir.id == out_dir_tab.back()->id )
{
if( out_filename.empty() || src_dir.url == out_filename )
return true; // the same directory -- there is nothing to do
}
return MoveDir(src_dir, out_dir_tab, out_filename);
}
bool Mv::IsTheSameFile(const Item & item)
// private
bool Mv::MoveFileOrSymlink(Item & src_file, std::vector<Item*> & dst_dir_tab, const std::wstring & new_url)
{
if( file.empty() )
plugin.Call(WINIX_FILE_PREPARE_TO_MOVE, &src_file);
old_url = src_file.url;
if( !new_url.empty() )
{
if( item.parent_id == dir_tab.back()->id )
return true; // nothing to do
src_file.url = new_url;
functions->PrepareUrl(src_file);
}
else
src_file.parent_id = dst_dir_tab.back()->id;
Error status = db->EditParentUrlById(src_file, src_file.id);
if( status == WINIX_ERR_OK )
{
if( item.parent_id == dir_tab.back()->id && item.url == file )
return true; // nothing to do
if( src_file.type == Item::file )
log << log3 << "Mv: file: ";
else
log << log3 << "Mv: symlink: ";
log << old_url << " was moved to: ";
system->dirs.LogDir(dst_dir_tab);
log << src_file.url << logend;
if( src_file.file_type != WINIX_ITEM_FILETYPE_NONE )
MoveStaticFile(src_file);
plugin.Call(WINIX_FILE_MOVED, &src_file);
return true;
}
return false;
@@ -364,48 +496,164 @@ return false;
void Mv::PostMoveFile()
// public
bool Mv::MoveFileOrSymlink(Item & src_file, long dst_dir_id, const std::wstring & new_url, bool check_access)
{
if( IsTheSameFile(cur->request->item) )
return;
bool res = MoveFileOrSymlink2(src_file, dst_dir_id, new_url, check_access);
Clear();
MoveFileOrSymlink(cur->request->item);
return res;
}
if( cur->request->status == WINIX_ERR_OK )
system->RedirectTo(cur->request->item);
// private
bool Mv::MoveFileOrSymlink2(Item & src_file, long dst_dir_id, const std::wstring & new_url, bool check_access)
{
if( src_file.type == Item::dir )
{
log << "Mv: a file/symlink required" << logend;
return false;
}
if( check_access && !CanRemoveRenameChild(src_file) )
return false;
if( src_file.parent_id == dst_dir_id )
{
if( new_url.empty() || src_file.url == new_url )
return true; // the same file -- there is nothing to do
}
if( !system->dirs.CreateDirTab(dst_dir_id, out_dir_tab) )
return false;
return MoveFileOrSymlink(src_file, out_dir_tab, new_url);
}
// public
bool Mv::MoveFileOrSymlink(Item & src_file, const std::wstring & dst_path, bool check_access)
{
bool res = MoveFileOrSymlink2(src_file, dst_path, check_access);
Clear();
return res;
}
// private
bool Mv::MoveFileOrSymlink2(Item & src_file, const std::wstring & dst_path, bool check_access)
{
if( src_file.type == Item::dir )
{
log << "Mv: a file/symlink required" << logend;
return false;
}
if( check_access && !CanRemoveRenameChild(src_file) )
return false;
if( !ParseDir(dst_path, check_access) )
return false;
if( src_file.parent_id == out_dir_tab.back()->id )
{
// actually out_filename is here empty
// because ParseDir() have been read it to out_item
if( out_filename.empty() || src_file.url == out_filename )
return true; // the same file -- there is nothing to do
}
return MoveFileOrSymlink(src_file, out_dir_tab, out_filename);
}
void Mv::PostMoveDirContent()
// private
void Mv::MoveAllFilesFromDir(Item & src_dir, std::vector<Item*> & dst_dir_tab, bool check_access)
{
if( !file.empty() )
content_dir_iq.WhereParentId(src_dir.id);
db->GetItems(item_tab, content_dir_iq);
out_filename.clear();
for(size_t i=0 ; i<item_tab.size() ; ++i)
{
cur->request->status = WINIX_ERR_INCORRECT_DIR;
if( check_access && !system->CanRemoveRenameChild(src_dir, item_tab[i].user_id) )
{
log << log1 << "Mv: permission denied to: " << src_dir.url << logend;
slog << logerror << T("mv_permission_denied_to") << ": " << src_dir.url << logend;
}
else
{
if( item_tab[i].type == Item::dir )
MoveDir(item_tab[i], dst_dir_tab, out_filename);
else
MoveFileOrSymlink(item_tab[i], dst_dir_tab, out_filename);
}
}
}
// public
void Mv::MoveDirContent(Item & src_dir, long dst_dir_id, bool check_access)
{
MoveDirContent2(src_dir, dst_dir_id, check_access);
Clear();
}
// private
void Mv::MoveDirContent2(Item & src_dir, long dst_dir_id, bool check_access)
{
if( src_dir.type != Item::dir )
{
log << "Mv: a directory required" << logend;
return;
}
if( cur->request->dir_tab.back()->id == dir_tab.back()->id )
return; // nothing to do
if( src_dir.parent_id == -1 )
{
log << log1 << "Mv: the root directory cannot be moved anywhere" << logend;
slog << logerror << T("mv_cant_move_root_dir") << logend;
return;
}
MoveDirContent(*cur->request->dir_tab.back());
system->RedirectToLastDir();
if( !system->dirs.CreateDirTab(dst_dir_id, out_dir_tab) )
{
log << log1 << "Mv: incorrect directory" << logend;
slog << logerror << T("mv_incorrect_dir") << logend;
return;
}
MoveAllFilesFromDir(src_dir, out_dir_tab, check_access);
}
void Mv::PostMoveDir()
// public
void Mv::MoveDirContent(Item & src_dir, const std::wstring & dst_dir, bool check_access)
{
Item & last_dir = *cur->request->dir_tab.back();
Item & new_dir = *dir_tab.back();
MoveDirContent2(src_dir, dst_dir, check_access);
Clear();
}
if( file.empty() && new_dir.id == last_dir.id )
return; // nothing to do
MoveDir(last_dir);
if( cur->request->status == WINIX_ERR_OK )
system->RedirectToLastDir();
// private
void Mv::MoveDirContent2(Item & src_dir, const std::wstring & dst_dir, bool check_access)
{
if( !ParseDir(dst_dir, check_access) )
return;
if( out_has_file || !out_filename.empty() )
{
log << log1 << "Mv: directory content can be moved only to a directory" << logend;
slog << logerror << T("mv_dir_content_can_be_moved_to_dir") << logend;
return;
}
MoveDirContent2(src_dir, out_dir_tab.back()->id, check_access);
}
@@ -413,26 +661,23 @@ void Mv::PostMoveDir()
void Mv::MakePost()
{
if( CheckAccessFrom() &&
ParseDir() &&
CheckAccessTo() )
const std::wstring & dst_path = cur->request->PostVar(L"dst_path");
bool ok = true;
if( cur->request->is_item )
{
Prepare();
if( cur->request->is_item )
{
PostMoveFile();
}
else
{
if( cur->request->IsPostVar(L"onlycontent") )
PostMoveDirContent();
else
PostMoveDir();
}
Clear();
ok = MoveFileOrSymlink(cur->request->item, dst_path, true);
}
else
{
if( cur->request->IsParam(L"c") || cur->request->IsPostVar(L"c") )
MoveDirContent(*cur->request->dir_tab.back(), dst_path, true);
else
ok = MoveDir(*cur->request->dir_tab.back(), dst_path, true);
}
if( ok )
system->RedirectToLastItem();
}

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010, Tomasz Sowa
* Copyright (c) 2010-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -28,46 +28,74 @@ public:
bool HasAccess();
void MakePost();
// moving a directory
// new_url can be empty (in such a case the old one is preserved)
// src_dir will be accordingly updated
bool MoveDir(Item & src_dir, long dst_dir_id, const std::wstring & new_url, bool check_access = true);
bool MoveDir(Item & src_dir, const std::wstring & dst_path, bool check_access = true);
// moving only the content of src_dir
// dst_path should point to an existing directory
// src_dir will be accordingly updated
void MoveDirContent(Item & src_dir, long dst_dir_id, bool check_access = true);
void MoveDirContent(Item & src_dir, const std::wstring & dst_dir, bool check_access = true);
// moving a file
// new_url can be empty (the old one is used then)
// src_file will be accordingly updated
bool MoveFileOrSymlink(Item & src_file, long dst_dir_id, const std::wstring & new_url, bool check_access = true);
bool MoveFileOrSymlink(Item & src_file, const std::wstring & dst_path, bool check_access = true);
private:
// destination dir
std::vector<Item*> dir_tab;
// destination file (if exists)
std::wstring file;
// directories parsed by ParseDir()
std::vector<Item*> out_dir_tab; // destination directories
Item out_item; // destination file/symlink (if out_has_file is true)
bool out_has_file; // if true then out_item is set
std::wstring out_filename; // the last part in an input path (not an existing directory, file or symlink)
// can be empty
// for copying static files
std::wstring new_path, new_path_thumb;
std::wstring old_path, old_path_thumb;
// temporaries
std::wstring out_path;
std::wstring old_url;
// for files in a directory
std::wstring old_static_path;
std::wstring old_static_thumb_path;
std::wstring new_static_path;
std::wstring new_static_thumb_path;
// for files/symlinks in a directory
std::vector<Item> files_item_tab;
DbItemQuery files_iq;
// for moving content of a directory
// for moving content of a directory (all dirs/files/symlinks)
DbItemQuery content_dir_iq;
std::vector<Item> item_tab;
// for logging
std::wstring old_url;
bool CheckAccessFromToDir();
bool CheckAccessFrom();
bool CheckAccessTo();
bool ParseDir();
bool CheckAccessFromToDir(const Item & dir, bool only_content);
bool CanRemoveRenameChild(const Item & child);
void Prepare();
bool ParseDirCheckLastName();
bool ParseDir(const std::wstring & dst_path, bool check_access);
bool MoveStaticFile(const std::wstring & from, const std::wstring & to);
void MoveStaticFile(Item & item);
void MoveFileOrSymlink(Item & item);
void MoveDirContent(const Item & dir);
void Prepare();
void Clear();
void MoveFilesPrepareTree(const Item & dir);
void MoveFilesPrepareTreeGo(const Item & src_dir);
void MoveFilesPrepareTree(const Item & src_dir);
void MoveFilesTree(const Item & dir);
void MoveDir(Item & dir);
bool IsTheSameFile(const Item & item);
void PostMoveFile();
void PostMoveDirContent();
void PostMoveDir();
bool MoveDir(Item & src_dir, std::vector<Item*> & dst_dir_tab, const std::wstring & dst_name);
bool MoveFileOrSymlink(Item & src_file, std::vector<Item*> & dst_dir_tab, const std::wstring & new_url);
void Clear();
bool MoveDir2(Item & src_dir, long dst_dir_id, const std::wstring & new_url, bool check_access);
bool MoveDir2(Item & src_dir, const std::wstring & dst_path, bool check_access);
bool MoveFileOrSymlink2(Item & src_file, long dst_dir_id, const std::wstring & new_url, bool check_access);
bool MoveFileOrSymlink2(Item & src_file, const std::wstring & dst_path, bool check_access);
void MoveDirContent2(Item & src_dir, long dst_dir_id, bool check_access);
void MoveAllFilesFromDir(Item & src_dir, std::vector<Item*> & dst_dir_tab, bool check_access);
void MoveDirContent2(Item & src_dir, const std::wstring & dst_dir, bool check_access);
};

View File

@@ -51,13 +51,13 @@ bool PrivChanger::ChangeOwner(Item & item, long user_id, long group_id)
{
if( !system->CanChangeUser(item, user_id) )
{
log << log3 << "Content: can't change the user" << logend;
log << log3 << "Priv: can't change the user" << logend;
return false;
}
if( !system->CanChangeGroup(item, group_id) )
{
log << log3 << "Content: can't change the group" << logend;
log << log3 << "Priv: can't change the group" << logend;
return false;
}
}
@@ -76,7 +76,7 @@ bool PrivChanger::ChangePrivileges(Item & item, int privileges)
{
if( !system->CanChangePrivileges(item, privileges) )
{
log << log3 << "Content: can't change privileges" << logend;
log << log3 << "Priv: can't change privileges" << logend;
return false;
}
}
@@ -153,7 +153,7 @@ Item * root = 0;
if( id != -1 )
root = system->dirs.GetRootDir();
log << log3 << "Content: " << what;
log << log3 << "Priv: " << what;
if( root && root->id == id )
log << "(root)";
@@ -169,7 +169,7 @@ void PrivChanger::PrivFilesInDir(long parent_id)
DbItemQuery iq;
iq.SetAll(false, false);
iq.sel_user_id = iq.sel_group_id = iq.sel_guest_name = iq.sel_privileges = true;
iq.sel_user_id = iq.sel_group_id = iq.sel_guest_name = iq.sel_privileges = iq.sel_url = true;
iq.WhereParentId(parent_id);
iq.WhereType(Item::dir, false);
@@ -230,8 +230,8 @@ void PrivChanger::PrivDir()
ReadPriv(L"userfile", L"groupfile", L"privilegesfile", user_id_file, group_id_file, priv_file);
ReadPriv(L"userdir", L"groupdir", L"privilegesdir", user_id_dir, group_id_dir, priv_dir);
PrivLogStart(L"Content: changes for files: ", user_id_file, group_id_file, priv_file);
PrivLogStart(L"Content: changes for dirs: ", user_id_dir, group_id_dir, priv_dir);
PrivLogStart(L"Priv: changes for files: ", user_id_file, group_id_file, priv_file);
PrivLogStart(L"Priv: changes for dirs: ", user_id_dir, group_id_dir, priv_dir);
if( cur->request->IsPostVar(L"changecurrentdir") )
@@ -256,7 +256,7 @@ void PrivChanger::PrivDir()
void PrivChanger::PrivOneItem()
{
ReadPriv(L"user", L"group", L"privileges", user_id_file, group_id_file, priv_file);
PrivLogStart(L"Content: changes: ", user_id_file, group_id_file, priv_file);
PrivLogStart(L"Priv: changes: ", user_id_file, group_id_file, priv_file);
if( cur->request->is_item )
{

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2010, Tomasz Sowa
* Copyright (c) 2008-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -18,10 +18,17 @@ namespace Fun
Reload::Reload()
{
fun.url = L"reload";
fun.privileges = 0700;
fun.privileges = 07000;
}
bool Reload::HasAccess()
{
return cur->session->puser && cur->session->puser->super_user;
}
void Reload::FunReloadTemplates()
{
log << log1 << "Content: reloading html templates" << logend;

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010, Tomasz Sowa
* Copyright (c) 2010-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -23,6 +23,7 @@ class Reload : public FunctionBase
public:
Reload();
bool HasAccess();
void MakeGet();
private:

View File

@@ -2,13 +2,12 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2010, Tomasz Sowa
* Copyright (c) 2008-2012, Tomasz Sowa
* All rights reserved.
*
*/
#include <cstdio>
#include <errno.h>
#include "rm.h"
#include "core/plugin.h"
#include "core/misc.h"
@@ -27,49 +26,70 @@ Rm::Rm()
bool Rm::HasAccess(const Item & item)
bool Rm::HasAccessToDir(const Item & dir, bool only_content)
{
// !! temporarily (we're waiting for the sticky bit to be implemented)
// not logged users cannot remove anything
if( !cur->session->puser )
return false;
if( item.parent_id == -1 )
if( dir.parent_id == -1 )
{
// this is a root directory
// 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) )
// sticky bit for a specified child will be checked later
if( !only_content || !system->HasWriteAccess(dir) )
return false;
}
else
if( only_content )
{
// sticky bit for a specified child will be checked later
if( !system->HasWriteAccess(dir) )
return false;
}
else
{
Item * last_but_one_dir = system->dirs.GetDir(item.parent_id);
Item * last_but_one_dir = system->dirs.GetDir(dir.parent_id);
if( !last_but_one_dir )
// ops, there is no a parent dir
return false;
if( !system->HasWriteAccess(*last_but_one_dir) )
if( !system->CanRemoveRenameChild(*last_but_one_dir, dir.user_id) )
return false;
}
if( system->mounts.pmount->IsPar(system->mounts.MountParOnlyRootRemove()) )
if( !cur->session->puser || !cur->session->puser->super_user )
return false;
return true;
}
/*
here we are making a little test -- this method returns false if
we are sure that the permissions is not allowed (consequently the html form
will not be displayed)
the correct checking for permissions is done later in MakePost() method
parameter 'c' to rm function means removing only the content of a directory
this parameter can be sent either by a get or a post variable
*/
bool Rm::HasAccess()
{
bool res;
if( !cur->request->is_item )
res = HasAccess(*cur->request->dir_tab.back());
if( cur->request->is_item )
{
res = system->CanRemoveRenameChild(*cur->request->dir_tab.back(), cur->request->item.user_id);
}
else
res = HasAccess(cur->request->item);
{
if( cur->request->IsParam(L"r") )
{
bool only_content = (cur->request->IsParam(L"c") || cur->request->IsPostVar(L"c"));
res = HasAccessToDir(*cur->request->dir_tab.back(), only_content);
}
else
{
log << log3 << "Rm: directories can be removed only with 'r' parameter" << logend;
slog << logerror << T("rm_use_r_option") << logend;
}
}
if( !res && cur->request->IsParam(L"jquery_upload") )
CreateJSON(res);
@@ -83,66 +103,70 @@ void Rm::Prepare()
{
// selecting files and symlinks (without directories)
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;
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;
content_dir_iq.sel_user_id = true;
content_dir_iq.sel_group_id = true;
content_dir_iq.sel_privileges = true;
content_dir_iq.sel_meta = true;
content_dir_iq.WhereType(Item::dir, false);
// selecting files, symlinks and directories
content_dir_iq2.SetAll(false, false);
content_dir_iq2.sel_parent_id = true;
content_dir_iq2.sel_type = true;
content_dir_iq2.sel_url = true;
content_dir_iq2.sel_file = true;
}
bool Rm::RemoveStaticFile(const std::wstring & path)
void Rm::RemoveStaticFile(const std::wstring & path)
{
if( ::RemoveFile(path) )
{
log << log2 << "Rm: removed static file: " << path << logend;
return true;
log << log2 << "Rm: static file removed: " << path << logend;
}
else
{
log << log1 << "Rm: can't remove a file: " << path << logend;
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
return false;
log << log1 << "Rm: I can't remove a static file: " << path << logend;
slog << logerror << T("rm_cannot_remove_static_file") << ": " << path << logend;
}
}
void Rm::RemoveStaticFile(Item & item)
void Rm::RemoveStaticFile(const Item & item)
{
if( system->MakeFilePath(item, path, false) )
{
if( RemoveStaticFile(path) )
{
if( item.has_thumb && system->MakeFilePath(item, path, true) )
RemoveStaticFile(path);
RemoveStaticFile(path);
// we don't change item.file_path and others file_* variables
// they can be used by a plugin
}
if( item.has_thumb && system->MakeFilePath(item, path, true) )
RemoveStaticFile(path);
}
else
{
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
log << log1 << "Rm: I cannot create a path to a static file, url: "
<< item.url << ", id: " << item.id << logend;
slog << logerror << T("rm_cannot_create_static_path") << ": " << item.url << logend;
}
}
void Rm::RemoveFileOrSymlink(Item & item)
/*
!! IMPROVE ME:
plugin.Call(WINIX_FILE_REMOVED, &item) is getting its parameter as non-const
in the future we can add a pointer cp1, cp2 (in plugins) but pointing to a const object
and this bool Rm::RemoveFile(Item & item) can became bool Rm::RemoveFile(const Item & item)
*/
bool Rm::RemoveFile(Item & item)
{
plugin.Call(WINIX_FILE_PREPARE_TO_REMOVE, &item);
if( db->DelItem(item) == WINIX_ERR_OK )
{
if( item.type == Item::file )
log << log2 << "Rm: deleted file ";
log << log2 << "Rm: deleted file: ";
else
log << log2 << "Rm: deleted symlink ";
log << log2 << "Rm: deleted symlink: ";
log << item.url << logend;
@@ -152,121 +176,209 @@ void Rm::RemoveFileOrSymlink(Item & item)
RemoveStaticFile(item);
plugin.Call(WINIX_FILE_REMOVED, &item);
return true;
}
return false;
}
/*
we do not modify item
it is non-const because we use plugin.Call() later with a pointer to this structure
(and we want to avoid casting)
*/
bool Rm::RemoveFileOrSymlink(Item & item, bool check_access)
{
if( item.type == Item::dir )
return false;
if( check_access )
{
Item * dir = system->dirs.GetDir(item.parent_id);
// if there is not 'dir' directory then we can simply remove 'item'
if( dir )
{
if( !system->CanRemoveRenameChild(*dir, item.user_id) )
{
log << log1 << "Rm: permission denied to remove: " << item.url << ", id: " << item.id << logend;
slog << logerror << T("rm_permission_denied_to") << ": " << item.url << logend;
return false;
}
}
}
return RemoveFile(item);
}
// for other uses (plugins etc)
void Rm::RemoveItemById(long item_id)
void Rm::RemoveItemById(long item_id, bool check_access)
{
// selecting files, symlinks and directories
rm_by_id_iq.SetAll(false, false);
rm_by_id_iq.sel_parent_id = true;
rm_by_id_iq.sel_type = true;
rm_by_id_iq.sel_url = true;
rm_by_id_iq.sel_file = true;
rm_by_id_iq.sel_parent_id = true;
rm_by_id_iq.sel_type = true;
rm_by_id_iq.sel_url = true;
rm_by_id_iq.sel_file = true;
rm_by_id_iq.sel_user_id = true;
rm_by_id_iq.sel_group_id = true;
rm_by_id_iq.sel_privileges = true;
rm_by_id_iq.sel_meta = true;
rm_by_id_iq.WhereId(item_id);
if( db->GetItem(rm_by_id_item, rm_by_id_iq) == WINIX_ERR_OK )
{
if( rm_by_id_item.type == Item::dir )
RemoveDir(rm_by_id_item);
RemoveDirTree(rm_by_id_item, true, check_access);
else
RemoveFileOrSymlink(rm_by_id_item);
RemoveFileOrSymlink(rm_by_id_item, check_access);
}
}
void Rm::RemoveDirTree(long dir_id)
bool Rm::RemoveDirFiles(long dir_id, bool check_access)
{
DirContainer::ParentIterator pnext, p = system->dirs.FindFirstChild(dir_id);
for( ; p != system->dirs.ParentEnd() ; p = pnext )
{
plugin.Call(WINIX_DIR_PREPARE_TO_REMOVE, &(*p->second));
// 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);
}
content_dir_iq.WhereParentId(dir_id);
db->GetItems(content_item_tab, content_dir_iq);
for(size_t i=0 ; i<content_item_tab.size() ; ++i)
RemoveFileOrSymlink(content_item_tab[i]);
size_t removed = 0;
if( db->DelDirById(dir_id) == WINIX_ERR_OK )
for(size_t i=0 ; i<content_item_tab.size() ; ++i)
if( RemoveFileOrSymlink(content_item_tab[i], check_access) )
removed += 1;
return removed == content_item_tab.size();
}
/*
parent_dir can be null (when current_dir is the root directory)
*/
void Rm::RemoveCurrentDir(Item * parent_dir, Item * current_dir, bool check_access)
{
if( check_access )
{
if( !parent_dir || !system->CanRemoveRenameChild(*parent_dir, current_dir->user_id) )
{
log << log1 << "Rm: permission denied to directory: " << current_dir->url << logend;
slog << logerror << T("rm_permission_denied_to") << ": " << current_dir->url << logend;
return;
}
}
plugin.Call(WINIX_DIR_PREPARE_TO_REMOVE, current_dir);
if( db->DelDirById(current_dir->id) == WINIX_ERR_OK )
{
long dir_id = current_dir->id;
old_url = current_dir->url;
system->dirs.DelDir(dir_id);
// don't use current_dir pointer anymore
log << log2 << "Rm: directory removed: " << old_url << logend;
plugin.Call(WINIX_DIR_REMOVED, dir_id);
}
}
void Rm::RemoveDir(const Item & dir)
{
plugin.Call(WINIX_DIR_PREPARE_TO_REMOVE, const_cast<Item*>(&dir));
old_url = dir.url;
RemoveDirTree(dir.id);
// warning: 'dir' has been deleted so don't use the 'dir' reference
if( cur->request->status == WINIX_ERR_OK )
log << log3 << "Rm: removed directory " << old_url << logend;
}
void Rm::RemoveFile()
{
RemoveFileOrSymlink(cur->request->item);
}
void Rm::RemoveDirContent(const Item & dir)
{
content_dir_iq2.WhereParentId(dir.id);
db->GetItems(content_item_tab2, content_dir_iq2);
for(size_t i=0 ; i<content_item_tab2.size() ; ++i)
else
{
if( content_item_tab2[i].type == Item::dir )
RemoveDir(content_item_tab2[i]);
else
RemoveFileOrSymlink(content_item_tab2[i]);
log << log1 << "Rm: I cannot remove a directory: " << current_dir->url << " (database error)" << logend;
}
}
/*
parent_dir can be null (when current_dir is pointing to the root directory)
current_dir is pointing to the directory which should be deleted
(contents of this directory is removed but the directory is deleted only if remove_this_dir is true)
*/
void Rm::RemoveDirTree(Item * parent_dir, Item * current_dir, bool remove_this_dir, bool check_access)
{
if( check_access && !system->HasReadExecAccess(*current_dir) )
{
log << log1 << "Rm: permission denied to directory: " << current_dir->url << logend;
slog << logerror << T("rm_permission_denied_to") << ": " << current_dir->url << logend;
return;
}
DirContainer::ParentIterator pnext, p = system->dirs.FindFirstChild(current_dir->id);
for( ; p != system->dirs.ParentEnd() ; p = pnext )
{
Item * child_dir = &(*p->second);
// this iterator p will be invalidated by the below RemoveDirTree() call
// (the next iterator we must calculate beforehand)
pnext = system->dirs.NextChild(p);
RemoveDirTree(current_dir, child_dir, true, check_access);
}
bool all_file_removed = RemoveDirFiles(current_dir->id, check_access);
if( remove_this_dir )
{
if( all_file_removed )
{
RemoveCurrentDir(parent_dir, current_dir, check_access);
// don't use current_dir pointer anymore
}
else
{
log << log1 << "Rm: " << current_dir->url << " directory not empty" << logend;
slog << logerror << current_dir->url << T("rm_directory_not_empty") << logend;
}
}
}
void Rm::RemoveDirTree(Item & dir, bool remove_this_dir, bool check_access)
{
Item * parent = system->dirs.GetDir(dir.parent_id);
RemoveDirTree(parent, &dir, remove_this_dir, check_access);
}
void Rm::RemoveDirContent()
{
if( !cur->request->IsParam(L"r") )
{
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
log << log3 << "Rm: directory content can be removed only with 'r' parameter" << logend;
slog << logerror << T("rm_content_use_r_option") << logend;
return;
}
RemoveDirContent(*cur->request->dir_tab.back());
RemoveDirTree(*cur->request->dir_tab.back(), false, true);
}
void Rm::RemoveDir()
{
if( !cur->request->IsParam(L"r") || cur->request->dir_tab.size() <= 1 )
if( !cur->request->IsParam(L"r") )
{
// we cannot remove the root directory (dir_tab.size()==1)
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
log << log3 << "Rm: a directory can be removed only with 'r' parameter" << logend;
slog << logerror << T("rm_use_r_option") << logend;
return;
}
RemoveDir(*cur->request->dir_tab.back());
if( cur->request->dir_tab.size() <= 1 )
{
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
log << log1 << "Rm: the root directory cannot be removed" << logend;
slog << logerror << T("rm_cannot_remove_root_dir") << logend;
return;
}
RemoveDirTree(*cur->request->dir_tab.back(), true, true);
cur->request->dir_tab.erase(--cur->request->dir_tab.end());
}
@@ -276,7 +388,6 @@ void Rm::RemoveDir()
void Rm::Clear()
{
content_item_tab.clear();
content_item_tab2.clear();
}
@@ -288,7 +399,7 @@ void Rm::CreateJSON(bool status)
else
cur->request->page << "false\n";
cur->request->page_generated = true;
cur->request->page_generated = true;
cur->request->use_html_filter = false;
}
@@ -299,11 +410,11 @@ void Rm::MakePost()
if( cur->request->is_item )
{
RemoveFile();
RemoveFileOrSymlink(cur->request->item, true);
}
else
{
if( cur->request->IsPostVar(L"onlycontent") )
if( cur->request->IsParam(L"c") || cur->request->IsPostVar(L"c") )
RemoveDirContent();
else
RemoveDir();

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010, Tomasz Sowa
* Copyright (c) 2010-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -26,12 +26,16 @@ public:
bool HasAccess();
void MakePost();
void RemoveDir(const Item & dir);
void RemoveDirContent(const Item & dir);
void RemoveFileOrSymlink(Item & item);
// removing the whole directory structure
// if remove_this_dir is false then only content of dir is removed
void RemoveDirTree(Item & dir, bool remove_this_dir, bool check_access = true);
// removing either a file or a symlink
bool RemoveFileOrSymlink(Item & item, bool check_access = true);
// removing either a directory or a symlink or a file
void RemoveItemById(long item_id);
// if item_id is a directory then the whole subdirectories are removed too
void RemoveItemById(long item_id, bool check_access = true);
private:
@@ -40,10 +44,6 @@ private:
std::vector<Item> content_item_tab;
std::wstring path;
// for deleting content in a directory (files, symlinks and directories)
DbItemQuery content_dir_iq2;
std::vector<Item> content_item_tab2;
// for logging
std::wstring old_url;
@@ -51,15 +51,18 @@ private:
DbItemQuery rm_by_id_iq;
Item rm_by_id_item;
bool HasAccess(const Item & item);
bool HasAccessToDir(const Item & dir, bool only_content);
void Prepare();
void Clear();
bool RemoveStaticFile(const std::wstring & path);
void RemoveStaticFile(Item & item);
void RemoveDirTree(long dir_id);
bool RemoveFile(Item & item);
bool RemoveDirFiles(long dir_id, bool check_access);
void RemoveCurrentDir(Item * parent_dir, Item * current_dir, bool check_access);
void RemoveDirTree(Item * parent_dir, Item * current_dir, bool remove_this_dir, bool check_access);
void RemoveStaticFile(const std::wstring & path);
void RemoveStaticFile(const Item & item);
void RemoveDirContent();
void RemoveDir();
void RemoveFile();
void CreateJSON(bool status);
};

View File

@@ -224,7 +224,7 @@ void Upload::UploadMulti()
cur->request->item.Clear(); // clearing and setting date
cur->request->item.parent_id = cur->request->dir_tab.back()->id;
cur->request->item.type = Item::file;
cur->request->item.privileges = 0644; // !! tymczasowo
cur->request->item.privileges = system->NewFilePrivileges();
functions->SetUser(cur->request->item);
PostFileTab::iterator i = cur->request->post_file_tab.begin();
@@ -259,7 +259,7 @@ void Upload::UploadSingle()
functions->ReadItem(cur->request->item, Item::file); // ReadItem() changes the url if it is empty
functions->SetUser(cur->request->item);
cur->request->item.privileges = 0644; // !! tymczasowo
cur->request->item.privileges = system->NewFilePrivileges();
PostFile & post_file = cur->request->post_file_tab.begin()->second;