]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/coremods/core_channel/invite.cpp
Fix conversion issues by replacing ConvToInt with ConvToNum<T>.
[user/henk/code/inspircd.git] / src / coremods / core_channel / invite.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2012, 2015 Attila Molnar <attilamolnar@hush.com>
5  *
6  * This file is part of InspIRCd.  InspIRCd is free software: you can
7  * redistribute it and/or modify it under the terms of the GNU General Public
8  * License as published by the Free Software Foundation, version 2.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19
20 #include "inspircd.h"
21
22 #include "invite.h"
23
24 class InviteExpireTimer : public Timer
25 {
26         Invite::Invite* const inv;
27
28         bool Tick(time_t currtime) CXX11_OVERRIDE;
29
30  public:
31         InviteExpireTimer(Invite::Invite* invite, time_t timeout);
32 };
33
34 static Invite::APIImpl* apiimpl;
35
36 void RemoveInvite(Invite::Invite* inv, bool remove_user, bool remove_chan)
37 {
38         apiimpl->Destruct(inv, remove_user, remove_chan);
39 }
40
41 void UnserializeInvite(LocalUser* user, const std::string& str)
42 {
43         apiimpl->Unserialize(user, str);
44 }
45
46 Invite::APIBase::APIBase(Module* parent)
47         : DataProvider(parent, "core_channel_invite")
48 {
49 }
50
51 Invite::APIImpl::APIImpl(Module* parent)
52         : APIBase(parent)
53         , userext(parent, "invite_user")
54         , chanext(parent, "invite_chan")
55 {
56         apiimpl = this;
57 }
58
59 void Invite::APIImpl::Destruct(Invite* inv, bool remove_user, bool remove_chan)
60 {
61         Store<LocalUser>* ustore = userext.get(inv->user);
62         if (ustore)
63         {
64                 ustore->invites.erase(inv);
65                 if ((remove_user) && (ustore->invites.empty()))
66                         userext.unset(inv->user);
67         }
68
69         Store<Channel>* cstore = chanext.get(inv->chan);
70         if (cstore)
71         {
72                 cstore->invites.erase(inv);
73                 if ((remove_chan) && (cstore->invites.empty()))
74                         chanext.unset(inv->chan);
75         }
76
77         delete inv;
78 }
79
80 bool Invite::APIImpl::Remove(LocalUser* user, Channel* chan)
81 {
82         Invite* inv = Find(user, chan);
83         if (inv)
84         {
85                 Destruct(inv);
86                 return true;
87         }
88         return false;
89 }
90
91 void Invite::APIImpl::Create(LocalUser* user, Channel* chan, time_t timeout)
92 {
93         if ((timeout != 0) && (ServerInstance->Time() >= timeout))
94                 // Expired, don't bother
95                 return;
96
97         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);
98
99         Invite* inv = Find(user, chan);
100         if (inv)
101         {
102                 // We only ever extend invites, so nothing to do if the existing one is not timed
103                 if (!inv->IsTimed())
104                         return;
105
106                 ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::APIImpl::Create(): changing expiration in %p", (void*) inv);
107                 if (timeout == 0)
108                 {
109                         // Convert timed invite to non-expiring
110                         delete inv->expiretimer;
111                         inv->expiretimer = NULL;
112                 }
113                 else if (inv->expiretimer->GetTrigger() >= ServerInstance->Time() + timeout)
114                 {
115                         // New expiration time is further than the current, extend the expiration
116                         inv->expiretimer->SetInterval(timeout - ServerInstance->Time());
117                 }
118         }
119         else
120         {
121                 inv = new Invite(user, chan);
122                 if (timeout)
123                 {
124                         inv->expiretimer = new InviteExpireTimer(inv, timeout - ServerInstance->Time());
125                         ServerInstance->Timers.AddTimer(inv->expiretimer);
126                 }
127
128                 userext.get(user, true)->invites.push_front(inv);
129                 chanext.get(chan, true)->invites.push_front(inv);
130                 ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::APIImpl::Create(): created new Invite %p", (void*) inv);
131         }
132 }
133
134 Invite::Invite* Invite::APIImpl::Find(LocalUser* user, Channel* chan)
135 {
136         const List* list = APIImpl::GetList(user);
137         if (!list)
138                 return NULL;
139
140         for (List::iterator i = list->begin(); i != list->end(); ++i)
141         {
142                 Invite* inv = *i;
143                 if (inv->chan == chan)
144                         return inv;
145         }
146
147         return NULL;
148 }
149
150 const Invite::List* Invite::APIImpl::GetList(LocalUser* user)
151 {
152         Store<LocalUser>* list = userext.get(user);
153         if (list)
154                 return &list->invites;
155         return NULL;
156 }
157
158 void Invite::APIImpl::Unserialize(LocalUser* user, const std::string& value)
159 {
160         irc::spacesepstream ss(value);
161         for (std::string channame, exptime; (ss.GetToken(channame) && ss.GetToken(exptime)); )
162         {
163                 Channel* chan = ServerInstance->FindChan(channame);
164                 if (chan)
165                         Create(user, chan, ConvToNum<time_t>(exptime));
166         }
167 }
168
169 Invite::Invite::Invite(LocalUser* u, Channel* c)
170         : user(u)
171         , chan(c)
172         , expiretimer(NULL)
173 {
174 }
175
176 Invite::Invite::~Invite()
177 {
178         delete expiretimer;
179         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::~ %p", (void*) this);
180 }
181
182 void Invite::Invite::Serialize(SerializeFormat format, bool show_chans, std::string& out)
183 {
184         if (show_chans)
185                 out.append(this->chan->name);
186         else
187                 out.append((format == FORMAT_USER) ? user->nick : user->uuid);
188         out.push_back(' ');
189
190         if (expiretimer)
191                 out.append(ConvToStr(expiretimer->GetTrigger()));
192         else
193                 out.push_back('0');
194         out.push_back(' ');
195 }
196
197 InviteExpireTimer::InviteExpireTimer(Invite::Invite* invite, time_t timeout)
198         : Timer(timeout)
199         , inv(invite)
200 {
201 }
202
203 bool InviteExpireTimer::Tick(time_t currtime)
204 {
205         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "InviteExpireTimer::Tick(): expired %p", (void*) inv);
206         apiimpl->Destruct(inv);
207         return false;
208 }