* | Inspire Internet Relay Chat Daemon |
* +------------------------------------+
*
- * InspIRCd: (C) 2002-2008 InspIRCd Development Team
- * See: http://www.inspircd.org/wiki/index.php/Credits
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
*
* This program is free but copyrighted software; see
* the file COPYING for details.
* ---------------------------------------------------
*/
-/* $Core: libIRCDmode */
-/* $ExtraDeps: $(RELCPPFILES) */
-/* $ExtraObjects: modes/modeclasses.a */
-/* $ExtraBuild: @${MAKE} -C "modes" DIRNAME="src/modes" CC="$(CC)" $(MAKEARGS) CPPFILES="$(CPPFILES)" */
+/* $Core */
#include "inspircd.h"
#include "inspstring.h"
#include "modes/cmode_h.h"
/* +v (channel voice) */
#include "modes/cmode_v.h"
-/* +s (server notices) */
-#include "modes/umode_s.h"
/* +w (see wallops) */
#include "modes/umode_w.h"
/* +i (invisible) */
#include "modes/umode_i.h"
/* +o (operator) */
#include "modes/umode_o.h"
-/* +n (notice mask - our implementation of snomasks) */
-#include "modes/umode_n.h"
+/* +s (server notice masks) */
+#include "modes/umode_s.h"
-ModeHandler::ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly, char mprefix, char prefixrequired)
- : 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), prefixneeded(prefixrequired)
+ModeHandler::ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly, char mprefix, char prefixrequired, TranslateType translate)
+ : ServerInstance(Instance), mode(modeletter), n_params_on(parameters_on), n_params_off(parameters_off), list(listmode), m_type(type), m_paramtype(translate), oper(operonly), prefix(mprefix), count(0), prefixneeded(prefixrequired)
{
}
char ModeHandler::GetNeededPrefix()
{
+ if (prefixneeded == '%' && !ServerInstance->Config->AllowHalfop)
+ return '@';
return prefixneeded;
}
return m_type;
}
+TranslateType ModeHandler::GetTranslateType()
+{
+ return m_paramtype;
+}
+
bool ModeHandler::NeedsOper()
{
return oper;
return mode;
}
+std::string ModeHandler::GetUserParameter(User* user)
+{
+ return "";
+}
+
ModeAction ModeHandler::OnModeChange(User*, User*, Channel*, std::string&, bool, bool)
{
return MODEACTION_DENY;
{
}
+void ModeHandler::OnParameterMissing(User* user, User* dest, Channel* channel)
+{
+}
+
bool ModeHandler::CheckTimeStamp(time_t theirs, time_t ours, const std::string&, const std::string&, Channel*)
{
return (ours < theirs);
ModeAction SimpleUserModeHandler::OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding, bool servermode)
{
- /* Only opers can change other users modes */
- if (source != dest)
- return MODEACTION_DENY;
-
if (adding)
{
if (!dest->IsModeSet(this->GetModeChar()))
return;
}
- if ((targetuser == user) || (IS_OPER(user)))
+ if (targetuser == user || user->HasPrivPermission("users/auspex"))
{
/* Display user's current mode string */
user->WriteNumeric(RPL_UMODEIS, "%s :+%s",targetuser->nick.c_str(),targetuser->FormatModes());
User* targetuser = ServerInstance->FindNick(parameters[0]);
LastParse.clear();
+ LastParseParams.clear();
+ LastParseTranslate.clear();
/* Special case for displaying the list for listmodes,
* e.g. MODE #chan b, or MODE #chan +b without a parameter
seq++;
mask = MASK_CHANNEL;
-
+
while (mode && *mode)
{
unsigned char mletter = *mode;
mode++;
continue;
}
-
+
/* Ensure the user doesnt request the same mode twice,
* so they cant flood themselves off out of idiocy.
*/
continue;
}
- if (!IS_OPER(user))
+ if (!user->HasPrivPermission("channels/auspex"))
{
if (ServerInstance->Config->HideModeLists[mletter] && (targetchannel->GetStatus(user) < STATUS_HOP))
{
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 ((IS_LOCAL(user)) && (!ServerInstance->ULine(user->server)) && (!servermode))
{
+ /* Make modes that are being changed visible to OnAccessCheck */
+ LastParse = parameters[1];
/* We don't have halfop */
int MOD_RESULT = 0;
FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user, NULL, targetchannel, AC_GENERAL_MODE));
+ LastParse.clear();
if (MOD_RESULT == ACR_DENY)
return;
SkipAccessChecks = (MOD_RESULT == ACR_ALLOW);
{
type = MODETYPE_USER;
mask = MASK_USER;
- if ((user != targetuser) && (!ServerInstance->ULine(user->server)))
+ if (user != targetuser && IS_LOCAL(user) && !ServerInstance->ULine(user->server))
{
user->WriteNumeric(ERR_USERSDONTMATCH, "%s :Can't change mode for other users", user->nick.c_str());
return;
unsigned int parameter_counter = 2; /* Index of first parameter */
unsigned int parameter_count = 0;
bool last_successful_state_change = false;
+ LastParseTranslate.push_back(TR_TEXT);
/* A mode sequence that doesnt start with + or -. Assume +. - Thanks for the suggestion spike (bug#132) */
if ((*mode_sequence.begin() != '+') && (*mode_sequence.begin() != '-'))
else
{
/* No parameter, continue to the next mode */
+ modehandlers[handler_id]->OnParameterMissing(user, targetuser, targetchannel);
continue;
}
/* If the mode defined by the handler is not '\0', but the handler for it
* cannot be found, they probably dont have the right module loaded to implement
* the prefix they want to compare the mode against, e.g. '&' for m_chanprotect.
- * Revert to checking against the minimum core prefix, '%'.
+ * Revert to checking against the minimum core prefix, '%' or '@'.
*/
if (needed && !prefixmode)
- prefixmode = FindPrefix('%');
-
+ prefixmode = ServerInstance->Config->AllowHalfop ? FindPrefix('%') : FindPrefix('@');
+
unsigned int neededrank = prefixmode->GetPrefixRank();
/* Compare our rank on the channel against the rank of the required prefix,
* allow if >= ours. Because mIRC and xchat throw a tizz if the modes shown
}
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, servermode) == false)
output_sequence.append(adding ? "+" : "-");
last_successful_state_change = adding;
}
-
+
/* Add the mode letter */
output_sequence.push_back(modechar);
if ((modehandlers[handler_id]->GetNumParams(adding)) && (!parameter.empty()))
{
parameter_list << " " << parameter;
+ LastParseParams.push_back(parameter);
+ LastParseTranslate.push_back(modehandlers[handler_id]->GetTranslateType());
parameter_count++;
/* Does this mode have a prefix? */
if (modehandlers[handler_id]->GetPrefix() && targetchannel)
/* Was there at least one valid mode in the sequence? */
if (!output_sequence.empty())
{
- if (servermode)
+ LastParseParams.push_front(output_sequence);
+ if (!user)
{
if (type == MODETYPE_CHANNEL)
{
if (type == MODETYPE_CHANNEL)
{
targetchannel->WriteChannel(user, "MODE %s %s%s", targetchannel->name.c_str(), output_sequence.c_str(), parameter_list.str().c_str());
- FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, output_sequence + parameter_list.str()));
+ FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, LastParseParams, LastParseTranslate));
this->LastParse = targetchannel->name;
}
else
{
user->WriteTo(targetuser, "MODE %s %s%s", targetuser->nick.c_str(), output_sequence.c_str(), parameter_list.str().c_str());
- FOREACH_MOD(I_OnMode,OnMode(user, targetuser, TYPE_USER, output_sequence + parameter_list.str()));
+ FOREACH_MOD(I_OnMode,OnMode(user, targetuser, TYPE_USER, LastParseParams, LastParseTranslate));
this->LastParse = targetuser->nick;
}
}
for (unsigned char mode = 'A'; mode <= 'z'; mode++)
{
- if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
- continue;
-
unsigned char pos = (mode-65) | MASK_CHANNEL;
if (modehandlers[pos])
for (unsigned char mode = 'A'; mode <= 'z'; mode++)
{
- if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
- continue;
-
unsigned char pos = (mode-65) | MASK_CHANNEL;
if ((modehandlers[pos]) && (modehandlers[pos]->GetNumParams(true)))
return types;
}
-std::string ModeParser::ChanModes()
+std::string ModeParser::GiveModeList(ModeMasks m)
{
std::string type1; /* Listmodes EXCEPT those with a prefix */
std::string type2; /* Modes that take a param when adding or removing */
for (unsigned char mode = 'A'; mode <= 'z'; mode++)
{
- if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
- continue;
-
- unsigned char pos = (mode-65) | MASK_CHANNEL;
+ unsigned char pos = (mode-65) | m;
/* One parameter when adding */
if (modehandlers[pos])
- {
+ {
if (modehandlers[pos]->GetNumParams(true))
{
if ((modehandlers[pos]->IsListMode()) && (!modehandlers[pos]->GetPrefix()))
type4 += modehandlers[pos]->GetModeChar();
}
}
-
}
return type1 + "," + type2 + "," + type3 + "," + type4;
}
bool ModeParser::PrefixComparison(prefixtype one, prefixtype two)
-{
+{
return one.second > two.second;
}
for (unsigned char mode = 'A'; mode <= 'z'; mode++)
{
- if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
- continue;
-
unsigned char pos = (mode-65) | MASK_CHANNEL;
if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix()))
sprintf(moderemove,"-%c",this->GetModeChar());
parameters.push_back(user->nick);
parameters.push_back(moderemove);
- ServerInstance->Parser->CallHandler("MODE", parameters, user);
+ ServerInstance->Modes->Process(parameters, ServerInstance->FakeClient, true);
}
}
}
new ModeChannelOp(Instance),
new ModeChannelHalfOp(Instance),
new ModeChannelVoice(Instance),
- new ModeUserServerNotice(Instance),
new ModeUserWallops(Instance),
new ModeUserInvisible(Instance),
new ModeUserOperator(Instance),