summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/channels.h2
-rw-r--r--include/modules.h7
-rw-r--r--src/channels.cpp62
-rw-r--r--src/modules.cpp2
-rw-r--r--src/modules/extra/m_sqlv2.h1
-rw-r--r--src/modules/m_spanningtree.cpp33
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 &parameter) { }
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);
}
}