/* * 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"; } bool Rm::HasAccess(const Item & item) { // !! temporarily (we're waiting for the sticky bit to be implemented) // not logged users cannot remove anything if( !request->session->puser ) return false; if( item.parent_id == -1 ) { // rm for the root dir // only the superuser can do it if( !request->session->puser || !request->session->puser->super_user ) return false; } else { Item * last_but_one_dir = system->dirs.GetDir(item.parent_id); if( !last_but_one_dir ) // ops, there is no a parent dir return false; if( !system->HasWriteAccess(*last_but_one_dir) ) return false; } if( system->mounts.pmount->IsPar(system->mounts.MountParOnlyRootRemove()) ) if( !request->session->puser || !request->session->puser->super_user ) return false; return true; } bool Rm::HasAccess() { if( !request->is_item ) return HasAccess(*request->dir_tab.back()); else return HasAccess(request->item); return true; } void Rm::RemoveAuthPrepareQuery() { rm_auth_iq.SetAll(true, false); rm_auth_iq.sel_parent_id = true; rm_auth_iq.sel_type = true; rm_auth_iq.sel_auth = true; rm_auth_iq.WhereType(Item::file); rm_auth_iq.WhereAuth(Item::auth_none, false); } void Rm::RemoveAllDirs(long dir_id) { DirContainer::ParentIterator pnext, p = system->dirs.FindFirstParent(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.NextParent(p); RemoveAllDirs(p->second->id); } plugin.Call(WINIX_DIR_PREPARE_TO_REMOVE, dir_id); rm_auth_iq.WhereParentId(dir_id); db->GetItems(request->item_tab, rm_auth_iq); for(size_t i=0 ; iitem_tab.size() ; ++i) RemoveAuth(request->item_tab[i]); if( db->DelDirById(dir_id) == WINIX_ERR_OK ) { system->dirs.DelDir(dir_id); db->RemoveThread(dir_id); // !! tticket // db->RemoveTicket(dir_id); plugin.Call(WINIX_DIR_REMOVED, dir_id); } } void Rm::RemoveAllDirs() { RemoveAuthPrepareQuery(); // this method deletes recursively all directories RemoveAllDirs(request->dir_tab.back()->id); request->dir_tab.erase(--request->dir_tab.end()); if( request->dir_tab.empty() ) { // we have deleted the root directory system->dirs.CheckRootDir(); // adding a new root dir Item * proot = system->dirs.GetRootDir(); if( proot ) request->dir_tab.push_back(proot); else // there is no a root dir // CheckRootDir() didn't add the root dir (probably problem with the database) // make sure that ::Make() will check that the dir_tab is empty and returns return; } system->RedirectToLastDir(); } void Rm::RemoveDir() { if( request->param_tab.empty() ) request->status = WINIX_ERR_PERMISSION_DENIED; // use parameter "r" for removing a directory else if( request->IsParam(L"r") ) RemoveAllDirs(); else request->status = WINIX_ERR_UNKNOWN_PARAM; } void Rm::RemoveAuth(Item & item) { if( item.auth_path.empty() ) { log << log1 << "Content: can't remove a static file: auth_path is empty" << logend; return; } if( ::RemoveFile(item.auth_path) ) { log << log1 << "Content: removed static file: " << item.auth_path << logend; item.auth_path.clear(); item.auth = Item::auth_none; // we don't store it to db (will be removed or is removed already) } else { int err = errno; log << log1 << "Content: can't remove a file: " << item.auth_path; log.SystemErr(err); log << logend; request->status = WINIX_ERR_PERMISSION_DENIED; } } void Rm::RemoveFile() { // for safety we check if param_tab is empty // a user can use "confirm" but can make a mistake when typing if( !request->param_tab.empty() ) { request->status = WINIX_ERR_UNKNOWN_PARAM; return; } if( db->DelItem( request->item ) ) { log << log2 << "Content: deleted item: subject: " << request->item.subject << ", id: " << request->item.id << logend; TemplatesFunctions::pattern_cacher.DeletePattern(request->item); plugin.Call(WINIX_FILE_REMOVED, request->item.id); if( system->mounts.pmount->type == system->mounts.MountTypeThread() ) db->EditThreadRemoveItem(request->item.parent_id); /* !! tticket else if( system->mounts.pmount->type == system->mounts.MountTypeTicket() ) db->EditTicketRemoveItem(request->item.id); */ if( request->item.auth != Item::auth_none ) RemoveAuth(request->item); } else { request->status = WINIX_ERR_NO_ITEM; } system->RedirectToLastDir(); } void Rm::MakeGet() { if( request->IsParam(L"confirm") ) return; // show confirmation dialog if( request->is_item ) RemoveFile(); else RemoveDir(); } } // namespace