Przeglądaj źródła

Assorted fixes

* Fix #679 (borked reply to `JOIN #chan,\r\n`)
* Replace invalid error parameters with *'s in various places
* Fix PART with no message sending an empty trailing parameter to the channel
* Fix some error responses not getting labeled
tags/v2.0.0-rc1
Shivaram Lingamneni 4 lat temu
rodzic
commit
aa8579b6e8
5 zmienionych plików z 94 dodań i 58 usunięć
  1. 8
    3
      irc/channel.go
  2. 29
    21
      irc/commands.go
  3. 39
    34
      irc/handlers.go
  4. 9
    0
      irc/utils/args.go
  5. 9
    0
      irc/utils/args_test.go

+ 8
- 3
irc/channel.go Wyświetl plik

@@ -684,13 +684,18 @@ func (channel *Channel) Part(client *Client, message string, rb *ResponseBuffer)
684 684
 	splitMessage := utils.MakeSplitMessage(message, true)
685 685
 
686 686
 	details := client.Details()
687
+	params := make([]string, 1, 2)
688
+	params[0] = chname
689
+	if message != "" {
690
+		params = append(params, message)
691
+	}
687 692
 	for _, member := range channel.Members() {
688
-		member.sendFromClientInternal(false, splitMessage.Time, splitMessage.Msgid, details.nickMask, details.accountName, nil, "PART", chname, message)
693
+		member.sendFromClientInternal(false, splitMessage.Time, splitMessage.Msgid, details.nickMask, details.accountName, nil, "PART", params...)
689 694
 	}
690
-	rb.AddFromClient(splitMessage.Time, splitMessage.Msgid, details.nickMask, details.accountName, nil, "PART", chname, message)
695
+	rb.AddFromClient(splitMessage.Time, splitMessage.Msgid, details.nickMask, details.accountName, nil, "PART", params...)
691 696
 	for _, session := range client.Sessions() {
692 697
 		if session != rb.session {
693
-			session.sendFromClientInternal(false, splitMessage.Time, splitMessage.Msgid, details.nickMask, details.accountName, nil, "PART", chname, message)
698
+			session.sendFromClientInternal(false, splitMessage.Time, splitMessage.Msgid, details.nickMask, details.accountName, nil, "PART", params...)
694 699
 		}
695 700
 	}
696 701
 

+ 29
- 21
irc/commands.go Wyświetl plik

@@ -21,31 +21,39 @@ type Command struct {
21 21
 }
22 22
 
23 23
 // Run runs this command with the given client/message.
