Merge pull request #60 from slingamn/ircevent_truncation
fix #59, add a message sanitizer
This commit is contained in:
commit
de8a22cda2
@ -351,7 +351,7 @@ func (irc *Connection) sendInternal(b []byte) (err error) {
|
||||
// Send a built ircmsg.Message.
|
||||
func (irc *Connection) SendIRCMessage(msg ircmsg.Message) error {
|
||||
b, err := msg.LineBytesStrict(true, irc.MaxLineLen)
|
||||
if err != nil {
|
||||
if err != nil && !(irc.AllowTruncation && err == ircmsg.ErrorBodyTooLong) {
|
||||
if irc.Debug {
|
||||
irc.Log.Printf("couldn't assemble message: %v\n", err)
|
||||
}
|
||||
|
@ -41,28 +41,29 @@ type capResult struct {
|
||||
|
||||
type Connection struct {
|
||||
// config data, user-settable
|
||||
Server string
|
||||
TLSConfig *tls.Config
|
||||
Nick string
|
||||
User string
|
||||
RealName string // IRC realname/gecos
|
||||
WebIRC []string // parameters for the WEBIRC command
|
||||
Password string // server password (PASS command)
|
||||
RequestCaps []string // IRCv3 capabilities to request (failure is non-fatal)
|
||||
SASLLogin string // SASL credentials to log in with (failure is fatal)
|
||||
SASLPassword string
|
||||
SASLMech string
|
||||
QuitMessage string
|
||||
Version string
|
||||
Timeout time.Duration
|
||||
KeepAlive time.Duration
|
||||
ReconnectFreq time.Duration
|
||||
MaxLineLen int // maximum line length, not including tags
|
||||
UseTLS bool
|
||||
UseSASL bool
|
||||
EnableCTCP bool
|
||||
Debug bool
|
||||
AllowPanic bool // if set, don't recover() from panics in callbacks
|
||||
Server string
|
||||
TLSConfig *tls.Config
|
||||
Nick string
|
||||
User string
|
||||
RealName string // IRC realname/gecos
|
||||
WebIRC []string // parameters for the WEBIRC command
|
||||
Password string // server password (PASS command)
|
||||
RequestCaps []string // IRCv3 capabilities to request (failure is non-fatal)
|
||||
SASLLogin string // SASL credentials to log in with (failure is fatal)
|
||||
SASLPassword string
|
||||
SASLMech string
|
||||
QuitMessage string
|
||||
Version string
|
||||
Timeout time.Duration
|
||||
KeepAlive time.Duration
|
||||
ReconnectFreq time.Duration
|
||||
MaxLineLen int // maximum line length, not including tags
|
||||
UseTLS bool
|
||||
UseSASL bool
|
||||
EnableCTCP bool
|
||||
Debug bool
|
||||
AllowPanic bool // if set, don't recover() from panics in callbacks
|
||||
AllowTruncation bool // if set, truncate lines exceeding MaxLineLen and send them
|
||||
|
||||
// networking and synchronization
|
||||
stateMutex sync.Mutex // innermost mutex: don't block while holding this
|
||||
|
@ -4,6 +4,8 @@
|
||||
package ircutils
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
@ -23,3 +25,38 @@ func TruncateUTF8Safe(message string, byteLimit int) (result string) {
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
// Sanitizes human-readable text to make it safe for IRC;
|
||||
// assumes UTF-8 and uses the replacement character where
|
||||
// applicable.
|
||||
func SanitizeText(message string, byteLimit int) (result string) {
|
||||
var buf strings.Builder
|
||||
|
||||
for _, r := range message {
|
||||
if r == '\x00' || r == '\r' {
|
||||
continue
|
||||
} else if r == '\n' {
|
||||
if buf.Len()+2 <= byteLimit {
|
||||
buf.WriteString(" ")
|
||||
continue
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else if unicode.IsSpace(r) {
|
||||
if buf.Len()+1 <= byteLimit {
|
||||
buf.WriteString(" ")
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
rLen := utf8.RuneLen(r)
|
||||
if buf.Len()+rLen <= byteLimit {
|
||||
buf.WriteRune(r)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
@ -31,3 +31,16 @@ func TestTruncateUTF8(t *testing.T) {
|
||||
// shouldn't truncate the whole string
|
||||
assertEqual(TruncateUTF8Safe("\xff\xff\xff\xff\xff\xff", 5), "\xff\xff")
|
||||
}
|
||||
|
||||
func TestSanitize(t *testing.T) {
|
||||
assertEqual(SanitizeText("abc", 10), "abc")
|
||||
assertEqual(SanitizeText("abcdef", 5), "abcde")
|
||||
|
||||
assertEqual(SanitizeText("shivaram\x00shivaram\x00shivarampassphrase", 400), "shivaramshivaramshivarampassphrase")
|
||||
|
||||
assertEqual(SanitizeText("the quick brown fox\xffjumps over the lazy dog", 400), "the quick brown fox\xef\xbf\xbdjumps over the lazy dog")
|
||||
|
||||
// \r ignored, \n is two spaces
|
||||
assertEqual(SanitizeText("the quick brown fox\r\njumps over the lazy dog", 400), "the quick brown fox jumps over the lazy dog")
|
||||
assertEqual(SanitizeText("the quick brown fox\njumps over the lazy dog", 400), "the quick brown fox jumps over the lazy dog")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user