Migrate case-mapping to xirc
This commit is contained in:
parent
07cd1f2f5d
commit
3eb2679612
@ -365,7 +365,7 @@ func newDownstreamConn(srv *Server, ic ircConn, id uint64) *downstreamConn {
|
||||
monitored: newCasemapMap[struct{}](),
|
||||
registration: new(downstreamRegistration),
|
||||
}
|
||||
dc.monitored.SetCasemapping(casemapASCII)
|
||||
dc.monitored.SetCasemapping(xirc.CaseMappingASCII)
|
||||
if host, _, err := net.SplitHostPort(remoteAddr); err == nil {
|
||||
dc.hostname = host
|
||||
} else {
|
||||
@ -1110,7 +1110,7 @@ func (dc *downstreamConn) updateNick() {
|
||||
Params: []string{nick},
|
||||
})
|
||||
dc.nick = nick
|
||||
dc.nickCM = casemapASCII(dc.nick)
|
||||
dc.nickCM = xirc.CaseMappingASCII(dc.nick)
|
||||
}
|
||||
|
||||
func (dc *downstreamConn) updateHost() {
|
||||
@ -1197,7 +1197,7 @@ func (dc *downstreamConn) updateAccount() {
|
||||
}
|
||||
|
||||
func (dc *downstreamConn) updateCasemapping() {
|
||||
cm := casemapASCII
|
||||
cm := xirc.CaseMappingASCII
|
||||
if dc.network != nil {
|
||||
cm = dc.network.casemap
|
||||
}
|
||||
@ -1397,7 +1397,7 @@ func (dc *downstreamConn) loadNetwork(ctx context.Context) error {
|
||||
Params: []string{dc.nick, dc.registration.nick, "Nickname contains illegal characters"},
|
||||
}}
|
||||
}
|
||||
if casemapASCII(nick) == serviceNickCM {
|
||||
if xirc.CaseMappingASCII(nick) == serviceNickCM {
|
||||
return ircError{&irc.Message{
|
||||
Command: irc.ERR_NICKNAMEINUSE,
|
||||
Params: []string{dc.nick, dc.registration.nick, "Nickname reserved for bouncer service"},
|
||||
@ -1446,7 +1446,7 @@ func (dc *downstreamConn) welcome(ctx context.Context) error {
|
||||
} else {
|
||||
dc.nick = dc.user.Username
|
||||
}
|
||||
dc.nickCM = casemapASCII(dc.nick)
|
||||
dc.nickCM = xirc.CaseMappingASCII(dc.nick)
|
||||
|
||||
var isupport []string
|
||||
if dc.network != nil {
|
||||
@ -1761,7 +1761,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||
Params: []string{dc.nick, nick, "Nickname contains illegal characters"},
|
||||
}}
|
||||
}
|
||||
if casemapASCII(nick) == serviceNickCM {
|
||||
if xirc.CaseMappingASCII(nick) == serviceNickCM {
|
||||
return ircError{&irc.Message{
|
||||
Command: irc.ERR_NICKNAMEINUSE,
|
||||
Params: []string{dc.nick, nick, "Nickname reserved for bouncer service"},
|
||||
@ -2000,7 +2000,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||
modeStr = msg.Params[1]
|
||||
}
|
||||
|
||||
if casemapASCII(name) == dc.nickCM {
|
||||
if xirc.CaseMappingASCII(name) == dc.nickCM {
|
||||
if modeStr != "" {
|
||||
if uc := dc.upstream(); uc != nil {
|
||||
uc.SendMessageLabeled(ctx, dc.id, &irc.Message{
|
||||
@ -2165,7 +2165,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||
fields, whoxToken := xirc.ParseWHOXOptions(options)
|
||||
|
||||
// TODO: support mixed bouncer/upstream WHO queries
|
||||
maskCM := casemapASCII(mask)
|
||||
maskCM := xirc.CaseMappingASCII(mask)
|
||||
if dc.network == nil && maskCM == dc.nickCM {
|
||||
// TODO: support AWAY (H/G) in self WHO reply
|
||||
flags := "H"
|
||||
@ -2274,7 +2274,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||
mask = mask[:i]
|
||||
}
|
||||
|
||||
if dc.network == nil && casemapASCII(mask) == dc.nickCM {
|
||||
if dc.network == nil && xirc.CaseMappingASCII(mask) == dc.nickCM {
|
||||
dc.SendMessage(&irc.Message{
|
||||
Prefix: dc.srv.prefix(),
|
||||
Command: irc.RPL_WHOISUSER,
|
||||
@ -2304,7 +2304,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||
})
|
||||
return nil
|
||||
}
|
||||
if casemapASCII(mask) == serviceNickCM {
|
||||
if xirc.CaseMappingASCII(mask) == serviceNickCM {
|
||||
dc.SendMessage(&irc.Message{
|
||||
Prefix: dc.srv.prefix(),
|
||||
Command: irc.RPL_WHOISUSER,
|
||||
@ -2391,7 +2391,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||
continue
|
||||
}
|
||||
|
||||
if dc.network == nil && casemapASCII(name) == dc.nickCM {
|
||||
if dc.network == nil && xirc.CaseMappingASCII(name) == dc.nickCM {
|
||||
dc.SendMessage(&irc.Message{
|
||||
Tags: msg.Tags.Copy(),
|
||||
Prefix: dc.prefix(),
|
||||
@ -2401,7 +2401,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||
continue
|
||||
}
|
||||
|
||||
if casemapASCII(name) == serviceNickCM {
|
||||
if xirc.CaseMappingASCII(name) == serviceNickCM {
|
||||
if dc.caps.IsEnabled("echo-message") {
|
||||
echoTags := tags.Copy()
|
||||
echoTags["time"] = dc.user.FormatServerTime(time.Now())
|
||||
@ -2724,7 +2724,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||
}
|
||||
|
||||
// We don't save history for our service
|
||||
if casemapASCII(target) == serviceNickCM {
|
||||
if xirc.CaseMappingASCII(target) == serviceNickCM {
|
||||
dc.SendBatch("chathistory", []string{target}, nil, func(batchRef string) {})
|
||||
return nil
|
||||
}
|
||||
@ -2849,7 +2849,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||
}
|
||||
|
||||
// We don't save read receipts for our service
|
||||
if casemapASCII(target) == serviceNickCM {
|
||||
if xirc.CaseMappingASCII(target) == serviceNickCM {
|
||||
dc.SendMessage(&irc.Message{
|
||||
Prefix: dc.prefix(),
|
||||
Command: msg.Command,
|
||||
|
76
irc.go
76
irc.go
@ -216,79 +216,11 @@ func copyClientTags(tags irc.Tags) irc.Tags {
|
||||
return t
|
||||
}
|
||||
|
||||
type casemapping func(string) string
|
||||
|
||||
func casemapNone(name string) string {
|
||||
return name
|
||||
}
|
||||
|
||||
// CasemapASCII of name is the canonical representation of name according to the
|
||||
// ascii casemapping.
|
||||
func casemapASCII(name string) string {
|
||||
nameBytes := []byte(name)
|
||||
for i, r := range nameBytes {
|
||||
if 'A' <= r && r <= 'Z' {
|
||||
nameBytes[i] = r + 'a' - 'A'
|
||||
}
|
||||
}
|
||||
return string(nameBytes)
|
||||
}
|
||||
|
||||
// casemapRFC1459 of name is the canonical representation of name according to the
|
||||
// rfc1459 casemapping.
|
||||
func casemapRFC1459(name string) string {
|
||||
nameBytes := []byte(name)
|
||||
for i, r := range nameBytes {
|
||||
if 'A' <= r && r <= 'Z' {
|
||||
nameBytes[i] = r + 'a' - 'A'
|
||||
} else if r == '{' {
|
||||
nameBytes[i] = '['
|
||||
} else if r == '}' {
|
||||
nameBytes[i] = ']'
|
||||
} else if r == '\\' {
|
||||
nameBytes[i] = '|'
|
||||
} else if r == '~' {
|
||||
nameBytes[i] = '^'
|
||||
}
|
||||
}
|
||||
return string(nameBytes)
|
||||
}
|
||||
|
||||
// casemapRFC1459Strict of name is the canonical representation of name
|
||||
// according to the rfc1459-strict casemapping.
|
||||
func casemapRFC1459Strict(name string) string {
|
||||
nameBytes := []byte(name)
|
||||
for i, r := range nameBytes {
|
||||
if 'A' <= r && r <= 'Z' {
|
||||
nameBytes[i] = r + 'a' - 'A'
|
||||
} else if r == '{' {
|
||||
nameBytes[i] = '['
|
||||
} else if r == '}' {
|
||||
nameBytes[i] = ']'
|
||||
} else if r == '\\' {
|
||||
nameBytes[i] = '|'
|
||||
}
|
||||
}
|
||||
return string(nameBytes)
|
||||
}
|
||||
|
||||
func parseCasemappingToken(tokenValue string) (casemap casemapping, ok bool) {
|
||||
switch tokenValue {
|
||||
case "ascii":
|
||||
casemap = casemapASCII
|
||||
case "rfc1459":
|
||||
casemap = casemapRFC1459
|
||||
case "rfc1459-strict":
|
||||
casemap = casemapRFC1459Strict
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
return casemap, true
|
||||
}
|
||||
var stdCaseMapping = xirc.CaseMappingRFC1459
|
||||
|
||||
type casemapMap[V interface{}] struct {
|
||||
m map[string]casemapEntry[V]
|
||||
casemap casemapping
|
||||
casemap xirc.CaseMapping
|
||||
}
|
||||
|
||||
type casemapEntry[V interface{}] struct {
|
||||
@ -299,7 +231,7 @@ type casemapEntry[V interface{}] struct {
|
||||
func newCasemapMap[V interface{}]() casemapMap[V] {
|
||||
return casemapMap[V]{
|
||||
m: make(map[string]casemapEntry[V]),
|
||||
casemap: casemapNone,
|
||||
casemap: xirc.CaseMappingNone,
|
||||
}
|
||||
}
|
||||
|
||||
@ -345,7 +277,7 @@ func (cm *casemapMap[V]) ForEach(f func(string, V)) {
|
||||
}
|
||||
}
|
||||
|
||||
func (cm *casemapMap[V]) SetCasemapping(newCasemap casemapping) {
|
||||
func (cm *casemapMap[V]) SetCasemapping(newCasemap xirc.CaseMapping) {
|
||||
cm.casemap = newCasemap
|
||||
m := make(map[string]casemapEntry[V], len(cm.m))
|
||||
for _, entry := range cm.m {
|
||||
|
@ -942,9 +942,9 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
|
||||
var err error
|
||||
switch parameter {
|
||||
case "CASEMAPPING":
|
||||
casemap, ok := parseCasemappingToken(value)
|
||||
if !ok {
|
||||
casemap = casemapRFC1459
|
||||
casemap := xirc.ParseCaseMapping(value)
|
||||
if casemap == nil {
|
||||
casemap = xirc.CaseMappingRFC1459
|
||||
}
|
||||
uc.network.updateCasemapping(casemap)
|
||||
case "CHANMODES":
|
||||
@ -992,7 +992,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
|
||||
// If upstream did not send any CASEMAPPING token, assume it
|
||||
// implements the old RFCs with rfc1459.
|
||||
if uc.isupport["CASEMAPPING"] == nil {
|
||||
uc.network.updateCasemapping(casemapRFC1459)
|
||||
uc.network.updateCasemapping(stdCaseMapping)
|
||||
}
|
||||
|
||||
// If the server doesn't support MONITOR, periodically try to
|
||||
|
6
user.go
6
user.go
@ -151,7 +151,7 @@ type network struct {
|
||||
delivered deliveredStore
|
||||
pushTargets casemapMap[time.Time]
|
||||
lastError error
|
||||
casemap casemapping
|
||||
casemap xirc.CaseMapping
|
||||
}
|
||||
|
||||
func newNetwork(user *user, record *database.Network, channels []database.Channel) *network {
|
||||
@ -171,7 +171,7 @@ func newNetwork(user *user, record *database.Network, channels []database.Channe
|
||||
channels: m,
|
||||
delivered: newDeliveredStore(),
|
||||
pushTargets: newCasemapMap[time.Time](),
|
||||
casemap: casemapRFC1459,
|
||||
casemap: stdCaseMapping,
|
||||
}
|
||||
}
|
||||
|
||||
@ -387,7 +387,7 @@ func (net *network) deleteChannel(ctx context.Context, name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (net *network) updateCasemapping(newCasemap casemapping) {
|
||||
func (net *network) updateCasemapping(newCasemap xirc.CaseMapping) {
|
||||
net.casemap = newCasemap
|
||||
net.channels.SetCasemapping(newCasemap)
|
||||
net.delivered.m.SetCasemapping(newCasemap)
|
||||
|
77
xirc/casemapping.go
Normal file
77
xirc/casemapping.go
Normal file
@ -0,0 +1,77 @@
|
||||
package xirc
|
||||
|
||||
func casemapNone(name string) string {
|
||||
return name
|
||||
}
|
||||
|
||||
// CasemapASCII of name is the canonical representation of name according to the
|
||||
// ascii casemapping.
|
||||
func casemapASCII(name string) string {
|
||||
nameBytes := []byte(name)
|
||||
for i, r := range nameBytes {
|
||||
if 'A' <= r && r <= 'Z' {
|
||||
nameBytes[i] = r + 'a' - 'A'
|
||||
}
|
||||
}
|
||||
return string(nameBytes)
|
||||
}
|
||||
|
||||
// casemapRFC1459 of name is the canonical representation of name according to the
|
||||
// rfc1459 casemapping.
|
||||
func casemapRFC1459(name string) string {
|
||||
nameBytes := []byte(name)
|
||||
for i, r := range nameBytes {
|
||||
if 'A' <= r && r <= 'Z' {
|
||||
nameBytes[i] = r + 'a' - 'A'
|
||||
} else if r == '{' {
|
||||
nameBytes[i] = '['
|
||||
} else if r == '}' {
|
||||
nameBytes[i] = ']'
|
||||
} else if r == '\\' {
|
||||
nameBytes[i] = '|'
|
||||
} else if r == '~' {
|
||||
nameBytes[i] = '^'
|
||||
}
|
||||
}
|
||||
return string(nameBytes)
|
||||
}
|
||||
|
||||
// casemapRFC1459Strict of name is the canonical representation of name
|
||||
// according to the rfc1459-strict casemapping.
|
||||
func casemapRFC1459Strict(name string) string {
|
||||
nameBytes := []byte(name)
|
||||
for i, r := range nameBytes {
|
||||
if 'A' <= r && r <= 'Z' {
|
||||
nameBytes[i] = r + 'a' - 'A'
|
||||
} else if r == '{' {
|
||||
nameBytes[i] = '['
|
||||
} else if r == '}' {
|
||||
nameBytes[i] = ']'
|
||||
} else if r == '\\' {
|
||||
nameBytes[i] = '|'
|
||||
}
|
||||
}
|
||||
return string(nameBytes)
|
||||
}
|
||||
|
||||
type CaseMapping func(string) string
|
||||
|
||||
var (
|
||||
CaseMappingNone CaseMapping = casemapNone
|
||||
CaseMappingASCII CaseMapping = casemapASCII
|
||||
CaseMappingRFC1459 CaseMapping = casemapRFC1459
|
||||
CaseMappingRFC1459Strict CaseMapping = casemapRFC1459Strict
|
||||
)
|
||||
|
||||
func ParseCaseMapping(s string) CaseMapping {
|
||||
var cm CaseMapping
|
||||
switch s {
|
||||
case "ascii":
|
||||
cm = CaseMappingASCII
|
||||
case "rfc1459":
|
||||
cm = CaseMappingRFC1459
|
||||
case "rfc1459-strict":
|
||||
cm = CaseMappingRFC1459Strict
|
||||
}
|
||||
return cm
|
||||
}
|
Loading…
Reference in New Issue
Block a user