Punt hid back where it came from
This commit is contained in:
		
							
								
								
									
										22
									
								
								README.adoc
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								README.adoc
									
									
									
									
									
								
							@@ -34,7 +34,6 @@ figured out it would make sense:
 | 
				
			|||||||
 - hbfe - bitmap font editor
 | 
					 - hbfe - bitmap font editor
 | 
				
			||||||
 - he   - text editor
 | 
					 - he   - text editor
 | 
				
			||||||
 - hfm  - file manager
 | 
					 - hfm  - file manager
 | 
				
			||||||
 - hid  - IRC daemon
 | 
					 | 
				
			||||||
 - hm   - mail client
 | 
					 - hm   - mail client
 | 
				
			||||||
 - hnc  - netcat-alike
 | 
					 - hnc  - netcat-alike
 | 
				
			||||||
 - ho   - all-powerful organizer
 | 
					 - ho   - all-powerful organizer
 | 
				
			||||||
@@ -57,26 +56,11 @@ permeating the entire list.
 | 
				
			|||||||
Some information is omitted from these descriptions and lies either in my head
 | 
					Some information is omitted from these descriptions and lies either in my head
 | 
				
			||||||
or in my other notes.
 | 
					or in my other notes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
hid -- IRC daemon
 | 
					 | 
				
			||||||
~~~~~~~~~~~~~~~~~
 | 
					 | 
				
			||||||
This project is unimportant by itself, its sole purpose is to gain experience
 | 
					 | 
				
			||||||
with Go on something that I have already done and understand well.  Nothing
 | 
					 | 
				
			||||||
beyond achieving feature parity is in the initial scope.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
One possibility of complicating would be adding simple WebSocket listeners but
 | 
					 | 
				
			||||||
that's already been done for me https://github.com/kiwiirc/webircgateway and
 | 
					 | 
				
			||||||
it's even in Go, I just need to set up kiwiirc.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Later, when we have a pleasant IRC client, implement either the P10 or the TS6
 | 
					 | 
				
			||||||
server-linking protocol and make atheme work with a generic module.
 | 
					 | 
				
			||||||
Alternatively add support for plugins.  The goal is to allow creating integrated
 | 
					 | 
				
			||||||
bridges to various public forums.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
hnc -- netcat-alike
 | 
					hnc -- netcat-alike
 | 
				
			||||||
~~~~~~~~~~~~~~~~~~~
 | 
					~~~~~~~~~~~~~~~~~~~
 | 
				
			||||||
The result of testing hid with telnet, OpenSSL s_client, OpenBSD nc, GNU nc and
 | 
					The result of testing xK/xS with telnet, OpenSSL s_client, OpenBSD nc, GNU nc,
 | 
				
			||||||
Ncat is that neither of them can properly shutdown the connection.  We need
 | 
					and Ncat is that neither of them can properly shutdown the connection.
 | 
				
			||||||
a good implementation with TLS support.
 | 
					We need a good implementation with TLS support.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
hpcu -- PRIMARY-CLIPBOARD unifier
 | 
					hpcu -- PRIMARY-CLIPBOARD unifier
 | 
				
			||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
					~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,16 +0,0 @@
 | 
				
			|||||||
#!/bin/sh
 | 
					 | 
				
			||||||
