]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/coremods/core_channel/invite.cpp
Fix a bunch of weird indentation and spacing issues.
[user/henk/code/inspircd.git] / src / coremods / core_channel / invite.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2018-2019 Sadie Powell <sadie@witchery.services>
5  *   Copyright (C) 2015 Attila Molnar <attilamolnar@hush.com>
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 #include "invite.h"
24
25 class InviteExpireTimer : public Timer
26 {
27         Invite::Invite* const inv;
28
29         bool Tick(time_t currtime) CXX11_OVERRIDE;
30
31  public:
32         InviteExpireTimer(Invite::Invite* invite, time_t timeout);
33 };
34
35 static Invite::APIImpl* apiimpl;
36
37 void RemoveInvite(Invite::Invite* inv, bool remove_user, bool remove_chan)
38 {
39         apiimpl->Destruct(inv, remove_user, remove_chan);
40 }
41
42 void UnserializeInvite(LocalUser* user, const std::string& str)
43 {
44         apiimpl->Unserialize(user, str);
45 }
46
47 Invite::APIBase::APIBase(Module* parent)
48         : DataProvider(parent, "core_channel_invite")
49 {
50 }
51
52 Invite::APIImpl::APIImpl(Module* parent)
53         : APIBase(parent)
54         , userext(parent, "invite_user")
55         , chanext(parent, "invite_chan")
56 {
57         apiimpl = this;
58 }
59
60 void Invite::APIImpl::Destruct(Invite* inv, bool remove_user, bool remove_chan)
61 {
62         Store<LocalUser>* ustore = userext.get(inv->user);
63         if (ustore)
64         {
65                 ustore->invites.erase(inv);
66                 if ((remove_user) && (ustore->invites.empty()))
67                         userext.unset(inv->user);
68         }
69
70         Store<Channel>* cstore = chanext.get(inv->chan);
71         if (cstore)
72         {
73                 cstore->invites.erase(inv);
74                 if ((remove_chan) && (cstore->invites.empty()))
75                         chanext.unset(inv->chan);
76         }
77
78         delete inv;
79 }
80
81 bool Invite::APIImpl::Remove(LocalUser* user, Channel* chan)
82 {
83         Invite* inv = Find(user, chan);
84         if (inv)
85         {
86                 Destruct(inv);
87                 return true;
88         }
89         return false;
90 }
91
92 void Invite::APIImpl::Create(LocalUser* user, Channel* chan, time_t timeout)
93 {
94         if ((timeout != 0) && (ServerInstance->Time() >= timeout))
95                 // Expired, don't bother
96                 return;
97
98         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::APIImpl::Create(): user=%s chan=%s timeout=%lu", user->uuid.c_str(), chan->name.c_str(), (unsigned long)timeout);
99
100         Invite* inv = Find(user, chan);
101         if (inv)
102         {
103                 // We only ever extend invites, so nothing to do if the existing one is not timed
104                 if (!inv->IsTimed())
105                         return;
106
107                 ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::APIImpl::Create(): changing expiration in %p", (void*) inv);
108                 if (timeout == 0)
109                 {
110                         // Convert timed invite to non-expiring
111                         delete inv->expiretimer;
112                         inv->expiretimer = NULL;
113                 }
114                 else if (inv->expiretimer->GetTrigger() >= ServerInstance->Time() + timeout)
115                 {
116                         // New expiration time is further than the current, extend the expiration
117                         inv->expiretimer->SetInterval(timeout - ServerInstance->Time());
118                 }
119         }
120         else
121         {
122                 inv = new Invite(user, chan);
123                 if (timeout)
124                 {
125                         inv->expiretimer = new InviteExpireTimer(inv, timeout - ServerInstance->Time());
126                         ServerInstance->Timers.AddTimer(inv->expiretimer);
127                 }
128
129                 userext.get(user, true)->invites.push_front(inv);
130                 chanext.get(chan, true)->invites.push_front(inv);
131                 ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::APIImpl::Create(): created new Invite %p", (void*) inv);
132         }
133 }
134
135 Invite::Invite* Invite::APIImpl::Find(LocalUser* user, Channel* chan)
136 {
137         const List* list = APIImpl::GetList(user);
138         if (!list)
139                 return NULL;
140
141         for (List::iterator i = list->begin(); i != list->end(); ++i)
142         {
143                 Invite* inv = *i;
144                 if (inv->chan == chan)
145                         return inv;
146         }
147
148         return NULL;
149 }
150
151 const Invite::List* Invite::APIImpl::GetList(LocalUser* user)
152 {
153         Store<LocalUser>* list = userext.get(user);
154         if (list)
155                 return &list->invites;
156         return NULL;
157 }
158
159 void Invite::APIImpl::Unserialize(LocalUser* user, const std::string& value)
160 {
161         irc::spacesepstream ss(value);
162         for (std::string channame, exptime; (ss.GetToken(channame) && ss.GetToken(exptime)); )
163         {
164                 Channel* chan = ServerInstance->FindChan(channame);
165                 if (chan)
166                         Create(user, chan, ConvToNum<time_t>(exptime));
167         }
168 }
169
170 Invite::Invite::Invite(LocalUser* u, Channel* c)
171         : user(u)
172         , chan(c)
173         , expiretimer(NULL)
174 {
175 }
176
177 Invite::Invite::~Invite()
178 {
179         delete expiretimer;
180         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::~ %p", (void*) this);
181 }
182
183 void Invite::Invite::Serialize(bool human, bool show_chans, std::string& out)
184 {
185         if (show_chans)
186                 out.append(this->chan->name);
187         else
188                 out.append(human ? user->nick : user->uuid);
189         out.push_back(' ');
190
191         if (expiretimer)
192                 out.append(ConvToStr(expiretimer->GetTrigger()));
193         else
194                 out.push_back('0');
195         out.push_back(' ');
196 }
197
198 InviteExpireTimer::InviteExpireTimer(Invite::Invite* invite, time_t timeout)
199         : Timer(timeout)
200         , inv(invite)
201 {
202 }
203
204 bool InviteExpireTimer::Tick(time_t currtime)
205 {
206         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "InviteExpireTimer::Tick(): expired %p", (void*) inv);
207         apiimpl->Destruct(inv);
208         return false;
209 }