/* * RAM $Id: ban.c 84 2009-01-17 23:19:56Z ghasatta $ */ /*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ /*************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * ***************************************************************************/ #include <sys/types.h> #include <sys/time.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string> #include "merc.h" #include "strings.h" #include "db.h" #include "interp.h" #include "ban.h" #include <fstream> #include <sstream> #include <algorithm> #include <cctype> #include <iomanip> ban_manager *ban_manager::pInstance = NULL; ban_manager *ban_manager::Instance() { if(ban_manager::pInstance == NULL) ban_manager::pInstance = new ban_manager; return ban_manager::pInstance; } ban_manager::ban_manager() { } ban_manager::~ban_manager() { } bool ban_manager::add_ban(int _level, std::string _name, int _type, bool _perm) { std::transform(_name.begin(), _name.end(), _name.begin(), tolower); // remove existing ban for _name, if any. if(this->remove_ban(_level, _name, false) == true) { ban_data new_ban(_level, _name, _type, _perm); this->bans.push_back(new_ban); this->save_bans(); return true; } else return false; } bool ban_manager::remove_ban(int _level, std::string _name, bool should_save /* = true */) { std::transform(_name.begin(), _name.end(), _name.begin(), tolower); // remove any asterisks. if(_name.empty() == false) { if(_name.at(0) == '*') _name.erase(0,1); if(_name.at(_name.size() - 1) == '*') _name.erase(_name.size() - 1, 1); } std::vector<ban_data>::iterator existing_iter = this->find_ban(_name, true); // if we already have a ban for _name, verify that _level is sufficient to change the ban. If so, remove the existing ban. if(existing_iter != this->bans.end()) { if(_level < existing_iter->level) return false; else this->bans.erase(existing_iter); } if(should_save == true) this->save_bans(); return true; } void ban_manager::save_bans() const { std::ofstream out; out.exceptions(std::ios::eofbit | std::ios::failbit | std::ios::badbit); try { out.open(BAN_FILE_NEW, std::ios::trunc); for(std::vector<ban_data>::const_iterator i = this->bans.begin(); i != this->bans.end(); ++i) i->write_save(out); out.close(); } catch(std::exception &e) { log_error("ban_manager::save_bans(): %s", e.what()); } } void ban_manager::load_bans() { if(this->load_old_format() == false) { std::ifstream in; in.exceptions(std::ios::eofbit | std::ios::failbit | std::ios::badbit); try { in.open(BAN_FILE_NEW, std::ios::in); while(in.eof() == false) { std::string name; int level; std::string flags; in >> name >> level >> flags; this->bans.push_back(ban_data(level, name, str_read_flag(flags.c_str()))); } in.close(); } catch(std::exception &e) { log_error("ban_manager::load_bans(): %s", e.what()); } } } bool ban_manager::load_old_format() { FILE *fp = NULL; if ( ( fp = fopen( BAN_FILE, "r" ) ) == NULL ) return false; while(!feof(fp)) { std::string name = fread_word( fp ); int level = fread_number( fp ); int ban_flags = fread_flag( fp ); fread_to_eol( fp ); this->bans.push_back(ban_data(level, name, ban_flags)); } fclose(fp); // write in the new format. this->save_bans(); // remove the old file. unlink(BAN_FILE); return true; } std::string ban_manager::print_bans() const { std::ostringstream out; const char *_type; const char *_perm; out << "Banned sites level type status\r\n"; for(std::vector<ban_manager::ban_data>::const_iterator i = this->bans.begin(); i != this->bans.end(); ++i) { std::string name; if(IS_SET(i->ban_flags, BAN_PREFIX)) name += "*"; name += i->name; if(IS_SET(i->ban_flags, BAN_SUFFIX)) name += "*"; out << std::setw(12) << name << " "; out << std::setprecision(3) << i->level << " "; _type = IS_SET( i->ban_flags, BAN_NEWBIES ) ? "newbies" : IS_SET( i->ban_flags, BAN_PERMIT ) ? "permit" : IS_SET( i->ban_flags, BAN_ALL ) ? "all" : ""; _perm = IS_SET( i->ban_flags, BAN_PERMANENT ) ? "perm" : "temp"; out << std::setw(7) << std::left << _type << " "; out << _perm; out << "\r\n"; } if(this->bans.empty() == true) out << "(none)" << "\r\n"; return out.str(); } std::vector<ban_manager::ban_data>::iterator ban_manager::find_ban(std::string _name, bool exact_match /* = false */) { std::transform(_name.begin(), _name.end(), _name.begin(), tolower); for(std::vector<ban_manager::ban_data>::iterator i = this->bans.begin(); i != this->bans.end(); ++i) if(i->is_match(_name, exact_match) == true) return i; // else... not found return this->bans.end(); } std::vector<ban_manager::ban_data>::const_iterator ban_manager::find_ban(std::string _name, bool exact_match /* = false */) const { std::transform(_name.begin(), _name.end(), _name.begin(), tolower); for(std::vector<ban_manager::ban_data>::const_iterator i = this->bans.begin(); i != this->bans.end(); ++i) if(i->is_match(_name, exact_match) == true) return i; // else... not found return this->bans.end(); } bool ban_manager::is_banned(std::string _name, int _type) const { // look for an exact match first. std::vector<ban_manager::ban_data>::const_iterator i = this->find_ban(_name, true); // if we didn't find an exact match, look for a wildcard match next. if(i == this->bans.end()) i = this->find_ban(_name, false); // if we still haven't found a matching ban, there is no ban, return false. if(i == this->bans.end()) return false; else if(IS_SET(i->ban_flags, _type)) return true; // else... return false; } ban_manager::ban_data::ban_data(int _level, std::string _name, int flags) { name = _name; level = _level; ban_flags = flags; } ban_manager::ban_data::ban_data(int _level, std::string _name, int _type, bool _perm) { name = _name; level = _level; ban_flags = _type; if(_perm == true) SET_BIT(this->ban_flags, BAN_PERMANENT); this->parse_name(); } ban_manager::ban_data::~ban_data() { } void ban_manager::ban_data::parse_name() { // transform to lowercase. std::transform(this->name.begin(), this->name.end(), this->name.begin(), tolower); if(name.find("*") == 0) { name.erase(0, 1); SET_BIT(this->ban_flags, BAN_PREFIX); } if(name.rfind("*") == (name.size() - 1)) { SET_BIT(this->ban_flags, BAN_SUFFIX); name.erase(name.size() - 1); } // if name is empty, it means both suffix and prefix are true. else if(name.empty() == true) SET_BIT(this->ban_flags, BAN_SUFFIX); } bool ban_manager::ban_data::is_match(std::string _name, bool exact_match) const { // transform arg to lowercase. std::transform(_name.begin(), _name.end(), _name.begin(), tolower); if( (exact_match == true && this->name == _name) || (exact_match == false && IS_SET(this->ban_flags, BAN_PREFIX) && _name.rfind(this->name) == (_name.size() - this->name.size())) || (exact_match == false && IS_SET(this->ban_flags, BAN_SUFFIX) && _name.find(this->name) == 0) ) return true; // else... return false; } void ban_manager::ban_data::write_save(std::ofstream &out) const { // only write if this is a permanent ban if(IS_SET(this->ban_flags, BAN_PERMANENT)) out << this->name << " " << this->level << " " << print_flags(this->ban_flags) << std::endl; } void ban_manager::do_ban(CHAR_DATA *ch, const char *argument) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char arg3[MAX_INPUT_LENGTH]; argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); argument = one_argument(argument, arg3); // no arg means just print the ban list. if(arg1[0] == '\0') send_to_char(ban_manager::Instance()->print_bans().c_str(), ch); // else we want to add a ban else { std::string name(arg1); int type = 0; bool perm; // arg1 is name // arg2 is type // arg3 is either perm or temp // verify name contains something besides the wildcard character. if(name.find_first_not_of("*") == std::string::npos) { ch_printf(ch, "Ban name must include at least 1 character besides the wildcard '*'"); return; } if(!str_prefix(arg2, "all")) type = BAN_ALL; else if(!str_prefix(arg2, "newbies")) type = BAN_NEWBIES; else if(!str_prefix(arg2, "permit")) type = BAN_PERMIT; else { ch_printf( ch, "Acceptable ban types are all, newbies, and permit.\r\n" ); return; } if(!str_prefix(arg3, "temp")) perm = false; else if(!str_prefix(arg3, "perm")) perm = true; else { ch_printf(ch, "Error: Must specify either 'perm' or 'temp' for ban length.\r\n"); return; } bool success = ban_manager::Instance()->add_ban(get_trust(ch), name, type, perm); if(success == true) ch_printf(ch, "%s has been banned.\r\n", name.c_str()); else ch_printf(ch, "Error: Ban was not successful. Check for existing bans set to a level higher than your trust level.\r\n"); } } void ban_manager::do_permban(CHAR_DATA *ch, const char *argument) { send_to_char("Error: Permban command is obsolete. Use: ban sitename type perm/temp", ch); } void ban_manager::do_allow(CHAR_DATA *ch, const char *argument) { char arg1[MAX_INPUT_LENGTH]; bool success; one_argument(argument, arg1); if(arg1[0] == '\0') { ch_printf( ch, "Remove which site from the ban list?\r\n" ); return; } success = ban_manager::Instance()->remove_ban(get_trust(ch), arg1); if(success == true) ch_printf( ch, "Ban on %s lifted.\r\n", arg1 ); else ch_printf( ch, "You are not powerful enough to lift that ban.\r\n" ); }