Added a new feature to ignore channels/nicks which you do not want to have logged and replayed. Ignores are wildcard based and nick ignores includes the mask which allows you to block an entire ip address/hostname and or nick name.

This commit is contained in:
GRMrGecko 2012-02-13 21:43:03 -06:00
parent b0ed19fe38
commit 3cf9cf5bd7
3 changed files with 581 additions and 48 deletions

View File

@ -31,4 +31,15 @@ BEGIN;
INSERT INTO `settings` VALUES ('replayAll', '0'), ('logLimit', '1'), ('logLevel', '1'); INSERT INTO `settings` VALUES ('replayAll', '0'), ('logLimit', '1'), ('logLevel', '1');
COMMIT; COMMIT;
-- ----------------------------
-- Table structure for `ignorelist`
-- ----------------------------
DROP TABLE IF EXISTS `ignorelist`;
CREATE TABLE `ignorelist` (
`rowid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`type` text,
`target` text,
PRIMARY KEY (`rowid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS = 1; SET FOREIGN_KEY_CHECKS = 1;

View File

@ -40,6 +40,9 @@ public:
AddCommand("ReplayAll", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::ReplayAllCommand), "[1|0]", "Replay all messages stored."); AddCommand("ReplayAll", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::ReplayAllCommand), "[1|0]", "Replay all messages stored.");
AddCommand("LogLimit", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::LogLimitCommand), "[0-9]+", "Limit the amount of items to store into the log."); AddCommand("LogLimit", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::LogLimitCommand), "[0-9]+", "Limit the amount of items to store into the log.");
AddCommand("LogLevel", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::LogLevelCommand), "[0-4]", "Log level."); AddCommand("LogLevel", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::LogLevelCommand), "[0-4]", "Log level.");
AddCommand("AddIgnore", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::AddIgnoreCommand), "Type[nick|chan] Target", "Add to ignore list.");
AddCommand("RemoveIgnore", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::RemoveIgnoreCommand), "Type[nick|chan] Target", "Remove from ignore list.");
AddCommand("IgnoreList", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::IgnoreListCommand), "", "View what is currently ignored.");
} }
void HostCommand(const CString &sLine) { void HostCommand(const CString &sLine) {
@ -196,6 +199,88 @@ public:
PutModule("LogLevel is "+now+"set to: "+setting); PutModule("LogLevel is "+now+"set to: "+setting);
} }
void AddIgnoreCommand(const CString &sLine) {
CString type = sLine.Token(1);
CString target = sLine.Token(2);
bool help = sLine.Equals("HELP");
if (help) {
PutModule("Inorder to add an ignore, you must choose what type of ignore it is which can ether be a nick or a chan.");
PutModule("Nicks are matched with wildcards against the full mask.");
PutModule("Channels are matched by #channel which can contain wildcards.");
} else if (!type.empty() && !target.empty()) {
if (type.Equals("nick"))
type = "nick";
else if (type.Equals("chan") || type.Equals("channel"))
type = "chan";
else
type = "";
if (type.empty()) {
PutModule("Unknown type. If you need help, type \"AddIgnore help\".");
return;
}
if (AddIgnore(type, target))
PutModule("Successfully added \""+target+"\" to the ignore list.");
else
PutModule("Failed, maybe it already existed?");
} else {
PutModule("If you need help, type \"AddIgnore help\".");
}
}
void RemoveIgnoreCommand(const CString &sLine) {
CString type = sLine.Token(1);
CString target = sLine.Token(2);
bool help = sLine.Equals("HELP");
if (help) {
PutModule("Inorder to remove an ignore, you must specify the type and the exact pattren used to add it. If you need to find what currently exists, type \"IgnoreList\".");
} else if (!type.empty() && !target.empty()) {
if (type.Equals("nick"))
type = "nick";
else if (type.Equals("chan") || type.Equals("channel"))
type = "chan";
else
type = "";
if (type.empty()) {
PutModule("Unknown type. If you need help, type \"RemoveIgnore help\".");
return;
}
if (RemoveIgnore(type, target))
PutModule("Successfully removed \""+target+"\" from the ignore list.");
else
PutModule("Failed, maybe it does not exist?");
} else {
PutModule("If you need help, type \"RemoveIgnore help\".");
}
}
void IgnoreListCommand(const CString &sLine) {
if (nickIgnoreList.size()==0) {
PutModule("The nick ignore list is currently empty.");
} else {
PutModule("Nick ignore list contains:");
for (vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
PutModule(*it);
}
}
PutModule("---");
if (chanIgnoreList.size()==0) {
PutModule("The channel ignore list is currently empty.");
} else {
PutModule("Channel ignore list contains:");
for (vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
PutModule(*it);
}
}
}
virtual bool OnLoad(const CString& sArgs, CString& sMessage) { virtual bool OnLoad(const CString& sArgs, CString& sMessage) {
connected = true; connected = true;
databaseConnected = false; databaseConnected = false;
@ -237,45 +322,51 @@ public:
cout << "LogMySQL: Database connected.\n"; cout << "LogMySQL: Database connected.\n";
MYSQL_RES *settings = mysql_list_tables(database, "settings"); MYSQL_RES *settings = mysql_list_tables(database, "settings");
MYSQL_RES *messages = mysql_list_tables(database, "messages"); if (mysql_num_rows(settings)==0) {
if (mysql_num_rows(settings)==0 || mysql_num_rows(messages)==0) {
cout << "Creating tables\n";
MYSQL_STMT *statement = mysql_stmt_init(database); MYSQL_STMT *statement = mysql_stmt_init(database);
int status = mysql_stmt_prepare(statement, "DROP TABLE IF EXISTS `settings`", 31); int status = mysql_stmt_prepare(statement, "CREATE TABLE `settings` (`name` text,`value` text)", 50);
if (status==0) { if (status==0) {
mysql_stmt_execute(statement); mysql_stmt_execute(statement);
mysql_stmt_close(statement); mysql_stmt_close(statement);
SetSetting("replayAll","0");
SetSetting("logLimit","1");
SetSetting("logLevel","1");
SetSetting("version","1");
} }
statement = mysql_stmt_init(database);
status = mysql_stmt_prepare(statement, "CREATE TABLE `settings` (`name` text,`value` text)", 50);
if (status==0) {
mysql_stmt_execute(statement);
mysql_stmt_close(statement);
}
statement = mysql_stmt_init(database);
status = mysql_stmt_prepare(statement, "DROP TABLE IF EXISTS `messages`", 31);
if (status==0) {
mysql_stmt_execute(statement);
mysql_stmt_close(statement);
}
statement = mysql_stmt_init(database);
status = mysql_stmt_prepare(statement, "CREATE TABLE `messages` (`rowid` int UNSIGNED AUTO_INCREMENT,`target` text,`nick` text,`type` text,`message` longblob,`time` decimal(20,5) UNSIGNED,PRIMARY KEY (`rowid`))", 170);
if (status==0) {
mysql_stmt_execute(statement);
mysql_stmt_close(statement);
}
SetSetting("replayAll","0");
SetSetting("logLimit","1");
SetSetting("logLevel","1");
} }
if (settings!=NULL) if (settings!=NULL)
mysql_free_result(settings); mysql_free_result(settings);
MYSQL_RES *messages = mysql_list_tables(database, "messages");
if (mysql_num_rows(messages)==0) {
MYSQL_STMT *statement = mysql_stmt_init(database);
int status = mysql_stmt_prepare(statement, "CREATE TABLE `messages` (`rowid` int UNSIGNED AUTO_INCREMENT,`target` text,`nick` text,`type` text,`message` longblob,`time` decimal(20,5) UNSIGNED,PRIMARY KEY (`rowid`))", 170);
if (status==0) {
mysql_stmt_execute(statement);
mysql_stmt_close(statement);
}
}
if (messages!=NULL) if (messages!=NULL)
mysql_free_result(messages); mysql_free_result(messages);
MYSQL_RES *ignorelist = mysql_list_tables(database, "ignorelist");
if (mysql_num_rows(ignorelist)==0) {
MYSQL_STMT *statement = mysql_stmt_init(database);
int status = mysql_stmt_prepare(statement, "CREATE TABLE `ignorelist` (`rowid` int UNSIGNED AUTO_INCREMENT,`type` text,`target` text,PRIMARY KEY (`rowid`))", 111);
if (status==0) {
mysql_stmt_execute(statement);
mysql_stmt_close(statement);
}
}
if (ignorelist!=NULL)
mysql_free_result(ignorelist);
replayAll = atoi(GetSetting("replayAll").c_str()); replayAll = atoi(GetSetting("replayAll").c_str());
logLimit = strtoul(GetSetting("logLimit").c_str(), NULL, 10); logLimit = strtoul(GetSetting("logLimit").c_str(), NULL, 10);
logLevel = atoi(GetSetting("logLevel").c_str()); logLevel = atoi(GetSetting("logLevel").c_str());
unsigned long version = strtoul(GetSetting("version").c_str(), NULL, 10);
if (version==0)
SetSetting("version","1");
} else { } else {
cout << "LogMySQL: Database unable to connect.\n"; cout << "LogMySQL: Database unable to connect.\n";
} }
@ -295,6 +386,8 @@ public:
void AddMessage(const CString& target, const CString& nick, const CString& type, const CString& message) { void AddMessage(const CString& target, const CString& nick, const CString& type, const CString& message) {
if (!databaseConnected) if (!databaseConnected)
return; return;
if (IsIgnored("nick",nick) || (target.Left(1).Equals("#") && IsIgnored("chan",target)))
return;
MYSQL_STMT *statement = mysql_stmt_init(database); MYSQL_STMT *statement = mysql_stmt_init(database);
int status = mysql_stmt_prepare(statement, "INSERT INTO `messages` (`target`, `nick`, `type`, `message`, `time`) VALUES (?,?,?,?,?)", 87); int status = mysql_stmt_prepare(statement, "INSERT INTO `messages` (`target`, `nick`, `type`, `message`, `time`) VALUES (?,?,?,?,?)", 87);
if (status!=0) if (status!=0)
@ -611,8 +704,186 @@ public:
mysql_stmt_close(statement); mysql_stmt_close(statement);
return stringValue; return stringValue;
} }
//Server stuff
void UpdateIgnoreLists() {
if (!databaseConnected)
return;
nickIgnoreList.clear();
MYSQL_STMT *statement = mysql_stmt_init(database);
int status = mysql_stmt_prepare(statement, "SELECT `target` FROM `ignorelist` WHERE `type`='nick'", 53);
if (status==0) {
status = mysql_stmt_execute(statement);
if (status==0) {
MYSQL_RES *result = mysql_stmt_result_metadata(statement);
unsigned int dataCount = mysql_num_fields(result);
if (dataCount==1) {
MYSQL_FIELD *fields = mysql_fetch_fields(result);
unsigned long length;
char targetData[fields[0].length];
MYSQL_BIND results[1];
memset(results, 0, sizeof(results));
results[0].buffer_type = MYSQL_TYPE_STRING;
results[0].buffer = (void *)targetData;
results[0].buffer_length = fields[0].length;
results[0].length = &length;
status = mysql_stmt_bind_result(statement, results);
if (status==0) {
while (true) {
status = mysql_stmt_fetch(statement);
if (status!=0)
break;
CString ignore = CString(targetData, length);
nickIgnoreList.push_back(ignore);
break;
}
}
}
mysql_free_result(result);
}
mysql_stmt_close(statement);
}
chanIgnoreList.clear();
statement = mysql_stmt_init(database);
status = mysql_stmt_prepare(statement, "SELECT `target` FROM `ignorelist` WHERE `type`='chan'", 53);
if (status==0) {
status = mysql_stmt_execute(statement);
if (status==0) {
MYSQL_RES *result = mysql_stmt_result_metadata(statement);
unsigned int dataCount = mysql_num_fields(result);
if (dataCount==1) {
MYSQL_FIELD *fields = mysql_fetch_fields(result);
unsigned long length;
char targetData[fields[0].length];
MYSQL_BIND results[1];
memset(results, 0, sizeof(results));
results[0].buffer_type = MYSQL_TYPE_STRING;
results[0].buffer = (void *)targetData;
results[0].buffer_length = fields[0].length;
results[0].length = &length;
status = mysql_stmt_bind_result(statement, results);
if (status==0) {
while (true) {
status = mysql_stmt_fetch(statement);
if (status!=0)
break;
CString ignore = CString(targetData, length);
chanIgnoreList.push_back(ignore);
break;
}
}
}
mysql_free_result(result);
}
mysql_stmt_close(statement);
}
}
bool AddIgnore(const CString& type, const CString& target) {
if (!IgnoreExists(type, target)) {
MYSQL_STMT *statement = mysql_stmt_init(database);
int status = mysql_stmt_prepare(statement, "INSERT INTO `ignorelist` (`type`, `target`) VALUES (?,?)", 56);
if (status!=0)
return false;
MYSQL_BIND bind[2];
memset(bind, 0, sizeof(bind));
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = (void*)type.c_str();
bind[0].buffer_length = type.length();
bind[0].is_null = false;
bind[1].buffer_type = MYSQL_TYPE_STRING;
bind[1].buffer = (void*)target.c_str();
bind[1].buffer_length = target.length();
bind[1].is_null = false;
status = mysql_stmt_bind_param(statement, bind);
if (status!=0) {
mysql_stmt_close(statement);
return false;
}
mysql_stmt_execute(statement);
mysql_stmt_close(statement);
if (type.Equals("nick"))
nickIgnoreList.push_back(target);
else if (type.Equals("chan"))
chanIgnoreList.push_back(target);
return true;
}
return false;
}
bool RemoveIgnore(const CString& type, const CString& target) {
if (IgnoreExists(type, target)) {
MYSQL_STMT *statement = mysql_stmt_init(database);
int status = mysql_stmt_prepare(statement, "DELETE FROM `ignorelist` WHERE `type`=? AND `target`=?", 54);
if (status!=0)
return false;
MYSQL_BIND bind[2];
memset(bind, 0, sizeof(bind));
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = (void*)type.c_str();
bind[0].buffer_length = type.length();
bind[0].is_null = false;
bind[1].buffer_type = MYSQL_TYPE_STRING;
bind[1].buffer = (void*)target.c_str();
bind[1].buffer_length = target.length();
bind[1].is_null = false;
status = mysql_stmt_bind_param(statement, bind);
if (status!=0) {
mysql_stmt_close(statement);
return false;
}
mysql_stmt_execute(statement);
mysql_stmt_close(statement);
UpdateIgnoreLists();
return true;
}
return false;
}
bool IgnoreExists(const CString& type, const CString& target) {
if (type.Equals("nick")) {
for (vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
if (target.Equals(*it))
return true;
}
} else if (type.Equals("chan")) {
for (vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
if (target.Equals(*it))
return true;
}
}
return false;
}
bool IsIgnored(const CString& type, const CString& target) {
if (type.Equals("nick")) {
for (vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
if (target.WildCmp(*it))
return true;
}
} else if (type.Equals("chan")) {
for (vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
if (target.WildCmp(*it))
return true;
}
}
return false;
}
//Server stuff
virtual void OnIRCDisconnected() { virtual void OnIRCDisconnected() {
if (connected) { if (connected) {
connected = false; connected = false;
@ -955,6 +1226,9 @@ private:
bool replayAll; bool replayAll;
unsigned long logLimit; unsigned long logLimit;
int logLevel; int logLevel;
vector<CString> nickIgnoreList;
vector<CString> chanIgnoreList;
}; };
template<> void TModInfo<CLogMySQL>(CModInfo& Info) { template<> void TModInfo<CLogMySQL>(CModInfo& Info) {

View File

@ -33,6 +33,9 @@ public:
AddCommand("ReplayAll", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::ReplayAllCommand), "[1|0]", "Replay all messages stored."); AddCommand("ReplayAll", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::ReplayAllCommand), "[1|0]", "Replay all messages stored.");
AddCommand("LogLimit", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::LogLimitCommand), "[0-9]+", "Limit the amount of items to store into the log."); AddCommand("LogLimit", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::LogLimitCommand), "[0-9]+", "Limit the amount of items to store into the log.");
AddCommand("LogLevel", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::LogLevelCommand), "[0-4]", "Log level."); AddCommand("LogLevel", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::LogLevelCommand), "[0-4]", "Log level.");
AddCommand("AddIgnore", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::AddIgnoreCommand), "Type[nick|chan] Target", "Add to ignore list.");
AddCommand("RemoveIgnore", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::RemoveIgnoreCommand), "Type[nick|chan] Target", "Remove from ignore list.");
AddCommand("IgnoreList", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::IgnoreListCommand), "", "View what is currently ignored.");
} }
void ReplayCommand(const CString &sLine) { void ReplayCommand(const CString &sLine) {
@ -109,41 +112,157 @@ public:
PutModule("LogLevel is "+now+"set to: "+setting); PutModule("LogLevel is "+now+"set to: "+setting);
} }
void AddIgnoreCommand(const CString &sLine) {
CString type = sLine.Token(1);
CString target = sLine.Token(2);
bool help = sLine.Equals("HELP");
if (help) {
PutModule("Inorder to add an ignore, you must choose what type of ignore it is which can ether be a nick or a chan.");
PutModule("Nicks are matched with wildcards against the full mask.");
PutModule("Channels are matched by #channel which can contain wildcards.");
} else if (!type.empty() && !target.empty()) {
if (type.Equals("nick"))
type = "nick";
else if (type.Equals("chan") || type.Equals("channel"))
type = "chan";
else
type = "";
if (type.empty()) {
PutModule("Unknown type. If you need help, type \"AddIgnore help\".");
return;
}
if (AddIgnore(type, target))
PutModule("Successfully added \""+target+"\" to the ignore list.");
else
PutModule("Failed, maybe it already existed?");
} else {
PutModule("If you need help, type \"AddIgnore help\".");
}
}
void RemoveIgnoreCommand(const CString &sLine) {
CString type = sLine.Token(1);
CString target = sLine.Token(2);
bool help = sLine.Equals("HELP");
if (help) {
PutModule("Inorder to remove an ignore, you must specify the type and the exact pattren used to add it. If you need to find what currently exists, type \"IgnoreList\".");
} else if (!type.empty() && !target.empty()) {
if (type.Equals("nick"))
type = "nick";
else if (type.Equals("chan") || type.Equals("channel"))
type = "chan";
else
type = "";
if (type.empty()) {
PutModule("Unknown type. If you need help, type \"RemoveIgnore help\".");
return;
}
if (RemoveIgnore(type, target))
PutModule("Successfully removed \""+target+"\" from the ignore list.");
else
PutModule("Failed, maybe it does not exist?");
} else {
PutModule("If you need help, type \"RemoveIgnore help\".");
}
}
void IgnoreListCommand(const CString &sLine) {
if (nickIgnoreList.size()==0) {
PutModule("The nick ignore list is currently empty.");
} else {
PutModule("Nick ignore list contains:");
for (vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
PutModule(*it);
}
}
PutModule("---");
if (chanIgnoreList.size()==0) {
PutModule("The channel ignore list is currently empty.");
} else {
PutModule("Channel ignore list contains:");
for (vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
PutModule(*it);
}
}
}
virtual bool OnLoad(const CString& sArgs, CString& sMessage) { virtual bool OnLoad(const CString& sArgs, CString& sMessage) {
connected = true; connected = true;
CString savePath = GetSavePath(); CString savePath = GetSavePath();
savePath += "/log.sqlite"; savePath += "/log.sqlite";
bool found = false;
FILE *fp = fopen(savePath.c_str(), "rb");
if (fp!=NULL) {
found = true;
fclose(fp);
}
sqlite3_open(savePath.c_str(), &database); sqlite3_open(savePath.c_str(), &database);
if (!found) { sqlite3_stmt *result;
sqlite3_stmt *result; int status = sqlite3_prepare(database, "SELECT `name` FROM `sqlite_master` WHERE `name`='settings'", -1, &result, NULL);
int status = sqlite3_prepare(database, "CREATE TABLE `settings` (`name` text, `value` text)", -1, &result, NULL); if (status==SQLITE_OK) {
if (status==SQLITE_OK) { status = SQLITE_BUSY;
sqlite3_step(result); while (status==SQLITE_BUSY) {
sqlite3_finalize(result); status = sqlite3_step(result);
} }
status = sqlite3_prepare(database, "CREATE TABLE `messages` (`target` text, `nick` text, `type` text, `message` text, `time` real(20,5))", -1, &result, NULL); sqlite3_finalize(result);
if (status==SQLITE_OK) { if (status!=SQLITE_ROW) {
sqlite3_step(result); status = sqlite3_prepare(database, "CREATE TABLE `settings` (`name` text, `value` text)", -1, &result, NULL);
sqlite3_finalize(result); if (status==SQLITE_OK) {
sqlite3_step(result);
sqlite3_finalize(result);
SetSetting("replayAll","0");
SetSetting("logLimit","1");
SetSetting("logLevel","1");
SetSetting("version","1");
}
}
}
status = sqlite3_prepare(database, "SELECT `name` FROM `sqlite_master` WHERE `name`='messages'", -1, &result, NULL);
if (status==SQLITE_OK) {
status = SQLITE_BUSY;
while (status==SQLITE_BUSY) {
status = sqlite3_step(result);
}
sqlite3_finalize(result);
if (status!=SQLITE_ROW) {
status = sqlite3_prepare(database, "CREATE TABLE `messages` (`target` text, `nick` text, `type` text, `message` text, `time` real(20,5))", -1, &result, NULL);
if (status==SQLITE_OK) {
sqlite3_step(result);
sqlite3_finalize(result);
}
}
}
status = sqlite3_prepare(database, "SELECT `name` FROM `sqlite_master` WHERE `name`='ignorelist'", -1, &result, NULL);
if (status==SQLITE_OK) {
status = SQLITE_BUSY;
while (status==SQLITE_BUSY) {
status = sqlite3_step(result);
}
sqlite3_finalize(result);
if (status!=SQLITE_ROW) {
status = sqlite3_prepare(database, "CREATE TABLE `ignorelist` (`type` text, `target` text)", -1, &result, NULL);
if (status==SQLITE_OK) {
sqlite3_step(result);
sqlite3_finalize(result);
}
} }
SetSetting("replayAll","0");
SetSetting("logLimit","1");
SetSetting("logLevel","1");
} }
replayAll = atoi(GetSetting("replayAll").c_str()); replayAll = atoi(GetSetting("replayAll").c_str());
logLimit = strtoul(GetSetting("logLimit").c_str(), NULL, 10); logLimit = strtoul(GetSetting("logLimit").c_str(), NULL, 10);
logLevel = atoi(GetSetting("logLevel").c_str()); logLevel = atoi(GetSetting("logLevel").c_str());
unsigned long version = strtoul(GetSetting("version").c_str(), NULL, 10);
if (version==0)
SetSetting("version","1");
UpdateIgnoreLists();
return true; return true;
} }
@ -170,6 +289,8 @@ public:
} }
void AddMessage(const CString& target, const CString& nick, const CString& type, const CString& message) { void AddMessage(const CString& target, const CString& nick, const CString& type, const CString& message) {
if (IsIgnored("nick",nick) || (target.Left(1).Equals("#") && IsIgnored("chan",target)))
return;
sqlite3_stmt *result; sqlite3_stmt *result;
int status = sqlite3_prepare(database, "INSERT INTO `messages` (`target`, `nick`, `type`, `message`, `time`) VALUES (?,?,?,?,?)", -1, &result, NULL); int status = sqlite3_prepare(database, "INSERT INTO `messages` (`target`, `nick`, `type`, `message`, `time`) VALUES (?,?,?,?,?)", -1, &result, NULL);
if (status!=SQLITE_OK) if (status!=SQLITE_OK)
@ -355,8 +476,132 @@ public:
sqlite3_finalize(result); sqlite3_finalize(result);
return stringValue; return stringValue;
} }
//Server stuff
void UpdateIgnoreLists() {
nickIgnoreList.clear();
sqlite3_stmt *result;
int status = sqlite3_prepare(database, "SELECT `target` FROM `ignorelist` WHERE `type`='nick'", -1, &result, NULL);
if (status==SQLITE_OK) {
while (true) {
status = SQLITE_BUSY;
while (status==SQLITE_BUSY) {
status = sqlite3_step(result);
}
if (status!=SQLITE_ROW)
break;
int dataCount = sqlite3_data_count(result);
if (dataCount!=1)
break;
CString ignore = CString((const char *)sqlite3_column_text(result, 0));
nickIgnoreList.push_back(ignore);
}
sqlite3_finalize(result);
}
chanIgnoreList.clear();
status = sqlite3_prepare(database, "SELECT `target` FROM `ignorelist` WHERE `type`='chan'", -1, &result, NULL);
if (status==SQLITE_OK) {
while (true) {
status = SQLITE_BUSY;
while (status==SQLITE_BUSY) {
status = sqlite3_step(result);
}
if (status!=SQLITE_ROW)
break;
int dataCount = sqlite3_data_count(result);
if (dataCount!=1)
break;
CString ignore = CString((const char *)sqlite3_column_text(result, 0));
chanIgnoreList.push_back(ignore);
}
sqlite3_finalize(result);
}
}
bool AddIgnore(const CString& type, const CString& target) {
if (!IgnoreExists(type, target)) {
sqlite3_stmt *result;
int status = sqlite3_prepare(database, "INSERT INTO `ignorelist` (`type`, `target`) VALUES (?,?)", -1, &result, NULL);
if (status!=SQLITE_OK)
return false;
status = sqlite3_bind_text(result, 1, type.c_str(), type.length(), SQLITE_STATIC);
if (status!=SQLITE_OK) {
sqlite3_finalize(result);
return false;
}
status = sqlite3_bind_text(result, 2, target.c_str(), target.length(), SQLITE_STATIC);
if (status!=SQLITE_OK) {
sqlite3_finalize(result);
return false;
}
sqlite3_step(result);
sqlite3_finalize(result);
if (type.Equals("nick"))
nickIgnoreList.push_back(target);
else if (type.Equals("chan"))
chanIgnoreList.push_back(target);
return true;
}
return false;
}
bool RemoveIgnore(const CString& type, const CString& target) {
if (IgnoreExists(type, target)) {
sqlite3_stmt *result;
int status = sqlite3_prepare(database, "DELETE FROM `ignorelist` WHERE `type`=? AND `target`=?", -1, &result, NULL);
if (status!=SQLITE_OK)
return false;
status = sqlite3_bind_text(result, 1, type.c_str(), type.length(), SQLITE_STATIC);
if (status!=SQLITE_OK) {
sqlite3_finalize(result);
return false;
}
status = sqlite3_bind_text(result, 2, target.c_str(), target.length(), SQLITE_STATIC);
if (status!=SQLITE_OK) {
sqlite3_finalize(result);
return false;
}
sqlite3_step(result);
sqlite3_finalize(result);
UpdateIgnoreLists();
return true;
}
return false;
}
bool IgnoreExists(const CString& type, const CString& target) {
if (type.Equals("nick")) {
for (vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
if (target.Equals(*it))
return true;
}
} else if (type.Equals("chan")) {
for (vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
if (target.Equals(*it))
return true;
}
}
return false;
}
bool IsIgnored(const CString& type, const CString& target) {
if (type.Equals("nick")) {
for (vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
if (target.WildCmp(*it))
return true;
}
} else if (type.Equals("chan")) {
for (vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
if (target.WildCmp(*it))
return true;
}
}
return false;
}
//Server stuff
virtual void OnIRCDisconnected() { virtual void OnIRCDisconnected() {
if (connected) { if (connected) {
connected = false; connected = false;
@ -647,10 +892,13 @@ private:
bool replayAll; bool replayAll;
unsigned long logLimit; unsigned long logLimit;
int logLevel; int logLevel;
vector<CString> nickIgnoreList;
vector<CString> chanIgnoreList;
}; };
template<> void TModInfo<CLogSQLite>(CModInfo& Info) { template<> void TModInfo<CLogSQLite>(CModInfo& Info) {
Info.SetWikiPage("logsqlite"); Info.SetWikiPage("logsqlite");
} }
NETWORKMODULEDEFS(CLogSQLite, "Add logging to SQLite") NETWORKMODULEDEFS(CLogSQLite, "Add logging to SQLite")