Index: trunk/downstream.go
===================================================================
--- trunk/downstream.go	(revision 464)
+++ trunk/downstream.go	(revision 478)
@@ -117,4 +117,5 @@
 	user        *user
 	nick        string
+	nickCM      string
 	rawUsername string
 	networkName string
@@ -193,5 +194,5 @@
 	// TODO: this doesn't account for nick changes
 	if net.conn != nil {
-		return nick == net.conn.nick
+		return net.casemap(nick) == net.conn.nickCM
 	}
 	// We're not currently connected to the upstream connection, so we don't
@@ -199,5 +200,5 @@
 	// configured nickname and hope it was the one being used when we were
 	// connected.
-	return nick == net.Nick
+	return net.casemap(nick) == net.casemap(net.Nick)
 }
 
@@ -211,4 +212,5 @@
 		return dc.nick
 	}
+	name = partialCasemap(net.casemap, name)
 	if dc.network != nil {
 		if dc.network != net {
@@ -224,4 +226,5 @@
 		return dc.prefix()
 	}
+	prefix.Name = partialCasemap(net.casemap, prefix.Name)
 	if dc.network != nil {
 		if dc.network != net {
@@ -359,6 +362,6 @@
 	}
 
-	delivered, ok := network.delivered[entity]
-	if !ok {
+	delivered := network.delivered.Value(entity)
+	if delivered == nil {
 		return
 	}
@@ -446,5 +449,6 @@
 			}}
 		}
-		if nick == serviceNick {
+		nickCM := casemapASCII(nick)
+		if nickCM == serviceNickCM {
 			return ircError{&irc.Message{
 				Command: irc.ERR_NICKNAMEINUSE,
@@ -453,4 +457,5 @@
 		}
 		dc.nick = nick
+		dc.nickCM = nickCM
 	case "USER":
 		if err := parseMessageParams(msg, &dc.rawUsername, nil, nil, &dc.realname); err != nil {
@@ -767,4 +772,5 @@
 		})
 		dc.nick = uc.nick
+		dc.nickCM = casemapASCII(dc.nick)
 	}
 }
@@ -912,4 +918,5 @@
 	isupport := []string{
 		fmt.Sprintf("CHATHISTORY=%v", dc.srv.HistoryLimit),
+		"CASEMAPPING=ascii",
 	}
 
