From 4acc9ec2342f45e4b998ea4013a8e421bbd8065f Mon Sep 17 00:00:00 2001 From: doitux Date: Sun, 19 Jul 2009 23:14:27 +0000 Subject: [PATCH] next steps pokerthcleaner, read config file with badwords and settings, warn + kick procedure --- chatcleaner.pro | 23 +- src/chatcleaner/badwordcheck.cpp | 8 +- src/chatcleaner/badwordcheck.h | 3 + src/chatcleaner/chatcleaner.cpp | 1 - src/chatcleaner/cleanerconfig.cpp | 584 +++++++++++++++++++++++++++++ src/chatcleaner/cleanerconfig.h | 81 ++++ src/chatcleaner/cleanerserver.cpp | 43 ++- src/chatcleaner/cleanerserver.h | 4 + src/chatcleaner/messagefilter.cpp | 91 ++++- src/chatcleaner/messagefilter.h | 13 +- src/chatcleaner/textfloodcheck.cpp | 34 +- src/chatcleaner/textfloodcheck.h | 13 +- 12 files changed, 856 insertions(+), 42 deletions(-) create mode 100644 src/chatcleaner/cleanerconfig.cpp create mode 100644 src/chatcleaner/cleanerconfig.h diff --git a/chatcleaner.pro b/chatcleaner.pro index 86a1c407..d8d8d11a 100644 --- a/chatcleaner.pro +++ b/chatcleaner.pro @@ -5,19 +5,32 @@ CODECFORSRC = UTF-8 QT += network QT -= gui TARGET = chatcleaner -CONFIG += console +CONFIG += console debug CONFIG -= app_bundle MOC_DIR = mocs OBJECTS_DIR = obj TEMPLATE = app -INCLUDEPATH += src/ src/chatcleaner/ -DEPENDPATH += src/ src/chatcleaner/ +INCLUDEPATH += src/ \ + src/third_party/tinyxml \ + src/chatcleaner/ +DEPENDPATH += src/ \ + src/third_party/tinyxml \ + src/chatcleaner/ SOURCES += chatcleaner.cpp \ cleanerserver.cpp \ messagefilter.cpp \ badwordcheck.cpp \ - textfloodcheck.cpp + textfloodcheck.cpp \ + cleanerconfig.cpp \ + tinystr.cpp \ + tinyxml.cpp \ + tinyxmlerror.cpp \ + tinyxmlparser.cpp HEADERS += cleanerserver.h \ messagefilter.h \ badwordcheck.h \ - textfloodcheck.h + textfloodcheck.h \ + cleanerconfig.h \ + tinyxml.h \ + tinystr.h + diff --git a/src/chatcleaner/badwordcheck.cpp b/src/chatcleaner/badwordcheck.cpp index 81ab1598..70475513 100644 --- a/src/chatcleaner/badwordcheck.cpp +++ b/src/chatcleaner/badwordcheck.cpp @@ -4,17 +4,15 @@ BadWordCheck::BadWordCheck() { - badWords << "arsch" << "asshole" << "bastard" << "bitch" << "cunt" << " dick " << "drecksau" << " fag " << "fagget" << "fotze" << "fuker" - << "fuck" << " fuk " << "gay" << "horny" << "hure" << "mistgeburt" << "missgeburt" << "motherfucker" << "nazi" << "nigga" - << "nigger" << "nutte" << "ommak" << "penis" << "pussy" << "schlampe" << "schwanz" << "sex" << "shit" << "sieg heil" << "slut" - << "suck" << "whore"; } bool BadWordCheck::run(QString msg) { + msg = msg.toLower(); + QStringListIterator it(badWords); while (it.hasNext()) { - if(msg.toLower().contains(it.next())) + if(msg.contains(it.next())) return true; } return false; diff --git a/src/chatcleaner/badwordcheck.h b/src/chatcleaner/badwordcheck.h index f13bdaaa..8685e720 100644 --- a/src/chatcleaner/badwordcheck.h +++ b/src/chatcleaner/badwordcheck.h @@ -8,7 +8,10 @@ Q_OBJECT public: BadWordCheck(); + void setBadWords(QStringList bw) { badWords = bw; } + bool run(QString); + private: QStringList badWords; diff --git a/src/chatcleaner/chatcleaner.cpp b/src/chatcleaner/chatcleaner.cpp index f2b76ede..b44ba4c6 100644 --- a/src/chatcleaner/chatcleaner.cpp +++ b/src/chatcleaner/chatcleaner.cpp @@ -5,6 +5,5 @@ int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); CleanerServer server; - qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); return a.exec(); } diff --git a/src/chatcleaner/cleanerconfig.cpp b/src/chatcleaner/cleanerconfig.cpp new file mode 100644 index 00000000..43b85ac2 --- /dev/null +++ b/src/chatcleaner/cleanerconfig.cpp @@ -0,0 +1,584 @@ +/*************************************************************************** + * Copyright (C) 2006 by Felix Hammer * + * f.hammer@web.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "cleanerconfig.h" +#include "tinyxml.h" + +#define MODUS 0711 + +#ifdef _WIN32 +#include +#include +#endif + +#include +#include +#include +#include + +#include +#include + +#include + +using namespace std; + + +CleanerConfig::CleanerConfig() +{ + // !!!! Revisionsnummer der Configdefaults !!!!! + configRev = 1; + + // Pfad und Dateinamen setzen +#ifdef _WIN32 + const char *appDataPath = getenv("AppData"); + if (appDataPath && appDataPath[0] != 0) { + configFileName = appDataPath; + } + else { + const int MaxPathSize = 1024; + char curDir[MaxPathSize + 1]; + curDir[0] = 0; + _getcwd(curDir, MaxPathSize); + curDir[MaxPathSize] = 0; + configFileName = curDir; + // Testen ob das Verzeichnis beschreibbar ist + ofstream tmpFile; + const char *tmpFileName = "pokerth_test.tmp"; + tmpFile.open((configFileName + "\\" + tmpFileName).c_str()); + if (tmpFile) { + // Erfolgreich, Verzeichnis beschreibbar. + // Datei wieder loeschen. + tmpFile.close(); + remove((configFileName + "\\" + tmpFileName).c_str()); + } + else { + // Fehlgeschlagen, Verzeichnis nicht beschreibbar + curDir[0] = 0; + GetTempPathA(MaxPathSize, curDir); + curDir[MaxPathSize] = 0; + configFileName = curDir; + } + } + //define app-dir + configFileName += "\\pokerth\\"; + ////define log-dir +// logDir = configFileName; +// logDir += "log-files\\"; + + //create directories on first start of app + mkdir(configFileName.c_str()); +// mkdir(logDir.c_str()); + + +#else + //define app-dir + const char *homePath = getenv("HOME"); + if(homePath) { + configFileName = homePath; + configFileName += "/.pokerth/"; + ////define log-dir +// logDir = configFileName; +// logDir += "log-files/"; + //create directories on first start of app + mkdir(configFileName.c_str(), MODUS) ; +// mkdir(logDir.c_str(), MODUS); + + } + +#endif + + string userDir = configFileName.c_str(); + + ostringstream tempIntToString; + tempIntToString << configRev; + + configList.push_back(ConfigInfo("ConfigRevision", CONFIG_TYPE_INT, tempIntToString.str())); + configList.push_back(ConfigInfo("Language", CONFIG_TYPE_STRING, getDefaultLanguage())); + + configList.push_back(ConfigInfo("HostAddress", CONFIG_TYPE_STRING, "127.0.0.1")); + configList.push_back(ConfigInfo("DefaultListenPort", CONFIG_TYPE_STRING, "4327")); + configList.push_back(ConfigInfo("WarnLevelToKick", CONFIG_TYPE_INT, "1")); + configList.push_back(ConfigInfo("TextFloodLevelToTrigger", CONFIG_TYPE_INT, "3")); + + list badWordsList; + + badWordsList.push_back("arsch"); + badWordsList.push_back("asshole"); + badWordsList.push_back("bastard"); + badWordsList.push_back("bitch"); + badWordsList.push_back("cunt"); + badWordsList.push_back(" dick "); + badWordsList.push_back("drecksau"); + badWordsList.push_back(" fag "); + badWordsList.push_back("fagget"); + badWordsList.push_back("fotze"); + badWordsList.push_back("fuker"); + badWordsList.push_back("fuck"); + badWordsList.push_back(" fuk "); + badWordsList.push_back("gay"); + badWordsList.push_back("horny"); + badWordsList.push_back("hure"); + badWordsList.push_back("mistgeburt"); + badWordsList.push_back("missgeburt"); + badWordsList.push_back("motherfucker"); + badWordsList.push_back("nazi"); + badWordsList.push_back("nigga"); + badWordsList.push_back("nigger"); + badWordsList.push_back("nutte"); + badWordsList.push_back("ommak"); + badWordsList.push_back("penis"); + badWordsList.push_back("pussy"); + badWordsList.push_back("schlampe"); + badWordsList.push_back("schwanz"); + badWordsList.push_back("sex"); + badWordsList.push_back("shit"); + badWordsList.push_back("sieg heil"); + badWordsList.push_back("slut"); + badWordsList.push_back("suck"); + badWordsList.push_back("whore"); + + configList.push_back(ConfigInfo("BadWordsList", CONFIG_TYPE_STRING_LIST, "BadWords", badWordsList)); + + //fill tempList firstTime + configBufferList = configList; + + configFileName += "cleanerconfig.xml"; + + //Prüfen ob Configfile existiert --> sonst anlegen + TiXmlDocument doc(configFileName); + if(!doc.LoadFile()){ + myConfigState = NONEXISTING; + updateConfig(myConfigState); + } + else { + //Check if config revision is ok. Otherwise --> update() + int tempRevision = 0; + + TiXmlHandle docHandle( &doc ); + TiXmlElement* confRevision = docHandle.FirstChild( "PokerTHCleaner" ).FirstChild( "Configuration" ).FirstChild( "ConfigRevision" ).ToElement(); + if ( confRevision ) { confRevision->QueryIntAttribute("value", &tempRevision ); } + + if (tempRevision < configRev ) { /*löschen()*/ + myConfigState = OLD; + updateConfig(myConfigState) ; + } + } + + + fillBuffer(); +} + + +CleanerConfig::~CleanerConfig() +{ +} + + +void CleanerConfig::fillBuffer() { + + size_t i; + string tempString1(""); + string tempString2(""); + + TiXmlDocument doc(configFileName); + + if(doc.LoadFile()) { + TiXmlHandle docHandle( &doc ); + + for (i=0; iAttribute("value"); + if (tmpStr1) tempString1 = tmpStr1; + configBufferList[i].defaultValue = tempString1; + + const char *tmpStr2 = conf->Attribute("type"); + if (tmpStr2) { + tempString2 = tmpStr2; + if(tempString2 == "list") { + + list tempStringList2; + + TiXmlElement* confList = docHandle.FirstChild( "PokerTHCleaner" ).FirstChild( "Configuration" ).FirstChild( configList[i].name ).FirstChild().ToElement(); + + for( ; confList; confList=confList->NextSiblingElement()) { + tempStringList2.push_back(confList->Attribute("value")); + } + + configBufferList[i].defaultListValue = tempStringList2; + } + } + } + else { qDebug("Could not find the root element in the config file!"); } + } + } +} + +void CleanerConfig::writeBuffer() const { + + TiXmlDocument doc; + TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "UTF-8", ""); + doc.LinkEndChild( decl ); + + TiXmlElement * root = new TiXmlElement( "PokerTHCleaner" ); + doc.LinkEndChild( root ); + + TiXmlElement * config; + config = new TiXmlElement( "Configuration" ); + root->LinkEndChild( config ); + + size_t i; + + for (i=0; iLinkEndChild( tmpElement ); + tmpElement->SetAttribute("value", configBufferList[i].defaultValue); + + if(configBufferList[i].type == CONFIG_TYPE_INT_LIST || configBufferList[i].type == CONFIG_TYPE_STRING_LIST) { + + tmpElement->SetAttribute("type", "list"); + list tempList = configBufferList[i].defaultListValue; + list::iterator it; + for(it = tempList.begin(); it != tempList.end(); it++) { + + TiXmlElement *tmpSubElement = new TiXmlElement(configBufferList[i].defaultValue); + tmpElement->LinkEndChild( tmpSubElement ); + tmpSubElement->SetAttribute("value", *it); + } + + } + } + doc.SaveFile( configFileName ); + +} + +void CleanerConfig::updateConfig(ConfigState myConfigState) { + + size_t i; + + if(myConfigState == NONEXISTING) { + + //Create a new ConfigFile! + TiXmlDocument doc; + TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "UTF-8", ""); + doc.LinkEndChild( decl ); + + TiXmlElement * root = new TiXmlElement( "PokerTHCleaner" ); + doc.LinkEndChild( root ); + + TiXmlElement * config; + config = new TiXmlElement( "Configuration" ); + root->LinkEndChild( config ); + + for (i=0; iLinkEndChild( tmpElement ); + tmpElement->SetAttribute("value", stringToUtf8(configList[i].defaultValue)); + + if(configList[i].type == CONFIG_TYPE_INT_LIST || configList[i].type == CONFIG_TYPE_STRING_LIST) { + + tmpElement->SetAttribute("type", "list"); + list tempList = configList[i].defaultListValue; + list::iterator it; + for(it = tempList.begin(); it != tempList.end(); it++) { + + TiXmlElement *tmpSubElement = new TiXmlElement(configList[i].defaultValue); + tmpElement->LinkEndChild( tmpSubElement ); + tmpSubElement->SetAttribute("value", *it); + } + + } + } + + doc.SaveFile( configFileName ); + } + + + if(myConfigState == OLD) { + + TiXmlDocument oldDoc(configFileName); + + //load the old one + if(oldDoc.LoadFile()) { + + string tempString1(""); + string tempString2(""); + + TiXmlDocument newDoc; + + //Create the new one + TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "UTF-8", ""); + newDoc.LinkEndChild( decl ); + + TiXmlElement * root = new TiXmlElement( "PokerTHCleaner" ); + newDoc.LinkEndChild( root ); + + TiXmlElement * config; + config = new TiXmlElement( "Configuration" ); + root->LinkEndChild( config ); + + //change configRev and AppDataPath + TiXmlElement * confElement0 = new TiXmlElement( "ConfigRevision" ); + config->LinkEndChild( confElement0 ); + confElement0->SetAttribute("value", configRev); + + TiXmlHandle oldDocHandle( &oldDoc ); + + for (i=0; i take over the saved values + + if(configList[i].name != "ConfigRevision") { + // dont update ConfigRevision because it was already set ^ + + TiXmlElement *tmpElement = new TiXmlElement(configList[i].name); + config->LinkEndChild( tmpElement ); + + const char *tmpStr1 = oldConf->Attribute("value"); + if (tmpStr1) tempString1 = tmpStr1; + tmpElement->SetAttribute("value", tempString1); + + //for lists copy elements + const char *tmpStr2 = oldConf->Attribute("type"); + if (tmpStr2) { + tempString2 = tmpStr2; + if(tempString2 == "list") { + + list tempStringList2; + + TiXmlElement* oldConfList = oldDocHandle.FirstChild( "PokerTHCleaner" ).FirstChild( "Configuration" ).FirstChild( configList[i].name ).FirstChild().ToElement(); + + for( ; oldConfList; oldConfList=oldConfList->NextSiblingElement()) { + tempStringList2.push_back(oldConfList->Attribute("value")); + } + + tmpElement->SetAttribute("type", "list"); + list tempList = tempStringList2; + list::iterator it; + for(it = tempList.begin(); it != tempList.end(); it++) { + + TiXmlElement *tmpSubElement = new TiXmlElement(tempString1); + tmpElement->LinkEndChild( tmpSubElement ); + tmpSubElement->SetAttribute("value", *it); + } + } + } + } + } + else { + // if element is not there --> set it with defaultValue + TiXmlElement *tmpElement = new TiXmlElement(configList[i].name); + config->LinkEndChild( tmpElement ); + tmpElement->SetAttribute("value", stringToUtf8(configList[i].defaultValue)); + + if(configList[i].type == CONFIG_TYPE_INT_LIST || configList[i].type == CONFIG_TYPE_STRING_LIST) { + + tmpElement->SetAttribute("type", "list"); + list tempList = configList[i].defaultListValue; + list::iterator it; + for(it = tempList.begin(); it != tempList.end(); it++) { + + TiXmlElement *tmpSubElement = new TiXmlElement(configList[i].defaultValue); + tmpElement->LinkEndChild( tmpSubElement ); + tmpSubElement->SetAttribute("value", *it); + } + } + } + } + newDoc.SaveFile( configFileName ); + } + else { qDebug("Cannot update config file: Unable to load configuration."); } + + + } +} + +string CleanerConfig::readConfigString(string varName) const +{ + + size_t i; + string tempString(""); + + for (i=0; i> tempInt; + + return tempInt; +} + +list CleanerConfig::readConfigStringList(string varName) const +{ + + size_t i; + list tempStringList; + + for (i=0; i CleanerConfig::readConfigIntList(string varName) const +{ + + size_t i; + list tempStringList; + list tempIntList; + + for (i=0; i::iterator it; + for(it = tempStringList.begin(); it != tempStringList.end(); it++) { + + isst.str(*it); + isst >> tempInt; + tempIntList.push_back(tempInt); + isst.str(""); + isst.clear(); + } + + return tempIntList; +} + + +void CleanerConfig::writeConfigInt(string varName, int varCont) +{ + + size_t i; + string tempString; + ostringstream intToString; + + for (i=0; i varCont) +{ + + size_t i; + ostringstream intToString; + list stringList; + + for (i=0; i::iterator it; + for(it = varCont.begin(); it != varCont.end(); it++) { + + intToString << (*it); + stringList.push_back(intToString.str()); + intToString.str(""); + intToString.clear(); + } + + configBufferList[i].defaultListValue = stringList; + } + } +} + +void CleanerConfig::writeConfigStringList(string varName, list varCont) +{ + + size_t i; + list stringList; + + for (i=0; i +#include +#include + +enum ConfigState { NONEXISTING, OLD }; +enum ConfigType { CONFIG_TYPE_INT, CONFIG_TYPE_STRING, CONFIG_TYPE_INT_LIST, CONFIG_TYPE_STRING_LIST }; + + +class CleanerConfig{ +public: + CleanerConfig(); + + ~CleanerConfig(); + + void fillBuffer(); + void writeBuffer() const; + + void updateConfig(ConfigState); + + int readConfigInt(std::string varName) const; + std::string readConfigString(std::string varName) const; + std::list readConfigIntList(std::string varName) const; + std::list readConfigStringList(std::string varName) const; + + void writeConfigInt(std::string varName, int varCont); + void writeConfigString(std::string varName, std::string varCont); + void writeConfigIntList(std::string varName, std::list varCont); + void writeConfigStringList(std::string varName, std::list varCont); + + std::string stringToUtf8(const std::string & ); + std::string stringFromUtf8(const std::string &); + std::string getDefaultLanguage(); + +private: + + struct ConfigInfo + { + ConfigInfo(const std::string &n, ConfigType t, const std::string &d, const std::list &l =std::list()) : name(n), type(t), defaultValue(d), defaultListValue(l) {} + std::string name; + ConfigType type; + std::string defaultValue; + std::list defaultListValue; + + }; + + std::vector configList; + std::vector configBufferList; + + std::string configFileName; + std::string logDir; + std::string dataDir; + std::string cacheDir; + int configRev; + + ConfigState myConfigState; + +}; + +#endif diff --git a/src/chatcleaner/cleanerserver.cpp b/src/chatcleaner/cleanerserver.cpp index b069a5f1..13ea0d7a 100644 --- a/src/chatcleaner/cleanerserver.cpp +++ b/src/chatcleaner/cleanerserver.cpp @@ -5,19 +5,26 @@ #include #include "messagefilter.h" +#include "cleanerconfig.h" -CleanerServer::CleanerServer() +CleanerServer::CleanerServer(): config(0) { - myMessageFilter = new MessageFilter; - tcpServer = new QTcpServer(); - if (!tcpServer->listen(QHostAddress("127.0.0.1"), 7777) ) { - qDebug() << QString("Unable to start the server: %1.").arg(tcpServer->errorString()); - return; - } + config = new CleanerConfig; + + myMessageFilter = new MessageFilter(config); + tcpServer = new QTcpServer(); + tcpServer->setMaxPendingConnections(1); + + if (!tcpServer->listen(QHostAddress(QString::fromUtf8(config->readConfigString("HostAddress").c_str())), config->readConfigInt("DefaultListenPort")) ) { + qDebug() << QString("Unable to start the server: %1.").arg(tcpServer->errorString()); + return; + } + + qDebug() << QString("The server is running on port %1.").arg(tcpServer->serverPort()); - qDebug() << QString("The server is running on port %1.").arg(tcpServer->serverPort()); - - connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newCon())); + connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newCon())); + + refreshConfig(); } CleanerServer::~CleanerServer() @@ -32,9 +39,21 @@ void CleanerServer::newCon() void CleanerServer::onRead() { - char buf[20000]; + char buf[1024]; tcpSocket->readLine(buf, sizeof(buf)); QString message = QString::fromUtf8("%1").arg(buf); - QString checkMessage = myMessageFilter->check(message); + + // TESTING DEFAULT VALUES + QString nick = "PlayerNick"; + unsigned playerId = 1; + // TESTING DEFAULT VALUES + + QString checkMessage = myMessageFilter->check(playerId, nick, message); tcpSocket->write(checkMessage.toAscii().data(), checkMessage.length()); } + +void CleanerServer::refreshConfig() { + +// config->fillBuffer(); + myMessageFilter->refreshConfig(); +} diff --git a/src/chatcleaner/cleanerserver.h b/src/chatcleaner/cleanerserver.h index 8c8878d3..d0e7ba88 100644 --- a/src/chatcleaner/cleanerserver.h +++ b/src/chatcleaner/cleanerserver.h @@ -5,6 +5,7 @@ #include class MessageFilter; +class CleanerConfig; class CleanerServer: public QObject { Q_OBJECT @@ -16,12 +17,15 @@ public: private slots: void newCon(); void onRead(); + + void refreshConfig(); private: QTcpServer *tcpServer; QTcpSocket *tcpSocket; MessageFilter *myMessageFilter; + CleanerConfig *config; }; #endif // CLEANERSERVER_H diff --git a/src/chatcleaner/messagefilter.cpp b/src/chatcleaner/messagefilter.cpp index fcae3735..f9c7f530 100644 --- a/src/chatcleaner/messagefilter.cpp +++ b/src/chatcleaner/messagefilter.cpp @@ -3,25 +3,98 @@ #include #include "badwordcheck.h" #include "textfloodcheck.h" +#include "cleanerconfig.h" + +enum ActionType { + NOTHING, + WARN, + KICK }; enum OffenceType { + NONE, BAD_WORD, TEXT_FLOOD_LINES }; -MessageFilter::MessageFilter() +MessageFilter::MessageFilter(CleanerConfig *c): config(c) { myBadWordCheck = new BadWordCheck; myTextFloodCheck = new TextFloodCheck; } -QString MessageFilter::check(QString msg) +QString MessageFilter::check(unsigned playerId, QString nick, QString msg) { - if(myBadWordCheck->run(msg)) { - return QString(" Der Blitz soll dich beim Scheißen erschlagen du Spammer\n"); - } - if(myTextFloodCheck->run(1)) { - return QString(" Bitte langsamer schreiben!!!\n"); - } + QString returnMessage; - return QString(""); + OffenceType offence = NONE; + ActionType action = NOTHING; + + if(myBadWordCheck->run(msg)) offence = BAD_WORD; + if(myTextFloodCheck->run(playerId)) offence = TEXT_FLOOD_LINES; + + if(offence){ + + QMap::const_iterator i = myClientWarnLevelList.find(playerId); + + if(i == myClientWarnLevelList.end()) { + myClientWarnInfos.warnLevel = 1; + myClientWarnInfos.lastWarnType = offence; + myClientWarnInfos.nick = nick; + myClientWarnLevelList.insert(playerId, myClientWarnInfos); + action = WARN; + } + else { + if(i.value().warnLevel == warnLevelToKick) { +// Kick Command + action = KICK; + myClientWarnLevelList.remove(i.key()); + } + else { + myClientWarnInfos.warnLevel++; + myClientWarnInfos.lastWarnType = offence; + myClientWarnInfos.nick = nick; + myClientWarnLevelList.insert(playerId, myClientWarnInfos); + action = WARN; + } + } + + if(action == KICK) { + returnMessage = QString("Kick: %1\n").arg(nick); + } + if(action == WARN) { + + switch(offence) { + case BAD_WORD: { + returnMessage = QString (" %1: Warning! No racial, religious, or sexually inflammatory language!\n").arg(nick); + } + break; + case TEXT_FLOOD_LINES: { + returnMessage = QString (" %1: Warning! You've triggered text flood (lines) protection, slow down your typing!\n").arg(nick); + } + break; + default:; + } + } + } + else { + returnMessage = QString(""); + } + return returnMessage; +} + +void MessageFilter::refreshConfig() { + + // global settings + warnLevelToKick = config->readConfigInt("WarnLevelToKick"); + + // special check settings + //Bad Words + std::list badWordsList = config->readConfigStringList("BadWordsList"); + std::list::iterator it1; + QStringList bwList; + for(it1= badWordsList.begin(); it1 != badWordsList.end(); it1++) { + bwList << QString::fromUtf8(it1->c_str()); + } + myBadWordCheck->setBadWords(bwList); + + myTextFloodCheck->setTextFloodLevelToTrigger(config->readConfigInt("TextFloodLevelToTrigger")); } diff --git a/src/chatcleaner/messagefilter.h b/src/chatcleaner/messagefilter.h index 98b76018..1f7c448d 100644 --- a/src/chatcleaner/messagefilter.h +++ b/src/chatcleaner/messagefilter.h @@ -6,14 +6,16 @@ class BadWordCheck; class TextFloodCheck; +class CleanerConfig; class MessageFilter: public QObject { Q_OBJECT public: - MessageFilter(); + MessageFilter(CleanerConfig*); - QString check(QString); - + QString check(unsigned, QString, QString); + void refreshConfig(); + private: BadWordCheck *myBadWordCheck; TextFloodCheck *myTextFloodCheck; @@ -23,9 +25,12 @@ private: int lastWarnType; int warnLevel; }; + ClientWarnInfos myClientWarnInfos; + QMap myClientWarnLevelList; - QMap clientWarnLevelList; + int warnLevelToKick; + CleanerConfig *config; }; #endif // MESSAGEFILTER_H diff --git a/src/chatcleaner/textfloodcheck.cpp b/src/chatcleaner/textfloodcheck.cpp index 8934fae9..ec69c053 100644 --- a/src/chatcleaner/textfloodcheck.cpp +++ b/src/chatcleaner/textfloodcheck.cpp @@ -1,9 +1,17 @@ #include "textfloodcheck.h" +#include TextFloodCheck::TextFloodCheck() { timer.reset(); timer.start(); + + cleanTimer = new QTimer(); + + connect(cleanTimer, SIGNAL(timeout()), this, SLOT(cleanMsgTimesList())); + + cleanTimer->start(4000); + } bool TextFloodCheck::run(unsigned playerId) { @@ -23,12 +31,10 @@ bool TextFloodCheck::run(unsigned playerId) { } else { if(timer.elapsed().total_seconds()-i.value().timeStamp <= 1) { - if(i.value().floodLevel == 2) + if(i.value().floodLevel == textFloodLevelToTrigger) return true; - else if(i.value().floodLevel == 1) - myTextFloodInfos.floodLevel = 2; else - myTextFloodInfos.floodLevel = 1; + myTextFloodInfos.floodLevel++; } myTextFloodInfos.timeStamp = timer.elapsed().total_seconds(); @@ -39,5 +45,25 @@ bool TextFloodCheck::run(unsigned playerId) { void TextFloodCheck::cleanMsgTimesList() { + QMapIterator it(msgTimesList); + while (it.hasNext()) { + it.next(); + if(timer.elapsed().total_seconds()-it.value().timeStamp > 3) { + + if(it.value().floodLevel == 0) + msgTimesList.remove(it.key()); + + else { + myTextFloodInfos.floodLevel--; + myTextFloodInfos.timeStamp = it.value().timeStamp; + msgTimesList.insert(it.key(), myTextFloodInfos); + } + } + qDebug() << msgTimesList.count() << it.key() << ": " << it.value().floodLevel << it.value().timeStamp << endl; + } +} +void TextFloodCheck::removeNickFromList(unsigned playerId) { + + msgTimesList.remove(playerId); } diff --git a/src/chatcleaner/textfloodcheck.h b/src/chatcleaner/textfloodcheck.h index 4c29d325..1fef9445 100644 --- a/src/chatcleaner/textfloodcheck.h +++ b/src/chatcleaner/textfloodcheck.h @@ -6,15 +6,22 @@ #include -class TextFloodCheck +class TextFloodCheck: public QObject { + Q_OBJECT public: TextFloodCheck(); + + void setTextFloodLevelToTrigger(int level) { textFloodLevelToTrigger = level; } + bool run(unsigned); + +public slots: void cleanMsgTimesList(); + void removeNickFromList(unsigned); private: - QTimer cleanTimer; + QTimer *cleanTimer; boost::timers::portable::second_timer timer; struct TextFloodInfos { int floodLevel; @@ -22,6 +29,8 @@ private: }; TextFloodInfos myTextFloodInfos; QMap msgTimesList; + + int textFloodLevelToTrigger; }; #endif // TEXTFLOODCHECK_H