gnuworld/mod.cservice/STATUSCommand.cc

356 lines
9.0 KiB
C++

/**
* STATUSCommand.cc
*
* 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: STATUSCommand.cc,v 1.48 2007/12/26 20:38:57 kewlio Exp $
*/
#include <string>
#include <sstream>
#include <iostream>
#include "StringTokenizer.h"
#include "ELog.h"
#include "cservice.h"
#include "levels.h"
#include "responses.h"
#include "Network.h"
#include "cservice_config.h"
const char STATUSCommand_cc_rcsId[] = "$Id: STATUSCommand.cc,v 1.48 2007/12/26 20:38:57 kewlio Exp $" ;
namespace gnuworld
{
using std::cout ;
using std::string ;
using std::endl ;
using std::ends ;
using std::stringstream ;
bool STATUSCommand::Exec( iClient* theClient, const string& Message )
{
bot->incStat("COMMANDS.STATUS");
StringTokenizer st( Message ) ;
if( st.size() < 2 )
{
Usage(theClient);
return true;
}
/*
* Fetch the sqlUser record attached to this client. If there isn't one,
* they aren't logged in - tell them they should be.
*/
sqlUser* theUser = bot->isAuthed(theClient, true);
if (!theUser)
{
return false;
}
/*
* Check the channel is actually registered.
*/
if (st[1] == "*")
{
/*
* Special case, display admin stat(u)s. - of all logged official stuff (Seven)
*/
/* Don't show if they don't have any admin or coder-com access. */
if (!bot->getAdminAccessLevel(theUser) && !bot->getCoderAccessLevel(theUser))
{
bot->Notice(theClient,
bot->getResponse(theUser, language::chan_not_reg).c_str(),
st[1].c_str());
return false;
}
//bot->doCoderStats(theClient); //moved to STATS * (Seven)
bot->showAdmins(theClient);
return true;
}
sqlChannel* theChan = bot->getChannelRecord(st[1]);
if (!theChan)
{
bot->Notice(theClient,
bot->getResponse(theUser, language::chan_not_reg).c_str(),
st[1].c_str());
return false;
}
/*
* Check the user has sufficient access on this channel.
*/
int level = bot->getEffectiveAccessLevel(theUser, theChan, true);
// Let authenticated admins view status also.
int admLevel = bot->getAdminAccessLevel(theUser);
if ((level < level::status) && (admLevel <= 0) && !theClient->isOper())
{
bot->Notice(theClient,
bot->getResponse(theUser, language::insuf_access).c_str());
return false;
}
/*
* Display some fancy info about the channel.
*/
Channel* tmpChan = Network->findChannel(theChan->getName());
if (tmpChan)
{
// If the person has access >200, or is a 1+ admin (or and Oper).
bot->Notice(theClient,
bot->getResponse(theUser,
language::status_chan_info,
string("Channel %s has %d users (%i operators)")).c_str(),
tmpChan->getName().c_str(),
tmpChan->size(),
bot->countChanOps(tmpChan) ) ;
if ((level >= 200) || (admLevel >= 1) || theClient->isOper())
{
bot->Notice(theClient,
bot->getResponse(theUser,
language::status_mode,
string("Mode is: %s")).c_str(),
tmpChan->getModeString().c_str() ) ;
}
/*
* Are we on this channel?
*/
if (!theChan->getInChan())
{
bot->Notice(theClient, "I'm \002not\002 in this channel.");
} else
{
bot->Notice(theClient, "I'm currently in this channel.");
}
} // if( tmpChan )
else
{
bot->Notice(theClient, "I'm \002not\002 in this channel.");
}
bot->Notice(theClient, "MassDeopPro: %i", theChan->getMassDeopPro());
string flagsSet;
if (admLevel > 0)
{
/* only "*" access can view certain flags */
if (theChan->getFlag(sqlChannel::F_NOPURGE)) flagsSet += "NOPURGE ";
if (theChan->getFlag(sqlChannel::F_SPECIAL)) flagsSet += "SPECIAL ";
if (theChan->getFlag(sqlChannel::F_NOREG)) flagsSet += "NOREG ";
if (theChan->getFlag(sqlChannel::F_NEVREG)) flagsSet += "NEVERREG ";
if (theChan->getFlag(sqlChannel::F_CAUTION)) flagsSet += "CAUTION ";
if (theChan->getFlag(sqlChannel::F_LOCKED)) flagsSet += "LOCKED ";
if (theChan->getFlag(sqlChannel::F_NOFORCE)) flagsSet += "NOFORCE ";
if (theChan->getFlag(sqlChannel::F_MIA)) flagsSet += "MIA ";
}
/* anyone with access can view the rest of the flags (below) */
if (theChan->getFlag(sqlChannel::F_SUSPEND)) flagsSet += "SUSPEND ";
if (theChan->getFlag(sqlChannel::F_TEMP)) flagsSet += "TEMP ";
if (theChan->getFlag(sqlChannel::F_VACATION)) flagsSet += "VACATION ";
if (theChan->getFlag(sqlChannel::F_ALWAYSOP)) flagsSet += "ALWAYSOP ";
if (theChan->getFlag(sqlChannel::F_STRICTOP)) flagsSet += "STRICTOP ";
if (theChan->getFlag(sqlChannel::F_NOOP)) flagsSet += "NOOP ";
if (theChan->getFlag(sqlChannel::F_NOVOICE)) flagsSet += "NOVOICE ";
if (theChan->getFlag(sqlChannel::F_AUTOTOPIC)) flagsSet += "AUTOTOPIC ";
if (theChan->getFlag(sqlChannel::F_AUTOJOIN)) flagsSet += "AUTOJOIN ";
if (((level >= level::set::notake) || (admLevel)) &&
(theChan->getFlag(sqlChannel::F_NOTAKE)))
{
flagsSet += "NOTAKE (REV:";
if (theChan->getNoTake() == 1) flagsSet += "IGNORE)";
if (theChan->getNoTake() == 2) flagsSet += "BAN)";
if (theChan->getNoTake() == 3) flagsSet += "SUSPEND)";
}
bot->Notice(theClient,
bot->getResponse(theUser, language::status_flags,
string("Flags set: %s")).c_str(),flagsSet.c_str());
flagsSet.clear();
if (theChan->getFlag(sqlChannel::F_FLOATLIM))
{
stringstream floatLim;
floatLim
<< " FLOATLIM (MGN:"
<< theChan->getLimitOffset()
<< ", PRD:"
<< theChan->getLimitPeriod()
<< ", GRC:"
<< theChan->getLimitGrace()
<< ", MAX:"
<< theChan->getLimitMax()
<< ") "
<< ends;
flagsSet += floatLim.str().c_str();
}
/* show userflags (if not 'NONE') */
if (theChan->getUserFlags() == 1) flagsSet += "USERFLAGS=OP ";
else if (theChan->getUserFlags() == 2) flagsSet += "USERFLAGS=VOICE ";
bot->Notice(theClient,flagsSet.c_str());
/*
* Get a list of authenticated users on this channel.
*/
stringstream authQuery;
authQuery << "SELECT users.user_name,levels.access FROM "
<< "users,levels WHERE users.id = levels.user_id "
<< "AND levels.channel_id = "
<< theChan->getID()
<< " ORDER BY levels.access DESC"
<< ends;
#ifdef LOG_SQL
elog << "sqlQuery> "
<< authQuery.str().c_str()
<< endl;
#endif
if( !bot->SQLDb->Exec( authQuery, true ) )
//if( PGRES_TUPLES_OK != status )
{
elog << "STATUS> SQL Error: "
<< bot->SQLDb->ErrorMessage()
<< endl ;
return false ;
}
string authList;
string nextPerson;
bool showNick = false;
for (unsigned int i = 0 ; i < bot->SQLDb->Tuples(); i++)
{
/*
* Look up this username in the cache.
*/
cservice::sqlUserHashType::iterator ptr =
bot->sqlUserCache.find(bot->SQLDb->GetValue(i, 0));
if(ptr != bot->sqlUserCache.end())
{
sqlUser* currentUser = ptr->second;
if( !currentUser->isAuthed() )
{
continue ;
}
nextPerson += bot->SQLDb->GetValue(i, 0);
nextPerson += "/\002";
/*
* Only show the online nickname if that person is in the target
* channel.
*
* Loop around all people auth'd as this nick and append their nicks
*/
for( sqlUser::networkClientListType::iterator ptr = currentUser->networkClientList.begin() ;
ptr != currentUser->networkClientList.end() ; ++ptr )
{
iClient* tmpClient = (*ptr);
showNick = false;
/* If we have admin access, always show the nick's of auth'd users. */
showNick = admLevel;
/* Only show the nick of the client if he's actually in the channel */
if (tmpChan) showNick = (tmpChan->findUser(tmpClient) || admLevel);
if (showNick)
{
nextPerson += "";
nextPerson += tmpClient->getNickName();
nextPerson += " ";
}
}
nextPerson += "\002[";
nextPerson += bot->SQLDb->GetValue(i, 1);
nextPerson += "] ";
/*
* Will this string overflow our Notice buffer?
* If so, dump it now..
*/
if(nextPerson.size() + authList.size() > 400)
{
bot->Notice(theClient, "Auth: %s", authList.c_str());
authList.erase( authList.begin(), authList.end() );
}
/*
* Add it on to our list.
*/
authList += nextPerson;
nextPerson.erase( nextPerson.begin(), nextPerson.end() );
}
} // for()
bot->Notice(theClient, "Auth: %s", authList.c_str());
/*
* Finally(!) display a quick list of everyone 'forced' on the
* channel.
*/
if (admLevel >= 1)
{
for(sqlChannel::forceMapType::const_iterator ptr = theChan->forceMap.begin();
ptr != theChan->forceMap.end(); ++ptr)
{
if ((!theChan->getFlag(sqlChannel::F_NOFORCE)) || (admLevel >= level::immune::noforce))
{
bot->Notice(theClient, "Force: %s (%i)",
ptr->second.second.c_str(), ptr->second.first);
}
}
}
/*
if (admLevel > level::admin::admin)
{
bot->Notice(theClient, "DB TS: %i -- IRC TS: %i",
theChan->getChannelTS(), tmpChan ? tmpChan->getCreationTime() : 0 );
}
*/
return true ;
}
} // namespace gnuworld.