* | Inspire Internet Relay Chat Daemon |
* +------------------------------------+
*
- * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
- * E-mail:
- * <brain@chatspike.net>
- * <Craig@chatspike.net>
- *
- * Written by Craig Edwards, Craig McLure, and others.
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
* This program is free but copyrighted software; see
- * the file COPYING for details.
+ * the file COPYING for details.
*
* ---------------------------------------------------
*/
-using namespace std;
-
#include "inspircd.h"
#include "users.h"
#include "modules.h"
#include "modes/umode_n.h"
ModeHandler::ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly, char mprefix)
- : ServerInstance(Instance), mode(modeletter), n_params_on(parameters_on), n_params_off(parameters_off), list(listmode), m_type(type), oper(operonly), prefix(mprefix)
+ : ServerInstance(Instance), mode(modeletter), n_params_on(parameters_on), n_params_off(parameters_off), list(listmode), m_type(type), oper(operonly), prefix(mprefix), count(0)
{
}
return 0;
}
+unsigned int ModeHandler::GetCount()
+{
+ return 0;
+}
+
+void ModeHandler::ChangeCount(int modifier)
+{
+ count += modifier;
+}
+
ModeType ModeHandler::GetModeType()
{
return m_type;
if (!chan)
return "";
- for (std::vector<ucrec*>::const_iterator i = d->chans.begin(); i != d->chans.end(); i++)
+ UCListIter n = d->chans.find(chan);
+ if (n != d->chans.end())
{
- ucrec* n = (ucrec*)(*i);
- if (n->channel == chan)
+ if (n->second & MASK)
{
- if (n->uc_modes & MASK)
- {
- return "";
- }
- n->uc_modes = n->uc_modes | MASK;
- switch (MASK)
- {
- case UCMODE_OP:
- n->channel->AddOppedUser(d);
- break;
- case UCMODE_HOP:
- n->channel->AddHalfoppedUser(d);
- break;
- case UCMODE_VOICE:
- n->channel->AddVoicedUser(d);
- break;
- }
- ServerInstance->Log(DEBUG,"grant: %s %s",n->channel->name,d->nick);
- return d->nick;
+ return "";
+ }
+ n->second = n->second | MASK;
+ switch (MASK)
+ {
+ case UCMODE_OP:
+ n->first->AddOppedUser(d);
+ break;
+ case UCMODE_HOP:
+ n->first->AddHalfoppedUser(d);
+ break;
+ case UCMODE_VOICE:
+ n->first->AddVoicedUser(d);
+ break;
}
+ return d->nick;
}
return "";
}
if (!chan)
return "";
- for (std::vector<ucrec*>::const_iterator i = d->chans.begin(); i != d->chans.end(); i++)
+ UCListIter n = d->chans.find(chan);
+ if (n != d->chans.end())
{
- ucrec* n = (ucrec*)(*i);
- if (n->channel == chan)
+ if ((n->second & MASK) == 0)
{
- if ((n->uc_modes & MASK) == 0)
- {
- return "";
- }
- n->uc_modes ^= MASK;
- switch (MASK)
- {
- case UCMODE_OP:
- n->channel->DelOppedUser(d);
- break;
- case UCMODE_HOP:
- n->channel->DelHalfoppedUser(d);
- break;
- case UCMODE_VOICE:
- n->channel->DelVoicedUser(d);
- break;
- }
- ServerInstance->Log(DEBUG,"revoke: %s %s",n->channel->name,d->nick);
- return d->nick;
+ return "";
}
+ n->second ^= MASK;
+ switch (MASK)
+ {
+ case UCMODE_OP:
+ n->first->DelOppedUser(d);
+ break;
+ case UCMODE_HOP:
+ n->first->DelHalfoppedUser(d);
+ break;
+ case UCMODE_VOICE:
+ n->first->DelVoicedUser(d);
+ break;
+ }
+ return d->nick;
}
return "";
}
else
{
user->WriteServ("502 %s :Can't change mode for other users", user->nick);
+ return;
}
}
chanrec* targetchannel = ServerInstance->FindChan(parameters[0]);
userrec* targetuser = ServerInstance->FindNick(parameters[0]);
- ServerInstance->Log(DEBUG,"ModeParser::Process start: pcnt=%d",pcnt);
- for (int j = 0; j < pcnt; j++)
- ServerInstance->Log(DEBUG," parameters[%d] = '%s'", j, parameters[j]);
-
LastParse = "";
/* Special case for displaying the list for listmodes,
*/
if ((targetchannel) && (pcnt == 2))
{
- ServerInstance->Log(DEBUG,"Spool list");
const char* mode = parameters[1];
+ int nonlistmodes_found = 0;
+ mask = MASK_CHANNEL;
+
while (mode && *mode)
{
if (*mode == '+')
}
ModeHandler *mh = this->FindMode(*mode, MODETYPE_CHANNEL);
+ bool display = true;
if ((mh) && (mh->IsListMode()))
{
- mh->DisplayList(user, targetchannel);
+ /** See below for a description of what craq this is :D
+ */
+ unsigned char handler_id = (*mode - 65) | mask;
+
+ for(ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
+ {
+ std::string dummyparam;
+
+ if (!((*watchers)->BeforeMode(user, NULL, targetchannel, dummyparam, true, MODETYPE_CHANNEL)))
+ display = false;
+ }
+
+ if (display)
+ mh->DisplayList(user, targetchannel);
}
+ else
+ nonlistmodes_found++;
mode++;
}
+
+ /* We didnt have any modes that were non-list, we can return here */
+ if (!nonlistmodes_found)
+ return;
}
if (pcnt == 1)
{
- ServerInstance->Log(DEBUG,"Mode list request");
this->DisplayCurrentModes(user, targetuser, targetchannel, parameters[0]);
}
else if (pcnt > 1)
{
- ServerInstance->Log(DEBUG,"More than one parameter");
-
if (targetchannel)
{
type = MODETYPE_CHANNEL;
if ((IS_LOCAL(user)) && (targetchannel->GetStatus(user) < STATUS_HOP))
{
/* We don't have halfop */
- ServerInstance->Log(DEBUG,"The user is not a halfop or above, checking other reasons for being able to set the modes");
-
int MOD_RESULT = 0;
FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user, NULL, targetchannel, AC_GENERAL_MODE));
if (MOD_RESULT == ACR_DENY)
unsigned char handler_id = 0;
int parameter_counter = 2; /* Index of first parameter */
int parameter_count = 0;
+ bool last_successful_state_change = false;
/* A mode sequence that doesnt start with + or -. Assume +. - Thanks for the suggestion spike (bug#132) */
if ((*mode_sequence.begin() != '+') && (*mode_sequence.begin() != '-'))
{
unsigned char modechar = *letter;
- ServerInstance->Log(DEBUG,"Process letter %c", modechar);
-
switch (modechar)
{
/* NB:
if ((!adding) || (!output_sequence.length()))
state_change = true;
adding = true;
+ if (!output_sequence.length())
+ last_successful_state_change = false;
continue;
break;
case '-':
if ((adding) || (!output_sequence.length()))
state_change = true;
adding = false;
+ if (!output_sequence.length())
+ last_successful_state_change = true;
continue;
break;
default:
{
bool abort = false;
- for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
- {
- if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type) == MODEACTION_DENY)
- abort = true;
- }
- if ((modehandlers[handler_id]->GetModeType() == type) && (!abort))
+ if (modehandlers[handler_id]->GetModeType() == type)
{
if (modehandlers[handler_id]->GetNumParams(adding))
{
/* This mode expects a parameter, do we have any parameters left in our list to use? */
if (parameter_counter < pcnt)
{
- ServerInstance->Log(DEBUG,"parameter_counter = %d, pcnt = %d", parameter_counter, pcnt);
parameter = parameters[parameter_counter++];
/* Yerk, invalid! */
/* No parameter, continue to the next mode */
continue;
}
+
+ bool had_parameter = !parameter.empty();
+
+ for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
+ {
+ if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type) == false)
+ {
+ abort = true;
+ break;
+ }
+ /* A module whacked the parameter completely, and there was one. abort. */
+ if ((had_parameter) && (parameter.empty()))
+ {
+ abort = true;
+ break;
+ }
+ }
+
+ if (abort)
+ continue;
}
/* It's an oper only mode, check if theyre an oper. If they arent,
{
/* We're about to output a valid mode letter - was there previously a pending state-change? */
if (state_change)
- output_sequence.append(adding ? "+" : "-");
+ {
+ if (adding != last_successful_state_change)
+ output_sequence.append(adding ? "+" : "-");
+ last_successful_state_change = adding;
+ }
/* Add the mode letter */
output_sequence.push_back(modechar);
{
if (type == MODETYPE_CHANNEL)
{
- ServerInstance->Log(DEBUG,"Write output sequence and parameters to channel: %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str());
targetchannel->WriteChannel(user,"MODE %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str());
FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, output_sequence + parameter_list.str()));
this->LastParse = targetchannel->name;
return false;
modehandlers[pos] = mh;
- ServerInstance->Log(DEBUG,"ModeParser::AddMode: added mode %c",mh->GetModeChar());
return true;
}
switch (mh->GetModeType())
{
case MODETYPE_USER:
- for (user_hash::iterator i = ServerInstance->clientlist.begin(); i != ServerInstance->clientlist.end(); i++)
+ for (user_hash::iterator i = ServerInstance->clientlist->begin(); i != ServerInstance->clientlist->end(); i++)
{
mh->RemoveMode(i->second);
}
break;
case MODETYPE_CHANNEL:
- for (chan_hash::iterator i = ServerInstance->chanlist.begin(); i != ServerInstance->chanlist.end(); i++)
+ for (chan_hash::iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++)
{
mh->RemoveMode(i->second);
}
pos = (mw->GetModeChar()-65) | mask;
modewatchers[pos].push_back(mw);
- ServerInstance->Log(DEBUG,"ModeParser::AddModeWatcher: watching mode %c",mw->GetModeChar());
-
return true;
}
if (a == modewatchers[pos].end())
{
- ServerInstance->Log(DEBUG, "ModeParser::DelModeWatcher: Couldn't find watcher for mode %c in list", mw->GetModeChar());
return false;
}
modewatchers[pos].erase(a);
- ServerInstance->Log(DEBUG,"ModeParser::DelModeWatcher: stopped watching mode %c",mw->GetModeChar());
return true;
}