Пример #1
0
func cmdWho(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
		}
	}

	it := ch.Users()
	c.WriteBlock(func() []byte {
		if it == nil {
			return nil
		}

		user := it.User()

		var prefixes string
		if user.Data("away") == "" {
			prefixes += "H"
		} else {
			prefixes += "G"
		}
		if user.Data("op") != "" {
			prefixes += "*"
		}
		prefixes += ChanModes.GetPrefixes(it)

		servername := core.Global.Data("name")
		result := fmt.Sprintf(":%s 352 %s #%s %s %s %s %s %s :0 %s\r\n",
			servername, c.u.Nick(), channame, user.GetIdent(),
			user.GetHostname(), servername, user.Nick(),
			prefixes, user.Data("realname"))

		it = it.ChanNext()
		return []byte(result)
	})

	c.SendLineTo(nil, "315", "%s :End of /WHO list.", params[0])
}
Пример #2
0
func cmdNames(source interface{}, params [][]byte) {
	c := source.(*Client)
	channame := string(params[0])
	if len(channame) > 0 && 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.
	// Otherwise, get their prefixes.
	var myprefix string
	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
		}
		myprefix = "="
	} else {
		myprefix = ChanModes.GetPrefixes(m)
	}

	it := ch.Users()
	c.WriteBlock(func() []byte {
		if it == nil {
			return nil
		}

		names := fmt.Sprintf(":%s 353 %s %s #%s :",
			core.Global.Data("name"), c.u.Nick(), myprefix,
			channame)

		for ; it != nil; it = it.ChanNext() {
			name := ChanModes.GetPrefixes(it) + it.User().Nick()
			if len(names)+len(name) > 508 {
				break
			}
			names += " " + name
		}

		names += "\r\n"
		return []byte(names)
	})

	c.SendLineTo(nil, "366", "#%s :End of /NAMES list", channame)
}
Пример #3
0
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)
}
Пример #4
0
func cmdMode(source interface{}, params [][]byte) {
	c := source.(*Client)

	// If we're viewing the modes of ourselves or a channel...
	if len(params) < 2 {
		if strings.ToUpper(c.u.Nick()) == strings.ToUpper(string(params[0])) {
			modeline := UserModes.GetModes(c.u)
			c.SendLineTo(nil, "221", ":+%s", modeline)
			return
		}

		if params[0][0] == '#' {
			channame := string(params[0][1:])
			ch := core.FindChannel("", channame)
			if ch == nil {
				return
			}
			modeline := ChanModes.GetModes(ch)
			ts := ch.TS()
			c.SendLineTo(nil, "324", "#%s +%s", ch.Name(), modeline)
			c.SendLineTo(nil, "329", "#%s %d", ch.Name(), ts)
			return
		}
		return
	}

	// If we're listing list modes on a channel...
	if params[0][0] == '#' && params[1][0] != '+' && params[1][0] != '-' {
		channame := string(params[0][1:])
		ch := core.FindChannel("", channame)
		if ch == nil {
			return
		}

		var badmodes string
		for _, mode := range string(params[1]) {
			name := ChanModes.GetName(mode)
			if name == "" {
				badmodes += string(mode)
				continue
			}

			if ok, err := perm.CheckChanViewData(me, c.u, ch, name); !ok {
				c.SendLineTo(nil, "482", "#%s :%s", ch.Name(), err)
				continue
			}

			// Different, fixed numerics for different
			// modes. Stupid protocol.
			num := "941"
			endnum := "940"
			switch mode {
			case 'b':
				num = "367"
				endnum = "368"
			case 'e':
				num = "348"
				endnum = "349"
			case 'I':
				num = "346"
				endnum = "347"
			}

			valid := ChanModes.ListMode(ch, int(mode), func(p, v string) {
				var setTime string = "0"
				var setBy string = core.Global.Data("name")
				words := strings.Fields(v)
				for _, word := range words {
					if len(word) > 6 && word[:6] == "setat-" {
						setTime = word[6:]
						continue
					}
					if len(word) > 6 && word[:6] == "setby-" {
						setBy = word[6:]
						continue
					}
				}

				c.SendLineTo(nil, num, "#%s %s %s %s",
					ch.Name(), p, setBy, setTime)
			})
			if valid {
				c.SendLineTo(nil, endnum, "#%s :End of mode list.",
					ch.Name())
			} else {
				badmodes += string(mode)
			}
		}
		if badmodes != "" {
			if badmodes != string(params[1]) {
				c.SendLineTo(nil, "501", "Unknown list modes: %s", badmodes)
				return
			}
			// If ALL the mode characters were invalid, we let it
			// fall through and try to treat it as setting modes.
		} else {
			return
		}
	}

	// If we're setting modes on ourselves...
	if strings.ToUpper(c.u.Nick()) == strings.ToUpper(string(params[0])) {
		var mpars []string
		if len(params) == 3 {
			mpars = strings.Fields(string(params[2]))
		}
		changes, err := UserModes.ParseModeLine(c.u, c.u, params[1], mpars)
		if err != nil {
			c.SendLineTo(nil, "501", "%s", err)
		}

		todo := make([]core.DataChange, 0, len(changes))
		for _, cha := range changes {
			ok, err := perm.CheckUserData(me, c.u, c.u, cha.Name, cha.Data)
			if !ok {
				m := UserModes.GetMode(cha.Name)
				c.SendLineTo(nil, "482", "%s %c: %s", c.u.Nick(),
					m, err)
				continue
			}
			todo = append(todo, cha)
		}
		if len(todo) != 0 {
			c.u.SetDataList(me, c.u, todo)
		}
		return
	}

	if params[0][0] == '#' {
		channame := string(params[0][1:])
		ch := core.FindChannel("", channame)
		if ch == nil {
			return
		}

		var mpars []string
		if len(params) == 3 {
			mpars = strings.Fields(string(params[2]))
		}
		changes, err := ChanModes.ParseModeLine(c.u, ch, params[1], mpars)
		if err != nil {
			c.SendLineTo(nil, "501", "%s", err)
		}

		todo := make([]core.DataChange, 0, len(changes))
		for _, cha := range changes {
			if cha.Member != nil {
				ok, err := perm.CheckMemberData(me, c.u, cha.Member, cha.Name, cha.Data)
				if !ok {
					m := ChanModes.GetMode(cha.Name)
					c.SendLineTo(nil, "482", "#%s %c: %s", ch.Name(), m, err)
					continue
				}
			} else {
				ok, err := perm.CheckChanData(me, c.u, ch, cha.Name, cha.Data)
				if !ok {
					m := ChanModes.GetMode(cha.Name)
					c.SendLineTo(nil, "482", "#%s %c: %s", ch.Name(), m, err)
					continue
				}
			}
			todo = append(todo, cha)
		}
		if todo != nil {
			ch.SetDataList(me, c.u, todo)
		}

		return
	}

	c.SendLineTo(nil, "401", "%s %s :%s", c.u.Nick(), params[0],
		"No such nick or channel.")
}