diff -ruNx index -x langstrs.h ircservices-5.0a25/channels.h ircservices-5.0a25+hybrid/channels. h --- ircservices-5.0a25/channels.h Tue Mar 19 02:16:18 2002 +++ ircservices-5.0a25+hybrid/channels.h Sun Mar 24 03:38:35 2002 @@ -33,6 +33,8 @@ char **bans; int32 exceptcount, exceptsize; char **excepts; + int32 invexcount, invexsize; + char **invexs; struct c_userlist { struct c_userlist *next, *prev; diff -ruNx index -x langstrs.h ircservices-5.0a25/lang/en_us.l ircservices-5.0a25+hybrid/lang/en _us.l --- ircservices-5.0a25/lang/en_us.l Sun Mar 24 04:05:10 2002 +++ ircservices-5.0a25+hybrid/lang/en_us.l Sun Mar 24 03:35:26 2002 @@ -1409,6 +1409,8 @@ All bans on channel %s have been removed. CHAN_CLEARED_EXCEPTIONS All exceptions on channel %s have been removed. +CHAN_CLEARED_INVEXS + All invite exceptions on channel %s have been removed. CHAN_CLEARED_MODES All modes on channel %s have been reset. CHAN_CLEARED_OPS @@ -1820,10 +1822,10 @@ News : %6d records, %5d kB OPER_STATS_ALL_AKILL_MEM Autokills : %6d records, %5d kB -OPER_STATS_ALL_INVEX_MEM - Invite Exs: %6d records, %5d kB OPER_STATS_ALL_EXCEPTION_MEM Exceptions: %6d records, %5d kB +OPER_STATS_ALL_INVEXS_MEM + Inviti Exs: %6d records, %5d kB OPER_STATS_ALL_SGLINE_MEM SGlines : %6d records, %5d kB OPER_STATS_ALL_SQLINE_MEM @@ -1844,6 +1846,8 @@ Binary modes and bans cleared from channel %s. OPER_CLEARMODES_EXCEPT_DONE Binary modes, bans, and exceptions cleared from channel %s. +OPER_CLEARMODES_EXCEPT_INVEX_DONE + Binary modes, bans, ban and invite exceptions cleared from channel %s. OPER_CLEARMODES_ALL_DONE All modes cleared from channel %s. @@ -3793,6 +3797,8 @@ BANS Clears all bans on the channel. CHAN_HELP_CLEAR_EXCEPTIONS EXCEPTIONS Clears all exceptions on the channel. +CHAN_HELP_CLEAR_INVEXS + INVEXS Clears all invite exceptions on the channel. CHAN_HELP_CLEAR_MID OPS Removes channel-operator status (mode +o) from all users. Binary files ircservices-5.0a25/lang/langcomp and ircservices-5.0a25+hybrid/lang/langcomp differ diff -ruNx index -x langstrs.h ircservices-5.0a25/modules/protocol/Makefile ircservices-5.0a25+h ybrid/modules/protocol/Makefile --- ircservices-5.0a25/modules/protocol/Makefile Tue Mar 19 02:16:18 2002 +++ ircservices-5.0a25+hybrid/modules/protocol/Makefile Sun Mar 24 03:42:38 2002 @@ -11,12 +11,13 @@ include ../../Makefile.inc MODULES = bahamut.so dalnet.so dreamforge.so esper.so rfc1459.so \ - trircd4.so ts8.so undernet-p9.so unreal.so + trircd4.so ts8.so undernet-p9.so unreal.so hybrid.so OBJECTS-bahamut.so = banexcept.o sjoin.o svsnick.o OBJECTS-dreamforge.so = svsnick.o OBJECTS-trircd4.so = banexcept.o chanprot.o sjoin.o svsnick.o OBJECTS-unreal.so = banexcept.o chanprot.o halfop.o sjoin.o svsnick.o \ token.o +OBJECTS-hybrid.so = banexcept.o sjoin.o halfop.o invex.o INCLUDES-bahamut.o = banexcept.h sjoin.h svsnick.h \ $(TOPDIR)/messages.h $(TOPDIR)/language.h \ diff -ruNx index -x langstrs.h ircservices-5.0a25/modules/protocol/hybrid.c ircservices-5.0a25+h ybrid/modules/protocol/hybrid.c --- ircservices-5.0a25/modules/protocol/hybrid.c Thu Jan 1 01:00:00 1970 +++ ircservices-5.0a25+hybrid/modules/protocol/hybrid.c Sun Mar 24 03:43:05 2002 @@ -0,0 +1,395 @@ +/* Hybrid-7 (TS5) protocol module for IRC Services. + * + * IRC Services is copyright (c) 1996-2002 Andrew Church. + * E-mail: + * Parts written by Andrew Kempe and others. + * This program is free but copyrighted software; see the file COPYING for + * details. + */ + +#include "services.h" +#include "modules.h" +#include "conffile.h" +#include "language.h" +#include "messages.h" + +#include "modules/chanserv/chanserv.h" + +#include "sjoin.h" +#include "banexcept.h" +#include "halfop.h" +#include "invex.h" + + +/*************************************************************************/ + +static Module *module; + +static char *NetworkDomain = NULL; + +static char **p_s_ChanServ = &ServerName; +#define s_ChanServ (*p_s_ChanServ) + +static Module *module_chanserv; + +/*************************************************************************/ +/************************** User/channel modes ***************************/ +/*************************************************************************/ + +struct modedata_init { + uint8 mode; + ModeData data; +}; + +static const struct modedata_init new_usermodes[] = { + {'a', {0x0000000}}, /* server admin */ +}; + +static const struct modedata_init new_chanmodes[] = { + {'I', {0x00000100,1,1,0,MI_MULTIPLE}}, /* invite exception */ + {'e', {0x00000200,1,1,0,MI_MULTIPLE}}, /* ban exception */ + {'a', {0x00000400,0,0,0}}, /* hide ops */ +}; + +static const struct modedata_init new_chanusermodes[] = { +}; + +static void init_modes(void) +{ + int i; + + for (i = 0; i < lenof(new_usermodes); i++) + usermodes[new_usermodes[i].mode] = new_usermodes[i].data; + for (i = 0; i < lenof(new_chanmodes); i++) + chanmodes[new_chanmodes[i].mode] = new_chanmodes[i].data; + for (i = 0; i < lenof(new_chanusermodes); i++) + chanusermodes[new_chanusermodes[i].mode] = new_chanusermodes[i].data; + + mode_setup(); +}; + +/*************************************************************************/ +/************************* IRC message receiving *************************/ +/*************************************************************************/ + +static void m_nick(char *source, int ac, char **av) +{ + char *newmodes; + char *nav[7]; + + if (*source) { + /* Old user changing nicks. */ + if (ac != 2) { + if (debug) + module_log("debug: NICK message: wrong number of parameters" + " (%d) for source `%s'", ac, source); + } else { + do_nick(source, ac, av); + } + return; + } + + /* New user. */ + + if (ac != 8) { + if (debug) + module_log("debug: NICK message: wrong number of parameters (%d)" + " for new user", ac); + return; + } + + + nav[0] = av[0]; + nav[1] = av[1]; + nav[2] = av[2]; + nav[3] = av[4]; + nav[4] = av[5]; + nav[5] = av[6]; + nav[6] = av[7]; + + if (do_nick("", 7, nav)) { + av[1] = av[3]; + do_umode(av[0], 2, av); + } +} + +/*************************************************************************/ + +/* SJOIN message handler. The actual code is in sjoin.c. */ + +static void m_sjoin(char *source, int ac, char **av) +{ + if (ac < 3) { + if (debug) + module_log("debug: SJOIN: expected >=3 params, got %d", ac); + return; + } + do_sjoin(source, ac, av); +} + +/*************************************************************************/ + +static Message hybrid_messages[] = { + { "NICK", m_nick }, + { "SJOIN", m_sjoin }, + { NULL } +}; + +/*************************************************************************/ +/************************** IRC message sending **************************/ +/*************************************************************************/ + +/* Send a NICK command for a new user. */ + +static void do_send_nick(const char *nick, const char *user, const char *host, + const char *server, const char *name, + const char *modes) +{ + send_cmd(NULL, "NICK %s 1 %ld +%s %s %s %s :%s", nick, time(NULL), + modes ? modes : "", user, host, server, name); +} + +/*************************************************************************/ + +/* Send a NICK command to change an existing user's nick. */ + +static void do_send_nickchange(const char *nick, const char *newnick) +{ + send_cmd(nick, "NICK %s %ld", newnick, time(NULL)); +} + +/*************************************************************************/ + +/* Send a command to change a user's "real name". */ + +static void do_send_namechange(const char *nick, const char *newname) +{ + /* Not supported by this protocol. */ +} + +/*************************************************************************/ + +/* Send a SERVER command, and anything else needed at the beginning of the + * connection. + */ + +static void do_send_server(void) +{ + send_cmd(NULL, "PASS %s :TS", RemotePassword); + send_cmd(NULL, "CAPAB :EX IE HOPS HUB"); + send_cmd(NULL, "SERVER %s 1 :%s", ServerName, ServerDesc); + send_cmd(NULL, "SVINFO 5 5 0 :%ld", time(NULL)); +} + +/*************************************************************************/ + +/* Send a SERVER command for a remote (juped) server. */ + +static void do_send_server_remote(const char *server, const char *reason) +{ + send_cmd(NULL, "SERVER %s 2 :Juped: %s", server, reason); +} + +/*************************************************************************/ + +/* Send a WALLOPS. */ + +static void do_wallops(const char *source, const char *fmt, ...) +{ + va_list args; + char buf[BUFSIZE]; + + va_start(args, fmt); + snprintf(buf, sizeof(buf), "WALLOPS :%s", fmt); + vsend_cmd(source ? source : ServerName, buf, args); + va_end(args); +} + +/*************************************************************************/ + +/* Send a NOTICE to all users on the network. */ + +static void do_notice_all(const char *source, const char *fmt, ...) +{ + va_list args; + char msgbuf[BUFSIZE]; + + va_start(args, fmt); + vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); + va_end(args); + if (NetworkDomain) { + send_cmd(source, "NOTICE $*.%s :%s", NetworkDomain, msgbuf); + } else { + /* Go through all common top-level domains. If you have others, + * add them here. */ + send_cmd(source, "NOTICE $*.com :%s", msgbuf); + send_cmd(source, "NOTICE $*.net :%s", msgbuf); + send_cmd(source, "NOTICE $*.org :%s", msgbuf); + send_cmd(source, "NOTICE $*.edu :%s", msgbuf); + } +} + +/*************************************************************************/ + +/* Send a command which modifies channel status. */ + +static void do_send_channel_cmd(const char *source, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vsend_cmd(source, fmt, args); + va_end(args); +} + +/*************************************************************************/ +/******************************* Callbacks *******************************/ +/*************************************************************************/ + +static int do_set_topic(Channel *c, const char *topic, const char *setter, + time_t t) +{ + if (t >= c->topic_time) + t = c->topic_time - 1; /* Force topic change */ + if (setter) + return 0; + c->topic_time = t; + + /* This is a hack - for some reason, hybrid ms_sjoin is ignoring our + * op for chanserv during the burst, so send it as a MODE instead + */ + + send_cmd(ServerName, "SJOIN %ld %s + :%s", c->creation_time, c->name, s_ChanServ); + send_cmd(ServerName, "MODE %s +o %s", c->name, s_ChanServ); + send_cmd(s_ChanServ, "TOPIC %s :%s", c->name, c->topic ? c->topic : ""); + send_cmd(s_ChanServ, "PART %s", c->name); + return 1; +} + +/*************************************************************************/ + +static int do_send_akill(const char *username, const char *host, + time_t expires, const char *who, const char *reason) +{ + /* not supported by this protocol */ + return 1; +} + +/*************************************************************************/ + +static int do_cancel_akill(const char *username, const char *host) +{ + /* not supported by this protocol */ + return 1; +} + +/*************************************************************************/ +/***************************** Module stuff ******************************/ +/*************************************************************************/ + +const int32 module_version = MODULE_VERSION_CODE; + +const char protocol_name[] = "Hybrid/TS"; +const char protocol_version[] = "5"; +uint32 protocol_features = 0; +int protocol_nickmax = 30; + +ConfigDirective module_config[] = { + { "NetworkDomain", { { CD_STRING, 0, &NetworkDomain } } }, + { NULL } +}; + +/*************************************************************************/ + +static int do_load_module(Module *mod, const char *modname) +{ + if (strcmp(modname, "chanserv/main") == 0) { + module_chanserv = mod; + p_s_ChanServ = get_module_symbol(mod, "s_ChanServ"); + if (!p_s_ChanServ) { + /* FIXME: make a generalized logging routine for this problem? */ + module_log("Unable to resolve symbol `s_ChanServ' in module" + " `chanserv/main'"); + p_s_ChanServ = &ServerName; + } + } + + return 0; +} + +/*************************************************************************/ + +static int do_unload_module(Module *mod) +{ + return 0; +} + +/*************************************************************************/ + +int init_module(Module *module_) +{ + module = module_; + + if (protocol_nickmax+1 > NICKMAX) { + module_log("NICKMAX is too small (%d)--increase to at least %d and" + " recompile", NICKMAX, protocol_nickmax+1); + return 0; + } + + if (!register_messages(hybrid_messages)) { + module_log("Unable to register messages"); + exit_module(1); + return 0; + } + + if (!add_callback(NULL, "load module", do_load_module) + || !add_callback(NULL, "unload module", do_unload_module) + || !add_callback(NULL, "set topic", do_set_topic) + ) { + module_log("Unable to add callbacks"); + exit_module(1); + return 0; + } + + init_modes(); + + if (!init_halfop(module) + || !init_sjoin(module) + || !init_banexcept(module) + || !init_invex(module) + ) { + return 0; + } + + + send_nick = do_send_nick; + send_nickchange = do_send_nickchange; + send_namechange = do_send_namechange; + send_server = do_send_server; + send_server_remote = do_send_server_remote; + wallops = do_wallops; + notice_all = do_notice_all; + send_channel_cmd = do_send_channel_cmd; + pseudoclient_modes = ""; + enforcer_modes = ""; + + return 1; +} + +/*************************************************************************/ + +int exit_module(int shutdown) +{ + if (!shutdown) { + /* Do not allow removal */ + return 0; + } + + remove_callback(NULL, "set topic", do_set_topic); + remove_callback(NULL, "unload module", do_unload_module); + remove_callback(NULL, "load module", do_load_module); + unregister_messages(hybrid_messages); + return 1; +} + +/*************************************************************************/ diff -ruNx index -x langstrs.h ircservices-5.0a25/modules/protocol/invex.c ircservices-5.0a25+hy brid/modules/protocol/invex.c --- ircservices-5.0a25/modules/protocol/invex.c Thu Jan 1 01:00:00 1970 +++ ircservices-5.0a25+hybrid/modules/protocol/invex.c Sun Mar 24 03:43:57 2002 @@ -0,0 +1,182 @@ +/* Invite exception related functions. + * + * IRC Services is copyright (c) 1996-2002 Andrew Church. + * E-mail: + * Parts written by Andrew Kempe and others. + * This program is free but copyrighted software; see the file COPYING for + * details. + */ + +#include "services.h" +#include "modules.h" +#include "language.h" +#include "modules/chanserv/chanserv.h" + +#include "invex.h" + +/*************************************************************************/ + +static Module *module; +static Module *module_chanserv; + +static const char **p_s_ChanServ = NULL; /* we never use it if it's NULL */ +#define s_ChanServ (*p_s_ChanServ) + +/*************************************************************************/ +/*************************************************************************/ + +/* Callback to handle MODE +/-I. */ + +static int do_channel_mode(const char *source, Channel *chan, + int modechar, int add, char **av) +{ + if (modechar == 'I') { + if (add) { + if (chan->invexcount >= chan->invexsize) { + chan->invexsize += 8; + chan->invexs = srealloc(chan->invexs, + sizeof(char *) * chan->invexsize); + } + chan->invexs[chan->invexcount++] = sstrdup(av[0]); + } else { + char **s = chan->invexs; + int i = 0; + while (i < chan->invexcount && strcmp(*s, av[0]) != 0) { + i++; + s++; + } + if (i < chan->invexcount) { + chan->invexcount--; + if (i < chan->invexcount) + memmove(s, s+1, sizeof(char *)*(chan->invexcount-i)); + } else { + module_log("invex: MODE %s -e %s: invite exception not found", + chan->name, *av); + } + av++; + } + return 0; + } + return 0; +} + +/*************************************************************************/ + +/* Callback to handle clearing exceptions for clear_channel(). */ + +static void clear_invexs(const char *sender, Channel *chan, const User *u); +static int do_clear_channel(const char *sender, Channel *chan, int what, + const void *param) +{ + if (what & (CLEAR_USERS | CLEAR_BANS)) + clear_invexs(sender, chan, (what & CLEAR_BANS) ? param : NULL); + return 0; +} + + +static void clear_invexs(const char *sender, Channel *chan, const User *u) +{ + int i, count; + char **invexs; + + if (!chan->invexcount) + return; + count = chan->invexcount; + invexs = smalloc(sizeof(char *) * count); + memcpy(invexs, chan->invexs, sizeof(char *) * count); + for (i = 0; i < count; i++) { + if (!u || match_usermask(invexs[i], u)) + set_cmode(sender, chan, "-I", invexs[i]); + } + free(invexs); +} + +/*************************************************************************/ + +/* Callback to handle ChanServ CLEAR EXCEPTIONS. */ + +static int do_cs_clear(User *u, Channel *c, const char *what) +{ + if (stricmp(what, "INVEXS") == 0) { + clear_invexs(s_ChanServ, c, NULL); + set_cmode(NULL, c); + notice_lang(s_ChanServ, u, CHAN_CLEARED_INVEXS, c->name); + return 1; + } + return 0; +} + +/*************************************************************************/ +/*************************************************************************/ + +/* Callback to watch for modules being loaded. */ + +static int do_load_module(Module *mod, const char *name) +{ + if (strcmp(name, "chanserv/main") == 0) { + module_chanserv = mod; + p_s_ChanServ = get_module_symbol(mod, "s_ChanServ"); + if (p_s_ChanServ) { + if (!(add_callback(mod, "CLEAR", do_cs_clear))) + module_log("banexcept: Unable to add ChanServ CLEAR callback"); + } else { + module_log("invexs: Unable to resolve symbol `s_ChanServ' in" + " module `chanserv/main', CLEAR INVEXS will not" + " be available"); + } + } + return 0; +} + +/*************************************************************************/ + +/* Callback to watch for modules being unloaded. */ + +static int do_unload_module(Module *mod) +{ + if (mod == module_chanserv) { + p_s_ChanServ = NULL; + module_chanserv = NULL; + } + return 0; +} + +/*************************************************************************/ +/*************************************************************************/ + +static int old_CLEARMODES_DONE = -1; + +/*************************************************************************/ + +int init_invex(Module *module_) +{ + module = module_; + if (!add_callback(NULL, "channel MODE", do_channel_mode) + || !add_callback(NULL, "clear channel", do_clear_channel) + || !add_callback(NULL, "load module", do_load_module) + || !add_callback(NULL, "unload module", do_unload_module) + ) { + module_log("banexcept: Unable to add callbacks"); + exit_invex(); + return 0; + } + protocol_features |= PF_INVEX; + old_CLEARMODES_DONE = + setstring(OPER_CLEARMODES_DONE, OPER_CLEARMODES_EXCEPT_INVEX_DONE); + return 1; +} + +/*************************************************************************/ + +void exit_invex(void) +{ + if (old_CLEARMODES_DONE >= 0) + setstring(OPER_CLEARMODES_DONE, old_CLEARMODES_DONE); + old_CLEARMODES_DONE = -1; + remove_callback(NULL, "unload module", do_unload_module); + remove_callback(NULL, "load module", do_load_module); + remove_callback(NULL, "clear channel", do_clear_channel); + remove_callback(NULL, "channel MODE", do_channel_mode); +} + +/*************************************************************************/ diff -ruNx index -x langstrs.h ircservices-5.0a25/modules/protocol/invex.h ircservices-5.0a25+hy brid/modules/protocol/invex.h --- ircservices-5.0a25/modules/protocol/invex.h Thu Jan 1 01:00:00 1970 +++ ircservices-5.0a25+hybrid/modules/protocol/invex.h Sun Mar 24 03:26:47 2002 @@ -0,0 +1,16 @@ +/* banexcept.c header file. + * + * IRC Services is copyright (c) 1996-2002 Andrew Church. + * E-mail: + * Parts written by Andrew Kempe and others. + * This program is free but copyrighted software; see the file COPYING for + * details. + */ + +#ifndef INVEX_H +#define INVEX_H + +extern int init_invex(Module *module_); +extern void exit_invex(void); + +#endif diff -ruNx index -x langstrs.h ircservices-5.0a25/modules/protocol/sjoin.c ircservices-5.0a25+hy brid/modules/protocol/sjoin.c --- ircservices-5.0a25/modules/protocol/sjoin.c Tue Mar 19 02:16:20 2002 +++ ircservices-5.0a25+hybrid/modules/protocol/sjoin.c Sat Mar 23 10:26:05 2002 @@ -23,7 +23,7 @@ /*************************************************************************/ /* Handle an SJOIN command. - * Bahamut no-SSJOIN format: + * Bahamut no-SSJOIN format / Hybrid format: * av[0] = TS3 timestamp * av[1] = TS3 timestamp - channel creation time * av[2] = channel @@ -70,6 +70,9 @@ } while (*(nick=t)) { int32 modes = 0, thismode; + + while (*nick == ' ') + nick++; t = nick + strcspn(nick, " "); if (*t) diff -ruNx index -x langstrs.h ircservices-5.0a25/services.h ircservices-5.0a25+hybrid/services. h --- ircservices-5.0a25/services.h Tue Mar 19 02:16:18 2002 +++ ircservices-5.0a25+hybrid/services.h Sun Mar 24 03:44:25 2002 @@ -60,6 +60,7 @@ #define CLEAR_BANS 0x0002 /* Bans */ #define CLEAR_EXCEPTS 0x0004 /* Ban exceptions (no-op if not supported) */ #define CLEAR_UMODES 0x0008 /* User modes (+v, +o) */ +#define CLEAR_INVEXS 0x0010 /* Invite exceptions */ #define CLEAR_USERS 0x8000 /* Kick all users and empty the channel */ @@ -81,6 +82,8 @@ #define PF_SVSJOIN 0x00000020 /* Supports some method of forcibly changing a client's nickname */ #define PF_CHANGENICK 0x00000040 +/* Has Invite Exceptions (+I) */ +#define PF_INVEX 0x00000080 /*************************************************************************/ /*************************************************************************/ Binary files ircservices-5.0a25/tools/convert-db and ircservices-5.0a25+hybrid/tools/convert-db differ diff -ruNx index -x langstrs.h ircservices-5.0a25/version.sh ircservices-5.0a25+hybrid/version.s h --- ircservices-5.0a25/version.sh Tue Mar 19 02:11:13 2002 +++ ircservices-5.0a25+hybrid/version.sh Sat Mar 23 10:32:41 2002 @@ -3,7 +3,7 @@ # Build the version.c file which contains all the version related info and # needs to be updated on a per-build basis. -VERSION=5.0a25 +VERSION=5.0a25+hybrid # Increment Services build number if [ -f version.c ] ; then