Index: trunk/upstream.go
===================================================================
--- trunk/upstream.go	(revision 42)
+++ trunk/upstream.go	(revision 43)
@@ -107,9 +107,8 @@
 		return nil
 	case "MODE":
-		if len(msg.Params) < 2 {
-			return newNeedMoreParamsError(msg.Command)
-		}
-		name := msg.Params[0]
-		modeStr := msg.Params[1]
+		var name, modeStr string
+		if err := parseMessageParams(msg, &name, &modeStr); err != nil {
+			return err
+		}
 
 		if name == msg.Prefix.Name { // user mode change
@@ -144,18 +143,15 @@
 		}
 	case irc.RPL_MYINFO:
-		if len(msg.Params) < 5 {
-			return newNeedMoreParamsError(msg.Command)
-		}
-		c.serverName = msg.Params[1]
-		c.availableUserModes = msg.Params[3]
-		c.availableChannelModes = msg.Params[4]
+		if err := parseMessageParams(msg, nil, &c.serverName, nil, &c.availableUserModes, &c.availableChannelModes); err != nil {
+			return err
+		}
 		if len(msg.Params) > 5 {
 			c.channelModesWithParam = msg.Params[5]
 		}
 	case "NICK":
-		if len(msg.Params) < 1 {
-			return newNeedMoreParamsError(msg.Command)
-		}
-		newNick := msg.Params[0]
+		var newNick string
+		if err := parseMessageParams(msg, &newNick); err != nil {
+			return err
+		}
 
 		if msg.Prefix.Name == c.nick {
@@ -175,9 +171,10 @@
 		})
 	case "JOIN":
-		if len(msg.Params) < 1 {
-			return newNeedMoreParamsError(msg.Command)
-		}
-
-		for _, ch := range strings.Split(msg.Params[0], ",") {
+		var channels string
+		if err := parseMessageParams(msg, &channels); err != nil {
+			return err
+		}
+
+		for _, ch := range strings.Split(channels, ",") {
 			if msg.Prefix.Name == c.nick {
 				c.logger.Printf("joined channel %q", ch)
@@ -199,9 +196,10 @@
 		})
 	case "PART":
-		if len(msg.Params) < 1 {
-			return newNeedMoreParamsError(msg.Command)
-		}
-
-		for _, ch := range strings.Split(msg.Params[0], ",") {
+		var channels string
+		if err := parseMessageParams(msg, &channels); err != nil {
+			return err
+		}
+
+		for _, ch := range strings.Split(channels, ",") {
 			if msg.Prefix.Name == c.nick {
 				c.logger.Printf("parted channel %q", ch)
@@ -220,21 +218,23 @@
 		})
 	case irc.RPL_TOPIC, irc.RPL_NOTOPIC:
-		if len(msg.Params) < 3 {
-			return newNeedMoreParamsError(msg.Command)
-		}
-		ch, err := c.getChannel(msg.Params[1])
+		var name, topic string
+		if err := parseMessageParams(msg, nil, &name, &topic); err != nil {
+			return err
+		}
+		ch, err := c.getChannel(name)
 		if err != nil {
 			return err
 		}
 		if msg.Command == irc.RPL_TOPIC {
-			ch.Topic = msg.Params[2]
+			ch.Topic = topic
 		} else {
 			ch.Topic = ""
 		}
 	case "TOPIC":
-		if len(msg.Params) < 1 {
-			return newNeedMoreParamsError(msg.Command)
-		}
-		ch, err := c.getChannel(msg.Params[0])
+		var name string
+		if err := parseMessageParams(msg, nil, &name); err != nil {
+			return err
+		}
+		ch, err := c.getChannel(name)
 		if err != nil {
 			return err
@@ -246,13 +246,14 @@
 		}
 	case rpl_topicwhotime:
-		if len(msg.Params) < 4 {
-			return newNeedMoreParamsError(msg.Command)
-		}
-		ch, err := c.getChannel(msg.Params[1])
-		if err != nil {
-			return err
-		}
-		ch.TopicWho = msg.Params[2]
-		sec, err := strconv.ParseInt(msg.Params[3], 10, 64)
+		var name, who, timeStr string
+		if err := parseMessageParams(msg, nil, &name, &who, &timeStr); err != nil {
+			return err
+		}
+		ch, err := c.getChannel(name)
+		if err != nil {
+			return err
+		}
+		ch.TopicWho = who
+		sec, err := strconv.ParseInt(timeStr, 10, 64)
 		if err != nil {
 			return fmt.Errorf("failed to parse topic time: %v", err)
@@ -260,13 +261,14 @@
 		ch.TopicTime = time.Unix(sec, 0)
 	case irc.RPL_NAMREPLY:
-		if len(msg.Params) < 4 {
-			return newNeedMoreParamsError(msg.Command)
-		}
-		ch, err := c.getChannel(msg.Params[2])
-		if err != nil {
-			return err
-		}
-
-		status, err := parseChannelStatus(msg.Params[1])
+		var name, statusStr, members string
+		if err := parseMessageParams(msg, nil, &statusStr, &name, &members); err != nil {
+			return err
+		}
+		ch, err := c.getChannel(name)
+		if err != nil {
+			return err
+		}
+
+		status, err := parseChannelStatus(statusStr)
 		if err != nil {
 			return err
@@ -274,13 +276,14 @@
 		ch.Status = status
 
-		for _, s := range strings.Split(msg.Params[3], " ") {
+		for _, s := range strings.Split(members, " ") {
 			membership, nick := parseMembershipPrefix(s)
 			ch.Members[nick] = membership
 		}
 	case irc.RPL_ENDOFNAMES:
-		if len(msg.Params) < 2 {
-			return newNeedMoreParamsError(msg.Command)
-		}
-		ch, err := c.getChannel(msg.Params[1])
+		var name string
+		if err := parseMessageParams(msg, nil, &name); err != nil {
+			return err
+		}
+		ch, err := c.getChannel(name)
 		if err != nil {
 			return err
@@ -323,5 +326,4 @@
 		Params:  []string{c.upstream.Nick},
 	}
-
 	c.messages <- &irc.Message{
 		Command: "USER",
