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.
|
// Send a built ircmsg.Message.
|
||||||
func (irc *Connection) SendIRCMessage(msg ircmsg.Message) error {
|
func (irc *Connection) SendIRCMessage(msg ircmsg.Message) error {
|
||||||
b, err := msg.LineBytesStrict(true, irc.MaxLineLen)
|
b, err := msg.LineBytesStrict(true, irc.MaxLineLen)
|
||||||
if err != nil {
|
if err != nil && !(irc.AllowTruncation && err == ircmsg.ErrorBodyTooLong) {
|
||||||
if irc.Debug {
|
if irc.Debug {
|
||||||
irc.Log.Printf("couldn't assemble message: %v\n", err)
|
irc.Log.Printf("couldn't assemble message: %v\n", err)
|
||||||
}
|
}
|
||||||
|
@ -41,28 +41,29 @@ type capResult struct {
|
|||||||
|
|
||||||
type Connection struct {
|
type Connection struct {
|
||||||
// config data, user-settable
|
// config data, user-settable
|
||||||
Server string
|
Server string
|
||||||
TLSConfig *tls.Config
|
TLSConfig *tls.Config
|
||||||
Nick string
|
Nick string
|
||||||
User string
|
User string
|
||||||
RealName string // IRC realname/gecos
|
RealName string // IRC realname/gecos
|
||||||
WebIRC []string // parameters for the WEBIRC command
|
WebIRC []string // parameters for the WEBIRC command
|
||||||
Password string // server password (PASS command)
|
Password string // server password (PASS command)
|
||||||
RequestCaps []string // IRCv3 capabilities to request (failure is non-fatal)
|
RequestCaps []string // IRCv3 capabilities to request (failure is non-fatal)
|
||||||
SASLLogin string // SASL credentials to log in with (failure is fatal)
|
SASLLogin string // SASL credentials to log in with (failure is fatal)
|
||||||
SASLPassword string
|
SASLPassword string
|
||||||
SASLMech string
|
SASLMech string
|
||||||
QuitMessage string
|
QuitMessage string
|
||||||
Version string
|
Version string
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
KeepAlive time.Duration
|
KeepAlive time.Duration
|
||||||
ReconnectFreq time.Duration
|
ReconnectFreq time.Duration
|
||||||
MaxLineLen int // maximum line length, not including tags
|
MaxLineLen int // maximum line length, not including tags
|
||||||
UseTLS bool
|
UseTLS bool
|
||||||
UseSASL bool
|
UseSASL bool
|
||||||
EnableCTCP bool
|
EnableCTCP bool
|
||||||
Debug bool
|
Debug bool
|
||||||
AllowPanic bool // if set, don't recover() from panics in callbacks
|
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
|
// networking and synchronization
|
||||||
stateMutex sync.Mutex // innermost mutex: don't block while holding this
|
stateMutex sync.Mutex // innermost mutex: don't block while holding this
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
package ircutils
|
package ircutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,3 +25,38 @@ func TruncateUTF8Safe(message string, byteLimit int) (result string) {
|
|||||||
}
|
}
|
||||||
return message
|
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
|
// shouldn't truncate the whole string
|
||||||
assertEqual(TruncateUTF8Safe("\xff\xff\xff\xff\xff\xff", 5), "\xff\xff")
|
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