gnuworld/mod.cservice/ACCESSCommand.cc

444 lines
9.8 KiB
C++

/**
* ACCESSCommand.cc
*
* 24/12/2000 - Greg Sikorski <gte@atomicrevs.demon.co.uk>
* Initial Version.
* 15/02/2001 - David Henriksen <david@itwebnet.dk>
* Added -op/-voice/-none support
*
* 01/03/01 - Daniel Simard <svr@undernet.org>
* Fixed Language module stuff.
*
* Displays all "Level" records for a specified channel.
* Can optionally narrow down selection using a number of switches.
*
* 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: ACCESSCommand.cc,v 1.50 2009/06/09 15:40:29 mrbean_ Exp $
*/
#include <string>
#include <sstream>
#include <iostream>
#include "StringTokenizer.h"
#include "ELog.h"
#include "cservice.h"
#include "dbHandle.h"
#include "match.h"
#include "responses.h"
#include "cservice_config.h"
#include "Network.h"
const char ACCESSCommand_cc_rcsId[] = "$Id: ACCESSCommand.cc,v 1.50 2009/06/09 15:40:29 mrbean_ Exp $" ;
namespace gnuworld
{
using std::endl ;
using std::ends ;
using std::stringstream ;
using std::string ;
static const char* queryHeader = "SELECT channels.name,users.user_name,levels.access,levels.flags,users_lastseen.last_seen,levels.suspend_expires,levels.last_modif,levels.last_modif_by,levels.suspend_level,levels.suspend_reason FROM levels,channels,users,users_lastseen ";
static const char* queryCondition = "WHERE levels.channel_id=channels.id AND levels.user_id=users.id AND users.id=users_lastseen.user_id ";
static const char* queryFooter = "ORDER BY levels.access DESC;";
bool ACCESSCommand::Exec( iClient* theClient, const string& Message )
{
bot->incStat("COMMANDS.ACCESS");
/*
* This command will build up a custom SQL query and execute it on
* the 'levels' table.
*/
StringTokenizer st( Message ) ;
if( st.size() < 3 )
{
Usage(theClient);
return true;
}
sqlUser* theUser = bot->isAuthed(theClient, true);
if (!theUser)
{
return false;
}
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;
}
/* Don't let ordinary people view * accesses */
if (theChan->getName() == "*")
{
sqlUser* theUser = bot->isAuthed(theClient, false);
if (!theUser)
{
bot->Notice(theClient,
bot->getResponse(theUser,
language::chan_not_reg).c_str(),
st[1].c_str()
);
return false;
}
if (theUser && !bot->getAdminAccessLevel(theUser))
{
bot->Notice(theClient,
bot->getResponse(theUser,
language::chan_not_reg).c_str(),
st[1].c_str()
);
return false;
}
}
/*
* Figure out the switches and append to the SQL statement accordingly.
*/
/* 0 = None, 1 = min, 2 = max, 3 = modif, 4 = op, 5 = voice, 6 = none. */
unsigned short currentType = 0;
unsigned int minAmount = 0;
unsigned int maxAmount = 0;
bool modif = false;
bool showAll = false;
bool aOp = false;
bool aHalfOp = false;
bool aVoice = false;
bool aNone = false;
string modifMask;
for( StringTokenizer::const_iterator ptr = st.begin() ; ptr != st.end() ;
++ptr )
{
if (string_lower(*ptr) == "-min")
{
currentType = 1;
continue;
}
if (string_lower(*ptr) == "-max")
{
currentType = 2;
continue;
}
if (string_lower(*ptr) == "-modif")
{
currentType = 3;
modif = true;
continue;
}
if (string_lower(*ptr) == "-op")
{
currentType = 4;
aOp = true;
continue;
}
if (string_lower(*ptr) == "-halfop")
{
currentType = 5;
aHalfOp = true;
continue;
}
if (string_lower(*ptr) == "-voice")
{
currentType = 6;
aVoice = true;
continue;
}
if (string_lower(*ptr) == "-none")
{
currentType = 7;
aNone = true;
continue;
}
if (string_lower(*ptr) == "-all")
{
sqlUser* tmpUser = bot->isAuthed(theClient, false);
if( tmpUser && bot->getAdminAccessLevel(tmpUser) )
{
showAll = true;
}
continue;
}
switch(currentType)
{
case 1: /* Min */
{
minAmount = atoi( (*ptr).c_str() );
if ((minAmount > 1000) /* || (minAmount < 0) */)
{
bot->Notice(theClient,
bot->getResponse(theUser,
language::inval_min_lvl).c_str()
);
return false;
}
currentType = 0;
break;
}
case 2: /* Max */
{
maxAmount = atoi( (*ptr).c_str() );
if ((maxAmount > 1000) /* || (maxAmount < 0) */)
{
bot->Notice(theClient,
bot->getResponse(theUser,
language::inval_max_lvl).c_str()
);
return false;
}
currentType = 0;
break;
}
case 3: /* Modif */
{
// [22:13] <DrCkTaiL> backburner
break;
}
case 4: /* Automode Op */
{
break;
}
case 5: /* Automode HalfOp */
{
break;
}
case 6: /* Automode Voice */
{
break;
}
case 7: /* Automode None */
{
break;
}
}
}
/* Sort out the additional conditions */
stringstream extraCond;
if (minAmount)
{
extraCond << "AND levels.access >= " << minAmount << " ";
}
if (maxAmount)
{
extraCond << "AND levels.access <= " << maxAmount << " ";
}
extraCond << ends;
stringstream theQuery;
theQuery << queryHeader
<< queryCondition
<< extraCond.str().c_str()
<< "AND levels.channel_id = "
<< theChan->getID()
<< " "
<< queryFooter
<< ends;
#ifdef LOG_SQL
elog << "ACCESS::sqlQuery> "
<< theQuery.str().c_str()
<< endl;
#endif
/*
* All done, display the output. (Only fetch 15 results).
*/
if( !bot->SQLDb->Exec( theQuery, true ) )
//if( PGRES_TUPLES_OK != status )
{
elog << "ACCESS> SQL Error: "
<< bot->SQLDb->ErrorMessage()
<< endl ;
return false ;
}
sqlLevel::flagType flag = 0 ;
string autoMode;
int duration = 0;
int suspend_expires = 0;
int suspend_expires_d = 0;
int suspend_expires_f = 0;
int results = 0;
string matchString = st[2];
if(matchString[0] == '-')
{
matchString = "*";
}
/*
* Convert =nick to username.
*/
if (matchString[0] == '=')
{
const char* theNick = matchString.c_str();
// Skip the '='
++theNick;
iClient *theClient = Network->findNick(theNick);
if (theClient)
{
sqlUser* tmpUser = bot->isAuthed(theClient,false);
if (tmpUser)
{
matchString = tmpUser->getUserName();
}
}
}
for (unsigned int i = 0 ; i < bot->SQLDb->Tuples(); i++)
{
autoMode = "None";
/* Does the username match the query? */
if (match(matchString, bot->SQLDb->GetValue(i, 1)) == 0)
{
flag = atoi(bot->SQLDb->GetValue(i, 3));
duration = atoi(bot->SQLDb->GetValue(i, 4));
suspend_expires = atoi(bot->SQLDb->GetValue(i, 5));
suspend_expires_d = suspend_expires - bot->currentTime();
suspend_expires_f = bot->currentTime() - suspend_expires_d;
if (flag & sqlLevel::F_AUTOOP) autoMode = "OP";
if (flag & sqlLevel::F_AUTOHALFOP) autoMode = "HALFOP";
if (flag & sqlLevel::F_AUTOVOICE) autoMode = "VOICE";
if(aVoice == true || aHalfOp == true || aOp == true || aNone == true)
{
if(aNone == true)
{
if(!aVoice && (flag & sqlLevel::F_AUTOVOICE)) continue;
if(!aHalfOp && (flag & sqlLevel::F_AUTOHALFOP)) continue;
if(!aOp && (flag & sqlLevel::F_AUTOOP)) continue;
}
else
{
if(!(flag & sqlLevel::F_AUTOVOICE) &&
!(flag & sqlLevel::F_AUTOHALFOP) &&
!(flag & sqlLevel::F_AUTOOP)) continue;
if(!aVoice && (flag & sqlLevel::F_AUTOVOICE)) continue;
if(!aHalfOp && (flag & sqlLevel::F_AUTOHALFOP)) continue;
if(!aOp && (flag & sqlLevel::F_AUTOOP)) continue;
}
}
results++;
bot->Notice(theClient,
bot->getResponse(theUser, language::user_access_is).c_str(),
bot->SQLDb->GetValue(i, 1).c_str(),
bot->SQLDb->GetValue(i, 2).c_str(),
bot->userStatusFlags(bot->SQLDb->GetValue(i, 1)).c_str()
);
bot->Notice(theClient,
bot->getResponse(theUser, language::channel_automode_is).c_str(),
bot->SQLDb->GetValue(i, 0).c_str(),
autoMode.c_str());
unsigned int suspendLevel = atoi(bot->SQLDb->GetValue(i, 8));
string suspReason = bot->SQLDb->GetValue(i,9);
if( suspend_expires > bot->currentTime() )
{
unsigned int suspendLevel = atoi(bot->SQLDb->GetValue(i, 8));
bot->Notice(theClient,
bot->getResponse(theUser,
language::suspend_expires_in).c_str(),
prettyDuration(suspend_expires_f).c_str(),
suspendLevel
);
bot->Notice(theClient,bot->getResponse(theUser,
language::susp_reason,string("Reason: %s")).c_str(),suspReason.c_str());
}
else if ((suspReason != "") && (suspend_expires == 0))
bot->Notice(theClient,bot->getResponse(theUser,
language::unsusp_reason,string("UNSUSPENDED - %s")).c_str(),suspReason.c_str());
bot->Notice(theClient,
bot->getResponse(theUser,
language::last_seen).c_str(),
prettyDuration(duration).c_str()
);
if(modif)
{
bot->Notice(theClient,
bot->getResponse(theUser,
language::last_mod).c_str(),
bot->SQLDb->GetValue(i, 7).c_str(),
prettyDuration(atoi(bot->SQLDb->GetValue(i,6))).c_str()
);
}
}
if ((results >= MAX_ACCESS_RESULTS) && !showAll) break;
} // for()
if ((results >= MAX_ACCESS_RESULTS) && !showAll)
{
bot->Notice(theClient,
bot->getResponse(theUser, language::more_than_max).c_str(),
MAX_ACCESS_RESULTS
);
bot->Notice(theClient,
bot->getResponse(theUser, language::restrict_query).c_str()
);
}
else if (results > 0)
{
bot->Notice(theClient,
bot->getResponse(theUser, language::end_access_list).c_str()
);
}
else
{
bot->Notice(theClient,
bot->getResponse(theUser, language::no_match).c_str()
);
}
return true ;
}
} // namespace gnuworld.