#include "ircd_defs.h"
#include "ircd_features.h"
#include "ircd_log.h"
-#include "ircd_policy.h"
#include "ircd_reply.h"
#include "ircd_snprintf.h"
#include "ircd_string.h"
* who then will educate them on the use of Apass/upass.
*/
+ if (feature_bool(FEAT_OPLEVELS)) {
if (TStime() - chptr->creationtime < 172800) /* Channel younger than 48 hours? */
schedule_destruct_event_1m(chptr); /* Get rid of it in approximately 4-5 minutes */
else
schedule_destruct_event_48h(chptr); /* Get rid of it in approximately 48 hours */
+ } else
+ destruct_channel(chptr);
return 0;
}
assert(0 != ban->value.ban.banstr);
strcpy(ban->value.ban.banstr, banid);
-#ifdef HEAD_IN_SAND_BANWHO
- if (IsServer(cptr))
+ if (IsServer(cptr) && feature_bool(FEAT_HIS_BANWHO))
DupString(ban->value.ban.who, cli_name(&me));
else
-#endif
DupString(ban->value.ban.who, cli_name(cptr));
assert(0 != ban->value.ban.who);
struct Membership* member)
{
struct SLink* tmp;
+ char tmphost[HOSTLEN + 1];
char nu_host[NUH_BUFSIZE];
char nu_realhost[NUH_BUFSIZE];
char nu_ip[NUI_BUFSIZE];
s = make_nick_user_host(nu_host, cli_name(cptr), (cli_user(cptr))->username,
(cli_user(cptr))->host);
- if (HasHiddenHost(cptr))
- sr = make_nick_user_host(nu_realhost, cli_name(cptr),
- (cli_user(cptr))->username,
- cli_user(cptr)->realhost);
+ if (IsAccount(cptr))
+ {
+ if (HasHiddenHost(cptr))
+ {
+ sr = make_nick_user_host(nu_realhost, cli_name(cptr),
+ (cli_user(cptr))->username,
+ cli_user(cptr)->realhost);
+ }
+ else
+ {
+ ircd_snprintf(0, tmphost, HOSTLEN, "%s.%s",
+ cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST));
+ sr = make_nick_user_host(nu_realhost, cli_name(cptr),
+ cli_user(cptr)->username,
+ tmphost);
+ }
+ }
for (tmp = chptr->banlist; tmp; tmp = tmp->next) {
if ((tmp->flags & CHFL_BAN_IPMASK)) {
member = find_channel_member(cptr, chptr);
/*
- * You can't speak if your off channel, if the channel is modeless, or
- * +n (no external messages) or +m (moderated).
+ * You can't speak if you're off channel, and it is +n (no external messages)
+ * or +m (moderated).
*/
if (!member) {
if ((chptr->mode.mode & (MODE_NOPRIVMSGS|MODE_MODERATED)) ||
- IsModelessChannel(chptr->chname) ||
((chptr->mode.mode & MODE_REGONLY) && !IsAccount(cptr)))
return 0;
else
/*
* find_no_nickchange_channel
- * if a member and not opped or voiced and banned
+ * if a member and not (opped or voiced) and (banned or moderated)
* return the name of the first channel banned on
*/
const char* find_no_nickchange_channel(struct Client* cptr)
struct Membership* member;
for (member = (cli_user(cptr))->channel; member;
member = member->next_channel) {
- if (!IsVoicedOrOpped(member) && is_banned(cptr, member->channel, member))
+ if (!IsVoicedOrOpped(member) &&
+ (is_banned(cptr, member->channel, member) ||
+ (member->channel->mode.mode & MODE_MODERATED)))
return member->channel->chname;
}
}
a HACK(4) notice will be sent if he would not have been supposed
to join normally. */
if (IsLocalChannel(chptr->chname) && HasPriv(sptr, PRIV_WALK_LCHAN) &&
- !BadPtr(key) && compall("OVERRIDE",key) == 0)
+ !BadPtr(key) && compall("OVERRIDE",chptr->mode.key) != 0 &&
+ compall("OVERRIDE",key) == 0)
overrideJoin = MAGIC_OPER_OVERRIDE;
if (chptr->mode.mode & MODE_INVITEONLY)
* of course, str2 is not NULL)
*/
static void
-build_string(char *strptr, int *strptr_i, char *str1, char *str2, char c)
+build_string(char *strptr, int *strptr_i, const char *str1,
+ const char *str2, char c)
{
if (c)
strptr[(*strptr_i)++] = c;
if (mbuf->mb_add == 0 && mbuf->mb_rem == 0 && mbuf->mb_count == 0)
return 0;
- /* Ok, if we were given the OPMODE flag, hide the source if its a user */
- if (mbuf->mb_dest & MODEBUF_DEST_OPMODE && !IsServer(mbuf->mb_source))
+ /* Ok, if we were given the OPMODE flag, or its a server, hide the source.
+ */
+ if (mbuf->mb_dest & MODEBUF_DEST_OPMODE || IsServer(mbuf->mb_source))
app_source = &me;
else
app_source = mbuf->mb_source;
bufptr[(*bufptr_i)++] = MB_TYPE(mbuf, i) & MODE_CHANOP ? 'o' : 'v';
totalbuflen -= IRCD_MAX(5, tmp) + 1;
}
- } else if (MB_TYPE(mbuf, i) & (MODE_KEY | MODE_BAN | MODE_APASS | MODE_UPASS)) {
+ } else if (MB_TYPE(mbuf, i) & (MODE_BAN | MODE_APASS | MODE_UPASS)) {
tmp = strlen(MB_STRING(mbuf, i));
if ((totalbuflen - tmp) <= 0) /* don't overflow buffer */
MB_TYPE(mbuf, i) |= MODE_SAVE; /* save for later */
else {
char mode_char;
- switch(MB_TYPE(mbuf, i) & (MODE_KEY | MODE_BAN | MODE_APASS | MODE_UPASS))
+ switch(MB_TYPE(mbuf, i) & (MODE_BAN | MODE_APASS | MODE_UPASS))
{
case MODE_APASS:
mode_char = 'A';
case MODE_UPASS:
mode_char = 'u';
break;
- case MODE_KEY:
- mode_char = 'k';
- break;
default:
mode_char = 'b';
break;
bufptr[(*bufptr_i)++] = mode_char;
totalbuflen -= tmp + 1;
}
+ } else if (MB_TYPE(mbuf, i) & MODE_KEY) {
+ tmp = (mbuf->mb_dest & MODEBUF_DEST_NOKEY ? 1 :
+ strlen(MB_STRING(mbuf, i)));
+
+ if ((totalbuflen - tmp) <= 0) /* don't overflow buffer */
+ MB_TYPE(mbuf, i) |= MODE_SAVE; /* save for later */
+ else {
+ bufptr[(*bufptr_i)++] = 'k';
+ totalbuflen -= tmp + 1;
+ }
} else if (MB_TYPE(mbuf, i) & MODE_LIMIT) {
/* if it's a limit, we also format the number */
ircd_snprintf(0, limitbuf, sizeof(limitbuf), "%u", MB_UINT(mbuf, i));
if (MB_TYPE(mbuf, i) & (MODE_CHANOP | MODE_VOICE))
build_string(strptr, strptr_i, cli_name(MB_CLIENT(mbuf, i)), 0, ' ');
- /* deal with strings... */
- else if (MB_TYPE(mbuf, i) & (MODE_KEY | MODE_BAN))
+ /* deal with bans... */
+ else if (MB_TYPE(mbuf, i) & MODE_BAN)
build_string(strptr, strptr_i, MB_STRING(mbuf, i), 0, ' ');
+ /* deal with keys... */
+ else if (MB_TYPE(mbuf, i) & MODE_KEY)
+ build_string(strptr, strptr_i, mbuf->mb_dest & MODEBUF_DEST_NOKEY ?
+ "*" : MB_STRING(mbuf, i), 0, ' ');
+
/* deal with invisible passwords */
else if (MB_TYPE(mbuf, i) & (MODE_APASS | MODE_UPASS))
build_string(strptr, strptr_i, "*", 0, ' ');
if (mbuf->mb_dest & MODEBUF_DEST_HACK2)
sendto_opmask_butone(0, SNO_HACK2, "HACK(2): %s MODE %s %s%s%s%s%s%s "
"[%Tu]",
-#ifdef HEAD_IN_SAND_SNOTICES
- cli_name(mbuf->mb_source),
-#else
- cli_name(app_source),
-#endif
+ cli_name(feature_bool(FEAT_HIS_SNOTICES) ?
+ mbuf->mb_source : app_source),
mbuf->mb_channel->chname,
rembuf_i ? "-" : "", rembuf, addbuf_i ? "+" : "",
addbuf, remstr, addstr,
if (mbuf->mb_dest & MODEBUF_DEST_HACK3)
sendto_opmask_butone(0, SNO_HACK3, "BOUNCE or HACK(3): %s MODE %s "
"%s%s%s%s%s%s [%Tu]",
-#ifdef HEAD_IN_SAND_SNOTICES
- cli_name(mbuf->mb_source),
-#else
- cli_name(app_source),
-#endif
+ cli_name(feature_bool(FEAT_HIS_SNOTICES) ?
+ mbuf->mb_source : app_source),
mbuf->mb_channel->chname, rembuf_i ? "-" : "",
rembuf, addbuf_i ? "+" : "", addbuf, remstr, addstr,
mbuf->mb_channel->creationtime);
assert(0 != chan);
assert(0 != dest);
+ if (IsLocalChannel(chan->chname)) dest &= ~MODEBUF_DEST_SERVER;
+
mbuf->mb_add = 0;
mbuf->mb_rem = 0;
mbuf->mb_source = source;
int i, bufpos = 0, len;
int *flag_p;
char *key = 0, limitbuf[20];
- char *apass, *upass;
+ char *apass = 0, *upass = 0;
assert(0 != mbuf);
assert(0 != buf);
return;
state->done |= DONE_KEY;
- t_len = KEYLEN + 1;
+ t_len = KEYLEN;
/* clean up the key string */
s = t_str;
} else if (!mmatch(t_str, ban->value.ban.banstr))
ban->flags |= MODE_DEL; /* mark ban for deletion: overlapping */
- if (!ban->next && (newban->flags & MODE_ADD)) {
+ if (!ban->next && (newban->flags & MODE_ADD))
+ {
ban->next = newban; /* add our ban with its flags */
break; /* get out of loop */
}
} else {
if (state->flags & MODE_PARSE_SET && MyUser(state->sptr) &&
(len > (feature_int(FEAT_AVBANLEN) * feature_int(FEAT_MAXBANS)) ||
- count >= feature_int(FEAT_MAXBANS))) {
+ count > feature_int(FEAT_MAXBANS))) {
send_reply(state->sptr, ERR_BANLISTFULL, state->chptr->chname,
ban->value.ban.banstr);
count--;
if (MyUser(state->sptr)) {
/* don't allow local opers to be deopped on local channels */
- if (state->cli_change[i].client != state->sptr &&
+ if (MyUser(state->sptr) &&
+ state->cli_change[i].client != state->sptr &&
IsLocalChannel(state->chptr->chname) &&
HasPriv(state->cli_change[i].client, PRIV_DEOP_LCHAN)) {
send_reply(state->sptr, ERR_ISOPERLCHAN,
continue;
}
+ if (feature_bool(FEAT_OPLEVELS)) {
/* don't allow to deop members with an op level that is <= our own level */
if (state->sptr != state->cli_change[i].client /* but allow to deop oneself */
&& state->member
}
}
}
+ }
/* set op-level of member being opped */
if ((state->cli_change[i].flag & (MODE_ADD | MODE_CHANOP)) ==
break;
case 'A': /* deal with Admin passes */
+ if (feature_bool(FEAT_OPLEVELS))
mode_parse_apass(&state, flag_p);
break;
case 'u': /* deal with user passes */
+ if (feature_bool(FEAT_OPLEVELS))
mode_parse_upass(&state, flag_p);
break;
joinbuf_join(struct JoinBuf *jbuf, struct Channel *chan, unsigned int flags)
{
unsigned int len;
+ int is_local;
assert(0 != jbuf);
return;
}
+ is_local = IsLocalChannel(chan->chname);
+
if (jbuf->jb_type == JOINBUF_TYPE_PART ||
jbuf->jb_type == JOINBUF_TYPE_PARTALL) {
+ struct Membership *member = find_member_link(chan, jbuf->jb_source);
+ if (IsUserParting(member))
+ return;
+ SetUserParting(member);
+
/* Send notification to channel */
if (!(flags & CHFL_ZOMBIE))
sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_PART, chan, NULL,
* the original m_part.c */
if (jbuf->jb_type == JOINBUF_TYPE_PARTALL ||
- IsLocalChannel(chan->chname)) /* got to remove user here */
+ is_local) /* got to remove user here */
remove_user_from_channel(jbuf->jb_source, chan);
} else {
/* Add user to channel */
add_user_to_channel(chan, jbuf->jb_source, flags, 0);
/* send notification to all servers */
- if (jbuf->jb_type != JOINBUF_TYPE_CREATE && !IsLocalChannel(chan->chname))
+ if (jbuf->jb_type != JOINBUF_TYPE_CREATE && !is_local)
sendcmdto_serv_butone(jbuf->jb_source, CMD_JOIN, jbuf->jb_connect,
"%H %Tu", chan, chan->creationtime);
sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_JOIN, chan, NULL, ":%H", chan);
/* send an op, too, if needed */
- if (!MyUser(jbuf->jb_source) && jbuf->jb_type == JOINBUF_TYPE_CREATE &&
- !IsModelessChannel(chan->chname))
+ if (!MyUser(jbuf->jb_source) && jbuf->jb_type == JOINBUF_TYPE_CREATE)
sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_MODE, chan, NULL, "%H +o %C",
chan, jbuf->jb_source);
}
- if (jbuf->jb_type == JOINBUF_TYPE_PARTALL || IsLocalChannel(chan->chname))
+ if (jbuf->jb_type == JOINBUF_TYPE_PARTALL ||
+ jbuf->jb_type == JOINBUF_TYPE_JOIN || is_local)
return; /* don't send to remote */
/* figure out if channel name will cause buffer to be overflowed */
return 0;
}
+
+/* Returns TRUE (1) if client is invited, FALSE (0) if not */
+int IsInvited(struct Client* cptr, const void* chptr)
+{
+ struct SLink *lp;
+
+ for (lp = (cli_user(cptr))->invited; lp; lp = lp->next)
+ if (lp->value.chptr == chptr)
+ return 1;
+ return 0;
+}