diff --git a/server.go b/server.go index 5ffe018..b10b1ad 100644 --- a/server.go +++ b/server.go @@ -22,7 +22,7 @@ const ( ) var myinfo string = "%s %s/%s * *" -var isupport string = "CASEMAPPING=rfc1459 CHANTYPES=# NICKLEN=32 PREFIX=(aohv)&@%%+" +var isupport string = "CASEMAPPING=rfc1459 CHANTYPES=# NICKLEN=32 PREFIX=(ohv)@%%+" type Server struct { queue chan *irc.Message @@ -338,6 +338,15 @@ func (sv *Server) channelCheckMode(chid, mode string) bool { return true } +func (sv *Server) channelCheckPerm(chid, clid, modes string) bool { + for _, m := range modes { + if sv.channelCheckMode(chid, string(m)+" "+clid) { + return true + } + } + return false +} + type commandHook struct { HookFn func(sv *Server, msg *irc.Message) MinArgs int @@ -352,10 +361,12 @@ var svCommandHooks = map[string]commandHook{ "QUIT": {handleCmdQuit, 0, false, ""}, "MODE": {handleCmdMode, 1, false, ""}, "TOPIC": {handleCmdTopic, 1, false, ""}, + "KICK": {handleCmdKick, 2, false, ""}, "NAMES": {handleCmdNames, 1, false, ""}, "WHOIS": {handleCmdWhois, 0, false, ""}, "PING": {handleCmdPing, 1, false, ""}, "REHASH": {handleCmdRehash, 0, false, "ao"}, + "KILL": {handleCmdKill, 0, false, "ao"}, /* "LIST": {handleCmdList, 0, false, false}, "VERSION": {handleCmdVersion, 0, false, false}, @@ -366,7 +377,6 @@ var svCommandHooks = map[string]commandHook{ "INFO": {handleCmdInfo, 0, false, false}, "WHO": {handleCmdWho, 0, false, false}, "WHOWAS": {handleCmdWhowas, 0, false, false}, - "KILL": {handleCmdKill, 0, false, false}, "PONG": {handleCmdPong, 0, false, false}, "ERROR": {handleCmdError, 0, false, false}, "AWAY": {handleCmdAway, 0, false, false}, @@ -383,7 +393,12 @@ func handleCmdPrivmsg(sv *Server, msg *irc.Message) { clid := strings.ToLower(msg.Pre) chid := strings.ToLower(msg.Args[0]) if sv.channelCheckMode(chid, "m") && - !sv.channelCheckMode(chid, "v "+clid) { + !sv.channelCheckPerm(chid, clid, "ohv") { + sv.sendReply(clid, ERR_CANNOTSENDTOCHAN, chid, "Cannot send to channel") + return + } + if _, exists := sv.chUsers[clid]; !exists { + sv.sendReply(clid, ERR_CANNOTSENDTOCHAN, chid, "Cannot send to channel") return } } @@ -452,58 +467,52 @@ func handleCmdMode(sv *Server, msg *irc.Message) { if len(msg.Args) < 2 { return } - modeFlag := msg.Args[1] - if len(msg.Args) < 3 { - //modeTar := "" - } else { - //modeTar := strings.ToLower(msg.Args[2]) + mode := "" + modeSwitch := msg.Args[1] + modeTarget := "" + if len(modeSwitch) < 2 { + return } - switch modeFlag { + if len(msg.Args) > 2 { + modeTarget = strings.ToLower(msg.Args[2]) + } + switch modeSwitch[1] { // maybe this can be done more elegant - case "+o": - if !sv.channelCheckMode(chid, "o "+clid) { + case 'o': + if !sv.channelCheckPerm(chid, clid, "o") { goto noPerm } - case "-o": - if !sv.channelCheckMode(chid, "o "+clid) { + case 'h': + if !sv.channelCheckPerm(chid, clid, "o") { goto noPerm } - case "+h": - if !sv.channelCheckMode(chid, "o "+clid) { + case 'b': + if !sv.channelCheckPerm(chid, clid, "oh") { goto noPerm } - case "-h": - if !sv.channelCheckMode(chid, "o "+clid) { + case 'v': + if !sv.channelCheckPerm(chid, clid, "oh") { goto noPerm } - case "+b": - if !sv.channelCheckMode(chid, "o "+clid) && - !sv.channelCheckMode(chid, "h "+clid) { + case 'm': + if !sv.channelCheckPerm(chid, clid, "oh") { goto noPerm } - case "-b": - if !sv.channelCheckMode(chid, "o "+clid) && - !sv.channelCheckMode(chid, "h "+clid) { - goto noPerm - } - case "+v": - if !sv.channelCheckMode(chid, "o "+clid) && - !sv.channelCheckMode(chid, "h "+clid) { - goto noPerm - } - case "-v": - if !sv.channelCheckMode(chid, "o "+clid) && - !sv.channelCheckMode(chid, "h "+clid) { - goto noPerm - } - case "+m": - if !sv.channelCheckMode(chid, "o "+clid) { - goto noPerm - } - case "-m": - if !sv.channelCheckMode(chid, "o "+clid) { + case 't': + if !sv.channelCheckPerm(chid, clid, "oh") { goto noPerm } + default: + return + } + mode = string(modeSwitch[1]) + if modeTarget != "" { + mode = mode + " " + modeTarget + } + if modeSwitch[0] == '+' { + sv.chModes[chid][mode] = true + } else { + delete(sv.chModes[chid], mode) } sv.sendMsg(msg) return @@ -513,24 +522,45 @@ func handleCmdMode(sv *Server, msg *irc.Message) { } func handleCmdTopic(sv *Server, msg *irc.Message) { - ch := msg.Args[0] - if _, exists := sv.chUsers[ch]; !exists { - sv.sendReply(msg.Pre, ERR_NOSUCHCHANNEL, ch, "No such channel") + chid := strings.ToLower(msg.Args[0]) + clid := strings.ToLower(msg.Pre) + if _, exists := sv.chUsers[chid]; !exists { + sv.sendReply(msg.Pre, ERR_NOSUCHCHANNEL, chid, "No such channel") } if msg.Trail == "" { - sv.sendReply(msg.Pre, RPL_TOPIC, ch, sv.chTopics[ch]) + sv.sendReply(msg.Pre, RPL_TOPIC, chid, sv.chTopics[chid]) } else { - sv.chTopics[ch] = msg.Trail + if sv.channelCheckMode(chid, "t") && + !sv.channelCheckPerm(chid, clid, "oh") { + sv.sendReply(clid, ERR_CHANOPRIVSNEEDED, chid, "You're not channel operator") + return + } + sv.chTopics[chid] = msg.Trail sv.sendMsg(msg) //sv.sendReply(msg.Pre, RPL_TOPIC, ch, msg.Trail) } } -func handleCmdNames(sv *Server, msg *irc.Message) { - ch := msg.Args[0] - if _, exists := sv.chUsers[ch]; !exists { - sv.sendReply(msg.Pre, ERR_NOSUCHCHANNEL, ch, "No such channel") + +func handleCmdKick(sv *Server, msg *irc.Message) { + chid := strings.ToLower(msg.Args[0]) + clid := strings.ToLower(msg.Pre) + target := strings.ToLower(msg.Args[1]) + if !sv.channelCheckPerm(chid, clid, "oh") { + sv.sendReply(clid, ERR_CHANOPRIVSNEEDED, chid, "You're not channel operator") } - sv.channelNames(msg.Pre, ch) + sv.sendMsg(msg) + delete(sv.chUsers[chid], target) + delete(sv.chModes[chid], "o "+target) + delete(sv.chModes[chid], "h "+target) + delete(sv.chModes[chid], "v "+target) +} + +func handleCmdNames(sv *Server, msg *irc.Message) { + chid := strings.ToLower(msg.Args[0]) + if _, exists := sv.chUsers[chid]; !exists { + sv.sendReply(msg.Pre, ERR_NOSUCHCHANNEL, chid, "No such channel") + } + sv.channelNames(msg.Pre, chid) } func handleCmdWhois(sv *Server, msg *irc.Message) { @@ -546,3 +576,6 @@ func handleCmdRehash(sv *Server, msg *irc.Message) { sv.sendReply(msg.Pre, RPL_REHASHING, "", "Rehashing.") xlog.Info("Rehashing") } + +func handleCmdKill(sv *Server, msg *irc.Message) { +}