Completed support for module-handled umodes

git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@377 e03df62e-2008-0410-955e-edbf42e46eb7
This commit is contained in:
brain 2004-04-04 21:30:41 +00:00
parent 9ed9068cc6
commit dae8024a46
8 changed files with 258 additions and 113 deletions

View File

@ -85,5 +85,7 @@ std::string getadminemail();
std::string getadminnick(); std::string getadminnick();
void readfile(file_cache &F, const char* fname); void readfile(file_cache &F, const char* fname);
bool ModeDefined(char c, int i); bool ModeDefined(char c, int i);
bool ModeDefinedOper(char c, int i);
int ModeDefinedOn(char c, int i); int ModeDefinedOn(char c, int i);
int ModeDefinedOff(char c, int i); int ModeDefinedOff(char c, int i);

View File

@ -293,9 +293,10 @@ class Server : public classbase
* This allows modules to add extra mode letters, e.g. +x for hostcloak. * 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 * 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. * 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 * 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 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 * 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 * 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 * a mode can have at most one parameter, attempting to use more parameters will have undefined
* effects. * 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. /** 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 * This allows modules to add extra commands into the command table. You must place a function within your

View File

@ -87,7 +87,7 @@ class userrec : public connection
* This may contain any of the following RFC characters: o, w, s, i * This may contain any of the following RFC characters: o, w, s, i
* Your module may define other mode characters as it sees fit. * Your module may define other mode characters as it sees fit.
*/ */
char modes[32]; char modes[MAXBUF];
ucrec chans[MAXCHANS]; ucrec chans[MAXCHANS];

View File

@ -13,9 +13,9 @@ LeftChar=1
[Editor_1] [Editor_1]
Open=1 Open=1
Top=1 Top=1
CursorCol=2 CursorCol=1
CursorRow=3439 CursorRow=2503
TopLine=3410 TopLine=2471
LeftChar=1 LeftChar=1
[Editor_2] [Editor_2]
@ -38,8 +38,8 @@ LeftChar=1
Open=1 Open=1
Top=0 Top=0
CursorCol=1 CursorCol=1
CursorRow=32 CursorRow=37
TopLine=32 TopLine=6
LeftChar=1 LeftChar=1
[Editor_5] [Editor_5]
@ -53,8 +53,8 @@ LeftChar=1
[Editor_6] [Editor_6]
Open=1 Open=1
Top=0 Top=0
CursorCol=1 CursorCol=22
CursorRow=9 CursorRow=51
TopLine=1 TopLine=1
LeftChar=1 LeftChar=1
@ -85,9 +85,9 @@ LeftChar=1
[Editor_10] [Editor_10]
Open=1 Open=1
Top=0 Top=0
CursorCol=1 CursorCol=29
CursorRow=1 CursorRow=65
TopLine=1 TopLine=19
LeftChar=1 LeftChar=1
[Editor_11] [Editor_11]
@ -103,7 +103,7 @@ Open=1
Top=0 Top=0
CursorCol=18 CursorCol=18
CursorRow=10 CursorRow=10
TopLine=1 TopLine=64
LeftChar=1 LeftChar=1
[Editor_13] [Editor_13]
@ -131,7 +131,7 @@ TopLine=1
LeftChar=1 LeftChar=1
[Editor_16] [Editor_16]
Open=0 Open=1
Top=0 Top=0
CursorCol=21 CursorCol=21
CursorRow=22 CursorRow=22
@ -141,9 +141,9 @@ LeftChar=1
[Editor_17] [Editor_17]
Open=1 Open=1
Top=0 Top=0
CursorCol=20 CursorCol=5
CursorRow=43 CursorRow=88
TopLine=27 TopLine=34
LeftChar=1 LeftChar=1
[Editor_18] [Editor_18]
@ -165,9 +165,9 @@ LeftChar=1
[Editor_20] [Editor_20]
Open=1 Open=1
Top=0 Top=0
CursorCol=28 CursorCol=89
CursorRow=115 CursorRow=297
TopLine=408 TopLine=1
LeftChar=1 LeftChar=1
[Editor_21] [Editor_21]
@ -181,9 +181,9 @@ LeftChar=1
[Editor_22] [Editor_22]
Open=1 Open=1
Top=0 Top=0
CursorCol=51 CursorCol=19
CursorRow=87 CursorRow=90
TopLine=67 TopLine=61
LeftChar=1 LeftChar=1
[Editor_23] [Editor_23]
@ -204,14 +204,14 @@ LeftChar=1
[Editor_25] [Editor_25]
Open=1 Open=1
Top=0 Top=0
CursorCol=1 CursorCol=4
CursorRow=18 CursorRow=76
TopLine=1 TopLine=1
LeftChar=1 LeftChar=1
[Editor_26] [Editor_26]
Open=1 Open=1
Top=0 Top=0
CursorCol=4 CursorCol=7
CursorRow=73 CursorRow=63
TopLine=44 TopLine=27
LeftChar=1 LeftChar=1

