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:
Tomasz Sowa 2012-01-24 23:03:36 +00:00
parent 5aaab89cd8
commit 6e2d00bc5b
34 changed files with 1109 additions and 557 deletions

View File

@ -229,6 +229,7 @@ void Config::AssignValues(bool stdout_is_closed)
pattern_cacher_how_many_delete = Size(L"pattern_cacher_how_many_delete", 30);
content_type_header = Int(L"content_type_header", 0);
umask = Int(L"umask", 0222);
}

View File

@ -453,7 +453,10 @@ public:
// if utf8 is true then "; charset=UTF-8" will also be appended
int content_type_header;
// global umask
// it is used when an user doesn't have your own umask or for guests (not logged users)
// default: 0222
int umask;

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.
*
*/
@ -48,7 +48,7 @@ public:
bool DelById(long id);
ParentIterator ParentBegin();
ParentIterator ParentBegin(); // IMPROVE ME: may it should be renamed to ChildBegin() similarly as FindFirstChild() ?
ParentIterator ParentEnd();
ParentSizeType ParentSize();
bool ParentEmpty();

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.
*
*/
@ -41,7 +41,7 @@ void Dirs::Clear()
bool Dirs::HasReadExecAccessForRoot(const Item & item)
{
// there must be at least one 'x' (for the root)
return (item.privileges & 01111) != 0; // !! in the future there'll be another 'x'
return (item.privileges & 01111) != 0;
}
@ -53,8 +53,8 @@ void Dirs::CheckRootDir()
{
if( !HasReadExecAccessForRoot(*i) )
{
i->privileges = 0755;
log << log1 << "Dirs: there is no access for root (admin) to the root dir, setting 0755 for root dir" << logend;
i->privileges = 07555;
log << log1 << "Dirs: there is no access for a root (admin) to the root dir, setting 07555 for the root directory" << logend;
db->EditPrivById(*i, i->id);
}
@ -62,7 +62,7 @@ void Dirs::CheckRootDir()
}
log << log1 << "Dirs: there is no a root dir in the database (creating one)" << logend;
log << log1 << "Dirs: there is no a root directory in the database (creating one)" << logend;
Item root;
@ -70,7 +70,7 @@ void Dirs::CheckRootDir()
root.parent_id = -1;
root.user_id = -1;
root.group_id = -1;
root.privileges = 0755;
root.privileges = 07555;
// !! upewnic sie ze baza nie zmieni url (gdyby wczesniej juz byl w bazie pusty url)
// !! zrobic jakis wyjatek do wprowadzania roota?
@ -487,7 +487,7 @@ return 0;
// current_dir_tab can be the same container as out_dir_tab
// current_dir_tab can be the same container as out_dir_tab
void Dirs::CopyDirTab(const std::vector<Item*> & in, std::vector<Item*> & out)
{
if( &in != &out )
@ -502,13 +502,13 @@ void Dirs::CopyDirTab(const std::vector<Item*> & in, std::vector<Item*> & out)
size_t Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_to)
bool Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_to, size_t & i)
{
if( dir_tab.empty() )
return 0;
size_t i = 0;
size_t old_i;
i = 0;
if( dir_tab.empty() )
return false;
while( true )
{
@ -516,7 +516,7 @@ size_t Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_
for( ; i<link_to.size() && link_to[i] == '/' ; ++i);
if( i == link_to.size() )
return i; // end of the path
return true; // end of the path
// creating a name
old_i = i;
@ -525,12 +525,26 @@ size_t Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_
for( ; i<link_to.size() && link_to[i] != '/' ; ++i)
analyze_temp += link_to[i];
Item * pdir = GetDir(analyze_temp, dir_tab.back()->id);
if( !pdir )
return old_i; // analyze_temp is not a directory
if( analyze_temp == L".." )
{
if( dir_tab.size() <= 1 )
return false;
dir_tab.push_back(pdir);
dir_tab.pop_back();
}
else
if( analyze_temp != L"." )
{
Item * pdir = GetDir(analyze_temp, dir_tab.back()->id);
if( !pdir )
{
i = old_i;
return true; // analyze_temp is not a directory
}
dir_tab.push_back(pdir);
}
}
}
@ -541,7 +555,10 @@ size_t Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_
int Dirs::FollowLink(std::vector<Item*> & dir_tab, const std::wstring & link_to, std::wstring & out_item)
{
size_t i = AnalyzeDir(dir_tab, link_to);
size_t i;
if( !AnalyzeDir(dir_tab, link_to, i) )
return 2; // incorrect link_to
if( i < link_to.size() )
{
@ -574,7 +591,7 @@ return 0;
4 - current_dir_tab was empty
current_dir_tab can be the same container as out_dir_tab
link_to can be a relative path (without the first slash)
link_to can be a relative path (without the first slash) and can contain ".." or "."
*/
int Dirs::FollowLink(const std::vector<Item*> & current_dir_tab, const std::wstring & link_to,
std::vector<Item*> & out_dir_tab, std::wstring & out_item)
@ -693,9 +710,9 @@ Item * Dirs::CreateVarDir()
if( root )
{
v.parent_id = root->id;
v.user_id = -1;
v.group_id = -1;
v.privileges = 0755;
v.user_id = root->user_id;
v.group_id = root->group_id;
v.privileges = root->privileges;
v.subject = L"var";
v.url = L"var";
v.type = Item::dir;

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.
*
*/
@ -47,6 +47,7 @@ public:
bool DelDir(long dir_id);
// if returns true then out_dir_tab is not empty
bool CreateDirTab(long dir_id, std::vector<Item*> & out_dir_tab);
void LogDir(const std::vector<Item*> & dir_tab);
@ -98,7 +99,7 @@ private:
std::wstring temp_link_to;
size_t AnalyzeDir(Item * pdir, const std::wstring & path, long & dir_id, std::wstring & dir);
size_t AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_to);
bool AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_to, size_t & i);
std::wstring analyze_temp;
std::wstring get_dir_temp;

View File

@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2009-2011, Tomasz Sowa
* Copyright (c) 2009-2012, Tomasz Sowa
* All rights reserved.
*
*/
@ -53,9 +53,6 @@ void Mounts::CreateMountPar()
mount_par_image_size = AddMountPar(L"image_size");
mount_par_image_mode = AddMountPar(L"image_mode");
mount_par_image_quality = AddMountPar(L"image_quality");
//mount_par_thread = AddMountPar(L"thread");
//mount_par_createthread_on = AddMountPar(L"createthread_on");
mount_par_only_root_remove = AddMountPar(L"only_root_remove");
mount_par_emacs_on = AddMountPar(L"emacs_on");
mount_par_mkdir_on = AddMountPar(L"mkdir_on");
mount_par_app = AddMountPar(L"app");

View File

@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2009-2011, Tomasz Sowa
* Copyright (c) 2009-2012, Tomasz Sowa
* All rights reserved.
*
*/
@ -73,9 +73,6 @@ public:
int MountParImageSize() { return mount_par_image_size; }
int MountParImageMode() { return mount_par_image_mode; }
int MountParImageQuality() { return mount_par_image_quality; }
//int MountParThread() { return mount_par_thread; }
//int MountParCreatethreadOn() { return mount_par_createthread_on; }
int MountParOnlyRootRemove() { return mount_par_only_root_remove; }
int MountParEmacsOn() { return mount_par_emacs_on; }
int MountParMkdirOn() { return mount_par_mkdir_on; }
int MountParApp() { return mount_par_app; }
@ -148,9 +145,6 @@ private:
int mount_par_image_size;
int mount_par_image_mode;
int mount_par_image_quality;
//int mount_par_thread;
//int mount_par_createthread_on;
int mount_par_only_root_remove;
int mount_par_emacs_on;
int mount_par_mkdir_on;
int mount_par_app;

View File

@ -29,121 +29,137 @@
// winix function and parameters have been parsed
// the request.status is OK
// (the winix function was not called yet)
#define WINIX_PREPARE_REQUEST 2000
#define WINIX_PREPARE_REQUEST 20000
// post and get functions have done their jobs
// now you can act
// this is called only if the request.status is OK
#define WINIX_PROCESS_REQUEST 2001
#define WINIX_PROCESS_REQUEST 20010
// prepere your content for displaying
// this is called after WINIX_PROCESS_REQUEST
// and when there is not a redirect
// request.status is not checked here
#define WINIX_CONTENT_MAKE 2002
#define WINIX_CONTENT_MAKE 20020
// here you can attach your own session data (based on PluginDataBase class)
// call cur->session->plugin_data.Assign(pointer)
#define WINIX_SESSION_CREATED 3000
#define WINIX_SESSION_CREATED 30000
// here you should remove your session data
// this message can be sent even if you don't assing your plugin data
#define WINIX_SESSION_REMOVE 3001
#define WINIX_SESSION_REMOVE 30010
// when a session is changed (you can save a pointer to your data here)
#define WINIX_SESSION_CHANGED 3002
#define WINIX_SESSION_CHANGED 30020
// the winix is closing
// the is not any session available (cur->session is null)
#define WINIX_CLOSE 3004
#define WINIX_CLOSE 30040
// preparing to remove a file (rm function)
// in p1 you have a pointer to the Item struct (file)
// valid members are:
// id, parent_id, type, url, file_path, file_fs, file_type, has_thumb, hash, hash_type, file_size
// user_id, group_id, privileges
// (sometimes rest members can be valid as well -- when you call directly fun_rm->RemoveFileOrSymlink() method)
#define WINIX_FILE_PREPARE_TO_REMOVE 30045
// a file or symlink was removed (rm function)
// in p1 you have a pointer to the Item struct (old file)
#define WINIX_FILE_REMOVED 3005
// directory was removed (rm function)
// PluginInfo::l1 is the dir id
#define WINIX_DIR_REMOVED 3006
// valid members are the same as in WINIX_FILE_PREPARE_TO_REMOVE
#define WINIX_FILE_REMOVED 30050
// preparing to remove a directory (rm function)
// in p1 you have a pointer to the Item struct (directory)
#define WINIX_DIR_PREPARE_TO_REMOVE 3007
// this message is sent after checking the directory permissions
// so consequently if there is no any database error then the
// directory will be removed
// and after removed WINIX_DIR_REMOVED message is sent
#define WINIX_DIR_PREPARE_TO_REMOVE 30070
// directory was removed (rm function)
// PluginInfo::l1 is the directory id
#define WINIX_DIR_REMOVED 30060
// winix is initialized,
// now you can initialize your plugin
#define WINIX_PLUGIN_INIT 3008
#define WINIX_PLUGIN_INIT 30080
// here you can add your own mount point, file systems, mount parameters
// for adding a new mount type call: system->mounts.AddMountType("new_mount_name")
#define WINIX_ADD_MOUNTS 3009
#define WINIX_ADD_MOUNTS 30090
// add plugin functions (winix functions) here
// call info.functions->Add() to add a function
#define WINIX_CREATE_FUNCTIONS 3010
#define WINIX_CREATE_FUNCTIONS 30100
// choose a default function
// if you do not select it then it will be choosen by winix
#define WINIX_SELECT_DEFAULT_FUNCTION 3011
#define WINIX_SELECT_DEFAULT_FUNCTION 30110
// /etc/fstab has been changed
// now we have new mount points
#define WINIX_FSTAB_CHANGED 3012
#define WINIX_FSTAB_CHANGED 30120
// here you add your own template to notification system
// call system->notify.AddTemplate() method
// with a template file name
#define WINIX_NOTIFY_ADD_TEMPLATE 3013
#define WINIX_NOTIFY_ADD_TEMPLATE 30130
// the request is being ended
// you can clear some of your objects here
#define WINIX_END_REQUEST 3014
#define WINIX_END_REQUEST 30140
// a new file (page) has been added
// in p1 you have a pointer to the Item struct
#define WINIX_FILE_ADDED 3015
#define WINIX_FILE_ADDED 30150
// a file (page) has been changed (edited)
// in p1 you have a pointer to the Item struct
#define WINIX_FILE_CHANGED 3016
#define WINIX_FILE_CHANGED 30160
// a file (page) has been copied
// in p1 you have a pointer to the Item struct
// not every fields of Item struct are filled
#define WINIX_FILE_COPIED 3017
#define WINIX_FILE_COPIED 30170
// a file will be moved
// in p1 you have a pointer to the Item struct
// not every fields of Item struct are filled
#define WINIX_FILE_PREPARE_TO_MOVE 3018
// valid members are:
// id, parent_id, type, url, file_path, file_fs, file_type, has_thumb, hash, hash_type, file_size
// user_id, group_id, privileges, meta
// (sometimes rest members can be valid as well -- when you call directly fun_rm->RemoveFileOrSymlink() method)
#define WINIX_FILE_PREPARE_TO_MOVE 30180
// a file has been moved
// in p1 you have a pointer to the Item struct (new file)
// not every fields of Item struct are filled
#define WINIX_FILE_MOVED 3019
// valid members are the same as in WINIX_FILE_PREPARE_TO_MOVE
#define WINIX_FILE_MOVED 30190
// a thumbnail was created
// this message is called from another thread
// the thread is called Lock() before sending this message
// in p1 you have a pointer to the Item struct
#define WINIX_CREATED_THUMB 3050
#define WINIX_CREATED_THUMB 30500
// an image has been resized
// this message is called from another thread
// the thread is called Lock() before sending this message
// in p1 you have a pointer to the Item struct
#define WINIX_IMAGE_RESIZED 3052
#define WINIX_IMAGE_RESIZED 30520
// content of a directory was sorted
// (winix 'sort' function was used)
// in p1 you have a pointer to the Item struct (of the directory)
// this is from system->dirs so you should not change the item
#define WINIX_DIR_CONTENT_SORTED 3050
#define WINIX_DIR_CONTENT_SORTED 30500
// a user has been logged
// send from 'login' winix function
// this message is also called when winix starts and reads sessions
// from the session file
#define WINIX_USER_LOGGED 3060
#define WINIX_USER_LOGGED 30600
// here you add your own html templates
@ -154,7 +170,7 @@
// the message will be sent too whenever 'reload/templates' winix function is called
// templates you should add only in this message
// in other cases after 'reload' function the indexes would be wrong
#define WINIX_ADD_TEMPLATE 3100
#define WINIX_ADD_TEMPLATE 31000

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.
*
*/
@ -260,12 +260,12 @@ bool System::CanChangeUser(const Item & item, long new_user_id)
// super user is allowed everything
return true;
// !! przeciez to prosciej mozna zapisac
// albo dac od razu return false
if( item.user_id != new_user_id )
if( item.user_id == -1 || new_user_id == -1 || item.user_id != new_user_id )
// only super user can change the owner of an item
return false;
// item.user_id is equal new_user_id -- we return true
return true;
}
@ -285,10 +285,10 @@ bool System::CanChangeGroup(const Item & item, long new_group_id)
// user is allowed to change the group only if he is an owner of the item
// he can change only into a group in which he is a member of, or into a 'no_group'
if( !cur->session->puser )
if( !cur->session->puser || cur->session->puser->id == -1 )
return false;
if( cur->session->puser->id != item.user_id )
if( item.user_id == -1 || cur->session->puser->id != item.user_id )
return false;
if( new_group_id == -1 )
@ -316,12 +316,12 @@ bool System::CanChangePrivileges(const Item & item, int new_priv)
if( item.privileges != new_priv )
{
// the owner of an item is allowed to change the privileges
if( !cur->session->puser )
// the owner of an item is allowed to change the privileges
if( !cur->session->puser || cur->session->puser->id == -1 )
return false;
if( cur->session->puser->id != item.user_id )
if( item.user_id == -1 || cur->session->puser->id != item.user_id )
return false;
}
@ -329,7 +329,7 @@ return true;
}
// private
bool System::HasAccess(const Item & item, int mask)
{
if( !cur->session )
@ -340,20 +340,26 @@ bool System::HasAccess(const Item & item, int mask)
// super user is allowed everything
return true;
if( cur->session->puser && cur->session->puser->id == item.user_id )
if( cur->session->puser && item.user_id != -1 && cur->session->puser->id == item.user_id )
{
// the owner
return ((item.privileges >> 9) & mask) == mask;
}
if( cur->session->puser && item.group_id != -1 && cur->session->puser->IsMemberOf(item.group_id) )
{
// group
return ((item.privileges >> 6) & mask) == mask;
}
if( cur->session->puser && cur->session->puser->IsMemberOf(item.group_id) )
if( cur->session->puser )
{
// group
// others -- others logged people
return ((item.privileges >> 3) & mask) == mask;
}
// others
// guests -- not logged people
return (item.privileges & mask) == mask;
}
@ -381,8 +387,8 @@ bool System::HasReadExecAccess(const Item & item)
if( cur->session && cur->session->puser && cur->session->puser->super_user )
{
// there must be at least one 'x' (for the root)
return (item.privileges & 0111) != 0;
// !! CHECK ME: is it applicable to directories too?
return (item.privileges & 01111) != 0;
}
return HasAccess(item, 5); // r+x
@ -468,6 +474,76 @@ size_t i = 0;
}
int System::NewPrivileges(int creation_mask)
{
if( cur && cur->session && cur->session->puser )
{
int umask = cur->session->puser->env.Int(L"umask", config->umask);
return (~umask) & creation_mask;
}
else
{
return (~config->umask) & creation_mask;
}
}
/*
from man sticky:
A directory whose `sticky bit' is set becomes an append-only directory,
or, more accurately, a directory in which the deletion of files is
restricted. A file in a sticky directory may only be removed or renamed
by a user if the user has write permission for the directory and the user
is the owner of the file, the owner of the directory, or the super-user.
This feature is usefully applied to directories such as /tmp which must
be publicly writable but should deny users the license to arbitrarily
delete or rename each others' files.
*/
bool System::CanRemoveRenameChild(const Item & dir, long child_item_user_id)
{
if( dir.type != Item::dir )
return false;
if( !HasWriteAccess(dir) )
return false;
if( (dir.privileges & 010000) == 0 )
// there is no a sticky bit set to this directory
return true;
if( cur->session->puser )
{
if( cur->session->puser->super_user )
return true;
if( dir.user_id != -1 && cur->session->puser->id != -1 && child_item_user_id != -1 )
{
if( cur->session->puser->id == child_item_user_id ||
cur->session->puser->id == dir.user_id )
return true;
}
}
return false;
}
int System::NewFilePrivileges()
{
return NewPrivileges(06666);
}
int System::NewDirPrivileges()
{
return NewPrivileges(07777);
}
bool System::CanUseHtml(long user_id)
{
return IsMemberOfGroup(user_id, L"allow_html");
@ -1068,9 +1144,9 @@ bool System::AddCommonFileToVar(const wchar_t * file_path, const wchar_t * url,
file_content_item.Clear();
file_content_item.parent_id = var->id;
file_content_item.user_id = -1;
file_content_item.group_id = -1;
file_content_item.privileges = 0755;
file_content_item.user_id = var->user_id;
file_content_item.group_id = var->group_id;
file_content_item.privileges = 07555; // !! IMPROVE ME: may it should be added as a parameter to this function?
file_content_item.subject = url;
file_content_item.url = url;
file_content_item.type = Item::file;

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.
*
*/
@ -88,7 +88,8 @@ public:
bool CanChangeUser(const Item & item, long new_user_id);
bool CanChangeGroup(const Item & item, long new_group_id);
bool CanChangePrivileges(const Item & item, int new_priv);
bool HasAccess(const Item & item, int mask);
bool HasReadAccess(const Item & item);
bool HasWriteAccess(const Item & item);
bool HasReadWriteAccess(const Item & item);
@ -99,6 +100,16 @@ public:
void CheckAccessToItems(std::vector<Item> & item_tab);
void CheckWriteAccessToItems(std::vector<Item> & item_tab);
/*
this method checks the sticky bit and write permissions
it returns true if we can remove/rename an item for the given child_item_user_id user id
*/
bool CanRemoveRenameChild(const Item & dir, long child_item_user_id);
int NewFilePrivileges();
int NewDirPrivileges();
bool CanUseHtml(long user_id);
bool CanUseBBCode(long user_id);
bool CanUseRaw(long user_id);
@ -156,6 +167,9 @@ private:
std::vector<Item*> root_follow_dir_tab;
Item temp_follow_item;
bool HasAccess(const Item & item, int mask);
int NewPrivileges(int creation_mask);
bool CreateNewFileSimpleFs(Item & item);
bool CreateNewFileHashFs(Item & item);

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;

View File

@ -7,16 +7,16 @@
<legend>{mv_form_legend}</legend>
<p>
[if-one item_is]{mv_page} "[item_url]":[else]{mv_dir} "[dir_without_slash]"[end]
[if-one item_is]{mv_page} [item_url]:[else]{mv_dir} [dir][end]
</p>
<p class="withnext">{suggested_url}</p>
<input class="edit" type="text" name="to" value="[dir_without_slash][if-one item_is]/[item_url][end]">
<input class="edit" type="text" name="dst_path" value="[dir_without_slash][if-one item_is]/[item_url][end]">
[if-no item_is]
<label><input type="checkbox" name="onlycontent">{mv_only_content}</label>
<label><input type="checkbox" name="c"[if winix_function_param_is "c"]checked="checked"[end]>{mv_only_content}</label>
[end]
<input class="submit" type="submit" value="{move}">

View File

@ -1,5 +1,4 @@
<h1>{rm_header}</h1>
[include "error.html"]
<form id="additem" method="post" action="[doc_base_url][dir][if-one item_is][item_url]/[end]rm[if-no item_is]/r[end]">
<fieldset>
@ -28,7 +27,7 @@
[if-no item_is]
<p>
<label><input type="checkbox" name="onlycontent">{rm_only_content}</label>
<label><input type="checkbox" name="c" [if winix_function_param_is "c"]checked="checked"[end]>{rm_only_content}</label>
</p>
[end]

View File

@ -25,7 +25,7 @@ by = by
error_404 = Error 404
error_404_msg = We are sory but there is no such a page in our service.
internal_error = Internal error, check system log for more details
was_errors = We are sory but there were some problems with the operation.
@ -182,6 +182,14 @@ rm_dir = Do you really want to remove directory
rm_only_content = Remove only the content of the directory
rm_root = You cannot remove the root directory, you are only allowed to delete the content of the directory
rm_submit = Remove
rm_cannot_create_static_path = I cannot create a path to a static file
rm_cannot_remove_static_file = I cannot remove a static file
rm_permission_denied_to = Permission denied to remove
rm_directory_not_empty = directory not empty
rm_use_r_option = This is a directory, use 'r' parameter to remove it
rm_cannot_remove_root_dir = You cannot remove the root directory
rm_content_use_r_option = Content of a directory can be removed only with 'r' parameter
thread_create_new = Create a new thread
thread_tab_title = Thread title
@ -306,6 +314,14 @@ mv_form_legend = Move form
mv_page = Move page
mv_dir = Move directory
mv_only_content = Move only content of the directory
mv_cant_move_root_dir = the root directory cannot be moved anywhere
mv_permission_denied_to = Permission denied to
mv_incorrect_path = Incorrent path
mv_dir_can_be_moved_to_dir = A directory can be moved only to an other directory
mv_dir_content_can_be_moved_to_dir = Directory content can be moved only to an other directory
mv_cannot_move_to_inside = A directory cannot be moved to inside it
mv_incorrect_dst_path = Incorrect destination path
mv_incorrect_dir = Incorrect directory
cp_header = Copy

View File

@ -26,6 +26,8 @@ error_404 = Błąd 404
error_404_msg = Przykro nam ale podanej strony nie ma w naszym serwisie.
internal_error = Błąd wewnętrzny, po więcej szczegółów sprawdź dziennik systemowy
was_errors = Przepraszamy ale wystąpiły problemy z wykonaniem tej operacji.
error_code = Kod błędu
@ -201,6 +203,15 @@ rm_dir = Czy napewno usunąć katalog
rm_only_content = Usuń jedynie zawartość katalogu
rm_root = Nie możesz skasować katalogu głównego, możesz jedynie usunąć jego zawartość
rm_submit = Usuń
rm_cannot_create_static_path = Nie mogę utworzyć ścieżki do pliku statycznego
rm_cannot_remove_static_file = Nie mogę usunąć pliku statycznego
rm_permission_denied_to = Brak dostępu do usunięcia
rm_directory_not_empty = katalog nie jest pusty
rm_use_r_option = To jest katalog, aby go usunąć musisz użyć parametru 'r'
rm_cannot_remove_root_dir = Nie możesz usunąć głównego katalogu
rm_content_use_r_option = Zawartość katalogu może zostać usunięta tylko z użyciem parametru 'r'
thread_create_new = Załóż nowy wątek
thread_tab_title = Tytuł wątku
@ -323,6 +334,14 @@ mv_form_legend = Formularz zmiany
mv_page = Przenieś stronę
mv_dir = Przenieś katalog
mv_only_content = Przenieś tylko zawartość katalogu
mv_cant_move_root_dir = Katalog główny nie może być przeniesiony
mv_permission_denied_to = Brak dostępu do
mv_incorrect_path = Nieprawidłowa ścieżka
mv_dir_can_be_moved_to_dir = Katalog może zostać przeniesiony tylko do innego katalogu
mv_dir_content_can_be_moved_to_dir = Zawartość katalogu może zostać przeniesiona tylko do innego katalogu
mv_cannot_move_to_inside = Nie mogę przenieść katalogu do jego środka
mv_incorrect_dst_path = Nieprawidłowa ścieżka docelowa
mv_incorrect_dir = Nieprawidłowy katalog
cp_header = Kopiuj

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.
*
*/
@ -72,7 +72,7 @@ void CreateThread::MakePost()
functions->SetUser(cur->request->item);
functions->PrepareUrl(cur->request->item);
cur->request->item.parent_id = cur->request->dir_tab.back()->id;
cur->request->item.privileges = 0644; // !! tymczasowo
cur->request->item.privileges = system->NewFilePrivileges();
if( functions->CheckAbuse() )
return;

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.
*
*/
@ -92,7 +92,7 @@ void Reply::MakePost()
functions->SetUser(answer);
functions->PrepareUrl(answer);
answer.parent_id = files_dir->id;
answer.privileges = 0644; // !! tymczasowo
answer.privileges = system->NewFilePrivileges();
if( functions->CheckAbuse() )
return;

View File

@ -80,7 +80,7 @@ void CreateTicket::Submit(Ticket & ticket, Item & item)
return;
functions->SetUser(item);
item.privileges = 0644; // !! tymczasowo
item.privileges = system->NewFilePrivileges();
item.parent_id = cur->request->dir_tab.back()->id;
// adding without notificating

View File

@ -61,7 +61,7 @@ void SessionData::RemoveAllFiles(PT::Space & new_space)
BuildFileList(new_file_tab, new_space);
for(size_t i=0 ; i<new_file_tab.size() ; ++i)
fun_rm->RemoveItemById(new_file_tab[i]);
fun_rm->RemoveItemById(new_file_tab[i], false);
}
@ -86,7 +86,7 @@ void SessionData::RemoveAllStaleFiles(PT::Space & new_space, PT::Space & old_spa
{
if( new_file_tab[n] < old_file_tab[o] )
{
fun_rm->RemoveItemById(new_file_tab[n]);
fun_rm->RemoveItemById(new_file_tab[n], false);
n += 1;
}
else
@ -103,7 +103,7 @@ void SessionData::RemoveAllStaleFiles(PT::Space & new_space, PT::Space & old_spa
while( n < new_file_tab.size() )
{
fun_rm->RemoveItemById(new_file_tab[n]);
fun_rm->RemoveItemById(new_file_tab[n], false);
n += 1;
}
}

View File

@ -132,16 +132,12 @@ bool TicketInfo::ParseTicketConf(long mount_dir_id, const std::wstring & path)
{
log << log3 << "Ticket: parsing conf file: " << path << logend;
log << log1 << config_file.content << logend;
conf_tab[mount_dir_id].file_name = path;
conf_parser.UTF8(true);
conf_parser.SetSpace(conf_tab[mount_dir_id].conf);
conf_parser.SplitSingle(true);
conf_tab[mount_dir_id].conf.Clear();
//log << log1 << "status: " << conf_parser.Parse(config_file.content) << logend;
return (conf_parser.ParseString(config_file.content) == PT::ConfParser::ok);
}
@ -343,7 +339,7 @@ void TicketInfo::ReadTicketValue(PT::Space & space,
file.Clear(); // clearing and setting date
file.parent_id = upload_dir.id;
file.type = Item::file;
file.privileges = 0644; // !! tymczasowo
file.privileges = system->NewFilePrivileges();
file.file_type = SelectFileType(value.filename);
file.url = value.filename;
functions->PrepareUrl(file);

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.
*
*/
@ -253,15 +253,13 @@ void priv_privileges(Info & i)
void priv_privileges_for_files(Info & i)
{
//!! bedzie uzyte umask
i.out << Toa((int)0644, 8);
i.out << Toa(system->NewFilePrivileges(), 8);
}
void priv_privileges_for_dirs(Info & i)
{
//!! bedzie uzyte umask
i.out << Toa((int)0755, 8);
i.out << Toa(system->NewDirPrivileges(), 8);
}