++/** 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 */
++
++ 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));
++
++ /* 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))
++ 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 (!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",
++ name, sptr, WELCOME_MAX_ENTRIES);
++ 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;
++ }
++
++ /* correct namearray for local offset */
++ if (flags & WELCOME_LOCAL)
++ namearray += WELCOME_MAX_ENTRIES;
++
++ /* must be true by now */
++ assert(WelcomeIsValid(namearray));
++ assert(nameint > 0 && nameint <= WELCOME_MAX_ENTRIES);
++
++ /* cannot unset welcome that is not set */
++ if (!WelcomeIsSet(namearray) && 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 (WelcomeIsSet(namearray)) {
++
++ /* global */
++ if (!(flags & WELCOME_LOCAL)) {
++
++ /* 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 (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();
++
++ /* 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",
++ sptr, (flags & WELCOME_LOCAL) ? "local" : "global", name);
++ return 0;
++ }
++ }
++ }
++
++ /* do not insert for last global/local entry and when not set yet */
++ 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_unset() assumes it is being called from welcome_insert()
++ * and wont propagate the change
++ */
++ 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);
++}
++
++