Browse Source

review fix: add maxParams for service commands

tags/v1.0.0-rc1
Shivaram Lingamneni 5 years ago
parent
commit
598d9a025b
4 changed files with 85 additions and 12 deletions
  1. 1
    2
      irc/chanserv.go
  2. 2
    2
      irc/hostserv.go
  3. 30
    8
      irc/services.go
  4. 52
    0
      irc/utils/fieldsn.go

+ 1
- 2
irc/chanserv.go View File

91
 
91
 
92
 func csAmodeHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
92
 func csAmodeHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
93
 	channelName := params[0]
93
 	channelName := params[0]
94
-	modeChange := strings.Join(params[1:], " ")
95
 
94
 
96
 	channel := server.channels.Get(channelName)
95
 	channel := server.channels.Get(channelName)
97
 	if channel == nil {
96
 	if channel == nil {
102
 		return
101
 		return
103
 	}
102
 	}
104
 
103
 
105
-	modeChanges, unknown := modes.ParseChannelModeChanges(strings.Fields(modeChange)...)
104
+	modeChanges, unknown := modes.ParseChannelModeChanges(params[1:]...)
106
 	var change modes.ModeChange
105
 	var change modes.ModeChange
107
 	if len(modeChanges) > 1 || len(unknown) > 0 {
106
 	if len(modeChanges) > 1 || len(unknown) > 0 {
108
 		csNotice(rb, client.t("Invalid mode change"))
107
 		csNotice(rb, client.t("Invalid mode change"))

+ 2
- 2
irc/hostserv.go View File

7
 	"errors"
7
 	"errors"
8
 	"fmt"
8
 	"fmt"
9
 	"regexp"
9
 	"regexp"
10
-	"strings"
11
 	"time"
10
 	"time"
12
 )
11
 )
13
 
12
 
125
 			capabs:    []string{"vhosts"},
124
 			capabs:    []string{"vhosts"},
126
 			enabled:   hostservEnabled,
125
 			enabled:   hostservEnabled,
127
 			minParams: 1,
126
 			minParams: 1,
127
+			maxParams: 2,
128
 		},
128
 		},
129
 	}
129
 	}
130
 )
130
 )
296
 	var reason string
296
 	var reason string
297
 	user := params[0]
297
 	user := params[0]
298
 	if len(params) > 1 {
298
 	if len(params) > 1 {
299
-		reason = strings.Join(params[1:], " ")
299
+		reason = params[1]
300
 	}
300
 	}
301
 
301
 
302
 	vhostInfo, err := server.accounts.VHostReject(user, reason)
302
 	vhostInfo, err := server.accounts.VHostReject(user, reason)

+ 30
- 8
irc/services.go View File

11
 
11
 
12
 	"github.com/goshuirc/irc-go/ircfmt"
12
 	"github.com/goshuirc/irc-go/ircfmt"
13
 	"github.com/goshuirc/irc-go/ircmsg"
13
 	"github.com/goshuirc/irc-go/ircmsg"
14
+	"github.com/oragono/oragono/irc/utils"
14
 )
15
 )
15
 
16
 
16
 // defines an IRC service, e.g., NICKSERV
17
 // defines an IRC service, e.g., NICKSERV
32
 	authRequired bool
33
 	authRequired bool
33
 	enabled      func(*Config) bool // is this command enabled in the server config?
34
 	enabled      func(*Config) bool // is this command enabled in the server config?
34
 	minParams    int
35
 	minParams    int
36
+	maxParams    int // split into at most n params, with last param containing remaining unsplit text
35
 }
37
 }
36
 
38
 
37
 // looks up a command in the table of command definitions for a service, resolving aliases
39
 // looks up a command in the table of command definitions for a service, resolving aliases
97
 		return false
99
 		return false
98
 	}
100
 	}
99
 
101
 
100
-	serviceRunCommand(service, server, client, msg.Params, rb)
102
+	if len(msg.Params) == 0 {
103
+		return false
104
+	}
105
+	commandName := strings.ToLower(msg.Params[0])
106
+	params := msg.Params[1:]
107
+	cmd := lookupServiceCommand(service.Commands, commandName)
108
+	// for a maxParams command, join all final parameters together if necessary
109
+	if cmd != nil && cmd.maxParams != 0 && cmd.maxParams < len(params) {
110
+		newParams := make([]string, cmd.maxParams)
111
+		copy(newParams, params[:cmd.maxParams-1])
112
+		newParams[cmd.maxParams-1] = strings.Join(params[cmd.maxParams-1:], " ")
113
+		params = newParams
114
+	}
115
+	serviceRunCommand(service, server, client, cmd, commandName, params, rb)
101
 	return false
