summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/inspircd.h2
-rw-r--r--include/modules.h7
-rw-r--r--include/users.h2
-rw-r--r--src/InspIRCd.layout52
-rw-r--r--src/channels.cpp9
-rw-r--r--src/inspircd.cpp251
-rw-r--r--src/modules.cpp26
-rw-r--r--src/users.cpp22
8 files changed, 258 insertions, 113 deletions
diff --git a/include/inspircd.h b/include/inspircd.h
index 5eae2f189..4a0762dbd 100644
--- a/include/inspircd.h
+++ b/include/inspircd.h
@@ -85,5 +85,7 @@ std::string getadminemail();
std::string getadminnick();
void readfile(file_cache &F, const char* fname);
bool ModeDefined(char c, int i);
+bool ModeDefinedOper(char c, int i);
int ModeDefinedOn(char c, int i);
int ModeDefinedOff(char c, int i);
+
diff --git a/include/modules.h b/include/modules.h
index 74d7800d3..1391c5958 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -293,9 +293,10 @@ class Server : public classbase
* This allows modules to add extra mode letters, e.g. +x for hostcloak.
* the "type" parameter is either MT_CHANNEL, MT_CLIENT, or MT_SERVER, to
* indicate wether the mode is a channel mode, a client mode, or a server mode.
- * default_on is true if the mode is to be applied to default connections.
+ * requires_oper is used with MT_CLIENT type modes only to indicate the mode can only
+ * be set or unset by an oper. If this is used for MT_CHANNEL type modes it is ignored.
* params_when_on is the number of modes to expect when the mode is turned on
- * (for type MT_CHANNEL only), e.g. with mode +b, this would have a value of 1.
+ * (for type MT_CHANNEL only), e.g. with mode +k, this would have a value of 1.
* the params_when_off value has a similar value to params_when_on, except it indicates
* the number of parameters to expect when the mode is disabled. Modes which act in a similar
* way to channel mode +l (e.g. require a parameter to enable, but not to disable) should
@@ -306,7 +307,7 @@ class Server : public classbase
* a mode can have at most one parameter, attempting to use more parameters will have undefined
* effects.
*/
- virtual bool AddExtendedMode(char modechar, int type, bool default_on, int params_when_on, int params_when_off);
+ virtual bool AddExtendedMode(char modechar, int type, bool requires_oper, int params_when_on, int params_when_off);
/** Adds a command to the command table.
* This allows modules to add extra commands into the command table. You must place a function within your
diff --git a/include/users.h b/include/users.h
index 728a82d00..901b30321 100644
--- a/include/users.h
+++ b/include/users.h
@@ -87,7 +87,7 @@ class userrec : public connection
* This may contain any of the following RFC characters: o, w, s, i
* Your module may define other mode characters as it sees fit.
*/
- char modes[32];
+ char modes[MAXBUF];
ucrec chans[MAXCHANS];
diff --git a/src/InspIRCd.layout b/src/InspIRCd.layout
index 658ada2a4..342b4d6eb 100644
--- a/src/InspIRCd.layout
+++ b/src/InspIRCd.layout
@@ -13,9 +13,9 @@ LeftChar=1
[Editor_1]
Open=1
Top=1
-CursorCol=2
-CursorRow=3439
-TopLine=3410
+CursorCol=1
+CursorRow=2503
+TopLine=2471
LeftChar=1
[Editor_2]
@@ -38,8 +38,8 @@ LeftChar=1
Open=1
Top=0
CursorCol=1
-CursorRow=32
-TopLine=32
+CursorRow=37
+TopLine=6
LeftChar=1
[Editor_5]
@@ -53,8 +53,8 @@ LeftChar=1
[Editor_6]
Open=1
Top=0
-CursorCol=1
-CursorRow=9
+CursorCol=22
+CursorRow=51
TopLine=1
LeftChar=1
@@ -85,9 +85,9 @@ LeftChar=1
[Editor_10]
Open=1
Top=0
-CursorCol=1
-CursorRow=1
-TopLine=1
+CursorCol=29
+CursorRow=65
+TopLine=19
LeftChar=1
[Editor_11]
@@ -103,7 +103,7 @@ Open=1
Top=0
CursorCol=18
CursorRow=10
-TopLine=1
+TopLine=64
LeftChar=1
[Editor_13]
@@ -131,7 +131,7 @@ TopLine=1
LeftChar=1
[Editor_16]
-Open=0
+Open=1
Top=0
CursorCol=21
CursorRow=22
@@ -141,9 +141,9 @@ LeftChar=1
[Editor_17]
Open=1
Top=0
-CursorCol=20
-CursorRow=43
-TopLine=27
+CursorCol=5
+CursorRow=88
+TopLine=34
LeftChar=1
[Editor_18]
@@ -165,9 +165,9 @@ LeftChar=1
[Editor_20]
Open=1
Top=0
-CursorCol=28
-CursorRow=115
-TopLine=408
+CursorCol=89
+CursorRow=297
+TopLine=1
LeftChar=1
[Editor_21]
@@ -181,9 +181,9 @@ LeftChar=1
[Editor_22]
Open=1
Top=0
-CursorCol=51
-CursorRow=87
-TopLine=67
+CursorCol=19
+CursorRow=90
+TopLine=61
LeftChar=1
[Editor_23]
@@ -204,14 +204,14 @@ LeftChar=1
[Editor_25]
Open=1
Top=0
-CursorCol=1
-CursorRow=18
+CursorCol=4
+CursorRow=76
TopLine=1
LeftChar=1
[Editor_26]
Open=1
Top=0
-CursorCol=4
-CursorRow=73
-TopLine=44
+CursorCol=7
+CursorRow=63
+TopLine=27
LeftChar=1
diff --git a/src/channels.cpp b/src/channels.cpp
index 2b2e5963e..8fd510f7b 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -3,6 +3,11 @@
#include "inspircd.h"
#include <stdio.h>
#include <string>
+#include <vector>
+
+using namespace std;
+
+vector<ModeParameter> custom_mode_params;
chanrec::chanrec()
{
@@ -28,7 +33,7 @@ void chanrec::SetCustomMode(char mode,bool mode_on)
log(DEBUG,"Custom mode %c set",mode);
}
else {
- char temp[MAXMODES];
+ char temp[MAXBUF];
int count = 0;
for (int q = 0; q < strlen(custom_modes); q++) {
if (custom_modes[q] != mode) {
@@ -42,8 +47,6 @@ void chanrec::SetCustomMode(char mode,bool mode_on)
}
}
-vector<ModeParameter> custom_mode_params;
-
void chanrec::SetCustomModeParam(char mode,char* parameter,bool mode_on)
{
diff --git a/src/inspircd.cpp b/src/inspircd.cpp
index 15ce95fad..d1f4bd27b 100644
--- a/src/inspircd.cpp
+++ b/src/inspircd.cpp
@@ -1003,8 +1003,8 @@ char* cmode(userrec *user, chanrec *chan)
}
}
-char scratch[MAXMODES];
-char sparam[MAXMODES];
+char scratch[MAXBUF];
+char sparam[MAXBUF];
char* chanmodes(chanrec *chan)
{
@@ -1019,45 +1019,45 @@ char* chanmodes(chanrec *chan)
strcpy(sparam,"");
if (chan->noexternal)
{
- strcat(scratch,"n");
+ strncat(scratch,"n",MAXMODES);
}
if (chan->topiclock)
{
- strcat(scratch,"t");
+ strncat(scratch,"t",MAXMODES);
}
if (strcmp(chan->key,""))
{
- strcat(scratch,"k");
+ strncat(scratch,"k",MAXMODES);
}
if (chan->limit)
{
- strcat(scratch,"l");
+ strncat(scratch,"l",MAXMODES);
}
if (chan->inviteonly)
{
- strcat(scratch,"i");
+ strncat(scratch,"i",MAXMODES);
}
if (chan->moderated)
{
- strcat(scratch,"m");
+ strncat(scratch,"m",MAXMODES);
}
if (chan->secret)
{
- strcat(scratch,"s");
+ strncat(scratch,"s",MAXMODES);
}
if (chan->c_private)
{
- strcat(scratch,"p");
+ strncat(scratch,"p",MAXMODES);
}
if (strcmp(chan->key,""))
{
- strcat(sparam,chan->key);
+ strncat(sparam,chan->key,MAXBUF);
}
if (chan->limit)
{
char foo[24];
sprintf(foo," %d",chan->limit);
- strcat(sparam,foo);
+ strncat(sparam,foo,MAXBUF);
}
if (strlen(chan->custom_modes))
{
@@ -1067,8 +1067,8 @@ char* chanmodes(chanrec *chan)
std::string extparam = chan->GetModeParameter(chan->custom_modes[z]);
if (extparam != "")
{
- strcat(sparam," ");
- strcat(sparam,extparam.c_str());
+ strncat(sparam," ",MAXBUF);
+ strncat(sparam,extparam.c_str(),MAXBUF);
}
}
}
@@ -2345,6 +2345,78 @@ void process_modes(char **parameters,userrec* user,chanrec *chan,int status, int
}
}
+// based on sourcemodes, return true or false to determine if umode is a valid mode a user may set on themselves or others.
+
+bool allowed_umode(char umode, char* sourcemodes,bool adding)
+{
+ log(DEBUG,"Allowed_umode: %c %s",umode,sourcemodes);
+ // RFC1459 specified modes
+ if ((umode == 'w') || (umode == 's') || (umode == 'i'))
+ {
+ log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
+ return true;
+ }
+
+ // user may not +o themselves or others, but an oper may de-oper other opers or themselves
+ if ((strchr(sourcemodes,'o')) && (!adding))
+ {
+ log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
+ return true;
+ }
+ else if (umode == 'o')
+ {
+ log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
+ return false;
+ }
+
+ // process any module-defined modes that need oper
+ if ((ModeDefinedOper(umode,MT_CLIENT)) && (strchr(sourcemodes,'o')))
+ {
+ log(DEBUG,"umode %c allowed by module handler (oper only mode)",umode);
+ return true;
+ }
+ else
+ if (ModeDefined(umode,MT_CLIENT))
+ {
+ // process any module-defined modes that don't need oper
+ log(DEBUG,"umode %c allowed by module handler (non-oper mode)",umode);
+ if ((ModeDefinedOper(umode,MT_CLIENT)) && (!strchr(sourcemodes,'o')))
+ {
+ // no, this mode needs oper, and this user 'aint got what it takes!
+ return false;
+ }
+ return true;
+ }
+
+ // anything else - return false.
+ log(DEBUG,"umode %c not known by any ruleset",umode);
+ return false;
+}
+
+bool process_module_umode(char umode, userrec* source, userrec* dest, bool adding)
+{
+ string_list p;
+ p.clear();
+ if (ModeDefined(umode,MT_CLIENT))
+ {
+ for (int i = 0; i <= MODCOUNT; i++)
+ {
+ if (modules[i]->OnExtendedMode(source,(chanrec*)NULL,umode,MT_CLIENT,adding,p))
+ {
+ log(DEBUG,"Module claims umode %c",umode);
+ return true;
+ }
+ }
+ log(DEBUG,"No module claims umode %c",umode);
+ return false;
+ }
+ else
+ {
+ log(DEBUG,"*** BUG *** Non-module umode passed to process_module_umode!");
+ return false;
+ }
+}
+
void handle_mode(char **parameters, int pcnt, userrec *user)
{
chanrec* Ptr;
@@ -2360,8 +2432,13 @@ void handle_mode(char **parameters, int pcnt, userrec *user)
WriteServ(user->fd,"221 %s :+%s",user->nick,user->modes);
return;
}
+
if ((dest) && (pcnt > 1))
{
+ char dmodes[MAXBUF];
+ strncpy(dmodes,dest->modes,MAXBUF);
+ log(DEBUG,"pulled up dest user modes: %s",dmodes);
+
can_change = 0;
if (user != dest)
{
@@ -2428,7 +2505,7 @@ void handle_mode(char **parameters, int pcnt, userrec *user)
}
else
{
- if ((parameters[1][i] == 'i') || (parameters[1][i] == 'w') || (parameters[1][i] == 's'))
+ if ((parameters[1][i] == 'i') || (parameters[1][i] == 'w') || (parameters[1][i] == 's') || (allowed_umode(parameters[1][i],user->modes,direction)))
{
can_change = 1;
}
@@ -2437,34 +2514,45 @@ void handle_mode(char **parameters, int pcnt, userrec *user)
{
if (direction == 1)
{
- if (!strchr(dest->modes,parameters[1][i]))
+ if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
{
- dest->modes[strlen(dest->modes)+1]='\0';
- dest->modes[strlen(dest->modes)] = parameters[1][i];
- outpars[strlen(outpars)+1]='\0';
- outpars[strlen(outpars)] = parameters[1][i];
+ char umode = parameters[1][i];
+ if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
+ {
+ dmodes[strlen(dmodes)+1]='\0';
+ dmodes[strlen(dmodes)] = parameters[1][i];
+ outpars[strlen(outpars)+1]='\0';
+ outpars[strlen(outpars)] = parameters[1][i];
+ }
}
}
else
{
- int q = 0;
- char temp[MAXBUF];
- char moo[MAXBUF];
-
- outpars[strlen(outpars)+1]='\0';
- outpars[strlen(outpars)] = parameters[1][i];
-
- strcpy(temp,"");
- for (q = 0; q < strlen(user->modes); q++)
+ if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
{
- if (user->modes[q] != parameters[1][i])
+ char umode = parameters[1][i];
+ if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
{
- moo[0] = user->modes[q];
- moo[1] = '\0';
- strcat(temp,moo);
+ int q = 0;
+ char temp[MAXBUF];
+ char moo[MAXBUF];
+
+ outpars[strlen(outpars)+1]='\0';
+ outpars[strlen(outpars)] = parameters[1][i];
+
+ strcpy(temp,"");
+ for (q = 0; q < strlen(dmodes); q++)
+ {
+ if (dmodes[q] != parameters[1][i])
+ {
+ moo[0] = dmodes[q];
+ moo[1] = '\0';
+ strcat(temp,moo);
+ }
+ }
+ strcpy(dmodes,temp);
}
}
- strcpy(user->modes,temp);
}
}
}
@@ -2505,7 +2593,17 @@ void handle_mode(char **parameters, int pcnt, userrec *user)
return;
WriteTo(user, dest, "MODE %s :%s", dest->nick, b);
+
+ if (strlen(dmodes)>MAXMODES)
+ {
+ dmodes[MAXMODES-1] = '\0';
+ }
+ log(DEBUG,"Stripped mode line");
+ log(DEBUG,"Line dest is now %s",dmodes);
+ strncpy(dest->modes,dmodes,MAXMODES);
+
}
+
return;
}
@@ -2559,9 +2657,16 @@ void server_mode(char **parameters, int pcnt, userrec *user)
char outpars[MAXBUF];
dest = Find(parameters[0]);
+
+ log(DEBUG,"server_mode on %s",dest->nick);
if ((dest) && (pcnt > 1))
{
+ log(DEBUG,"params > 1");
+
+ char dmodes[MAXBUF];
+ strncpy(dmodes,dest->modes,MAXBUF);
+
strcpy(outpars,"+");
direction = 1;
@@ -2603,50 +2708,56 @@ void server_mode(char **parameters, int pcnt, userrec *user)
}
else
{
- can_change = 0;
- if (strchr(user->modes,'o'))
- {
- can_change = 1;
- }
- else
- {
- if ((parameters[1][i] == 'i') || (parameters[1][i] == 'w') || (parameters[1][i] == 's'))
- {
- can_change = 1;
- }
- }
+ log(DEBUG,"begin mode processing entry");
+ can_change = 1;
if (can_change)
{
if (direction == 1)
{
- if (!strchr(dest->modes,parameters[1][i]))
+ log(DEBUG,"umode %c being added",parameters[1][i]);
+ if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
{
- dest->modes[strlen(dest->modes)+1]='\0';
- dest->modes[strlen(dest->modes)] = parameters[1][i];
- outpars[strlen(outpars)+1]='\0';
- outpars[strlen(outpars)] = parameters[1][i];
+ char umode = parameters[1][i];
+ log(DEBUG,"umode %c is an allowed umode",umode);
+ if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
+ {
+ dmodes[strlen(dmodes)+1]='\0';
+ dmodes[strlen(dmodes)] = parameters[1][i];
+ outpars[strlen(outpars)+1]='\0';
+ outpars[strlen(outpars)] = parameters[1][i];
+ }
}
}
else
{
- int q = 0;
- char temp[MAXBUF];
- char moo[MAXBUF];
-
- outpars[strlen(outpars)+1]='\0';
- outpars[strlen(outpars)] = parameters[1][i];
-
- strcpy(temp,"");
- for (q = 0; q < strlen(user->modes); q++)
+ // can only remove a mode they already have
+ log(DEBUG,"umode %c being removed",parameters[1][i]);
+ if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
{
- if (user->modes[q] != parameters[1][i])
+ char umode = parameters[1][i];
+ log(DEBUG,"umode %c is an allowed umode",umode);
+ if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
{
- moo[0] = user->modes[q];
- moo[1] = '\0';
- strcat(temp,moo);
+ int q = 0;
+ char temp[MAXBUF];
+ char moo[MAXBUF];
+
+ outpars[strlen(outpars)+1]='\0';
+ outpars[strlen(outpars)] = parameters[1][i];
+
+ strcpy(temp,"");
+ for (q = 0; q < strlen(dmodes); q++)
+ {
+ if (dmodes[q] != parameters[1][i])
+ {
+ moo[0] = dmodes[q];
+ moo[1] = '\0';
+ strcat(temp,moo);
+ }
+ }
+ strcpy(dmodes,temp);
}
}
- strcpy(user->modes,temp);
}
}
}
@@ -2687,7 +2798,17 @@ void server_mode(char **parameters, int pcnt, userrec *user)
return;
WriteTo(user, dest, "MODE %s :%s", dest->nick, b);
+
+ if (strlen(dmodes)>MAXMODES)
+ {
+ dmodes[MAXMODES-1] = '\0';
+ }
+ log(DEBUG,"Stripped mode line");
+ log(DEBUG,"Line dest is now %s",dmodes);
+ strncpy(dest->modes,dmodes,MAXMODES);
+
}
+
return;
}
diff --git a/src/modules.cpp b/src/modules.cpp
index 8e591ba0c..59834eefc 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -19,10 +19,10 @@ class ExtMode
public:
char modechar;
int type;
- bool default_on;
int params_when_on;
int params_when_off;
- ExtMode(char mc, int ty, bool d_on, int p_on, int p_off) : modechar(mc), type(ty), default_on(d_on), params_when_on(p_on), params_when_off(p_off) { };
+ bool needsoper;
+ ExtMode(char mc, int ty, bool oper, int p_on, int p_off) : modechar(mc), type(ty), needsoper(oper), params_when_on(p_on), params_when_off(p_off) { };
};
typedef std::vector<ExtMode> ExtModeList;
@@ -45,6 +45,20 @@ bool ModeDefined(char modechar, int type)
return false;
}
+bool ModeDefinedOper(char modechar, int type)
+{
+ log(DEBUG,"Size of extmodes vector is %d",EMode.size());
+ for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++)
+ {
+ log(DEBUG,"i->modechar==%c, modechar=%c, i->type=%d, type=%d",i->modechar,modechar,i->type,type);
+ if ((i->modechar == modechar) && (i->type == type) && (i->needsoper == true))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
// returns number of parameters for a custom mode when it is switched on
int ModeDefinedOn(char modechar, int type)
{
@@ -72,12 +86,12 @@ int ModeDefinedOff(char modechar, int type)
}
// returns true if an extended mode character is in use
-bool DoAddExtendedMode(char modechar, int type, bool default_on, int params_on, int params_off)
+bool DoAddExtendedMode(char modechar, int type, bool requires_oper, int params_on, int params_off)
{
if (ModeDefined(modechar,type)) {
return false;
}
- EMode.push_back(ExtMode(modechar,type,default_on,params_on,params_off));
+ EMode.push_back(ExtMode(modechar,type,requires_oper,params_on,params_off));
return true;
}
@@ -227,7 +241,7 @@ Admin Server::GetAdmin()
-bool Server::AddExtendedMode(char modechar, int type, bool default_on, int params_when_on, int params_when_off)
+bool Server::AddExtendedMode(char modechar, int type, bool requires_oper, int params_when_on, int params_when_off)
{
if (type == MT_SERVER)
{
@@ -244,7 +258,7 @@ bool Server::AddExtendedMode(char modechar, int type, bool default_on, int param
log(DEBUG,"*** API ERROR *** More than one parameter for an MT_CHANNEL mode is not yet supported");
return false;
}
- return DoAddExtendedMode(modechar,type,default_on,params_when_on,params_when_off);
+ return DoAddExtendedMode(modechar,type,requires_oper,params_when_on,params_when_off);
}
diff --git a/src/users.cpp b/src/users.cpp
index 4a9ada90d..857e2f1d6 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -69,14 +69,18 @@ void userrec::InviteTo(char* channel)
void userrec::RemoveInvite(char* channel)
{
- for (InvitedList::iterator i = invites.begin(); i != invites.end(); i++)
- {
- if (i->channel) {
- if (!strcasecmp(i->channel,channel))
- {
- invites.erase(i);
- return;
- }
- }
+ log(DEBUG,"Removing invites");
+ if (invites.size())
+ {
+ for (InvitedList::iterator i = invites.begin(); i != invites.end(); i++)
+ {
+ if (i->channel) {
+ if (!strcasecmp(i->channel,channel))
+ {
+ invites.erase(i);
+ return;
+ }
+ }
+ }
}
}