// Copyright (c) Hercules Dev Team & hemagx, licensed under GNU GPL. // See the LICENSE file #include #include #include #include "../common/HPMi.h" #include "../common/mmo.h" #include "../common/malloc.h" #include "../common/strlib.h" #include "../map/atcommand.h" #include "../map/pc.h" #include "../map/clif.h" #include "../../3rdparty/pcre/include/pcre.h" HPExport struct hplugin_info pinfo = { "PCRE Chat Filter", SERVER_TYPE_MAP, "0.1", HPM_VERSION, }; struct manner_pcre { pcre *regex; pcre_extra *extra; }; struct manner_pcre *mannerlist = NULL; unsigned int mannersize = 0; unsigned int bypass_chat_filter = UINT_MAX - 1; bool filter_chat(bool retVal, struct map_session_data *sd, int *format, char **name_, size_t *namelen_, char **message_, size_t *messagelen_) { char *message = *message_; unsigned int i; if( !retVal || !message ) return false; if( !mannersize || pc_has_permission(sd, bypass_chat_filter) ) return true; for(i = 0; i < mannersize; i++) { if(pcre_exec(mannerlist[i].regex, mannerlist[i].extra, message, (int)strlen(message), 0, 0, NULL, 0) != PCRE_ERROR_NOMATCH) { char output[254]; sprintf(output, "Chat Filter: Yeah, uh, I don't think so, buddy..."); clif->colormes(sd->fd, COLOR_RED, output); return false; } } return true; } bool read_manner(const char* confpath) { FILE* fp; char line[1024], param[1024]; const char *error = NULL; int offset; pcre *regex = NULL; pcre_extra *extra = NULL; fp = fopen(confpath, "r"); if (fp == NULL) { ShowError("File not found: '%s'.\n", confpath); return false; } while(fgets(line, sizeof(line), fp)) { if((line[0] == '/' && line[1] == '/') || ( line[0] == '\0' || line[0] == '\n' || line[0] == '\r')) continue; if (sscanf(line, "%1023s", param) != 1) continue; regex = pcre_compile(param, 0, &error, &offset, NULL); if ( regex == NULL ) { ShowError("Could not compile regex '%s'. Error: '%s'.\n", param, error); continue; } extra = pcre_study(regex, 0, &error); if (error != NULL) { ShowError("Could not optimize '%s' Error: '%s'.\n", param, error); continue; } //ShowDebug("Loaded '%s'\n", param); RECREATE(mannerlist, struct manner_pcre, mannersize + 1); mannerlist[mannersize].regex = regex; mannerlist[mannersize].extra = extra; mannersize++; } ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", mannersize, confpath); return true; } void clean_manner(void) { unsigned int i; for (i = 0; i < mannersize; i++) { pcre_free(mannerlist[i].regex); if (mannerlist[i].extra) pcre_free(mannerlist[i].extra); } aFree(mannerlist); mannerlist = NULL; mannersize = 0; } ACMD(reloadmanner) { clean_manner(); read_manner("conf/plugin/manner.txt"); return true; } HPExport void plugin_init(void) { clif = GET_SYMBOL("clif"); pc = GET_SYMBOL("pc"); iMalloc = GET_SYMBOL("iMalloc"); strlib = GET_SYMBOL("strlib"); script = GET_SYMBOL("script"); status = GET_SYMBOL("status"); addGroupPermission("bypass_chat_filter", bypass_chat_filter); addHookPost("clif->process_message", filter_chat); addAtcommand("reloadmanner", reloadmanner); read_manner("conf/plugin/manner.txt"); } HPExport void plugin_final(void) { clean_manner(); }