llmutelist.cpp

Go to the documentation of this file.
00001 
00033 /*
00034  * How should muting work?
00035  * Mute an avatar
00036  * Mute a specific object (accidentally spamming)
00037  *
00038  * right-click avatar, mute
00039  * see list of recent chatters, mute
00040  * type a name to mute?
00041  *
00042  * show in list whether chatter is avatar or object
00043  *
00044  * need fast lookup by id
00045  * need lookup by name, doesn't have to be fast
00046  */
00047 
00048 #include "llviewerprecompiledheaders.h"
00049 
00050 #include "llmutelist.h"
00051 
00052 #include <boost/tokenizer.hpp>
00053 
00054 #include "llcrc.h"
00055 #include "lldir.h"
00056 #include "lldispatcher.h"
00057 #include "llsdserialize.h"
00058 #include "llxfermanager.h"
00059 #include "message.h"
00060 
00061 #include "llagent.h"
00062 #include "llviewergenericmessage.h"     // for gGenericDispatcher
00063 #include "llviewerwindow.h"
00064 #include "llworld.h" //for particle system banning
00065 #include "llchat.h"
00066 #include "llfloaterchat.h"
00067 #include "llimpanel.h"
00068 #include "llimview.h"
00069 #include "llnotify.h"
00070 #include "lluistring.h"
00071 #include "llviewerobject.h" 
00072 #include "llviewerobjectlist.h"
00073 
00074 
00075 std::map<LLUUID, F32> LLMuteList::sUserVolumeSettings;
00076 
00077 
00078 // "emptymutelist"
00079 class LLDispatchEmptyMuteList : public LLDispatchHandler
00080 {
00081 public:
00082         virtual bool operator()(
00083                 const LLDispatcher* dispatcher,
00084                 const std::string& key,
00085                 const LLUUID& invoice,
00086                 const sparam_t& strings)
00087         {
00088                 LLMuteList::getInstance()->setLoaded();
00089                 return true;
00090         }
00091 };
00092 
00093 static LLDispatchEmptyMuteList sDispatchEmptyMuteList;
00094 
00095 //-----------------------------------------------------------------------------
00096 // LLMute()
00097 //-----------------------------------------------------------------------------
00098 const char BY_NAME_SUFFIX[] = " (by name)";
00099 const char AGENT_SUFFIX[] = " (resident)";
00100 const char OBJECT_SUFFIX[] = " (object)";
00101 const char GROUP_SUFFIX[] = " (group)";
00102 
00103 LLString LLMute::getDisplayName() const
00104 {
00105         LLString name_with_suffix = mName;
00106         switch (mType)
00107         {
00108                 case BY_NAME:
00109                 default:
00110                         name_with_suffix += BY_NAME_SUFFIX;
00111                         break;
00112                 case AGENT:
00113                         name_with_suffix += AGENT_SUFFIX;
00114                         break;
00115                 case OBJECT:
00116                         name_with_suffix += OBJECT_SUFFIX;
00117                         break;
00118                 case GROUP:
00119                         name_with_suffix += GROUP_SUFFIX;
00120                         break;
00121         }
00122         return name_with_suffix;
00123 }
00124 
00125 void LLMute::setFromDisplayName(const LLString& display_name)
00126 {
00127         size_t pos = 0;
00128         mName = display_name;
00129         
00130         pos = mName.rfind(GROUP_SUFFIX);
00131         if (pos != std::string::npos)
00132         {
00133                 mName.erase(pos);
00134                 mType = GROUP;
00135                 return;
00136         }
00137         
00138         pos = mName.rfind(OBJECT_SUFFIX);
00139         if (pos != std::string::npos)
00140         {
00141                 mName.erase(pos);
00142                 mType = OBJECT;
00143                 return;
00144         }
00145         
00146         pos = mName.rfind(AGENT_SUFFIX);
00147         if (pos != std::string::npos)
00148         {
00149                 mName.erase(pos);
00150                 mType = AGENT;
00151                 return;
00152         }
00153         
00154         pos = mName.rfind(BY_NAME_SUFFIX);
00155         if (pos != std::string::npos)
00156         {
00157                 mName.erase(pos);
00158                 mType = BY_NAME;
00159                 return;
00160         }
00161         
00162         llwarns << "Unable to set mute from display name " << display_name << llendl;
00163         return;
00164 }
00165 
00166 /* static */
00167 LLMuteList* LLMuteList::getInstance()
00168 {
00169         // Register callbacks at the first time that we find that the message system has been created.
00170         static BOOL registered = FALSE;
00171         if( !registered && gMessageSystem != NULL)
00172         {
00173                 registered = TRUE;
00174                 // Register our various callbacks
00175                 gMessageSystem->setHandlerFuncFast(_PREHASH_MuteListUpdate, processMuteListUpdate);
00176                 gMessageSystem->setHandlerFuncFast(_PREHASH_UseCachedMuteList, processUseCachedMuteList);
00177         }
00178         return LLSingleton<LLMuteList>::getInstance(); // Call the "base" implementation.
00179 }
00180 
00181 //-----------------------------------------------------------------------------
00182 // LLMuteList()
00183 //-----------------------------------------------------------------------------
00184 LLMuteList::LLMuteList() :
00185         mIsLoaded(FALSE)
00186 {
00187         gGenericDispatcher.addHandler("emptymutelist", &sDispatchEmptyMuteList);
00188 
00189         // load per-resident voice volume information
00190         // conceptually, this is part of the mute list information, although it is only stored locally
00191         std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "volume_settings.xml");
00192 
00193         LLSD settings_llsd;
00194         llifstream file;
00195         file.open(filename.c_str());
00196         if (file.is_open())
00197         {
00198                 LLSDSerialize::fromXML(settings_llsd, file);
00199         }
00200 
00201         for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
00202                  iter != settings_llsd.endMap(); ++iter)
00203         {
00204                 sUserVolumeSettings.insert(std::make_pair(LLUUID(iter->first), (F32)iter->second.asReal()));
00205         }
00206 }
00207 
00208 //-----------------------------------------------------------------------------
00209 // ~LLMuteList()
00210 //-----------------------------------------------------------------------------
00211 LLMuteList::~LLMuteList()
00212 {
00213         std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "volume_settings.xml");
00214         LLSD settings_llsd;
00215 
00216         for(user_volume_map_t::iterator iter = sUserVolumeSettings.begin(); iter != sUserVolumeSettings.end(); ++iter)
00217         {
00218                 settings_llsd[iter->first.asString()] = iter->second;
00219         }
00220 
00221         llofstream file;
00222         file.open(filename.c_str());
00223         LLSDSerialize::toPrettyXML(settings_llsd, file);
00224 }
00225 
00226 BOOL LLMuteList::isLinden(const LLString& name) const
00227 {
00228         typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
00229         boost::char_separator<char> sep(" ");
00230         tokenizer tokens(name, sep);
00231         tokenizer::iterator token_iter = tokens.begin();
00232         
00233         if (token_iter == tokens.end()) return FALSE;
00234         token_iter++;
00235         if (token_iter == tokens.end()) return FALSE;
00236         
00237         LLString last_name = *token_iter;
00238         return last_name == "Linden";
00239 }
00240 
00241 
00242 BOOL LLMuteList::add(const LLMute& mute, U32 flags)
00243 {
00244         // Can't mute text from Lindens
00245         if ((mute.mType == LLMute::AGENT)
00246                 && isLinden(mute.mName) && (flags & LLMute::flagTextChat || flags == 0))
00247         {
00248                 gViewerWindow->alertXml("MuteLinden");
00249                 return FALSE;
00250         }
00251         
00252         // Can't mute self.
00253         if (mute.mType == LLMute::AGENT
00254                 && mute.mID == gAgent.getID())
00255         {
00256                 return FALSE;
00257         }
00258         
00259         if (mute.mType == LLMute::BY_NAME)
00260         {               
00261                 // Can't mute empty string by name
00262                 if (mute.mName.empty()) 
00263                 {
00264                         llwarns << "Trying to mute empty string by-name" << llendl;
00265                         return FALSE;
00266                 }
00267 
00268                 // Null mutes must have uuid null
00269                 if (mute.mID.notNull())
00270                 {
00271                         llwarns << "Trying to add by-name mute with non-null id" << llendl;
00272                         return FALSE;
00273                 }
00274 
00275                 std::pair<string_set_t::iterator, bool> result = mLegacyMutes.insert(mute.mName);
00276                 if (result.second)
00277                 {
00278                         llinfos << "Muting by name " << mute.mName << llendl;
00279                         updateAdd(mute);
00280                         notifyObservers();
00281                         return TRUE;
00282                 }
00283                 else
00284                 {
00285                         // was duplicate
00286                         return FALSE;
00287                 }
00288         }
00289         else
00290         {
00291                 // Need a local (non-const) copy to set up flags properly.
00292                 LLMute localmute = mute;
00293                 
00294                 // If an entry for the same entity is already in the list, remove it, saving flags as necessary.
00295                 mute_set_t::iterator it = mMutes.find(localmute);
00296                 if (it != mMutes.end())
00297                 {
00298                         // This mute is already in the list.  Save the existing entry's flags if that's warranted.
00299                         localmute.mFlags = it->mFlags;
00300                         
00301                         mMutes.erase(it);
00302                         // Don't need to call notifyObservers() here, since it will happen after the entry has been re-added below.
00303                 }
00304                 else
00305                 {
00306                         // There was no entry in the list previously.  Fake things up by making it look like the previous entry had all properties unmuted.
00307                         localmute.mFlags = LLMute::flagAll;
00308                 }
00309 
00310                 if(flags)
00311                 {
00312                         // The user passed some combination of flags.  Make sure those flag bits are turned off (i.e. those properties will be muted).
00313                         localmute.mFlags &= (~flags);
00314                 }
00315                 else
00316                 {
00317                         // The user passed 0.  Make sure all flag bits are turned off (i.e. all properties will be muted).
00318                         localmute.mFlags = 0;
00319                 }
00320                 
00321                 // (re)add the mute entry.
00322                 {                       
00323                         std::pair<mute_set_t::iterator, bool> result = mMutes.insert(localmute);
00324                         if (result.second)
00325                         {
00326                                 llinfos << "Muting " << localmute.mName << " id " << localmute.mID << " flags " << localmute.mFlags << llendl;
00327                                 updateAdd(localmute);
00328                                 notifyObservers();
00329                                 if(!(localmute.mFlags & LLMute::flagParticles))
00330                                 {
00331                                         //Kill all particle systems owned by muted task
00332                                         if(localmute.mType == LLMute::AGENT || localmute.mType == LLMute::OBJECT)
00333                                         {
00334                                                 LLViewerPartSim::getInstance()->clearParticlesByOwnerID(localmute.mID);
00335                                         }
00336                                 }
00337                                 return TRUE;
00338                         }
00339                 }
00340         }
00341         
00342         // If we were going to return success, we'd have done it by now.
00343         return FALSE;
00344 }
00345 
00346 void LLMuteList::updateAdd(const LLMute& mute)
00347 {
00348         // Update the database
00349         LLMessageSystem* msg = gMessageSystem;
00350         msg->newMessageFast(_PREHASH_UpdateMuteListEntry);
00351         msg->nextBlockFast(_PREHASH_AgentData);
00352         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00353         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00354         msg->nextBlockFast(_PREHASH_MuteData);
00355         msg->addUUIDFast(_PREHASH_MuteID, mute.mID);
00356         msg->addStringFast(_PREHASH_MuteName, mute.mName);
00357         msg->addS32("MuteType", mute.mType);
00358         msg->addU32("MuteFlags", mute.mFlags);
00359         gAgent.sendReliableMessage();
00360 
00361         mIsLoaded = TRUE; // why is this here? -MG
00362 }
00363 
00364 
00365 BOOL LLMuteList::remove(const LLMute& mute, U32 flags)
00366 {
00367         BOOL found = FALSE;
00368         
00369         // First, remove from main list.
00370         mute_set_t::iterator it = mMutes.find(mute);
00371         if (it != mMutes.end())
00372         {
00373                 LLMute localmute = *it;
00374                 bool remove = true;
00375                 if(flags)
00376                 {
00377                         // If the user passed mute flags, we may only want to turn some flags on.
00378                         localmute.mFlags |= flags;
00379                         
00380                         if(localmute.mFlags == LLMute::flagAll)
00381                         {
00382                                 // Every currently available mute property has been masked out.
00383                                 // Remove the mute entry entirely.
00384                         }
00385                         else
00386                         {
00387                                 // Only some of the properties are masked out.  Update the entry.
00388                                 remove = false;
00389                         }
00390                 }
00391                 else
00392                 {
00393                         // The caller didn't pass any flags -- just remove the mute entry entirely.
00394                 }
00395                 
00396                 // Always remove the entry from the set -- it will be re-added with new flags if necessary.
00397                 mMutes.erase(it);
00398 
00399                 if(remove)
00400                 {
00401                         // The entry was actually removed.  Notify the server.
00402                         updateRemove(localmute);
00403                         llinfos << "Unmuting " << localmute.mName << " id " << localmute.mID << " flags " << localmute.mFlags << llendl;
00404                 }
00405                 else
00406                 {
00407                         // Flags were updated, the mute entry needs to be retransmitted to the server and re-added to the list.
00408                         mMutes.insert(localmute);
00409                         updateAdd(localmute);
00410                         llinfos << "Updating mute entry " << localmute.mName << " id " << localmute.mID << " flags " << localmute.mFlags << llendl;
00411                 }
00412                 
00413                 // Must be after erase.
00414                 setLoaded();  // why is this here? -MG
00415         }
00416 
00417         // Clean up any legacy mutes
00418         string_set_t::iterator legacy_it = mLegacyMutes.find(mute.mName);
00419         if (legacy_it != mLegacyMutes.end())
00420         {
00421                 // Database representation of legacy mute is UUID null.
00422                 LLMute mute(LLUUID::null, *legacy_it, LLMute::BY_NAME);
00423                 updateRemove(mute);
00424                 mLegacyMutes.erase(legacy_it);
00425                 // Must be after erase.
00426                 setLoaded(); // why is this here? -MG
00427         }
00428         
00429         return found;
00430 }
00431 
00432 
00433 void LLMuteList::updateRemove(const LLMute& mute)
00434 {
00435         LLMessageSystem* msg = gMessageSystem;
00436         msg->newMessageFast(_PREHASH_RemoveMuteListEntry);
00437         msg->nextBlockFast(_PREHASH_AgentData);
00438         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00439         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00440         msg->nextBlockFast(_PREHASH_MuteData);
00441         msg->addUUIDFast(_PREHASH_MuteID, mute.mID);
00442         msg->addString("MuteName", mute.mName);
00443         gAgent.sendReliableMessage();
00444 }
00445 
00446 void notify_automute_callback(const LLUUID& agent_id, const char* first_name, const char* last_name, BOOL is_group, void* user_data)
00447 {
00448         U32 temp_data = (U32)user_data;
00449         LLMuteList::EAutoReason reason = (LLMuteList::EAutoReason)temp_data;
00450         LLUIString auto_message;
00451 
00452         switch (reason)
00453         {
00454         default:
00455         case LLMuteList::AR_IM:
00456                 auto_message = LLNotifyBox::getTemplateMessage("AutoUnmuteByIM");
00457                 break;
00458         case LLMuteList::AR_INVENTORY:
00459                 auto_message = LLNotifyBox::getTemplateMessage("AutoUnmuteByInventory");
00460                 break;
00461         case LLMuteList::AR_MONEY:
00462                 auto_message = LLNotifyBox::getTemplateMessage("AutoUnmuteByMoney");
00463                 break;
00464         }
00465 
00466         auto_message.setArg("[FIRST]", first_name);
00467         auto_message.setArg("[LAST]", last_name);
00468 
00469         if (reason == LLMuteList::AR_IM)
00470         {
00471                 LLFloaterIMPanel *timp = gIMMgr->findFloaterBySession(agent_id);
00472                 if (timp)
00473                 {
00474                         timp->addHistoryLine(auto_message.getString());
00475                 }
00476         }
00477 
00478         LLChat auto_chat(auto_message.getString());
00479         LLFloaterChat::addChat(auto_chat, FALSE, FALSE);
00480 }
00481 
00482 
00483 BOOL LLMuteList::autoRemove(const LLUUID& agent_id, const EAutoReason reason, const LLString& first_name, const LLString& last_name)
00484 {
00485         BOOL removed = FALSE;
00486 
00487         if (isMuted(agent_id))
00488         {
00489                 LLMute automute(agent_id, "", LLMute::AGENT);
00490                 removed = TRUE;
00491                 remove(automute);
00492 
00493                 if (first_name.empty() && last_name.empty())
00494                 {
00495                         char cache_first[DB_FIRST_NAME_BUF_SIZE];               /* Flawfinder: ignore */
00496                         char cache_last[DB_LAST_NAME_BUF_SIZE];         /* Flawfinder: ignore */
00497                         if (gCacheName->getName(agent_id, cache_first, cache_last))
00498                         {
00499                                 // name in cache, call callback directly
00500                                 notify_automute_callback(agent_id, cache_first, cache_last, FALSE, (void *)reason);
00501                         }
00502                         else
00503                         {
00504                                 // not in cache, lookup name from cache
00505                                 gCacheName->get(agent_id, FALSE, notify_automute_callback, (void *)reason);
00506                         }
00507                 }
00508                 else
00509                 {
00510                         // call callback directly
00511                         notify_automute_callback(agent_id, first_name.c_str(), last_name.c_str(), FALSE, (void *)reason);
00512                 }
00513         }
00514 
00515         return removed;
00516 }
00517 
00518 
00519 std::vector<LLMute> LLMuteList::getMutes() const
00520 {
00521         std::vector<LLMute> mutes;
00522         
00523         for (mute_set_t::const_iterator it = mMutes.begin();
00524                  it != mMutes.end();
00525                  ++it)
00526         {
00527                 mutes.push_back(*it);
00528         }
00529         
00530         for (string_set_t::const_iterator it = mLegacyMutes.begin();
00531                  it != mLegacyMutes.end();
00532                  ++it)
00533         {
00534                 LLMute legacy(LLUUID::null, *it);
00535                 mutes.push_back(legacy);
00536         }
00537         
00538         std::sort(mutes.begin(), mutes.end(), compare_by_name());
00539         return mutes;
00540 }
00541 
00542 //-----------------------------------------------------------------------------
00543 // loadFromFile()
00544 //-----------------------------------------------------------------------------
00545 BOOL LLMuteList::loadFromFile(const LLString& filename)
00546 {
00547         if(!filename.size())
00548         {
00549                 llwarns << "Mute List Filename is Empty!" << llendl;
00550                 return FALSE;
00551         }
00552 
00553         LLFILE* fp = LLFile::fopen(filename.c_str(), "rb");             /*Flawfinder: ignore*/
00554         if (!fp)
00555         {
00556                 llwarns << "Couldn't open mute list " << filename << llendl;
00557                 return FALSE;
00558         }
00559 
00560         // *NOTE: Changing the size of these buffers will require changes
00561         // in the scanf below.
00562         char id_buffer[MAX_STRING];             /*Flawfinder: ignore*/
00563         char name_buffer[MAX_STRING];           /*Flawfinder: ignore*/
00564         char buffer[MAX_STRING];                /*Flawfinder: ignore*/
00565         while (!feof(fp) 
00566                    && fgets(buffer, MAX_STRING, fp))
00567         {
00568                 id_buffer[0] = '\0';
00569                 name_buffer[0] = '\0';
00570                 S32 type = 0;
00571                 U32 flags = 0;
00572                 sscanf( /* Flawfinder: ignore */
00573                         buffer, " %d %254s %254[^|]| %u\n", &type, id_buffer, name_buffer,
00574                         &flags);
00575                 LLUUID id = LLUUID(id_buffer);
00576                 LLMute mute(id, name_buffer, (LLMute::EType)type, flags);
00577                 if (mute.mID.isNull()
00578                         || mute.mType == LLMute::BY_NAME)
00579                 {
00580                         mLegacyMutes.insert(mute.mName);
00581                 }
00582                 else
00583                 {
00584                         mMutes.insert(mute);
00585                 }
00586         }
00587         fclose(fp);
00588         setLoaded();
00589         return TRUE;
00590 }
00591 
00592 //-----------------------------------------------------------------------------
00593 // saveToFile()
00594 //-----------------------------------------------------------------------------
00595 BOOL LLMuteList::saveToFile(const LLString& filename)
00596 {
00597         if(!filename.size())
00598         {
00599                 llwarns << "Mute List Filename is Empty!" << llendl;
00600                 return FALSE;
00601         }
00602 
00603         LLFILE* fp = LLFile::fopen(filename.c_str(), "wb");             /*Flawfinder: ignore*/
00604         if (!fp)
00605         {
00606                 llwarns << "Couldn't open mute list " << filename << llendl;
00607                 return FALSE;
00608         }
00609         // legacy mutes have null uuid
00610         char id_string[UUID_STR_LENGTH];                /*Flawfinder: ignore*/
00611         LLUUID::null.toString(id_string);
00612         for (string_set_t::iterator it = mLegacyMutes.begin();
00613                  it != mLegacyMutes.end();
00614                  ++it)
00615         {
00616                 fprintf(fp, "%d %s %s|\n", (S32)LLMute::BY_NAME, id_string, it->c_str());
00617         }
00618         for (mute_set_t::iterator it = mMutes.begin();
00619                  it != mMutes.end();
00620                  ++it)
00621         {
00622                 it->mID.toString(id_string);
00623                 const LLString& name = it->mName;
00624                 fprintf(fp, "%d %s %s|%u\n", (S32)it->mType, id_string, name.c_str(), it->mFlags);
00625         }
00626         fclose(fp);
00627         return TRUE;
00628 }
00629 
00630 
00631 BOOL LLMuteList::isMuted(const LLUUID& id, const LLString& name, U32 flags) const
00632 {
00633         LLUUID id_to_check = id;
00634         
00635         // for objects, check for muting on their parent prim
00636         LLViewerObject *objectp = gObjectList.findObject(id);
00637         if ((objectp) && (!objectp->isAvatar()))
00638         {
00639                 LLViewerObject *parentp = (LLViewerObject *)objectp->getParent();
00640                 if (parentp)
00641                 {
00642                         id_to_check = parentp->getID();
00643                 }
00644         }
00645         
00646         // don't need name or type for lookup
00647         LLMute mute(id_to_check);
00648         mute_set_t::const_iterator mute_it = mMutes.find(mute);
00649         if (mute_it != mMutes.end())
00650         {
00651                 // If any of the flags the caller passed are set, this item isn't considered muted for this caller.
00652                 if(flags & mute_it->mFlags)
00653                 {
00654                         return FALSE;
00655                 }
00656                 return TRUE;
00657         }
00658 
00659         // empty names can't be legacy-muted
00660         if (name.empty()) return FALSE;
00661 
00662         // Look in legacy pile
00663         string_set_t::const_iterator legacy_it = mLegacyMutes.find(name);
00664         return legacy_it != mLegacyMutes.end();
00665 }
00666 
00667 //-----------------------------------------------------------------------------
00668 // requestFromServer()
00669 //-----------------------------------------------------------------------------
00670 void LLMuteList::requestFromServer(const LLUUID& agent_id)
00671 {
00672         char agent_id_string[UUID_STR_LENGTH];          /*Flawfinder: ignore*/
00673         char filename[LL_MAX_PATH];             /*Flawfinder: ignore*/
00674         agent_id.toString(agent_id_string);
00675         snprintf(filename, sizeof(filename), "%s.cached_mute", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string).c_str());                  /* Flawfinder: ignore */
00676         LLCRC crc;
00677         crc.update(filename);
00678 
00679         LLMessageSystem* msg = gMessageSystem;
00680         msg->newMessageFast(_PREHASH_MuteListRequest);
00681         msg->nextBlockFast(_PREHASH_AgentData);
00682         msg->addUUIDFast(_PREHASH_AgentID, agent_id);
00683         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00684         msg->nextBlockFast(_PREHASH_MuteData);
00685         msg->addU32Fast(_PREHASH_MuteCRC, crc.getCRC());
00686         gAgent.sendReliableMessage();
00687 }
00688 
00689 //-----------------------------------------------------------------------------
00690 // cache()
00691 //-----------------------------------------------------------------------------
00692 
00693 void LLMuteList::cache(const LLUUID& agent_id)
00694 {
00695         // Write to disk even if empty.
00696         if(mIsLoaded)
00697         {
00698                 char agent_id_string[UUID_STR_LENGTH];          /*Flawfinder: ignore*/
00699                 char filename[LL_MAX_PATH];             /*Flawfinder: ignore*/
00700                 agent_id.toString(agent_id_string);
00701                 snprintf(filename, sizeof(filename), "%s.cached_mute", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string).c_str());                  /* Flawfinder: ignore */
00702                 saveToFile(filename);
00703         }
00704 }
00705 
00706 void LLMuteList::setSavedResidentVolume(const LLUUID& id, F32 volume)
00707 {
00708         // store new value in volume settings file
00709         sUserVolumeSettings[id] = volume;
00710 }
00711 
00712 F32 LLMuteList::getSavedResidentVolume(const LLUUID& id)
00713 {
00714         const F32 DEFAULT_VOLUME = 0.5f;
00715         
00716         user_volume_map_t::iterator found_it = sUserVolumeSettings.find(id);
00717         if (found_it != sUserVolumeSettings.end())
00718         {
00719                 return found_it->second;
00720         }
00721         //FIXME: assumes default, should get this from somewhere
00722         return DEFAULT_VOLUME;
00723 }
00724 
00725 
00726 //-----------------------------------------------------------------------------
00727 // Static message handlers
00728 //-----------------------------------------------------------------------------
00729 
00730 void LLMuteList::processMuteListUpdate(LLMessageSystem* msg, void**)
00731 {
00732         llinfos << "LLMuteList::processMuteListUpdate()" << llendl;
00733         LLUUID agent_id;
00734         msg->getUUIDFast(_PREHASH_MuteData, _PREHASH_AgentID, agent_id);
00735         if(agent_id != gAgent.getID())
00736         {
00737                 llwarns << "Got an mute list update for the wrong agent." << llendl;
00738                 return;
00739         }
00740         char filename[MAX_STRING];              /*Flawfinder: ignore*/
00741         filename[0] = '\0';
00742         msg->getStringFast(_PREHASH_MuteData, _PREHASH_Filename, MAX_STRING, filename);
00743         
00744         std::string *local_filename_and_path = new std::string(gDirUtilp->getExpandedFilename( LL_PATH_CACHE, filename ));
00745         gXferManager->requestFile(local_filename_and_path->c_str(),
00746                                                           filename,
00747                                                           LL_PATH_CACHE,
00748                                                           msg->getSender(),
00749                                                           TRUE, // make the remote file temporary.
00750                                                           onFileMuteList,
00751                                                           (void**)local_filename_and_path,
00752                                                           LLXferManager::HIGH_PRIORITY);
00753 }
00754 
00755 void LLMuteList::processUseCachedMuteList(LLMessageSystem* msg, void**)
00756 {
00757         llinfos << "LLMuteList::processUseCachedMuteList()" << llendl;
00758 
00759         char agent_id_string[UUID_STR_LENGTH];          /*Flawfinder: ignore*/
00760         gAgent.getID().toString(agent_id_string);
00761         char filename[LL_MAX_PATH];             /*Flawfinder: ignore*/
00762         snprintf(filename, sizeof(filename), "%s.cached_mute", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string).c_str());                  /* Flawfinder: ignore */
00763         LLMuteList::getInstance()->loadFromFile(filename);
00764 }
00765 
00766 void LLMuteList::onFileMuteList(void** user_data, S32 error_code, LLExtStat ext_status)
00767 {
00768         llinfos << "LLMuteList::processMuteListFile()" << llendl;
00769 
00770         std::string *local_filename_and_path = (std::string*)user_data;
00771         if(local_filename_and_path && !local_filename_and_path->empty() && (error_code == 0))
00772         {
00773                 LLMuteList::getInstance()->loadFromFile(local_filename_and_path->c_str());
00774                 LLFile::remove(local_filename_and_path->c_str());
00775         }
00776         delete local_filename_and_path;
00777 }
00778 
00779 void LLMuteList::addObserver(LLMuteListObserver* observer)
00780 {
00781         mObservers.insert(observer);
00782 }
00783 
00784 void LLMuteList::removeObserver(LLMuteListObserver* observer)
00785 {
00786         mObservers.erase(observer);
00787 }
00788 
00789 void LLMuteList::setLoaded()
00790 {
00791         mIsLoaded = TRUE;
00792         notifyObservers();
00793 }
00794 
00795 void LLMuteList::notifyObservers()
00796 {
00797         for (observer_set_t::iterator it = mObservers.begin();
00798                 it != mObservers.end();
00799                 )
00800         {
00801                 LLMuteListObserver* observer = *it;
00802                 observer->onChange();
00803                 // In case onChange() deleted an entry.
00804                 it = mObservers.upper_bound(observer);
00805         }
00806 }

Generated on Fri May 16 08:33:48 2008 for SecondLife by  doxygen 1.5.5