24
-func (cmd *Command) Run(server *Server, client *Client, session *Session, msg ircmsg.IrcMessage) bool {
25
-	if !client.registered && !cmd.usablePreReg {
26
-		client.Send(nil, server.name, ERR_NOTREGISTERED, "*", client.t("You need to register before you can use that command"))
27
-		return false
28
-	}
29
-	if cmd.oper && !client.HasMode(modes.Operator) {
30
-		client.Send(nil, server.name, ERR_NOPRIVILEGES, client.nick, client.t("Permission Denied - You're not an IRC operator"))
31
-		return false
32
-	}
33
-	if len(cmd.capabs) > 0 && !client.HasRoleCapabs(cmd.capabs...) {
34
-		client.Send(nil, server.name, ERR_NOPRIVILEGES, client.nick, client.t("Permission Denied"))
35
-		return false
36
-	}
37
-	if len(msg.Params) < cmd.minParams {
38
-		client.Send(nil, server.name, ERR_NEEDMOREPARAMS, client.nick, msg.Command, client.t("Not enough parameters"))
39
-		return false
40
-	}
41
-
24
+func (cmd *Command) Run(server *Server, client *Client, session *Session, msg ircmsg.IrcMessage) (exiting bool) {
42 25
 	rb := NewResponseBuffer(session)
43 26
 	rb.Label = GetLabel(msg)
44
-	exiting := cmd.handler(server, client, msg, rb)
45
-	rb.Send(true)
27
+
28
+	exiting = func() bool {
29
+		defer rb.Send(true)
30
+
31
+		if !client.registered && !cmd.usablePreReg {
32
+			rb.Add(nil, server.name, ERR_NOTREGISTERED, "*", client.t("You need to register before you can use that command"))
33
+			return false
34
+		}
35
+		if cmd.oper && !client.HasMode(modes.Operator) {
36
+			rb.Add(nil, server.name, ERR_NOPRIVILEGES, client.Nick(), client.t("Permission Denied - You're not an IRC operator"))
37
+			return false
38
+		}
39
+		if len(cmd.capabs) > 0 && !client.HasRoleCapabs(cmd.capabs...) {
40
+			rb.Add(nil, server.name, ERR_NOPRIVILEGES, client.Nick(), client.t("Permission Denied"))
41
+			return false
42
+		}
43
+		if len(msg.Params) < cmd.minParams {
44
+			rb.Add(nil, server.name, ERR_NEEDMOREPARAMS, client.Nick(), msg.Command, rb.target.t("Not enough parameters"))
45
+			return false
46
+		}
47
+
48
+		return cmd.handler(server, client, msg, rb)
49
+	}()
50
+
51
+	if exiting {
52
+		return
53
+	}
46 54
 
47 55
 	// after each command, see if we can send registration to the client
48
-	if !exiting && !client.registered {
56
+	if !client.registered {
49 57
 		exiting = server.tryRegister(client, session)
50 58
 	}
51 59
 

+ 39
- 34
irc/handlers.go Wyświetl plik

@@ -1162,7 +1162,7 @@ func historyHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *R
1162 1162
 
1163 1163
 	if hist == nil {
1164 1164
 		if channel == nil {
1165
-			rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.Nick(), target, client.t("No such channel"))
1165
+			rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.Nick(), utils.SafeErrorParam(target), client.t("No such channel"))
1166 1166
 		} else {
1167 1167
 			rb.Add(nil, server.name, ERR_NOTONCHANNEL, client.Nick(), target, client.t("You're not on that channel"))
1168 1168
 		}
@@ -1238,7 +1238,7 @@ func inviteHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re
1238 1238
 	casefoldedChannelName, err := CasefoldChannel(channelName)
1239 1239
 	channel := server.channels.Get(casefoldedChannelName)
1240 1240
 	if err != nil || channel == nil {
1241
-		rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, channelName, client.t("No such channel"))
1241
+		rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, utils.SafeErrorParam(channelName), client.t("No such channel"))
1242 1242
 		return false
1243 1243
 	}
1244 1244
 
@@ -1280,6 +1280,9 @@ func joinHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
1280 1280
 	config := server.Config()
1281 1281
 	oper := client.Oper()
1282 1282
 	for i, name := range channels {
1283
+		if name == "" {
1284
+			continue // #679
1285
+		}
1283 1286
 		if config.Channels.MaxChannelsPerClient <= client.NumChannels() && oper == nil {
1284 1287
 			rb.Add(nil, server.name, ERR_TOOMANYCHANNELS, client.Nick(), name, client.t("You have joined too many channels"))
1285 1288
 			return false
@@ -1290,7 +1293,7 @@ func joinHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
1290 1293
 		}
1291 1294
 		err := server.channels.Join(client, name, key, false, rb)
1292 1295
 		if err == errNoSuchChannel {
1293
-			rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.Nick(), name, client.t("No such channel"))
1296
+			rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.Nick(), utils.SafeErrorParam(name), client.t("No such channel"))
1294 1297
 		}
1295 1298
 	}
1296 1299
 	return false
@@ -1333,12 +1336,19 @@ func kickHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
1333 1336
 		return false
1334 1337
 	}
1335 1338
 
1336
-	var kicks [][]string
1339
+	type kickCmd struct {
1340
+		channel string
1341
+		nick    string
1342
+	}
1343
+	kicks := make([]kickCmd, 0, len(channels))
1337 1344
 	for index, channel := range channels {
1345
+		if channel == "" {
1346
+			continue // #679
1347
+		}
1338 1348
 		if len(users) == 1 {
1339
-			kicks = append(kicks, []string{channel, users[0]})
1349
+			kicks = append(kicks, kickCmd{channel, users[0]})
1340 1350
 		} else {
1341
-			kicks = append(kicks, []string{channel, users[index]})
1351
+			kicks = append(kicks, kickCmd{channel, users[index]})
1342 1352
 		}
1343 1353
 	}
1344 1354
 
