capability: Add 3.2 CAP values

This commit is contained in:
Daniel Oaks 2016-10-16 13:54:09 +10:00
parent 9162d0da61
commit e643c2101f
3 changed files with 40 additions and 12 deletions

View File

@ -12,8 +12,9 @@ Improved compatibility, more features, etc.
### Security
### Added
* Added integrated help.
* Support for IRCv3 capability [`account-notify`](http://ircv3.net/specs/extensions/account-notify-3.1.html), and draft capability [`message-tags`](http://ircv3.net/specs/core/message-tags-3.3.html) as `draft/message-tags`.
* Added integrated help (with the `/HELP` command).
* Added support for IRCv3.2 [capability negotiation](http://ircv3.net/specs/core/capability-negotiation-3.2.html) including CAP values.
* Added support for IRCv3 capability [`account-notify`](http://ircv3.net/specs/extensions/account-notify-3.1.html), and draft capability [`message-tags`](http://ircv3.net/specs/core/message-tags-3.3.html) as `draft/message-tags`.
### Changed
* Casemapping changed from custom unicode mapping to preliminary [rfc7700](https://github.com/ircv3/ircv3-specifications/pull/272) mapping.
@ -43,7 +44,7 @@ Initial release of Oragono!
* Ability to parse complex mode change syntax commonly used these days (i.e. `+h-ov dan dan dan`).
* User mode for clients connected via TLS (`+Z`).
* Ability to register and login to accounts (with passphrase or certfp).
* Support for IRCv3 capabilities [`account-tag`](http://ircv3.net/specs/extensions/account-tag-3.2.html), [`away-notify`](http://ircv3.net/specs/extensions/away-notify-3.1.html), [`extended-join`](http://ircv3.net/specs/extensions/extended-join-3.1.html), [`sasl`](http://ircv3.net/specs/extensions/sasl-3.1.html), [`server-time`](http://ircv3.net/specs/extensions/server-time-3.2.html), and [`userhost-in-names`](http://ircv3.net/specs/extensions/userhost-in-names-3.2.html).
* Added support for IRCv3 capabilities [`account-tag`](http://ircv3.net/specs/extensions/account-tag-3.2.html), [`away-notify`](http://ircv3.net/specs/extensions/away-notify-3.1.html), [`extended-join`](http://ircv3.net/specs/extensions/extended-join-3.1.html), [`sasl`](http://ircv3.net/specs/extensions/sasl-3.1.html), [`server-time`](http://ircv3.net/specs/extensions/server-time-3.2.html), and [`userhost-in-names`](http://ircv3.net/specs/extensions/userhost-in-names-3.2.html).
### Changed
* Channel creator (`O`) privilege changed to founder/admin/halfops (`qah`) privileges.

View File

@ -37,6 +37,9 @@ var (
ServerTime: true,
UserhostInNames: true,
}
CapValues = map[Capability]string{
SASL: "PLAIN,EXTERNAL",
}
)
func (capability Capability) String() string {
@ -65,14 +68,32 @@ const (
CapNegotiated CapState = iota
)
// CapVersion is used to select which max version of CAP the client supports.
type CapVersion uint
const (
// Cap301 refers to the base CAP spec.
Cap301 CapVersion = 301
// Cap302 refers to the IRCv3.2 CAP spec.
Cap302 CapVersion = 302
)
// CapabilitySet is used to track supported, enabled, and existing caps.
type CapabilitySet map[Capability]bool
func (set CapabilitySet) String() string {
func (set CapabilitySet) String(version CapVersion) string {
strs := make([]string, len(set))
index := 0
for capability := range set {
strs[index] = string(capability)
index += 1
capString := string(capability)
if version == Cap302 {
val, exists := CapValues[capability]
if exists {
capString += "=" + val
}
}
strs[index] = capString
index++
}
return strings.Join(strs, " ")
}
@ -108,13 +129,17 @@ func capHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
if !client.registered {
client.capState = CapNegotiating
}
// client.server needs to be here to workaround a parsing bug in weechat 1.4
// and let it connect to the server (otherwise it doesn't respond to the CAP
// message with anything and just hangs on connection)
client.Send(nil, server.name, "CAP", client.nick, subCommand, SupportedCapabilities.String())
if len(msg.Params) > 1 && msg.Params[1] == "302" {
client.capVersion = 302
}
// weechat 1.4 has a bug here where it won't accept the CAP reply unless it contains
// the server.name source... otherwise it doesn't respond to the CAP message with
// anything and just hangs on connection.
//TODO(dan): limit number of caps and send it multiline in 3.2 style as appropriate.
client.Send(nil, server.name, "CAP", client.nick, subCommand, SupportedCapabilities.String(client.capVersion))
case "LIST":
client.Send(nil, server.name, "CAP", client.nick, subCommand, client.capabilities.String())
client.Send(nil, server.name, "CAP", client.nick, subCommand, client.capabilities.String(Cap301)) // values not sent on LIST so force 3.1
case "REQ":
// make sure all capabilities actually exist

View File

@ -33,6 +33,7 @@ type Client struct {
awayMessage string
capabilities CapabilitySet
capState CapState
capVersion CapVersion
certfp string
channels ChannelSet
ctime time.Time
@ -64,8 +65,9 @@ func NewClient(server *Server, conn net.Conn, isTLS bool) *Client {
client := &Client{
atime: now,
authorized: server.password == nil,
capState: CapNone,
capabilities: make(CapabilitySet),
capState: CapNone,
capVersion: Cap301,
channels: make(ChannelSet),
ctime: now,
flags: make(map[UserMode]bool),