Example #1
0
void change_user_realname(User * user, const char *realname)
{
    if (user->realname)
        free(user->realname);
    user->realname = sstrdup(realname);

    if (user->na && (nick_identified(user)
                     || (!(user->na->nc->flags & NI_SECURE)
                         && nick_recognized(user)))) {
        if (user->na->last_realname)
            free(user->na->last_realname);
        user->na->last_realname = sstrdup(realname);
    }

    if (debug)
        alog("debug: %s changes its realname to %s", user->nick, realname);
}
Example #2
0
/**
 * check_memos:  See if the given user has any unread memos, and send a
 *               NOTICE to that user if so (and if the appropriate flag is
 *               set).
 * @param u User Struct
 * @return void
 */
void check_memos(User * u)
{
    NickCore *nc;
    int i, newcnt = 0;

    if (!u) {
        if (debug) {
            alog("debug: check_memos called with NULL values");
        }
        return;
    }

    if (!(nc = (u->na ? u->na->nc : NULL)) || !nick_recognized(u) ||
        !(nc->flags & NI_MEMO_SIGNON)) {
        return;
    }

    for (i = 0; i < nc->memos.memocount; i++) {
        if (nc->memos.memos[i].flags & MF_UNREAD)
            newcnt++;
    }
    if (newcnt > 0) {
        notice_lang(s_MemoServ, u,
                    newcnt == 1 ? MEMO_HAVE_NEW_MEMO : MEMO_HAVE_NEW_MEMOS,
                    newcnt);
        if (newcnt == 1 && (nc->memos.memos[i - 1].flags & MF_UNREAD)) {
            notice_lang(s_MemoServ, u, MEMO_TYPE_READ_LAST, s_MemoServ);
        } else if (newcnt == 1) {
            for (i = 0; i < nc->memos.memocount; i++) {
                if (nc->memos.memos[i].flags & MF_UNREAD)
                    break;
            }
            notice_lang(s_MemoServ, u, MEMO_TYPE_READ_NUM, s_MemoServ,
                        nc->memos.memos[i].number);
        } else {
            notice_lang(s_MemoServ, u, MEMO_TYPE_LIST_NEW, s_MemoServ);
        }
    }
    if (nc->memos.memomax > 0 && nc->memos.memocount >= nc->memos.memomax) {
        if (nc->memos.memocount > nc->memos.memomax)
            notice_lang(s_MemoServ, u, MEMO_OVER_LIMIT, nc->memos.memomax);
        else
            notice_lang(s_MemoServ, u, MEMO_AT_LIMIT, nc->memos.memomax);
    }
}
Example #3
0
void update_host(User * user)
{
    if (user->na && (nick_identified(user)
                     || (!(user->na->nc->flags & NI_SECURE)
                         && nick_recognized(user)))) {
        if (user->na->last_usermask)
            free(user->na->last_usermask);

        user->na->last_usermask =
            smalloc(strlen(common_get_vident(user)) +
                    strlen(common_get_vhost(user)) + 2);
        sprintf(user->na->last_usermask, "%s@%s", common_get_vident(user),
                common_get_vhost(user));
    }

    if (debug)
        alog("debug: %s changes its host to %s", user->nick,
             common_get_vhost(user));
}
Example #4
0
void change_user_username(User * user, const char *username)
{
    if (user->vident)
        free(user->vident);
    user->vident = sstrdup(username);
    if (user->na && (nick_identified(user)
                     || (!(user->na->nc->flags & NI_SECURE)
                         && nick_recognized(user)))) {
        if (user->na->last_usermask)
            free(user->na->last_usermask);

        user->na->last_usermask =
            smalloc(strlen(common_get_vident(user)) +
                    strlen(common_get_vhost(user)) + 2);
        sprintf(user->na->last_usermask, "%s@%s", common_get_vident(user),
                common_get_vhost(user));
    }
    if (debug)
        alog("debug: %s changes its username to %s", user->nick, username);
}
Example #5
0
/**
 * The /ms cancel command.
 * @param u The user who issued the command
 * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing.
 **/
int do_cancel(User * u)
{
    int ischan;
    int isforbid;
    char *name = strtok(NULL, " ");
    MemoInfo *mi;

    if (!name) {
        syntax_error(s_MemoServ, u, "CANCEL", MEMO_CANCEL_SYNTAX);

    } else if (!nick_recognized(u)) {
        notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ);

    } else if (!(mi = getmemoinfo(name, &ischan, &isforbid))) {
        if (isforbid) {
            notice_lang(s_MemoServ, u,
                        ischan ? CHAN_X_FORBIDDEN :
                        NICK_X_FORBIDDEN, name);
        } else {
            notice_lang(s_MemoServ, u,
                        ischan ? CHAN_X_NOT_REGISTERED :
                        NICK_X_NOT_REGISTERED, name);
        }
    } else {
        int i;

        for (i = mi->memocount - 1; i >= 0; i--) {
            if ((mi->memos[i].flags & MF_UNREAD)
                && !stricmp(mi->memos[i].sender, u->na->nc->display)
                && (!(mi->memos[i].flags & MF_NOTIFYS))) {
                delmemo(mi, mi->memos[i].number);
                notice_lang(s_MemoServ, u, MEMO_CANCELLED, name);
                return MOD_CONT;
            }
        }

        notice_lang(s_MemoServ, u, MEMO_CANCEL_NONE);
    }
    return MOD_CONT;
}
Example #6
0
File: commands.c Project: goXXip/K9
void run_cmd(const char *service, User *u, Command *list, const char *cmd, ChannelInfo *ci)
{
	Command *c = lookup_cmd(list, cmd);
	int ulevel = 0;

	ulevel = check_cservice(u);
	if ( (ulevel == 0) && ci )
		ulevel = get_access(u, ci);
	if ( ulevel == 0 )
		if ( (stricmp(u->nick, ServicesRoot) == 0) && nick_recognized(u) )
			ulevel = ACCLEV_GOD;
            
	if (c && c->routine)
	{
		if ( ((c->has_priv == NULL) || c->has_priv(u)) && (ulevel >= c->level) )
			c->routine(u);
		else
			notice_lang(service, u, ACCESS_DENIED);
	} else {
		notice_lang(service, u, UNKNOWN_COMMAND_HELP, cmd, service);
	}
}
Example #7
0
/**
 * Adds a new user to anopes internal userlist.
 *
 * If the SVID passed is 2, the user will not be marked registered or requested to ID.
 * This is an addition to accomodate IRCds where we cannot determine this based on the NICK 
 * or UID command. Some IRCd's keep +r on when changing nicks and do not use SVID (ex. InspIRCd 1.2).
 * Instead we get a METADATA command containing the accountname the user was last identified to.
 * Since this is received after the user is introduced to us we should not yet mark the user
 * as identified or ask him to identify. We will mark him as recognized for the time being and let
 * him keep his +r if he has it.
 * It is the responsibility of the protocol module to make sure that this is either invalidated,
 * or changed to identified. ~ Viper
 **/
