ban.cpp

Go to the documentation of this file.
00001 /* $Id: ban.cpp 26653 2008-05-16 16:08:26Z suokko $ */
00002 /*
00003    Copyright (C) 2008 by Pauli Nieminen <paniemin@cc.hut.fi>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License version 2
00008    or at your option any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 #include "../log.hpp"
00016 #include "../config.hpp"
00017 
00018 #include "ban.hpp"
00019 #include <sstream>
00020 
00021 namespace wesnothd {
00022 
00023 #define LOG_SERVER LOG_STREAM(info, mp_server)
00024 #define DBG_SERVER LOG_STREAM(debug, mp_server)
00025 
00026     bool banned_compare::operator()(const banned* a, const banned* b) const
00027     {
00028         return (*a) > (*b);
00029     }
00030 
00031     banned::banned(const std::string& ip, const time_t end_time, const std::string& reason) : ip_(ip), end_time_(end_time), reason_(reason), deleted_(false)
00032     {
00033     }
00034 
00035     banned::banned(const config& cfg)
00036     {
00037         read(cfg);
00038     }
00039 
00040     void banned::read(const config& cfg)
00041     {
00042         ip_       = cfg["ip"];
00043         end_time_ = lexical_cast<time_t>(cfg["end_time"]);
00044         reason_   = cfg["reason"];
00045         deleted_  = utils::string_bool(cfg["deleted"]);
00046     }
00047 
00048     void banned::write(config& cfg) const
00049     {
00050         std::stringstream ss;
00051         cfg["ip"]       = ip_;
00052         ss << end_time_;
00053         cfg["end_time"] = ss.str();
00054         cfg["reason"]   = reason_;
00055         cfg["deleted"]  = deleted_ ? "yes":"no";
00056     }
00057 
00058     std::string banned::get_human_end_time() const
00059     {
00060         char buf[30];
00061         struct tm* local;
00062         local = localtime(&end_time_);
00063         strftime(buf,30,"%H:%M:%S %d.%m.%Y", local );
00064         return std::string(buf);
00065     }
00066     
00067     bool banned::operator>(const banned& b) const
00068     {
00069         return end_time_ > b.get_end_time();
00070     }
00071     
00072     void ban_manager::read(const config& cfg)
00073     {
00074         const config::child_list& bans = cfg.get_children("ban");
00075         for (config::child_list::const_iterator itor = bans.begin();
00076                 itor != bans.end(); ++itor)
00077         {
00078             banned* new_ban = new banned(**itor);
00079             if (!new_ban->is_deleted())
00080             {
00081                 bans_[new_ban->get_ip()] = new_ban;
00082             }
00083             time_queue_.push(new_ban);
00084         }
00085     }
00086 
00087     void ban_manager::write(config& cfg) const
00088     {
00089         for (ban_map::const_iterator itor = bans_.begin();
00090                 itor != bans_.end(); ++itor)
00091         {
00092             config& child = cfg.add_child("ban");
00093             itor->second->write(child);
00094         }
00095     }
00096 
00097     time_t ban_manager::parse_time(std::string time_in) const
00098     {
00099         time_t ret;
00100         ret = time(NULL);
00101         if (time_in.substr(0,4) == "TIME")
00102         {
00103             struct tm* loc;
00104             loc = localtime(&ret);
00105 
00106             std::string::iterator i = time_in.begin() + 4;
00107             size_t number = 0;
00108             for (; i != time_in.end(); ++i)
00109             {
00110                 if (is_number(*i))
00111                 {
00112                     number = number*10 + to_number(*i);
00113                 }
00114                 else
00115                 {
00116                     switch(*i)
00117                     {
00118                         case 'Y':
00119                             loc->tm_year = number;
00120                             break;
00121                         case 'M':
00122                             loc->tm_mon = number;
00123                             break;
00124                         case 'D':
00125                             loc->tm_mday = number;
00126                             break;
00127                         case 'h':
00128                             loc->tm_hour = number;
00129                             break;
00130                         case 'm':
00131                             loc->tm_min = number;
00132                             break;
00133                         case 's':
00134                             loc->tm_sec = number;
00135                             break;
00136                         default:
00137                             LOG_SERVER << "Wrong time code for ban: " << *i << "\n";
00138                             break;
00139                     }
00140                     number = 0;
00141                 }
00142             }
00143             return mktime(loc);
00144         }
00145         default_ban_times::const_iterator time_itor = ban_times_.find(time_in); 
00146         if (time_itor != ban_times_.end())
00147             ret += time_itor->second;
00148         else
00149         {
00150             size_t multipler = 60; // default minutes
00151             std::string::iterator i = time_in.begin();
00152             size_t number = 0;
00153             for (; i != time_in.end(); ++i)
00154             {
00155                 if (is_number(*i))
00156                 {
00157                     number = number * 10  + to_number(*i);
00158                 } else {
00159                     switch(*i)
00160                     {
00161                         case 'Y':
00162                             multipler = 365*24*60*60; // a year;
00163                             break;
00164                         case 'M':
00165                             multipler = 30*24*60*60; // 30 days
00166                             break;
00167                         case 'D':
00168                             multipler = 24*60*60;
00169                             break;
00170                         case 'h':
00171                             multipler = 60*60;
00172                             break;
00173                         case 'm':
00174                             multipler = 60;
00175                             break;
00176                         case 's':
00177                             multipler = 1;
00178                             break;
00179                         default:
00180                             LOG_SERVER << "Wrong time multipler code given: " << *i << "\n";
00181                             break;
00182                     }
00183                     ret += number * multipler;
00184                 }
00185             }
00186             --i;
00187             if (is_number(*i))
00188             {
00189                     ret += number * multipler;
00190             }
00191         }
00192         return ret;
00193     }
00194 
00195     void ban_manager::ban(const std::string& ip, const time_t& end_time, const std::string& reason)
00196     {
00197         ban_map::iterator ban;
00198         if ((ban = bans_.find(ip)) != bans_.end())
00199         {
00200             // Already exsiting ban for ip. We have to first remove it
00201             ban->second->remove_ban();
00202             bans_.erase(ban);
00203         }
00204         banned *new_ban = new banned(ip, end_time, reason);
00205         bans_.insert(ban_map::value_type(ip,new_ban));
00206         time_queue_.push(new_ban);
00207     }
00208 
00209     void ban_manager::unban(std::ostringstream& os, const std::string& ip)
00210     {
00211         ban_map::iterator ban = bans_.find(ip);
00212         if (ban == bans_.end())
00213         {
00214             os << "There is no ban on '" << ip << "'.";
00215             return;
00216         }
00217         ban->second->remove_ban();
00218         bans_.erase(ban);
00219 
00220         os << "Ban on '" << ip << "' removed.";
00221     }
00222 
00223     void ban_manager::check_ban_times(time_t time_now)
00224     {
00225         while (!time_queue_.empty())
00226         {
00227             banned* ban = time_queue_.top();
00228 
00229             if (ban->get_end_time() > time_now)
00230             {
00231                 // No bans going to expire
00232                 LOG_SERVER << "ban " << ban->get_ip() << " not removed. time: " << time_now << " end_time " << ban->get_end_time() << "\n";
00233                 break;
00234             }
00235 
00236             if (ban->is_deleted())
00237             {
00238                 // This was allready deleted have to free memory;
00239                 time_queue_.pop();
00240                 delete ban;
00241                 continue;
00242             }
00243 
00244             // This ban is going to expire so delete it.
00245             LOG_SERVER << "Remove a ban " << ban->get_ip() << ". time: " << time_now << " end_time " << ban->get_end_time() << "\n";
00246 
00247             bans_.erase(bans_.find(ban->get_ip()));
00248             time_queue_.pop();
00249             delete ban;
00250 
00251         }
00252     }
00253 
00254     void ban_manager::list_bans(std::ostringstream& out) const
00255     {
00256         if (bans_.empty()) 
00257         { 
00258             out << "No bans set.";
00259             return;
00260         }
00261 
00262         out << "BAN LIST\n";
00263         for (ban_map::const_iterator i = bans_.begin();
00264                 i != bans_.end(); ++i)
00265         {
00266             out << "IP: '" << i->second->get_ip() << 
00267                 "' end_time: '" << i->second->get_human_end_time() <<
00268                 "' reason: '" << i->second->get_reason() << "'\n";
00269         }
00270 
00271     }
00272 
00273 
00274     bool ban_manager::is_ip_banned(std::string ip) const 
00275     {
00276         for (ban_map::const_iterator i = bans_.begin(); i != bans_.end(); ++i) {
00277             if (utils::wildcard_string_match(ip, i->first)) {
00278                 DBG_SERVER << "Comparing ban '" << i->first << "' vs '..." << ip << "'\t" << "banned.\n";
00279                 return true;
00280             }
00281             DBG_SERVER << "Comparing ban '" << i->first << "' vs '..." << ip << "'\t" << "not banned.\n";
00282         }
00283         return false;
00284     }
00285     
00286     void ban_manager::init_ban_help()
00287     {
00288         ban_help_ = "ban <ip|nickname> <time> [<reason>]\nTime is give in formar ‰d[‰s‰d‰s...] (where ‰s is s, m, h, D, M or Y).\nIf no time modifier is given minutes are used.\n";
00289         default_ban_times::iterator itor = ban_times_.begin();
00290         if (itor != ban_times_.end())
00291         {
00292             ban_help_ += "You can also use " + itor->first;
00293             ++itor;
00294         }
00295         for (; itor != ban_times_.end(); ++itor)
00296         {
00297             ban_help_ += std::string(", ") + itor->first;
00298         }
00299         if (!ban_times_.empty())
00300         {
00301             ban_help_ += " for standard ban times.\n";
00302         }
00303         ban_help_ += "ban 127.0.0.1 2H20m flooded lobby\nban 127.0.0.2 medium flooded lobby again\n";
00304     }
00305 
00306     void ban_manager::set_default_ban_times(const config& cfg)
00307     {
00308         ban_times_.clear();
00309         const config::child_list& times = cfg.get_children("ban_time");
00310         for (config::child_list::const_iterator itor = times.begin();
00311                 itor != times.end(); ++itor)
00312         {
00313             ban_times_.insert(default_ban_times::value_type((**itor)["name"],
00314                         parse_time((**itor)["time"])-time(NULL)));
00315         }
00316         init_ban_help();
00317     }
00318 
00319     ban_manager::~ban_manager()
00320     {
00321         bans_.clear();
00322         while(!time_queue_.empty())
00323         {
00324             banned* ban = time_queue_.top();
00325             delete ban;
00326             time_queue_.pop();
00327         }
00328     }
00329     
00330     ban_manager::ban_manager() : bans_(), time_queue_(), ban_times_(), ban_help_()
00331     {
00332         init_ban_help();
00333     }   
00334 
00335 
00336 }

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs