The Battle for Wesnoth  1.15.0-dev
ban.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2018 by Pauli Nieminen <paniemin@cc.hut.fi>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "config.hpp"
16 #include "lexical_cast.hpp"
17 #include "log.hpp"
18 #include "filesystem.hpp"
19 #include "serialization/parser.hpp"
23 
24 #include "server/ban.hpp"
25 
26 #include "utils/functional.hpp"
27 
28 namespace wesnothd {
29 
30 
31 static lg::log_domain log_server("server");
32 #define ERR_SERVER LOG_STREAM(err, log_server)
33 #define LOG_SERVER LOG_STREAM(info, log_server)
34 #define DBG_SERVER LOG_STREAM(debug, log_server)
35 
36  std::ostream& operator<<(std::ostream& o, const banned& n)
37  {
38  return o << "IP: " << n.get_ip() <<
39  (n.get_nick().empty() ? "" : " nick: " + n.get_nick()) <<
40  " reason: '" << n.get_reason() << "'"
41  " start_time: " << n.get_human_start_time() <<
42  " end_time: " << n.get_human_end_time() <<
43  " issuer: " << n.get_who_banned();
44  }
45 
46  bool banned_compare::operator()(const banned_ptr& a, const banned_ptr& b) const
47  {
48  return (*a) > (*b);
49  }
50 
52 
54  {
55  return (this->*(active_))(a,b);
56  }
57 
59  {
60  return a->get_int_ip() < b->get_int_ip();
61  }
62 
63  const std::string banned::who_banned_default_ = "system";
64 
65  banned_ptr banned::create_dummy(const std::string& ip)
66  {
67  banned_ptr dummy(new banned(ip));
68  return dummy;
69  }
70 
71  banned::banned(const std::string& ip) :
72  ip_(0),
73  mask_(0),
74  ip_text_(),
75  end_time_(0),
76  start_time_(0),
77  reason_(),
78  who_banned_(who_banned_default_),
79  group_(),
80  nick_()
81  {
82  ip_mask pair = parse_ip(ip);
83  ip_ = pair.first;
84  mask_ = 0xFFFFFFFF;
85  }
86 
87  banned::banned(const std::string& ip,
88  const std::time_t end_time,
89  const std::string& reason,
90  const std::string& who_banned,
91  const std::string& group,
92  const std::string& nick) :
93  ip_(0),
94  mask_(0),
95  ip_text_(ip),
96  end_time_(end_time),
97  start_time_(std::time(0)),
98  reason_(reason),
99  who_banned_(who_banned),
100  group_(group),
101  nick_(nick)
102  {
103  ip_mask pair = parse_ip(ip_text_);
104  ip_ = pair.first;
105  mask_ = pair.second;
106  }
107 
108  banned::banned(const config& cfg) :
109  ip_(0),
110  mask_(0),
111  ip_text_(),
112  end_time_(0),
113  start_time_(0),
114  reason_(),
116  group_(),
117  nick_()
118  {
119  read(cfg);
120  }
121 
122  ip_mask parse_ip(const std::string& ip)
123  {
124  // We use bit operations to construct the integer
125  // ip_mask is a pair: first is ip and second is mask
126  ip_mask ret;
127  ret.first = 0;
128  ret.second = 0;
129  std::vector<std::string> split_ip = utils::split(ip, '.');
130  if (split_ip.size() > 4) throw banned::error("Malformed ip address: " + ip);
131 
132  unsigned int shift = 4*8; // start shifting from the highest byte
133  unsigned int mask = 0xFF000000;
134  const unsigned int complete_part_mask = 0xFF;
135  std::vector<std::string>::const_iterator part = split_ip.begin();
136  bool wildcard = false;
137  do {
138  shift -= 8;
139  mask >>= 8;
140  if (part == split_ip.end())
141  {
142  if (!wildcard)
143  throw banned::error("Malformed ip address: '" + ip + "'");
144  // Adding 0 to ip and mask is nop
145  // we can then break out of loop
146  break;
147  } else {
148  if (*part == "*")
149  {
150  wildcard = true;
151  // Adding 0 to ip and mask is nop
152  } else {
153  //wildcard = false;
154  unsigned int part_ip = lexical_cast_default<unsigned int>(*part, complete_part_mask + 1);
155  if (part_ip > complete_part_mask)
156  throw banned::error("Malformed ip address: '" + ip + "'");
157  ret.first |= (part_ip << shift);
158  ret.second |= (complete_part_mask << shift);
159  }
160  }
161  ++part;
162  } while (shift);
163  return ret;
164  }
165 
166  void banned::read(const config& cfg)
167  {
168  {
169  // parse ip and mask
170  ip_text_ = cfg["ip"].str();
171  ip_mask pair = parse_ip(ip_text_);
172  ip_ = pair.first;
173  mask_ = pair.second;
174  }
175  nick_ = cfg["nick"].str();
176  if (cfg.has_attribute("end_time"))
177  end_time_ = cfg["end_time"].to_time_t(0);
178  if (cfg.has_attribute("start_time"))
179  start_time_ = cfg["start_time"].to_time_t(0);
180  reason_ = cfg["reason"].str();
181 
182  // only overwrite defaults if exists
183  if (cfg.has_attribute("who_banned"))
184  who_banned_ = cfg["who_banned"].str();
185  if (cfg.has_attribute("group"))
186  group_ = cfg["group"].str();
187  }
188 
189  void banned::write(config& cfg) const
190  {
191  cfg["ip"] = get_ip();
192  cfg["nick"] = get_nick();
193  if (end_time_ > 0)
194  {
195  std::stringstream ss;
196  ss << end_time_;
197  cfg["end_time"] = ss.str();
198  }
199  if (start_time_ > 0)
200  {
201  std::stringstream ss;
202  ss << start_time_;
203  cfg["start_time"] = ss.str();
204  }
205 
206  cfg["reason"] = reason_;
208  {
209  cfg["who_banned"] = who_banned_;
210  }
211  if (!group_.empty())
212  {
213  cfg["group"] = group_;
214  }
215  }
216 
217  std::string banned::get_human_start_time() const
218  {
219  if (start_time_ == 0)
220  return "unknown";
222  }
223 
224  std::string banned::get_human_end_time() const
225  {
226  if (end_time_ == 0)
227  {
228  return "permanent";
229  }
231  }
232 
233  std::string banned::get_human_time_span() const
234  {
235  if (end_time_ == 0)
236  {
237  return "permanent";
238  }
239  return lg::get_timespan(end_time_ - std::time(nullptr));
240  }
241 
242  bool banned::operator>(const banned& b) const
243  {
244  return end_time_ > b.get_end_time();
245  }
246 
247  unsigned int banned::get_mask_ip(unsigned int mask) const
248  {
249  return ip_ & mask & mask_;
250  }
251 
252  bool banned::match_ip(const ip_mask& pair) const {
253  return (ip_ & mask_) == (pair.first & mask_);
254  }
255 
256  // Unlike match_ip this function takes both masks into account.
257  bool banned::match_ipmask(const ip_mask& pair) const {
258  return (ip_ & mask_ & pair.second) == (pair.first & pair.second & mask_);
259  }
260 
262  {
264  return;
265  LOG_SERVER << "Reading bans from " << filename_ << "\n";
266  config cfg;
267  dirty_ = false;
269  read_gz(cfg, *ban_file);
270 
271  for (const config &b : cfg.child_range("ban"))
272  {
273  try {
274  banned_ptr new_ban(new banned(b));
275  assert(bans_.insert(new_ban).second);
276 
277  if (new_ban->get_end_time() != 0)
278  time_queue_.push(new_ban);
279  } catch (const banned::error& e) {
280  ERR_SERVER << e.message << " while reading bans" << std::endl;
281  }
282  }
283 
284  // load deleted too
285  if (const config &cfg_del = cfg.child("deleted"))
286  {
287  for (const config &b : cfg_del.child_range("ban"))
288  {
289  try {
290  banned_ptr new_ban(new banned(b));
291  deleted_bans_.push_back(new_ban);
292  } catch (const banned::error& e) {
293  ERR_SERVER << e.message << " while reading deleted bans" << std::endl;
294  }
295  }
296  }
297 
298 
299  }
300 
302  {
303  if (filename_.empty() || !dirty_)
304  return;
305  LOG_SERVER << "Writing bans to " << filename_ << "\n";
306  dirty_ = false;
307  config cfg;
308  for (ban_set::const_iterator itor = bans_.begin();
309  itor != bans_.end(); ++itor)
310  {
311  config& child = cfg.add_child("ban");
312  (*itor)->write(child);
313  }
314  config& deleted = cfg.add_child("deleted");
315  for (deleted_ban_list::const_iterator itor = deleted_bans_.begin();
316  itor != deleted_bans_.end(); ++itor)
317  {
318  config& child = deleted.add_child("ban");
319  (*itor)->write(child);
320  }
321 
323  config_writer writer(*ban_file, true);
324  writer.write(cfg);
325  }
326 
327  bool ban_manager::parse_time(const std::string& duration, std::time_t* time) const
328  {
329  if (!time) return false;
330 
331  if (duration.substr(0,4) == "TIME") {
332  std::tm* loc;
333  loc = std::localtime(time);
334 
335  std::size_t number = 0;
336  for (std::string::const_iterator i = duration.begin() + 4;
337  i != duration.end(); ++i) {
338  if (is_digit(*i))
339  {
340  number = number * 10 + to_digit(*i);
341  }
342  else
343  {
344  switch(*i)
345  {
346  case 'Y':
347  loc->tm_year = number;
348  break;
349  case 'M':
350  loc->tm_mon = number;
351  break;
352  case 'D':
353  loc->tm_mday = number;
354  break;
355  case 'h':
356  loc->tm_hour = number;
357  break;
358  case 'm':
359  loc->tm_min = number;
360  break;
361  case 's':
362  loc->tm_sec = number;
363  break;
364  default:
365  LOG_SERVER << "Invalid time modifier given: '" << *i << "'.\n";
366  break;
367  }
368  number = 0;
369  }
370  }
371  *time = mktime(loc);
372  return true;
373  }
374  default_ban_times::const_iterator time_itor = ban_times_.find(duration);
375 
376  std::string dur_lower;
377  try {
378  dur_lower = utf8::lowercase(duration);
379  } catch (const utf8::invalid_utf8_exception & e ) {
380  ERR_SERVER << "While parsing ban command duration string, caught an invalid utf8 exception: " << e.what() << std::endl;
381  return false;
382  }
383 
384  if (dur_lower == "permanent" || duration == "0") {
385  *time = 0;
386  } else if (ban_times_.find(duration) != ban_times_.end()) {
387  *time += time_itor->second;
388  } else {
389  std::string::const_iterator i = duration.begin();
390  int number = -1;
391  for (std::string::const_iterator d_end = duration.end(); i != d_end; ++i) {
392  if (is_digit(*i))
393  {
394  if (number == -1) number = 0;
395  number = number * 10 + to_digit(*i);
396  } else {
397  if (number == -1) number = 1;
398  switch(*i)
399  {
400  case 'Y':
401  case 'y':
402  if (++i != d_end && tolower(*i) == 'e'
403  && ++i != d_end && tolower(*i) == 'a'
404  && ++i != d_end && tolower(*i) == 'r'
405  && ++i != d_end && tolower(*i) == 's') {
406  } else --i;
407  *time += number * 365*24*60*60; // a year;
408  break;
409  case 'M':
410  if (++i != d_end && tolower(*i) == 'i') {
411  if (++i != d_end && tolower(*i) == 'n'
412  && ++i != d_end && tolower(*i) == 'u'
413  && ++i != d_end && tolower(*i) == 't'
414  && ++i != d_end && tolower(*i) == 'e'
415  && ++i != d_end && tolower(*i) == 's') {
416  } else --i;
417  *time += number * 60;
418  break;
419  }
420  --i;
421  if (++i != d_end && tolower(*i) == 'o'
422  && ++i != d_end && tolower(*i) == 'n'
423  && ++i != d_end && tolower(*i) == 't'
424  && ++i != d_end && tolower(*i) == 'h'
425  && ++i != d_end && tolower(*i) == 's') {
426  } else --i;
427  *time += number * 30*24*60*60; // 30 days
428  break;
429  case 'D':
430  case 'd':
431  if (++i != d_end && tolower(*i) == 'a'
432  && ++i != d_end && tolower(*i) == 'y'
433  && ++i != d_end && tolower(*i) == 's') {
434  } else --i;
435  *time += number * 24*60*60;
436  break;
437  case 'H':
438  case 'h':
439  if (++i != d_end && tolower(*i) == 'o'
440  && ++i != d_end && tolower(*i) == 'u'
441  && ++i != d_end && tolower(*i) == 'r'
442  && ++i != d_end && tolower(*i) == 's') {
443  } else --i;
444  *time += number * 60*60;
445  break;
446  case 'm':
447  if (++i != d_end && tolower(*i) == 'o') {
448  if (++i != d_end && tolower(*i) == 'n'
449  && ++i != d_end && tolower(*i) == 't'
450  && ++i != d_end && tolower(*i) == 'h'
451  && ++i != d_end && tolower(*i) == 's') {
452  } else --i;
453  *time += number * 30*24*60*60; // 30 days
454  break;
455  }
456  --i;
457  if (++i != d_end && tolower(*i) == 'i'
458  && ++i != d_end && tolower(*i) == 'n'
459  && ++i != d_end && tolower(*i) == 'u'
460  && ++i != d_end && tolower(*i) == 't'
461  && ++i != d_end && tolower(*i) == 'e'
462  && ++i != d_end && tolower(*i) == 's') {
463  } else --i;
464  *time += number * 60;
465  break;
466  case 'S':
467  case 's':
468  if (++i != d_end && tolower(*i) == 'e'
469  && ++i != d_end && tolower(*i) == 'c'
470  && ++i != d_end && tolower(*i) == 'o'
471  && ++i != d_end && tolower(*i) == 'n'
472  && ++i != d_end && tolower(*i) == 'd'
473  && ++i != d_end && tolower(*i) == 's') {
474  } else --i;
475  *time += number;
476  break;
477  default:
478  return false;
479  break;
480  }
481  number = -1;
482  }
483  }
484  if (is_digit(*--i)) {
485  *time += number * 60; // default to minutes
486  }
487  }
488  return true;
489  }
490 
491  std::string ban_manager::ban(const std::string& ip,
492  const std::time_t& end_time,
493  const std::string& reason,
494  const std::string& who_banned,
495  const std::string& group,
496  const std::string& nick)
497  {
498  std::ostringstream ret;
499  try {
500  ban_set::iterator ban;
501  if ((ban = bans_.find(banned::create_dummy(ip))) != bans_.end())
502  {
503  // Already exsiting ban for ip. We have to first remove it
504  ret << "Overwriting ban: " << (**ban) << "\n";
505  bans_.erase(ban);
506  }
507  } catch (const banned::error& e) {
508  ERR_SERVER << e.message << " while creating dummy ban for finding existing ban" << std::endl;
509  return e.message;
510  }
511  try {
512  banned_ptr new_ban(new banned(ip, end_time, reason,who_banned, group, nick));
513  bans_.insert(new_ban);
514  if (end_time != 0)
515  time_queue_.push(new_ban);
516  ret << *new_ban;
517  } catch (const banned::error& e) {
518  ERR_SERVER << e.message << " while banning" << std::endl;
519  return e.message;
520  }
521  dirty_ = true;
522  write();
523  return ret.str();
524  }
525 
526  void ban_manager::unban(std::ostringstream& os, const std::string& ip, bool immediate_write)
527  {
528  ban_set::iterator ban;
529  try {
530  ban = bans_.find(banned::create_dummy(ip));
531  } catch (const banned::error& e) {
532  ERR_SERVER << e.message << std::endl;
533  os << e.message;
534  return;
535  }
536 
537  if (ban == bans_.end())
538  {
539  os << "There is no ban on '" << ip << "'.";
540  return;
541  }
542  // keep ban entry still in memory
543  os << "Ban on '" << **ban << "' removed.";
544  // group bans don't get saved
545  if ((*ban)->get_group().empty()) deleted_bans_.push_back(*ban);
546  bans_.erase(ban);
547  dirty_ = true;
548  if (immediate_write) {
549  write();
550  }
551  }
552 
553  void ban_manager::unban_group(std::ostringstream& os, const std::string& group)
554  {
555  ban_set temp;
556  std::insert_iterator<ban_set> temp_inserter(temp, temp.begin());
557  std::remove_copy_if(bans_.begin(), bans_.end(), temp_inserter, [&group](const banned_ptr& p) { return p->match_group(group); });
558 
559  os << "Removed " << (bans_.size() - temp.size()) << " bans";
560  bans_.swap(temp);
561  dirty_ = true;
562  write();
563  }
564 
565  void ban_manager::check_ban_times(std::time_t time_now)
566  {
567  while (!time_queue_.empty())
568  {
569  banned_ptr ban = time_queue_.top();
570 
571  if (ban->get_end_time() > time_now)
572  {
573  // No bans going to expire
574  DBG_SERVER << "ban " << ban->get_ip() << " not removed. time: " << time_now << " end_time " << ban->get_end_time() << "\n";
575  break;
576  }
577 
578  // This ban is going to expire so delete it.
579  LOG_SERVER << "Remove a ban " << ban->get_ip() << ". time: " << time_now << " end_time " << ban->get_end_time() << "\n";
580  std::ostringstream os;
581  unban(os, ban->get_ip(), false);
582  time_queue_.pop();
583 
584  }
585  // Save bans if there is any new ones
586  write();
587  }
588 
589  void ban_manager::list_deleted_bans(std::ostringstream& out, const std::string& mask) const
590  {
591  if (deleted_bans_.empty())
592  {
593  out << "No removed bans found.";
594  return;
595  }
596 
597  ip_mask pair;
598  try {
599  pair = parse_ip(mask);
600  } catch (const banned::error& e) {
601  out << "parse error: " << e.message;
602  return;
603  }
604 
605  out << "DELETED BANS LIST";
606  for (deleted_ban_list::const_iterator i = deleted_bans_.begin();
607  i != deleted_bans_.end();
608  ++i)
609  {
610  if ((*i)->match_ipmask(pair)) out << "\n" << (**i);
611  }
612 
613  }
614 
615 
616 
617  void ban_manager::list_bans(std::ostringstream& out, const std::string& mask)
618  {
619  expire_bans();
620  if (bans_.empty())
621  {
622  out << "No bans set.";
623  return;
624  }
625 
626  ip_mask pair;
627  try {
628  pair = parse_ip(mask);
629  } catch (const banned::error& e) {
630  out << "parse error: " << e.message;
631  return;
632  }
633 
634  out << "BAN LIST";
635  std::set<std::string> groups;
636 
637  for (ban_set::const_iterator i = bans_.begin();
638  i != bans_.end(); ++i)
639  {
640  if ((*i)->get_group().empty())
641  {
642  if ((*i)->match_ipmask(pair)) out << "\n" << (**i);
643  } else {
644  groups.insert((*i)->get_group());
645  }
646  }
647 
648  // Don't list ban groups when looking for specific bans.
649  if (!groups.empty() && mask == "*")
650  {
651  out << "\nban groups: ";
652 
653  out << *groups.begin();
654  std::ostream& (*fn)(std::ostream&,const std::string&) = &std::operator<<;
655  std::for_each( ++groups.begin(), groups.end(), std::bind(fn,std::bind(fn,std::ref(out),std::string(", ")),_1));
656  }
657 
658  }
659 
660 
661  std::string ban_manager::is_ip_banned(const std::string& ip)
662  {
663  expire_bans();
664  ip_mask pair;
665  try {
666  pair = parse_ip(ip);
667  } catch (const banned::error&) {
668  return "";
669  }
670  ban_set::const_iterator ban = std::find_if(bans_.begin(), bans_.end(), [pair](const banned_ptr& p) { return p->match_ip(pair); });
671  if (ban == bans_.end()) return "";
672  const std::string& nick = (*ban)->get_nick();
673  return (*ban)->get_reason() + (nick.empty() ? "" : " (" + nick + ")") + " (Remaining ban duration: " + (*ban)->get_human_time_span() + ")";
674  }
675 
677  {
678  ban_help_ = "ban <mask> <time> <reason>\n"
679  "The time format is: %d[%s[%d[%s[...]]]] where %s is a time"
680  " modifier: s or S (seconds), m (minutes), h or H (hours), d"
681  " or D (days), M (months) or y or Y (years) and %d is a number.\n"
682  "Permanent bans can be set with 'permanent' or '0' as the time"
683  " argument.\n";
684  default_ban_times::iterator itor = ban_times_.begin();
685  if (itor != ban_times_.end())
686  {
687  ban_help_ += "You can also use " + itor->first;
688  ++itor;
689  }
690  for (; itor != ban_times_.end(); ++itor)
691  {
692  ban_help_ += std::string(", ") + itor->first;
693  }
694  if (!ban_times_.empty())
695  {
696  ban_help_ += " for standard ban times. (not combinable)\n";
697  }
698  ban_help_ += "ban 127.0.0.1 2h20m flooded lobby\n"
699  "kban suokko 5D flooded again\n"
700  "kban suokko Y One year ban for constant flooding";
701  }
702 
704  {
705  ban_times_.clear();
706  for (const config &bt : cfg.child_range("ban_time")) {
707  std::time_t duration = 0;
708  if (parse_time(bt["time"], &duration)) {
709  ban_times_.emplace(bt["name"], duration);
710  }
711  }
712  init_ban_help();
713  if (filename_ != cfg["ban_save_file"])
714  {
715  dirty_ = true;
716  filename_ = cfg["ban_save_file"].str();
717  }
718  }
719 
721  {
722  try {
723  write();
724  } catch (...) {}
725  }
726 
728  : bans_()
729  , deleted_bans_()
730  , time_queue_()
731  , ban_times_()
732  , ban_help_()
733  , filename_()
734  , dirty_(false)
735  {
736  init_ban_help();
737  }
738 
739 
740 }
bool(banned_compare_subnet::* compare_fn)(const banned_ptr &a, const banned_ptr &b) const
Definition: ban.hpp:44
#define LOG_SERVER
Definition: ban.cpp:33
bool match_ipmask(const ip_mask &ip) const
Definition: ban.cpp:257
#define DBG_SERVER
Definition: ban.cpp:34
std::string reason_
Definition: ban.hpp:62
std::string get_reason() const
Definition: ban.hpp:85
std::string get_timestamp(const std::time_t &t, const std::string &format)
Definition: log.cpp:175
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:423
void write(const config &cfg)
std::string get_timespan(const std::time_t &t)
Definition: log.cpp:182
int dummy
Definition: lstrlib.cpp:1125
void load_config(const config &)
Definition: ban.cpp:703
bool less(const banned_ptr &a, const banned_ptr &b) const
Definition: ban.cpp:58
std::time_t start_time_
Definition: ban.hpp:61
static bool file_exists(const fs::path &fpath)
Definition: filesystem.cpp:300
static l_noret error(LoadState *S, const char *why)
Definition: lundump.cpp:39
New lexcical_cast header.
bool has_attribute(config_key_type key) const
Definition: config.cpp:217
#define a
void check_ban_times(std::time_t time_now)
Definition: ban.cpp:565
std::string is_ip_banned(const std::string &ip)
Definition: ban.cpp:661
std::time_t get_end_time() const
Definition: ban.hpp:77
child_itors child_range(config_key_type key)
Definition: config.cpp:366
std::string get_human_end_time() const
Definition: ban.cpp:224
filesystem::scoped_istream istream_file(const std::string &fname, bool treat_failure_as_error)
Definition: filesystem.cpp:894
STL namespace.
void read_gz(config &cfg, std::istream &file, abstract_validator *validator)
Might throw a std::ios_base::failure especially a gzip_error.
Definition: parser.cpp:668
Definitions for the interface to Wesnoth Markup Language (WML).
std::set< banned_ptr, banned_compare_subnet > ban_set
Definition: ban.hpp:48
std::string group_
Definition: ban.hpp:64
std::vector< std::string > split(const std::string &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
static compare_fn active_
Definition: ban.hpp:45
std::string filename_
Definition: action_wml.cpp:555
#define b
std::pair< unsigned int, unsigned int > ip_mask
Definition: ban.hpp:52
std::shared_ptr< banned > banned_ptr
Definition: ban.hpp:33
std::string get_who_banned() const
Definition: ban.hpp:93
void read(const config &)
Definition: ban.cpp:166
std::string nick_
Definition: ban.hpp:65
static lg::log_domain log_server("server")
void unban_group(std::ostringstream &os, const std::string &group)
Definition: ban.cpp:553
Class for writing a config out to a file in pieces.
void list_deleted_bans(std::ostringstream &out, const std::string &mask="*") const
Definition: ban.cpp:589
std::string ban(const std::string &, const std::time_t &, const std::string &, const std::string &, const std::string &, const std::string &="")
Definition: ban.cpp:491
bool operator()(const banned_ptr &a, const banned_ptr &b) const
Definition: ban.cpp:46
std::time_t end_time_
Definition: ban.hpp:60
std::string get_human_start_time() const
Definition: ban.cpp:217
std::unique_ptr< std::istream > scoped_istream
Definition: filesystem.hpp:39
ip_mask parse_ip(const std::string &ip)
Definition: ban.cpp:122
banned(const std::string &ip)
Definition: ban.cpp:71
unsigned int mask() const
Definition: ban.hpp:109
std::unique_ptr< std::ostream > scoped_ostream
Definition: filesystem.hpp:40
static banned_ptr create_dummy(const std::string &ip)
Definition: ban.cpp:65
std::size_t i
Definition: function.cpp:933
Thrown by operations encountering invalid UTF-8 data.
std::string who_banned_
Definition: ban.hpp:63
mock_party p
std::ostream & operator<<(std::ostream &o, const banned &n)
Definition: ban.cpp:36
void write(config &) const
Definition: ban.cpp:189
std::string get_nick() const
Definition: ban.hpp:96
static const std::string who_banned_default_
Definition: ban.hpp:66
Declarations for File-IO.
static int writer(lua_State *L, const void *b, size_t size, void *B)
Definition: lstrlib.cpp:182
std::string lowercase(const std::string &s)
Returns a lowercased version of the string.
Definition: unicode.cpp:51
unsigned int ip_
Definition: ban.hpp:57
config & add_child(config_key_type key)
Definition: config.cpp:479
#define ERR_SERVER
Definition: ban.cpp:32
void list_bans(std::ostringstream &out, const std::string &mask="*")
Definition: ban.cpp:617
void init_ban_help()
Definition: ban.cpp:676
bool match_ip(const ip_mask &ip) const
Definition: ban.cpp:252
std::string get_ip() const
Definition: ban.hpp:88
void unban(std::ostringstream &os, const std::string &ip, bool immediate_write=true)
Definition: ban.cpp:526
Definition: ban.cpp:28
bool parse_time(const std::string &duration, std::time_t *time) const
Parses the given duration and adds it to *time except if the duration is &#39;0&#39; or &#39;permanent&#39; in which ...
Definition: ban.cpp:327
Standard logging facilities (interface).
std::string message
Definition: exceptions.hpp:31
unsigned int get_mask_ip(unsigned int) const
Definition: ban.cpp:247
#define e
bool operator>(const banned &b) const
Definition: ban.cpp:242
std::string get_human_time_span() const
Definition: ban.cpp:233
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
static map_location::DIRECTION n
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
bool operator()(const banned_ptr &a, const banned_ptr &b) const
Definition: ban.cpp:53
std::string ip_text_
Definition: ban.hpp:59
unsigned int mask_
Definition: ban.hpp:58
filesystem::scoped_ostream ostream_file(const std::string &fname, bool create_directory)
Definition: filesystem.cpp:932