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