diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 33e27cfc1a..5255df08e3 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -24659,17 +24659,6 @@ Change of this parameter will affect the layout of buttons in notification toast Value 1 - FSUseReadOfflineMsgsCap - - Comment - If enabled, use the ReadOfflineMsgsCap to request offline messages at login - Persist - 1 - Type - Boolean - Value - 0 - FSExperimentalRegionCrossingMovementFix Comment diff --git a/indra/newview/llfloaternotificationstabbed.cpp b/indra/newview/llfloaternotificationstabbed.cpp index cc94ef71d9..9805d2d68b 100644 --- a/indra/newview/llfloaternotificationstabbed.cpp +++ b/indra/newview/llfloaternotificationstabbed.cpp @@ -412,7 +412,8 @@ void LLFloaterNotificationsTabbed::onStoreToast(LLPanel* info_panel, LLUUID id) p.notification_name = notify->getName(); p.transaction_id = payload["transaction_id"]; p.group_id = payload["group_id"]; - p.fee = payload["fee"]; + p.fee = payload["fee"]; + p.use_offline_cap = payload["use_offline_cap"].asInteger(); p.subject = payload["subject"].asString(); p.message = payload["message"].asString(); // Unscrew avatar icon for transaction messages diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index 865cfa3a96..aedf31f2cf 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -1284,10 +1284,11 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, LLSD payload; payload["transaction_id"] = session_id; - payload["group_id"] = from_id; + payload["group_id"] = from_group ? from_id : aux_id; payload["name"] = name; payload["message"] = message; payload["fee"] = membership_fee; + payload["use_offline_cap"] = session_id.isNull() && (offline == IM_OFFLINE); LLSD args; args["MESSAGE"] = message; @@ -2118,8 +2119,12 @@ void LLIMProcessing::requestOfflineMessages() // Auto-accepted inventory items may require the avatar object // to build a correct name. Likewise, inventory offers from // muted avatars require the mute list to properly mute. - if (cap_url.empty() || !gSavedSettings.getBOOL("FSUseReadOfflineMsgsCap")) + if (cap_url.empty() + || gAgent.getRegionCapability("AcceptFriendship").empty() + || gAgent.getRegionCapability("AcceptGroupInvite").empty()) { + // Offline messages capability provides no session/transaction ids for message AcceptFriendship and IM_GROUP_INVITATION to work + // So make sure we have the caps before using it. requestOfflineMessagesLegacy(); } else @@ -2220,7 +2225,7 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url) message_data["to_agent_id"].asUUID(), IM_OFFLINE, (EInstantMessage)message_data["dialog"].asInteger(), - LLUUID::null, // session id, fix this for friendship offers to work + LLUUID::null, // session id, since there is none we can only use frienship/group invite caps message_data["timestamp"].asInteger(), message_data["from_agent_name"].asString(), message_data["message"].asString(), diff --git a/indra/newview/llnotificationlistitem.cpp b/indra/newview/llnotificationlistitem.cpp index 66ad5c0b7b..99c6ffcba1 100644 --- a/indra/newview/llnotificationlistitem.cpp +++ b/indra/newview/llnotificationlistitem.cpp @@ -324,38 +324,15 @@ void LLGroupInviteNotificationListItem::onClickJoinBtn() return; } - if(mParams.fee > 0) - { - LLSD args; - args["COST"] = llformat("%d", mParams.fee); - // Set the fee for next time to 0, so that we don't keep - // asking about a fee. - LLSD next_payload; - next_payload["group_id"]= mParams.group_id; - next_payload["transaction_id"]= mParams.transaction_id; - next_payload["fee"] = 0; - LLNotificationsUtil::add("JoinGroupCanAfford", args, next_payload); - } - else - { - send_improved_im(mParams.group_id, - std::string("name"), - std::string("message"), - IM_ONLINE, - IM_GROUP_INVITATION_ACCEPT, - mParams.transaction_id); - } + send_join_group_response(mParams.group_id, mParams.transaction_id, true, mParams.fee, mParams.use_offline_cap); + LLNotificationListItem::onClickCloseBtn(); } void LLGroupInviteNotificationListItem::onClickDeclineBtn() { - send_improved_im(mParams.group_id, - std::string("name"), - std::string("message"), - IM_ONLINE, - IM_GROUP_INVITATION_DECLINE, - mParams.transaction_id); + send_join_group_response(mParams.group_id, mParams.transaction_id, false, mParams.fee, mParams.use_offline_cap); + LLNotificationListItem::onClickCloseBtn(); } diff --git a/indra/newview/llnotificationlistitem.h b/indra/newview/llnotificationlistitem.h index d2d90b35e3..cfcd90f782 100644 --- a/indra/newview/llnotificationlistitem.h +++ b/indra/newview/llnotificationlistitem.h @@ -60,6 +60,7 @@ public: // std::string sender; S32 fee; + U8 use_offline_cap; LLDate time_stamp; LLDate received_time; LLSD inventory_offer; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index f3e7a2f0ee..aa883a5a97 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -294,6 +294,7 @@ static bool mLoginStatePastUI = false; const S32 DEFAULT_MAX_AGENT_GROUPS = 42; const S32 ALLOWED_MAX_AGENT_GROUPS = 500; +const F32 STATE_AGENT_WAIT_TIMEOUT = 240; //seconds boost::scoped_ptr LLStartUp::sStateWatcher(new LLEventStream("StartupState")); boost::scoped_ptr LLStartUp::sListener(new LLStartupListener()); @@ -2330,6 +2331,13 @@ bool idle_startup() LLStartUp::setStartupState( STATE_INVENTORY_SEND ); } display_startup(); + + if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT) + { + LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL; + LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); + reset_login(); + } return FALSE; } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 63d0cc5cec..102d583c40 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -138,6 +138,7 @@ #include "llpathfindingmanager.h" #include "llstartup.h" #include "boost/unordered_map.hpp" +#include #include "llcleanup.h" // [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "fsavatarrenderpersistence.h" @@ -10191,11 +10192,15 @@ void handle_report_bug(const LLSD& param) LLStringUtil::format_map_t replace; // FIRE-14001: JIRA report is being cut off when using Help -> Report Bug - //replace["[ENVIRONMENT]"] = LLURI::escape(LLAppViewer::instance()->getViewerInfoString(true)); + //std::string environment = LLAppViewer::instance()->getViewerInfoString(true); + //boost::regex regex; + //regex.assign(""); + //std::string stripped_env = boost::regex_replace(environment, regex, ""); + + //replace["[ENVIRONMENT]"] = LLURI::escape(stripped_env); LLSD sysinfo = FSData::getSystemInfo(); replace["[ENVIRONMENT]"] = LLURI::escape(sysinfo["Part1"].asString().substr(1) + sysinfo["Part2"].asString().substr(1)); // - LLSLURL location_url; LLAgentUI::buildSLURL(location_url); replace["[LOCATION]"] = LLURI::escape(location_url.getSLURLString()); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index b9cf54329a..8bbe313414 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -228,15 +228,15 @@ void accept_friendship_coro(std::string url, LLSD notification) void decline_friendship_coro(std::string url, LLSD notification, S32 option) { - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("friendshipResponceErrorProcessing", httpPolicy)); - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); if (url.empty()) { LL_WARNS() << "Empty capability!" << LL_ENDL; return; } + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("friendshipResponceErrorProcessing", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); LLSD payload = notification["payload"]; url += "?from=" + payload["from_id"].asString(); @@ -765,6 +765,119 @@ void send_sound_trigger(const LLUUID& sound_id, F32 gain) static LLSD sSavedGroupInvite; static LLSD sSavedResponse; +void response_group_invitation_coro(std::string url, LLUUID group_id, bool notify_and_update) +{ + if (url.empty()) + { + LL_WARNS("GroupInvite") << "Empty capability!" << LL_ENDL; + return; + } + + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("friendshipResponceErrorProcessing", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD payload; + payload["group"] = group_id; + + LLSD result = httpAdapter->postAndSuspend(httpRequest, url, payload); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS("GroupInvite") << "HTTP status, " << status.toTerseString() << + ". Group " << group_id << " invitation response processing failed." << LL_ENDL; + } + else + { + if (!result.has("success") || result["success"].asBoolean() == false) + { + LL_WARNS("GroupInvite") << "Server failed to process group " << group_id << " invitation response. " << httpResults << LL_ENDL; + } + else + { + LL_DEBUGS("GroupInvite") << "Successfully sent response to group " << group_id << " invitation" << LL_ENDL; + if (notify_and_update) + { + LLNotificationsUtil::add("JoinGroupSuccess"); + gAgent.sendAgentDataUpdateRequest(); + + LLGroupMgr::getInstance()->clearGroupData(group_id); + // refresh the floater for this group, if any. + LLGroupActions::refresh(group_id); + } + } + } +} + +void send_join_group_response(LLUUID group_id, LLUUID transaction_id, bool accept_invite, S32 fee, bool use_offline_cap, LLSD &payload) +{ + if (accept_invite && fee > 0) + { + // If there is a fee to join this group, make + // sure the user is sure they want to join. + LLSD args; + args["COST"] = llformat("%d", fee); + // Set the fee for next time to 0, so that we don't keep + // asking about a fee. + LLSD next_payload = payload; + next_payload["fee"] = 0; + LLNotificationsUtil::add("JoinGroupCanAfford", + args, + next_payload); + } + else if (use_offline_cap) + { + std::string url; + if (accept_invite) + { + url = gAgent.getRegionCapability("AcceptGroupInvite"); + } + else + { + url = gAgent.getRegionCapability("DeclineGroupInvite"); + } + + if (!url.empty()) + { + LLCoros::instance().launch("LLMessageSystem::acceptGroupInvitation", + boost::bind(response_group_invitation_coro, url, group_id, accept_invite)); + } + else + { + // if sim has no this cap, we can do nothing - regular request will fail + LL_WARNS("GroupInvite") << "No capability, can't reply to offline invitation!" << LL_ENDL; + } + } + else + { + EInstantMessage type = accept_invite ? IM_GROUP_INVITATION_ACCEPT : IM_GROUP_INVITATION_DECLINE; + + send_improved_im(group_id, + std::string("name"), + std::string("message"), + IM_ONLINE, + type, + transaction_id); + } +} + +void send_join_group_response(LLUUID group_id, LLUUID transaction_id, bool accept_invite, S32 fee, bool use_offline_cap) +{ + LLSD payload; + if (accept_invite) + { + payload["group_id"] = group_id; + payload["transaction_id"] = transaction_id; + payload["fee"] = fee; + payload["use_offline_cap"] = use_offline_cap; + } + send_join_group_response(group_id, transaction_id, accept_invite, fee, use_offline_cap, payload); +} + bool join_group_response(const LLSD& notification, const LLSD& response) { // A bit of variable saving and restoring is used to deal with the case where your group list is full and you @@ -803,6 +916,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response) std::string name = notification_adjusted["payload"]["name"].asString(); std::string message = notification_adjusted["payload"]["message"].asString(); S32 fee = notification_adjusted["payload"]["fee"].asInteger(); + U8 use_offline_cap = notification_adjusted["payload"]["use_offline_cap"].asInteger(); if (option == 2 && !group_id.isNull()) { @@ -847,42 +961,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response) return false; } } - - if (accept_invite) - { - // If there is a fee to join this group, make - // sure the user is sure they want to join. - if (fee > 0) - { - LLSD args; - args["COST"] = llformat("%d", fee); - // Set the fee for next time to 0, so that we don't keep - // asking about a fee. - LLSD next_payload = notification_adjusted["payload"]; - next_payload["fee"] = 0; - LLNotificationsUtil::add("JoinGroupCanAfford", - args, - next_payload); - } - else - { - send_improved_im(group_id, - std::string("name"), - std::string("message"), - IM_ONLINE, - IM_GROUP_INVITATION_ACCEPT, - transaction_id); - } - } - else - { - send_improved_im(group_id, - std::string("name"), - std::string("message"), - IM_ONLINE, - IM_GROUP_INVITATION_DECLINE, - transaction_id); - } + send_join_group_response(group_id, transaction_id, accept_invite, fee, use_offline_cap, notification_adjusted["payload"]); sSavedGroupInvite[id] = LLSD::emptyMap(); sSavedResponse[id] = LLSD::emptyMap(); @@ -1916,7 +1995,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& //don't spam them if they are getting flooded if (check_offer_throttle(mFromName, true)) { - log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString("."); + log_message = "" + chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + getSanitizedDescription() + LLTrans::getString("."); LLSD args; args["MESSAGE"] = log_message; LLNotificationsUtil::add("SystemMessageTip", args); @@ -2191,7 +2270,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const //don't spam them if they are getting flooded if (check_offer_throttle(mFromName, true)) { - log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString("."); + log_message = "" + chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + getSanitizedDescription() + LLTrans::getString("."); LLSD args; args["MESSAGE"] = log_message; LLNotificationsUtil::add("SystemMessageTip", args); @@ -2275,6 +2354,23 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const return false; } +std::string LLOfferInfo::getSanitizedDescription() +{ + // currently we get description from server as: 'Object' ( Location ) + // object name shouldn't be shown as a hyperlink + std::string description = mDesc; + + std::size_t start = mDesc.find_first_of("'"); + std::size_t end = mDesc.find_last_of("'"); + if ((start != std::string::npos) && (end != std::string::npos)) + { + description.insert(start, ""); + description.insert(end + 8, ""); + } + return description; +} + + void LLOfferInfo::initRespondFunctionMap() { if(mRespondFunctions.empty()) diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 9f7faed9f4..04e71726c7 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -74,6 +74,11 @@ enum InventoryOfferResponse BOOL can_afford_transaction(S32 cost); void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_group = FALSE, S32 trx_type = TRANS_GIFT, const std::string& desc = LLStringUtil::null); +void send_join_group_response(LLUUID group_id, + LLUUID transaction_id, + bool accept_invite, + S32 fee, + bool use_offline_cap); void process_logout_reply(LLMessageSystem* msg, void**); void process_layer_data(LLMessageSystem *mesgsys, void **user_data); @@ -278,6 +283,7 @@ public: private: void initRespondFunctionMap(); + std::string getSanitizedDescription(); typedef boost::function respond_function_t; typedef std::map respond_function_map_t; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 70e62a203c..132968fb16 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -3005,6 +3005,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) { capabilityNames.append("AbuseCategories"); capabilityNames.append("AcceptFriendship"); + capabilityNames.append("AcceptGroupInvite"); // ReadOfflineMsgs recieved messages only!!! capabilityNames.append("AgentPreferences"); capabilityNames.append("AgentState"); capabilityNames.append("AttachmentResources"); @@ -3015,6 +3016,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("CopyInventoryFromNotecard"); capabilityNames.append("CreateInventoryCategory"); capabilityNames.append("DeclineFriendship"); + capabilityNames.append("DeclineGroupInvite"); // ReadOfflineMsgs recieved messages only!!! capabilityNames.append("DispatchRegionInfo"); capabilityNames.append("DirectDelivery"); capabilityNames.append("EnvironmentSettings"); @@ -3077,7 +3079,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("ParcelVoiceInfoRequest"); capabilityNames.append("ProductInfoRequest"); capabilityNames.append("ProvisionVoiceAccountRequest"); - capabilityNames.append("ReadOfflineMsgs"); + capabilityNames.append("ReadOfflineMsgs"); // Only use with AcceptGroupInvite AcceptFriendship capabilityNames.append("RemoteParcelRequest"); capabilityNames.append("RenderMaterials"); capabilityNames.append("RequestTextureDownload"); diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 9ac17ecc6a..472598e306 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -275,6 +275,12 @@ bool LLWeb::useExternalBrowser(const std::string &url) boost::match_results matches; return !(boost::regex_search(uri_string, matches, pattern)); } + else + { + boost::regex pattern = boost::regex("^mailto:", boost::regex::perl | boost::regex::icase); + boost::match_results matches; + return boost::regex_search(url, matches, pattern); + } return false; #endif }