* +------------------------------------+
*
* InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
- * E-mail:
+ * E-mail:
* <brain@chatspike.net>
* <Craig@chatspike.net>
*
#include "inspircd_config.h"
#include "inspircd.h"
-#include "inspircd_io.h"
+#include "configreader.h"
#include <unistd.h>
#include <sys/errno.h>
#include <time.h>
extern time_t TIME;
+ModeHandler::ModeHandler(char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly) : mode(modeletter), n_params_on(parameters_on), n_params_off(parameters_off), list(listmode), m_type(type), oper(operonly)
+{
+}
+
+ModeHandler::~ModeHandler()
+{
+}
+
+bool ModeHandler::IsListMode()
+{
+ return list;
+}
+
+ModeType ModeHandler::GetModeType()
+{
+ return m_type;
+}
+
+bool ModeHandler::NeedsOper()
+{
+ return oper;
+}
+
+int ModeHandler::GetNumParams(bool adding)
+{
+ return adding ? n_params_on : n_params_off;
+}
+
+char ModeHandler::GetModeChar()
+{
+ return mode;
+}
+
+ModeAction ModeHandler::OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string ¶meter, bool adding)
+{
+ return MODEACTION_DENY;
+}
+
+void ModeHandler::DisplayList(userrec* user, chanrec* channel)
+{
+}
+
+bool ModeHandler::CheckTimeStamp(time_t theirs, time_t ours, const std::string &their_param, const std::string &our_param, chanrec* channel)
+{
+ return (ours < theirs);
+}
+
+ModeWatcher::ModeWatcher(char modeletter, ModeType type) : mode(modeletter), m_type(type)
+{
+}
+
+ModeWatcher::~ModeWatcher()
+{
+}
+
+char ModeWatcher::GetModeChar()
+{
+ return mode;
+}
+
+ModeType ModeWatcher::GetModeType()
+{
+ return m_type;
+}
+
+bool ModeWatcher::BeforeMode(userrec* source, userrec* dest, chanrec* channel, std::string ¶meter, bool adding, ModeType type)
+{
+ return true;
+}
+
+void ModeWatcher::AfterMode(userrec* source, userrec* dest, chanrec* channel, const std::string ¶meter, bool adding, ModeType type)
+{
+}
+
userrec* ModeParser::SanityChecks(userrec *user,char *dest,chanrec *chan,int status)
{
userrec *d;
char* ModeParser::Grant(userrec *d,chanrec *chan,int MASK)
{
- for (unsigned int i = 0; i < d->chans.size(); i++)
+ if (!chan)
+ return NULL;
+
+ for (std::vector<ucrec*>::const_iterator i = d->chans.begin(); i != d->chans.end(); i++)
{
- if ((d->chans[i].channel != NULL) && (chan != NULL))
- if (d->chans[i].channel == chan)
+ if (((ucrec*)(*i))->channel == chan)
{
- if (d->chans[i].uc_modes & MASK)
+ if (((ucrec*)(*i))->uc_modes & MASK)
{
return NULL;
}
- d->chans[i].uc_modes = d->chans[i].uc_modes | MASK;
+ ((ucrec*)(*i))->uc_modes = ((ucrec*)(*i))->uc_modes | MASK;
switch (MASK)
{
case UCMODE_OP:
- d->chans[i].channel->AddOppedUser((char*)d);
+ ((ucrec*)(*i))->channel->AddOppedUser(d);
break;
case UCMODE_HOP:
- d->chans[i].channel->AddHalfoppedUser((char*)d);
+ ((ucrec*)(*i))->channel->AddHalfoppedUser(d);
break;
case UCMODE_VOICE:
- d->chans[i].channel->AddVoicedUser((char*)d);
+ ((ucrec*)(*i))->channel->AddVoicedUser(d);
break;
}
- log(DEBUG,"grant: %s %s",d->chans[i].channel->name,d->nick);
+ log(DEBUG,"grant: %s %s",((ucrec*)(*i))->channel->name,d->nick);
return d->nick;
}
}
char* ModeParser::Revoke(userrec *d,chanrec *chan,int MASK)
{
- for (unsigned int i = 0; i < d->chans.size(); i++)
+ if (!chan)
+ return NULL;
+
+ for (std::vector<ucrec*>::const_iterator i = d->chans.begin(); i != d->chans.end(); i++)
{
- if ((d->chans[i].channel != NULL) && (chan != NULL))
- if (d->chans[i].channel == chan)
+ if (((ucrec*)(*i))->channel == chan)
{
- if ((d->chans[i].uc_modes & MASK) == 0)
+ if ((((ucrec*)(*i))->uc_modes & MASK) == 0)
{
return NULL;
}
- d->chans[i].uc_modes ^= MASK;
+ ((ucrec*)(*i))->uc_modes ^= MASK;
switch (MASK)
{
case UCMODE_OP:
- d->chans[i].channel->DelOppedUser((char*)d);
+ ((ucrec*)(*i))->channel->DelOppedUser(d);
break;
case UCMODE_HOP:
- d->chans[i].channel->DelHalfoppedUser((char*)d);
+ ((ucrec*)(*i))->channel->DelHalfoppedUser(d);
break;
case UCMODE_VOICE:
- d->chans[i].channel->DelVoicedUser((char*)d);
+ ((ucrec*)(*i))->channel->DelVoicedUser(d);
break;
}
- log(DEBUG,"revoke: %s %s",d->chans[i].channel->name,d->nick);
+ log(DEBUG,"revoke: %s %s",((ucrec*)(*i))->channel->name,d->nick);
return d->nick;
}
}
{
if (!strcasecmp(i->data,dest))
{
- int MOD_RESULT = 0;
- FOREACH_RESULT(I_OnDelBan,OnDelBan(user,chan,dest));
- if (MOD_RESULT)
- return NULL;
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnDelBan,OnDelBan(user,chan,dest));
+ if (MOD_RESULT)
+ return NULL;
chan->bans.erase(i);
return dest;
}
return NULL;
}
-// tidies up redundant modes, e.g. +nt-nt+i becomes +-+i,
-// a section further down the chain tidies up the +-+- crap.
-std::string ModeParser::CompressModes(std::string modes,bool channelmodes)
+void ModeParser::Process(char **parameters, int pcnt, userrec *user, bool servermode)
{
- int counts[127];
- bool active[127];
- memset(counts,0,sizeof(counts));
- memset(active,0,sizeof(active));
- for (unsigned int i = 0; i < modes.length(); i++)
+ std::string target = parameters[0];
+ ModeType type = MODETYPE_USER;
+ chanrec* targetchannel = FindChan(parameters[0]);
+ userrec* targetuser = Find(parameters[0]);
+
+ if (pcnt > 1)
{
- if ((modes[i] == '+') || (modes[i] == '-'))
- continue;
- if (channelmodes)
+ if (targetchannel)
{
- if ((strchr("itnmsp",modes[i])) || ((ModeDefined(modes[i],MT_CHANNEL)) && (ModeDefinedOn(modes[i],MT_CHANNEL)==0) && (ModeDefinedOff(modes[i],MT_CHANNEL)==0)))
- {
- log(DEBUG,"Tidy mode %c",modes[i]);
- counts[(unsigned int)modes[i]]++;
- active[(unsigned int)modes[i]] = true;
- }
+ type = MODETYPE_CHANNEL;
+ }
+ else if (targetuser)
+ {
+ type = MODETYPE_USER;
}
else
{
- log(DEBUG,"Tidy mode %c",modes[i]);
- counts[(unsigned int)modes[i]]++;
- active[(unsigned int)modes[i]] = true;
+ /* No such nick/channel */
+ return;
}
- }
- for (int j = 65; j < 127; j++)
- {
- if ((counts[j] > 1) && (active[j] == true))
+ std::string mode_sequence = parameters[1];
+ std::string parameter = "";
+ std::ostringstream parameter_list;
+ std::string output_sequence = "";
+ bool adding = true, state_change = false;
+ int handler_id = 0;
+ int parameter_counter = 2; /* Index of first parameter */
+
+ for (std::string::const_iterator modeletter = mode_sequence.begin(); modeletter != mode_sequence.end(); modeletter++)
{
- static char v[2];
- v[0] = (unsigned char)j;
- v[1] = '\0';
- std::string mode_str = v;
- std::string::size_type pos = modes.find(mode_str);
- if (pos != std::string::npos)
+ switch (*modeletter)
{
- log(DEBUG,"all occurances of mode %c to be deleted...",(unsigned char)j);
- while (modes.find(mode_str) != std::string::npos)
- modes.erase(modes.find(mode_str),1);
- log(DEBUG,"New mode line: %s",modes.c_str());
+ /* NB:
+ * For + and - mode characters, we don't just stick the character into the output sequence.
+ * This is because the user may do something dumb, like: +-+ooo or +oo-+. To prevent this
+ * appearing in the output sequence, we store a flag which says there was a state change,
+ * which is set on any + or -, however, the + or - that we finish on is only appended to
+ * the output stream in the event it is followed by a non "+ or -" character, such as o or v.
+ */
+ case '+':
+ /* The following expression prevents: +o+o nick nick, compressing it to +oo nick nick,
+ * however, will allow the + if it is the first item in the sequence, regardless.
+ */
+ if ((!adding) || (!output_sequence.length()))
+ state_change = true;
+ adding = true;
+ continue;
+ break;
+ case '-':
+ if ((adding) || (!output_sequence.length()))
+ state_change = true;
+ adding = false;
+ continue;
+ break;
+ default:
+
+ /* 65 is the ascii value of 'A' */
+ handler_id = *modeletter - 65;
+
+ if (modehandlers[handler_id])
+ {
+ 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]->GetNumParams(adding))
+ {
+ if (pcnt < parameter_counter)
+ {
+ parameter = parameters[parameter_counter++];
+ }
+ else
+ {
+ parameter = "";
+ }
+ }
+ ModeAction ma = modehandlers[handler_id]->OnModeChange(user, targetuser, targetchannel, parameter, adding);
+ if (ma == MODEACTION_ALLOW)
+ {
+ /* We're about to output a valid mode letter - was there previously a pending state-change? */
+ if (state_change)
+ output_sequence.append(adding ? "+" : "-");
+
+ /* Add the mode letter */
+ output_sequence = output_sequence + *modeletter;
+
+ /* Is there a valid parameter for this mode? If so add it to the parameter list */
+ if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter != ""))
+ {
+ parameter_list << " " << parameter;
+ }
+
+ /* Call all the AfterMode events in the mode watchers for this mode */
+ for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
+ {
+ (*watchers)->AfterMode(user, targetuser, targetchannel, parameter, adding, type);
+ }
+
+ /* Reset the state change flag */
+ state_change = false;
+ }
+ }
+ }
+ break;
+ }
+ }
+ /* Was there at least one valid mode in the sequence? */
+ if (output_sequence != "")
+ {
+ if (servermode)
+ {
+ if (type == MODETYPE_CHANNEL)
+ {
+ WriteChannelWithServ(Config->ServerName,targetchannel,"MODE %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str());
+ }
+ }
+ else
+ {
+ if (type == MODETYPE_CHANNEL)
+ {
+ WriteChannel(targetchannel,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()));
+ }
}
}
}
- return modes;
+}
+
+std::string ModeParser::CompressModes(std::string modes,bool channelmodes)
+{
+ return "";
}
void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int status, int pcnt, bool servermode, bool silent, bool local)
}
char outlist[MAXBUF];
+ char mlist[MAXBUF];
char *outpars[32];
int param = 2;
int pc = 0;
return;
}
- char* modelist = parameters[1]; /* mode list, e.g. +oo-o *
- * parameters[2] onwards are parameters for
- * modes that require them :) */
+ std::string tidied = this->CompressModes(parameters[1],true);
+ strlcpy(mlist,tidied.c_str(),MAXBUF);
+ char* modelist = mlist;
+
*outlist = *modelist;
char* outl = outlist+1;
log(DEBUG,"process_modes: modelist: %s",modelist);
- std::string tidied = this->CompressModes(modelist,true);
- strlcpy(modelist,tidied.c_str(),MAXBUF);
-
int len = tidied.length();
while (modelist[len-1] == ' ')
modelist[--len] = '\0';
}
else
{
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'o', parameters[param], false, 1));
- if (!MOD_RESULT)
- {
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'o', parameters[param], false, 1));
+ if (!MOD_RESULT)
+ {
r = TakeOps(user,parameters[param++],chan,status);
}
else param++;
r = NULL;
if (mdir == 1)
{
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'h', parameters[param], true, 1));
- if (!MOD_RESULT)
- {
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'h', parameters[param], true, 1));
+ if (!MOD_RESULT)
+ {
r = GiveHops(user,parameters[param++],chan,status);
}
else param++;
}
else
{
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'h', parameters[param], false, 1));
- if (!MOD_RESULT)
- {
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'h', parameters[param], false, 1));
+ if (!MOD_RESULT)
+ {
r = TakeHops(user,parameters[param++],chan,status);
}
else param++;
r = NULL;
if (mdir == 1)
{
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'v', parameters[param], true, 1));
- if (!MOD_RESULT)
- {
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'v', parameters[param], true, 1));
+ if (!MOD_RESULT)
+ {
r = GiveVoice(user,parameters[param++],chan,status);
}
else param++;
}
else
{
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'v', parameters[param], false, 1));
- if (!MOD_RESULT)
- {
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'v', parameters[param], false, 1));
+ if (!MOD_RESULT)
+ {
r = TakeVoice(user,parameters[param++],chan,status);
}
else param++;
r = NULL;
if (mdir == 1)
{
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'b', parameters[param], true, 1));
- if (!MOD_RESULT)
- {
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'b', parameters[param], true, 1));
+ if (!MOD_RESULT)
+ {
r = AddBan(user,parameters[param++],chan,status);
}
else param++;
}
else
{
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'b', parameters[param], false, 1));
- if (!MOD_RESULT)
- {
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'b', parameters[param], false, 1));
+ if (!MOD_RESULT)
+ {
r = TakeBan(user,parameters[param++],chan,status);
}
else param++;
break;
previously_set_k = true;
- if (!*chan->key)
+ if (!chan->modes[CM_KEY])
{
MOD_RESULT = 0;
FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'k', parameters[param], true, 1));
strlcpy(key,parameters[param++],32);
outpars[pc++] = key;
strlcpy(chan->key,key,MAXBUF);
+ chan->modes[CM_KEY] = 1;
k_set = true;
}
else param++;
{
*outl++ = 'k';
*chan->key = 0;
+ chan->modes[CM_KEY] = 0;
outpars[pc++] = key;
}
}
if (previously_set_l)
break;
previously_unset_l = true;
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'l', "", false, 0));
- if (!MOD_RESULT)
- {
- if (chan->limit)
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'l', "", false, 0));
+ if (!MOD_RESULT)
+ {
+ if (chan->modes[CM_LIMIT])
{
*outl++ = 'l';
chan->limit = 0;
+ chan->modes[CM_LIMIT] = 0;
}
}
}
if (invalid)
break;
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'l', parameters[param], true, 1));
- if (!MOD_RESULT)
- {
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'l', parameters[param], true, 1));
+ if (!MOD_RESULT)
+ {
chan->limit = atoi(parameters[param]);
if (chan->limit)
{
*outl++ = 'l';
+ chan->modes[CM_LIMIT] = 1;
outpars[pc++] = parameters[param++];
l_set = true;
}
break;
case 'i':
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'i', "", mdir, 0));
- if (!MOD_RESULT)
- {
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'i', "", mdir, 0));
+ if (!MOD_RESULT)
+ {
if (mdir)
{
- if (!(chan->binarymodes & CM_INVITEONLY)) *outl++ = 'i';
- chan->binarymodes |= CM_INVITEONLY;
+ if (!(chan->modes[CM_INVITEONLY])) *outl++ = 'i';
+ chan->modes[CM_INVITEONLY] = 1;
}
else
{
- if (chan->binarymodes & CM_INVITEONLY) *outl++ = 'i';
- chan->binarymodes &= ~CM_INVITEONLY;
+ if (chan->modes[CM_INVITEONLY]) *outl++ = 'i';
+ chan->modes[CM_INVITEONLY] = 0;
}
}
break;
case 't':
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 't', "", mdir, 0));
- if (!MOD_RESULT)
- {
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 't', "", mdir, 0));
+ if (!MOD_RESULT)
+ {
if (mdir)
- {
- if (!(chan->binarymodes & CM_TOPICLOCK)) *outl++ = 't';
- chan->binarymodes |= CM_TOPICLOCK;
- }
- else
- {
- if (chan->binarymodes & CM_TOPICLOCK) *outl++ = 't';
- chan->binarymodes &= ~CM_TOPICLOCK;
- }
+ {
+ if (!(chan->modes[CM_TOPICLOCK])) *outl++ = 't';
+ chan->modes[CM_TOPICLOCK] = 1;
+ }
+ else
+ {
+ if (chan->modes[CM_TOPICLOCK]) *outl++ = 't';
+ chan->modes[CM_TOPICLOCK] = 0;
+ }
}
break;
case 'n':
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'n', "", mdir, 0));
- if (!MOD_RESULT)
- {
- if (mdir)
- {
- if (!(chan->binarymodes & CM_NOEXTERNAL)) *outl++ = 'n';
- chan->binarymodes |= CM_NOEXTERNAL;
- }
- else
- {
- if (chan->binarymodes & CM_NOEXTERNAL) *outl++ = 'n';
- chan->binarymodes &= ~CM_NOEXTERNAL;
- }
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'n', "", mdir, 0));
+ if (!MOD_RESULT)
+ {
+ if (mdir)
+ {
+ if (!(chan->modes[CM_NOEXTERNAL])) *outl++ = 'n';
+ chan->modes[CM_NOEXTERNAL] = 1;
+ }
+ else
+ {
+ if (chan->modes[CM_NOEXTERNAL]) *outl++ = 'n';
+ chan->modes[CM_NOEXTERNAL] = 0;
+ }
}
break;
case 'm':
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'm', "", mdir, 0));
- if (!MOD_RESULT)
- {
- if (mdir)
- {
- if (!(chan->binarymodes & CM_MODERATED)) *outl++ = 'm';
- chan->binarymodes |= CM_MODERATED;
- }
- else
- {
- if (chan->binarymodes & CM_MODERATED) *outl++ = 'm';
- chan->binarymodes &= ~CM_MODERATED;
- }
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'm', "", mdir, 0));
+ if (!MOD_RESULT)
+ {
+ if (mdir)
+ {
+ if (!(chan->modes[CM_MODERATED])) *outl++ = 'm';
+ chan->modes[CM_MODERATED] = 1;
+ }
+ else
+ {
+ if (chan->modes[CM_MODERATED]) *outl++ = 'm';
+ chan->modes[CM_MODERATED] = 0;
+ }
}
break;
case 's':
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 's', "", mdir, 0));
- if (!MOD_RESULT)
- {
- if (mdir)
- {
- if (!(chan->binarymodes & CM_SECRET)) *outl++ = 's';
- chan->binarymodes |= CM_SECRET;
- if (chan->binarymodes & CM_PRIVATE)
- {
- chan->binarymodes &= ~CM_PRIVATE;
- if (mdir)
- {
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 's', "", mdir, 0));
+ if (!MOD_RESULT)
+ {
+ if (mdir)
+ {
+ if (!(chan->modes[CM_SECRET])) *outl++ = 's';
+ chan->modes[CM_SECRET] = 1;
+ if (chan->modes[CM_PRIVATE])
+ {
+ chan->modes[CM_PRIVATE] = 0;
+ if (mdir)
+ {
*outl++ = '-'; *outl++ = 'p'; *outl++ = '+';
- }
- }
- }
- else
- {
- if (chan->binarymodes & CM_SECRET) *outl++ = 's';
- chan->binarymodes &= ~CM_SECRET;
- }
+ }
+ }
+ }
+ else
+ {
+ if (chan->modes[CM_SECRET]) *outl++ = 's';
+ chan->modes[CM_SECRET] = 0;
+ }
}
break;
case 'p':
- MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'p', "", mdir, 0));
- if (!MOD_RESULT)
- {
- if (mdir)
- {
- if (!(chan->binarymodes & CM_PRIVATE)) *outl++ = 'p';
- chan->binarymodes |= CM_PRIVATE;
- if (chan->binarymodes & CM_SECRET)
- {
- chan->binarymodes &= ~CM_SECRET;
- if (mdir)
- {
- *outl++ = '-'; *outl++ = 's'; *outl++ = '+';
- }
- }
- }
- else
- {
- if (chan->binarymodes & CM_PRIVATE) *outl++ = 'p';
- chan->binarymodes &= ~CM_PRIVATE;
- }
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, 'p', "", mdir, 0));
+ if(!MOD_RESULT)
+ {
+ if(mdir)
+ {
+ if(!(chan->modes[CM_PRIVATE]))
+ *outl++ = 'p';
+
+ chan->modes[CM_PRIVATE] = 1;
+
+ if(chan->modes[CM_SECRET])
+ {
+ chan->modes[CM_SECRET] = 0;
+
+ *outl++ = '-';
+ *outl++ = 's';
+ *outl++ = '+';
+ }
+ }
+ else
+ {
+ if(chan->modes[CM_PRIVATE])
+ *outl++ = 'p';
+
+ chan->modes[CM_PRIVATE] = 0;
+ }
}
- break;
+ break;
default:
string_list p;
p.clear();
- bool x = strchr(chan->custom_modes,*modechar);
+ bool x = chan->modes[*modechar-65];
if ((!x && !mdir) || (x && mdir))
{
if (!ModeIsListMode(*modechar,MT_CHANNEL))
/* A module has claimed this mode */
if (param<pcnt)
{
- if ((ModeDefinedOn(*modechar,MT_CHANNEL)>0) && (mdir))
+ if ((ModeDefinedOn(*modechar,MT_CHANNEL)>0) && (mdir))
{
p.push_back(parameters[param]);
}
// Using OnRawMode on another modules mode's behavour
// will confuse the crap out of admins! just because you CAN
// do it, doesnt mean you SHOULD!
- MOD_RESULT = 0;
+ MOD_RESULT = 0;
std::string para = "";
if (p.size())
para = p[0];
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, *modechar, para, mdir, pcnt));
- if (!MOD_RESULT)
- {
- for (int i = 0; i <= MODCOUNT; i++)
+
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, *modechar, para, mdir, pcnt));
+ if(!MOD_RESULT)
+ {
+ for (int i = 0; i <= MODCOUNT; i++)
{
if (!handled)
{
{
if (param < pcnt)
{
- chan->SetCustomModeParam(modelist[ptr],parameters[param],mdir);
+ chan->SetCustomModeParam(*modechar,parameters[param],mdir);
outpars[pc++] = parameters[param++];
}
}
void cmd_mode::Handle (char **parameters, int pcnt, userrec *user)
{
- chanrec* Ptr;
+ chanrec* chan;
userrec* dest = Find(parameters[0]);
+ int MOD_RESULT;
int can_change;
int direction = 1;
char outpars[MAXBUF];
{
charlcat(dmodes,*i,53);
charlcat(outpars,*i,MAXMODES);
- if (*i == 'o')
+ switch (*i)
{
- FOREACH_MOD(I_OnGlobalOper,OnGlobalOper(dest));
+ case 'o':
+ FOREACH_MOD(I_OnGlobalOper,OnGlobalOper(dest));
+ break;
+ case 'i':
+ dest->modebits |= UM_INVISIBLE;
+ break;
+ case 's':
+ dest->modebits |= UM_SERVERNOTICE;
+ break;
+ case 'w':
+ dest->modebits |= UM_WALLOPS;
+ break;
+ default:
+ break;
}
}
}
{
charlcat(outpars,*i,MAXMODES);
charremove(dmodes,*i);
- if (*i == 'o')
+ switch (*i)
{
- *dest->oper = 0;
- DeleteOper(dest);
+ case 'o':
+ *dest->oper = 0;
+ DeleteOper(dest);
+ break;
+ case 'i':
+ dest->modebits &= ~UM_INVISIBLE;
+ break;
+ case 's':
+ dest->modebits &= ~UM_SERVERNOTICE;
+ break;
+ case 'w':
+ dest->modebits &= ~UM_WALLOPS;
+ break;
+ default:
+ break;
}
}
}
}
else
{
- Ptr = FindChan(parameters[0]);
- if (Ptr)
+ chan = FindChan(parameters[0]);
+ if(chan)
{
if (pcnt == 1)
{
/* just /modes #channel */
- WriteServ(user->fd,"324 %s %s +%s",user->nick, Ptr->name, chanmodes(Ptr,has_channel(user,Ptr)));
- WriteServ(user->fd,"329 %s %s %d", user->nick, Ptr->name, Ptr->created);
+ WriteServ(user->fd,"324 %s %s +%s",user->nick, chan->name, chanmodes(chan, chan->HasUser(user)));
+ WriteServ(user->fd,"329 %s %s %d", user->nick, chan->name, chan->created);
return;
}
else if (pcnt == 2)
{
char* mode = parameters[1];
+
+ MOD_RESULT = 0;
+
if (*mode == '+')
mode++;
- int MOD_RESULT = 0;
- FOREACH_RESULT(I_OnRawMode,OnRawMode(user, Ptr, *mode, "", false, 0));
- if (!MOD_RESULT)
- {
+
+ FOREACH_RESULT(I_OnRawMode,OnRawMode(user, chan, *mode, "", false, 0));
+ if(!MOD_RESULT)
+ {
if (*mode == 'b')
{
- for (BanList::iterator i = Ptr->bans.begin(); i != Ptr->bans.end(); i++)
+ for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++)
{
- WriteServ(user->fd,"367 %s %s %s %s %d",user->nick, Ptr->name, i->data, i->set_by, i->set_time);
+ WriteServ(user->fd,"367 %s %s %s %s %d",user->nick, chan->name, i->data, i->set_by, i->set_time);
}
- WriteServ(user->fd,"368 %s %s :End of channel ban list",user->nick, Ptr->name);
+ WriteServ(user->fd,"368 %s %s :End of channel ban list",user->nick, chan->name);
return;
}
+
if ((ModeDefined(*mode,MT_CHANNEL)) && (ModeIsListMode(*mode,MT_CHANNEL)))
{
// list of items for an extmode
log(DEBUG,"Calling OnSendList for all modules, list output for mode %c",*mode);
- FOREACH_MOD(I_OnSendList,OnSendList(user,Ptr,*mode));
+ FOREACH_MOD(I_OnSendList,OnSendList(user,chan,*mode));
return;
}
}
}
- if (((Ptr) && (!has_channel(user,Ptr))) && (!is_uline(user->server)) && (IS_LOCAL(user)))
- {
- WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, Ptr->name);
- return;
- }
-
- if (Ptr)
+ if ((IS_LOCAL(user)) && (!is_uline(user->server)) && (!chan->HasUser(user)))
{
- int MOD_RESULT = 0;
- FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user,NULL,Ptr,AC_GENERAL_MODE));
+ WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, chan->name);
+ return;
+ }
+
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user, NULL, chan, AC_GENERAL_MODE));
- if (MOD_RESULT == ACR_DENY)
- return;
- if (MOD_RESULT == ACR_DEFAULT)
+ if(MOD_RESULT == ACR_DENY)
+ return;
+
+ if(MOD_RESULT == ACR_DEFAULT)
+ {
+ if ((IS_LOCAL(user)) && (cstatus(user,chan) < STATUS_HOP))
{
- if ((cstatus(user,Ptr) < STATUS_HOP) && (IS_LOCAL(user)))
- {
- WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, Ptr->name);
- return;
- }
+ WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, chan->name);
+ return;
}
-
- ServerInstance->ModeGrok->ProcessModes(parameters,user,Ptr,cstatus(user,Ptr),pcnt,false,false,false);
}
+
+ ServerInstance->ModeGrok->ProcessModes(parameters,user,chan,cstatus(user,chan),pcnt,false,false,false);
}
else
{
if ((dest) && (pcnt > 1))
{
- std::string tidied = ServerInstance->ModeGrok->CompressModes(parameters[1],false);
- parameters[1] = (char*)tidied.c_str();
+ std::string tidied = ServerInstance->ModeGrok->CompressModes(parameters[1],false);
+ parameters[1] = (char*)tidied.c_str();
char dmodes[MAXBUF];
strlcpy(dmodes,dest->modes,MAXBUF);
switch (*i)
{
- case ' ':
- continue;
+ case ' ':
+ continue;
case '+':
if ((direction != 1) && (next_ok))
{
charlcat(dmodes,*i,MAXBUF);
charlcat(outpars,*i,53);
+ switch (*i)
+ {
+ case 'i':
+ dest->modebits |= UM_INVISIBLE;
+ break;
+ case 's':
+ dest->modebits |= UM_SERVERNOTICE;
+ break;
+ case 'w':
+ dest->modebits |= UM_WALLOPS;
+ break;
+ default:
+ break;
+ }
}
}
}
{
charlcat(outpars,*i,MAXBUF);
charremove(dmodes,*i);
+ switch (*i)
+ {
+ case 'i':
+ dest->modebits &= ~UM_INVISIBLE;
+ break;
+ case 's':
+ dest->modebits &= ~UM_SERVERNOTICE;
+ break;
+ case 'w':
+ dest->modebits &= ~UM_WALLOPS;
+ break;
+ default:
+ break;
+ }
}
}
}
break;
}
}
- if (*outpars)
- {
- char b[MAXBUF];
- char* z = b;
-
- for (char* i = outpars; *i;)
- {
- *z++ = *i++;
- if (((*i == '-') || (*i == '+')) && ((*(i+1) == '-') || (*(i+1) == '+')))
- {
- // someones playing silly buggers and trying
- // to put a +- or -+ into the line...
- i++;
- }
- if (!*(i+1))
- {
- // Someone's trying to make the last character in
- // the line be a + or - symbol.
- if ((*i == '-') || (*i == '+'))
- {
- i++;
- }
- }
- }
- *z = 0;
-
- if ((*b) && (!IS_SINGLE(b,'+')) && (!IS_SINGLE(b,'-')))
- {
- WriteTo(user, dest, "MODE %s :%s", dest->nick, b);
- FOREACH_MOD(I_OnMode,OnMode(user, dest, TYPE_USER, b));
- }
-
- log(DEBUG,"Stripped mode line");
- log(DEBUG,"Line dest is now %s",dmodes);
- strlcpy(dest->modes,dmodes,MAXMODES-1);
-
- }
+ if (*outpars)
+ {
+ char b[MAXBUF];
+ char* z = b;
+
+ for (char* i = outpars; *i;)
+ {
+ *z++ = *i++;
+ if (((*i == '-') || (*i == '+')) && ((*(i+1) == '-') || (*(i+1) == '+')))
+ {
+ // someones playing silly buggers and trying
+ // to put a +- or -+ into the line...
+ i++;
+ }
+ if (!*(i+1))
+ {
+ // Someone's trying to make the last character in
+ // the line be a + or - symbol.
+ if ((*i == '-') || (*i == '+'))
+ {
+ i++;
+ }
+ }
+ }
+ *z = 0;
+
+ if ((*b) && (!IS_SINGLE(b,'+')) && (!IS_SINGLE(b,'-')))
+ {
+ WriteTo(user, dest, "MODE %s :%s", dest->nick, b);
+ FOREACH_MOD(I_OnMode,OnMode(user, dest, TYPE_USER, b));
+ }
+
+ log(DEBUG,"Stripped mode line");
+ log(DEBUG,"Line dest is now %s",dmodes);
+ strlcpy(dest->modes,dmodes,MAXMODES-1);
+
+ }
return;
}