MAINT-8203 Use the ReadOfflineMsgs cap to fetch IMs after login

Tue, 13 Feb 2018 15:40:21 +0200

author
andreykproductengine <andreykproductengine@lindenlab.com>
date
Tue, 13 Feb 2018 15:40:21 +0200
changeset 55336
5c65f763f4e4
parent 55332
eb12b1bdf847
child 55337
47a0198ea43a
child 55342
0f210bf34c09

MAINT-8203 Use the ReadOfflineMsgs cap to fetch IMs after login

indra/newview/CMakeLists.txt file | annotate | diff | revisions
indra/newview/llappviewer.cpp file | annotate | diff | revisions
indra/newview/llimprocessing.cpp file | annotate | diff | revisions
indra/newview/llimprocessing.h file | annotate | diff | revisions
indra/newview/llviewermessage.cpp file | annotate | diff | revisions
indra/newview/llviewerregion.cpp file | annotate | diff | revisions
     1.1 --- a/indra/newview/CMakeLists.txt	Fri Mar 09 16:57:47 2018 +0200
     1.2 +++ b/indra/newview/CMakeLists.txt	Tue Feb 13 15:40:21 2018 +0200
     1.3 @@ -345,6 +345,7 @@
     1.4      llhudview.cpp
     1.5      llimagefiltersmanager.cpp
     1.6      llimhandler.cpp
     1.7 +    llimprocessing.cpp
     1.8      llimview.cpp
     1.9      llinspect.cpp
    1.10      llinspectavatar.cpp
    1.11 @@ -966,6 +967,7 @@
    1.12      llhudtext.h
    1.13      llhudview.h
    1.14      llimagefiltersmanager.h
    1.15 +    llimprocessing.h
    1.16      llimview.h
    1.17      llinspect.h
    1.18      llinspectavatar.h
     2.1 --- a/indra/newview/llappviewer.cpp	Fri Mar 09 16:57:47 2018 +0200
     2.2 +++ b/indra/newview/llappviewer.cpp	Tue Feb 13 15:40:21 2018 +0200
     2.3 @@ -43,6 +43,7 @@
     2.4  #include "llagentui.h"
     2.5  #include "llagentwearables.h"
     2.6  #include "llfloaterimcontainer.h"
     2.7 +#include "llimprocessing.h"
     2.8  #include "llwindow.h"
     2.9  #include "llviewerstats.h"
    2.10  #include "llviewerstatsrecorder.h"
    2.11 @@ -548,27 +549,6 @@
    2.12  	return true;
    2.13  }
    2.14  
    2.15 -void request_initial_instant_messages()
    2.16 -{
    2.17 -	static BOOL requested = FALSE;
    2.18 -	if (!requested
    2.19 -		&& gMessageSystem
    2.20 -		&& LLMuteList::getInstance()->isLoaded()
    2.21 -		&& isAgentAvatarValid())
    2.22 -	{
    2.23 -		// Auto-accepted inventory items may require the avatar object
    2.24 -		// to build a correct name.  Likewise, inventory offers from
    2.25 -		// muted avatars require the mute list to properly mute.
    2.26 -		LLMessageSystem* msg = gMessageSystem;
    2.27 -		msg->newMessageFast(_PREHASH_RetrieveInstantMessages);
    2.28 -		msg->nextBlockFast(_PREHASH_AgentData);
    2.29 -		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
    2.30 -		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
    2.31 -		gAgent.sendReliableMessage();
    2.32 -		requested = TRUE;
    2.33 -	}
    2.34 -}
    2.35 -
    2.36  // Use these strictly for things that are constructed at startup,
    2.37  // or for things that are performance critical.  JC
    2.38  static void settings_to_globals()
    2.39 @@ -4623,7 +4603,7 @@
    2.40  
    2.41  	// Must wait until both have avatar object and mute list, so poll
    2.42  	// here.
    2.43 -	request_initial_instant_messages();
    2.44 +	LLIMProcessing::requestOfflineMessages();
    2.45  
    2.46  	///////////////////////////////////
    2.47  	//
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/indra/newview/llimprocessing.cpp	Tue Feb 13 15:40:21 2018 +0200
     3.3 @@ -0,0 +1,1519 @@
     3.4 +/**
     3.5 +* @file LLIMProcessing.cpp
     3.6 +* @brief Container for Instant Messaging
     3.7 +*
     3.8 +* $LicenseInfo:firstyear=2001&license=viewerlgpl$
     3.9 +* Second Life Viewer Source Code
    3.10 +* Copyright (C) 2018, Linden Research, Inc.
    3.11 +*
    3.12 +* This library is free software; you can redistribute it and/or
    3.13 +* modify it under the terms of the GNU Lesser General Public
    3.14 +* License as published by the Free Software Foundation;
    3.15 +* version 2.1 of the License only.
    3.16 +*
    3.17 +* This library is distributed in the hope that it will be useful,
    3.18 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.19 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    3.20 +* Lesser General Public License for more details.
    3.21 +*
    3.22 +* You should have received a copy of the GNU Lesser General Public
    3.23 +* License along with this library; if not, write to the Free Software
    3.24 +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
    3.25 +*
    3.26 +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
    3.27 +* $/LicenseInfo$
    3.28 +*/
    3.29 +
    3.30 +#include "llviewerprecompiledheaders.h"
    3.31 +
    3.32 +#include "llimprocessing.h"
    3.33 +
    3.34 +#include "llagent.h"
    3.35 +#include "llavatarnamecache.h"
    3.36 +#include "llfirstuse.h"
    3.37 +#include "llfloaterreg.h"
    3.38 +#include "llfloaterimnearbychat.h"
    3.39 +#include "llimview.h"
    3.40 +#include "llinventoryobserver.h"
    3.41 +#include "llinventorymodel.h"
    3.42 +#include "llmutelist.h"
    3.43 +#include "llnotifications.h"
    3.44 +#include "llnotificationsutil.h"
    3.45 +#include "llnotificationmanager.h"
    3.46 +#include "llpanelgroup.h"
    3.47 +#include "llregionhandle.h"
    3.48 +#include "llslurl.h"
    3.49 +#include "llstring.h"
    3.50 +#include "lltoastnotifypanel.h"
    3.51 +#include "lltrans.h"
    3.52 +#include "llviewergenericmessage.h"
    3.53 +#include "llviewerobjectlist.h"
    3.54 +#include "llviewermessage.h"
    3.55 +#include "llviewerwindow.h"
    3.56 +#include "llviewerregion.h"
    3.57 +#include "llvoavatarself.h"
    3.58 +
    3.59 +#include <boost/regex.hpp>
    3.60 +#include "boost/lexical_cast.hpp"
    3.61 +#if LL_MSVC
    3.62 +// disable boost::lexical_cast warning
    3.63 +#pragma warning (disable:4702)
    3.64 +#endif
    3.65 +
    3.66 +// Strip out "Resident" for display, but only if the message came from a user
    3.67 +// (rather than a script)
    3.68 +static std::string clean_name_from_im(const std::string& name, EInstantMessage type)
    3.69 +{
    3.70 +    switch (type)
    3.71 +    {
    3.72 +        case IM_NOTHING_SPECIAL:
    3.73 +        case IM_MESSAGEBOX:
    3.74 +        case IM_GROUP_INVITATION:
    3.75 +        case IM_INVENTORY_OFFERED:
    3.76 +        case IM_INVENTORY_ACCEPTED:
    3.77 +        case IM_INVENTORY_DECLINED:
    3.78 +        case IM_GROUP_VOTE:
    3.79 +        case IM_GROUP_MESSAGE_DEPRECATED:
    3.80 +            //IM_TASK_INVENTORY_OFFERED
    3.81 +            //IM_TASK_INVENTORY_ACCEPTED
    3.82 +            //IM_TASK_INVENTORY_DECLINED
    3.83 +        case IM_NEW_USER_DEFAULT:
    3.84 +        case IM_SESSION_INVITE:
    3.85 +        case IM_SESSION_P2P_INVITE:
    3.86 +        case IM_SESSION_GROUP_START:
    3.87 +        case IM_SESSION_CONFERENCE_START:
    3.88 +        case IM_SESSION_SEND:
    3.89 +        case IM_SESSION_LEAVE:
    3.90 +            //IM_FROM_TASK
    3.91 +        case IM_DO_NOT_DISTURB_AUTO_RESPONSE:
    3.92 +        case IM_CONSOLE_AND_CHAT_HISTORY:
    3.93 +        case IM_LURE_USER:
    3.94 +        case IM_LURE_ACCEPTED:
    3.95 +        case IM_LURE_DECLINED:
    3.96 +        case IM_GODLIKE_LURE_USER:
    3.97 +        case IM_TELEPORT_REQUEST:
    3.98 +        case IM_GROUP_ELECTION_DEPRECATED:
    3.99 +            //IM_GOTO_URL
   3.100 +            //IM_FROM_TASK_AS_ALERT
   3.101 +        case IM_GROUP_NOTICE:
   3.102 +        case IM_GROUP_NOTICE_INVENTORY_ACCEPTED:
   3.103 +        case IM_GROUP_NOTICE_INVENTORY_DECLINED:
   3.104 +        case IM_GROUP_INVITATION_ACCEPT:
   3.105 +        case IM_GROUP_INVITATION_DECLINE:
   3.106 +        case IM_GROUP_NOTICE_REQUESTED:
   3.107 +        case IM_FRIENDSHIP_OFFERED:
   3.108 +        case IM_FRIENDSHIP_ACCEPTED:
   3.109 +        case IM_FRIENDSHIP_DECLINED_DEPRECATED:
   3.110 +            //IM_TYPING_START
   3.111 +            //IM_TYPING_STOP
   3.112 +            return LLCacheName::cleanFullName(name);
   3.113 +        default:
   3.114 +            return name;
   3.115 +    }
   3.116 +}
   3.117 +
   3.118 +static std::string clean_name_from_task_im(const std::string& msg,
   3.119 +    BOOL from_group)
   3.120 +{
   3.121 +    boost::smatch match;
   3.122 +    static const boost::regex returned_exp(
   3.123 +        "(.*been returned to your inventory lost and found folder by )(.+)( (from|near).*)");
   3.124 +    if (boost::regex_match(msg, match, returned_exp))
   3.125 +    {
   3.126 +        // match objects are 1-based for groups
   3.127 +        std::string final = match[1].str();
   3.128 +        std::string name = match[2].str();
   3.129 +        // Don't try to clean up group names
   3.130 +        if (!from_group)
   3.131 +        {
   3.132 +            final += LLCacheName::buildUsername(name);
   3.133 +        }
   3.134 +        final += match[3].str();
   3.135 +        return final;
   3.136 +    }
   3.137 +    return msg;
   3.138 +}
   3.139 +
   3.140 +const std::string NOT_ONLINE_MSG("User not online - message will be stored and delivered later.");
   3.141 +const std::string NOT_ONLINE_INVENTORY("User not online - inventory has been saved.");
   3.142 +void translate_if_needed(std::string& message)
   3.143 +{
   3.144 +    if (message == NOT_ONLINE_MSG)
   3.145 +    {
   3.146 +        message = LLTrans::getString("not_online_msg");
   3.147 +    }
   3.148 +    else if (message == NOT_ONLINE_INVENTORY)
   3.149 +    {
   3.150 +        message = LLTrans::getString("not_online_inventory");
   3.151 +    }
   3.152 +}
   3.153 +
   3.154 +class LLPostponedIMSystemTipNotification : public LLPostponedNotification
   3.155 +{
   3.156 +protected:
   3.157 +    /* virtual */
   3.158 +    void modifyNotificationParams()
   3.159 +    {
   3.160 +        LLSD payload = mParams.payload;
   3.161 +        payload["SESSION_NAME"] = mName;
   3.162 +        mParams.payload = payload;
   3.163 +    }
   3.164 +};
   3.165 +
   3.166 +class LLPostponedOfferNotification : public LLPostponedNotification
   3.167 +{
   3.168 +protected:
   3.169 +    /* virtual */
   3.170 +    void modifyNotificationParams()
   3.171 +    {
   3.172 +        LLSD substitutions = mParams.substitutions;
   3.173 +        substitutions["NAME"] = mName;
   3.174 +        mParams.substitutions = substitutions;
   3.175 +    }
   3.176 +};
   3.177 +
   3.178 +void inventory_offer_handler(LLOfferInfo* info)
   3.179 +{
   3.180 +    // If muted, don't even go through the messaging stuff.  Just curtail the offer here.
   3.181 +    // Passing in a null UUID handles the case of where you have muted one of your own objects by_name.
   3.182 +    // The solution for STORM-1297 seems to handle the cases where the object is owned by someone else.
   3.183 +    if (LLMuteList::getInstance()->isMuted(info->mFromID, info->mFromName) ||
   3.184 +        LLMuteList::getInstance()->isMuted(LLUUID::null, info->mFromName))
   3.185 +    {
   3.186 +        info->forceResponse(IOR_MUTE);
   3.187 +        return;
   3.188 +    }
   3.189 +
   3.190 +    bool bAutoAccept(false);
   3.191 +    // Avoid the Accept/Discard dialog if the user so desires. JC
   3.192 +    if (gSavedSettings.getBOOL("AutoAcceptNewInventory")
   3.193 +        && (info->mType == LLAssetType::AT_NOTECARD
   3.194 +        || info->mType == LLAssetType::AT_LANDMARK
   3.195 +        || info->mType == LLAssetType::AT_TEXTURE))
   3.196 +    {
   3.197 +        // For certain types, just accept the items into the inventory,
   3.198 +        // and possibly open them on receipt depending upon "ShowNewInventory".
   3.199 +        bAutoAccept = true;
   3.200 +    }
   3.201 +
   3.202 +    // Strip any SLURL from the message display. (DEV-2754)
   3.203 +    std::string msg = info->mDesc;
   3.204 +    int indx = msg.find(" ( http://slurl.com/secondlife/");
   3.205 +    if (indx == std::string::npos)
   3.206 +    {
   3.207 +        // try to find new slurl host
   3.208 +        indx = msg.find(" ( http://maps.secondlife.com/secondlife/");
   3.209 +    }
   3.210 +    if (indx >= 0)
   3.211 +    {
   3.212 +        LLStringUtil::truncate(msg, indx);
   3.213 +    }
   3.214 +
   3.215 +    LLSD args;
   3.216 +    args["[OBJECTNAME]"] = msg;
   3.217 +
   3.218 +    LLSD payload;
   3.219 +
   3.220 +    // must protect against a NULL return from lookupHumanReadable()
   3.221 +    std::string typestr = ll_safe_string(LLAssetType::lookupHumanReadable(info->mType));
   3.222 +    if (!typestr.empty())
   3.223 +    {
   3.224 +        // human readable matches string name from strings.xml
   3.225 +        // lets get asset type localized name
   3.226 +        args["OBJECTTYPE"] = LLTrans::getString(typestr);
   3.227 +    }
   3.228 +    else
   3.229 +    {
   3.230 +        LL_WARNS("Messaging") << "LLAssetType::lookupHumanReadable() returned NULL - probably bad asset type: " << info->mType << LL_ENDL;
   3.231 +        args["OBJECTTYPE"] = "";
   3.232 +
   3.233 +        // This seems safest, rather than propagating bogosity
   3.234 +        LL_WARNS("Messaging") << "Forcing an inventory-decline for probably-bad asset type." << LL_ENDL;
   3.235 +        info->forceResponse(IOR_DECLINE);
   3.236 +        return;
   3.237 +    }
   3.238 +
   3.239 +    // If mObjectID is null then generate the object_id based on msg to prevent
   3.240 +    // multiple creation of chiclets for same object.
   3.241 +    LLUUID object_id = info->mObjectID;
   3.242 +    if (object_id.isNull())
   3.243 +        object_id.generate(msg);
   3.244 +
   3.245 +    payload["from_id"] = info->mFromID;
   3.246 +    // Needed by LLScriptFloaterManager to bind original notification with 
   3.247 +    // faked for toast one.
   3.248 +    payload["object_id"] = object_id;
   3.249 +    // Flag indicating that this notification is faked for toast.
   3.250 +    payload["give_inventory_notification"] = FALSE;
   3.251 +    args["OBJECTFROMNAME"] = info->mFromName;
   3.252 +    args["NAME"] = info->mFromName;
   3.253 +    if (info->mFromGroup)
   3.254 +    {
   3.255 +        args["NAME_SLURL"] = LLSLURL("group", info->mFromID, "about").getSLURLString();
   3.256 +    }
   3.257 +    else
   3.258 +    {
   3.259 +        args["NAME_SLURL"] = LLSLURL("agent", info->mFromID, "about").getSLURLString();
   3.260 +    }
   3.261 +    std::string verb = "select?name=" + LLURI::escape(msg);
   3.262 +    args["ITEM_SLURL"] = LLSLURL("inventory", info->mObjectID, verb.c_str()).getSLURLString();
   3.263 +
   3.264 +    LLNotification::Params p;
   3.265 +
   3.266 +    // Object -> Agent Inventory Offer
   3.267 +    if (info->mFromObject && !bAutoAccept)
   3.268 +    {
   3.269 +        // Inventory Slurls don't currently work for non agent transfers, so only display the object name.
   3.270 +        args["ITEM_SLURL"] = msg;
   3.271 +        // Note: sets inventory_task_offer_callback as the callback
   3.272 +        p.substitutions(args).payload(payload).functor.responder(LLNotificationResponderPtr(info));
   3.273 +        info->mPersist = true;
   3.274 +
   3.275 +        // Offers from your own objects need a special notification template.
   3.276 +        p.name = info->mFromID == gAgentID ? "OwnObjectGiveItem" : "ObjectGiveItem";
   3.277 +
   3.278 +        // Pop up inv offer chiclet and let the user accept (keep), or reject (and silently delete) the inventory.
   3.279 +        LLPostponedNotification::add<LLPostponedOfferNotification>(p, info->mFromID, info->mFromGroup == TRUE);
   3.280 +    }
   3.281 +    else // Agent -> Agent Inventory Offer
   3.282 +    {
   3.283 +        p.responder = info;
   3.284 +        // Note: sets inventory_offer_callback as the callback
   3.285 +        // *TODO fix memory leak
   3.286 +        // inventory_offer_callback() is not invoked if user received notification and 
   3.287 +        // closes viewer(without responding the notification)
   3.288 +        p.substitutions(args).payload(payload).functor.responder(LLNotificationResponderPtr(info));
   3.289 +        info->mPersist = true;
   3.290 +        p.name = "UserGiveItem";
   3.291 +        p.offer_from_agent = true;
   3.292 +
   3.293 +        // Prefetch the item into your local inventory.
   3.294 +        LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID);
   3.295 +        fetch_item->startFetch();
   3.296 +        if (fetch_item->isFinished())
   3.297 +        {
   3.298 +            fetch_item->done();
   3.299 +        }
   3.300 +        else
   3.301 +        {
   3.302 +            gInventory.addObserver(fetch_item);
   3.303 +        }
   3.304 +
   3.305 +        // In viewer 2 we're now auto receiving inventory offers and messaging as such (not sending reject messages).
   3.306 +        info->send_auto_receive_response();
   3.307 +
   3.308 +        if (gAgent.isDoNotDisturb())
   3.309 +        {
   3.310 +            send_do_not_disturb_message(gMessageSystem, info->mFromID);
   3.311 +        }
   3.312 +
   3.313 +        if (!bAutoAccept) // if we auto accept, do not pester the user
   3.314 +        {
   3.315 +            // Inform user that there is a script floater via toast system
   3.316 +            payload["give_inventory_notification"] = TRUE;
   3.317 +            p.payload = payload;
   3.318 +            LLPostponedNotification::add<LLPostponedOfferNotification>(p, info->mFromID, false);
   3.319 +        }
   3.320 +    }
   3.321 +
   3.322 +    LLFirstUse::newInventory();
   3.323 +}
   3.324 +
   3.325 +// Callback for name resolution of a god/estate message
   3.326 +static void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string message)
   3.327 +{
   3.328 +    LLSD args;
   3.329 +    args["NAME"] = av_name.getCompleteName();
   3.330 +    args["MESSAGE"] = message;
   3.331 +    LLNotificationsUtil::add("GodMessage", args);
   3.332 +
   3.333 +    // Treat like a system message and put in chat history.
   3.334 +    chat.mSourceType = CHAT_SOURCE_SYSTEM;
   3.335 +    chat.mText = message;
   3.336 +
   3.337 +    LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
   3.338 +    if (nearby_chat)
   3.339 +    {
   3.340 +        nearby_chat->addMessage(chat);
   3.341 +    }
   3.342 +}
   3.343 +
   3.344 +static bool parse_lure_bucket(const std::string& bucket,
   3.345 +    U64& region_handle,
   3.346 +    LLVector3& pos,
   3.347 +    LLVector3& look_at,
   3.348 +    U8& region_access)
   3.349 +{
   3.350 +    // tokenize the bucket
   3.351 +    typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
   3.352 +    boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
   3.353 +    tokenizer tokens(bucket, sep);
   3.354 +    tokenizer::iterator iter = tokens.begin();
   3.355 +
   3.356 +    S32 gx, gy, rx, ry, rz, lx, ly, lz;
   3.357 +    try
   3.358 +    {
   3.359 +        gx = boost::lexical_cast<S32>((*(iter)).c_str());
   3.360 +        gy = boost::lexical_cast<S32>((*(++iter)).c_str());
   3.361 +        rx = boost::lexical_cast<S32>((*(++iter)).c_str());
   3.362 +        ry = boost::lexical_cast<S32>((*(++iter)).c_str());
   3.363 +        rz = boost::lexical_cast<S32>((*(++iter)).c_str());
   3.364 +        lx = boost::lexical_cast<S32>((*(++iter)).c_str());
   3.365 +        ly = boost::lexical_cast<S32>((*(++iter)).c_str());
   3.366 +        lz = boost::lexical_cast<S32>((*(++iter)).c_str());
   3.367 +    }
   3.368 +    catch (boost::bad_lexical_cast&)
   3.369 +    {
   3.370 +        LL_WARNS("parse_lure_bucket")
   3.371 +            << "Couldn't parse lure bucket."
   3.372 +            << LL_ENDL;
   3.373 +        return false;
   3.374 +    }
   3.375 +    // Grab region access
   3.376 +    region_access = SIM_ACCESS_MIN;
   3.377 +    if (++iter != tokens.end())
   3.378 +    {
   3.379 +        std::string access_str((*iter).c_str());
   3.380 +        LLStringUtil::trim(access_str);
   3.381 +        if (access_str == "A")
   3.382 +        {
   3.383 +            region_access = SIM_ACCESS_ADULT;
   3.384 +        }
   3.385 +        else if (access_str == "M")
   3.386 +        {
   3.387 +            region_access = SIM_ACCESS_MATURE;
   3.388 +        }
   3.389 +        else if (access_str == "PG")
   3.390 +        {
   3.391 +            region_access = SIM_ACCESS_PG;
   3.392 +        }
   3.393 +    }
   3.394 +
   3.395 +    pos.setVec((F32)rx, (F32)ry, (F32)rz);
   3.396 +    look_at.setVec((F32)lx, (F32)ly, (F32)lz);
   3.397 +
   3.398 +    region_handle = to_region_handle(gx, gy);
   3.399 +    return true;
   3.400 +}
   3.401 +
   3.402 +static void notification_display_name_callback(const LLUUID& id,
   3.403 +    const LLAvatarName& av_name,
   3.404 +    const std::string& name,
   3.405 +    LLSD& substitutions,
   3.406 +    const LLSD& payload)
   3.407 +{
   3.408 +    substitutions["NAME"] = av_name.getDisplayName();
   3.409 +    LLNotificationsUtil::add(name, substitutions, payload);
   3.410 +}
   3.411 +
   3.412 +void LLIMProcessing::processNewMessage(LLUUID from_id,
   3.413 +    BOOL from_group,
   3.414 +    LLUUID to_id,
   3.415 +    U8 offline,
   3.416 +    EInstantMessage dialog, // U8
   3.417 +    LLUUID session_id,
   3.418 +    U32 timestamp,
   3.419 +    std::string agentName,
   3.420 +    std::string message,
   3.421 +    U32 parent_estate_id,
   3.422 +    LLUUID region_id,
   3.423 +    LLVector3 position,
   3.424 +    U8 *binary_bucket,
   3.425 +    S32 binary_bucket_size,
   3.426 +    LLHost &sender)
   3.427 +{
   3.428 +    LLChat chat;
   3.429 +    std::string buffer;
   3.430 +    std::string name = agentName;
   3.431 +
   3.432 +    // make sure that we don't have an empty or all-whitespace name
   3.433 +    LLStringUtil::trim(name);
   3.434 +    if (name.empty())
   3.435 +    {
   3.436 +        name = LLTrans::getString("Unnamed");
   3.437 +    }
   3.438 +
   3.439 +    // Preserve the unaltered name for use in group notice mute checking.
   3.440 +    std::string original_name = name;
   3.441 +
   3.442 +    // IDEVO convert new-style "Resident" names for display
   3.443 +    name = clean_name_from_im(name, dialog);
   3.444 +
   3.445 +    BOOL is_do_not_disturb = gAgent.isDoNotDisturb();
   3.446 +    BOOL is_muted = LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat)
   3.447 +        // object IMs contain sender object id in session_id (STORM-1209)
   3.448 +        || (dialog == IM_FROM_TASK && LLMuteList::getInstance()->isMuted(session_id));
   3.449 +    BOOL is_owned_by_me = FALSE;
   3.450 +    BOOL is_friend = (LLAvatarTracker::instance().getBuddyInfo(from_id) == NULL) ? false : true;
   3.451 +    BOOL accept_im_from_only_friend = gSavedSettings.getBOOL("VoiceCallsFriendsOnly");
   3.452 +    BOOL is_linden = chat.mSourceType != CHAT_SOURCE_OBJECT &&
   3.453 +        LLMuteList::getInstance()->isLinden(name);
   3.454 +
   3.455 +    chat.mMuted = is_muted;
   3.456 +    chat.mFromID = from_id;
   3.457 +    chat.mFromName = name;
   3.458 +    chat.mSourceType = (from_id.isNull() || (name == std::string(SYSTEM_FROM))) ? CHAT_SOURCE_SYSTEM : CHAT_SOURCE_AGENT;
   3.459 +
   3.460 +    if (chat.mSourceType == CHAT_SOURCE_SYSTEM)
   3.461 +    { // Translate server message if required (MAINT-6109)
   3.462 +        translate_if_needed(message);
   3.463 +    }
   3.464 +
   3.465 +    LLViewerObject *source = gObjectList.findObject(session_id); //Session ID is probably the wrong thing.
   3.466 +    if (source)
   3.467 +    {
   3.468 +        is_owned_by_me = source->permYouOwner();
   3.469 +    }
   3.470 +
   3.471 +    std::string separator_string(": ");
   3.472 +
   3.473 +    LLSD args;
   3.474 +    LLSD payload;
   3.475 +    LLNotification::Params params;
   3.476 +
   3.477 +    switch (dialog)
   3.478 +    {
   3.479 +        case IM_CONSOLE_AND_CHAT_HISTORY:
   3.480 +            args["MESSAGE"] = message;
   3.481 +            payload["from_id"] = from_id;
   3.482 +
   3.483 +            params.name = "IMSystemMessageTip";
   3.484 +            params.substitutions = args;
   3.485 +            params.payload = payload;
   3.486 +            LLPostponedNotification::add<LLPostponedIMSystemTipNotification>(params, from_id, false);
   3.487 +            break;
   3.488 +
   3.489 +        case IM_NOTHING_SPECIAL:	// p2p IM
   3.490 +            // Don't show dialog, just do IM
   3.491 +            if (!gAgent.isGodlike()
   3.492 +                && gAgent.getRegion()->isPrelude()
   3.493 +                && to_id.isNull())
   3.494 +            {
   3.495 +                // do nothing -- don't distract newbies in
   3.496 +                // Prelude with global IMs
   3.497 +            }
   3.498 +            else if (offline == IM_ONLINE
   3.499 +                && is_do_not_disturb
   3.500 +                && from_id.notNull() //not a system message
   3.501 +                && to_id.notNull()) //not global message
   3.502 +            {
   3.503 +
   3.504 +                // now store incoming IM in chat history
   3.505 +
   3.506 +                buffer = message;
   3.507 +
   3.508 +                LL_DEBUGS("Messaging") << "session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
   3.509 +
   3.510 +                // add to IM panel, but do not bother the user
   3.511 +                gIMMgr->addMessage(
   3.512 +                    session_id,
   3.513 +                    from_id,
   3.514 +                    name,
   3.515 +                    buffer,
   3.516 +                    IM_OFFLINE == offline,
   3.517 +                    LLStringUtil::null,
   3.518 +                    dialog,
   3.519 +                    parent_estate_id,
   3.520 +                    region_id,
   3.521 +                    position,
   3.522 +                    true);
   3.523 +
   3.524 +                if (!gIMMgr->isDNDMessageSend(session_id))
   3.525 +                {
   3.526 +                    // return a standard "do not disturb" message, but only do it to online IM
   3.527 +                    // (i.e. not other auto responses and not store-and-forward IM)
   3.528 +                    send_do_not_disturb_message(gMessageSystem, from_id, session_id);
   3.529 +                    gIMMgr->setDNDMessageSent(session_id, true);
   3.530 +                }
   3.531 +
   3.532 +            }
   3.533 +            else if (from_id.isNull())
   3.534 +            {
   3.535 +                LLSD args;
   3.536 +                args["MESSAGE"] = message;
   3.537 +                LLNotificationsUtil::add("SystemMessage", args);
   3.538 +            }
   3.539 +            else if (to_id.isNull())
   3.540 +            {
   3.541 +                // Message to everyone from GOD, look up the fullname since
   3.542 +                // server always slams name to legacy names
   3.543 +                LLAvatarNameCache::get(from_id, boost::bind(god_message_name_cb, _2, chat, message));
   3.544 +            }
   3.545 +            else
   3.546 +            {
   3.547 +                // standard message, not from system
   3.548 +                std::string saved;
   3.549 +                if (offline == IM_OFFLINE)
   3.550 +                {
   3.551 +                    LLStringUtil::format_map_t args;
   3.552 +                    args["[LONG_TIMESTAMP]"] = formatted_time(timestamp);
   3.553 +                    saved = LLTrans::getString("Saved_message", args);
   3.554 +                }
   3.555 +                buffer = saved + message;
   3.556 +
   3.557 +                LL_DEBUGS("Messaging") << "session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
   3.558 +
   3.559 +                bool mute_im = is_muted;
   3.560 +                if (accept_im_from_only_friend && !is_friend && !is_linden)
   3.561 +                {
   3.562 +                    if (!gIMMgr->isNonFriendSessionNotified(session_id))
   3.563 +                    {
   3.564 +                        std::string message = LLTrans::getString("IM_unblock_only_groups_friends");
   3.565 +                        gIMMgr->addMessage(session_id, from_id, name, message, IM_OFFLINE == offline);
   3.566 +                        gIMMgr->addNotifiedNonFriendSessionID(session_id);
   3.567 +                    }
   3.568 +
   3.569 +                    mute_im = true;
   3.570 +                }
   3.571 +                if (!mute_im)
   3.572 +                {
   3.573 +                    gIMMgr->addMessage(
   3.574 +                        session_id,
   3.575 +                        from_id,
   3.576 +                        name,
   3.577 +                        buffer,
   3.578 +                        IM_OFFLINE == offline,
   3.579 +                        LLStringUtil::null,
   3.580 +                        dialog,
   3.581 +                        parent_estate_id,
   3.582 +                        region_id,
   3.583 +                        position,
   3.584 +                        true);
   3.585 +                }
   3.586 +                else
   3.587 +                {
   3.588 +                    /*
   3.589 +                    EXT-5099
   3.590 +                    */
   3.591 +                }
   3.592 +            }
   3.593 +            break;
   3.594 +
   3.595 +        case IM_TYPING_START:
   3.596 +        {
   3.597 +            LLPointer<LLIMInfo> im_info = new LLIMInfo(gMessageSystem);
   3.598 +            gIMMgr->processIMTypingStart(im_info);
   3.599 +        }
   3.600 +        break;
   3.601 +
   3.602 +        case IM_TYPING_STOP:
   3.603 +        {
   3.604 +            LLPointer<LLIMInfo> im_info = new LLIMInfo(gMessageSystem);
   3.605 +            gIMMgr->processIMTypingStop(im_info);
   3.606 +        }
   3.607 +        break;
   3.608 +
   3.609 +        case IM_MESSAGEBOX:
   3.610 +        {
   3.611 +            // This is a block, modeless dialog.
   3.612 +            args["MESSAGE"] = message;
   3.613 +            LLNotificationsUtil::add("SystemMessageTip", args);
   3.614 +        }
   3.615 +        break;
   3.616 +        case IM_GROUP_NOTICE:
   3.617 +        case IM_GROUP_NOTICE_REQUESTED:
   3.618 +        {
   3.619 +            LL_INFOS("Messaging") << "Received IM_GROUP_NOTICE message." << LL_ENDL;
   3.620 +            // Read the binary bucket for more information.
   3.621 +            struct notice_bucket_header_t
   3.622 +            {
   3.623 +                U8 has_inventory;
   3.624 +                U8 asset_type;
   3.625 +                LLUUID group_id;
   3.626 +            };
   3.627 +            struct notice_bucket_full_t
   3.628 +            {
   3.629 +                struct notice_bucket_header_t header;
   3.630 +                U8 item_name[DB_INV_ITEM_NAME_BUF_SIZE];
   3.631 +            }*notice_bin_bucket;
   3.632 +
   3.633 +            // Make sure the binary bucket is big enough to hold the header 
   3.634 +            // and a null terminated item name.
   3.635 +            if ((binary_bucket_size < (S32)((sizeof(notice_bucket_header_t) + sizeof(U8))))
   3.636 +                || (binary_bucket[binary_bucket_size - 1] != '\0'))
   3.637 +            {
   3.638 +                LL_WARNS("Messaging") << "Malformed group notice binary bucket" << LL_ENDL;
   3.639 +                break;
   3.640 +            }
   3.641 +
   3.642 +            // The group notice packet does not have an AgentID.  Obtain one from the name cache.
   3.643 +            // If last name is "Resident" strip it out so the cache name lookup works.
   3.644 +            S32 index = original_name.find(" Resident");
   3.645 +            if (index != std::string::npos)
   3.646 +            {
   3.647 +                original_name = original_name.substr(0, index);
   3.648 +            }
   3.649 +
   3.650 +            std::string legacy_name = gCacheName->buildLegacyName(original_name);
   3.651 +            LLUUID agent_id = LLAvatarNameCache::findIdByName(legacy_name);
   3.652 +
   3.653 +            if (agent_id.isNull())
   3.654 +            {
   3.655 +                LL_WARNS("Messaging") << "buildLegacyName returned null while processing " << original_name << LL_ENDL;
   3.656 +            }
   3.657 +            else if (LLMuteList::getInstance()->isMuted(agent_id))
   3.658 +            {
   3.659 +                break;
   3.660 +            }
   3.661 +
   3.662 +            notice_bin_bucket = (struct notice_bucket_full_t*) &binary_bucket[0];
   3.663 +            U8 has_inventory = notice_bin_bucket->header.has_inventory;
   3.664 +            U8 asset_type = notice_bin_bucket->header.asset_type;
   3.665 +            LLUUID group_id = notice_bin_bucket->header.group_id;
   3.666 +            std::string item_name = ll_safe_string((const char*)notice_bin_bucket->item_name);
   3.667 +
   3.668 +            // If there is inventory, give the user the inventory offer.
   3.669 +            LLOfferInfo* info = NULL;
   3.670 +
   3.671 +            if (has_inventory)
   3.672 +            {
   3.673 +                info = new LLOfferInfo();
   3.674 +
   3.675 +                info->mIM = IM_GROUP_NOTICE;
   3.676 +                info->mFromID = from_id;
   3.677 +                info->mFromGroup = from_group;
   3.678 +                info->mTransactionID = session_id;
   3.679 +                info->mType = (LLAssetType::EType) asset_type;
   3.680 +                info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType));
   3.681 +                std::string from_name;
   3.682 +
   3.683 +                from_name += "A group member named ";
   3.684 +                from_name += name;
   3.685 +
   3.686 +                info->mFromName = from_name;
   3.687 +                info->mDesc = item_name;
   3.688 +                info->mHost = sender;
   3.689 +            }
   3.690 +
   3.691 +            std::string str(message);
   3.692 +
   3.693 +            // Tokenize the string.
   3.694 +            // TODO: Support escaped tokens ("||" -> "|")
   3.695 +            typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
   3.696 +            boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
   3.697 +            tokenizer tokens(str, sep);
   3.698 +            tokenizer::iterator iter = tokens.begin();
   3.699 +
   3.700 +            std::string subj(*iter++);
   3.701 +            std::string mes(*iter++);
   3.702 +
   3.703 +            // Send the notification down the new path.
   3.704 +            // For requested notices, we don't want to send the popups.
   3.705 +            if (dialog != IM_GROUP_NOTICE_REQUESTED)
   3.706 +            {
   3.707 +                payload["subject"] = subj;
   3.708 +                payload["message"] = mes;
   3.709 +                payload["sender_name"] = name;
   3.710 +                payload["sender_id"] = agent_id;
   3.711 +                payload["group_id"] = group_id;
   3.712 +                payload["inventory_name"] = item_name;
   3.713 +                payload["received_time"] = LLDate::now();
   3.714 +                if (info && info->asLLSD())
   3.715 +                {
   3.716 +                    payload["inventory_offer"] = info->asLLSD();
   3.717 +                }
   3.718 +
   3.719 +                LLSD args;
   3.720 +                args["SUBJECT"] = subj;
   3.721 +                args["MESSAGE"] = mes;
   3.722 +                LLDate notice_date = LLDate(timestamp).notNull() ? LLDate(timestamp) : LLDate::now();
   3.723 +                LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).time_stamp(notice_date));
   3.724 +            }
   3.725 +
   3.726 +            // Also send down the old path for now.
   3.727 +            if (IM_GROUP_NOTICE_REQUESTED == dialog)
   3.728 +            {
   3.729 +
   3.730 +                LLPanelGroup::showNotice(subj, mes, group_id, has_inventory, item_name, info);
   3.731 +            }
   3.732 +            else
   3.733 +            {
   3.734 +                delete info;
   3.735 +            }
   3.736 +        }
   3.737 +        break;
   3.738 +        case IM_GROUP_INVITATION:
   3.739 +        {
   3.740 +            if (!is_muted)
   3.741 +            {
   3.742 +                // group is not blocked, but we still need to check agent that sent the invitation
   3.743 +                // and we have no agent's id
   3.744 +                // Note: server sends username "first.last".
   3.745 +                is_muted |= LLMuteList::getInstance()->isMuted(name);
   3.746 +            }
   3.747 +            if (is_do_not_disturb || is_muted)
   3.748 +            {
   3.749 +                send_do_not_disturb_message(gMessageSystem, from_id);
   3.750 +            }
   3.751 +
   3.752 +            if (!is_muted)
   3.753 +            {
   3.754 +                LL_INFOS("Messaging") << "Received IM_GROUP_INVITATION message." << LL_ENDL;
   3.755 +                // Read the binary bucket for more information.
   3.756 +                struct invite_bucket_t
   3.757 +                {
   3.758 +                    S32 membership_fee;
   3.759 +                    LLUUID role_id;
   3.760 +                }*invite_bucket;
   3.761 +
   3.762 +                // Make sure the binary bucket is the correct size.
   3.763 +                if (binary_bucket_size != sizeof(invite_bucket_t))
   3.764 +                {
   3.765 +                    LL_WARNS("Messaging") << "Malformed group invite binary bucket" << LL_ENDL;
   3.766 +                    break;
   3.767 +                }
   3.768 +
   3.769 +                invite_bucket = (struct invite_bucket_t*) &binary_bucket[0];
   3.770 +                S32 membership_fee = ntohl(invite_bucket->membership_fee);
   3.771 +
   3.772 +                LLSD payload;
   3.773 +                payload["transaction_id"] = session_id;
   3.774 +                payload["group_id"] = from_id;
   3.775 +                payload["name"] = name;
   3.776 +                payload["message"] = message;
   3.777 +                payload["fee"] = membership_fee;
   3.778 +
   3.779 +                LLSD args;
   3.780 +                args["MESSAGE"] = message;
   3.781 +                // we shouldn't pass callback functor since it is registered in LLFunctorRegistration
   3.782 +                LLNotificationsUtil::add("JoinGroup", args, payload);
   3.783 +            }
   3.784 +        }
   3.785 +        break;
   3.786 +
   3.787 +        case IM_INVENTORY_OFFERED:
   3.788 +        case IM_TASK_INVENTORY_OFFERED:
   3.789 +            // Someone has offered us some inventory.
   3.790 +        {
   3.791 +            LLOfferInfo* info = new LLOfferInfo;
   3.792 +            if (IM_INVENTORY_OFFERED == dialog)
   3.793 +            {
   3.794 +                struct offer_agent_bucket_t
   3.795 +                {
   3.796 +                    S8		asset_type;
   3.797 +                    LLUUID	object_id;
   3.798 +                }*bucketp;
   3.799 +
   3.800 +                if (sizeof(offer_agent_bucket_t) != binary_bucket_size)
   3.801 +                {
   3.802 +                    LL_WARNS("Messaging") << "Malformed inventory offer from agent" << LL_ENDL;
   3.803 +                    delete info;
   3.804 +                    break;
   3.805 +                }
   3.806 +                bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0];
   3.807 +                info->mType = (LLAssetType::EType) bucketp->asset_type;
   3.808 +                info->mObjectID = bucketp->object_id;
   3.809 +                info->mFromObject = FALSE;
   3.810 +            }
   3.811 +            else // IM_TASK_INVENTORY_OFFERED
   3.812 +            {
   3.813 +                if (sizeof(S8) != binary_bucket_size)
   3.814 +                {
   3.815 +                    LL_WARNS("Messaging") << "Malformed inventory offer from object" << LL_ENDL;
   3.816 +                    delete info;
   3.817 +                    break;
   3.818 +                }
   3.819 +                info->mType = (LLAssetType::EType) binary_bucket[0];
   3.820 +                info->mObjectID = LLUUID::null;
   3.821 +                info->mFromObject = TRUE;
   3.822 +            }
   3.823 +
   3.824 +            info->mIM = dialog;
   3.825 +            info->mFromID = from_id;
   3.826 +            info->mFromGroup = from_group;
   3.827 +            info->mTransactionID = session_id;
   3.828 +            info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType));
   3.829 +
   3.830 +            info->mFromName = name;
   3.831 +            info->mDesc = message;
   3.832 +            info->mHost = sender;
   3.833 +            //if (((is_do_not_disturb && !is_owned_by_me) || is_muted))
   3.834 +            if (is_muted)
   3.835 +            {
   3.836 +                // Prefetch the offered item so that it can be discarded by the appropriate observer. (EXT-4331)
   3.837 +                LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID);
   3.838 +                fetch_item->startFetch();
   3.839 +                delete fetch_item;
   3.840 +
   3.841 +                // Same as closing window
   3.842 +                info->forceResponse(IOR_DECLINE);
   3.843 +            }
   3.844 +            // old logic: busy mode must not affect interaction with objects (STORM-565)
   3.845 +            // new logic: inventory offers from in-world objects should be auto-declined (CHUI-519)
   3.846 +            else if (is_do_not_disturb && dialog == IM_TASK_INVENTORY_OFFERED)
   3.847 +            {
   3.848 +                // Until throttling is implemented, do not disturb mode should reject inventory instead of silently
   3.849 +                // accepting it.  SEE SL-39554
   3.850 +                info->forceResponse(IOR_DECLINE);
   3.851 +            }
   3.852 +            else
   3.853 +            {
   3.854 +                inventory_offer_handler(info);
   3.855 +            }
   3.856 +        }
   3.857 +        break;
   3.858 +
   3.859 +        case IM_INVENTORY_ACCEPTED:
   3.860 +        {
   3.861 +            args["NAME"] = LLSLURL("agent", from_id, "completename").getSLURLString();;
   3.862 +            args["ORIGINAL_NAME"] = original_name;
   3.863 +            LLSD payload;
   3.864 +            payload["from_id"] = from_id;
   3.865 +            // Passing the "SESSION_NAME" to use it for IM notification logging
   3.866 +            // in LLTipHandler::processNotification(). See STORM-941.
   3.867 +            payload["SESSION_NAME"] = name;
   3.868 +            LLNotificationsUtil::add("InventoryAccepted", args, payload);
   3.869 +            break;
   3.870 +        }
   3.871 +        case IM_INVENTORY_DECLINED:
   3.872 +        {
   3.873 +            args["NAME"] = LLSLURL("agent", from_id, "completename").getSLURLString();;
   3.874 +            LLSD payload;
   3.875 +            payload["from_id"] = from_id;
   3.876 +            LLNotificationsUtil::add("InventoryDeclined", args, payload);
   3.877 +            break;
   3.878 +        }
   3.879 +        // TODO: _DEPRECATED suffix as part of vote removal - DEV-24856
   3.880 +        case IM_GROUP_VOTE:
   3.881 +        {
   3.882 +            LL_WARNS("Messaging") << "Received IM: IM_GROUP_VOTE_DEPRECATED" << LL_ENDL;
   3.883 +        }
   3.884 +        break;
   3.885 +
   3.886 +        case IM_GROUP_ELECTION_DEPRECATED:
   3.887 +        {
   3.888 +            LL_WARNS("Messaging") << "Received IM: IM_GROUP_ELECTION_DEPRECATED" << LL_ENDL;
   3.889 +        }
   3.890 +        break;
   3.891 +
   3.892 +        case IM_FROM_TASK:
   3.893 +        {
   3.894 +
   3.895 +            if (is_do_not_disturb && !is_owned_by_me)
   3.896 +            {
   3.897 +                return;
   3.898 +            }
   3.899 +
   3.900 +            // Build a link to open the object IM info window.
   3.901 +            std::string location = ll_safe_string((char*)binary_bucket, binary_bucket_size - 1);
   3.902 +
   3.903 +            if (session_id.notNull())
   3.904 +            {
   3.905 +                chat.mFromID = session_id;
   3.906 +            }
   3.907 +            else
   3.908 +            {
   3.909 +                // This message originated on a region without the updated code for task id and slurl information.
   3.910 +                // We just need a unique ID for this object that isn't the owner ID.
   3.911 +                // If it is the owner ID it will overwrite the style that contains the link to that owner's profile.
   3.912 +                // This isn't ideal - it will make 1 style for all objects owned by the the same person/group.
   3.913 +                // This works because the only thing we can really do in this case is show the owner name and link to their profile.
   3.914 +                chat.mFromID = from_id ^ gAgent.getSessionID();
   3.915 +            }
   3.916 +
   3.917 +            chat.mSourceType = CHAT_SOURCE_OBJECT;
   3.918 +
   3.919 +            // To conclude that the source type of message is CHAT_SOURCE_SYSTEM it's not
   3.920 +            // enough to check only from name (i.e. fromName = "Second Life"). For example
   3.921 +            // source type of messages from objects called "Second Life" should not be CHAT_SOURCE_SYSTEM.
   3.922 +            bool chat_from_system = (SYSTEM_FROM == name) && region_id.isNull() && position.isNull();
   3.923 +            if (chat_from_system)
   3.924 +            {
   3.925 +                // System's UUID is NULL (fixes EXT-4766)
   3.926 +                chat.mFromID = LLUUID::null;
   3.927 +                chat.mSourceType = CHAT_SOURCE_SYSTEM;
   3.928 +            }
   3.929 +
   3.930 +            // IDEVO Some messages have embedded resident names
   3.931 +            message = clean_name_from_task_im(message, from_group);
   3.932 +
   3.933 +            LLSD query_string;
   3.934 +            query_string["owner"] = from_id;
   3.935 +            query_string["slurl"] = location;
   3.936 +            query_string["name"] = name;
   3.937 +            if (from_group)
   3.938 +            {
   3.939 +                query_string["groupowned"] = "true";
   3.940 +            }
   3.941 +
   3.942 +            chat.mURL = LLSLURL("objectim", session_id, "").getSLURLString();
   3.943 +            chat.mText = message;
   3.944 +
   3.945 +            // Note: lie to Nearby Chat, pretending that this is NOT an IM, because
   3.946 +            // IMs from obejcts don't open IM sessions.
   3.947 +            LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
   3.948 +            if (!chat_from_system && nearby_chat)
   3.949 +            {
   3.950 +                chat.mOwnerID = from_id;
   3.951 +                LLSD args;
   3.952 +                args["slurl"] = location;
   3.953 +
   3.954 +                // Look for IRC-style emotes here so object name formatting is correct
   3.955 +                std::string prefix = message.substr(0, 4);
   3.956 +                if (prefix == "/me " || prefix == "/me'")
   3.957 +                {
   3.958 +                    chat.mChatStyle = CHAT_STYLE_IRC;
   3.959 +                }
   3.960 +
   3.961 +                LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args);
   3.962 +            }
   3.963 +
   3.964 +
   3.965 +            //Object IMs send with from name: 'Second Life' need to be displayed also in notification toasts (EXT-1590)
   3.966 +            if (!chat_from_system) break;
   3.967 +
   3.968 +            LLSD substitutions;
   3.969 +            substitutions["NAME"] = name;
   3.970 +            substitutions["MSG"] = message;
   3.971 +
   3.972 +            LLSD payload;
   3.973 +            payload["object_id"] = session_id;
   3.974 +            payload["owner_id"] = from_id;
   3.975 +            payload["from_id"] = from_id;
   3.976 +            payload["slurl"] = location;
   3.977 +            payload["name"] = name;
   3.978 +
   3.979 +            if (from_group)
   3.980 +            {
   3.981 +                payload["group_owned"] = "true";
   3.982 +            }
   3.983 +
   3.984 +            LLNotificationsUtil::add("ServerObjectMessage", substitutions, payload);
   3.985 +        }
   3.986 +        break;
   3.987 +
   3.988 +        case IM_SESSION_SEND:		// ad-hoc or group IMs
   3.989 +
   3.990 +            // Only show messages if we have a session open (which
   3.991 +            // should happen after you get an "invitation"
   3.992 +            if (!gIMMgr->hasSession(session_id))
   3.993 +            {
   3.994 +                return;
   3.995 +            }
   3.996 +
   3.997 +            else if (offline == IM_ONLINE && is_do_not_disturb)
   3.998 +            {
   3.999 +
  3.1000 +                // return a standard "do not disturb" message, but only do it to online IM 
  3.1001 +                // (i.e. not other auto responses and not store-and-forward IM)
  3.1002 +                if (!gIMMgr->hasSession(session_id))
  3.1003 +                {
  3.1004 +                    // if there is not a panel for this conversation (i.e. it is a new IM conversation
  3.1005 +                    // initiated by the other party) then...
  3.1006 +                    send_do_not_disturb_message(gMessageSystem, from_id, session_id);
  3.1007 +                }
  3.1008 +
  3.1009 +                // now store incoming IM in chat history
  3.1010 +
  3.1011 +                buffer = message;
  3.1012 +
  3.1013 +                LL_DEBUGS("Messaging") << "message in dnd; session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
  3.1014 +
  3.1015 +                // add to IM panel, but do not bother the user
  3.1016 +                gIMMgr->addMessage(
  3.1017 +                    session_id,
  3.1018 +                    from_id,
  3.1019 +                    name,
  3.1020 +                    buffer,
  3.1021 +                    IM_OFFLINE == offline,
  3.1022 +                    ll_safe_string((char*)binary_bucket),
  3.1023 +                    IM_SESSION_INVITE,
  3.1024 +                    parent_estate_id,
  3.1025 +                    region_id,
  3.1026 +                    position,
  3.1027 +                    true);
  3.1028 +            }
  3.1029 +            else
  3.1030 +            {
  3.1031 +                // standard message, not from system
  3.1032 +                std::string saved;
  3.1033 +                if (offline == IM_OFFLINE)
  3.1034 +                {
  3.1035 +                    saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
  3.1036 +                }
  3.1037 +
  3.1038 +                buffer = saved + message;
  3.1039 +
  3.1040 +                LL_DEBUGS("Messaging") << "standard message session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
  3.1041 +
  3.1042 +                gIMMgr->addMessage(
  3.1043 +                    session_id,
  3.1044 +                    from_id,
  3.1045 +                    name,
  3.1046 +                    buffer,
  3.1047 +                    IM_OFFLINE == offline,
  3.1048 +                    ll_safe_string((char*)binary_bucket),
  3.1049 +                    IM_SESSION_INVITE,
  3.1050 +                    parent_estate_id,
  3.1051 +                    region_id,
  3.1052 +                    position,
  3.1053 +                    true);
  3.1054 +            }
  3.1055 +            break;
  3.1056 +
  3.1057 +        case IM_FROM_TASK_AS_ALERT:
  3.1058 +            if (is_do_not_disturb && !is_owned_by_me)
  3.1059 +            {
  3.1060 +                return;
  3.1061 +            }
  3.1062 +            {
  3.1063 +                // Construct a viewer alert for this message.
  3.1064 +                args["NAME"] = name;
  3.1065 +                args["MESSAGE"] = message;
  3.1066 +                LLNotificationsUtil::add("ObjectMessage", args);
  3.1067 +            }
  3.1068 +            break;
  3.1069 +        case IM_DO_NOT_DISTURB_AUTO_RESPONSE:
  3.1070 +            if (is_muted)
  3.1071 +            {
  3.1072 +                LL_DEBUGS("Messaging") << "Ignoring do-not-disturb response from " << from_id << LL_ENDL;
  3.1073 +                return;
  3.1074 +            }
  3.1075 +            else
  3.1076 +            {
  3.1077 +                gIMMgr->addMessage(session_id, from_id, name, message);
  3.1078 +            }
  3.1079 +            break;
  3.1080 +
  3.1081 +        case IM_LURE_USER:
  3.1082 +        case IM_TELEPORT_REQUEST:
  3.1083 +        {
  3.1084 +            if (is_muted)
  3.1085 +            {
  3.1086 +                return;
  3.1087 +            }
  3.1088 +            else if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(from_id) == NULL))
  3.1089 +            {
  3.1090 +                return;
  3.1091 +            }
  3.1092 +            else
  3.1093 +            {
  3.1094 +                if (is_do_not_disturb)
  3.1095 +                {
  3.1096 +                    send_do_not_disturb_message(gMessageSystem, from_id);
  3.1097 +                }
  3.1098 +
  3.1099 +                LLVector3 pos, look_at;
  3.1100 +                U64 region_handle(0);
  3.1101 +                U8 region_access(SIM_ACCESS_MIN);
  3.1102 +                std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size);
  3.1103 +                std::string region_access_str = LLStringUtil::null;
  3.1104 +                std::string region_access_icn = LLStringUtil::null;
  3.1105 +                std::string region_access_lc = LLStringUtil::null;
  3.1106 +
  3.1107 +                bool canUserAccessDstRegion = true;
  3.1108 +                bool doesUserRequireMaturityIncrease = false;
  3.1109 +
  3.1110 +                // Do not parse the (empty) lure bucket for TELEPORT_REQUEST
  3.1111 +                if (IM_TELEPORT_REQUEST != dialog && parse_lure_bucket(region_info, region_handle, pos, look_at, region_access))
  3.1112 +                {
  3.1113 +                    region_access_str = LLViewerRegion::accessToString(region_access);
  3.1114 +                    region_access_icn = LLViewerRegion::getAccessIcon(region_access);
  3.1115 +                    region_access_lc = region_access_str;
  3.1116 +                    LLStringUtil::toLower(region_access_lc);
  3.1117 +
  3.1118 +                    if (!gAgent.isGodlike())
  3.1119 +                    {
  3.1120 +                        switch (region_access)
  3.1121 +                        {
  3.1122 +                            case SIM_ACCESS_MIN:
  3.1123 +                            case SIM_ACCESS_PG:
  3.1124 +                                break;
  3.1125 +                            case SIM_ACCESS_MATURE:
  3.1126 +                                if (gAgent.isTeen())
  3.1127 +                                {
  3.1128 +                                    canUserAccessDstRegion = false;
  3.1129 +                                }
  3.1130 +                                else if (gAgent.prefersPG())
  3.1131 +                                {
  3.1132 +                                    doesUserRequireMaturityIncrease = true;
  3.1133 +                                }
  3.1134 +                                break;
  3.1135 +                            case SIM_ACCESS_ADULT:
  3.1136 +                                if (!gAgent.isAdult())
  3.1137 +                                {
  3.1138 +                                    canUserAccessDstRegion = false;
  3.1139 +                                }
  3.1140 +                                else if (!gAgent.prefersAdult())
  3.1141 +                                {
  3.1142 +                                    doesUserRequireMaturityIncrease = true;
  3.1143 +                                }
  3.1144 +                                break;
  3.1145 +                            default:
  3.1146 +                                llassert(0);
  3.1147 +                                break;
  3.1148 +                        }
  3.1149 +                    }
  3.1150 +                }
  3.1151 +
  3.1152 +                LLSD args;
  3.1153 +                // *TODO: Translate -> [FIRST] [LAST] (maybe)
  3.1154 +                args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString();
  3.1155 +                args["MESSAGE"] = message;
  3.1156 +                args["MATURITY_STR"] = region_access_str;
  3.1157 +                args["MATURITY_ICON"] = region_access_icn;
  3.1158 +                args["REGION_CONTENT_MATURITY"] = region_access_lc;
  3.1159 +                LLSD payload;
  3.1160 +                payload["from_id"] = from_id;
  3.1161 +                payload["lure_id"] = session_id;
  3.1162 +                payload["godlike"] = FALSE;
  3.1163 +                payload["region_maturity"] = region_access;
  3.1164 +
  3.1165 +                if (!canUserAccessDstRegion)
  3.1166 +                {
  3.1167 +                    LLNotification::Params params("TeleportOffered_MaturityBlocked");
  3.1168 +                    params.substitutions = args;
  3.1169 +                    params.payload = payload;
  3.1170 +                    LLPostponedNotification::add<LLPostponedOfferNotification>(params, from_id, false);
  3.1171 +                    send_simple_im(from_id, LLTrans::getString("TeleportMaturityExceeded"), IM_NOTHING_SPECIAL, session_id);
  3.1172 +                    send_simple_im(from_id, LLStringUtil::null, IM_LURE_DECLINED, session_id);
  3.1173 +                }
  3.1174 +                else if (doesUserRequireMaturityIncrease)
  3.1175 +                {
  3.1176 +                    LLNotification::Params params("TeleportOffered_MaturityExceeded");
  3.1177 +                    params.substitutions = args;
  3.1178 +                    params.payload = payload;
  3.1179 +                    LLPostponedNotification::add<LLPostponedOfferNotification>(params, from_id, false);
  3.1180 +                }
  3.1181 +                else
  3.1182 +                {
  3.1183 +                    LLNotification::Params params;
  3.1184 +                    if (IM_LURE_USER == dialog)
  3.1185 +                    {
  3.1186 +                        params.name = "TeleportOffered";
  3.1187 +                        params.functor.name = "TeleportOffered";
  3.1188 +                    }
  3.1189 +                    else if (IM_TELEPORT_REQUEST == dialog)
  3.1190 +                    {
  3.1191 +                        params.name = "TeleportRequest";
  3.1192 +                        params.functor.name = "TeleportRequest";
  3.1193 +                    }
  3.1194 +
  3.1195 +                    params.substitutions = args;
  3.1196 +                    params.payload = payload;
  3.1197 +                    LLPostponedNotification::add<LLPostponedOfferNotification>(params, from_id, false);
  3.1198 +                }
  3.1199 +            }
  3.1200 +        }
  3.1201 +        break;
  3.1202 +
  3.1203 +        case IM_GODLIKE_LURE_USER:
  3.1204 +        {
  3.1205 +            LLVector3 pos, look_at;
  3.1206 +            U64 region_handle(0);
  3.1207 +            U8 region_access(SIM_ACCESS_MIN);
  3.1208 +            std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size);
  3.1209 +            std::string region_access_str = LLStringUtil::null;
  3.1210 +            std::string region_access_icn = LLStringUtil::null;
  3.1211 +            std::string region_access_lc = LLStringUtil::null;
  3.1212 +
  3.1213 +            bool canUserAccessDstRegion = true;
  3.1214 +            bool doesUserRequireMaturityIncrease = false;
  3.1215 +
  3.1216 +            if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access))
  3.1217 +            {
  3.1218 +                region_access_str = LLViewerRegion::accessToString(region_access);
  3.1219 +                region_access_icn = LLViewerRegion::getAccessIcon(region_access);
  3.1220 +                region_access_lc = region_access_str;
  3.1221 +                LLStringUtil::toLower(region_access_lc);
  3.1222 +
  3.1223 +                if (!gAgent.isGodlike())
  3.1224 +                {
  3.1225 +                    switch (region_access)
  3.1226 +                    {
  3.1227 +                        case SIM_ACCESS_MIN:
  3.1228 +                        case SIM_ACCESS_PG:
  3.1229 +                            break;
  3.1230 +                        case SIM_ACCESS_MATURE:
  3.1231 +                            if (gAgent.isTeen())
  3.1232 +                            {
  3.1233 +                                canUserAccessDstRegion = false;
  3.1234 +                            }
  3.1235 +                            else if (gAgent.prefersPG())
  3.1236 +                            {
  3.1237 +                                doesUserRequireMaturityIncrease = true;
  3.1238 +                            }
  3.1239 +                            break;
  3.1240 +                        case SIM_ACCESS_ADULT:
  3.1241 +                            if (!gAgent.isAdult())
  3.1242 +                            {
  3.1243 +                                canUserAccessDstRegion = false;
  3.1244 +                            }
  3.1245 +                            else if (!gAgent.prefersAdult())
  3.1246 +                            {
  3.1247 +                                doesUserRequireMaturityIncrease = true;
  3.1248 +                            }
  3.1249 +                            break;
  3.1250 +                        default:
  3.1251 +                            llassert(0);
  3.1252 +                            break;
  3.1253 +                    }
  3.1254 +                }
  3.1255 +            }
  3.1256 +
  3.1257 +            LLSD args;
  3.1258 +            // *TODO: Translate -> [FIRST] [LAST] (maybe)
  3.1259 +            args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString();
  3.1260 +            args["MESSAGE"] = message;
  3.1261 +            args["MATURITY_STR"] = region_access_str;
  3.1262 +            args["MATURITY_ICON"] = region_access_icn;
  3.1263 +            args["REGION_CONTENT_MATURITY"] = region_access_lc;
  3.1264 +            LLSD payload;
  3.1265 +            payload["from_id"] = from_id;
  3.1266 +            payload["lure_id"] = session_id;
  3.1267 +            payload["godlike"] = TRUE;
  3.1268 +            payload["region_maturity"] = region_access;
  3.1269 +
  3.1270 +            if (!canUserAccessDstRegion)
  3.1271 +            {
  3.1272 +                LLNotification::Params params("TeleportOffered_MaturityBlocked");
  3.1273 +                params.substitutions = args;
  3.1274 +                params.payload = payload;
  3.1275 +                LLPostponedNotification::add<LLPostponedOfferNotification>(params, from_id, false);
  3.1276 +                send_simple_im(from_id, LLTrans::getString("TeleportMaturityExceeded"), IM_NOTHING_SPECIAL, session_id);
  3.1277 +                send_simple_im(from_id, LLStringUtil::null, IM_LURE_DECLINED, session_id);
  3.1278 +            }
  3.1279 +            else if (doesUserRequireMaturityIncrease)
  3.1280 +            {
  3.1281 +                LLNotification::Params params("TeleportOffered_MaturityExceeded");
  3.1282 +                params.substitutions = args;
  3.1283 +                params.payload = payload;
  3.1284 +                LLPostponedNotification::add<LLPostponedOfferNotification>(params, from_id, false);
  3.1285 +            }
  3.1286 +            else
  3.1287 +            {
  3.1288 +                // do not show a message box, because you're about to be
  3.1289 +                // teleported.
  3.1290 +                LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0);
  3.1291 +            }
  3.1292 +        }
  3.1293 +        break;
  3.1294 +
  3.1295 +        case IM_GOTO_URL:
  3.1296 +        {
  3.1297 +            LLSD args;
  3.1298 +            // n.b. this is for URLs sent by the system, not for
  3.1299 +            // URLs sent by scripts (i.e. llLoadURL)
  3.1300 +            if (binary_bucket_size <= 0)
  3.1301 +            {
  3.1302 +                LL_WARNS("Messaging") << "bad binary_bucket_size: "
  3.1303 +                    << binary_bucket_size
  3.1304 +                    << " - aborting function." << LL_ENDL;
  3.1305 +                return;
  3.1306 +            }
  3.1307 +
  3.1308 +            std::string url;
  3.1309 +
  3.1310 +            url.assign((char*)binary_bucket, binary_bucket_size - 1);
  3.1311 +            args["MESSAGE"] = message;
  3.1312 +            args["URL"] = url;
  3.1313 +            LLSD payload;
  3.1314 +            payload["url"] = url;
  3.1315 +            LLNotificationsUtil::add("GotoURL", args, payload);
  3.1316 +        }
  3.1317 +        break;
  3.1318 +
  3.1319 +        case IM_FRIENDSHIP_OFFERED:
  3.1320 +        {
  3.1321 +            LLSD payload;
  3.1322 +            payload["from_id"] = from_id;
  3.1323 +            payload["session_id"] = session_id;;
  3.1324 +            payload["online"] = (offline == IM_ONLINE);
  3.1325 +            payload["sender"] = sender.getIPandPort();
  3.1326 +
  3.1327 +            bool add_notification = true;
  3.1328 +            for (LLToastNotifyPanel::instance_iter ti(LLToastNotifyPanel::beginInstances())
  3.1329 +                , tend(LLToastNotifyPanel::endInstances()); ti != tend; ++ti)
  3.1330 +            {
  3.1331 +                LLToastNotifyPanel& panel = *ti;
  3.1332 +                const std::string& notification_name = panel.getNotificationName();
  3.1333 +                if (notification_name == "OfferFriendship" && panel.isControlPanelEnabled())
  3.1334 +                {
  3.1335 +                    add_notification = false;
  3.1336 +                    break;
  3.1337 +                }
  3.1338 +            }
  3.1339 +
  3.1340 +            if (is_muted && add_notification)
  3.1341 +            {
  3.1342 +                LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1);
  3.1343 +            }
  3.1344 +            else
  3.1345 +            {
  3.1346 +                if (is_do_not_disturb)
  3.1347 +                {
  3.1348 +                    send_do_not_disturb_message(gMessageSystem, from_id);
  3.1349 +                }
  3.1350 +                args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString();
  3.1351 +
  3.1352 +                if (add_notification)
  3.1353 +                {
  3.1354 +                    if (message.empty())
  3.1355 +                    {
  3.1356 +                        //support for frienship offers from clients before July 2008
  3.1357 +                        LLNotificationsUtil::add("OfferFriendshipNoMessage", args, payload);
  3.1358 +                    }
  3.1359 +                    else
  3.1360 +                    {
  3.1361 +                        args["[MESSAGE]"] = message;
  3.1362 +                        LLNotification::Params params("OfferFriendship");
  3.1363 +                        params.substitutions = args;
  3.1364 +                        params.payload = payload;
  3.1365 +                        LLPostponedNotification::add<LLPostponedOfferNotification>(params, from_id, false);
  3.1366 +                    }
  3.1367 +                }
  3.1368 +            }
  3.1369 +        }
  3.1370 +        break;
  3.1371 +
  3.1372 +        case IM_FRIENDSHIP_ACCEPTED:
  3.1373 +        {
  3.1374 +            // In the case of an offline IM, the formFriendship() may be extraneous
  3.1375 +            // as the database should already include the relationship.  But it
  3.1376 +            // doesn't hurt for dupes.
  3.1377 +            LLAvatarTracker::formFriendship(from_id);
  3.1378 +
  3.1379 +            std::vector<std::string> strings;
  3.1380 +            strings.push_back(from_id.asString());
  3.1381 +            send_generic_message("requestonlinenotification", strings);
  3.1382 +
  3.1383 +            args["NAME"] = name;
  3.1384 +            LLSD payload;
  3.1385 +            payload["from_id"] = from_id;
  3.1386 +            LLAvatarNameCache::get(from_id, boost::bind(&notification_display_name_callback, _1, _2, "FriendshipAccepted", args, payload));
  3.1387 +        }
  3.1388 +        break;
  3.1389 +
  3.1390 +        case IM_FRIENDSHIP_DECLINED_DEPRECATED:
  3.1391 +        default:
  3.1392 +            LL_WARNS("Messaging") << "Instant message calling for unknown dialog "
  3.1393 +                << (S32)dialog << LL_ENDL;
  3.1394 +            break;
  3.1395 +    }
  3.1396 +
  3.1397 +    LLWindow* viewer_window = gViewerWindow->getWindow();
  3.1398 +    if (viewer_window && viewer_window->getMinimized())
  3.1399 +    {
  3.1400 +        viewer_window->flashIcon(5.f);
  3.1401 +    }
  3.1402 +}
  3.1403 +
  3.1404 +void LLIMProcessing::requestOfflineMessages()
  3.1405 +{
  3.1406 +    static BOOL requested = FALSE;
  3.1407 +    if (!requested
  3.1408 +        && gMessageSystem
  3.1409 +        && LLMuteList::getInstance()->isLoaded()
  3.1410 +        && isAgentAvatarValid()
  3.1411 +        && gAgent.getRegion()
  3.1412 +        && gAgent.getRegion()->capabilitiesReceived())
  3.1413 +    {
  3.1414 +        std::string cap_url = gAgent.getRegionCapability("ReadOfflineMsgs");
  3.1415 +
  3.1416 +        // Auto-accepted inventory items may require the avatar object
  3.1417 +        // to build a correct name.  Likewise, inventory offers from
  3.1418 +        // muted avatars require the mute list to properly mute.
  3.1419 +        if (cap_url.empty())
  3.1420 +        {
  3.1421 +            requestOfflineMessagesLegacy();
  3.1422 +        }
  3.1423 +        else
  3.1424 +        {
  3.1425 +            LLCoros::instance().launch("LLIMProcessing::requestOfflineMessagesCoro",
  3.1426 +                boost::bind(&LLIMProcessing::requestOfflineMessagesCoro, cap_url));
  3.1427 +        }
  3.1428 +        requested = TRUE;
  3.1429 +    }
  3.1430 +}
  3.1431 +
  3.1432 +void LLIMProcessing::requestOfflineMessagesCoro(std::string url)
  3.1433 +{
  3.1434 +    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
  3.1435 +    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
  3.1436 +        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("requestOfflineMessagesCoro", httpPolicy));
  3.1437 +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
  3.1438 +
  3.1439 +    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
  3.1440 +
  3.1441 +    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
  3.1442 +    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
  3.1443 +
  3.1444 +    if (!status) // success = httpResults["success"].asBoolean();
  3.1445 +    {
  3.1446 +        LL_WARNS() << "Error requesting offline messages via capability " << url << ", Status: " << status.toString() << "\nFalling back to legacy method." << LL_ENDL;
  3.1447 +
  3.1448 +        requestOfflineMessagesLegacy();
  3.1449 +        return;
  3.1450 +    }
  3.1451 +
  3.1452 +    LLSD contents = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT];
  3.1453 +
  3.1454 +    if (!contents.size())
  3.1455 +    {
  3.1456 +        LL_WARNS() << "No contents received for offline messages via capability " << url << LL_ENDL;
  3.1457 +        return;
  3.1458 +    }
  3.1459 +
  3.1460 +    LLSD messages;
  3.1461 +    if (contents.isArray())
  3.1462 +    {
  3.1463 +        messages = *contents.beginArray();
  3.1464 +    }
  3.1465 +    else if (contents.has("messages"))
  3.1466 +    {
  3.1467 +        messages = contents["messages"];
  3.1468 +    }
  3.1469 +    else
  3.1470 +    {
  3.1471 +        LL_WARNS() << "Invalid offline message content received via capability " << url << LL_ENDL;
  3.1472 +        return;
  3.1473 +    }
  3.1474 +
  3.1475 +    if (!messages.isArray())
  3.1476 +    {
  3.1477 +        LL_WARNS() << "Invalid offline message content received via capability " << url << LL_ENDL;
  3.1478 +        return;
  3.1479 +    }
  3.1480 +
  3.1481 +    std::vector<U8> data;
  3.1482 +    S32 binary_bucket_size = 0;
  3.1483 +    LLHost sender = gAgent.getRegion()->getHost();
  3.1484 +
  3.1485 +    LLSD::array_iterator i = messages.beginArray();
  3.1486 +    LLSD::array_iterator iEnd = messages.endArray();
  3.1487 +    for (; i != iEnd; ++i)
  3.1488 +    {
  3.1489 +        const LLSD &message_data(*i);
  3.1490 +        LLVector3 position(message_data["local_x"].asReal(), message_data["local_y"].asReal(), message_data["local_z"].asReal());
  3.1491 +        data = message_data["binary_bucket"].asBinary();
  3.1492 +        binary_bucket_size = data.size(); // message_data["count"] == data.size() - 1 due to ('\0')
  3.1493 +        U32 parent_estate_id = message_data.has("parent_estate_id") ? message_data["ParentEstateID"].asInteger() : 1; // 1 - IMMainland
  3.1494 +
  3.1495 +        LLIMProcessing::processNewMessage(message_data["from_agent_id"].asUUID(),
  3.1496 +            message_data["from_group"].asInteger(), // BOOL
  3.1497 +            message_data["to_agent_id"].asUUID(),
  3.1498 +            IM_OFFLINE,
  3.1499 +            (EInstantMessage)message_data["dialog"].asInteger(),
  3.1500 +            message_data["session_id"].asUUID(),
  3.1501 +            message_data["timestamp"].asInteger(),
  3.1502 +            message_data["from_agent_name"].asString(),
  3.1503 +            message_data["message"].asString(),
  3.1504 +            parent_estate_id,
  3.1505 +            message_data["region_id"].asUUID(),
  3.1506 +            position,
  3.1507 +            &data[0],
  3.1508 +            binary_bucket_size,
  3.1509 +            sender);
  3.1510 +    }
  3.1511 +}
  3.1512 +
  3.1513 +void LLIMProcessing::requestOfflineMessagesLegacy()
  3.1514 +{
  3.1515 +    LLMessageSystem* msg = gMessageSystem;
  3.1516 +    msg->newMessageFast(_PREHASH_RetrieveInstantMessages);
  3.1517 +    msg->nextBlockFast(_PREHASH_AgentData);
  3.1518 +    msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  3.1519 +    msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  3.1520 +    gAgent.sendReliableMessage();
  3.1521 +}
  3.1522 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/indra/newview/llimprocessing.h	Tue Feb 13 15:40:21 2018 +0200
     4.3 @@ -0,0 +1,62 @@
     4.4 +/**
     4.5 +* @file LLIMMgr.h
     4.6 +* @brief Container for Instant Messaging
     4.7 +*
     4.8 +* $LicenseInfo:firstyear=2001&license=viewerlgpl$
     4.9 +* Second Life Viewer Source Code
    4.10 +* Copyright (C) 2010, Linden Research, Inc.
    4.11 +*
    4.12 +* This library is free software; you can redistribute it and/or
    4.13 +* modify it under the terms of the GNU Lesser General Public
    4.14 +* License as published by the Free Software Foundation;
    4.15 +* version 2.1 of the License only.
    4.16 +*
    4.17 +* This library is distributed in the hope that it will be useful,
    4.18 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.19 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    4.20 +* Lesser General Public License for more details.
    4.21 +*
    4.22 +* You should have received a copy of the GNU Lesser General Public
    4.23 +* License along with this library; if not, write to the Free Software
    4.24 +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
    4.25 +*
    4.26 +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
    4.27 +* $/LicenseInfo$
    4.28 +*/
    4.29 +
    4.30 +#ifndef LL_LLIMPROCESSING_H
    4.31 +#define LL_LLIMPROCESSING_H
    4.32 +
    4.33 +#include "llinstantmessage.h"
    4.34 +
    4.35 +class LLIMProcessing
    4.36 +{
    4.37 +public:
    4.38 +    // Pre-process message for IM manager
    4.39 +    static void processNewMessage(LLUUID from_id,
    4.40 +        BOOL from_group,
    4.41 +        LLUUID to_id,
    4.42 +        U8 offline,
    4.43 +        EInstantMessage dialog, // U8
    4.44 +        LLUUID session_id,
    4.45 +        U32 timestamp,
    4.46 +        std::string agentName,
    4.47 +        std::string message,
    4.48 +        U32 parent_estate_id,
    4.49 +        LLUUID region_id,
    4.50 +        LLVector3 position,
    4.51 +        U8 *binary_bucket,
    4.52 +        S32 binary_bucket_size,
    4.53 +        LLHost &sender);
    4.54 +
    4.55 +    // Either receives list of offline messages from 'ReadOfflineMsgs' capability
    4.56 +    // or uses legacy method
    4.57 +    static void requestOfflineMessages();
    4.58 +
    4.59 +private:
    4.60 +    static void requestOfflineMessagesCoro(std::string url);
    4.61 +    static void requestOfflineMessagesLegacy();
    4.62 +};
    4.63 +
    4.64 +
    4.65 +#endif  // LL_LLLLIMPROCESSING_H
     5.1 --- a/indra/newview/llviewermessage.cpp	Fri Mar 09 16:57:47 2018 +0200
     5.2 +++ b/indra/newview/llviewermessage.cpp	Tue Feb 13 15:40:21 2018 +0200
     5.3 @@ -26,7 +26,6 @@
     5.4  
     5.5  #include "llviewerprecompiledheaders.h"
     5.6  #include "llviewermessage.h"
     5.7 -#include "boost/lexical_cast.hpp"
     5.8  
     5.9  // Linden libraries
    5.10  #include "llanimationstates.h"
    5.11 @@ -66,7 +65,7 @@
    5.12  #include "llfloatersnapshot.h"
    5.13  #include "llhudeffecttrail.h"
    5.14  #include "llhudmanager.h"
    5.15 -#include "llimview.h"
    5.16 +#include "llimprocessing.h"
    5.17  #include "llinventoryfunctions.h"
    5.18  #include "llinventoryobserver.h"
    5.19  #include "llinventorypanel.h"
    5.20 @@ -116,7 +115,6 @@
    5.21  #include "llfloaterregionrestarting.h"
    5.22  
    5.23  #include <boost/algorithm/string/split.hpp> //
    5.24 -#include <boost/regex.hpp>
    5.25  #include <boost/foreach.hpp>
    5.26  
    5.27  #include "llnotificationmanager.h" //
    5.28 @@ -124,11 +122,6 @@
    5.29  
    5.30  #include "llexperiencecache.h"
    5.31  
    5.32 -#if LL_MSVC
    5.33 -// disable boost::lexical_cast warning
    5.34 -#pragma warning (disable:4702)
    5.35 -#endif
    5.36 -
    5.37  extern void on_new_message(const LLSD& msg);
    5.38  
    5.39  //
    5.40 @@ -1883,18 +1876,6 @@
    5.41  	return false;
    5.42  }
    5.43  
    5.44 -class LLPostponedOfferNotification: public LLPostponedNotification
    5.45 -{
    5.46 -protected:
    5.47 -	/* virtual */
    5.48 -	void modifyNotificationParams()
    5.49 -	{
    5.50 -		LLSD substitutions = mParams.substitutions;
    5.51 -		substitutions["NAME"] = mName;
    5.52 -		mParams.substitutions = substitutions;
    5.53 -	}
    5.54 -};
    5.55 -
    5.56  void LLOfferInfo::initRespondFunctionMap()
    5.57  {
    5.58  	if(mRespondFunctions.empty())
    5.59 @@ -1905,153 +1886,6 @@
    5.60  	}
    5.61  }
    5.62  
    5.63 -void inventory_offer_handler(LLOfferInfo* info)
    5.64 -{
    5.65 -	// If muted, don't even go through the messaging stuff.  Just curtail the offer here.
    5.66 -	// Passing in a null UUID handles the case of where you have muted one of your own objects by_name.
    5.67 -	// The solution for STORM-1297 seems to handle the cases where the object is owned by someone else.
    5.68 -	if (LLMuteList::getInstance()->isMuted(info->mFromID, info->mFromName) ||
    5.69 -		LLMuteList::getInstance()->isMuted(LLUUID::null, info->mFromName))
    5.70 -	{
    5.71 -		info->forceResponse(IOR_MUTE);
    5.72 -		return;
    5.73 -	}
    5.74 -
    5.75 -	bool bAutoAccept(false);
    5.76 -	// Avoid the Accept/Discard dialog if the user so desires. JC
    5.77 -	if (gSavedSettings.getBOOL("AutoAcceptNewInventory")
    5.78 -		&& (info->mType == LLAssetType::AT_NOTECARD
    5.79 -			|| info->mType == LLAssetType::AT_LANDMARK
    5.80 -			|| info->mType == LLAssetType::AT_TEXTURE))
    5.81 -	{
    5.82 -		// For certain types, just accept the items into the inventory,
    5.83 -		// and possibly open them on receipt depending upon "ShowNewInventory".
    5.84 -		bAutoAccept = true;
    5.85 -	}
    5.86 -
    5.87 -	// Strip any SLURL from the message display. (DEV-2754)
    5.88 -	std::string msg = info->mDesc;
    5.89 -	int indx = msg.find(" ( http://slurl.com/secondlife/");
    5.90 -	if(indx == std::string::npos)
    5.91 -	{
    5.92 -		// try to find new slurl host
    5.93 -		indx = msg.find(" ( http://maps.secondlife.com/secondlife/");
    5.94 -	}
    5.95 -	if(indx >= 0)
    5.96 -	{
    5.97 -		LLStringUtil::truncate(msg, indx);
    5.98 -	}
    5.99 -
   5.100 -	LLSD args;
   5.101 -	args["[OBJECTNAME]"] = msg;
   5.102 -
   5.103 -	LLSD payload;
   5.104 -
   5.105 -	// must protect against a NULL return from lookupHumanReadable()
   5.106 -	std::string typestr = ll_safe_string(LLAssetType::lookupHumanReadable(info->mType));
   5.107 -	if (!typestr.empty())
   5.108 -	{
   5.109 -		// human readable matches string name from strings.xml
   5.110 -		// lets get asset type localized name
   5.111 -		args["OBJECTTYPE"] = LLTrans::getString(typestr);
   5.112 -	}
   5.113 -	else
   5.114 -	{
   5.115 -		LL_WARNS("Messaging") << "LLAssetType::lookupHumanReadable() returned NULL - probably bad asset type: " << info->mType << LL_ENDL;
   5.116 -		args["OBJECTTYPE"] = "";
   5.117 -
   5.118 -		// This seems safest, rather than propagating bogosity
   5.119 -		LL_WARNS("Messaging") << "Forcing an inventory-decline for probably-bad asset type." << LL_ENDL;
   5.120 -		info->forceResponse(IOR_DECLINE);
   5.121 -		return;
   5.122 -	}
   5.123 -
   5.124 -	// If mObjectID is null then generate the object_id based on msg to prevent
   5.125 -	// multiple creation of chiclets for same object.
   5.126 -	LLUUID object_id = info->mObjectID;
   5.127 -	if (object_id.isNull())
   5.128 -		object_id.generate(msg);
   5.129 -
   5.130 -	payload["from_id"] = info->mFromID;
   5.131 -	// Needed by LLScriptFloaterManager to bind original notification with 
   5.132 -	// faked for toast one.
   5.133 -	payload["object_id"] = object_id;
   5.134 -	// Flag indicating that this notification is faked for toast.
   5.135 -	payload["give_inventory_notification"] = FALSE;
   5.136 -	args["OBJECTFROMNAME"] = info->mFromName;
   5.137 -	args["NAME"] = info->mFromName;
   5.138 -	if (info->mFromGroup)
   5.139 -	{
   5.140 -		args["NAME_SLURL"] = LLSLURL("group", info->mFromID, "about").getSLURLString();
   5.141 -	}
   5.142 -	else
   5.143 -	{
   5.144 -		args["NAME_SLURL"] = LLSLURL("agent", info->mFromID, "about").getSLURLString();
   5.145 -	}
   5.146 -	std::string verb = "select?name=" + LLURI::escape(msg);
   5.147 -	args["ITEM_SLURL"] = LLSLURL("inventory", info->mObjectID, verb.c_str()).getSLURLString();
   5.148 -
   5.149 -	LLNotification::Params p;
   5.150 -
   5.151 -	// Object -> Agent Inventory Offer
   5.152 -	if (info->mFromObject && !bAutoAccept)
   5.153 -	{
   5.154 -		// Inventory Slurls don't currently work for non agent transfers, so only display the object name.
   5.155 -		args["ITEM_SLURL"] = msg;
   5.156 -		// Note: sets inventory_task_offer_callback as the callback
   5.157 -		p.substitutions(args).payload(payload).functor.responder(LLNotificationResponderPtr(info));
   5.158 -		info->mPersist = true;
   5.159 -
   5.160 -		// Offers from your own objects need a special notification template.
   5.161 -		p.name = info->mFromID == gAgentID ? "OwnObjectGiveItem" : "ObjectGiveItem";
   5.162 -
   5.163 -		// Pop up inv offer chiclet and let the user accept (keep), or reject (and silently delete) the inventory.
   5.164 -	    LLPostponedNotification::add<LLPostponedOfferNotification>(p, info->mFromID, info->mFromGroup == TRUE);
   5.165 -	}
   5.166 -	else // Agent -> Agent Inventory Offer
   5.167 -	{
   5.168 -		p.responder = info;
   5.169 -		// Note: sets inventory_offer_callback as the callback
   5.170 -		// *TODO fix memory leak
   5.171 -		// inventory_offer_callback() is not invoked if user received notification and 
   5.172 -		// closes viewer(without responding the notification)
   5.173 -		p.substitutions(args).payload(payload).functor.responder(LLNotificationResponderPtr(info));
   5.174 -		info->mPersist = true;
   5.175 -		p.name = "UserGiveItem";
   5.176 -		p.offer_from_agent = true;
   5.177 -		
   5.178 -		// Prefetch the item into your local inventory.
   5.179 -		LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID);
   5.180 -		fetch_item->startFetch();
   5.181 -		if(fetch_item->isFinished())
   5.182 -		{
   5.183 -			fetch_item->done();
   5.184 -		}
   5.185 -		else
   5.186 -		{
   5.187 -			gInventory.addObserver(fetch_item);
   5.188 -		}
   5.189 -		
   5.190 -		// In viewer 2 we're now auto receiving inventory offers and messaging as such (not sending reject messages).
   5.191 -		info->send_auto_receive_response();
   5.192 -
   5.193 -        if (gAgent.isDoNotDisturb()) 
   5.194 -        {
   5.195 -            send_do_not_disturb_message(gMessageSystem, info->mFromID);
   5.196 -        }
   5.197 -
   5.198 -		if( !bAutoAccept ) // if we auto accept, do not pester the user
   5.199 -		{
   5.200 -			// Inform user that there is a script floater via toast system
   5.201 -			payload["give_inventory_notification"] = TRUE;
   5.202 -			p.payload = payload;
   5.203 -			LLPostponedNotification::add<LLPostponedOfferNotification>(p, info->mFromID, false);
   5.204 -		}
   5.205 -	}
   5.206 -
   5.207 -	LLFirstUse::newInventory();
   5.208 -}
   5.209 -
   5.210  bool lure_callback(const LLSD& notification, const LLSD& response)
   5.211  {
   5.212  	S32 option = 0;
   5.213 @@ -2175,1212 +2009,57 @@
   5.214  	}
   5.215  };
   5.216  
   5.217 -static bool parse_lure_bucket(const std::string& bucket,
   5.218 -							  U64& region_handle,
   5.219 -							  LLVector3& pos,
   5.220 -							  LLVector3& look_at,
   5.221 -							  U8& region_access)
   5.222 -{
   5.223 -	// tokenize the bucket
   5.224 -	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
   5.225 -	boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
   5.226 -	tokenizer tokens(bucket, sep);
   5.227 -	tokenizer::iterator iter = tokens.begin();
   5.228 -
   5.229 -	S32 gx,gy,rx,ry,rz,lx,ly,lz;
   5.230 -	try
   5.231 -	{
   5.232 -		gx = boost::lexical_cast<S32>((*(iter)).c_str());
   5.233 -		gy = boost::lexical_cast<S32>((*(++iter)).c_str());
   5.234 -		rx = boost::lexical_cast<S32>((*(++iter)).c_str());
   5.235 -		ry = boost::lexical_cast<S32>((*(++iter)).c_str());
   5.236 -		rz = boost::lexical_cast<S32>((*(++iter)).c_str());
   5.237 -		lx = boost::lexical_cast<S32>((*(++iter)).c_str());
   5.238 -		ly = boost::lexical_cast<S32>((*(++iter)).c_str());
   5.239 -		lz = boost::lexical_cast<S32>((*(++iter)).c_str());
   5.240 -	}
   5.241 -	catch( boost::bad_lexical_cast& )
   5.242 -	{
   5.243 -		LL_WARNS("parse_lure_bucket")
   5.244 -			<< "Couldn't parse lure bucket."
   5.245 -			<< LL_ENDL;
   5.246 -		return false;
   5.247 -	}
   5.248 -	// Grab region access
   5.249 -	region_access = SIM_ACCESS_MIN;
   5.250 -	if (++iter != tokens.end())
   5.251 -	{
   5.252 -		std::string access_str((*iter).c_str());
   5.253 -		LLStringUtil::trim(access_str);
   5.254 -		if ( access_str == "A" )
   5.255 -		{
   5.256 -			region_access = SIM_ACCESS_ADULT;
   5.257 -		}
   5.258 -		else if ( access_str == "M" )
   5.259 -		{
   5.260 -			region_access = SIM_ACCESS_MATURE;
   5.261 -		}
   5.262 -		else if ( access_str == "PG" )
   5.263 -		{
   5.264 -			region_access = SIM_ACCESS_PG;
   5.265 -		}
   5.266 -	}
   5.267 -
   5.268 -	pos.setVec((F32)rx, (F32)ry, (F32)rz);
   5.269 -	look_at.setVec((F32)lx, (F32)ly, (F32)lz);
   5.270 -
   5.271 -	region_handle = to_region_handle(gx, gy);
   5.272 -	return true;
   5.273 -}
   5.274 -
   5.275 -// Strip out "Resident" for display, but only if the message came from a user
   5.276 -// (rather than a script)
   5.277 -static std::string clean_name_from_im(const std::string& name, EInstantMessage type)
   5.278 -{
   5.279 -	switch(type)
   5.280 -	{
   5.281 -	case IM_NOTHING_SPECIAL:
   5.282 -	case IM_MESSAGEBOX:
   5.283 -	case IM_GROUP_INVITATION:
   5.284 -	case IM_INVENTORY_OFFERED:
   5.285 -	case IM_INVENTORY_ACCEPTED:
   5.286 -	case IM_INVENTORY_DECLINED:
   5.287 -	case IM_GROUP_VOTE:
   5.288 -	case IM_GROUP_MESSAGE_DEPRECATED:
   5.289 -	//IM_TASK_INVENTORY_OFFERED
   5.290 -	//IM_TASK_INVENTORY_ACCEPTED
   5.291 -	//IM_TASK_INVENTORY_DECLINED
   5.292 -	case IM_NEW_USER_DEFAULT:
   5.293 -	case IM_SESSION_INVITE:
   5.294 -	case IM_SESSION_P2P_INVITE:
   5.295 -	case IM_SESSION_GROUP_START:
   5.296 -	case IM_SESSION_CONFERENCE_START:
   5.297 -	case IM_SESSION_SEND:
   5.298 -	case IM_SESSION_LEAVE:
   5.299 -	//IM_FROM_TASK
   5.300 -	case IM_DO_NOT_DISTURB_AUTO_RESPONSE:
   5.301 -	case IM_CONSOLE_AND_CHAT_HISTORY:
   5.302 -	case IM_LURE_USER:
   5.303 -	case IM_LURE_ACCEPTED:
   5.304 -	case IM_LURE_DECLINED:
   5.305 -	case IM_GODLIKE_LURE_USER:
   5.306 -	case IM_TELEPORT_REQUEST:
   5.307 -	case IM_GROUP_ELECTION_DEPRECATED:
   5.308 -	//IM_GOTO_URL
   5.309 -	//IM_FROM_TASK_AS_ALERT
   5.310 -	case IM_GROUP_NOTICE:
   5.311 -	case IM_GROUP_NOTICE_INVENTORY_ACCEPTED:
   5.312 -	case IM_GROUP_NOTICE_INVENTORY_DECLINED:
   5.313 -	case IM_GROUP_INVITATION_ACCEPT:
   5.314 -	case IM_GROUP_INVITATION_DECLINE:
   5.315 -	case IM_GROUP_NOTICE_REQUESTED:
   5.316 -	case IM_FRIENDSHIP_OFFERED:
   5.317 -	case IM_FRIENDSHIP_ACCEPTED:
   5.318 -	case IM_FRIENDSHIP_DECLINED_DEPRECATED:
   5.319 -	//IM_TYPING_START
   5.320 -	//IM_TYPING_STOP
   5.321 -		return LLCacheName::cleanFullName(name);
   5.322 -	default:
   5.323 -		return name;
   5.324 -	}
   5.325 -}
   5.326 -
   5.327 -static std::string clean_name_from_task_im(const std::string& msg,
   5.328 -										   BOOL from_group)
   5.329 -{
   5.330 -	boost::smatch match;
   5.331 -	static const boost::regex returned_exp(
   5.332 -		"(.*been returned to your inventory lost and found folder by )(.+)( (from|near).*)");
   5.333 -	if (boost::regex_match(msg, match, returned_exp))
   5.334 -	{
   5.335 -		// match objects are 1-based for groups
   5.336 -		std::string final = match[1].str();
   5.337 -		std::string name = match[2].str();
   5.338 -		// Don't try to clean up group names
   5.339 -		if (!from_group)
   5.340 -		{
   5.341 -			final += LLCacheName::buildUsername(name);
   5.342 -		}
   5.343 -		final += match[3].str();
   5.344 -		return final;
   5.345 -	}
   5.346 -	return msg;
   5.347 -}
   5.348 -
   5.349 -static void notification_display_name_callback(const LLUUID& id,
   5.350 -					  const LLAvatarName& av_name,
   5.351 -					  const std::string& name, 
   5.352 -					  LLSD& substitutions, 
   5.353 -					  const LLSD& payload)
   5.354 -{
   5.355 -	substitutions["NAME"] = av_name.getDisplayName();
   5.356 -	LLNotificationsUtil::add(name, substitutions, payload);
   5.357 -}
   5.358 -
   5.359 -class LLPostponedIMSystemTipNotification: public LLPostponedNotification
   5.360 -{
   5.361 -protected:
   5.362 -	/* virtual */
   5.363 -	void modifyNotificationParams()
   5.364 -	{
   5.365 -		LLSD payload = mParams.payload;
   5.366 -		payload["SESSION_NAME"] = mName;
   5.367 -		mParams.payload = payload;
   5.368 -	}
   5.369 -
   5.370 -};
   5.371 -
   5.372 -// Callback for name resolution of a god/estate message
   5.373 -static void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string message)
   5.374 -{	
   5.375 -	LLSD args;
   5.376 -	args["NAME"] = av_name.getCompleteName();
   5.377 -	args["MESSAGE"] = message;
   5.378 -	LLNotificationsUtil::add("GodMessage", args);
   5.379 -
   5.380 -	// Treat like a system message and put in chat history.
   5.381 -	chat.mSourceType = CHAT_SOURCE_SYSTEM;
   5.382 -	chat.mText = message;
   5.383 -
   5.384 -	LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
   5.385 -	if (nearby_chat)
   5.386 -	{
   5.387 -		nearby_chat->addMessage(chat);
   5.388 -	}
   5.389 -}
   5.390 -
   5.391 -const std::string NOT_ONLINE_MSG("User not online - message will be stored and delivered later.");
   5.392 -const std::string NOT_ONLINE_INVENTORY("User not online - inventory has been saved.");
   5.393 -void translate_if_needed(std::string& message)
   5.394 -{
   5.395 -	if (message == NOT_ONLINE_MSG)
   5.396 -	{
   5.397 -		message = LLTrans::getString("not_online_msg");
   5.398 -	}
   5.399 -	else if (message == NOT_ONLINE_INVENTORY)
   5.400 -	{
   5.401 -		message = LLTrans::getString("not_online_inventory");
   5.402 -	}
   5.403 -}
   5.404 -
   5.405  void process_improved_im(LLMessageSystem *msg, void **user_data)
   5.406  {
   5.407 -	LLUUID from_id;
   5.408 -	BOOL from_group;
   5.409 -	LLUUID to_id;
   5.410 -	U8 offline;
   5.411 -	U8 d = 0;
   5.412 -	LLUUID session_id;
   5.413 -	U32 timestamp;
   5.414 -	std::string name;
   5.415 -	std::string message;
   5.416 -	U32 parent_estate_id = 0;
   5.417 -	LLUUID region_id;
   5.418 -	LLVector3 position;
   5.419 -	U8 binary_bucket[MTUBYTES];
   5.420 -	S32 binary_bucket_size;
   5.421 -	LLChat chat;
   5.422 -	std::string buffer;
   5.423 -	
   5.424 -	// *TODO: Translate - need to fix the full name to first/last (maybe)
   5.425 -	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, from_id);
   5.426 -	msg->getBOOLFast(_PREHASH_MessageBlock, _PREHASH_FromGroup, from_group);
   5.427 -	msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ToAgentID, to_id);
   5.428 -	msg->getU8Fast(  _PREHASH_MessageBlock, _PREHASH_Offline, offline);
   5.429 -	msg->getU8Fast(  _PREHASH_MessageBlock, _PREHASH_Dialog, d);
   5.430 -	msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ID, session_id);
   5.431 -	msg->getU32Fast( _PREHASH_MessageBlock, _PREHASH_Timestamp, timestamp);
   5.432 -	//msg->getData("MessageBlock", "Count",		&count);
   5.433 -	msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_FromAgentName, name);
   5.434 -	msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_Message,		message);
   5.435 -	msg->getU32Fast(_PREHASH_MessageBlock, _PREHASH_ParentEstateID, parent_estate_id);
   5.436 -	msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_RegionID, region_id);
   5.437 -	msg->getVector3Fast(_PREHASH_MessageBlock, _PREHASH_Position, position);
   5.438 -	msg->getBinaryDataFast(  _PREHASH_MessageBlock, _PREHASH_BinaryBucket, binary_bucket, 0, 0, MTUBYTES);
   5.439 -	binary_bucket_size = msg->getSizeFast(_PREHASH_MessageBlock, _PREHASH_BinaryBucket);
   5.440 -	EInstantMessage dialog = (EInstantMessage)d;
   5.441 -
   5.442 -    // make sure that we don't have an empty or all-whitespace name
   5.443 -	LLStringUtil::trim(name);
   5.444 -	if (name.empty())
   5.445 -	{
   5.446 -        name = LLTrans::getString("Unnamed");
   5.447 -	}
   5.448 -
   5.449 -	// Preserve the unaltered name for use in group notice mute checking.
   5.450 -	std::string original_name = name;
   5.451 -
   5.452 -	// IDEVO convert new-style "Resident" names for display
   5.453 -	name = clean_name_from_im(name, dialog);
   5.454 -
   5.455 -	BOOL is_do_not_disturb = gAgent.isDoNotDisturb();
   5.456 -	BOOL is_muted = LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat)
   5.457 -		// object IMs contain sender object id in session_id (STORM-1209)
   5.458 -		|| (dialog == IM_FROM_TASK && LLMuteList::getInstance()->isMuted(session_id));
   5.459 -	BOOL is_owned_by_me = FALSE;
   5.460 -	BOOL is_friend = (LLAvatarTracker::instance().getBuddyInfo(from_id) == NULL) ? false : true;
   5.461 -	BOOL accept_im_from_only_friend = gSavedSettings.getBOOL("VoiceCallsFriendsOnly");
   5.462 -	BOOL is_linden = chat.mSourceType != CHAT_SOURCE_OBJECT &&
   5.463 -			LLMuteList::getInstance()->isLinden(name);
   5.464 -
   5.465 -	chat.mMuted = is_muted;
   5.466 -	chat.mFromID = from_id;
   5.467 -	chat.mFromName = name;
   5.468 -	chat.mSourceType = (from_id.isNull() || (name == std::string(SYSTEM_FROM))) ? CHAT_SOURCE_SYSTEM : CHAT_SOURCE_AGENT;
   5.469 -	
   5.470 -	if (chat.mSourceType == CHAT_SOURCE_SYSTEM)
   5.471 -	{ // Translate server message if required (MAINT-6109)
   5.472 -		translate_if_needed(message);
   5.473 -	}
   5.474 -
   5.475 -	LLViewerObject *source = gObjectList.findObject(session_id); //Session ID is probably the wrong thing.
   5.476 -	if (source)
   5.477 -	{
   5.478 -		is_owned_by_me = source->permYouOwner();
   5.479 -	}
   5.480 -
   5.481 -	std::string separator_string(": ");
   5.482 -
   5.483 -	LLSD args;
   5.484 -	LLSD payload;
   5.485 -	LLNotification::Params params;
   5.486 -
   5.487 -	switch(dialog)
   5.488 -	{ 
   5.489 -	case IM_CONSOLE_AND_CHAT_HISTORY:
   5.490 -		args["MESSAGE"] = message;
   5.491 -		payload["from_id"] = from_id;
   5.492 -
   5.493 -		params.name = "IMSystemMessageTip";
   5.494 -		params.substitutions = args;
   5.495 -		params.payload = payload;
   5.496 -	    LLPostponedNotification::add<LLPostponedIMSystemTipNotification>(params, from_id, false);
   5.497 -		break;
   5.498 -
   5.499 -	case IM_NOTHING_SPECIAL:	// p2p IM
   5.500 -		// Don't show dialog, just do IM
   5.501 -		if (!gAgent.isGodlike()
   5.502 -				&& gAgent.getRegion()->isPrelude() 
   5.503 -				&& to_id.isNull() )
   5.504 -		{
   5.505 -			// do nothing -- don't distract newbies in
   5.506 -			// Prelude with global IMs
   5.507 -		}
   5.508 -		else if (offline == IM_ONLINE 
   5.509 -					&& is_do_not_disturb
   5.510 -					&& from_id.notNull() //not a system message
   5.511 -					&& to_id.notNull()) //not global message
   5.512 -		{
   5.513 -
   5.514 -			// now store incoming IM in chat history
   5.515 -
   5.516 -			buffer = message;
   5.517 -	
   5.518 -			LL_DEBUGS("Messaging") << "session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
   5.519 -
   5.520 -			// add to IM panel, but do not bother the user
   5.521 -			gIMMgr->addMessage(
   5.522 -				session_id,
   5.523 -				from_id,
   5.524 -				name,
   5.525 -				buffer,
   5.526 -				IM_OFFLINE == offline,
   5.527 -				LLStringUtil::null,
   5.528 -				dialog,
   5.529 -				parent_estate_id,
   5.530 -				region_id,
   5.531 -				position,
   5.532 -				true);
   5.533 -
   5.534 -			if (!gIMMgr->isDNDMessageSend(session_id))
   5.535 -			{
   5.536 -				// return a standard "do not disturb" message, but only do it to online IM
   5.537 -				// (i.e. not other auto responses and not store-and-forward IM)
   5.538 -				send_do_not_disturb_message(msg, from_id, session_id);
   5.539 -				gIMMgr->setDNDMessageSent(session_id, true);
   5.540 -			}
   5.541 -
   5.542 -		}
   5.543 -		else if (from_id.isNull())
   5.544 -		{
   5.545 -			LLSD args;
   5.546 -			args["MESSAGE"] = message;
   5.547 -			LLNotificationsUtil::add("SystemMessage", args);
   5.548 -		}
   5.549 -		else if (to_id.isNull())
   5.550 -		{
   5.551 -			// Message to everyone from GOD, look up the fullname since
   5.552 -			// server always slams name to legacy names
   5.553 -			LLAvatarNameCache::get(from_id, boost::bind(god_message_name_cb, _2, chat, message));
   5.554 -		}
   5.555 -		else
   5.556 -		{
   5.557 -			// standard message, not from system
   5.558 -			std::string saved;
   5.559 -			if(offline == IM_OFFLINE)
   5.560 -			{
   5.561 -				LLStringUtil::format_map_t args;
   5.562 -				args["[LONG_TIMESTAMP]"] = formatted_time(timestamp);
   5.563 -				saved = LLTrans::getString("Saved_message", args);
   5.564 -			}
   5.565 -			buffer = saved + message;
   5.566 -
   5.567 -			LL_DEBUGS("Messaging") << "session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
   5.568 -
   5.569 -			bool mute_im = is_muted;
   5.570 -			if(accept_im_from_only_friend && !is_friend && !is_linden)
   5.571 -			{
   5.572 -				if (!gIMMgr->isNonFriendSessionNotified(session_id))
   5.573 -				{
   5.574 -					std::string message = LLTrans::getString("IM_unblock_only_groups_friends");
   5.575 -					gIMMgr->addMessage(session_id, from_id, name, message, IM_OFFLINE == offline);
   5.576 -					gIMMgr->addNotifiedNonFriendSessionID(session_id);
   5.577 -				}
   5.578 -
   5.579 -				mute_im = true;
   5.580 -			}
   5.581 -			if (!mute_im) 
   5.582 -			{
   5.583 -				gIMMgr->addMessage(
   5.584 -					session_id,
   5.585 -					from_id,
   5.586 -					name,
   5.587 -					buffer,
   5.588 -					IM_OFFLINE == offline,
   5.589 -					LLStringUtil::null,
   5.590 -					dialog,
   5.591 -					parent_estate_id,
   5.592 -					region_id,
   5.593 -					position,
   5.594 -					true);
   5.595 -			}
   5.596 -			else
   5.597 -			{
   5.598 -				/*
   5.599 -				EXT-5099
   5.600 -				currently there is no way to store in history only...
   5.601 -				using  LLNotificationsUtil::add will add message to Nearby Chat
   5.602 -
   5.603 -				// muted user, so don't start an IM session, just record line in chat
   5.604 -				// history.  Pretend the chat is from a local agent,
   5.605 -				// so it will go into the history but not be shown on screen.
   5.606 -
   5.607 -				LLSD args;
   5.608 -				args["MESSAGE"] = buffer;
   5.609 -				LLNotificationsUtil::add("SystemMessageTip", args);
   5.610 -				*/
   5.611 -			}
   5.612 -		}
   5.613 -		break;
   5.614 -
   5.615 -	case IM_TYPING_START:
   5.616 -		{
   5.617 -			LLPointer<LLIMInfo> im_info = new LLIMInfo(gMessageSystem);
   5.618 -			gIMMgr->processIMTypingStart(im_info);
   5.619 -		}
   5.620 -		break;
   5.621 -
   5.622 -	case IM_TYPING_STOP:
   5.623 -		{
   5.624 -			LLPointer<LLIMInfo> im_info = new LLIMInfo(gMessageSystem);
   5.625 -			gIMMgr->processIMTypingStop(im_info);
   5.626 -		}
   5.627 -		break;
   5.628 -
   5.629 -	case IM_MESSAGEBOX:
   5.630 -		{
   5.631 -			// This is a block, modeless dialog.
   5.632 -			//*TODO: Translate
   5.633 -			args["MESSAGE"] = message;
   5.634 -			LLNotificationsUtil::add("SystemMessageTip", args);
   5.635 -		}
   5.636 -		break;
   5.637 -	case IM_GROUP_NOTICE:
   5.638 -	case IM_GROUP_NOTICE_REQUESTED:
   5.639 -		{
   5.640 -			LL_INFOS("Messaging") << "Received IM_GROUP_NOTICE message." << LL_ENDL;
   5.641 -			// Read the binary bucket for more information.
   5.642 -			struct notice_bucket_header_t
   5.643 -			{
   5.644 -				U8 has_inventory;
   5.645 -				U8 asset_type;
   5.646 -				LLUUID group_id;
   5.647 -			};
   5.648 -			struct notice_bucket_full_t
   5.649 -			{
   5.650 -				struct notice_bucket_header_t header;
   5.651 -				U8 item_name[DB_INV_ITEM_NAME_BUF_SIZE];
   5.652 -			}* notice_bin_bucket;
   5.653 -
   5.654 -			// Make sure the binary bucket is big enough to hold the header 
   5.655 -			// and a null terminated item name.
   5.656 -			if ( (binary_bucket_size < (S32)((sizeof(notice_bucket_header_t) + sizeof(U8))))
   5.657 -				|| (binary_bucket[binary_bucket_size - 1] != '\0') )
   5.658 -			{
   5.659 -				LL_WARNS("Messaging") << "Malformed group notice binary bucket" << LL_ENDL;
   5.660 -				break;
   5.661 -			}
   5.662 -
   5.663 -			// The group notice packet does not have an AgentID.  Obtain one from the name cache.
   5.664 -			// If last name is "Resident" strip it out so the cache name lookup works.
   5.665 -			std::string::size_type index = original_name.find(" Resident");
   5.666 -			if (index != std::string::npos)
   5.667 -			{
   5.668 -				original_name = original_name.substr(0, index);
   5.669 -			}
   5.670 -
   5.671 -			std::string legacy_name = gCacheName->buildLegacyName(original_name);
   5.672 -			LLUUID agent_id = LLAvatarNameCache::findIdByName(legacy_name);
   5.673 -
   5.674 -			if (agent_id.isNull())
   5.675 -			{
   5.676 -				LL_WARNS("Messaging") << "buildLegacyName returned null while processing " << original_name << LL_ENDL;
   5.677 -			}
   5.678 -			else if (LLMuteList::getInstance()->isMuted(agent_id))
   5.679 -			{
   5.680 -				break;
   5.681 -			}
   5.682 -
   5.683 -			notice_bin_bucket = (struct notice_bucket_full_t*) &binary_bucket[0];
   5.684 -			U8 has_inventory = notice_bin_bucket->header.has_inventory;
   5.685 -			U8 asset_type = notice_bin_bucket->header.asset_type;
   5.686 -			LLUUID group_id = notice_bin_bucket->header.group_id;
   5.687 -			std::string item_name = ll_safe_string((const char*) notice_bin_bucket->item_name);
   5.688 -
   5.689 -			// If there is inventory, give the user the inventory offer.
   5.690 -			LLOfferInfo* info = NULL;
   5.691 -
   5.692 -			if (has_inventory)
   5.693 -			{
   5.694 -				info = new LLOfferInfo();
   5.695 -				
   5.696 -				info->mIM = IM_GROUP_NOTICE;
   5.697 -				info->mFromID = from_id;
   5.698 -				info->mFromGroup = from_group;
   5.699 -				info->mTransactionID = session_id;
   5.700 -				info->mType = (LLAssetType::EType) asset_type;
   5.701 -				info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType));
   5.702 -				std::string from_name;
   5.703 -
   5.704 -				from_name += "A group member named ";
   5.705 -				from_name += name;
   5.706 -
   5.707 -				info->mFromName = from_name;
   5.708 -				info->mDesc = item_name;
   5.709 -				info->mHost = msg->getSender();
   5.710 -			}
   5.711 -			
   5.712 -			std::string str(message);
   5.713 -
   5.714 -			// Tokenize the string.
   5.715 -			// TODO: Support escaped tokens ("||" -> "|")
   5.716 -			typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
   5.717 -			boost::char_separator<char> sep("|","",boost::keep_empty_tokens);
   5.718 -			tokenizer tokens(str, sep);
   5.719 -			tokenizer::iterator iter = tokens.begin();
   5.720 -
   5.721 -			std::string subj(*iter++);
   5.722 -			std::string mes(*iter++);
   5.723 -
   5.724 -			// Send the notification down the new path.
   5.725 -			// For requested notices, we don't want to send the popups.
   5.726 -			if (dialog != IM_GROUP_NOTICE_REQUESTED)
   5.727 -			{
   5.728 -				payload["subject"] = subj;
   5.729 -				payload["message"] = mes;
   5.730 -				payload["sender_name"] = name;
   5.731 -				payload["sender_id"] = agent_id;
   5.732 -				payload["group_id"] = group_id;
   5.733 -				payload["inventory_name"] = item_name;
   5.734 - 				payload["received_time"] = LLDate::now();
   5.735 -				if(info && info->asLLSD())
   5.736 -				{
   5.737 -					payload["inventory_offer"] = info->asLLSD();
   5.738 -				}
   5.739 -
   5.740 -				LLSD args;
   5.741 -				args["SUBJECT"] = subj;
   5.742 -				args["MESSAGE"] = mes;
   5.743 -				LLDate notice_date = LLDate(timestamp).notNull() ? LLDate(timestamp) : LLDate::now();
   5.744 -				LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).time_stamp(notice_date));
   5.745 -			}
   5.746 -
   5.747 -			// Also send down the old path for now.
   5.748 -			if (IM_GROUP_NOTICE_REQUESTED == dialog)
   5.749 -			{
   5.750 -				
   5.751 -				LLPanelGroup::showNotice(subj,mes,group_id,has_inventory,item_name,info);
   5.752 -			}
   5.753 -			else
   5.754 -			{
   5.755 -				delete info;
   5.756 -			}
   5.757 -		}
   5.758 -		break;
   5.759 -	case IM_GROUP_INVITATION:
   5.760 -		{
   5.761 -			if (!is_muted)
   5.762 -			{
   5.763 -				// group is not blocked, but we still need to check agent that sent the invitation
   5.764 -				// and we have no agent's id
   5.765 -				// Note: server sends username "first.last".
   5.766 -				is_muted |= LLMuteList::getInstance()->isMuted(name);
   5.767 -			}
   5.768 -			if (is_do_not_disturb || is_muted)
   5.769 -			{
   5.770 -				send_do_not_disturb_message(msg, from_id);
   5.771 -			}
   5.772 -			
   5.773 -			if (!is_muted)
   5.774 -			{
   5.775 -				LL_INFOS("Messaging") << "Received IM_GROUP_INVITATION message." << LL_ENDL;
   5.776 -				// Read the binary bucket for more information.
   5.777 -				struct invite_bucket_t
   5.778 -				{
   5.779 -					S32 membership_fee;
   5.780 -					LLUUID role_id;
   5.781 -				}* invite_bucket;
   5.782 -
   5.783 -				// Make sure the binary bucket is the correct size.
   5.784 -				if (binary_bucket_size != sizeof(invite_bucket_t))
   5.785 -				{
   5.786 -					LL_WARNS("Messaging") << "Malformed group invite binary bucket" << LL_ENDL;
   5.787 -					break;
   5.788 -				}
   5.789 -
   5.790 -				invite_bucket = (struct invite_bucket_t*) &binary_bucket[0];
   5.791 -				S32 membership_fee = ntohl(invite_bucket->membership_fee);
   5.792 -
   5.793 -				LLSD payload;
   5.794 -				payload["transaction_id"] = session_id;
   5.795 -				payload["group_id"] = from_id;
   5.796 -				payload["name"] = name;
   5.797 -				payload["message"] = message;
   5.798 -				payload["fee"] = membership_fee;
   5.799 -
   5.800 -				LLSD args;
   5.801 -				args["MESSAGE"] = message;
   5.802 -				// we shouldn't pass callback functor since it is registered in LLFunctorRegistration
   5.803 -				LLNotificationsUtil::add("JoinGroup", args, payload);
   5.804 -			}
   5.805 -		}
   5.806 -		break;
   5.807 -
   5.808 -	case IM_INVENTORY_OFFERED:
   5.809 -	case IM_TASK_INVENTORY_OFFERED:
   5.810 -		// Someone has offered us some inventory.
   5.811 -		{
   5.812 -			LLOfferInfo* info = new LLOfferInfo;
   5.813 -			if (IM_INVENTORY_OFFERED == dialog)
   5.814 -			{
   5.815 -				struct offer_agent_bucket_t
   5.816 -				{
   5.817 -					S8		asset_type;
   5.818 -					LLUUID	object_id;
   5.819 -				}* bucketp;
   5.820 -
   5.821 -				if (sizeof(offer_agent_bucket_t) != binary_bucket_size)
   5.822 -				{
   5.823 -					LL_WARNS("Messaging") << "Malformed inventory offer from agent" << LL_ENDL;
   5.824 -					delete info;
   5.825 -					break;
   5.826 -				}
   5.827 -				bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0];
   5.828 -				info->mType = (LLAssetType::EType) bucketp->asset_type;
   5.829 -				info->mObjectID = bucketp->object_id;
   5.830 -				info->mFromObject = FALSE;
   5.831 -			}
   5.832 -			else // IM_TASK_INVENTORY_OFFERED
   5.833 -			{
   5.834 -				if (sizeof(S8) != binary_bucket_size)
   5.835 -				{
   5.836 -					LL_WARNS("Messaging") << "Malformed inventory offer from object" << LL_ENDL;
   5.837 -					delete info;
   5.838 -					break;
   5.839 -				}
   5.840 -				info->mType = (LLAssetType::EType) binary_bucket[0];
   5.841 -				info->mObjectID = LLUUID::null;
   5.842 -				info->mFromObject = TRUE;
   5.843 -			}
   5.844 -
   5.845 -			info->mIM = dialog;
   5.846 -			info->mFromID = from_id;
   5.847 -			info->mFromGroup = from_group;
   5.848 -			info->mTransactionID = session_id;
   5.849 -			info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType));
   5.850 -
   5.851 -			info->mFromName = name;
   5.852 -			info->mDesc = message;
   5.853 -			info->mHost = msg->getSender();
   5.854 -			//if (((is_do_not_disturb && !is_owned_by_me) || is_muted))
   5.855 -			if (is_muted)
   5.856 -			{
   5.857 -				// Prefetch the offered item so that it can be discarded by the appropriate observer. (EXT-4331)
   5.858 -				LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID);
   5.859 -				fetch_item->startFetch();
   5.860 -				delete fetch_item;
   5.861 -
   5.862 -				// Same as closing window
   5.863 -				info->forceResponse(IOR_DECLINE);
   5.864 -			}
   5.865 -			// old logic: busy mode must not affect interaction with objects (STORM-565)
   5.866 -			// new logic: inventory offers from in-world objects should be auto-declined (CHUI-519)
   5.867 -			else if (is_do_not_disturb && dialog == IM_TASK_INVENTORY_OFFERED)
   5.868 -			{
   5.869 -				// Until throttling is implemented, do not disturb mode should reject inventory instead of silently
   5.870 -				// accepting it.  SEE SL-39554
   5.871 -				info->forceResponse(IOR_DECLINE);
   5.872 -			}
   5.873 -			else
   5.874 -			{
   5.875 -				inventory_offer_handler(info);
   5.876 -			}
   5.877 -		}
   5.878 -		break;
   5.879 -
   5.880 -	case IM_INVENTORY_ACCEPTED:
   5.881 -	{
   5.882 -		args["NAME"] = LLSLURL("agent", from_id, "completename").getSLURLString();;
   5.883 -		args["ORIGINAL_NAME"] = original_name;
   5.884 -		LLSD payload;
   5.885 -		payload["from_id"] = from_id;
   5.886 -		// Passing the "SESSION_NAME" to use it for IM notification logging
   5.887 -		// in LLTipHandler::processNotification(). See STORM-941.
   5.888 -		payload["SESSION_NAME"] = name;
   5.889 -		LLNotificationsUtil::add("InventoryAccepted", args, payload);
   5.890 -		break;
   5.891 -	}
   5.892 -	case IM_INVENTORY_DECLINED:
   5.893 -	{
   5.894 -		args["NAME"] = LLSLURL("agent", from_id, "completename").getSLURLString();;
   5.895 -		LLSD payload;
   5.896 -		payload["from_id"] = from_id;
   5.897 -		LLNotificationsUtil::add("InventoryDeclined", args, payload);
   5.898 -		break;
   5.899 -	}
   5.900 -	// TODO: _DEPRECATED suffix as part of vote removal - DEV-24856
   5.901 -	case IM_GROUP_VOTE:
   5.902 -		{
   5.903 -			LL_WARNS("Messaging") << "Received IM: IM_GROUP_VOTE_DEPRECATED" << LL_ENDL;
   5.904 -		}
   5.905 -		break;
   5.906 -
   5.907 -	case IM_GROUP_ELECTION_DEPRECATED:
   5.908 -	{
   5.909 -		LL_WARNS("Messaging") << "Received IM: IM_GROUP_ELECTION_DEPRECATED" << LL_ENDL;
   5.910 -	}
   5.911 -	break;
   5.912 -	
   5.913 -	case IM_FROM_TASK:
   5.914 -		{
   5.915 -
   5.916 -			if (is_do_not_disturb && !is_owned_by_me)
   5.917 -			{
   5.918 -				return;
   5.919 -			}
   5.920 -
   5.921 -			// Build a link to open the object IM info window.
   5.922 -			std::string location = ll_safe_string((char*)binary_bucket, binary_bucket_size-1);
   5.923 -
   5.924 -			if (session_id.notNull())
   5.925 -			{
   5.926 -				chat.mFromID = session_id;
   5.927 -			}
   5.928 -			else
   5.929 -			{
   5.930 -				// This message originated on a region without the updated code for task id and slurl information.
   5.931 -				// We just need a unique ID for this object that isn't the owner ID.
   5.932 -				// If it is the owner ID it will overwrite the style that contains the link to that owner's profile.
   5.933 -				// This isn't ideal - it will make 1 style for all objects owned by the the same person/group.
   5.934 -				// This works because the only thing we can really do in this case is show the owner name and link to their profile.
   5.935 -				chat.mFromID = from_id ^ gAgent.getSessionID();
   5.936 -			}
   5.937 -
   5.938 -			chat.mSourceType = CHAT_SOURCE_OBJECT;
   5.939 -
   5.940 -			// To conclude that the source type of message is CHAT_SOURCE_SYSTEM it's not
   5.941 -			// enough to check only from name (i.e. fromName = "Second Life"). For example
   5.942 -			// source type of messages from objects called "Second Life" should not be CHAT_SOURCE_SYSTEM.
   5.943 -			bool chat_from_system = (SYSTEM_FROM == name) && region_id.isNull() && position.isNull();
   5.944 -			if(chat_from_system)
   5.945 -			{
   5.946 -				// System's UUID is NULL (fixes EXT-4766)
   5.947 -				chat.mFromID = LLUUID::null;
   5.948 -				chat.mSourceType = CHAT_SOURCE_SYSTEM;
   5.949 -			}
   5.950 -
   5.951 -			// IDEVO Some messages have embedded resident names
   5.952 -			message = clean_name_from_task_im(message, from_group);
   5.953 -
   5.954 -			LLSD query_string;
   5.955 -			query_string["owner"] = from_id;
   5.956 -			query_string["slurl"] = location;
   5.957 -			query_string["name"] = name;
   5.958 -			if (from_group)
   5.959 -			{
   5.960 -				query_string["groupowned"] = "true";
   5.961 -			}	
   5.962 -
   5.963 -			chat.mURL = LLSLURL("objectim", session_id, "").getSLURLString();
   5.964 -			chat.mText = message;
   5.965 -
   5.966 -			// Note: lie to Nearby Chat, pretending that this is NOT an IM, because
   5.967 -			// IMs from obejcts don't open IM sessions.
   5.968 -			LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
   5.969 -			if(!chat_from_system && nearby_chat)
   5.970 -			{
   5.971 -				chat.mOwnerID = from_id;
   5.972 -				LLSD args;
   5.973 -				args["slurl"] = location;
   5.974 -
   5.975 -				// Look for IRC-style emotes here so object name formatting is correct
   5.976 -				std::string prefix = message.substr(0, 4);
   5.977 -				if (prefix == "/me " || prefix == "/me'")
   5.978 -				{
   5.979 -					chat.mChatStyle = CHAT_STYLE_IRC;
   5.980 -				}
   5.981 -
   5.982 -				LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args);
   5.983 -			}
   5.984 -
   5.985 -
   5.986 -			//Object IMs send with from name: 'Second Life' need to be displayed also in notification toasts (EXT-1590)
   5.987 -			if (!chat_from_system) break;
   5.988 -			
   5.989 -			LLSD substitutions;
   5.990 -			substitutions["NAME"] = name;
   5.991 -			substitutions["MSG"] = message;
   5.992 -
   5.993 -			LLSD payload;
   5.994 -			payload["object_id"] = session_id;
   5.995 -			payload["owner_id"] = from_id;
   5.996 -			payload["from_id"] = from_id;
   5.997 -			payload["slurl"] = location;
   5.998 -			payload["name"] = name;
   5.999 -
  5.1000 -			if (from_group)
  5.1001 -			{
  5.1002 -				payload["group_owned"] = "true";
  5.1003 -			}
  5.1004 -
  5.1005 -			LLNotificationsUtil::add("ServerObjectMessage", substitutions, payload);
  5.1006 -		}
  5.1007 -		break;
  5.1008 -
  5.1009 -	case IM_SESSION_SEND:		// ad-hoc or group IMs
  5.1010 -
  5.1011 -		// Only show messages if we have a session open (which
  5.1012 -		// should happen after you get an "invitation"
  5.1013 -		if ( !gIMMgr->hasSession(session_id) )
  5.1014 -		{
  5.1015 -			return;
  5.1016 -		}
  5.1017 -
  5.1018 -		else if (offline == IM_ONLINE && is_do_not_disturb)
  5.1019 -		{
  5.1020 -
  5.1021 -			// return a standard "do not disturb" message, but only do it to online IM 
  5.1022 -			// (i.e. not other auto responses and not store-and-forward IM)
  5.1023 -			if (!gIMMgr->hasSession(session_id))
  5.1024 -			{
  5.1025 -				// if there is not a panel for this conversation (i.e. it is a new IM conversation
  5.1026 -				// initiated by the other party) then...
  5.1027 -				send_do_not_disturb_message(msg, from_id, session_id);
  5.1028 -			}
  5.1029 -
  5.1030 -			// now store incoming IM in chat history
  5.1031 -
  5.1032 -			buffer = message;
  5.1033 -	
  5.1034 -			LL_DEBUGS("Messaging") << "message in dnd; session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
  5.1035 -
  5.1036 -			// add to IM panel, but do not bother the user
  5.1037 -			gIMMgr->addMessage(
  5.1038 -				session_id,
  5.1039 -				from_id,
  5.1040 -				name,
  5.1041 -				buffer,
  5.1042 -				IM_OFFLINE == offline,
  5.1043 -				ll_safe_string((char*)binary_bucket),
  5.1044 -				IM_SESSION_INVITE,
  5.1045 -				parent_estate_id,
  5.1046 -				region_id,
  5.1047 -				position,
  5.1048 -				true);
  5.1049 -		}
  5.1050 -		else
  5.1051 -		{
  5.1052 -			// standard message, not from system
  5.1053 -			std::string saved;
  5.1054 -			if(offline == IM_OFFLINE)
  5.1055 -			{
  5.1056 -				saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
  5.1057 -			}
  5.1058 -
  5.1059 -			buffer = saved + message;
  5.1060 -
  5.1061 -			LL_DEBUGS("Messaging") << "standard message session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
  5.1062 -
  5.1063 -			gIMMgr->addMessage(
  5.1064 -				session_id,
  5.1065 -				from_id,
  5.1066 -				name,
  5.1067 -				buffer,
  5.1068 -				IM_OFFLINE == offline,
  5.1069 -				ll_safe_string((char*)binary_bucket),
  5.1070 -				IM_SESSION_INVITE,
  5.1071 -				parent_estate_id,
  5.1072 -				region_id,
  5.1073 -				position,
  5.1074 -				true);
  5.1075 -		}
  5.1076 -		break;
  5.1077 -
  5.1078 -	case IM_FROM_TASK_AS_ALERT:
  5.1079 -		if (is_do_not_disturb && !is_owned_by_me)
  5.1080 -		{
  5.1081 -			return;
  5.1082 -		}
  5.1083 -		{
  5.1084 -			// Construct a viewer alert for this message.
  5.1085 -			args["NAME"] = name;
  5.1086 -			args["MESSAGE"] = message;
  5.1087 -			LLNotificationsUtil::add("ObjectMessage", args);
  5.1088 -		}
  5.1089 -		break;
  5.1090 -	case IM_DO_NOT_DISTURB_AUTO_RESPONSE:
  5.1091 -		if (is_muted)
  5.1092 -		{
  5.1093 -			LL_DEBUGS("Messaging") << "Ignoring do-not-disturb response from " << from_id << LL_ENDL;
  5.1094 -			return;
  5.1095 -		}
  5.1096 -		else
  5.1097 -		{
  5.1098 -			gIMMgr->addMessage(session_id, from_id, name, message);
  5.1099 -		}
  5.1100 -		break;
  5.1101 -		
  5.1102 -	case IM_LURE_USER:
  5.1103 -	case IM_TELEPORT_REQUEST:
  5.1104 -		{
  5.1105 -			if (is_muted)
  5.1106 -			{ 
  5.1107 -				return;
  5.1108 -			}
  5.1109 -			else if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(from_id) == NULL))
  5.1110 -			{
  5.1111 -				return;
  5.1112 -			}
  5.1113 -			else
  5.1114 -			{
  5.1115 -				if (is_do_not_disturb)
  5.1116 -				{
  5.1117 -					send_do_not_disturb_message(msg, from_id);
  5.1118 -				}
  5.1119 -
  5.1120 -				LLVector3 pos, look_at;
  5.1121 -				U64 region_handle(0);
  5.1122 -				U8 region_access(SIM_ACCESS_MIN);
  5.1123 -				std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size);
  5.1124 -				std::string region_access_str = LLStringUtil::null;
  5.1125 -				std::string region_access_icn = LLStringUtil::null;
  5.1126 -				std::string region_access_lc  = LLStringUtil::null;
  5.1127 -
  5.1128 -				bool canUserAccessDstRegion = true;
  5.1129 -				bool doesUserRequireMaturityIncrease = false;
  5.1130 -
  5.1131 -				// Do not parse the (empty) lure bucket for TELEPORT_REQUEST
  5.1132 -				if (IM_TELEPORT_REQUEST != dialog && parse_lure_bucket(region_info, region_handle, pos, look_at, region_access))
  5.1133 -				{
  5.1134 -					region_access_str = LLViewerRegion::accessToString(region_access);
  5.1135 -					region_access_icn = LLViewerRegion::getAccessIcon(region_access);
  5.1136 -					region_access_lc  = region_access_str;
  5.1137 -					LLStringUtil::toLower(region_access_lc);
  5.1138 -
  5.1139 -					if (!gAgent.isGodlike())
  5.1140 -					{
  5.1141 -						switch (region_access)
  5.1142 -						{
  5.1143 -						case SIM_ACCESS_MIN :
  5.1144 -						case SIM_ACCESS_PG :
  5.1145 -							break;
  5.1146 -						case SIM_ACCESS_MATURE :
  5.1147 -							if (gAgent.isTeen())
  5.1148 -							{
  5.1149 -								canUserAccessDstRegion = false;
  5.1150 -							}
  5.1151 -							else if (gAgent.prefersPG())
  5.1152 -							{
  5.1153 -								doesUserRequireMaturityIncrease = true;
  5.1154 -							}
  5.1155 -							break;
  5.1156 -						case SIM_ACCESS_ADULT :
  5.1157 -							if (!gAgent.isAdult())
  5.1158 -							{
  5.1159 -								canUserAccessDstRegion = false;
  5.1160 -							}
  5.1161 -							else if (!gAgent.prefersAdult())
  5.1162 -							{
  5.1163 -								doesUserRequireMaturityIncrease = true;
  5.1164 -							}
  5.1165 -							break;
  5.1166 -						default :
  5.1167 -							llassert(0);
  5.1168 -							break;
  5.1169 -						}
  5.1170 -					}
  5.1171 -				}
  5.1172 -
  5.1173 -				LLSD args;
  5.1174 -				// *TODO: Translate -> [FIRST] [LAST] (maybe)
  5.1175 -				args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString();
  5.1176 -				args["MESSAGE"] = message;
  5.1177 -				args["MATURITY_STR"] = region_access_str;
  5.1178 -				args["MATURITY_ICON"] = region_access_icn;
  5.1179 -				args["REGION_CONTENT_MATURITY"] = region_access_lc;
  5.1180 -				LLSD payload;
  5.1181 -				payload["from_id"] = from_id;
  5.1182 -				payload["lure_id"] = session_id;
  5.1183 -				payload["godlike"] = FALSE;
  5.1184 -				payload["region_maturity"] = region_access;
  5.1185 -
  5.1186 -				if (!canUserAccessDstRegion)
  5.1187 -				{
  5.1188 -					LLNotification::Params params("TeleportOffered_MaturityBlocked");
  5.1189 -					params.substitutions = args;
  5.1190 -					params.payload = payload;
  5.1191 -					LLPostponedNotification::add<LLPostponedOfferNotification>(	params, from_id, false);
  5.1192 -					send_simple_im(from_id, LLTrans::getString("TeleportMaturityExceeded"), IM_NOTHING_SPECIAL, session_id);
  5.1193 -					send_simple_im(from_id, LLStringUtil::null, IM_LURE_DECLINED, session_id);
  5.1194 -				}
  5.1195 -				else if (doesUserRequireMaturityIncrease)
  5.1196 -				{
  5.1197 -					LLNotification::Params params("TeleportOffered_MaturityExceeded");
  5.1198 -					params.substitutions = args;
  5.1199 -					params.payload = payload;
  5.1200 -					LLPostponedNotification::add<LLPostponedOfferNotification>(	params, from_id, false);
  5.1201 -				}
  5.1202 -				else
  5.1203 -				{
  5.1204 -					LLNotification::Params params;
  5.1205 -					if (IM_LURE_USER == dialog)
  5.1206 -					{
  5.1207 -						params.name = "TeleportOffered";
  5.1208 -						params.functor.name = "TeleportOffered";
  5.1209 -					}
  5.1210 -					else if (IM_TELEPORT_REQUEST == dialog)
  5.1211 -					{
  5.1212 -						params.name = "TeleportRequest";
  5.1213 -						params.functor.name = "TeleportRequest";
  5.1214 -					}
  5.1215 -
  5.1216 -			    params.substitutions = args;
  5.1217 -			    params.payload = payload;
  5.1218 -			    LLPostponedNotification::add<LLPostponedOfferNotification>(	params, from_id, false);
  5.1219 -			}
  5.1220 -			}
  5.1221 -		}
  5.1222 -		break;
  5.1223 -
  5.1224 -	case IM_GODLIKE_LURE_USER:
  5.1225 -		{
  5.1226 -			LLVector3 pos, look_at;
  5.1227 -			U64 region_handle(0);
  5.1228 -			U8 region_access(SIM_ACCESS_MIN);
  5.1229 -			std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size);
  5.1230 -			std::string region_access_str = LLStringUtil::null;
  5.1231 -			std::string region_access_icn = LLStringUtil::null;
  5.1232 -			std::string region_access_lc  = LLStringUtil::null;
  5.1233 -
  5.1234 -			bool canUserAccessDstRegion = true;
  5.1235 -			bool doesUserRequireMaturityIncrease = false;
  5.1236 -
  5.1237 -			if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access))
  5.1238 -			{
  5.1239 -				region_access_str = LLViewerRegion::accessToString(region_access);
  5.1240 -				region_access_icn = LLViewerRegion::getAccessIcon(region_access);
  5.1241 -				region_access_lc  = region_access_str;
  5.1242 -				LLStringUtil::toLower(region_access_lc);
  5.1243 -
  5.1244 -				if (!gAgent.isGodlike())
  5.1245 -				{
  5.1246 -					switch (region_access)
  5.1247 -					{
  5.1248 -					case SIM_ACCESS_MIN :
  5.1249 -					case SIM_ACCESS_PG :
  5.1250 -						break;
  5.1251 -					case SIM_ACCESS_MATURE :
  5.1252 -						if (gAgent.isTeen())
  5.1253 -						{
  5.1254 -							canUserAccessDstRegion = false;
  5.1255 -						}
  5.1256 -						else if (gAgent.prefersPG())
  5.1257 -						{
  5.1258 -							doesUserRequireMaturityIncrease = true;
  5.1259 -						}
  5.1260 -						break;
  5.1261 -					case SIM_ACCESS_ADULT :
  5.1262 -						if (!gAgent.isAdult())
  5.1263 -						{
  5.1264 -							canUserAccessDstRegion = false;
  5.1265 -						}
  5.1266 -						else if (!gAgent.prefersAdult())
  5.1267 -						{
  5.1268 -							doesUserRequireMaturityIncrease = true;
  5.1269 -						}
  5.1270 -						break;
  5.1271 -					default :
  5.1272 -						llassert(0);
  5.1273 -						break;
  5.1274 -					}
  5.1275 -				}
  5.1276 -			}
  5.1277 -
  5.1278 -			LLSD args;
  5.1279 -			// *TODO: Translate -> [FIRST] [LAST] (maybe)
  5.1280 -			args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString();
  5.1281 -			args["MESSAGE"] = message;
  5.1282 -			args["MATURITY_STR"] = region_access_str;
  5.1283 -			args["MATURITY_ICON"] = region_access_icn;
  5.1284 -			args["REGION_CONTENT_MATURITY"] = region_access_lc;
  5.1285 -			LLSD payload;
  5.1286 -			payload["from_id"] = from_id;
  5.1287 -			payload["lure_id"] = session_id;
  5.1288 -			payload["godlike"] = TRUE;
  5.1289 -			payload["region_maturity"] = region_access;
  5.1290 -
  5.1291 -			if (!canUserAccessDstRegion)
  5.1292 -			{
  5.1293 -				LLNotification::Params params("TeleportOffered_MaturityBlocked");
  5.1294 -				params.substitutions = args;
  5.1295 -				params.payload = payload;
  5.1296 -				LLPostponedNotification::add<LLPostponedOfferNotification>(	params, from_id, false);
  5.1297 -				send_simple_im(from_id, LLTrans::getString("TeleportMaturityExceeded"), IM_NOTHING_SPECIAL, session_id);
  5.1298 -				send_simple_im(from_id, LLStringUtil::null, IM_LURE_DECLINED, session_id);
  5.1299 -			}
  5.1300 -			else if (doesUserRequireMaturityIncrease)
  5.1301 -			{
  5.1302 -				LLNotification::Params params("TeleportOffered_MaturityExceeded");
  5.1303 -				params.substitutions = args;
  5.1304 -				params.payload = payload;
  5.1305 -				LLPostponedNotification::add<LLPostponedOfferNotification>(	params, from_id, false);
  5.1306 -			}
  5.1307 -			else
  5.1308 -			{
  5.1309 -			// do not show a message box, because you're about to be
  5.1310 -			// teleported.
  5.1311 -			LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0);
  5.1312 -		}
  5.1313 -		}
  5.1314 -		break;
  5.1315 -
  5.1316 -	case IM_GOTO_URL:
  5.1317 -		{
  5.1318 -			LLSD args;
  5.1319 -			// n.b. this is for URLs sent by the system, not for
  5.1320 -			// URLs sent by scripts (i.e. llLoadURL)
  5.1321 -			if (binary_bucket_size <= 0)
  5.1322 -			{
  5.1323 -				LL_WARNS("Messaging") << "bad binary_bucket_size: "
  5.1324 -					<< binary_bucket_size
  5.1325 -					<< " - aborting function." << LL_ENDL;
  5.1326 -				return;
  5.1327 -			}
  5.1328 -
  5.1329 -			std::string url;
  5.1330 -			
  5.1331 -			url.assign((char*)binary_bucket, binary_bucket_size-1);
  5.1332 -			args["MESSAGE"] = message;
  5.1333 -			args["URL"] = url;
  5.1334 -			LLSD payload;
  5.1335 -			payload["url"] = url;
  5.1336 -			LLNotificationsUtil::add("GotoURL", args, payload );
  5.1337 -		}
  5.1338 -		break;
  5.1339 -
  5.1340 -	case IM_FRIENDSHIP_OFFERED:
  5.1341 -		{
  5.1342 -			LLSD payload;
  5.1343 -			payload["from_id"] = from_id;
  5.1344 -			payload["session_id"] = session_id;;
  5.1345 -			payload["online"] = (offline == IM_ONLINE);
  5.1346 -			payload["sender"] = msg->getSender().getIPandPort();
  5.1347 -
  5.1348 -			bool add_notification = true;
  5.1349 -			for (LLToastNotifyPanel::instance_iter ti(LLToastNotifyPanel::beginInstances())
  5.1350 -				, tend(LLToastNotifyPanel::endInstances()); ti != tend; ++ti)
  5.1351 -			{
  5.1352 -				LLToastNotifyPanel& panel = *ti;
  5.1353 -				const std::string& notification_name = panel.getNotificationName();
  5.1354 -				if (notification_name == "OfferFriendship" && panel.isControlPanelEnabled())
  5.1355 -				{
  5.1356 -					add_notification = false;
  5.1357 -					break;
  5.1358 -				}
  5.1359 -			}
  5.1360 -
  5.1361 -			if (is_muted && add_notification)
  5.1362 -			{
  5.1363 -				LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1);
  5.1364 -			}
  5.1365 -			else
  5.1366 -			{
  5.1367 -				if (is_do_not_disturb)
  5.1368 -				{
  5.1369 -					send_do_not_disturb_message(msg, from_id);
  5.1370 -				}
  5.1371 -				args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString();
  5.1372 -
  5.1373 -				if (add_notification)
  5.1374 -				{
  5.1375 -				if(message.empty())
  5.1376 -				{
  5.1377 -					//support for frienship offers from clients before July 2008
  5.1378 -				        LLNotificationsUtil::add("OfferFriendshipNoMessage", args, payload);
  5.1379 -				}
  5.1380 -				else
  5.1381 -				{
  5.1382 -					args["[MESSAGE]"] = message;
  5.1383 -				    LLNotification::Params params("OfferFriendship");
  5.1384 -				    params.substitutions = args;
  5.1385 -				    params.payload = payload;
  5.1386 -				    LLPostponedNotification::add<LLPostponedOfferNotification>(	params, from_id, false);
  5.1387 -				}
  5.1388 -			}
  5.1389 -		}
  5.1390 -		}
  5.1391 -		break;
  5.1392 -
  5.1393 -	case IM_FRIENDSHIP_ACCEPTED:
  5.1394 -		{
  5.1395 -			// In the case of an offline IM, the formFriendship() may be extraneous
  5.1396 -			// as the database should already include the relationship.  But it
  5.1397 -			// doesn't hurt for dupes.
  5.1398 -			LLAvatarTracker::formFriendship(from_id);
  5.1399 -			
  5.1400 -			std::vector<std::string> strings;
  5.1401 -			strings.push_back(from_id.asString());
  5.1402 -			send_generic_message("requestonlinenotification", strings);
  5.1403 -			
  5.1404 -			args["NAME"] = name;
  5.1405 -			LLSD payload;
  5.1406 -			payload["from_id"] = from_id;
  5.1407 -			LLAvatarNameCache::get(from_id, boost::bind(&notification_display_name_callback,_1,_2,"FriendshipAccepted",args,payload));
  5.1408 -		}
  5.1409 -		break;
  5.1410 -
  5.1411 -	case IM_FRIENDSHIP_DECLINED_DEPRECATED:
  5.1412 -	default:
  5.1413 -		LL_WARNS("Messaging") << "Instant message calling for unknown dialog "
  5.1414 -				<< (S32)dialog << LL_ENDL;
  5.1415 -		break;
  5.1416 -	}
  5.1417 -
  5.1418 -	LLWindow* viewer_window = gViewerWindow->getWindow();
  5.1419 -	if (viewer_window && viewer_window->getMinimized())
  5.1420 -	{
  5.1421 -		viewer_window->flashIcon(5.f);
  5.1422 -	}
  5.1423 +    LLUUID from_id;
  5.1424 +    BOOL from_group;
  5.1425 +    LLUUID to_id;
  5.1426 +    U8 offline;
  5.1427 +    U8 d = 0;
  5.1428 +    LLUUID session_id;
  5.1429 +    U32 timestamp;
  5.1430 +    std::string agentName;
  5.1431 +    std::string message;
  5.1432 +    U32 parent_estate_id = 0;
  5.1433 +    LLUUID region_id;
  5.1434 +    LLVector3 position;
  5.1435 +    U8 binary_bucket[MTUBYTES];
  5.1436 +    S32 binary_bucket_size;
  5.1437 +
  5.1438 +    // *TODO: Translate - need to fix the full name to first/last (maybe)
  5.1439 +    msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, from_id);
  5.1440 +    msg->getBOOLFast(_PREHASH_MessageBlock, _PREHASH_FromGroup, from_group);
  5.1441 +    msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ToAgentID, to_id);
  5.1442 +    msg->getU8Fast(_PREHASH_MessageBlock, _PREHASH_Offline, offline);
  5.1443 +    msg->getU8Fast(_PREHASH_MessageBlock, _PREHASH_Dialog, d);
  5.1444 +    msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ID, session_id);
  5.1445 +    msg->getU32Fast(_PREHASH_MessageBlock, _PREHASH_Timestamp, timestamp);
  5.1446 +    //msg->getData("MessageBlock", "Count",		&count);
  5.1447 +    msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_FromAgentName, agentName);
  5.1448 +    msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_Message, message);
  5.1449 +    msg->getU32Fast(_PREHASH_MessageBlock, _PREHASH_ParentEstateID, parent_estate_id);
  5.1450 +    msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_RegionID, region_id);
  5.1451 +    msg->getVector3Fast(_PREHASH_MessageBlock, _PREHASH_Position, position);
  5.1452 +    msg->getBinaryDataFast(_PREHASH_MessageBlock, _PREHASH_BinaryBucket, binary_bucket, 0, 0, MTUBYTES);
  5.1453 +    binary_bucket_size = msg->getSizeFast(_PREHASH_MessageBlock, _PREHASH_BinaryBucket);
  5.1454 +    EInstantMessage dialog = (EInstantMessage)d;
  5.1455 +    LLHost sender = msg->getSender();
  5.1456 +
  5.1457 +    LLIMProcessing::processNewMessage(from_id,
  5.1458 +        from_group,
  5.1459 +        to_id,
  5.1460 +        offline,
  5.1461 +        dialog,
  5.1462 +        session_id,
  5.1463 +        timestamp,
  5.1464 +        agentName,
  5.1465 +        message,
  5.1466 +        parent_estate_id,
  5.1467 +        region_id,
  5.1468 +        position,
  5.1469 +        binary_bucket,
  5.1470 +        binary_bucket_size,
  5.1471 +        sender);
  5.1472  }
  5.1473  
  5.1474  void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id)
     6.1 --- a/indra/newview/llviewerregion.cpp	Fri Mar 09 16:57:47 2018 +0200
     6.2 +++ b/indra/newview/llviewerregion.cpp	Tue Feb 13 15:40:21 2018 +0200
     6.3 @@ -2868,6 +2868,7 @@
     6.4  	capabilityNames.append("ParcelVoiceInfoRequest");
     6.5  	capabilityNames.append("ProductInfoRequest");
     6.6  	capabilityNames.append("ProvisionVoiceAccountRequest");
     6.7 +	capabilityNames.append("ReadOfflineMsgs");
     6.8  	capabilityNames.append("RemoteParcelRequest");
     6.9  	capabilityNames.append("RenderMaterials");
    6.10  	capabilityNames.append("RequestTextureDownload");

mercurial