/* * This file is a part of Winix * and is not publicly distributed * * Copyright (c) 2008-2010, Tomasz Sowa * All rights reserved. * */ #include #include #include "rm.h" #include "core/plugin.h" #include "core/misc.h" #include "templates/templates.h" namespace Fun { Rm::Rm() { fun.url = L"rm"; follow_symlinks = false; } bool Rm::HasAccess(const Item & item) { // !! temporarily (we're waiting for the sticky bit to be implemented) // not logged users cannot remove anything if( !cur->session->puser ) return false; if( item.parent_id == -1 ) { // we can only remove the content of the root directory // and here we check only access the the root dir // "onlycontent" parameter should be check in post method if( !system->HasWriteAccess(item) ) return false; } else { Item * last_but_one_dir = system->dirs.GetDir(item.parent_id); if( !last_but_one_dir ) // ops, there is no a parent dir return false; if( !system->HasWriteAccess(*last_but_one_dir) ) return false; } if( system->mounts.pmount->IsPar(system->mounts.MountParOnlyRootRemove()) ) if( !cur->session->puser || !cur->session->puser->super_user ) return false; return true; } bool Rm::HasAccess() { bool res; if( !cur->request->is_item ) res = HasAccess(*cur->request->dir_tab.back()); else res = HasAccess(cur->request->item); if( !res && cur->request->IsParam(L"jquery_upload") ) CreateJSON(res); return res; } 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.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) { if( ::RemoveFile(path) ) { log << log2 << "Rm: removed static file: " << path << logend; return true; } else { log << log1 << "Rm: can't remove a file: " << path << logend; cur->request->status = WINIX_ERR_PERMISSION_DENIED; return false; } } void Rm::RemoveStaticFile(Item & item) { if( system->MakeFilePath(item, path, false) ) { if( RemoveStaticFile(path) ) { if( item.has_thumb && system->MakeFilePath(item, path, true) ) { RemoveStaticFile(path); item.has_thumb = false; } // we don't store it to db (it will be removed or is removed already) item.file_path.clear(); item.file_type = WINIX_ITEM_FILETYPE_NONE; } } else { cur->request->status = WINIX_ERR_PERMISSION_DENIED; } } void Rm::RemoveFileOrSymlink(Item & item) { if( db->DelItem(item) == WINIX_ERR_OK ) { if( item.type == Item::file ) log << log2 << "Rm: deleted file "; else log << log2 << "Rm: deleted symlink "; log << item.url << logend; TemplatesFunctions::pattern_cacher.DeletePattern(item); plugin.Call(WINIX_FILE_REMOVED, item.id); if( item.file_type != WINIX_ITEM_FILETYPE_NONE ) RemoveStaticFile(item); } } // for other uses (plugins etc) void Rm::RemoveItemById(long item_id) { // 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.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); else RemoveFileOrSymlink(rm_by_id_item); } } void Rm::RemoveDirTree(long dir_id) { DirContainer::ParentIterator pnext, p = system->dirs.FindFirstChild(dir_id); for( ; p != system->dirs.ParentEnd() ; p = pnext ) { // this iterator p will be deleted by the next DeleteDir(p->second->id) // (the next iterator we must calculate beforehand) pnext = system->dirs.NextChild(p); RemoveDirTree(p->second->id); } plugin.Call(WINIX_DIR_PREPARE_TO_REMOVE, dir_id); content_dir_iq.WhereParentId(dir_id); db->GetItems(content_item_tab, content_dir_iq); for(size_t i=0 ; iDelDirById(dir_id) == WINIX_ERR_OK ) { system->dirs.DelDir(dir_id); plugin.Call(WINIX_DIR_REMOVED, dir_id); } } void Rm::RemoveDir(const Item & dir) { old_url = dir.url; RemoveDirTree(dir.id); 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 ; irequest->IsParam(L"r") ) { cur->request->status = WINIX_ERR_PERMISSION_DENIED; return; } RemoveDirContent(*cur->request->dir_tab.back()); } void Rm::RemoveDir() { if( !cur->request->IsParam(L"r") || cur->request->dir_tab.size() <= 1 ) { // we cannot remove the root directory (dir_tab.size()==1) cur->request->status = WINIX_ERR_PERMISSION_DENIED; return; } RemoveDir(*cur->request->dir_tab.back()); cur->request->dir_tab.erase(--cur->request->dir_tab.end()); } void Rm::Clear() { content_item_tab.clear(); content_item_tab2.clear(); } void Rm::CreateJSON(bool status) { if( status ) cur->request->page << "true\n"; else cur->request->page << "false\n"; cur->request->page_generated = true; cur->request->use_html_filter = false; } void Rm::MakePost() { Prepare(); if( cur->request->is_item ) { RemoveFile(); } else { if( cur->request->IsPostVar(L"onlycontent") ) RemoveDirContent(); else RemoveDir(); } Clear(); if( cur->request->IsParam(L"jquery_upload") ) CreateJSON(true); else if( cur->request->status == WINIX_ERR_OK ) system->RedirectToLastDir(); } } // namespace