Anope IRC Services  Version 2.0
hs_request.cpp
Go to the documentation of this file.
1 /* hs_request.c - Add request and activate functionality to HostServ,
2  *
3  *
4  * (C) 2003-2014 Anope Team
5  * Contact us at team@anope.org
6  *
7  * Based on the original module by Rob <rob@anope.org>
8  * Included in the Anope module pack since Anope 1.7.11
9  * Anope Coder: GeniusDex <geniusdex@anope.org>
10  *
11  * Please read COPYING and README for further details.
12  *
13  * Send bug reports to the Anope Coder instead of the module
14  * author, because any changes since the inclusion into anope
15  * are not supported by the original author.
16  */
17 
18 #include "module.h"
19 
20 static ServiceReference<MemoServService> memoserv("MemoServService", "MemoServ");
21 
22 static void req_send_memos(Module *me, CommandSource &source, const Anope::string &vIdent, const Anope::string &vHost);
23 
25 {
29  time_t time;
30 
31  HostRequest(Extensible *) : Serializable("HostRequest") { }
32 
34  {
35  data["nick"] << this->nick;
36  data["ident"] << this->ident;
37  data["host"] << this->host;
38  data.SetType("time", Serialize::Data::DT_INT); data["time"] << this->time;
39  }
40 
42  {
43  Anope::string snick;
44  data["nick"] >> snick;
45 
46  NickAlias *na = NickAlias::Find(snick);
47  if (na == NULL)
48  return NULL;
49 
50  HostRequest *req;
51  if (obj)
53  else
54  req = na->Extend<HostRequest>("hostrequest");
55  if (req)
56  {
57  req->nick = na->nick;
58  data["ident"] >> req->ident;
59  data["host"] >> req->host;
60  data["time"] >> req->time;
61  }
62 
63  return req;
64  }
65 };
66 
67 class CommandHSRequest : public Command
68 {
69  bool isvalidchar(char c)
70  {
71  if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-')
72  return true;
73  return false;
74  }
75 
76  public:
77  CommandHSRequest(Module *creator) : Command(creator, "hostserv/request", 1, 1)
78  {
79  this->SetDesc(_("Request a vHost for your nick"));
80  this->SetSyntax(_("vhost"));
81  }
82 
83  void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
84  {
85  if (Anope::ReadOnly)
86  {
87  source.Reply(READ_ONLY_MODE);
88  return;
89  }
90 
91  User *u = source.GetUser();
92  NickAlias *na = NickAlias::Find(source.GetNick());
93  if (!na || na->nc != source.GetAccount())
94  {
95  source.Reply(ACCESS_DENIED);
96  return;
97  }
98 
99  Anope::string rawhostmask = params[0];
100 
101  Anope::string user, host;
102  size_t a = rawhostmask.find('@');
103 
104  if (a == Anope::string::npos)
105  host = rawhostmask;
106  else
107  {
108  user = rawhostmask.substr(0, a);
109  host = rawhostmask.substr(a + 1);
110  }
111 
112  if (host.empty())
113  {
114  this->OnSyntaxError(source, "");
115  return;
116  }
117 
118  if (!user.empty())
119  {
120  if (user.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen"))
121  {
122  source.Reply(HOST_SET_IDENTTOOLONG, Config->GetBlock("networkinfo")->Get<unsigned>("userlen"));
123  return;
124  }
125  else if (!IRCD->CanSetVIdent)
126  {
127  source.Reply(HOST_NO_VIDENT);
128  return;
129  }
130  for (Anope::string::iterator s = user.begin(), s_end = user.end(); s != s_end; ++s)
131  if (!isvalidchar(*s))
132  {
133  source.Reply(HOST_SET_IDENT_ERROR);
134  return;
135  }
136  }
137 
138  if (host.length() > Config->GetBlock("networkinfo")->Get<unsigned>("hostlen"))
139  {
140  source.Reply(HOST_SET_TOOLONG, Config->GetBlock("networkinfo")->Get<unsigned>("hostlen"));
141  return;
142  }
143 
144  if (!IRCD->IsHostValid(host))
145  {
146  source.Reply(HOST_SET_ERROR);
147  return;
148  }
149 
150  time_t send_delay = Config->GetModule("memoserv")->Get<time_t>("senddelay");
151  if (Config->GetModule(this->owner)->Get<bool>("memooper") && send_delay > 0 && u && u->lastmemosend + send_delay > Anope::CurTime)
152  {
153  source.Reply(_("Please wait %d seconds before requesting a new vHost."), send_delay);
155  return;
156  }
157 
158  HostRequest req(na);
159  req.nick = source.GetNick();
160  req.ident = user;
161  req.host = host;
162  req.time = Anope::CurTime;
163  na->Extend<HostRequest>("hostrequest", req);
164 
165  source.Reply(_("Your vHost has been requested."));
166  req_send_memos(owner, source, user, host);
167  Log(LOG_COMMAND, source, this) << "to request new vhost " << (!user.empty() ? user + "@" : "") << host;
168  }
169 
170  bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
171  {
172  this->SendSyntax(source);
173  source.Reply(" ");
174  source.Reply(_("Request the given vHost to be actived for your nick by the\n"
175  "network administrators. Please be patient while your request\n"
176  "is being considered."));
177  return true;
178  }
179 };
180 
182 {
183  public:
184  CommandHSActivate(Module *creator) : Command(creator, "hostserv/activate", 1, 1)
185  {
186  this->SetDesc(_("Approve the requested vHost of a user"));
187  this->SetSyntax(_("\037nick\037"));
188  }
189 
190  void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
191  {
192  if (Anope::ReadOnly)
193  {
194  source.Reply(READ_ONLY_MODE);
195  return;
196  }
197 
198  const Anope::string &nick = params[0];
199 
200  NickAlias *na = NickAlias::Find(nick);
201  HostRequest *req = na ? na->GetExt<HostRequest>("hostrequest") : NULL;
202  if (req)
203  {
204  na->SetVhost(req->ident, req->host, source.GetNick(), req->time);
205  FOREACH_MOD(OnSetVhost, (na));
206 
207  if (Config->GetModule(this->owner)->Get<bool>("memouser") && memoserv)
208  memoserv->Send(source.service->nick, na->nick, _("[auto memo] Your requested vHost has been approved."), true);
209 
210  source.Reply(_("vHost for %s has been activated."), na->nick.c_str());
211  Log(LOG_COMMAND, source, this) << "for " << na->nick << " for vhost " << (!req->ident.empty() ? req->ident + "@" : "") << req->host;
212  na->Shrink<HostRequest>("hostrequest");
213  }
214  else
215  source.Reply(_("No request for nick %s found."), nick.c_str());
216  }
217 
218  bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
219  {
220  this->SendSyntax(source);
221  source.Reply(" ");
222  source.Reply(_("Activate the requested vHost for the given nick."));
223  if (Config->GetModule(this->owner)->Get<bool>("memouser"))
224  source.Reply(_("A memo informing the user will also be sent."));
225 
226  return true;
227  }
228 };
229 
230 class CommandHSReject : public Command
231 {
232  public:
233  CommandHSReject(Module *creator) : Command(creator, "hostserv/reject", 1, 2)
234  {
235  this->SetDesc(_("Reject the requested vHost of a user"));
236  this->SetSyntax(_("\037nick\037 [\037reason\037]"));
237  }
238 
239  void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
240  {
241  if (Anope::ReadOnly)
242  {
243  source.Reply(READ_ONLY_MODE);
244  return;
245  }
246 
247  const Anope::string &nick = params[0];
248  const Anope::string &reason = params.size() > 1 ? params[1] : "";
249 
250  NickAlias *na = NickAlias::Find(nick);
251  HostRequest *req = na ? na->GetExt<HostRequest>("hostrequest") : NULL;
252  if (req)
253  {
254  na->Shrink<HostRequest>("hostrequest");
255 
256  if (Config->GetModule(this->owner)->Get<bool>("memouser") && memoserv)
257  {
258  Anope::string message;
259  if (!reason.empty())
260  message = Anope::printf(_("[auto memo] Your requested vHost has been rejected. Reason: %s"), reason.c_str());
261  else
262  message = _("[auto memo] Your requested vHost has been rejected.");
263 
264  memoserv->Send(source.service->nick, nick, Language::Translate(source.GetAccount(), message.c_str()), true);
265  }
266 
267  source.Reply(_("vHost for %s has been rejected."), nick.c_str());
268  Log(LOG_COMMAND, source, this) << "to reject vhost for " << nick << " (" << (!reason.empty() ? reason : "no reason") << ")";
269  }
270  else
271  source.Reply(_("No request for nick %s found."), nick.c_str());
272  }
273 
274  bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
275  {
276  this->SendSyntax(source);
277  source.Reply(" ");
278  source.Reply(_("Reject the requested vHost for the given nick."));
279  if (Config->GetModule(this->owner)->Get<bool>("memouser"))
280  source.Reply(_("A memo informing the user will also be sent, which includes the reason for the rejection if supplied."));
281 
282  return true;
283  }
284 };
285 
286 class CommandHSWaiting : public Command
287 {
288  public:
289  CommandHSWaiting(Module *creator) : Command(creator, "hostserv/waiting", 0, 0)
290  {
291  this->SetDesc(_("Retrieves the vhost requests"));
292  }
293 
294  void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
295  {
296  unsigned counter = 0;
297  unsigned display_counter = 0, listmax = Config->GetModule(this->owner)->Get<unsigned>("listmax");
298  ListFormatter list(source.GetAccount());
299 
300  list.AddColumn(_("Number")).AddColumn(_("Nick")).AddColumn(_("Vhost")).AddColumn(_("Created"));
301 
302  for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ++it)
303  {
304  const NickAlias *na = it->second;
305  HostRequest *hr = na->GetExt<HostRequest>("hostrequest");
306  if (!hr)
307  continue;
308 
309  if (!listmax || display_counter < listmax)
310  {
311  ++display_counter;
312 
314  entry["Number"] = stringify(display_counter);
315  entry["Nick"] = it->first;
316  if (!hr->ident.empty())
317  entry["Vhost"] = hr->ident + "@" + hr->host;
318  else
319  entry["Vhost"] = hr->host;
320  entry["Created"] = Anope::strftime(hr->time, NULL, true);
321  list.AddEntry(entry);
322  }
323  ++counter;
324  }
325 
326  std::vector<Anope::string> replies;
327  list.Process(replies);
328 
329  for (unsigned i = 0; i < replies.size(); ++i)
330  source.Reply(replies[i]);
331 
332  source.Reply(_("Displayed \002%d\002 records (\002%d\002 total)."), display_counter, counter);
333  }
334 
335  bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
336  {
337  this->SendSyntax(source);
338  source.Reply(" ");
339  source.Reply(_("This command retrieves the vhost requests."));
340 
341  return true;
342  }
343 };
344 
345 class HSRequest : public Module
346 {
353 
354  public:
355  HSRequest(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
356  commandhsrequest(this), commandhsactive(this),
357  commandhsreject(this), commandhswaiting(this), hostrequest(this, "hostrequest"), request_type("HostRequest", HostRequest::Unserialize)
358  {
359 
360  if (!IRCD || !IRCD->CanSetVHost)
361  throw ModuleException("Your IRCd does not support vhosts");
362  }
363 };
364 
365 static void req_send_memos(Module *me, CommandSource &source, const Anope::string &vIdent, const Anope::string &vHost)
366 {
367  Anope::string host;
368  std::list<std::pair<Anope::string, Anope::string> >::iterator it, it_end;
369 
370  if (!vIdent.empty())
371  host = vIdent + "@" + vHost;
372  else
373  host = vHost;
374 
375  if (Config->GetModule(me)->Get<bool>("memooper") && memoserv)
376  for (unsigned i = 0; i < Oper::opers.size(); ++i)
377  {
378  Oper *o = Oper::opers[i];
379 
380  const NickAlias *na = NickAlias::Find(o->name);
381  if (!na)
382  continue;
383 
384  Anope::string message = Anope::printf(_("[auto memo] vHost \002%s\002 has been requested by %s."), host.c_str(), source.GetNick().c_str());
385 
386  memoserv->Send(source.service->nick, na->nick, message, true);
387  }
388 }
389 
Serialize::Reference< NickCore > nc
Definition: account.h:47
CoreExport bool ReadOnly
Definition: main.cpp:28
static NickAlias * Find(const Anope::string &nick)
Definition: nickalias.cpp:121
#define HOST_SET_ERROR
Definition: language.h:123
static Serializable * Unserialize(Serializable *obj, Serialize::Data &data)
Definition: hs_request.cpp:41
HSRequest(const Anope::string &modname, const Anope::string &creator)
Definition: hs_request.cpp:355
CommandHSWaiting(Module *creator)
Definition: hs_request.cpp:289
Definition: opertype.h:18
time_t time
Definition: hs_request.cpp:29
ExtensibleItem< HostRequest > hostrequest
Definition: hs_request.cpp:351
Anope::string nick
Definition: account.h:37
#define ACCESS_DENIED
Definition: language.h:73
CoreExport string printf(const char *fmt,...)
Definition: misc.cpp:536
#define HOST_SET_IDENT_ERROR
Definition: language.h:124
#define HOST_NO_VIDENT
Definition: language.h:128
static void req_send_memos(Module *me, CommandSource &source, const Anope::string &vIdent, const Anope::string &vHost)
Definition: hs_request.cpp:365
CommandHSReject commandhsreject
Definition: hs_request.cpp:349
Serialize::Type request_type
Definition: hs_request.cpp:352
CommandHSReject(Module *creator)
Definition: hs_request.cpp:233
Definition: users.h:34
T * Extend(const Anope::string &name, const T &what)
Definition: extensible.h:224
Anope::string host
Definition: hs_request.cpp:28
#define HOST_SET_TOOLONG
Definition: language.h:125
Anope::string name
Definition: opertype.h:21
HostRequest(Extensible *)
Definition: hs_request.cpp:31
#define READ_ONLY_MODE
Definition: language.h:71
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
Definition: hs_request.cpp:335
bool CanSetVHost
Definition: protocol.h:53
void SetDesc(const Anope::string &d)
Definition: command.cpp:130
CoreExport time_t CurTime
Definition: main.cpp:41
virtual bool IsHostValid(const Anope::string &)
Definition: protocol.cpp:401
time_t lastmemosend
Definition: users.h:90
const Anope::string & GetNick() const
Definition: command.cpp:26
CommandHSActivate commandhsactive
Definition: hs_request.cpp:348
#define FOREACH_MOD(ename, args)
Definition: modules.h:62
void Execute(CommandSource &source, const std::vector< Anope::string > &params) anope_override
Definition: hs_request.cpp:83
CoreExport Serialize::Checker< nickalias_map > NickAliasList
static Module * me
Definition: bs_kick.cpp:18
string substr(size_type pos=0, size_type n=npos) const
Definition: anope.h:277
std::map< Anope::string, Anope::string > ListEntry
Definition: lists.h:68
static std::vector< Oper * > opers
Definition: opertype.h:35
bool CanSetVIdent
Definition: protocol.h:53
size_type length() const
Definition: anope.h:131
Definition: Config.cs:26
void Shrink(const Anope::string &name)
Definition: extensible.h:253
virtual void OnSyntaxError(CommandSource &source, const Anope::string &subcommand)
Definition: command.cpp:191
static const size_type npos
Definition: anope.h:44
Reference< BotInfo > service
Definition: commands.h:67
static ServiceReference< MemoServService > memoserv("MemoServService","MemoServ")
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
Definition: hs_request.cpp:170
#define HOST_SET_IDENTTOOLONG
Definition: language.h:126
#define anope_override
Definition: services.h:56
bool empty() const
Definition: anope.h:126
void Execute(CommandSource &source, const std::vector< Anope::string > &params) anope_override
Definition: hs_request.cpp:190
CoreExport IRCDProto * IRCD
Definition: protocol.cpp:23
#define MODULE_INIT(x)
Definition: modules.h:45
CoreExport const char * Translate(const char *string)
Definition: language.cpp:59
void SetSyntax(const Anope::string &s)
Definition: command.cpp:140
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
Definition: hs_request.cpp:218
CommandHSRequest commandhsrequest
Definition: hs_request.cpp:347
Anope::string stringify(const T &x)
Definition: anope.h:710
Anope::string nick
Definition: users.h:62
CommandHSActivate(Module *creator)
Definition: hs_request.cpp:184
iterator end()
Definition: anope.h:284
Anope::string nick
Definition: hs_request.cpp:26
T anope_dynamic_static_cast(O ptr)
Definition: anope.h:774
void SendSyntax(CommandSource &)
Definition: command.cpp:145
void Execute(CommandSource &source, const std::vector< Anope::string > &params) anope_override
Definition: hs_request.cpp:294
std::string::iterator iterator
Definition: anope.h:39
void Execute(CommandSource &source, const std::vector< Anope::string > &params) anope_override
Definition: hs_request.cpp:239
const char * c_str() const
Definition: anope.h:117
Definition: logger.h:53
void SetVhost(const Anope::string &ident, const Anope::string &host, const Anope::string &creator, time_t created=Anope::CurTime)
Definition: nickalias.cpp:80
bool isvalidchar(char c)
Definition: hs_request.cpp:69
CommandHSWaiting commandhswaiting
Definition: hs_request.cpp:350
T * GetExt(const Anope::string &name) const
Definition: extensible.h:213
CommandHSRequest(Module *creator)
Definition: hs_request.cpp:77
CoreExport Anope::string strftime(time_t t, const NickCore *nc=NULL, bool short_output=false)
Definition: misc.cpp:356
iterator begin()
Definition: anope.h:282
size_type find(const string &_str, size_type pos=0) const
Definition: anope.h:192
#define _(x)
Definition: services.h:50
ListFormatter & AddColumn(const Anope::string &name)
Definition: misc.cpp:128
Type(const Anope::string &n, unserialize_func f, Module *owner=NULL)
void Serialize(Serialize::Data &data) const anope_override
Definition: hs_request.cpp:33
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
Definition: hs_request.cpp:274
Anope::string ident
Definition: hs_request.cpp:27
Module * owner
Definition: service.h:84