User *do_nick(const char *source, char *nick, char *username, char *host,
              char *server, char *realname, time_t ts, uint32 svid,
              uint32 ip, char *vhost, char *uid)
{
    User *user = NULL;

    char *tmp = NULL;
    NickAlias *old_na;          /* Old nick rec */
    int nc_changed = 1;         /* Did nick core change? */
    int status = 0;             /* Status to apply */
    char mask[USERMAX + HOSTMAX + 2];
    char *logrealname;
    char *oldnick;

    if (!*source) {
        char ipbuf[16];
        struct in_addr addr;

        if (ircd->nickvhost) {
            if (vhost) {
                if (!strcmp(vhost, "*")) {
                    vhost = NULL;
                    if (debug)
                        alog("debug: new user�with no vhost in NICK command: %s", nick);
                }
            }
        }

        /* This is a new user; create a User structure for it. */
        if (debug)
            alog("debug: new user: %s", nick);

        if (ircd->nickip) {
            addr.s_addr = htonl(ip);
            ntoa(addr, ipbuf, sizeof(ipbuf));
        }


        if (LogUsers) {
        /**
         * Ugly swap routine for Flop's bug :)
         **/
            if (realname) {
                tmp = strchr(realname, '%');
                while (tmp) {
                    *tmp = '-';
                    tmp = strchr(realname, '%');
                }
            }
            logrealname = normalizeBuffer(realname);

        /**
         * End of ugly swap
         **/

            if (ircd->nickvhost) {
                if (ircd->nickip) {
                    alog("LOGUSERS: %s (%s@%s => %s) (%s) [%s] connected to the network (%s).", nick, username, host, (vhost ? vhost : "none"), logrealname, ipbuf, server);
                } else {
                    alog("LOGUSERS: %s (%s@%s => %s) (%s) connected to the network (%s).", nick, username, host, (vhost ? vhost : "none"), logrealname, server);
                }
            } else {
                if (ircd->nickip) {
                    alog("LOGUSERS: %s (%s@%s) (%s) [%s] connected to the network (%s).", nick, username, host, logrealname, ipbuf, server);
                } else {
                    alog("LOGUSERS: %s (%s@%s) (%s) connected to the network (%s).", nick, username, host, logrealname, server);
                }
            }
            Anope_Free(logrealname);
        }

        /* We used to ignore the ~ which a lot of ircd's use to indicate no
         * identd response.  That caused channel bans to break, so now we
         * just take what the server gives us.  People are still encouraged
         * to read the RFCs and stop doing anything to usernames depending
         * on the result of an identd lookup.
         */

        /* First check for AKILLs. */
        /* DONT just return null if its an akill match anymore - yes its more efficent to, however, now that ircd's are
         * starting to use things like E/F lines, we cant be 100% sure the client will be removed from the network :/
         * as such, create a user_struct, and if the client is removed, we'll delete it again when the QUIT notice
         * comes in from the ircd.
         **/
        if (check_akill(nick, username, host, vhost, ipbuf)) {
/*            return NULL; */
        }

/**
 * DefCon AKILL system, if we want to akill all connecting user's here's where to do it
 * then force check_akill again on them...
 **/
        /* don't akill on netmerges -Certus */
        /* don't akill clients introduced by ulines. -Viper */
        if (is_sync(findserver(servlist, server))
            && checkDefCon(DEFCON_AKILL_NEW_CLIENTS) && !is_ulined(server)) {
            strncpy(mask, "*@", 3);
            strncat(mask, host, HOSTMAX);
            alog("DEFCON: adding akill for %s", mask);
            add_akill(NULL, mask, s_OperServ,
                      time(NULL) + dotime(DefConAKILL),
                      DefConAkillReason ? DefConAkillReason :
                      "DEFCON AKILL");
            if (check_akill(nick, username, host, vhost, ipbuf)) {
/*            return NULL; */
            }
        }

        /* SGLINE */
        if (ircd->sgline) {
            if (check_sgline(nick, realname))
                return NULL;
        }

        /* SQLINE */
        if (ircd->sqline) {
            if (check_sqline(nick, 0))
                return NULL;
        }

        /* SZLINE */
        if (ircd->szline && ircd->nickip) {
            if (check_szline(nick, ipbuf))
                return NULL;
        }
        /* Now check for session limits */
        if (LimitSessions && !is_ulined(server)
            && !add_session(nick, host, ipbuf))
            return NULL;

        /* Allocate User structure and fill it in. */
        user = new_user(nick);
        user->username = sstrdup(username);
        user->host = sstrdup(host);
        user->server = findserver(servlist, server);
        user->realname = sstrdup(realname);
        user->timestamp = ts;
        user->my_signon = time(NULL);
        user->chost = vhost ? sstrdup(vhost) : sstrdup(host);
        user->vhost = vhost ? sstrdup(vhost) : sstrdup(host);
        if (uid) {
            user->uid = sstrdup(uid);   /* p10/ts6 stuff */
        } else {
            user->uid = NULL;
        }
        user->vident = sstrdup(username);
        /* We now store the user's ip in the user_ struct,
         * because we will use it in serveral places -- DrStein */
        if (ircd->nickip) {
            user->hostip = sstrdup(ipbuf);
        } else {
            user->hostip = NULL;
        }

        if (svid == 0) {
            display_news(user, NEWS_LOGON);
            display_news(user, NEWS_RANDOM);
        }

        if (svid == 2 && user->na) {
            /* We do not yet know if the user should be identified or not.
             * mark him as recognized for now. 
             * It s up to the protocol module to make sure this either becomes ID'd or
             * is invalidated. ~ Viper */
            if (debug) 
                alog("debug: Marking %s as recognized..", user->nick);
            user->svid = 1;
            user->na->status |= NS_RECOGNIZED;
            nc_changed = 0;
        } else if (svid == ts && user->na) {
            /* Timestamp and svid match, and nick is registered; automagically identify the nick */
            user->svid = svid;
            user->na->status |= NS_IDENTIFIED;
            check_memos(user);
            nc_changed = 0;

            /* Start nick tracking if available */
            if (NSNickTracking)
                nsStartNickTracking(user);

        } else if (svid != 1) {
            /* Resets the svid because it doesn't match */
            user->svid = 1;

            anope_cmd_svid_umode(user->nick, user->timestamp);

        } else {
            user->svid = 1;
        }
        send_event(EVENT_NEWNICK, 1, nick);

    } else {
        /* An old user changing nicks. */
        if (UseTS6 && ircd->ts6)
            user = find_byuid(source);

        if (!user)
            user = finduser(source);

        if (!user) {
            alog("user: NICK from nonexistent nick %s", source);
            return NULL;
        }
        user->isSuperAdmin = 0; /* Dont let people nick change and stay SuperAdmins */
        if (debug)
            alog("debug: %s changes nick to %s", source, nick);

        if (LogUsers) {
            logrealname = normalizeBuffer(user->realname);
            if (ircd->vhost) {
                alog("LOGUSERS: %s (%s@%s => %s) (%s) changed nick to %s (%s).", user->nick, user->username, user->host, (user->vhost ? user->vhost : "(none)"), logrealname, nick, user->server->name);
            } else {
                alog("LOGUSERS: %s (%s@%s) (%s) changed nick to %s (%s).",
                     user->nick, user->username, user->host, logrealname,
                     nick, user->server->name);
            }
            if (logrealname) {
                free(logrealname);
            }
        }

        user->timestamp = ts;

        if (stricmp(nick, user->nick) == 0) {
            /* No need to redo things */
            change_user_nick(user, nick);
            nc_changed = 0;
        } else {
            /* Update this only if nicks aren't the same */
            user->my_signon = time(NULL);

            old_na = user->na;
            if (old_na) {
                if (nick_recognized(user))
                    user->na->last_seen = time(NULL);
                status = old_na->status & NS_TRANSGROUP;
                cancel_user(user);
            }

            oldnick = sstrdup(user->nick);
            change_user_nick(user, nick);

            if ((old_na ? old_na->nc : NULL) ==
                (user->na ? user->na->nc : NULL))
                nc_changed = 0;

            if (!nc_changed && (user->na))
                user->na->status |= status;
            else {
                anope_cmd_nc_change(user);
            }

            send_event(EVENT_CHANGE_NICK, 2, nick, oldnick);
            free(oldnick);
        }

        if (ircd->sqline) {
            if (!is_oper(user) && check_sqline(user->nick, 1))
                return NULL;
        }

    }                           /* if (!*source) */

    /* Check for nick tracking to bypass identification */
    if (NSNickTracking && nsCheckNickTracking(user)) {
        user->na->status |= NS_IDENTIFIED;
        nc_changed = 0;
    }

    if (nc_changed || !nick_recognized(user)) {
        if (validate_user(user))
            check_memos(user);

    } else {
        if (nick_identified(user)) {
            char tsbuf[16];
            user->na->last_seen = time(NULL);

            if (user->na->last_usermask)
                free(user->na->last_usermask);
            user->na->last_usermask =
                smalloc(strlen(common_get_vident(user)) +
                        strlen(common_get_vhost(user)) + 2);
            sprintf(user->na->last_usermask, "%s@%s",
                    common_get_vident(user), common_get_vhost(user));

            snprintf(tsbuf, sizeof(tsbuf), "%lu",
                     (unsigned long int) user->timestamp);
            anope_cmd_svid_umode2(user, tsbuf);

            alog("%s: %s!%s@%s automatically identified for nick %s",
                 s_NickServ, user->nick, user->username,
                 user->host, user->nick);
        }
    }

    /* Bahamut sets -r on every nick changes, so we must test it even if nc_changed == 0 */
    if (ircd->check_nick_id) {
        if (nick_identified(user)) {
            char tsbuf[16];
            snprintf(tsbuf, sizeof(tsbuf), "%lu",
                     (unsigned long int) user->timestamp);
            anope_cmd_svid_umode3(user, tsbuf);
        }
    }

    return user;
}
/**
 * The /cs register command.
 * @param u The user who issued the command
 * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing.
 **/
