444 lines
9.8 KiB
C++
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.
|