View File

@ -3,6 +3,11 @@
#include "inspircd.h" #include "inspircd.h"
#include <stdio.h> #include <stdio.h>
#include <string> #include <string>
#include <vector>
using namespace std;
vector<ModeParameter> custom_mode_params;
chanrec::chanrec() chanrec::chanrec()
{ {
@ -28,7 +33,7 @@ void chanrec::SetCustomMode(char mode,bool mode_on)
log(DEBUG,"Custom mode %c set",mode); log(DEBUG,"Custom mode %c set",mode);
} }
else { else {
char temp[MAXMODES]; char temp[MAXBUF];
int count = 0; int count = 0;
for (int q = 0; q < strlen(custom_modes); q++) { for (int q = 0; q < strlen(custom_modes); q++) {
if (custom_modes[q] != mode) { 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) void chanrec::SetCustomModeParam(char mode,char* parameter,bool mode_on)
{ {

View File

@ -1003,8 +1003,8 @@ char* cmode(userrec *user, chanrec *chan)
} }
} }
char scratch[MAXMODES]; char scratch[MAXBUF];
char sparam[MAXMODES]; char sparam[MAXBUF];
char* chanmodes(chanrec *chan) char* chanmodes(chanrec *chan)
{ {
@ -1019,45 +1019,45 @@ char* chanmodes(chanrec *chan)
strcpy(sparam,""); strcpy(sparam,"");
if (chan->noexternal) if (chan->noexternal)
{ {
strcat(scratch,"n"); strncat(scratch,"n",MAXMODES);
} }
if (chan->topiclock) if (chan->topiclock)
{ {
strcat(scratch,"t"); strncat(scratch,"t",MAXMODES);
} }
if (strcmp(chan->key,"")) if (strcmp(chan->key,""))
{ {
strcat(scratch,"k"); strncat(scratch,"k",MAXMODES);
} }
if (chan->limit) if (chan->limit)
{ {
strcat(scratch,"l"); strncat(scratch,"l",MAXMODES);
} }
if (chan->inviteonly) if (chan->inviteonly)
{ {
strcat(scratch,"i"); strncat(scratch,"i",MAXMODES);
} }
if (chan->moderated) if (chan->moderated)
{ {
strcat(scratch,"m"); strncat(scratch,"m",MAXMODES);
} }
if (chan->secret) if (chan->secret)
{ {
strcat(scratch,"s"); strncat(scratch,"s",MAXMODES);
} }
if (chan->c_private) if (chan->c_private)
{ {
strcat(scratch,"p"); strncat(scratch,"p",MAXMODES);
} }
if (strcmp(chan->key,"")) if (strcmp(chan->key,""))
{ {
strcat(sparam,chan->key); strncat(sparam,chan->key,MAXBUF);
} }
if (chan->limit) if (chan->limit)
{ {
char foo[24]; char foo[24];
sprintf(foo," %d",chan->limit); sprintf(foo," %d",chan->limit);
strcat(sparam,foo); strncat(sparam,foo,MAXBUF);
} }
if (strlen(chan->custom_modes)) if (strlen(chan->custom_modes))
{ {
@ -1067,8 +1067,8 @@ char* chanmodes(chanrec *chan)
std::string extparam = chan->GetModeParameter(chan->custom_modes[z]); std::string extparam = chan->GetModeParameter(chan->custom_modes[z]);
if (extparam != "") if (extparam != "")
{ {
strcat(sparam," "); strncat(sparam," ",MAXBUF);
strcat(sparam,extparam.c_str()); 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) void handle_mode(char **parameters, int pcnt, userrec *user)
{ {
chanrec* Ptr; 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); WriteServ(user->fd,"221 %s :+%s",user->nick,user->modes);
return; return;
} }
if ((dest) && (pcnt > 1)) if ((dest) && (pcnt > 1))
{ {
char dmodes[MAXBUF];
strncpy(dmodes,dest->modes,MAXBUF);
log(DEBUG,"pulled up dest user modes: %s",dmodes);
can_change = 0; can_change = 0;
if (user != dest) if (user != dest)
{ {
@ -2428,7 +2505,7 @@ void handle_mode(char **parameters, int pcnt, userrec *user)
} }
else 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; can_change = 1;
} }
@ -2437,34 +2514,45 @@ void handle_mode(char **parameters, int pcnt, userrec *user)
{ {
if (direction == 1) 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'; char umode = parameters[1][i];
dest->modes[strlen(dest->modes)] = parameters[1][i]; if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
outpars[strlen(outpars)+1]='\0'; {
outpars[strlen(outpars)] = parameters[1][i]; dmodes[strlen(dmodes)+1]='\0';
dmodes[strlen(dmodes)] = parameters[1][i];
outpars[strlen(outpars)+1]='\0';
outpars[strlen(outpars)] = parameters[1][i];
}
} }
} }
else else
{ {
int q = 0; if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
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 (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]; int q = 0;
moo[1] = '\0'; char temp[MAXBUF];
strcat(temp,moo); 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; return;
WriteTo(user, dest, "MODE %s :%s", dest->nick, b); 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; return;
} }
@ -2559,9 +2657,16 @@ void server_mode(char **parameters, int pcnt, userrec *user)
char outpars[MAXBUF]; char outpars[MAXBUF];
dest = Find(parameters[0]); dest = Find(parameters[0]);
log(DEBUG,"server_mode on %s",dest->nick);
if ((dest) && (pcnt > 1)) if ((dest) && (pcnt > 1))
{ {
log(DEBUG,"params > 1");
char dmodes[MAXBUF];
strncpy(dmodes,dest->modes,MAXBUF);
strcpy(outpars,"+"); strcpy(outpars,"+");
direction = 1; direction = 1;
@ -2603,50 +2708,56 @@ void server_mode(char **parameters, int pcnt, userrec *user)
} }
else else
{ {
can_change = 0; log(DEBUG,"begin mode processing entry");
if (strchr(user->modes,'o')) can_change = 1;
{
can_change = 1;
}
else
{
if ((parameters[1][i] == 'i') || (parameters[1][i] == 'w') || (parameters[1][i] == 's'))
{
can_change = 1;
}
}
if (can_change) if (can_change)
{ {
if (direction == 1) 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'; char umode = parameters[1][i];
dest->modes[strlen(dest->modes)] = parameters[1][i]; log(DEBUG,"umode %c is an allowed umode",umode);
outpars[strlen(outpars)+1]='\0'; if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
outpars[strlen(outpars)] = parameters[1][i]; {
dmodes[strlen(dmodes)+1]='\0';
dmodes[strlen(dmodes)] = parameters[1][i];
outpars[strlen(outpars)+1]='\0';
outpars[strlen(outpars)] = parameters[1][i];
}
} }
} }
else else
{ {
int q = 0; // can only remove a mode they already have
char temp[MAXBUF]; log(DEBUG,"umode %c being removed",parameters[1][i]);
char moo[MAXBUF]; if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
outpars[strlen(outpars)+1]='\0';
outpars[strlen(outpars)] = parameters[1][i];
strcpy(temp,"");
for (q = 0; q < strlen(user->modes); q++)
{ {
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]; int q = 0;
moo[1] = '\0'; char temp[MAXBUF];
strcat(temp,moo); 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; return;
WriteTo(user, dest, "MODE %s :%s", dest->nick, b); 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; return;
} }

View File

@ -19,10 +19,10 @@ class ExtMode
public: public:
char modechar; char modechar;
int type; int type;
bool default_on;
int params_when_on; int params_when_on;
int params_when_off; 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; typedef std::vector<ExtMode> ExtModeList;
@ -45,6 +45,20 @@ bool ModeDefined(char modechar, int type)
return false; 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 // returns number of parameters for a custom mode when it is switched on
int ModeDefinedOn(char modechar, int type) 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 // 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)) { if (ModeDefined(modechar,type)) {
return false; 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; 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) 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"); log(DEBUG,"*** API ERROR *** More than one parameter for an MT_CHANNEL mode is not yet supported");
return false; 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);
} }

View File

@ -69,14 +69,18 @@ void userrec::InviteTo(char* channel)
void userrec::RemoveInvite(char* channel) void userrec::RemoveInvite(char* channel)
{ {
for (InvitedList::iterator i = invites.begin(); i != invites.end(); i++) log(DEBUG,"Removing invites");
{ if (invites.size())
if (i->channel) { {
if (!strcasecmp(i->channel,channel)) for (InvitedList::iterator i = invites.begin(); i != invites.end(); i++)
{ {
invites.erase(i); if (i->channel) {
return; if (!strcasecmp(i->channel,channel))
} {
} invites.erase(i);
return;
}
}
}
} }
} }