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
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
return
var named []string
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
return
if c.HasMode(ChannelModePrivate) && !isMember { // If channel is private and client isn't a member, don't reply
return named
}
allMembers := make([]string, len(c.members))
@ -120,6 +122,9 @@ func (c *Channel) Names(client *Client) {
for _, member := range allMembers[i*20 : end] {
mClient, _ := client.Server.GetClientByNick(member)
if mClient.HasMode(UserModeInvisible) && !isMember { //the requesting client shouldn't know about this client
continue
}
if mClient != nil {
if c.MemberHasMode(mClient, ChannelModeOperator) {
@ -128,6 +133,7 @@ func (c *Channel) Names(client *Client) {
memberStr += "+"
}
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"}
client.Encode(&m)
return named
}
// 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
func (c *Client) SendWho() {
// Who rmanages responding to the WHO request for all visible clients of this client
func (c *Client) Who() {
clients := map[string]*Client{}
for name, client := range c.Server.clientsByNick {
if client.HasMode(UserModeInvisible) {

View File

@ -315,7 +315,7 @@ func NoticeHandler(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] == '*' {
//return listing of all visible users - visible people and people in channels with this client
client.SendWho()
client.Who()
return
}
@ -786,18 +786,56 @@ func ChannelModeHandler(message *irc.Message, client *Client) {
// Implemented according to RFC 1459 Section 4.2.5 and RFC 2812 Section 3.2.5
func NamesHandler(message *irc.Message, client *Client) {
if len(message.Params) == 0 { // Send NAMES response for all channels
for _, ch := range client.Server.channels {
ch.Names(client)
}
} else {
channelNames := strings.Split(message.Params[0], ",")
for _, channelName := range channelNames {
ch, ok := client.Server.GetChannel(channelName)
if ok {
ch.Names(client)
}
named := map[string]interface{}{}
for _, ch := range client.Server.channels {
n := ch.Names(client)
for _, k := range n {
named[k] = nil
}
}
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], ",")
for _, channelName := range channelNames {
ch, ok := client.Server.GetChannel(channelName)
if ok {
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)
}
}
}