diff options
-rw-r--r-- | include/channels.h | 2 | ||||
-rw-r--r-- | include/modules.h | 7 | ||||
-rw-r--r-- | src/channels.cpp | 62 | ||||
-rw-r--r-- | src/modules.cpp | 2 | ||||
-rw-r--r-- | src/modules/extra/m_sqlv2.h | 1 | ||||
-rw-r--r-- | src/modules/m_spanningtree.cpp | 33 |
6 files changed, 54 insertions, 53 deletions
diff --git a/include/channels.h b/include/channels.h index 6c92f0801..648723b09 100644 --- a/include/channels.h +++ b/include/channels.h @@ -150,7 +150,7 @@ class chanrec : public Extensible /** Connect a chanrec to a userrec */ - static chanrec* ForceChan(InspIRCd* Instance, chanrec* Ptr,ucrec *a,userrec* user, int created); + static chanrec* ForceChan(InspIRCd* Instance, chanrec* Ptr,ucrec *a,userrec* user, const std::string &privs); prefixlist prefixes; diff --git a/include/modules.h b/include/modules.h index 95dbd764e..3f6ddb8d0 100644 --- a/include/modules.h +++ b/include/modules.h @@ -488,10 +488,13 @@ class Module : public Extensible * processing on the actual channel record at this point, however the channel NAME will still be passed in * char* cname, so that you could for example implement a channel blacklist or whitelist, etc. * @param user The user joining the channel - * @param cname The channel name being joined + * @param chan If the channel is a new channel, this will be NULL, otherwise it will be a pointer to the channel being joined + * @param cname The channel name being joined. For new channels this is valid where chan is not. + * @param privs A string containing the users privilages when joining the channel. For new channels this will contain "@". + * You may alter this string to alter the user's modes on the channel. * @return 1 To prevent the join, 0 to allow it. */ - virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname); + virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname, std::string &privs); /** Called whenever a user is about to be kicked. * Returning a value of 1 from this function stops the process immediately, causing no diff --git a/src/channels.cpp b/src/channels.cpp index 4c5965759..ad8dfbbd4 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -199,19 +199,22 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo if (!user || !cn) return NULL; - int created = 0; + bool new_channel = false; char cname[MAXBUF]; int MOD_RESULT = 0; strlcpy(cname,cn,CHANMAX); + std::string privs; + chanrec* Ptr = Instance->FindChan(cname); if (!Ptr) { if (IS_LOCAL(user)) { + privs = "@"; MOD_RESULT = 0; - FOREACH_RESULT_I(Instance,I_OnUserPreJoin,OnUserPreJoin(user,NULL,cname)); + FOREACH_RESULT_I(Instance,I_OnUserPreJoin,OnUserPreJoin(user,NULL,cname,privs)); if (MOD_RESULT == 1) return NULL; } @@ -227,12 +230,7 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo *Ptr->setby = 0; Ptr->topicset = 0; Instance->Log(DEBUG,"chanrec::JoinUser(): created: %s",cname); - /* - * set created to 2 to indicate user - * is the first in the channel - * and should be given ops - */ - created = 2; + new_channel = true; } else { @@ -247,7 +245,7 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo if (IS_LOCAL(user)) /* was a check on fd > -1 */ { MOD_RESULT = 0; - FOREACH_RESULT_I(Instance,I_OnUserPreJoin,OnUserPreJoin(user,Ptr,cname)); + FOREACH_RESULT_I(Instance,I_OnUserPreJoin,OnUserPreJoin(user,Ptr,cname,privs)); if (MOD_RESULT == 1) { return NULL; @@ -321,14 +319,13 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo { Instance->Log(DEBUG,"chanrec::JoinUser(): Overridden checks"); } - created = 1; } for (UserChanList::const_iterator index = user->chans.begin(); index != user->chans.end(); index++) { if ((*index)->channel == NULL) { - return chanrec::ForceChan(Instance, Ptr, *index, user, created); + return chanrec::ForceChan(Instance, Ptr, *index, user, privs); } } @@ -340,7 +337,7 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo if (!IS_LOCAL(user)) /* was a check on fd < 0 */ { ucrec* a = new ucrec(); - chanrec* c = chanrec::ForceChan(Instance, Ptr,a,user,created); + chanrec* c = chanrec::ForceChan(Instance, Ptr, a, user, privs); user->chans.push_back(a); return c; } @@ -350,7 +347,7 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo if (user->chans.size() < OPERMAXCHANS) { ucrec* a = new ucrec(); - chanrec* c = chanrec::ForceChan(Instance, Ptr,a,user,created); + chanrec* c = chanrec::ForceChan(Instance, Ptr, a, user, privs); user->chans.push_back(a); return c; } @@ -358,7 +355,7 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo user->WriteServ("405 %s %s :You are on too many channels",user->nick, cname); - if (created == 2) + if (new_channel) { Instance->Log(DEBUG,"BLAMMO, Whacking channel."); /* Things went seriously pear shaped, so take this away. bwahaha. */ @@ -392,18 +389,30 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo return NULL; } -chanrec* chanrec::ForceChan(InspIRCd* Instance, chanrec* Ptr,ucrec *a,userrec* user, int created) +chanrec* chanrec::ForceChan(InspIRCd* Instance, chanrec* Ptr,ucrec *a,userrec* user, const std::string &privs) { - if (created == 2) - { - /* first user in is given ops */ - a->uc_modes = UCMODE_OP; - Ptr->AddOppedUser(user); - Ptr->SetPrefix(user, '@', OP_VALUE, true); - } - else + a->uc_modes = 0; + + for (std::string::const_iterator x = privs.begin(); x != privs.end(); x++) { - a->uc_modes = 0; + const char status = *x; + switch (status) + { + case '@': + a->uc_modes = UCMODE_OP; + break; + case '%': + a->uc_modes = UCMODE_HOP; + break; + case '+': + a->uc_modes = UCMODE_VOICE; + break; + } + ModeHandler* mh = ServerInstance->Modes->FindPrefix(status); + if (mh) + { + Ptr->SetPrefix(user, status, mh->GetRank(), true); + } } a->channel = Ptr; @@ -411,6 +420,11 @@ chanrec* chanrec::ForceChan(InspIRCd* Instance, chanrec* Ptr,ucrec *a,userrec* u user->ModChannelCount(1); Ptr->WriteChannel(user,"JOIN :%s",Ptr->name); + /* Theyre not the first ones in here, make sure everyone else sees the modes we gave the user */ + std::string ms = ServerInstance->Modes->ModeString(user, channel); + if ((channel->usercount() > 1) && (ms.length())) + channel->WriteAllExceptSender(user, true, 0, "MODE %s +%s", channel->name, ms.c_str()); + /* Major improvement by Brain - we dont need to be calculating all this pointlessly for remote users */ if (IS_LOCAL(user)) { diff --git a/src/modules.cpp b/src/modules.cpp index db5a976c5..faee68075 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -113,7 +113,7 @@ void Module::OnUserJoin(userrec* user, chanrec* channel) { } void Module::OnUserPart(userrec* user, chanrec* channel, const std::string &partmessage) { } void Module::OnRehash(const std::string ¶meter) { } void Module::OnServerRaw(std::string &raw, bool inbound, userrec* user) { } -int Module::OnUserPreJoin(userrec* user, chanrec* chan, const char* cname) { return 0; } +int Module::OnUserPreJoin(userrec* user, chanrec* chan, const char* cname, std::string &privs) { return 0; } void Module::OnMode(userrec* user, void* dest, int target_type, const std::string &text) { }; Version Module::GetVersion() { return Version(1,0,0,0,VF_VENDOR); } void Module::OnOper(userrec* user, const std::string &opertype) { }; diff --git a/src/modules/extra/m_sqlv2.h b/src/modules/extra/m_sqlv2.h index 76d39a8f6..a48b9b147 100644 --- a/src/modules/extra/m_sqlv2.h +++ b/src/modules/extra/m_sqlv2.h @@ -30,6 +30,7 @@ typedef std::deque<std::string> ParamL; */ class SQLexception : public ModuleException { + public: SQLexception(const std::string &reason) : ModuleException(reason) { } diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp index 2651b4f90..fc5d824de 100644 --- a/src/modules/m_spanningtree.cpp +++ b/src/modules/m_spanningtree.cpp @@ -4495,34 +4495,17 @@ class ModuleSpanningTree : public Module // Only do this for local users if (IS_LOCAL(user)) { - char ts[24]; - snprintf(ts,24,"%lu",(unsigned long)channel->age); - std::deque<std::string> params; params.clear(); params.push_back(channel->name); - - /** XXX: The client protocol will IGNORE this parameter. - * We could make use of it if we wanted to keep the TS - * in step if somehow we lose it. - */ - params.push_back(ts); - - if (channel->GetUserCounter() > 1) - { - // not the first in the channel - DoOneToMany(user->nick,"JOIN",params); - } - else - { - // first in the channel, set up their permissions - // and the channel TS with FJOIN. - params.clear(); - params.push_back(channel->name); - params.push_back(ts); - params.push_back("@,"+std::string(user->nick)); - DoOneToMany(ServerInstance->Config->ServerName,"FJOIN",params); - } + // set up their permissions and the channel TS with FJOIN. + // All users are FJOINed now, because a module may specify + // new joining permissions for the user. + params.clear(); + params.push_back(channel->name); + params.push_back(ConvToStr(channel->age)); + params.push_back(c->GetAllPrefixChars(i->second)+","+std::string(user->nick)); + DoOneToMany(ServerInstance->Config->ServerName,"FJOIN",params); } } |