llmutelist.cpp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336
  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-2009, 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. #include "llviewerprecompiledheaders.h"
  34. #include "llmutelist.h"
  35. #include "llcachename.h"
  36. #include "llcrc.h"
  37. #include "lldir.h"
  38. #include "lldispatcher.h"
  39. #include "llnotifications.h"
  40. #include "llsdserialize.h"
  41. #include "llxfermanager.h"
  42. #include "llmessage.h"
  43. #include "llagent.h"
  44. #include "llchat.h"
  45. #include "llfloaterchat.h"
  46. #include "llfloaterim.h"
  47. #include "llviewercontrol.h"
  48. #include "llviewermessage.h" // For gGenericDispatcher
  49. #include "llviewerobjectlist.h"
  50. #include "llvoavatarself.h"
  51. #include "llworld.h" // For particle system banning
  52. namespace
  53. {
  54. // This method is used to return an object to mute given an object id.
  55. // It is used by the LLMute constructor and LLMuteList::isMuted.
  56. LLViewerObject* get_object_to_mute_from_id(LLUUID object_id)
  57. {
  58. LLViewerObject* objectp = gObjectList.findObject(object_id);
  59. if (objectp && !objectp->isAvatar())
  60. {
  61. LLViewerObject* parentp = objectp->getRootEdit();
  62. if (parentp)
  63. {
  64. objectp = parentp;
  65. }
  66. }
  67. return objectp;
  68. }
  69. }
  70. // "emptymutelist"
  71. class LLDispatchEmptyMuteList final : public LLDispatchHandler
  72. {
  73. protected:
  74. LOG_CLASS(LLDispatchEmptyMuteList);
  75. public:
  76. bool operator()(const LLDispatcher* dispatcher, const std::string& key,
  77. const LLUUID& invoice, const sparam_t& strings) override
  78. {
  79. LLMuteList::setLoaded();
  80. llinfos << "Mute list dispatched." << llendl;
  81. return true;
  82. }
  83. };
  84. static LLDispatchEmptyMuteList sDispatchEmptyMuteList;
  85. const char EMPTY_NAME[] = "*[<empty name>]*";
  86. //-----------------------------------------------------------------------------
  87. // LLMute class
  88. //-----------------------------------------------------------------------------
  89. char LLMute::CHAT_SUFFIX[] = " (chat)";
  90. char LLMute::VOICE_SUFFIX[] = " (voice)";
  91. char LLMute::PARTICLES_SUFFIX[] = " (particles)";
  92. char LLMute::SOUNDS_SUFFIX[] = " (sounds)";
  93. char LLMute::BY_NAME_SUFFIX[] = " (by name)";
  94. char LLMute::AGENT_SUFFIX[] = " (resident)";
  95. char LLMute::OBJECT_SUFFIX[] = " (object)";
  96. char LLMute::GROUP_SUFFIX[] = " (group)";
  97. LLMute::LLMute(const LLUUID& id, const std::string& name, EType type,
  98. U32 flags)
  99. : mID(id),
  100. mName(name),
  101. mType(type),
  102. mFlags(flags)
  103. {
  104. if (id.isNull())
  105. {
  106. mType = BY_NAME;
  107. return;
  108. }
  109. // Muting is done on root objects only, so get the root of this object
  110. LLViewerObject* mute_object = get_object_to_mute_from_id(id);
  111. if (mute_object && mute_object->getID() != id)
  112. {
  113. mID = mute_object->getID();
  114. if (mute_object->isAvatar())
  115. {
  116. mType = AGENT;
  117. LLNameValue* firstname = mute_object->getNVPair("FirstName");
  118. LLNameValue* lastname = mute_object->getNVPair("LastName");
  119. if (firstname && lastname)
  120. {
  121. mName.assign(firstname->getString());
  122. mName.append(" ");
  123. mName.append(lastname->getString());
  124. }
  125. }
  126. else
  127. {
  128. mType = OBJECT;
  129. }
  130. }
  131. if (mType == AGENT)
  132. {
  133. if (mName.empty())
  134. {
  135. std::string fullname;
  136. if (gCacheNamep && gCacheNamep->getFullName(id, fullname))
  137. {
  138. mName = fullname;
  139. }
  140. }
  141. else if (mName.find(" ") == std::string::npos)
  142. {
  143. // Residents must always appear with their legacy name in the mute
  144. // list
  145. mName += " Resident";
  146. }
  147. }
  148. else if (mName.empty())
  149. {
  150. if (mType == GROUP)
  151. {
  152. std::string groupname;
  153. if (gCacheNamep && gCacheNamep->getGroupName(id, groupname))
  154. {
  155. mName = groupname;
  156. }
  157. }
  158. else if (mType == OBJECT)
  159. {
  160. mName = "Object";
  161. }
  162. }
  163. }
  164. std::string LLMute::getNameAndType() const
  165. {
  166. std::string name_with_suffix = mName;
  167. switch (mType)
  168. {
  169. case BY_NAME:
  170. default:
  171. name_with_suffix += BY_NAME_SUFFIX;
  172. break;
  173. case AGENT:
  174. name_with_suffix += AGENT_SUFFIX;
  175. break;
  176. case OBJECT:
  177. name_with_suffix += OBJECT_SUFFIX;
  178. break;
  179. case GROUP:
  180. name_with_suffix += GROUP_SUFFIX;
  181. break;
  182. }
  183. if (mFlags != 0)
  184. {
  185. if (~mFlags & flagTextChat)
  186. {
  187. name_with_suffix += CHAT_SUFFIX;
  188. }
  189. if (~mFlags & flagVoiceChat)
  190. {
  191. name_with_suffix += VOICE_SUFFIX;
  192. }
  193. if (~mFlags & flagObjectSounds)
  194. {
  195. name_with_suffix += SOUNDS_SUFFIX;
  196. }
  197. if (~mFlags & flagParticles)
  198. {
  199. name_with_suffix += PARTICLES_SUFFIX;
  200. }
  201. }
  202. return name_with_suffix;
  203. }
  204. void LLMute::setFromDisplayName(const std::string& entry_name)
  205. {
  206. size_t pos = 0;
  207. mName = entry_name;
  208. pos = mName.rfind(GROUP_SUFFIX);
  209. if (pos != std::string::npos)
  210. {
  211. mName.erase(pos);
  212. mType = GROUP;
  213. return;
  214. }
  215. pos = mName.rfind(OBJECT_SUFFIX);
  216. if (pos != std::string::npos)
  217. {
  218. mName.erase(pos);
  219. mType = OBJECT;
  220. return;
  221. }
  222. pos = mName.rfind(AGENT_SUFFIX);
  223. if (pos != std::string::npos)
  224. {
  225. mName.erase(pos);
  226. mType = AGENT;
  227. return;
  228. }
  229. pos = mName.rfind(BY_NAME_SUFFIX);
  230. if (pos != std::string::npos)
  231. {
  232. mName.erase(pos);
  233. mType = BY_NAME;
  234. return;
  235. }
  236. llwarns << "Unable to set mute from entry: " << entry_name << llendl;
  237. }
  238. //-----------------------------------------------------------------------------
  239. // LLMuteList class (purely static class)
  240. //-----------------------------------------------------------------------------
  241. // static member variables
  242. bool LLMuteList::sIsLoaded = false;
  243. bool LLMuteList::sUserVolumesLoaded = false;
  244. boost::signals2::connection LLMuteList::sRegionBoundaryCrossingSlot;
  245. boost::signals2::connection LLMuteList::sSimFeaturesReceivedSlot;
  246. std::set<std::string> LLMuteList::sGodLastNames;
  247. std::set<std::string> LLMuteList::sGodFullNames;
  248. LLMuteList::mute_set_t LLMuteList::sMutes;
  249. LLMuteList::string_set_t LLMuteList::sLegacyMutes;
  250. LLMuteList::observer_set_t LLMuteList::sObservers;
  251. LLMuteList::user_volume_map_t LLMuteList::sUserVolumeSettings;
  252. //static
  253. void LLMuteList::initClass()
  254. {
  255. gGenericDispatcher.addHandler("emptymutelist", &sDispatchEmptyMuteList);
  256. // Register our callbacks
  257. gMessageSystemp->setHandlerFuncFast(_PREHASH_MuteListUpdate,
  258. processMuteListUpdate);
  259. gMessageSystemp->setHandlerFuncFast(_PREHASH_UseCachedMuteList,
  260. processUseCachedMuteList);
  261. }
  262. //static
  263. void LLMuteList::shutDownClass()
  264. {
  265. if (sSimFeaturesReceivedSlot.connected())
  266. {
  267. sSimFeaturesReceivedSlot.disconnect();
  268. }
  269. if (sRegionBoundaryCrossingSlot.connected())
  270. {
  271. sRegionBoundaryCrossingSlot.disconnect();
  272. }
  273. if (sUserVolumesLoaded)
  274. {
  275. std::string user_dir = gDirUtil.getLindenUserDir();
  276. std::string filename = gDirUtil.getFullPath(LL_PATH_PER_ACCOUNT,
  277. "volume_settings.xml");
  278. LLSD settings_llsd;
  279. for (user_volume_map_t::iterator iter = sUserVolumeSettings.begin(),
  280. end = sUserVolumeSettings.end();
  281. iter != end; ++iter)
  282. {
  283. settings_llsd[iter->first.asString()] = iter->second;
  284. }
  285. llofstream file(filename.c_str());
  286. if (file.is_open())
  287. {
  288. LLSDSerialize::toPrettyXML(settings_llsd, file);
  289. file.close();
  290. llinfos << "User volumes saved" << llendl;
  291. }
  292. else
  293. {
  294. llwarns << "Could not open file '" << filename << "' for writing."
  295. << llendl;
  296. }
  297. }
  298. }
  299. // Call once, after LLDir::setLindenUserDir() has been called
  300. //static
  301. void LLMuteList::loadUserVolumes()
  302. {
  303. if (sUserVolumesLoaded)
  304. {
  305. return;
  306. }
  307. sUserVolumesLoaded = true;
  308. // Load per-resident voice volume information. Conceptually, this is part
  309. // of the mute list information, although it is only stored locally
  310. std::string filename = gDirUtil.getFullPath(LL_PATH_PER_ACCOUNT,
  311. "volume_settings.xml");
  312. LLSD settings_llsd;
  313. llifstream file(filename.c_str());
  314. if (file.is_open())
  315. {
  316. LLSDSerialize::fromXML(settings_llsd, file);
  317. }
  318. for (LLSD::map_const_iterator iter = settings_llsd.beginMap(),
  319. end = settings_llsd.endMap();
  320. iter != end; ++iter)
  321. {
  322. sUserVolumeSettings[LLUUID(iter->first)] = (F32)iter->second.asReal();
  323. }
  324. }
  325. //static
  326. bool LLMuteList::isLinden(const std::string& name)
  327. {
  328. if (sGodFullNames.count(name)) return true;
  329. if (sGodLastNames.empty()) return false;
  330. size_t i = name.rfind(' ');
  331. if (i == std::string::npos || i >= name.length() - 1)
  332. {
  333. // No space in name, or one space at the end of the name (the latter
  334. // should not happen, but let's be paranoid).
  335. return false;
  336. }
  337. return sGodLastNames.count(name.substr(i + 1)) != 0;
  338. }
  339. //static
  340. bool LLMuteList::add(const LLMute& mute, U32 flags)
  341. {
  342. // Cannot mute text from Lindens
  343. if (mute.mType == LLMute::AGENT && isLinden(mute.mName) &&
  344. (flags == 0 || (flags & LLMute::flagTextChat)))
  345. {
  346. gNotifications.add("MuteLinden");
  347. return false;
  348. }
  349. if (mute.mID.notNull())
  350. {
  351. LLViewerObject* vobj = gObjectList.findObject(mute.mID);
  352. if (mute.mID == gAgentID)
  353. {
  354. if (flags != LLMute::flagVoiceChat)
  355. {
  356. // Cannot mute self.
  357. gNotifications.add("MuteSelf");
  358. return false;
  359. }
  360. }
  361. else if (vobj && vobj->permYouOwner())
  362. {
  363. // Cannot mute our own objects
  364. gNotifications.add("MuteOwnObject");
  365. return false;
  366. }
  367. }
  368. size_t max_entries = gSavedSettings.getU32("MuteListLimit");
  369. if (sMutes.size() >= max_entries)
  370. {
  371. llwarns << "Mute list too large; new mute discarded." << llendl;
  372. LLSD args;
  373. args["MUTE_LIMIT"] = llformat("%d", (S32)max_entries);
  374. gNotifications.add("MuteLimitReached", args);
  375. return false;
  376. }
  377. if (mute.mType == LLMute::BY_NAME)
  378. {
  379. // Cannot mute empty string by name
  380. if (mute.mName.empty())
  381. {
  382. llwarns << "Trying to mute empty string by-name" << llendl;
  383. return false;
  384. }
  385. // Null mutes must have uuid null
  386. if (mute.mID.notNull())
  387. {
  388. llwarns << "Trying to add by-name mute with non-null id" << llendl;
  389. return false;
  390. }
  391. if (!isAgentAvatarValid())
  392. {
  393. return false;
  394. }
  395. std::string name;
  396. name.assign(gAgentAvatarp->getNVPair("FirstName")->getString());
  397. name.append(" ");
  398. name.append(gAgentAvatarp->getNVPair("LastName")->getString());
  399. if (mute.mName == name)
  400. {
  401. // Cannot mute self.
  402. gNotifications.add("MuteSelf");
  403. return false;
  404. }
  405. std::pair<string_set_t::iterator, bool> result =
  406. sLegacyMutes.emplace(mute.mName);
  407. if (result.second)
  408. {
  409. llinfos << "Muting by name " << mute.mName << llendl;
  410. updateAdd(mute);
  411. notifyObservers();
  412. cache(true);
  413. return true;
  414. }
  415. else
  416. {
  417. // Was a duplicate
  418. gNotifications.add("MuteByNameFailed");
  419. return false;
  420. }
  421. }
  422. else
  423. {
  424. // Need a local (non-const) copy to set up flags properly.
  425. LLMute localmute = mute;
  426. // If an entry for the same entity is already in the list, remove it,
  427. // saving flags as necessary.
  428. mute_set_t::iterator it = sMutes.find(localmute);
  429. if (it != sMutes.end())
  430. {
  431. // This mute is already in the list. Save the existing entry's
  432. // flags if that's warranted.
  433. localmute.mFlags = it->mFlags;
  434. sMutes.erase(it);
  435. // Do not need to call notifyObservers() here, since it will happen
  436. // after the entry has been re-added below.
  437. }
  438. else
  439. {
  440. // There was no entry in the list previously. Fake things up by
  441. // making it look like the previous entry had all properties
  442. // unmuted.
  443. localmute.mFlags = LLMute::flagAll;
  444. }
  445. if (flags)
  446. {
  447. // The user passed some combination of flags.
  448. // Make sure those flag bits are turned off (i.e. those properties
  449. // will be muted) and that mFlags will not be 0 (0 = full mute,
  450. // including things not covered by flags such as script dialogs,
  451. // inventory offers, avatar rendering, etc...).
  452. localmute.mFlags = LLMute::flagPartialMute | (localmute.mFlags & ~flags);
  453. }
  454. else
  455. {
  456. // The user passed 0. Make sure all flag bits are turned off (i.e.
  457. // all properties will be muted).
  458. localmute.mFlags = 0;
  459. }
  460. std::string trimed_name = localmute.mName;
  461. LLStringUtil::trimHead(trimed_name);
  462. if (trimed_name.empty())
  463. {
  464. // Do not pass an empty name (or a name with only spaces in it)
  465. // to the server because it is impossible to remove such mutes
  466. // (server bug) ! Since it is a mute by id, changing the name
  467. // is not an issue... We simply use a name that is unlikely to
  468. // correspond to anormal object name.
  469. localmute.mName.assign(EMPTY_NAME);
  470. }
  471. // (Re)add the mute entry.
  472. std::pair<mute_set_t::iterator, bool> result =
  473. sMutes.emplace(localmute);
  474. if (result.second)
  475. {
  476. llinfos << "Muting " << localmute.mName << " id "
  477. << localmute.mID << " flags " << localmute.mFlags
  478. << llendl;
  479. updateAdd(localmute);
  480. notifyObservers();
  481. if (!(localmute.mFlags & LLMute::flagParticles))
  482. {
  483. // Kill all particle systems owned by muted task
  484. if (localmute.mType == LLMute::AGENT)
  485. {
  486. gViewerPartSim.clearParticlesByOwnerID(localmute.mID);
  487. }
  488. else if (localmute.mType == LLMute::OBJECT)
  489. {
  490. gViewerPartSim.clearParticlesByRootObjectID(localmute.mID);
  491. }
  492. }
  493. cache(true);
  494. return true;
  495. }
  496. }
  497. // If we were going to return success, we would have done it by now.
  498. return false;
  499. }
  500. //static
  501. void LLMuteList::updateAdd(const LLMute& mute)
  502. {
  503. // Update the database
  504. LLMessageSystem* msg = gMessageSystemp;
  505. msg->newMessageFast(_PREHASH_UpdateMuteListEntry);
  506. msg->nextBlockFast(_PREHASH_AgentData);
  507. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  508. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  509. msg->nextBlockFast(_PREHASH_MuteData);
  510. msg->addUUIDFast(_PREHASH_MuteID, mute.mID);
  511. msg->addStringFast(_PREHASH_MuteName, mute.mName);
  512. msg->addS32("MuteType", mute.mType);
  513. msg->addU32("MuteFlags", mute.mFlags);
  514. gAgent.sendReliableMessage();
  515. }
  516. //static
  517. bool LLMuteList::remove(const LLMute& mute, U32 flags)
  518. {
  519. bool removed = false;
  520. // First, remove from main list.
  521. mute_set_t::iterator it = sMutes.find(mute);
  522. if (it != sMutes.end())
  523. {
  524. LLMute localmute = *it;
  525. // When the caller did not pass any flag remove the entire entry:
  526. removed = true;
  527. if (flags)
  528. {
  529. // If the user passed mute flags, we may only want to change some flags.
  530. localmute.mFlags |= flags | LLMute::flagPartialMute;
  531. if (localmute.mFlags != (LLMute::flagAll | LLMute::flagPartialMute))
  532. {
  533. // Only some of the properties are masked out. Update the entry.
  534. removed = false;
  535. }
  536. else
  537. {
  538. localmute.mFlags = 0;
  539. }
  540. }
  541. // Always remove the entry from the set -- it will be re-added with new
  542. // flags if necessary.
  543. sMutes.erase(it);
  544. if (removed)
  545. {
  546. // The entry was actually removed. Notify the server.
  547. updateRemove(localmute);
  548. llinfos << "Unmuting " << localmute.mName << " id "
  549. << localmute.mID << " flags " << localmute.mFlags
  550. << llendl;
  551. }
  552. else
  553. {
  554. // Flags were updated, the mute entry needs to be retransmitted to
  555. // the server and re-added to the list.
  556. sMutes.emplace(localmute);
  557. updateAdd(localmute);
  558. llinfos << "Updating mute entry " << localmute.mName << " id "
  559. << localmute.mID << " flags " << localmute.mFlags
  560. << llendl;
  561. }
  562. }
  563. // Clean up any legacy mutes
  564. string_set_t::iterator legacy_it = sLegacyMutes.find(mute.mName);
  565. if (legacy_it != sLegacyMutes.end())
  566. {
  567. removed = true;
  568. // Database representation of legacy mute is UUID null.
  569. LLMute mute(LLUUID::null, *legacy_it, LLMute::BY_NAME);
  570. updateRemove(mute);
  571. sLegacyMutes.erase(legacy_it);
  572. }
  573. if (removed)
  574. {
  575. cache(true);
  576. notifyObservers();
  577. }
  578. return removed;
  579. }
  580. //static
  581. void LLMuteList::updateRemove(const LLMute& mute)
  582. {
  583. LLMessageSystem* msg = gMessageSystemp;
  584. msg->newMessageFast(_PREHASH_RemoveMuteListEntry);
  585. msg->nextBlockFast(_PREHASH_AgentData);
  586. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  587. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  588. msg->nextBlockFast(_PREHASH_MuteData);
  589. msg->addUUIDFast(_PREHASH_MuteID, mute.mID);
  590. msg->addString("MuteName", mute.mName);
  591. gAgent.sendReliableMessage();
  592. }
  593. void notify_automute_callback(const LLUUID& agent_id,
  594. const std::string& full_name,
  595. bool is_group, LLMuteList::EAutoReason reason)
  596. {
  597. std::string notif_name;
  598. switch (reason)
  599. {
  600. default:
  601. case LLMuteList::AR_IM:
  602. notif_name = "AutoUnmuteByIM";
  603. break;
  604. case LLMuteList::AR_INVENTORY:
  605. notif_name = "AutoUnmuteByInventory";
  606. break;
  607. case LLMuteList::AR_MONEY:
  608. notif_name = "AutoUnmuteByMoney";
  609. break;
  610. }
  611. LLSD args;
  612. args["NAME"] = full_name;
  613. LLNotificationPtr notif_ptr = gNotifications.add(notif_name, args);
  614. if (notif_ptr)
  615. {
  616. std::string message = notif_ptr->getMessage();
  617. if (reason == LLMuteList::AR_IM)
  618. {
  619. LLFloaterIMSession* timp =
  620. LLFloaterIMSession::findInstance(agent_id);
  621. if (timp)
  622. {
  623. timp->addHistoryLine(message);
  624. }
  625. }
  626. LLChat auto_chat(message);
  627. LLFloaterChat::addChat(auto_chat, false, false);
  628. }
  629. }
  630. //static
  631. bool LLMuteList::autoRemove(const LLUUID& agent_id,
  632. const EAutoReason reason,
  633. const std::string& first_name,
  634. const std::string& last_name)
  635. {
  636. bool removed = false;
  637. if (isMuted(agent_id))
  638. {
  639. LLMute automute(agent_id, LLStringUtil::null, LLMute::AGENT);
  640. removed = true;
  641. remove(automute);
  642. std::string full_name = LLCacheName::buildFullName(first_name,
  643. last_name);
  644. if (full_name.empty())
  645. {
  646. if (!gCacheNamep) return removed; // Paranoia
  647. if (gCacheNamep->getFullName(agent_id, full_name))
  648. {
  649. // Name in cache, call callback directly
  650. notify_automute_callback(agent_id, full_name, false, reason);
  651. }
  652. else
  653. {
  654. // Not in cache, lookup name from cache
  655. gCacheNamep->get(agent_id, false,
  656. boost::bind(&notify_automute_callback,
  657. _1, _2, _3, reason));
  658. }
  659. }
  660. else
  661. {
  662. // Call callback directly
  663. notify_automute_callback(agent_id, full_name, false, reason);
  664. }
  665. }
  666. return removed;
  667. }
  668. //static
  669. std::vector<LLMute> LLMuteList::getMutes()
  670. {
  671. std::vector<LLMute> mutes;
  672. for (mute_set_t::const_iterator it = sMutes.begin(), end = sMutes.end();
  673. it != end; ++it)
  674. {
  675. mutes.emplace_back(*it);
  676. }
  677. for (string_set_t::const_iterator it = sLegacyMutes.begin(),
  678. end = sLegacyMutes.end();
  679. it != end; ++it)
  680. {
  681. mutes.emplace_back(LLUUID::null, *it);
  682. }
  683. std::sort(mutes.begin(), mutes.end(), compare_by_name());
  684. return mutes;
  685. }
  686. //static
  687. std::string LLMuteList::getCachedMuteFilename()
  688. {
  689. std::string agent_id_string;
  690. gAgentID.toString(agent_id_string);
  691. std::string filename = gDirUtil.getFullPath(LL_PATH_CACHE,
  692. agent_id_string) +
  693. ".cached_mute";
  694. return filename;
  695. }
  696. //static
  697. bool LLMuteList::loadFromFile(const std::string& filename)
  698. {
  699. if (!sRegionBoundaryCrossingSlot.connected())
  700. {
  701. onRegionBoundaryCrossed();
  702. sRegionBoundaryCrossingSlot =
  703. gAgent.addRegionChangedCB(boost::bind(&onRegionBoundaryCrossed));
  704. }
  705. if (filename.empty())
  706. {
  707. llwarns << "Mute list filename is empty !" << llendl;
  708. return false;
  709. }
  710. LLFILE* fp = LLFile::open(filename, "rb");
  711. if (!fp)
  712. {
  713. llwarns << "Could not open mute list " << filename << llendl;
  714. return false;
  715. }
  716. // *NOTE: Changing the size of these buffers will require changes
  717. // in the scanf below.
  718. char id_buffer[MAX_STRING];
  719. char name_buffer[MAX_STRING];
  720. char buffer[MAX_STRING];
  721. while (!feof(fp) && fgets(buffer, MAX_STRING, fp))
  722. {
  723. id_buffer[0] = '\0';
  724. name_buffer[0] = '\0';
  725. S32 type = 0;
  726. U32 flags = 0;
  727. sscanf(buffer, " %d %254s %254[^|]| %u\n",
  728. &type, id_buffer, name_buffer, &flags);
  729. LLUUID id = LLUUID(id_buffer);
  730. // Work around for a server bug that prevents removing a mute entry
  731. // without a name... Just do not take these entries into account since
  732. // they are most likely stale ones (entries the user tried to remove
  733. // but that crept back in)... Our own code does not allow name-less
  734. // entries (EMPTY_NAME is used as the name for name-less objects muted
  735. // by id: see LLMute::add() for details).
  736. if (strlen(name_buffer) == 0)
  737. {
  738. llwarns << "Received a mute entry without a name from the server for id: "
  739. << id << ". Ignoring..." << llendl;
  740. continue;
  741. }
  742. LLMute mute(id, std::string(name_buffer), (LLMute::EType)type, flags);
  743. if (mute.mID.isNull() || mute.mType == LLMute::BY_NAME)
  744. {
  745. sLegacyMutes.emplace(mute.mName);
  746. }
  747. else
  748. {
  749. sMutes.emplace(mute);
  750. }
  751. }
  752. LLFile::close(fp);
  753. setLoaded();
  754. llinfos << "Mute list loaded from file: " << filename << llendl;
  755. return true;
  756. }
  757. //static
  758. bool LLMuteList::saveToFile(const std::string& filename)
  759. {
  760. if (filename.empty())
  761. {
  762. llwarns << "Mute list filename is empty !" << llendl;
  763. return false;
  764. }
  765. LLFILE* fp = LLFile::open(filename, "wb");
  766. if (!fp)
  767. {
  768. llwarns << "Could not open mute list " << filename << llendl;
  769. return false;
  770. }
  771. // Legacy mutes have null uuid
  772. std::string id_string;
  773. LLUUID::null.toString(id_string);
  774. for (string_set_t::iterator it = sLegacyMutes.begin(),
  775. end = sLegacyMutes.end();
  776. it != end; ++it)
  777. {
  778. fprintf(fp, "%d %s %s|\n", (S32)LLMute::BY_NAME, id_string.c_str(),
  779. it->c_str());
  780. }
  781. for (mute_set_t::iterator it = sMutes.begin(), end = sMutes.end();
  782. it != end; ++it)
  783. {
  784. it->mID.toString(id_string);
  785. const std::string& name = it->mName;
  786. fprintf(fp, "%d %s %s|%u\n", (S32)it->mType, id_string.c_str(),
  787. name.c_str(), it->mFlags);
  788. }
  789. LLFile::close(fp);
  790. llinfos << "Mute list saved to file: " << filename << llendl;
  791. return true;
  792. }
  793. //static
  794. bool LLMuteList::isMuted(const LLUUID& id, const std::string& name, U32 flags,
  795. LLMute::EType type)
  796. {
  797. if (id.notNull())
  798. {
  799. // For objects, check for muting on their parent prim
  800. LLViewerObject* mute_object = get_object_to_mute_from_id(id);
  801. LLUUID id_to_check = mute_object ? mute_object->getID() : id;
  802. LL_DEBUGS("Mute") << "Checking mute by id for object " << id
  803. << " (parent object: " << id_to_check << ")..."
  804. << LL_ENDL;
  805. // Do not need name or type for lookup
  806. LLMute mute(id_to_check);
  807. mute_set_t::const_iterator mute_it = sMutes.find(mute);
  808. if (mute_it != sMutes.end())
  809. {
  810. // If any of the flags the caller passed are set, this item is not
  811. // considered muted for this caller.
  812. if (flags & mute_it->mFlags)
  813. {
  814. LL_DEBUGS("Mute") << "The object is not muted for this mute type ("
  815. << flags << ")" << LL_ENDL;
  816. return false;
  817. }
  818. // If the mute got flags and no flag was passed by the caller,
  819. // this item is not considered muted for this caller (for example
  820. // if we muted for chat only, we do not want the avatar to be
  821. // considered muted for the rest)
  822. if (flags == 0 && mute_it->mFlags != 0)
  823. {
  824. LL_DEBUGS("Mute") << "The object is not muted for everything."
  825. << LL_ENDL;
  826. return false;
  827. }
  828. LL_DEBUGS("Mute") << "The object is muted." << LL_ENDL;
  829. return true;
  830. }
  831. LL_DEBUGS("Mute") << "The object is not muted by id..." << LL_ENDL;
  832. }
  833. // If no name was provided, we cannot proceed further
  834. if (name.empty())
  835. {
  836. LL_DEBUGS("Mute") << "The object is not muted." << LL_ENDL;
  837. return false;
  838. }
  839. LL_DEBUGS("Mute") << "Checking mute by name for: " << name << LL_ENDL;
  840. // The following checks are useful when we want to check for mutes
  841. // on something for which we do not have an UUID for, but that was
  842. // previously muted by UUID and not by name (legacy mute). This can
  843. // be used in some callbacks of llviewermessage.cpp, since not all
  844. // callbacks provide both object and avatar UUIDs, for example...
  845. // Note that partial mutes (mutes containing flags, such as flagVoiceChat
  846. // for example) will not be taken into account (we want to check for
  847. // full mutes only, here).
  848. if (type != LLMute::COUNT)
  849. {
  850. std::string name_and_type = name;
  851. switch (type)
  852. {
  853. case LLMute::AGENT:
  854. {
  855. LL_DEBUGS("Mute") << "Checking mute by name for AGENT '"
  856. << name << "'" << LL_ENDL;
  857. if (name_and_type.find(" ") == std::string::npos)
  858. {
  859. // Residents always appear with their legacy name in the
  860. // mute list
  861. name_and_type += " Resident";
  862. }
  863. name_and_type += LLMute::AGENT_SUFFIX;
  864. break;
  865. }
  866. case LLMute::OBJECT:
  867. {
  868. LL_DEBUGS("Mute") << "Checking mute by name for OBJECT '"
  869. << name << "'" << LL_ENDL;
  870. name_and_type += LLMute::OBJECT_SUFFIX;
  871. break;
  872. }
  873. case LLMute::GROUP:
  874. {
  875. LL_DEBUGS("Mute") << "Checking mute by name for GROUP '"
  876. << name << "'" << LL_ENDL;
  877. name_and_type += LLMute::GROUP_SUFFIX;
  878. break;
  879. }
  880. case LLMute::BY_NAME:
  881. default:
  882. {
  883. LL_DEBUGS("Mute") << "Checking mute BY_NAME for '"
  884. << name << "'" << LL_ENDL;
  885. name_and_type += LLMute::BY_NAME_SUFFIX;
  886. }
  887. }
  888. std::vector<LLMute> mutes = getMutes();
  889. for (std::vector<LLMute>::iterator it = mutes.begin(),
  890. end = mutes.end();
  891. it != end; ++it)
  892. {
  893. if (name_and_type == it->getNameAndType())
  894. {
  895. // If any of the flags the caller passed are set, this item
  896. // is not considered muted for this caller.
  897. if (flags & it->mFlags)
  898. {
  899. LL_DEBUGS("Mute") << "The object is not muted for this mute type ("
  900. << flags << ")" << LL_ENDL;
  901. return false;
  902. }
  903. LL_DEBUGS("Mute") << "The object is muted." << LL_ENDL;
  904. return true;
  905. }
  906. }
  907. }
  908. // Agents and groups are always muted by Id and thus should never appear in
  909. // the legacy mutes (and we do not want to mute an agent or group whose
  910. // name would accidentally match an object muted by name...).
  911. if (type == LLMute::AGENT || type == LLMute::GROUP)
  912. {
  913. LL_DEBUGS("Mute") << "Non-muted "
  914. << (type == LLMute::AGENT ? "AGENT" : "GROUP")
  915. << LL_ENDL;
  916. return false;
  917. }
  918. else
  919. {
  920. // Look in legacy pile
  921. string_set_t::const_iterator legacy_it = sLegacyMutes.find(name);
  922. bool muted = legacy_it != sLegacyMutes.end();
  923. LL_DEBUGS("Mute") << "Legacy mutes check: "
  924. << (muted ? "muted." : "not muted.")
  925. << LL_ENDL;
  926. return muted;
  927. }
  928. }
  929. //static
  930. S32 LLMuteList::getMuteFlags(const LLUUID& id, std::string& description)
  931. {
  932. S32 flags = -1; // Defaults to no mute
  933. description.clear(); // Empty description for no mute.
  934. if (id.notNull())
  935. {
  936. // For objects, check for muting on their parent prim
  937. LLViewerObject* mute_object = get_object_to_mute_from_id(id);
  938. LLUUID id_to_check = (mute_object) ? mute_object->getID() : id;
  939. LLMute mute(id_to_check);
  940. mute_set_t::const_iterator mute_it = sMutes.find(mute);
  941. if (mute_it != sMutes.end())
  942. {
  943. flags = (S32)mute_it->mFlags;
  944. if (flags == 0)
  945. {
  946. description = "Muted";
  947. }
  948. else
  949. {
  950. flags = ~flags & LLMute::flagAll;
  951. if (flags & LLMute::flagTextChat)
  952. {
  953. description = 'C';
  954. }
  955. if (flags & LLMute::flagVoiceChat)
  956. {
  957. if (!description.empty())
  958. {
  959. description += '/';
  960. }
  961. description += 'V';
  962. }
  963. if (flags & LLMute::flagObjectSounds)
  964. {
  965. if (!description.empty())
  966. {
  967. description += '/';
  968. }
  969. description += 'S';
  970. }
  971. if (flags & LLMute::flagParticles)
  972. {
  973. if (!description.empty())
  974. {
  975. description += '/';
  976. }
  977. description += 'P';
  978. }
  979. description = "Muted (" + description + ")";
  980. }
  981. }
  982. }
  983. return flags;
  984. }
  985. //static
  986. void LLMuteList::loadPerAccountMuteList()
  987. {
  988. std::string filename = gDirUtil.getFullPath(LL_PATH_PER_ACCOUNT,
  989. "mute_list.txt");
  990. if (LLFile::exists(filename))
  991. {
  992. llinfos << "Loading per-account mute-list..." << llendl;
  993. loadFromFile(filename);
  994. }
  995. }
  996. //static
  997. void LLMuteList::savePerAccountMuteList()
  998. {
  999. std::string filename = gDirUtil.getFullPath(LL_PATH_PER_ACCOUNT,
  1000. "mute_list.txt");
  1001. llinfos << "Saving per-account mute-list..." << llendl;
  1002. saveToFile(filename);
  1003. }
  1004. //static
  1005. void LLMuteList::requestFromServer()
  1006. {
  1007. loadUserVolumes();
  1008. loadPerAccountMuteList();
  1009. LLCRC crc;
  1010. crc.update(getCachedMuteFilename());
  1011. LLMessageSystem* msg = gMessageSystemp;
  1012. msg->newMessageFast(_PREHASH_MuteListRequest);
  1013. msg->nextBlockFast(_PREHASH_AgentData);
  1014. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  1015. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  1016. msg->nextBlockFast(_PREHASH_MuteData);
  1017. msg->addU32Fast(_PREHASH_MuteCRC, crc.getCRC());
  1018. gAgent.sendReliableMessage(2);
  1019. }
  1020. //static
  1021. void LLMuteList::cache(bool force)
  1022. {
  1023. // Write to disk even if empty.
  1024. if (sIsLoaded || force)
  1025. {
  1026. saveToFile(getCachedMuteFilename());
  1027. savePerAccountMuteList();
  1028. }
  1029. }
  1030. //static
  1031. void LLMuteList::setSavedResidentVolume(const LLUUID& id, F32 volume)
  1032. {
  1033. // Store new value in volume settings file
  1034. sUserVolumeSettings[id] = volume;
  1035. }
  1036. //static
  1037. F32 LLMuteList::getSavedResidentVolume(const LLUUID& id)
  1038. {
  1039. constexpr F32 DEFAULT_VOLUME = 0.5f;
  1040. user_volume_map_t::iterator found_it = sUserVolumeSettings.find(id);
  1041. if (found_it != sUserVolumeSettings.end())
  1042. {
  1043. return found_it->second;
  1044. }
  1045. // *FIXME: assumes default, should get this from somewhere
  1046. return DEFAULT_VOLUME;
  1047. }
  1048. //static
  1049. void LLMuteList::processMuteListUpdate(LLMessageSystem* msg, void**)
  1050. {
  1051. if (!gXferManagerp)
  1052. {
  1053. llwarns << "Transfer manager gone. Aborted." << llendl;
  1054. return;
  1055. }
  1056. LLUUID agent_id;
  1057. msg->getUUIDFast(_PREHASH_MuteData, _PREHASH_AgentID, agent_id);
  1058. if (agent_id != gAgentID)
  1059. {
  1060. llwarns << "Got a mute list update for the wrong agent." << llendl;
  1061. return;
  1062. }
  1063. std::string unclean_filename;
  1064. msg->getStringFast(_PREHASH_MuteData, _PREHASH_Filename, unclean_filename);
  1065. std::string filename = LLDir::getScrubbedFileName(unclean_filename);
  1066. llinfos << "Updating mute list from server..." << llendl;
  1067. std::string* local_filename_and_path =
  1068. new std::string(gDirUtil.getFullPath(LL_PATH_CACHE, filename));
  1069. gXferManagerp->requestFile(*local_filename_and_path, filename,
  1070. LL_PATH_CACHE, msg->getSender(),
  1071. true, // make the remote file temporary.
  1072. onFileMuteList, (void**)local_filename_and_path,
  1073. LLXferManager::HIGH_PRIORITY);
  1074. }
  1075. //static
  1076. void LLMuteList::processUseCachedMuteList(LLMessageSystem* msg, void**)
  1077. {
  1078. if (gSavedSettings.getBool("MuteListIgnoreServer"))
  1079. {
  1080. llinfos << "Server-provided (cached) mute list ignore, as per user setting."
  1081. << llendl;
  1082. }
  1083. else
  1084. {
  1085. llinfos << "Using cached mute list" << llendl;
  1086. std::string filename = getCachedMuteFilename();
  1087. loadFromFile(filename);
  1088. }
  1089. }
  1090. //static
  1091. void LLMuteList::onFileMuteList(void** user_data, S32 error_code,
  1092. LLExtStat ext_status)
  1093. {
  1094. std::string* local_filename_and_path = (std::string*)user_data;
  1095. if (local_filename_and_path && !local_filename_and_path->empty() &&
  1096. error_code == 0)
  1097. {
  1098. if (gSavedSettings.getBool("MuteListIgnoreServer"))
  1099. {
  1100. llinfos << "Server-provided mute list ignore, as per user setting."
  1101. << llendl;
  1102. }
  1103. else
  1104. {
  1105. llinfos << "Loading server-provided mute list." << llendl;
  1106. loadFromFile(*local_filename_and_path);
  1107. }
  1108. LLFile::remove(*local_filename_and_path);
  1109. }
  1110. else
  1111. {
  1112. llwarns << "Mute list not received." << llendl;
  1113. }
  1114. delete local_filename_and_path;
  1115. }
  1116. //static
  1117. void LLMuteList::addObserver(LLMuteListObserver* observer)
  1118. {
  1119. sObservers.insert(observer);
  1120. }
  1121. //static
  1122. void LLMuteList::removeObserver(LLMuteListObserver* observer)
  1123. {
  1124. sObservers.erase(observer);
  1125. }
  1126. //static
  1127. void LLMuteList::setLoaded()
  1128. {
  1129. llinfos << "Mute list loaded." << llendl;
  1130. sIsLoaded = true;
  1131. notifyObservers();
  1132. }
  1133. //static
  1134. void LLMuteList::notifyObservers()
  1135. {
  1136. for (observer_set_t::iterator it = sObservers.begin();
  1137. it != sObservers.end(); )
  1138. {
  1139. LLMuteListObserver* observer = *it;
  1140. observer->onChange();
  1141. // In case onChange() deleted an entry.
  1142. it = sObservers.upper_bound(observer);
  1143. }
  1144. }
  1145. //static
  1146. void LLMuteList::onRegionBoundaryCrossed()
  1147. {
  1148. LLViewerRegion* regionp = gAgent.getRegion();
  1149. if (regionp)
  1150. {
  1151. if (regionp->getFeaturesReceived())
  1152. {
  1153. if (sSimFeaturesReceivedSlot.connected())
  1154. {
  1155. sSimFeaturesReceivedSlot.disconnect();
  1156. }
  1157. getGodsNames();
  1158. }
  1159. else if (!sSimFeaturesReceivedSlot.connected())
  1160. {
  1161. sSimFeaturesReceivedSlot =
  1162. regionp->setFeaturesReceivedCB(boost::bind(&getGodsNames));
  1163. }
  1164. }
  1165. }
  1166. //static
  1167. void LLMuteList::getGodsNames()
  1168. {
  1169. LLViewerRegion* regionp = gAgent.getRegion();
  1170. if (!regionp) return;
  1171. sGodLastNames.clear();
  1172. sGodFullNames.clear();
  1173. const LLSD& info = regionp->getSimulatorFeatures();
  1174. if (info.has("god_names"))
  1175. {
  1176. const LLSD& god_names = info["god_names"];
  1177. if (god_names.has("last_names"))
  1178. {
  1179. const LLSD& names = god_names["last_names"];
  1180. for (LLSD::array_const_iterator it = names.beginArray(),
  1181. end = names.endArray();
  1182. it != end; ++it)
  1183. {
  1184. std::string name = it->asString();
  1185. sGodLastNames.emplace(name);
  1186. LL_DEBUGS("Mute") << "Added '" << name
  1187. << "' to the list of grid Gods' last name."
  1188. << LL_ENDL;
  1189. }
  1190. }
  1191. if (god_names.has("full_names"))
  1192. {
  1193. const LLSD& names = god_names["full_names"];
  1194. for (LLSD::array_const_iterator it = names.beginArray(),
  1195. end = names.endArray();
  1196. it != end; ++it)
  1197. {
  1198. std::string name = it->asString();
  1199. sGodFullNames.emplace(name);
  1200. LL_DEBUGS("Mute") << "Added '" << name
  1201. << "' to the list of grid Gods." << LL_ENDL;
  1202. }
  1203. }
  1204. }
  1205. else
  1206. {
  1207. sGodLastNames.emplace("Linden");
  1208. }
  1209. }