LC_ALL=C exec awk '
 | 
					 | 
				
			||||||
	/^[0-9]+ *(ERR|RPL)_[A-Z]+ *".*"$/ {
 | 
					 | 
				
			||||||
		match($0, /".*"/);
 | 
					 | 
				
			||||||
		ids[$1] = $2;
 | 
					 | 
				
			||||||
		texts[$2] = substr($0, RSTART, RLENGTH);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	END {
 | 
					 | 
				
			||||||
		print "package " ENVIRON["GOPACKAGE"] "\n\nconst ("
 | 
					 | 
				
			||||||
		for (i in ids)
 | 
					 | 
				
			||||||
			printf("\t%s = %s\n", ids[i], i)
 | 
					 | 
				
			||||||
		print ")\n\nvar defaultReplies = map[int]string{"
 | 
					 | 
				
			||||||
		for (i in ids)
 | 
					 | 
				
			||||||
			print "\t" ids[i] ": " texts[ids[i]] ","
 | 
					 | 
				
			||||||
		print "}"
 | 
					 | 
				
			||||||
	}'
 | 
					 | 
				
			||||||
@@ -1,87 +0,0 @@
 | 
				
			|||||||
1 RPL_WELCOME ":Welcome to the Internet Relay Network %s!%s@%s"
 | 
					 | 
				
			||||||
2 RPL_YOURHOST ":Your host is %s, running version %s"
 | 
					 | 
				
			||||||
3 RPL_CREATED ":This server was created %s"
 | 
					 | 
				
			||||||
4 RPL_MYINFO "%s %s %s %s"
 | 
					 | 
				
			||||||
5 RPL_ISUPPORT "%s :are supported by this server"
 | 
					 | 
				
			||||||
211 RPL_STATSLINKINFO "%s %d %d %d %d %d %d"
 | 
					 | 
				
			||||||
212 RPL_STATSCOMMANDS "%s %d %d %d"
 | 
					 | 
				
			||||||
219 RPL_ENDOFSTATS "%c :End of STATS report"
 | 
					 | 
				
			||||||
221 RPL_UMODEIS "+%s"
 | 
					 | 
				
			||||||
242 RPL_STATSUPTIME ":Server Up %d days %d:%02d:%02d"
 | 
					 | 
				
			||||||
251 RPL_LUSERCLIENT ":There are %d users and %d services on %d servers"
 | 
					 | 
				
			||||||
252 RPL_LUSEROP "%d :operator(s) online"
 | 
					 | 
				
			||||||
253 RPL_LUSERUNKNOWN "%d :unknown connection(s)"
 | 
					 | 
				
			||||||
254 RPL_LUSERCHANNELS "%d :channels formed"
 | 
					 | 
				
			||||||
255 RPL_LUSERME ":I have %d clients and %d servers"
 | 
					 | 
				
			||||||
301 RPL_AWAY "%s :%s"
 | 
					 | 
				
			||||||
302 RPL_USERHOST ":%s"
 | 
					 | 
				
			||||||
303 RPL_ISON ":%s"
 | 
					 | 
				
			||||||
305 RPL_UNAWAY ":You are no longer marked as being away"
 | 
					 | 
				
			||||||
306 RPL_NOWAWAY ":You have been marked as being away"
 | 
					 | 
				
			||||||
311 RPL_WHOISUSER "%s %s %s * :%s"
 | 
					 | 
				
			||||||
312 RPL_WHOISSERVER "%s %s :%s"
 | 
					 | 
				
			||||||
313 RPL_WHOISOPERATOR "%s :is an IRC operator"
 | 
					 | 
				
			||||||
314 RPL_WHOWASUSER "%s %s %s * :%s"
 | 
					 | 
				
			||||||
315 RPL_ENDOFWHO "%s :End of WHO list"
 | 
					 | 
				
			||||||
317 RPL_WHOISIDLE "%s %d :seconds idle"
 | 
					 | 
				
			||||||
318 RPL_ENDOFWHOIS "%s :End of WHOIS list"
 | 
					 | 
				
			||||||
319 RPL_WHOISCHANNELS "%s :%s"
 | 
					 | 
				
			||||||
322 RPL_LIST "%s %d :%s"
 | 
					 | 
				
			||||||
323 RPL_LISTEND ":End of LIST"
 | 
					 | 
				
			||||||
324 RPL_CHANNELMODEIS "%s +%s"
 | 
					 | 
				
			||||||
329 RPL_CREATIONTIME "%s %d"
 | 
					 | 
				
			||||||
331 RPL_NOTOPIC "%s :No topic is set"
 | 
					 | 
				
			||||||
332 RPL_TOPIC "%s :%s"
 | 
					 | 
				
			||||||
333 RPL_TOPICWHOTIME "%s %s %d"
 | 
					 | 
				
			||||||
341 RPL_INVITING "%s %s"
 | 
					 | 
				
			||||||
346 RPL_INVITELIST "%s %s"
 | 
					 | 
				
			||||||
347 RPL_ENDOFINVITELIST "%s :End of channel invite list"
 | 
					 | 
				
			||||||
348 RPL_EXCEPTLIST "%s %s"
 | 
					 | 
				
			||||||
349 RPL_ENDOFEXCEPTLIST "%s :End of channel exception list"
 | 
					 | 
				
			||||||
351 RPL_VERSION "%s.%d %s :%s"
 | 
					 | 
				
			||||||
352 RPL_WHOREPLY "%s %s %s %s %s %s :%d %s"
 | 
					 | 
				
			||||||
353 RPL_NAMREPLY "%c %s :%s"
 | 
					 | 
				
			||||||
364 RPL_LINKS "%s %s :%d %s"
 | 
					 | 
				
			||||||
365 RPL_ENDOFLINKS "%s :End of LINKS list"
 | 
					 | 
				
			||||||
366 RPL_ENDOFNAMES "%s :End of NAMES list"
 | 
					 | 
				
			||||||
367 RPL_BANLIST "%s %s"
 | 
					 | 
				
			||||||
368 RPL_ENDOFBANLIST "%s :End of channel ban list"
 | 
					 | 
				
			||||||
369 RPL_ENDOFWHOWAS "%s :End of WHOWAS"
 | 
					 | 
				
			||||||
372 RPL_MOTD ":- %s"
 | 
					 | 
				
			||||||
375 RPL_MOTDSTART ":- %s Message of the day - "
 | 
					 | 
				
			||||||
376 RPL_ENDOFMOTD ":End of MOTD command"
 | 
					 | 
				
			||||||
391 RPL_TIME "%s :%s"
 | 
					 | 
				
			||||||
401 ERR_NOSUCHNICK "%s :No such nick/channel"
 | 
					 | 
				
			||||||
402 ERR_NOSUCHSERVER "%s :No such server"
 | 
					 | 
				
			||||||
403 ERR_NOSUCHCHANNEL "%s :No such channel"
 | 
					 | 
				
			||||||
404 ERR_CANNOTSENDTOCHAN "%s :Cannot send to channel"
 | 
					 | 
				
			||||||
406 ERR_WASNOSUCHNICK "%s :There was no such nickname"
 | 
					 | 
				
			||||||
409 ERR_NOORIGIN ":No origin specified"
 | 
					 | 
				
			||||||
410 ERR_INVALIDCAPCMD "%s :%s"
 | 
					 | 
				
			||||||
411 ERR_NORECIPIENT ":No recipient given (%s)"
 | 
					 | 
				
			||||||
412 ERR_NOTEXTTOSEND ":No text to send"
 | 
					 | 
				
			||||||
421 ERR_UNKNOWNCOMMAND "%s: Unknown command"
 | 
					 | 
				
			||||||
422 ERR_NOMOTD ":MOTD File is missing"
 | 
					 | 
				
			||||||
423 ERR_NOADMININFO "%s :No administrative info available"
 | 
					 | 
				
			||||||
431 ERR_NONICKNAMEGIVEN ":No nickname given"
 | 
					 | 
				
			||||||
432 ERR_ERRONEOUSNICKNAME "%s :Erroneous nickname"
 | 
					 | 
				
			||||||
433 ERR_NICKNAMEINUSE "%s :Nickname is already in use"
 | 
					 | 
				
			||||||
441 ERR_USERNOTINCHANNEL "%s %s :They aren't on that channel"
 | 
					 | 
				
			||||||
442 ERR_NOTONCHANNEL "%s :You're not on that channel"
 | 
					 | 
				
			||||||
443 ERR_USERONCHANNEL "%s %s :is already on channel"
 | 
					 | 
				
			||||||
445 ERR_SUMMONDISABLED ":SUMMON has been disabled"
 | 
					 | 
				
			||||||
446 ERR_USERSDISABLED ":USERS has been disabled"
 | 
					 | 
				
			||||||
451 ERR_NOTREGISTERED ":You have not registered"
 | 
					 | 
				
			||||||
461 ERR_NEEDMOREPARAMS "%s :Not enough parameters"
 | 
					 | 
				
			||||||
462 ERR_ALREADYREGISTERED ":Unauthorized command (already registered)"
 | 
					 | 
				
			||||||
467 ERR_KEYSET "%s :Channel key already set"
 | 
					 | 
				
			||||||
471 ERR_CHANNELISFULL "%s :Cannot join channel (+l)"
 | 
					 | 
				
			||||||
472 ERR_UNKNOWNMODE "%c :is unknown mode char to me for %s"
 | 
					 | 
				
			||||||
473 ERR_INVITEONLYCHAN "%s :Cannot join channel (+i)"
 | 
					 | 
				
			||||||
474 ERR_BANNEDFROMCHAN "%s :Cannot join channel (+b)"
 | 
					 | 
				
			||||||
475 ERR_BADCHANNELKEY "%s :Cannot join channel (+k)"
 | 
					 | 
				
			||||||
476 ERR_BADCHANMASK "%s :Bad Channel Mask"
 | 
					 | 
				
			||||||
481 ERR_NOPRIVILEGES ":Permission Denied- You're not an IRC operator"
 | 
					 | 
				
			||||||
482 ERR_CHANOPRIVSNEEDED "%s :You're not channel operator"
 | 
					 | 
				
			||||||
501 ERR_UMODEUNKNOWNFLAG ":Unknown MODE flag"
 | 
					 | 
				
			||||||
502 ERR_USERSDONTMATCH ":Cannot change mode for other users"
 | 
					 | 
				
			||||||
							
								
								
									
										3530
									
								
								hid/main.go
									
									
									
									
									
								
							
							
						
						
									
										3530
									
								
								hid/main.go
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										168
									
								
								hid/main_test.go
									
									
									
									
									
								
							
							
						
						
									
										168
									
								
								hid/main_test.go
									
									
									
									
									
								
							@@ -1,168 +0,0 @@
 | 
				
			|||||||
//
 | 
					 | 
				
			||||||
// Copyright (c) 2015 - 2018, Přemysl Eric Janouch <p@janouch.name>
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Permission to use, copy, modify, and/or distribute this software for any
 | 
					 | 
				
			||||||
// purpose with or without fee is hereby granted.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
					 | 
				
			||||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
					 | 
				
			||||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 | 
					 | 
				
			||||||
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
					 | 
				
			||||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 | 
					 | 
				
			||||||
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 | 
					 | 
				
			||||||
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"crypto/tls"
 | 
					 | 
				
			||||||
	"net"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"reflect"
 | 
					 | 
				
			||||||
	"syscall"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSplitString(t *testing.T) {
 | 
					 | 
				
			||||||
	var splitStringTests = []struct {
 | 
					 | 
				
			||||||
		s, delims   string
 | 
					 | 
				
			||||||
		ignoreEmpty bool
 | 
					 | 
				
			||||||
		result      []string
 | 
					 | 
				
			||||||
	}{
 | 
					 | 
				
			||||||
		{",a,,bc", ",", false, []string{"", "a", "", "bc"}},
 | 
					 | 
				
			||||||
		{",a,,bc", ",", true, []string{"a", "bc"}},
 | 
					 | 
				
			||||||
		{"a,;bc,", ",;", false, []string{"a", "", "bc", ""}},
 | 
					 | 
				
			||||||
		{"a,;bc,", ",;", true, []string{"a", "bc"}},
 | 
					 | 
				
			||||||
		{"", ",", false, []string{""}},
 | 
					 | 
				
			||||||
		{"", ",", true, nil},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for i, d := range splitStringTests {
 | 
					 | 
				
			||||||
		got := splitString(d.s, d.delims, d.ignoreEmpty)
 | 
					 | 
				
			||||||
		if !reflect.DeepEqual(got, d.result) {
 | 
					 | 
				
			||||||
			t.Errorf("case %d: %v should be %v\n", i, got, d.result)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func socketpair() (*os.File, *os.File, error) {
 | 
					 | 
				
			||||||
	pair, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// See go #24331, this makes 1.11 use the internal poller
 | 
					 | 
				
			||||||
	// while there wasn't a way to achieve that before.
 | 
					 | 
				
			||||||
	if err := syscall.SetNonblock(int(pair[0]), true); err != nil {
 | 
					 | 
				
			||||||
		return nil, nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err := syscall.SetNonblock(int(pair[1]), true); err != nil {
 | 
					 | 
				
			||||||
		return nil, nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fa := os.NewFile(uintptr(pair[0]), "a")
 | 
					 | 
				
			||||||
	if fa == nil {
 | 
					 | 
				
			||||||
		return nil, nil, os.ErrInvalid
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fb := os.NewFile(uintptr(pair[1]), "b")
 | 
					 | 
				
			||||||
	if fb == nil {
 | 
					 | 
				
			||||||
		fa.Close()
 | 
					 | 
				
			||||||
		return nil, nil, os.ErrInvalid
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return fa, fb, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestDetectTLS(t *testing.T) {
 | 
					 | 
				
			||||||
	detectTLSFromFunc := func(t *testing.T, writer func(net.Conn)) bool {
 | 
					 | 
				
			||||||
		// net.Pipe doesn't use file descriptors, we need a socketpair.
 | 
					 | 
				
			||||||
		sockA, sockB, err := socketpair()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			t.Fatal(err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		defer sockA.Close()
 | 
					 | 
				
			||||||
		defer sockB.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		fcB, err := net.FileConn(sockB)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			t.Fatal(err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		go writer(fcB)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		fcA, err := net.FileConn(sockA)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			t.Fatal(err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		sc, err := fcA.(syscall.Conn).SyscallConn()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			t.Fatal(err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return detectTLS(sc)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	t.Run("SSL_2.0", func(t *testing.T) {
 | 
					 | 
				
			||||||
		if !detectTLSFromFunc(t, func(fc net.Conn) {
 | 
					 | 
				
			||||||
			// The obsolete, useless, unsupported SSL 2.0 record format.
 | 
					 | 
				
			||||||
			_, _ = fc.Write([]byte{0x80, 0x01, 0x01})
 | 
					 | 
				
			||||||
		}) {
 | 
					 | 
				
			||||||
			t.Error("could not detect SSL")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	t.Run("crypto_tls", func(t *testing.T) {
 | 
					 | 
				
			||||||
		if !detectTLSFromFunc(t, func(fc net.Conn) {
 | 
					 | 
				
			||||||
			conn := tls.Client(fc, &tls.Config{InsecureSkipVerify: true})
 | 
					 | 
				
			||||||
			_ = conn.Handshake()
 | 
					 | 
				
			||||||
		}) {
 | 
					 | 
				
			||||||
			t.Error("could not detect TLS")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	t.Run("text", func(t *testing.T) {
 | 
					 | 
				
			||||||
		if detectTLSFromFunc(t, func(fc net.Conn) {
 | 
					 | 
				
			||||||
			_, _ = fc.Write([]byte("ПРЕВЕД"))
 | 
					 | 
				
			||||||
		}) {
 | 
					 | 
				
			||||||
			t.Error("detected UTF-8 as TLS")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	t.Run("EOF", func(t *testing.T) {
 | 
					 | 
				
			||||||
		type connCloseWriter interface {
 | 
					 | 
				
			||||||
			net.Conn
 | 
					 | 
				
			||||||
			CloseWrite() error
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if detectTLSFromFunc(t, func(fc net.Conn) {
 | 
					 | 
				
			||||||
			_ = fc.(connCloseWriter).CloseWrite()
 | 
					 | 
				
			||||||
		}) {
 | 
					 | 
				
			||||||
			t.Error("detected EOF as TLS")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestIRC(t *testing.T) {
 | 
					 | 
				
			||||||
	msg := ircParseMessage(
 | 
					 | 
				
			||||||
		`@first=a\:\s\r\n\\;2nd :srv hi there :good m8 :how are you?`)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !reflect.DeepEqual(msg.tags, map[string]string{
 | 
					 | 
				
			||||||
		"first": "a; \r\n\\",
 | 
					 | 
				
			||||||
		"2nd":   "",
 | 
					 | 
				
			||||||
	}) {
 | 
					 | 
				
			||||||
		t.Error("tags parsed incorrectly")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if msg.nick != "srv" || msg.user != "" || msg.host != "" {
 | 
					 | 
				
			||||||
		t.Error("server name parsed incorrectly")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if msg.command != "hi" {
 | 
					 | 
				
			||||||
		t.Error("command name parsed incorrectly")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !reflect.DeepEqual(msg.params,
 | 
					 | 
				
			||||||
		[]string{"there", "good m8 :how are you?"}) {
 | 
					 | 
				
			||||||
		t.Error("params parsed incorrectly")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !ircEqual("[fag]^", "{FAG}~") {
 | 
					 | 
				
			||||||
		t.Error("string case comparison not according to RFC 2812")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TODO: More tests.
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user