diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bots.cpp | 75 | ||||
-rw-r--r-- | src/botserv.cpp | 554 | ||||
-rw-r--r-- | src/channels.cpp | 52 | ||||
-rw-r--r-- | src/chanserv.cpp | 274 | ||||
-rw-r--r-- | src/commands.cpp | 8 | ||||
-rw-r--r-- | src/config.cpp | 207 | ||||
-rw-r--r-- | src/hostserv.cpp | 97 | ||||
-rw-r--r-- | src/init.cpp | 47 | ||||
-rw-r--r-- | src/logger.cpp | 65 | ||||
-rw-r--r-- | src/main.cpp | 57 | ||||
-rw-r--r-- | src/memoserv.cpp | 334 | ||||
-rw-r--r-- | src/misc.cpp | 310 | ||||
-rw-r--r-- | src/modes.cpp | 2 | ||||
-rw-r--r-- | src/nickalias.cpp | 11 | ||||
-rw-r--r-- | src/nickcore.cpp | 20 | ||||
-rw-r--r-- | src/nickserv.cpp | 242 | ||||
-rw-r--r-- | src/operserv.cpp | 294 | ||||
-rw-r--r-- | src/protocol.cpp | 64 | ||||
-rw-r--r-- | src/regchannel.cpp | 16 | ||||
-rw-r--r-- | src/servers.cpp | 4 | ||||
-rw-r--r-- | src/sessions.cpp | 292 | ||||
-rw-r--r-- | src/users.cpp | 109 | ||||
-rw-r--r-- | src/win32/anope_windows.h | 6 | ||||
-rw-r--r-- | src/win32/windows.cpp | 152 |
24 files changed, 419 insertions, 2873 deletions
diff --git a/src/bots.cpp b/src/bots.cpp index 95a5c2aa5..c67456ba4 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -12,14 +12,6 @@ Anope::insensitive_map<BotInfo *> BotListByNick; Anope::map<BotInfo *> BotListByUID; -BotInfo *BotServ = NULL; -BotInfo *ChanServ = NULL; -BotInfo *Global = NULL; -BotInfo *HostServ = NULL; -BotInfo *MemoServ = NULL; -BotInfo *NickServ = NULL; -BotInfo *OperServ = NULL; - BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal) : User(nnick, nuser, nhost, ts6_uid_retrieve()), Flags<BotFlag, BI_END>(BotFlagString) { this->realname = nreal; @@ -28,24 +20,6 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A this->chancount = 0; this->lastmsg = this->created = Anope::CurTime; - this->SetFlag(BI_CORE); - if (!Config->s_ChanServ.empty() && nnick.equals_ci(Config->s_ChanServ)) - ChanServ = this; - else if (!Config->s_BotServ.empty() && nnick.equals_ci(Config->s_BotServ)) - BotServ = this; - else if (!Config->s_HostServ.empty() && nnick.equals_ci(Config->s_HostServ)) - HostServ = this; - else if (!Config->s_OperServ.empty() && nnick.equals_ci(Config->s_OperServ)) - OperServ = this; - else if (!Config->s_MemoServ.empty() && nnick.equals_ci(Config->s_MemoServ)) - MemoServ = this; - else if (!Config->s_NickServ.empty() && nnick.equals_ci(Config->s_NickServ)) - NickServ = this; - else if (!Config->s_GlobalNoticer.empty() && nnick.equals_ci(Config->s_GlobalNoticer)) - Global = this; - else - this->UnsetFlag(BI_CORE); - BotListByNick[this->nick] = this; if (!this->uid.empty()) BotListByUID[this->uid] = this; @@ -60,6 +34,31 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A this->SetModeInternal(ModeManager::FindUserModeByName(UMODE_PROTECTED)); this->SetModeInternal(ModeManager::FindUserModeByName(UMODE_GOD)); + + for (unsigned i = 0; i < Config->LogInfos.size(); ++i) + { + LogInfo *l = Config->LogInfos[i]; + + if (!ircd->join2msg && !l->Inhabit) + continue; + + for (std::list<Anope::string>::const_iterator sit = l->Targets.begin(), sit_end = l->Targets.end(); sit != sit_end; ++sit) + { + const Anope::string &target = *sit; + + if (target[0] == '#') + { + Channel *c = findchan(target); + if (!c) + c = new Channel(target); + c->SetFlag(CH_LOGCHAN); + c->SetFlag(CH_PERSIST); + + if (!c->FindUser(this)) + this->Join(c, &Config->BotModeList); + } + } + } } BotInfo::~BotInfo() @@ -91,24 +90,6 @@ BotInfo::~BotInfo() BotListByNick.erase(this->nick); if (!this->uid.empty()) BotListByUID.erase(this->uid); - - if (this->HasFlag(BI_CORE)) - { - if (this == ChanServ) - ChanServ = NULL; - else if (this == BotServ) - BotServ = NULL; - else if (this == HostServ) - HostServ = NULL; - else if (this == OperServ) - OperServ = NULL; - else if (this == MemoServ) - MemoServ = NULL; - else if (this == NickServ) - NickServ = NULL; - else if (this == Global) - Global = NULL; - } } void BotInfo::SetNewNick(const Anope::string &newnick) @@ -213,3 +194,9 @@ void BotInfo::Part(Channel *c, const Anope::string &reason) ircdproto->SendPart(this, c, "%s", !reason.empty() ? reason.c_str() : ""); c->DeleteUser(this); } + +void BotInfo::OnMessage(User *u, const Anope::string &message) +{ + mod_run_cmd(this, u, NULL, message); +} + diff --git a/src/botserv.cpp b/src/botserv.cpp index 119264c1d..45d30b395 100644 --- a/src/botserv.cpp +++ b/src/botserv.cpp @@ -14,351 +14,6 @@ #include "services.h" #include "modules.h" -static UserData *get_user_data(Channel *c, User *u); - -E void moduleAddBotServCmds(); - -/*************************************************************************/ - -void moduleAddBotServCmds() -{ - ModuleManager::LoadModuleList(Config->BotServCoreModules); -} - -/*************************************************************************/ -/*************************************************************************/ - -/* Return information on memory use. Assumes pointers are valid. */ - -void get_botserv_stats(long *nrec, long *memuse) -{ - long count = 0, mem = 0; - - for (Anope::insensitive_map<BotInfo *>::const_iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it) - { - BotInfo *bi = it->second; - - ++count; - mem += sizeof(*bi); - mem += bi->nick.length() + 1; - mem += bi->GetIdent().length() + 1; - mem += bi->host.length() + 1; - mem += bi->realname.length() + 1; - } - - *nrec = count; - *memuse = mem; -} - -/*************************************************************************/ -/*************************************************************************/ - -/* BotServ initialization. */ - -void bs_init() -{ - if (!Config->s_BotServ.empty()) - moduleAddBotServCmds(); -} - -/*************************************************************************/ - -/* Handles all messages that are sent to registered channels where a - * bot is on. - */ - -void botchanmsgs(User *u, ChannelInfo *ci, const Anope::string &buf) -{ - if (!u || !ci || !ci->c || buf.empty()) - return; - - /* Answer to ping if needed */ - if (buf.substr(0, 6).equals_ci("\1PING ") && buf[buf.length() - 1] == '\1') - { - Anope::string ctcp = buf; - ctcp.erase(ctcp.begin()); - ctcp.erase(ctcp.length() - 1); - ircdproto->SendCTCP(ci->bi, u->nick, "%s", ctcp.c_str()); - } - - bool was_action = false; - Anope::string realbuf = buf; - - /* If it's a /me, cut the CTCP part because the ACTION will cause - * problems with the caps or badwords kicker - */ - if (realbuf.substr(0, 8).equals_ci("\1ACTION ") && realbuf[realbuf.length() - 1] == '\1') - { - realbuf.erase(0, 8); - realbuf.erase(realbuf.length() - 1); - was_action = true; - } - - if (realbuf.empty()) - return; - - /* Now we can make kicker stuff. We try to order the checks - * from the fastest one to the slowest one, since there's - * no need to process other kickers if a user is kicked before - * the last kicker check. - * - * But FIRST we check whether the user is protected in any - * way. - */ - - bool Allow = true; - if (check_access(u, ci, CA_NOKICK)) - Allow = false; - else if (ci->botflags.HasFlag(BS_DONTKICKOPS) && (ci->c->HasUserStatus(u, CMODE_HALFOP) || ci->c->HasUserStatus(u, CMODE_OP) || ci->c->HasUserStatus(u, CMODE_PROTECT) || ci->c->HasUserStatus(u, CMODE_OWNER))) - Allow = false; - else if (ci->botflags.HasFlag(BS_DONTKICKVOICES) && ci->c->HasUserStatus(u, CMODE_VOICE)) - Allow = false; - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPrivmsg, OnPrivmsg(u, ci, realbuf, Allow)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (Allow) - { - /* Bolds kicker */ - if (ci->botflags.HasFlag(BS_KICK_BOLDS) && realbuf.find(2) != Anope::string::npos) - { - check_ban(ci, u, TTB_BOLDS); - bot_kick(ci, u, _("Don't use bolds on this channel!")); - return; - } - - /* Color kicker */ - if (ci->botflags.HasFlag(BS_KICK_COLORS) && realbuf.find(3) != Anope::string::npos) - { - check_ban(ci, u, TTB_COLORS); - bot_kick(ci, u, _("Don't use colors on this channel!")); - return; - } - - /* Reverses kicker */ - if (ci->botflags.HasFlag(BS_KICK_REVERSES) && realbuf.find(22) != Anope::string::npos) - { - check_ban(ci, u, TTB_REVERSES); - bot_kick(ci, u, _("Don't use reverses on this channel!")); - return; - } - - /* Italics kicker */ - if (ci->botflags.HasFlag(BS_KICK_ITALICS) && realbuf.find(29) != Anope::string::npos) - { - check_ban(ci, u, TTB_ITALICS); - bot_kick(ci, u, _("Don't use italics on this channel!")); - return; - } - - /* Underlines kicker */ - if (ci->botflags.HasFlag(BS_KICK_UNDERLINES) && realbuf.find(31) != Anope::string::npos) - { - check_ban(ci, u, TTB_UNDERLINES); - bot_kick(ci, u, _("Don't use underlines on this channel!")); - return; - } - - /* Caps kicker */ - if (ci->botflags.HasFlag(BS_KICK_CAPS) && realbuf.length() >= ci->capsmin) - { - int i = 0, l = 0; - - for (unsigned j = 0, end = realbuf.length(); j < end; ++j) - { - if (isupper(realbuf[j])) - ++i; - else if (islower(realbuf[j])) - ++l; - } - - /* i counts uppercase chars, l counts lowercase chars. Only - * alphabetic chars (so islower || isupper) qualify for the - * percentage of caps to kick for; the rest is ignored. -GD - */ - - if ((i || l) && i >= ci->capsmin && i * 100 / (i + l) >= ci->capspercent) - { - check_ban(ci, u, TTB_CAPS); - bot_kick(ci, u, _("Turn caps lock OFF!")); - return; - } - } - - /* Bad words kicker */ - if (ci->botflags.HasFlag(BS_KICK_BADWORDS)) - { - bool mustkick = false; - - /* Normalize the buffer */ - Anope::string nbuf = normalizeBuffer(realbuf); - - for (unsigned i = 0, end = ci->GetBadWordCount(); i < end; ++i) - { - BadWord *bw = ci->GetBadWord(i); - - if (bw->type == BW_ANY && ((Config->BSCaseSensitive && nbuf.find(bw->word) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(bw->word) != Anope::string::npos))) - mustkick = true; - else if (bw->type == BW_SINGLE) - { - size_t len = bw->word.length(); - - if ((Config->BSCaseSensitive && bw->word.equals_cs(nbuf)) || (!Config->BSCaseSensitive && bw->word.equals_ci(nbuf))) - mustkick = true; - else if (nbuf.find(' ') == len && ((Config->BSCaseSensitive && bw->word.equals_cs(nbuf)) || (!Config->BSCaseSensitive && bw->word.equals_ci(nbuf)))) - mustkick = true; - else - { - if (nbuf.rfind(' ') == nbuf.length() - len - 1 && ((Config->BSCaseSensitive && nbuf.find(bw->word) == nbuf.length() - len) || (!Config->BSCaseSensitive && nbuf.find_ci(bw->word) == nbuf.length() - len))) - mustkick = true; - else - { - Anope::string wordbuf = " " + bw->word + " "; - - if ((Config->BSCaseSensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) - mustkick = true; - } - } - } - else if (bw->type == BW_START) - { - size_t len = bw->word.length(); - - if ((Config->BSCaseSensitive && nbuf.substr(0, len).equals_cs(bw->word)) || (!Config->BSCaseSensitive && nbuf.substr(0, len).equals_ci(bw->word))) - mustkick = true; - else - { - Anope::string wordbuf = " " + bw->word; - - if ((Config->BSCaseSensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) - mustkick = true; - } - } - else if (bw->type == BW_END) - { - size_t len = bw->word.length(); - - if ((Config->BSCaseSensitive && nbuf.substr(nbuf.length() - len).equals_cs(bw->word)) || (!Config->BSCaseSensitive && nbuf.substr(nbuf.length() - len).equals_ci(bw->word))) - mustkick = true; - else - { - Anope::string wordbuf = bw->word + " "; - - if ((Config->BSCaseSensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) - mustkick = true; - } - } - - if (mustkick) - { - check_ban(ci, u, TTB_BADWORDS); - if (Config->BSGentleBWReason) - bot_kick(ci, u, _("Watch your language!")); - else - bot_kick(ci, u, _("Don't use the word \"%s\" on this channel!"), bw->word.c_str()); - - return; - } - } - } - - /* Flood kicker */ - if (ci->botflags.HasFlag(BS_KICK_FLOOD)) - { - UserData *ud = get_user_data(ci->c, u); - if (!ud) - return; - - if (Anope::CurTime - ud->last_start > ci->floodsecs) - { - ud->last_start = Anope::CurTime; - ud->lines = 0; - } - - ++ud->lines; - if (ud->lines >= ci->floodlines) - { - check_ban(ci, u, TTB_FLOOD); - bot_kick(ci, u, _("Stop flooding!")); - return; - } - } - - /* Repeat kicker */ - if (ci->botflags.HasFlag(BS_KICK_REPEAT)) - { - UserData *ud = get_user_data(ci->c, u); - if (!ud) - return; - - if (!ud->lastline.empty() && !ud->lastline.equals_ci(buf)) - { - ud->lastline = buf; - ud->times = 0; - } - else - { - if (ud->lastline.empty()) - ud->lastline = buf; - ++ud->times; - } - - if (ud->times >= ci->repeattimes) - { - check_ban(ci, u, TTB_REPEAT); - bot_kick(ci, u, _("Stop repeating yourself!")); - return; - } - } - } - - /* Fantaisist commands */ - if (ci->botflags.HasFlag(BS_FANTASY) && buf[0] == Config->BSFantasyCharacter[0] && !was_action) - { - Anope::string message = buf; - /* Strip off the fantasy character */ - message.erase(message.begin()); - - size_t space = message.find(' '); - Anope::string command, rest; - if (space == Anope::string::npos) - command = message; - else - { - command = message.substr(0, space); - rest = message.substr(space + 1); - } - - if (check_access(u, ci, CA_FANTASIA)) - { - - Command *cmd = FindCommand(ChanServ, command); - - /* Command exists and can be called by fantasy */ - if (cmd && !cmd->HasFlag(CFLAG_DISABLE_FANTASY)) - { - Anope::string params = rest; - /* Some commands don't need the channel name added.. eg !help */ - if (!cmd->HasFlag(CFLAG_STRIP_CHANNEL)) - params = ci->name + " " + params; - params = command + " " + params; - - mod_run_cmd(ChanServ, u, ci, params); - } - - FOREACH_MOD(I_OnBotFantasy, OnBotFantasy(command, u, ci, rest)); - } - else - { - FOREACH_MOD(I_OnBotNoFantasyAccess, OnBotNoFantasyAccess(command, u, ci, rest)); - } - } -} - -/*************************************************************************/ - BotInfo *findbot(const Anope::string &nick) { BotInfo *bi = NULL; @@ -380,138 +35,6 @@ BotInfo *findbot(const Anope::string &nick) return bi; } -/*************************************************************************/ - -/* Returns ban data associated with a user if it exists, allocates it - otherwise. */ - -static BanData *get_ban_data(Channel *c, User *u) -{ - if (!c || !u) - return NULL; - - Anope::string mask = u->GetIdent() + "@" + u->GetDisplayedHost(); - /* XXX This should really be on some sort of timer/garbage collector, and use std::map */ - for (std::list<BanData *>::iterator it = c->bd.begin(), it_end = c->bd.end(), it_next; it != it_end; it = it_next) - { - it_next = it; - ++it_next; - - if (Anope::CurTime - (*it)->last_use > Config->BSKeepData) - { - delete *it; - c->bd.erase(it); - continue; - } - if ((*it)->mask.equals_ci(mask)) - { - (*it)->last_use = Anope::CurTime; - return *it; - } - } - - /* If we fall here it is that we haven't found the record */ - BanData *bd = new BanData(); - bd->mask = mask; - bd->last_use = Anope::CurTime; - for (int x = 0; x < TTB_SIZE; ++x) - bd->ttb[x] = 0; - - c->bd.push_front(bd); - - return bd; -} - -/*************************************************************************/ - -/* Returns BotServ data associated with a user on a given channel. - * Allocates it if necessary. - */ - -static UserData *get_user_data(Channel *c, User *u) -{ - if (!c || !u) - return NULL; - - for (CUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it) - { - UserContainer *uc = *it; - - if (uc->user == u) - { - /* Checks whether data is obsolete */ - if (Anope::CurTime - uc->ud.last_use > Config->BSKeepData) - { - /* We should not free and realloc, but reset to 0 - instead. */ - uc->ud.Clear(); - uc->ud.last_use = Anope::CurTime; - } - - return &uc->ud; - } - } - - return NULL; -} - -/*************************************************************************/ - -/** Check if a user should be banned by botserv - * @param ci The channel the user is on - * @param u The user - * @param ttbtype The type of bot kicker the user should be checked against - */ -void check_ban(ChannelInfo *ci, User *u, int ttbtype) -{ - BanData *bd = get_ban_data(ci->c, u); - - if (!bd) - return; - - /* Don't ban ulines */ - if (u->server->IsULined()) - return; - - ++bd->ttb[ttbtype]; - if (ci->ttb[ttbtype] && bd->ttb[ttbtype] >= ci->ttb[ttbtype]) - { - /* Should not use == here because bd->ttb[ttbtype] could possibly be > ci->ttb[ttbtype] - * if the TTB was changed after it was not set (0) before and the user had already been - * kicked a few times. Bug #1056 - Adam */ - Anope::string mask; - - bd->ttb[ttbtype] = 0; - - get_idealban(ci, u, mask); - - if (ci->c) - ci->c->SetMode(NULL, CMODE_BAN, mask); - FOREACH_MOD(I_OnBotBan, OnBotBan(u, ci, mask)); - } -} - -/*************************************************************************/ - -/* This makes a bot kick a user. Works somewhat like notice_lang in fact ;) */ - -void bot_kick(ChannelInfo *ci, User *u, const char *message, ...) -{ - va_list args; - char buf[1024]; - - if (!ci || !ci->bi || !ci->c || !u) - return; - - Anope::string fmt = GetString(u->Account(), message); - va_start(args, message); - if (fmt.empty()) - return; - vsnprintf(buf, sizeof(buf), fmt.c_str(), args); - va_end(args); - - ci->c->Kick(ci->bi, u, "%s", buf); -} /*************************************************************************/ @@ -585,80 +108,3 @@ void bot_raw_kick(User *requester, ChannelInfo *ci, User *u, const Anope::string ci->c->Kick(ci->bi, u, "%s", !reason.empty() ? reason.c_str() : ci->bi->nick.c_str()); } -/*************************************************************************/ - -/** - * Normalize buffer stripping control characters and colors - * @param A string to be parsed for control and color codes - * @return A string stripped of control and color codes - */ -Anope::string normalizeBuffer(const Anope::string &buf) -{ - Anope::string newbuf; - - for (unsigned i = 0, end = buf.length(); i < end; ++i) - { - switch (buf[i]) - { - /* ctrl char */ - case 1: - break; - /* Bold ctrl char */ - case 2: - break; - /* Color ctrl char */ - case 3: - /* If the next character is a digit, its also removed */ - if (isdigit(buf[i + 1])) - { - ++i; - - /* not the best way to remove colors - * which are two digit but no worse then - * how the Unreal does with +S - TSL - */ - if (isdigit(buf[i + 1])) - ++i; - - /* Check for background color code - * and remove it as well - */ - if (buf[i + 1] == ',') - { - ++i; - - if (isdigit(buf[i + 1])) - ++i; - /* not the best way to remove colors - * which are two digit but no worse then - * how the Unreal does with +S - TSL - */ - if (isdigit(buf[i + 1])) - ++i; - } - } - - break; - /* line feed char */ - case 10: - break; - /* carriage returns char */ - case 13: - break; - /* Reverse ctrl char */ - case 22: - break; - /* Underline ctrl char */ - case 31: - break; - /* Italic ctrl char */ - case 29: - break; - /* A valid char gets copied into the new buffer */ - default: - newbuf += buf[i]; - } - } - - return newbuf; -} diff --git a/src/channels.cpp b/src/channels.cpp index 2fe4e037d..29e34cfaf 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -52,9 +52,6 @@ Channel::~Channel() Log(NULL, this, "destroy"); - for (std::list<BanData *>::iterator it = this->bd.begin(), it_end = this->bd.end(); it != it_end; ++it) - delete *it; - if (this->ci) this->ci->c = NULL; @@ -128,14 +125,6 @@ void Channel::JoinUser(User *user) this->Reset(); } - if (this->ci && check_access(user, this->ci, CA_MEMO) && this->ci->memos.memos.size() > 0) - { - if (this->ci->memos.memos.size() == 1) - user->SendMessage(MemoServ, _("There is \002%d\002 memo on channel %s."), this->ci->memos.memos.size(), this->ci->name.c_str()); - else - user->SendMessage(MemoServ, _("There are \002%d\002 memos on channel %s."), this->ci->memos.memos.size(), this->ci->name.c_str()); - } - if (!Config->s_BotServ.empty() && this->ci && this->ci->bi) { /** @@ -838,8 +827,8 @@ bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...) FOREACH_RESULT(I_OnBotKick, OnBotKick(bi, this, u, buf)); if (MOD_RESULT == EVENT_STOP) return false; - ircdproto->SendKick(bi ? bi : whosends(this->ci), this, u, "%s", buf); - this->KickInternal(bi ? bi->nick : whosends(this->ci)->nick, u->nick, buf); + ircdproto->SendKick(bi ? bi : this->ci->WhoSends(), this, u, "%s", buf); + this->KickInternal(bi ? bi->nick : this->ci->WhoSends()->nick, u->nick, buf); return true; } @@ -891,7 +880,7 @@ void Channel::ChangeTopic(const Anope::string &user, const Anope::string &newtop this->topic_setter = u ? u->nick : user; this->topic_time = ts; - ircdproto->SendTopic(whosends(this->ci), this); + ircdproto->SendTopic(this->ci->WhoSends(), this); FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(this, this->topic)); @@ -914,41 +903,6 @@ Channel *findchan(const Anope::string &chan) /*************************************************************************/ -/* Return statistics. Pointers are assumed to be valid. */ - -void get_channel_stats(long *nrec, long *memuse) -{ - long count = 0, mem = 0; - Anope::string buf; - - for (channel_map::const_iterator cit = ChannelList.begin(); cit != ChannelList.end(); ++cit) - { - Channel *chan = cit->second; - - ++count; - mem += sizeof(*chan); - if (!chan->topic.empty()) - mem += chan->topic.length() + 1; - for (CUserList::iterator it = chan->users.begin(), it_end = chan->users.end(); it != it_end; ++it) - { - mem += sizeof(*it); - mem += sizeof((*it)->ud); - if (!(*it)->ud.lastline.empty()) - mem += (*it)->ud.lastline.length() + 1; - } - for (std::list<BanData *>::iterator it = chan->bd.begin(), it_end = chan->bd.end(); it != it_end; ++it) - { - if (!(*it)->mask.empty()) - mem += (*it)->mask.length() + 1; - mem += sizeof(*it); - } - } - *nrec = count; - *memuse = mem; -} - -/*************************************************************************/ - /* Is the given nick on the given channel? This function supports links. */ diff --git a/src/chanserv.cpp b/src/chanserv.cpp index ef7005667..fe86cdae3 100644 --- a/src/chanserv.cpp +++ b/src/chanserv.cpp @@ -13,6 +13,7 @@ #include "services.h" #include "modules.h" +#include "chanserv.h" registered_channel_map RegisteredChannelList; @@ -140,70 +141,6 @@ Anope::string get_mlock_modes(ChannelInfo *ci, int complete) /*************************************************************************/ -/* Return information on memory use. Assumes pointers are valid. */ - -void get_chanserv_stats(long *nrec, long *memuse) -{ - long count = 0, mem = 0; - ModeLock *ml; - - for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ++it) - { - ChannelInfo *ci = it->second; - - ++count; - mem += sizeof(*ci); - if (!ci->desc.empty()) - mem += ci->desc.length() + 1; - mem += ci->GetAccessCount() * sizeof(ChanAccess); - mem += ci->GetAkickCount() * sizeof(AutoKick); - - ml = ci->GetMLock(CMODE_KEY); - if (ml && !ml->param.empty()) - mem += ml->param.length() + 1; - - ml = ci->GetMLock(CMODE_FLOOD); - if (ml && !ml->param.empty()) - mem += ml->param.length() + 1; - - ml = ci->GetMLock(CMODE_REDIRECT); - if (ml && !ml->param.empty()) - mem += ml->param.length() + 1; - - if (!ci->last_topic.empty()) - mem += ci->last_topic.length() + 1; - if (!ci->forbidby.empty()) - mem += ci->forbidby.length() + 1; - if (!ci->forbidreason.empty()) - mem += ci->forbidreason.length() + 1; - if (ci->levels) - mem += sizeof(*ci->levels) * CA_SIZE; - unsigned memos = ci->memos.memos.size(); - mem += memos * sizeof(Memo); - for (unsigned j = 0; j < memos; ++j) - if (!ci->memos.memos[j]->text.empty()) - mem += ci->memos.memos[j]->text.length() + 1; - if (ci->ttb) - mem += sizeof(*ci->ttb) * TTB_SIZE; - mem += ci->GetBadWordCount() * sizeof(BadWord); - } - *nrec = count; - *memuse = mem; -} - -/*************************************************************************/ -/*************************************************************************/ - -/* ChanServ initialization. */ - -void cs_init() -{ - if (!Config->s_ChanServ.empty()) - ModuleManager::LoadModuleList(Config->ChanServCoreModules); -} - -/*************************************************************************/ - /* Check the current modes on a channel; if they conflict with a mode lock, * fix them. */ @@ -288,194 +225,6 @@ void check_modes(Channel *c) /*************************************************************************/ -int check_valid_admin(User *user, Channel *chan, int servermode) -{ - ChannelMode *cm; - - if (!chan || !chan->ci) - return 1; - - if (!(cm = ModeManager::FindChannelModeByName(CMODE_PROTECT))) - return 0; - - /* They will be kicked; no need to deop, no need to update our internal struct too */ - if (chan->ci->HasFlag(CI_FORBIDDEN)) - return 0; - - if (servermode && !check_access(user, chan->ci, CA_AUTOPROTECT)) - { - user->SendMessage(ChanServ, _("This channel has been registered with %s."), Config->s_ChanServ.c_str()); - chan->RemoveMode(NULL, CMODE_PROTECT, user->nick); - return 0; - } - - return 1; -} - -/*************************************************************************/ - -/* Check whether a user is allowed to be opped on a channel; if they - * aren't, deop them. If serverop is 1, the +o was done by a server. - * Return 1 if the user is allowed to be opped, 0 otherwise. */ - -int check_valid_op(User *user, Channel *chan, int servermode) -{ - ChannelMode *owner, *protect, *halfop; - if (!chan || !chan->ci) - return 1; - - /* They will be kicked; no need to deop, no need to update our internal struct too */ - if (chan->ci->HasFlag(CI_FORBIDDEN)) - return 0; - - owner = ModeManager::FindChannelModeByName(CMODE_OWNER); - protect = ModeManager::FindChannelModeByName(CMODE_PROTECT); - halfop = ModeManager::FindChannelModeByName(CMODE_HALFOP); - - if (servermode && !check_access(user, chan->ci, CA_AUTOOP)) - { - user->SendMessage(ChanServ, _("This channel has been registered with %s."), Config->s_ChanServ.c_str()); - - if (owner) - chan->RemoveMode(NULL, CMODE_OWNER, user->nick); - if (protect) - chan->RemoveMode(NULL, CMODE_PROTECT, user->nick); - chan->RemoveMode(NULL, CMODE_OP, user->nick); - if (halfop && !check_access(user, chan->ci, CA_AUTOHALFOP)) - chan->RemoveMode(NULL, CMODE_HALFOP, user->nick); - - return 0; - } - - return 1; -} - -/*************************************************************************/ - -/* Remove all channels which have expired. */ - -void expire_chans() -{ - if (!Config->CSExpire) - return; - - for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ) - { - ChannelInfo *ci = it->second; - ++it; - - bool expire = false; - if (ci->HasFlag(CI_SUSPENDED)) - { - if (Config->CSSuspendExpire && Anope::CurTime - ci->last_used >= Config->CSSuspendExpire) - expire = true; - } - else if (ci->HasFlag(CI_FORBIDDEN)) - { - if (Config->CSForbidExpire && Anope::CurTime - ci->last_used >= Config->CSForbidExpire) - expire = true; - } - else if (!ci->c && Anope::CurTime - ci->last_used >= Config->CSExpire) - expire = true; - - if (ci->HasFlag(CI_NO_EXPIRE)) - expire = false; - - if (expire) - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreChanExpire, OnPreChanExpire(ci)); - if (MOD_RESULT == EVENT_STOP) - continue; - - Anope::string extra; - if (ci->HasFlag(CI_FORBIDDEN)) - extra = "forbidden "; - else if (ci->HasFlag(CI_SUSPENDED)) - extra = "suspended "; - - Log(LOG_NORMAL, "chanserv/expire") << "Expiring " << extra << "channel " << ci->name << " (founder: " << (ci->founder ? ci->founder->display : "(none)") << ")"; - FOREACH_MOD(I_OnChanExpire, OnChanExpire(ci)); - delete ci; - } - } -} - -/*************************************************************************/ - -// XXX this is slightly inefficient -void cs_remove_nick(NickCore *nc) -{ - for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end;) - { - ChannelInfo *ci = it->second; - ++it; - - for (unsigned j = ci->GetAkickCount(); j > 0; --j) - { - AutoKick *akick = ci->GetAkick(j - 1); - if (akick->HasFlag(AK_ISNICK) && akick->nc == nc) - ci->EraseAkick(j - 1); - } - - if (ci->founder == nc) - { - NickCore *newowner = NULL; - if (ci->successor && (ci->successor->IsServicesOper() || !Config->CSMaxReg || ci->successor->channelcount < Config->CSMaxReg)) - newowner = ci->successor; - else - { - ChanAccess *highest = NULL; - for (unsigned j = 0; j < ci->GetAccessCount(); ++j) - { - ChanAccess *ca = ci->GetAccess(j); - - if (!ca->nc || (!ca->nc->IsServicesOper() && Config->CSMaxReg && ca->nc->channelcount >= Config->CSMaxReg) || (ca->nc == nc)) - continue; - if (!highest || ca->level > highest->level) - highest = ca; - } - if (highest) - newowner = highest->nc; - } - - if (newowner) - { - Log(LOG_NORMAL, "chanserv/expire") << "Transferring foundership of " << ci->name << " from deleted nick " << nc->display << " to " << newowner->display; - ci->founder = newowner; - ci->successor = NULL; - ++newowner->channelcount; - } - else - { - Log(LOG_NORMAL, "chanserv/expire") << "Deleting channel " << ci->name << " owned by deleted nick " << nc->display; - - if (ModeManager::FindChannelModeByName(CMODE_REGISTERED)) - { - /* Maybe move this to delchan() ? */ - if (ci->c && ci->c->HasMode(CMODE_REGISTERED)) - ci->c->RemoveMode(NULL, CMODE_REGISTERED, true); - } - - delete ci; - continue; - } - } - - if (ci->successor == nc) - ci->successor = NULL; - - /* Note that it is important we lookup the access for the channel after the new founder - * has been determined incase this user was the founder and also was on the access list! - */ - ChanAccess *access = ci->GetAccess(nc); - if (access) - ci->EraseAccess(access); - } -} - -/*************************************************************************/ - ChannelInfo *cs_findchan(const Anope::string &chan) { FOREACH_MOD(I_OnFindChan, OnFindChan(chan)); @@ -534,10 +283,6 @@ int check_access(User *user, ChannelInfo *ci, int what) return level >= ci->levels[what]; } -/*************************************************************************/ -/*********************** ChanServ private routines ***********************/ -/*************************************************************************/ - /* Reset channel access level values to their default state. */ void reset_levels(ChannelInfo *ci) @@ -657,26 +402,29 @@ Anope::string get_xop_level(int level) ChanServTimer::ChanServTimer(Channel *chan) : Timer(Config->CSInhabit), c(chan) { - if (!ChanServ) + if (!chanserv) return; if (c->ci) c->ci->SetFlag(CI_INHABIT); if (!c->ci || !c->ci->bi) - ChanServ->Join(*c); + chanserv->Bot()->Join(c); else if (!c->FindUser(c->ci->bi)) - c->ci->bi->Join(*c); + c->ci->bi->Join(c); } void ChanServTimer::Tick(time_t) { - if (!c || !c->ci || !ChanServ) + if (!c || !c->ci) return; c->ci->UnsetFlag(CI_INHABIT); - if (!c->ci->bi && ChanServ) - ChanServ->Part(*c); + if (!c->ci->bi) + { + if (chanserv) + chanserv->Bot()->Part(c); + } else if (c->users.size() == 1 || c->users.size() < Config->BSMinUsers) - c->ci->bi->Part(*c); + c->ci->bi->Part(c); } diff --git a/src/commands.cpp b/src/commands.cpp index cfff8c764..03bc368cd 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -93,7 +93,7 @@ void mod_run_cmd(BotInfo *bi, User *u, ChannelInfo *ci, Command *c, const Anope: } bool fantasy = ci != NULL; - if (params.size() > 0 && !c->HasFlag(CFLAG_STRIP_CHANNEL) && (bi == ChanServ || bi == BotServ)) +/* if (params.size() > 0 && !c->HasFlag(CFLAG_STRIP_CHANNEL) && (bi == ChanServ || bi == BotServ)) { if (ircdproto->IsChannelValid(params[0])) { @@ -121,15 +121,15 @@ void mod_run_cmd(BotInfo *bi, User *u, ChannelInfo *ci, Command *c, const Anope: PopLanguage(); return; } - } + }*/ /* A user not giving a channel name for a param that should be a channel */ - else +/* else { u->SendMessage(bi, _(CHAN_X_INVALID), params[0].c_str()); PopLanguage(); return; } - } + }*/ CommandSource source; source.u = u; diff --git a/src/config.cpp b/src/config.cpp index f75913fc9..293f3947f 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -20,16 +20,6 @@ ServerConfig *Config = NULL; static Anope::string Modules; static Anope::string EncModules; static Anope::string DBModules; -static Anope::string HostCoreModules; -static Anope::string MemoCoreModules; -static Anope::string BotCoreModules; -static Anope::string OperCoreModules; -static Anope::string NickCoreModules; -static Anope::string ChanCoreModules; -static Anope::string DefCon1; -static Anope::string DefCon2; -static Anope::string DefCon3; -static Anope::string DefCon4; static Anope::string UlineServers; static Anope::string OSNotifications; static Anope::string BSDefaults; @@ -212,12 +202,6 @@ ServerConfig::ServerConfig() : config_data(), NSDefFlags(NickCoreFlagStrings), C this->ModulesAutoLoad = BuildStringList(Modules); this->EncModuleList = BuildStringList(EncModules); this->DBModuleList = BuildStringList(DBModules); - this->HostServCoreModules = BuildStringList(HostCoreModules); - this->MemoServCoreModules = BuildStringList(MemoCoreModules); - this->BotServCoreModules = BuildStringList(BotCoreModules); - this->OperServCoreModules = BuildStringList(OperCoreModules); - this->ChanServCoreModules = BuildStringList(ChanCoreModules); - this->NickServCoreModules = BuildStringList(NickCoreModules); if (this->LimitSessions) { @@ -237,93 +221,7 @@ ServerConfig::ServerConfig() : config_data(), NSDefFlags(NickCoreFlagStrings), C if (this->UserKey1 == this->UserKey2 || this->UserKey1 == this->UserKey3 || this->UserKey3 == this->UserKey2) Log() << "Every UserKey must be different. It's for YOUR safety! Remember that!"; - /** - * Check all DEFCON dependiencies... - **/ - if (this->DefConLevel) - { - /* Build DefCon's */ - DefCon.resize(6); - DefCon[5].reset(); - for (unsigned int level = 1; level < 5; ++level) - { - DefCon[level] = 0; - Anope::string *levelDefinition = NULL; - switch (level) - { - case 1: - levelDefinition = &DefCon1; - break; - case 2: - levelDefinition = &DefCon2; - break; - case 3: - levelDefinition = &DefCon3; - break; - case 4: - levelDefinition = &DefCon4; - } - spacesepstream operations(*levelDefinition); - Anope::string operation; - while (operations.GetToken(operation)) - { - if (operation.equals_ci("nonewchannels")) - AddDefCon(level, DEFCON_NO_NEW_CHANNELS); - else if (operation.equals_ci("nonewnicks")) - AddDefCon(level, DEFCON_NO_NEW_NICKS); - else if (operation.equals_ci("nomlockchanges")) - AddDefCon(level, DEFCON_NO_MLOCK_CHANGE); - else if (operation.equals_ci("forcechanmodes")) - AddDefCon(level, DEFCON_FORCE_CHAN_MODES); - else if (operation.equals_ci("reducedsessions")) - AddDefCon(level, DEFCON_REDUCE_SESSION); - else if (operation.equals_ci("nonewclients")) - AddDefCon(level, DEFCON_NO_NEW_CLIENTS); - else if (operation.equals_ci("operonly")) - AddDefCon(level, DEFCON_OPER_ONLY); - else if (operation.equals_ci("silentoperonly")) - AddDefCon(level, DEFCON_SILENT_OPER_ONLY); - else if (operation.equals_ci("akillnewclients")) - AddDefCon(level, DEFCON_AKILL_NEW_CLIENTS); - else if (operation.equals_ci("nonewmemos")) - AddDefCon(level, DEFCON_NO_NEW_MEMOS); - } - } - - /* Check any defcon needed settings */ - for (int defconCount = 1; defconCount <= 5; ++defconCount) - { - if (CheckDefCon(defconCount, DEFCON_REDUCE_SESSION)) - { - if (!this->DefConSessionLimit) - { - throw ConfigException("this->DefConSessionLimit missing"); - } - } - if (CheckDefCon(defconCount, DEFCON_AKILL_NEW_CLIENTS)) - { - if (!this->DefConAKILL) - { - throw ConfigException("this->DefConAKILL missing"); - } - if (this->DefConAkillReason.empty()) - { - throw ConfigException("this->DefConAkillReason missing"); - } - } - if (CheckDefCon(defconCount, DEFCON_FORCE_CHAN_MODES)) - { - if (this->DefConChanModes.empty()) - { - throw ConfigException("this->DefConChanModes missing"); - } - } - } - } - SetDefaultMLock(this); - if (ircd) - InitLogChannels(this); if (IsFile(this->NameServer)) { @@ -614,7 +512,7 @@ bool ValidateOperServ(ServerConfig *config, const Anope::string &tag, const Anop bool ValidateGlobal(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data) { - if (!config->s_GlobalNoticer.empty()) + if (!config->s_Global.empty()) { if (value.equals_ci("description") && data.GetValue().empty()) throw ConfigException("The value for <" + tag + ":" + value + "> cannot be empty when Global is enabled!"); @@ -622,37 +520,6 @@ bool ValidateGlobal(ServerConfig *config, const Anope::string &tag, const Anope: return true; } -bool ValidateDefCon(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data) -{ - if (value.equals_ci("defaultlevel")) - { - int level = data.GetInteger(); - if (!level) - return true; - if (level > 5) - throw ConfigException("The value for <defcon:defaultlevel> must be between 1 through 5 if you wish to use DefCon or 0 if you wish to disable it!"); - } - else if (config->DefConLevel) - { - if ((value.substr(0, 5).equals_ci("level") && isdigit(value[5])) || value.equals_ci("chanmodes") || value.equals_ci("akillreason")) - { - if (data.GetValue().empty()) - throw ConfigException("The value for <" + tag + ":" + value + "> cannot be empty when DefCon is enabled!"); - } - else if (value.equals_ci("message") && config->GlobalOnDefconMore) - { - if (data.GetValue().empty()) - throw ConfigException("The value for <defcon:message> cannot be empty when globalondefconmore is enabled!"); - } - else if (value.equals_ci("sessionlimit") || value.equals_ci("akillexpire")) - { - if (!data.GetInteger() && dotime(data.GetValue()) <= 0) - throw ConfigException("The value for <" + tag + ":" + value + "> must be non-zero when DefCon is enabled!"); - } - } - return true; -} - bool ValidateNickLen(ServerConfig *, const Anope::string &, const Anope::string &, ValueItem &data) { int nicklen = data.GetInteger(); @@ -927,10 +794,8 @@ bool InitLogs(ServerConfig *config, const Anope::string &) UserContainer *uc = *cit; BotInfo *bi = findbot(uc->user->nick); - if (bi && bi->HasFlag(BI_CORE)) - { + if (bi) bi->Part(c, "Reloading configuration"); - } } c->UnsetFlag(CH_PERSIST); @@ -989,6 +854,35 @@ bool DoneLogs(ServerConfig *config, const Anope::string &) { Log() << "Loaded " << config->LogInfos.size() << " log blocks"; + for (unsigned i = 0; i < config->LogInfos.size(); ++i) + { + LogInfo *l = config->LogInfos[i]; + + if ((!ircd || !ircd->join2msg) && !l->Inhabit) + continue; + + for (std::list<Anope::string>::const_iterator sit = l->Targets.begin(), sit_end = l->Targets.end(); sit != sit_end; ++sit) + { + const Anope::string &target = *sit; + + if (target[0] == '#') + { + Channel *c = findchan(target); + if (!c) + c = new Channel(target); + c->SetFlag(CH_LOGCHAN); + c->SetFlag(CH_PERSIST); + + for (Anope::insensitive_map<BotInfo *>::const_iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it) + { + BotInfo *bi = it->second; + if (!c->FindUser(bi)) + bi->Join(c, &config->BotModeList); + } + } + } + } + return true; } @@ -1144,10 +1038,6 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"options", "useprivmsg", "no", new ValueContainerBool(&conf->UsePrivmsg), DT_BOOLEAN, NoValidation}, {"options", "usestrictprivmsg", "no", new ValueContainerBool(&conf->UseStrictPrivMsg), DT_BOOLEAN, NoValidation}, {"options", "hidestatso", "no", new ValueContainerBool(&conf->HideStatsO), DT_BOOLEAN, NoValidation}, - {"options", "globaloncycle", "no", new ValueContainerBool(&conf->GlobalOnCycle), DT_BOOLEAN, NoValidation}, - {"options", "globaloncycledown", "", new ValueContainerString(&conf->GlobalOnCycleMessage), DT_STRING, ValidateGlobalOnCycle}, - {"options", "globaloncycleup", "", new ValueContainerString(&conf->GlobalOnCycleUP), DT_STRING, ValidateGlobalOnCycle}, - {"options", "anonymousglobal", "no", new ValueContainerBool(&conf->AnonymousGlobal), DT_BOOLEAN, NoValidation}, {"options", "nickregdelay", "0", new ValueContainerUInt(&conf->NickRegDelay), DT_UINTEGER, NoValidation}, {"options", "restrictopernicks", "no", new ValueContainerBool(&conf->RestrictOperNicks), DT_BOOLEAN, NoValidation}, {"options", "newscount", "3", new ValueContainerUInt(&conf->NewsCount), DT_UINTEGER, NoValidation}, @@ -1161,7 +1051,7 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"nickserv", "nick", "NickServ", new ValueContainerString(&conf->s_NickServ), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, {"nickserv", "description", "Nickname Registration Service", new ValueContainerString(&conf->desc_NickServ), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, {"nickserv", "emailregistration", "no", new ValueContainerBool(&conf->NSEmailReg), DT_BOOLEAN, NoValidation}, - {"nickserv", "modules", "", new ValueContainerString(&NickCoreModules), DT_STRING, NoValidation}, + {"nickserv", "modules", "", new ValueContainerString(&conf->NickCoreModules), DT_STRING, NoValidation}, {"nickserv", "forceemail", "no", new ValueContainerBool(&conf->NSForceEmail), DT_BOOLEAN, ValidateEmailReg}, {"nickserv", "confirmemailchanges", "no", new ValueContainerBool(&conf->NSConfirmEmailChanges), DT_BOOLEAN, NoValidation}, {"nickserv", "defaults", "secure memosignon memoreceive", new ValueContainerString(&NSDefaults), DT_STRING, NoValidation}, @@ -1197,7 +1087,7 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"dns", "timeout", "5", new ValueContainerTime(&conf->DNSTimeout), DT_TIME, NoValidation}, {"chanserv", "nick", "", new ValueContainerString(&conf->s_ChanServ), DT_STRING | DT_NORELOAD, NoValidation}, {"chanserv", "description", "Channel Registration Service", new ValueContainerString(&conf->desc_ChanServ), DT_STRING | DT_NORELOAD, ValidateChanServ}, - {"chanserv", "modules", "", new ValueContainerString(&ChanCoreModules), DT_STRING, ValidateChanServ}, + {"chanserv", "modules", "", new ValueContainerString(&conf->ChanCoreModules), DT_STRING, ValidateChanServ}, {"chanserv", "defaults", "keeptopic secure securefounder signkick", new ValueContainerString(&CSDefaults), DT_STRING, ValidateChanServ}, {"chanserv", "maxregistered", "0", new ValueContainerUInt(&conf->CSMaxReg), DT_UINTEGER, ValidateChanServ}, {"chanserv", "expire", "14d", new ValueContainerTime(&conf->CSExpire), DT_TIME, ValidateChanServ}, @@ -1213,14 +1103,14 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"chanserv", "opersonly", "no", new ValueContainerBool(&conf->CSOpersOnly), DT_BOOLEAN, ValidateChanServ}, {"memoserv", "nick", "", new ValueContainerString(&conf->s_MemoServ), DT_STRING | DT_NORELOAD, NoValidation}, {"memoserv", "description", "Memo Service", new ValueContainerString(&conf->desc_MemoServ), DT_STRING | DT_NORELOAD, ValidateMemoServ}, - {"memoserv", "modules", "", new ValueContainerString(&MemoCoreModules), DT_STRING, NoValidation}, + {"memoserv", "modules", "", new ValueContainerString(&Config->MemoCoreModules), DT_STRING, NoValidation}, {"memoserv", "maxmemos", "0", new ValueContainerUInt(&conf->MSMaxMemos), DT_UINTEGER, NoValidation}, {"memoserv", "senddelay", "0", new ValueContainerTime(&conf->MSSendDelay), DT_TIME, NoValidation}, {"memoserv", "notifyall", "no", new ValueContainerBool(&conf->MSNotifyAll), DT_BOOLEAN, NoValidation}, {"memoserv", "memoreceipt", "0", new ValueContainerUInt(&conf->MSMemoReceipt), DT_UINTEGER, NoValidation}, {"botserv", "nick", "", new ValueContainerString(&conf->s_BotServ), DT_STRING | DT_NORELOAD, NoValidation}, {"botserv", "description", "Bot Service", new ValueContainerString(&conf->desc_BotServ), DT_STRING | DT_NORELOAD, ValidateBotServ}, - {"botserv", "modules", "", new ValueContainerString(&BotCoreModules), DT_STRING, NoValidation}, + {"botserv", "modules", "", new ValueContainerString(&conf->BotCoreModules), DT_STRING, NoValidation}, {"botserv", "defaults", "", new ValueContainerString(&BSDefaults), DT_STRING, NoValidation}, {"botserv", "minusers", "0", new ValueContainerUInt(&conf->BSMinUsers), DT_UINTEGER, ValidateBotServ}, {"botserv", "badwordsmax", "0", new ValueContainerUInt(&conf->BSBadWordsMax), DT_UINTEGER, ValidateBotServ}, @@ -1231,10 +1121,10 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"botserv", "fantasycharacter", "!", new ValueContainerString(&conf->BSFantasyCharacter), DT_STRING, NoValidation}, {"hostserv", "nick", "", new ValueContainerString(&conf->s_HostServ), DT_STRING | DT_NORELOAD, NoValidation}, {"hostserv", "description", "vHost Service", new ValueContainerString(&conf->desc_HostServ), DT_STRING | DT_NORELOAD, ValidateHostServ}, - {"hostserv", "modules", "", new ValueContainerString(&HostCoreModules), DT_STRING, NoValidation}, + {"hostserv", "modules", "", new ValueContainerString(&conf->HostCoreModules), DT_STRING, NoValidation}, {"operserv", "nick", "", new ValueContainerString(&conf->s_OperServ), DT_STRING | DT_NORELOAD, NoValidation}, {"operserv", "description", "Operator Service", new ValueContainerString(&conf->desc_OperServ), DT_STRING | DT_NORELOAD, ValidateOperServ}, - {"operserv", "modules", "", new ValueContainerString(&OperCoreModules), DT_STRING, NoValidation}, + {"operserv", "modules", "", new ValueContainerString(&conf->OperCoreModules), DT_STRING, NoValidation}, {"operserv", "superadmin", "no", new ValueContainerBool(&conf->SuperAdmin), DT_BOOLEAN, NoValidation}, {"operserv", "autokillexpiry", "0", new ValueContainerTime(&conf->AutokillExpiry), DT_TIME, ValidateOperServ}, {"operserv", "chankillexpiry", "0", new ValueContainerTime(&conf->ChankillExpiry), DT_TIME, ValidateOperServ}, @@ -1255,22 +1145,13 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"operserv", "sessionautokillexpiry", "0", new ValueContainerTime(&conf->SessionAutoKillExpiry), DT_TIME, NoValidation}, {"operserv", "addakiller", "no", new ValueContainerBool(&conf->AddAkiller), DT_BOOLEAN, NoValidation}, {"operserv", "opersonly", "no", new ValueContainerBool(&conf->OSOpersOnly), DT_BOOLEAN, NoValidation}, - {"global", "nick", "", new ValueContainerString(&conf->s_GlobalNoticer), DT_STRING | DT_NORELOAD, NoValidation}, - {"global", "description", "Global Noticer", new ValueContainerString(&conf->desc_GlobalNoticer), DT_STRING | DT_NORELOAD, ValidateGlobal}, - {"defcon", "defaultlevel", "0", new ValueContainerInt(&conf->DefConLevel), DT_INTEGER, ValidateDefCon}, - {"defcon", "level4", "", new ValueContainerString(&DefCon4), DT_STRING, ValidateDefCon}, - {"defcon", "level3", "", new ValueContainerString(&DefCon3), DT_STRING, ValidateDefCon}, - {"defcon", "level2", "", new ValueContainerString(&DefCon2), DT_STRING, ValidateDefCon}, - {"defcon", "level1", "", new ValueContainerString(&DefCon1), DT_STRING, ValidateDefCon}, - {"defcon", "sessionlimit", "0", new ValueContainerUInt(&conf->DefConSessionLimit), DT_UINTEGER, ValidateDefCon}, - {"defcon", "akillexpire", "0", new ValueContainerTime(&conf->DefConAKILL), DT_TIME, ValidateDefCon}, - {"defcon", "chanmodes", "", new ValueContainerString(&conf->DefConChanModes), DT_STRING, ValidateDefCon}, - {"defcon", "timeout", "0", new ValueContainerTime(&conf->DefConTimeOut), DT_TIME, NoValidation}, - {"defcon", "globalondefcon", "no", new ValueContainerBool(&conf->GlobalOnDefcon), DT_BOOLEAN, NoValidation}, - {"defcon", "globalondefconmore", "no", new ValueContainerBool(&conf->GlobalOnDefconMore), DT_BOOLEAN, NoValidation}, - {"defcon", "message", "", new ValueContainerString(&conf->DefconMessage), DT_STRING, ValidateDefCon}, - {"defcon", "offmessage", "", new ValueContainerString(&conf->DefConOffMessage), DT_STRING, NoValidation}, - {"defcon", "akillreason", "", new ValueContainerString(&conf->DefConAkillReason), DT_STRING, ValidateDefCon}, + {"global", "nick", "", new ValueContainerString(&conf->s_Global), DT_STRING | DT_NORELOAD, NoValidation}, + {"global", "description", "Global Noticer", new ValueContainerString(&conf->desc_Global), DT_STRING | DT_NORELOAD, ValidateGlobal}, + {"global", "modules", "", new ValueContainerString(&conf->GlobalCoreModules), DT_STRING, NoValidation}, + {"global", "globaloncycle", "no", new ValueContainerBool(&conf->GlobalOnCycle), DT_BOOLEAN, NoValidation}, + {"global", "globaloncycledown", "", new ValueContainerString(&conf->GlobalOnCycleMessage), DT_STRING, ValidateGlobalOnCycle}, + {"global", "globaloncycleup", "", new ValueContainerString(&conf->GlobalOnCycleUP), DT_STRING, ValidateGlobalOnCycle}, + {"global", "anonymousglobal", "no", new ValueContainerBool(&conf->AnonymousGlobal), DT_BOOLEAN, NoValidation}, {"", "", "", NULL, DT_NOTHING, NoValidation} }; diff --git a/src/hostserv.cpp b/src/hostserv.cpp index bfd68f17f..d3000d552 100644 --- a/src/hostserv.cpp +++ b/src/hostserv.cpp @@ -12,59 +12,6 @@ #include "services.h" #include "modules.h" -E void moduleAddHostServCmds(); - -/*************************************************************************/ - -void moduleAddHostServCmds() -{ - ModuleManager::LoadModuleList(Config->HostServCoreModules); -} - -/*************************************************************************/ - -/** - * Return information on memory use. - * Assumes pointers are valid. - **/ - -void get_hostserv_stats(long *nrec, long *memuse) -{ - long count = 0, mem = 0; - - for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ++it) - { - NickAlias *na = it->second; - - if (!na->hostinfo.HasVhost()) - continue; - - if (!na->hostinfo.GetIdent().empty()) - mem += na->hostinfo.GetIdent().length(); - if (!na->hostinfo.GetHost().empty()) - mem += na->hostinfo.GetHost().length(); - if (!na->hostinfo.GetCreator().empty()) - mem += na->hostinfo.GetCreator().length(); - ++count; - } - - *nrec = count; - *memuse = mem; -} - -/*************************************************************************/ - -/** - * HostServ initialization. - * @return void - */ -void hostserv_init() -{ - if (!Config->s_HostServ.empty()) - moduleAddHostServCmds(); -} - -/*************************************************************************/ /** Set a vhost for the user * @param ident The ident @@ -130,47 +77,3 @@ const time_t HostInfo::GetTime() const return Time; } -/*************************************************************************/ -/* Start of Generic Functions */ -/*************************************************************************/ - -/** Sync all vhosts in a group to the same thing - * @param na The nick with the vhost wanting to by synced - */ -void HostServSyncVhosts(NickAlias *na) -{ - if (!na || !na->hostinfo.HasVhost()) - return; - - for (std::list<NickAlias *>::iterator it = na->nc->aliases.begin(), it_end = na->nc->aliases.end(); it != it_end; ++it) - { - NickAlias *nick = *it; - nick->hostinfo.SetVhost(na->hostinfo.GetIdent(), na->hostinfo.GetHost(), na->hostinfo.GetCreator()); - } -} - -/*************************************************************************/ - -void do_on_id(User *u) -{ - if (!u) - return; - NickAlias *na = findnick(u->nick); - if (!na || !na->hostinfo.HasVhost()) - return; - - if (u->vhost.empty() || !u->vhost.equals_cs(na->hostinfo.GetHost()) || (!na->hostinfo.GetIdent().empty() && !u->GetVIdent().equals_cs(na->hostinfo.GetIdent()))) - { - ircdproto->SendVhost(u, na->hostinfo.GetIdent(), na->hostinfo.GetHost()); - if (ircd->vhost) - u->vhost = na->hostinfo.GetHost(); - if (ircd->vident && !na->hostinfo.GetIdent().empty()) - u->SetVIdent(na->hostinfo.GetIdent()); - u->UpdateHost(); - - if (!na->hostinfo.GetIdent().empty()) - u->SendMessage(HostServ, _("Your vhost of \002%s\002@\002%s\002 is now activated."), na->hostinfo.GetIdent().c_str(), na->hostinfo.GetHost().c_str()); - else - u->SendMessage(HostServ, _("Your vhost of \002%s\002 is now activated."), na->hostinfo.GetHost().c_str()); - } -} diff --git a/src/init.cpp b/src/init.cpp index 31d525c7b..f79de5a34 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -342,33 +342,6 @@ void Init(int ac, char **av) /* Create me */ Me = new Server(NULL, Config->ServerName, 0, Config->ServerDesc, Config->Numeric); - /* First thing, add our core bots internally. Before modules are loaded and before the database is read - * This is used for modules adding commands and for the BotInfo* poiners in the command classes. - * When these bots are loaded from the databases the proper user/host/rname are added. - * - * If a user renames a bot in the configuration file, the new bot gets created here, and the old bot - * that is in the database gets created aswell, on its old nick. The old nick remains in all the channels - * etc and the new bot becomes the new client to accept commands. The user can use /bs bot del later - * if they want the old bot deleted. - * - * Note that it is important this is after loading the protocol module. The ircd struct must exist for - * the ts6_ functions - */ - if (!Config->s_OperServ.empty()) - new BotInfo(Config->s_OperServ, Config->ServiceUser, Config->ServiceHost, Config->desc_OperServ); - if (!Config->s_NickServ.empty()) - new BotInfo(Config->s_NickServ, Config->ServiceUser, Config->ServiceHost, Config->desc_NickServ); - if (!Config->s_ChanServ.empty()) - new BotInfo(Config->s_ChanServ, Config->ServiceUser, Config->ServiceHost, Config->desc_ChanServ); - if (!Config->s_HostServ.empty()) - new BotInfo(Config->s_HostServ, Config->ServiceUser, Config->ServiceHost, Config->desc_HostServ); - if (!Config->s_MemoServ.empty()) - new BotInfo(Config->s_MemoServ, Config->ServiceUser, Config->ServiceHost, Config->desc_MemoServ); - if (!Config->s_BotServ.empty()) - new BotInfo(Config->s_BotServ, Config->ServiceUser, Config->ServiceHost, Config->desc_BotServ); - if (!Config->s_GlobalNoticer.empty()) - new BotInfo(Config->s_GlobalNoticer, Config->ServiceUser, Config->ServiceHost, Config->desc_GlobalNoticer); - /* Add Encryption Modules */ ModuleManager::LoadModuleList(Config->EncModuleList); @@ -379,14 +352,7 @@ void Init(int ac, char **av) /* Add Database Modules */ ModuleManager::LoadModuleList(Config->DBModuleList); - try - { - DNSEngine = new DNSManager(); - } - catch (const SocketException &ex) - { - throw FatalException(ex.GetReason()); - } + DNSEngine = new DNSManager(); #ifndef _WIN32 if (!nofork) @@ -440,14 +406,6 @@ void Init(int ac, char **av) Log(LOG_DEBUG) << "Loading Languages..."; InitLanguages(); - /* Initialize subservices */ - ns_init(); - cs_init(); - ms_init(); - bs_init(); - os_init(); - hostserv_init(); - /* load any custom modules */ if (!nothird) ModuleManager::LoadModuleList(Config->ModulesAutoLoad); @@ -456,9 +414,6 @@ void Init(int ac, char **av) rand_init(); add_entropy_userkeys(); - /* Init log channels */ - InitLogChannels(Config); - /* Load up databases */ Log() << "Loading databases..."; EventReturn MOD_RESULT; diff --git a/src/logger.cpp b/src/logger.cpp index 51a8ce69c..4ccfa813f 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -10,39 +10,10 @@ */ #include "services.h" - -void InitLogChannels(ServerConfig *config) -{ - for (unsigned i = 0; i < config->LogInfos.size(); ++i) - { - LogInfo *l = config->LogInfos[i]; - - if (!ircd->join2msg && !l->Inhabit) - continue; - - for (std::list<Anope::string>::const_iterator sit = l->Targets.begin(), sit_end = l->Targets.end(); sit != sit_end; ++sit) - { - const Anope::string &target = *sit; - - if (target[0] == '#') - { - Channel *c = findchan(target); - if (!c) - c = new Channel(target); - c->SetFlag(CH_LOGCHAN); - c->SetFlag(CH_PERSIST); - - for (Anope::insensitive_map<BotInfo *>::iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it) - { - BotInfo *bi = it->second; - - if (bi->HasFlag(BI_CORE) && !c->FindUser(bi)) - bi->Join(c, &config->BotModeList); - } - } - } - } -} +#include "modules.h" +#include "chanserv.h" +#include "operserv.h" +#include "global.h" static Anope::string GetTimeStamp() { @@ -96,10 +67,10 @@ Anope::string LogFile::GetName() const Log::Log(LogType type, const Anope::string &category, BotInfo *b) : bi(b), Type(type), Category(category) { - if (!b) - b = Global; - if (b) - this->Sources.push_back(b->nick); + if (!bi && global) + bi = global->Bot(); + if (bi) + this->Sources.push_back(bi->nick); } Log::Log(LogType type, User *u, Command *c, ChannelInfo *ci) : Type(type) @@ -110,7 +81,7 @@ Log::Log(LogType type, User *u, Command *c, ChannelInfo *ci) : Type(type) if (type != LOG_COMMAND && type != LOG_OVERRIDE && type != LOG_ADMIN) throw CoreException("This constructor does not support this log type"); - this->bi = c->service ? c->service : Global; + this->bi = c->service ? c->service : (global ? global->Bot() : NULL); this->Category = (c->service ? c->service->nick + "/" : "") + c->name; if (this->bi) this->Sources.push_back(this->bi->nick); @@ -135,7 +106,7 @@ Log::Log(User *u, Channel *c, const Anope::string &category) : Type(LOG_CHANNEL) if (!c) throw CoreException("Invalid pointers passed to Log::Log"); - this->bi = ChanServ; + this->bi = chanserv ? chanserv->Bot() : NULL; this->Category = category; if (this->bi) this->Sources.push_back(this->bi->nick); @@ -150,11 +121,13 @@ Log::Log(User *u, Channel *c, const Anope::string &category) : Type(LOG_CHANNEL) buf << this->Category << " " << c->name << " "; } -Log::Log(User *u, const Anope::string &category) : bi(Global), Type(LOG_USER), Category(category) +Log::Log(User *u, const Anope::string &category) : bi(NULL), Type(LOG_USER), Category(category) { if (!u) throw CoreException("Invalid pointers passed to Log::Log"); + if (!this->bi && global) + this->bi = global->Bot(); if (this->bi) this->Sources.push_back(this->bi->nick); this->Sources.push_back(u->nick); @@ -162,13 +135,15 @@ Log::Log(User *u, const Anope::string &category) : bi(Global), Type(LOG_USER), C buf << "USERS: " << u->GetMask() << " "; } -Log::Log(Server *s, const Anope::string &category) : bi(OperServ), Type(LOG_SERVER), Category(category) +Log::Log(Server *s, const Anope::string &category) : bi(NULL), Type(LOG_SERVER), Category(category) { if (!s) throw CoreException("Invalid pointer passed to Log::Log"); - if (!this->bi) - this->bi = Global; + if (operserv) + this->bi = operserv->Bot(); + if (!this->bi && global) + this->bi = global->Bot(); if (this->bi) this->Sources.push_back(this->bi->nick); this->Sources.push_back(s->GetName()); @@ -178,8 +153,8 @@ Log::Log(Server *s, const Anope::string &category) : bi(OperServ), Type(LOG_SERV Log::Log(BotInfo *b, const Anope::string &category) : bi(b), Type(LOG_NORMAL), Category(category) { - if (!b) - this->bi = Global; + if (!b && global) + this->bi = global->Bot(); if (this->bi) this->Sources.push_back(bi->nick); } diff --git a/src/main.cpp b/src/main.cpp index b71a7754a..fd3ab52d5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -79,22 +79,10 @@ static bool started = false; /*************************************************************************/ -class ExpireTimer : public Timer -{ - public: - ExpireTimer(time_t timeout, time_t now) : Timer(timeout, now, true) { } - - void Tick(time_t) - { - if (!readonly && !noexpire) - expire_all(); - } -}; - class UpdateTimer : public Timer { public: - UpdateTimer(time_t timeout, time_t now) : Timer(timeout, now, true) { } + UpdateTimer(time_t timeout) : Timer(timeout, Anope::CurTime, true) { } void Tick(time_t) { @@ -123,26 +111,6 @@ bool UplinkSocket::Read(const Anope::string &buf) /*************************************************************************/ -/* Run expiration routines */ - -extern void expire_all() -{ - if (noexpire || readonly) - // Definitely *do not* want. - return; - - FOREACH_MOD(I_OnPreDatabaseExpire, OnPreDatabaseExpire()); - - Log(LOG_DEBUG) << "Running expire routines"; - expire_nicks(); - expire_chans(); - expire_exceptions(); - - FOREACH_MOD(I_OnDatabaseExpire, OnDatabaseExpire()); -} - -/*************************************************************************/ - void save_databases() { if (readonly) @@ -160,7 +128,6 @@ void do_restart_services() { if (!readonly) { - expire_all(); save_databases(); } Log() << "Restarting"; @@ -261,23 +228,25 @@ void sighandler(int signum) { #ifndef _WIN32 case SIGHUP: + { Log() << "Received SIGHUP: Saving databases & rehashing configuration"; - expire_all(); save_databases(); + ServerConfig *old_config = Config; try { - ServerConfig *newconfig = new ServerConfig(); - delete Config; - Config = newconfig; - FOREACH_MOD(I_OnReload, OnReload(true)); + Config = new ServerConfig(); + FOREACH_MOD(I_OnReload, OnReload()); + delete old_config; } catch (const ConfigException &ex) { + Config = old_config; Log() << "Error reloading configuration file: " << ex.GetReason(); } break; + } #endif case SIGINT: case SIGTERM: @@ -292,11 +261,8 @@ void sighandler(int signum) Log() << "Received signal " << signum << ", exiting."; #endif - if (Config->GlobalOnCycle) - oper_global("", "%s", Config->GlobalOnCycleMessage.c_str()); - - expire_all(); save_databases(); + services_shutdown(); default: fatal = true; break; @@ -455,8 +421,7 @@ int main(int ac, char **av, char **envp) /* Set up timers */ time_t last_check = Anope::CurTime; - ExpireTimer expireTimer(Config->ExpireTimeout, Anope::CurTime); - UpdateTimer updateTimer(Config->UpdateTimeout, Anope::CurTime); + UpdateTimer updateTimer(Config->UpdateTimeout); /*** Main loop. ***/ while (!quitting) @@ -467,8 +432,6 @@ int main(int ac, char **av, char **envp) if (!readonly && (save_data || shutting_down)) { - if (!noexpire) - expire_all(); if (shutting_down) ircdproto->SendGlobops(NULL, "Updating databases on shutdown, please wait."); save_databases(); diff --git a/src/memoserv.cpp b/src/memoserv.cpp index f10a11d5f..21940aca1 100644 --- a/src/memoserv.cpp +++ b/src/memoserv.cpp @@ -12,281 +12,8 @@ #include "services.h" #include "modules.h" -static bool SendMemoMail(NickCore *nc, MemoInfo *mi, Memo *m); - Memo::Memo() : Flags<MemoFlag>(MemoFlagStrings) { } -/** - * MemoServ initialization. - * @return void - */ -void ms_init() -{ - if (!Config->s_MemoServ.empty()) - ModuleManager::LoadModuleList(Config->MemoServCoreModules); -} - -/*************************************************************************/ -/** - * 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) -{ - if (Config->s_MemoServ.empty()) - return; - - if (!u) - { - Log() << "check_memos called with NULL values"; - return; - } - - const NickCore *nc = u->Account(); - if (!nc || !u->IsRecognized() || !nc->HasFlag(NI_MEMO_SIGNON)) - return; - - unsigned i = 0, end = nc->memos.memos.size(), newcnt = 0; - for (; i < end; ++i) - { - if (nc->memos.memos[i]->HasFlag(MF_UNREAD)) - ++newcnt; - } - if (newcnt > 0) - { - u->SendMessage(MemoServ, newcnt == 1 ? _("You have 1 new memo.") : _("You have %d new memos."), newcnt); - if (newcnt == 1 && (nc->memos.memos[i - 1]->HasFlag(MF_UNREAD))) - u->SendMessage(MemoServ, _("Type \002%s%s READ LAST\002 to read it."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str()); - else if (newcnt == 1) - { - for (i = 0; i < end; ++i) - { - if (nc->memos.memos[i]->HasFlag(MF_UNREAD)) - break; - } - u->SendMessage(MemoServ, _("Type \002%s%s READ %d\002 to read it."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), i); - } - else - u->SendMessage(MemoServ, _("Type \002%s%s LIST NEW\002 to list them."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str()); - } - if (nc->memos.memomax > 0 && nc->memos.memos.size() >= nc->memos.memomax) - { - if (nc->memos.memos.size() > nc->memos.memomax) - u->SendMessage(MemoServ, _("Warning: You are over your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."), nc->memos.memomax); - else - u->SendMessage(MemoServ, _("Warning: You have reached your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."), nc->memos.memomax); - } -} - -/*************************************************************************/ -/*********************** MemoServ private routines ***********************/ -/*************************************************************************/ - -/** - * Return the MemoInfo corresponding to the given nick or channel name. - * @param name Name to check - * @param ischan - the result its a channel will be stored in here - * @param isforbid - the result if its forbidden will be stored in here - * @return `ischan' 1 if the name was a channel name, else 0. - * @return `isforbid' 1 if the name is forbidden, else 0. - */ -MemoInfo *getmemoinfo(const Anope::string &name, bool &ischan, bool &isforbid) -{ - if (name[0] == '#') - { - ischan = true; - ChannelInfo *ci = cs_findchan(name); - if (ci) - { - if (!ci->HasFlag(CI_FORBIDDEN)) - { - isforbid = false; - return &ci->memos; - } - else - { - isforbid = true; - return NULL; - } - } - else - { - isforbid = false; - return NULL; - } - } - else - { - ischan = false; - NickAlias *na = findnick(name); - if (na) - { - if (!na->HasFlag(NS_FORBIDDEN)) - { - isforbid = false; - return &na->nc->memos; - } - else - { - isforbid = true; - return NULL; - } - } - else - { - isforbid = false; - return NULL; - } - } -} - -/*************************************************************************/ - -/** - * Split from do_send, this way we can easily send a memo from any point - * @param source Where replies should go - * @param name Target of the memo - * @param text Memo Text - * @param z type see info - * 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(CommandSource &source, const Anope::string &name, const Anope::string &text, int z) -{ - if (Config->s_MemoServ.empty()) - return; - - User *u = source.u; - - bool ischan, isforbid; - MemoInfo *mi; - Anope::string sender = u && u->Account() ? u->Account()->display : ""; - bool is_servoper = u != NULL && u->IsServicesOper(); - - if (readonly) - u->SendMessage(MemoServ, _(MEMO_SEND_DISABLED)); - else if (text.empty()) - { - if (!z) - SyntaxError(source, "SEND", _(MEMO_SEND_SYNTAX)); - - if (z == 3) - SyntaxError(source, "RSEND", _("{\037nick\037 | \037channel\037} \037memo-text\037")); // XXX? - } - else if (!u->IsIdentified() && !u->IsRecognized()) - { - if (!z || z == 3) - source.Reply(_(NICK_IDENTIFY_REQUIRED), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); - } - else if (!(mi = getmemoinfo(name, ischan, isforbid))) - { - if (!z || z == 3) - { - if (isforbid) - source.Reply(ischan ? _(CHAN_X_FORBIDDEN) : _(NICK_X_FORBIDDEN), name.c_str()); - else - source.Reply(ischan ? _(CHAN_X_NOT_REGISTERED) : _(NICK_X_NOT_REGISTERED), name.c_str()); - } - } - else if (z != 2 && Config->MSSendDelay > 0 && u && u->lastmemosend + Config->MSSendDelay > Anope::CurTime) - { - u->lastmemosend = Anope::CurTime; - if (!z) - source.Reply(_("Please wait %d seconds before using the SEND command again."), Config->MSSendDelay); - - if (z == 3) - source.Reply(_("Please wait %d seconds before using the RSEND command again."), Config->MSSendDelay); - } - else if (!mi->memomax && !is_servoper) - { - if (!z || z == 3) - source.Reply(_("%s cannot receive memos."), name.c_str()); - } - else if (mi->memomax > 0 && mi->memos.size() >= mi->memomax && !is_servoper) - { - if (!z || z == 3) - source.Reply(_("%s currently has too many memos and cannot receive more."), name.c_str()); - } - else - { - if (!z || z == 3) - source.Reply(_("Memo sent to \002%s\002."), name.c_str()); - if (!u->IsServicesOper() && mi->HasIgnore(u)) - return; - - u->lastmemosend = Anope::CurTime; - Memo *m = new Memo(); - mi->memos.push_back(m); - m->sender = sender; - m->time = Anope::CurTime; - m->text = text; - m->SetFlag(MF_UNREAD); - /* Set notify sent flag - DrStein */ - if (z == 2) - m->SetFlag(MF_NOTIFYS); - /* Set receipt request flag */ - if (z == 3) - m->SetFlag(MF_RECEIPT); - if (!ischan) - { - NickCore *nc = findnick(name)->nc; - - FOREACH_MOD(I_OnMemoSend, OnMemoSend(u, nc, m)); - - if (Config->MSNotifyAll) - { - if (nc->HasFlag(NI_MEMO_RECEIVE)) - { - for (std::list<NickAlias *>::iterator it = nc->aliases.begin(), it_end = nc->aliases.end(); it != it_end; ++it) - { - NickAlias *na = *it; - User *user = finduser(na->nick); - if (user && user->IsIdentified()) - user->SendMessage(MemoServ, _(MEMO_NEW_MEMO_ARRIVED), sender.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), mi->memos.size()); - } - } - else - { - if ((u = finduser(name)) && u->IsIdentified() && nc->HasFlag(NI_MEMO_RECEIVE)) - u->SendMessage(MemoServ, _(MEMO_NEW_MEMO_ARRIVED), sender.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), mi->memos.size()); - } /* if (flags & MEMO_RECEIVE) */ - } - /* if (MSNotifyAll) */ - /* let's get out the mail if set in the nickcore - certus */ - if (nc->HasFlag(NI_MEMO_MAIL)) - SendMemoMail(nc, mi, m); - } - else - { - Channel *c; - - FOREACH_MOD(I_OnMemoSend, OnMemoSend(u, cs_findchan(name), m)); - - if (Config->MSNotifyAll && (c = findchan(name))) - { - for (CUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it) - { - UserContainer *cu = *it; - - if (check_access(cu->user, c->ci, CA_MEMO)) - { - if (cu->user->Account() && cu->user->Account()->HasFlag(NI_MEMO_RECEIVE)) - cu->user->SendMessage(MemoServ, _(MEMO_NEW_X_MEMO_ARRIVED), c->ci->name.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), c->ci->name.c_str(), mi->memos.size()); - } - } - } /* MSNotifyAll */ - } /* if (!ischan) */ - } /* if command is valid */ -} - -/*************************************************************************/ - unsigned MemoInfo::GetIndex(Memo *m) const { for (unsigned i = 0; i < this->memos.size(); ++i) @@ -322,64 +49,3 @@ bool MemoInfo::HasIgnore(User *u) return false; } -/*************************************************************************/ - -static bool SendMemoMail(NickCore *nc, MemoInfo *mi, Memo *m) -{ - char message[BUFSIZE]; - - snprintf(message, sizeof(message), GetString(nc, - "Hi %s\n" - " \n" - "You've just received a new memo from %s. This is memo number %d.\n" - " \n" - "Memo text:\n" - " \n" - "%s").c_str(), nc->display.c_str(), m->sender.c_str(), mi->GetIndex(m), m->text.c_str()); - - return Mail(nc, GetString(nc, _("New memo")), message); -} - -/*************************************************************************/ - -/* Send receipt notification to sender. */ - -void rsend_notify(CommandSource &source, Memo *m, const Anope::string &chan) -{ - /* Only send receipt if memos are allowed */ - if (!readonly) - { - /* Get nick alias for sender */ - NickAlias *na = findnick(m->sender); - - if (!na) - return; - - /* Get nick core for sender */ - NickCore *nc = na->nc; - - if (!nc) - return; - - /* Text of the memo varies if the recepient was a - nick or channel */ - char text[256]; - if (!chan.empty()) - snprintf(text, sizeof(text), GetString(na->nc, _("\002[auto-memo]\002 The memo you sent to %s has been viewed.")).c_str(), chan.c_str()); - else - snprintf(text, sizeof(text), "%s", GetString(na->nc, _("\002[auto-memo]\002 The memo you sent has been viewed.")).c_str()); - - /* Send notification */ - memo_send(source, m->sender, text, 2); - - /* Notify recepient of the memo that a notification has - been sent to the sender */ - source.Reply(_("A notification memo has been sent to %s informing him/her you have\n" - "read his/her memo."), nc->display.c_str()); - } - - /* Remove receipt flag from the original memo */ - m->UnsetFlag(MF_RECEIPT); - - return; -} diff --git a/src/misc.cpp b/src/misc.cpp index 113dc059c..90239a886 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -14,9 +14,6 @@ #include "version.h" #include "modules.h" -/* Cheaper than isspace() or isblank() */ -#define issp(c) ((c) == 32) - struct arc4_stream { uint8 i; @@ -800,242 +797,6 @@ Anope::string Anope::printf(const char *fmt, ...) } -/* -* strlcat and strlcpy were ripped from openssh 2.5.1p2 -* They had the following Copyright info: -* -* -* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. The name of the author may not be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY -* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef HAVE_STRLCAT -size_t strlcat(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz, dlen; - - while (n-- && *d) - ++d; - - dlen = d - dst; - n = siz - dlen; - - if (!n) - return dlen + strlen(s); - - while (*s) - { - if (n != 1) - { - *d++ = *s; - --n; - } - - ++s; - } - - *d = '\0'; - return dlen + (s - src); /* count does not include NUL */ -} -#endif - -#ifndef HAVE_STRLCPY -size_t strlcpy(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n && --n) - { - do - { - if (!(*d++ = *s++)) - break; - } - while (--n); - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (!n) - { - if (siz) - *d = '\0'; /* NUL-terminate dst */ - while (*s++); - } - - return s - src - 1; /* count does not include NUL */ -} -#endif - -#ifdef _WIN32 -Anope::string GetWindowsVersion() -{ - OSVERSIONINFOEX osvi; - SYSTEM_INFO si; - - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - ZeroMemory(&si, sizeof(SYSTEM_INFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - - BOOL bOsVersionInfoEx = GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi)); - if (!bOsVersionInfoEx) - { - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi))) - return ""; - } - GetSystemInfo(&si); - - Anope::string buf, extra, cputype; - /* Determine CPU type 32 or 64 */ - if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) - cputype = " 64-bit"; - else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) - cputype = " 32-bit"; - else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) - cputype = " Itanium 64-bit"; - - switch (osvi.dwPlatformId) - { - /* test for the Windows NT product family. */ - case VER_PLATFORM_WIN32_NT: - /* Windows Vista or Windows Server 2008 */ - if (osvi.dwMajorVersion == 6 && !osvi.dwMinorVersion) - { - if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) - extra = " Enterprise Edition"; - else if (osvi.wSuiteMask & VER_SUITE_DATACENTER) - extra = " Datacenter Edition"; - else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) - extra = " Home Premium/Basic"; - if (osvi.wProductType & VER_NT_WORKSTATION) - buf = "Microsoft Windows Vista" + cputype + extra; - else - buf = "Microsoft Windows Server 2008" + cputype + extra; - } - /* Windows 2003 or Windows XP Pro 64 */ - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) - { - if (osvi.wSuiteMask & VER_SUITE_DATACENTER) - extra = " Datacenter Edition"; - else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) - extra = " Enterprise Edition"; -#ifdef VER_SUITE_COMPUTE_SERVER - else if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER) - extra = " Compute Cluster Edition"; -#endif - else if (osvi.wSuiteMask == VER_SUITE_BLADE) - extra = " Web Edition"; - else - extra = " Standard Edition"; - if (osvi.wProductType & VER_NT_WORKSTATION && si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) - buf = "Microsoft Windows XP Professional x64 Edition" + extra; - else - buf = "Microsoft Windows Server 2003 Family" + cputype + extra; - } - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) - { - if (osvi.wSuiteMask & VER_SUITE_EMBEDDEDNT) - extra = " Embedded"; - else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) - extra = " Home Edition"; - buf = "Microsoft Windows XP" + extra; - } - if (osvi.dwMajorVersion == 5 && !osvi.dwMinorVersion) - { - if (osvi.wSuiteMask & VER_SUITE_DATACENTER) - extra = " Datacenter Server"; - else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) - extra = " Advanced Server"; - else - extra = " Server"; - buf = "Microsoft Windows 2000" + extra; - } - if (osvi.dwMajorVersion <= 4) - { - if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) - extra = " Enterprise Edition"; - buf = "Microsoft Windows NT Server 4.0" + extra; - } - break; - case VER_PLATFORM_WIN32_WINDOWS: - if (osvi.dwMajorVersion == 4 && !osvi.dwMinorVersion) - { - if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B') - extra = " OSR2"; - buf = "Microsoft Windows 95" + extra; - } - if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) - { - if (osvi.szCSDVersion[1] == 'A') - extra = "SE"; - buf = "Microsoft Windows 98" + extra; - } - if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) - buf = "Microsoft Windows Millenium Edition"; - } - return buf; -} - -bool SupportedWindowsVersion() -{ - OSVERSIONINFOEX osvi; - - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - - BOOL bOsVersionInfoEx = GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi)); - if (!bOsVersionInfoEx) - { - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi))) - return false; - } - - switch (osvi.dwPlatformId) - { - /* test for the Windows NT product family. */ - case VER_PLATFORM_WIN32_NT: - /* win nt4 */ - if (osvi.dwMajorVersion <= 4) - return false; - /* the rest */ - return true; - /* win95 win98 winME */ - case VER_PLATFORM_WIN32_WINDOWS: - return false; - } - return false; -} - -#endif - /*************************************************************************/ /** @@ -1163,3 +924,74 @@ int Anope::VersionMinor() { return VERSION_MINOR; } int Anope::VersionPatch() { return VERSION_PATCH; } int Anope::VersionBuild() { return VERSION_BUILD; } +/** + * Normalize buffer stripping control characters and colors + * @param A string to be parsed for control and color codes + * @return A string stripped of control and color codes + */ +Anope::string normalizeBuffer(const Anope::string &buf) +{ + Anope::string newbuf; + + for (unsigned i = 0, end = buf.length(); i < end; ++i) + { + switch (buf[i]) + { + /* ctrl char */ + case 1: + /* Bold ctrl char */ + case 2: + break; + /* Color ctrl char */ + case 3: + /* If the next character is a digit, its also removed */ + if (isdigit(buf[i + 1])) + { + ++i; + + /* not the best way to remove colors + * which are two digit but no worse then + * how the Unreal does with +S - TSL + */ + if (isdigit(buf[i + 1])) + ++i; + + /* Check for background color code + * and remove it as well + */ + if (buf[i + 1] == ',') + { + ++i; + + if (isdigit(buf[i + 1])) + ++i; + /* not the best way to remove colors + * which are two digit but no worse then + * how the Unreal does with +S - TSL + */ + if (isdigit(buf[i + 1])) + ++i; + } + } + + break; + /* line feed char */ + case 10: + /* carriage returns char */ + case 13: + /* Reverse ctrl char */ + case 22: + /* Italic ctrl char */ + case 29: + /* Underline ctrl char */ + case 31: + break; + /* A valid char gets copied into the new buffer */ + default: + newbuf += buf[i]; + } + } + + return newbuf; +} + diff --git a/src/modes.cpp b/src/modes.cpp index dd147118c..b91cc9b85 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -477,7 +477,7 @@ void ModeManager::StackerAddInternal(BotInfo *bi, Base *Object, Mode *mode, bool if (bi) s->bi = bi; else if (Type == ST_CHANNEL) - s->bi = whosends(debug_cast<Channel *>(Object)->ci); + s->bi = debug_cast<Channel *>(Object)->ci->WhoSends(); else if (Type == ST_USER) s->bi = NULL; } diff --git a/src/nickalias.cpp b/src/nickalias.cpp index 06e5f60dd..019c54615 100644 --- a/src/nickalias.cpp +++ b/src/nickalias.cpp @@ -34,17 +34,6 @@ NickAlias::~NickAlias() { FOREACH_MOD(I_OnDelNick, OnDelNick(this)); - /* Second thing to do: look for a user using the alias - * being deleted, and make appropriate changes */ - User *u = finduser(this->nick); - if (u && u->Account() == this->nc) - { - ircdproto->SendAccountLogout(u, u->Account()); - u->RemoveMode(NickServ, UMODE_REGISTERED); - ircdproto->SendUnregisteredNick(u); - u->Logout(); - } - /* Accept nicks that have no core, because of database load functions */ if (this->nc) { diff --git a/src/nickcore.cpp b/src/nickcore.cpp index 5fdf9c2dd..a33382f06 100644 --- a/src/nickcore.cpp +++ b/src/nickcore.cpp @@ -31,29 +31,9 @@ NickCore::~NickCore() { FOREACH_MOD(I_OnDelCore, OnDelCore(this)); - /* Clean up this nick core from any users online using it - * (ones that /nick but remain unidentified) - */ - for (std::list<User *>::iterator it = this->Users.begin(); it != this->Users.end();) - { - User *user = *it++; - ircdproto->SendAccountLogout(user, user->Account()); - user->RemoveMode(NickServ, UMODE_REGISTERED); - ircdproto->SendUnregisteredNick(user); - user->Logout(); - FOREACH_MOD(I_OnNickLogout, OnNickLogout(user)); - } - this->Users.clear(); - - /* (Hopefully complete) cleanup */ - cs_remove_nick(this); - /* Remove the core from the list */ NickCoreList.erase(this->display); - /* Log .. */ - Log(NickServ, "nick") << "deleting nickname group " << this->display; - /* Clear access before deleting display name, we want to be able to use the display name in the clear access event */ this->ClearAccess(); diff --git a/src/nickserv.cpp b/src/nickserv.cpp index 396c55c53..943b0715b 100644 --- a/src/nickserv.cpp +++ b/src/nickserv.cpp @@ -77,225 +77,6 @@ void NickServRelease::Tick(time_t) */ } -/*************************************************************************/ -/* *INDENT-OFF* */ -void moduleAddNickServCmds() -{ - ModuleManager::LoadModuleList(Config->NickServCoreModules); -} -/* *INDENT-ON* */ -/*************************************************************************/ - -/* Return information on memory use. Assumes pointers are valid. */ - -void get_aliases_stats(long &count, long &mem) -{ - count = mem = 0; - - for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ++it) - { - NickAlias *na = it->second; - - ++count; - mem += sizeof(*na); - if (!na->nick.empty()) - mem += na->nick.length() + 1; - if (!na->last_usermask.empty()) - mem += na->last_usermask.length() + 1; - if (!na->last_realname.empty()) - mem += na->last_realname.length() + 1; - if (!na->last_quit.empty()) - mem += na->last_quit.length() + 1; - } -} - -/*************************************************************************/ - -/* Return information on memory use. Assumes pointers are valid. */ - -void get_core_stats(long &count, long &mem) -{ - count = mem = 0; - unsigned j, end; - - for (nickcore_map::const_iterator it = NickCoreList.begin(), it_end = NickCoreList.end(); it != it_end; ++it) - { - NickCore *nc = it->second; - - ++count; - mem += sizeof(*nc); - - if (!nc->display.empty()) - mem += nc->display.length() + 1; - if (!nc->pass.empty()) - mem += nc->pass.length() + 1; - if (!nc->greet.empty()) - mem += nc->greet.length() + 1; - - mem += sizeof(Anope::string) * nc->access.size(); - - for (j = 0, end = nc->access.size(); j < end; ++j) - mem += nc->GetAccess(j).length() + 1; - - mem += nc->memos.memos.size() * sizeof(Memo); - for (j = 0, end = nc->memos.memos.size(); j < end; ++j) - if (!nc->memos.memos[j]->text.empty()) - mem += nc->memos.memos[j]->text.length() + 1; - - mem += sizeof(NickAlias *) * nc->aliases.size(); - } -} - -/*************************************************************************/ -/*************************************************************************/ - -/* NickServ initialization. */ - -void ns_init() -{ - moduleAddNickServCmds(); -} - -/*************************************************************************/ - -/* Check whether a user is on the access list of the nick they're using If - * not, send warnings as appropriate. If so (and not NI_SECURE), update - * last seen info. - * Return 1 if the user is valid and recognized, 0 otherwise (note - * that this means an NI_SECURE nick will return 0 from here). - * If the user's nick is not registered, 0 is returned. - */ - -int validate_user(User *u) -{ - NickAlias *na = findnick(u->nick); - if (!na) - return 0; - - if (na->HasFlag(NS_FORBIDDEN)) - { - u->SendMessage(NickServ, _("This nickname may not be used. Please choose another one.")); - u->Collide(na); - return 0; - } - - if (na->nc->HasFlag(NI_SUSPENDED)) - { - u->SendMessage(NickServ, _(NICK_X_SUSPENDED), u->nick.c_str()); - u->Collide(na); - return 0; - } - - if (!u->IsIdentified() && !u->fingerprint.empty() && na->nc->FindCert(u->fingerprint)) - { - u->SendMessage(NickServ, _("SSL Fingerprint accepted, you are now identified")); - u->Identify(na); - return 1; - } - - if (!na->nc->HasFlag(NI_SECURE) && u->IsRecognized()) - { - na->last_seen = Anope::CurTime; - Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost(); - na->last_usermask = last_usermask; - na->last_realname = u->realname; - - check_memos(u); - - return 1; - } - - if (u->IsRecognized() || !na->nc->HasFlag(NI_KILL_IMMED)) - { - if (na->nc->HasFlag(NI_SECURE)) - u->SendMessage(NickServ, _(NICK_IS_SECURE), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); - else - u->SendMessage(NickServ, _(NICK_IS_REGISTERED), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); - } - - if (na->nc->HasFlag(NI_KILLPROTECT) && !u->IsRecognized()) - { - if (na->nc->HasFlag(NI_KILL_IMMED)) - { - u->SendMessage(NickServ, _(FORCENICKCHANGE_NOW)); - u->Collide(na); - } - else if (na->nc->HasFlag(NI_KILL_QUICK)) - { - u->SendMessage(NickServ, _("If you do not change within 20 seconds, I will change your nick.")); - new NickServCollide(u, 20); - } - else - { - u->SendMessage(NickServ, _("If you do not change within one minute, I will change your nick.")); - new NickServCollide(u, 60); - } - } - - return 0; -} - -/*************************************************************************/ - -/* Remove all nicks which have expired. Also update last-seen time for all - * nicks. - */ - -void expire_nicks() -{ - for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end;) - { - NickAlias *na = it->second; - ++it; - - User *u = finduser(na->nick); - if (u && (na->nc->HasFlag(NI_SECURE) ? u->IsIdentified(true) : u->IsRecognized(true))) - { - Log(LOG_DEBUG_2) << "NickServ: updating last seen time for " << na->nick; - na->last_seen = Anope::CurTime; - } - - bool expire = false; - - if (na->nc->HasFlag(NI_UNCONFIRMED)) - if (Config->NSUnconfirmedExpire && Anope::CurTime - na->time_registered >= Config->NSUnconfirmedExpire) - expire = true; - - if (na->nc->HasFlag(NI_SUSPENDED)) - { - if (Config->NSSuspendExpire && Anope::CurTime - na->last_seen >= Config->NSSuspendExpire) - expire = true; - } - else if (na->HasFlag(NS_FORBIDDEN)) - { - if (Config->NSForbidExpire && Anope::CurTime - na->last_seen >= Config->NSForbidExpire) - expire = true; - } - else if (Config->NSExpire && Anope::CurTime - na->last_seen >= Config->NSExpire) - expire = true; - if (na->HasFlag(NS_NO_EXPIRE)) - expire = false; - - if (expire) - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreNickExpire, OnPreNickExpire(na)); - if (MOD_RESULT == EVENT_STOP) - continue; - Anope::string extra; - if (na->HasFlag(NS_FORBIDDEN)) - extra = "forbidden "; - else if (na->nc->HasFlag(NI_SUSPENDED)) - extra = "suspended "; - Log(LOG_NORMAL, "expire") << "Expiring " << extra << "nickname " << na->nick << " (group: " << na->nc->display << ") (e-mail: " << (na->nc->email.empty() ? "none" : na->nc->email) << ")"; - FOREACH_MOD(I_OnNickExpire, OnNickExpire(na)); - delete na; - } - } -} - -/*************************************************************************/ - NickAlias *findnick(const Anope::string &nick) { FOREACH_MOD(I_OnFindNick, OnFindNick(nick)); @@ -320,10 +101,6 @@ NickCore *findcore(const Anope::string &nick) return NULL; } -/*************************************************************************/ -/*********************** NickServ private routines ***********************/ -/*************************************************************************/ - /** Is the user's address on the nickcores access list? * @param u The user * @param nc The nickcore @@ -360,9 +137,7 @@ bool is_on_access(const User *u, const NickCore *nc) void change_core_display(NickCore *nc, const Anope::string &newdisplay) { - /* Log ... */ FOREACH_MOD(I_OnChangeCoreDisplay, OnChangeCoreDisplay(nc, newdisplay)); - Log(LOG_NORMAL, "nick") << Config->s_NickServ << ": changing " << nc->display << " nickname group display to " << newdisplay; /* Remove the core from the list */ NickCoreList.erase(nc->display); @@ -381,20 +156,3 @@ void change_core_display(NickCore *nc) change_core_display(nc, na->nick); } -/*************************************************************************/ -/*********************** NickServ command routines ***********************/ -/*************************************************************************/ - -int do_setmodes(User *u) -{ - /* Walk users current channels */ - for (UChannelList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it) - { - ChannelContainer *cc = *it; - - Channel *c = cc->chan; - if (c) - chan_set_correct_modes(u, c, 1); - } - return MOD_CONT; -} diff --git a/src/operserv.cpp b/src/operserv.cpp index 86afda8bc..44f62e48c 100644 --- a/src/operserv.cpp +++ b/src/operserv.cpp @@ -11,137 +11,12 @@ #include "services.h" #include "modules.h" +#include "operserv.h" std::vector<NewsItem *> News; -std::vector<std::bitset<32> > DefCon; -bool DefConModesSet = false; -/* Defcon modes mlocked on */ -Flags<ChannelModeName, CMODE_END * 2> DefConModesOn(ChannelModeNameStrings); -/* Defcon modes mlocked off */ -Flags<ChannelModeName, CMODE_END * 2> DefConModesOff(ChannelModeNameStrings); -/* Map of Modesa and Params for DefCon */ -std::map<ChannelModeName, Anope::string> DefConModesOnParams; - XLineManager *SGLine = NULL, *SZLine = NULL, *SQLine = NULL, *SNLine = NULL; -void os_init() -{ - if (!Config->s_OperServ.empty()) - { - ModuleManager::LoadModuleList(Config->OperServCoreModules); - - /* Yes, these are in this order for a reason. Most violent->least violent. */ - XLineManager::RegisterXLineManager(SGLine = new SGLineManager()); - XLineManager::RegisterXLineManager(SZLine = new SZLineManager()); - XLineManager::RegisterXLineManager(SQLine = new SQLineManager()); - XLineManager::RegisterXLineManager(SNLine = new SNLineManager()); - } -} - -bool SetDefConParam(ChannelModeName Name, const Anope::string &buf) -{ - return DefConModesOnParams.insert(std::make_pair(Name, buf)).second; -} - -bool GetDefConParam(ChannelModeName Name, Anope::string &buf) -{ - std::map<ChannelModeName, Anope::string>::iterator it = DefConModesOnParams.find(Name); - - buf.clear(); - - if (it != DefConModesOnParams.end()) - { - buf = it->second; - return true; - } - - return false; -} - -void UnsetDefConParam(ChannelModeName Name) -{ - std::map<ChannelModeName, Anope::string>::iterator it = DefConModesOnParams.find(Name); - - if (it != DefConModesOnParams.end()) - DefConModesOnParams.erase(it); -} - -/** Check if a certain defcon option is currently in affect - * @param Level The level - * @return true and false - */ -bool CheckDefCon(DefconLevel Level) -{ - if (Config->DefConLevel) - return DefCon[Config->DefConLevel][Level]; - return false; -} - -/** Check if a certain defcon option is in a certain defcon level - * @param level The defcon level - * @param Level The defcon level name - * @return true or false - */ -bool CheckDefCon(int level, DefconLevel Level) -{ - return DefCon[level][Level]; -} - -/** Add a defcon level option to a defcon level - * @param level The defcon level - * @param Level The defcon level option - */ -void AddDefCon(int level, DefconLevel Level) -{ - DefCon[level][Level] = true; -} - -/** Remove a defcon level option from a defcon level - * @param level The defcon level - * @param Level The defcon level option - */ -void DelDefCon(int level, DefconLevel Level) -{ - DefCon[level][Level] = false; -} - -void server_global(const Server *s, const Anope::string &message) -{ - if (Config->s_GlobalNoticer.empty()) - return; - - /* Do not send the notice to ourselves our juped servers */ - if (s != Me && !s->HasFlag(SERVER_JUPED)) - notice_server(Config->s_GlobalNoticer, s, "%s", message.c_str()); - - if (!s->GetLinks().empty()) - { - for (unsigned i = 0, j = s->GetLinks().size(); i < j; ++i) - server_global(s->GetLinks()[i], message); - } -} - -void oper_global(const Anope::string &nick, const char *fmt, ...) -{ - va_list args; - char msg[2048]; /* largest valid message is 512, this should cover any global */ - - va_start(args, fmt); - vsnprintf(msg, sizeof(msg), fmt, args); - va_end(args); - - if (!nick.empty() && !Config->AnonymousGlobal) - { - Anope::string rmsg = "[" + nick + "] " + msg; - server_global(Me->GetLinks().front(), rmsg); - } - else - server_global(Me->GetLinks().front(), msg); -} - -/**************************************************************************/ - /* List of XLine managers we check users against in XLineManager::CheckAll */ std::list<XLineManager *> XLineManager::XLineManagers; @@ -318,14 +193,13 @@ void XLineManager::Clear() } /** Add an entry to this XLine Manager - * @param bi The bot error replies should be sent from - * @param u The user adding the XLine * @param mask The mask of the XLine + * @param creator The creator of the XLine * @param expires When this should expire * @param reaosn The reason * @return A pointer to the XLine */ -XLine *XLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason) +XLine *XLineManager::Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) { return NULL; } @@ -468,53 +342,16 @@ void XLineManager::OnExpire(XLine *x) { } -XLine *SGLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason) +XLine *SGLineManager::Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) { - if (mask.find('!') != Anope::string::npos) - { - if (bi && u) - u->SendMessage(bi, _("\002Reminder\002: AKILL masks cannot contain nicknames; make sure you have \002not\002 included a nick portion in your mask.")); - return NULL; - } - - if (mask.find('@') == Anope::string::npos) - { - if (bi && u) - u->SendMessage(bi, _(BAD_USERHOST_MASK)); - return NULL; - } - - if (mask.find_first_not_of("~@.*?") == Anope::string::npos) - { - if (bi && u) - u->SendMessage(bi, _(USERHOST_MASK_TOO_WIDE), mask.c_str()); - return NULL; - } - - std::pair<int, XLine *> canAdd = this->CanAdd(mask, expires); - if (canAdd.first) - { - if (bi && u) - { - if (canAdd.first == 1) - u->SendMessage(bi, _("\002%s\002 already exists on the AKILL list."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 2) - u->SendMessage(bi, _("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 3) - u->SendMessage(bi, _("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); - } - - return NULL; - } - Anope::string realreason = reason; - if (u && Config->AddAkiller) - realreason = "[" + u->nick + "] " + reason; + if (!creator.empty() && Config->AddAkiller) + realreason = "[" + creator + "] " + reason; - XLine *x = new XLine(mask, u ? u->nick : (OperServ ? OperServ->nick : "OperServ"), expires, realreason); + XLine *x = new XLine(mask, creator, expires, realreason); EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnAddAkill, OnAddAkill(u, x)); + FOREACH_RESULT(I_OnAddAkill, OnAddAkill(x)); if (MOD_RESULT == EVENT_STOP) { delete x; @@ -543,8 +380,8 @@ void SGLineManager::OnMatch(User *u, XLine *x) void SGLineManager::OnExpire(XLine *x) { - if (Config->WallAkillExpire) - ircdproto->SendGlobops(OperServ, "AKILL on %s has expired", x->Mask.c_str()); + if (Config->WallAkillExpire && operserv) + ircdproto->SendGlobops(operserv->Bot(), "AKILL on %s has expired", x->Mask.c_str()); } void SGLineManager::Send(User *u, XLine *x) @@ -552,35 +389,12 @@ void SGLineManager::Send(User *u, XLine *x) ircdproto->SendAkill(u, x); } -XLine *SNLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason) +XLine *SNLineManager::Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) { - if (!mask.empty() && mask.find_first_not_of("*?") == Anope::string::npos) - { - if (bi && u) - u->SendMessage(bi, _(USERHOST_MASK_TOO_WIDE), mask.c_str()); - return NULL; - } - - std::pair<int, XLine *> canAdd = this->CanAdd(mask, expires); - if (canAdd.first) - { - if (bi && u) - { - if (canAdd.first == 1) - u->SendMessage(bi, _("\002%s\002 already exists on the SNLINE list."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 2) - u->SendMessage(bi, _("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 3) - u->SendMessage(bi, _("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); - } - - return NULL; - } - - XLine *x = new XLine(mask, u ? u->nick : (OperServ ? OperServ->nick : "OperServ"), expires, reason); + XLine *x = new XLine(mask, creator, expires, reason); EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnAddXLine, OnAddXLine(u, x, X_SNLINE)); + FOREACH_RESULT(I_OnAddXLine, OnAddXLine(x, X_SNLINE)); if (MOD_RESULT == EVENT_STOP) { delete x; @@ -623,8 +437,8 @@ void SNLineManager::OnMatch(User *u, XLine *x) void SNLineManager::OnExpire(XLine *x) { - if (Config->WallSNLineExpire) - ircdproto->SendGlobops(OperServ, "SNLINE on \2%s\2 has expired", x->Mask.c_str()); + if (Config->WallSNLineExpire && operserv) + ircdproto->SendGlobops(operserv->Bot(), "SNLINE on \2%s\2 has expired", x->Mask.c_str()); } void SNLineManager::Send(User *u, XLine *x) @@ -657,42 +471,12 @@ XLine *SNLineManager::Check(User *u) return NULL; } -XLine *SQLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason) +XLine *SQLineManager::Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) { - if (mask.find_first_not_of("*") == Anope::string::npos) - { - if (bi && u) - u->SendMessage(OperServ, _(USERHOST_MASK_TOO_WIDE), mask.c_str()); - return NULL; - } - - if (mask[0] == '#' && !ircd->chansqline) - { - if (bi && u) - u->SendMessage(OperServ, _("Channel SQLINEs are not supported by your IRCd, so you can't use them.")); - return NULL; - } - - std::pair<int, XLine *> canAdd = this->CanAdd(mask, expires); - if (canAdd.first) - { - if (bi && u) - { - if (canAdd.first == 1) - u->SendMessage(bi, _("\002%s\002 already exists on the SQLINE list."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 2) - u->SendMessage(bi, _("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 3) - u->SendMessage(bi, _("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); - } - - return NULL; - } - - XLine *x = new XLine(mask, u ? u->nick : (OperServ ? OperServ->nick : "OperServ"), expires, reason); + XLine *x = new XLine(mask, creator, expires, reason); EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnAddXLine, OnAddXLine(u, x, X_SQLINE)); + FOREACH_RESULT(I_OnAddXLine, OnAddXLine(x, X_SQLINE)); if (MOD_RESULT == EVENT_STOP) { delete x; @@ -761,8 +545,8 @@ void SQLineManager::OnMatch(User *u, XLine *x) void SQLineManager::OnExpire(XLine *x) { - if (Config->WallSQLineExpire) - ircdproto->SendGlobops(OperServ, "SQLINE on \2%s\2 has expired", x->Mask.c_str()); + if (Config->WallSQLineExpire && operserv) + ircdproto->SendGlobops(operserv->Bot(), "SQLINE on \2%s\2 has expired", x->Mask.c_str()); } void SQLineManager::Send(User *u, XLine *x) @@ -786,40 +570,12 @@ bool SQLineManager::Check(Channel *c) return false; } -XLine *SZLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason) +XLine *SZLineManager::Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) { - if (mask.find('!') != Anope::string::npos || mask.find('@') != Anope::string::npos) - { - u->SendMessage(OperServ, _("\002Reminder:\002 you can only add IP masks to the SZLINE list.")); - return NULL; - } - - if (mask.find_first_not_of("*?") == Anope::string::npos) - { - u->SendMessage(OperServ, _(USERHOST_MASK_TOO_WIDE), mask.c_str()); - return NULL; - } - - std::pair<int, XLine *> canAdd = this->CanAdd(mask, expires); - if (canAdd.first) - { - if (bi && u) - { - if (canAdd.first == 1) - u->SendMessage(bi, _("\002%s\002 already exists on the SZLINE list."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 2) - u->SendMessage(bi, _("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 3) - u->SendMessage(bi, _("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); - } - - return NULL; - } - - XLine *x = new XLine(mask, u ? u->nick : (OperServ ? OperServ->nick : "OperServ"), expires, reason); + XLine *x = new XLine(mask, creator, expires, reason); EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnAddXLine, OnAddXLine(u, x, X_SZLINE)); + FOREACH_RESULT(I_OnAddXLine, OnAddXLine(x, X_SZLINE)); if (MOD_RESULT == EVENT_STOP) { delete x; @@ -852,8 +608,8 @@ void SZLineManager::OnMatch(User *u, XLine *x) void SZLineManager::OnExpire(XLine *x) { - if (Config->WallSZLineExpire) - ircdproto->SendGlobops(OperServ, "SZLINE on \2%s\2 has expired", x->Mask.c_str()); + if (Config->WallSZLineExpire && operserv) + ircdproto->SendGlobops(operserv->Bot(), "SZLINE on \2%s\2 has expired", x->Mask.c_str()); } void SZLineManager::Send(User *u, XLine *x) diff --git a/src/protocol.cpp b/src/protocol.cpp index ddf1557bd..d923f914e 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -295,8 +295,10 @@ bool IRCdMessage::On436(const Anope::string &, const std::vector<Anope::string> bool IRCdMessage::OnAway(const Anope::string &source, const std::vector<Anope::string> ¶ms) { User *u = finduser(source); - if (u && params.empty()) /* un-away */ - check_memos(u); + if (u) + { + FOREACH_MOD(I_OnUserAway, OnUserAway(u, params.empty() ? "" : params[0])); + } return true; } @@ -361,7 +363,7 @@ bool IRCdMessage::OnPing(const Anope::string &, const std::vector<Anope::string> bool IRCdMessage::OnPrivmsg(const Anope::string &source, const std::vector<Anope::string> ¶ms) { const Anope::string &receiver = params.size() > 0 ? params[0] : ""; - const Anope::string &message = params.size() > 1 ? params[1] : ""; + Anope::string message = params.size() > 1 ? params[1] : ""; /* Messages from servers can happen on some IRCds, check for . */ if (source.empty() || receiver.empty() || message.empty() || source.find('.') != Anope::string::npos) @@ -380,12 +382,14 @@ bool IRCdMessage::OnPrivmsg(const Anope::string &source, const std::vector<Anope return true; } - if (receiver[0] == '#' && !Config->s_BotServ.empty()) + if (receiver[0] == '#') { ChannelInfo *ci = cs_findchan(receiver); /* Some paranoia checks */ - if (ci && !ci->HasFlag(CI_FORBIDDEN) && ci->c && ci->bi) - botchanmsgs(u, ci, message); + if (ci && !ci->HasFlag(CI_FORBIDDEN) && ci->c) + { + FOREACH_MOD(I_OnPrivmsg, OnPrivmsg(u, ci, message)); + } } else { @@ -433,36 +437,8 @@ bool IRCdMessage::OnPrivmsg(const Anope::string &source, const std::vector<Anope ircdproto->SendCTCP(bi, u->nick, "VERSION Anope-%s %s :%s - (%s) -- %s", Anope::Version().c_str(), Config->ServerName.c_str(), ircd->name, Config->EncModuleList.begin()->c_str(), Anope::VersionBuildString().c_str()); } } - else if (bi == ChanServ) - { - if (!u->HasMode(UMODE_OPER) && Config->CSOpersOnly) - u->SendMessage(ChanServ, _(ACCESS_DENIED)); - else - mod_run_cmd(bi, u, NULL, message); - } - else if (bi == HostServ) - { - if (!ircd->vhost) - u->SendMessage(HostServ, _("%s is currently offline."), Config->s_HostServ.c_str()); - else - mod_run_cmd(bi, u, NULL, message); - } - else if (bi == OperServ) - { - if (!u->HasMode(UMODE_OPER) && Config->OSOpersOnly) - { - u->SendMessage(OperServ, _(ACCESS_DENIED)); - if (Config->WallBadOS) - ircdproto->SendGlobops(OperServ, "Denied access to %s from %s!%s@%s (non-oper)", Config->s_OperServ.c_str(), u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str()); - } - else - { - Log(OperServ) << u->nick << ": " << message; - mod_run_cmd(bi, u, NULL, message); - } - } - else - mod_run_cmd(bi, u, NULL, message); + + bi->OnMessage(u, message); } } @@ -507,17 +483,7 @@ bool IRCdMessage::OnSQuit(const Anope::string &source, const std::vector<Anope:: FOREACH_MOD(I_OnServerQuit, OnServerQuit(s)); - Anope::string buf; - /* If this is a juped server, send a nice global to inform the online - * opers that we received it. - */ - if (s->HasFlag(SERVER_JUPED)) - { - buf = "Received SQUIT for juped server " + s->GetName(); - ircdproto->SendGlobops(OperServ, "%s", buf.c_str()); - } - - buf = s->GetName() + " " + s->GetUplink()->GetName(); + Anope::string buf = s->GetName() + " " + s->GetUplink()->GetName(); if (s->GetUplink() == Me && Capab.HasFlag(CAPAB_UNCONNECT)) { @@ -547,14 +513,14 @@ bool IRCdMessage::OnWhois(const Anope::string &source, const std::vector<Anope:: ircdproto->SendNumeric(Config->ServerName, 317, source, "%s %ld %ld :seconds idle, signon time", bi->nick.c_str(), static_cast<long>(Anope::CurTime - bi->lastmsg), static_cast<long>(start_time)); ircdproto->SendNumeric(Config->ServerName, 318, source, "%s :End of /WHOIS list.", who.c_str()); } - else if (!ircd->svshold && (u = finduser(who)) && u->server == Me) + else if ((u = finduser(who)) && u->server == Me) { ircdproto->SendNumeric(Config->ServerName, 311, source, "%s %s %s * :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), u->realname.c_str()); ircdproto->SendNumeric(Config->ServerName, 312, source, "%s %s :%s", u->nick.c_str(), Config->ServerName.c_str(), Config->ServerDesc.c_str()); ircdproto->SendNumeric(Config->ServerName, 318, source, "%s :End of /WHOIS list.", u->nick.c_str()); } else - ircdproto->SendNumeric(Config->ServerName, 401, source, "%s :No such service.", who.c_str()); + ircdproto->SendNumeric(Config->ServerName, 401, source, "%s :No such user.", who.c_str()); } return true; diff --git a/src/regchannel.cpp b/src/regchannel.cpp index 9d0a95059..8bc369511 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -11,6 +11,8 @@ #include "services.h" #include "modules.h" +#include "chanserv.h" +#include "nickserv.h" ChanAccess::ChanAccess(const Anope::string &umask) { @@ -164,6 +166,16 @@ ChannelInfo::~ChannelInfo() --this->founder->channelcount; } +/** Find which bot should send mode/topic/etc changes for this channel + * @return The bot + */ +BotInfo *ChannelInfo::WhoSends() +{ + if (!this || !this->bi || !this->c || !this->botflags.HasFlag(BS_SYMBIOSIS) || !this->c->FindUser(this->bi)) + return chanserv ? chanserv->Bot() : (nickserv ? nickserv->Bot() : NULL); + return this->bi; +} + /** Add an entry to the channel access list * * @param mask The mask of the access entry @@ -553,7 +565,7 @@ void ChannelInfo::LoadMLock() else { if (!this->bi) - whosends(this)->Assign(NULL, this); + this->WhoSends()->Assign(NULL, this); if (this->c->FindUser(this->bi) == NULL) this->bi->Join(this->c); @@ -860,7 +872,7 @@ void ChannelInfo::RestoreTopic() if ((this->HasFlag(CI_KEEPTOPIC) || this->HasFlag(CI_TOPICLOCK)) && this->last_topic != this->c->topic) { - this->c->ChangeTopic(!this->last_topic_setter.empty() ? this->last_topic_setter : whosends(this)->nick, this->last_topic, this->last_topic_time ? this->last_topic_time : Anope::CurTime); + this->c->ChangeTopic(!this->last_topic_setter.empty() ? this->last_topic_setter : this->WhoSends()->nick, this->last_topic, this->last_topic_time ? this->last_topic_time : Anope::CurTime); } } diff --git a/src/servers.cpp b/src/servers.cpp index 7bde57a35..096be0c9c 100644 --- a/src/servers.cpp +++ b/src/servers.cpp @@ -309,10 +309,6 @@ void do_server(const Anope::string &source, const Anope::string &servername, uns /* Create a server structure. */ Server *newserver = new Server(s, servername, hops, descript, numeric); - /* Announce services being online. */ - if (Config->GlobalOnCycle && !Config->GlobalOnCycleUP.empty() && !Config->s_GlobalNoticer.empty()) - notice_server(Config->s_GlobalNoticer, newserver, "%s", Config->GlobalOnCycleUP.c_str()); - /* Let modules know about the connection */ FOREACH_MOD(I_OnNewServer, OnNewServer(newserver)); } diff --git a/src/sessions.cpp b/src/sessions.cpp deleted file mode 100644 index 358527ea0..000000000 --- a/src/sessions.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* Session Limiting functions. - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "services.h" -#include "modules.h" - -/*************************************************************************/ - -/* SESSION LIMITING - * - * The basic idea of session limiting is to prevent one host from having more - * than a specified number of sessions (client connections/clones) on the - * network at any one time. To do this we have a list of sessions and - * exceptions. Each session structure records information about a single host, - * including how many clients (sessions) that host has on the network. When a - * host reaches it's session limit, no more clients from that host will be - * allowed to connect. - * - * When a client connects to the network, we check to see if their host has - * reached the default session limit per host, and thus whether it is allowed - * any more. If it has reached the limit, we kill the connecting client; all - * the other clients are left alone. Otherwise we simply increment the counter - * within the session structure. When a client disconnects, we decrement the - * counter. When the counter reaches 0, we free the session. - * - * Exceptions allow one to specify custom session limits for a specific host - * or a range thereof. The first exception that the host matches is the one - * used. - * - * -TheShadow (02 April 1999) - */ - -/*************************************************************************/ - -Anope::map<Session *> SessionList; - -std::vector<Exception *> exceptions; - -/*************************************************************************/ -/****************************** Statistics *******************************/ -/*************************************************************************/ - -void get_session_stats(long &count, long &mem) -{ - count = SessionList.size(); - mem = sizeof(Session) * SessionList.size(); - - for (Anope::map<Session *>::iterator it = SessionList.begin(), it_end = SessionList.end(); it != it_end; ++it) - { - Session *session = it->second; - mem += session->host.length() + 1; - } -} - -void get_exception_stats(long &count, long &mem) -{ - count = exceptions.size(); - mem = sizeof(Exception) * exceptions.size(); - - for (std::vector<Exception *>::const_iterator it = exceptions.begin(), it_end = exceptions.end(); it != it_end; ++it) - { - Exception *e = *it; - if (!e->mask.empty()) - mem += e->mask.length() + 1; - if (!e->reason.empty()) - mem += e->reason.length() + 1; - if (!e->who.empty()) - mem += e->who.length() + 1; - } -} - -/*************************************************************************/ -/********************* Internal Session Functions ************************/ -/*************************************************************************/ - -Session *findsession(const Anope::string &host) -{ - Anope::map<Session *>::iterator it = SessionList.find(host); - if (it != SessionList.end()) - return it->second; - return NULL; -} - -/* Attempt to add a host to the session list. If the addition of the new host - * causes the the session limit to be exceeded, kill the connecting user. - */ - -void add_session(User *u) -{ - const Anope::string &hostip = u->ip() ? u->ip.addr() : ""; - Session *session = findsession(u->host); - - if (session) - { - bool kill = false; - if (Config->DefSessionLimit && session->count >= Config->DefSessionLimit) - { - kill = true; - Exception *exception = find_hostip_exception(u->host, hostip); - if (exception) - { - kill = false; - if (exception->limit && session->count >= exception->limit) - kill = true; - } - } - - if (kill) - { - if (!Config->SessionLimitExceeded.empty()) - u->SendMessage(OperServ, Config->SessionLimitExceeded.c_str(), u->host.c_str()); - if (!Config->SessionLimitDetailsLoc.empty()) - u->SendMessage(OperServ, "%s", Config->SessionLimitDetailsLoc.c_str()); - - /* Previously on IRCds that send a QUIT (InspIRCD) when a user is killed, the session for a host was - * decremented in do_quit, which caused problems and fixed here - * - * Now, we create the user struture before calling this to fix some user tracking issues, - * so we must increment this here no matter what because it will either be - * decremented in do_kill or in do_quit - Adam - */ - ++session->count; - kill_user(Config->s_OperServ, u, "Session limit exceeded"); - - ++session->hits; - if (Config->MaxSessionKill && session->hits >= Config->MaxSessionKill && SGLine) - { - const Anope::string &akillmask = "*@" + u->host; - const Anope::string &akillreason = "Session limit exceeded for " + u->host; - SGLine->Add(NULL, NULL, akillmask, Anope::CurTime + Config->SessionAutoKillExpiry, akillreason); - ircdproto->SendGlobops(OperServ, "Added a temporary AKILL for \2%s\2 due to excessive connections", akillmask.c_str()); - } - } - else - { - ++session->count; - } - } - else - { - session = new Session(); - session->host = u->host; - session->count = 1; - session->hits = 0; - - SessionList[session->host] = session; - } -} - -void del_session(User *u) -{ - if (!Config->LimitSessions) - { - Log(LOG_DEBUG) << "del_session called when LimitSessions is disabled"; - return; - } - - if (!u) - { - Log(LOG_DEBUG) << "del_session called with NULL values"; - return; - } - - Log(LOG_DEBUG_2) << "del_session() called"; - - Session *session = findsession(u->host); - - if (!session) - { - if (debug) - { - ircdproto->SendGlobops(OperServ, "WARNING: Tried to delete non-existant session: \2%s", u->host.c_str()); - Log() << "session: Tried to delete non-existant session: " << u->host; - } - return; - } - - if (session->count > 1) - { - --session->count; - return; - } - - SessionList.erase(session->host); - - delete session; - - Log(LOG_DEBUG_2) << "del_session() done"; -} - -/*************************************************************************/ -/********************** Internal Exception Functions *********************/ -/*************************************************************************/ - -void expire_exceptions() -{ - for (unsigned i = exceptions.size(); i > 0; --i) - { - Exception *e = exceptions[i - 1]; - - if (!e->expires || e->expires > Anope::CurTime) - continue; - if (Config->WallExceptionExpire) - ircdproto->SendGlobops(OperServ, "Session limit exception for %s has expired.", e->mask.c_str()); - delete e; - exceptions.erase(exceptions.begin() + i - 1); - } -} - -/* Find the first exception this host matches and return it. */ -Exception *find_host_exception(const Anope::string &host) -{ - for (std::vector<Exception *>::const_iterator it = exceptions.begin(), it_end = exceptions.end(); it != it_end; ++it) - { - Exception *e = *it; - if (Anope::Match(host, e->mask)) - return e; - } - - return NULL; -} - -/* Same as find_host_exception() except - * this tries to find the exception by IP also. */ -Exception *find_hostip_exception(const Anope::string &host, const Anope::string &hostip) -{ - for (std::vector<Exception *>::const_iterator it = exceptions.begin(), it_end = exceptions.end(); it != it_end; ++it) - { - Exception *e = *it; - if (Anope::Match(host, e->mask) || (!hostip.empty() && Anope::Match(hostip, e->mask))) - return e; - } - - return NULL; -} - -/*************************************************************************/ -/************************ Exception Manipulation *************************/ -/*************************************************************************/ - -int exception_add(User *u, const Anope::string &mask, unsigned limit, const Anope::string &reason, const Anope::string &who, time_t expires) -{ - /* Check if an exception already exists for this mask */ - for (std::vector<Exception *>::iterator it = exceptions.begin(), it_end = exceptions.end(); it != it_end; ++it) - { - Exception *e = *it; - if (e->mask.equals_ci(mask)) - { - if (e->limit != limit) - { - e->limit = limit; - if (u) - u->SendMessage(OperServ, _("Exception for \002%s\002 has been updated to %d."), mask.c_str(), e->limit); - return -2; - } - else - { - if (u) - u->SendMessage(OperServ, _("\002%s\002 already exists on the EXCEPTION list."), mask.c_str()); - return -1; - } - } - } - - Exception *exception = new Exception(); - exception->mask = mask; - exception->limit = limit; - exception->reason = reason; - exception->time = Anope::CurTime; - exception->who = who; - exception->expires = expires; - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnExceptionAdd, OnExceptionAdd(u, exception)); - if (MOD_RESULT == EVENT_STOP) - { - delete exception; - return -3; - } - - exceptions.push_back(exception); - - return 1; -} diff --git a/src/users.cpp b/src/users.cpp index f2206be7f..88ab225b6 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -11,6 +11,7 @@ #include "services.h" #include "modules.h" +#include "nickserv.h" Anope::insensitive_map<User *> UserListByNick; Anope::map<User *> UserListByUID; @@ -204,9 +205,6 @@ User::~User() while (!this->chans.empty()) this->chans.front()->chan->DeleteUser(this); - if (Config->LimitSessions && !this->server->IsULined()) - del_session(this); - UserListByNick.erase(this->nick); if (!this->uid.empty()) UserListByUID.erase(this->uid); @@ -322,7 +320,7 @@ void User::Collide(NickAlias *na) guestnick = Config->NSGuestNickPrefix + stringify(getrandom16()); } while (finduser(guestnick)); - this->SendMessage(NickServ, _("Your nickname is now being changed to \002%s\002"), guestnick.c_str()); + this->SendMessage(nickserv->Bot(), _("Your nickname is now being changed to \002%s\002"), guestnick.c_str()); ircdproto->SendForceNickChange(this, guestnick, Anope::CurTime); } else @@ -354,36 +352,7 @@ void User::Identify(NickAlias *na) ircdproto->SendAccountLogin(this, this->Account()); ircdproto->SetAutoIdentificationToken(this); - NickAlias *this_na = findnick(this->nick); - if (this_na && this_na->nc == na->nc && this_na->nc->HasFlag(NI_UNCONFIRMED) == false) - this->SetMode(NickServ, UMODE_REGISTERED); - if (ircd->vhost) - do_on_id(this); - if (Config->NSModeOnID) - do_setmodes(this); - FOREACH_MOD(I_OnNickIdentify, OnNickIdentify(this)); - - if (Config->NSForceEmail && na->nc->email.empty()) - { - this->SendMessage(NickServ, _("You must now supply an e-mail for your nick.\n" - "This e-mail will allow you to retrieve your password in\n" - "case you forget it.")); - this->SendMessage(NickServ, _("Type \002%s%s SET EMAIL \037e-mail\037\002 in order to set your e-mail.\n" - "Your privacy is respected; this e-mail won't be given to\n" - "any third-party person."), Config->UseStrictPrivMsgString.c_str(), NickServ->nick.c_str()); - } - - if (na->nc->HasFlag(NI_UNCONFIRMED)) - { - this->SendMessage(NickServ, _("Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you when you registered.")); - time_t time_registered = Anope::CurTime - na->time_registered; - if (Config->NSUnconfirmedExpire > time_registered) - this->SendMessage(NickServ, _("Your account will expire, if not confirmed, in %s"), duration(Config->NSUnconfirmedExpire - time_registered).c_str()); - } - - check_memos(this); - } @@ -397,7 +366,6 @@ void User::Login(NickCore *core) core->Users.push_back(this); this->UpdateHost(); - check_memos(this); } /** Logout the user @@ -698,22 +666,14 @@ void User::SetModesInternal(const char *umodes, ...) { case UMODE_OPER: if (add) - { ++opcnt; - if (Config->WallOper) - ircdproto->SendGlobops(OperServ, "\2%s\2 is now an IRC operator.", this->nick.c_str()); - Log(OperServ) << this->nick << " is now an IRC operator"; - } else - { --opcnt; - Log(OperServ) << this->nick << " is no longer an IRC operator"; - } break; case UMODE_REGISTERED: - if (add && !this->IsIdentified()) - this->RemoveMode(NickServ, UMODE_REGISTERED); + if (add && !this->IsIdentified() && nickserv) + this->RemoveMode(nickserv->Bot(), UMODE_REGISTERED); break; case UMODE_CLOAK: case UMODE_VHOST: @@ -751,32 +711,6 @@ bool User::IsProtected() const return false; } -/*************************************************************************/ - -void get_user_stats(long &count, long &mem) -{ - count = mem = 0; - - for (Anope::insensitive_map<User *>::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - { - User *user = it->second; - - ++count; - mem += sizeof(*user); - if (!user->host.empty()) - mem += user->host.length() + 1; - if (ircd->vhost) - { - if (!user->vhost.empty()) - mem += user->vhost.length() + 1; - } - if (!user->realname.empty()) - mem += user->realname.length() + 1; - mem += user->server->GetName().length() + 1; - mem += (sizeof(ChannelContainer) * user->chans.size()); - } -} - User *finduser(const Anope::string &nick) { if (isdigit(nick[0]) && ircd->ts6) @@ -836,28 +770,14 @@ User *do_nick(const Anope::string &source, const Anope::string &nick, const Anop } } - Log(*user, "connect") << (!vhost.empty() ? Anope::string("(") + vhost + ")" : "") << " (" << user->realname << ") " << (user->ip() ? Anope::string("[") + user->ip.addr() + "] " : "") << "connected to the network (" << serv->GetName() << ")"; - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreUserConnect, OnPreUserConnect(*user)); - - if (user && MOD_RESULT != EVENT_STOP) - { - if (Config->LimitSessions && !serv->IsULined()) - add_session(*user); + Log(user, "connect") << (!vhost.empty() ? Anope::string("(") + vhost + ")" : "") << " (" << user->realname << ") " << (user->ip() ? Anope::string("[") + user->ip.addr() + "] " : "") << "connected to the network (" << serv->GetName() << ")"; - if (!user) - return NULL; - - XLineManager::CheckAll(*user); - } - - if (!user) - return NULL; - - FOREACH_MOD(I_OnUserConnect, OnUserConnect(*user)); + bool exempt = false; + if (user->server && user->server->IsULined()) + exempt = true; + FOREACH_MOD(I_OnUserConnect, OnUserConnect(user, exempt)); - return user ? *user : NULL; + return user; } else { @@ -898,20 +818,19 @@ User *do_nick(const Anope::string &source, const Anope::string &nick, const Anop /* If the new nick isnt registerd or its registerd and not yours */ if (!na || na->nc != user->Account()) { - user->RemoveMode(NickServ, UMODE_REGISTERED); + user->RemoveMode(nickserv->Bot(), UMODE_REGISTERED); ircdproto->SendUnregisteredNick(user); - validate_user(user); + nickserv->Validate(user); } else { na->last_seen = Anope::CurTime; user->UpdateHost(); - do_on_id(user); ircdproto->SetAutoIdentificationToken(user); if (na->nc->HasFlag(NI_UNCONFIRMED) == false) - user->SetMode(NickServ, UMODE_REGISTERED); - Log(NickServ) << user->GetMask() << " automatically identified for group " << user->Account()->display; + user->SetMode(nickserv->Bot(), UMODE_REGISTERED); + Log(nickserv->Bot()) << user->GetMask() << " automatically identified for group " << user->Account()->display; } if (ircd->sqline) diff --git a/src/win32/anope_windows.h b/src/win32/anope_windows.h index 3abe8bd13..97ad76080 100644 --- a/src/win32/anope_windows.h +++ b/src/win32/anope_windows.h @@ -45,7 +45,9 @@ extern CoreExport USHORT WindowsGetLanguage(const char *lang);
extern CoreExport int inet_pton(int af, const char *src, void *dst);
extern CoreExport const char *inet_ntop(int af, const void *src, char *dst, size_t size);
-extern CoreExport int gettimeofday(timeval *tv, char *);
+extern CoreExport int gettimeofday(timeval *tv, void *);
+extern CoreExport Anope::string GetWindowsVersion();
+extern CoreExport bool SupportedWindowsVersion();
#endif // _WIN32
- #endif // WINDOWS_H
\ No newline at end of file + #endif // WINDOWS_H
diff --git a/src/win32/windows.cpp b/src/win32/windows.cpp index b57171dec..3876c62bf 100644 --- a/src/win32/windows.cpp +++ b/src/win32/windows.cpp @@ -128,7 +128,7 @@ const char *inet_ntop(int af, const void *src, char *dst, size_t size) * @param tz Should be NULL, it is not used * @return 0 on success */ -int gettimeofday(timeval *tv, char *) +int gettimeofday(timeval *tv, void *) { SYSTEMTIME st; GetSystemTime(&st); @@ -139,4 +139,154 @@ int gettimeofday(timeval *tv, char *) return 0; } +Anope::string GetWindowsVersion() +{ + OSVERSIONINFOEX osvi; + SYSTEM_INFO si; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + ZeroMemory(&si, sizeof(SYSTEM_INFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + BOOL bOsVersionInfoEx = GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi)); + if (!bOsVersionInfoEx) + { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi))) + return ""; + } + GetSystemInfo(&si); + + Anope::string buf, extra, cputype; + /* Determine CPU type 32 or 64 */ + if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) + cputype = " 64-bit"; + else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) + cputype = " 32-bit"; + else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) + cputype = " Itanium 64-bit"; + + switch (osvi.dwPlatformId) + { + /* test for the Windows NT product family. */ + case VER_PLATFORM_WIN32_NT: + /* Windows Vista or Windows Server 2008 */ + if (osvi.dwMajorVersion == 6 && !osvi.dwMinorVersion) + { + if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + extra = " Enterprise Edition"; + else if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + extra = " Datacenter Edition"; + else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) + extra = " Home Premium/Basic"; + if (osvi.dwMinorVersion == 0) + { + if (osvi.wProductType & VER_NT_WORKSTATION) + buf = "Microsoft Windows Vista" + cputype + extra; + else + buf = "Microsoft Windows Server 2008" + cputype + extra; + } + else if (osvi.dwMinorVersion == 1) + { + if (osvi.wProductType & VER_NT_WORKSTATION) + buf = "Microsoft Windows 7" + cputype + extra; + else + buf = "Microsoft Windows Server 2008 R2" + cputype + extra; + } + } + /* Windows 2003 or Windows XP Pro 64 */ + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) + { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + extra = " Datacenter Edition"; + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + extra = " Enterprise Edition"; +#ifdef VER_SUITE_COMPUTE_SERVER + else if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER) + extra = " Compute Cluster Edition"; +#endif + else if (osvi.wSuiteMask == VER_SUITE_BLADE) + extra = " Web Edition"; + else + extra = " Standard Edition"; + if (osvi.wProductType & VER_NT_WORKSTATION && si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) + buf = "Microsoft Windows XP Professional x64 Edition" + extra; + else + buf = "Microsoft Windows Server 2003 Family" + cputype + extra; + } + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) + { + if (osvi.wSuiteMask & VER_SUITE_EMBEDDEDNT) + extra = " Embedded"; + else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) + extra = " Home Edition"; + buf = "Microsoft Windows XP" + extra; + } + if (osvi.dwMajorVersion == 5 && !osvi.dwMinorVersion) + { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + extra = " Datacenter Server"; + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + extra = " Advanced Server"; + else + extra = " Server"; + buf = "Microsoft Windows 2000" + extra; + } + if (osvi.dwMajorVersion <= 4) + { + if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + extra = " Enterprise Edition"; + buf = "Microsoft Windows NT Server 4.0" + extra; + } + break; + case VER_PLATFORM_WIN32_WINDOWS: + if (osvi.dwMajorVersion == 4 && !osvi.dwMinorVersion) + { + if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B') + extra = " OSR2"; + buf = "Microsoft Windows 95" + extra; + } + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) + { + if (osvi.szCSDVersion[1] == 'A') + extra = "SE"; + buf = "Microsoft Windows 98" + extra; + } + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) + buf = "Microsoft Windows Millenium Edition"; + } + return buf; +} + +bool SupportedWindowsVersion() +{ + OSVERSIONINFOEX osvi; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + BOOL bOsVersionInfoEx = GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi)); + if (!bOsVersionInfoEx) + { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi))) + return false; + } + + switch (osvi.dwPlatformId) + { + /* test for the Windows NT product family. */ + case VER_PLATFORM_WIN32_NT: + /* win nt4 */ + if (osvi.dwMajorVersion <= 4) + return false; + /* the rest */ + return true; + /* win95 win98 winME */ + case VER_PLATFORM_WIN32_WINDOWS: + return false; + } + return false; +} + #endif |