Anope IRC Services  Version 2.0
ns_list.cpp
Go to the documentation of this file.
1 /* NickServ core functions
2  *
3  * (C) 2003-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  */
11 
12 #include "module.h"
13 
14 class CommandNSList : public Command
15 {
16  public:
17  CommandNSList(Module *creator) : Command(creator, "nickserv/list", 1, 2)
18  {
19  this->SetDesc(_("List all registered nicknames that match a given pattern"));
20  this->SetSyntax(_("\037pattern\037 [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"));
21  }
22 
23  void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
24  {
25 
26  Anope::string pattern = params[0];
27  const NickCore *mync;
28  unsigned nnicks;
29  bool is_servadmin = source.HasCommand("nickserv/list");
30  int count = 0, from = 0, to = 0;
31  bool suspended, nsnoexpire, unconfirmed;
32  unsigned listmax = Config->GetModule(this->owner)->Get<unsigned>("listmax", "50");
33 
34  suspended = nsnoexpire = unconfirmed = false;
35 
36  if (pattern[0] == '#')
37  {
38  Anope::string n1, n2;
39  sepstream(pattern.substr(1), '-').GetToken(n1, 0);
40  sepstream(pattern, '-').GetToken(n2, 1);
41  try
42  {
43  from = convertTo<int>(n1);
44  to = convertTo<int>(n2);
45  }
46  catch (const ConvertException &)
47  {
48  source.Reply(LIST_INCORRECT_RANGE);
49  return;
50  }
51 
52  pattern = "*";
53  }
54 
55  nnicks = 0;
56 
57  if (is_servadmin && params.size() > 1)
58  {
59  Anope::string keyword;
60  spacesepstream keywords(params[1]);
61  while (keywords.GetToken(keyword))
62  {
63  if (keyword.equals_ci("NOEXPIRE"))
64  nsnoexpire = true;
65  if (keyword.equals_ci("SUSPENDED"))
66  suspended = true;
67  if (keyword.equals_ci("UNCONFIRMED"))
68  unconfirmed = true;
69  }
70  }
71 
72  mync = source.nc;
73  ListFormatter list(source.GetAccount());
74 
75  list.AddColumn(_("Nick")).AddColumn(_("Last usermask"));
76 
77  Anope::map<NickAlias *> ordered_map;
78  for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ++it)
79  ordered_map[it->first] = it->second;
80 
81  for (Anope::map<NickAlias *>::const_iterator it = ordered_map.begin(), it_end = ordered_map.end(); it != it_end; ++it)
82  {
83  const NickAlias *na = it->second;
84 
85  /* Don't show private nicks to non-services admins. */
86  if (na->nc->HasExt("NS_PRIVATE") && !is_servadmin && na->nc != mync)
87  continue;
88  else if (nsnoexpire && !na->HasExt("NS_NO_EXPIRE"))
89  continue;
90  else if (suspended && !na->nc->HasExt("NS_SUSPENDED"))
91  continue;
92  else if (unconfirmed && !na->nc->HasExt("UNCONFIRMED"))
93  continue;
94 
95  /* We no longer compare the pattern against the output buffer.
96  * Instead we build a nice nick!user@host buffer to compare.
97  * The output is then generated separately. -TheShadow */
98  Anope::string buf = Anope::printf("%s!%s", na->nick.c_str(), !na->last_usermask.empty() ? na->last_usermask.c_str() : "*@*");
99  if (na->nick.equals_ci(pattern) || Anope::Match(buf, pattern, false, true))
100  {
101  if (((count + 1 >= from && count + 1 <= to) || (!from && !to)) && ++nnicks <= listmax)
102  {
103  bool isnoexpire = false;
104  if (is_servadmin && na->HasExt("NS_NO_EXPIRE"))
105  isnoexpire = true;
106 
108  entry["Nick"] = (isnoexpire ? "!" : "") + na->nick;
109  if (na->nc->HasExt("HIDE_MASK") && !is_servadmin && na->nc != mync)
110  entry["Last usermask"] = Language::Translate(source.GetAccount(), _("[Hostname hidden]"));
111  else if (na->nc->HasExt("NS_SUSPENDED"))
112  entry["Last usermask"] = Language::Translate(source.GetAccount(), _("[Suspended]"));
113  else if (na->nc->HasExt("UNCONFIRMED"))
114  entry["Last usermask"] = Language::Translate(source.GetAccount(), _("[Unconfirmed]"));
115  else
116  entry["Last usermask"] = na->last_usermask;
117  list.AddEntry(entry);
118  }
119  ++count;
120  }
121  }
122 
123  source.Reply(_("List of entries matching \002%s\002:"), pattern.c_str());
124 
125  std::vector<Anope::string> replies;
126  list.Process(replies);
127 
128  for (unsigned i = 0; i < replies.size(); ++i)
129  source.Reply(replies[i]);
130 
131  source.Reply(_("End of list - %d/%d matches shown."), nnicks > listmax ? listmax : nnicks, nnicks);
132  return;
133  }
134 
135  bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
136  {
137  this->SendSyntax(source);
138  source.Reply(" ");
139  source.Reply(_("Lists all registered nicknames which match the given\n"
140  "pattern, in \037nick!user@host\037 format. Nicks with the \002PRIVATE\002\n"
141  "option set will only be displayed to Services Operators with the\n"
142  "proper access. Nicks with the \002NOEXPIRE\002 option set will have\n"
143  "a \002!\002 prefixed to the nickname for Services Operators to see.\n"
144  " \n"
145  "Note that a preceding '#' specifies a range.\n"
146  " \n"
147  "If the SUSPENDED, UNCONFIRMED or NOEXPIRE options are given, only\n"
148  "nicks which, respectively, are SUSPENDED, UNCONFIRMED or have the\n"
149  "NOEXPIRE flag set will be displayed. If multiple options are\n"
150  "given, all nicks matching at least one option will be displayed.\n"
151  "Note that these options are limited to \037Services Operators\037.\n"
152  " \n"
153  "Examples:\n"
154  " \n"
155  " \002LIST *!joeuser@foo.com\002\n"
156  " Lists all registered nicks owned by joeuser@foo.com.\n"
157  " \n"
158  " \002LIST *Bot*!*@*\002\n"
159  " Lists all registered nicks with \002Bot\002 in their\n"
160  " names (case insensitive).\n"
161  " \n"
162  " \002LIST * NOEXPIRE\002\n"
163  " Lists all registered nicks which have been set to not expire.\n"
164  " \n"
165  " \002LIST #51-100\002\n"
166  " Lists all registered nicks within the given range (51-100)."));
167 
168  const Anope::string &regexengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine");
169  if (!regexengine.empty())
170  {
171  source.Reply(" ");
172  source.Reply(_("Regex matches are also supported using the %s engine.\n"
173  "Enclose your pattern in // if this is desired."), regexengine.c_str());
174  }
175 
176  return true;
177  }
178 };
179 
180 
182 {
183  public:
184  CommandNSSetPrivate(Module *creator, const Anope::string &sname = "nickserv/set/private", size_t min = 1) : Command(creator, sname, min, min + 1)
185  {
186  this->SetDesc(_("Prevent the nickname from appearing in the LIST command"));
187  this->SetSyntax("{ON | OFF}");
188  }
189 
190  void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
191  {
192  if (Anope::ReadOnly)
193  {
194  source.Reply(READ_ONLY_MODE);
195  return;
196  }
197 
198  const NickAlias *na = NickAlias::Find(user);
199  if (!na)
200  {
201  source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
202  return;
203  }
204  NickCore *nc = na->nc;
205 
206  EventReturn MOD_RESULT;
207  FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
208  if (MOD_RESULT == EVENT_STOP)
209  return;
210 
211  if (param.equals_ci("ON"))
212  {
213  Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable private for " << nc->display;
214  nc->Extend<bool>("NS_PRIVATE");
215  source.Reply(_("Private option is now \002on\002 for \002%s\002."), nc->display.c_str());
216  }
217  else if (param.equals_ci("OFF"))
218  {
219  Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable private for " << nc->display;
220  nc->Shrink<bool>("NS_PRIVATE");
221  source.Reply(_("Private option is now \002off\002 for \002%s\002."), nc->display.c_str());
222  }
223  else
224  this->OnSyntaxError(source, "PRIVATE");
225  }
226 
227  void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
228  {
229  this->Run(source, source.nc->display, params[0]);
230  }
231 
233  {
234  this->SendSyntax(source);
235  source.Reply(" ");
236  source.Reply(_("Turns %s's privacy option on or off for your nick.\n"
237  "With \002PRIVATE\002 set, your nickname will not appear in\n"
238  "nickname lists generated with %s's \002LIST\002 command.\n"
239  "(However, anyone who knows your nickname can still get\n"
240  "information on it using the \002INFO\002 command.)"),
241  source.service->nick.c_str(), source.service->nick.c_str());
242  return true;
243  }
244 };
245 
247 {
248  public:
249  CommandNSSASetPrivate(Module *creator) : CommandNSSetPrivate(creator, "nickserv/saset/private", 2)
250  {
251  this->ClearSyntax();
252  this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
253  }
254 
255  void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
256  {
257  this->Run(source, params[0], params[1]);
258  }
259 
261  {
262  this->SendSyntax(source);
263  source.Reply(" ");
264  source.Reply(_("Turns %s's privacy option on or off for the nick.\n"
265  "With \002PRIVATE\002 set, the nickname will not appear in\n"
266  "nickname lists generated with %s's \002LIST\002 command.\n"
267  "(However, anyone who knows the nickname can still get\n"
268  "information on it using the \002INFO\002 command.)"),
269  source.service->nick.c_str(), source.service->nick.c_str());
270  return true;
271  }
272 };
273 
274 
275 class NSList : public Module
276 {
278 
281 
283 
284  public:
285  NSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
286  commandnslist(this), commandnssetprivate(this), commandnssasetprivate(this),
287  priv(this, "NS_PRIVATE")
288  {
289  }
290 
291  void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_all) anope_override
292  {
293  if (!show_all)
294  return;
295 
296  if (priv.HasExt(na->nc))
297  info.AddOption(_("Private"));
298  }
299 };
300 
CommandNSSetPrivate(Module *creator, const Anope::string &sname="nickserv/set/private", size_t min=1)
Definition: ns_list.cpp:184
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
bool OnHelp(CommandSource &source, const Anope::string &) anope_override
Definition: ns_list.cpp:260
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
Definition: ns_list.cpp:135
Anope::string nick
Definition: account.h:37
CoreExport string printf(const char *fmt,...)
Definition: misc.cpp:536
Anope::string last_usermask
Definition: account.h:41
void Execute(CommandSource &source, const std::vector< Anope::string > &params) anope_override
Definition: ns_list.cpp:23
T * Extend(const Anope::string &name, const T &what)
Definition: extensible.h:224
#define NICK_X_NOT_REGISTERED
Definition: language.h:79
void ClearSyntax()
Definition: command.cpp:135
#define READ_ONLY_MODE
Definition: language.h:71
#define FOREACH_RESULT(ename, ret, args)
Definition: modules.h:95
void SetDesc(const Anope::string &d)
Definition: command.cpp:130
bool equals_ci(const char *_str) const
Definition: anope.h:78
CommandNSSASetPrivate(Module *creator)
Definition: ns_list.cpp:249
CoreExport Serialize::Checker< nickalias_map > NickAliasList
bool OnHelp(CommandSource &source, const Anope::string &) anope_override
Definition: ns_list.cpp:232
string substr(size_type pos=0, size_type n=npos) const
Definition: anope.h:277
void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
Definition: ns_list.cpp:190
std::map< Anope::string, Anope::string > ListEntry
Definition: lists.h:68
Definition: Config.cs:26
void Shrink(const Anope::string &name)
Definition: extensible.h:253
CoreExport bool Match(const string &str, const string &mask, bool case_sensitive=false, bool use_regex=false)
Definition: misc.cpp:407
virtual void OnSyntaxError(CommandSource &source, const Anope::string &subcommand)
Definition: command.cpp:191
void Reply(const char *message,...)
Definition: command.cpp:96
CommandNSSASetPrivate commandnssasetprivate
Definition: ns_list.cpp:280
Reference< BotInfo > service
Definition: commands.h:67
Anope::string display
Definition: account.h:113
void Execute(CommandSource &source, const std::vector< Anope::string > &params) anope_override
Definition: ns_list.cpp:255
#define anope_override
Definition: services.h:56
bool empty() const
Definition: anope.h:126
#define LIST_INCORRECT_RANGE
Definition: language.h:90
EventReturn
Definition: modules.h:129
#define MODULE_INIT(x)
Definition: modules.h:45
CoreExport const char * Translate(const char *string)
Definition: language.cpp:59
CommandNSList commandnslist
Definition: ns_list.cpp:277
void Execute(CommandSource &source, const std::vector< Anope::string > &params) anope_override
Definition: ns_list.cpp:227
void SetSyntax(const Anope::string &s)
Definition: command.cpp:140
Anope::string nick
Definition: users.h:62
bool GetToken(Anope::string &token)
Definition: hashcomp.cpp:99
void SendSyntax(CommandSource &)
Definition: command.cpp:145
NickCore * GetAccount()
Definition: command.cpp:36
CommandNSList(Module *creator)
Definition: ns_list.cpp:17
const char * c_str() const
Definition: anope.h:117
Definition: logger.h:53
void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_all) anope_override
Definition: ns_list.cpp:291
NSList(const Anope::string &modname, const Anope::string &creator)
Definition: ns_list.cpp:285
bool HasExt(const Extensible *obj) const
Definition: extensible.h:111
#define _(x)
Definition: services.h:50
SerializableExtensibleItem< bool > priv
Definition: ns_list.cpp:282
bool HasExt(const Anope::string &name) const
Definition: extensible.cpp:31
ListFormatter & AddColumn(const Anope::string &name)
Definition: misc.cpp:128
CommandNSSetPrivate commandnssetprivate
Definition: ns_list.cpp:279
Module * owner
Definition: service.h:84