@@ -1346,25 +1356,21 @@ func kickHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
1346 1356
 	if len(msg.Params) > 2 {
1347 1357
 		comment = msg.Params[2]
1348 1358
 	}
1349
-	for _, info := range kicks {
1350
-		chname := info[0]
1351
-		nickname := info[1]
1352
-		casefoldedChname, err := CasefoldChannel(chname)
1353
-		channel := server.channels.Get(casefoldedChname)
1354
-		if err != nil || channel == nil {
1355
-			rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, chname, client.t("No such channel"))
1359
+	for _, kick := range kicks {
1360
+		channel := server.channels.Get(kick.channel)
1361
+		if channel == nil {
1362
+			rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, utils.SafeErrorParam(kick.channel), client.t("No such channel"))
1356 1363
 			continue
1357 1364
 		}
1358 1365
 
1359
-		casefoldedNickname, err := CasefoldName(nickname)
1360
-		target := server.clients.Get(casefoldedNickname)
1361
-		if err != nil || target == nil {
1362
-			rb.Add(nil, server.name, ERR_NOSUCHNICK, client.nick, nickname, client.t("No such nick"))
1366
+		target := server.clients.Get(kick.nick)
1367
+		if target == nil {
1368
+			rb.Add(nil, server.name, ERR_NOSUCHNICK, client.nick, utils.SafeErrorParam(kick.nick), client.t("No such nick"))
1363 1369
 			continue
1364 1370
 		}
1365 1371
 
1366 1372
 		if comment == "" {
1367
-			comment = nickname
1373
+			comment = kick.nick
1368 1374
 		}
1369 1375
 		channel.Kick(client, target, comment, rb)
1370 1376
 	}
@@ -1647,11 +1653,10 @@ func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
1647 1653
 		}
1648 1654
 
1649 1655
 		for _, chname := range channels {
1650
-			casefoldedChname, err := CasefoldChannel(chname)
1651
-			channel := server.channels.Get(casefoldedChname)
1652
-			if err != nil || channel == nil || (!clientIsOp && channel.flags.HasMode(modes.Secret)) {
1656
+			channel := server.channels.Get(chname)
1657
+			if channel == nil || (!clientIsOp && channel.flags.HasMode(modes.Secret)) {
1653 1658
 				if len(chname) > 0 {
1654
-					rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, chname, client.t("No such channel"))
1659
+					rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, utils.SafeErrorParam(chname), client.t("No such channel"))
1655 1660
 				}
1656 1661
 				continue
1657 1662
 			}
@@ -1686,7 +1691,7 @@ func cmodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
1686 1691
 	channel := server.channels.Get(channelName)
1687 1692
 
1688 1693
 	if err != nil || channel == nil {
1689
-		rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, msg.Params[0], client.t("No such channel"))
1694
+		rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, utils.SafeErrorParam(msg.Params[0]), client.t("No such channel"))
1690 1695
 		return false
1691 1696
 	}
1692 1697
 
@@ -2052,7 +2057,7 @@ func messageHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *R
2052 2057
 			channel := server.channels.Get(targetString)
2053 2058
 			if channel == nil {
2054 2059
 				if histType != history.Notice {
2055
-					rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, cnick, targetString, client.t("No such channel"))
2060
+					rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, cnick, utils.SafeErrorParam(targetString), client.t("No such channel"))
2056 2061
 				}
2057 2062
 				continue
2058 2063
 			}
@@ -2224,15 +2229,18 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
2224 2229
 // PART <channel>{,<channel>} [<reason>]
2225 2230
 func partHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
2226 2231
 	channels := strings.Split(msg.Params[0], ",")
2227
-	var reason string //TODO(dan): if this isn't supplied here, make sure the param doesn't exist in the PART message sent to other users
2232
+	var reason string
2228 2233
 	if len(msg.Params) > 1 {
2229 2234
 		reason = msg.Params[1]
2230 2235
 	}
2231 2236
 
2232 2237
 	for _, chname := range channels {
2238
+		if chname == "" {
2239
+			continue // #679
2240
+		}
2233 2241
 		err := server.channels.Part(client, chname, reason, rb)
2234 2242
 		if err == errNoSuchChannel {
2235
-			rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, chname, client.t("No such channel"))
2243
+			rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, utils.SafeErrorParam(chname), client.t("No such channel"))
2236 2244
 		}
