diff --git a/ircmsg/message.go b/ircmsg/message.go index 5bb8ae0..d7e17b8 100644 --- a/ircmsg/message.go +++ b/ircmsg/message.go @@ -155,6 +155,14 @@ func trimFinalNewlines(str string) string { return str[:i+1] } +// slice off any amount of ' ' from the front of the string +func trimInitialSpaces(str string) string { + var i int + for i = 0; i < len(str) && str[i] == ' '; i += 1 { + } + return str[i:] +} + func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg IrcMessage, err error) { if strings.IndexByte(line, '\x00') != -1 { err = ErrorLineContainsBadChar @@ -190,8 +198,12 @@ func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg IrcMe line = line[:truncateLen] } + // modern: "These message parts, and parameters themselves, are separated + // by one or more ASCII SPACE characters" + line = trimInitialSpaces(line) + // prefix - if line[0] == ':' { + if 0 < len(line) && line[0] == ':' { prefixEnd := strings.IndexByte(line, ' ') if prefixEnd == -1 { return ircmsg, ErrorLineIsEmpty @@ -201,6 +213,8 @@ func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg IrcMe line = line[prefixEnd+1:] } + line = trimInitialSpaces(line) + // command commandEnd := strings.IndexByte(line, ' ') paramStart := commandEnd + 1 @@ -215,7 +229,11 @@ func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg IrcMe } line = line[paramStart:] - for 0 < len(line) { + for { + line = trimInitialSpaces(line) + if len(line) == 0 { + break + } // handle trailing if line[0] == ':' { ircmsg.Params = append(ircmsg.Params, line[1:]) @@ -225,9 +243,6 @@ func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg IrcMe if paramEnd == -1 { ircmsg.Params = append(ircmsg.Params, line) break - } else if paramEnd == 0 { - // only a trailing parameter can be empty - return ircmsg, ErrorLineContainsBadChar } ircmsg.Params = append(ircmsg.Params, line[:paramEnd]) line = line[paramEnd+1:] diff --git a/ircmsg/message_test.go b/ircmsg/message_test.go index c9b55f1..963d49c 100644 --- a/ircmsg/message_test.go +++ b/ircmsg/message_test.go @@ -61,8 +61,18 @@ var decodetests = []testcode{ MakeMessage(map[string]string{"+draft/test": "hi\nthere"}, "", "PING", "HiThere!")}, {"ping asdf\n", MakeMessage(nil, "", "PING", "asdf")}, + {"JoIN #channel\n", + MakeMessage(nil, "", "JOIN", "#channel")}, + {"@draft/label=l join #channel\n", + MakeMessage(map[string]string{"draft/label": "l"}, "", "JOIN", "#channel")}, {"list", MakeMessage(nil, "", "LIST")}, + {"list ", + MakeMessage(nil, "", "LIST")}, + {"list ", + MakeMessage(nil, "", "LIST")}, + {"@time=2848 :dan-!d@localhost LIST \r\n", + MakeMessage(map[string]string{"time": "2848"}, "dan-!d@localhost", "LIST")}, } type testparseerror struct {