func cmdOpflags(source interface{}, params [][]byte) { c := source.(*Client) channame := string(params[0]) if channame[0] == '#' { channame = channame[1:] } var ch *core.Channel if ch = core.FindChannel("", channame); ch == nil { c.SendLineTo(nil, "403", "#%s :No such channel.", channame) return } // If the user isn't on the channel, don't let them check unless they // can view private channel data. if m := ch.GetMember(c.u); m == nil { if ok, err := perm.CheckChanViewData(me, c.u, ch, "members"); !ok { c.SendLineTo(nil, "482", "#%s :%s", ch.Name(), err) return } } var target *core.User if target = core.GetUserByNick(string(params[1])); target == nil { c.SendLineTo(nil, "401", "%s :No such user.", params[1]) return } var m *core.Membership if m = ch.GetMember(target); m == nil { c.SendLineTo(nil, "304", ":OPFLAGS #%s: %s is not in the channel.", ch.Name(), target.Nick()) return } if ok, err := perm.CheckMemberViewData(me, c.u, m, "op"); !ok { c.SendLineTo(nil, "482", "#%s :%s: %s", ch.Name(), target.Nick(), err) return } var flags string if flags = m.Data("op"); flags == "" { c.SendLineTo(nil, "304", ":OPFLAGS #%s: %s has no channel op flags.", ch.Name(), target.Nick()) return } if flags == "on" { flags = perm.DefaultChanOp() } c.SendLineTo(nil, "304", ":OPFLAGS #%s: %s has channel op flags: %s", ch.Name(), target.Nick(), flags) }
// Function handling processing of extended op syntax into metadata. // It returns the data change object. func processOp(adding bool, ch *core.Channel, param string) []core.DataChange { var change core.DataChange change.Name = "op" change.Data = perm.DefaultChanOp() // Find a colon, indicating extended op syntax. var colon, mask int colon = strings.IndexRune(param, ':') if colon > -1 && len(param) > colon+1 { mask = colon + 1 } else { colon = -1 } // Set the member this opping refers to. if target := core.GetUserByNick(param[mask:]); target != nil { if m := ch.GetMember(target); m != nil { change.Member = m } else { return nil } } else { return nil } // If a colon exists, treat everything before it as opflags. if colon > -1 { change.Data = "" for _, char := range param[:colon] { if v := Flags.Str(char); v != "" { if change.Data != "" { change.Data += " " } change.Data += v } } } // Get the existing op flags, expanding default ops. existingData := change.Member.Data("op") words := strings.Fields(existingData) var existing string for _, word := range words { if word == "on" { word = perm.DefaultChanOp() } if existing != "" { existing += " " } existing += word } if adding { // If we're adding the ban, add the new restrictions to the // previous restrictions. if existing != "" { words := strings.Fields(existing) remwords := strings.Fields(change.Data) for _, flag := range words { var found bool for _, w := range remwords { if w == flag { found = true break } } if !found { if change.Data != "" { change.Data += " " } change.Data += flag } } } } else { // If we're removing the ban, remove the removed restrictions. // Leave restrictions not removed alone. // This is "fun". This is also O(n^2). var left string if existing != "" { words := strings.Fields(existing) remwords := strings.Fields(change.Data) for _, flag := range words { var found bool for _, w := range remwords { if w == flag { found = true break } } if !found && Flags.Char(flag) != 0 { if left != "" { left += " " } left += flag } } } change.Data = left } // Test for whether we have a default restriction. var outsideDefault bool var missingDefault bool defwords := strings.Fields(perm.DefaultChanOp()) words = strings.Fields(change.Data) for _, word := range words { var found bool for _, defword := range defwords { if defword == word { found = true break } } if !found { outsideDefault = true break } } if !outsideDefault { for _, defword := range defwords { var found bool for _, word := range words { if defword == word { found = true break } } if !found { missingDefault = true break } } } // If the restriction is the same as the default restriction, quietly // change it to "on". if !outsideDefault && !missingDefault { change.Data = "on" } return []core.DataChange{change} }