|
@@ -6,6 +6,7 @@
|
6
|
6
|
package irc
|
7
|
7
|
|
8
|
8
|
import (
|
|
9
|
+ "bytes"
|
9
|
10
|
"crypto/subtle"
|
10
|
11
|
"fmt"
|
11
|
12
|
"strconv"
|
|
@@ -24,7 +25,7 @@ type Channel struct {
|
24
|
25
|
lists map[modes.Mode]*UserMaskSet
|
25
|
26
|
key string
|
26
|
27
|
members MemberSet
|
27
|
|
- membersCache []*Client // allow iteration over channel members without holding the lock
|
|
28
|
+ membersCache []*Client // allow iteration over channel members without holding the lock
|
28
|
29
|
name string
|
29
|
30
|
nameCasefolded string
|
30
|
31
|
server *Server
|
|
@@ -180,27 +181,47 @@ func (channel *Channel) regenerateMembersCache() {
|
180
|
181
|
|
181
|
182
|
// Names sends the list of users joined to the channel to the given client.
|
182
|
183
|
func (channel *Channel) Names(client *Client, rb *ResponseBuffer) {
|
183
|
|
- currentNicks := channel.nicks(client)
|
184
|
|
- // assemble and send replies
|
185
|
|
- maxNamLen := 480 - len(client.server.name) - len(client.nick)
|
186
|
|
- var buffer string
|
187
|
|
- for _, nick := range currentNicks {
|
188
|
|
- if buffer == "" {
|
189
|
|
- buffer += nick
|
190
|
|
- continue
|
|
184
|
+ isMultiPrefix := client.capabilities.Has(caps.MultiPrefix)
|
|
185
|
+ isUserhostInNames := client.capabilities.Has(caps.UserhostInNames)
|
|
186
|
+
|
|
187
|
+ maxNamLen := 480 - len(client.server.name) - len(client.Nick())
|
|
188
|
+ var namesLines []string
|
|
189
|
+ var buffer bytes.Buffer
|
|
190
|
+ for _, target := range channel.Members() {
|
|
191
|
+ var nick string
|
|
192
|
+ if isUserhostInNames {
|
|
193
|
+ nick = target.NickMaskString()
|
|
194
|
+ } else {
|
|
195
|
+ nick = target.Nick()
|
191
|
196
|
}
|
192
|
|
-
|
193
|
|
- if len(buffer)+1+len(nick) > maxNamLen {
|
194
|
|
- rb.Add(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, buffer)
|
195
|
|
- buffer = nick
|
|
197
|
+ channel.stateMutex.RLock()
|
|
198
|
+ modes := channel.members[target]
|
|
199
|
+ channel.stateMutex.RUnlock()
|
|
200
|
+ if modes == nil {
|
196
|
201
|
continue
|
197
|
202
|
}
|
198
|
|
-
|
199
|
|
- buffer += " "
|
200
|
|
- buffer += nick
|
|
203
|
+ prefix := modes.Prefixes(isMultiPrefix)
|
|
204
|
+ if buffer.Len()+len(nick)+len(prefix)+1 > maxNamLen {
|
|
205
|
+ namesLines = append(namesLines, buffer.String())
|
|
206
|
+ // memset(&buffer, 0, sizeof(bytes.Buffer));
|
|
207
|
+ var newBuffer bytes.Buffer
|
|
208
|
+ buffer = newBuffer
|
|
209
|
+ }
|
|
210
|
+ if buffer.Len() > 0 {
|
|
211
|
+ buffer.WriteString(" ")
|
|
212
|
+ }
|
|
213
|
+ buffer.WriteString(prefix)
|
|
214
|
+ buffer.WriteString(nick)
|
|
215
|
+ }
|
|
216
|
+ if buffer.Len() > 0 {
|
|
217
|
+ namesLines = append(namesLines, buffer.String())
|
201
|
218
|
}
|
202
|
219
|
|
203
|
|
- rb.Add(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, buffer)
|
|
220
|
+ for _, line := range namesLines {
|
|
221
|
+ if buffer.Len() > 0 {
|
|
222
|
+ rb.Add(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, line)
|
|
223
|
+ }
|
|
224
|
+ }
|
204
|
225
|
rb.Add(nil, client.server.name, RPL_ENDOFNAMES, client.nick, channel.name, client.t("End of NAMES list"))
|
205
|
226
|
}
|
206
|
227
|
|
|
@@ -263,37 +284,6 @@ func (channel *Channel) ClientHasPrivsOver(client *Client, target *Client) bool
|
263
|
284
|
return result
|
264
|
285
|
}
|
265
|
286
|
|
266
|
|
-func (channel *Channel) nicks(target *Client) []string {
|
267
|
|
- isMultiPrefix := (target != nil) && target.capabilities.Has(caps.MultiPrefix)
|
268
|
|
- isUserhostInNames := (target != nil) && target.capabilities.Has(caps.UserhostInNames)
|
269
|
|
-
|
270
|
|
- // slightly cumbersome: get the mutex and copy both the client pointers and
|
271
|
|
- // the mode prefixes
|
272
|
|
- channel.stateMutex.RLock()
|
273
|
|
- length := len(channel.members)
|
274
|
|
- clients := make([]*Client, length)
|
275
|
|
- result := make([]string, length)
|
276
|
|
- i := 0
|
277
|
|
- for client, modes := range channel.members {
|
278
|
|
- clients[i] = client
|
279
|
|
- result[i] = modes.Prefixes(isMultiPrefix)
|
280
|
|
- i++
|
281
|
|
- }
|
282
|
|
- channel.stateMutex.RUnlock()
|
283
|
|
-
|
284
|
|
- i = 0
|
285
|
|
- for i < length {
|
286
|
|
- if isUserhostInNames {
|
287
|
|
- result[i] += clients[i].NickMaskString()
|
288
|
|
- } else {
|
289
|
|
- result[i] += clients[i].Nick()
|
290
|
|
- }
|
291
|
|
- i++
|
292
|
|
- }
|
293
|
|
-
|
294
|
|
- return result
|
295
|
|
-}
|
296
|
|
-
|
297
|
287
|
func (channel *Channel) hasClient(client *Client) bool {
|
298
|
288
|
channel.stateMutex.RLock()
|
299
|
289
|
defer channel.stateMutex.RUnlock()
|