/** * SUSPENDCommand.cc * * 06/01/2001 - David Henriksen * Initial Version, done with a fever :/ * * Suspends an user on the specified channel, if suspend duration 0 * is defined, the user will be unsuspended. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * $Id: SUSPENDCommand.cc,v 1.29 2010/04/10 18:56:06 danielaustin Exp $ */ #include #include #include #include "StringTokenizer.h" #include "ELog.h" #include "cservice.h" #include "Network.h" #include "levels.h" #include "responses.h" const char SUSPENDCommand_cc_rcsId[] = "$Id: SUSPENDCommand.cc,v 1.29 2010/04/10 18:56:06 danielaustin Exp $" ; namespace gnuworld { using std::string ; using namespace level; bool SUSPENDCommand::Exec( iClient* theClient, const string& Message ) { bot->incStat("COMMANDS.SUSPEND"); StringTokenizer st( Message ) ; if( st.size() < 3 ) { Usage(theClient); return true; } /* Is the user authenticated? */ sqlUser* theUser = bot->isAuthed(theClient, true); if(!theUser) { return false; } /* * Trying to suspend a user, or a channel? * If there is no #, check this person's admin access.. * If it passes, we can suspend a whole user account. */ if ((st[1][0] != '#') && (st[1][0] != '*')) { /* Got enough admin access? */ int level = bot->getAdminAccessLevel(theUser); if (level == 0) { Usage(theClient); return true; } if ((level > 0) && (level < level::globalsuspend)) { bot->Notice(theClient, bot->getResponse(theUser, language::insuf_access, string("Sorry, you have insufficient access to perform that command."))); return true; } /* Does this user account even exist? */ sqlUser* targetUser = bot->getUserRecord(st[1]); if (!targetUser) { bot->Notice(theClient, bot->getResponse(theUser, language::not_registered, string("I don't know who %s is")).c_str(), st[1].c_str()); return true; } /* * Check the target's admin access, if its >= ours, don't * allow it. :) */ int targetLevel = bot->getAdminAccessLevel(targetUser); if (!theUser->getFlag(sqlUser::F_POWER)) if (targetLevel >= level) { bot->Notice(theClient, bot->getResponse(theUser, language::suspend_access_higher, string("Cannot suspend a user with equal or higher access than your own."))); return false; } if (targetUser->getFlag(sqlUser::F_GLOBAL_SUSPEND)) { bot->Notice(theClient, "%s is already suspended, you could always try execution?", targetUser->getUserName().c_str()); return true; } // Suspend them. targetUser->setFlag(sqlUser::F_GLOBAL_SUSPEND); targetUser->commit(theClient); bot->Notice(theClient, "%s has been globally suspended and will have level 0 access in all" " channels until unsuspended.", targetUser->getUserName().c_str()); if ((theUser->getFlag(sqlUser::F_POWER)) && (targetUser == theUser)) bot->Notice(theClient,"CSC is You!! YOU CAN NEVER ESCAPE!"); targetUser->writeEvent(sqlUser::EV_SUSPEND, theUser, st.assemble(2)); //Deop the all newly suspended clients for (sqlUser::networkClientListType::iterator cliPtr = targetUser->networkClientList.begin(); cliPtr != targetUser->networkClientList.end() ; ++cliPtr ) { for (iClient::channelIterator chItr = (*cliPtr)->channels_begin(); chItr != (*cliPtr)->channels_end(); ++chItr) { ChannelUser* theChannelUser = (*chItr)->findUser(*cliPtr); sqlChannel* theChan = bot->getChannelRecord((*chItr)->getName()); if ((theChan) && (theChannelUser->getMode(ChannelUser::MODE_O))) { sqlLevel* tmpLevel = bot->getLevelRecord(targetUser, theChan); if (tmpLevel) { std::pair thePair; thePair = std::make_pair(tmpLevel->getUserId(), tmpLevel->getChannelId()); bot->sqlLevelCache.erase(thePair); delete(tmpLevel); } bot->deopSuspendedOnChan(*chItr,targetUser); } } if (targetUser->getLanguageId() == 8) bot->Notice((*cliPtr),"Userul tau a fost suspendat global."); else bot->Notice((*cliPtr),"Your user account has been globally suspended."); } bot->logAdminMessage("%s (%s) has globally suspended %s's user account.", theClient->getNickName().c_str(), theUser->getUserName().c_str(), targetUser->getUserName().c_str()); return true; } //end of Global user suspend, begin channel suspend if( st.size() < 4 ) { Usage(theClient); return true; } /* Is the channel registered? */ sqlChannel* theChan = bot->getChannelRecord(st[1]); if(!theChan) { bot->Notice(theClient, bot->getResponse(theUser, language::chan_not_reg, string("Sorry, %s isn't registered with me.")).c_str(), st[1].c_str()); return false; } /* Check level. */ int level = bot->getEffectiveAccessLevel(theUser, theChan, true); int suspendLevel = level; if ((level < level::suspend) || (( st[1] == "*" ) && (level < adminlevel::suspend))) { bot->Notice(theClient, bot->getResponse(theUser, language::insuf_access, string("Sorry, you have insufficient access to perform that command."))); return false; } /* Check whether the user is in the access list. */ sqlUser* Target = bot->getUserRecord(st[2]); if(!Target) { bot->Notice(theClient, bot->getResponse(theUser, language::not_registered, string("I don't know who %s is")).c_str(), st[2].c_str()); return true; } int usrLevel = bot->getAccessLevel(Target, theChan); if(!usrLevel) { bot->Notice(theClient, bot->getResponse(theUser, language::doesnt_have_access, string("%s doesn't appear to have access in %s.")).c_str(), Target->getUserName().c_str(), theChan->getName().c_str()); return true; } if (!theUser->getFlag(sqlUser::F_POWER)) if (level <= usrLevel) { bot->Notice(theClient, bot->getResponse(theUser, language::suspend_access_higher, string("Cannot suspend a user with equal or higher access than your own."))); return false; } time_t finalDuration; string suspReason; if (!IsTimeSpec(st[3])) //this means only a reason was specified, no duration, no level and we use the defaults { suspReason = st.assemble(3); finalDuration = 3 * 3600; } else finalDuration = extractTime(st[3], 60); /* If we have a length at least of 5, then if the 5th param is a number then it is the susp level * else the reason is specified */ if ((st.size() > 4) && (suspReason.empty())) { if (IsNumeric(st[4])) suspendLevel = atoi(st[4].c_str()); else suspReason = st.assemble(4); } if ((st.size() > 5) && (suspReason.empty())) { suspReason = st.assemble(5); } /* Greater than a year? */ if(finalDuration > 32140800 || finalDuration < 0) { bot->Notice(theClient, bot->getResponse(theUser, language::inval_suspend_dur, string("Invalid suspend duration."))); return true; } sqlLevel* aLevel = bot->getLevelRecord(Target, theChan); if (suspReason.empty()) suspReason = "No reason supplied."; if( 0 == finalDuration ) { if (theUser->getFlag(sqlUser::F_POWER)) level = bot->getAdminAccessLevel(theUser); /* * Was this suspension set with a higher suspend level? */ if (!theUser->getFlag(sqlUser::F_POWER)) if (aLevel->getSuspendLevel() > level) { bot->Notice(theClient, "Cannot unsuspend a user that was suspended at a higher level than your own access."); return false; } if ((suspReason.size() < 2) || (suspReason.size() > 300)) { //bot->Notice(theClient,"Your reason must be 2 - 300 charcters long."); bot->Notice(theClient, bot->getResponse(theUser,language::reason_must).c_str(),2,300); return false; } aLevel->setSuspendLevel(0); aLevel->setSuspendExpire(finalDuration); aLevel->setSuspendBy(string()); aLevel->setSuspendReason(suspReason); aLevel->setLastModif(bot->currentTime()); aLevel->setLastModifBy( string( "(" + theUser->getUserName() + ") " + theClient->getNickUserHost() ) ); if( !aLevel->commit() ) { bot->Notice( theClient, "Error updating channel status." ); elog << "UNSUSPEND> SQL error" << std::endl; return false; } bot->Notice(theClient, bot->getResponse(theUser, language::susp_cancelled, string("SUSPENSION for %s is cancelled")).c_str(), Target->getUserName().c_str()); if (Target != theUser) bot->NoteAllAuthedClients(Target, bot->getResponse(Target,language::acc_unsusp).c_str(), theChan->getName().c_str()); return true; } //end of (0 == finalDuration) (unsuspend) if (aLevel->getSuspendExpire() > bot->currentTime()) { bot->Notice(theClient, bot->getResponse(theUser, language::already_susp, string("%s is already suspended on %s")).c_str(), Target->getUserName().c_str(), theChan->getName().c_str()); return false; } if ((suspReason.size() < 2) || (suspReason.size() > 300)) { //bot->Notice(theClient,"Your reason must be 2 - 300 charcters long."); bot->Notice(theClient, bot->getResponse(theUser,language::reason_must).c_str(),2,300); return false; } if ((suspendLevel > level) || (suspendLevel > 500) || (suspendLevel <= 0)) suspendLevel = level; aLevel->setSuspendExpire(finalDuration + bot->currentTime()); aLevel->setSuspendBy(theClient->getNickUserHost()); aLevel->setSuspendLevel(suspendLevel); aLevel->setSuspendReason(suspReason); aLevel->setLastModif(bot->currentTime()); aLevel->setLastModifBy( string( "(" + theUser->getUserName() + ") " + theClient->getNickUserHost() ) ); aLevel->commit(); Channel* tmpChan = Network->findChannel(theChan->getName()); if (tmpChan) bot->deopSuspendedOnChan(tmpChan,Target); bot->Notice(theClient, bot->getResponse(theUser, language::susp_set, string("SUSPENSION for %s will expire in %s")).c_str(), Target->getUserName().c_str(), prettyDuration(bot->currentTime() - finalDuration ).c_str()); if (Target != theUser) bot->NoteAllAuthedClients(Target, bot->getResponse(Target,language::acc_susp).c_str(), theChan->getName().c_str()); if ((theUser->getFlag(sqlUser::F_POWER)) && (Target == theUser)) bot->Notice(theClient,"CSC is You!! YOU CAN NEVER ESCAPE!"); return true ; } } // namespace gnuworld.