135 lines
3.2 KiB
Go
135 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// ValidateConfig performs comprehensive validation of the server configuration
|
|
func (c *Config) Validate() error {
|
|
// Validate server settings
|
|
if c.Server.Name == "" {
|
|
return fmt.Errorf("server name cannot be empty")
|
|
}
|
|
|
|
if c.Server.Network == "" {
|
|
return fmt.Errorf("network name cannot be empty")
|
|
}
|
|
|
|
if c.Server.Listen.Host == "" {
|
|
c.Server.Listen.Host = "localhost" // Default fallback
|
|
}
|
|
|
|
if c.Server.Listen.Port <= 0 || c.Server.Listen.Port > 65535 {
|
|
return fmt.Errorf("invalid port number: %d", c.Server.Listen.Port)
|
|
}
|
|
|
|
if c.Server.Listen.EnableSSL && (c.Server.Listen.SSLPort <= 0 || c.Server.Listen.SSLPort > 65535) {
|
|
return fmt.Errorf("invalid SSL port number: %d", c.Server.Listen.SSLPort)
|
|
}
|
|
|
|
// Validate limits
|
|
if c.Limits.MaxClients <= 0 {
|
|
c.Limits.MaxClients = 1000 // Default
|
|
}
|
|
|
|
if c.Limits.MaxChannels <= 0 {
|
|
c.Limits.MaxChannels = 100 // Default
|
|
}
|
|
|
|
if c.Limits.MaxNickLength <= 0 || c.Limits.MaxNickLength > 50 {
|
|
c.Limits.MaxNickLength = 30 // Default
|
|
}
|
|
|
|
if c.Limits.PingTimeout <= 0 {
|
|
c.Limits.PingTimeout = 300 // Default 5 minutes
|
|
}
|
|
|
|
if c.Limits.FloodLines <= 0 {
|
|
c.Limits.FloodLines = 10 // Default
|
|
}
|
|
|
|
if c.Limits.FloodSeconds <= 0 {
|
|
c.Limits.FloodSeconds = 60 // Default
|
|
}
|
|
|
|
// Validate channels
|
|
for _, channelName := range c.Channels.AutoJoin {
|
|
if !isChannelName(channelName) {
|
|
return fmt.Errorf("invalid channel name in auto_join: %s", channelName)
|
|
}
|
|
}
|
|
|
|
// Validate default modes
|
|
validChannelModes := "mntisp"
|
|
for _, mode := range c.Channels.DefaultModes {
|
|
if mode != '+' && !strings.ContainsRune(validChannelModes, mode) {
|
|
return fmt.Errorf("invalid default channel mode: %c", mode)
|
|
}
|
|
}
|
|
|
|
// Validate founder mode
|
|
validFounderModes := []string{"q", "a", "o", "h", "v"}
|
|
foundValidMode := false
|
|
for _, validMode := range validFounderModes {
|
|
if c.Channels.FounderMode == validMode {
|
|
foundValidMode = true
|
|
break
|
|
}
|
|
}
|
|
if !foundValidMode {
|
|
return fmt.Errorf("invalid founder_mode '%s', must be one of: q (owner), a (admin), o (operator), h (halfop), v (voice)", c.Channels.FounderMode)
|
|
}
|
|
|
|
// Validate operators
|
|
for i, oper := range c.Opers {
|
|
if oper.Name == "" {
|
|
return fmt.Errorf("operator %d: name cannot be empty", i)
|
|
}
|
|
if oper.Password == "" {
|
|
return fmt.Errorf("operator %s: password cannot be empty", oper.Name)
|
|
}
|
|
if oper.Host == "" {
|
|
return fmt.Errorf("operator %s: host cannot be empty", oper.Name)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SanitizeConfig applies safe defaults and sanitizes configuration values
|
|
func (c *Config) SanitizeConfig() {
|
|
// Ensure reasonable limits
|
|
if c.Limits.MaxClients > 10000 {
|
|
c.Limits.MaxClients = 10000
|
|
}
|
|
|
|
if c.Limits.MaxChannels > 1000 {
|
|
c.Limits.MaxChannels = 1000
|
|
}
|
|
|
|
// Set default founder mode if empty or invalid
|
|
if c.Channels.FounderMode == "" {
|
|
c.Channels.FounderMode = "o" // Default to operator
|
|
}
|
|
|
|
// Ensure reasonable string lengths
|
|
if c.Limits.MaxTopicLength > 2048 {
|
|
c.Limits.MaxTopicLength = 2048
|
|
}
|
|
|
|
if c.Limits.MaxKickLength > 2048 {
|
|
c.Limits.MaxKickLength = 2048
|
|
}
|
|
|
|
// Ensure MOTD isn't too long
|
|
if len(c.MOTD) > 50 {
|
|
c.MOTD = c.MOTD[:50]
|
|
}
|
|
|
|
// Sanitize channel modes
|
|
if c.Channels.DefaultModes == "" {
|
|
c.Channels.DefaultModes = "+nt"
|
|
}
|
|
}
|