#define MODE_REGISTERED 0x8000 /* Bahamut +r */
#define MODE_APASS 0x10000 /* +A adminpass */
#define MODE_UPASS 0x20000 /* +U userpass */
+#define MODE_NONOTICES 0x40000 /* +N */
+#define MODE_NOAMSGS 0x80000 /* +M */
+#define MODE_ALTCHAN 0x100000 /* +F */
+#define MODE_ACCESS 0x200000 /* +a */
#define MODE_REMOVE 0x80000000
-#define FLAGS_OPER 0x0001 /* global operator +o */
-#define FLAGS_INVISIBLE 0x0004 /* invisible +i */
-#define FLAGS_WALLOP 0x0008 /* receives wallops +w */
-#define FLAGS_DEAF 0x0020 /* deaf +d */
-#define FLAGS_SERVICE 0x0040 /* cannot be kicked, killed or deoped +k */
-#define FLAGS_GLOBAL 0x0080 /* receives global messages +g */
-#define FLAGS_NOCHAN 0x0100 /* hide channels in whois +n */
+#define FLAGS_OPER 0x0001 /* +o global operator */
+#define FLAGS_INVISIBLE 0x0004 /* +i invisible */
+#define FLAGS_WALLOP 0x0008 /* +w receives wallops */
+#define FLAGS_DEAF 0x0020 /* +d deaf */
+#define FLAGS_SERVICE 0x0040 /* +k cannot be kicked, killed or deoped */
+#define FLAGS_GLOBAL 0x0080 /* +g receives global messages */
+#define FLAGS_NOCHAN 0x0100 /* +n hide channels in whois */
#define FLAGS_PERSISTENT 0x0200 /* for reserved nicks, this isn't just one-shot */
#define FLAGS_GAGGED 0x0400 /* for gagged users */
#define FLAGS_AWAY 0x0800 /* for away users */
#define FLAGS_STAMPED 0x1000 /* for users who have been stamped */
-#define FLAGS_HIDDEN_HOST 0x2000 /* user's host is masked by their account */
-#define FLAGS_REGNICK 0x4000 /* user owns their current nick */
+#define FLAGS_HIDDEN_HOST 0x2000 /* +x user's host is masked by their account */
+#define FLAGS_REGNICK 0x4000 /* +r user owns their current nick */
#define FLAGS_REGISTERING 0x8000 /* user has issued account register command, is waiting for email cookie */
#define FLAGS_DUMMY 0x10000 /* user is not announced to other servers */
-#define FLAGS_NOIDLE 0x20000 /* hide idle time in whois +I */
+#define FLAGS_NOIDLE 0x20000 /* +I hide idle time in whois */
+#define FLAGS_NETSERV 0x40000 /* +S */
+#define FLAGS_SECURITYSERV 0x80000 /* +D */
+#define FLAGS_XTRAOP 0x100000 /* +X */
+#define FLAGS_HIDDENOPER 0x200000 /* +H */
+#define FLAGS_SERVERNOTICE 0x400000 /* +s */
+#define FLAGS_SEENOIDLE 0x800000 /* +t */
#define IsOper(x) ((x)->modes & FLAGS_OPER)
#define IsService(x) ((x)->modes & FLAGS_SERVICE)
#define IsRegistering(x) ((x)->modes & FLAGS_REGISTERING)
#define IsDummy(x) ((x)->modes & FLAGS_DUMMY)
#define IsNoIdle(x) ((x)->modes & FLAGS_NOIDLE)
+#define IsSecurityServ(x) ((x)->modes & FLAGS_SECURITYSERV)
+#define IsNetServ(x) ((x)->modes & FLAGS_NETSERV)
+#define IsXtraOp(x) ((x)->modes & FLAGS_XTRAOP)
+#define IsServerNotice(x) ((x)->modes & FLAGS_SERVERNOTICE)
+#define IsHiddenOper(x) ((x)->modes & FLAGS_HIDDENOPER)
+#define IsSeeNoIdle(x) ((x)->modes & FLAGS_SEENOIDLE)
#define IsFakeHost(x) ((x)->fakehost[0] != '\0')
#define IsFakeIdent(x) ((x)->fakeident[0] != '\0')
#define IsLocal(x) ((x)->uplink == self)
struct chanNode {
chan_mode_t modes;
unsigned int limit;
+ unsigned int access;
unsigned int locks;
char key[KEYLEN + 1];
+ char altchan[CHANNELLEN + 1];
char upass[KEYLEN + 1];
char apass[KEYLEN + 1];
unsigned long timestamp; /* creation time */
res->modes_set = orig->modes_set;
res->modes_clear = orig->modes_clear;
res->new_limit = orig->new_limit;
+ res->new_access = orig->new_access;
+ memcpy(res->new_altchan, orig->new_altchan, sizeof(res->new_altchan));
memcpy(res->new_key, orig->new_key, sizeof(res->new_key));
memcpy(res->new_upass, orig->new_upass, sizeof(res->new_upass));
memcpy(res->new_apass, orig->new_apass, sizeof(res->new_apass));
channel->modes = (channel->modes & ~change->modes_clear) | change->modes_set;
if (change->modes_set & MODE_LIMIT)
channel->limit = change->new_limit;
+ if (change->modes_set & MODE_ACCESS)
+ channel->access = change->new_access;
if (change->modes_set & MODE_KEY)
strcpy(channel->key, change->new_key);
+ if (change->modes_set & MODE_ALTCHAN)
+ strcpy(channel->altchan, change->new_altchan);
if (change->modes_set & MODE_UPASS)
strcpy(channel->upass, change->new_upass);
if (change->modes_set & MODE_APASS)
mod_chanmode_init(&change);
change.modes_set = chan->modes;
change.new_limit = chan->limit;
+ change.new_access = chan->access;
+ safestrncpy(change.new_altchan, chan->altchan, sizeof(change.new_altchan));
safestrncpy(change.new_key, chan->key, sizeof(change.new_key));
safestrncpy(change.new_upass, chan->upass, sizeof(change.new_upass));
safestrncpy(change.new_apass, chan->apass, sizeof(change.new_apass));
static const char *his_servercomment;
static struct channelList dead_channels;
-/* These correspond to 1 << X: 012345678901234567 */
-const char irc_user_mode_chars[] = "o iw dkgn x I";
+/* These correspond to 1 << X: 012345678901234567890123 */
+const char irc_user_mode_chars[] = "o iw dkgn x ISDXHst";
static struct userNode *AddUser(struct server* uplink, const char *nick, const char *ident, const char *hostname, const char *modes, const char *numeric, const char *userinfo, unsigned long timestamp, const char *realip);
int n_modes;
for (pos=argv[next], n_modes = 1; *pos; pos++)
if ((*pos == 'k') || (*pos == 'l') || (*pos == 'A')
- || (*pos == 'U'))
+ || (*pos == 'U') || (*pos == 'a') || (*pos == 'F'))
n_modes++;
if (next + n_modes > argc)
n_modes = argc - next;
case 'g': do_user_mode(FLAGS_GLOBAL); break;
case 'n': do_user_mode(FLAGS_NOCHAN); break;
case 'I': do_user_mode(FLAGS_NOIDLE); break;
+ case 'S': do_user_mode(FLAGS_NETSERV); break;
+ case 'D': do_user_mode(FLAGS_SECURITYSERV); break;
+ case 'X': do_user_mode(FLAGS_XTRAOP); break;
+ case 's': do_user_mode(FLAGS_SERVERNOTICE); break;
+ case 'H': do_user_mode(FLAGS_HIDDENOPER); break;
+ case 't': do_user_mode(FLAGS_SEENOIDLE); break;
case 'x': do_user_mode(FLAGS_HIDDEN_HOST); break;
case 'r':
if (*word) {
case 'C': do_chan_mode(MODE_NOCTCPS); break;
case 'D': do_chan_mode(MODE_DELAYJOINS); break;
case 'c': do_chan_mode(MODE_NOCOLORS); break;
+ case 'M': do_chan_mode(MODE_NOAMSGS); break;
+ case 'N': do_chan_mode(MODE_NONOTICES); break;
case 'i': do_chan_mode(MODE_INVITEONLY); break;
case 'm': do_chan_mode(MODE_MODERATED); break;
case 'n': do_chan_mode(MODE_NOPRIVMSGS); break;
change->modes_clear |= MODE_LIMIT;
}
break;
+ case 'a':
+ if (add) {
+ if (in_arg >= argc)
+ goto error;
+ change->modes_set |= MODE_ACCESS;
+ change->new_access = atoi(modes[in_arg++]);
+ } else {
+ change->modes_set &= ~MODE_ACCESS;
+ change->modes_clear |= MODE_ACCESS;
+ }
+ break;
case 'k':
if (add) {
if ((in_arg >= argc)
}
}
break;
+ case 'F':
+ if (add) {
+ if (in_arg >= argc)
+ goto error;
+ change->modes_set |= MODE_ALTCHAN;
+ safestrncpy(change->new_altchan, modes[in_arg++], sizeof(change->new_altchan));
+ } else {
+ change->modes_clear |= MODE_ALTCHAN;
+ }
+ break;
case 'U':
if (flags & MCP_NO_APASS)
goto error;
DO_MODE_CHAR(INVITEONLY, 'i');
DO_MODE_CHAR(NOPRIVMSGS, 'n');
DO_MODE_CHAR(LIMIT, 'l');
+ DO_MODE_CHAR(ACCESS, 'a');
+ DO_MODE_CHAR(ALTCHAN, 'F');
DO_MODE_CHAR(DELAYJOINS, 'D');
DO_MODE_CHAR(REGONLY, 'r');
DO_MODE_CHAR(NOCOLORS, 'c');
DO_MODE_CHAR(NOCTCPS, 'C');
+ DO_MODE_CHAR(NONOTICES, 'N');
+ DO_MODE_CHAR(NOAMSGS, 'M');
DO_MODE_CHAR(REGISTERED, 'z');
#undef DO_MODE_CHAR
if (change->modes_clear & channel->modes & MODE_KEY)
DO_MODE_CHAR(REGONLY, 'r');
DO_MODE_CHAR(NOCOLORS, 'c');
DO_MODE_CHAR(NOCTCPS, 'C');
+ DO_MODE_CHAR(NONOTICES, 'N');
+ DO_MODE_CHAR(NOAMSGS, 'M');
DO_MODE_CHAR(REGISTERED, 'z');
#undef DO_MODE_CHAR
if(change->modes_set & MODE_KEY)
sprintf(int_buff, "%d", change->new_limit);
mod_chanmode_append(&chbuf, 'l', int_buff);
}
+ if(change->modes_set & MODE_ACCESS) {
+ sprintf(int_buff, "%d", change->new_access);
+ mod_chanmode_append(&chbuf, 'a', int_buff);
+ }
+ if (change->modes_set & MODE_ALTCHAN)
+ mod_chanmode_append(&chbuf, 'F', change->new_altchan);
}
for (arg = 0; arg < change->argc; ++arg) {
if (change->args[arg].mode & MODE_REMOVE)
DO_MODE_CHAR(INVITEONLY, 'i');
DO_MODE_CHAR(NOPRIVMSGS, 'n');
DO_MODE_CHAR(LIMIT, 'l');
+ DO_MODE_CHAR(ACCESS, 'a');
+ DO_MODE_CHAR(ALTCHAN, 'F');
DO_MODE_CHAR(KEY, 'k');
DO_MODE_CHAR(UPASS, 'U');
DO_MODE_CHAR(APASS, 'A');
DO_MODE_CHAR(REGONLY, 'r');
DO_MODE_CHAR(NOCOLORS, 'c');
DO_MODE_CHAR(NOCTCPS, 'C');
+ DO_MODE_CHAR(NONOTICES, 'N');
+ DO_MODE_CHAR(NOAMSGS, 'M');
DO_MODE_CHAR(REGISTERED, 'z');
#undef DO_MODE_CHAR
}
DO_MODE_CHAR(REGONLY, 'r');
DO_MODE_CHAR(NOCOLORS, 'c');
DO_MODE_CHAR(NOCTCPS, 'C');
+ DO_MODE_CHAR(NONOTICES, 'N');
+ DO_MODE_CHAR(NOAMSGS, 'M');
DO_MODE_CHAR(REGISTERED, 'z');
DO_MODE_CHAR(LIMIT, 'l'), args_used += sprintf(args + args_used, " %d", change->new_limit);
DO_MODE_CHAR(KEY, 'k'), args_used += sprintf(args + args_used, " %s", change->new_key);
+ DO_MODE_CHAR(KEY, 'a'), args_used += sprintf(args + args_used, " %s", change->new_access);
+ DO_MODE_CHAR(KEY, 'F'), args_used += sprintf(args + args_used, " %s", change->new_altchan);
DO_MODE_CHAR(UPASS, 'U'), args_used += sprintf(args + args_used, " %s", change->new_upass);
DO_MODE_CHAR(APASS, 'A'), args_used += sprintf(args + args_used, " %s", change->new_apass);
#undef DO_MODE_CHAR
case 't': cleared |= MODE_TOPICLIMIT; break;
case 'i': cleared |= MODE_INVITEONLY; break;
case 'n': cleared |= MODE_NOPRIVMSGS; break;
+ case 'F':
+ cleared |= MODE_ALTCHAN;
+ channel->altchan[0] = '\0';
+ break;
case 'k':
cleared |= MODE_KEY;
channel->key[0] = '\0';
cleared |= MODE_LIMIT;
channel->limit = 0;
break;
+ case 'a':
+ cleared |= MODE_ACCESS;
+ channel->access = 0;
+ break;
case 'b': cleared |= MODE_BAN; break;
case 'D': cleared |= MODE_DELAYJOINS; break;
case 'r': cleared |= MODE_REGONLY; break;
case 'c': cleared |= MODE_NOCOLORS; break;
case 'C': cleared |= MODE_NOCTCPS; break;
+ case 'M': cleared |= MODE_NOAMSGS; break;
+ case 'N': cleared |= MODE_NONOTICES; break;
case 'z': cleared |= MODE_REGISTERED; break;
}
}
/* Channel mode manipulation */
#define KEYLEN 23
+#define CHANNELLEN 200
typedef unsigned long chan_mode_t;
/* Rules for struct mod_chanmode:
* For a membership mode change, args[n].mode can contain more than
*/
struct mod_chanmode {
chan_mode_t modes_set, modes_clear;
- unsigned int new_limit, argc;
+ unsigned int new_limit, new_access, argc;
#ifndef NDEBUG
unsigned int alloc_argc;
#endif
char new_key[KEYLEN + 1];
+ char new_altchan[CHANNELLEN + 1];
char new_upass[KEYLEN + 1];
char new_apass[KEYLEN + 1];
struct {
} u;
} args[1];
};
-#define MCP_ALLOW_OVB 0x0001 /* allow op, voice, ban manipulation */
-#define MCP_FROM_SERVER 0x0002 /* parse as from a server */
-#define MCP_KEY_FREE 0x0004 /* -k without a key argument */
-#define MCP_REGISTERED 0x0008 /* chan is already registered; do not allow changes to MODE_REGISTERED */
-#define MCP_UPASS_FREE 0x0010 /* -U without a key argument */
-#define MCP_APASS_FREE 0x0020 /* -A without a key argument */
-#define MCP_NO_APASS 0x0040 /* Do not allow +/-A or +/-U */
-#define MC_ANNOUNCE 0x0100 /* send a mod_chanmode() change out */
-#define MC_NOTIFY 0x0200 /* make local callbacks to announce */
+#define MCP_ALLOW_OVB 0x0001 /* allow op, voice, ban manipulation */
+#define MCP_FROM_SERVER 0x0002 /* parse as from a server */
+#define MCP_KEY_FREE 0x0004 /* -k without a key argument */
+#define MCP_REGISTERED 0x0008 /* chan is already registered; do not allow changes to MODE_REGISTERED */
+#define MCP_UPASS_FREE 0x0010 /* -U without a key argument */
+#define MCP_APASS_FREE 0x0020 /* -A without a key argument */
+#define MCP_NO_APASS 0x0040 /* Do not allow +/-A or +/-U */
+#define MCP_IGN_REGISTERED 0x0080 /* chan is already registered; ignore changes to MODE_REGISTERED */
+#define MC_ANNOUNCE 0x0100 /* send a mod_chanmode() change out */
+#define MC_NOTIFY 0x0200 /* make local callbacks to announce */
#ifdef NDEBUG
#define mod_chanmode_init(CHANMODE) do { memset((CHANMODE), 0, sizeof(*CHANMODE)); } while (0)
#else