From: root Date: Thu, 2 Feb 2012 21:44:45 +0000 (+0100) Subject: Merge remote branch 'upstream/master' X-Git-Url: http://git.pk910.de/?p=srvx.git;a=commitdiff_plain;h=fffe459760943b6ed8e0bb736c87ef424ce38fdc;hp=-c Merge remote branch 'upstream/master' Conflicts: src/proto-p10.c --- fffe459760943b6ed8e0bb736c87ef424ce38fdc diff --combined configure.in index 9540a00,5b350a9..a3a8851 --- a/configure.in +++ b/configure.in @@@ -3,12 -3,13 +3,13 @@@ dnl Process this file with autoconf to dnl General initialization. AC_PREREQ(2.64) AC_INIT([srvx],[1.4.0-rc3],[srvx-bugs@lists.sourceforge.net]) -CODENAME=surge +CODENAME=wgn AC_CONFIG_HEADERS(src/config.h) AC_CONFIG_SRCDIR(src/opserv.c) dnl AM_CANONICAL_TARGET must be before AM_INIT_AUTOMAKE() or autoconf whines AC_CANONICAL_TARGET - AM_INIT_AUTOMAKE([gnu 1.6]) + AC_CONFIG_MACRO_DIR([m4]) + AM_INIT_AUTOMAKE([gnu 1.10 silent-rules]) AM_MAINTAINER_MODE LT_INIT @@@ -23,7 -24,6 +24,7 @@@ AC_PROG_INSTAL AC_PROG_LN_S AC_PROG_MAKE_SET AC_PROG_GCC_TRADITIONAL +AC_PROG_RANLIB dnl Look for a git client AC_CHECK_PROGS(GIT, [git]) @@@ -333,7 -333,7 +334,7 @@@ AC_ARG_ENABLE(modules module_list="" dnl Must use a separate file because autoconf can't stand newlines in an AC_SUBSTed variable. for module in $enableval ; do - module=`echo $module | sed -e s/^mod-// -e s/\.c\$//` + module=`echo $module | sed -e s/^mod-// -e s/\\\.c\\\$//` EXTRA_MODULE_OBJS="$EXTRA_MODULE_OBJS mod-$module.\$(OBJEXT)" module_list="$module_list $module" echo "WITH_MODULE($module)" >> $MODULE_DEFINES diff --combined src/proto-bahamut.c index 99ffa3b,af7e554..a0c1d98 --- a/src/proto-bahamut.c +++ b/src/proto-bahamut.c @@@ -1105,6 -1105,7 +1105,7 @@@ void init_parse(void) userList_init(&dead_users); reg_exit_func(parse_cleanup); + (void)call_xquery_funcs; } int parse_line(char *line, int recursive) { @@@ -1230,7 -1231,7 +1231,7 @@@ void mod_usermode(struct userNode *user } struct mod_chanmode * -mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, unsigned int flags, short base_oplevel) +mod_chanmode_parse(struct chanNode *channel, struct userNode *user, char **modes, unsigned int argc, unsigned int flags, short base_oplevel) { struct mod_chanmode *change; unsigned int ii, in_arg, ch_arg, add; diff --combined src/proto-common.c index e690726,6039d75..bc37f32 --- a/src/proto-common.c +++ b/src/proto-common.c @@@ -23,9 -23,6 +23,9 @@@ #include "ioset.h" #include "log.h" #include "nickserv.h" +#include "opserv.h" +#include "chanserv.h" +#include "spamserv.h" #include "timeq.h" #ifdef HAVE_SYS_SOCKET_H #include @@@ -450,8 -447,6 +450,8 @@@ privmsg_chan_helper(struct chanNode *cn && (offchannel_allowed[(unsigned char)pd->text[0]] || (GetUserMode(cn, cf->service) && !IsDeaf(cf->service)))) cf->func(pd->user, cn, pd->text+1, cf->service, pd->is_notice); + else + spamserv_channel_message(cn, pd->user, pd->text); /* This catches *all* text sent to the channel that the services server sees */ for (x = 0; x < ALLCHANMSG_FUNCS_MAX; x++) { @@@ -483,8 -478,6 +483,8 @@@ part_helper(struct chanNode *cn, void * { struct part_desc *desc = data; DelChannelUser(desc->user, cn, desc->text, false); + if (IsOper(desc->user)) + operpart(cn, desc->user); } static CMD_FUNC(cmd_part) @@@ -577,6 -570,34 +577,34 @@@ call_oper_funcs(struct userNode *user } } + static xquery_func_t *xqf_list; + static unsigned int xqf_size = 0, xqf_used = 0; + + void + reg_xquery_func(xquery_func_t handler) + { + if (xqf_used == xqf_size) { + if (xqf_size) { + xqf_size <<= 1; + xqf_list = realloc(xqf_list, xqf_size*sizeof(xquery_func_t)); + } else { + xqf_size = 8; + xqf_list = malloc(xqf_size*sizeof(xquery_func_t)); + } + } + xqf_list[xqf_used++] = handler; + } + + static void + call_xquery_funcs(struct server *source, const char routing[], const char query[]) + { + unsigned int n; + for (n=0; n < xqf_used; n++) + { + xqf_list[n](source, routing, query); + } + } + struct mod_chanmode * mod_chanmode_alloc(unsigned int argc) { @@@ -603,9 -624,6 +631,9 @@@ mod_chanmode_dup(struct mod_chanmode *o 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_noflood, orig->new_noflood, sizeof(res->new_noflood)); 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)); @@@ -625,14 -643,8 +653,14 @@@ mod_chanmode_apply(struct userNode *who 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_NOFLOOD) + strcpy(channel->noflood, change->new_noflood); if (change->modes_set & MODE_UPASS) strcpy(channel->upass, change->new_upass); if (change->modes_set & MODE_APASS) @@@ -709,7 -721,7 +737,7 @@@ mod_chanmode(struct userNode *who, stru base_oplevel = member->oplevel; else base_oplevel = MAXOPLEVEL; - if (!(change = mod_chanmode_parse(channel, modes, argc, flags, base_oplevel))) + if (!(change = mod_chanmode_parse(channel, who, modes, argc, flags, base_oplevel))) return 0; if (flags & MC_ANNOUNCE) mod_chanmode_announce(who, channel, change); @@@ -729,9 -741,6 +757,9 @@@ irc_make_chanmode(struct chanNode *chan 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_noflood, chan->noflood, sizeof(change.new_noflood)); 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)); @@@ -765,12 -774,7 +793,12 @@@ generate_hostmask(struct userNode *user } hostname = user->hostname; if (IsFakeHost(user) && IsHiddenHost(user) && !(options & GENMASK_NO_HIDING)) { - hostname = user->fakehost; + if(user->fakehost && user->fakehost[0] == '$') { + hostname = alloca(strlen(user->handle_info->handle) + strlen(user->fakehost)); + sprintf(hostname, "%s%s", user->handle_info->handle, user->fakehost+1); + } else { + hostname = user->fakehost; + } } else if (IsHiddenHost(user) && user->handle_info && hidden_host_suffix && !(options & GENMASK_NO_HIDING)) { hostname = alloca(strlen(user->handle_info->handle) + strlen(hidden_host_suffix) + 2); sprintf(hostname, "%s.%s", user->handle_info->handle, hidden_host_suffix); diff --combined src/proto-p10.c index c48d21b,71f6d37..d08fb18 --- a/src/proto-p10.c +++ b/src/proto-p10.c @@@ -40,7 -40,6 +40,7 @@@ #define CMD_EOB_ACK "EOB_ACK" #define CMD_ERROR "ERROR" #define CMD_FAKEHOST "FAKE" +#define CMD_FAKEHOST2 "FAKE2" #define CMD_GET "GET" #define CMD_GLINE "GLINE" #define CMD_HASH "HASH" @@@ -73,7 -72,6 +73,7 @@@ #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" @@@ -88,8 -86,6 +88,8 @@@ #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" @@@ -105,6 -101,8 +105,8 @@@ #define CMD_WHO "WHO" #define CMD_WHOIS "WHOIS" #define CMD_WHOWAS "WHOWAS" + #define CMD_XQUERY "XQUERY" + #define CMD_XRESPONSE "XRESPONSE" /* Tokenized commands. */ #define TOK_ACCOUNT "AC" @@@ -126,7 -124,6 +128,7 @@@ #define TOK_EOB_ACK "EA" #define TOK_ERROR "Y" #define TOK_FAKEHOST "FA" +#define TOK_FAKEHOST2 "NFH" #define TOK_GET "GET" #define TOK_GLINE "GL" #define TOK_HASH "HASH" @@@ -159,7 -156,6 +161,7 @@@ #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" @@@ -174,8 -170,6 +176,8 @@@ #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" @@@ -191,6 -185,8 +193,8 @@@ #define TOK_WHO "H" #define TOK_WHOIS "W" #define TOK_WHOWAS "X" + #define TOK_XQUERY "XQ" + #define TOK_XRESPONSE "XR" /* Protocol messages; aliased to full commands or tokens depending on compile-time configuration. ircu prefers tokens WITH THE @@@ -223,7 -219,6 +227,7 @@@ #define P10_EOB_ACK TYPE(EOB_ACK) #define P10_ERROR TYPE(ERROR) #define P10_FAKEHOST TYPE(FAKEHOST) +#define P10_FAKEHOST2 TYPE(FAKEHOST2) #define P10_GET TYPE(GET) #define P10_GLINE TYPE(GLINE) #define P10_HASH TYPE(HASH) @@@ -256,7 -251,6 +260,7 @@@ #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) @@@ -271,8 -265,6 +275,8 @@@ #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) @@@ -288,6 -280,8 +292,8 @@@ #define P10_WHO TYPE(WHO) #define P10_WHOIS TYPE(WHOIS) #define P10_WHOWAS TYPE(WHOWAS) + #define P10_XQUERY TYPE(XQUERY) + #define P10_XRESPONSE TYPE(XRESPONSE) /* Servers claiming to have a boot or link time before PREHISTORY * trigger errors to the log. We hope no server has been running @@@ -305,8 -299,8 +311,8 @@@ static const char *his_servername 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); @@@ -505,25 -499,7 +511,25 @@@ irc_account(struct userNode *user, cons void irc_fakehost(struct userNode *user, const char *host, const char *ident, int force) { - putsock("%s " P10_FAKEHOST " %s %s %s%s", self->numeric, user->numeric, ident, host, force ? " FORCE" : ""); + /* SRVX added the possibility for FAKE IDENTS + * but this is currently *NOT* supported by our IRCu + * + * edit 24.11.11: + * NFH (P10_FAKEHOST2) is now supported by our IRCu (git-65-21592a4) + */ + putsock("%s " P10_FAKEHOST2 " %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); +} + +void +irc_simul(struct userNode *target, char *command) +{ + putsock("%s " P10_RELAY " %s SI %s :%s", self->numeric, target->numeric, target->numeric, command); } void @@@ -624,24 -600,6 +630,24 @@@ irc_privmsg(struct userNode *from, cons 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) { @@@ -702,16 -660,12 +708,16 @@@ irc_introduce(const char *passwd void irc_gline(struct server *srv, struct gline *gline) { + // GL [!][+|-|>|<] [] [] [] [:] + //expiration = relative time (seconds) + //lastmod = timestamp + //livetime = timestamp if (gline->lastmod) - putsock("%s " P10_GLINE " %s +%s %lu %lu %lu :%s", - self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires, gline->lastmod, gline->lifetime, gline->reason); + putsock("%s " P10_GLINE " %s +%s %lu %lu %lu :%s", self->numeric, (srv ? srv->numeric : "*"), + gline->target, gline->expires-now, gline->lastmod, gline->lifetime, gline->reason); else - putsock("%s " P10_GLINE " %s +%s %lu :%s", - self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires, gline->reason); + putsock("%s " P10_GLINE " %s +%s %lu :%s", self->numeric, (srv ? srv->numeric : "*"), + gline->target, gline->expires-now, gline->reason); } void @@@ -727,7 -681,6 +733,7 @@@ voi 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, @@@ -961,6 -914,12 +967,12 @@@ irc_numeric(struct userNode *user, unsi putsock(":%s %03d %s %s", self->name, num, user->nick, buffer); } + void + irc_xresponse(struct server *target, const char *routing, const char *response) + { + putsock("%s " P10_XRESPONSE " %s %s :%s", self->numeric, target->numeric, routing, response); + } + static void send_burst(void); static void @@@ -1209,8 -1168,6 +1221,8 @@@ create_helper(char *name, void *data return; } + handle_new_channel_created(name, cd->user); + AddChannelUser(cd->user, AddChannel(name, cd->when, NULL, NULL)); } @@@ -1344,7 -1301,7 +1356,7 @@@ static CMD_FUNC(cmd_burst 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; @@@ -1599,8 -1556,6 +1611,8 @@@ static CMD_FUNC(cmd_kick { 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; } @@@ -1723,105 -1678,16 +1735,115 @@@ static CMD_FUNC(cmd_time return 1; } +static CMD_FUNC(cmd_relay) +{ + struct server *sNode; + unsigned int len; + char buf[3]; + // RELAY + 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], tmp2[MAXLEN]; + sprintf(tmp, "%s@%s",argv[7],argv[6]); + sprintf(tmp2, "%s@%s",argv[7],argv[5]); + if((hi = checklogin(argv[4],argv[argc-1],&argv[3][1],tmp,tmp2))) { + //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(!HANDLE_FLAGGED(hi, AUTOHIDE)) { + sprintf(tmp,"%s LA %s 0 %s\n",argv[3],hi->handle,devnull); + } else 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; +} + + static CMD_FUNC(cmd_xquery) + { + struct server *source; + if ((argc < 4) + || !(source = GetServerH(origin))) + return 0; + call_xquery_funcs(source, argv[2], argv[3]); + return 1; + } + void free_user(struct userNode *user) { @@@ -1949,8 -1815,6 +1971,8 @@@ init_parse(void 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); @@@ -1965,6 -1829,8 +1987,8 @@@ dict_insert(irc_func_dict, TOK_ADMIN, cmd_admin); dict_insert(irc_func_dict, CMD_TIME, cmd_time); dict_insert(irc_func_dict, TOK_TIME, cmd_time); + /* We don't handle XR or the (not really defined) XQUERY. */ + dict_insert(irc_func_dict, TOK_XQUERY, cmd_xquery); /* In P10, DESTRUCT doesn't do anything except be broadcast to servers. * Apparently to obliterate channels from any servers that think they @@@ -2456,10 -2322,8 +2480,10 @@@ void mod_usermode(struct userNode *user 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); } @@@ -2476,12 -2340,6 +2500,12 @@@ 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) { @@@ -2557,7 -2415,7 +2581,7 @@@ keyncpy(char output[], char input[], si } struct mod_chanmode * -mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, unsigned int flags, short base_oplevel) +mod_chanmode_parse(struct chanNode *channel, struct userNode *user, char **modes, unsigned int argc, unsigned int flags, short base_oplevel) { struct mod_chanmode *change; unsigned int ii, in_arg, ch_arg, add; @@@ -2581,10 -2439,6 +2605,10 @@@ 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 'u': do_chan_mode(MODE_AUDITORIUM); break; + case 'S': do_chan_mode(MODE_SSLCHAN); 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; @@@ -2593,14 -2447,8 +2617,14 @@@ 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': @@@ -2614,17 -2462,6 +2638,17 @@@ 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) @@@ -2640,70 -2477,6 +2664,70 @@@ } } break; + case 'f': + if (add) { + if (in_arg >= argc) + goto error; + char *mode = modes[in_arg++]; + if(mode[0] == '!' && !(flags & MCP_OPERMODE)) //noflood flag also for overriders + goto error;//only allow opers + else if(mode[0] == '!') + mode++; + + if(mode[0] == '+' || mode[0] == '@') { + mode++; + } + char *p; + int count = 0, time = 0; + for(p = mode; p[0]; p++) { + if(p[0] == ':') { + char tmpchar = p[0]; + p[0] = '\0'; + count = strtoul(mode,0,10); + p[0] = tmpchar; + p++; + time = strtoul(p,0,10); + break; + } + } + if(count <= 0 || time <= 0 || count > 100 || time > 600) + goto error; + change->modes_set |= MODE_NOFLOOD; + safestrncpy(change->new_noflood, modes[in_arg - 1], sizeof(change->new_noflood)); + } else { + change->modes_clear |= MODE_NOFLOOD; + } + break; + case 'F': + if (add) { + if (in_arg >= argc) + goto error; + char *altchan = modes[in_arg++]; + struct chanNode *target; + if(!IsChannelName(altchan) || !(target = GetChannel(altchan))) + goto error; + if(!(flags & MCP_OPERMODE)) { + //check if the user has the permissions to use this channel as target + struct modeNode *mn; + struct userData *uData; + struct chanData *cData; + if(user && (mn = GetUserMode(target, user)) && (mn->modes & MODE_CHANOP)) { + //allow - user is opped on target channel + } else if(user && user->handle_info && + (uData = GetChannelUser(channel->channel_info, user->handle_info)) && + (cData = uData->channel) && + uData->access >= cData->lvlOpts[lvlGiveOps] + ) { + //allow - user has access to get op on the channel + } else + goto error; + } + change->modes_set |= MODE_ALTCHAN; + safestrncpy(change->new_altchan, altchan, sizeof(change->new_altchan)); + } else { + change->modes_clear |= MODE_ALTCHAN; + } + break; case 'U': if (flags & MCP_NO_APASS) goto error; @@@ -2884,17 -2657,10 +2908,17 @@@ mod_chanmode_announce(struct userNode * 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(NOFLOOD, '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(AUDITORIUM, 'u'); + DO_MODE_CHAR(SSLCHAN, 'S'); DO_MODE_CHAR(REGISTERED, 'z'); #undef DO_MODE_CHAR if (change->modes_clear & channel->modes & MODE_KEY) @@@ -2938,10 -2704,6 +2962,10 @@@ 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(AUDITORIUM, 'u'); + DO_MODE_CHAR(SSLCHAN, 'S'); DO_MODE_CHAR(REGISTERED, 'z'); #undef DO_MODE_CHAR if(change->modes_set & MODE_KEY) @@@ -2954,14 -2716,6 +2978,14 @@@ 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); + if (change->modes_set & MODE_NOFLOOD) + mod_chanmode_append(&chbuf, 'f', change->new_noflood); } for (arg = 0; arg < change->argc; ++arg) { if (change->args[arg].mode & MODE_REMOVE) @@@ -3008,9 -2762,6 +3032,9 @@@ mod_chanmode_format(struct mod_chanmod 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(NOFLOOD, 'f'); DO_MODE_CHAR(KEY, 'k'); DO_MODE_CHAR(UPASS, 'U'); DO_MODE_CHAR(APASS, 'A'); @@@ -3018,10 -2769,6 +3042,10 @@@ 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(AUDITORIUM, 'u'); + DO_MODE_CHAR(SSLCHAN, 'S'); DO_MODE_CHAR(REGISTERED, 'z'); #undef DO_MODE_CHAR } @@@ -3038,16 -2785,9 +3062,16 @@@ 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(AUDITORIUM, 'u'); + DO_MODE_CHAR(SSLCHAN, 'S'); 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(ACCESS, 'a'), args_used += sprintf(args + args_used, " %d", change->new_access); + DO_MODE_CHAR(ALTCHAN, 'F'), args_used += sprintf(args + args_used, " %s", change->new_altchan); + DO_MODE_CHAR(NOFLOOD, 'f'), args_used += sprintf(args + args_used, " %s", change->new_noflood); 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 @@@ -3072,14 -2812,6 +3096,14 @@@ clear_chanmode(struct chanNode *channel 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 'f': + cleared |= MODE_NOFLOOD; + channel->noflood[0] = '\0'; + break; case 'k': cleared |= MODE_KEY; channel->key[0] = '\0'; @@@ -3096,19 -2828,11 +3120,19 @@@ 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 'u': cleared |= MODE_AUDITORIUM; break; + case 'S': cleared |= MODE_SSLCHAN; break; + case 'N': cleared |= MODE_NONOTICES; break; case 'z': cleared |= MODE_REGISTERED; break; } } diff --combined src/proto.h index 54c5e23,6ded4df..2bd70b4 --- a/src/proto.h +++ b/src/proto.h @@@ -104,6 -104,9 +104,9 @@@ void unreg_notice_func(struct userNode typedef void (*oper_func_t) (struct userNode *user); void reg_oper_func(oper_func_t handler); + typedef void (*xquery_func_t) (struct server *source, const char routing[], const char query[]); + void reg_xquery_func(xquery_func_t handler); + /* replay silliness */ void replay_read_line(void); void replay_event_loop(void); @@@ -142,19 -145,13 +145,20 @@@ void irc_kill(struct userNode *from, st void irc_raw(const char *what); void irc_stats(struct userNode *from, struct server *target, char type); void irc_svsnick(struct userNode *from, struct userNode *target, const char *newnick); + void irc_xresponse(struct server *target, const char *routing, const char *response); /* account maintenance */ void irc_account(struct userNode *user, const char *stamp, unsigned long timestamp, unsigned long serial); void irc_regnick(struct userNode *user); void irc_fakehost(struct userNode *user, const char *host, const char *ident, int force); +/* svs maintenance */ +void irc_svsmode(struct userNode *from, struct userNode *user, const char *modes); +void irc_svsjoin(struct userNode *from, struct userNode *user, struct chanNode *chan); +void irc_svsjoinchan(struct userNode *from, struct userNode *user, const char *chan); +void irc_relay(char *message); +void irc_simul(struct userNode *target, char *command); + /* numeric messages */ void irc_numeric(struct userNode *user, unsigned int num, const char *format, ...); /* RFC1459-compliant numeric responses */ @@@ -188,8 -185,6 +192,8 @@@ unsigned int irc_user_modes(const struc /* Channel mode manipulation */ #define KEYLEN 23 +#define NOFLOODLEN 15 +#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 @@@ -198,13 -193,11 +202,13 @@@ */ 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_noflood[NOFLOODLEN + 1]; char new_upass[KEYLEN + 1]; char new_apass[KEYLEN + 1]; struct { @@@ -215,17 -208,15 +219,17 @@@ } 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 */ +#define MCP_OPERMODE 0x0400 #ifdef NDEBUG #define mod_chanmode_init(CHANMODE) do { memset((CHANMODE), 0, sizeof(*CHANMODE)); } while (0) #else @@@ -234,7 -225,7 +238,7 @@@ struct mod_chanmode *mod_chanmode_alloc(unsigned int argc); struct mod_chanmode *mod_chanmode_dup(struct mod_chanmode *orig, unsigned int extra); -struct mod_chanmode *mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, unsigned int flags, short base_oplevel); +struct mod_chanmode *mod_chanmode_parse(struct chanNode *channel, struct userNode *user, char **modes, unsigned int argc, unsigned int flags, short base_oplevel); void mod_chanmode_apply(struct userNode *who, struct chanNode *channel, struct mod_chanmode *change); void mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod_chanmode *change); char *mod_chanmode_format(struct mod_chanmode *desc, char *buffer);