NAMES responses for global added.

When no parameter is passed all channels and global are returned
Now prevents invisible users from being revealed
This commit is contained in:
Justin 2015-08-09 12:56:44 -07:00
parent aa1780a415
commit e31fe5d24d
3 changed files with 63 additions and 20 deletions

View File

@ -84,13 +84,15 @@ func (c *Channel) Join(client *Client, key string) {
} }
// Names responds to to IRC NAMES command for the channel // Names responds to to IRC NAMES command for the channel
func (c *Channel) Names(client *Client) { func (c *Channel) Names(client *Client) []string {
if c.HasMode(ChannelModeSecret) && !c.HasMember(client) { // If channel is secret and client isn't a member, don't reveal it var named []string
return isMember := c.HasMember(client)
if c.HasMode(ChannelModeSecret) && !isMember { // If channel is secret and client isn't a member, don't reveal it
return named
} }
if c.HasMode(ChannelModePrivate) && !c.HasMember(client) { // If channel is private and client isn't a member, don't reply if c.HasMode(ChannelModePrivate) && !isMember { // If channel is private and client isn't a member, don't reply
return return named
} }
allMembers := make([]string, len(c.members)) allMembers := make([]string, len(c.members))
@ -120,6 +122,9 @@ func (c *Channel) Names(client *Client) {
for _, member := range allMembers[i*20 : end] { for _, member := range allMembers[i*20 : end] {
mClient, _ := client.Server.GetClientByNick(member) mClient, _ := client.Server.GetClientByNick(member)
if mClient.HasMode(UserModeInvisible) && !isMember { //the requesting client shouldn't know about this client
continue
}
if mClient != nil { if mClient != nil {
if c.MemberHasMode(mClient, ChannelModeOperator) { if c.MemberHasMode(mClient, ChannelModeOperator) {
@ -128,6 +133,7 @@ func (c *Channel) Names(client *Client) {
memberStr += "+" memberStr += "+"
} }
memberStr += mClient.Nickname + " " memberStr += mClient.Nickname + " "
named = append(named, mClient.Nickname)
} }
@ -137,8 +143,7 @@ func (c *Channel) Names(client *Client) {
} }
m := irc.Message{Prefix: c.Server.Prefix, Command: irc.RPL_ENDOFNAMES, Params: []string{client.Nickname, c.Name}, Trailing: "End of NAMES list"} return named
client.Encode(&m)
} }
// Part handles when a client leaves a channel // Part handles when a client leaves a channel

View File

@ -273,8 +273,8 @@ func (c *Client) SendMessagetoVisible(m *irc.Message) {
} }
} }
// SendWho rmanages responding to the WHO request for all visible clients of this client // Who rmanages responding to the WHO request for all visible clients of this client
func (c *Client) SendWho() { func (c *Client) Who() {
clients := map[string]*Client{} clients := map[string]*Client{}
for name, client := range c.Server.clientsByNick { for name, client := range c.Server.clientsByNick {
if client.HasMode(UserModeInvisible) { if client.HasMode(UserModeInvisible) {

View File

@ -315,7 +315,7 @@ func NoticeHandler(message *irc.Message, client *Client) {
func WhoHandler(message *irc.Message, client *Client) { func WhoHandler(message *irc.Message, client *Client) {
if len(message.Params) == 0 || len(message.Params[0]) == 0 || message.Params[0][0] == '*' { if len(message.Params) == 0 || len(message.Params[0]) == 0 || message.Params[0][0] == '*' {
//return listing of all visible users - visible people and people in channels with this client //return listing of all visible users - visible people and people in channels with this client
client.SendWho() client.Who()
return return
} }
@ -786,19 +786,57 @@ func ChannelModeHandler(message *irc.Message, client *Client) {
// Implemented according to RFC 1459 Section 4.2.5 and RFC 2812 Section 3.2.5 // Implemented according to RFC 1459 Section 4.2.5 and RFC 2812 Section 3.2.5
func NamesHandler(message *irc.Message, client *Client) { func NamesHandler(message *irc.Message, client *Client) {
if len(message.Params) == 0 { // Send NAMES response for all channels if len(message.Params) == 0 { // Send NAMES response for all channels
named := map[string]interface{}{}
for _, ch := range client.Server.channels { for _, ch := range client.Server.channels {
ch.Names(client) n := ch.Names(client)
for _, k := range n {
named[k] = nil
} }
} else { }
count := 0
memberStr := ""
for n, cl := range client.Server.clientsByNick {
_, alreadyNamed := named[n]
if !alreadyNamed && !cl.HasMode(UserModeInvisible) { //don't name people that are already named or that shouldn't be named
count++
if cl != nil {
if cl.HasMode(UserModeOperator) || cl.HasMode(UserModeLocalOperator) {
memberStr += "@"
}
memberStr += cl.Nickname + " "
}
if count%20 == 0 { // String is long enough, send message
m := irc.Message{Prefix: client.Server.Prefix, Command: irc.RPL_NAMREPLY, Params: []string{client.Nickname, "*", "*"}, Trailing: memberStr}
client.Encode(&m)
memberStr = ""
}
}
}
m := irc.Message{Prefix: client.Server.Prefix, Command: irc.RPL_NAMREPLY, Params: []string{client.Nickname, "*", "*"}, Trailing: memberStr}
client.Encode(&m)
m = irc.Message{Prefix: client.Server.Prefix, Command: irc.RPL_ENDOFNAMES, Params: []string{client.Nickname, "*"}, Trailing: "End of NAMES list"}
client.Encode(&m)
return
}
if len(message.Params) == 2 { //Client has provided target server for the request
m := irc.Message{Prefix: client.Server.Prefix, Command: irc.ERR_NOSUCHSERVER, Params: []string{client.Nickname, message.Params[0]}, Trailing: "No such server"}
client.Encode(&m)
return
}
channelNames := strings.Split(message.Params[0], ",") channelNames := strings.Split(message.Params[0], ",")
for _, channelName := range channelNames { for _, channelName := range channelNames {
ch, ok := client.Server.GetChannel(channelName) ch, ok := client.Server.GetChannel(channelName)
if ok { if ok {
ch.Names(client) ch.Names(client)
m := irc.Message{Prefix: client.Server.Prefix, Command: irc.RPL_ENDOFNAMES, Params: []string{client.Nickname, ch.Name}, Trailing: "End of NAMES list"}
client.Encode(&m)
} }
} }
}
} }
// MOTDHandler is a specialized CommandHandler to respond to channel IRC MOTD commands from a client // MOTDHandler is a specialized CommandHandler to respond to channel IRC MOTD commands from a client