2010-08-10 18:12:50 +02:00
|
|
|
/*
|
|
|
|
* This file is a part of Winix
|
|
|
|
* and is not publicly distributed
|
|
|
|
*
|
2014-02-12 17:30:49 +01:00
|
|
|
* Copyright (c) 2008-2014, Tomasz Sowa
|
2010-08-10 18:12:50 +02:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "cp.h"
|
|
|
|
#include "core/misc.h"
|
2010-08-12 21:10:12 +02:00
|
|
|
#include "functions.h"
|
2011-09-13 08:08:34 +02:00
|
|
|
#include "core/plugin.h"
|
|
|
|
|
2010-08-10 18:12:50 +02:00
|
|
|
|
|
|
|
|
2014-02-12 17:30:49 +01:00
|
|
|
namespace Winix
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-08-10 18:12:50 +02:00
|
|
|
namespace Fun
|
|
|
|
{
|
|
|
|
|
|
|
|
Cp::Cp()
|
|
|
|
{
|
2010-11-21 01:19:17 +01:00
|
|
|
fun.url = L"cp";
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
bool Cp::HasAccess()
|
|
|
|
{
|
|
|
|
return CheckAccessFrom();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Cp::CheckAccessFrom()
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->is_item )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
if( !system->HasReadAccess(cur->request->item) || cur->request->item.type == Item::symlink )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
2010-08-10 18:12:50 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2011-01-23 15:15:30 +01:00
|
|
|
if( !cur->request->IsParam(L"r") )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
|
|
|
// directories need 'r' parameter
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
bool Cp::CheckAccessTo()
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
if( dir_tab.empty() ||
|
|
|
|
!system->HasReadExecAccessToPath(dir_tab) ||
|
|
|
|
!system->HasWriteAccess(*dir_tab.back()) )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
2010-08-10 18:12:50 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
bool Cp::ParseDir()
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
const std::wstring & new_dir = cur->request->PostVar(L"to");
|
|
|
|
int res = system->dirs.FollowLink(cur->request->dir_tab, new_dir, dir_tab, file);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( res == 3 )
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_NO_ROOT_DIR;
|
2010-08-10 18:12:50 +02:00
|
|
|
else
|
2011-01-05 22:24:11 +01:00
|
|
|
if( res != 0 && res != 1 )
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_INCORRECT_DIR;
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
return res == 0 || res == 1;
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
bool Cp::CopyStaticFile(const std::wstring & from, const std::wstring & to)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
if( from == to )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
log << log3 << "Cp: the same path to a static file: " << to << logend;
|
|
|
|
return true;
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
2014-02-12 17:30:49 +01:00
|
|
|
if( Winix::CopyFile(from, to) )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
log << log2 << "Cp: copied a static file from: " << from << ", to: " << to << logend;
|
|
|
|
return true;
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
log << log1 << "Cp: can't copy a file from: " << from << ", to: " << to << logend;
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
2011-01-05 22:24:11 +01:00
|
|
|
return false;
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
|
|
|
|
void Cp::CopyStaticFile(Item & item)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
bool res1, res2, res3, res4, res5;
|
|
|
|
|
|
|
|
res1 = system->MakeFilePath(item, old_path, false);
|
|
|
|
res2 = !item.has_thumb || system->MakeFilePath(item, old_path_thumb, 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);
|
|
|
|
|
|
|
|
if( !res1 || !res2 || !res3 || !res4 || !res5 )
|
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_PERMISSION_DENIED;
|
2011-01-05 22:24:11 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( CopyStaticFile(old_path, new_path) )
|
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = db->EditFileById(item, item.id);
|
2011-01-05 22:24:11 +01:00
|
|
|
|
|
|
|
if( item.has_thumb )
|
|
|
|
CopyStaticFile(old_path_thumb, new_path_thumb);
|
|
|
|
}
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
|
|
|
|
void Cp::SetNewAttributes(Item & item)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
item.user_id = new_user;
|
|
|
|
item.group_id = new_group;
|
|
|
|
item.SetDateModifyToNow();
|
|
|
|
}
|
2010-08-10 18:12:50 +02:00
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
void Cp::CopyFile(Item & item, long dst_dir_id)
|
|
|
|
{
|
|
|
|
if( !preserve_attr )
|
|
|
|
SetNewAttributes(item);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-09-13 08:08:34 +02:00
|
|
|
item.parent_id = dst_dir_id;
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = db->AddItem(item);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->status == WINIX_ERR_OK )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2010-12-10 22:07:01 +01:00
|
|
|
if( item.file_type != WINIX_ITEM_FILETYPE_NONE )
|
2011-01-05 22:24:11 +01:00
|
|
|
CopyStaticFile(item);
|
2011-09-13 08:08:34 +02:00
|
|
|
|
|
|
|
plugin.Call(WINIX_FILE_COPIED, &item);
|
2011-01-05 22:24:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Cp::CopyFileOrSymlink(Item & item, long dst_dir_id)
|
|
|
|
{
|
|
|
|
if( !system->HasReadAccess(item) )
|
|
|
|
return; // !! w przyszlosci bedziemy dodawac komunikaty do specjalnej tablicy (narazie nie zaimplementowane)
|
|
|
|
|
|
|
|
if( item.type == Item::symlink && follow_symlinks )
|
|
|
|
{
|
|
|
|
if( system->dirs.CreateDirTab(item.parent_id, symlink_dir_tab) )
|
|
|
|
{
|
|
|
|
int res = system->FollowAllLinks(symlink_dir_tab, item.link_to, symlink_dir_tab, item);
|
|
|
|
|
|
|
|
if( res == 0 )
|
|
|
|
CopyDirTree(*symlink_dir_tab.back(), dst_dir_id);
|
|
|
|
else
|
|
|
|
if( res == 1 )
|
|
|
|
CopyFile(item, dst_dir_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CopyFile(item, dst_dir_id);
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
void Cp::Prepare()
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
iq.SetAll(true, false);
|
|
|
|
iq.WhereType(Item::dir, false);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
new_user = -1;
|
|
|
|
new_group = dir_tab.back()->group_id;
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->session->puser )
|
|
|
|
new_user = cur->session->puser->id;
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
loop_checker.clear();
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
|
|
|
|
void Cp::CopyFilesInDir(const Item & dir, long dst_dir_id)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
iq.WhereParentId(dir.id);
|
|
|
|
db->GetItems(item_tab, iq);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
for(size_t i=0 ; i<item_tab.size() ; ++i)
|
|
|
|
CopyFileOrSymlink(item_tab[i], dst_dir_id);
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
void Cp::CopyDirContentTree(const Item & dir, long dst_dir_id)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
DirContainer::ParentIterator i = system->dirs.FindFirstChild(dir.id);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
|
|
|
// go through all directories
|
2011-01-05 22:24:11 +01:00
|
|
|
for( ; i != system->dirs.ParentEnd() ; i = system->dirs.NextChild(i) )
|
|
|
|
CopyDirTree(*(i->second), dst_dir_id);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
CopyFilesInDir(dir, dst_dir_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Cp::WasThisDir(const Item & dir)
|
|
|
|
{
|
|
|
|
for(size_t i=0 ; i<loop_checker.size() ; ++i)
|
|
|
|
if( loop_checker[i] == dir.id )
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// we shouldn't change 'item' because we have references to our app.dirs objects
|
2011-01-05 22:24:11 +01:00
|
|
|
long Cp::CopyDirTree(const Item & dir, long dst_dir_id)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
if( WasThisDir(dir) )
|
|
|
|
{
|
|
|
|
log << log1 << "Cp: a loop between directories found (created by a symlink), "
|
|
|
|
<< "dir_id: " << dir.id << ", dir_url: " << dir.url << logend;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
loop_checker.push_back(dir.id);
|
|
|
|
temp = dir;
|
|
|
|
temp.parent_id = dst_dir_id;
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( !file.empty() )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
temp.url = file;
|
|
|
|
functions->PrepareUrl(temp);
|
|
|
|
file.clear();
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( !preserve_attr )
|
|
|
|
SetNewAttributes(temp);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( remove_defaults )
|
|
|
|
{
|
|
|
|
temp.link_to.clear();
|
|
|
|
temp.link_redirect = 0;
|
|
|
|
}
|
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = system->dirs.AddDirectory(temp);
|
2011-01-05 22:24:11 +01:00
|
|
|
loop_checker.push_back(temp.id);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
// remember the new dir_id because temp can be changed
|
|
|
|
// this method is called in recurrences
|
|
|
|
long new_dir_id = temp.id;
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( system->HasReadExecAccess(dir) )
|
|
|
|
CopyDirContentTree(dir, temp.id);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
|
|
|
return new_dir_id; // and return it
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
|
|
|
|
|
2010-08-10 18:12:50 +02:00
|
|
|
bool Cp::IsTheSameFile(const Item & item)
|
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
if( file.empty() )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
if( item.parent_id == dir_tab.back()->id )
|
2010-08-10 18:12:50 +02:00
|
|
|
return true; // nothing to do
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
if( item.parent_id == dir_tab.back()->id && item.url == file )
|
2010-08-10 18:12:50 +02:00
|
|
|
return true; // nothing to do
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// here 'item' can be changed in place
|
2011-01-05 22:24:11 +01:00
|
|
|
void Cp::PostCopyFile(Item & item, bool redirect)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
|
|
|
if( IsTheSameFile(item) )
|
|
|
|
return;
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( !file.empty() )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
item.url = file;
|
2010-08-12 21:10:12 +02:00
|
|
|
functions->PrepareUrl(item);
|
2011-01-05 22:24:11 +01:00
|
|
|
file.clear();
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
CopyFileOrSymlink(item, dir_tab.back()->id);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->status == WINIX_ERR_OK && redirect )
|
2010-08-10 18:12:50 +02:00
|
|
|
system->RedirectTo(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
|
|
|
|
|
|
|
|
void Cp::PostCopyDirContent(const Item & dir, bool redirect)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
if( !file.empty() )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
cur->request->status = WINIX_ERR_INCORRECT_DIR;
|
2010-08-10 18:12:50 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( dir_tab.back()->id == dir.id )
|
2010-08-10 18:12:50 +02:00
|
|
|
return; // nothing to do
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
CopyDirContentTree(dir, dir_tab.back()->id);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->status == WINIX_ERR_OK && redirect )
|
2011-01-05 22:24:11 +01:00
|
|
|
system->RedirectTo(dir_tab.back()->id);
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
void Cp::PostCopyDir(const Item & dir, bool redirect)
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
long dir_id = dir_tab.back()->id;
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
if( file.empty() && dir_id == dir.id )
|
|
|
|
return; // nothing to do
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
long new_dir_id = CopyDirTree(dir, dir_id);
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( new_dir_id != -1 && cur->request->status == WINIX_ERR_OK && redirect )
|
2010-08-10 18:12:50 +02:00
|
|
|
system->RedirectTo(new_dir_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
void Cp::Clear()
|
|
|
|
{
|
|
|
|
loop_checker.clear();
|
|
|
|
dir_tab.clear();
|
|
|
|
item_tab.clear();
|
|
|
|
symlink_dir_tab.clear();
|
|
|
|
}
|
|
|
|
|
2010-08-10 18:12:50 +02:00
|
|
|
|
|
|
|
void Cp::MakePost()
|
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
if( ParseDir() && CheckAccessTo() )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-05 22:24:11 +01:00
|
|
|
Prepare();
|
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
preserve_attr = cur->request->IsPostVar(L"preserveattr");
|
|
|
|
remove_defaults = cur->request->IsPostVar(L"removedefaults");
|
|
|
|
follow_symlinks = cur->request->IsPostVar(L"followsymlinks");
|
2010-08-10 18:12:50 +02:00
|
|
|
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->is_item )
|
2010-08-10 18:12:50 +02:00
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
PostCopyFile(cur->request->item);
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-01-23 15:15:30 +01:00
|
|
|
if( cur->request->IsPostVar(L"onlycontent") )
|
|
|
|
PostCopyDirContent(*cur->request->dir_tab.back());
|
2010-08-10 18:12:50 +02:00
|
|
|
else
|
2011-01-23 15:15:30 +01:00
|
|
|
PostCopyDir(*cur->request->dir_tab.back());
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
2011-01-05 22:24:11 +01:00
|
|
|
Clear();
|
|
|
|
}
|
2010-08-10 18:12:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace
|
2014-02-12 17:30:49 +01:00
|
|
|
|
|
|
|
} // namespace Winix
|
|
|
|
|