X-Git-Url: https://jfr.im/git/irc/quakenet/snircd-patchqueue.git/blobdiff_plain/4fef253326cdece44962e223a232686dd37da462..540990d59da7b6ed6a206e3650a2e970bb082de5:/welcome.patch diff --git a/welcome.patch b/welcome.patch index b9ca20a..a07b69a 100644 --- a/welcome.patch +++ b/welcome.patch @@ -77,7 +77,7 @@ ircd/ircd_lexer.l ircd/ircd_parser.y add PRIV_LOCAL_WELCOME PRIV_WELCOME -diff -r 4676d2565f9b include/client.h +diff -r 93eb31739cc6 include/client.h --- a/include/client.h +++ b/include/client.h @@ -142,6 +142,8 @@ @@ -89,7 +89,7 @@ diff -r 4676d2565f9b include/client.h PRIV_LAST_PRIV /**< number of privileges */ }; -diff -r 4676d2565f9b include/handlers.h +diff -r 93eb31739cc6 include/handlers.h --- a/include/handlers.h +++ b/include/handlers.h @@ -138,6 +138,7 @@ @@ -116,7 +116,7 @@ diff -r 4676d2565f9b include/handlers.h extern int ms_whois(struct Client*, struct Client*, int, char*[]); extern int ms_xquery(struct Client*, struct Client*, int, char*[]); extern int ms_xreply(struct Client*, struct Client*, int, char*[]); -diff -r 4676d2565f9b include/ircd_features.h +diff -r 93eb31739cc6 include/ircd_features.h --- a/include/ircd_features.h +++ b/include/ircd_features.h @@ -101,6 +101,7 @@ @@ -135,7 +135,7 @@ diff -r 4676d2565f9b include/ircd_features.h FEAT_HIS_STATS_w, FEAT_HIS_STATS_x, FEAT_HIS_STATS_y, -diff -r 4676d2565f9b include/msg.h +diff -r 93eb31739cc6 include/msg.h --- a/include/msg.h +++ b/include/msg.h @@ -196,6 +196,10 @@ @@ -149,7 +149,7 @@ diff -r 4676d2565f9b include/msg.h #define MSG_WALLCHOPS "WALLCHOPS" /* WC */ #define TOK_WALLCHOPS "WC" #define CMD_WALLCHOPS MSG_WALLCHOPS, TOK_WALLCHOPS -diff -r 4676d2565f9b include/numeric.h +diff -r 93eb31739cc6 include/numeric.h --- a/include/numeric.h +++ b/include/numeric.h @@ -116,6 +116,7 @@ @@ -169,10 +169,10 @@ diff -r 4676d2565f9b include/numeric.h #define ERR_SILELISTFULL 511 /* Undernet extension */ /* ERR_NOTIFYFULL 512 aircd */ /* ERR_TOOMANYWATCH 512 Numeric List: Dalnet */ -diff -r 4676d2565f9b include/welcome.h +diff -r 93eb31739cc6 include/welcome.h --- /dev/null +++ b/include/welcome.h -@@ -0,0 +1,63 @@ +@@ -0,0 +1,75 @@ +#ifndef INCLUDED_welcome_h +#define INCLUDED_welcome_h +/* @@ -210,10 +210,22 @@ diff -r 4676d2565f9b include/welcome.h +#define WELCOME_MAX_ENTRIES 10 +/* Maximum length of a welcome message */ +#define WELCOMELEN TOPICLEN -+/* Maximum timestamp drift in seconds allowed ahead of our idea of nettime -+ * before we throw a warning to ops -+ */ -+#define WELCOME_MAX_DRIFT 600 ++ ++ ++/* Test if a welcome entry is in a valid range */ ++#define WelcomeIsValid(x) ((unsigned) (x) <= 2 * WELCOME_MAX_ENTRIES -1) ++/* Test if a welcome entry is set */ ++#define WelcomeIsSet(x) (WelcomeArray[(x)].timestamp > 0) ++/* Test if a welcome entry is empty */ ++#define WelcomeIsEmpty(x) (*WelcomeArray[(x)].text == 0) ++ ++/* Get welcome timestamp */ ++#define WelcomeTS(x) (WelcomeArray[(x)].timestamp) ++/* Get welcome text */ ++#define WelcomeText(x) (WelcomeArray[(x)].text) ++/* Get welcome who info */ ++#define WelcomeWho(x) (WelcomeArray[(x)].who) ++ + +/* Describes a Welcome message entry. */ +struct Welcome { @@ -236,7 +248,7 @@ diff -r 4676d2565f9b include/welcome.h +extern void welcome_stats(struct Client *sptr, const struct StatDesc *sd, char *param); + +#endif /* INCLUDED_welcome_h */ -diff -r 4676d2565f9b ircd/Makefile.in +diff -r 93eb31739cc6 ircd/Makefile.in --- a/ircd/Makefile.in +++ b/ircd/Makefile.in @@ -186,6 +186,7 @@ @@ -281,7 +293,7 @@ diff -r 4676d2565f9b ircd/Makefile.in whocmds.o: whocmds.c ../config.h ../include/whocmds.h \ ../include/channel.h ../include/ircd_defs.h ../include/res.h \ ../config.h ../include/client.h ../include/dbuf.h ../include/msgq.h \ -diff -r 4676d2565f9b ircd/client.c +diff -r 93eb31739cc6 ircd/client.c --- a/ircd/client.c +++ b/ircd/client.c @@ -177,6 +177,7 @@ @@ -309,7 +321,7 @@ diff -r 4676d2565f9b ircd/client.c #undef P { 0, 0 } }; -diff -r 4676d2565f9b ircd/ircd_features.c +diff -r 93eb31739cc6 ircd/ircd_features.c --- a/ircd/ircd_features.c +++ b/ircd/ircd_features.c @@ -366,6 +366,7 @@ @@ -328,7 +340,7 @@ diff -r 4676d2565f9b ircd/ircd_features.c F_B(HIS_STATS_w, 0, 1, 0), F_B(HIS_STATS_x, 0, 1, 0), F_B(HIS_STATS_y, 0, 1, 0), -diff -r 4676d2565f9b ircd/ircd_lexer.l +diff -r 93eb31739cc6 ircd/ircd_lexer.l --- a/ircd/ircd_lexer.l +++ b/ircd/ircd_lexer.l @@ -166,6 +166,8 @@ @@ -340,7 +352,7 @@ diff -r 4676d2565f9b ircd/ircd_lexer.l { NULL, 0 } }; static int ntokens; -diff -r 4676d2565f9b ircd/ircd_parser.y +diff -r 93eb31739cc6 ircd/ircd_parser.y --- a/ircd/ircd_parser.y +++ b/ircd/ircd_parser.y @@ -189,6 +189,7 @@ @@ -360,10 +372,10 @@ diff -r 4676d2565f9b ircd/ircd_parser.y TPRIV_PARANOID { $$ = PRIV_PARANOID; } ; yesorno: YES { $$ = 1; } | NO { $$ = 0; }; -diff -r 4676d2565f9b ircd/m_welcome.c +diff -r 93eb31739cc6 ircd/m_welcome.c --- /dev/null +++ b/ircd/m_welcome.c -@@ -0,0 +1,296 @@ +@@ -0,0 +1,292 @@ +/* + * IRC - Internet Relay Chat, ircd/m_welcome.c + * Copyright (C) 1990 Jarkko Oikarinen and @@ -567,16 +579,12 @@ diff -r 4676d2565f9b ircd/m_welcome.c + flags |= WELCOME_LOCAL; + } + -+ /* TODO: disallow global announcement from oper? -+ * as PRIVMSG/NOTICE to $* is not allowed either by the ircd -+ * when PRIV for that is added, use that here? PRIV_BROADCAST or something -+ * -+ * change prefix to $ ? -+ */ + /* check for anounce prefix */ -+ if (*name == '!') { ++ if (*name == '$') { + name++; -+ flags |= WELCOME_ANNOUNCE; ++ /* only allow announce by oper for local welcome */ ++ if (flags & WELCOME_LOCAL) ++ flags |= WELCOME_ANNOUNCE; + } + + /* check for insert prefix */ @@ -646,7 +654,7 @@ diff -r 4676d2565f9b ircd/m_welcome.c + } + + /* check for anounce prefix */ -+ if (*name == '!') { ++ if (*name == '$') { + name++; + flags |= WELCOME_ANNOUNCE; + } @@ -660,7 +668,7 @@ diff -r 4676d2565f9b ircd/m_welcome.c + /* and do it */ + return welcome_do(cptr, sptr, name, timestamp, who, text, flags); +} -diff -r 4676d2565f9b ircd/parse.c +diff -r 93eb31739cc6 ircd/parse.c --- a/ircd/parse.c +++ b/ircd/parse.c @@ -661,6 +661,15 @@ @@ -679,7 +687,7 @@ diff -r 4676d2565f9b ircd/parse.c /* This command is an alias for QUIT during the unregistered part of * of the server. This is because someone jumping via a broken web -diff -r 4676d2565f9b ircd/s_err.c +diff -r 93eb31739cc6 ircd/s_err.c --- a/ircd/s_err.c +++ b/ircd/s_err.c @@ -486,7 +486,7 @@ @@ -700,7 +708,7 @@ diff -r 4676d2565f9b ircd/s_err.c /* 510 */ { 0 }, /* 511 */ -diff -r 4676d2565f9b ircd/s_serv.c +diff -r 93eb31739cc6 ircd/s_serv.c --- a/ircd/s_serv.c +++ b/ircd/s_serv.c @@ -57,6 +57,7 @@ @@ -719,7 +727,7 @@ diff -r 4676d2565f9b ircd/s_serv.c /* * Pass on my client information to the new server -diff -r 4676d2565f9b ircd/s_stats.c +diff -r 93eb31739cc6 ircd/s_stats.c --- a/ircd/s_stats.c +++ b/ircd/s_stats.c @@ -54,6 +54,7 @@ @@ -744,7 +752,7 @@ diff -r 4676d2565f9b ircd/s_stats.c { 'x', "memusage", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_x, stats_meminfo, 0, "List usage information." }, -diff -r 4676d2565f9b ircd/s_user.c +diff -r 93eb31739cc6 ircd/s_user.c --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -63,6 +63,7 @@ @@ -765,10 +773,10 @@ diff -r 4676d2565f9b ircd/s_user.c } else { struct Client *acptr = user->server; -diff -r 4676d2565f9b ircd/welcome.c +diff -r 93eb31739cc6 ircd/welcome.c --- /dev/null +++ b/ircd/welcome.c -@@ -0,0 +1,584 @@ +@@ -0,0 +1,628 @@ +/* + * IRC - Internet Relay Chat, ircd/welcome.c + * Copyright (C) 1990 Jarkko Oikarinen and @@ -832,8 +840,9 @@ diff -r 4676d2565f9b ircd/welcome.c +static int +welcome_make(int name, char *text, char *who, time_t timestamp) +{ -+ /* range 0 to 2 * max - 1 */ -+ assert(name >= 0 && name <= 2 * WELCOME_MAX_ENTRIES - 1); ++ assert(WelcomeIsValid(name)); ++ assert(NULL != text); ++ assert(NULL != who); + + /* store it */ + ircd_strncpy(WelcomeArray[name].text, text, WELCOMELEN); @@ -858,26 +867,51 @@ diff -r 4676d2565f9b ircd/welcome.c +welcome_propagate(struct Client *cptr, struct Client *sptr, int nameint, + time_t timestamp, char *who, char *text, unsigned int flags) +{ ++ assert(NULL != sptr); ++ assert(NULL != cptr); ++ assert(nameint > 0 && nameint <= WELCOME_MAX_ENTRIES); + assert(!(flags & WELCOME_LOCAL)); + + sendcmdto_serv_butone(sptr, CMD_WELCOME, cptr, "* %s%s%d %Tu %s :%s", -+ (flags & WELCOME_ANNOUNCE) ? "!" : "", (flags & WELCOME_INSERT) ? "+" : "", ++ (flags & WELCOME_ANNOUNCE) ? "$" : "", (flags & WELCOME_INSERT) ? "+" : "", + nameint, timestamp, who, text); + + return 0; +} + + ++/** Resend a welcome message. ++ * @param[in] cptr Local client that sent us the welcome. ++ * @param[in] nameint Name of the message. ++ * @param[in] namearray Name of the array item. ++ * @return Zero ++ */ ++int ++welcome_resend(struct Client *cptr, int nameint, int namearray) ++{ ++ assert(NULL != cptr); ++ assert(IsServer(cptr)); ++ assert(nameint > 0 && nameint <= WELCOME_MAX_ENTRIES); ++ assert(WelcomeIsValid(namearray)); ++ ++ sendcmdto_one(&me, CMD_WELCOME, cptr, "* %d %Tu %s :%s", ++ nameint, WelcomeTS(namearray), WelcomeWho(namearray), WelcomeText(namearray)); ++ ++ return 0; ++} ++ ++ +/** Log a welcome message. + * @param[in] sptr Originator of the welcome. + * @param[in] msg The message to show. -+ * @param[in] who Who set this message. + * @param[in] flags Flags to set on welcome. + * @return Zero + */ +int -+welcome_log(struct Client *sptr, char *msg, char *who, unsigned int flags) ++welcome_log(struct Client *sptr, char *msg, unsigned int flags) +{ ++ assert(NULL != sptr); ++ assert(NULL != msg); + + /* inform ops */ + sendto_opmask_butone(0, SNO_OLDSNO, "%s %s", @@ -885,7 +919,7 @@ diff -r 4676d2565f9b ircd/welcome.c + get_client_name_and_opername(sptr) : cli_name((cli_user(sptr))->server), msg); + + /* log it */ -+ log_write(LS_NETWORK, L_INFO, LOG_NOSNOTICE, "%#C (%s) %s", sptr, who, msg); ++ log_write(LS_NETWORK, L_INFO, LOG_NOSNOTICE, "%s %s", get_client_name_and_opername(sptr), msg); + + /* welcome by remote user, inform oper of success */ + if ((flags & WELCOME_LOCAL) && IsUser(sptr) && !MyUser(sptr)) { @@ -916,29 +950,34 @@ diff -r 4676d2565f9b ircd/welcome.c +welcome_set(struct Client *cptr, struct Client *sptr, int nameint, + int namearray, time_t timestamp, char *who, char *text, unsigned int flags) +{ -+ char msg[BUFSIZE]; /* msg for snomask, logging, etc. */ ++ char msg[BUFSIZE]; /* msg for logging */ + int new = 0; + ++ assert(NULL != cptr); ++ assert(NULL != sptr); ++ assert(nameint > 0 && nameint <= WELCOME_MAX_ENTRIES); ++ assert(WelcomeIsValid(namearray)); ++ + /* debug */ + Debug((DEBUG_DEBUG, "welcome_set(\"%s\", \"%s\", %d, %d, %Tu, \"%s\", \"%s\", 0x%04x)", + cli_name(cptr), cli_name(sptr), nameint, namearray, timestamp, who, text, flags)); + + /* not set */ -+ if (*WelcomeArray[namearray].text == 0) ++ if (WelcomeIsEmpty(namearray)) + new = 1; + + /* update */ + welcome_make(namearray, text, who, timestamp); + -+ /* create msg for snomask, logging, etc. */ -+ ircd_snprintf(0, msg, 0, "%s%s%s WELCOME %d \"%s\" [%Tu]", ++ /* create msg for log */ ++ ircd_snprintf(0, msg, 0, "%s%s%s WELCOME %d \"%s\" %s [%Tu]", + new ? "setting" : "changing", + (flags & WELCOME_ANNOUNCE) ? " and announcing " : " ", + (flags & WELCOME_LOCAL) ? "local" : "global", -+ nameint, text, timestamp); ++ nameint, WelcomeText(namearray), WelcomeWho(namearray), timestamp); + + /* log it */ -+ welcome_log(sptr, msg, who, flags); ++ welcome_log(sptr, msg, flags); + + /* propagate it */ + if (!(flags & WELCOME_LOCAL)) @@ -966,29 +1005,31 @@ diff -r 4676d2565f9b ircd/welcome.c +welcome_unset(struct Client *cptr, struct Client *sptr, int nameint, + int namearray, time_t timestamp, char *who, unsigned int flags) +{ -+ char msg[BUFSIZE]; /* msg for snomask, logging, etc. */ -+ char text[WELCOMELEN + 1]; /* save old text */ ++ char msg[BUFSIZE]; /* msg for logging */ + int i; /* loop variable */ -+ int empty = namearray; /* first empty spot in array after arrayname */ ++ int empty = namearray; /* first empty spot in array after namearray */ + int end = WELCOME_MAX_ENTRIES -1; /* last element to check in array */ + ++ assert(NULL != cptr); ++ assert(NULL != sptr); ++ assert(nameint > 0 && nameint <= WELCOME_MAX_ENTRIES); ++ assert(WelcomeIsValid(namearray)); ++ + /* debug */ + Debug((DEBUG_DEBUG, "welcome_unset(\"%s\", \"%s\", %d, %d, %Tu, \"%s\", 0x%04x)", + cli_name(cptr), cli_name(sptr), nameint, namearray, timestamp, who, flags)); + -+ /* save text */ -+ ircd_strncpy(text, WelcomeArray[namearray].text, WELCOMELEN); ++ /* create msg for log */ ++ ircd_snprintf(0, msg, 0, "unsetting %s WELCOME %d \"%s\" %s [%Tu]", ++ (flags & WELCOME_LOCAL) ? "local" : "global", ++ nameint, WelcomeText(namearray), WelcomeWho(namearray), timestamp); ++ ++ /* log it */ ++ welcome_log(sptr, msg, flags); + + /* update */ + welcome_make(namearray, "", who, timestamp); + -+ /* create msg for snomask, logging, etc. */ -+ ircd_snprintf(0, msg, 0, "unsetting %s WELCOME %d \"%s\" [%Tu]", -+ (flags & WELCOME_LOCAL) ? "local" : "global", nameint, text, timestamp); -+ -+ /* log it */ -+ welcome_log(sptr, msg, who, flags); -+ + /* propagate it, but not when inserting */ + if (!(flags & (WELCOME_LOCAL|WELCOME_INSERT))) + welcome_propagate(cptr, sptr, nameint, timestamp, who, "", flags); @@ -997,11 +1038,11 @@ diff -r 4676d2565f9b ircd/welcome.c + if (flags & WELCOME_LOCAL) + end += WELCOME_MAX_ENTRIES; + -+ /* found first empty spot */ ++ /* move entries up, update timestamp */ + for (i = namearray; i < end; i++) -+ welcome_make(i, WelcomeArray[i+1].text, WelcomeArray[i+1].who, timestamp); ++ welcome_make(i, WelcomeText(i+1), WelcomeWho(i+1), timestamp); + -+ /* clear last entry */ ++ /* clear last entry, update timestamp */ + welcome_make(end, "", who, timestamp); + + return 0; @@ -1023,12 +1064,17 @@ diff -r 4676d2565f9b ircd/welcome.c +welcome_insert(struct Client *cptr, struct Client *sptr, int nameint, + int namearray, time_t timestamp, char *who, char *text, unsigned int flags) +{ -+ char msg[BUFSIZE]; /* msg for snomask, logging, etc. */ ++ char msg[BUFSIZE]; /* msg for logging */ + int i; /* loop variable */ -+ int empty = -1; /* first empty spot in array after arrayname */ ++ int empty = -1; /* first empty spot in array after namearray */ + int end = WELCOME_MAX_ENTRIES -1; /* last element to check in array */ + int last = end; /* last welcome message to feed to welcome_unset */ + ++ assert(NULL != cptr); ++ assert(NULL != sptr); ++ assert(nameint > 0 && nameint <= WELCOME_MAX_ENTRIES); ++ assert(WelcomeIsValid(namearray)); ++ + /* debug */ + Debug((DEBUG_DEBUG, "welcome_insert(\"%s\", \"%s\", %d, %d, %Tu, \"%s\", \"%s\", 0x%04x)", + cli_name(cptr), cli_name(sptr), nameint, namearray, timestamp, who, text, flags)); @@ -1037,9 +1083,9 @@ diff -r 4676d2565f9b ircd/welcome.c + if (flags & WELCOME_LOCAL) + end += WELCOME_MAX_ENTRIES; + -+ /* found first empty spot */ ++ /* find first empty spot */ + for (i = namearray; i <= end; i++) { -+ if (*WelcomeArray[i].text == 0) { ++ if (WelcomeIsEmpty(i)) { + empty = i; + break; + } @@ -1053,13 +1099,13 @@ diff -r 4676d2565f9b ircd/welcome.c + + /* move entries down, update timestamp */ + for (i = empty; i > namearray; i--) -+ welcome_make(i, WelcomeArray[i-1].text, WelcomeArray[i-1].who, timestamp); ++ welcome_make(i, WelcomeText(i-1), WelcomeWho(i-1), timestamp); + + /* correct empty for local offset */ + if (flags & WELCOME_LOCAL) + empty -= WELCOME_MAX_ENTRIES; + -+ /* create msg for snomask, logging, etc. */ ++ /* create msg for log */ + if (nameint == empty) + ircd_snprintf(0, msg, 0, "moving %s WELCOME message %d one place down", + (flags & WELCOME_LOCAL) ? "local" : "global", nameint); @@ -1068,7 +1114,7 @@ diff -r 4676d2565f9b ircd/welcome.c + (flags & WELCOME_LOCAL) ? "local" : "global", nameint, (empty - nameint > 1) ? "to" : "and" , empty); + + /* log it */ -+ welcome_log(sptr, msg, who, flags); ++ welcome_log(sptr, msg, flags); + + /* set it */ + welcome_set(cptr, sptr, nameint, namearray, timestamp, who, text, flags); @@ -1093,7 +1139,6 @@ diff -r 4676d2565f9b ircd/welcome.c +{ + int nameint = atoi(name); /* transform to int */ + int namearray = nameint - 1; /* used to test the array element */ -+ static time_t rate; /* rate limit snomask message */ + + assert(NULL != cptr); + assert(NULL != sptr); @@ -1105,6 +1150,10 @@ diff -r 4676d2565f9b ircd/welcome.c + Debug((DEBUG_DEBUG, "welcome_do(\"%s\", \"%s\", \"%s\", %Tu, \"%s\", \"%s\", 0x%04x)", + cli_name(cptr), cli_name(sptr), name, timestamp, who, text, flags)); + ++ /* if for some reason timestamp is 0, increase it */ ++ if (timestamp == 0) ++ timestamp++; ++ + /* name empty after taking off the prefixes? */ + if (EmptyString(name)) { + if (IsUser(sptr)) @@ -1115,21 +1164,26 @@ diff -r 4676d2565f9b ircd/welcome.c + } + + /* check name */ -+ if (nameint < 1 || nameint > WELCOME_MAX_ENTRIES) { ++ if (!WelcomeIsValid(namearray)) { + if (IsUser(sptr)) + sendcmdto_one(&me, CMD_NOTICE, sptr, + "%C :WELCOME: Invalid message number %s - should between 1 and %d", + sptr, name, WELCOME_MAX_ENTRIES); -+ else { -+ protocol_violation(cptr, "WELCOME: Invalid message number %s from %C - should be between 1 and %d", ++ else ++ protocol_violation(cptr, ++ "WELCOME: Invalid message number %s from %C - should be between 1 and %d", + name, sptr, WELCOME_MAX_ENTRIES); -+ /* nameint greater than MAX, perhaps we are upgrading, but used extra slots too soon? -+ * propagate it manually -+ * TODO: cant do announce here? -+ */ -+ if (nameint > WELCOME_MAX_ENTRIES && !(flags & WELCOME_LOCAL)) -+ welcome_propagate(cptr, sptr, nameint, timestamp, who, text, flags); -+ } ++ return 0; ++ } ++ ++ /* source is user, and is myuser or welcome is local, check length of the message */ ++ if ((IsUser(sptr)) && ((MyUser(sptr)) || (flags & WELCOME_LOCAL)) && (strlen(text) > WELCOMELEN)) { ++ sendcmdto_one(&me, CMD_NOTICE, sptr, ++ "%C :WELCOME: The message is too long with %d chars - max is %d chars", ++ sptr, strlen(text), WELCOMELEN); ++ ircd_strncpy(text, text, WELCOMELEN); ++ sendcmdto_one(&me, CMD_NOTICE, sptr, ++ "%C :WELCOME: Change or truncate the message to: \"%s\"", sptr, text); + return 0; + } + @@ -1138,10 +1192,11 @@ diff -r 4676d2565f9b ircd/welcome.c + namearray += WELCOME_MAX_ENTRIES; + + /* must be true by now */ -+ assert(namearray >= 0 && namearray <= 2 * WELCOME_MAX_ENTRIES - 1); ++ assert(WelcomeIsValid(namearray)); ++ assert(nameint > 0 && nameint <= WELCOME_MAX_ENTRIES); + + /* cannot unset welcome that is not set */ -+ if (WelcomeArray[namearray].timestamp == 0 && EmptyString(text)) { ++ if (!WelcomeIsSet(namearray) && EmptyString(text)) { + + /* from user, throw error */ + if (IsUser(sptr)) @@ -1156,61 +1211,60 @@ diff -r 4676d2565f9b ircd/welcome.c + + /* check if there is something to change */ + /* we got a record for it */ -+ if (WelcomeArray[namearray].timestamp != 0) { ++ if (WelcomeIsSet(namearray)) { + + /* global */ + if (!(flags & WELCOME_LOCAL)) { + -+ /* netburst and we got the same or a newer one -+ * -+ * we only use the timestamp for resolving conflicts in net burst -+ * outside of netburst, we simply parse whatever we get -+ * this way we will not get stuck with a welcome message set by a server -+ * running ahead with the time ++ /* myuser changes it, ++ * welcomeTS greater than or equal to timestamp, take welcomeTS+1 as timestamp ++ * else the change is not accepted upstream because of the older TS + */ -+ if (IsBurstOrBurstAck(cptr) && timestamp <= WelcomeArray[namearray].timestamp) -+ return 0; ++ if (MyUser(sptr)) { ++ if (WelcomeTS(namearray) >= timestamp) ++ timestamp = WelcomeTS(namearray) +1; ++ } ++ ++ /* compare timestamps, ignore welcome when: ++ * we got a newer one ++ * or when timestamps are the same and our text is 'smaller' ++ */ ++ else if ((timestamp < WelcomeTS(namearray)) || /* we got a newer one */ ++ ((timestamp == WelcomeTS(namearray)) && /* same timestamp */ ++ (strcmp(WelcomeText(namearray), text) < 0))) { /* our text is 'smaller' */ ++ /* burst or burst ack, cptr gets our version from the burst */ ++ if (IsBurstOrBurstAck(cptr)) ++ return 0; ++ /* sync server */ ++ return welcome_resend(cptr, nameint, namearray); ++ } + + /* local welcome - we use our idea of the time */ + } else + timestamp = TStime(); + -+ /* compare new message with old message */ -+ if (ircd_strcmp(text, WelcomeArray[namearray].text) == 0) { -+ if (IsUser(sptr)) ++ /* new global welcome from my user or local welcome ++ * compare new message with old message ++ */ ++ if (IsUser(sptr) && (MyUser(sptr) || (flags & WELCOME_LOCAL))) { ++ if (strcmp(text, WelcomeText(namearray)) == 0) { /* use strcmp because the user may wish to change case */ + sendcmdto_one(&me, CMD_NOTICE, sptr, -+ "%C :WELCOME: Cannot change %s message for %s - nothing to change.", ++ "%C :WELCOME: Cannot change %s message for %s - nothing to change", + sptr, (flags & WELCOME_LOCAL) ? "local" : "global", name); -+ return 0; ++ return 0; ++ } + } + } + + /* do not insert for last global/local entry and when not set yet */ -+ if (flags & WELCOME_INSERT) { -+ if ((WelcomeArray[namearray].timestamp == 0) || -+ (!(flags & WELCOME_LOCAL) && nameint == WELCOME_MAX_ENTRIES) || -+ ((flags & WELCOME_LOCAL) && nameint == 2 * WELCOME_MAX_ENTRIES)) -+ flags &= ~WELCOME_INSERT; -+ } -+ -+ /* TODO: rate limited for what? max 10 welcome messages..? */ -+ /* possible timestamp drift - warn ops */ -+ if (timestamp - TStime() > WELCOME_MAX_DRIFT) { -+ sendto_opmask_butone_ratelimited(0, SNO_NETWORK, &rate, -+ "Possible timestamp drift from %C; timestamp in WELCOME message is %is ahead of time", -+ IsServer(sptr) ? sptr : cli_user(sptr)->server, timestamp - TStime()); -+ -+ /* warn remote oper too */ -+ if (IsUser(sptr)) -+ sendcmdto_one(&me, CMD_NOTICE, sptr, -+ "%C :Possible timestamp drift from %C; timestamp in WELCOME message is %is ahead of time", -+ sptr, cli_user(sptr)->server, timestamp - TStime()); -+ } ++ if ((flags & WELCOME_INSERT) && ++ ((!WelcomeIsSet(namearray)) || (nameint == WELCOME_MAX_ENTRIES))) ++ flags &= ~WELCOME_INSERT; + + /* unset */ + if (EmptyString(text)) { + /* clear insert flag, -+ * when this flag is set, welcome_set() assumes it is being called from welcome_insert() ++ * when this flag is set, welcome_unset() assumes it is being called from welcome_insert() + * and wont propagate the change + */ + flags &= ~WELCOME_INSERT; @@ -1236,8 +1290,10 @@ diff -r 4676d2565f9b ircd/welcome.c + struct MsgBuf *msgbuf; + int i; + -+ /* range 0 to 2 * max - 1 */ -+ assert(name >= 0 && name <= 2 * WELCOME_MAX_ENTRIES - 1); ++ /* valid range, set and not empty */ ++ assert(WelcomeIsValid(name)); ++ assert(WelcomeIsSet(name)); ++ assert(!WelcomeIsEmpty(name)); + + /* TODO: target is $* as if it were a global broadcast + * could make it $servername for local message announcement @@ -1247,14 +1303,12 @@ diff -r 4676d2565f9b ircd/welcome.c + /* build msgbuf */ + msgbuf = msgq_make(0, ":%C %s $* :[%s] %s", &me, MSG_NOTICE, + name >= WELCOME_MAX_ENTRIES ? cli_name(&me) : feature_str(FEAT_NETWORK), -+ WelcomeArray[name].text); ++ WelcomeText(name)); + + /* go over local clients */ + for (i = HighestFd; i > 0; --i) { + -+ /* skip unregistered clients - they see the message during login -+ * skip servers -+ */ ++ /* skip unregistered clients, skip servers */ + if (!(acptr = LocalClientArray[i]) || !IsRegistered(acptr) || IsServer(acptr)) + continue; + @@ -1276,10 +1330,9 @@ diff -r 4676d2565f9b ircd/welcome.c + + /* loop over global entries - 0 to max - 1*/ + for (name = 0; name <= WELCOME_MAX_ENTRIES - 1; name++) { -+ if (WelcomeArray[name].timestamp != 0) ++ if (WelcomeIsSet(name)) + sendcmdto_one(&me, CMD_WELCOME, cptr, "* %d %Tu %s :%s", -+ name + 1, WelcomeArray[name].timestamp, WelcomeArray[name].who, -+ WelcomeArray[name].text); ++ name + 1, WelcomeTS(name), WelcomeWho(name), WelcomeText(name)); + } +} + @@ -1304,14 +1357,13 @@ diff -r 4676d2565f9b ircd/welcome.c + local = 1; + + /* not set or empty - skip */ -+ /* TODO: EmptyString? */ -+ if (WelcomeArray[name].timestamp == 0 || *WelcomeArray[name].text == 0) ++ if (!WelcomeIsSet(name) || WelcomeIsEmpty(name)) + continue; + + /* got one */ + found++; + sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :[%s] %s", -+ sptr, local ? cli_name(&me) : feature_str(FEAT_NETWORK), WelcomeArray[name].text); ++ sptr, local ? cli_name(&me) : feature_str(FEAT_NETWORK), WelcomeText(name)); + } + + /* nothing set */ @@ -1342,14 +1394,14 @@ diff -r 4676d2565f9b ircd/welcome.c + local = 1; + + /* not set */ -+ if (WelcomeArray[name].timestamp == 0) ++ if (!WelcomeIsSet(name)) + continue; + + /* send it */ + send_reply(sptr, RPL_STATSWELCOME, + local ? name + 1 - WELCOME_MAX_ENTRIES : name + 1, + local ? cli_name(&me) : "*", -+ WelcomeArray[name].who, WelcomeArray[name].timestamp, -+ EmptyString(WelcomeArray[name].text) ? "" : WelcomeArray[name].text); ++ WelcomeWho(name), WelcomeTS(name), ++ WelcomeIsEmpty(name) ? "" : WelcomeText(name)); + } +}