llmutelist.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:21k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llmutelist.cpp
  3.  * @author Richard Nelson, James Cook
  4.  * @brief Management of list of muted players
  5.  *
  6.  * $LicenseInfo:firstyear=2003&license=viewergpl$
  7.  * 
  8.  * Copyright (c) 2003-2010, Linden Research, Inc.
  9.  * 
  10.  * Second Life Viewer Source Code
  11.  * The source code in this file ("Source Code") is provided by Linden Lab
  12.  * to you under the terms of the GNU General Public License, version 2.0
  13.  * ("GPL"), unless you have obtained a separate licensing agreement
  14.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  15.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17.  * 
  18.  * There are special exceptions to the terms and conditions of the GPL as
  19.  * it is applied to this Source Code. View the full text of the exception
  20.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  21.  * online at
  22.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23.  * 
  24.  * By copying, modifying or distributing this software, you acknowledge
  25.  * that you have read and understood your obligations described above,
  26.  * and agree to abide by those obligations.
  27.  * 
  28.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30.  * COMPLETENESS OR PERFORMANCE.
  31.  * $/LicenseInfo$
  32.  */
  33. /*
  34.  * How should muting work?
  35.  * Mute an avatar
  36.  * Mute a specific object (accidentally spamming)
  37.  *
  38.  * right-click avatar, mute
  39.  * see list of recent chatters, mute
  40.  * type a name to mute?
  41.  *
  42.  * show in list whether chatter is avatar or object
  43.  *
  44.  * need fast lookup by id
  45.  * need lookup by name, doesn't have to be fast
  46.  */
  47. #include "llviewerprecompiledheaders.h"
  48. #include "llmutelist.h"
  49. #include <boost/tokenizer.hpp>
  50. #include "lldispatcher.h"
  51. #include "llxfermanager.h"
  52. #include "llagent.h"
  53. #include "llviewergenericmessage.h" // for gGenericDispatcher
  54. #include "llworld.h" //for particle system banning
  55. #include "llimview.h"
  56. #include "llnotifications.h"
  57. #include "llviewerobjectlist.h"
  58. #include "lltrans.h"
  59. namespace 
  60. {
  61. // This method is used to return an object to mute given an object id.
  62. // Its used by the LLMute constructor and LLMuteList::isMuted.
  63. LLViewerObject* get_object_to_mute_from_id(LLUUID object_id)
  64. {
  65. LLViewerObject *objectp = gObjectList.findObject(object_id);
  66. if ((objectp) && (!objectp->isAvatar()))
  67. {
  68. LLViewerObject *parentp = (LLViewerObject *)objectp->getParent();
  69. if (parentp && parentp->getID() != gAgent.getID())
  70. {
  71. objectp = parentp;
  72. }
  73. }
  74. return objectp;
  75. }
  76. }
  77. // "emptymutelist"
  78. class LLDispatchEmptyMuteList : public LLDispatchHandler
  79. {
  80. public:
  81. virtual bool operator()(
  82. const LLDispatcher* dispatcher,
  83. const std::string& key,
  84. const LLUUID& invoice,
  85. const sparam_t& strings)
  86. {
  87. LLMuteList::getInstance()->setLoaded();
  88. return true;
  89. }
  90. };
  91. static LLDispatchEmptyMuteList sDispatchEmptyMuteList;
  92. //-----------------------------------------------------------------------------
  93. // LLMute()
  94. //-----------------------------------------------------------------------------
  95. LLMute::LLMute(const LLUUID& id, const std::string& name, EType type, U32 flags)
  96.   : mID(id),
  97. mName(name),
  98. mType(type),
  99. mFlags(flags)
  100. {
  101. // muting is done by root objects only - try to find this objects root
  102. LLViewerObject* mute_object = get_object_to_mute_from_id(id);
  103. if(mute_object && mute_object->getID() != id)
  104. {
  105. mID = mute_object->getID();
  106. LLNameValue* firstname = mute_object->getNVPair("FirstName");
  107. LLNameValue* lastname = mute_object->getNVPair("LastName");
  108. if (firstname && lastname)
  109. {
  110. mName.assign( firstname->getString() );
  111. mName.append(" ");
  112. mName.append( lastname->getString() );
  113. }
  114. mType = mute_object->isAvatar() ? AGENT : OBJECT;
  115. }
  116. }
  117. std::string LLMute::getDisplayName() const
  118. {
  119. std::string name_with_suffix = mName;
  120. switch (mType)
  121. {
  122. case BY_NAME:
  123. default:
  124. name_with_suffix += " " + LLTrans::getString("MuteByName");
  125. break;
  126. case AGENT:
  127. name_with_suffix += " " + LLTrans::getString("MuteAgent");
  128. break;
  129. case OBJECT:
  130. name_with_suffix += " " + LLTrans::getString("MuteObject");
  131. break;
  132. case GROUP:
  133. name_with_suffix += " " + LLTrans::getString("MuteGroup");
  134. break;
  135. }
  136. return name_with_suffix;
  137. }
  138. void LLMute::setFromDisplayName(const std::string& display_name)
  139. {
  140. size_t pos = 0;
  141. mName = display_name;
  142. pos = mName.rfind(" " + LLTrans::getString("MuteGroup"));
  143. if (pos != std::string::npos)
  144. {
  145. mName.erase(pos);
  146. mType = GROUP;
  147. return;
  148. }
  149. pos = mName.rfind(" " + LLTrans::getString("MuteObject"));
  150. if (pos != std::string::npos)
  151. {
  152. mName.erase(pos);
  153. mType = OBJECT;
  154. return;
  155. }
  156. pos = mName.rfind(" " + LLTrans::getString("MuteAgent"));
  157. if (pos != std::string::npos)
  158. {
  159. mName.erase(pos);
  160. mType = AGENT;
  161. return;
  162. }
  163. pos = mName.rfind(" " + LLTrans::getString("MuteByName"));
  164. if (pos != std::string::npos)
  165. {
  166. mName.erase(pos);
  167. mType = BY_NAME;
  168. return;
  169. }
  170. llwarns << "Unable to set mute from display name " << display_name << llendl;
  171. return;
  172. }
  173. /* static */
  174. LLMuteList* LLMuteList::getInstance()
  175. {
  176. // Register callbacks at the first time that we find that the message system has been created.
  177. static BOOL registered = FALSE;
  178. if( !registered && gMessageSystem != NULL)
  179. {
  180. registered = TRUE;
  181. // Register our various callbacks
  182. gMessageSystem->setHandlerFuncFast(_PREHASH_MuteListUpdate, processMuteListUpdate);
  183. gMessageSystem->setHandlerFuncFast(_PREHASH_UseCachedMuteList, processUseCachedMuteList);
  184. }
  185. return LLSingleton<LLMuteList>::getInstance(); // Call the "base" implementation.
  186. }
  187. //-----------------------------------------------------------------------------
  188. // LLMuteList()
  189. //-----------------------------------------------------------------------------
  190. LLMuteList::LLMuteList() :
  191. mIsLoaded(FALSE)
  192. {
  193. gGenericDispatcher.addHandler("emptymutelist", &sDispatchEmptyMuteList);
  194. }
  195. //-----------------------------------------------------------------------------
  196. // ~LLMuteList()
  197. //-----------------------------------------------------------------------------
  198. LLMuteList::~LLMuteList()
  199. {
  200. }
  201. BOOL LLMuteList::isLinden(const std::string& name) const
  202. {
  203. typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
  204. boost::char_separator<char> sep(" ");
  205. tokenizer tokens(name, sep);
  206. tokenizer::iterator token_iter = tokens.begin();
  207. if (token_iter == tokens.end()) return FALSE;
  208. token_iter++;
  209. if (token_iter == tokens.end()) return FALSE;
  210. std::string last_name = *token_iter;
  211. return last_name == "Linden";
  212. }
  213. BOOL LLMuteList::add(const LLMute& mute, U32 flags)
  214. {
  215. // Can't mute text from Lindens
  216. if ((mute.mType == LLMute::AGENT)
  217. && isLinden(mute.mName) && (flags & LLMute::flagTextChat || flags == 0))
  218. {
  219. LLNotifications::instance().add("MuteLinden", LLSD(), LLSD());
  220. return FALSE;
  221. }
  222. // Can't mute self.
  223. if (mute.mType == LLMute::AGENT
  224. && mute.mID == gAgent.getID())
  225. {
  226. return FALSE;
  227. }
  228. if (mute.mType == LLMute::BY_NAME)
  229. {
  230. // Can't mute empty string by name
  231. if (mute.mName.empty()) 
  232. {
  233. llwarns << "Trying to mute empty string by-name" << llendl;
  234. return FALSE;
  235. }
  236. // Null mutes must have uuid null
  237. if (mute.mID.notNull())
  238. {
  239. llwarns << "Trying to add by-name mute with non-null id" << llendl;
  240. return FALSE;
  241. }
  242. std::pair<string_set_t::iterator, bool> result = mLegacyMutes.insert(mute.mName);
  243. if (result.second)
  244. {
  245. llinfos << "Muting by name " << mute.mName << llendl;
  246. updateAdd(mute);
  247. notifyObservers();
  248. return TRUE;
  249. }
  250. else
  251. {
  252. // was duplicate
  253. return FALSE;
  254. }
  255. }
  256. else
  257. {
  258. // Need a local (non-const) copy to set up flags properly.
  259. LLMute localmute = mute;
  260. // If an entry for the same entity is already in the list, remove it, saving flags as necessary.
  261. mute_set_t::iterator it = mMutes.find(localmute);
  262. if (it != mMutes.end())
  263. {
  264. // This mute is already in the list.  Save the existing entry's flags if that's warranted.
  265. localmute.mFlags = it->mFlags;
  266. mMutes.erase(it);
  267. // Don't need to call notifyObservers() here, since it will happen after the entry has been re-added below.
  268. }
  269. else
  270. {
  271. // There was no entry in the list previously.  Fake things up by making it look like the previous entry had all properties unmuted.
  272. localmute.mFlags = LLMute::flagAll;
  273. }
  274. if(flags)
  275. {
  276. // The user passed some combination of flags.  Make sure those flag bits are turned off (i.e. those properties will be muted).
  277. localmute.mFlags &= (~flags);
  278. }
  279. else
  280. {
  281. // The user passed 0.  Make sure all flag bits are turned off (i.e. all properties will be muted).
  282. localmute.mFlags = 0;
  283. }
  284. // (re)add the mute entry.
  285. {
  286. std::pair<mute_set_t::iterator, bool> result = mMutes.insert(localmute);
  287. if (result.second)
  288. {
  289. llinfos << "Muting " << localmute.mName << " id " << localmute.mID << " flags " << localmute.mFlags << llendl;
  290. updateAdd(localmute);
  291. notifyObservers();
  292. if(!(localmute.mFlags & LLMute::flagParticles))
  293. {
  294. //Kill all particle systems owned by muted task
  295. if(localmute.mType == LLMute::AGENT || localmute.mType == LLMute::OBJECT)
  296. {
  297. LLViewerPartSim::getInstance()->clearParticlesByOwnerID(localmute.mID);
  298. }
  299. }
  300. return TRUE;
  301. }
  302. }
  303. }
  304. // If we were going to return success, we'd have done it by now.
  305. return FALSE;
  306. }
  307. void LLMuteList::updateAdd(const LLMute& mute)
  308. {
  309. // Update the database
  310. LLMessageSystem* msg = gMessageSystem;
  311. msg->newMessageFast(_PREHASH_UpdateMuteListEntry);
  312. msg->nextBlockFast(_PREHASH_AgentData);
  313. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  314. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  315. msg->nextBlockFast(_PREHASH_MuteData);
  316. msg->addUUIDFast(_PREHASH_MuteID, mute.mID);
  317. msg->addStringFast(_PREHASH_MuteName, mute.mName);
  318. msg->addS32("MuteType", mute.mType);
  319. msg->addU32("MuteFlags", mute.mFlags);
  320. gAgent.sendReliableMessage();
  321. mIsLoaded = TRUE; // why is this here? -MG
  322. }
  323. BOOL LLMuteList::remove(const LLMute& mute, U32 flags)
  324. {
  325. BOOL found = FALSE;
  326. // First, remove from main list.
  327. mute_set_t::iterator it = mMutes.find(mute);
  328. if (it != mMutes.end())
  329. {
  330. LLMute localmute = *it;
  331. bool remove = true;
  332. if(flags)
  333. {
  334. // If the user passed mute flags, we may only want to turn some flags on.
  335. localmute.mFlags |= flags;
  336. if(localmute.mFlags == LLMute::flagAll)
  337. {
  338. // Every currently available mute property has been masked out.
  339. // Remove the mute entry entirely.
  340. }
  341. else
  342. {
  343. // Only some of the properties are masked out.  Update the entry.
  344. remove = false;
  345. }
  346. }
  347. else
  348. {
  349. // The caller didn't pass any flags -- just remove the mute entry entirely.
  350. }
  351. // Always remove the entry from the set -- it will be re-added with new flags if necessary.
  352. mMutes.erase(it);
  353. if(remove)
  354. {
  355. // The entry was actually removed.  Notify the server.
  356. updateRemove(localmute);
  357. llinfos << "Unmuting " << localmute.mName << " id " << localmute.mID << " flags " << localmute.mFlags << llendl;
  358. }
  359. else
  360. {
  361. // Flags were updated, the mute entry needs to be retransmitted to the server and re-added to the list.
  362. mMutes.insert(localmute);
  363. updateAdd(localmute);
  364. llinfos << "Updating mute entry " << localmute.mName << " id " << localmute.mID << " flags " << localmute.mFlags << llendl;
  365. }
  366. // Must be after erase.
  367. setLoaded();  // why is this here? -MG
  368. }
  369. // Clean up any legacy mutes
  370. string_set_t::iterator legacy_it = mLegacyMutes.find(mute.mName);
  371. if (legacy_it != mLegacyMutes.end())
  372. {
  373. // Database representation of legacy mute is UUID null.
  374. LLMute mute(LLUUID::null, *legacy_it, LLMute::BY_NAME);
  375. updateRemove(mute);
  376. mLegacyMutes.erase(legacy_it);
  377. // Must be after erase.
  378. setLoaded(); // why is this here? -MG
  379. }
  380. return found;
  381. }
  382. void LLMuteList::updateRemove(const LLMute& mute)
  383. {
  384. LLMessageSystem* msg = gMessageSystem;
  385. msg->newMessageFast(_PREHASH_RemoveMuteListEntry);
  386. msg->nextBlockFast(_PREHASH_AgentData);
  387. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  388. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  389. msg->nextBlockFast(_PREHASH_MuteData);
  390. msg->addUUIDFast(_PREHASH_MuteID, mute.mID);
  391. msg->addString("MuteName", mute.mName);
  392. gAgent.sendReliableMessage();
  393. }
  394. void notify_automute_callback(const LLUUID& agent_id, const std::string& first_name, const std::string& last_name, BOOL is_group, LLMuteList::EAutoReason reason)
  395. {
  396. std::string notif_name;
  397. switch (reason)
  398. {
  399. default:
  400. case LLMuteList::AR_IM:
  401. notif_name = "AutoUnmuteByIM";
  402. break;
  403. case LLMuteList::AR_INVENTORY:
  404. notif_name = "AutoUnmuteByInventory";
  405. break;
  406. case LLMuteList::AR_MONEY:
  407. notif_name = "AutoUnmuteByMoney";
  408. break;
  409. }
  410. LLSD args;
  411. args["FIRST"] = first_name;
  412. args["LAST"] = last_name;
  413.     
  414. LLNotificationPtr notif_ptr = LLNotifications::instance().add(notif_name, args, LLSD());
  415. if (notif_ptr)
  416. {
  417. std::string message = notif_ptr->getMessage();
  418. if (reason == LLMuteList::AR_IM)
  419. {
  420. LLIMModel::getInstance()->addMessage(agent_id, SYSTEM_FROM, LLUUID::null, message);
  421. }
  422. }
  423. }
  424. BOOL LLMuteList::autoRemove(const LLUUID& agent_id, const EAutoReason reason, const std::string& first_name, const std::string& last_name)
  425. {
  426. BOOL removed = FALSE;
  427. if (isMuted(agent_id))
  428. {
  429. LLMute automute(agent_id, LLStringUtil::null, LLMute::AGENT);
  430. removed = TRUE;
  431. remove(automute);
  432. if (first_name.empty() && last_name.empty())
  433. {
  434. std::string cache_first, cache_last;
  435. if (gCacheName->getName(agent_id, cache_first, cache_last))
  436. {
  437. // name in cache, call callback directly
  438. notify_automute_callback(agent_id, cache_first, cache_last, FALSE, reason);
  439. }
  440. else
  441. {
  442. // not in cache, lookup name from cache
  443. gCacheName->get(agent_id, FALSE, boost::bind(&notify_automute_callback, _1, _2, _3, _4, reason));
  444. }
  445. }
  446. else
  447. {
  448. // call callback directly
  449. notify_automute_callback(agent_id, first_name, last_name, FALSE, reason);
  450. }
  451. }
  452. return removed;
  453. }
  454. std::vector<LLMute> LLMuteList::getMutes() const
  455. {
  456. std::vector<LLMute> mutes;
  457. for (mute_set_t::const_iterator it = mMutes.begin();
  458.  it != mMutes.end();
  459.  ++it)
  460. {
  461. mutes.push_back(*it);
  462. }
  463. for (string_set_t::const_iterator it = mLegacyMutes.begin();
  464.  it != mLegacyMutes.end();
  465.  ++it)
  466. {
  467. LLMute legacy(LLUUID::null, *it);
  468. mutes.push_back(legacy);
  469. }
  470. std::sort(mutes.begin(), mutes.end(), compare_by_name());
  471. return mutes;
  472. }
  473. //-----------------------------------------------------------------------------
  474. // loadFromFile()
  475. //-----------------------------------------------------------------------------
  476. BOOL LLMuteList::loadFromFile(const std::string& filename)
  477. {
  478. if(!filename.size())
  479. {
  480. llwarns << "Mute List Filename is Empty!" << llendl;
  481. return FALSE;
  482. }
  483. LLFILE* fp = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
  484. if (!fp)
  485. {
  486. llwarns << "Couldn't open mute list " << filename << llendl;
  487. return FALSE;
  488. }
  489. // *NOTE: Changing the size of these buffers will require changes
  490. // in the scanf below.
  491. char id_buffer[MAX_STRING]; /*Flawfinder: ignore*/
  492. char name_buffer[MAX_STRING]; /*Flawfinder: ignore*/
  493. char buffer[MAX_STRING]; /*Flawfinder: ignore*/
  494. while (!feof(fp) 
  495.    && fgets(buffer, MAX_STRING, fp))
  496. {
  497. id_buffer[0] = '';
  498. name_buffer[0] = '';
  499. S32 type = 0;
  500. U32 flags = 0;
  501. sscanf( /* Flawfinder: ignore */
  502. buffer, " %d %254s %254[^|]| %un", &type, id_buffer, name_buffer,
  503. &flags);
  504. LLUUID id = LLUUID(id_buffer);
  505. LLMute mute(id, std::string(name_buffer), (LLMute::EType)type, flags);
  506. if (mute.mID.isNull()
  507. || mute.mType == LLMute::BY_NAME)
  508. {
  509. mLegacyMutes.insert(mute.mName);
  510. }
  511. else
  512. {
  513. mMutes.insert(mute);
  514. }
  515. }
  516. fclose(fp);
  517. setLoaded();
  518. return TRUE;
  519. }
  520. //-----------------------------------------------------------------------------
  521. // saveToFile()
  522. //-----------------------------------------------------------------------------
  523. BOOL LLMuteList::saveToFile(const std::string& filename)
  524. {
  525. if(!filename.size())
  526. {
  527. llwarns << "Mute List Filename is Empty!" << llendl;
  528. return FALSE;
  529. }
  530. LLFILE* fp = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/
  531. if (!fp)
  532. {
  533. llwarns << "Couldn't open mute list " << filename << llendl;
  534. return FALSE;
  535. }
  536. // legacy mutes have null uuid
  537. std::string id_string;
  538. LLUUID::null.toString(id_string);
  539. for (string_set_t::iterator it = mLegacyMutes.begin();
  540.  it != mLegacyMutes.end();
  541.  ++it)
  542. {
  543. fprintf(fp, "%d %s %s|n", (S32)LLMute::BY_NAME, id_string.c_str(), it->c_str());
  544. }
  545. for (mute_set_t::iterator it = mMutes.begin();
  546.  it != mMutes.end();
  547.  ++it)
  548. {
  549. it->mID.toString(id_string);
  550. const std::string& name = it->mName;
  551. fprintf(fp, "%d %s %s|%un", (S32)it->mType, id_string.c_str(), name.c_str(), it->mFlags);
  552. }
  553. fclose(fp);
  554. return TRUE;
  555. }
  556. BOOL LLMuteList::isMuted(const LLUUID& id, const std::string& name, U32 flags) const
  557. {
  558. // for objects, check for muting on their parent prim
  559. LLViewerObject* mute_object = get_object_to_mute_from_id(id);
  560. LLUUID id_to_check  = (mute_object) ? mute_object->getID() : id;
  561. // don't need name or type for lookup
  562. LLMute mute(id_to_check);
  563. mute_set_t::const_iterator mute_it = mMutes.find(mute);
  564. if (mute_it != mMutes.end())
  565. {
  566. // If any of the flags the caller passed are set, this item isn't considered muted for this caller.
  567. if(flags & mute_it->mFlags)
  568. {
  569. return FALSE;
  570. }
  571. return TRUE;
  572. }
  573. // empty names can't be legacy-muted
  574. if (name.empty()) return FALSE;
  575. // Look in legacy pile
  576. string_set_t::const_iterator legacy_it = mLegacyMutes.find(name);
  577. return legacy_it != mLegacyMutes.end();
  578. }
  579. //-----------------------------------------------------------------------------
  580. // requestFromServer()
  581. //-----------------------------------------------------------------------------
  582. void LLMuteList::requestFromServer(const LLUUID& agent_id)
  583. {
  584. std::string agent_id_string;
  585. std::string filename;
  586. agent_id.toString(agent_id_string);
  587. filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string) + ".cached_mute";
  588. LLCRC crc;
  589. crc.update(filename);
  590. LLMessageSystem* msg = gMessageSystem;
  591. msg->newMessageFast(_PREHASH_MuteListRequest);
  592. msg->nextBlockFast(_PREHASH_AgentData);
  593. msg->addUUIDFast(_PREHASH_AgentID, agent_id);
  594. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  595. msg->nextBlockFast(_PREHASH_MuteData);
  596. msg->addU32Fast(_PREHASH_MuteCRC, crc.getCRC());
  597. gAgent.sendReliableMessage();
  598. }
  599. //-----------------------------------------------------------------------------
  600. // cache()
  601. //-----------------------------------------------------------------------------
  602. void LLMuteList::cache(const LLUUID& agent_id)
  603. {
  604. // Write to disk even if empty.
  605. if(mIsLoaded)
  606. {
  607. std::string agent_id_string;
  608. std::string filename;
  609. agent_id.toString(agent_id_string);
  610. filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string) + ".cached_mute";
  611. saveToFile(filename);
  612. }
  613. }
  614. //-----------------------------------------------------------------------------
  615. // Static message handlers
  616. //-----------------------------------------------------------------------------
  617. void LLMuteList::processMuteListUpdate(LLMessageSystem* msg, void**)
  618. {
  619. llinfos << "LLMuteList::processMuteListUpdate()" << llendl;
  620. LLUUID agent_id;
  621. msg->getUUIDFast(_PREHASH_MuteData, _PREHASH_AgentID, agent_id);
  622. if(agent_id != gAgent.getID())
  623. {
  624. llwarns << "Got an mute list update for the wrong agent." << llendl;
  625. return;
  626. }
  627. std::string unclean_filename;
  628. msg->getStringFast(_PREHASH_MuteData, _PREHASH_Filename, unclean_filename);
  629. std::string filename = LLDir::getScrubbedFileName(unclean_filename);
  630. std::string *local_filename_and_path = new std::string(gDirUtilp->getExpandedFilename( LL_PATH_CACHE, filename ));
  631. gXferManager->requestFile(*local_filename_and_path,
  632.   filename,
  633.   LL_PATH_CACHE,
  634.   msg->getSender(),
  635.   TRUE, // make the remote file temporary.
  636.   onFileMuteList,
  637.   (void**)local_filename_and_path,
  638.   LLXferManager::HIGH_PRIORITY);
  639. }
  640. void LLMuteList::processUseCachedMuteList(LLMessageSystem* msg, void**)
  641. {
  642. llinfos << "LLMuteList::processUseCachedMuteList()" << llendl;
  643. std::string agent_id_string;
  644. gAgent.getID().toString(agent_id_string);
  645. std::string filename;
  646. filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string) + ".cached_mute";
  647. LLMuteList::getInstance()->loadFromFile(filename);
  648. }
  649. void LLMuteList::onFileMuteList(void** user_data, S32 error_code, LLExtStat ext_status)
  650. {
  651. llinfos << "LLMuteList::processMuteListFile()" << llendl;
  652. std::string* local_filename_and_path = (std::string*)user_data;
  653. if(local_filename_and_path && !local_filename_and_path->empty() && (error_code == 0))
  654. {
  655. LLMuteList::getInstance()->loadFromFile(*local_filename_and_path);
  656. LLFile::remove(*local_filename_and_path);
  657. }
  658. delete local_filename_and_path;
  659. }
  660. void LLMuteList::addObserver(LLMuteListObserver* observer)
  661. {
  662. mObservers.insert(observer);
  663. }
  664. void LLMuteList::removeObserver(LLMuteListObserver* observer)
  665. {
  666. mObservers.erase(observer);
  667. }
  668. void LLMuteList::setLoaded()
  669. {
  670. mIsLoaded = TRUE;
  671. notifyObservers();
  672. }
  673. void LLMuteList::notifyObservers()
  674. {
  675. for (observer_set_t::iterator it = mObservers.begin();
  676. it != mObservers.end();
  677. )
  678. {
  679. LLMuteListObserver* observer = *it;
  680. observer->onChange();
  681. // In case onChange() deleted an entry.
  682. it = mObservers.upper_bound(observer);
  683. }
  684. }