Commits

murarth committed a5fdc4d

Update to Go weekly 2011-12-14

Comments (0)

Files changed (37)

 package main
 
 import (
+	"errors"
 	"fmt"
 	"net"
-	"os"
-	"scanner"
+
+	"text/scanner"
 )
 
 type BindType int
 )
 
 type Bind struct {
-	Host string
+	Host  string
 	Ports []int
-	Type BindType
-	TLS bool
+	Type  BindType
+	TLS   bool
 
 	Config *Block
 }
 		b.Type == other.Type && b.TLS == other.TLS
 }
 
-func parsePorts(s string, pos scanner.Position) ([]int, os.Error) {
+func parsePorts(s string, pos scanner.Position) ([]int, error) {
 	ports := make([]int, 0)
 
-	scanLoop:
+scanLoop:
 	for s != "" {
 		var port int
 		var rest string
 		n, _ := fmt.Sscanf(s, "%d%s", &port, &rest)
 
 		if n == 0 {
-			return nil, os.NewError(fmt.Sprintf(
+			return nil, errors.New(fmt.Sprintf(
 				"Invalid port range %s at %s", s, pos))
 		} else if port < 1 || port > 65535 {
-			return nil, os.NewError(fmt.Sprintf(
+			return nil, errors.New(fmt.Sprintf(
 				"Invalid port %d at %s", port, pos))
 		}
 
 				n, _ := fmt.Sscanf(s, "%d%s", &maxPort, &rest)
 
 				if n == 0 || maxPort < port || maxPort > 65535 {
-					return nil, os.NewError(fmt.Sprintf(
+					return nil, errors.New(fmt.Sprintf(
 						"Invalid port range %s at %s", s, pos))
 				}
 
 	}
 
 	if len(ports) == 0 {
-		return nil, os.NewError(fmt.Sprintf("Empty port range at %s", pos))
+		return nil, errors.New(fmt.Sprintf("Empty port range at %s", pos))
 	}
 
 	return ports, nil
 }
 
-func LoadBinds(config *Config) (map[int] *Bind, os.Error) {
-	binds := make(map[int] *Bind)
+func LoadBinds(config *Config) (map[int]*Bind, error) {
+	binds := make(map[int]*Bind)
 
 	for _, b := range config.GetBlocks("Bind") {
-		 var ports []int
-		 bind := &Bind{Config: b}
+		var ports []int
+		bind := &Bind{Config: b}
 
-		 bind.Host = b.GetStringDefault("", "Address")
+		bind.Host = b.GetStringDefault("", "Address")
 
-		 portValue := b.GetValue("Port")
+		portValue := b.GetValue("Port")
 
-		 switch p := portValue.(type) {
-			case *Int:
-				if p.Value > 65535 {
-					return nil, os.NewError("Invalid port number " + p.String())
-				}
-				ports = []int{p.Value}
-		 	case *String:
-				if parsed, err := parsePorts(p.Value, p.Pos()); err != nil {
-					return nil, err
-				} else {
-					ports = parsed
-				}
-			default:
-				return nil, os.NewError(fmt.Sprintf(
-					"Expected int or string at %s", portValue.Pos()))
-		 }
+		switch p := portValue.(type) {
+		case *Int:
+			if p.Value > 65535 {
+				return nil, errors.New("Invalid port number " + p.String())
+			}
+			ports = []int{p.Value}
+		case *String:
+			if parsed, err := parsePorts(p.Value, p.Pos()); err != nil {
+				return nil, err
+			} else {
+				ports = parsed
+			}
+		default:
+			return nil, errors.New(fmt.Sprintf(
+				"Expected int or string at %s", portValue.Pos()))
+		}
 
-		 if typ, err := b.GetString("Type"); err != nil {
-		 	return nil, err
-		 } else if typ == "clients" {
-		 	bind.Type = BindClients
-		 } else if typ == "servers" {
-		 	bind.Type = BindServers
-		 } else {
-		 	return nil, os.NewError(fmt.Sprintf(
+		if typ, err := b.GetString("Type"); err != nil {
+			return nil, err
+		} else if typ == "clients" {
+			bind.Type = BindClients
+		} else if typ == "servers" {
+			bind.Type = BindServers
+		} else {
+			return nil, errors.New(fmt.Sprintf(
 				"Expected \"clients\" or \"servers\" at %s",
 				b.GetValue("Type").Pos()))
-		 }
+		}
 
-		 bind.TLS = b.GetBoolDefault(false, "TLS")
+		bind.TLS = b.GetBoolDefault(false, "TLS")
 
-		 bind.Ports = ports
+		bind.Ports = ports
 
-		 for _, port := range ports {
-		 	if existingBind, ok := binds[port]; ok {
-				return nil, os.NewError(fmt.Sprintf(
+		for _, port := range ports {
+			if existingBind, ok := binds[port]; ok {
+				return nil, errors.New(fmt.Sprintf(
 					"Port %d bound at %s was rebound at %s",
 					port, b.Pos, existingBind.Config.Pos))
 			}
 			binds[port] = bind
-		 }
+		}
 	}
 
 	return binds, nil
 )
 
 type ModeMask struct {
-	Mask string
-	SetBy string
+	Mask     string
+	SetBy    string
 	Creation int64
 }
 
-type MaskMap map[string] *ModeMask
+type MaskMap map[string]*ModeMask
 
 type Channel struct {
 	Name string
 
 	Creation int64
 
-	Users map[*User] bool
+	Users map[*User]bool
 
-	Prefixes map[*User] PrefixLevel
+	Prefixes map[*User]PrefixLevel
 
-	Bans MaskMap
+	Bans       MaskMap
 	Exceptions MaskMap
-	Invexes MaskMap
+	Invexes    MaskMap
 
-	Invitees map[*LocalUser] bool
-	modeParameters map[byte] string
+	Invitees       map[*LocalUser]bool
+	modeParameters map[byte]string
 
-	Metadata map[string] interface{}
+	Metadata map[string]interface{}
 
 	Modes
 }
 func NewChannel(name string) *Channel {
 	ch := new(Channel)
 	ch.Name = name
-	ch.Users = make(map[*User] bool)
-	ch.Prefixes = make(map[*User] PrefixLevel)
-	ch.Creation = time.Seconds()
+	ch.Users = make(map[*User]bool)
+	ch.Prefixes = make(map[*User]PrefixLevel)
+	ch.Creation = time.Now().Unix()
 
 	ch.Bans = make(MaskMap)
 	ch.Exceptions = make(MaskMap)
 	ch.Invexes = make(MaskMap)
 
-	ch.Invitees = make(map[*LocalUser] bool)
-	ch.modeParameters = make(map[byte] string)
+	ch.Invitees = make(map[*LocalUser]bool)
+	ch.modeParameters = make(map[byte]string)
 
-	ch.Metadata = make(map[string] interface{})
+	ch.Metadata = make(map[string]interface{})
 
 	return ch
 }
 func (ch *Channel) RemoveMask(mapping MaskMap, mask string) bool {
 	maskLow := IRCToLower(mask)
 	if _, ok := mapping[maskLow]; ok {
-		mapping[maskLow] = nil, false
+		delete(mapping, maskLow)
 		return true
 	}
 
 
 func (ch *Channel) AddPrefix(user *User, pfx PrefixLevel) bool {
 	if level, ok := ch.Prefixes[user]; ok {
-		if level & pfx != 0 {
+		if level&pfx != 0 {
 			return false
 		}
 		ch.Prefixes[user] = level | pfx
 
 func (ch *Channel) RemovePrefix(user *User, pfx PrefixLevel) bool {
 	if level, ok := ch.Prefixes[user]; ok {
-		if level & pfx != 0 {
+		if level&pfx != 0 {
 			level ^= pfx
 			if level == 0 {
-				ch.Prefixes[user] = 0, false
+				delete(ch.Prefixes, user)
 			} else {
 				ch.Prefixes[user] = level
 			}
 	for mask := range mapping {
 		if maskExt, mask := ParseExtBan(mask); ext == maskExt {
 			if PatternMatch(mask, host) || PatternMatch(mask, hostMask) ||
-					(!hostIsIP &&
-						(PatternMatch(mask, ip) || PatternMatch(mask, ipMask))) ||
-					(virt != "" && PatternMatch(mask, virt)){
+				(!hostIsIP &&
+					(PatternMatch(mask, ip) || PatternMatch(mask, ipMask))) ||
+				(virt != "" && PatternMatch(mask, virt)) {
 				return true
 			}
 		}
 }
 
 func (ch *Channel) RemoveModeParameter(mode byte) {
-	ch.modeParameters[mode] = "", false
+	delete(ch.modeParameters, mode)
 }
 
 func (ch *Channel) IsBanned(user *User) bool {
 }
 
 func (ch *Channel) UserUninvite(user *LocalUser) {
-	ch.Invitees[user] = false, false
-	user.Invites[ch] = false, false
+	delete(ch.Invitees, user)
+	delete(user.Invites, ch)
 }
 
 func (ch *Channel) UserJoin(user *User) {
 }
 
 func (ch *Channel) RemoveUser(user *User) {
-	ch.Prefixes[user] = 0, false
-	ch.Users[user] = false, false
+	delete(ch.Prefixes, user)
+	delete(ch.Users, user)
 	user.PartChannel(ch)
 }
 

commands/cmd_channels.go

 		serv.UserJoined(user, ch, targets)
 		continue
 
-		joinError:
+	joinError:
 		serv.SendError(user, err)
 	}
 
 			}
 		}
 
-		allowKick:
+	allowKick:
 
 		serv.SendChannel(user, ch, TargetLocal, "KICK %s %s :%s",
 			ch.Name, kickee.Nick, reason)
 		serv.SendChannel(user, ch, &TargetAnd{TargetRemote,
-				&TargetPropagate{user.Server}},
+			&TargetPropagate{user.Server}},
 			"KICK %s %s :%s", ch.Name, kickee.Id, reason)
 
 		ch.RemoveUser(kickee)
 		}
 		continue
 
-		kickError:
+	kickError:
 		serv.SendError(user, err)
 	}
 
 					goto modeError
 				}
 
-				switch (hdlr.Type()) {
-					case ModeBoolean:
-						if sign == ch.HasMode(mode) {
-							continue
-						}
-					case ModeStringSet:
-						if sign && param == "" {
-							continue
-						}
-					case ModeString, ModePrefix:
-						if param == "" {
-							continue
-						}
-					case ModeList:
-						if !sign && param == "" {
-							continue
-						}
+				switch hdlr.Type() {
+				case ModeBoolean:
+					if sign == ch.HasMode(mode) {
+						continue
+					}
+				case ModeStringSet:
+					if sign && param == "" {
+						continue
+					}
+				case ModeString, ModePrefix:
+					if param == "" {
+						continue
+					}
+				case ModeList:
+					if !sign && param == "" {
+						continue
+					}
 				}
 
-				switch (hdlr.CanSet()) {
-					case ModeOpers:
-						if !user.IsOper() {
-							err = NoPrivileges
-							goto modeError
-						}
-					case ModeULines:
-						if !(user.IsServer() && user.Server.IsULine()) {
-							err = NoPrivileges
-							goto modeError
-						}
+				switch hdlr.CanSet() {
+				case ModeOpers:
+					if !user.IsOper() {
+						err = NoPrivileges
+						goto modeError
+					}
+				case ModeULines:
+					if !(user.IsServer() && user.Server.IsULine()) {
+						err = NoPrivileges
+						goto modeError
+					}
 				}
 
 				chdlr = hdlr.(CModeHandler)
 
-				switch res, e := chdlr.HandlePre(serv, user, ch, sign, &param); (res) {
-					case Allow:
-						goto modeAllow
-					case Deny:
-						err = e
-						goto modeError
-					case PassThrough:
+				switch res, e := chdlr.HandlePre(serv, user, ch, sign, &param); res {
+				case Allow:
+					goto modeAllow
+				case Deny:
+					err = e
+					goto modeError
+				case PassThrough:
 				}
 
 				if !allow {
 					}
 				}
 
-				modeAllow:
+			modeAllow:
 
-				switch typ := hdlr.Type(); (typ) {
-					case ModeString, ModeStringSet:
+				switch typ := hdlr.Type(); typ {
+				case ModeString, ModeStringSet:
+					if sign {
+						ch.SetModeParameter(mode, param)
+					} else {
+						ch.RemoveModeParameter(mode)
+					}
+					fallthrough
+				case ModeBoolean:
+					if sign {
+						ch.SetMode(mode)
+					} else {
+						ch.RemoveMode(mode)
+					}
+				case ModePrefix:
+					pHandler := hdlr.(PrefixModeHandler)
+					pfxUser = serv.GetUser(param)
+
+					if pfxUser == nil {
+						err = NoSuchNickChannel.Set(ch.Name)
+						goto modeError
+					} else if !ch.HasUser(pfxUser) {
+						err = NotOnChannel.Set(pfxUser.Nick, ch.Name)
+						goto modeError
+					} else {
+						level := pHandler.Level()
 						if sign {
-							ch.SetModeParameter(mode, param)
+							if !ch.AddPrefix(pfxUser, level) {
+								continue
+							}
+							if user == pfxUser {
+								pfx |= level
+							}
 						} else {
-							ch.RemoveModeParameter(mode)
+							if !ch.RemovePrefix(pfxUser, level) {
+								continue
+							}
+							if user == pfxUser {
+								pfx &^= level
+							}
 						}
-						fallthrough
-					case ModeBoolean:
-						if sign {
-							ch.SetMode(mode)
-						} else {
-							ch.RemoveMode(mode)
-						}
-					case ModePrefix:
-						pHandler := hdlr.(PrefixModeHandler)
-						pfxUser = serv.GetUser(param)
 
-						if pfxUser == nil {
-							err = NoSuchNickChannel.Set(ch.Name)
-							goto modeError
-						} else if !ch.HasUser(pfxUser) {
-							err = NotOnChannel.Set(pfxUser.Nick, ch.Name)
-							goto modeError
-						} else {
-							level := pHandler.Level()
-							if sign {
-								if !ch.AddPrefix(pfxUser, level) {
-									continue
-								}
-								if user == pfxUser {
-									pfx |= level
-								}
-							} else {
-								if !ch.RemovePrefix(pfxUser, level) {
-									continue
-								}
-								if user == pfxUser {
-									pfx &^= level
-								}
-							}
-
-							param = pfxUser.Nick
-						}
+						param = pfxUser.Nick
+					}
 				}
 
 				chdlr.HandlePost(serv, user, ch, sign, param)
 
 				continue
 
-				modeError:
+			modeError:
 				if err != nil {
 					serv.SendError(user, err)
 				}
 						goto umodeAllow
 					}
 
-					switch (hdlr.CanSet()) {
-						case ModeOpers:
-							if !user.IsOper() {
-								err = NoPrivileges
-								goto umodeError
-							}
-						case ModeULines:
-							if !(user.IsServer() && user.Server.IsULine()) {
-								err = NoPrivileges
-								goto umodeError
-							}
+					switch hdlr.CanSet() {
+					case ModeOpers:
+						if !user.IsOper() {
+							err = NoPrivileges
+							goto umodeError
+						}
+					case ModeULines:
+						if !(user.IsServer() && user.Server.IsULine()) {
+							err = NoPrivileges
+							goto umodeError
+						}
 					}
 				}
 
-				umodeAllow:
+			umodeAllow:
 
 				if hdlr.Type() < ModeMany {
 					if sign {
 
 				continue
 
-				umodeError:
+			umodeError:
 				if err != nil {
 					serv.SendError(user, err)
 				}
 		}
 
 		serv.SendChannel(user, ch, t,
-			"%s %s :%s", typ, string(pfx.Prefix()) + ch.Name, message)
+			"%s %s :%s", typ, string(pfx.Prefix())+ch.Name, message)
 
 		for _, handler := range UserPostMessage {
 			handler.(UserPostMessageHandler).UserPostMessage(
 
 func doMessage(serv *Server, user *User, typ, targets, message string) ClientError {
 	if user.IsLocal() {
-		user.Local().IdleTime = time.Seconds()
+		user.Local().IdleTime = time.Now()
 		if message == "" {
 			return NoTextToSend
 		}
 
 		continue
 
-		partError:
+	partError:
 		serv.SendError(user, err)
 	}
 
 
 		for _, handler := range UserPreSetTopic {
 			res, err := handler.(UserPreSetTopicHandler).UserPreSetTopic(
-				serv, user, ch, topic);
+				serv, user, ch, topic)
 
 			if res == Allow {
 				break
 			}
 		}
 
-		now := time.Seconds()
+		now := time.Now().Unix()
 
 		serv.SetTopic(user, ch, now, topic)
 		serv.Broadcast(":%s STOPIC %s %d %s %d :%s", user.Id,

commands/cmd_opers.go

 
 import (
 	"fmt"
-	"os"
 	"strings"
 	"time"
 )
 }
 
 type nodeMapData struct {
-	Text string
-	NumUsers int
-	Connected int64
+	Text      string
+	NumUsers  int
+	Connected time.Time
 }
 
 func makeNodeMap(node *ServerNode, mapData []nodeMapData, offset, indent int,
-		flat, showId bool) int {
+	flat, showId bool) int {
 	var text string
 
 	if !flat {
 
 	for _, child := range node.Nodes {
 		if child != node.Return {
-			offset = makeNodeMap(child, mapData, offset, indent + 1, flat, showId)
+			offset = makeNodeMap(child, mapData, offset, indent+1, flat, showId)
 		}
 	}
 
 
 	totalUsers := len(serv.Users)
 	totalUsersf := float32(totalUsers)
-	now := time.Seconds()
+	now := time.Now()
 
 	for i := 0; i < end; i++ {
 		d := &mapData[i]
 		userShare := (float32(d.NumUsers) / totalUsersf) * 100
-		uptime := FormatDuration(now - d.Connected)
+		uptime := FormatDuration(now.Sub(d.Connected))
 		serv.SendNumeric(user, 6, "%-30s %5d [%05.2f] [Up: %s]",
 			d.Text, d.NumUsers, userShare, uptime)
 	}
 
 	serv.SendNumeric(user, 270,
 		"%d servers and %d users, average %.2f per server",
-		numServers, totalUsers, float32(totalUsers) / float32(numServers))
+		numServers, totalUsers, float32(totalUsers)/float32(numServers))
 
 	serv.SendNumeric(user, 7, "End of /MAP")
 	return nil
 			serv.SetUMode(user, true, 'o', "")
 		}
 
-		serv.GlobalNotice('o', "%s (%s@%s) is now an IRC operator of type %s " +
+		serv.GlobalNotice('o', "%s (%s@%s) is now an IRC operator of type %s "+
 			"using login %s", user.Nick, user.Ident, user.GetRealHost(),
 			typeName, name)
-		serv.SendNumeric(user, 381, "You are now a " + oper.Type.Name)
+		serv.SendNumeric(user, 381, "You are now a "+oper.Type.Name)
 	}
 
 	return nil
 		serv.GlobalNotice('s', "Stats '%c' requested by %s (%s@%s)",
 			statChar, user.Nick, user.Ident, user.GetRealHost())
 
-		switch (statChar) {
-			case 'e':
-				// TODO: E-lines
-				SendXLines(serv, user, serv.GetXLines('E'))
-			case 'k':
-				SendXLines(serv, user, serv.GetXLines('K'))
-			case 'c':
-				//serv.SendLinks(user)
-			case 'l':
-				//serv.SendClients(user, false)
-			case 'o':
-				// TODO: Show oper blocks
-			case 'p':
-				// TODO: Show listening addresses and ports
-			case 'u':
-				up := serv.GetUptime()
-				days := up / 86400
-				hours := (up - days) / 3600
-				minutes := (up - hours) / 60
-				seconds := up - minutes
-				serv.SendNumeric(user, 242, "Server up %d days, %02d:%02d:%02d",
-					days, hours, minutes, seconds)
-			case 'L':
-				//serv.SendClients(user, true)
-			case 'P':
-				//serv.SendOnlineOperators(user)
-			case 'T':
-				// TODO: Bandwidth statistics
-			case 'U':
-				// TODO: Show U-lined servers from config
-			case 'Y':
-				// TODO: Show connect classes
+		switch statChar {
+		case 'e':
+			// TODO: E-lines
+			SendXLines(serv, user, serv.GetXLines('E'))
+		case 'k':
+			SendXLines(serv, user, serv.GetXLines('K'))
+		case 'c':
+			//serv.SendLinks(user)
+		case 'l':
+			//serv.SendClients(user, false)
+		case 'o':
+			// TODO: Show oper blocks
+		case 'p':
+			// TODO: Show listening addresses and ports
+		case 'u':
+			up := serv.GetUptime()
+			days := up / 86400
+			hours := (up - days) / 3600
+			minutes := (up - hours) / 60
+			seconds := up - minutes
+			serv.SendNumeric(user, 242, "Server up %d days, %02d:%02d:%02d",
+				days, hours, minutes, seconds)
+		case 'L':
+			//serv.SendClients(user, true)
+		case 'P':
+			//serv.SendOnlineOperators(user)
+		case 'T':
+			// TODO: Bandwidth statistics
+		case 'U':
+			// TODO: Show U-lined servers from config
+		case 'Y':
+			// TODO: Show connect classes
 		}
 
 		for _, handler := range StatsRequest {
 }
 
 func doAddXLine(serv *Server, user *User, typ byte,
-		apply Applier, mask, duration, reason string) {
+	apply Applier, mask, duration, reason string) {
 	if dur := ParseDuration(duration); dur == -1 {
 		serv.SendServer(user, "NOTICE %s :*** Invalid %c-Line duration %s",
 			user.Nick, typ, duration)
 			user.Nick, typ, mask)
 	} else {
 		var matcher Matcher
-		var err os.Error
+		var err error
 
 		if u := serv.GetUser(mask); u != nil {
 			matcher, err = NewMatcherFromUser(typ, u)
 			return
 		}
 
-		xline := NewXLine(time.Seconds(), dur, typ,
+		xline := NewXLine(time.Now(), dur, typ,
 			user.Nick, reason, apply, matcher)
 
 		match := serv.XLineMatch(xline)
 
 		if int(match) > serv.MaxXLine {
-			serv.ServerNotice('a', "%s tried to set " +
+			serv.ServerNotice('a', "%s tried to set "+
 				"a %c-Line on %s, which covers %.2f%% of the network!",
 				user.Nick, typ, xline.Mask(), match)
 		} else {
 				serv.GlobalNotice('x', "%s added permanent %c-Line for %s: %s",
 					user.Nick, typ, xline.Mask(), xline.Reason)
 			} else {
-				expiry := time.SecondsToLocalTime(time.Seconds() + xline.Duration)
-				serv.GlobalNotice('x', "%s added timed %c-Line for %s, " +
-					"expires on %s: %s", user.Nick, typ, xline.Mask(),
+				expiry := time.Now().Add(xline.Duration)
+				serv.GlobalNotice('x',
+					"%s added timed %c-Line for %s, expires on %s: %s",
+					user.Nick, typ, xline.Mask(),
 					expiry.Format("Mon Jan _2 15:04:05 2006"), xline.Reason)
 			}
 

commands/cmd_server.go

 }
 
 func cmdTime(serv *Server, user *User, tokens Tokens) ClientError {
-	serv.SendServer(user, "391 %s %s :%s", user.Nick, serv.ServerName, time.LocalTime())
+	serv.SendServer(user, "391 %s %s :%s", user.Nick, serv.ServerName, time.Now())
 	return nil
 }
 

commands/cmd_users.go

 
 func cmdUser(serv *Server, user *User, tokens Tokens) ClientError {
 	if local := user.Local(); local != nil {
-		if local.registration & REG_IDENT != 0 {
+		if local.registration&REG_IDENT != 0 {
 			return AlreadyRegistered
 		} else {
 			ident := tokens[0]
 	var chName string
 	away := "H"
 
-	if flags & WHO_REALHOST == 0 {
+	if flags&WHO_REALHOST == 0 {
 		host = other.GetHost()
 	} else {
 		host = other.Host
 		return false
 	}
 
-	if flags & WHO_OPER != 0 {
+	if flags&WHO_OPER != 0 {
 		if !user.IsOper() {
 			return false
 		}
 	}
-	if flags & WHO_AWAY != 0 {
+	if flags&WHO_AWAY != 0 {
 		if !PatternMatch(pattern, other.Away) {
 			return false
 		}
 	}
-	if flags & WHO_IDENT != 0 {
+	if flags&WHO_IDENT != 0 {
 		if !PatternMatch(pattern, other.Ident) {
 			return false
 		}
 	}
-	if flags & WHO_PORT != 0 {
+	if flags&WHO_PORT != 0 {
 		port, _ := strconv.Atoi(pattern)
 
 		if local := other.Local(); local == nil {
 			return false
 		}
 	}
-	if flags & WHO_REALNAME != 0 {
+	if flags&WHO_REALNAME != 0 {
 		if !PatternMatch(pattern, other.RealName) {
 			return false
 		}
 	}
-	if flags & WHO_USERMODE != 0 {
+	if flags&WHO_USERMODE != 0 {
 		for i := 0; i < len(pattern); i++ {
 			c := byte(pattern[i])
 			if !(IsModeChar(c) && other.HasMode(c)) {
 			}
 		}
 	}
-	if flags & WHO_TIME != 0 {
-		var connTime int64
-		fmt.Sscanf(pattern, "%d", &connTime)
-		connTime = time.Seconds() - connTime
-		if other.Connected > connTime {
+	if flags&WHO_TIME != 0 {
+		connTime, err := strconv.ParseInt(pattern, 10, 64)
+		if err != nil {
+			return false
+		}
+		t := time.Now().Add(-time.Duration(connTime))
+		if other.Connected.After(t) {
 			return false
 		}
 	}
 	if flags & (WHO_AWAY | WHO_IDENT | WHO_PORT |
-			WHO_REALNAME | WHO_USERMODE | WHO_TIME) == 0 &&
+		WHO_REALNAME | WHO_USERMODE | WHO_TIME) == 0 &&
 		!(PatternMatch(pattern, other.Nick) ||
 			PatternMatch(pattern, other.GetHost()) ||
-			(user.IsOper() && (
-				PatternMatch(pattern, other.Host) ||
+			(user.IsOper() && (PatternMatch(pattern, other.Host) ||
 				PatternMatch(pattern, other.IPString)))) {
 		return false
 	}
 		pattern = tokens[0]
 		if len(tokens) > 1 {
 			for _, c := range tokens[1] {
-				switch (c) {
-					case 'o':
-						flags |= WHO_OPER
-					case 'a':
-						flags |= WHO_AWAY
-					case 'i':
-						flags |= WHO_IDENT
-					case 'p':
-						if isOper {
-							flags |= WHO_PORT
-						}
-					case 'r':
-						flags |= WHO_REALNAME
-					case 'm':
-						if isOper {
-							flags |= WHO_USERMODE
-						}
-					case 't':
-						flags |= WHO_TIME
-					case 'f':
-						flags |= WHO_REMOTE
-					case 'l':
-						flags |= WHO_LOCAL
-					case 'h':
-						if isOper {
-							flags |= WHO_REALHOST
-						}
-					case 'u':
-						if isOper {
-							flags |= WHO_UNLIMIT
-						}
+				switch c {
+				case 'o':
+					flags |= WHO_OPER
+				case 'a':
+					flags |= WHO_AWAY
+				case 'i':
+					flags |= WHO_IDENT
+				case 'p':
+					if isOper {
+						flags |= WHO_PORT
+					}
+				case 'r':
+					flags |= WHO_REALNAME
+				case 'm':
+					if isOper {
+						flags |= WHO_USERMODE
+					}
+				case 't':
+					flags |= WHO_TIME
+				case 'f':
+					flags |= WHO_REMOTE
+				case 'l':
+					flags |= WHO_LOCAL
+				case 'h':
+					if isOper {
+						flags |= WHO_REALHOST
+					}
+				case 'u':
+					if isOper {
+						flags |= WHO_UNLIMIT
+					}
 				}
 			}
 		}
 	}
 
-	if flags & (WHO_REMOTE | WHO_LOCAL) == 0 {
+	if flags&(WHO_REMOTE|WHO_LOCAL) == 0 {
 		flags |= WHO_REMOTE | WHO_LOCAL
 	}
 
 	// Special case a simple nick lookup
-	if !IsPattern(pattern) && flags & (WHO_AWAY | WHO_IDENT |
-			WHO_PORT | WHO_REALNAME | WHO_USERMODE | WHO_TIME) == 0 {
+	if !IsPattern(pattern) && flags&(WHO_AWAY|WHO_IDENT|
+		WHO_PORT|WHO_REALNAME|WHO_USERMODE|WHO_TIME) == 0 {
 		if pattern[0] == '#' {
 			ch := serv.GetChannel(pattern)
 
 		goto endWho
 	}
 
-	if flags & WHO_UNLIMIT != 0 {
+	if flags&WHO_UNLIMIT != 0 {
 		limit = len(serv.UserNicks)
 	}
 
 		}
 	}
 
-	endWho:
+endWho:
 
 	serv.SendServer(user, "315 %s %s :End of /WHO list", user.Nick, pattern)
 
 
 		for ch := range u.Channels {
 			if !(ch.HasMode('p') || ch.HasMode('s')) ||
-					(user.IsOper() || ch.HasUser(user)) {
+				(user.IsOper() || ch.HasUser(user)) {
 				name := ch.Name
 
 				pfx := ch.GetHighestPrefix(u)
 
 		if local := u.Local(); local != nil {
 			serv.SendServer(user, "317 %s %s %d %d :seconds idle, signon time",
-				user.Nick, u.Nick, time.Seconds() - local.IdleTime, u.Connected)
+				user.Nick, u.Nick,
+				int64(time.Now().Sub(local.IdleTime).Seconds()),
+				u.Connected.Unix())
 		}
 	}
 
 	"io"
 	"os"
 	"path"
-	"scanner"
 	"strconv"
 	"strings"
+	"text/scanner"
 )
 
 type Value interface {
 }
 
 type Block struct {
-	Pos scanner.Position
-	blocks map[string] []*Block
-	value Value
+	Pos    scanner.Position
+	blocks map[string][]*Block
+	value  Value
 }
 
 func (b *Block) AddBlock(name string, block *Block) {
 	if b.blocks == nil {
-		b.blocks = make(map[string] []*Block)
+		b.blocks = make(map[string][]*Block)
 	}
 	if b.blocks[name] == nil {
 		b.blocks[name] = make([]*Block, 0)
 	b.AddBlock(name, newb)
 }
 
-func (b *Block) GetBlock(strs... string) *Block {
+func (b *Block) GetBlock(strs ...string) *Block {
 	block := b
 
 	for _, name := range strs {
 	return block
 }
 
-func (b *Block) GetBlocks(strs... string) []*Block {
+func (b *Block) GetBlocks(strs ...string) []*Block {
 	if len(strs) == 0 {
 		panic("Block.GetBlocks requires one or more strings")
 	}
 
 type Float struct {
 	Position scanner.Position
-	Value float64
+	Value    float64
 }
 
 func (f *Float) Pos() scanner.Position { return f.Position }
-func (f *Float) String() string { return fmt.Sprint(f.Value) }
+func (f *Float) String() string        { return fmt.Sprint(f.Value) }
 
 type Int struct {
 	Position scanner.Position
-	Value int
+	Value    int
 }
 
 func (i *Int) Pos() scanner.Position { return i.Position }
-func (i *Int) String() string { return fmt.Sprint(i.Value) }
+func (i *Int) String() string        { return fmt.Sprint(i.Value) }
 
 type String struct {
 	Position scanner.Position
-	Value string
+	Value    string
 }
 
 func (s *String) Pos() scanner.Position { return s.Position }
-func (s *String) String() string { return s.Value }
+func (s *String) String() string        { return s.Value }
 
 type Bool struct {
 	Position scanner.Position
-	Value bool
+	Value    bool
 }
 
 func (b *Bool) Pos() scanner.Position { return b.Position }
-func (b *Bool) String() string { return fmt.Sprint(b.Value) }
+func (b *Bool) String() string        { return fmt.Sprint(b.Value) }
 
 type ParseError struct {
-	Pos scanner.Position
+	Pos     scanner.Position
 	Message string
 }
 
-func (e *ParseError) String() string {
+func (e *ParseError) Error() string {
 	return e.Message + " at " + e.Pos.String()
 }
 
-func parseChar(s string) int {
-	c, _, _, _ := strconv.UnquoteChar(s[1:len(s) - 1], '\'')
-	return c
-}
-
 func parseString(s string) string {
 	res, _ := strconv.Unquote(s)
 	return res
 }
 
 func parseFloat(s string) float64 {
-	f, _ := strconv.Atof64(s)
+	f, _ := strconv.ParseFloat(s, 64)
 	return f
 }
 
 	if s.Size() < 2 {
 		return false
 	}
-	s.items = s.items[:len(s.items) - 1]
+	s.items = s.items[:len(s.items)-1]
 	return true
 }
 
 	if s.items == nil {
 		return nil
 	}
-	return s.items[len(s.items) - 1]
+	return s.items[len(s.items)-1]
 }
 
 type Config struct {
 }
 
 type TypeError struct {
-	Pos scanner.Position
+	Pos     scanner.Position
 	Message string
 }
 
-func (e *KeyError) String() string {
+func (e *KeyError) Error() string {
 	return "Missing config value " + e.Key + " at " + e.Pos.String()
 }
-func (e *TypeError) String() string {
+func (e *TypeError) Error() string {
 	return e.Message + " at " + e.Pos.String()
 }
 
-func (block *Block) GetValue(strs... string) Value {
+func (block *Block) GetValue(strs ...string) Value {
 	b := block.GetBlock(strs...)
 
 	if b != nil {
 	return nil
 }
 
-func (block *Block) GetInt(strs... string) (int, os.Error) {
+func (block *Block) GetInt(strs ...string) (int, error) {
 	value := block.GetValue(strs...)
 
 	if value == nil {
 	return i.Value, nil
 }
 
-func (block *Block) GetFloat(strs... string) (float64, os.Error) {
+func (block *Block) GetFloat(strs ...string) (float64, error) {
 	value := block.GetValue(strs...)
 
 	if value == nil {
 	return f.Value, nil
 }
 
-func (block *Block) GetString(strs... string) (string, os.Error) {
+func (block *Block) GetString(strs ...string) (string, error) {
 	value := block.GetValue(strs...)
 
 	if value == nil {
 	return str.Value, nil
 }
 
-func (block *Block) GetBool(strs... string) (bool, os.Error) {
+func (block *Block) GetBool(strs ...string) (bool, error) {
 	value := block.GetValue(strs...)
 
 	if value == nil {
 	return b.Value, nil
 }
 
-func (block *Block) GetValueDefault(df Value, strs... string) Value {
+func (block *Block) GetValueDefault(df Value, strs ...string) Value {
 	v := block.GetValue(strs...)
 	if v == nil {
 		return df
 	return v
 }
 
-func (block *Block) GetIntDefault(df int, strs... string) int {
+func (block *Block) GetIntDefault(df int, strs ...string) int {
 	v, err := block.GetInt(strs...)
 	if err != nil {
 		return df
 	return v
 }
 
-func (block *Block) GetFloatDefault(df float64, strs... string) float64 {
+func (block *Block) GetFloatDefault(df float64, strs ...string) float64 {
 	v, err := block.GetFloat(strs...)
 	if err != nil {
 		return df
 	return v
 }
 
-func (block *Block) GetStringDefault(df string, strs... string) string {
+func (block *Block) GetStringDefault(df string, strs ...string) string {
 	v, err := block.GetString(strs...)
 	if err != nil {
 		return df
 	return v
 }
 
-func (block *Block) GetBoolDefault(df bool, strs... string) bool {
+func (block *Block) GetBoolDefault(df bool, strs ...string) bool {
 	v, err := block.GetBool(strs...)
 	if err != nil {
 		return df
 	return v
 }
 
-func (cfg *Config) Parse(name string) os.Error {
+func (cfg *Config) Parse(name string) error {
 	dir, base := path.Split(name)
 	root := &Block{Pos: scanner.Position{Filename: base}}
 
 	return p
 }
 
-func parseFile(root *Block, dir, name string, r io.Reader, recur int) os.Error {
+func parseFile(root *Block, dir, name string, r io.Reader, recur int) error {
 	s := new(scanner.Scanner)
 
 	s.Init(r)
 
 	s.Mode = scanner.GoTokens
-	s.Whitespace = (1 << '\t' | 1 << '\r' | 1 << ' ')
+	s.Whitespace = (1<<'\t' | 1<<'\r' | 1<<' ')
 
 	var blocks BlockStack
 	blocks.Push(root)
 	var curIdent string
 	var curParam Value
 
-	forLoop:
+forLoop:
 	for {
 		t := s.Scan()
 
 		switch expecting {
-			case ExIdent:
+		case ExIdent:
+			expecting = ExIdent
+			switch t {
+			case scanner.EOF:
+				break forLoop
+			case scanner.Ident:
+				curIdent = s.TokenText()
+				expecting = ExParam
+			case '\n': // Nothing
+			case '}':
+				if ok := blocks.Pop(); !ok {
+					return &ParseError{withFile(s.Pos(), name), "Closing brace outside a block"}
+				}
+			default:
+				return &ParseError{withFile(s.Pos(), name), "Unexpected " + scanner.TokenString(t)}
+			}
+		case ExParam:
+			expecting = ExPunctuation
+			switch t {
+			case scanner.Ident:
+				ident := s.TokenText()
+				if ident == "true" {
+					curParam = &Bool{withFile(s.Pos(), name), true}
+				} else if ident == "false" {
+					curParam = &Bool{withFile(s.Pos(), name), false}
+				} else {
+					return &ParseError{withFile(s.Pos(), name), "Unexpected identifier"}
+				}
+			case scanner.String, scanner.RawString:
+				curParam = &String{withFile(s.Pos(), name), parseString(s.TokenText())}
+			case scanner.Int:
+				curParam = &Int{withFile(s.Pos(), name), parseInt(s.TokenText())}
+			case scanner.Float:
+				curParam = &Float{withFile(s.Pos(), name), parseFloat(s.TokenText())}
+			case '{':
+				b := &Block{Pos: withFile(s.Pos(), name)}
+				blocks.Top().AddBlock(curIdent, b)
+				blocks.Push(b)
 				expecting = ExIdent
-				switch t {
-					case scanner.EOF:
-						break forLoop
-					case scanner.Ident:
-						curIdent = s.TokenText()
-						expecting = ExParam
-					case '\n': // Nothing
-					case '}':
-						if ok := blocks.Pop(); !ok {
-							return &ParseError{withFile(s.Pos(), name), "Closing brace outside a block"}
-						}
-					default:
-						return &ParseError{withFile(s.Pos(), name), "Unexpected " + scanner.TokenString(t)}
+			default:
+				return &ParseError{withFile(s.Pos(), name), "Unexpected " + scanner.TokenString(t)}
+			}
+		case ExPunctuation:
+			expecting = ExIdent
+			switch t {
+			case '\n', ';', '}':
+				if curIdent == "Include" {
+					if recur >= 10 {
+						return &ParseError{withFile(s.Pos(), name), "reached max Include depth"}
+					}
+
+					value, ok := curParam.(*String)
+					if !ok {
+						return &ParseError{withFile(s.Pos(), name), "Include with non-string filename"}
+					}
+
+					fname := value.Value
+
+					var file io.Reader
+					var err error
+
+					if path.IsAbs(fname) {
+						file, err = os.Open(fname)
+					} else {
+						file, err = os.Open(path.Join(dir, fname))
+					}
+
+					if err != nil {
+						return &ParseError{withFile(s.Pos(), name), fname + ": " + err.Error()}
+					}
+
+					if err := parseFile(blocks.Top(), dir, fname, file, recur+1); err != nil {
+						return err
+					}
+				} else {
+					blocks.Top().AddValue(curIdent, withFile(s.Pos(), name), curParam)
 				}
-			case ExParam:
-				expecting = ExPunctuation
-				switch t {
-					case scanner.Ident:
-						ident := s.TokenText()
-						if ident == "true" {
-							curParam = &Bool{withFile(s.Pos(), name), true}
-						} else if ident == "false" {
-							curParam = &Bool{withFile(s.Pos(), name), false}
-						} else {
-							return &ParseError{withFile(s.Pos(), name), "Unexpected identifier"}
-						}
-					case scanner.String, scanner.RawString:
-						curParam = &String{withFile(s.Pos(), name), parseString(s.TokenText())}
-					case scanner.Char:
-						curParam = &Int{withFile(s.Pos(), name), parseChar(s.TokenText())}
-					case scanner.Int:
-						curParam = &Int{withFile(s.Pos(), name), parseInt(s.TokenText())}
-					case scanner.Float:
-						curParam = &Float{withFile(s.Pos(), name), parseFloat(s.TokenText())}
-					case '{':
-						b := &Block{Pos: withFile(s.Pos(), name)}
-						blocks.Top().AddBlock(curIdent, b)
-						blocks.Push(b)
-						expecting = ExIdent
-					default:
-						return &ParseError{withFile(s.Pos(), name), "Unexpected " + scanner.TokenString(t)}
+
+				if t == '}' {
+					if ok := blocks.Pop(); !ok {
+						return &ParseError{withFile(s.Pos(), name), "Closing brace outside a block"}
+					}
 				}
-			case ExPunctuation:
-				expecting = ExIdent
-				switch t {
-					case '\n', ';', '}':
-						if curIdent == "Include" {
-							if recur >= 10 {
-								return &ParseError{withFile(s.Pos(), name), "reached max Include depth"}
-							}
-
-							value, ok := curParam.(*String)
-							if !ok {
-								return &ParseError{withFile(s.Pos(), name), "Include with non-string filename"}
-							}
-
-							fname := value.Value
-
-							var file io.Reader
-							var err os.Error
-
-							if path.IsAbs(fname) {
-								file, err = os.Open(fname)
-							} else {
-								file, err = os.Open(path.Join(dir, fname))
-							}
-
-							if err != nil {
-								return &ParseError{withFile(s.Pos(), name), fname + ": " + err.String()}
-							}
-
-							if err := parseFile(blocks.Top(), dir, fname, file, recur + 1); err != nil {
-								return err
-							}
-						} else {
-							blocks.Top().AddValue(curIdent, withFile(s.Pos(), name), curParam)
-						}
-
-						if t == '}' {
-							if ok := blocks.Pop(); !ok {
-								return &ParseError{withFile(s.Pos(), name), "Closing brace outside a block"}
-							}
-						}
-					case '{':
-						if curIdent == "Include" {
-							return &ParseError{withFile(s.Pos(), name), "Include opening a block"}
-						}
-						b := &Block{Pos: withFile(s.Pos(), name), value: curParam}
-						blocks.Top().AddBlock(curIdent, b)
-						blocks.Push(b)
-					default:
-						return &ParseError{withFile(s.Pos(), name), "Unexpected " + scanner.TokenString(t)}
+			case '{':
+				if curIdent == "Include" {
+					return &ParseError{withFile(s.Pos(), name), "Include opening a block"}
 				}
-				curIdent = ""
-				curParam = nil
+				b := &Block{Pos: withFile(s.Pos(), name), value: curParam}
+				blocks.Top().AddBlock(curIdent, b)
+				blocks.Push(b)
+			default:
+				return &ParseError{withFile(s.Pos(), name), "Unexpected " + scanner.TokenString(t)}
+			}
+			curIdent = ""
+			curParam = nil
 		}
 	}
 
 package main
 
-import (
-	"os"
-)
+import "errors"
 
 type Connect struct {
 	AllowMask string
-	DenyMask string
+	DenyMask  string
 
 	MaxGlobal int
-	MaxLocal int
+	MaxLocal  int
 
-	PingFreq int64
+	PingFreq            int64
 	RegistrationTimeout int64
-	SendQ int
-	RecvQ int
+	SendQ               int
+	RecvQ               int
 
-	FakeLag bool
+	FakeLag   bool
 	Threshold int
 
 	// For modules to access extra values
 			(matchHost && PatternMatch(c.DenyMask, user.Host)))
 }
 
-func LoadConnectBlocks(config *Config) ([]*Connect, os.Error) {
+func LoadConnectBlocks(config *Config) ([]*Connect, error) {
 	connects := make([]*Connect, 0)
 
 	for _, c := range config.GetBlocks("Connect") {
 
 		conn.DenyMask = c.GetStringDefault("", "Deny")
 		conn.MaxGlobal, err = c.GetInt("MaxGlobal")
-		if err != nil { return nil, err }
+		if err != nil {
+			return nil, err
+		}
 		conn.MaxLocal, err = c.GetInt("MaxLocal")
-		if err != nil { return nil, err }
+		if err != nil {
+			return nil, err
+		}
 		pingFreq, err := c.GetInt("PingFreq")
-		if err != nil { return nil, err }
+		if err != nil {
+			return nil, err
+		}
 		conn.PingFreq = int64(pingFreq)
 		regTimeout, err := c.GetInt("RegistrationTimeout")
-		if err != nil { return nil, err }
+		if err != nil {
+			return nil, err
+		}
 		conn.RegistrationTimeout = int64(regTimeout)
 		conn.SendQ, err = c.GetInt("SendQ")
-		if err != nil { return nil, err }
+		if err != nil {
+			return nil, err
+		}
 		conn.RecvQ, err = c.GetInt("RecvQ")
-		if err != nil { return nil, err }
+		if err != nil {
+			return nil, err
+		}
 		conn.FakeLag, err = c.GetBool("FakeLag")
-		if err != nil { return nil, err }
+		if err != nil {
+			return nil, err
+		}
 		conn.Threshold, err = c.GetInt("Threshold")
-		if err != nil { return nil, err }
+		if err != nil {
+			return nil, err
+		}
 
 		connects = append(connects, conn)
 	}
 
 	if len(connects) == 0 {
-		return nil, os.NewError("No Connect blocks")
+		return nil, errors.New("No Connect blocks")
 	}
 
 	return connects, nil
 package main
 
-import (
-	"os"
-	"sort"
-)
+import "sort"
 
 type EventResult uint
 
 	Prioritize() int
 }
 
-type NormalPriority struct {}
-type LowPriority struct {}
-type HighPriority struct {}
+type NormalPriority struct{}
+type LowPriority struct{}
+type HighPriority struct{}
 
 func (*NormalPriority) Prioritize() int { return PRI_NORMAL }
-func (*LowPriority) Prioritize() int { return PRI_LOW }
-func (*HighPriority) Prioritize() int { return PRI_HIGH }
+func (*LowPriority) Prioritize() int    { return PRI_LOW }
+func (*HighPriority) Prioritize() int   { return PRI_HIGH }
 
 type TargetUsers interface {
 	TargetUser(*User) bool
 	return t.Source.Route != user.Server.Route
 }
 
-type ExceptUsers map[*User] bool
+type ExceptUsers map[*User]bool
 
 func (e ExceptUsers) TargetUser(user *User) bool {
 	return !e[user]
 
 type TargetPrefix struct {
 	Channel *Channel
-	Level PrefixLevel
+	Level   PrefixLevel
 }
 
 func (t *TargetPrefix) TargetUser(user *User) bool {
-	return t.Channel.GetPrefix(user) & t.Level != 0
+	return t.Channel.GetPrefix(user)&t.Level != 0
 }
 
 type TargetAnd struct {
 type ConfigureHandler interface {
 	EventHandler
 	// Called to load configuration directives
-	Configure(config *Config) os.Error
+	Configure(config *Config) error
 }
 
 type ChannelCreationHandler interface {
 		level *PrefixLevel, key string) (result EventResult, err ClientError)
 }
 
-type UserPreKickHandler interface{
+type UserPreKickHandler interface {
 	EventHandler
 	// Called before a User attempts to kick another User from a Channel
 	UserPreKick(user *User, ch *Channel, kickee *User, reason string) (EventResult, ClientError)
 
 // Convenience functions for compile-time safety
 
-func HandleChannelCreation(h ChannelCreationHandler) { ChannelCreation.AddHandler(h) }
-func HandleConfigure(h ConfigureHandler) { Configure.AddHandler(h) }
-func HandleNamesItem(h NamesItemHandler) { NamesItem.AddHandler(h) }
-func HandleNumeric005(h Numeric005Handler) { Numeric005.AddHandler(h) }
-func HandlePostModeChange(h PostModeChangeHandler) { PostModeChange.AddHandler(h) }
-func HandleReady(h ReadyHandler) { Ready.AddHandler(h) }
-func HandleServerLink(h ServerLinkHandler) { ServerLink.AddHandler(h) }
-func HandleServerSplit(h ServerSplitHandler) { ServerSplit.AddHandler(h) }
-func HandleStatsRequest(h StatsRequestHandler) { StatsRequest.AddHandler(h) }
-func HandleShutdown(h ShutdownHandler) { Shutdown.AddHandler(h) }
-func HandleUserKick(h UserKickHandler) { UserKick.AddHandler(h) }
-func HandleUserPart(h UserPartHandler) { UserPart.AddHandler(h) }
+func HandleChannelCreation(h ChannelCreationHandler)   { ChannelCreation.AddHandler(h) }
+func HandleConfigure(h ConfigureHandler)               { Configure.AddHandler(h) }
+func HandleNamesItem(h NamesItemHandler)               { NamesItem.AddHandler(h) }
+func HandleNumeric005(h Numeric005Handler)             { Numeric005.AddHandler(h) }
+func HandlePostModeChange(h PostModeChangeHandler)     { PostModeChange.AddHandler(h) }
+func HandleReady(h ReadyHandler)                       { Ready.AddHandler(h) }
+func HandleServerLink(h ServerLinkHandler)             { ServerLink.AddHandler(h) }
+func HandleServerSplit(h ServerSplitHandler)           { ServerSplit.AddHandler(h) }
+func HandleStatsRequest(h StatsRequestHandler)         { StatsRequest.AddHandler(h) }
+func HandleShutdown(h ShutdownHandler)                 { Shutdown.AddHandler(h) }
+func HandleUserKick(h UserKickHandler)                 { UserKick.AddHandler(h) }
+func HandleUserPart(h UserPartHandler)                 { UserPart.AddHandler(h) }
 func HandleUserPreBroadcast(h UserPreBroadcastHandler) { UserPreBroadcast.AddHandler(h) }
-func HandleUserPreCommand(h UserPreCommandHandler) { UserPreCommand.AddHandler(h) }
-func HandleUserPreJoin(h UserPreJoinHandler) { UserPreJoin.AddHandler(h) }
-func HandleUserPreKick(h UserPreKickHandler) { UserPreKick.AddHandler(h) }
-func HandleUserPreMessage(h UserPreMessageHandler) { UserPreMessage.AddHandler(h) }
-func HandleUserPreMode(h UserPreModeHandler) { UserPreMode.AddHandler(h) }
-func HandleUserPreNick(h UserPreNickHandler) { UserPreNick.AddHandler(h) }
-func HandleUserPreSetTopic(h UserPreSetTopicHandler) { UserPreSetTopic.AddHandler(h) }
-func HandleUserPreWhois(h UserPreWhoisHandler) { UserPreWhois.AddHandler(h) }
-func HandleUserPostJoin(h UserPostJoinHandler) { UserPostJoin.AddHandler(h) }
-func HandleUserPostMessage(h UserPostMessageHandler) { UserPostMessage.AddHandler(h) }
+func HandleUserPreCommand(h UserPreCommandHandler)     { UserPreCommand.AddHandler(h) }
+func HandleUserPreJoin(h UserPreJoinHandler)           { UserPreJoin.AddHandler(h) }
+func HandleUserPreKick(h UserPreKickHandler)           { UserPreKick.AddHandler(h) }
+func HandleUserPreMessage(h UserPreMessageHandler)     { UserPreMessage.AddHandler(h) }
+func HandleUserPreMode(h UserPreModeHandler)           { UserPreMode.AddHandler(h) }
+func HandleUserPreNick(h UserPreNickHandler)           { UserPreNick.AddHandler(h) }
+func HandleUserPreSetTopic(h UserPreSetTopicHandler)   { UserPreSetTopic.AddHandler(h) }
+func HandleUserPreWhois(h UserPreWhoisHandler)         { UserPreWhois.AddHandler(h) }
+func HandleUserPostJoin(h UserPostJoinHandler)         { UserPostJoin.AddHandler(h) }
+func HandleUserPostMessage(h UserPostMessageHandler)   { UserPostMessage.AddHandler(h) }
 func HandleUserPostRegister(h UserPostRegisterHandler) { UserPostRegister.AddHandler(h) }
-func HandleUserQuit(h UserQuitHandler) { UserQuit.AddHandler(h) }
+func HandleUserQuit(h UserQuitHandler)                 { UserQuit.AddHandler(h) }
 
 type FakeLag struct {
 	Threshold int
-	Input chan int
-	Output chan int
+	Input     chan int
+	Output    chan int
 }
 
 func NewFakeLag(threshold int) *FakeLag {
 
 const (
 	// Interval between messages when being throttled, in nanoseconds
-	FakeLagInterval int64 = 1000000000
+	FakeLagInterval time.Duration = 1000000000
 	// Decrement to lag value per FakeLagInterval of time passed
 	FakeLagDecrement int = 1
 )
 
 func (f *FakeLag) start() {
-	now := time.Nanoseconds()
+	now := time.Now().UnixNano()
 	lag := 0
 
 	for {
 			<-time.After(FakeLagInterval)
 		}
 
-		inputLoop:
+	inputLoop:
 		for {
 			select {
-				case value := <-f.Input:
-					if value <= 0 {
-						return
-					}
-					lag += value
-				default:
-					break inputLoop
+			case value := <-f.Input:
+				if value <= 0 {
+					return
+				}
+				lag += value
+			default:
+				break inputLoop
 			}
 		}
 
 		select {
-			case f.Output <- lag:
-			case <-time.After(FakeLagInterval):
+		case f.Output <- lag:
+		case <-time.After(FakeLagInterval):
 		}
 
-		t := time.Nanoseconds()
-		dec := FakeLagDecrement * int((t - now) / FakeLagInterval)
+		t := time.Now().UnixNano()
+		dec := FakeLagDecrement * int((t - now) / int64(FakeLagInterval))
 		lag -= dec
 
 		if lag < 0 {
 			lag = 0
 		}
 
-		now += int64(dec) * FakeLagInterval
+		now += int64(dec) * int64(FakeLagInterval)
 	}
 }
 	"bufio"
 	"bytes"
 	"crypto/tls"
+	"errors"
 	"fmt"
+	"io"
 	"net"
 	"os"
 	"os/signal"
 )
 
 type ServerMessage struct {
-	Node *ServerNode
+	Node   *ServerNode
 	Tokens Tokens
-	Line string
-	Error os.Error
+	Line   string
+	Error  error
 }
 
 type UserMessage struct {
-	User *User
+	User   *User
 	Tokens Tokens
-	Error os.Error
+	Error  error
 }
 
 type AdminData struct {
-	AdminName string
-	AdminNick string
+	AdminName  string
+	AdminNick  string
 	AdminEmail string
 }
 
 	return path.Join(base, name)
 }
 
-func (adm *AdminData) Configure(config *Block) os.Error {
+func (adm *AdminData) Configure(config *Block) error {
 	name, err := config.GetString("Name")
-	if err != nil { return err }
+	if err != nil {
+		return err
+	}
 	nick, err := config.GetString("Nick")
-	if err != nil { return err }
+	if err != nil {
+		return err
+	}
 	email, err := config.GetString("Email")
-	if err != nil { return err }
+	if err != nil {
+		return err
+	}
 
 	adm.AdminName = name
 	adm.AdminNick = nick
 }
 
 type Limits struct {
-	MaxNick int
-	MaxIdent int
+	MaxNick     int
+	MaxIdent    int
 	MaxRealName int
-	MaxVHost int
-
-	MaxAway int
-	MaxPartReason int
-	MaxQuitReason int
+	MaxVHost    int
+
+	MaxAway        int
+	MaxPartReason  int
+	MaxQuitReason  int
 	MaxChannelName int
 	MaxChannelList int
-	MaxTopic int
-	MaxKickReason int
-
-	MaxChannels int
+	MaxTopic       int
+	MaxKickReason  int
+
+	MaxChannels     int
 	MaxOperChannels int
 
 	MaxTargets int
-	MaxModes int
+	MaxModes   int
 
 	MaxXLine int
-	MaxWho int
+	MaxWho   int
 }
 
 func (lim *Limits) Configure(config *Block) {
 
 type Options struct {
 	DefaultModes string
-	HostInTopic bool
+	HostInTopic  bool
 
 	PartPrefix string
 	PartSuffix string
 		maskLen = net.IPv4len
 	}
 
-	if n > maskLen * 8 {
+	if n > maskLen*8 {
 		n = maskLen * 8
 	}
 
 		if n >= 8 {
 			res[i] = 0xff
 		} else {
-			res[i] = byte(0xff << uint(8 - n))
+			res[i] = byte(0xff << uint(8-n))
 			break
 		}
 
 }
 
 type Security struct {
-	FlatMap bool
+	FlatMap    bool
 	HideULines bool
 
-	DiePassword Password
+	DiePassword     Password
 	RestartPassword Password
 }
 
-func (sec *Security) Configure(config *Block) os.Error {
+func (sec *Security) Configure(config *Block) error {
 	sec.FlatMap = config.GetBoolDefault(true, "FlatMap")
 	sec.HideULines = config.GetBoolDefault(false, "HideULines")
 
 }
 
 type Server struct {
-	channels map[string] *Channel
-
-	UserNicks map[string] *User
-	LocalUsers map[UID] *User
-
-	MaxLocalUsers int
-	MaxGlobalUsers int
+	channels map[string]*Channel
+
+	UserNicks  map[string]*User
+	LocalUsers map[UID]*User
+
+	MaxLocalUsers     int
+	MaxGlobalUsers    int
 	UnregisteredCount int
 
 	nextUserId UID
 
 	Logger
 
-	StartTime int64
+	StartTime time.Time
 
 	MOTD []string
 
 
 	ServerTree
 
-	Operators map[*User] bool
-
-	LocalClones map[string] int
-
-	GlobalClones map[string] int
-
-	XLines map[byte] map[string] *XLine
-
-	OperTypes map[string] *OperType
-
-	OperBlocks map[string] *Oper
+	Operators map[*User]bool
+
+	LocalClones map[string]int
+
+	GlobalClones map[string]int
+
+	XLines map[byte]map[string]*XLine
+
+	OperTypes map[string]*OperType
+
+	OperBlocks map[string]*Oper
 
 	Connect []*Connect
 
-	Links map[string] *Link
-
-	ULines map[string] *ULine
+	Links map[string]*Link
+
+	ULines map[string]*ULine
 
 	config *Config
 
 	BaseDir string
 
-	ConfigDir string
+	ConfigDir  string
 	ConfigFile string
 
-	listeners map[string] *Listener
-
-	userMessages chan *UserMessage
+	listeners map[string]*Listener
+
+	userMessages   chan *UserMessage
 	serverMessages chan *ServerMessage
 
-	pendingClients chan *User
+	pendingClients  chan *User
 	pendingConnects chan *Link
-	pendingServers chan *ServerNode
+	pendingServers  chan *ServerNode
 
 	killswitch chan int
-	doRestart bool
+	doRestart  bool
 
 	routines chan int
 
 	routineCount int
 
-	channelModes string
+	channelModes      string
 	channelModesTypes string
-	prefixModes string
-	statusMsg string
-	extBans string
-	userModes string
+	prefixModes       string
+	statusMsg         string
+	extBans           string
+	userModes         string
 
 	ISupport []string
 }
 func NewServer(baseDir, configFile string) *Server {
 	serv := new(Server)
 
-	serv.channels = make(map[string] *Channel)
-	serv.UserNicks = make(map[string] *User)
-	serv.LocalUsers = make(map[UID] *User)
-	serv.StartTime = time.Seconds()
-	serv.listeners = make(map[string] *Listener)
+	serv.channels = make(map[string]*Channel)
+	serv.UserNicks = make(map[string]*User)
+	serv.LocalUsers = make(map[UID]*User)
+	serv.StartTime = time.Now()
+	serv.listeners = make(map[string]*Listener)
 	serv.userMessages = make(chan *UserMessage, 10240)
 	serv.serverMessages = make(chan *ServerMessage, 10240)
 	serv.pendingClients = make(chan *User, 64)
 	serv.routines = make(chan int, 4096)
 	serv.MOTD = make([]string, 0)
 	serv.Rules = make([]string, 0)
-	serv.Operators = make(map[*User] bool)
-	serv.LocalClones = make(map[string] int)
-	serv.GlobalClones = make(map[string] int)
-	serv.XLines = make(map[byte] map[string] *XLine)
+	serv.Operators = make(map[*User]bool)
+	serv.LocalClones = make(map[string]int)
+	serv.GlobalClones = make(map[string]int)
+	serv.XLines = make(map[byte]map[string]*XLine)
 	serv.nextUserId = 1
 	serv.Logger.Init()
 
 }
 
 func (self *Server) RemoveOperator(user *User) {
-	self.Operators[user] = false, false
+	delete(self.Operators, user)
 
 	// Remove Oper only modes
 	var i byte = 'A'
 	xlines, ok := self.XLines[typ]
 
 	if !ok {
-		xlines = make(map[string] *XLine)
+		xlines = make(map[string]*XLine)
 		self.XLines[typ] = xlines
 	}
 
 	}
 }
 
+// TestXLineExpire tests whether the given XLine is out of date and, if so,
+// expires it, returning whether the XLine was expired.
 func (self *Server) TestXLineExpire(x *XLine) bool {
-	now := time.Seconds()
-
-	if x.Duration != 0 && x.Creation + x.Duration < now {
+	now := time.Now()
+
+	if x.Duration != 0 && x.Creation.Add(x.Duration).Before(now) {
 		self.RemoveXLine(x.Type, x.Mask())
 		self.ServerNotice('x',
-			"Removing expired %c-Line %s (set by %s %d seconds ago)",
-			x.Type, x.Mask(), x.Setter, now - x.Creation)
+			"Removing expired %c-Line %s (set by %s %d ago)",
+			x.Type, x.Mask(), x.Setter, now.Sub(x.Creation))
 		return true
 	}
 
 }
 
 func (self *Server) MatchesXLine(typ byte, user *User) *XLine {
-	now := time.Seconds()
 	xlines := self.XLines[typ]
-	for mask, x := range xlines {
-		if x.Duration != 0 && x.Creation + x.Duration < now {
-			xlines[mask] = nil, false
-			self.ServerNotice('x', "Removing expired %c-Line %s " +
-				"(set by %s %d seconds ago)", x.Type, x.Mask(),
-				x.Setter, now - x.Creation)
-		} else if x.MatchesUser(user) {
+	for _, x := range xlines {
+		if !self.TestXLineExpire(x) && x.MatchesUser(user) {
 			return x
 		}
 	}
 		mask = IRCToLower(mask)
 
 		if _, ok := xlines[mask]; ok {
-			xlines[mask] = nil, false
+			delete(xlines, mask)
 			return true
 		}
 	}
 }
 
 func (self *Server) RoutineCount() int {
-	pollLoop:
+pollLoop:
 	for {
 		select {
-			case count := <-self.routines:
-				self.routineCount += count
-			default:
-				break pollLoop
+		case count := <-self.routines:
+			self.routineCount += count
+		default:
+			break pollLoop
 		}
 	}
 
 }
 
 // Send a message to a User
-func (self *Server) SendLine(user *User, format string, args... interface{}) {
+func (self *Server) SendLine(user *User, format string, args ...interface{}) {
 	if local := user.Local(); local != nil {
 		line := fmt.Sprintf(format, args...)
 		if err := local.QueueOutgoing(line); err != nil {
 }
 
 // Send a message to a User, sourced by another User
-func (self *Server) Send(source *User, target *User, format string, args... interface{}) {
+func (self *Server) Send(source *User, target *User, format string, args ...interface{}) {
 	var src string
 	if source == nil {
 		src = target.Server.Name
 }
 
 // Send a message to a User with the server as source
-func (self *Server) SendServer(user *User, format string, args... interface{}) {
+func (self *Server) SendServer(user *User, format string, args ...interface{}) {
 	self.Send(nil, user, format, args...)
 }
 
 // Send a message to all local Users
-func (self *Server) SendAll(source *User, format string, args... interface{}) {
+func (self *Server) SendAll(source *User, format string, args ...interface{}) {
 	for _, user := range self.LocalUsers {
 		self.Send(source, user, format, args...)
 	}
 }
 
 func (self *Server) SendChannel(source *User, ch *Channel, targets TargetUsers,
-		format string, args... interface{}) {
+	format string, args ...interface{}) {
 	var send RemoteSend
 
 	if source == nil {
 	send.Send(self, ":%s %s", source.Id, fmt.Sprintf(format, args...))
 }
 
-func (self *Server) SendNumeric(user *User, num uint, format string, args... interface{}) {
+func (self *Server) SendNumeric(user *User, num uint, format string, args ...interface{}) {
 	self.SendServer(user, "%03d %s :%s", num, user.Nick,
 		fmt.Sprintf(format, args...))
 }
 
-func (self *Server) GlobalNotice(mode byte, format string, args... interface{}) {
+func (self *Server) GlobalNotice(mode byte, format string, args ...interface{}) {
 	self.ServerNotice(mode, format, args...)
 	self.Broadcast(":%s SNOTE %c :%s",
-		self.Id, byte(IRCRuneToUpper(int(mode))), fmt.Sprintf(format, args...))
+		self.Id, byte(IRCRuneToUpper(rune(mode))), fmt.Sprintf(format, args...))
 }
 
-func (self *Server) ServerNotice(mode byte, format string, args... interface{}) {
-	modeLower := byte(IRCRuneToLower(int(mode)))
+func (self *Server) ServerNotice(mode byte, format string, args ...interface{}) {
+	modeLower := byte(IRCRuneToLower(rune(mode)))
 	if name, ok := snoNames[modeLower]; ok {
 		for u := range self.Operators {
 			if u.ServerNotices.HasMode(mode) {
 	}
 
 	self.SendNumeric(user, 251, "There are %d users and %d invisible on %d servers",
-		len(self.UserNicks) - invisible, invisible, len(self.Servers))
+		len(self.UserNicks)-invisible, invisible, len(self.Servers))
 
 	opers := len(self.Operators)
 	if opers != 0 {
 	if len(users) != 0 {
 		names := make([]string, 0, len(users))
 
-		namesLoop:
+	namesLoop:
 		for _, u := range users {
 			name := ch.FormatNick(u)
 
 	support = append(support,
 		fmt.Sprint("AWAYLEN=", self.MaxAway),
 		"CASEMAPPING=rfc1459",
-		"CHANMODES=" + self.channelModesTypes,
+		"CHANMODES="+self.channelModesTypes,
 		"CHANTYPES=#",
 		"CHARSET=ascii",
 		"ELIST=M",
 		"EXCEPTS=e",
-		"EXTBAN=," + self.extBans,
+		"EXTBAN=,"+self.extBans,