#define CMD_PROTO "PROTO"
#define CMD_QUIT "QUIT"
#define CMD_REHASH "REHASH"
+#define CMD_RELAY "RELAY"
#define CMD_RESET "RESET"
#define CMD_RESTART "RESTART"
#define CMD_RPING "RPING"
#define CMD_SQUIT "SQUIT"
#define CMD_STATS "STATS"
#define CMD_SVSNICK "SVSNICK"
+#define CMD_SVSMODE "SVSMODE"
+#define CMD_SVSJOIN "SVSJOIN"
#define CMD_TIME "TIME"
#define CMD_TOPIC "TOPIC"
#define CMD_TRACE "TRACE"
#define TOK_PROTO "PROTO"
#define TOK_QUIT "Q"
#define TOK_REHASH "REHASH"
+#define TOK_RELAY "RL"
#define TOK_RESET "RESET"
#define TOK_RESTART "RESTART"
#define TOK_RPING "RI"
#define TOK_SQUIT "SQ"
#define TOK_STATS "R"
#define TOK_SVSNICK "SN"
+#define TOK_SVSMODE "SM"
+#define TOK_SVSJOIN "SJ"
#define TOK_TIME "TI"
#define TOK_TOPIC "T"
#define TOK_TRACE "TR"
#define P10_PROTO TYPE(PROTO)
#define P10_QUIT TYPE(QUIT)
#define P10_REHASH TYPE(REHASH)
+#define P10_RELAY TYPE(RELAY)
#define P10_RESET TYPE(RESET)
#define P10_RESTART TYPE(RESTART)
#define P10_RPING TYPE(RPING)
#define P10_SQUIT TYPE(SQUIT)
#define P10_STATS TYPE(STATS)
#define P10_SVSNICK TYPE(SVSNICK)
+#define P10_SVSMODE TYPE(SVSMODE)
+#define P10_SVSJOIN TYPE(SVSJOIN)
#define P10_TIME TYPE(TIME)
#define P10_TOPIC TYPE(TOPIC)
#define P10_TRACE TYPE(TRACE)
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);
putsock("%s " P10_FAKEHOST " %s %s %s%s", self->numeric, user->numeric, ident, host, force ? " FORCE" : "");
}
+void
+irc_relay(char *message)
+{
+ putsock("%s " P10_RELAY " %s", self->numeric, message);
+ fprintf(stderr,"%s " P10_RELAY " %s", self->numeric, message);
+}
+
+void
+irc_simul(struct userNode *target, char *command)
+{
+ putsock("%s " P10_RELAY " %s SI %s :%s", self->numeric, target->numeric, target->numeric, command);
+}
+
void
irc_regnick(UNUSED_ARG(struct userNode *user))
{
putsock("%s " P10_PRIVMSG " %s :%s", from->numeric, to, message);
}
+void
+irc_svsmode(struct userNode *from, struct userNode *user, const char *modes)
+{
+putsock("%s " P10_SVSMODE " %s %s", from->numeric, user->numeric, modes);
+}
+
+void
+irc_svsjoin(struct userNode *from, struct userNode *user, struct chanNode *chan)
+{
+putsock("%s " P10_SVSJOIN " %s %s", from->numeric, user->numeric, chan->name);
+}
+
+void
+irc_svsjoinchan(struct userNode *from, struct userNode *user, const char *chan)
+{
+putsock("%s " P10_SVSJOIN " %s %s", from->numeric, user->numeric, chan);
+}
+
void
irc_eob(void)
{
irc_ungline(const char *mask)
{
putsock("%s " P10_GLINE " * -%s %lu", self->numeric, mask, now);
+ //putsock("%s " P10_GLINE " * %s * %lu", self->numeric, mask, now);
}
/* Return negative if *(struct modeNode**)pa is "less than" pb,
return;
}
+ handle_new_channel_created(name, cd->user);
+
AddChannelUser(cd->user, AddChannel(name, cd->when, NULL, NULL));
}
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;
{
if (argc < 3)
return 0;
+ if (GetUserN(argv[2]) && IsOper(GetUserN(argv[2])))
+ operpart(GetChannel(argv[1]), GetUserN(argv[2]));
ChannelUserKicked(GetUserH(origin), GetUserN(argv[2]), GetChannel(argv[1]));
return 1;
}
return 1;
}
+static CMD_FUNC(cmd_relay)
+{
+ struct server *sNode;
+ unsigned int len;
+ char buf[3];
+ //<sender> RELAY <destination> <command>
+ len = strlen(argv[1]);
+ buf[2] = 0;
+ switch(len) {
+ case 2:
+ sNode = GetServerN(argv[1]);
+ break;
+ case 5:
+ buf[0] = argv[1][0];
+ buf[1] = argv[1][1];
+ sNode = GetServerN(buf);
+ break;
+ case 6:
+ buf[0] = argv[1][1];
+ buf[1] = argv[1][2];
+ sNode = GetServerN(buf);
+ break;
+ default:
+ /* Invalid destination. Ignore. */
+ return 0;
+ }
+ if(sNode->numeric == self->numeric) {
+ //ok someone relayed something to us!
+ if(strcmp("LQ", argv[2]) == 0) {
+ //oooh thats exciting - we've got a LOC Query! :D
+ //LQ !ABADE pk910 80.153.5.212 server.zoelle1.de ~watchcat :test
+ //ok let's check the login datas
+ struct handle_info *hi;
+ char tmp[MAXLEN];
+ sprintf(tmp, "*!%s@%s",argv[7],argv[5]);
+ if((hi = checklogin(argv[4],argv[argc-1],&argv[3][1],tmp))) {
+ //login ok
+ struct devnull_class *th;
+ char devnull[512];
+ if(hi->devnull && (th = devnull_get(hi->devnull))) {
+ const char *devnull_modes = DEVNULL_MODES;
+ int ii, flen;
+ char flags[50];
+ for (ii=flen=0; devnull_modes[ii]; ++ii)
+ if (th->modes & (1 << ii))
+ flags[flen++] = devnull_modes[ii];
+ flags[flen] = 0;
+ sprintf(devnull, "+%s %s %lu %lu",flags,th->name,th->maxchan,th->maxsendq);
+ } else {
+ devnull[0] = 0;
+ }
+ if(getfakehost(argv[4])) {
+ sprintf(tmp,"%s LA %s %s %s\n",argv[3],hi->handle,getfakehost(argv[4]),devnull);
+ } else {
+ extern const char *hidden_host_suffix;
+ sprintf(tmp,"%s LA %s %s.%s %s\n",argv[3],hi->handle,hi->handle,hidden_host_suffix,devnull);
+ }
+ irc_relay(tmp);
+ } else {
+ //login rejected
+ sprintf(tmp,"%s LR\n",argv[3]);
+ irc_relay(tmp);
+ }
+ } else if(strcmp("UC", argv[2]) == 0) {
+ char tmp[MAXLEN];
+ sprintf(tmp,"%s UC %s %s",argv[3],argv[3],argv[4]);
+ irc_relay(tmp);
+ } else if(strcmp("JA", argv[2]) == 0) {
+ struct userData *uData;
+ struct chanNode *cn;
+ struct userNode *user;
+ char tmp[MAXLEN];
+ cn = GetChannel(argv[4]);
+ if (!cn) return 0;
+ if (!(user = GetUserN(argv[3]))) return 0;
+ if(!cn->channel_info) {
+ //channel not registered
+ sprintf(tmp,"%s JAA %s %s\n",argv[3],cn->name,argv[6]);
+ } else if((uData = GetChannelUser(cn->channel_info, user->handle_info))) {
+ if(uData->access >= atoi(argv[5])) {
+ //we can join
+ sprintf(tmp,"%s JAA %s %s\n",argv[3],cn->name,argv[6]);
+ } else {
+ //access too low
+ sprintf(tmp,"%s JAR %s %i %i\n",argv[3],cn->name,uData->access,uData->access);
+ }
+ } else {
+ //0 access
+ sprintf(tmp,"%s JAR %s %s %s\n",argv[3],cn->name,"0","0");
+ }
+ irc_relay(tmp);
+ }
+ }
+ return 1;
+}
+
void
free_user(struct userNode *user)
{
dict_insert(irc_func_dict, TOK_STATS, cmd_stats);
dict_insert(irc_func_dict, CMD_SVSNICK, cmd_svsnick);
dict_insert(irc_func_dict, TOK_SVSNICK, cmd_svsnick);
+ dict_insert(irc_func_dict, CMD_RELAY, cmd_relay);
+ dict_insert(irc_func_dict, TOK_RELAY, cmd_relay);
dict_insert(irc_func_dict, CMD_WHOIS, cmd_whois);
dict_insert(irc_func_dict, TOK_WHOIS, cmd_whois);
dict_insert(irc_func_dict, CMD_GLINE, cmd_gline);
case 'o':
do_user_mode(FLAGS_OPER);
if (!add) {
+ operdel(user);
userList_remove(&curr_opers, user);
} else if (!userList_contains(&curr_opers, user)) {
+ operadd(user);
userList_append(&curr_opers, user);
call_oper_funcs(user);
}
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;
case 's': do_chan_mode(MODE_SECRET); break;
case 't': do_chan_mode(MODE_TOPICLIMIT); break;
case 'z':
- if (!(flags & MCP_REGISTERED))
- do_chan_mode(MODE_REGISTERED);
+ if (!(flags & MCP_REGISTERED) && (!(flags & MCP_IGN_REGISTERED) || add)) {
+ do_chan_mode(MODE_REGISTERED);
+ } else if (flags & MCP_IGN_REGISTERED) {
+ /* ignore the modechange but continue parsing */
+ } else {
+ mod_chanmode_free(change);
+ return NULL;
+ }
break;
#undef do_chan_mode
case 'l':
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)
mod_chanmode_format(struct mod_chanmode *change, char *outbuff)
{
unsigned int used = 0;
+ unsigned int args_used = 0;
+ char args[MAXLEN];
+
assert(change->argc <= change->alloc_argc);
if (change->modes_clear) {
outbuff[used++] = '-';
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, " %d", 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
- switch (change->modes_set & (MODE_KEY|MODE_LIMIT|MODE_APASS|MODE_UPASS)) {
- /* Doing this implementation has been a pain in the arse, I hope I didn't forget a possible combination */
- case MODE_KEY|MODE_LIMIT|MODE_APASS|MODE_UPASS:
- used += sprintf(outbuff+used, "lkAU %d %s %s %s", change->new_limit, change->new_key, change->new_apass, change->new_upass);
- break;
-
- case MODE_KEY|MODE_LIMIT|MODE_APASS:
- used += sprintf(outbuff+used, "lkA %d %s %s", change->new_limit, change->new_key, change->new_apass);
- break;
- case MODE_KEY|MODE_LIMIT|MODE_UPASS:
- used += sprintf(outbuff+used, "lkU %d %s %s", change->new_limit, change->new_key, change->new_upass);
- break;
- case MODE_KEY|MODE_APASS|MODE_UPASS:
- used += sprintf(outbuff+used, "kAU %s %s %s", change->new_key, change->new_apass, change->new_upass);
- break;
-
- case MODE_KEY|MODE_APASS:
- used += sprintf(outbuff+used, "kA %s %s", change->new_key, change->new_apass);
- break;
- case MODE_KEY|MODE_UPASS:
- used += sprintf(outbuff+used, "kU %s %s", change->new_key, change->new_upass);
- break;
- case MODE_KEY|MODE_LIMIT:
- used += sprintf(outbuff+used, "lk %d %s", change->new_limit, change->new_key);
- break;
- case MODE_LIMIT|MODE_UPASS:
- used += sprintf(outbuff+used, "lU %d %s", change->new_limit, change->new_upass);
- break;
- case MODE_LIMIT|MODE_APASS:
- used += sprintf(outbuff+used, "lA %d %s", change->new_limit, change->new_apass);
- break;
- case MODE_APASS|MODE_UPASS:
- used += sprintf(outbuff+used, "AU %s %s", change->new_apass, change->new_upass);
- break;
-
- case MODE_LIMIT|MODE_APASS|MODE_UPASS:
- used += sprintf(outbuff+used, "lAU %d %s %s", change->new_limit, change->new_apass, change->new_upass);
- break;
-
- case MODE_APASS:
- used += sprintf(outbuff+used, "A %s", change->new_apass);
- break;
- case MODE_UPASS:
- used += sprintf(outbuff+used, "U %s", change->new_upass);
- break;
- case MODE_KEY:
- used += sprintf(outbuff+used, "k %s", change->new_key);
- break;
- case MODE_LIMIT:
- used += sprintf(outbuff+used, "l %d", change->new_limit);
- break;
- }
}
- outbuff[used] = 0;
+ args[args_used] = '\0';
+ strcpy(outbuff + used, args);
return outbuff;
}
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;
}
}