diff options
-rw-r--r-- | include/inspircd.h | 2 | ||||
-rw-r--r-- | include/modules.h | 7 | ||||
-rw-r--r-- | include/users.h | 2 | ||||
-rw-r--r-- | src/InspIRCd.layout | 52 | ||||
-rw-r--r-- | src/channels.cpp | 9 | ||||
-rw-r--r-- | src/inspircd.cpp | 251 | ||||
-rw-r--r-- | src/modules.cpp | 26 | ||||
-rw-r--r-- | src/users.cpp | 22 |
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; + } + } + } } } |