diff -uNr ircservices-5.0.26/Changes ircservices-5.0.27/Changes --- ircservices-5.0.26/Changes 2003-11-26 23:22:42 +0900 +++ ircservices-5.0.27/Changes 2003-12-03 11:28:37 +0900 @@ -1,5 +1,20 @@ Version 5.0 ----------- +2003/12/03 .27 Fixed a stupid bug in the AKILLCHAN command causing corrupted + autokills. Reported by +2003/12/03 Various code cleanups and memory leak fixes. +2003/12/02 Fixed security loophole allowing users to obtain channel + privileges with a nickname awaiting authentication + after a SET EMAIL command. +2003/12/02 MEMCHECKS/SHOWALLOCS log messages now show the full path of + the calling file. +2003/12/02 Implemented "overwrite" option for XML import. +2003/12/01 Services no longer logs errors when receiving SZLINE + messages (using the Bahamut protocol). Reported by + +2003/11/30 Fixed crash on exit in FreeBSD. Reported by Chris Riley + +2003/11/30 Fixed memory corruption when unable to open initial log file. 2003/11/26 .26 Some configuration settings (such as FromAddress in mail/main) which were only checked for validity at startup are now also checked when rehashing the configuration files. @@ -25,6 +40,8 @@ 2003/11/18 .25 Fixed potential crashes when importing or exporting data via the command line. 2003/11/18 Fixed various memory leaks. +2003/11/17 When SHOWALLOCS is enabled, the file and line at which + memory was allocated or freed is now logged. 2003/11/15 Fixed bugs in the configure script when using a deprecated version of GCC. Reported by Matthew Hodgson diff -uNr ircservices-5.0.26/Makefile ircservices-5.0.27/Makefile --- ircservices-5.0.26/Makefile 2003-11-26 23:28:18 +0900 +++ ircservices-5.0.27/Makefile 2003-12-03 11:48:45 +0900 @@ -44,7 +44,7 @@ OBJS = actions.o channels.o commands.o compat.o conffile.o encrypt.o \ ignore.o init.o language.o log.o main.o memory.o messages.o misc.o \ modes.o modules.o process.o send.o servers.o signals.o sockets.o \ - timeout.o users.o $(VSNPRINTF_O) + suspinfo.o timeout.o users.o $(VSNPRINTF_O) .c.o: $(CC) $(CFLAGS) -c $< -o $@ @@ -154,6 +154,7 @@ servers.o: servers.c modules.h hash.h signals.o: signals.c sockets.o: sockets.c +suspinfo.o: suspinfo.c timeout.o: timeout.c timeout.h users.o: users.c modules.h hash.h vsnprintf.o: vsnprintf.c diff -uNr ircservices-5.0.26/actions.c ircservices-5.0.27/actions.c --- ircservices-5.0.26/actions.c 2003-11-26 23:28:18 +0900 +++ ircservices-5.0.27/actions.c 2003-12-03 11:48:45 +0900 @@ -148,6 +148,16 @@ for (i = 0; i < count; i++) { if (!u || match_usermask(bans[i], u)) set_cmode(sender, chan, "-b", bans[i]); + if (u && u->ipaddr) { + char tmpbuf[BUFSIZE]; + int nicklen = snprintf(tmpbuf, sizeof(tmpbuf), "%s!", u->nick); + snprintf(tmpbuf+nicklen, sizeof(tmpbuf)-nicklen, "%s@%s", + u->username, u->ipaddr); + if (match_wild_nocase(bans[i], tmpbuf)) + set_cmode(sender, chan, "-b", bans[i]); + if (match_wild_nocase(bans[i], tmpbuf+nicklen)) + set_cmode(sender, chan, "-b", bans[i]); + } } free(bans); } @@ -420,12 +430,12 @@ continue; } } + params = (params >> (add*8)) & 0xFF; if (params) { /* Mode with parameters */ char parambuf[BUFSIZE]; /* for putting the parameters in */ int len = 0; - params = (params >> (add*8)) & 0xFF; if (params > MAXMODES) { /* Sanity check */ fatal("set_cmode(): too many parameters (%d) for mode `%c'\n", diff -uNr ircservices-5.0.26/conffile.c ircservices-5.0.27/conffile.c --- ircservices-5.0.26/conffile.c 2003-11-26 23:28:18 +0900 +++ ircservices-5.0.27/conffile.c 2003-12-03 11:48:45 +0900 @@ -161,7 +161,7 @@ s++; while (*s && *s != '"') { if (*s == '\\' && s[1] != 0) - memmove(s, s+1, strlen(s+1)+1); + strmove(s, s+1); s++; } if (!*s) diff -uNr ircservices-5.0.26/data/example-modules.conf ircservices-5.0.27/data/example-modules.conf --- ircservices-5.0.26/data/example-modules.conf 2003-11-26 23:28:18 +0900 +++ ircservices-5.0.27/data/example-modules.conf 2003-12-03 11:48:44 +0900 @@ -26,7 +26,7 @@ #NetworkDomain "example.net" # CSSetChannelTime [OPTIONAL] - # Protocols: bahamut, monkey, unreal + # Protocols: bahamut, monkey, trircd, unreal # # When enabled, causes Services to set the "creation time" (the # time at which the first user joined the channel) of a registered @@ -1460,9 +1460,18 @@ # import is already registered. The string must be one of either # "skipgroup" (skip over the nickname group containing the nickname # in the imported data), "skipnick" (skip only the colliding - # nickname), or "abort" (do not import any data). Note that when - # "abort" is selected, the entire XML input is still checked for - # errors, but Services will abort before actually merging any data. + # nickname), "overwrite" (drop the existing nickname), or "abort" + # (do not import any data). Note that when "abort" is selected, + # the entire XML input is still checked for errors, but Services + # will abort before actually merging any data. + # + # When using "overwrite", if a nickname group has only one nickname + # and that nickname is overwritten, the nickname group will be + # dropped as well. As a consequence, any channels owned by such a + # nickname will be dropped (or shifted to their successors) as + # well. All nicknames and channels overwritten or droppde in this + # manner will be displayed on standard error. + # # If not specified, defaults to "skipgroup". #OnNicknameCollision skipgroup @@ -1470,11 +1479,11 @@ # OnChannelCollision [OPTIONAL] # Specifies the action to be taken when a channel in the data to # import is already registered. The string must be one of either - # "skip" (skip over the channel in the imported data) or "abort" - # (do not import any data). Note that when "abort" is selected, - # the entire XML input is still checked for errors, but Services - # will abort before actually merging any data. If not specified, - # defaults to "skip". + # "skip" (skip over the channel in the imported data), "overwrite" + # (drop the existing channel), or "abort" (do not import any data). + # Note that when "abort" is selected, the entire XML input is still + # checked for errors, but Services will abort before actually + # merging any data. If not specified, defaults to "skip". #OnChannelCollision skip diff -uNr ircservices-5.0.26/docs/6.html ircservices-5.0.27/docs/6.html --- ircservices-5.0.26/docs/6.html 2003-10-20 16:20:42 +0900 +++ ircservices-5.0.27/docs/6.html 2003-12-01 13:48:06 +0900 @@ -52,14 +52,14 @@

6-1-1. Overview

Services modules are based on, and in fact use the same system as, -standard dynamic-link libraries. Upon startup, -Services will load a given module into memory and execute its -initialization function. This function should set up any data structures -necessary and register all callback functions needed (see below). At -shutdown, its -cleanup function will be called, which should free all resources in use and -perform other necessary cleanup functions, or return an error if the module -cannot unload itself for some reason. +standard dynamic-link libraries. Upon startup or reloading of the +configuration file, Services will load specified modules into memory and +execute each module's initialization function. This function should set up +any data structures necessary and register all callback functions needed +(see below). At shutdown, or when the module is otherwise unloaded, its +cleanup function will be called; this function should free all resources in +use and perform other necessary cleanup functions, or return an error if +the module cannot unload itself for some reason.

Module interaction with Services takes place primarily through the use of callbacks. These are functions which the module registers with Services @@ -924,8 +924,17 @@
Parameters: char *source, char *cmd, int ac, char **av

Called for every message received from the uplink server. The - callback routine should return 1 if it processes the message, - 0 otherwise. + callback routine should return 1 if it processes the message, 0 + otherwise. Note that it is acceptable for a callback routine to + modify the parameters passed and return 0 to allow the next routine + to continue, subject to the following constraints: +
    +
  • The number of message parameters (ac) is not + changed. +
  • None of the strings (source, cmd, + or any element of av) are lengthened. + (Shortening strings is allowed.) +

reconfigure diff -uNr ircservices-5.0.26/docs/a.html ircservices-5.0.27/docs/a.html --- ircservices-5.0.26/docs/a.html 2003-11-25 16:34:24 +0900 +++ ircservices-5.0.27/docs/a.html 2003-12-03 11:31:51 +0900 @@ -604,7 +604,7 @@

  • CSSetChannelTime    [OPTIONAL] -

    Protocols: bahamut, monkey, unreal +

    Protocols: bahamut, monkey, trircd, unreal

    When enabled, causes Services to set the "creation time" (the time at which the first user joined the channel) of a registered @@ -2344,10 +2344,19 @@ import is already registered. The string must be one of either "skipgroup" (skip over the nickname group containing the nickname in the imported data), "skipnick" (skip only the colliding -nickname), or "abort" (do not import any data). Note that when -"abort" is selected, the entire XML input is still checked for -errors, but Services will abort before actually merging any data. -If not specified, defaults to "skipgroup". +nickname), "overwrite" (drop the existing nickname), or "abort" +(do not import any data). Note that when "abort" is selected, +the entire XML input is still checked for errors, but Services +will abort before actually merging any data. + +

    When using "overwrite", if a nickname group has only one nickname +and that nickname is overwritten, the nickname group will be +dropped as well. As a consequence, any channels owned by such a +nickname will be dropped (or shifted to their successors) as +well. All nicknames and channels overwritten or droppde in this +manner will be displayed on standard error. + +

    If not specified, defaults to "skipgroup".

    Example: OnNicknameCollision skipgroup

@@ -2357,11 +2366,11 @@ OnChannelCollision action    [OPTIONAL]

Specifies the action to be taken when a channel in the data to import is already registered. The string must be one of either -"skip" (skip over the channel in the imported data) or "abort" -(do not import any data). Note that when "abort" is selected, -the entire XML input is still checked for errors, but Services -will abort before actually merging any data. If not specified, -defaults to "skip". +"skip" (skip over the channel in the imported data), "overwrite" +(drop the existing channel), or "abort" (do not import any data). +Note that when "abort" is selected, the entire XML input is still +checked for errors, but Services will abort before actually +merging any data. If not specified, defaults to "skip".

Example: OnChannelCollision skip diff -uNr ircservices-5.0.26/extern.h ircservices-5.0.27/extern.h --- ircservices-5.0.26/extern.h 2003-11-26 23:28:18 +0900 +++ ircservices-5.0.27/extern.h 2003-12-03 11:48:45 +0900 @@ -199,6 +199,7 @@ E int irc_stricmp(const char *s1, const char *s2); E int irc_strnicmp(const char *s1, const char *s2, int max); E char *strscpy(char *d, const char *s, size_t len); +E char *strmove(char *d, char *s); E char *stristr(const char *s1, const char *s2); E char *strupper(char *s); E char *strlower(char *s); @@ -308,6 +309,12 @@ E void disable_signals(void); +/**** suspinfo.c ****/ + +E SuspendInfo *new_suspendinfo(const char *who, char *reason, time_t expires); +E void free_suspendinfo(SuspendInfo *si); + + /**** users.c ****/ E int32 usercnt, opcnt, maxusercnt; diff -uNr ircservices-5.0.26/lang/tr.l ircservices-5.0.27/lang/tr.l --- ircservices-5.0.26/lang/tr.l 2003-11-25 19:37:40 +0900 +++ ircservices-5.0.27/lang/tr.l 2003-11-29 14:19:17 +0900 @@ -263,7 +263,7 @@ NICK_REG_PLEASE_WAIT Lütfen %s bekleyerek yeniden deneyiniz. NICK_REG_PLEASE_WAIT_FIRST - Lütfen %d bekledikten sonra REGISTER komutunu tekrar + Lütfen %s bekledikten sonra REGISTER komutunu tekrar kullaniniz. NICK_CANNOT_BE_REGISTERED %s nick'i kaydedilemez. diff -uNr ircservices-5.0.26/language.c ircservices-5.0.27/language.c --- ircservices-5.0.26/language.c 2003-11-26 23:28:18 +0900 +++ ircservices-5.0.27/language.c 2003-12-03 11:48:45 +0900 @@ -311,7 +311,7 @@ char *end = s+2; while (s > tmpbuf && s[-1] == ' ') s--; - memmove(s, end, strlen(end)+1); + strmove(s, end); } } else { tm = localtime(&time); diff -uNr ircservices-5.0.26/log.c ircservices-5.0.27/log.c --- ircservices-5.0.26/log.c 2003-11-26 23:28:18 +0900 +++ ircservices-5.0.27/log.c 2003-12-03 11:48:45 +0900 @@ -106,10 +106,12 @@ if (len > LOGMEMSIZE - (logmemptr-logmem)) { int oldlen = len; len = LOGMEMSIZE - (logmemptr-logmem); - if (tmpbuf[oldlen-1] == '\n') { - tmpbuf[len-1] = '\n'; /* always end with a newline */ - } else { - len--; + if (len > 0) { + if (tmpbuf[oldlen-1] == '\n') { + tmpbuf[len-1] = '\n'; /* always end with a newline */ + } else { + len--; + } } } if (len > 0) { diff -uNr ircservices-5.0.26/memory.c ircservices-5.0.27/memory.c --- ircservices-5.0.26/memory.c 2003-11-26 23:28:18 +0900 +++ ircservices-5.0.27/memory.c 2003-12-03 11:48:45 +0900 @@ -162,16 +162,18 @@ mb->data = (void *)((char *)(mb) + sizeof(MemBlock)); allocated += size; # ifdef SHOWALLOCS - if (showallocs) + if (showallocs) { log("smalloc(): Allocated %ld bytes at %p (%s:%d)", size, mb->data, file, line); + } # endif return mb->data; } else { # ifdef SHOWALLOCS - if (showallocs) + if (showallocs) { log("mcalloc(): Unable to allocate %ld bytes (%s:%d)", size, file, line); + } # endif return NULL; } @@ -193,16 +195,18 @@ memset(mb->data, 0, elsize * els); allocated += mb->size; # ifdef SHOWALLOCS - if (showallocs) + if (showallocs) { log("scalloc(): Allocated %ld bytes at %p (%s:%d)", els*elsize, mb->data, file, line); + } # endif return mb->data; } else { # ifdef SHOWALLOCS - if (showallocs) + if (showallocs) { log("scalloc(): Unable to allocate %ld bytes (%s:%d)", els*elsize, file, line); + } # endif return NULL; } @@ -225,9 +229,10 @@ if (oldptr == NULL) return MCmalloc(newsize, file, line); oldb = (MemBlock *)((char *)(oldptr) - sizeof(MemBlock)); - if (oldb->sig != SIGNATURE) + if (oldb->sig != SIGNATURE) { fatal("Attempt to realloc() an invalid pointer (%p) (%s:%d)", oldptr, file, line); + } # ifdef SHOWALLOCS olddata = oldb->data; # endif @@ -266,14 +271,16 @@ if (ptr == NULL) return; mb = (MemBlock *)((char *)(ptr) - sizeof(MemBlock)); - if (mb->sig != SIGNATURE) + if (mb->sig != SIGNATURE) { fatal("Attempt to free() an invalid pointer (%p) (%s:%d)", ptr, file, line); + } allocated -= mb->size; # ifdef SHOWALLOCS - if (showallocs) + if (showallocs) { log("sfree(): Released %ld bytes at %p (%s:%d)", mb->size, mb->data, file, line); + } # endif mb->sig = FREE_SIGNATURE; free(mb); diff -uNr ircservices-5.0.26/misc.c ircservices-5.0.27/misc.c --- ircservices-5.0.26/misc.c 2003-11-26 23:28:18 +0900 +++ ircservices-5.0.27/misc.c 2003-12-03 11:48:45 +0900 @@ -122,6 +122,18 @@ /*************************************************************************/ +/* strmove: Like strcpy(), but handles overlapping regions of memory + * properly. The str*() analog of memmove(). + */ + +char *strmove(char *d, char *s) +{ + memmove(d, s, strlen(s)+1); + return d; +} + +/*************************************************************************/ + /* stristr: Search case-insensitively for string s2 within string s1, * returning the first occurrence of s2 or NULL if s2 was not * found. diff -uNr ircservices-5.0.26/modules/Makerules ircservices-5.0.27/modules/Makerules --- ircservices-5.0.26/modules/Makerules 2003-07-09 16:16:20 +0900 +++ ircservices-5.0.27/modules/Makerules 2003-12-03 11:45:30 +0900 @@ -164,7 +164,7 @@ $(TARGET).o: .compiled-$(TARGET).o FRC @echo >/dev/null .compiled-$(TARGET).o: $(TARGET).c $(DEPS) $(INCLUDES2) - $(CC) $(CFLAGS) -I$(TOPDIR) -c $< -o $(TARGET).o + cd $(TOPDIR) && $(CC) $(CFLAGS) -I. -c modules/$(DIRNAME)/$< -o modules/$(DIRNAME)/$(TARGET).o @rm -f $@ @ln -s $(TARGET).o $@ @@ -176,8 +176,8 @@ .compiled-$(TARGET)_static.o: $(TARGET).c $(DEPS) $(INCLUDES2) @MODNAME=`echo $(DIRNAME)_$(TARGET) | sed -e 'y/-/_/' -e 's/_$$//'` ; \ DEFS="-Dmodule_version=module_version_$$MODNAME -Dmodule_config=module_config_$$MODNAME -Dinit_module=init_module_$$MODNAME -Dexit_module=exit_module_$$MODNAME" ; \ - echo "$(CC) $(CFLAGS) -I$(TOPDIR) $$DEFS -c $< -o $(TARGET)_static.o" ; \ - $(CC) $(CFLAGS) -I$(TOPDIR) $$DEFS -c $< -o $(TARGET)_static.o + echo "cd $(TOPDIR) && $(CC) $(CFLAGS) -I. $$DEFS -c modules/$(DIRNAME)/$< -o modules/$(DIRNAME)/$(TARGET)_static.o" ; \ + cd $(TOPDIR) && $(CC) $(CFLAGS) -I. $$DEFS -c modules/$(DIRNAME)/$< -o modules/$(DIRNAME)/$(TARGET)_static.o @touch $@ endif # REALLY_COMPILE == 2 diff -uNr ircservices-5.0.26/modules/chanserv/access.c ircservices-5.0.27/modules/chanserv/access.c --- ircservices-5.0.26/modules/chanserv/access.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/chanserv/access.c 2003-12-03 11:48:46 +0900 @@ -28,15 +28,15 @@ LevelInfo levelinfo[] = { /* Dummy entry for channel owner; flags filled in by init_access */ { CA_AUTOOWNER, ACCLEV_FOUNDER, "", -1, - CL_SET_MODE, { cumode: {"", 1} } }, /* FIXME: `field:' gcc-ism */ + CL_SET_MODE, { .cumode = {"", 1} } }, { CA_AUTOPROTECT, ACCLEV_SOP, "AUTOPROTECT", CHAN_LEVEL_AUTOPROTECT, - CL_SET_MODE, { cumode: {"a",0} } }, + CL_SET_MODE, { .cumode = {"a",0} } }, { CA_AUTOOP, ACCLEV_AOP, "AUTOOP", CHAN_LEVEL_AUTOOP, - CL_SET_MODE, { cumode: {"o",1} } }, + CL_SET_MODE, { .cumode = {"o",1} } }, { CA_AUTOHALFOP, ACCLEV_HOP, "AUTOHALFOP", CHAN_LEVEL_AUTOHALFOP, - CL_SET_MODE, { cumode: {"h",1} } }, + CL_SET_MODE, { .cumode = {"h",1} } }, { CA_AUTOVOICE, ACCLEV_VOP, "AUTOVOICE", CHAN_LEVEL_AUTOVOICE, - CL_SET_MODE, { cumode: {"v",0} } }, + CL_SET_MODE, { .cumode = {"v",0} } }, /* Internal use; not settable by users. These two levels change based * on the SECUREOPS and RESTRICTED settings. */ diff -uNr ircservices-5.0.26/modules/chanserv/chanserv.h ircservices-5.0.27/modules/chanserv/chanserv.h --- ircservices-5.0.26/modules/chanserv/chanserv.h 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/chanserv/chanserv.h 2003-12-03 11:48:46 +0900 @@ -190,7 +190,14 @@ E char *s_ChanServ; E int32 CSMaxReg; -E void free_channelinfo(ChannelInfo *ci); +#ifdef STANDALONE_CHANSERV /* see util.c */ +# define E2 static +#else +# define E2 extern +#endif +E2 ChannelInfo *new_channelinfo(void); +E2 void free_channelinfo(ChannelInfo *ci); +#undef E2 E int check_expire_channel(ChannelInfo *ci); E int check_access(User *user, ChannelInfo *ci, int what); E int check_access_if_idented(User *user, ChannelInfo *ci, int what); diff -uNr ircservices-5.0.26/modules/chanserv/util.c ircservices-5.0.27/modules/chanserv/util.c --- ircservices-5.0.26/modules/chanserv/util.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/chanserv/util.c 2003-12-03 11:48:46 +0900 @@ -7,58 +7,98 @@ * details. */ -#include "services.h" -#include "modules.h" -#include "language.h" -#include "modules/nickserv/nickserv.h" +/* If STANDALONE_CHANSERV is defined when compiling this file, the + * following routines will be defined as `static' for use in other + * modules/programs: + * new_channelinfo() + * free_channelinfo() + * This file should be #include'd in the file making use of the routines. + */ + +#ifdef STANDALONE_CHANSERV + +# define STANDALONE_STATIC static +# undef EXPORT_FUNC +# define EXPORT_FUNC(x) /*nothing*/ + +#else + +# define STANDALONE_STATIC /*nothing*/ + +# include "services.h" +# include "modules.h" +# include "language.h" +# include "modules/nickserv/nickserv.h" -#include "chanserv.h" -#include "cs-local.h" +# include "chanserv.h" +# include "cs-local.h" + +#endif /*************************************************************************/ +#ifndef STANDALONE_CHANSERV + static Module *module; +#endif + /*************************************************************************/ /************************ Global utility routines ************************/ /*************************************************************************/ +/* Allocate and initialize a new ChannelInfo structure. */ + +EXPORT_FUNC(new_channelinfo) +STANDALONE_STATIC ChannelInfo *new_channelinfo(void) +{ + ChannelInfo *ci = scalloc(sizeof(ChannelInfo), 1); + ci->memos.memomax = MEMOMAX_DEFAULT; + return ci; +} + +/*************************************************************************/ + /* Free a ChannelInfo structure and all associated data. */ EXPORT_FUNC(free_channelinfo) -void free_channelinfo(ChannelInfo *ci) +STANDALONE_STATIC void free_channelinfo(ChannelInfo *ci) { int i; - free(ci->desc); - free(ci->url); - free(ci->email); - free(ci->last_topic); - if (ci->suspendinfo) { - free(ci->suspendinfo->reason); - free(ci->suspendinfo); - } - free(ci->levels); - free(ci->access); - ARRAY_FOREACH (i, ci->akick) { - free(ci->akick[i].mask); - free(ci->akick[i].reason); - } - free(ci->akick); - free(ci->mlock_key); - free(ci->mlock_link); - free(ci->mlock_flood); - free(ci->entry_message); - if (ci->memos.memos) { - ARRAY_FOREACH (i, ci->memos.memos) - free(ci->memos.memos[i].text); - free(ci->memos.memos); - } - free(ci); + if (ci) { + free(ci->desc); + free(ci->url); + free(ci->email); + free(ci->last_topic); + if (ci->suspendinfo) + free_suspendinfo(ci->suspendinfo); + free(ci->levels); + free(ci->access); + ARRAY_FOREACH (i, ci->akick) { + free(ci->akick[i].mask); + free(ci->akick[i].reason); + } + free(ci->akick); + free(ci->mlock_key); + free(ci->mlock_link); + free(ci->mlock_flood); + free(ci->entry_message); + if (ci->memos.memos) { + ARRAY_FOREACH (i, ci->memos.memos) + free(ci->memos.memos[i].text); + free(ci->memos.memos); + } + free(ci); + } /* if (ci) */ } /*************************************************************************/ +#ifndef STANDALONE_CHANSERV /* to the end of the file */ + +/*************************************************************************/ + /* Check whether the given channel (or its suspension) should be expired, * and do the expiration if so. Return 1 if the nickname was deleted, else 0. */ @@ -296,13 +336,7 @@ void suspend_channel(ChannelInfo *ci, const char *reason, const char *who, const time_t expires) { - SuspendInfo *si; - - si = scalloc(sizeof(*si), 1); - strscpy(si->who, who, NICKMAX); - si->reason = sstrdup(reason); - si->suspended = time(NULL); - si->expires = expires; + SuspendInfo *si = new_suspendinfo(who, sstrdup(reason), expires); ci->suspendinfo = si; put_channelinfo(ci); } @@ -324,8 +358,7 @@ ci->name); return; } - free(ci->suspendinfo->reason); - free(ci->suspendinfo); + free_suspendinfo(ci->suspendinfo); ci->suspendinfo = NULL; if (set_time && CSExpire && CSSuspendGrace && (now - ci->last_used >= CSExpire - CSSuspendGrace) @@ -417,3 +450,5 @@ } /*************************************************************************/ + +#endif /* !STANDALONE_CHANSERV */ diff -uNr ircservices-5.0.26/modules/database/extsyms.c ircservices-5.0.27/modules/database/extsyms.c --- ircservices-5.0.26/modules/database/extsyms.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/database/extsyms.c 2003-12-03 11:48:46 +0900 @@ -182,10 +182,7 @@ IMPORT_FUNC("nickserv/main", module_nickserv, _get_ngi); IMPORT_FUNC("nickserv/main", module_nickserv, _get_ngi_id); -IMPORT_FUNC("nickserv/main", module_nickserv, free_nickinfo); -IMPORT_FUNC("nickserv/main", module_nickserv, free_nickgroupinfo); IMPORT_FUNC("nickserv/main", module_nickserv, check_expire_nick); -IMPORT_FUNC("chanserv/main", module_chanserv, free_channelinfo); IMPORT_FUNC("chanserv/main", module_chanserv, check_expire_channel); IMPORT_FUNC("chanserv/main", module_chanserv, reset_levels); IMPORT_FUNC("operserv/main", module_operserv, check_expire_maskdata); @@ -201,12 +198,9 @@ module_nickserv = NULL; __dblocal__get_ngi = (void *) __dblocal__get_ngi_stub; __dblocal__get_ngi_id = (void *) __dblocal__get_ngi_id_stub; - __dblocal_free_nickinfo = (void *) __dblocal_free_nickinfo_stub; - __dblocal_free_nickgroupinfo = (void *) __dblocal_free_nickgroupinfo_stub; } else if (mod == module_chanserv) { module_chanserv = NULL; __dblocal_CSMaxReg_ptr = NULL; - __dblocal_free_channelinfo = (void *) __dblocal_free_channelinfo_stub; __dblocal_reset_levels = (void *) __dblocal_reset_levels_stub; } else if (mod == module_memoserv) { module_memoserv = NULL; diff -uNr ircservices-5.0.26/modules/database/extsyms.h ircservices-5.0.27/modules/database/extsyms.h --- ircservices-5.0.26/modules/database/extsyms.h 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/database/extsyms.h 2003-12-03 11:48:46 +0900 @@ -17,7 +17,6 @@ #include "modules/operserv/maskdata.h" #include "modules/statserv/statserv.h" -/* FIXME: this is very GCCish */ #define DEFINE_LOCAL_VAR(sym) extern typeof(sym) __dblocal_get_##sym(void) #define DEFINE_LOCAL_FUNC(sym) extern typeof(sym) *__dblocal_##sym @@ -25,10 +24,7 @@ DEFINE_LOCAL_VAR(MSMaxMemos); DEFINE_LOCAL_FUNC(_get_ngi); DEFINE_LOCAL_FUNC(_get_ngi_id); -DEFINE_LOCAL_FUNC(free_nickinfo); -DEFINE_LOCAL_FUNC(free_nickgroupinfo); DEFINE_LOCAL_FUNC(check_expire_nick); -DEFINE_LOCAL_FUNC(free_channelinfo); DEFINE_LOCAL_FUNC(check_expire_channel); DEFINE_LOCAL_FUNC(reset_levels); DEFINE_LOCAL_FUNC(check_expire_maskdata); @@ -40,10 +36,7 @@ # define MSMaxMemos ((*__dblocal_get_MSMaxMemos)()) # define _get_ngi (*__dblocal__get_ngi) # define _get_ngi_id (*__dblocal__get_ngi_id) -# define free_nickinfo (*__dblocal_free_nickinfo) -# define free_nickgroupinfo (*__dblocal_free_nickgroupinfo) # define check_expire_nick (*__dblocal_check_expire_nick) -# define free_channelinfo (*__dblocal_free_channelinfo) # define check_expire_channel (*__dblocal_check_expire_channel) # define reset_levels (*__dblocal_reset_levels) # define check_expire_maskdata (*__dblocal_check_expire_maskdata) diff -uNr ircservices-5.0.26/modules/database/version4.c ircservices-5.0.27/modules/database/version4.c --- ircservices-5.0.26/modules/database/version4.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/database/version4.c 2003-12-03 11:48:46 +0900 @@ -14,6 +14,9 @@ #include "encrypt.h" #include "hash.h" #include "language.h" + +#define STANDALONE_NICKSERV +#define STANDALONE_CHANSERV #include "modules/nickserv/nickserv.h" #include "modules/chanserv/chanserv.h" #include "modules/memoserv/memoserv.h" @@ -25,6 +28,10 @@ #include "modules/operserv/sline.h" #include "modules/statserv/statserv.h" +/* New/free functions */ +#include "modules/nickserv/util.c" +#include "modules/chanserv/util.c" + #include "extsyms.h" #include "fileutil.h" @@ -195,7 +202,7 @@ char passbuf[PASSMAX]; char *url, *email; - ni = scalloc(sizeof(NickInfo), 1); + ni = new_nickinfo(); SAFE(read_buffer(ni->nick, f)); if (debug >= 2) module_log("debug: loading nick %s", ni->nick); @@ -226,7 +233,7 @@ free(url); free(email); } else { - ngi = scalloc(sizeof(NickGroupInfo), 1); + ngi = new_nickgroupinfo(NULL); ngi->id = next_id++; ARRAY_EXTEND(ngi->nicks); strscpy(ngi->nicks[0], ni->nick, NICKMAX); @@ -859,7 +866,7 @@ int i; int is_default; /* Are all access levels at defaults? */ - ci = scalloc(sizeof(ChannelInfo), 1); + ci = new_channelinfo(); SAFE(read_buffer(ci->name, f)); if (debug >= 2) module_log("debug: loading channel %s", ci->name); diff -uNr ircservices-5.0.26/modules/httpd/main.c ircservices-5.0.27/modules/httpd/main.c --- ircservices-5.0.26/modules/httpd/main.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/httpd/main.c 2003-12-03 11:48:46 +0900 @@ -244,7 +244,7 @@ * the hostname and just pretend it's us) */ s = strchr(url+7, '/'); if (s) { - memmove(url, s, strlen(s)+1); + strmove(url, s); } else { url[0] = '/'; url[1] = 0; @@ -457,7 +457,7 @@ s = linestart; while (*s == ' ' || *s == '\t') s++; - memmove(linestart, s, strlen(s)+1); + strmove(linestart, s); c->request_len -= s-linestart; } else { /* New header: split into name and value, and create a new @@ -474,7 +474,7 @@ linestart = s; while (*s == ' ' || *s == '\t') s++; - memmove(linestart, s, strlen(s)+1); + strmove(linestart, s); c->request_len -= s - linestart; } } @@ -571,21 +571,30 @@ if (*s == '\r') *s++ = 0; *s++ = 0; - /* FIXME: This should probably be made more robust */ - if (strnicmp(buf,"Content-Disposition: form-data; name=",37) == 0){ - buf += 37; - if (*buf == '"') { - char *t = strchr(++buf, '"'); - if (t) - *t = 0; - } else { - char *t = strchr(buf, ';'); - if (t) - *t = 0; + if (strnicmp(buf,"Content-Disposition:",20) == 0) { + buf += 20; + while (*buf && isspace(*buf)) + buf++; + if (*buf && strnicmp(buf,"form-data;",10) == 0) { + buf += 10; + while (*buf && isspace(*buf)) + buf++; + if (*buf && strnicmp(buf,"name=",5) == 0) { + buf += 5; + if (*buf == '"') { + char *t = strchr(++buf, '"'); + if (t) + *t = 0; + } else { + char *t = strchr(buf, ';'); + if (t) + *t = 0; + } + varname = dest; + strmove(dest, buf); + dest += strlen(buf)+1; + } } - varname = dest; - memmove(dest, buf, strlen(buf)+1); - dest += strlen(buf)+1; } buf = s; } /* while (*buf != '\r' && *buf != '\n') */ diff -uNr ircservices-5.0.26/modules/memoserv/main.c ircservices-5.0.27/modules/memoserv/main.c --- ircservices-5.0.26/modules/memoserv/main.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/memoserv/main.c 2003-12-03 11:48:46 +0900 @@ -764,9 +764,6 @@ } /* if (MSNotifyAll) */ } /* if (flags & MEMO_RECEIVE) */ } /* if (!ischan) */ - /* FIXME: this looks dangerous... maybe we should have magic - * numbers in structures? (re: what a structure really is vs. - * what routine it's passed to) */ if (ischan) put_channelinfo(owner); else diff -uNr ircservices-5.0.26/modules/misc/Makefile ircservices-5.0.27/modules/misc/Makefile --- ircservices-5.0.26/modules/misc/Makefile 2003-11-26 23:28:18 +0900 +++ ircservices-5.0.27/modules/misc/Makefile 2003-12-03 11:48:45 +0900 @@ -14,7 +14,9 @@ INCLUDES-helpserv.o = $(TOPDIR)/language.h INCLUDES-xml-export.o = $(XML_INCLUDES) -INCLUDES-xml-import.o = $(XML_INCLUDES) +INCLUDES-xml-import.o = $(XML_INCLUDES) \ + $(TOPDIR)/modules/nickserv/util.c \ + $(TOPDIR)/modules/chanserv/util.c include ../Makerules diff -uNr ircservices-5.0.26/modules/misc/xml-import.c ircservices-5.0.27/modules/misc/xml-import.c --- ircservices-5.0.26/modules/misc/xml-import.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/misc/xml-import.c 2003-12-03 11:48:46 +0900 @@ -12,6 +12,12 @@ #include "modules.h" #include "language.h" #include "conffile.h" + +/* We include new_xxx() and free_xxx() routines in here directly, so we + * need to make sure the appropriate preprocessor symbols are defined here + * to avoid static/non-static warnings. */ +#define STANDALONE_NICKSERV +#define STANDALONE_CHANSERV #include "modules/nickserv/nickserv.h" #include "modules/chanserv/chanserv.h" #include "modules/memoserv/memoserv.h" @@ -28,8 +34,6 @@ * misleading: the parser will continue to parse to the end of the file * even if an `abort' condition is encountered, but will not actually merge * the read-in data with the current databases in such a case. - * - * Note: overwriting is not yet supported. */ /* Behavior for nickname collisions: default is to skip the entire nickname @@ -252,99 +256,36 @@ }; /*************************************************************************/ -/************** Utility routines (copied from other modules **************/ -/*************************************************************************/ - -/* The NickServ/ChanServ/etc. modules may not be loaded at this point, so - * we need to have the freeing routines locally. */ - +/***************************** Error output ******************************/ /*************************************************************************/ -/* Free a NickGroupInfo structure and all associated data. */ +/* Write the given error message, along with a line number. The message + * will be truncated at 4095 bytes if it exceeds that length. + */ -static void my_free_nickgroupinfo(NickGroupInfo *ngi) +static void error(const char *fmt, ...) FORMAT(printf,1,2); +static void error(const char *fmt, ...) { - int i; + char buf[4096]; + va_list args; - free(ngi->url); - free(ngi->email); - if (ngi->suspendinfo) { - free(ngi->suspendinfo->reason); - free(ngi->suspendinfo); - } - free(ngi->nicks); - ARRAY_FOREACH (i, ngi->access) - free(ngi->access[i]); - free(ngi->access); - free(ngi->channels); - ARRAY_FOREACH (i, ngi->memos.memos) - free(ngi->memos.memos[i].text); - free(ngi->memos.memos); - ARRAY_FOREACH (i, ngi->ignore) - free(ngi->ignore[i]); - free(ngi->ignore); - ARRAY_FOREACH (i, ngi->id_users) { - User *u = ngi->id_users[i]; - int j; - ARRAY_SEARCH_PLAIN_SCALAR(u->id_nicks, ngi->id, j); - if (j < u->id_nicks_count) { - ARRAY_REMOVE(u->id_nicks, j); - } else { - module_log("BUG: free_nickgroupinfo(): user %p (%s) listed in" - " id_users for nickgroup %u, but nickgroup not in" - " id_nicks!", u, u->nick, ngi->id); - } - } - free(ngi); + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + fprintf(stderr, "Line %d: %s\n", lines_read, buf); } /*************************************************************************/ - -/* Free a NickInfo structure and all associated data. */ - -static void my_free_nickinfo(NickInfo *ni) -{ - free(ni->last_usermask); - free(ni->last_realmask); - free(ni->last_realname); - free(ni->last_quit); - free(ni); -} - +/************** Utility routines (taken from other modules) **************/ /*************************************************************************/ -/* Free a ChannelInfo structure and all associated data. */ +/* The NickServ/ChanServ/etc. modules may not be loaded at this point, so + * we need to have the freeing routines locally. */ -static void my_free_channelinfo(ChannelInfo *ci) -{ - int i; +/*************************************************************************/ - free(ci->desc); - free(ci->url); - free(ci->email); - free(ci->last_topic); - if (ci->suspendinfo) { - free(ci->suspendinfo->reason); - free(ci->suspendinfo); - } - free(ci->levels); - free(ci->access); - ARRAY_FOREACH (i, ci->akick) { - free(ci->akick[i].mask); - free(ci->akick[i].reason); - } - free(ci->akick); - free(ci->mlock_key); - free(ci->mlock_link); - free(ci->mlock_flood); - free(ci->entry_message); - if (ci->memos.memos) { - ARRAY_FOREACH (i, ci->memos.memos) - free(ci->memos.memos[i].text); - free(ci->memos.memos); - } - free(ci); -} +#include "modules/nickserv/util.c" +#include "modules/chanserv/util.c" /*************************************************************************/ @@ -379,23 +320,63 @@ } /*************************************************************************/ -/***************************** Error output ******************************/ -/*************************************************************************/ -/* Write the given error message, along with a line number. The message - * will be truncated at 4095 bytes if it exceeds that length. +/* Unlink and free a nickname, and remove it from its associated nickname + * group, if any. If the nickname is the last in its group, remove the + * group as well, along with any channels owned by the group (unless the + * channels have successors, in which case the successor gets the channel). */ -static void error(const char *fmt, ...) FORMAT(printf,1,2); -static void error(const char *fmt, ...) +static void my_delnick(NickInfo *ni) { - char buf[4096]; - va_list args; - - va_start(args, fmt); - vsnprintf(buf, sizeof(buf), fmt, args); - va_end(args); - fprintf(stderr, "Line %d: %s\n", lines_read, buf); + if (ni->nickgroup) { + NickGroupInfo *ngi = get_nickgroupinfo(ni->nickgroup); + if (ngi) { + int i; + ARRAY_SEARCH_PLAIN(ngi->nicks, ni->nick, irc_stricmp, i); + if (i < ngi->nicks_count) { + ARRAY_REMOVE(ngi->nicks, i); + if (ngi->mainnick > i || ngi->mainnick >= ngi->nicks_count) + ngi->mainnick--; + if (!ngi->nicks_count) { + ChannelInfo *ci; + del_nickgroupinfo(ngi); /* also frees */ + for (ci = first_channelinfo(); ci; + ci = next_channelinfo() + ) { + if (ci->successor == ni->nickgroup) + ci->successor = 0; + if (ci->founder == ni->nickgroup) { + if (ci->successor) { + NickGroupInfo *ngi2 = + get_nickgroupinfo(ci->successor); + if (ngi2) { + error("Giving channel %s (owned by deleted" + " nick %s) to %s", + ci->name, ni->nick, + ngi2->nicks[ngi2->mainnick]); + ci->founder = ci->successor; + ci->successor = 0; + } else { + error("Dropping channel %s (owned by" + " deleted nick %s, invalid successor" + " %u)", ci->name, ni->nick, + ci->successor); + del_channelinfo(ci); + } + } else { /* !ci->successor */ + error("Dropping channel %s (owned by deleted" + " nick %s, no successor)", + ci->name, ni->nick); + del_channelinfo(ci); + } /* if (ci->successor) */ + } /* if (ci->founder == ni->nickgroup) */ + } /* for all channels */ + } /* if (!ngi->nicks_count) */ + } /* if (i < ngi->nicks_count) */ + } /* if (ngi) */ + } /* if (ni->nickgroup) */ + del_nickinfo(ni); /* also frees */ } /*************************************************************************/ @@ -741,7 +722,7 @@ /* Copy tag name to return buffer */ if (found_tag_ret) - strscpy(found_tag_ret, tag, 256); + strscpy(found_tag_ret, tag, 256); /* sizeof(found_tag_ret) == 4 */ /* Look up tag in table and call handler */ for (i = 0; tags[i].tag != NULL; i++) { @@ -1056,19 +1037,14 @@ char tag2[256]; NickGroupInfo *ngi; - ngi = malloc(sizeof(*ngi)); + ngi = new_nickgroupinfo(NULL); if (!ngi) { error("Out of memory for <%s>", tag); return NULL; } - memset(ngi, 0, sizeof(*ngi)); - ngi->language = LANG_DEFAULT; - ngi->timezone = TIMEZONE_DEFAULT; - ngi->channelmax = CHANMAX_DEFAULT; - ngi->memos.memomax = MEMOMAX_DEFAULT; while ((result = parse_tag(tag, tag2, NULL, NULL)) != PARSETAG_END) { if (result == NULL) { - my_free_nickgroupinfo(ngi); + free_nickgroupinfo(ngi); return NULL; } else if (result == CONTINUE) { continue; @@ -1083,11 +1059,11 @@ ngi->nicks = calloc(ngi->nicks_count, sizeof(*ngi->nicks)); if (!ngi->nicks) { error("Out of memory for <%s>", tag2); - my_free_nickgroupinfo(ngi); + free_nickgroupinfo(ngi); return NULL; } ARRAY_FOREACH (i, ngi->nicks) { - strscpy(ngi->nicks[i], nicks[i], NICKMAX); + strscpy(ngi->nicks[i], nicks[i], sizeof(ngi->nicks[i])); free(nicks[i]); } free(nicks); @@ -1147,11 +1123,11 @@ } if (!ngi->id) { error(" tag missing from nick group, ignoring"); - my_free_nickgroupinfo(ngi); + free_nickgroupinfo(ngi); return CONTINUE; } else if (!ngi->nicks_count) { error("Nick group %u has no nicks, ignoring", ngi->id); - my_free_nickgroupinfo(ngi); + free_nickgroupinfo(ngi); return CONTINUE; } if (ngi->mainnick >= ngi->nicks_count) { @@ -1174,12 +1150,11 @@ char tag2[256]; static SuspendInfo *si; - si = malloc(sizeof(*si)); + si = new_suspendinfo("", NULL, 0); if (!si) { error("Out of memory for <%s>", tag); return NULL; } - memset(si, 0, sizeof(*si)); while ((result = parse_tag(tag, tag2, NULL, NULL)) != PARSETAG_END) { if (result == NULL) { free(si->reason); @@ -1188,7 +1163,7 @@ } else if (result == CONTINUE) { continue; } else if (stricmp(tag2, "who") == 0) { - strscpy(si->who, ((TextInfo *)result)->text, NICKMAX); + strscpy(si->who, ((TextInfo *)result)->text, sizeof(si->who)); free(((TextInfo *)result)->text); } else if (stricmp(tag2, "reason") == 0) { si->reason = ((TextInfo *)result)->text; @@ -1201,7 +1176,7 @@ } } if (!*si->who) - strscpy(si->who, "", NICKMAX); + strscpy(si->who, "", sizeof(si->who)); if (!si->reason) { si->reason = strdup(""); if (!si->reason) { @@ -1338,7 +1313,8 @@ } else if (stricmp(tag2, "time") == 0) { memo.time = *(time_t *)result; } else if (stricmp(tag2, "sender") == 0) { - strscpy(memo.sender, ((TextInfo *)result)->text, NICKMAX); + strscpy(memo.sender, ((TextInfo *)result)->text, + sizeof(memo.sender)); free(((TextInfo *)result)->text); } else if (stricmp(tag2, "text") == 0) { memo.text = ((TextInfo *)result)->text; @@ -1347,7 +1323,7 @@ } } if (!*memo.sender) - strscpy(memo.sender, "", NICKMAX); + strscpy(memo.sender, "", sizeof(memo.sender)); return &memo; } @@ -1363,20 +1339,19 @@ char tag2[256]; NickInfo *ni; - ni = malloc(sizeof(*ni)); + ni = new_nickinfo(); if (!ni) { error("Out of memory for <%s>", tag); return NULL; } - memset(ni, 0, sizeof(*ni)); while ((result = parse_tag(tag, tag2, NULL, NULL)) != PARSETAG_END) { if (result == NULL) { - my_free_nickinfo(ni); + free_nickinfo(ni); return NULL; } else if (result == CONTINUE) { continue; } else if (stricmp(tag2, "nick") == 0) { - strscpy(ni->nick, ((TextInfo *)result)->text, NICKMAX); + strscpy(ni->nick, ((TextInfo *)result)->text, sizeof(ni->nick)); free(((TextInfo *)result)->text); if (!*ni->nick) error("Empty tag"); @@ -1402,12 +1377,12 @@ } if (!*ni->nick) { error(" tag missing from nick, ignoring"); - my_free_nickinfo(ni); + free_nickinfo(ni); return CONTINUE; } else if (!(ni->status & NS_VERBOTEN)) { if (!ni->nickgroup) { error("Nick %s has no nick group, ignoring", ni->nick); - my_free_nickinfo(ni); + free_nickinfo(ni); return CONTINUE; } if (!ni->last_usermask) { @@ -1416,7 +1391,7 @@ ni->last_usermask = strdup("@"); if (!ni->last_usermask) { error("Out of memory"); - my_free_nickinfo(ni); + free_nickinfo(ni); return CONTINUE; } } @@ -1426,7 +1401,7 @@ ni->last_realname = strdup(""); if (!ni->last_realname) { error("Out of memory"); - my_free_nickinfo(ni); + free_nickinfo(ni); return CONTINUE; } } @@ -1460,21 +1435,19 @@ char tag2[256]; ChannelInfo *ci; - ci = malloc(sizeof(*ci)); + ci = new_channelinfo(); if (!ci) { error("Out of memory for <%s>", tag); return NULL; } - memset(ci, 0, sizeof(*ci)); - ci->memos.memomax = MEMOMAX_DEFAULT; while ((result = parse_tag(tag, tag2, NULL, NULL)) != PARSETAG_END) { if (result == NULL) { - my_free_channelinfo(ci); + free_channelinfo(ci); return NULL; } else if (result == CONTINUE) { continue; } else if (stricmp(tag2, "name") == 0) { - strscpy(ci->name, ((TextInfo *)result)->text, CHANMAX); + strscpy(ci->name, ((TextInfo *)result)->text, sizeof(ci->name)); free(((TextInfo *)result)->text); if (!*ci->name) error("Empty tag"); @@ -1502,10 +1475,12 @@ } else if (stricmp(tag2, "last_topic") == 0) { ci->last_topic = ((TextInfo *)result)->text; } else if (stricmp(tag2, "last_topic_setter") == 0) { - strscpy(ci->last_topic_setter,((TextInfo *)result)->text,NICKMAX); + strscpy(ci->last_topic_setter, ((TextInfo *)result)->text, + sizeof(ci->last_topic_setter)); free(((TextInfo *)result)->text); if (!*ci->last_topic_setter) - strscpy(ci->last_topic_setter, "", NICKMAX); + strscpy(ci->last_topic_setter, "", + sizeof(ci->last_topic_setter)); } else if (stricmp(tag2, "last_topic_time") == 0) { ci->last_topic_time = *(time_t *)result; } else if (stricmp(tag2, "flags") == 0) { @@ -1542,15 +1517,15 @@ } if (!*ci->name) { error(" tag missing from channel, ignoring"); - my_free_channelinfo(ci); + free_channelinfo(ci); return CONTINUE; } else if (strcmp(ci->name, "#") == 0) { error("Channel \"#\" not supported"); - my_free_channelinfo(ci); + free_channelinfo(ci); return CONTINUE; } else if (!ci->founder && !(ci->flags & CI_VERBOTEN)) { error("Channel %s has no founder, ignoring", ci->name); - my_free_channelinfo(ci); + free_channelinfo(ci); return CONTINUE; } if (ci->founder && ci->successor == ci->founder) { @@ -1582,7 +1557,7 @@ * * FIXME: this depends on chanserv/main for reset_levels()... is there a * better way to deal with the fact that we may not have all the - * levels listed in the XML file? + * levels listed in the XML file? --> to be fixed in 5.1 */ #define DEFINE_LEVEL(name) {#name,name} @@ -1821,7 +1796,7 @@ } else if (stricmp(tag2, "reason") == 0) { akick.reason = ((TextInfo *)result)->text; } else if (stricmp(tag2, "who") == 0) { - strscpy(akick.who, ((TextInfo *)result)->text, NICKMAX); + strscpy(akick.who, ((TextInfo *)result)->text, sizeof(akick.who)); free(((TextInfo *)result)->text); } else if (stricmp(tag2, "set") == 0) { akick.set = *(time_t *)result; @@ -1836,7 +1811,7 @@ memset(&akick, 0, sizeof(akick)); } else { if (!*akick.who) - strscpy(akick.who, "", NICKMAX); + strscpy(akick.who, "", sizeof(akick.who)); } return &akick; } @@ -1916,7 +1891,7 @@ } else if (stricmp(tag2, "text") == 0) { news->text = ((TextInfo *)result)->text; } else if (stricmp(tag2, "who") == 0) { - strscpy(news->who, ((TextInfo *)result)->text, NICKMAX); + strscpy(news->who, ((TextInfo *)result)->text, sizeof(news->who)); free(((TextInfo *)result)->text); } else if (stricmp(tag2, "time") == 0) { news->time = *(time_t *)result; @@ -1934,7 +1909,7 @@ return CONTINUE; } if (!*news->who) { - strscpy(news->who, "", NICKMAX); + strscpy(news->who, "", sizeof(news->who)); } if (!news->time) { error("Warning: News item has no creation time, setting to current" @@ -2009,7 +1984,7 @@ } else if (stricmp(tag2, "reason") == 0) { md->reason = ((TextInfo *)result)->text; } else if (stricmp(tag2, "who") == 0) { - strscpy(md->who, ((TextInfo *)result)->text, NICKMAX); + strscpy(md->who, ((TextInfo *)result)->text, sizeof(md->who)); free(((TextInfo *)result)->text); } else if (stricmp(tag2, "time") == 0) { md->time = *(time_t *)result; @@ -2038,7 +2013,7 @@ } } if (!*md->who) { - strscpy(md->who, "", NICKMAX); + strscpy(md->who, "", sizeof(md->who)); } if (!md->time) { error("Warning: Mask data entry has no creation time, setting to" @@ -2109,13 +2084,13 @@ int i; LIST_FOREACH_SAFE (ngi, ngi_list, ngi2) - my_free_nickgroupinfo(ngi); + free_nickgroupinfo(ngi); ngi_list = NULL; LIST_FOREACH_SAFE (ni, ni_list, ni2) - my_free_nickinfo(ni); + free_nickinfo(ni); ni_list = NULL; LIST_FOREACH_SAFE (ci, ci_list, ci2) - my_free_channelinfo(ci); + free_channelinfo(ci); ci_list = NULL; LIST_FOREACH_SAFE (news, news_list, news2) my_free_newsitem(news); @@ -2169,6 +2144,7 @@ /* See if the nick already exists in the database */ NickInfo *ni = get_nickinfo(ngi->nicks[i]); if (ni) { + int j; printf("Line %d: %sImported nick %s collides with %s" " nick, discarding nick group with nicks:", lines_read, @@ -2177,11 +2153,9 @@ ngi->nicks[i], ni->status & NS_VERBOTEN ? "forbidden" : "registered"); - /* Let them know what nicks get discarded. We'll - * break out of the loop afterward, so we can - * reuse `i' here. */ - ARRAY_FOREACH (i, ngi->nicks) - printf(" %s", ngi->nicks[i]); + /* Let them know what nicks get discarded. */ + ARRAY_FOREACH (j, ngi->nicks) + printf(" %s", ngi->nicks[j]); printf("\n"); LIST_INSERT(ngi, ngi_discarded); ngi = NULL; @@ -2202,8 +2176,9 @@ /* Special handling for forbidden nicks (which have no groups) */ if (!ni->nickgroup) { if (flags_nickcoll != XMLI_NICKCOLL_OVERWRITE - && get_nickinfo(ni->nick)) { - my_free_nickinfo(ni); + && get_nickinfo(ni->nick) + ) { + free_nickinfo(ni); continue; } LIST_INSERT(ni, ni_list); @@ -2214,14 +2189,14 @@ LIST_SEARCH_SCALAR(ngi_discarded, id, ni->nickgroup, ngi); if (ngi) { /* It's from a discarded nickgroup, drop it and continue */ - my_free_nickinfo(ni); + free_nickinfo(ni); continue; } LIST_SEARCH_SCALAR(ngi_list, id, ni->nickgroup, ngi); if (!ngi) { error("Nick %s has invalid nick group %u, discarding", ni->nick, ni->nickgroup); - my_free_nickinfo(ni); + free_nickinfo(ni); continue; } /* Also make sure nickgroup has nick listed */ @@ -2229,7 +2204,7 @@ if (i >= ngi->nicks_count) { error("Nick %s not listed in nick array for nick group %u" " (corrupt database?), discarding", ni->nick, ngi->id); - my_free_nickinfo(ni); + free_nickinfo(ni); continue; } /* Check for nick collisions if in discard-colliding-nick-only @@ -2241,11 +2216,11 @@ " discarding imported nick", ni->nick, ni2->status & NS_VERBOTEN ? "forbidden" : "registered"); - my_free_nickinfo(ni); + free_nickinfo(ni); if (ngi->nicks_count == 1) { /* Only nick in group, delete group */ LIST_REMOVE(ngi, ngi_list); - my_free_nickgroupinfo(ngi); + free_nickgroupinfo(ngi); } else { /* Delete nick from group's nick list; `i' still * holds nicks[] index from above */ @@ -2271,7 +2246,7 @@ flags_chancoll==XMLI_CHANCOLL_ABORT ? "":"Warning: ", ci->name, ci->flags&CI_VERBOTEN ? "forbidden" : "registered"); - my_free_channelinfo(ci); + free_channelinfo(ci); ci = NULL; if (flags_chancoll == XMLI_CHANCOLL_ABORT) failed = 1; @@ -2301,6 +2276,7 @@ } error("MaskData entry for `%s' (%s) already exists in" " database, skipping", md->mask, s); + my_free_maskdata(md); } else { LIST_INSERT(md, md_list[md->modified]); md->modified = 0; @@ -2311,6 +2287,7 @@ if (get_serverstats(ss->name)) { error("ServerStats entry for `%s' already exists in" " database, skipping", ss->name); + my_free_serverstats(ss); } else { LIST_INSERT(ss, ss_list); } @@ -2318,6 +2295,13 @@ } /* while not PARSETAG_END */ + /* Free discarded nickgroups */ + { + NickGroupInfo *ngi, *ngi2; + LIST_FOREACH_SAFE (ngi, ngi_discarded, ngi2) + free_nickgroupinfo(ngi); + } + return !failed; } @@ -2373,6 +2357,15 @@ } LIST_FOREACH_SAFE (ni, ni_list, ni2) { + NickInfo *oldni = get_nickinfo(ni->nick); + if (oldni) { + if ((flags & XMLI_NICKCOLL_MASK) == XMLI_NICKCOLL_OVERWRITE) { + error("Overwriting nick %s", oldni->nick); + my_delnick(oldni); + } else { + fatal("BUG: Colliding nick %s not removed!", ni->nick); + } + } LIST_REMOVE(ni, ni_list); add_nickinfo(ni); error("Nick %s imported", ni->nick); @@ -2382,17 +2375,23 @@ LIST_REMOVE(ci, ci_list); if (ci->founder) { NickGroupInfo *ngi = get_nickgroupinfo(ci->founder); - if (ngi) { - ARRAY_EXTEND(ngi->channels); - strscpy(ngi->channels[ngi->channels_count-1],ci->name,CHANMAX); - } else { + if (!ngi) { error("Warning: Founder nickgroup missing for channel %s," " deleting channel", ci->name); - my_free_channelinfo(ci); + free_channelinfo(ci); ci = NULL; } } if (ci) { + ChannelInfo *oldci = get_channelinfo(ci->name); + if (oldci) { + if ((flags & XMLI_CHANCOLL_MASK) == XMLI_CHANCOLL_OVERWRITE) { + error("Overwriting channel %s", oldci->name); + del_channelinfo(oldci); /* also frees */ + } else { + fatal("BUG: Colliding nick %s not removed!", ni->nick); + } + } add_channelinfo(ci); error("Channel %s imported", ci->name); } @@ -2444,15 +2443,6 @@ const_MD_SQLINE = MD_SQLINE; const_MD_SZLINE = MD_SZLINE; - /* Overwriting doesn't work yet */ - if ((flags & XMLI_NICKCOLL_MASK) == XMLI_NICKCOLL_OVERWRITE) { - error("Nickname overwriting not yet supported"); - return 0; - } else if ((flags & XMLI_CHANCOLL_MASK) == XMLI_CHANCOLL_OVERWRITE) { - error("Channel overwriting not yet supported"); - return 0; - } - /* Read in initial tag(s) */ if (read_tag(&tag, &attr, &attrval, NULL, NULL) != 1) { error("Error reading initial tag"); @@ -2557,10 +2547,8 @@ value_to_set = 0; } else if (stricmp(value, "skipnick") == 0) { value_to_set = XMLI_NICKCOLL_SKIPNICK; -#if 0 /*FIXME for overwrite*/ } else if (stricmp(value, "overwrite") == 0) { value_to_set = XMLI_NICKCOLL_OVERWRITE; -#endif } else if (stricmp(value, "abort") == 0) { value_to_set = XMLI_NICKCOLL_ABORT; } else { @@ -2589,10 +2577,8 @@ } if (stricmp(value, "skip") == 0) { value_to_set = 0; -#if 0 /*FIXME for overwrite*/ } else if (stricmp(value, "overwrite") == 0) { value_to_set = XMLI_CHANCOLL_OVERWRITE; -#endif } else if (stricmp(value, "abort") == 0) { value_to_set = XMLI_CHANCOLL_ABORT; } else { diff -uNr ircservices-5.0.26/modules/nickserv/link.c ircservices-5.0.27/modules/nickserv/link.c --- ircservices-5.0.26/modules/nickserv/link.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/nickserv/link.c 2003-12-03 11:48:46 +0900 @@ -60,10 +60,7 @@ notice_lang(s_NickServ, u, NICK_TOO_LONG, protocol_nickmax); } else if (!valid_nick(nick)) { notice_lang(s_NickServ, u, NICK_INVALID, nick); - } else if (call_callback_4(module_nickserv, cb_reglink_check, - u, nick, NULL, NULL) > 0) { - /* FIXME: we really shouldn't call another module's - * callbacks; put this in a function in util.c? */ + } else if (!reglink_check(u, nick, NULL, NULL)) { notice_lang(s_NickServ, u, NICK_CANNOT_BE_LINKED, nick); return; } else if (!ni || !ngi || ngi == NICKGROUPINFO_INVALID) { diff -uNr ircservices-5.0.26/modules/nickserv/mail-auth.c ircservices-5.0.27/modules/nickserv/mail-auth.c --- ircservices-5.0.26/modules/nickserv/mail-auth.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/nickserv/mail-auth.c 2003-12-03 11:48:46 +0900 @@ -27,9 +27,7 @@ * code (see below) is generated and mailed to the user, with instructions * to use the AUTH command (provided by this module) to verify the nick * registration or address change. Until this is done, the nick may not - * be identified for, essentially preventing use of the nick. (FIXME: they - * can get around this by clearing SECURE and adding an appropriate access - * list entry before setting E-mail) + * be identified for, essentially preventing use of the nick. * * The access code generated is a random 9-digit number, lower-bounded to * 100,000,000 to avoid potential difficulties with leading zeroes. diff -uNr ircservices-5.0.26/modules/nickserv/main.c ircservices-5.0.27/modules/nickserv/main.c --- ircservices-5.0.26/modules/nickserv/main.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/nickserv/main.c 2003-12-03 11:48:46 +0900 @@ -25,7 +25,7 @@ static int cb_command = -1; static int cb_help = -1; static int cb_help_cmds = -1; - int cb_reglink_check = -1; /* used by link module */ + int cb_reglink_check = -1; /* called from util.c */ static int cb_registered = -1; static int cb_id_check = -1; static int cb_identified = -1; @@ -473,9 +473,7 @@ * in the command. */ syntax_error(s_NickServ, u, "REGISTER", NICK_REGISTER_SYNTAX); - } else if (call_callback_4(module, cb_reglink_check, u, u->nick, pass, - email) > 0 - ) { + } else if (!reglink_check(u, u->nick, pass, email)) { /* Denied by the callback. */ notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, u->nick); return; diff -uNr ircservices-5.0.26/modules/nickserv/nickserv.h ircservices-5.0.27/modules/nickserv/nickserv.h --- ircservices-5.0.26/modules/nickserv/nickserv.h 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/nickserv/nickserv.h 2003-12-03 11:48:46 +0900 @@ -15,6 +15,25 @@ #endif /*************************************************************************/ +/*************************************************************************/ + +/* User-configurable settings: */ + + +/* Maximum number of tries to randomly select a new NickGroupInfo ID before + * giving up. Assuming a sufficiently random random-number generator and a + * database of one million nicknames, the default setting of 1000 gives + * odds of approximately 10^3600 to 1 against an accidental failure. + */ +#define NEWNICKGROUP_TRIES 1000 + + +/* Number of DROPEMAIL commands to buffer for DROPEMAIL-CONFIRM. */ + +#define DROPEMAIL_BUFSIZE 4 + +/*************************************************************************/ +/*************************************************************************/ /* Data structure for a single nickname. */ @@ -215,11 +234,17 @@ E char *s_NickServ; -E NickInfo *new_nickinfo(void); -E void free_nickinfo(NickInfo *ni); -E NickGroupInfo *new_nickgroupinfo(const char *seed); -E void free_nickgroupinfo(NickGroupInfo *ngi); +#ifdef STANDALONE_NICKSERV /* see util.c */ +# define E2 static +#else +# define E2 extern +#endif +E2 NickInfo *new_nickinfo(void); +E2 void free_nickinfo(NickInfo *ni); +E2 NickGroupInfo *new_nickgroupinfo(const char *seed); +E2 void free_nickgroupinfo(NickGroupInfo *ngi); E int check_expire_nick(NickInfo *ni); +#undef E2 #define get_ngi(ni) _get_ngi((ni), __FILE__, __LINE__) #define check_ngi(ni) (get_ngi((ni)) != NULL) // Check for presence of NGI only diff -uNr ircservices-5.0.26/modules/nickserv/ns-local.h ircservices-5.0.27/modules/nickserv/ns-local.h --- ircservices-5.0.26/modules/nickserv/ns-local.h 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/nickserv/ns-local.h 2003-12-03 11:48:46 +0900 @@ -13,21 +13,6 @@ /*************************************************************************/ /*************************************************************************/ -/* Maximum number of tries to randomly select a new NickGroupInfo ID before - * giving up. Assuming a sufficiently random random-number generator and a - * database of one million nicknames, the default setting of 1000 gives - * odds of approximately 10^3600 to 1 against an accidental failure. - */ -#define NEWNICKGROUP_TRIES 1000 - -/*************************************************************************/ - -/* Number of DROPEMAIL commands to buffer for DROPEMAIL-CONFIRM. */ - -#define DROPEMAIL_BUFSIZE 4 - -/*************************************************************************/ - #define TO_COLLIDE 0 /* Collide the user with this nick */ #define TO_RELEASE 1 /* Release a collided nick */ #define TO_SEND_433 2 /* Send a 433 numeric */ @@ -93,6 +78,7 @@ #define init_util init_util_ns #define exit_util exit_util_ns +E int reglink_check(User *u, const char *nick, char *password, char *email); E void update_userinfo(User *u); E int validate_user(User *u); E void cancel_user(User *u); diff -uNr ircservices-5.0.26/modules/nickserv/util.c ircservices-5.0.27/modules/nickserv/util.c --- ircservices-5.0.26/modules/nickserv/util.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/nickserv/util.c 2003-12-03 11:48:46 +0900 @@ -7,16 +7,43 @@ * details. */ -#include "services.h" -#include "modules.h" -#include "language.h" -#include "encrypt.h" +/* If STANDALONE_NICKSERV is defined when compiling this file, the + * following four routines will be defined as `static' for use in other + * modules/programs: + * new_nickinfo() + * free_nickinfo() + * new_nickgroupinfo() + * free_nickgroupinfo() + * This file should be #include'd in the file making use of the routines. + * Note that new_nickgroupinfo() will not check for the presence of any + * nickgroup ID it assigns, since get_nickgroupinfo() is not assumed to be + * available. + */ + +#ifdef STANDALONE_NICKSERV + +# define STANDALONE_STATIC static +# undef EXPORT_FUNC +# define EXPORT_FUNC(x) /*nothing*/ + +#else + +# define STANDALONE_STATIC /*nothing*/ + +# include "services.h" +# include "modules.h" +# include "language.h" +# include "encrypt.h" -#include "nickserv.h" -#include "ns-local.h" +# include "nickserv.h" +# include "ns-local.h" + +#endif /*************************************************************************/ +#ifndef STANDALONE_NICKSERV + static Module *module; static int cb_cancel_user = -1; static int cb_check_expire = -1; @@ -24,6 +51,8 @@ static int cb_delete = -1; static int cb_groupdelete = -1; +#endif + /*************************************************************************/ /************************ Global utility routines ************************/ /*************************************************************************/ @@ -31,7 +60,7 @@ /* Allocate and initialize a new NickInfo structure. */ EXPORT_FUNC(new_nickinfo) -NickInfo *new_nickinfo(void) +STANDALONE_STATIC NickInfo *new_nickinfo(void) { NickInfo *ni = scalloc(sizeof(*ni), 1); return ni; @@ -42,13 +71,15 @@ /* Free a NickInfo structure and all associated data. */ EXPORT_FUNC(free_nickinfo) -void free_nickinfo(NickInfo *ni) +STANDALONE_STATIC void free_nickinfo(NickInfo *ni) { - free(ni->last_usermask); - free(ni->last_realmask); - free(ni->last_realname); - free(ni->last_quit); - free(ni); + if (ni) { + free(ni->last_usermask); + free(ni->last_realmask); + free(ni->last_realname); + free(ni->last_quit); + free(ni); + } } /*************************************************************************/ @@ -61,7 +92,7 @@ */ EXPORT_FUNC(new_nickgroupinfo) -NickGroupInfo *new_nickgroupinfo(const char *seed) +STANDALONE_STATIC NickGroupInfo *new_nickgroupinfo(const char *seed) { NickGroupInfo *ngi = scalloc(sizeof(*ngi), 1); @@ -74,6 +105,7 @@ id ^= seed[count] << ((count % 6) * 5); if (id == 0) id = 1; +#ifndef STANDALONE_NICKSERV count = 0; while (get_nickgroupinfo(id) != NULL && ++count < NEWNICKGROUP_TRIES) { id = rand() + rand(); /* 32 bits of randomness, hopefully */ @@ -86,9 +118,14 @@ free(ngi); return NULL; } +#endif ngi->id = id; } + ngi->memos.memomax = MEMOMAX_DEFAULT; + ngi->channelmax = CHANMAX_DEFAULT; + ngi->language = LANG_DEFAULT; + ngi->timezone = TIMEZONE_DEFAULT; return ngi; } @@ -97,17 +134,17 @@ /* Free a NickGroupInfo structure and all associated data. */ EXPORT_FUNC(free_nickgroupinfo) -void free_nickgroupinfo(NickGroupInfo *ngi) +STANDALONE_STATIC void free_nickgroupinfo(NickGroupInfo *ngi) { int i; + if (!ngi) + return; free(ngi->url); free(ngi->email); free(ngi->info); - if (ngi->suspendinfo) { - free(ngi->suspendinfo->reason); - free(ngi->suspendinfo); - } + if (ngi->suspendinfo) + free_suspendinfo(ngi->suspendinfo); free(ngi->nicks); ARRAY_FOREACH (i, ngi->access) free(ngi->access[i]); @@ -128,10 +165,12 @@ ARRAY_SEARCH_PLAIN_SCALAR(u->id_nicks, ngi->id, j); if (j < u->id_nicks_count) { ARRAY_REMOVE(u->id_nicks, j); +#ifndef STANDALONE_NICKSERV } else { module_log("BUG: free_nickgroupinfo(): user %p (%s) listed in" " id_users for nickgroup %u, but nickgroup not in" " id_nicks!", u, u->nick, ngi->id); +#endif } } free(ngi->id_users); @@ -140,6 +179,10 @@ /*************************************************************************/ +#ifndef STANDALONE_NICKSERV /* to the end of the file */ + +/*************************************************************************/ + /* Check whether the given nickname (or its suspension) should be expired, * and do the expiration if so. Return 1 if the nickname was deleted, else * 0. Note that we do last-seen-time updates here as well. @@ -245,6 +288,22 @@ /*********************** Internal utility routines ***********************/ /*************************************************************************/ +/* Check whether the given nickname is allowed to be registered (with the + * given password and E-mail address) or linked (password/email NULL). + * Returns nonzero if allowed, 0 if not. A wrapper for the "REGISTER/LINK + * check" callback. + */ + +int reglink_check(User *u, const char *nick, char *password, char *email) +{ + int res = call_callback_4(module, cb_reglink_check, u,nick,password,email); + if (res < 0) + module_log("REGISTER/LINK callback returned an error"); + return res == 0; +} + +/*************************************************************************/ + /* Update the last_usermask, last_realmask, and last_realname nick fields * from the given user's data. Assumes u->ni is non-NULL. */ @@ -374,7 +433,7 @@ is_recognized = (call_callback_1(module, cb_check_recognized, u) == 1); - if (!(ngi->flags & NF_SECURE) && is_recognized) { + if (!(ngi->flags & NF_SECURE) && !ngi->authcode && is_recognized) { ni->authstat |= NA_RECOGNIZED; update_userinfo(u); put_nickinfo(u->ni); @@ -637,13 +696,7 @@ void suspend_nick(NickGroupInfo *ngi, const char *reason, const char *who, const time_t expires) { - SuspendInfo *si; - - si = scalloc(sizeof(*si), 1); - strscpy(si->who, who, NICKMAX); - si->reason = sstrdup(reason); - si->suspended = time(NULL); - si->expires = expires; + SuspendInfo *si = new_suspendinfo(who, sstrdup(reason), expires); ngi->suspendinfo = si; put_nickgroupinfo(ngi); } @@ -665,8 +718,7 @@ ngi->id, ngi->nicks[0]); return; } - free(ngi->suspendinfo->reason); - free(ngi->suspendinfo); + free_suspendinfo(ngi->suspendinfo); ngi->suspendinfo = NULL; put_nickgroupinfo(ngi); if (set_time && NSExpire && NSSuspendGrace) { @@ -798,3 +850,5 @@ } /*************************************************************************/ + +#endif /* !STANDALONE_NICKSERV */ diff -uNr ircservices-5.0.26/modules/operserv/akill.c ircservices-5.0.27/modules/operserv/akill.c --- ircservices-5.0.26/modules/operserv/akill.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/operserv/akill.c 2003-12-03 11:48:46 +0900 @@ -420,9 +420,11 @@ * the chance of people complaining about "user not found" errors * from ircds that kill users on autokill if we do the autokill * first is significantly greater... */ + /* But as long as you kill the user first, make sure you save the + * hostname _before_ it gets freed, idiot. */ + snprintf(buf, sizeof(buf), "*@%s", cu->user->host); if (kill) kill_user(s_OperServ, cu->user->nick, reason); - snprintf(buf, sizeof(buf), "*@%s", cu->user->host); if (!get_maskdata(MD_AKILL, buf)) create_akill(buf, reason, u->nick, expiry); count++; diff -uNr ircservices-5.0.26/modules/protocol/bahamut.c ircservices-5.0.27/modules/protocol/bahamut.c --- ircservices-5.0.26/modules/protocol/bahamut.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/protocol/bahamut.c 2003-12-03 11:48:46 +0900 @@ -203,9 +203,15 @@ static void m_svsmode(char *source, int ac, char **av) { if (*av[0] == '#') { - /* FIXME: support this */ - module_log("SVSMODE from %s for channel %s (not supported): %s", - source, av[0], merge_args(ac-1,av+1)); + if (ac >= 3 && strcmp(av[1],"-b") == 0) { + Channel *c = get_channel(av[0]); + User *u = get_user(av[2]); + if (c && u) + clear_channel(c, CLEAR_BANS, u); + } else { + module_log("Invalid SVSMODE from %s for channel %s: %s", + source, av[0], merge_args(ac-1,av+1)); + } } else if (*av[0] == '&') { module_log("SVSMODE from %s for invalid target (channel %s): %s", source, av[0], merge_args(ac-1,av+1)); @@ -237,6 +243,7 @@ { "SQLINE", NULL }, { "SVINFO", NULL }, { "SVSMODE", m_svsmode }, + { "SZLINE", NULL }, { NULL } }; @@ -428,19 +435,6 @@ /*************************************************************************/ -static int do_clear_bans(Channel *chan, int what, const void *param) -{ - if (what == CLEAR_BANS && param != NULL) { - /* SVSMODE handles unbanning for us */ - const User *u = param; - send_cmd(ServerName, "SVSMODE %s -b %s", chan->name, u->nick); - return 1; - } - return 0; -} - -/*************************************************************************/ - static int do_send_akill(const char *username, const char *host, time_t expires, const char *who, const char *reason) { @@ -586,7 +580,6 @@ || !add_callback(NULL, "user servicestamp change", do_user_servicestamp_change) || !add_callback(NULL, "user MODE", do_user_mode) - || !add_callback(NULL, "clear channel", do_clear_bans) || !add_callback(NULL, "set topic", do_set_topic) ) { module_log("Unable to add callbacks"); @@ -641,7 +634,6 @@ exit_sjoin(); exit_banexcept(); remove_callback(NULL, "set topic", do_set_topic); - remove_callback(NULL, "clear channel", do_clear_bans); remove_callback(NULL, "user MODE", do_user_mode); remove_callback(NULL, "user servicestamp change", do_user_servicestamp_change); diff -uNr ircservices-5.0.26/modules/protocol/banexcept.c ircservices-5.0.27/modules/protocol/banexcept.c --- ircservices-5.0.26/modules/protocol/banexcept.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/protocol/banexcept.c 2003-12-03 11:48:46 +0900 @@ -77,6 +77,16 @@ for (i = 0; i < count; i++) { if (!u || match_usermask(excepts[i], u)) set_cmode(sender, chan, "-e", excepts[i]); + if (u && u->ipaddr) { + char tmpbuf[BUFSIZE]; + int nicklen = snprintf(tmpbuf, sizeof(tmpbuf), "%s!", u->nick); + snprintf(tmpbuf+nicklen, sizeof(tmpbuf)-nicklen, "%s@%s", + u->username, u->ipaddr); + if (match_wild_nocase(excepts[i], tmpbuf)) + set_cmode(sender, chan, "-e", excepts[i]); + if (match_wild_nocase(excepts[i], tmpbuf+nicklen)) + set_cmode(sender, chan, "-e", excepts[i]); + } } free(excepts); } diff -uNr ircservices-5.0.26/modules/protocol/halfop.c ircservices-5.0.27/modules/protocol/halfop.c --- ircservices-5.0.26/modules/protocol/halfop.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/protocol/halfop.c 2003-12-03 11:48:46 +0900 @@ -24,7 +24,7 @@ static int old_HELP_SOP_MID2 = -1; static int old_HELP_AOP_MID = -1; -static const char **p_s_ChanServ; +static const char **p_s_ChanServ = NULL; #define s_ChanServ (*p_s_ChanServ) /*************************************************************************/ diff -uNr ircservices-5.0.26/modules/protocol/monkey.c ircservices-5.0.27/modules/protocol/monkey.c --- ircservices-5.0.26/modules/protocol/monkey.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/protocol/monkey.c 2003-12-03 11:48:46 +0900 @@ -154,9 +154,15 @@ static void m_svsmode(char *source, int ac, char **av) { if (*av[0] == '#') { - /* FIXME: support this */ - module_log("SVSMODE from %s for channel %s (not supported): %s", - source, av[0], merge_args(ac-1,av+1)); + if (ac >= 3 && strcmp(av[1],"-b") == 0) { + Channel *c = get_channel(av[0]); + User *u = get_user(av[2]); + if (c && u) + clear_channel(c, CLEAR_BANS, u); + } else { + module_log("Invalid SVSMODE from %s for channel %s: %s", + source, av[0], merge_args(ac-1,av+1)); + } } else if (*av[0] == '&') { module_log("SVSMODE from %s for invalid target (channel %s): %s", source, av[0], merge_args(ac-1,av+1)); @@ -374,19 +380,6 @@ /*************************************************************************/ -static int do_clear_bans(Channel *chan, int what, const void *param) -{ - if (what == CLEAR_BANS && param != NULL) { - /* SVSMODE handles unbanning for us */ - const User *u = param; - send_cmd(ServerName, "SVSMODE %s -b %s", chan->name, u->nick); - return 1; - } - return 0; -} - -/*************************************************************************/ - static int do_send_akill(const char *username, const char *host, time_t expires, const char *who, const char *reason) { @@ -532,7 +525,6 @@ || !add_callback(NULL, "user servicestamp change", do_user_servicestamp_change) || !add_callback(NULL, "user MODE", do_user_mode) - || !add_callback(NULL, "clear channel", do_clear_bans) || !add_callback(NULL, "set topic", do_set_topic) ) { module_log("Unable to add callbacks"); @@ -584,7 +576,6 @@ exit_sjoin(); exit_halfop(); remove_callback(NULL, "set topic", do_set_topic); - remove_callback(NULL, "clear channel", do_clear_bans); remove_callback(NULL, "user MODE", do_user_mode); remove_callback(NULL, "user servicestamp change", do_user_servicestamp_change); diff -uNr ircservices-5.0.26/modules/protocol/trircd.c ircservices-5.0.27/modules/protocol/trircd.c --- ircservices-5.0.26/modules/protocol/trircd.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/protocol/trircd.c 2003-12-03 11:48:46 +0900 @@ -52,13 +52,29 @@ /*************************************************************************/ static typeof(is_services_admin) *p_is_services_admin = NULL; - -static int local_is_services_admin(User *u) -{ +static int local_is_services_admin(User *u) { return p_is_services_admin && (*p_is_services_admin)(u); } #define is_services_admin local_is_services_admin +static typeof(get_channelinfo) *p_get_channelinfo = NULL; +static ChannelInfo *local_get_channelinfo(const char *name) { + return p_get_channelinfo ? (*p_get_channelinfo)(name) : NULL; +} +#define get_channelinfo local_get_channelinfo + +static typeof(first_channelinfo) *p_first_channelinfo = NULL; +static ChannelInfo *local_first_channelinfo(void) { + return p_first_channelinfo ? (*p_first_channelinfo)() : NULL; +} +#define first_channelinfo local_first_channelinfo + +static typeof(next_channelinfo) *p_next_channelinfo = NULL; +static ChannelInfo *local_next_channelinfo(void) { + return p_next_channelinfo ? (*p_next_channelinfo)() : NULL; +} +#define next_channelinfo local_next_channelinfo + /*************************************************************************/ /************************** User/channel modes ***************************/ /*************************************************************************/ @@ -653,6 +669,82 @@ /******************************* Callbacks *******************************/ /*************************************************************************/ +static int do_connect(void) +{ + /* Send MODEs to the server for all channels locked +L, in case the + * servers aren't aware of them. */ + + ChannelInfo *ci; + + for (ci = first_channelinfo(); ci; ci = next_channelinfo()) { + if ((ci->mlock_on & mode_char_to_flag('L',MODE_CHANNEL)) + && ci->mlock_link + ) { + send_cmd(s_ChanServ, "MODE %s +L %s", ci->name, ci->mlock_link); + } + } + return 0; +} + +/*************************************************************************/ + +static int do_receive_message(const char *source, const char *cmd, int ac, + char **av) +{ + /* Watch for MODE +/-L's for nonexistent channels, and: + * (1) reverse them if necessary + * (2) don't generate "no such channel" error messages for them + */ + char *s; + ChannelInfo *ci; + int add; + int modeL; /* status of +/-L wrt this message (1:on, 0:off, -1:not seen) */ + int lockL; /* status of MLOCK +/-l (1:+L, 0:-L) */ + + if (stricmp(cmd,"MODE") != 0 || ac < 2 || av[0][0] != '#' + || get_channel(av[0]) /* existing channels will get handled normally */ + || !(ci = get_channelinfo(av[0])) + ) { + return 0; + } + if ((ci->mlock_on & mode_char_to_flag('L',MODE_CHANNEL)) && ci->mlock_link) + lockL = 1; + else if (ci->mlock_off & mode_char_to_flag('L',MODE_CHANNEL)) + lockL = 0; + else + return 0; + add = -1; + modeL = -1; + for (s = av[1]; *s; s++) { + if (*s == '+') { + add = 1; + } else if (*s == '-') { + add = 0; + } else if (*s == 'L') { + if (add < 0) { + module_log("Invalid MODE message from server: MODE %s", + merge_args(ac,av)); + return 0; + } else { + modeL = add; + } + } + } + if (modeL == -1) + return 0; + if (modeL != lockL) { + if (lockL) { + /* ci->mlock_link checked above */ + send_cmd(s_ChanServ, "MODE %s +L %s", av[0], ci->mlock_link); + } else { + send_cmd(s_ChanServ, "MODE %s -L", av[0]); + } + } + return 1; /* don't let the main code see it and say "no such channel" */ +} + +/*************************************************************************/ + static int do_user_create(User *user, int ac, char **av) { user->fakehost = sstrdup(av[9]); @@ -813,6 +905,14 @@ } return 1; } + } else { /* remove */ + switch (mode_flag_to_char(flag, MODE_CHANNEL)) { + case 'L': + /* Theoretically the channel can't exist, but send a set_cmode() + * just to be safe */ + set_cmode(s_ChanServ, c, "-L"); + return 1; + } } return 0; } @@ -865,21 +965,18 @@ return 1; } } - } - return 0; -} - -/*************************************************************************/ - -static int do_clear_ban(Channel *chan, int what, const void *param) -{ - if (what == CLEAR_BANS && param != NULL) { - /* SVSMODE handles unbanning for us (note that we can't do it ourselves - * because Bahamut servers apply IP-address bans to hostnames, and - * we don't have the user's IP address) */ - const User *u = param; - send_cmd(ServerName, "SVSMODE %s -b %s", chan->name, u->nick); - return 1; + } else { /* !add -> lock off */ + switch (mode) { + case 'L': { + /* The channel should not exist here; check anyway just to be + * safe, and do a set_cmode() or send_cmd() as appropriate. */ + Channel *c = get_channel(ci->name); + if (c) + set_cmode(s_ChanServ, c, "-L"); + else + send_cmd(s_ChanServ, "MODE %s -L", ci->name); + } + } } return 0; } @@ -1021,11 +1118,17 @@ 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; } + /* first/next_channelinfo are defined in the database module */ + p_first_channelinfo = get_module_symbol(NULL, "first_channelinfo"); + if (!p_first_channelinfo) + module_log("Unable to resolve symbol `first_channelinfo'"); + p_next_channelinfo = get_module_symbol(NULL, "next_channelinfo"); + if (!p_next_channelinfo) + module_log("Unable to resolve symbol `next_channelinfo'"); if (!add_callback(mod, "check_modes", do_check_modes)) module_log("Unable to add ChanServ check_modes callback"); if (!add_callback(mod, "SET MLOCK", do_set_mlock)) @@ -1037,11 +1140,18 @@ /*************************************************************************/ -static int do_unload_module(Module *module) +static int do_unload_module(Module *mod) { - if (module == module_operserv) { + if (mod == module_operserv) { module_operserv = NULL; p_is_services_admin = NULL; + } else if (mod == module_chanserv) { + module_chanserv = NULL; + p_s_ChanServ = &ServerName; + p_first_channelinfo = NULL; + p_next_channelinfo = NULL; + remove_callback(mod, "SET MLOCK", do_set_mlock); + remove_callback(mod, "check_modes", do_check_modes); } return 0; } @@ -1067,12 +1177,13 @@ if (!add_callback(NULL, "load module", do_load_module) || !add_callback(NULL, "unload module", do_unload_module) + || !add_callback(NULL, "connect", do_connect) + || !add_callback(NULL, "receive message", do_receive_message) || !add_callback(NULL, "user create", do_user_create) || !add_callback(NULL, "channel MODE", do_channel_mode) || !add_callback(NULL, "user servicestamp change", do_user_servicestamp_change) || !add_callback(NULL, "user MODE", do_user_mode) - || !add_callback(NULL, "clear channel", do_clear_ban) || !add_callback(NULL, "set topic", do_set_topic) ) { module_log("Unable to add callbacks"); @@ -1136,11 +1247,12 @@ exit_banexcept(); remove_callback(NULL, "set topic", do_set_topic); - remove_callback(NULL, "clear channel", do_clear_ban); remove_callback(NULL, "user MODE", do_user_mode); remove_callback(NULL, "user servicestamp change", do_user_servicestamp_change); remove_callback(NULL, "user create", do_user_create); + remove_callback(NULL, "receive message", do_receive_message); + remove_callback(NULL, "connect", do_connect); remove_callback(NULL, "unload module", do_unload_module); remove_callback(NULL, "load module", do_load_module); unregister_messages(trircd_messages); diff -uNr ircservices-5.0.26/modules/protocol/unreal.c ircservices-5.0.27/modules/protocol/unreal.c --- ircservices-5.0.26/modules/protocol/unreal.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/modules/protocol/unreal.c 2003-12-03 11:48:46 +0900 @@ -92,7 +92,8 @@ * return false). * * Here, too, we use a #define to substitute `local_is_services_admin' for - * `is_services_admin'. + * `is_services_admin', so we can use the latter as if it were declared + * normally. */ static int (*p_is_services_admin)(User *u) = NULL; @@ -465,9 +466,15 @@ static void m_svsmode(char *source, int ac, char **av) { if (*av[0] == '#') { - /* FIXME: support this */ - module_log("SVS[2]MODE from %s for channel %s (not supported): %s", - source, av[0], merge_args(ac-1,av+1)); + if (ac >= 3 && strcmp(av[1],"-b") == 0) { + Channel *c = get_channel(av[0]); + User *u = get_user(av[2]); + if (c && u) + clear_channel(c, CLEAR_BANS, u); + } else { + module_log("Invalid SVS[2]MODE from %s for channel %s: %s", + source, av[0], merge_args(ac-1,av+1)); + } } else if (*av[0] == '&') { module_log("SVS[2]MODE from %s for invalid target (channel %s): %s", source, av[0], merge_args(ac-1,av+1)); diff -uNr ircservices-5.0.26/modules.c ircservices-5.0.27/modules.c --- ircservices-5.0.26/modules.c 2003-11-26 23:28:18 +0900 +++ ircservices-5.0.27/modules.c 2003-12-03 11:48:45 +0900 @@ -670,6 +670,7 @@ i = module->callbacks_count; ARRAY_EXTEND(module->callbacks); module->callbacks[i].name = sstrdup(name); + module->callbacks[i].calling = 0; module->callbacks[i].funcs_count = 0; module->callbacks[i].funcs = NULL; return i; @@ -702,8 +703,6 @@ if (cl->calling == 2) { /* flag indicating some callbacks were removed */ ARRAY_FOREACH (i, cl->funcs) { if (!cl->funcs[i].func) { - /* FIXME: make a general purpose macro for this, like - * LIST_FOREACH_SAFE? */ ARRAY_REMOVE(cl->funcs, i); i--; } diff -uNr ircservices-5.0.26/process.c ircservices-5.0.27/process.c --- ircservices-5.0.26/process.c 2003-11-26 23:28:18 +0900 +++ ircservices-5.0.27/process.c 2003-12-03 11:48:45 +0900 @@ -116,7 +116,7 @@ while (isspace(*++s)) ; strscpy(source, buf+1, sizeof(source)); - memmove(buf, s, strlen(s)+1); + strmove(buf, s); } else { *source = 0; } diff -uNr ircservices-5.0.26/suspinfo.c ircservices-5.0.27/suspinfo.c --- ircservices-5.0.26/suspinfo.c 1970-01-01 09:00:00 +0900 +++ ircservices-5.0.27/suspinfo.c 2003-12-03 11:48:45 +0900 @@ -0,0 +1,41 @@ +/* Routines to allocate and free SuspendInfo structures. + * + * IRC Services is copyright (c) 1996-2003 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" + +/*************************************************************************/ + +/* Allocate a SuspendInfo structure, and fill it in with the data provided. + * The structure will be allocated with smalloc(); the `suspended' field is + * set to the current time. Always succeeds. + */ + +SuspendInfo *new_suspendinfo(const char *who, char *reason, time_t expires) +{ + SuspendInfo *si = smalloc(sizeof(*si)); + strscpy(si->who, who, sizeof(si->who)); + si->reason = reason; + si->suspended = time(NULL); + si->expires = expires; + return si; +} + +/*************************************************************************/ + +/* Free a SuspendInfo structure, including the reason string. */ + +void free_suspendinfo(SuspendInfo *si) +{ + if (si) { + free(si->reason); + free(si); + } +} + +/*************************************************************************/ diff -uNr ircservices-5.0.26/tools/Makefile ircservices-5.0.27/tools/Makefile --- ircservices-5.0.26/tools/Makefile 2003-11-26 23:28:18 +0900 +++ ircservices-5.0.27/tools/Makefile 2003-12-03 11:48:45 +0900 @@ -28,7 +28,7 @@ convert-ver8.o CONVERT_DB_OBJS = convert-db.o $(CONVERT_DB_MODULES) \ - fileutil-x.o xml-export-x.o $(TOPDIR)/compat.o \ + fileutil-x.o suspinfo-x.o xml-export-x.o $(TOPDIR)/compat.o \ $(CONVERT_DB_VSNPRINTF_O) .c.o: @@ -76,6 +76,8 @@ fileutil-x.o: $(TOPDIR)/modules/database/fileutil.c $(TOPDIR)/services.h \ $(TOPDIR)/modules/database/fileutil.h $(CC) $(CFLAGS_CONVERT_DB) -c $< -o $@ +suspinfo-x.o: $(TOPDIR)/suspinfo.c $(TOPDIR)/services.h + $(CC) $(CFLAGS_CONVERT_DB) -c $< -o $@ xml-export-x.o: $(TOPDIR)/modules/misc/xml-export.c $(TOPDIR)/services.h \ $(TOPDIR)/language.h \ $(TOPDIR)/modules/nickserv/nickserv.h \ diff -uNr ircservices-5.0.26/tools/convert-cygnus.c ircservices-5.0.27/tools/convert-cygnus.c --- ircservices-5.0.26/tools/convert-cygnus.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/tools/convert-cygnus.c 2003-12-03 11:48:46 +0900 @@ -340,13 +340,11 @@ if (myflags & 0x1000) /* MEMOMAIL */ ngi->flags |= NF_MEMO_FWDCOPY; /* Cygnus uses forward+copy */ if (myflags & 0x2000) { /* FROZEN */ - ngi->suspendinfo = smalloc(sizeof(*ngi->suspendinfo)); - strscpy(ngi->suspendinfo->who, "", - sizeof(ngi->suspendinfo->who)); - ngi->suspendinfo->reason = - sstrdup("Unknown (imported from Cygnus)"); - ngi->suspendinfo->suspended = time(NULL); - ngi->suspendinfo->expires = 0; + ngi->suspendinfo = new_suspendinfo( + "", + "Unknown (imported from Cygnus)", + 0 + ); } if (myflags & 0x4000) /* HELD, i.e. not expiring */ ni->status |= NS_NOEXPIRE; @@ -494,7 +492,11 @@ fname, line, ni->nick); break; } - free(ngi->suspendinfo->reason); + /* Under normal circumstances si->reason will be a string + * constant at this point. If there are ever two FR lines for + * the same nick group, we leak memory here, but since + * convert-db doesn't worry about memory leaks in general we + * don't worry about them here. */ ngi->suspendinfo->reason = sstrdup(s); break; @@ -755,14 +757,13 @@ ci = NULL; break; } - ci = scalloc(sizeof(*ci), 1); + ci = makechan(s); if (!ci) { fprintf(stderr, "%s:%d: Unable to add channel `%s' to" " database, skipping\n", fname, line, s); ci = NULL; break; } - strscpy(ci->name, s, sizeof(ci->name)); add_channelinfo(ci); ci->founder = ni->nickgroup; if (strlen(pass) > sizeof(ci->founderpass)-1) { @@ -824,13 +825,11 @@ if (myflags & 0x0008) ci->flags |= CI_RESTRICTED; if (myflags & 0x0010) { /* FROZEN */ - ci->suspendinfo = smalloc(sizeof(*ci->suspendinfo)); - strscpy(ci->suspendinfo->who, "", - sizeof(ci->suspendinfo->who)); - ci->suspendinfo->reason = - sstrdup("Unknown (imported from Cygnus)"); - ci->suspendinfo->suspended = time(NULL); - ci->suspendinfo->expires = 0; + ci->suspendinfo = new_suspendinfo( + "", + "Unknown (imported from Cygnus)", + 0 + ); } if (myflags & 0x0020) /* HELD, i.e. not expiring */ ci->flags |= CI_NOEXPIRE; diff -uNr ircservices-5.0.26/tools/convert-db.c ircservices-5.0.27/tools/convert-db.c --- ircservices-5.0.26/tools/convert-db.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/tools/convert-db.c 2003-12-03 11:48:46 +0900 @@ -8,6 +8,8 @@ */ #define CONVERT_DB_MAIN +#define STANDALONE_NICKSERV +#define STANDALONE_CHANSERV #include "convert-db.h" #include "language.h" #include "modules/misc/xml.h" @@ -115,22 +117,20 @@ * fail, aborts the program). */ +#include "modules/nickserv/util.c" + NickInfo *makenick(const char *nick, NickGroupInfo **nickgroup_ret) { - NickInfo *ni = scalloc(sizeof(*ni), 1); + NickInfo *ni = new_nickinfo(); strscpy(ni->nick, nick, sizeof(ni->nick)); if (nickgroup_ret) { - NickGroupInfo *ngi = scalloc(sizeof(*ngi), 1); - do { + NickGroupInfo *ngi = new_nickgroupinfo(ni->nick); + while (get_nickgroupinfo(ngi->id)) { /* We assume that eventually we'll find one that's not in use */ ngi->id = rand() + rand(); if (ngi->id == 0) ngi->id = 1; - } while (get_nickgroupinfo(ngi->id)); - ngi->memos.memomax = MEMOMAX_DEFAULT; - ngi->channelmax = CHANMAX_DEFAULT; - ngi->language = LANG_DEFAULT; - ngi->timezone = TIMEZONE_DEFAULT; + } ni->nickgroup = ngi->id; ARRAY_EXTEND(ngi->nicks); strscpy(ngi->nicks[0], nick, sizeof(ngi->nicks[0])); @@ -143,6 +143,19 @@ /*************************************************************************/ +/* ChannelInfo allocation. */ + +#include "modules/chanserv/util.c" + +ChannelInfo *makechan(const char *name) +{ + ChannelInfo *ci = new_channelinfo(); + strscpy(ci->name, name, sizeof(ci->name)); + return ci; +} + +/*************************************************************************/ + /* Open a (Services pre-5.0 style) data file and check the version number. * Prints an error message and exits with 1 if either the file cannot be * opened or the version number is wrong. If `version_ret' is non-NULL, @@ -516,6 +529,12 @@ int i; char oldpath[PATH_MAX+1], newpath[PATH_MAX+1]; +#ifdef CLEAN_COMPILE + free_nickinfo(NULL); + free_nickgroupinfo(NULL); + free_channelinfo(NULL); +#endif + /* Parse command-line parameters */ newac = 1; newav = malloc(sizeof(*newav) * ac); diff -uNr ircservices-5.0.26/tools/convert-db.h ircservices-5.0.27/tools/convert-db.h --- ircservices-5.0.26/tools/convert-db.h 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/tools/convert-db.h 2003-12-03 11:48:46 +0900 @@ -89,8 +89,11 @@ /* Safe string duplication. */ extern char *sstrdup(const char *s); -/* Allocate a new, cleared NickInfo (and possibly NickGroupInfo) structure. */ +/* Allocate a new, initialized NickInfo (and possibly NickGroupInfo) + * structure. */ extern NickInfo *makenick(const char *nick, NickGroupInfo **nickgroup_ret); +/* Allocate a new, initialized ChannelInfo structure. */ +extern ChannelInfo *makechan(const char *name); /* Open a (Services pre-5.0 style) data file and check the version number. * Prints an error message and exits with 1 if either the file cannot be diff -uNr ircservices-5.0.26/tools/convert-epona.c ircservices-5.0.27/tools/convert-epona.c --- ircservices-5.0.26/tools/convert-epona.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/tools/convert-epona.c 2003-12-03 11:48:46 +0900 @@ -240,9 +240,8 @@ while ((c = getc_db(f)) == 1) { char namebuf[64], passbuf[32], nickbuf[32]; - ci = scalloc(sizeof(ChannelInfo), 1); SAFE(read_buffer(namebuf, f)); - strscpy(ci->name, namebuf, CHANMAX); + ci = makechan(namebuf); SAFE(read_string(&s, f)); if (s) { ni = get_nickinfo(s); @@ -312,13 +311,11 @@ if (tmp32 & 0x00000800) ci->flags |= CI_OPNOTICE; if (tmp32 & 0x00010000) { - ci->suspendinfo = smalloc(sizeof(*ci->suspendinfo)); - strscpy(ci->suspendinfo->who, "", - sizeof(ci->suspendinfo->who)); - ci->suspendinfo->reason = - "Unknown, imported from Anope Services"; - ci->suspendinfo->suspended = time(NULL); - ci->suspendinfo->expires = 0; + ci->suspendinfo = new_suspendinfo( + "", + "Unknown, imported from Anope Services", + 0 + ); } SAFE(read_string(&s, f)); /* forbidby */ SAFE(read_string(&s, f)); /* forbidreason */ diff -uNr ircservices-5.0.26/tools/convert-magick.c ircservices-5.0.27/tools/convert-magick.c --- ircservices-5.0.26/tools/convert-magick.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/tools/convert-magick.c 2003-12-03 11:48:46 +0900 @@ -86,14 +86,11 @@ if (oldni.flags & 0x00000010) ngi->flags |= NF_PRIVATE; if (oldni.flags & 0x00000020) { - ngi->suspendinfo = scalloc(sizeof(SuspendInfo), 1); - strcpy(ngi->suspendinfo->who, ""); + ngi->suspendinfo = new_suspendinfo("", NULL, 0); ngi->suspendinfo->reason = (char *)( version==6 ? "Unknown (imported from Wrecked IRC Services)" : "Unknown (imported from Magick IRC Services)" ); - ngi->suspendinfo->suspended = time(NULL); - ngi->suspendinfo->expires = 0; } if (oldni.flags & 0x00000080) { ni->status |= 0x8000; /* Flag: this is a linked nick */ @@ -253,8 +250,7 @@ SAFE(read_string(&oldci.mlock_key, f)); if (oldci.topic) SAFE(read_string(&oldci.topic, f)); - ci = scalloc(sizeof(*ci), 1); - strscpy(ci->name, oldci.name, CHANMAX); + ci = makechan(oldci.name); if (*oldci.founder) { ni = get_nickinfo(oldci.founder); if (!ni) { @@ -308,14 +304,11 @@ if (oldci.flags & 0x00000080) ci->flags |= CI_VERBOTEN; if (oldci.flags & 0x00000100) { - ci->suspendinfo = scalloc(sizeof(SuspendInfo), 1); - strcpy(ci->suspendinfo->who, ""); + ci->suspendinfo = new_suspendinfo("", NULL, 0); ci->suspendinfo->reason = (char *)( version==6 ? "Unknown (imported from Wrecked IRC Services)" : "Unknown (imported from Magick IRC Services)" ); - ci->suspendinfo->suspended = time(NULL); - ci->suspendinfo->expires = 0; } if (oldci.flags & 0x00000400) ci->flags |= CI_NOEXPIRE; diff -uNr ircservices-5.0.26/tools/convert-ptlink.c ircservices-5.0.27/tools/convert-ptlink.c --- ircservices-5.0.26/tools/convert-ptlink.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/tools/convert-ptlink.c 2003-12-03 11:48:46 +0900 @@ -153,12 +153,12 @@ SAFE(read_int32(&tmp32, f)); /* online */ if (ngi->flags & 0x80000000) { ngi->flags &= ~0x80000000; - ngi->suspendinfo = scalloc(sizeof(SuspendInfo), 1); - strcpy(ngi->suspendinfo->who, ""); - ngi->suspendinfo->reason = - (char *)"Unknown (imported from PTlink IRC Services)"; - SAFE(read_int32(&tmp32, f)); - ngi->suspendinfo->expires = tmp32; + SAFE(read_int32(&tmp32, f)); /* expires */ + ngi->suspendinfo = new_suspendinfo( + "", + "Unknown (imported from PTlink IRC Services)", + tmp32 + ); } SAFE(read_int16(&ngi->ajoin_count, f)); ngi->ajoin = scalloc(sizeof(char *), ngi->ajoin_count); @@ -308,9 +308,8 @@ while ((c = getc_db(f)) == 1) { char namebuf[64], passbuf[32], nickbuf[32]; - ci = scalloc(sizeof(ChannelInfo), 1); SAFE(read_buffer(namebuf, f)); - strscpy(ci->name, namebuf, CHANMAX); + ci = makechan(namebuf); SAFE(read_string(&s, f)); if (s) { ni = get_nickinfo(s); diff -uNr ircservices-5.0.26/tools/convert-sirv.c ircservices-5.0.27/tools/convert-sirv.c --- ircservices-5.0.26/tools/convert-sirv.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/tools/convert-sirv.c 2003-12-03 11:48:46 +0900 @@ -184,12 +184,11 @@ if (oldni.flags & 0x00002000) ngi->flags |= NF_HIDE_MASK; if (type == TYPE_BOLIVIA && (oldni.flags & 0x00020000)) { - ngi->suspendinfo = smalloc(sizeof(*ngi->suspendinfo)); - strscpy(ngi->suspendinfo->who, "", NICKMAX); - ngi->suspendinfo->reason = - (char *)"Unknown (imported from Bolivia IRC Services)"; - ngi->suspendinfo->suspended = time(NULL); - ngi->suspendinfo->expires = 0; + ngi->suspendinfo = new_suspendinfo( + "", + "Unknown (imported from Bolivia IRC Services)", + 0 + ); } if (type == TYPE_AUSPICE && (oldni.flags & 0x00800000)) { /* Linked ("slave") nick; parent is in last_usermask */ @@ -497,8 +496,7 @@ if (ver >= 8 && oldci_auspice8.lastgetpass) SAFE(read_string(&oldci_auspice8.lastgetpass, f)); } - ci = scalloc(sizeof(*ci), 1); - strscpy(ci->name, oldci.name, CHANMAX); + ci = makechan(oldci.name); if (*oldci.founder) { ni = get_nickinfo(oldci.founder); if (!ni) { @@ -576,8 +574,7 @@ if (type == TYPE_SIRV && (oldci2.flags & 0x04000000)) ci->flags |= CI_ENFORCE; if (type != TYPE_BOLIVIA && (oldci2.flags & 0x08000000)) { - ci->suspendinfo = scalloc(sizeof(SuspendInfo), 1); - strcpy(ci->suspendinfo->who, ""); + ci->suspendinfo = new_suspendinfo("", NULL, 0); if (type == TYPE_AUSPICE) { ci->suspendinfo->reason = (char *)"Unknown (imported from Auspice Services)"; @@ -585,8 +582,6 @@ ci->suspendinfo->reason = (char *)"Unknown (imported from SirvNET IRC Services)"; } - ci->suspendinfo->suspended = time(NULL); - ci->suspendinfo->expires = 0; } ci->mlock_on = scalloc(64, 1); diff -uNr ircservices-5.0.26/tools/convert-trircd.c ircservices-5.0.27/tools/convert-trircd.c --- ircservices-5.0.26/tools/convert-trircd.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/tools/convert-trircd.c 2003-12-03 11:48:46 +0900 @@ -101,14 +101,14 @@ ngi->flags |= NF_MEMO_FWD | NF_MEMO_FWDCOPY; SAFE(read_ptr((void **)&ngi->suspendinfo, f)); if (ngi->suspendinfo) { - ngi->suspendinfo = scalloc(sizeof(SuspendInfo), 1); + char *reason; + int32 suspended, expires; SAFE(read_buffer(nickbuf, f)); - strscpy(ngi->suspendinfo->who, nickbuf, NICKMAX); - SAFE(read_string(&ngi->suspendinfo->reason, f)); - SAFE(read_int32(&tmp32, f)); - ngi->suspendinfo->suspended = tmp32; - SAFE(read_int32(&tmp32, f)); - ngi->suspendinfo->expires = tmp32; + SAFE(read_string(&reason, f)); + SAFE(read_int32(&suspended, f)); + SAFE(read_int32(&expires, f)); + ngi->suspendinfo = new_suspendinfo(nickbuf,reason,expires); + ngi->suspendinfo->suspended = suspended; } SAFE(read_int16(&ngi->access_count, f)); if (ngi->access_count) { @@ -314,9 +314,8 @@ char namebuf[64], passbuf[32], nickbuf[32]; while ((c = getc_db(f)) == 1) { - ci = scalloc(sizeof(ChannelInfo), 1); SAFE(read_buffer(namebuf, f)); - strscpy(ci->name, namebuf, CHANMAX); + ci = makechan(namebuf); SAFE(read_string(&s, f)); if (s) { ni = get_nickinfo(s); @@ -395,14 +394,14 @@ SAFE(read_ptr((void **)&ci->suspendinfo, f)); if (ci->suspendinfo) { - ci->suspendinfo = scalloc(sizeof(SuspendInfo), 1); + char *reason; + int32 suspended, expires; SAFE(read_buffer(nickbuf, f)); - strscpy(ci->suspendinfo->who, nickbuf, NICKMAX); - SAFE(read_string(&ci->suspendinfo->reason, f)); - SAFE(read_int32(&tmp32, f)); - ci->suspendinfo->suspended = tmp32; - SAFE(read_int32(&tmp32, f)); - ci->suspendinfo->expires = tmp32; + SAFE(read_string(&reason, f)); + SAFE(read_int32(&suspended, f)); + SAFE(read_int32(&expires, f)); + ci->suspendinfo = new_suspendinfo(nickbuf, reason, expires); + ci->suspendinfo->suspended = suspended; } SAFE(read_int16(&tmp16, f)); /* n_levels */ diff -uNr ircservices-5.0.26/tools/convert-ver8.c ircservices-5.0.27/tools/convert-ver8.c --- ircservices-5.0.26/tools/convert-ver8.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/tools/convert-ver8.c 2003-12-03 11:48:46 +0900 @@ -248,15 +248,14 @@ while ((c = getc_db(f)) == 1) { char nickbuf[32]; - ci = scalloc(sizeof(ChannelInfo), 1); if (type == TYPE_IRCS) { char namebuf[204]; SAFE(read_buffer(namebuf, f)); - strscpy(ci->name, namebuf, CHANMAX); + ci = makechan(namebuf); } else { char namebuf[64]; SAFE(read_buffer(namebuf, f)); - strscpy(ci->name, namebuf, CHANMAX); + ci = makechan(namebuf); } SAFE(read_string(&s, f)); if (s) { diff -uNr ircservices-5.0.26/users.c ircservices-5.0.27/users.c --- ircservices-5.0.26/users.c 2003-11-26 23:28:19 +0900 +++ ircservices-5.0.27/users.c 2003-12-03 11:48:45 +0900 @@ -132,6 +132,7 @@ free(user->username); free(user->host); + free(user->ipaddr); free(user->realname); free(user->fakehost); free(user->id_nicks); diff -uNr ircservices-5.0.26/version.sh ircservices-5.0.27/version.sh --- ircservices-5.0.26/version.sh 2003-11-26 23:22:49 +0900 +++ ircservices-5.0.27/version.sh 2003-12-03 11:28:48 +0900 @@ -6,7 +6,7 @@ # $PROGRAM is the string returned as the first part of a /VERSION reply, # and must not contain spaces. It is not used anywhere else. PROGRAM=ircservices -VERSION=5.0.26 +VERSION=5.0.27 # Increment Services build number if [ -f version.c ] ; then