@@ -961,9 +968,11 @@
 
 	dc.forEachUpstream(func(uc *upstreamConn) {
-		for _, ch := range uc.channels {
+		for _, entry := range uc.channels.innerMap {
+			ch := entry.value.(*upstreamChannel)
 			if !ch.complete {
 				continue
 			}
-			if record, ok := uc.network.channels[ch.Name]; ok && record.Detached {
+			record := uc.network.channels.Value(ch.Name)
+			if record != nil && record.Detached {
 				continue
 			}
@@ -988,6 +997,8 @@
 
 		// Fast-forward history to last message
-		for target, delivered := range net.delivered {
-			if ch, ok := net.channels[target]; ok && ch.Detached {
+		for target, entry := range net.delivered.innerMap {
+			delivered := entry.value.(map[string]string)
+			ch := net.channels.Value(target)
+			if ch != nil && ch.Detached {
 				continue
 			}
@@ -1020,5 +1031,6 @@
 
 func (dc *downstreamConn) sendNetworkBacklog(net *network) {
-	for target := range net.delivered {
+	for _, entry := range net.delivered.innerMap {
+		target := entry.originalKey
 		dc.sendTargetBacklog(net, target)
 	}
@@ -1029,9 +1041,9 @@
 		return
 	}
-	if ch, ok := net.channels[target]; ok && ch.Detached {
+	if ch := net.channels.Value(target); ch != nil && ch.Detached {
 		return
 	}
-	delivered, ok := net.delivered[target]
-	if !ok {
+	delivered := net.delivered.Value(target)
+	if delivered == nil {
 		return
 	}
@@ -1159,5 +1171,5 @@
 			}}
 		}
-		if nick == serviceNick {
+		if casemapASCII(nick) == serviceNickCM {
 			return ircError{&irc.Message{
 				Command: irc.ERR_NICKNAMEINUSE,
@@ -1195,4 +1207,5 @@
 			})
 			dc.nick = nick
+			dc.nickCM = casemapASCII(dc.nick)
 		}
 	case "JOIN":
@@ -1227,7 +1240,6 @@
 			})
 
-			var ch *Channel
-			var ok bool
-			if ch, ok = uc.network.channels[upstreamName]; ok {
+			ch := uc.network.channels.Value(upstreamName)
+			if ch != nil {
 				// Don't clear the channel key if there's one set
 				// TODO: add a way to unset the channel key
@@ -1241,5 +1253,5 @@
 					Key:  key,
 				}
-				uc.network.channels[upstreamName] = ch
+				uc.network.channels.SetValue(upstreamName, ch)
 			}
 			if err := dc.srv.db.StoreChannel(uc.network.ID, ch); err != nil {
@@ -1265,7 +1277,6 @@
 
 			if strings.EqualFold(reason, "detach") {
-				var ch *Channel
-				var ok bool
-				if ch, ok = uc.network.channels[upstreamName]; ok {
+				ch := uc.network.channels.Value(upstreamName)
+				if ch != nil {
 					uc.network.detach(ch)
 				} else {
@@ -1274,5 +1285,5 @@
 						Detached: true,
 					}
-					uc.network.channels[upstreamName] = ch
+					uc.network.channels.SetValue(upstreamName, ch)
 				}
 				if err := dc.srv.db.StoreChannel(uc.network.ID, ch); err != nil {
@@ -1361,5 +1372,5 @@
 		}
 
-		if name == dc.nick {
+		if casemapASCII(name) == dc.nickCM {
 			if modeStr != "" {
 				dc.forEachUpstream(func(uc *upstreamConn) {
@@ -1399,6 +1410,6 @@
 			})
 		} else {
-			ch, ok := uc.channels[upstreamName]
-			if !ok {
+			ch := uc.channels.Value(upstreamName)
+			if ch == nil {
 				return ircError{&irc.Message{
 					Command: irc.ERR_NOSUCHCHANNEL,
@@ -1436,5 +1447,5 @@
 		}
 
-		uc, upstreamChannel, err := dc.unmarshalEntity(channel)
+		uc, upstreamName, err := dc.unmarshalEntity(channel)
 		if err != nil {
 			return err
@@ -1445,12 +1456,12 @@
 			uc.SendMessageLabeled(dc.id, &irc.Message{
 				Command: "TOPIC",
-				Params:  []string{upstreamChannel, topic},
+				Params:  []string{upstreamName, topic},
 			})
 		} else { // getting topic
-			ch, ok := uc.channels[upstreamChannel]
-			if !ok {
+			ch := uc.channels.Value(upstreamName)
+			if ch == nil {
 				return ircError{&irc.Message{
 					Command: irc.ERR_NOSUCHCHANNEL,
-					Params:  []string{dc.nick, upstreamChannel, "No such channel"},
+					Params:  []string{dc.nick, upstreamName, "No such channel"},
 				}}
 			}
@@ -1514,11 +1525,11 @@
 		channels := strings.Split(msg.Params[0], ",")
 		for _, channel := range channels {
-			uc, upstreamChannel, err := dc.unmarshalEntity(channel)
+			uc, upstreamName, err := dc.unmarshalEntity(channel)
 			if err != nil {
 				return err
 			}
 
-			ch, ok := uc.channels[upstreamChannel]
-			if ok {
+			ch := uc.channels.Value(upstreamName)
+			if ch != nil {
 				sendNames(dc, ch)
 			} else {
@@ -1526,5 +1537,5 @@
 				uc.SendMessageLabeled(dc.id, &irc.Message{
 					Command: "NAMES",
-					Params:  []string{upstreamChannel},
+					Params:  []string{upstreamName},
 				})
 			}
@@ -1543,6 +1554,7 @@
 		// TODO: support WHO masks
 		entity := msg.Params[0]
-
-		if entity == dc.nick {
+		entityCM := casemapASCII(entity)
+
+		if entityCM == dc.nickCM {
 			// TODO: support AWAY (H/G) in self WHO reply
 			dc.SendMessage(&irc.Message{
@@ -1558,5 +1570,5 @@
 			return nil
 		}
-		if entity == serviceNick {
+		if entityCM == serviceNickCM {
 			dc.SendMessage(&irc.Message{
 				Prefix:  dc.srv.prefix(),
@@ -1609,5 +1621,5 @@
 		}
 
-		if mask == dc.nick {
+		if casemapASCII(mask) == dc.nickCM {
 			dc.SendMessage(&irc.Message{
 				Prefix:  dc.srv.prefix(),
