From: wiebe Date: Mon, 5 Apr 2010 16:51:04 +0000 (+0200) Subject: welcome: moved unsetting to welcome_unset and setting/changing to welcome_set X-Git-Url: https://jfr.im/git/irc/quakenet/snircd-patchqueue.git/commitdiff_plain/c13e460205387d9886cefe4b78e70feddfa84b71?hp=c9c8d34ba0a6c3b8dcec05a92cdb9bfb31007777 welcome: moved unsetting to welcome_unset and setting/changing to welcome_set --- diff --git a/welcome.patch b/welcome.patch index 7b34e24..0314b6b 100644 --- a/welcome.patch +++ b/welcome.patch @@ -228,8 +228,8 @@ diff -r 4676d2565f9b include/welcome.h +#define WELCOME_ANNOUNCE 0x02 /**< announce change to users */ +#define WELCOME_INSERT 0x04 /**< insert welcome message, move down all others one place */ + -+extern int welcome_do(struct Client *cptr, struct Client *sptr, char *name, char *text, -+ char *who, time_t timestamp, unsigned int flags, int insert); ++extern int welcome_do(struct Client *cptr, struct Client *sptr, char *name, ++ time_t timestamp, char *who, char *text, unsigned int flags); +extern void welcome_announce(int name); +extern void welcome_burst(struct Client *cptr); +extern int welcome_list(struct Client *sptr, int connect); @@ -586,7 +586,7 @@ diff -r 4676d2565f9b ircd/m_welcome.c + } + + /* and do it */ -+ return welcome_do(cptr, sptr, name, text, who, timestamp, flags, 0); ++ return welcome_do(cptr, sptr, name, timestamp, who, text, flags); +} + + @@ -658,7 +658,7 @@ diff -r 4676d2565f9b ircd/m_welcome.c + } + + /* and do it */ -+ return welcome_do(cptr, sptr, name, text, who, timestamp, flags, 0); ++ return welcome_do(cptr, sptr, name, timestamp, who, text, flags); +} diff -r 4676d2565f9b ircd/parse.c --- a/ircd/parse.c @@ -768,7 +768,7 @@ diff -r 4676d2565f9b ircd/s_user.c diff -r 4676d2565f9b ircd/welcome.c --- /dev/null +++ b/ircd/welcome.c -@@ -0,0 +1,480 @@ +@@ -0,0 +1,582 @@ +/* + * IRC - Internet Relay Chat, ircd/welcome.c + * Copyright (C) 1990 Jarkko Oikarinen and @@ -844,150 +844,126 @@ diff -r 4676d2565f9b ircd/welcome.c +} + + -+/** Change a welcome message. ++/** Propagate a welcome message. + * @param[in] cptr Local client that sent us the welcome. + * @param[in] sptr Originator of the welcome. -+ * @param[in] name Name of the message. -+ * @param[in] text The welcome message. -+ * @param[in] who Who set this message. ++ * @param[in] nameint Name of the message. + * @param[in] timestamp Timestamp of when the message was set. ++ * @param[in] who Who set this message. ++ * @param[in] text The welcome message. + * @param[in] flags Flags to set on welcome. -+ * @param[in] insert Non-zero do not propagate change (welcome_insert) + * @return Zero + */ +int -+welcome_do(struct Client *cptr, struct Client *sptr, char *name, char *text, -+ char *who, time_t timestamp, unsigned int flags, int insert) ++welcome_propagate(struct Client *cptr, struct Client *sptr, int nameint, ++ time_t timestamp, char *who, char *text, unsigned int flags) +{ -+ int nameint = atoi(name); /* transform to int */ -+ int namearray = nameint - 1; /* used to test the array element */ -+ char oldtext[WELCOMELEN + 1]; /* save old text when unsetting */ -+ char msg[BUFSIZE]; /* msg for snomask, logging, etc. */ -+ static time_t rate; /* rate limit snomask message */ ++ assert(!(flags & WELCOME_LOCAL)); + -+ assert(NULL != cptr); -+ assert(NULL != sptr); -+ assert(NULL != name); -+ assert(NULL != text); -+ assert(NULL != who); ++ sendcmdto_serv_butone(sptr, CMD_WELCOME, cptr, "* %s%s%d %Tu %s :%s", ++ (flags & WELCOME_ANNOUNCE) ? "!" : "", (flags & WELCOME_INSERT) ? "+" : "", ++ nameint, timestamp, who, text); + -+ /* debug */ -+ Debug((DEBUG_DEBUG, "welcome_do(\"%s\", \"%s\", \"%s\", \"%s\" \"%s\", %Tu, 0x%04x, %d)", -+ cli_name(cptr), cli_name(sptr), name, text, who, timestamp, flags, insert)); -+ -+ /* name empty after taking off the prefixes? */ -+ if (EmptyString(name)) { -+ if (IsUser(sptr)) -+ sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :WELCOME: No message number given", sptr); -+ else -+ protocol_violation(cptr, "WELCOME: No message number given by %C", sptr); -+ return 0; -+ } ++ return 0; ++} + -+ /* check name */ -+ if (nameint < 1 || nameint > WELCOME_MAX_ENTRIES) { -+ 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", -+ 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) && !insert) -+ sendcmdto_serv_butone(sptr, CMD_WELCOME, cptr, "* %s%s%d %Tu %s :%s", -+ (flags & WELCOME_ANNOUNCE) ? "!" : "", (flags & WELCOME_INSERT) ? "+" : "", -+ nameint, timestamp, who, text); -+ } -+ return 0; -+ } + -+ /* correct namearray for local offset */ -+ if (flags & WELCOME_LOCAL) -+ namearray += WELCOME_MAX_ENTRIES; ++/** Set a welcome message. ++ * @param[in] cptr Local client that sent us the welcome. ++ * @param[in] sptr Originator of the welcome. ++ * @param[in] nameint Name of the message. ++ * @param[in] namearray Array entry. ++ * @param[in] timestamp Timestamp of when the message was set. ++ * @param[in] who Who set this message. ++ * @param[in] text The message. ++ * @param[in] flags Flags to set on welcome. ++ * @return Zero ++ */ ++int ++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. */ ++ int new = 0; + -+ /* cannot unset welcome that is not set */ -+ if (WelcomeArray[namearray].timestamp == 0 && EmptyString(text)) { ++ /* 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)); + -+ /* from user, throw error */ -+ if (IsUser(sptr)) -+ return send_reply(sptr, ERR_NOSUCHWELCOME, name); ++ /* not set */ ++ if (*WelcomeArray[namearray].text == 0) ++ new = 1; + -+ /* new local welcome from server, but empty - ignore -+ * we do accept a new global welcome message that is empty -+ */ -+ if (flags & WELCOME_LOCAL) -+ return 0; -+ } ++ /* update */ ++ welcome_make(namearray, text, who, timestamp); + -+ /* check if there is something to change */ -+ /* we got a record for it */ -+ if (WelcomeArray[namearray].timestamp != 0) { ++ /* create msg for snomask, logging, etc. */ ++ ircd_snprintf(0, msg, 0, "%s%s%s WELCOME %d \"%s\" [%Tu]", ++ new ? "setting" : "changing", ++ (flags & WELCOME_ANNOUNCE) ? " and announcing " : " ", ++ (flags & WELCOME_LOCAL) ? "local" : "global", ++ nameint, text, timestamp); + -+ /* global */ -+ if (!(flags & WELCOME_LOCAL)) { ++ /* inform ops */ ++ sendto_opmask_butone(0, SNO_OLDSNO, "%s %s", ++ (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ? ++ get_client_name_and_opername(sptr) : cli_name((cli_user(sptr))->server), msg); + -+ /* 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 -+ */ -+ if (IsBurstOrBurstAck(cptr) && timestamp <= WelcomeArray[namearray].timestamp) -+ return 0; ++ /* log it */ ++ log_write(LS_NETWORK, L_INFO, LOG_NOSNOTICE, "%#C (%s) %s", sptr, who, msg); + -+ /* local welcome - we use our idea of the time */ -+ } else -+ timestamp = TStime(); ++ /* welcome set by remote user, inform oper of success */ ++ if ((flags & WELCOME_LOCAL) && IsUser(sptr) && !MyUser(sptr)) { ++ sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s %s", ++ sptr, get_client_name_and_opername(sptr), msg); + -+ /* compare new message with old message */ -+ if (ircd_strcmp(text, WelcomeArray[namearray].text) == 0) { -+ if (IsUser(sptr)) -+ sendcmdto_one(&me, CMD_NOTICE, sptr, -+ "%C :WELCOME: Cannot change %s message for %s - nothing to change.", -+ sptr, (flags & WELCOME_LOCAL) ? "local" : "global", name); -+ return 0; -+ } ++ /* TODO: wallops all local changes, by both local and remote opers? */ ++ /* tell all opers about the local message being set remotely */ ++ sendwallto_group_butone(&me, WALL_WALLOPS, 0, "%s %s", get_client_name_and_opername(sptr), msg); + } + -+ /* 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()); ++ /* propagate it */ ++ if (!(flags & WELCOME_LOCAL)) ++ welcome_propagate(cptr, sptr, nameint, timestamp, who, text, flags); + -+ /* 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()); -+ } ++ /* announce it */ ++ if (flags & WELCOME_ANNOUNCE) ++ welcome_announce(namearray); + -+ /* unsetting - do not announce, do not insert, save text */ -+ if (EmptyString(text)) { -+ flags &= ~WELCOME_ANNOUNCE; -+ flags &= ~WELCOME_INSERT; -+ ircd_strncpy(oldtext, WelcomeArray[namearray].text, WELCOMELEN); -+ } ++ return 0; ++} + -+ /* make space if needed */ -+ if (flags & WELCOME_INSERT) -+ welcome_insert(cptr, sptr, name, nameint, namearray, who, timestamp, flags); ++ ++/** Unset a welcome message. ++ * @param[in] cptr Local client that sent us the welcome. ++ * @param[in] sptr Originator of the welcome. ++ * @param[in] nameint Name of the message. ++ * @param[in] namearray Array entry. ++ * @param[in] timestamp Timestamp of when the message was set. ++ * @param[in] who Who set this message. ++ * @param[in] flags Flags to set on welcome. ++ * @return Zero ++ */ ++int ++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 */ ++ ++ /* 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); + + /* update */ -+ welcome_make(namearray, text, who, timestamp); ++ welcome_make(namearray, "", who, timestamp); + + /* create msg for snomask, logging, etc. */ -+ ircd_snprintf(0, msg, 0, "%s%s%s WELCOME %d \"%s\" [%Tu]", -+ EmptyString(text) ? "unsetting" : "changing", -+ (flags & WELCOME_ANNOUNCE) ? " and announcing " : " ", -+ (flags & WELCOME_LOCAL) ? "local" : "global", -+ nameint, EmptyString(text) ? oldtext : text, timestamp); ++ ircd_snprintf(0, msg, 0, "unsetting %s WELCOME %d \"%s\" [%Tu]", ++ (flags & WELCOME_LOCAL) ? "local" : "global", nameint, text, timestamp); + + /* inform ops */ + sendto_opmask_butone(0, SNO_OLDSNO, "%s %s", @@ -1007,51 +983,38 @@ diff -r 4676d2565f9b ircd/welcome.c + sendwallto_group_butone(&me, WALL_WALLOPS, 0, "%s %s", get_client_name_and_opername(sptr), msg); + } + -+ /* propagate it */ -+ if (!(flags & WELCOME_LOCAL) && !insert) -+ sendcmdto_serv_butone(sptr, CMD_WELCOME, cptr, "* %s%s%d %Tu %s :%s", -+ (flags & WELCOME_ANNOUNCE) ? "!" : "", (flags & WELCOME_INSERT) ? "+" : "", -+ nameint, timestamp, who, text); -+ -+ /* announce it */ -+ if (flags & WELCOME_ANNOUNCE) -+ welcome_announce(namearray); ++ /* propagate it, but not when inserting */ ++ if (!(flags & (WELCOME_LOCAL|WELCOME_INSERT))) ++ welcome_propagate(cptr, sptr, nameint, timestamp, who, "", flags); + + return 0; +} + + -+/** Change a welcome message. ++/** Insert a welcome message. + * @param[in] cptr Local client that sent us the welcome. + * @param[in] sptr Originator of the welcome. -+ * @param[in] name Name of the message. + * @param[in] nameint Name of the message. + * @param[in] namearray Array entry. -+ * @param[in] who Who set this message. + * @param[in] timestamp Timestamp of when the message was set. ++ * @param[in] who Who set this message. ++ * @param[in] text The welcome message. + * @param[in] flags Flags to set on welcome. + * @return Zero + */ +int -+welcome_insert(struct Client *cptr, struct Client *sptr, char *name, int nameint, -+ int namearray, char *who, time_t timestamp, unsigned int flags) ++welcome_insert(struct Client *cptr, struct Client *sptr, int nameint, ++ int namearray, time_t timestamp, char *who, char *text, unsigned int flags) +{ -+ char *text = ""; /* empty text to clear to feed to welcome_do */ -+ char *last = "10"; /* last welcome message to feed to welcome_do */ + char msg[BUFSIZE]; /* msg for snomask, logging, etc. */ -+ unsigned int newflags = flags; /* new flags to feed back to welcome_do */ + int i; /* loop variable */ -+ int empty = -1; /* first empty spot array after arrayname */ ++ int empty = -1; /* first empty spot in array after arrayname */ + int end = WELCOME_MAX_ENTRIES -1; /* last element to check in array */ -+ -+ assert(NULL != cptr); -+ assert(NULL != sptr); -+ assert(flags & WELCOME_INSERT); -+ assert(namearray >= 0 && namearray <= 2 * WELCOME_MAX_ENTRIES - 1); ++ int last = end; /* last welcome message to feed to welcome_unset */ + + /* debug */ -+ Debug((DEBUG_DEBUG, "welcome_insert(\"%s\", \"%s\", \"%s\", %d, %d, \"%s\", %Tu, 0x%04x)", -+ cli_name(cptr), cli_name(sptr), name, nameint, namearray, who, timestamp, flags)); ++ 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)); + + /* not set yet, do not insert */ + if (WelcomeArray[namearray].timestamp == 0) @@ -1077,15 +1040,13 @@ diff -r 4676d2565f9b ircd/welcome.c + } + } + -+ /* no empty spot, need to unset last, do not insert or announce */ ++ /* no empty spot, need to unset last */ + if (empty == -1) { -+ newflags &= ~WELCOME_INSERT; -+ newflags &= ~WELCOME_ANNOUNCE; -+ welcome_do(cptr, sptr, last, text, who, timestamp, newflags, 1); ++ welcome_unset(cptr, sptr, end, namearray, timestamp, who, flags); + empty = end; + } + -+ /* move entries down */ ++ /* move entries down, update timestamp */ + for (i = empty; i > namearray; i--) + welcome_make(i, WelcomeArray[i-1].text, WelcomeArray[i-1].who, timestamp); + @@ -1118,10 +1079,151 @@ diff -r 4676d2565f9b ircd/welcome.c + /* tell all opers about the local message being set remotely */ + sendwallto_group_butone(&me, WALL_WALLOPS, 0, "%s %s", get_client_name_and_opername(sptr), msg); + } ++ ++ /* set it */ ++ welcome_set(cptr, sptr, nameint, namearray, timestamp, who, text, flags); ++ + return 0; +} + + ++/** Change a welcome message. ++ * @param[in] cptr Local client that sent us the welcome. ++ * @param[in] sptr Originator of the welcome. ++ * @param[in] name Name of the message. ++ * @param[in] timestamp Timestamp of when the message was set. ++ * @param[in] who Who set this message. ++ * @param[in] text The welcome message. ++ * @param[in] flags Flags to set on welcome. ++ * @return Zero ++ */ ++int ++welcome_do(struct Client *cptr, struct Client *sptr, char *name, ++ time_t timestamp, char *who, char *text, unsigned int flags) ++{ ++ 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); ++ assert(NULL != name); ++ assert(NULL != text); ++ assert(NULL != who); ++ ++ /* debug */ ++ Debug((DEBUG_DEBUG, "welcome_do(\"%s\", \"%s\", \"%s\", %Tu, \"%s\", \"%s\", 0x%04x)", ++ cli_name(cptr), cli_name(sptr), name, timestamp, who, text, flags)); ++ ++ /* name empty after taking off the prefixes? */ ++ if (EmptyString(name)) { ++ if (IsUser(sptr)) ++ sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :WELCOME: No message number given", sptr); ++ else ++ protocol_violation(cptr, "WELCOME: No message number given by %C", sptr); ++ return 0; ++ } ++ ++ /* check name */ ++ if (nameint < 1 || nameint > WELCOME_MAX_ENTRIES) { ++ 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", ++ 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; ++ } ++ ++ /* correct namearray for local offset */ ++ if (flags & WELCOME_LOCAL) ++ namearray += WELCOME_MAX_ENTRIES; ++ ++ /* must be true by now */ ++ assert(namearray >= 0 && namearray <= 2 * WELCOME_MAX_ENTRIES - 1); ++ ++ /* cannot unset welcome that is not set */ ++ if (WelcomeArray[namearray].timestamp == 0 && EmptyString(text)) { ++ ++ /* from user, throw error */ ++ if (IsUser(sptr)) ++ return send_reply(sptr, ERR_NOSUCHWELCOME, name); ++ ++ /* new local welcome from server, but empty - ignore ++ * we do accept a new global welcome message that is empty ++ */ ++ if (flags & WELCOME_LOCAL) ++ return 0; ++ } ++ ++ /* check if there is something to change */ ++ /* we got a record for it */ ++ if (WelcomeArray[namearray].timestamp != 0) { ++ ++ /* 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 ++ */ ++ if (IsBurstOrBurstAck(cptr) && timestamp <= WelcomeArray[namearray].timestamp) ++ return 0; ++ ++ /* 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)) ++ sendcmdto_one(&me, CMD_NOTICE, sptr, ++ "%C :WELCOME: Cannot change %s message for %s - nothing to change.", ++ sptr, (flags & WELCOME_LOCAL) ? "local" : "global", name); ++ return 0; ++ } ++ } ++ ++ /* 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()); ++ } ++ ++ /* unset */ ++ if (EmptyString(text)) { ++ flags &= ~WELCOME_INSERT; ++ return welcome_unset(cptr, sptr, nameint, namearray, timestamp, who, flags); ++ } ++ ++ /* insert */ ++ if (flags & WELCOME_INSERT) ++ return welcome_insert(cptr, sptr, nameint, namearray, timestamp, who, text, flags); ++ ++ /* new or change */ ++ return welcome_set(cptr, sptr, nameint, namearray, timestamp, who, text, flags); ++} ++ ++ +/** Announce a welcome message to local clients. + * @param[in] name Welcome message to announce. + */