int do_register(User * u)
{
    char *chan = strtok(NULL, " ");
    char *pass = strtok(NULL, " ");
    char *desc = strtok(NULL, "");
    NickCore *nc;
    Channel *c;
    ChannelInfo *ci;
    struct u_chaninfolist *uc;
    int is_servadmin = is_services_admin(u);
    char founderpass[PASSMAX + 1];
    char tmp_pass[PASSMAX];

    if (readonly) {
        notice_lang(s_ChanServ, u, CHAN_REGISTER_DISABLED);
        return MOD_CONT;
    }

    if (checkDefCon(DEFCON_NO_NEW_CHANNELS)) {
        notice_lang(s_ChanServ, u, OPER_DEFCON_DENIED);
        return MOD_CONT;
    }

    if (!desc) {
        syntax_error(s_ChanServ, u, "REGISTER", CHAN_REGISTER_SYNTAX);
    } else if (*chan == '&') {
        notice_lang(s_ChanServ, u, CHAN_REGISTER_NOT_LOCAL);
    } else if (*chan != '#') {
        notice_lang(s_ChanServ, u, CHAN_SYMBOL_REQUIRED);
    } else if (!xanadu_valid_chan(chan)) {
        notice_lang(s_ChanServ, u, CHAN_X_INVALID, chan);
    } else if (!u->na || !(nc = u->na->nc)) {
        notice_lang(s_ChanServ, u, CHAN_MUST_REGISTER_NICK, s_NickServ);
    } else if (!nick_recognized(u)) {
        notice_lang(s_ChanServ, u, CHAN_MUST_IDENTIFY_NICK, s_NickServ,
                    s_NickServ);
    } else if (!(c = findchan(chan))) {
        notice_lang(s_ChanServ, u, CHAN_REGISTER_NONE_CHANNEL, chan);
    } else if ((ci = cs_findchan(chan)) != NULL) {
        if (ci->flags & CI_VERBOTEN) {
            alog("%s: Attempt to register FORBIDden channel %s by %s!%s@%s", s_ChanServ, ci->name, u->nick, u->username, u->host);
            notice_lang(s_ChanServ, u, CHAN_MAY_NOT_BE_REGISTERED, chan);
        } else {
            notice_lang(s_ChanServ, u, CHAN_ALREADY_REGISTERED, chan);
        }
    } else if (!stricmp(chan, "#")) {
        notice_lang(s_ChanServ, u, CHAN_MAY_NOT_BE_REGISTERED, chan);
    } else if (!chan_has_user_status(c, u, CUS_OP)) {
        notice_lang(s_ChanServ, u, CHAN_MUST_BE_CHANOP);

    } else if (!is_servadmin && nc->channelmax > 0
               && nc->channelcount >= nc->channelmax) {
        notice_lang(s_ChanServ, u,
                    nc->channelcount >
                    nc->
                    channelmax ? CHAN_EXCEEDED_CHANNEL_LIMIT :
                    CHAN_REACHED_CHANNEL_LIMIT, nc->channelmax);
    } else if (stricmp(u->nick, pass) == 0
               || (StrictPasswords && strlen(pass) < 5)) {
        notice_lang(s_ChanServ, u, MORE_OBSCURE_PASSWORD);
    } else if (!(ci = makechan(chan))) {
        alog("%s: makechan() failed for REGISTER %s", s_ChanServ, chan);
        notice_lang(s_ChanServ, u, CHAN_REGISTRATION_FAILED);

    } else if (strscpy(founderpass, pass, PASSMAX + 1),
               enc_encrypt_in_place(founderpass, PASSMAX) < 0) {
        alog("%s: Couldn't encrypt password for %s (REGISTER)",
             s_ChanServ, chan);
        notice_lang(s_ChanServ, u, CHAN_REGISTRATION_FAILED);
        delchan(ci);
    } else {
        c->ci = ci;
        ci->c = c;
        ci->bantype = CSDefBantype;
        ci->flags = CSDefFlags;
        ci->mlock_on = ircd->defmlock;
        ci->memos.memomax = MSMaxMemos;
        ci->last_used = ci->time_registered;
        ci->founder = nc;
        if (strlen(pass) > PASSMAX)
            notice_lang(s_ChanServ, u, PASSWORD_TRUNCATED, PASSMAX);
        memset(pass, 0, strlen(pass));
        memcpy(ci->founderpass, founderpass, PASSMAX);
        ci->desc = sstrdup(desc);
        if (c->topic) {
            ci->last_topic = sstrdup(c->topic);
            strscpy(ci->last_topic_setter, c->topic_setter, NICKMAX);
            ci->last_topic_time = c->topic_time;
        } else {
            /* Set this to something, otherwise it will maliform the topic */
            strscpy(ci->last_topic_setter, s_ChanServ, NICKMAX);
        }
        ci->bi = NULL;
        ci->botflags = BSDefFlags;
        ci->founder->channelcount++;
        alog("%s: Channel '%s' registered by %s!%s@%s", s_ChanServ, chan,
             u->nick, u->username, u->host);
        notice_lang(s_ChanServ, u, CHAN_REGISTERED, chan, u->nick);
	
	if(enc_decrypt(ci->founderpass,tmp_pass,PASSMAX) == 1) {
            notice_lang(s_ChanServ, u, CHAN_PASSWORD_IS, ci->founderpass);
	}

        uc = scalloc(sizeof(*uc), 1);
        uc->next = u->founder_chans;
        uc->prev = NULL;
        if (u->founder_chans)
            u->founder_chans->prev = uc;
        u->founder_chans = uc;
        uc->chan = ci;
        /* Implement new mode lock */
        check_modes(c);
        /* On most ircds you do not receive the admin/owner mode till its registered */
        if (ircd->admin) {
            xanadu_cmd_mode(s_ChanServ, chan, "%s %s", ircd->adminset,
                           u->nick);
        }
        if (ircd->owner && ircd->ownerset) {
            xanadu_cmd_mode(s_ChanServ, chan, "%s %s", ircd->ownerset,
                           u->nick);
        }
        send_event(EVENT_CHAN_REGISTERED, 1, chan);
    }
    return MOD_CONT;
}
Example #9
0
/**
 * Split from do_send, this way we can easily send a memo from any point.
 *
 * @param u User Struct
 * @param name Target of the memo
 * @param text Memo Text
 * @param z type see info
 * @param source Nickname of the alias the memo originates from.
 *	0 - reply to user
 *	1 - silent
 *	2 - silent with no delay timer
 *	3 - reply to user and request read receipt
 * @return void
 */
