mirror of
https://github.com/matrix-construct/construct
synced 2024-12-25 23:14:13 +01:00
Upgrade channel membership lists.
This commit is contained in:
parent
276cad4275
commit
5752be41b8
33 changed files with 447 additions and 394 deletions
|
@ -52,7 +52,7 @@ m_findforwards(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *
|
|||
/* Allow ircops to search for forwards to nonexistent channels */
|
||||
if(!IsOper(source_p))
|
||||
{
|
||||
if((chptr = find_channel(parv[1])) == NULL || (msptr = find_channel_membership(chptr, source_p)) == NULL)
|
||||
if((chptr = find_channel(parv[1])) == NULL || (msptr = get(chptr->members, *source_p, std::nothrow)) == NULL)
|
||||
{
|
||||
sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
|
||||
form_str(ERR_NOTONCHANNEL), parv[1]);
|
||||
|
|
|
@ -84,7 +84,7 @@ mo_ojoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
|
||||
if(*parv[1] == '@')
|
||||
{
|
||||
add_user_to_channel(chptr, source_p, chan::CHANOP);
|
||||
add(*chptr, *source_p, chan::CHANOP);
|
||||
sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
|
||||
":%s SJOIN %ld %s + :@%s",
|
||||
me.id, (long) chptr->channelts, chptr->name.c_str(), source_p->id);
|
||||
|
@ -95,7 +95,7 @@ mo_ojoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
}
|
||||
else if(*parv[1] == '+')
|
||||
{
|
||||
add_user_to_channel(chptr, source_p, chan::VOICE);
|
||||
add(*chptr, *source_p, chan::VOICE);
|
||||
sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
|
||||
":%s SJOIN %ld %s + :+%s",
|
||||
me.id, (long) chptr->channelts, chptr->name.c_str(), source_p->id);
|
||||
|
@ -105,7 +105,7 @@ mo_ojoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
}
|
||||
else
|
||||
{
|
||||
add_user_to_channel(chptr, source_p, chan::PEON);
|
||||
add(*chptr, *source_p, chan::PEON);
|
||||
sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
|
||||
":%s JOIN %ld %s +",
|
||||
source_p->id, (long) chptr->channelts, chptr->name.c_str());
|
||||
|
|
|
@ -97,7 +97,7 @@ mo_okick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
return;
|
||||
}
|
||||
|
||||
if((msptr = find_channel_membership(chptr, target_p)) == NULL)
|
||||
if((msptr = get(chptr->members, *target_p, std::nothrow)) == NULL)
|
||||
{
|
||||
sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL), parv[1], parv[2]);
|
||||
return;
|
||||
|
@ -120,5 +120,6 @@ mo_okick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
me.name, chptr->name.c_str(), who->name, comment);
|
||||
sendto_server(&me, chptr, CAP_TS6, NOCAPS,
|
||||
":%s KICK %s %s :%s", me.id, chptr->name.c_str(), who->id, comment);
|
||||
remove_user_from_channel(msptr);
|
||||
|
||||
del(*chptr, *target_p);
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ mo_omode(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
}
|
||||
|
||||
/* Now know the channel exists */
|
||||
msptr = find_channel_membership(chptr, source_p);
|
||||
msptr = get(chptr->members, *source_p, std::nothrow);
|
||||
wasonchannel = msptr != NULL;
|
||||
|
||||
if (is_chanop(msptr))
|
||||
|
@ -133,8 +133,8 @@ mo_omode(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
msptr->flags |= chan::CHANOP;
|
||||
else
|
||||
{
|
||||
add_user_to_channel(chptr, source_p, chan::CHANOP);
|
||||
msptr = find_channel_membership(chptr, source_p);
|
||||
add(*chptr, *source_p, chan::CHANOP);
|
||||
msptr = get(chptr->members, *source_p, std::nothrow);
|
||||
}
|
||||
set_channel_mode(client_p, source_p, chptr, msptr,
|
||||
parc - 2, parv + 2);
|
||||
|
@ -144,7 +144,7 @@ mo_omode(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
if (wasonchannel)
|
||||
msptr->flags &= ~chan::CHANOP;
|
||||
else
|
||||
remove_user_from_channel(msptr);
|
||||
del(*chptr, get_client(*msptr));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -57,9 +57,9 @@ mo_opme(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
|
|||
return;
|
||||
}
|
||||
|
||||
RB_DLINK_FOREACH(ptr, chptr->members.head)
|
||||
for(auto &pit : chptr->members.global)
|
||||
{
|
||||
msptr = (chan::membership *)ptr->data;
|
||||
msptr = &pit.second;
|
||||
|
||||
if(is_chanop(msptr))
|
||||
{
|
||||
|
@ -68,7 +68,7 @@ mo_opme(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
|
|||
}
|
||||
}
|
||||
|
||||
msptr = find_channel_membership(chptr, source_p);
|
||||
msptr = get(chptr->members, *source_p, std::nothrow);
|
||||
|
||||
if(msptr == NULL)
|
||||
return;
|
||||
|
|
|
@ -80,7 +80,7 @@ m_remove(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
|
||||
if(!IsServer(source_p))
|
||||
{
|
||||
msptr = find_channel_membership(chptr, source_p);
|
||||
msptr = get(chptr->members, *source_p, std::nothrow);
|
||||
|
||||
if((msptr == NULL) && MyConnect(source_p))
|
||||
{
|
||||
|
@ -139,7 +139,7 @@ m_remove(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
return;
|
||||
}
|
||||
|
||||
msptr = find_channel_membership(chptr, who);
|
||||
msptr = get(chptr->members, *who, std::nothrow);
|
||||
|
||||
if(msptr != NULL)
|
||||
{
|
||||
|
@ -190,7 +190,7 @@ m_remove(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
":%s KICK %s %s :%s",
|
||||
use_id(source_p), chptr->name.c_str(), use_id(who), comment);
|
||||
|
||||
remove_user_from_channel(msptr);
|
||||
del(*chptr, get_client(*msptr));
|
||||
}
|
||||
else if (MyClient(source_p))
|
||||
sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
|
||||
|
|
|
@ -140,7 +140,7 @@ m_displaymsg(struct MsgBuf *msgbuf_p, struct Client *source_p, const char *chann
|
|||
return;
|
||||
}
|
||||
|
||||
if(!(msptr = find_channel_membership(chptr, source_p)))
|
||||
if(!(msptr = get(chptr->members, *source_p, std::nothrow)))
|
||||
{
|
||||
sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
|
||||
form_str(ERR_NOTONCHANNEL), chptr->name.c_str());
|
||||
|
|
|
@ -43,7 +43,7 @@ h_scc_channel_join(void *vdata)
|
|||
struct Client *source_p = data->client;
|
||||
|
||||
/* If they just joined a channel, and it only has one member, then they just created it. */
|
||||
if(rb_dlink_list_length(&chptr->members) == 1 && is_chanop(find_channel_membership(chptr, source_p)))
|
||||
if(size(chptr->members) == 1 && is_chanop(get(chptr->members, *source_p, std::nothrow)))
|
||||
{
|
||||
sendto_realops_snomask(snomask_modes['l'], L_NETWIDE, "%s is creating new channel %s",
|
||||
source_p->name, chptr->name.c_str());
|
||||
|
|
|
@ -165,11 +165,10 @@ int chans_add(struct chan *const chan)
|
|||
if(!rb_radixtree_add(chans, chan->name.c_str(), chan))
|
||||
return 0;
|
||||
|
||||
rb_dlink_node *ptr;
|
||||
RB_DLINK_FOREACH(ptr, chan->members.head)
|
||||
for(const auto &pit : chan->members.global)
|
||||
{
|
||||
const auto msptr(reinterpret_cast<membership *>(ptr->data));
|
||||
bloom_add_str(msptr->client->name);
|
||||
const auto &client(pit.first);
|
||||
bloom_add_str(client->name);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace chan {
|
|||
IRCD_EXCEPTION(ircd::error, error)
|
||||
IRCD_EXCEPTION(error, not_found)
|
||||
IRCD_EXCEPTION(error, invalid_list)
|
||||
IRCD_EXCEPTION(error, invalid_argument)
|
||||
|
||||
enum status
|
||||
{
|
||||
|
@ -96,17 +97,15 @@ uint operator~(const modes &);
|
|||
|
||||
struct membership
|
||||
{
|
||||
rb_dlink_node channode;
|
||||
rb_dlink_node locchannode;
|
||||
rb_dlink_node usernode;
|
||||
|
||||
struct chan *chan;
|
||||
Client *client;
|
||||
unsigned int flags;
|
||||
using global = std::map<client *, membership>;
|
||||
using local = std::list<membership *>;
|
||||
|
||||
uint flags;
|
||||
time_t bants;
|
||||
global::iterator git;
|
||||
local::iterator lit;
|
||||
|
||||
membership();
|
||||
membership(const uint &flags = 0);
|
||||
~membership() noexcept;
|
||||
};
|
||||
|
||||
|
@ -119,6 +118,27 @@ bool is_chanop_voiced(const membership *const &);
|
|||
bool can_send_banned(const membership &);
|
||||
bool can_send_banned(const membership *const &);
|
||||
const char *find_status(const membership *const &msptr, const int &combine);
|
||||
const client &get_client(const membership &);
|
||||
client &get_client(membership &);
|
||||
|
||||
struct members
|
||||
{
|
||||
membership::global global;
|
||||
membership::local local;
|
||||
|
||||
members();
|
||||
~members() noexcept;
|
||||
};
|
||||
|
||||
bool empty(const members &);
|
||||
size_t size(const members &);
|
||||
bool local_empty(const members &);
|
||||
size_t local_size(const members &);
|
||||
bool exists(const members &, const client &);
|
||||
const membership *get(const members &, const client &, std::nothrow_t);
|
||||
const membership &get(const members &, const client &);
|
||||
membership *get(members &, const client &, std::nothrow_t);
|
||||
membership &get(members &, const client &);
|
||||
|
||||
bool has_prefix(const char *const &name);
|
||||
bool has_prefix(const std::string &name);
|
||||
|
@ -131,11 +151,8 @@ struct chan
|
|||
struct modes mode;
|
||||
std::string mode_lock;
|
||||
struct topic topic;
|
||||
|
||||
rb_dlink_list members;
|
||||
rb_dlink_list locmembers;
|
||||
struct members members;
|
||||
std::set<client *> invites;
|
||||
|
||||
list bans;
|
||||
list excepts;
|
||||
list invexs;
|
||||
|
@ -160,6 +177,7 @@ struct chan
|
|||
~chan() noexcept;
|
||||
};
|
||||
|
||||
const auto &name(const chan &);
|
||||
bool is_secret(const chan &);
|
||||
bool is_secret(const chan *const &);
|
||||
bool is_hidden(const chan &);
|
||||
|
@ -206,9 +224,6 @@ void del_invite(chan &, client &);
|
|||
void clear_invites(chan &);
|
||||
|
||||
bool flood_attack_channel(int p_or_n, client *source, chan *);
|
||||
void add_user_to_channel(chan *, client *, int flags);
|
||||
void remove_user_from_channel(membership *);
|
||||
void remove_user_from_channels(client *);
|
||||
void invalidate_bancache_user(client *);
|
||||
void channel_member_names(chan *, client *, int show_eon);
|
||||
const char *channel_modes(chan *, client *who);
|
||||
|
@ -227,13 +242,17 @@ int match_extban(const char *banstr, client *, chan *, long mode_type);
|
|||
int valid_extban(const char *banstr, client *, chan *, long mode_type);
|
||||
const char * get_extban_string(void);
|
||||
int get_channel_access(client *source, chan *, membership *, int dir, const char *modestr);
|
||||
membership *find_channel_membership(chan *chptr, client *client_p);
|
||||
void send_join(chan &, client &);
|
||||
|
||||
//extern std::map<std::string, std::unique_ptr<chan>> chans;
|
||||
extern rb_dlink_list global_channel_list;
|
||||
|
||||
// Add and remove clients from channels
|
||||
void add(chan &, client &, const int &flags = PEON);
|
||||
void del(chan &, client &);
|
||||
void del(client &); // remove from all channels
|
||||
|
||||
// Initialize subsystem
|
||||
void init();
|
||||
|
||||
|
||||
|
@ -276,8 +295,7 @@ is_public(const chan *const &c)
|
|||
inline bool
|
||||
is_member(const chan &c, const client &client)
|
||||
{
|
||||
//return client.user && get(c, client, std::nothrow) != nullptr;
|
||||
return find_channel_membership(const_cast<struct chan *>(&c), const_cast<Client *>(&client)) != nullptr;
|
||||
return exists(c.members, client);
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
@ -322,6 +340,42 @@ valid_name(const std::string &name)
|
|||
return !name.empty() && std::all_of(begin(name), end(name), rfc1459::is_chan);
|
||||
}
|
||||
|
||||
inline const auto &
|
||||
name(const chan &chan)
|
||||
{
|
||||
return chan.name;
|
||||
}
|
||||
|
||||
inline size_t
|
||||
local_size(const members &m)
|
||||
{
|
||||
return std::distance(begin(m.local), end(m.local));
|
||||
}
|
||||
|
||||
inline bool
|
||||
local_empty(const members &m)
|
||||
{
|
||||
return m.local.empty();
|
||||
}
|
||||
|
||||
inline size_t
|
||||
size(const members &m)
|
||||
{
|
||||
return m.global.size();
|
||||
}
|
||||
|
||||
inline bool
|
||||
empty(const members &m)
|
||||
{
|
||||
return m.global.empty();
|
||||
}
|
||||
|
||||
inline bool
|
||||
exists(const members &m, const client &c)
|
||||
{
|
||||
return m.global.count(const_cast<client *>(&c));
|
||||
}
|
||||
|
||||
inline bool
|
||||
is_chanop(const membership &m)
|
||||
{
|
||||
|
@ -358,6 +412,18 @@ is_chanop_voiced(const membership *const &m)
|
|||
return m && is_chanop_voiced(*m);
|
||||
}
|
||||
|
||||
inline client &
|
||||
get_client(membership &m)
|
||||
{
|
||||
return *m.git->first;
|
||||
}
|
||||
|
||||
inline const client &
|
||||
get_client(const membership &m)
|
||||
{
|
||||
return *m.git->first;
|
||||
}
|
||||
|
||||
inline bool
|
||||
can_send_banned(const membership &m)
|
||||
{
|
||||
|
|
|
@ -68,7 +68,7 @@ typedef int SSL_OPEN_CB(struct Client *, int status);
|
|||
*/
|
||||
struct User
|
||||
{
|
||||
rb_dlink_list channel; /* chain of channel pointer blocks */
|
||||
std::map<chan::chan *, chan::membership *> channel;
|
||||
std::set<chan::chan *> invited;
|
||||
char *away; /* pointer to away message */
|
||||
int refcnt; /* Number of times this block is referenced */
|
||||
|
|
346
ircd/channel.cc
346
ircd/channel.cc
|
@ -49,8 +49,7 @@ chan::chan::chan(const std::string &name)
|
|||
,mode{}
|
||||
,mode_lock{}
|
||||
,topic{}
|
||||
,members{0}
|
||||
,locmembers{0}
|
||||
,members{}
|
||||
,join_count{0}
|
||||
,join_delta{0}
|
||||
,flood_noticed{0}
|
||||
|
@ -74,13 +73,108 @@ noexcept
|
|||
del_from_channel_hash(name.c_str(), this);
|
||||
}
|
||||
|
||||
chan::membership::membership()
|
||||
:channode{0}
|
||||
,locchannode{0}
|
||||
,usernode{0}
|
||||
,chan{nullptr}
|
||||
,client{nullptr}
|
||||
,flags{0}
|
||||
/* remove_user_from_channels()
|
||||
*
|
||||
* input - user to remove from all channels
|
||||
* output -
|
||||
* side effects - user is removed from all channels
|
||||
*/
|
||||
void
|
||||
chan::del(client &client)
|
||||
{
|
||||
auto &client_chans(client.user->channel);
|
||||
for(const auto &pit : client_chans)
|
||||
{
|
||||
auto &chan(*pit.first);
|
||||
auto &member(*pit.second);
|
||||
|
||||
if (my(client))
|
||||
chan.members.local.erase(member.lit);
|
||||
|
||||
chan.members.global.erase(member.git);
|
||||
chan.invites.erase(&client);
|
||||
|
||||
if (empty(chan.members) && ~chan.mode & mode::PERMANENT)
|
||||
delete &chan;
|
||||
}
|
||||
|
||||
client_chans.clear();
|
||||
client.user->invited.clear();
|
||||
}
|
||||
|
||||
void
|
||||
chan::del(chan &chan,
|
||||
client &client)
|
||||
{
|
||||
// These are the relevant containers.
|
||||
auto &global(chan.members.global);
|
||||
auto &local(chan.members.local);
|
||||
auto &client_chans(client.user->channel);
|
||||
|
||||
const auto it(client_chans.find(&chan));
|
||||
if (it == end(client_chans))
|
||||
return;
|
||||
|
||||
auto &member(*it->second);
|
||||
|
||||
if (my(client))
|
||||
chan.members.local.erase(member.lit);
|
||||
|
||||
chan.members.global.erase(member.git); // The member is destroyed at this point.
|
||||
client_chans.erase(it);
|
||||
|
||||
if (empty(chan.members) && ~chan.mode & mode::PERMANENT)
|
||||
delete &chan;
|
||||
}
|
||||
|
||||
void
|
||||
chan::add(chan &chan,
|
||||
client &client,
|
||||
const int &flags)
|
||||
{
|
||||
if (!client.user)
|
||||
{
|
||||
s_assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// These are the relevant containers.
|
||||
auto &global(chan.members.global);
|
||||
auto &local(chan.members.local);
|
||||
auto &client_chans(client.user->channel);
|
||||
|
||||
// Add client to channel's global map
|
||||
const auto iit(global.emplace(&client, flags));
|
||||
if (!iit.second)
|
||||
return;
|
||||
|
||||
// The global map hosts the membership structure.
|
||||
auto &member(iit.first->second);
|
||||
|
||||
// Add iterator (pointer to the element) for constant time lookup/removal
|
||||
member.git = iit.first;
|
||||
|
||||
// Add channel to client's channel map, pointing to the membership;
|
||||
client_chans.emplace(&chan, &member);
|
||||
|
||||
// Add membership to a local list which can be iterated for local IO;
|
||||
// iterator to this element is saved more crucially here to prevent linear removal
|
||||
if (my(client))
|
||||
member.lit = local.emplace(end(local), &member);
|
||||
}
|
||||
|
||||
|
||||
chan::members::members()
|
||||
{
|
||||
}
|
||||
|
||||
chan::members::~members()
|
||||
noexcept
|
||||
{
|
||||
}
|
||||
|
||||
chan::membership::membership(const uint &flags)
|
||||
:flags{flags}
|
||||
,bants{0}
|
||||
{
|
||||
}
|
||||
|
@ -144,46 +238,66 @@ chan::send_join(chan &chan,
|
|||
client.user->away);
|
||||
}
|
||||
|
||||
/* find_channel_membership()
|
||||
*
|
||||
* input - channel to find them in, client to find
|
||||
* output - membership of client in channel, else NULL
|
||||
* side effects -
|
||||
*/
|
||||
chan::membership *
|
||||
chan::find_channel_membership(chan *chptr, client *client_p)
|
||||
chan::membership &
|
||||
chan::get(members &members,
|
||||
const client &client)
|
||||
{
|
||||
struct membership *msptr;
|
||||
rb_dlink_node *ptr;
|
||||
if (!is_client(client))
|
||||
throw invalid_argument();
|
||||
|
||||
if(!IsClient(client_p))
|
||||
return NULL;
|
||||
const auto key(const_cast<ircd::chan::client *>(&client)); //TODO: temp elaborated
|
||||
const auto it(members.global.find(key));
|
||||
if (it == end(members.global))
|
||||
throw not_found();
|
||||
|
||||
/* Pick the most efficient list to use to be nice to things like
|
||||
* CHANSERV which could be in a large number of channels
|
||||
*/
|
||||
if(rb_dlink_list_length(&chptr->members) < rb_dlink_list_length(&client_p->user->channel))
|
||||
{
|
||||
RB_DLINK_FOREACH(ptr, chptr->members.head)
|
||||
{
|
||||
msptr = (membership *)ptr->data;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
if(msptr->client == client_p)
|
||||
return msptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
|
||||
{
|
||||
msptr = (membership *)ptr->data;
|
||||
const chan::membership &
|
||||
chan::get(const members &members,
|
||||
const client &client)
|
||||
{
|
||||
if (!is_client(client))
|
||||
throw invalid_argument();
|
||||
|
||||
if(msptr->chan == chptr)
|
||||
return msptr;
|
||||
}
|
||||
}
|
||||
const auto key(const_cast<ircd::chan::client *>(&client)); //TODO: temp elaborated
|
||||
const auto it(members.global.find(key));
|
||||
if (it == end(members.global))
|
||||
throw not_found();
|
||||
|
||||
return NULL;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
chan::membership *
|
||||
chan::get(members &members,
|
||||
const client &client,
|
||||
std::nothrow_t)
|
||||
{
|
||||
if (!is_client(client))
|
||||
return nullptr;
|
||||
|
||||
const auto key(const_cast<ircd::chan::client *>(&client)); //TODO: temp elaborated
|
||||
const auto it(members.global.find(key));
|
||||
if (it == end(members.global))
|
||||
return nullptr;
|
||||
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
const chan::membership *
|
||||
chan::get(const members &members,
|
||||
const client &client,
|
||||
std::nothrow_t)
|
||||
{
|
||||
if (!is_client(client))
|
||||
return nullptr;
|
||||
|
||||
const auto key(const_cast<ircd::chan::client *>(&client)); //TODO: temp elaborated
|
||||
const auto it(members.global.find(key));
|
||||
if (it == end(members.global))
|
||||
return nullptr;
|
||||
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
/* find_channel_status()
|
||||
|
@ -215,102 +329,6 @@ chan::find_status(const membership *const &msptr,
|
|||
return buffer;
|
||||
}
|
||||
|
||||
/* add_user_to_channel()
|
||||
*
|
||||
* input - channel to add client to, client to add, channel flags
|
||||
* output -
|
||||
* side effects - user is added to channel
|
||||
*/
|
||||
void
|
||||
chan::add_user_to_channel(chan *chptr, client *client_p, int flags)
|
||||
{
|
||||
membership *msptr;
|
||||
|
||||
s_assert(client_p->user != NULL);
|
||||
if(client_p->user == NULL)
|
||||
return;
|
||||
|
||||
msptr = new membership;
|
||||
|
||||
msptr->chan = chptr;
|
||||
msptr->client = client_p;
|
||||
msptr->flags = flags;
|
||||
|
||||
rb_dlinkAdd(msptr, &msptr->usernode, &client_p->user->channel);
|
||||
rb_dlinkAdd(msptr, &msptr->channode, &chptr->members);
|
||||
|
||||
if(MyClient(client_p))
|
||||
rb_dlinkAdd(msptr, &msptr->locchannode, &chptr->locmembers);
|
||||
}
|
||||
|
||||
/* remove_user_from_channel()
|
||||
*
|
||||
* input - membership pointer to remove from channel
|
||||
* output -
|
||||
* side effects - membership (thus user) is removed from channel
|
||||
*/
|
||||
void
|
||||
chan::remove_user_from_channel(membership *msptr)
|
||||
{
|
||||
client *client_p;
|
||||
chan *chptr;
|
||||
s_assert(msptr != NULL);
|
||||
if(msptr == NULL)
|
||||
return;
|
||||
|
||||
client_p = msptr->client;
|
||||
chptr = msptr->chan;
|
||||
|
||||
rb_dlinkDelete(&msptr->usernode, &client_p->user->channel);
|
||||
rb_dlinkDelete(&msptr->channode, &chptr->members);
|
||||
|
||||
if(client_p->servptr == &me)
|
||||
rb_dlinkDelete(&msptr->locchannode, &chptr->locmembers);
|
||||
|
||||
if(!(chptr->mode.mode & mode::PERMANENT) && rb_dlink_list_length(&chptr->members) <= 0)
|
||||
delete chptr;
|
||||
|
||||
delete msptr;
|
||||
return;
|
||||
}
|
||||
|
||||
/* remove_user_from_channels()
|
||||
*
|
||||
* input - user to remove from all channels
|
||||
* output -
|
||||
* side effects - user is removed from all channels
|
||||
*/
|
||||
void
|
||||
chan::remove_user_from_channels(client *client_p)
|
||||
{
|
||||
chan *chptr;
|
||||
membership *msptr;
|
||||
rb_dlink_node *ptr;
|
||||
rb_dlink_node *next_ptr;
|
||||
|
||||
if(client_p == NULL)
|
||||
return;
|
||||
|
||||
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->user->channel.head)
|
||||
{
|
||||
msptr = (membership *)ptr->data;
|
||||
chptr = msptr->chan;
|
||||
|
||||
rb_dlinkDelete(&msptr->channode, &chptr->members);
|
||||
|
||||
if(client_p->servptr == &me)
|
||||
rb_dlinkDelete(&msptr->locchannode, &chptr->locmembers);
|
||||
|
||||
if(!(chptr->mode.mode & mode::PERMANENT) && rb_dlink_list_length(&chptr->members) <= 0)
|
||||
delete chptr;
|
||||
|
||||
delete msptr;
|
||||
}
|
||||
|
||||
client_p->user->channel.head = client_p->user->channel.tail = NULL;
|
||||
client_p->user->channel.length = 0;
|
||||
}
|
||||
|
||||
/* invalidate_bancache_user()
|
||||
*
|
||||
* input - user to invalidate ban cache for
|
||||
|
@ -319,19 +337,17 @@ chan::remove_user_from_channels(client *client_p)
|
|||
* to be used after a nick change
|
||||
*/
|
||||
void
|
||||
chan::invalidate_bancache_user(client *client_p)
|
||||
chan::invalidate_bancache_user(client *client)
|
||||
{
|
||||
membership *msptr;
|
||||
rb_dlink_node *ptr;
|
||||
|
||||
if(client_p == NULL)
|
||||
if(!client)
|
||||
return;
|
||||
|
||||
RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
|
||||
for(const auto &pair : client->user->channel)
|
||||
{
|
||||
msptr = (membership *)ptr->data;
|
||||
msptr->bants = 0;
|
||||
msptr->flags &= ~BANNED;
|
||||
auto &chan(*pair.first);
|
||||
auto &member(*pair.second);
|
||||
member.bants = 0;
|
||||
member.flags &= ~BANNED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -358,7 +374,6 @@ channel_pub_or_secret(chan::chan *const &chptr)
|
|||
void
|
||||
chan::channel_member_names(chan *chptr, client *client_p, int show_eon)
|
||||
{
|
||||
membership *msptr;
|
||||
client *target_p;
|
||||
rb_dlink_node *ptr;
|
||||
char lbuf[BUFSIZE];
|
||||
|
@ -376,10 +391,10 @@ chan::channel_member_names(chan *chptr, client *client_p, int show_eon)
|
|||
|
||||
t = lbuf + cur_len;
|
||||
|
||||
RB_DLINK_FOREACH(ptr, chptr->members.head)
|
||||
for(const auto &pair : chptr->members.global)
|
||||
{
|
||||
msptr = (membership *)ptr->data;
|
||||
target_p = msptr->client;
|
||||
auto *const target_p(pair.first);
|
||||
const auto &member(pair.second);
|
||||
|
||||
if(IsInvisible(target_p) && !is_member(chptr, client_p))
|
||||
continue;
|
||||
|
@ -395,7 +410,7 @@ chan::channel_member_names(chan *chptr, client *client_p, int show_eon)
|
|||
t = lbuf + mlen;
|
||||
}
|
||||
|
||||
tlen = sprintf(t, "%s%s!%s@%s ", find_status(msptr, stack),
|
||||
tlen = sprintf(t, "%s%s!%s@%s ", find_status(&member, stack),
|
||||
target_p->name, target_p->username, target_p->host);
|
||||
}
|
||||
else
|
||||
|
@ -409,7 +424,7 @@ chan::channel_member_names(chan *chptr, client *client_p, int show_eon)
|
|||
t = lbuf + mlen;
|
||||
}
|
||||
|
||||
tlen = sprintf(t, "%s%s ", find_status(msptr, stack),
|
||||
tlen = sprintf(t, "%s%s ", find_status(&member, stack),
|
||||
target_p->name);
|
||||
}
|
||||
|
||||
|
@ -733,8 +748,7 @@ chan::can_join(client *source_p, chan *chptr, const char *key, const char **forw
|
|||
}
|
||||
}
|
||||
|
||||
if(chptr->mode.limit &&
|
||||
rb_dlink_list_length(&chptr->members) >= (unsigned long) chptr->mode.limit)
|
||||
if(chptr->mode.limit && size(chptr->members) >= ulong(chptr->mode.limit))
|
||||
i = ERR_CHANNELISFULL;
|
||||
if(chptr->mode.mode & mode::REGONLY && EmptyString(source_p->user->suser))
|
||||
i = ERR_NEEDREGGEDNICK;
|
||||
|
@ -783,7 +797,7 @@ chan::can_send(chan *chptr, client *source_p, membership *msptr)
|
|||
|
||||
if(msptr == NULL)
|
||||
{
|
||||
msptr = find_channel_membership(chptr, source_p);
|
||||
msptr = get(chptr->members, *source_p, std::nothrow);
|
||||
|
||||
if(msptr == NULL)
|
||||
{
|
||||
|
@ -828,7 +842,7 @@ chan::can_send(chan *chptr, client *source_p, membership *msptr)
|
|||
moduledata.approved = CAN_SEND_OPV;
|
||||
|
||||
moduledata.client = source_p;
|
||||
moduledata.chptr = msptr->chan;
|
||||
moduledata.chptr = chptr;
|
||||
moduledata.msptr = msptr;
|
||||
moduledata.target = NULL;
|
||||
moduledata.dir = moduledata.approved == CAN_SEND_NO? MODE_ADD : MODE_QUERY;
|
||||
|
@ -913,10 +927,11 @@ chan::find_bannickchange_channel(client *client_p)
|
|||
sprintf(src_host, "%s!%s@%s", client_p->name, client_p->username, client_p->host);
|
||||
sprintf(src_iphost, "%s!%s@%s", client_p->name, client_p->username, client_p->sockhost);
|
||||
|
||||
RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
|
||||
for(const auto &pit : client_p->user->channel)
|
||||
{
|
||||
msptr = (membership *)ptr->data;
|
||||
chptr = msptr->chan;
|
||||
auto &chptr(pit.first);
|
||||
auto &msptr(pit.second);
|
||||
|
||||
if (is_chanop_voiced(msptr))
|
||||
continue;
|
||||
/* cached can_send */
|
||||
|
@ -1270,10 +1285,11 @@ chan::resv_chan_forcepart(const char *name, const char *reason, int temp_time)
|
|||
chptr = find_channel(name);
|
||||
if(chptr != NULL)
|
||||
{
|
||||
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
|
||||
// Iterate a copy of the local list while all of this is going on
|
||||
auto local(chptr->members.local);
|
||||
for(auto &msptr : local)
|
||||
{
|
||||
msptr = (membership *)ptr->data;
|
||||
target_p = msptr->client;
|
||||
const auto target_p(msptr->git->first);
|
||||
|
||||
if(IsExemptResv(target_p))
|
||||
continue;
|
||||
|
@ -1285,7 +1301,7 @@ chan::resv_chan_forcepart(const char *name, const char *reason, int temp_time)
|
|||
target_p->name, target_p->username,
|
||||
target_p->host, chptr->name.c_str(), target_p->name);
|
||||
|
||||
remove_user_from_channel(msptr);
|
||||
del(*chptr, *target_p);
|
||||
|
||||
/* notify opers & user they were removed from the channel */
|
||||
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||
|
|
|
@ -409,8 +409,7 @@ pretty_mask(const char *idmask)
|
|||
* side effects - numeric sent if not allowed
|
||||
*/
|
||||
static bool
|
||||
check_forward(struct Client *source_p, chan::chan *chptr,
|
||||
const char *forward)
|
||||
check_forward(Client *source_p, chan::chan *chptr, const char *forward)
|
||||
{
|
||||
chan::chan *targptr = NULL;
|
||||
chan::membership *msptr;
|
||||
|
@ -436,11 +435,13 @@ check_forward(struct Client *source_p, chan::chan *chptr,
|
|||
}
|
||||
if(MyClient(source_p) && !(targptr->mode.mode & mode::FREETARGET))
|
||||
{
|
||||
if((msptr = find_channel_membership(targptr, source_p)) == NULL ||
|
||||
chan::get_channel_access(source_p, targptr, msptr, MODE_QUERY, NULL) < chan::CHANOP)
|
||||
auto *const msptr(get(targptr->members, *source_p, std::nothrow));
|
||||
if(!msptr || get_channel_access(source_p, targptr, msptr, MODE_QUERY, NULL) < chan::CHANOP)
|
||||
{
|
||||
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
|
||||
me.name, source_p->name, targptr->name.c_str());
|
||||
me.name,
|
||||
source_p->name,
|
||||
targptr->name.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -954,7 +955,7 @@ mode::functor::op(client *source_p, chan *chptr,
|
|||
return;
|
||||
}
|
||||
|
||||
mstptr = find_channel_membership(chptr, targ_p);
|
||||
mstptr = get(chptr->members, *targ_p, std::nothrow);
|
||||
|
||||
if(mstptr == NULL)
|
||||
{
|
||||
|
@ -1030,7 +1031,7 @@ mode::functor::voice(client *source_p, chan *chptr,
|
|||
return;
|
||||
}
|
||||
|
||||
mstptr = find_channel_membership(chptr, targ_p);
|
||||
mstptr = get(chptr->members, *targ_p, std::nothrow);
|
||||
|
||||
if(mstptr == NULL)
|
||||
{
|
||||
|
|
|
@ -1265,10 +1265,10 @@ exit_generic_client(struct Client *client_p, struct Client *source_p, struct Cli
|
|||
source_p->name,
|
||||
source_p->username, source_p->host, comment);
|
||||
|
||||
chan::remove_user_from_channels(source_p);
|
||||
chan::del(*source_p);
|
||||
|
||||
/* Should not be in any channels now */
|
||||
s_assert(source_p->user->channel.head == NULL);
|
||||
s_assert(source_p->user->channel.empty());
|
||||
|
||||
// Clean up invitefield
|
||||
for (auto &chan : source_p->user->invited)
|
||||
|
@ -1839,10 +1839,10 @@ free_user(struct User *user, struct Client *client_p)
|
|||
/*
|
||||
* sanity check
|
||||
*/
|
||||
if(user->refcnt < 0 || !user->invited.empty() || user->channel.head)
|
||||
if(user->refcnt < 0 || !user->invited.empty() || !user->channel.empty())
|
||||
{
|
||||
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||
"* %p user (%s!%s@%s) %p %lu %p %lu %d *",
|
||||
"* %p user (%s!%s@%s) %p %lu %lu %d *",
|
||||
client_p,
|
||||
client_p ? client_p->
|
||||
name : "<noname>",
|
||||
|
@ -1850,12 +1850,11 @@ free_user(struct User *user, struct Client *client_p)
|
|||
client_p->host,
|
||||
user,
|
||||
user->invited.size(),
|
||||
user->channel.head,
|
||||
rb_dlink_list_length(&user->channel),
|
||||
user->channel.size(),
|
||||
user->refcnt);
|
||||
s_assert(!user->refcnt);
|
||||
s_assert(user->invited.empty());
|
||||
s_assert(!user->channel.head);
|
||||
s_assert(user->channel.empty());
|
||||
}
|
||||
|
||||
rb_bh_free(user_heap, user);
|
||||
|
|
|
@ -646,11 +646,12 @@ burst_TS6(struct Client *client_p)
|
|||
|
||||
t = buf + mlen;
|
||||
|
||||
RB_DLINK_FOREACH(uptr, chptr->members.head)
|
||||
for (auto &pair : chptr->members.global)
|
||||
{
|
||||
msptr = (chan::membership *)uptr->data;
|
||||
msptr = &pair.second;
|
||||
auto *const client(pair.first);
|
||||
|
||||
tlen = strlen(use_id(msptr->client)) + 1;
|
||||
tlen = strlen(use_id(client)) + 1;
|
||||
if(is_chanop(msptr))
|
||||
tlen++;
|
||||
if(is_voiced(msptr))
|
||||
|
@ -664,13 +665,13 @@ burst_TS6(struct Client *client_p)
|
|||
t = buf + mlen;
|
||||
}
|
||||
|
||||
sprintf(t, "%s%s ", chan::find_status(msptr, 1), use_id(msptr->client));
|
||||
sprintf(t, "%s%s ", chan::find_status(msptr, 1), use_id(client));
|
||||
|
||||
cur_len += tlen;
|
||||
t += tlen;
|
||||
}
|
||||
|
||||
if (rb_dlink_list_length(&chptr->members) > 0)
|
||||
if (!empty(chptr->members))
|
||||
{
|
||||
/* remove trailing space */
|
||||
*(t-1) = '\0';
|
||||
|
|
|
@ -1473,11 +1473,10 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use
|
|||
{
|
||||
rb_dlink_node *ptr;
|
||||
chan::chan *chptr;
|
||||
chan::membership *mscptr;
|
||||
int changed = irccmp(target_p->name, nick);
|
||||
int changed_case = strcmp(target_p->name, nick);
|
||||
int do_qjm = irccmp(target_p->username, user) || irccmp(target_p->host, host);
|
||||
char mode[10], modeval[NICKLEN * 2 + 2], reason[256], *mptr;
|
||||
char mode[10], modeval[NICKLEN * 2 + 2], reason[256];
|
||||
va_list ap;
|
||||
|
||||
modeval[0] = '\0';
|
||||
|
@ -1499,20 +1498,20 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use
|
|||
target_p->name, target_p->username, target_p->host,
|
||||
reason);
|
||||
|
||||
RB_DLINK_FOREACH(ptr, target_p->user->channel.head)
|
||||
for(const auto &pit : target_p->user->channel)
|
||||
{
|
||||
mscptr = (chan::membership *)ptr->data;
|
||||
chptr = mscptr->chan;
|
||||
mptr = mode;
|
||||
auto &chan(*pit.first);
|
||||
auto &member(*pit.second);
|
||||
char *mptr(mode);
|
||||
|
||||
if(is_chanop(mscptr))
|
||||
if(is_chanop(member))
|
||||
{
|
||||
*mptr++ = 'o';
|
||||
strcat(modeval, nick);
|
||||
strcat(modeval, " ");
|
||||
}
|
||||
|
||||
if(is_voiced(mscptr))
|
||||
if(is_voiced(member))
|
||||
{
|
||||
*mptr++ = 'v';
|
||||
strcat(modeval, nick);
|
||||
|
@ -1520,16 +1519,16 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use
|
|||
|
||||
*mptr = '\0';
|
||||
|
||||
sendto_channel_local_with_capability_butone(target_p, chan::ALL_MEMBERS, NOCAPS, CLICAP_EXTENDED_JOIN | CLICAP_CHGHOST, chptr,
|
||||
":%s!%s@%s JOIN %s", nick, user, host, chptr->name.c_str());
|
||||
sendto_channel_local_with_capability_butone(target_p, chan::ALL_MEMBERS, CLICAP_EXTENDED_JOIN, CLICAP_CHGHOST, chptr,
|
||||
":%s!%s@%s JOIN %s %s :%s", nick, user, host, chptr->name.c_str(),
|
||||
sendto_channel_local_with_capability_butone(target_p, chan::ALL_MEMBERS, NOCAPS, CLICAP_EXTENDED_JOIN | CLICAP_CHGHOST, &chan,
|
||||
":%s!%s@%s JOIN %s", nick, user, host, chan.name.c_str());
|
||||
sendto_channel_local_with_capability_butone(target_p, chan::ALL_MEMBERS, CLICAP_EXTENDED_JOIN, CLICAP_CHGHOST, &chan,
|
||||
":%s!%s@%s JOIN %s %s :%s", nick, user, host, chan.name.c_str(),
|
||||
EmptyString(target_p->user->suser) ? "*" : target_p->user->suser,
|
||||
target_p->info);
|
||||
|
||||
if(*mode)
|
||||
sendto_channel_local_with_capability_butone(target_p, chan::ALL_MEMBERS, NOCAPS, CLICAP_CHGHOST, chptr,
|
||||
":%s MODE %s +%s %s", target_p->servptr->name, chptr->name.c_str(), mode, modeval);
|
||||
sendto_channel_local_with_capability_butone(target_p, chan::ALL_MEMBERS, NOCAPS, CLICAP_CHGHOST, &chan,
|
||||
":%s MODE %s +%s %s", target_p->servptr->name, chan.name.c_str(), mode, modeval);
|
||||
|
||||
*modeval = '\0';
|
||||
}
|
||||
|
|
74
ircd/send.cc
74
ircd/send.cc
|
@ -485,8 +485,6 @@ sendto_channel_flags(struct Client *one, int type, struct Client *source_p,
|
|||
va_list args;
|
||||
buf_head_t rb_linebuf_local;
|
||||
buf_head_t rb_linebuf_id;
|
||||
struct Client *target_p;
|
||||
chan::membership *msptr;
|
||||
rb_dlink_node *ptr;
|
||||
rb_dlink_node *next_ptr;
|
||||
int current_capmask = 0;
|
||||
|
@ -506,10 +504,10 @@ sendto_channel_flags(struct Client *one, int type, struct Client *source_p,
|
|||
linebuf_put_msgbuf(&msgbuf, &rb_linebuf_local, NOCAPS, "%s", buf);
|
||||
rb_linebuf_putmsg(&rb_linebuf_id, NULL, NULL, ":%s %s", use_id(source_p), buf);
|
||||
|
||||
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->members.head)
|
||||
for(const auto &pair : chptr->members.global)
|
||||
{
|
||||
msptr = (chan::membership *)ptr->data;
|
||||
target_p = msptr->client;
|
||||
auto *const target_p(pair.first);
|
||||
const auto &member(pair.second);
|
||||
|
||||
if(!MyClient(source_p) && (IsIOError(target_p->from) || target_p->from == one))
|
||||
continue;
|
||||
|
@ -517,7 +515,7 @@ sendto_channel_flags(struct Client *one, int type, struct Client *source_p,
|
|||
if(MyClient(source_p) && !IsCapable(source_p, CLICAP_ECHO_MESSAGE) && target_p == one)
|
||||
continue;
|
||||
|
||||
if(type && ((msptr->flags & type) == 0))
|
||||
if(type && ((member.flags & type) == 0))
|
||||
continue;
|
||||
|
||||
if(IsDeaf(target_p))
|
||||
|
@ -572,8 +570,6 @@ sendto_channel_opmod(struct Client *one, struct Client *source_p,
|
|||
buf_head_t rb_linebuf_local;
|
||||
buf_head_t rb_linebuf_old;
|
||||
buf_head_t rb_linebuf_new;
|
||||
struct Client *target_p;
|
||||
chan::membership *msptr;
|
||||
rb_dlink_node *ptr;
|
||||
rb_dlink_node *next_ptr;
|
||||
|
||||
|
@ -606,10 +602,10 @@ sendto_channel_opmod(struct Client *one, struct Client *source_p,
|
|||
":%s %s =%s :%s",
|
||||
use_id(source_p), command, chptr->name.c_str(), text);
|
||||
|
||||
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->members.head)
|
||||
for(const auto &pair : chptr->members.global)
|
||||
{
|
||||
msptr = (chan::membership *)ptr->data;
|
||||
target_p = msptr->client;
|
||||
auto *const target_p(pair.first);
|
||||
const auto &member(pair.second);
|
||||
|
||||
if(!MyClient(source_p) && (IsIOError(target_p->from) || target_p->from == one))
|
||||
continue;
|
||||
|
@ -617,7 +613,7 @@ sendto_channel_opmod(struct Client *one, struct Client *source_p,
|
|||
if(MyClient(source_p) && !IsCapable(source_p, CLICAP_ECHO_MESSAGE) && target_p == one)
|
||||
continue;
|
||||
|
||||
if((msptr->flags & chan::CHANOP) == 0)
|
||||
if((member.flags & chan::CHANOP) == 0)
|
||||
continue;
|
||||
|
||||
if(IsDeaf(target_p))
|
||||
|
@ -660,10 +656,6 @@ sendto_channel_local(int type, chan::chan *chptr, const char *pattern, ...)
|
|||
{
|
||||
va_list args;
|
||||
buf_head_t linebuf;
|
||||
chan::membership *msptr;
|
||||
struct Client *target_p;
|
||||
rb_dlink_node *ptr;
|
||||
rb_dlink_node *next_ptr;
|
||||
|
||||
rb_linebuf_newbuf(&linebuf);
|
||||
|
||||
|
@ -671,10 +663,10 @@ sendto_channel_local(int type, chan::chan *chptr, const char *pattern, ...)
|
|||
rb_linebuf_putmsg(&linebuf, pattern, &args, NULL);
|
||||
va_end(args);
|
||||
|
||||
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
|
||||
for (const auto &pair : chptr->members.global)
|
||||
{
|
||||
msptr = (chan::membership *)ptr->data;
|
||||
target_p = msptr->client;
|
||||
auto *const target_p(pair.first);
|
||||
const auto &member(pair.second);
|
||||
|
||||
if(IsIOError(target_p))
|
||||
continue;
|
||||
|
@ -684,7 +676,7 @@ sendto_channel_local(int type, chan::chan *chptr, const char *pattern, ...)
|
|||
if (!IsOper(target_p))
|
||||
continue;
|
||||
}
|
||||
else if(type && ((msptr->flags & type) == 0))
|
||||
else if(type && ((member.flags & type) == 0))
|
||||
continue;
|
||||
|
||||
_send_linebuf(target_p, &linebuf);
|
||||
|
@ -703,18 +695,13 @@ _sendto_channel_local_with_capability_butone(struct Client *one, int type, int c
|
|||
const char *pattern, va_list * args)
|
||||
{
|
||||
buf_head_t linebuf;
|
||||
chan::membership *msptr;
|
||||
struct Client *target_p;
|
||||
rb_dlink_node *ptr;
|
||||
rb_dlink_node *next_ptr;
|
||||
|
||||
rb_linebuf_newbuf(&linebuf);
|
||||
rb_linebuf_putmsg(&linebuf, pattern, args, NULL);
|
||||
|
||||
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
|
||||
for(const auto &member : chptr->members.local)
|
||||
{
|
||||
msptr = (chan::membership *)ptr->data;
|
||||
target_p = msptr->client;
|
||||
const auto target_p(member->git->first);
|
||||
|
||||
if (target_p == one)
|
||||
continue;
|
||||
|
@ -724,7 +711,7 @@ _sendto_channel_local_with_capability_butone(struct Client *one, int type, int c
|
|||
!NotCapable(target_p, negcaps))
|
||||
continue;
|
||||
|
||||
if(type && ((msptr->flags & type) == 0))
|
||||
if(type && ((member->flags & type) == 0))
|
||||
continue;
|
||||
|
||||
_send_linebuf(target_p, &linebuf);
|
||||
|
@ -780,8 +767,6 @@ sendto_channel_local_butone(struct Client *one, int type, chan::chan *chptr, con
|
|||
{
|
||||
va_list args;
|
||||
buf_head_t linebuf;
|
||||
chan::membership *msptr;
|
||||
struct Client *target_p;
|
||||
struct MsgBuf msgbuf;
|
||||
rb_dlink_node *ptr;
|
||||
rb_dlink_node *next_ptr;
|
||||
|
@ -794,10 +779,9 @@ sendto_channel_local_butone(struct Client *one, int type, chan::chan *chptr, con
|
|||
rb_linebuf_putmsg(&linebuf, pattern, &args, NULL);
|
||||
va_end(args);
|
||||
|
||||
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
|
||||
for(const auto &member : chptr->members.local)
|
||||
{
|
||||
msptr = (chan::membership *)ptr->data;
|
||||
target_p = msptr->client;
|
||||
const auto target_p(member->git->first);
|
||||
|
||||
if(target_p == one)
|
||||
continue;
|
||||
|
@ -805,7 +789,7 @@ sendto_channel_local_butone(struct Client *one, int type, chan::chan *chptr, con
|
|||
if(IsIOError(target_p))
|
||||
continue;
|
||||
|
||||
if(type && ((msptr->flags & type) == 0))
|
||||
if(type && ((member->flags & type) == 0))
|
||||
continue;
|
||||
|
||||
/* attach the present linebuf to the target */
|
||||
|
@ -848,15 +832,14 @@ sendto_common_channels_local(struct Client *user, int cap, int negcap, const cha
|
|||
|
||||
++current_serial;
|
||||
|
||||
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, user->user->channel.head)
|
||||
for(const auto &pit : user->user->channel)
|
||||
{
|
||||
mscptr = (chan::membership *)ptr->data;
|
||||
chptr = mscptr->chan;
|
||||
auto &chptr(pit.first);
|
||||
auto &mscptr(pit.second);
|
||||
|
||||
RB_DLINK_FOREACH_SAFE(uptr, next_uptr, chptr->locmembers.head)
|
||||
for(const auto &msptr : chptr->members.local)
|
||||
{
|
||||
msptr = (chan::membership *)uptr->data;
|
||||
target_p = msptr->client;
|
||||
const auto target_p(msptr->git->first);
|
||||
|
||||
if(IsIOError(target_p) ||
|
||||
target_p->serial == current_serial ||
|
||||
|
@ -915,15 +898,14 @@ sendto_common_channels_local_butone(struct Client *user, int cap, int negcap, co
|
|||
/* Skip them -- jilles */
|
||||
user->serial = current_serial;
|
||||
|
||||
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, user->user->channel.head)
|
||||
for(const auto &pit : user->user->channel)
|
||||
{
|
||||
mscptr = (membership *)ptr->data;
|
||||
chptr = mscptr->chan;
|
||||
auto &chptr(pit.first);
|
||||
auto &mscptr(pit.second);
|
||||
|
||||
RB_DLINK_FOREACH_SAFE(uptr, next_uptr, chptr->locmembers.head)
|
||||
for(const auto &msptr : chptr->members.local)
|
||||
{
|
||||
msptr = (membership *)uptr->data;
|
||||
target_p = msptr->client;
|
||||
const auto target_p(msptr->git->first);
|
||||
|
||||
if(IsIOError(target_p) ||
|
||||
target_p->serial == current_serial ||
|
||||
|
|
|
@ -27,18 +27,18 @@ namespace ircd {
|
|||
static int add_hashed_target(struct Client *source_p, uint32_t hashv);
|
||||
|
||||
chan::chan *
|
||||
find_allowing_channel(struct Client *source_p, struct Client *target_p)
|
||||
find_allowing_channel(struct Client *source, struct Client *target)
|
||||
{
|
||||
rb_dlink_node *ptr;
|
||||
chan::membership *msptr;
|
||||
|
||||
RB_DLINK_FOREACH(ptr, source_p->user->channel.head)
|
||||
for(const auto &pit : source->user->channel)
|
||||
{
|
||||
msptr = (chan::membership *)ptr->data;
|
||||
if (is_chanop_voiced(msptr) && is_member(msptr->chan, target_p))
|
||||
return msptr->chan;
|
||||
auto &chan(*pit.first);
|
||||
auto &member(*pit.second);
|
||||
|
||||
if (is_chanop_voiced(member) && is_member(chan, *target))
|
||||
return &chan;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -48,7 +48,7 @@ chm_noctcp_process(hook_data_privmsg_channel *data)
|
|||
data->approved = ERR_CANNOTSENDTOCHAN;
|
||||
return;
|
||||
}
|
||||
else if (rb_dlink_list_length(&data->chptr->locmembers) > (unsigned)(GlobalSetOptions.floodcount / 2))
|
||||
else if (local_size(data->chptr->members) > (unsigned)(GlobalSetOptions.floodcount / 2))
|
||||
data->source_p->large_ctcp_sent = rb_current_time();
|
||||
}
|
||||
|
||||
|
|
|
@ -221,7 +221,7 @@ m_join(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
|
|||
/* JOIN 0 simply parts all channels the user is in */
|
||||
if(*name == '0' && !atoi(name))
|
||||
{
|
||||
if(source_p->user->channel.head == NULL)
|
||||
if(source_p->user->channel.empty())
|
||||
continue;
|
||||
|
||||
do_join_0(&me, source_p);
|
||||
|
@ -265,10 +265,10 @@ m_join(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
|
|||
flags = chan::CHANOP;
|
||||
}
|
||||
|
||||
if((rb_dlink_list_length(&source_p->user->channel) >=
|
||||
if(((source_p->user->channel.size()) >=
|
||||
(unsigned long) ConfigChannel.max_chans_per_user) &&
|
||||
(!IsExtendChans(source_p) ||
|
||||
(rb_dlink_list_length(&source_p->user->channel) >=
|
||||
(source_p->user->channel.size() >=
|
||||
(unsigned long) ConfigChannel.max_chans_per_user_large)))
|
||||
{
|
||||
sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS),
|
||||
|
@ -309,7 +309,7 @@ m_join(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
|
|||
chan::check_spambot_warning(source_p, name);
|
||||
|
||||
/* add the user to the channel */
|
||||
add_user_to_channel(chptr, source_p, flags);
|
||||
add(*chptr, *source_p, flags);
|
||||
if (chptr->mode.join_num &&
|
||||
rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
|
||||
{
|
||||
|
@ -482,7 +482,7 @@ ms_join(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
|
|||
|
||||
if(!is_member(chptr, source_p))
|
||||
{
|
||||
add_user_to_channel(chptr, source_p, chan::PEON);
|
||||
add(*chptr, *source_p, chan::PEON);
|
||||
if (chptr->mode.join_num &&
|
||||
rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
|
||||
{
|
||||
|
@ -637,12 +637,11 @@ ms_sjoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
{
|
||||
chan::membership *msptr;
|
||||
struct Client *who;
|
||||
int l = rb_dlink_list_length(&chptr->members);
|
||||
int l = size(chptr->members);
|
||||
|
||||
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
|
||||
for(const auto &msptr : chptr->members.local)
|
||||
{
|
||||
msptr = (chan::membership *)ptr->data;
|
||||
who = msptr->client;
|
||||
who = &get_client(*msptr);
|
||||
sendto_one(who, ":%s KICK %s %s :Net Rider",
|
||||
me.name, chptr->name.c_str(), who->name);
|
||||
|
||||
|
@ -650,7 +649,7 @@ ms_sjoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
":%s KICK %s %s :Net Rider",
|
||||
me.id, chptr->name.c_str(),
|
||||
who->id);
|
||||
remove_user_from_channel(msptr);
|
||||
del(*chptr, *who);
|
||||
if (--l == 0)
|
||||
break;
|
||||
}
|
||||
|
@ -822,7 +821,7 @@ ms_sjoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
|
||||
if(!is_member(chptr, target_p))
|
||||
{
|
||||
add_user_to_channel(chptr, target_p, fl);
|
||||
add(*chptr, *target_p, fl);
|
||||
send_join(*chptr, *target_p);
|
||||
joins++;
|
||||
}
|
||||
|
@ -953,18 +952,19 @@ do_join_0(struct Client *client_p, struct Client *source_p)
|
|||
|
||||
sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s JOIN 0", use_id(source_p));
|
||||
|
||||
while((ptr = source_p->user->channel.head))
|
||||
for(const auto &pit : source_p->user->channel)
|
||||
{
|
||||
if(MyConnect(source_p) &&
|
||||
!IsOper(source_p) && !IsExemptSpambot(source_p))
|
||||
chan::check_spambot_warning(source_p, NULL);
|
||||
|
||||
msptr = (chan::membership *)ptr->data;
|
||||
chptr = msptr->chan;
|
||||
auto &msptr(pit.second);
|
||||
auto &chptr(pit.first);
|
||||
sendto_channel_local(chan::ALL_MEMBERS, chptr, ":%s!%s@%s PART %s",
|
||||
source_p->name,
|
||||
source_p->username, source_p->host, chptr->name.c_str());
|
||||
remove_user_from_channel(msptr);
|
||||
|
||||
del(*chptr, get_client(*msptr));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1162,7 +1162,6 @@ set_final_mode(chan::modes *mode, chan::modes *oldmode)
|
|||
static void
|
||||
remove_our_modes(chan::chan *chptr, struct Client *source_p)
|
||||
{
|
||||
chan::membership *msptr;
|
||||
rb_dlink_node *ptr;
|
||||
char lmodebuf[chan::mode::BUFLEN];
|
||||
char *lpara[chan::mode::MAXPARAMS];
|
||||
|
@ -1175,14 +1174,15 @@ remove_our_modes(chan::chan *chptr, struct Client *source_p)
|
|||
for(i = 0; i < chan::mode::MAXPARAMS; i++)
|
||||
lpara[i] = NULL;
|
||||
|
||||
RB_DLINK_FOREACH(ptr, chptr->members.head)
|
||||
for(auto &pit : chptr->members.global)
|
||||
{
|
||||
msptr = (chan::membership *)ptr->data;
|
||||
auto &client(pit.first);
|
||||
auto &msptr(pit.second);
|
||||
|
||||
if(is_chanop(msptr))
|
||||
{
|
||||
msptr->flags &= ~chan::CHANOP;
|
||||
lpara[count++] = msptr->client->name;
|
||||
msptr.flags &= ~chan::CHANOP;
|
||||
lpara[count++] = client->name;
|
||||
*mbuf++ = 'o';
|
||||
|
||||
/* +ov, might not fit so check. */
|
||||
|
@ -1206,15 +1206,15 @@ remove_our_modes(chan::chan *chptr, struct Client *source_p)
|
|||
lpara[i] = NULL;
|
||||
}
|
||||
|
||||
msptr->flags &= ~chan::VOICE;
|
||||
lpara[count++] = msptr->client->name;
|
||||
msptr.flags &= ~chan::VOICE;
|
||||
lpara[count++] = client->name;
|
||||
*mbuf++ = 'v';
|
||||
}
|
||||
}
|
||||
else if(is_voiced(msptr))
|
||||
{
|
||||
msptr->flags &= ~chan::VOICE;
|
||||
lpara[count++] = msptr->client->name;
|
||||
msptr.flags &= ~chan::VOICE;
|
||||
lpara[count++] = client->name;
|
||||
*mbuf++ = 'v';
|
||||
}
|
||||
else
|
||||
|
|
|
@ -75,7 +75,7 @@ m_kick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
|
|||
|
||||
if(!IsServer(source_p))
|
||||
{
|
||||
msptr = find_channel_membership(chptr, source_p);
|
||||
msptr = get(chptr->members, *source_p, std::nothrow);
|
||||
|
||||
if((msptr == NULL) && MyConnect(source_p))
|
||||
{
|
||||
|
@ -114,7 +114,7 @@ m_kick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
|
|||
return;
|
||||
}
|
||||
|
||||
msptr = find_channel_membership(chptr, who);
|
||||
msptr = get(chptr->members, *who, std::nothrow);
|
||||
|
||||
if(msptr != NULL)
|
||||
{
|
||||
|
@ -168,7 +168,8 @@ m_kick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
|
|||
sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
|
||||
":%s KICK %s %s :%s",
|
||||
use_id(source_p), chptr->name.c_str(), use_id(who), comment);
|
||||
remove_user_from_channel(msptr);
|
||||
|
||||
del(*chptr, *who);
|
||||
}
|
||||
else if (MyClient(source_p))
|
||||
sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
|
||||
|
|
|
@ -336,7 +336,7 @@ build_target_list(enum message_type msgtype, struct Client *client_p,
|
|||
{
|
||||
chan::membership *msptr;
|
||||
|
||||
msptr = find_channel_membership(chptr, source_p);
|
||||
msptr = get(chptr->members, *source_p, std::nothrow);
|
||||
|
||||
if(!IsServer(source_p) && !IsService(source_p) && !is_chanop_voiced(msptr))
|
||||
{
|
||||
|
|
|
@ -120,7 +120,7 @@ m_mode(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
|
|||
}
|
||||
else
|
||||
{
|
||||
msptr = find_channel_membership(chptr, source_p);
|
||||
msptr = get(chptr->members, *source_p, std::nothrow);
|
||||
|
||||
/* Finish the flood grace period... */
|
||||
if(MyClient(source_p) && !IsFloodDone(source_p))
|
||||
|
@ -182,7 +182,7 @@ ms_tmode(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
}
|
||||
else
|
||||
{
|
||||
msptr = find_channel_membership(chptr, source_p);
|
||||
msptr = get(chptr->members, *source_p, std::nothrow);
|
||||
|
||||
set_channel_mode(client_p, source_p, chptr, msptr, parc - 3, parv + 3);
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ part_one_client(struct Client *client_p, struct Client *source_p, char *name, co
|
|||
return;
|
||||
}
|
||||
|
||||
msptr = find_channel_membership(chptr, source_p);
|
||||
msptr = get(chptr->members, *source_p, std::nothrow);
|
||||
if(msptr == NULL)
|
||||
{
|
||||
sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), name);
|
||||
|
@ -145,7 +145,7 @@ part_one_client(struct Client *client_p, struct Client *source_p, char *name, co
|
|||
chptr->name.c_str());
|
||||
}
|
||||
|
||||
remove_user_from_channel(msptr);
|
||||
del(*chptr, *source_p);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -212,7 +212,6 @@ m_chantrace(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou
|
|||
{
|
||||
struct Client *target_p;
|
||||
chan::chan *chptr;
|
||||
chan::membership *msptr;
|
||||
const char *sockhost;
|
||||
const char *name;
|
||||
rb_dlink_node *ptr;
|
||||
|
@ -251,10 +250,10 @@ m_chantrace(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou
|
|||
return;
|
||||
}
|
||||
|
||||
RB_DLINK_FOREACH(ptr, chptr->members.head)
|
||||
for(const auto &pit : chptr->members.global)
|
||||
{
|
||||
msptr = (chan::membership *)ptr->data;
|
||||
target_p = msptr->client;
|
||||
auto &target_p(pit.first);
|
||||
auto &member(pit.second);
|
||||
|
||||
if(EmptyString(target_p->sockhost))
|
||||
sockhost = empty_sockhost;
|
||||
|
|
|
@ -112,7 +112,7 @@ m_invite(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
return;
|
||||
}
|
||||
|
||||
msptr = find_channel_membership(chptr, source_p);
|
||||
msptr = get(chptr->members, *source_p, std::nothrow);
|
||||
if(MyClient(source_p) && (msptr == NULL))
|
||||
{
|
||||
sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
|
||||
|
|
|
@ -98,7 +98,7 @@ m_knock(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
|
|||
|
||||
if(!((chptr->mode.mode & chan::mode::INVITEONLY) || (*chptr->mode.key) ||
|
||||
(chptr->mode.limit &&
|
||||
rb_dlink_list_length(&chptr->members) >= (unsigned long)chptr->mode.limit)))
|
||||
size(chptr->members) >= (unsigned long)chptr->mode.limit)))
|
||||
{
|
||||
sendto_one_numeric(source_p, ERR_CHANOPEN,
|
||||
form_str(ERR_CHANOPEN), name);
|
||||
|
|
|
@ -291,7 +291,7 @@ static void list_one_channel(struct Client *source_p, chan::chan *chptr,
|
|||
strip_colour(topic);
|
||||
sendto_one(source_p, form_str(RPL_LIST), me.name, source_p->name,
|
||||
visible ? "" : "!",
|
||||
chptr->name.c_str(), rb_dlink_list_length(&chptr->members),
|
||||
chptr->name.c_str(), size(chptr->members),
|
||||
topic);
|
||||
}
|
||||
|
||||
|
@ -422,8 +422,7 @@ static void safelist_one_channel(struct Client *source_p, chan::chan *chptr, str
|
|||
if (!visible && !params->operspy)
|
||||
return;
|
||||
|
||||
if ((unsigned int)chptr->members.length < params->users_min
|
||||
|| (unsigned int)chptr->members.length > params->users_max)
|
||||
if (size(chptr->members) < params->users_min || size(chptr->members) > params->users_max)
|
||||
return;
|
||||
|
||||
if (params->topic_min && chptr->topic.time < params->topic_min)
|
||||
|
|
|
@ -113,7 +113,6 @@ names_global(struct Client *source_p)
|
|||
rb_dlink_node *lp, *ptr;
|
||||
struct Client *target_p;
|
||||
chan::chan *chptr = NULL;
|
||||
chan::membership *msptr;
|
||||
char buf[BUFSIZE];
|
||||
char *t;
|
||||
|
||||
|
@ -143,10 +142,9 @@ names_global(struct Client *source_p)
|
|||
* both were missed out above. if the target is on a
|
||||
* common channel with source, its already been shown.
|
||||
*/
|
||||
RB_DLINK_FOREACH(lp, target_p->user->channel.head)
|
||||
for(const auto &pit : target_p->user->channel)
|
||||
{
|
||||
msptr = (chan::membership *)lp->data;
|
||||
chptr = msptr->chan;
|
||||
auto &chptr(pit.first);
|
||||
|
||||
if(is_public(chptr) || is_member(chptr, source_p) || is_secret(chptr))
|
||||
{
|
||||
|
|
|
@ -1336,7 +1336,7 @@ stats_memory (struct Client *source_p)
|
|||
{
|
||||
users_counted++;
|
||||
users_invited_count += target_p->user->invited.size();
|
||||
user_channels += rb_dlink_list_length(&target_p->user->channel);
|
||||
user_channels += target_p->user->channel.size();
|
||||
if(target_p->user->away)
|
||||
{
|
||||
aways_counted++;
|
||||
|
@ -1352,7 +1352,7 @@ stats_memory (struct Client *source_p)
|
|||
channel_count++;
|
||||
channel_memory += (strlen(chptr->name.c_str()) + sizeof(chan::chan));
|
||||
|
||||
channel_users += rb_dlink_list_length(&chptr->members);
|
||||
channel_users += size(chptr->members);
|
||||
channel_invites += chptr->invites.size();
|
||||
|
||||
channel_bans += size(*chptr, chan::mode::BAN);
|
||||
|
|
|
@ -85,7 +85,7 @@ m_topic(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
|
|||
/* setting topic */
|
||||
if(parc > 2)
|
||||
{
|
||||
msptr = find_channel_membership(chptr, source_p);
|
||||
msptr = get(chptr->members, *source_p, std::nothrow);
|
||||
|
||||
if(msptr == NULL)
|
||||
{
|
||||
|
|
|
@ -54,7 +54,7 @@ static void do_who_on_channel(struct Client *source_p, chan::chan *chptr,
|
|||
struct who_format *fmt);
|
||||
static void who_global(struct Client *source_p, const char *mask, int server_oper, int operspy, struct who_format *fmt);
|
||||
static void do_who(struct Client *source_p,
|
||||
struct Client *target_p, chan::membership *msptr,
|
||||
struct Client *target_p, chan::chan *, chan::membership *msptr,
|
||||
struct who_format *fmt);
|
||||
|
||||
struct Message who_msgtab = {
|
||||
|
@ -144,10 +144,10 @@ m_who(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p,
|
|||
if(source_p->user == NULL)
|
||||
return;
|
||||
|
||||
if((lp = source_p->user->channel.head) != NULL)
|
||||
if (!source_p->user->channel.empty())
|
||||
{
|
||||
msptr = (chan::membership *)lp->data;
|
||||
do_who_on_channel(source_p, msptr->chan, server_oper, true, &fmt);
|
||||
auto *const chan(begin(source_p->user->channel)->first);
|
||||
do_who_on_channel(source_p, chan, server_oper, true, &fmt);
|
||||
}
|
||||
|
||||
sendto_one(source_p, form_str(RPL_ENDOFWHO),
|
||||
|
@ -176,7 +176,7 @@ m_who(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p,
|
|||
|
||||
if(chptr != NULL)
|
||||
{
|
||||
if (!IsOper(source_p) && !ratelimit_client_who(source_p, rb_dlink_list_length(&chptr->members)/50))
|
||||
if (!IsOper(source_p) && !ratelimit_client_who(source_p, size(chptr->members)/50))
|
||||
{
|
||||
sendto_one(source_p, form_str(RPL_LOAD2HI),
|
||||
me.name, source_p->name, "WHO");
|
||||
|
@ -207,27 +207,27 @@ m_who(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p,
|
|||
int isinvis = 0;
|
||||
|
||||
isinvis = IsInvisible(target_p);
|
||||
RB_DLINK_FOREACH(lp, target_p->user->channel.head)
|
||||
for(const auto &pit : target_p->user->channel)
|
||||
{
|
||||
msptr = (chan::membership *)lp->data;
|
||||
chptr = msptr->chan;
|
||||
|
||||
member = is_member(chptr, source_p);
|
||||
chptr = pit.first;
|
||||
msptr = get(chptr->members, *source_p, std::nothrow);
|
||||
|
||||
if(isinvis && !member)
|
||||
{
|
||||
msptr = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(member || (!isinvis && is_public(chptr)))
|
||||
break;
|
||||
|
||||
msptr = nullptr;
|
||||
}
|
||||
|
||||
/* if we stopped midlist, lp->data is the membership for
|
||||
/* if we stopped midlist, msptr is the membership for
|
||||
* target_p of chptr
|
||||
*/
|
||||
if(lp != NULL)
|
||||
do_who(source_p, target_p, (chan::membership *)lp->data, &fmt);
|
||||
else
|
||||
do_who(source_p, target_p, NULL, &fmt);
|
||||
do_who(source_p, target_p, chptr, msptr, &fmt);
|
||||
|
||||
sendto_one(source_p, form_str(RPL_ENDOFWHO),
|
||||
me.name, source_p->name, mask);
|
||||
|
@ -286,32 +286,28 @@ who_common_channel(struct Client *source_p, chan::chan *chptr,
|
|||
const char *mask, int server_oper, int *maxmatches,
|
||||
struct who_format *fmt)
|
||||
{
|
||||
chan::membership *msptr;
|
||||
struct Client *target_p;
|
||||
rb_dlink_node *ptr;
|
||||
|
||||
RB_DLINK_FOREACH(ptr, chptr->members.head)
|
||||
for(const auto &pit : chptr->members.global)
|
||||
{
|
||||
msptr = (chan::membership *)ptr->data;
|
||||
target_p = msptr->client;
|
||||
const auto &target(pit.first);
|
||||
const auto &member(pit.second);
|
||||
|
||||
if(!IsInvisible(target_p) || IsMarked(target_p))
|
||||
if(!IsInvisible(target) || IsMarked(target))
|
||||
continue;
|
||||
|
||||
if(server_oper && !IsOper(target_p))
|
||||
if(server_oper && !IsOper(target))
|
||||
continue;
|
||||
|
||||
SetMark(target_p);
|
||||
SetMark(target);
|
||||
|
||||
if(*maxmatches > 0)
|
||||
{
|
||||
if((mask == NULL) ||
|
||||
match(mask, target_p->name) || match(mask, target_p->username) ||
|
||||
match(mask, target_p->host) || match(mask, target_p->servptr->name) ||
|
||||
(IsOper(source_p) && match(mask, target_p->orighost)) ||
|
||||
match(mask, target_p->info))
|
||||
match(mask, target->name) || match(mask, target->username) ||
|
||||
match(mask, target->host) || match(mask, target->servptr->name) ||
|
||||
(IsOper(source_p) && match(mask, target->orighost)) ||
|
||||
match(mask, target->info))
|
||||
{
|
||||
do_who(source_p, target_p, NULL, fmt);
|
||||
do_who(source_p, target, chptr, nullptr, fmt);
|
||||
--(*maxmatches);
|
||||
}
|
||||
}
|
||||
|
@ -345,10 +341,10 @@ who_global(struct Client *source_p, const char *mask, int server_oper, int opers
|
|||
*/
|
||||
if(!operspy)
|
||||
{
|
||||
RB_DLINK_FOREACH(lp, source_p->user->channel.head)
|
||||
for(const auto &pit : source_p->user->channel)
|
||||
{
|
||||
msptr = (chan::membership *)lp->data;
|
||||
who_common_channel(source_p, msptr->chan, mask, server_oper, &maxmatches, fmt);
|
||||
auto &chan(pit.first);
|
||||
who_common_channel(source_p, chan, mask, server_oper, &maxmatches, fmt);
|
||||
}
|
||||
}
|
||||
else if (!ConfigFileEntry.operspy_dont_care_user_info)
|
||||
|
@ -382,7 +378,7 @@ who_global(struct Client *source_p, const char *mask, int server_oper, int opers
|
|||
(IsOper(source_p) && match(mask, target_p->orighost)) ||
|
||||
match(mask, target_p->info))
|
||||
{
|
||||
do_who(source_p, target_p, NULL, fmt);
|
||||
do_who(source_p, target_p, nullptr, nullptr, fmt);
|
||||
--maxmatches;
|
||||
}
|
||||
}
|
||||
|
@ -408,22 +404,18 @@ who_global(struct Client *source_p, const char *mask, int server_oper, int opers
|
|||
*/
|
||||
static void
|
||||
do_who_on_channel(struct Client *source_p, chan::chan *chptr,
|
||||
int server_oper, int member, struct who_format *fmt)
|
||||
int server_oper, int source_member, struct who_format *fmt)
|
||||
{
|
||||
struct Client *target_p;
|
||||
chan::membership *msptr;
|
||||
rb_dlink_node *ptr;
|
||||
|
||||
RB_DLINK_FOREACH(ptr, chptr->members.head)
|
||||
for(auto &pit : chptr->members.global)
|
||||
{
|
||||
msptr = (chan::membership *)ptr->data;
|
||||
target_p = msptr->client;
|
||||
const auto &target(pit.first);
|
||||
auto &member(pit.second);
|
||||
|
||||
if(server_oper && !IsOper(target_p))
|
||||
if(server_oper && !IsOper(target))
|
||||
continue;
|
||||
|
||||
if(member || !IsInvisible(target_p))
|
||||
do_who(source_p, target_p, msptr, fmt);
|
||||
if(source_member || !IsInvisible(target))
|
||||
do_who(source_p, target, chptr, &member, fmt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -464,7 +456,7 @@ append_format(char *buf, size_t bufsize, size_t *pos, const char *fmt, ...)
|
|||
*/
|
||||
|
||||
static void
|
||||
do_who(struct Client *source_p, struct Client *target_p, chan::membership *msptr, struct who_format *fmt)
|
||||
do_who(struct Client *source_p, struct Client *target_p, chan::chan *chan, chan::membership *msptr, struct who_format *fmt)
|
||||
{
|
||||
char status[16];
|
||||
char str[510 + 1]; /* linebuf.c will add \r\n */
|
||||
|
@ -476,7 +468,7 @@ do_who(struct Client *source_p, struct Client *target_p, chan::membership *msptr
|
|||
|
||||
if (fmt->fields == 0)
|
||||
sendto_one(source_p, form_str(RPL_WHOREPLY), me.name,
|
||||
source_p->name, msptr ? msptr->chan->name.c_str() : "*",
|
||||
source_p->name, msptr ? chan->name.c_str() : "*",
|
||||
target_p->username, target_p->host,
|
||||
target_p->servptr->name, target_p->name, status,
|
||||
ConfigServerHide.flatten_links && !IsOper(source_p) && !IsExemptShide(source_p) ? 0 : target_p->hopcount,
|
||||
|
@ -490,7 +482,7 @@ do_who(struct Client *source_p, struct Client *target_p, chan::membership *msptr
|
|||
if (fmt->fields & FIELD_QUERYTYPE)
|
||||
append_format(str, sizeof str, &pos, " %s", fmt->querytype);
|
||||
if (fmt->fields & FIELD_CHANNEL)
|
||||
append_format(str, sizeof str, &pos, " %s", msptr? msptr->chan->name.c_str() : "*");
|
||||
append_format(str, sizeof str, &pos, " %s", msptr? name(*chan).c_str() : "*");
|
||||
if (fmt->fields & FIELD_USER)
|
||||
append_format(str, sizeof str, &pos, " %s", target_p->username);
|
||||
if (fmt->fields & FIELD_IP)
|
||||
|
|
|
@ -252,10 +252,10 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy)
|
|||
|
||||
if (!IsService(target_p))
|
||||
{
|
||||
RB_DLINK_FOREACH(ptr, target_p->user->channel.head)
|
||||
for(const auto &pit : target_p->user->channel)
|
||||
{
|
||||
msptr = (chan::membership *)ptr->data;
|
||||
chptr = msptr->chan;
|
||||
auto &chptr(pit.first);
|
||||
auto &msptr(pit.second);
|
||||
|
||||
hdata.chptr = chptr;
|
||||
|
||||
|
|
Loading…
Reference in a new issue