]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_hostcycle.cpp
0f7405dcc8b83f45ca93428cffeadc97c3f343c0
[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 #include "modules/cap.h"
23
24 class ModuleHostCycle : public Module
25 {
26         Cap::Reference chghostcap;
27
28         /** Send fake quit/join/mode messages for host or ident cycle.
29          */
30         void DoHostCycle(User* user, const std::string& newident, const std::string& newhost, const char* quitmsg)
31         {
32                 // GetFullHost() returns the original data at the time this function is called
33                 const std::string quitline = ":" + user->GetFullHost() + " QUIT :" + quitmsg;
34
35                 already_sent_t silent_id = ServerInstance->Users.NextAlreadySentId();
36                 already_sent_t seen_id = ServerInstance->Users.NextAlreadySentId();
37
38                 IncludeChanList include_chans(user->chans.begin(), user->chans.end());
39                 std::map<User*,bool> exceptions;
40
41                 FOREACH_MOD(OnBuildNeighborList, (user, include_chans, exceptions));
42
43                 // Users shouldn't see themselves quitting when host cycling
44                 exceptions.erase(user);
45                 for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
46                 {
47                         LocalUser* u = IS_LOCAL(i->first);
48                         if ((u) && (!u->quitting) && (!chghostcap.get(u)))
49                         {
50                                 if (i->second)
51                                 {
52                                         u->already_sent = seen_id;
53                                         u->Write(quitline);
54                                 }
55                                 else
56                                 {
57                                         u->already_sent = silent_id;
58                                 }
59                         }
60                 }
61
62                 std::string newfullhost = user->nick + "!" + newident + "@" + newhost;
63
64                 for (IncludeChanList::const_iterator i = include_chans.begin(); i != include_chans.end(); ++i)
65                 {
66                         Membership* memb = *i;
67                         Channel* c = memb->chan;
68                         const std::string joinline = ":" + newfullhost + " JOIN " + c->name;
69                         std::string modeline;
70
71                         if (!memb->modes.empty())
72                         {
73                                 modeline = ":" + (ServerInstance->Config->CycleHostsFromUser ? newfullhost : ServerInstance->Config->ServerName)
74                                         + " MODE " + c->name + " +" + memb->modes;
75
76                                 for (size_t j = 0; j < memb->modes.length(); j++)
77                                         modeline.append(" ").append(user->nick);
78                         }
79
80                         const Channel::MemberMap& ulist = c->GetUsers();
81                         for (Channel::MemberMap::const_iterator j = ulist.begin(); j != ulist.end(); ++j)
82                         {
83                                 LocalUser* u = IS_LOCAL(j->first);
84                                 if (u == NULL || u == user)
85                                         continue;
86                                 if (u->already_sent == silent_id)
87                                         continue;
88                                 if (chghostcap.get(u))
89                                         continue;
90
91                                 if (u->already_sent != seen_id)
92                                 {
93                                         u->Write(quitline);
94                                         u->already_sent = seen_id;
95                                 }
96
97                                 u->Write(joinline);
98                                 if (!memb->modes.empty())
99                                         u->Write(modeline);
100                         }
101                 }
102         }
103
104  public:
105         ModuleHostCycle()
106                 : chghostcap(this, "chghost")
107         {
108         }
109
110         void OnChangeIdent(User* user, const std::string& newident) CXX11_OVERRIDE
111         {
112                 DoHostCycle(user, newident, user->GetDisplayedHost(), "Changing ident");
113         }
114
115         void OnChangeHost(User* user, const std::string& newhost) CXX11_OVERRIDE
116         {
117                 DoHostCycle(user, user->ident, newhost, "Changing host");
118         }
119
120         Version GetVersion() CXX11_OVERRIDE
121         {
122                 return Version("Cycles users in all their channels when their host or ident changes", VF_VENDOR);
123         }
124 };
125
126 MODULE_INIT(ModuleHostCycle)