116
 	return false
102
 }
117
 }
103
 
118
 
104
 // generic handler for service PRIVMSG, like `/msg NickServ INFO`
119
 // generic handler for service PRIVMSG, like `/msg NickServ INFO`
105
 func servicePrivmsgHandler(service *ircService, server *Server, client *Client, message string, rb *ResponseBuffer) {
120
 func servicePrivmsgHandler(service *ircService, server *Server, client *Client, message string, rb *ResponseBuffer) {
106
-	serviceRunCommand(service, server, client, strings.Fields(message), rb)
107
-}
108
-
109
-// actually execute a service command
110
-func serviceRunCommand(service *ircService, server *Server, client *Client, params []string, rb *ResponseBuffer) {
121
+	params := strings.Fields(message)
111
 	if len(params) == 0 {
122
 	if len(params) == 0 {
112
 		return
123
 		return
113
 	}
124
 	}
125
+
126
+	// look up the service command to see how to parse it
114
 	commandName := strings.ToLower(params[0])
127
 	commandName := strings.ToLower(params[0])
115
-	params = params[1:]
128
+	cmd := lookupServiceCommand(service.Commands, commandName)
129
+	// reparse if needed
130
+	if cmd != nil && cmd.maxParams != 0 {
131
+		params = utils.FieldsN(message, cmd.maxParams+1)[1:]
132
+	} else {
133
+		params = params[1:]
134
+	}
135
+	serviceRunCommand(service, server, client, cmd, commandName, params, rb)
136
+}
116
 
137
 
138
+// actually execute a service command
139
+func serviceRunCommand(service *ircService, server *Server, client *Client, cmd *serviceCommand, commandName string, params []string, rb *ResponseBuffer) {
117
 	nick := rb.target.Nick()
140
 	nick := rb.target.Nick()
118
 	sendNotice := func(notice string) {
141
 	sendNotice := func(notice string) {
119
 		rb.Add(nil, service.Name, "NOTICE", nick, notice)
142
 		rb.Add(nil, service.Name, "NOTICE", nick, notice)
120
 	}
143
 	}
121
 
144
 
122
-	cmd := lookupServiceCommand(service.Commands, commandName)
123
 	if cmd == nil {
145
 	if cmd == nil {
124
 		sendNotice(fmt.Sprintf("%s /%s HELP", client.t("Unknown command. To see available commands, run"), service.ShortName))
146
 		sendNotice(fmt.Sprintf("%s /%s HELP", client.t("Unknown command. To see available commands, run"), service.ShortName))
125
 		return
147
 		return

+ 52
- 0
irc/utils/fieldsn.go View File

1
+package utils
2
+
3
+// Copyright (c) 2014 Kevin Wallace <kevin@pentabarf.net>
4
+// Found here: https://github.com/kevinwallace/fieldsn
5
+// Released under the MIT license
6
+// XXX this implementation treats negative n as "return nil",
7
+// unlike stdlib SplitN and friends, which treat it as "no limit"
8
+
9
+// Original source code below:
10
+
11
+// Package fieldsn implements FieldsN and FieldsFuncN,
12
+// which are conspicuously missing from the strings package.
13
+
14
+import (
15
+	"unicode"
16
+)
17
+
18
+// FieldsN is like strings.Fields, but returns at most n fields,
19
+// and the nth field includes any whitespace at the end of the string.
20
+func FieldsN(s string, n int) []string {
21
+	return FieldsFuncN(s, unicode.IsSpace, n)
22
+}
23
+
24
+// FieldsFuncN is like strings.FieldsFunc, but returns at most n fields,
25
+// and the nth field includes any runes at the end of the string normally excluded by f.
26
+func FieldsFuncN(s string, f func(rune) bool, n int) []string {
27
+	if n <= 0 {
28
+		return nil
29
+	}
30
+
31
+	a := make([]string, 0, n)
32
+	na := 0
33
+	fieldStart := -1
34
+	for i, rune := range s {
35
+		if f(rune) {
36
+			if fieldStart >= 0 {
37
+				a = append(a, s[fieldStart:i])
38
+				na++
39
+				fieldStart = -1
40
+			}
41
+		} else if fieldStart == -1 {
42
+			fieldStart = i
43
+			if na+1 == n {
44
+				break
45
+			}
46
+		}
47
+	}
48
+	if fieldStart >= 0 {
49
+		a = append(a, s[fieldStart:])
50
+	}
51
+	return a
52
+}

Loading…
Cancel
Save