void memo_send_from(User * u, char *name, char *text, int z, char *source)
{
    int ischan;
    int isforbid;
    Memo *m;
    MemoInfo *mi;
    time_t now = time(NULL);
    int is_servoper = is_services_oper(u);

    if (readonly) {
        notice_lang(s_MemoServ, u, MEMO_SEND_DISABLED);
    } else if (checkDefCon(DEFCON_NO_NEW_MEMOS)) {
        notice_lang(s_MemoServ, u, OPER_DEFCON_DENIED);
        return;
    } else if (!text) {
        if (z == 0)
            syntax_error(s_MemoServ, u, "SEND", MEMO_SEND_SYNTAX);

        if (z == 3)
            syntax_error(s_MemoServ, u, "RSEND", MEMO_RSEND_SYNTAX);

    } else if (!nick_recognized(u)) {
        if (z == 0 || z == 3)
            notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ);

    } else if (!(mi = getmemoinfo(name, &ischan, &isforbid))) {
        if (z == 0 || z == 3) {
            if (isforbid) {
                notice_lang(s_MemoServ, u,
                            ischan ? CHAN_X_FORBIDDEN :
                            NICK_X_FORBIDDEN, name);
            } else {
                notice_lang(s_MemoServ, u,
                            ischan ? CHAN_X_NOT_REGISTERED :
                            NICK_X_NOT_REGISTERED, name);
            }
        }
    } else if (z != 2 && MSSendDelay > 0 &&
               u && u->lastmemosend + MSSendDelay > now && !is_servoper) {
        u->lastmemosend = now;
        if (z == 0)
            notice_lang(s_MemoServ, u, MEMO_SEND_PLEASE_WAIT, MSSendDelay);

        if (z == 3)
            notice_lang(s_MemoServ, u, MEMO_RSEND_PLEASE_WAIT,
                        MSSendDelay);

    } else if (mi->memomax == 0 && !is_servoper) {
        if (z == 0 || z == 3)
            notice_lang(s_MemoServ, u, MEMO_X_GETS_NO_MEMOS, name);

    } else if (mi->memocount >= 32767 || (mi->memomax > 0 && mi->memocount >= mi->memomax
               && !is_servoper)) {
        if (z == 0 || z == 3)
            notice_lang(s_MemoServ, u, MEMO_X_HAS_TOO_MANY_MEMOS, name);

    } else {
        u->lastmemosend = now;
        mi->memocount++;
        mi->memos = srealloc(mi->memos, sizeof(Memo) * mi->memocount);
        m = &mi->memos[mi->memocount - 1];
        strscpy(m->sender, source, NICKMAX);
        m->moduleData = NULL;
        if (mi->memocount > 1) {
            m->number = m[-1].number + 1;
            if (m->number < 1) {
                int i;
                for (i = 0; i < mi->memocount; i++) {
                    mi->memos[i].number = i + 1;
                }
            }
        } else {
            m->number = 1;
        }
        m->time = time(NULL);
        m->text = sstrdup(text);
        m->flags = MF_UNREAD;
#ifdef USE_MYSQL
	m->id = 0;
#endif
        /* Set notify sent flag - DrStein */
        if (z == 2) {
            m->flags |= MF_NOTIFYS;
        }
        /* Set receipt request flag */
        if (z == 3)
            m->flags |= MF_RECEIPT;
        if (z == 0 || z == 3)
            notice_lang(s_MemoServ, u, MEMO_SENT, name);
        if (!ischan) {
            NickAlias *na;
            NickCore *nc = (findnick(name))->nc;

            if (MSNotifyAll) {
                if ((nc->flags & NI_MEMO_RECEIVE)
                    && get_ignore(name) == NULL) {
                    int i;

                    for (i = 0; i < nc->aliases.count; i++) {
                        na = nc->aliases.list[i];
                        if (na->u && nick_identified(na->u))
                            notice_lang(s_MemoServ, na->u,
                                        MEMO_NEW_MEMO_ARRIVED, source,
                                        s_MemoServ, m->number);
                    }
                } else {
                    if ((u = finduser(name)) && nick_identified(u)
                        && (nc->flags & NI_MEMO_RECEIVE))
                        notice_lang(s_MemoServ, u, MEMO_NEW_MEMO_ARRIVED,
                                    source, s_MemoServ, m->number);
                }               /* if (flags & MEMO_RECEIVE) */
            }
            /* if (MSNotifyAll) */
            /* let's get out the mail if set in the nickcore - certus */
            if (nc->flags & NI_MEMO_MAIL)
                new_memo_mail(nc, m);
        } else {
            struct c_userlist *cu, *next;
            Channel *c;

            if (MSNotifyAll && (c = findchan(name))) {
                for (cu = c->users; cu; cu = next) {
                    next = cu->next;
                    if (check_access(cu->user, c->ci, CA_MEMO)) {
                        if (cu->user->na
                            && (cu->user->na->nc->flags & NI_MEMO_RECEIVE)
                            && get_ignore(cu->user->nick) == NULL) {
                            notice_lang(s_MemoServ, cu->user,
                                        MEMO_NEW_X_MEMO_ARRIVED,
                                        c->ci->name, s_MemoServ,
                                        c->ci->name, m->number);
                        }
                    }
                }
            }                   /* MSNotifyAll */
        }                       /* if (!ischan) */
    }                           /* if command is valid */
}