]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_hostcycle.cpp
e8a0abbf15800d1f6871483a2ad80e55c07a28b4
[user/henk/code/inspircd.git] / src / modules / m_hostcycle.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2013 Attila Molnar <attilamolnar@hush.com>
5  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
6  *
7  * This file is part of InspIRCd.  InspIRCd is free software: you can
8  * redistribute it and/or modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation, version 2.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20
21 #include "inspircd.h"
22
23 class ModuleHostCycle : public Module
24 {
25         /** Send fake quit/join/mode messages for host or ident cycle.
26          */
27         static void DoHostCycle(User* user, const std::string& newident, const std::string& newhost, const char* quitmsg)
28         {
29                 // GetFullHost() returns the original data at the time this function is called
30                 const std::string quitline = ":" + user->GetFullHost() + " QUIT :" + quitmsg;
31
32                 already_sent_t silent_id = ++LocalUser::already_sent_id;
33                 already_sent_t seen_id = ++LocalUser::already_sent_id;
34
35                 IncludeChanList include_chans(user->chans.begin(), user->chans.end());
36                 std::map<User*,bool> exceptions;
37
38                 FOREACH_MOD(OnBuildNeighborList, (user, include_chans, exceptions));
39
40                 for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
41                 {
42                         LocalUser* u = IS_LOCAL(i->first);
43                         if (u && !u->quitting)
44                         {
45                                 if (i->second)
46                                 {
47                                         u->already_sent = seen_id;
48                                         u->Write(quitline);
49                                 }
50                                 else
51                                 {
52                                         u->already_sent = silent_id;
53                                 }
54                         }
55                 }
56
57                 std::string newfullhost = user->nick + "!" + newident + "@" + newhost;
58
59                 for (IncludeChanList::const_iterator i = include_chans.begin(); i != include_chans.end(); ++i)
60                 {
61                         Membership* memb = *i;
62                         Channel* c = memb->chan;
63                         const std::string joinline = ":" + newfullhost + " JOIN " + c->name;
64                         std::string modeline;
65
66                         if (!memb->modes.empty())
67                         {
68                                 modeline = ":" + (ServerInstance->Config->CycleHostsFromUser ? newfullhost : ServerInstance->Config->ServerName)
69                                         + " MODE " + c->name + " +" + memb->modes;
70
71                                 for (size_t j = 0; j < memb->modes.length(); j++)
72                                         modeline.append(" ").append(user->nick);
73                         }
74
75                         const Channel::MemberMap& ulist = c->GetUsers();
76                         for (Channel::MemberMap::const_iterator j = ulist.begin(); j != ulist.end(); ++j)
77                         {
78                                 LocalUser* u = IS_LOCAL(j->first);
79                                 if (u == NULL || u == user)
80                                         continue;
81                                 if (u->already_sent == silent_id)
82                                         continue;
83
84                                 if (u->already_sent != seen_id)
85                                 {
86                                         u->Write(quitline);
87                                         u->already_sent = seen_id;
88                                 }
89
90                                 u->Write(joinline);
91                                 if (!memb->modes.empty())
92                                         u->Write(modeline);
93                         }
94                 }
95         }
96
97  public:
98         void OnChangeIdent(User* user, const std::string& newident) CXX11_OVERRIDE
99         {
100                 DoHostCycle(user, newident, user->dhost, "Changing ident");
101         }
102
103         void OnChangeHost(User* user, const std::string& newhost) CXX11_OVERRIDE
104         {
105                 DoHostCycle(user, user->ident, newhost, "Changing host");
106         }
107
108         Version GetVersion() CXX11_OVERRIDE
109         {
110                 return Version("Cycles users in all their channels when their host or ident changes", VF_VENDOR);
111         }
112 };
113
114 MODULE_INIT(ModuleHostCycle)