2237 2245
 	}
2238 2246
 	return false
@@ -2305,9 +2313,6 @@ func rehashHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re
2305 2313
 func renameHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) (result bool) {
2306 2314
 	result = false
2307 2315
 	oldName, newName := msg.Params[0], msg.Params[1]
2308
-	if newName == "" {
2309
-		newName = "<empty>" // intentionally invalid channel name, will error as expected
2310
-	}
2311 2316
 	var reason string
2312 2317
 	if 2 < len(msg.Params) {
2313 2318
 		reason = msg.Params[2]
@@ -2315,7 +2320,7 @@ func renameHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re
2315 2320
 
2316 2321
 	channel := server.channels.Get(oldName)
2317 2322
 	if channel == nil {
2318
-		rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.Nick(), oldName, client.t("No such channel"))
2323
+		rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.Nick(), utils.SafeErrorParam(oldName), client.t("No such channel"))
2319 2324
 		return false
2320 2325
 	}
2321 2326
 	if !(channel.ClientIsAtLeast(client, modes.Operator) || client.HasRoleCapabs("chanreg")) {
@@ -2332,11 +2337,11 @@ func renameHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re
2332 2337
 	// perform the channel rename
2333 2338
 	err := server.channels.Rename(oldName, newName)
2334 2339
 	if err == errInvalidChannelName {
2335
-		rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.Nick(), newName, client.t(err.Error()))
2340
+		rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.Nick(), utils.SafeErrorParam(newName), client.t(err.Error()))
2336 2341
 	} else if err == errChannelNameInUse {
2337
-		rb.Add(nil, server.name, ERR_CHANNAMEINUSE, client.Nick(), newName, client.t(err.Error()))
2342
+		rb.Add(nil, server.name, ERR_CHANNAMEINUSE, client.Nick(), utils.SafeErrorParam(newName), client.t(err.Error()))
2338 2343
 	} else if err != nil {
2339
-		rb.Add(nil, server.name, ERR_CANNOTRENAME, client.Nick(), oldName, newName, client.t("Cannot rename channel"))
2344
+		rb.Add(nil, server.name, ERR_CANNOTRENAME, client.Nick(), oldName, utils.SafeErrorParam(newName), client.t("Cannot rename channel"))
2340 2345
 	}
2341 2346
 	if err != nil {
2342 2347
 		return false
@@ -2460,7 +2465,7 @@ func topicHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
2460 2465
 	channel := server.channels.Get(name)
2461 2466
 	if err != nil || channel == nil {
2462 2467
 		if len(msg.Params[0]) > 0 {
2463
-			rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, msg.Params[0], client.t("No such channel"))
2468
+			rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, utils.SafeErrorParam(msg.Params[0]), client.t("No such channel"))
2464 2469
 		}
2465 2470
 		return false
2466 2471
 	}

+ 9
- 0
irc/utils/args.go Wyświetl plik

@@ -54,3 +54,12 @@ func StringToBool(str string) (result bool, err error) {
54 54
 	}
55 55
 	return
56 56
 }
57
+
58
+// Checks that a parameter can be passed as a non-trailing, and returns "*"
59
+// if it can't. See #697.
60
+func SafeErrorParam(param string) string {
61
+	if param == "" || param[0] == ':' || strings.IndexByte(param, ' ') != -1 {
62
+		return "*"
63
+	}
64
+	return param
65
+}

+ 9
- 0
irc/utils/args_test.go Wyświetl plik

@@ -21,3 +21,12 @@ func TestStringToBool(t *testing.T) {
21 21
 	val, err = StringToBool("default")
22 22
 	assertEqual(err, ErrInvalidParams, t)
23 23
 }
24
+
25
+func TestSafeErrorParam(t *testing.T) {
26
+	assertEqual(SafeErrorParam("hi"), "hi", t)
27
+	assertEqual(SafeErrorParam("#hi"), "#hi", t)
28
+	assertEqual(SafeErrorParam("#hi there"), "*", t)
29
+	assertEqual(SafeErrorParam(":"), "*", t)
30
+	assertEqual(SafeErrorParam("#hi:there"), "#hi:there", t)
31
+	assertEqual(SafeErrorParam(""), "*", t)
32
+}

Ładowanie…
Anuluj
Zapisz