예제 #1
0
파일: join.c 프로젝트: awilfox/tethys
static int try_local_join_chan(u_sourceinfo *si, char *chan, char *key)
{
	u_chan *c, *fwd;
	u_chanuser *cu;
	bool created;
	int num;
	char *modes;

	/* verify entry */

	if (!(c = u_chan_get_or_create(chan)))
		return u_user_num(si->u, ERR_NOSUCHCHANNEL, chan);
	created = c->ts == NOW.tv_sec; /* is this ok? */

	if ((cu = u_chan_user_find(c, si->u)) != NULL)
		return 0;

	if ((num = u_entry_blocked(c, si->u, key)) != 0) {
		fwd = u_find_forward(c, si->u, key);
		if (fwd == NULL || u_chan_user_find(fwd, si->u))
			return u_user_num(si->u, num, c);
		c = fwd;
	}

	/* perform join */

	cu = u_chan_user_add(c, si->u);
	u_del_invite(c, si->u);
	if (created)
		cu->flags |= CU_PFX_OP;

	/* send messages */

	u_sendto_chan(c, NULL, ST_USERS, ":%H JOIN %C", si->u, c);

	modes = u_chan_modes(c, 1);
	if (created) {
		u_log(LG_VERBOSE, "Channel %C %s created by %U", c, modes, si->u);
		u_conn_f(si->link, ":%S MODE %C %s", &me, c, modes);
	}

	if (!(c->flags & CHAN_LOCAL)) {
		if (c->members->size == 1) {
			u_sendto_servers(NULL, ":%S SJOIN %u %C %s :%s%U",
			           &me, c->ts, c, modes,
			           (cu->flags & CU_PFX_OP) ? "@" : "", si->u);
		} else {
			u_sendto_servers(NULL, ":%U JOIN %u %C +",
			           si->u, c->ts, c);
		}
	}

	/* Credit them */
	u_ratelimit_who_credit(si->u);

	u_chan_send_topic(c, si->u);
	u_chan_send_names(c, si->u);

	return 0;
}
예제 #2
0
파일: mode.c 프로젝트: Acidburn0zzz/tethys
/* this function is carefully written to handle both local and remote users
   and servers. */
static int c_a_mode(u_sourceinfo *si, u_msg *msg)
{
	char *target = msg->argv[0];
	int parc;
	char **parv;
	u_chan *c;
	u_modes m;
	struct cmode_stacker_private stack;

	if (!strchr(CHANTYPES, *target)) {
		u_user *tu = u_user_by_ref(si->source, target);
		if (tu == NULL) {
			/* legacy chary behavior */
			u_user_num(si->u, ERR_NOSUCHCHANNEL, target);
		} else if (si->u != tu) {
			u_user_num(si->u, ERR_USERSDONTMATCH);
		} else {
			return mode_user(si, msg->argv[1]);
		}
		return 0;
	}

	if (!(c = u_chan_get(target)))
		return u_user_num(si->u, ERR_NOSUCHCHANNEL, target);

	m.access = NULL;
	m.flags = 0;

	if (SRC_IS_LOCAL_USER(si)) {
		u_chanuser *cu = u_chan_user_find(c, si->u);

		if (msg->argc == 1) {
			return u_user_num(si->u, RPL_CHANNELMODEIS, c,
					  u_chan_modes(c, !!cu));
		}

		if (cu && (cu->flags & CU_PFX_OP))
			m.access = cu;

	} else { /* source is local server or remote user/server */
		m.flags |= MODE_FORCE_ALL;

		if (msg->argc == 1)
			return 0;
	}

	parc = msg->argc - 1;
	parv = msg->argv + 1;
	if (parc > 5)
		parc = 5;

	m.ctx = &cmodes;
	m.stacker = &cmode_stacker;
	m.setter = si;
	m.target = c;
	m.stack = &stack;

	u_mode_process(&m, parc, parv);

	if (SRC_IS_LOCAL_USER(si)) {
		if (m.errors & MODE_ERR_NO_ACCESS)
			u_src_num(si, ERR_CHANOPRIVSNEEDED, c);
		if (m.errors & MODE_ERR_NOT_OPER)
			u_src_num(si, ERR_NOPRIVILEGES);
	}

	return 0;
}