summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/channels.h7
-rw-r--r--include/mode.h33
-rw-r--r--include/modes/cmode_h.h1
-rw-r--r--include/modes/cmode_o.h1
-rw-r--r--include/modes/cmode_v.h1
-rw-r--r--src/channels.cpp59
-rw-r--r--src/mode.cpp34
-rw-r--r--src/modes/cmode_h.cpp7
-rw-r--r--src/modes/cmode_o.cpp7
-rw-r--r--src/modes/cmode_v.cpp7
10 files changed, 131 insertions, 26 deletions
diff --git a/include/channels.h b/include/channels.h
index 8f3b8ba3d..5186822e1 100644
--- a/include/channels.h
+++ b/include/channels.h
@@ -144,6 +144,9 @@ class ucrec : public classbase
class InspIRCd;
+typedef std::pair<char, unsigned int> prefixtype;
+typedef std::vector<prefixtype> pfxcontainer;
+typedef std::map<userrec*, std::vector<prefixtype> > prefixlist;
/** Holds all relevent information for a channel.
* This class represents a channel, and contains its name, modes, time created, topic, topic set time,
@@ -161,6 +164,8 @@ class chanrec : public Extensible
*/
static chanrec* ForceChan(InspIRCd* Instance, chanrec* Ptr,ucrec *a,userrec* user, int created);
+ prefixlist prefixes;
+
public:
/** The channels name.
*/
@@ -468,6 +473,8 @@ class chanrec : public Extensible
*/
const char* GetStatusChar(userrec *user);
+ void SetPrefix(userrec* user, char prefix, unsigned int prefix_rank, bool adding);
+
/** Destructor for chanrec
*/
virtual ~chanrec() { /* stub */ }
diff --git a/include/mode.h b/include/mode.h
index f1ef388d3..10b21a6b7 100644
--- a/include/mode.h
+++ b/include/mode.h
@@ -34,7 +34,8 @@ class InspIRCd;
* Holds the values for different type of modes
* that can exist, USER or CHANNEL type.
*/
-enum ModeType {
+enum ModeType
+{
MODETYPE_USER = 0,
MODETYPE_CHANNEL = 1
};
@@ -42,7 +43,8 @@ enum ModeType {
/**
* Holds mode actions - modes can be allowed or denied.
*/
-enum ModeAction {
+enum ModeAction
+{
MODEACTION_DENY = 0, /* Drop the mode change, AND a parameter if its a parameterized mode */
MODEACTION_ALLOW = 1 /* Allow the mode */
};
@@ -52,11 +54,19 @@ enum ModeAction {
* array. Used in a simple two instruction hashing function
* "(modeletter - 65) OR mask"
*/
-enum ModeMasks {
+enum ModeMasks
+{
MASK_USER = 128, /* A user mode */
MASK_CHANNEL = 0 /* A channel mode */
};
+enum PrefixModeValue
+{
+ VOICE_VALUE = 10000,
+ HALFOP_VALUE = 20000,
+ OP_VALUE = 30000
+};
+
/**
* Used by ModeHandler::ModeSet() to return the state of a mode upon a channel or user.
* The pair contains an activity flag, true if the mode is set with the given parameter,
@@ -116,6 +126,10 @@ class ModeHandler : public Extensible
*/
bool oper;
+ /** Mode prefix, or 0
+ */
+ char prefix;
+
public:
/**
* The constructor for ModeHandler initalizes the mode handler.
@@ -128,17 +142,26 @@ class ModeHandler : public Extensible
* @param ModeType Set this to MODETYPE_USER for a usermode, or MODETYPE_CHANNEL for a channelmode.
* @param operonly Set this to true if only opers should be allowed to set or unset the mode.
*/
- ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly);
+ ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly, char mprefix = 0);
/**
* The default destructor does nothing
*/
virtual ~ModeHandler();
-
/**
* Returns true if the mode is a list mode
*/
bool IsListMode();
/**
+ * Mode prefix or 0
+ */
+ char GetPrefix();
+ /**
+ * Get the 'value' of this modes prefix.
+ * determines which to display when there are multiple.
+ * The mode with the highest value is ranked first.
+ */
+ virtual unsigned int GetPrefixRank();
+ /**
* Returns the modes type
*/
ModeType GetModeType();
diff --git a/include/modes/cmode_h.h b/include/modes/cmode_h.h
index cf61726da..277d89625 100644
--- a/include/modes/cmode_h.h
+++ b/include/modes/cmode_h.h
@@ -14,5 +14,6 @@ class ModeChannelHalfOp : public ModeHandler
std::string AddHalfOp(userrec *user,const char *dest,chanrec *chan,int status);
std::string DelHalfOp(userrec *user,const char *dest,chanrec *chan,int status);
ModePair ModeSet(userrec* source, userrec* dest, chanrec* channel, const std::string &parameter);
+ unsigned int GetPrefixRank();
};
diff --git a/include/modes/cmode_o.h b/include/modes/cmode_o.h
index a308f9903..3fe097ec3 100644
--- a/include/modes/cmode_o.h
+++ b/include/modes/cmode_o.h
@@ -14,5 +14,6 @@ class ModeChannelOp : public ModeHandler
std::string AddOp(userrec *user,const char *dest,chanrec *chan,int status);
std::string DelOp(userrec *user,const char *dest,chanrec *chan,int status);
ModePair ModeSet(userrec* source, userrec* dest, chanrec* channel, const std::string &parameter);
+ unsigned int GetPrefixRank();
};
diff --git a/include/modes/cmode_v.h b/include/modes/cmode_v.h
index 51846d11a..b7e9b800e 100644
--- a/include/modes/cmode_v.h
+++ b/include/modes/cmode_v.h
@@ -14,5 +14,6 @@ class ModeChannelVoice : public ModeHandler
std::string AddVoice(userrec *user,const char *dest,chanrec *chan,int status);
std::string DelVoice(userrec *user,const char *dest,chanrec *chan,int status);
ModePair ModeSet(userrec* source, userrec* dest, chanrec* channel, const std::string &parameter);
+ unsigned int GetPrefixRank();
};
diff --git a/src/channels.cpp b/src/channels.cpp
index a89b9b2c4..4d68af99c 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -430,6 +430,7 @@ chanrec* chanrec::ForceChan(InspIRCd* Instance, chanrec* Ptr,ucrec *a,userrec* u
/* first user in is given ops */
a->uc_modes = UCMODE_OP;
Ptr->AddOppedUser(user);
+ Ptr->SetPrefix(user, '@', OP_VALUE, true);
}
else
{
@@ -880,26 +881,26 @@ long chanrec::GetMaxBans()
const char* chanrec::GetStatusChar(userrec *user)
{
- for (std::vector<ucrec*>::const_iterator i = user->chans.begin(); i != user->chans.end(); i++)
+ static char px[2];
+ unsigned int mx = 0;
+
+ *px = 0;
+ *(px+1) = 0;
+
+ prefixlist::iterator n = prefixes.find(user);
+ if (n != prefixes.end())
{
- if ((*i)->channel == this)
+ for (std::vector<prefixtype>::iterator x = n->second.begin(); x != n->second.end(); x++)
{
- if (((*i)->uc_modes & UCMODE_OP) > 0)
- {
- return "@";
- }
- if (((*i)->uc_modes & UCMODE_HOP) > 0)
- {
- return "%";
- }
- if (((*i)->uc_modes & UCMODE_VOICE) > 0)
+ if (x->second > mx)
{
- return "+";
+ *px = x->first;
+ mx = x->second;
}
- return "";
}
}
- return "";
+
+ return px;
}
@@ -944,4 +945,34 @@ int chanrec::GetStatus(userrec *user)
return STATUS_NORMAL;
}
+void chanrec::SetPrefix(userrec* user, char prefix, unsigned int prefix_value, bool adding)
+{
+ prefixlist::iterator n = prefixes.find(user);
+ prefixtype pfx = std::make_pair(prefix,prefix_value);
+ if (adding)
+ {
+ if (n != prefixes.end())
+ {
+ if (std::find(n->second.begin(), n->second.end(), pfx) == n->second.end())
+ {
+ n->second.push_back(pfx);
+ }
+ }
+ else
+ {
+ pfxcontainer one;
+ one.push_back(pfx);
+ prefixes.insert(std::make_pair<userrec*,pfxcontainer>(user, one));
+ }
+ }
+ else
+ {
+ if (n != prefixes.end())
+ {
+ pfxcontainer::iterator x = std::find(n->second.begin(), n->second.end(), pfx);
+ if (x != n->second.end())
+ n->second.erase(x);
+ }
+ }
+}
diff --git a/src/mode.cpp b/src/mode.cpp
index f3cf54e6a..790720c6b 100644
--- a/src/mode.cpp
+++ b/src/mode.cpp
@@ -65,8 +65,8 @@ using namespace std;
/* +n (notice mask - our implementation of snomasks) */
#include "modes/umode_n.h"
-ModeHandler::ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly)
- : ServerInstance(Instance), mode(modeletter), n_params_on(parameters_on), n_params_off(parameters_off), list(listmode), m_type(type), oper(operonly)
+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)
{
}
@@ -79,6 +79,11 @@ bool ModeHandler::IsListMode()
return list;
}
+unsigned int ModeHandler::GetPrefixRank()
+{
+ return 0;
+}
+
ModeType ModeHandler::GetModeType()
{
return m_type;
@@ -89,6 +94,11 @@ bool ModeHandler::NeedsOper()
return oper;
}
+char ModeHandler::GetPrefix()
+{
+ return prefix;
+}
+
int ModeHandler::GetNumParams(bool adding)
{
return adding ? n_params_on : n_params_off;
@@ -273,9 +283,10 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
*/
if ((targetchannel) && (pcnt == 2))
{
+ ServerInstance->Log(DEBUG,"Spool list");
const char* mode = parameters[1];
if (*mode == '+')
- mode++;
+ mode++;
unsigned char handler_id = ((*mode) - 65) | MASK_CHANNEL;
ModeHandler* mh = modehandlers[handler_id];
if ((mh) && (mh->IsListMode()))
@@ -287,10 +298,13 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
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;
@@ -341,6 +355,8 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
{
unsigned char modechar = *letter;
+ ServerInstance->Log(DEBUG,"Process letter %c", modechar);
+
switch (modechar)
{
/* NB:
@@ -397,7 +413,7 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
parameter = parameters[parameter_counter++];
/* Yerk, invalid! */
- if ((parameter.rfind(':') || (parameter.rfind(' '))))
+ if ((parameter.rfind(':') != std::string::npos) || (parameter.rfind(' ') != std::string::npos))
parameter = "";
}
else
@@ -436,7 +452,17 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
/* 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;
+ /* Does this mode have a prefix? */
+ if (modehandlers[handler_id]->GetPrefix() && targetchannel)
+ {
+ userrec* user_to_prefix = ServerInstance->FindNick(parameter);
+ if (user_to_prefix)
+ targetchannel->SetPrefix(user_to_prefix, modehandlers[handler_id]->GetPrefix(),
+ modehandlers[handler_id]->GetPrefixRank(), adding);
+ }
+ }
/* 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++)
diff --git a/src/modes/cmode_h.cpp b/src/modes/cmode_h.cpp
index 21c97cabc..1b0370439 100644
--- a/src/modes/cmode_h.cpp
+++ b/src/modes/cmode_h.cpp
@@ -14,10 +14,15 @@
#include "hashcomp.h"
#include "modes/cmode_h.h"
-ModeChannelHalfOp::ModeChannelHalfOp(InspIRCd* Instance) : ModeHandler(Instance, 'h', 1, 1, true, MODETYPE_CHANNEL, false)
+ModeChannelHalfOp::ModeChannelHalfOp(InspIRCd* Instance) : ModeHandler(Instance, 'h', 1, 1, true, MODETYPE_CHANNEL, false, '%')
{
}
+unsigned int ModeChannelHalfOp::GetPrefixRank()
+{
+ return HALFOP_VALUE;
+}
+
ModePair ModeChannelHalfOp::ModeSet(userrec* source, userrec* dest, chanrec* channel, const std::string &parameter)
{
userrec* x = ServerInstance->FindNick(parameter);
diff --git a/src/modes/cmode_o.cpp b/src/modes/cmode_o.cpp
index 0ab3d9d95..c631ec779 100644
--- a/src/modes/cmode_o.cpp
+++ b/src/modes/cmode_o.cpp
@@ -14,10 +14,15 @@
#include "hashcomp.h"
#include "modes/cmode_o.h"
-ModeChannelOp::ModeChannelOp(InspIRCd* Instance) : ModeHandler(Instance, 'o', 1, 1, true, MODETYPE_CHANNEL, false)
+ModeChannelOp::ModeChannelOp(InspIRCd* Instance) : ModeHandler(Instance, 'o', 1, 1, true, MODETYPE_CHANNEL, false, '@')
{
}
+unsigned int ModeChannelOp::GetPrefixRank()
+{
+ return OP_VALUE;
+}
+
ModePair ModeChannelOp::ModeSet(userrec* source, userrec* dest, chanrec* channel, const std::string &parameter)
{
userrec* x = ServerInstance->FindNick(parameter);
diff --git a/src/modes/cmode_v.cpp b/src/modes/cmode_v.cpp
index af1fbe22a..7b14d84d4 100644
--- a/src/modes/cmode_v.cpp
+++ b/src/modes/cmode_v.cpp
@@ -14,10 +14,15 @@
#include "hashcomp.h"
#include "modes/cmode_v.h"
-ModeChannelVoice::ModeChannelVoice(InspIRCd* Instance) : ModeHandler(Instance, 'v', 1, 1, true, MODETYPE_CHANNEL, false)
+ModeChannelVoice::ModeChannelVoice(InspIRCd* Instance) : ModeHandler(Instance, 'v', 1, 1, true, MODETYPE_CHANNEL, false, '+')
{
}
+unsigned int ModeChannelVoice::GetPrefixRank()
+{
+ return VOICE_VALUE;
+}
+
ModePair ModeChannelVoice::ModeSet(userrec* source, userrec* dest, chanrec* channel, const std::string &parameter)
{
userrec* x = ServerInstance->FindNick(parameter);