]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_hostcycle.cpp
Merge insp20
[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                 for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
44                 {
45                         LocalUser* u = IS_LOCAL(i->first);
46                         if ((u) && (!u->quitting) && (!chghostcap.get(u)))
47                         {
48                                 if (i->second)
49                                 {
50                                         u->already_sent = seen_id;
51                                         u->Write(quitline);
52                                 }
53                                 else
54                                 {
55                                         u->already_sent = silent_id;
56                                 }
57                         }
58                 }
59
60                 std::string newfullhost = user->nick + "!" + newident + "@" + newhost;
61
62                 for (IncludeChanList::const_iterator i = include_chans.begin(); i != include_chans.end(); ++i)
63                 {
64                         Membership* memb = *i;
65                         Channel* c = memb->chan;
66                         const std::string joinline = ":" + newfullhost + " JOIN " + c->name;
67                         std::string modeline;
68
69                         if (!memb->modes.empty())
70                         {
71                                 modeline = ":" + (ServerInstance->Config->CycleHostsFromUser ? newfullhost : ServerInstance->Config->ServerName)
72                                         + " MODE " + c->name + " +" + memb->modes;
73
74                                 for (size_t j = 0; j < memb->modes.length(); j++)
75                                         modeline.append(" ").append(user->nick);
76                         }
77
78                         const Channel::MemberMap& ulist = c->GetUsers();
79                         for (Channel::MemberMap::const_iterator j = ulist.begin(); j != ulist.end(); ++j)
80                         {
81                                 LocalUser* u = IS_LOCAL(j->first);
82                                 if (u == NULL || u == user)
83                                         continue;
84                                 if (u->already_sent == silent_id)
85                                         continue;
86                                 if (chghostcap.get(u))
87                                         continue;
88
89                                 if (u->already_sent != seen_id)
90                                 {
91                                         u->Write(quitline);
92                                         u->already_sent = seen_id;
93                                 }
94
95                                 u->Write(joinline);
96                                 if (!memb->modes.empty())
97                                         u->Write(modeline);
98                         }
99                 }
100         }
101
102  public:
103         ModuleHostCycle()
104                 : chghostcap(this, "chghost")
105         {
106         }
107
108         void OnChangeIdent(User* user, const std::string& newident) CXX11_OVERRIDE
109         {
110                 DoHostCycle(user, newident, user->dhost, "Changing ident");
111         }
112
113         void OnChangeHost(User* user, const std::string& newhost) CXX11_OVERRIDE
114         {
115                 DoHostCycle(user, user->ident, newhost, "Changing host");
116         }
117
118         Version GetVersion() CXX11_OVERRIDE
119         {
120                 return Version("Cycles users in all their channels when their host or ident changes", VF_VENDOR);
121         }
122 };
123
124 MODULE_INIT(ModuleHostCycle)