#include "llviewerprecompiledheaders.h" #include "NACLantispam.h" #include "llviewercontrol.h" #include "llnotificationsutil.h" #include "llviewerobjectlist.h" #include "llagent.h" #include U32 NACLAntiSpamRegistry::globalAmount; U32 NACLAntiSpamRegistry::globalTime; bool NACLAntiSpamRegistry::bGlobalQueue; NACLAntiSpamQueue* NACLAntiSpamRegistry::queues[NACLAntiSpamRegistry::QUEUE_MAX] = {0}; std::tr1::unordered_map NACLAntiSpamRegistry::globalEntries; std::tr1::unordered_map::iterator NACLAntiSpamRegistry::it2; // NACLAntiSpamQueueEntry NACLAntiSpamQueueEntry::NACLAntiSpamQueueEntry() { entryTime=0; entryAmount=0; blocked=false; } void NACLAntiSpamQueueEntry::clearEntry() { entryTime=0; entryAmount=0; blocked=false; } U32 NACLAntiSpamQueueEntry::getEntryAmount() { return entryAmount; } U32 NACLAntiSpamQueueEntry::getEntryTime() { return entryTime; } void NACLAntiSpamQueueEntry::updateEntryAmount() { entryAmount++; } void NACLAntiSpamQueueEntry::updateEntryTime() { entryTime=time(0); } void NACLAntiSpamQueueEntry::setBlocked() { blocked=true; } bool NACLAntiSpamQueueEntry::getBlocked() { return blocked; } // NACLAntiSpamQueue NACLAntiSpamQueue::NACLAntiSpamQueue(U32 time, U32 amount) { queueTime=time; queueAmount=amount; } void NACLAntiSpamQueue::setAmount(U32 amount) { queueAmount=amount; } void NACLAntiSpamQueue::setTime(U32 time) { queueTime=time; } U32 NACLAntiSpamQueue::getTime() { return queueTime; } U32 NACLAntiSpamQueue::getAmount() { return queueAmount; } void NACLAntiSpamQueue::clearEntries() { for(it = entries.begin(); it != entries.end(); it++) { //AO: Only clear entries that are not blocked. if (!it->second->getBlocked()) it->second->clearEntry(); } } void NACLAntiSpamQueue::purgeEntries() { for(it = entries.begin(); it != entries.end(); it++) { delete it->second; } entries.clear(); } void NACLAntiSpamQueue::blockEntry(LLUUID& source) { it=entries.find(source.asString()); if(it == entries.end()) { entries[source.asString()]=new NACLAntiSpamQueueEntry(); } entries[source.asString()]->setBlocked(); } int NACLAntiSpamQueue::checkEntry(LLUUID& name, U32 multiplier) // Returns 0 if unblocked, 1 if check results in a new block, 2 if by an existing block { it=entries.find(name.asString()); if(it != entries.end()) { if(it->second->getBlocked()) return 2; U32 eTime=it->second->getEntryTime(); U32 currentTime=time(0); if((currentTime-eTime) <= queueTime) { it->second->updateEntryAmount(); U32 eAmount = it->second->getEntryAmount(); if(eAmount > (queueAmount*multiplier)) { it->second->setBlocked(); return 1; } else return 0; } else { it->second->clearEntry(); it->second->updateEntryAmount(); it->second->updateEntryTime(); return 0; } } else { lldebugs << "[antispam] New queue entry:" << name.asString() << llendl; entries[name.asString()]=new NACLAntiSpamQueueEntry(); entries[name.asString()]->updateEntryAmount(); entries[name.asString()]->updateEntryTime(); return 0; } } // NACLAntiSpamRegistry static const char* QUEUE_NAME[NACLAntiSpamRegistry::QUEUE_MAX] = { "Chat", "Inventory", "Instant Message", "Calling Card", "Sound", "Sound Preload", "Script Dialog", "Teleport"}; NACLAntiSpamRegistry::NACLAntiSpamRegistry(U32 time, U32 amount) { globalTime=time; globalAmount=amount; static LLCachedControl _NACL_AntiSpamGlobalQueue(gSavedSettings,"_NACL_AntiSpamGlobalQueue"); bGlobalQueue=_NACL_AntiSpamGlobalQueue; for(int queue = 0; queue < QUEUE_MAX; ++queue) { queues[queue] = new NACLAntiSpamQueue(time,amount); } } const char* NACLAntiSpamRegistry::getQueueName(U32 queue_id) { if(queue_id >= QUEUE_MAX) return "Unknown"; return QUEUE_NAME[queue_id]; } void NACLAntiSpamRegistry::registerQueues(U32 time, U32 amount) { globalTime=time; globalAmount=amount; static LLCachedControl _NACL_AntiSpamGlobalQueue(gSavedSettings,"_NACL_AntiSpamGlobalQueue"); bGlobalQueue=_NACL_AntiSpamGlobalQueue; for(int queue = 0; queue < QUEUE_MAX; ++queue) { queues[queue] = new NACLAntiSpamQueue(time,amount); } } void NACLAntiSpamRegistry::registerQueue(U32 name, U32 time, U32 amount) { /* it=queues.find(name); if(it == queues.end()) { queues[name]=new NACLAntiSpamQueue(time,amount); } */ } void NACLAntiSpamRegistry::setRegisteredQueueTime(U32 name, U32 time) { if(name >= QUEUE_MAX || queues[name] == 0) { LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was not created or was outside of the reasonable range of queues. Queue: " << getQueueName(name) << llendl; return; } queues[name]->setTime(time); } void NACLAntiSpamRegistry::setRegisteredQueueAmount(U32 name, U32 amount) { if(name >= QUEUE_MAX || queues[name] == 0) { LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was not created or was outside of the reasonable range of queues. Queue: " << getQueueName(name) << llendl; return; } queues[name]->setAmount(amount); } void NACLAntiSpamRegistry::setAllQueueTimes(U32 time) { globalTime=time; for(int queue = 0; queue < QUEUE_MAX; ++queue) { if( queues[queue] ) queues[queue]->setTime(time); } } void NACLAntiSpamRegistry::setAllQueueAmounts(U32 amount) { globalAmount=amount; for(int queue = 0; queue < QUEUE_MAX; ++queue) { if( !queues[queue] ) continue; if(queue == QUEUE_SOUND || queue == QUEUE_SOUND_PRELOAD) queues[queue]->setAmount(amount*5); else queues[queue]->setAmount(amount); } } void NACLAntiSpamRegistry::clearRegisteredQueue(U32 name) { if(name >= QUEUE_MAX || queues[name] == 0) { LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was not created or was outside of the reasonable range of queues. Queue: " << getQueueName(name) << llendl; return; } queues[name]->clearEntries(); } void NACLAntiSpamRegistry::purgeRegisteredQueue(U32 name) { if(name >= QUEUE_MAX || queues[name] == 0) { LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was not created or was outside of the reasonable range of queues. Queue: " << getQueueName(name) << llendl; return; } queues[name]->purgeEntries(); } void NACLAntiSpamRegistry::blockOnQueue(U32 name, LLUUID& source) { if (!gSavedSettings.getBOOL("UseAntiSpam")) return; if(bGlobalQueue) { NACLAntiSpamRegistry::blockGlobalEntry(source); } else { if(name >= QUEUE_MAX || queues[name] == 0) { LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was not created or was outside of the reasonable range of queues. Queue: " << getQueueName(name) << llendl; return; } queues[name]->blockEntry(source); } } void NACLAntiSpamRegistry::blockGlobalEntry(LLUUID& source) { it2=globalEntries.find(source.asString()); if(it2 == globalEntries.end()) { globalEntries[source.asString()]=new NACLAntiSpamQueueEntry(); } globalEntries[source.asString()]->setBlocked(); } bool NACLAntiSpamRegistry::checkQueue(U32 name, LLUUID& source, U32 multiplier, bool silent) // returns TRUE if blocked, FALSE otherwise { // skip all checks if we're we've been administratively turned off if (gSavedSettings.getBOOL("UseAntiSpam") != TRUE) return false; if((source.isNull()) || (gAgent.getID() == source)) return false; LLViewerObject *obj=gObjectList.findObject(source); if(obj) if(obj->permYouOwner()) return false; int result = 0; if(bGlobalQueue) { result=NACLAntiSpamRegistry::checkGlobalEntry(source,multiplier); } else { if(name >= QUEUE_MAX || queues[name] == 0) { LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was not created or was outside of the reasonable range of queues. Queue: " << getQueueName(name) << llendl; return false; } result=queues[name]->checkEntry(source,multiplier); } if (result == 0) // safe return false; if (result == 2 ) // previously blocked { return true; } if (result == 1) // newly blocked, result == 1 { std::string msg = llformat("AntiSpam: Blocked %s for spamming a %s (%d) times in %d seconds.",source.asString().c_str(), getQueueName(name), multiplier * queues[name]->getAmount(), queues[name]->getTime()); if(silent == false) { LLSD args; args["MESSAGE"] = msg; LLNotificationsUtil::add("SystemMessageTip", args); } llinfos << "[antispam] " << msg << llendl; return true; } // fallback, should not get here return false; } // Global queue void NACLAntiSpamRegistry::setGlobalQueue(bool value) { NACLAntiSpamRegistry::purgeAllQueues(); bGlobalQueue=value; } void NACLAntiSpamRegistry::setGlobalAmount(U32 amount) { globalAmount=amount; } void NACLAntiSpamRegistry::setGlobalTime(U32 time) { globalTime=time; } void NACLAntiSpamRegistry::clearAllQueues() { if(bGlobalQueue) NACLAntiSpamRegistry::clearGlobalEntries(); else for(int queue = 0; queue < QUEUE_MAX; ++queue) { if( queues[queue] ) queues[queue]->clearEntries(); } } void NACLAntiSpamRegistry::purgeAllQueues() { if(bGlobalQueue) NACLAntiSpamRegistry::purgeGlobalEntries(); else for(int queue = 0; queue < QUEUE_MAX; ++queue) { if( queues[queue] ) queues[queue]->purgeEntries(); } llinfos << "AntiSpam Queues Purged" << llendl; } int NACLAntiSpamRegistry::checkGlobalEntry(LLUUID& name, U32 multiplier) { it2=globalEntries.find(name.asString()); if(it2 != globalEntries.end()) { if(it2->second->getBlocked()) return 2; U32 eTime=it2->second->getEntryTime(); U32 currentTime=time(0); if((currentTime-eTime) <= globalTime) { it2->second->updateEntryAmount(); U32 eAmount=it2->second->getEntryAmount(); if(eAmount > (globalAmount*multiplier)) return 1; else return 0; } else { it2->second->clearEntry(); it2->second->updateEntryAmount(); it2->second->updateEntryTime(); return 0; } } else { globalEntries[name.asString()]=new NACLAntiSpamQueueEntry(); globalEntries[name.asString()]->updateEntryAmount(); globalEntries[name.asString()]->updateEntryTime(); return 0; } } void NACLAntiSpamRegistry::clearGlobalEntries() { for(it2 = globalEntries.begin(); it2 != globalEntries.end(); it2++) { it2->second->clearEntry(); } } void NACLAntiSpamRegistry::purgeGlobalEntries() { for(it2 = globalEntries.begin(); it2 != globalEntries.end(); it2++) { delete it2->second; it2->second = 0; } globalEntries.clear(); }