summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/message.h1
-rw-r--r--src/message.cpp18
-rw-r--r--src/modules/m_spanningtree.cpp43
3 files changed, 61 insertions, 1 deletions
diff --git a/include/message.h b/include/message.h
index a7c2c4036..fb0e7cb64 100644
--- a/include/message.h
+++ b/include/message.h
@@ -46,5 +46,6 @@ int has_channel(userrec *u, chanrec *c);
void TidyBan(char *ban);
std::string chlist(userrec *user, userrec* source);
void send_network_quit(const char* nick, const char* reason);
+int cflags(userrec *user, chanrec *chan);
#endif
diff --git a/src/message.cpp b/src/message.cpp
index 0f49f9a0a..d071b13f0 100644
--- a/src/message.cpp
+++ b/src/message.cpp
@@ -325,6 +325,24 @@ char* cmode(userrec *user, chanrec *chan)
return "";
}
+int cflags(userrec *user, chanrec *chan)
+{
+ if ((!chan) || (!user))
+ return 0;
+
+ for (unsigned int i = 0; i < user->chans.size(); i++)
+ {
+ if (user->chans[i].channel)
+ {
+ if ((!strcasecmp(user->chans[i].channel->name,chan->name)) && (chan != NULL))
+ {
+ return user->chans[i].uc_modes;
+ }
+ }
+ }
+ return 0;
+}
+
/* returns the status value for a given user on a channel, e.g. STATUS_OP for
* op, STATUS_VOICE for voice etc. If the user has several modes set, the
* highest mode the user has must be returned. */
diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp
index a95d40b2f..060c4c39b 100644
--- a/src/modules/m_spanningtree.cpp
+++ b/src/modules/m_spanningtree.cpp
@@ -1129,26 +1129,67 @@ class TreeSocket : public InspSocket
{
log(DEBUG,"Sending FJOINs to other server for %s",c->name);
char list[MAXBUF];
+ std::string individual_halfops = ":"+Srv->GetServerName()+" FMODE "+c->name;
snprintf(list,MAXBUF,":%s FJOIN %s %lu",Srv->GetServerName().c_str(),c->name,(unsigned long)c->age);
std::map<char*,char*> *ulist = c->GetUsers();
+ std::vector<userrec*> specific_halfop;
+ std::vector<userrec*> specific_voice;
for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
{
char* o = i->second;
userrec* otheruser = (userrec*)o;
strlcat(list," ",MAXBUF);
- strlcat(list,cmode(otheruser,c),MAXBUF);
+ int x = cflags(otheruser,c);
+ if ((x & UCMODE_HOP) && (x & UCMODE_OP))
+ {
+ specific_halfop.push_back(otheruser);
+ }
+ if (((x & UCMODE_HOP) || (x & UCMODE_OP)) && (x & UCMODE_VOICE))
+ {
+ specific_voice.push_back(otheruser);
+ }
+ char* n = "";
+ if (x & UCMODE_OP)
+ {
+ n = "@";
+ }
+ else if (x & UCMODE_HOP)
+ {
+ n = "%";
+ }
+ else if (x & UCMODE_VOICE)
+ {
+ n = "+";
+ }
+ strlcat(list,n,MAXBUF);
strlcat(list,otheruser->nick,MAXBUF);
if (strlen(list)>(480-NICKMAX))
{
log(DEBUG,"FJOIN line wrapped");
this->WriteLine(list);
snprintf(list,MAXBUF,":%s FJOIN %s %lu",Srv->GetServerName().c_str(),c->name,(unsigned long)c->age);
+ for (unsigned int y = 0; y < specific_voice.size(); y++)
+ {
+ this->WriteLine(":"+Srv->GetServerName()+" FMODE "+c->name+" +v "+specific_voice[y]->nick);
+ }
+ for (unsigned int y = 0; y < specific_halfop.size(); y++)
+ {
+ this->WriteLine(":"+Srv->GetServerName()+" FMODE "+c->name+" +h "+specific_halfop[y]->nick);
+ }
}
}
if (list[strlen(list)-1] != ':')
{
log(DEBUG,"Final FJOIN line");
this->WriteLine(list);
+ for (unsigned int y = 0; y < specific_voice.size(); y++)
+ {
+ this->WriteLine(":"+Srv->GetServerName()+" FMODE "+c->name+" +v "+specific_voice[y]->nick);
+ }
+ for (unsigned int y = 0; y < specific_halfop.size(); y++)
+ {
+ this->WriteLine(":"+Srv->GetServerName()+" FMODE "+c->name+" +h "+specific_halfop[y]->nick);
+ }
}
}