summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreyL ProductEngine <alihatskiy@productengine.com>2019-09-05 22:00:41 +0300
committerAndreyL ProductEngine <alihatskiy@productengine.com>2019-09-05 22:00:41 +0300
commitc3bd256f3340e9223b8855368648f3925760c0b4 (patch)
tree072244e740dffe530b4bd9c7e41c3074ac337402
parentf636b48109e3234ce8a5c36502c7f2615c253bb1 (diff)
parent894725f3314d24c20414a9a2491cf0cd59882788 (diff)
Upstream merge from viewer-neko
-rw-r--r--indra/llui/llmenugl.cpp6
-rw-r--r--indra/llui/lluictrl.cpp37
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/app_settings/commands.xml10
-rw-r--r--indra/newview/app_settings/settings.xml13
-rw-r--r--indra/newview/llcontrolavatar.cpp10
-rw-r--r--indra/newview/llconversationlog.cpp4
-rw-r--r--indra/newview/llfavoritesbar.cpp70
-rw-r--r--indra/newview/llfavoritesbar.h9
-rw-r--r--indra/newview/llfloaterconversationpreview.cpp7
-rw-r--r--indra/newview/llfloaterconversationpreview.h1
-rw-r--r--indra/newview/llfloaterforgetuser.cpp154
-rw-r--r--indra/newview/llfloaterforgetuser.h46
-rw-r--r--indra/newview/llfloaterland.cpp2
-rw-r--r--indra/newview/llfloaterlinkreplace.cpp85
-rw-r--r--indra/newview/llfloaterlinkreplace.h1
-rw-r--r--indra/newview/llfloaterpreference.cpp6
-rw-r--r--indra/newview/llfloaterpreference.h1
-rw-r--r--indra/newview/llimview.cpp11
-rw-r--r--indra/newview/llimview.h1
-rw-r--r--indra/newview/llinventorypanel.cpp1
-rw-r--r--indra/newview/lllogchat.cpp47
-rw-r--r--indra/newview/lllogchat.h3
-rw-r--r--indra/newview/llloginhandler.cpp7
-rw-r--r--indra/newview/llmoveview.cpp2
-rw-r--r--indra/newview/llpanellogin.cpp426
-rw-r--r--indra/newview/llpanellogin.h17
-rw-r--r--indra/newview/llsecapi.h46
-rw-r--r--indra/newview/llsechandler_basic.cpp176
-rw-r--r--indra/newview/llsechandler_basic.h61
-rw-r--r--indra/newview/llstartup.cpp41
-rw-r--r--indra/newview/lltoastalertpanel.cpp71
-rw-r--r--indra/newview/lltoastalertpanel.h5
-rw-r--r--indra/newview/lltoastnotifypanel.cpp15
-rw-r--r--indra/newview/lltoastnotifypanel.h2
-rw-r--r--indra/newview/lltoastpanel.cpp97
-rw-r--r--indra/newview/lltoastpanel.h19
-rw-r--r--indra/newview/lltooldraganddrop.cpp2
-rw-r--r--indra/newview/lltoolmgr.cpp2
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/llviewerinventory.cpp2
-rw-r--r--indra/newview/llviewermenu.cpp27
-rw-r--r--indra/newview/pipeline.cpp3
-rw-r--r--indra/newview/skins/default/textures/textures.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_forget_user.xml40
-rw-r--r--indra/newview/skins/default/xui/en/floater_merchant_outbox.xml156
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_trash.xml2
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml9
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml18
-rw-r--r--indra/newview/skins/default/xui/en/panel_login.xml54
-rw-r--r--indra/newview/skins/default/xui/en/panel_outbox_inventory.xml31
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_advanced.xml23
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml4
-rw-r--r--indra/newview/skins/default/xui/es/floater_buy_currency.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_buy_currency.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_buy_currency.xml2
-rw-r--r--indra/newview/tests/llsecapi_test.cpp9
57 files changed, 1407 insertions, 496 deletions
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 92543b952e..676c94468f 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -788,6 +788,12 @@ void LLMenuItemCallGL::initFromParams(const Params& p)
{
setEnabledControlVariable(control);
}
+ else
+ {
+ LL_WARNS() << "Failed to assign 'enabled' control variable to menu " << getName()
+ << ": control " << p.on_enable.control_name()
+ << " does not exist." << LL_ENDL;
+ }
}
}
if (p.on_click.isProvided())
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index df74e113e9..c98da0d410 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -137,13 +137,29 @@ void LLUICtrl::initFromParams(const Params& p)
{
LLControlVariable* control = findControl(p.enabled_controls.enabled);
if (control)
+ {
setEnabledControlVariable(control);
+ }
+ else
+ {
+ LL_WARNS() << "Failed to assign 'enabled' control variable to " << getName()
+ << ": control " << p.enabled_controls.enabled()
+ << " does not exist." << LL_ENDL;
+ }
}
else if(p.enabled_controls.disabled.isChosen())
{
LLControlVariable* control = findControl(p.enabled_controls.disabled);
if (control)
+ {
setDisabledControlVariable(control);
+ }
+ else
+ {
+ LL_WARNS() << "Failed to assign 'disabled' control variable to " << getName()
+ << ": control " << p.enabled_controls.disabled()
+ << " does not exist." << LL_ENDL;
+ }
}
}
if(p.controls_visibility.isProvided())
@@ -152,13 +168,29 @@ void LLUICtrl::initFromParams(const Params& p)
{
LLControlVariable* control = findControl(p.controls_visibility.visible);
if (control)
+ {
setMakeVisibleControlVariable(control);
+ }
+ else
+ {
+ LL_WARNS() << "Failed to assign visibility control variable to " << getName()
+ << ": control " << p.controls_visibility.visible()
+ << " does not exist." << LL_ENDL;
+ }
}
else if (p.controls_visibility.invisible.isChosen())
{
LLControlVariable* control = findControl(p.controls_visibility.invisible);
if (control)
+ {
setMakeInvisibleControlVariable(control);
+ }
+ else
+ {
+ LL_WARNS() << "Failed to assign invisibility control variable to " << getName()
+ << ": control " << p.controls_visibility.invisible()
+ << " does not exist." << LL_ENDL;
+ }
}
}
@@ -497,6 +529,11 @@ void LLUICtrl::setControlName(const std::string& control_name, LLView *context)
if (!control_name.empty())
{
LLControlVariable* control = context->findControl(control_name);
+ if (!control)
+ {
+ LL_WARNS() << "Failed to assign control variable to " << getName()
+ << ": control "<< control_name << " does not exist." << LL_ENDL;
+ }
setControlVariable(control);
}
}
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index b8789da66b..0ca5a08dfc 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -246,6 +246,7 @@ set(viewer_SOURCE_FILES
llfloaterexperiences.cpp
llfloaterflickr.cpp
llfloaterfonttest.cpp
+ llfloaterforgetuser.cpp
llfloatergesture.cpp
llfloatergodtools.cpp
llfloatergotoline.cpp
@@ -871,6 +872,7 @@ set(viewer_HEADER_FILES
llfloaterexperiences.h
llfloaterflickr.h
llfloaterfonttest.h
+ llfloaterforgetuser.h
llfloatergesture.h
llfloatergodtools.h
llfloatergotoline.h
diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index cab0c523b2..dae397a3b6 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -150,16 +150,6 @@
is_running_function="Floater.IsOpen"
is_running_parameters="moveview"
/>
- <command name="outbox"
- available_in_toybox="false"
- icon="Command_Outbox_Icon"
- label_ref="Command_Outbox_Label"
- tooltip_ref="Command_Outbox_Tooltip"
- execute_function="Floater.ToggleOrBringToFront"
- execute_parameters="outbox"
- is_running_function="Floater.IsOpen"
- is_running_parameters="outbox"
- />
<command name="people"
available_in_toybox="true"
icon="Command_People_Icon"
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index b4919c6e48..f54f683757 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4913,7 +4913,7 @@
<key>InventoryOutboxDisplayBoth</key>
<map>
<key>Comment</key>
- <string>Show the legacy Merchant Outbox UI as well as the Marketplace Listings UI</string>
+ <string>(Deprecated) Show the legacy Merchant Outbox UI as well as the Marketplace Listings UI</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -8434,6 +8434,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>RememberUser</key>
+ <map>
+ <key>Comment</key>
+ <string>Keep user name for next login</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>RememberPassword</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp
index 92eeebd705..f0682dc1ba 100644
--- a/indra/newview/llcontrolavatar.cpp
+++ b/indra/newview/llcontrolavatar.cpp
@@ -171,7 +171,10 @@ void LLControlAvatar::matchVolumeTransform()
if (attached_av)
{
LLViewerJointAttachment *attach = attached_av->getTargetAttachmentPoint(mRootVolp);
- setPositionAgent(mRootVolp->getRenderPosition());
+ if (getRegion() && !isDead())
+ {
+ setPositionAgent(mRootVolp->getRenderPosition());
+ }
attach->updateWorldPRSParent();
LLVector3 joint_pos = attach->getWorldPosition();
LLQuaternion joint_rot = attach->getWorldRotation();
@@ -227,7 +230,10 @@ void LLControlAvatar::matchVolumeTransform()
#endif
setRotation(bind_rot*obj_rot);
mRoot->setWorldRotation(bind_rot*obj_rot);
- setPositionAgent(vol_pos);
+ if (getRegion() && !isDead())
+ {
+ setPositionAgent(vol_pos);
+ }
mRoot->setPosition(vol_pos + mPositionConstraintFixup);
F32 global_scale = gSavedSettings.getF32("AnimatedObjectsGlobalScale");
diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp
index 9ccf9b98f7..ba6b251d58 100644
--- a/indra/newview/llconversationlog.cpp
+++ b/indra/newview/llconversationlog.cpp
@@ -486,7 +486,7 @@ bool LLConversationLog::saveToFile(const std::string& filename)
(S32)conv_it->getConversationType(),
(S32)0,
(S32)conv_it->hasOfflineMessages(),
- conv_it->getConversationName().c_str(),
+ LLURI::escape(conv_it->getConversationName()).c_str(),
participant_id.c_str(),
conversation_id.c_str(),
LLURI::escape(conv_it->getHistoryFileName()).c_str());
@@ -541,7 +541,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename)
params.time(LLUnits::Seconds::fromValue(time))
.conversation_type((SessionType)stype)
.has_offline_ims(has_offline_ims)
- .conversation_name(conv_name_buffer)
+ .conversation_name(LLURI::unescape(conv_name_buffer))
.participant_id(LLUUID(part_id_buffer))
.session_id(LLUUID(conv_id_buffer))
.history_filename(LLURI::unescape(history_file_name));
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 5b4b7789b4..17952349dc 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -1493,19 +1493,25 @@ void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id)
}
// static
-std::string LLFavoritesOrderStorage::getStoredFavoritesFilename()
+std::string LLFavoritesOrderStorage::getStoredFavoritesFilename(const std::string &grid)
{
- std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
+ std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
return (user_dir.empty() ? ""
: gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
"stored_favorites_"
- + LLGridManager::getInstance()->getGrid()
+ + grid
+ ".xml")
);
}
// static
+std::string LLFavoritesOrderStorage::getStoredFavoritesFilename()
+{
+ return getStoredFavoritesFilename(LLGridManager::getInstance()->getGrid());
+}
+
+// static
void LLFavoritesOrderStorage::destroyClass()
{
LLFavoritesOrderStorage::instance().cleanup();
@@ -1602,6 +1608,64 @@ void LLFavoritesOrderStorage::load()
}
}
+// static
+void LLFavoritesOrderStorage::removeFavoritesRecordOfUser(const std::string &user, const std::string &grid)
+{
+ std::string filename = getStoredFavoritesFilename(grid);
+ if (!filename.empty())
+ {
+ LLSD fav_llsd;
+ llifstream file;
+ file.open(filename.c_str());
+ if (file.is_open())
+ {
+ LLSDSerialize::fromXML(fav_llsd, file);
+ file.close();
+
+ // Note : use the "John Doe" and not the "john.doe" version of the name.
+ // See saveFavoritesSLURLs() here above for the reason why.
+ if (fav_llsd.has(user))
+ {
+ LLSD user_llsd = fav_llsd[user];
+
+ if ((user_llsd.beginArray() != user_llsd.endArray()) && user_llsd.beginArray()->has("id"))
+ {
+ for (LLSD::array_iterator iter = user_llsd.beginArray(); iter != user_llsd.endArray(); ++iter)
+ {
+ LLSD value;
+ value["id"] = iter->get("id").asUUID();
+ iter->assign(value);
+ }
+ fav_llsd[user] = user_llsd;
+ llofstream file;
+ file.open(filename.c_str());
+ if (file.is_open())
+ {
+ LLSDSerialize::toPrettyXML(fav_llsd, file);
+ file.close();
+ }
+ }
+ else
+ {
+ LL_INFOS("FavoritesBar") << "Removed favorites for " << user << LL_ENDL;
+ fav_llsd.erase(user);
+ }
+ }
+
+ llofstream out_file;
+ out_file.open(filename.c_str());
+ if (out_file.is_open())
+ {
+ LLSDSerialize::toPrettyXML(fav_llsd, out_file);
+ LL_INFOS("FavoritesBar") << "saved favorites to '" << filename << "' "
+ << LL_ENDL;
+ out_file.close();
+ }
+ }
+ }
+}
+
+// static
void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()
{
std::string filename = getStoredFavoritesFilename();
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index cac32c7f2a..d93161fd7a 100644
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -208,9 +208,15 @@ public:
* @see cleanup()
*/
static void destroyClass();
+ static std::string getStoredFavoritesFilename(const std::string &grid);
static std::string getStoredFavoritesFilename();
static std::string getSavedOrderFileName();
+ // Remove record of specified user's favorites from file on disk.
+ static void removeFavoritesRecordOfUser(const std::string &user, const std::string &grid);
+ // Remove record of current user's favorites from file on disk.
+ static void removeFavoritesRecordOfUser();
+
BOOL saveFavoritesRecord(bool pref_changed = false);
void showFavoritesOnLoginChanged(BOOL show);
@@ -232,9 +238,6 @@ private:
void load();
- // Remove record of current user's favorites from file on disk.
- void removeFavoritesRecordOfUser();
-
void onLandmarkLoaded(const LLUUID& asset_id, class LLLandmark* landmark);
void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl);
diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp
index 66198b3bf6..37186ce3d5 100644
--- a/indra/newview/llfloaterconversationpreview.cpp
+++ b/indra/newview/llfloaterconversationpreview.cpp
@@ -50,6 +50,7 @@ LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_i
mShowHistory(false),
mMessages(NULL),
mHistoryThreadsBusy(false),
+ mIsGroup(false),
mOpened(false)
{
}
@@ -75,6 +76,7 @@ BOOL LLFloaterConversationPreview::postBuild()
{
name = conv->getConversationName();
file = conv->getHistoryFileName();
+ mIsGroup = (LLIMModel::LLIMSession::GROUP_SESSION == conv->getConversationType());
}
else
{
@@ -82,6 +84,10 @@ BOOL LLFloaterConversationPreview::postBuild()
file = "chat";
}
mChatHistoryFileName = file;
+ if (mIsGroup)
+ {
+ mChatHistoryFileName += GROUP_CHAT_SUFFIX;
+ }
LLStringUtil::format_map_t args;
args["[NAME]"] = name;
std::string title = getString("Title", args);
@@ -145,6 +151,7 @@ void LLFloaterConversationPreview::onOpen(const LLSD& key)
LLSD load_params;
load_params["load_all_history"] = true;
load_params["cut_off_todays_date"] = false;
+ load_params["is_group"] = mIsGroup;
// The temporary message list with "Loading..." text
// Will be deleted upon loading completion in setPages() method
diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h
index a8dbbc9ffe..7ca4ee6945 100644
--- a/indra/newview/llfloaterconversationpreview.h
+++ b/indra/newview/llfloaterconversationpreview.h
@@ -66,6 +66,7 @@ private:
bool mShowHistory;
bool mHistoryThreadsBusy;
bool mOpened;
+ bool mIsGroup;
};
#endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */
diff --git a/indra/newview/llfloaterforgetuser.cpp b/indra/newview/llfloaterforgetuser.cpp
new file mode 100644
index 0000000000..5659cb2f79
--- /dev/null
+++ b/indra/newview/llfloaterforgetuser.cpp
@@ -0,0 +1,154 @@
+/**
+ * @file llfloaterforgetuser.cpp
+ * @brief LLFloaterForgetUser class definition.
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterforgetuser.h"
+
+#include "llcheckboxctrl.h"
+#include "llfavoritesbar.h"
+#include "llpanellogin.h" // for helper function getUserName() and to repopulate list if nessesary
+#include "llscrolllistctrl.h"
+#include "llsecapi.h"
+#include "llviewernetwork.h"
+
+
+LLFloaterForgetUser::LLFloaterForgetUser(const LLSD &key)
+ : LLFloater("floater_forget_user"),
+ mLoginPanelDirty(false)
+{
+
+}
+
+LLFloaterForgetUser::~LLFloaterForgetUser()
+{
+ if (mLoginPanelDirty)
+ {
+ LLPanelLogin::resetFields();
+ }
+}
+
+BOOL LLFloaterForgetUser::postBuild()
+{
+ // Note, storage works per grid, watever is selected currently in login screen or logged in.
+ // Since login screen can change grid, store the value.
+ mGrid = LLGridManager::getInstance()->getGrid();
+
+ LLScrollListCtrl *scroll_list = getChild<LLScrollListCtrl>("user_list");
+ if (gSecAPIHandler->hasCredentialMap("login_list", mGrid))
+ {
+ LLSecAPIHandler::credential_map_t credencials;
+ gSecAPIHandler->loadCredentialMap("login_list", mGrid, credencials);
+
+ LLSecAPIHandler::credential_map_t::iterator cr_iter = credencials.begin();
+ LLSecAPIHandler::credential_map_t::iterator cr_end = credencials.end();
+ while (cr_iter != cr_end)
+ {
+ if (cr_iter->second.notNull()) // basic safety
+ {
+ LLScrollListItem::Params item_params;
+ item_params.value(cr_iter->first);
+ item_params.columns.add()
+ .value(LLPanelLogin::getUserName(cr_iter->second))
+ .column("user")
+ .font(LLFontGL::getFontSansSerifSmall());
+ scroll_list->addRow(item_params, ADD_BOTTOM);
+ }
+ cr_iter++;
+ }
+ scroll_list->selectFirstItem();
+ }
+ else
+ {
+ LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(mGrid);
+ if (cred.notNull())
+ {
+ LLScrollListItem::Params item_params;
+ item_params.value(cred->userID());
+ item_params.columns.add()
+ .value(LLPanelLogin::getUserName(cred))
+ .column("user")
+ .font(LLFontGL::getFontSansSerifSmall());
+ scroll_list->addRow(item_params, ADD_BOTTOM);
+ scroll_list->selectFirstItem();
+ }
+ }
+
+ bool enable_button = scroll_list->getFirstSelectedIndex() != -1;
+ getChild<LLView>("delete_data")->setEnabled(enable_button);
+ LLButton *button = getChild<LLButton>("forget");
+ button->setEnabled(enable_button);
+ button->setCommitCallback(boost::bind(&LLFloaterForgetUser::onForgetClicked, this));
+
+ return TRUE;
+}
+
+void LLFloaterForgetUser::onForgetClicked()
+{
+ mLoginPanelDirty = true;
+ LLScrollListCtrl *scroll_list = getChild<LLScrollListCtrl>("user_list");
+ std::string user_key = scroll_list->getSelectedValue();
+
+ // remove creds
+ gSecAPIHandler->removeFromCredentialMap("login_list", mGrid, user_key);
+
+ LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(mGrid);
+ if (cred.notNull() && cred->userID() == user_key)
+ {
+ gSecAPIHandler->deleteCredential(cred);
+ }
+
+ // Clean data
+ LLCheckBoxCtrl *chk_box = getChild<LLCheckBoxCtrl>("delete_data");
+ BOOL delete_data = chk_box->getValue();
+ if (delete_data)
+ {
+ // key is edentical to one we use for name of user's folder
+ std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + user_key;
+ gDirUtilp->deleteDirAndContents(user_path);
+
+ // Clean favorites, label is edentical to username
+ LLFavoritesOrderStorage::removeFavoritesRecordOfUser(scroll_list->getSelectedItemLabel(), mGrid);
+
+ // Note: we do not clean user-related files from cache because there are id dependent (inventory)
+ // files and cache has separate cleaning mechanism either way.
+ // Also this only cleans user from current grid, not all of them.
+ }
+
+
+ // Update UI
+ scroll_list->deleteSelectedItems();
+ scroll_list->selectFirstItem();
+ if (scroll_list->getFirstSelectedIndex() == -1)
+ {
+ LLButton *button = getChild<LLButton>("forget");
+ button->setEnabled(false);
+ chk_box->setEnabled(false);
+ }
+}
+
+
diff --git a/indra/newview/llfloaterforgetuser.h b/indra/newview/llfloaterforgetuser.h
new file mode 100644
index 0000000000..119aece2d1
--- /dev/null
+++ b/indra/newview/llfloaterforgetuser.h
@@ -0,0 +1,46 @@
+/**
+ * @file llfloaterforgetuser.h
+ * @brief LLFloaterForgetUser class declaration.
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERFORGETUSER_H
+#define LL_LLFLOATERFORGETUSER_H
+
+#include "llfloater.h"
+
+class LLFloaterForgetUser : public LLFloater
+{
+public:
+ LLFloaterForgetUser(const LLSD &key);
+ ~LLFloaterForgetUser();
+
+ BOOL postBuild();
+ void onForgetClicked();
+
+private:
+ bool mLoginPanelDirty;
+ std::string mGrid;
+};
+
+#endif
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 3098c6d118..d8f4360142 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -2209,7 +2209,7 @@ void LLPanelLandOptions::refreshSearch()
// effort to reduce search spam from small parcels. See also
// the search crawler "grid-crawl.py" in secondlife.com/doc/app/search/ JC
const S32 MIN_PARCEL_AREA_FOR_SEARCH = 128;
- bool large_enough = parcel->getArea() > MIN_PARCEL_AREA_FOR_SEARCH;
+ bool large_enough = parcel->getArea() >= MIN_PARCEL_AREA_FOR_SEARCH;
if (large_enough)
{
if (can_change)
diff --git a/indra/newview/llfloaterlinkreplace.cpp b/indra/newview/llfloaterlinkreplace.cpp
index 10cce3bd22..595d584799 100644
--- a/indra/newview/llfloaterlinkreplace.cpp
+++ b/indra/newview/llfloaterlinkreplace.cpp
@@ -32,6 +32,8 @@
#include "llagent.h"
#include "llappearancemgr.h"
#include "lllineeditor.h"
+#include "llnotificationsutil.h"
+#include "llnotifications.h"
#include "lltextbox.h"
#include "llviewercontrol.h"
@@ -142,37 +144,72 @@ void LLFloaterLinkReplace::onStartClicked()
LL_WARNS() << "Cannot replace. Source and target are identical." << LL_ENDL;
return;
}
+
+ const LLUUID& source_item_id = gInventory.getLinkedItemID(mSourceUUID);
+ LLViewerInventoryItem *source_item = gInventory.getItem(source_item_id);
+ const LLUUID& target_item_id = gInventory.getLinkedItemID(mTargetUUID);
+ LLViewerInventoryItem *target_item = gInventory.getItem(target_item_id);
- LLInventoryModel::cat_array_t cat_array;
- LLLinkedItemIDMatches is_linked_item_match(mSourceUUID);
- gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
- cat_array,
- mRemainingInventoryItems,
- LLInventoryModel::INCLUDE_TRASH,
- is_linked_item_match);
- LL_INFOS() << "Found " << mRemainingInventoryItems.size() << " inventory links that need to be replaced." << LL_ENDL;
- if (mRemainingInventoryItems.size() > 0)
+ LLNotification::Params params("ConfirmReplaceLink");
+ params.functor.function(boost::bind(&LLFloaterLinkReplace::onStartClickedResponse, this, _1, _2));
+ if (source_item && source_item->isWearableType() && source_item->getWearableType() <= LLWearableType::WT_EYES)
{
- LLViewerInventoryItem* target_item = gInventory.getItem(mTargetUUID);
- if (target_item)
+ if(target_item && target_item->isWearableType() && source_item->getWearableType() == target_item->getWearableType())
{
- mRemainingItems = (U32)mRemainingInventoryItems.size();
-
- LLStringUtil::format_map_t args;
- args["NUM"] = llformat("%d", mRemainingItems);
- mStatusText->setText(getString("ItemsRemaining", args));
-
- mStartBtn->setEnabled(FALSE);
- mRefreshBtn->setEnabled(FALSE);
-
- mEventTimer.start();
- tick();
+ LLNotifications::instance().forceResponse(params, 0);
}
else
{
- mStatusText->setText(getString("TargetNotFound"));
- LL_WARNS() << "Link replace target not found." << LL_ENDL;
+ LLSD args;
+ args["TYPE"] = LLWearableType::getTypeName(source_item->getWearableType());
+ params.substitutions(args);
+ LLNotifications::instance().add(params);
+ }
+ }
+ else
+ {
+ LLNotifications::instance().forceResponse(params, 0);
+ }
+}
+
+void LLFloaterLinkReplace::onStartClickedResponse(const LLSD& notification, const LLSD& response)
+{
+
+ if (LLNotificationsUtil::getSelectedOption(notification, response) == 0)
+ {
+
+ LLInventoryModel::cat_array_t cat_array;
+ LLLinkedItemIDMatches is_linked_item_match(mSourceUUID);
+ gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
+ cat_array,
+ mRemainingInventoryItems,
+ LLInventoryModel::INCLUDE_TRASH,
+ is_linked_item_match);
+ LL_INFOS() << "Found " << mRemainingInventoryItems.size() << " inventory links that need to be replaced." << LL_ENDL;
+
+ if (mRemainingInventoryItems.size() > 0)
+ {
+ LLViewerInventoryItem* target_item = gInventory.getItem(mTargetUUID);
+ if (target_item)
+ {
+ mRemainingItems = (U32)mRemainingInventoryItems.size();
+
+ LLStringUtil::format_map_t args;
+ args["NUM"] = llformat("%d", mRemainingItems);
+ mStatusText->setText(getString("ItemsRemaining", args));
+
+ mStartBtn->setEnabled(FALSE);
+ mRefreshBtn->setEnabled(FALSE);
+
+ mEventTimer.start();
+ tick();
+ }
+ else
+ {
+ mStatusText->setText(getString("TargetNotFound"));
+ LL_WARNS() << "Link replace target not found." << LL_ENDL;
+ }
}
}
}
diff --git a/indra/newview/llfloaterlinkreplace.h b/indra/newview/llfloaterlinkreplace.h
index dd5c301206..060773f93e 100644
--- a/indra/newview/llfloaterlinkreplace.h
+++ b/indra/newview/llfloaterlinkreplace.h
@@ -94,6 +94,7 @@ public:
private:
void checkEnableStart();
void onStartClicked();
+ void onStartClickedResponse(const LLSD& notification, const LLSD& response);
void decreaseOpenItemCount();
void updateFoundLinks();
void processBatch(LLInventoryModel::item_array_t items);
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 27a597a631..9d0e1972a3 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -419,6 +419,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
mCommitCallbackRegistrar.add("Pref.TranslationSettings", boost::bind(&LLFloaterPreference::onClickTranslationSettings, this));
mCommitCallbackRegistrar.add("Pref.AutoReplace", boost::bind(&LLFloaterPreference::onClickAutoReplace, this));
mCommitCallbackRegistrar.add("Pref.PermsDefault", boost::bind(&LLFloaterPreference::onClickPermsDefault, this));
+ mCommitCallbackRegistrar.add("Pref.RememberedUsernames", boost::bind(&LLFloaterPreference::onClickRememberedUsernames, this));
mCommitCallbackRegistrar.add("Pref.SpellChecker", boost::bind(&LLFloaterPreference::onClickSpellChecker, this));
mCommitCallbackRegistrar.add("Pref.Advanced", boost::bind(&LLFloaterPreference::onClickAdvanced, this));
@@ -2256,6 +2257,11 @@ void LLFloaterPreference::onClickPermsDefault()
LLFloaterReg::showInstance("perms_default");
}
+void LLFloaterPreference::onClickRememberedUsernames()
+{
+ LLFloaterReg::showInstance("forget_username");
+}
+
void LLFloaterPreference::onDeleteTranscripts()
{
LLSD args;
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index d46f0deb7a..8345ad1bb6 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -181,6 +181,7 @@ public:
void onClickProxySettings();
void onClickTranslationSettings();
void onClickPermsDefault();
+ void onClickRememberedUsernames();
void onClickAutoReplace();
void onClickSpellChecker();
void onClickRenderExceptions();
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 0f5d514660..c07064389b 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -848,7 +848,7 @@ void LLIMModel::LLIMSession::loadHistory()
std::list<LLSD> chat_history;
//involves parsing of a chat history
- LLLogChat::loadChatHistory(mHistoryFileName, chat_history);
+ LLLogChat::loadChatHistory(mHistoryFileName, chat_history, LLSD(), isGroupChat());
addMessagesFromHistory(chat_history);
}
}
@@ -912,6 +912,11 @@ bool LLIMModel::LLIMSession::isP2P()
return IM_NOTHING_SPECIAL == mType;
}
+bool LLIMModel::LLIMSession::isGroupChat()
+{
+ return IM_SESSION_GROUP_START == mType || (IM_SESSION_INVITE == mType && gAgent.isInGroup(mSessionID));
+}
+
bool LLIMModel::LLIMSession::isOtherParticipantAvaline()
{
return !mOtherParticipantIsAvatar;
@@ -969,6 +974,10 @@ void LLIMModel::LLIMSession::buildHistoryFileName()
mHistoryFileName = LLCacheName::buildUsername(mName);
}
}
+ else if (isGroupChat())
+ {
+ mHistoryFileName = mName + GROUP_CHAT_SUFFIX;
+ }
}
//static
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 81d3ffa1a6..344f6d9a83 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -91,6 +91,7 @@ public:
bool isOutgoingAdHoc() const;
bool isAdHoc();
bool isP2P();
+ bool isGroupChat();
bool isOtherParticipantAvaline();
bool isP2PSessionType() const { return mSessionType == P2P_SESSION;}
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index d4993a1091..6f461673ee 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -291,7 +291,6 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
if (!gSavedSettings.getBOOL("InventoryOutboxMakeVisible"))
{
getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX));
- getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX));
}
// hide marketplace listing box, unless we are a marketplace panel
if (!gSavedSettings.getBOOL("InventoryOutboxMakeVisible") && !mParams.use_marketplace_folders)
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 1bdeddbcfe..e2f253d2bd 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -67,6 +67,8 @@ const std::string LL_IM_FROM("from");
const std::string LL_IM_FROM_ID("from_id");
const std::string LL_TRANSCRIPT_FILE_EXTENSION("txt");
+const std::string GROUP_CHAT_SUFFIX(" (group)");
+
const static char IM_SYMBOL_SEPARATOR(':');
const static std::string IM_SEPARATOR(std::string() + IM_SYMBOL_SEPARATOR + " ");
const static std::string NEW_LINE("\n");
@@ -345,7 +347,7 @@ void LLLogChat::saveHistory(const std::string& filename,
}
// static
-void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params)
+void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params, bool is_group)
{
if (file_name.empty())
{
@@ -358,10 +360,25 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& m
LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");/*Flawfinder: ignore*/
if (!fptr)
{
- fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+ if (is_group)
+ {
+ std::string old_name(file_name);
+ old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size());
+ fptr = LLFile::fopen(LLLogChat::makeLogFileName(old_name), "r");
+ if (fptr)
+ {
+ fclose(fptr);
+ LLFile::copy(LLLogChat::makeLogFileName(old_name), LLLogChat::makeLogFileName(file_name));
+ }
+ fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");
+ }
if (!fptr)
{
- return; //No previous conversation with this name.
+ fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+ if (!fptr)
+ {
+ return; //No previous conversation with this name.
+ }
}
}
@@ -1047,12 +1064,28 @@ void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list<LL
if (!fptr)
{
- fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+ bool is_group = load_params.has("is_group") ? load_params["is_group"].asBoolean() : false;
+ if (is_group)
+ {
+ std::string old_name(file_name);
+ old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size());
+ fptr = LLFile::fopen(LLLogChat::makeLogFileName(old_name), "r");
+ if (fptr)
+ {
+ fclose(fptr);
+ LLFile::copy(LLLogChat::makeLogFileName(old_name), LLLogChat::makeLogFileName(file_name));
+ }
+ fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");
+ }
if (!fptr)
{
- mNewLoad = false;
- (*mLoadEndSignal)(messages, file_name);
- return; //No previous conversation with this name.
+ fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+ if (!fptr)
+ {
+ mNewLoad = false;
+ (*mLoadEndSignal)(messages, file_name);
+ return; //No previous conversation with this name.
+ }
}
}
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index fcbd38a044..6ccb2caf43 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -104,7 +104,7 @@ public:
static void getListOfTranscriptFiles(std::vector<std::string>& list);
static void getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions);
- static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD());
+ static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD(), bool is_group = false);
typedef boost::signals2::signal<void ()> save_history_signal_t;
static boost::signals2::connection setSaveHistorySignal(const save_history_signal_t::slot_type& cb);
@@ -192,6 +192,7 @@ protected:
virtual ~LLChatLogParser() {};
};
+extern const std::string GROUP_CHAT_SUFFIX;
// LLSD map lookup constants
extern const std::string LL_IM_TIME; //("time");
diff --git a/indra/newview/llloginhandler.cpp b/indra/newview/llloginhandler.cpp
index eca34c0d4d..22cedf450e 100644
--- a/indra/newview/llloginhandler.cpp
+++ b/indra/newview/llloginhandler.cpp
@@ -139,8 +139,11 @@ LLPointer<LLCredential> LLLoginHandler::initializeLoginInfo()
// so try to load it from the UserLoginInfo
result = loadSavedUserLoginInfo();
if (result.isNull())
- {
- result = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
+ {
+ // Since legacy viewer store login info one per grid, newer viewers have to
+ // reuse same information to remember last user and for compatibility,
+ // but otherwise login info is stored in separate map in gSecAPIHandler
+ result = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
}
return result;
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index 19f238d99a..28201b7345 100644
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -574,6 +574,8 @@ BOOL LLPanelStandStopFlying::postBuild()
//mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE));
mStopFlyingButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStopFlyingButtonClick, this));
mStopFlyingButton->setVisible(FALSE);
+
+ gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLPanelStandStopFlying::updatePosition, this));
return TRUE;
}
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index e253557797..d7c189271e 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -77,6 +77,60 @@ LLPanelLogin *LLPanelLogin::sInstance = NULL;
BOOL LLPanelLogin::sCapslockDidNotification = FALSE;
BOOL LLPanelLogin::sCredentialSet = FALSE;
+// Helper functions
+
+LLPointer<LLCredential> load_user_credentials(std::string &user_key)
+{
+ if (gSecAPIHandler->hasCredentialMap("login_list", LLGridManager::getInstance()->getGrid()))
+ {
+ // user_key should be of "name Resident" format
+ return gSecAPIHandler->loadFromCredentialMap("login_list", LLGridManager::getInstance()->getGrid(), user_key);
+ }
+ else
+ {
+ // legacy (or legacy^2, since it also tries to load from settings)
+ return gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
+ }
+}
+
+// keys are lower case to be case insensitive so they are not always
+// identical to names which retain user input, like:
+// "AwEsOmE Resident" -> "awesome_resident"
+std::string get_user_key_from_name(const std::string &username)
+{
+ std::string key = username;
+ LLStringUtil::trim(key);
+ LLStringUtil::toLower(key);
+ if (!LLGridManager::getInstance()->isSystemGrid())
+ {
+ size_t separator_index = username.find_first_of(" ");
+ if (separator_index == username.npos)
+ {
+ // CRED_IDENTIFIER_TYPE_ACCOUNT
+ return key;
+ }
+ }
+ // CRED_IDENTIFIER_TYPE_AGENT
+ size_t separator_index = username.find_first_of(" ._");
+ std::string first = username.substr(0, separator_index);
+ std::string last;
+ if (separator_index != username.npos)
+ {
+ last = username.substr(separator_index + 1, username.npos);
+ LLStringUtil::trim(last);
+ }
+ else
+ {
+ // ...on Linden grids, single username users as considered to have
+ // last name "Resident"
+ // *TODO: Make login.cgi support "account_name" like above
+ last = "resident";
+ }
+
+ key = first + "_" + last;
+ return key;
+}
+
class LLLoginLocationAutoHandler : public LLCommandHandler
{
public:
@@ -168,6 +222,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
mCallback(callback),
mCallbackData(cb_data),
mListener(new LLPanelLoginListener(this)),
+ mFirstLoginThisInstall(gSavedSettings.getBOOL("FirstLoginThisInstall")),
mUsernameLength(0),
mPasswordLength(0),
mLocationLength(0),
@@ -186,7 +241,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
login_holder->addChild(this);
}
- if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
+ if (mFirstLoginThisInstall)
{
buildFromFile( "panel_login_first.xml");
}
@@ -206,35 +261,39 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
sendChildToBack(getChildView("forgot_password_text"));
sendChildToBack(getChildView("sign_up_text"));
- LLComboBox* favorites_combo = getChild<LLComboBox>("start_location_combo");
- updateLocationSelectorsVisibility(); // separate so that it can be called from preferences
- favorites_combo->setReturnCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
- favorites_combo->setFocusLostCallback(boost::bind(&LLPanelLogin::onLocationSLURL, this));
-
- LLComboBox* server_choice_combo = getChild<LLComboBox>("server_combo");
- server_choice_combo->setCommitCallback(boost::bind(&LLPanelLogin::onSelectServer, this));
-
- // Load all of the grids, sorted, and then add a bar and the current grid at the top
- server_choice_combo->removeall();
-
- std::string current_grid = LLGridManager::getInstance()->getGrid();
- std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();
- for (std::map<std::string, std::string>::iterator grid_choice = known_grids.begin();
- grid_choice != known_grids.end();
- grid_choice++)
- {
- if (!grid_choice->first.empty() && current_grid != grid_choice->first)
- {
- LL_DEBUGS("AppInit")<<"adding "<<grid_choice->first<<LL_ENDL;
- server_choice_combo->add(grid_choice->second, grid_choice->first);
- }
- }
- server_choice_combo->sortByName();
- LL_DEBUGS("AppInit")<<"adding current "<<current_grid<<LL_ENDL;
- server_choice_combo->add(LLGridManager::getInstance()->getGridLabel(),
- current_grid,
- ADD_TOP);
- server_choice_combo->selectFirstItem();
+ std::string current_grid = LLGridManager::getInstance()->getGrid();
+ if (!mFirstLoginThisInstall)
+ {
+ LLComboBox* favorites_combo = getChild<LLComboBox>("start_location_combo");
+ updateLocationSelectorsVisibility(); // separate so that it can be called from preferences
+ favorites_combo->setReturnCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
+ favorites_combo->setFocusLostCallback(boost::bind(&LLPanelLogin::onLocationSLURL, this));
+
+ LLComboBox* server_choice_combo = getChild<LLComboBox>("server_combo");
+ server_choice_combo->setCommitCallback(boost::bind(&LLPanelLogin::onSelectServer, this));
+
+ // Load all of the grids, sorted, and then add a bar and the current grid at the top
+ server_choice_combo->removeall();
+
+ std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();
+ for (std::map<std::string, std::string>::iterator grid_choice = known_grids.begin();
+ grid_choice != known_grids.end();
+ grid_choice++)
+ {
+ if (!grid_choice->first.empty() && current_grid != grid_choice->first)
+ {
+ LL_DEBUGS("AppInit") << "adding " << grid_choice->first << LL_ENDL;
+ server_choice_combo->add(grid_choice->second, grid_choice->first);
+ }
+ }
+ server_choice_combo->sortByName();
+
+ LL_DEBUGS("AppInit") << "adding current " << current_grid << LL_ENDL;
+ server_choice_combo->add(LLGridManager::getInstance()->getGridLabel(),
+ current_grid,
+ ADD_TOP);
+ server_choice_combo->selectFirstItem();
+ }
LLSLURL start_slurl(LLStartUp::getStartSLURL());
// The StartSLURL might have been set either by an explicit command-line
@@ -297,14 +356,30 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
loadLoginPage();
LLComboBox* username_combo(getChild<LLComboBox>("username_combo"));
- username_combo->setTextChangedCallback(boost::bind(&LLPanelLogin::addFavoritesToStartLocation, this));
+ username_combo->setTextChangedCallback(boost::bind(&LLPanelLogin::onUserNameTextEnty, this));
// STEAM-14: When user presses Enter with this field in focus, initiate login
- username_combo->setCommitCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
+ username_combo->setCommitCallback(boost::bind(&LLPanelLogin::onUserListCommit, this));
+ username_combo->setReturnCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
username_combo->setKeystrokeOnEsc(TRUE);
+
+ if (!mFirstLoginThisInstall)
+ {
+ LLCheckBoxCtrl* remember_name = getChild<LLCheckBoxCtrl>("remember_name");
+ remember_name->setCommitCallback(boost::bind(&LLPanelLogin::onRememberUserCheck, this));
+ }
}
void LLPanelLogin::addFavoritesToStartLocation()
{
+ if (mFirstLoginThisInstall)
+ {
+ // first login panel has no favorites, just update name length and buttons
+ std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple();
+ mUsernameLength = user_defined_name.length();
+ updateLoginButtons();
+ return;
+ }
+
// Clear the combo.
LLComboBox* combo = getChild<LLComboBox>("start_location_combo");
if (!combo) return;
@@ -316,14 +391,14 @@ void LLPanelLogin::addFavoritesToStartLocation()
// Load favorites into the combo.
std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple();
+ LLStringUtil::trim(user_defined_name);
LLStringUtil::toLower(user_defined_name);
- std::replace(user_defined_name.begin(), user_defined_name.end(), '.', ' ');
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites_" + LLGridManager::getInstance()->getGrid() + ".xml");
std::string old_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
mUsernameLength = user_defined_name.length();
updateLoginButtons();
- std::string::size_type index = user_defined_name.find(' ');
+ std::string::size_type index = user_defined_name.find_first_of(" ._");
if (index != std::string::npos)
{
std::string username = user_defined_name.substr(0, index);
@@ -332,6 +407,10 @@ void LLPanelLogin::addFavoritesToStartLocation()
{
user_defined_name = username;
}
+ else
+ {
+ user_defined_name = username + " " + lastname;
+ }
}
LLSD fav_llsd;
@@ -443,24 +522,6 @@ void LLPanelLogin::giveFocus()
}
// static
-void LLPanelLogin::showLoginWidgets()
-{
- if (sInstance)
- {
- // *NOTE: Mani - This may or may not be obselete code.
- // It seems to be part of the defunct? reg-in-client project.
- sInstance->getChildView("login_widgets")->setVisible( true);
- LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
-
- // *TODO: Append all the usual login parameters, like first_login=Y etc.
- std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage();
- web_browser->navigateTo( splash_screen_url, "text/html" );
- LLUICtrl* username_combo = sInstance->getChild<LLUICtrl>("username_combo");
- username_combo->setFocus(TRUE);
- }
-}
-
-// static
void LLPanelLogin::show(const LLRect &rect,
void (*callback)(S32 option, void* user_data),
void* callback_data)
@@ -480,9 +541,55 @@ void LLPanelLogin::show(const LLRect &rect,
gFocusMgr.setDefaultKeyboardFocus(sInstance);
}
+//static
+void LLPanelLogin::populateFields(LLPointer<LLCredential> credential, bool remember_user, bool remember_psswrd)
+{
+ if (!sInstance)
+ {
+ LL_WARNS() << "Attempted fillFields with no login view shown" << LL_ENDL;
+ return;
+ }
+ LLUICtrl* remember_check = sInstance->getChild<LLUICtrl>("remember_check");
+ remember_check->setValue(remember_psswrd);
+ if (sInstance->mFirstLoginThisInstall)
+ {
+ // no list to populate
+ setFields(credential, remember_psswrd);
+ }
+ else
+ {
+ sInstance->getChild<LLUICtrl>("remember_name")->setValue(remember_user);
+ sInstance->populateUserList(credential, remember_psswrd);
+ remember_check->setEnabled(remember_user);
+ }
+}
+
+//static
+void LLPanelLogin::resetFields()
+{
+ if (!sInstance)
+ {
+ // class not existing at this point might happen since this
+ // function is used to reset list in case of changes by external sources
+ return;
+ }
+ if (sInstance->mFirstLoginThisInstall)
+ {
+ // no list to populate
+ LL_WARNS() << "Shouldn't happen, user should have no ability to modify list on first install" << LL_ENDL;
+ }
+ else
+ {
+ LLUICtrl* remember_check = sInstance->getChild<LLUICtrl>("remember_check");
+ bool remember_psswrd = remember_check->getValue();
+ LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
+ sInstance->populateUserList(cred, remember_psswrd);
+ }
+}
+
// static
void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
- BOOL remember)
+ bool remember_psswrd)
{
if (!sInstance)
{
@@ -492,13 +599,15 @@ void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
sCredentialSet = TRUE;
LL_INFOS("Credentials") << "Setting login fields to " << *credential << LL_ENDL;
- LLSD identifier = credential->getIdentifier();
- if((std::string)identifier["type"] == "agent")
+ LLSD identifier = credential.notNull() ? credential->getIdentifier() : LLSD();
+
+ if(identifier.has("type") && (std::string)identifier["type"] == "agent")
{
+ // not nessesary for panel_login.xml, needed for panel_login_first.xml
std::string firstname = identifier["first_name"].asString();
std::string lastname = identifier["last_name"].asString();
std::string login_id = firstname;
- if (!lastname.empty() && lastname != "Resident")
+ if (!lastname.empty() && lastname != "Resident" && lastname != "resident")
{
// support traditional First Last name SLURLs
login_id += " ";
@@ -506,22 +615,23 @@ void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
}
sInstance->getChild<LLComboBox>("username_combo")->setLabel(login_id);
}
- else if((std::string)identifier["type"] == "account")
+ else if(identifier.has("type") && (std::string)identifier["type"] == "account")
{
sInstance->getChild<LLComboBox>("username_combo")->setLabel((std::string)identifier["account_name"]);
}
else
{
- sInstance->getChild<LLComboBox>("username_combo")->setLabel(std::string());
+ sInstance->getChild<LLComboBox>("username_combo")->setLabel(std::string());
}
+
sInstance->addFavoritesToStartLocation();
// if the password exists in the credential, set the password field with
// a filler to get some stars
- LLSD authenticator = credential->getAuthenticator();
+ LLSD authenticator = credential.notNull() ? credential->getAuthenticator() : LLSD();
LL_INFOS("Credentials") << "Setting authenticator field " << authenticator["type"].asString() << LL_ENDL;
if(authenticator.isMap() &&
authenticator.has("secret") &&
- (authenticator["secret"].asString().size() > 0) && remember)
+ (authenticator["secret"].asString().size() > 0) && remember_psswrd)
{
// This is a MD5 hex digest of a password.
@@ -537,36 +647,25 @@ void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
{
sInstance->getChild<LLUICtrl>("password_edit")->setValue(std::string());
}
- sInstance->getChild<LLUICtrl>("remember_check")->setValue(remember);
}
-
// static
void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
- BOOL& remember)
+ bool& remember_user,
+ bool& remember_psswrd)
{
if (!sInstance)
{
LL_WARNS() << "Attempted getFields with no login view shown" << LL_ENDL;
return;
}
-
- // load the credential so we can pass back the stored password or hash if the user did
- // not modify the password field.
-
- credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
LLSD identifier = LLSD::emptyMap();
LLSD authenticator = LLSD::emptyMap();
-
- if(credential.notNull())
- {
- authenticator = credential->getAuthenticator();
- }
- std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
- LLStringUtil::trim(username);
+ std::string username = sInstance->getChild<LLComboBox>("username_combo")->getValue().asString();
std::string password = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
+ LLStringUtil::trim(username);
LL_INFOS("Credentials", "Authentication") << "retrieving username:" << username << LL_ENDL;
// determine if the username is a first/last form or not.
@@ -586,6 +685,14 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
authenticator["type"] = CRED_AUTHENTICATOR_TYPE_CLEAR;
authenticator["secret"] = password;
}
+ else
+ {
+ credential = load_user_credentials(username);
+ if (credential.notNull())
+ {
+ authenticator = credential->getAuthenticator();
+ }
+ }
}
else
{
@@ -597,7 +704,7 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
if (separator_index != username.npos)
{
last = username.substr(separator_index+1, username.npos);
- LLStringUtil::trim(last);
+ LLStringUtil::trim(last);
}
else
{
@@ -625,10 +732,28 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
pass.hex_digest(md5pass);
authenticator["secret"] = md5pass;
}
+ else
+ {
+ std::string key = first + "_" + last;
+ LLStringUtil::toLower(key);
+ credential = load_user_credentials(key);
+ if (credential.notNull())
+ {
+ authenticator = credential->getAuthenticator();
+ }
+ }
}
}
credential = gSecAPIHandler->createCredential(LLGridManager::getInstance()->getGrid(), identifier, authenticator);
- remember = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
+ remember_psswrd = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
+ if (!sInstance->mFirstLoginThisInstall)
+ {
+ remember_user = sInstance->getChild<LLUICtrl>("remember_name")->getValue();
+ }
+ else
+ {
+ remember_user = true;
+ }
}
@@ -898,8 +1023,8 @@ void LLPanelLogin::onClickConnect(void *)
{
sCredentialSet = FALSE;
LLPointer<LLCredential> cred;
- BOOL remember;
- getFields(cred, remember);
+ bool remember_1, remember_2;
+ getFields(cred, remember_1, remember_2);
std::string identifier_type;
cred->identifierType(identifier_type);
LLSD allowed_credential_types;
@@ -953,6 +1078,57 @@ void LLPanelLogin::onClickSignUp(void*)
}
// static
+void LLPanelLogin::onUserNameTextEnty(void*)
+{
+ sInstance->mPasswordModified = true;
+ sInstance->getChild<LLUICtrl>("password_edit")->setValue(std::string());
+ sInstance->addFavoritesToStartLocation(); //will call updateLoginButtons()
+}
+
+// static
+void LLPanelLogin::onUserListCommit(void*)
+{
+ if (sInstance)
+ {
+ LLComboBox* username_combo(sInstance->getChild<LLComboBox>("username_combo"));
+ static S32 ind = -1;
+ if (ind != username_combo->getCurrentIndex())
+ {
+ std::string user_key = username_combo->getSelectedValue();
+ LLPointer<LLCredential> cred = gSecAPIHandler->loadFromCredentialMap("login_list", LLGridManager::getInstance()->getGrid(), user_key);
+ bool remember_psswrd = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
+ setFields(cred, remember_psswrd);
+ sInstance->mPasswordModified = false;
+ }
+ else
+ {
+ std::string pass = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
+ if (pass.empty())
+ {
+ sInstance->giveFocus();
+ }
+ else
+ {
+ onClickConnect(NULL);
+ }
+ }
+ }
+}
+
+// static
+void LLPanelLogin::onRememberUserCheck(void*)
+{
+ if (sInstance)
+ {
+ LLCheckBoxCtrl* remember_name(sInstance->getChild<LLCheckBoxCtrl>("remember_name"));
+ LLCheckBoxCtrl* remember_psswrd(sInstance->getChild<LLCheckBoxCtrl>("remember_check"));
+
+ bool remember = remember_name->getValue().asBoolean();
+ remember_psswrd->setEnabled(remember);
+ }
+}
+
+// static
void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data)
{
LLPanelLogin *self = (LLPanelLogin *)user_data;
@@ -979,9 +1155,11 @@ void LLPanelLogin::updateServer()
// for that grid and set them to the UI.
if(!sInstance->areCredentialFieldsDirty())
{
- LLPointer<LLCredential> credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
- bool remember = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
- sInstance->setFields(credential, remember);
+ // populate dropbox and setFields
+ bool remember_psswrd = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
+ // Note: following call is related to initializeLoginInfo()
+ LLPointer<LLCredential> credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
+ sInstance->populateUserList(credential, remember_psswrd);
}
// update the login panel links
@@ -1011,14 +1189,63 @@ void LLPanelLogin::updateLoginButtons()
LLButton* login_btn = getChild<LLButton>("connect_btn");
login_btn->setEnabled(mUsernameLength != 0 && mPasswordLength != 0);
+
+ if (!mFirstLoginThisInstall)
+ {
+ LLComboBox* user_combo = getChild<LLComboBox>("username_combo");
+ LLCheckBoxCtrl* remember_name = getChild<LLCheckBoxCtrl>("remember_name");
+ remember_name->setEnabled(user_combo->getCurrentIndex() == -1);
+ }
+}
+
+void LLPanelLogin::populateUserList(LLPointer<LLCredential> credential, bool remember_psswrd)
+{
+ LLComboBox* user_combo = getChild<LLComboBox>("username_combo");
+ user_combo->removeall();
+ user_combo->clear();
+
+ if (gSecAPIHandler->hasCredentialMap("login_list", LLGridManager::getInstance()->getGrid()))
+ {
+ LLSecAPIHandler::credential_map_t credencials;
+ gSecAPIHandler->loadCredentialMap("login_list", LLGridManager::getInstance()->getGrid(), credencials);
+
+ LLSecAPIHandler::credential_map_t::iterator cr_iter = credencials.begin();
+ LLSecAPIHandler::credential_map_t::iterator cr_end = credencials.end();
+ while (cr_iter != cr_end)
+ {
+ if (cr_iter->second.notNull()) // basic safety in case of future changes
+ {
+ // cr_iter->first == user_id , to be able to be find it in case we select it
+ user_combo->add(LLPanelLogin::getUserName(cr_iter->second), cr_iter->first, ADD_BOTTOM, TRUE);
+ }
+ cr_iter++;
+ }
+
+ if (credential.isNull() || !user_combo->setSelectedByValue(LLSD(credential->userID()), true))
+ {
+ // selection failed, just deselect whatever might be selected
+ user_combo->setValue(std::string());
+ }
+ else
+ {
+ setFields(credential, remember_psswrd);
+ }
+ }
+ else
+ {
+ if (credential.notNull())
+ {
+ user_combo->add(LLPanelLogin::getUserName(credential), credential->userID(), ADD_BOTTOM, TRUE);
+ setFields(credential, remember_psswrd);
+ }
+ }
}
+
void LLPanelLogin::onSelectServer()
{
// The user twiddled with the grid choice ui.
// apply the selection to the grid setting.
- LLPointer<LLCredential> credential;
-
LLComboBox* server_combo = getChild<LLComboBox>("server_combo");
LLSD server_combo_val = server_combo->getSelectedValue();
LL_INFOS("AppInit") << "grid "<<server_combo_val.asString()<< LL_ENDL;
@@ -1077,3 +1304,34 @@ bool LLPanelLogin::getShowFavorites()
{
return gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin");
}
+
+// static
+std::string LLPanelLogin::getUserName(LLPointer<LLCredential> &cred)
+{
+ if (cred.isNull())
+ {
+ return "unknown";
+ }
+ const LLSD &ident = cred->getIdentifier();
+
+ if (!ident.isMap())
+ {
+ return "unknown";
+ }
+ else if ((std::string)ident["type"] == "agent")
+ {
+ std::string second_name = ident["last_name"];
+ if (second_name == "resident" || second_name == "Resident")
+ {
+ return (std::string)ident["first_name"];
+ }
+ return (std::string)ident["first_name"] + " " + (std::string)ident["last_name"];
+ }
+ else if ((std::string)ident["type"] == "account")
+ {
+ return LLCacheName::cleanFullName((std::string)ident["account_name"]);
+ }
+
+ return "unknown";
+}
+
diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h
index c633582d89..3eb7b68949 100644
--- a/indra/newview/llpanellogin.h
+++ b/indra/newview/llpanellogin.h
@@ -55,9 +55,9 @@ public:
void (*callback)(S32 option, void* user_data),
void* callback_data);
- static void setFields(LLPointer<LLCredential> credential, BOOL remember);
-
- static void getFields(LLPointer<LLCredential>& credential, BOOL& remember);
+ static void populateFields(LLPointer<LLCredential> credential, bool remember_user, bool remember_psswrd);
+ static void resetFields();
+ static void getFields(LLPointer<LLCredential>& credential, bool& remember_user, bool& remember_psswrd);
static BOOL isCredentialSet() { return sCredentialSet; }
@@ -72,8 +72,6 @@ public:
void setSiteIsAlive( bool alive );
- void showLoginWidgets();
-
static void loadLoginPage();
static void giveFocus();
static void setAlwaysRefresh(bool refresh);
@@ -88,6 +86,9 @@ public:
// called from prefs when initializing panel
static bool getShowFavorites();
+ // extract name from cred in a format apropriate for username field
+ static std::string getUserName(LLPointer<LLCredential> &cred);
+
private:
friend class LLPanelLoginListener;
void addFavoritesToStartLocation();
@@ -95,11 +96,16 @@ private:
void onSelectServer();
void onLocationSLURL();
+ static void setFields(LLPointer<LLCredential> credential, bool remember_psswrd);
+
static void onClickConnect(void*);
static void onClickNewAccount(void*);
static void onClickVersion(void*);
static void onClickForgotPassword(void*);
static void onClickSignUp(void*);
+ static void onUserNameTextEnty(void*);
+ static void onUserListCommit(void*);
+ static void onRememberUserCheck(void*);
static void onPassKey(LLLineEditor* caller, void* user_data);
static void updateServerCombo();
@@ -107,6 +113,7 @@ private:
boost::scoped_ptr<LLPanelLoginListener> mListener;
void updateLoginButtons();
+ void populateUserList(LLPointer<LLCredential> credential, bool remember_psswrd);
void (*mCallback)(S32 option, void *userdata);
void* mCallbackData;
diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h
index d207f3b5b7..c0f0a367c7 100644
--- a/indra/newview/llsecapi.h
+++ b/indra/newview/llsecapi.h
@@ -464,7 +464,19 @@ public:
// delete a protected data item from the store
virtual void deleteProtectedData(const std::string& data_type,
const std::string& data_id)=0;
-
+
+ // persist data in a protected store's map
+ virtual void addToProtectedMap(const std::string& data_type,
+ const std::string& data_id,
+ const std::string& map_elem,
+ const LLSD& data)=0;
+
+ // remove data from protected store's map
+ virtual void removeFromProtectedMap(const std::string& data_type,
+ const std::string& data_id,
+ const std::string& map_elem)=0;
+
+public:
virtual LLPointer<LLCredential> createCredential(const std::string& grid,
const LLSD& identifier,
const LLSD& authenticator)=0;
@@ -474,6 +486,38 @@ public:
virtual void saveCredential(LLPointer<LLCredential> cred, bool save_authenticator)=0;
virtual void deleteCredential(LLPointer<LLCredential> cred)=0;
+
+ // has map of credentials declared as specific storage
+ virtual bool hasCredentialMap(const std::string& storage,
+ const std::string& grid)=0;
+
+ // load map of credentials from specific storage
+ typedef std::map<std::string, LLPointer<LLCredential> > credential_map_t;
+ virtual void loadCredentialMap(const std::string& storage,
+ const std::string& grid,
+ credential_map_t& credential_map)=0;
+
+ // load single username from map of credentials from specific storage
+ virtual LLPointer<LLCredential> loadFromCredentialMap(const std::string& storage,
+ const std::string& grid,
+ const std::string& userid)=0;
+
+ // add item to map of credentials from specific storage
+ virtual void addToCredentialMap(const std::string& storage,
+ LLPointer<LLCredential> cred,
+ bool save_authenticator)=0;
+
+ // remove item from map of credentials from specific storage
+ virtual void removeFromCredentialMap(const std::string& storage,
+ LLPointer<LLCredential> cred)=0;
+
+ // remove item from map of credentials from specific storage
+ virtual void removeFromCredentialMap(const std::string& storage,
+ const std::string& grid,
+ const std::string& userid)=0;
+
+ virtual void removeCredentialMap(const std::string& storage,
+ const std::string& grid)=0;
};
diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp
index 9ab9e4a1a2..a8bb54a90e 100644
--- a/indra/newview/llsechandler_basic.cpp
+++ b/indra/newview/llsechandler_basic.cpp
@@ -52,6 +52,7 @@
#include "llmachineid.h"
+static const std::string DEFAULT_CREDENTIAL_STORAGE = "credential";
// 128 bits of salt data...
#define STORE_SALT_SIZE 16
@@ -1533,6 +1534,38 @@ void LLSecAPIBasicHandler::setProtectedData(const std::string& data_type,
mProtectedDataMap[data_type][data_id] = data;
}
+// persist data in a protected store's map
+void LLSecAPIBasicHandler::addToProtectedMap(const std::string& data_type,
+ const std::string& data_id,
+ const std::string& map_elem,
+ const LLSD& data)
+{
+ if (!mProtectedDataMap.has(data_type) || !mProtectedDataMap[data_type].isMap()) {
+ mProtectedDataMap[data_type] = LLSD::emptyMap();
+ }
+
+ if (!mProtectedDataMap[data_type].has(data_id) || !mProtectedDataMap[data_type][data_id].isMap()) {
+ mProtectedDataMap[data_type][data_id] = LLSD::emptyMap();
+ }
+
+ mProtectedDataMap[data_type][data_id][map_elem] = data;
+}
+
+// remove data from protected store's map
+void LLSecAPIBasicHandler::removeFromProtectedMap(const std::string& data_type,
+ const std::string& data_id,
+ const std::string& map_elem)
+{
+ if (mProtectedDataMap.has(data_type) &&
+ mProtectedDataMap[data_type].isMap() &&
+ mProtectedDataMap[data_type].has(data_id) &&
+ mProtectedDataMap[data_type][data_id].isMap() &&
+ mProtectedDataMap[data_type][data_id].has(map_elem))
+ {
+ mProtectedDataMap[data_type][data_id].erase(map_elem);
+ }
+}
+
//
// Create a credential object from an identifier and authenticator. credentials are
// per grid.
@@ -1545,10 +1578,10 @@ LLPointer<LLCredential> LLSecAPIBasicHandler::createCredential(const std::string
return result;
}
-// Load a credential from the credential store, given the grid
+// Load a credential from default credential store, given the grid
LLPointer<LLCredential> LLSecAPIBasicHandler::loadCredential(const std::string& grid)
{
- LLSD credential = getProtectedData("credential", grid);
+ LLSD credential = getProtectedData(DEFAULT_CREDENTIAL_STORAGE, grid);
LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid);
if(credential.isMap() &&
credential.has("identifier"))
@@ -1603,7 +1636,7 @@ void LLSecAPIBasicHandler::saveCredential(LLPointer<LLCredential> cred, bool sav
credential["authenticator"] = cred->getAuthenticator();
}
LL_DEBUGS("SECAPI") << "Saving Credential " << cred->getGrid() << ":" << cred->userID() << " " << save_authenticator << LL_ENDL;
- setProtectedData("credential", cred->getGrid(), credential);
+ setProtectedData(DEFAULT_CREDENTIAL_STORAGE, cred->getGrid(), credential);
//*TODO: If we're saving Agni credentials, should we write the
// credentials to the legacy password.dat/etc?
_writeProtectedData();
@@ -1613,11 +1646,137 @@ void LLSecAPIBasicHandler::saveCredential(LLPointer<LLCredential> cred, bool sav
void LLSecAPIBasicHandler::deleteCredential(LLPointer<LLCredential> cred)
{
LLSD undefVal;
- deleteProtectedData("credential", cred->getGrid());
+ deleteProtectedData(DEFAULT_CREDENTIAL_STORAGE, cred->getGrid());
cred->setCredentialData(undefVal, undefVal);
_writeProtectedData();
}
+// has map of credentials declared as specific storage
+bool LLSecAPIBasicHandler::hasCredentialMap(const std::string& storage, const std::string& grid)
+{
+ if (storage == DEFAULT_CREDENTIAL_STORAGE)
+ {
+ LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+ }
+
+ LLSD credential = getProtectedData(storage, grid);
+
+ return credential.isMap();
+}
+
+// Load map of credentials from specified credential store, given the grid
+void LLSecAPIBasicHandler::loadCredentialMap(const std::string& storage, const std::string& grid, credential_map_t& credential_map)
+{
+ if (storage == DEFAULT_CREDENTIAL_STORAGE)
+ {
+ LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+ }
+
+ LLSD credential = getProtectedData(storage, grid);
+ if (credential.isMap())
+ {
+ LLSD::map_const_iterator crd_it = credential.beginMap();
+ for (; crd_it != credential.endMap(); crd_it++)
+ {
+ LLSD::String name = crd_it->first;
+ const LLSD &link_map = crd_it->second;
+ LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid);
+ if (link_map.has("identifier"))
+ {
+ LLSD identifier = link_map["identifier"];
+ LLSD authenticator;
+ if (link_map.has("authenticator"))
+ {
+ authenticator = link_map["authenticator"];
+ }
+ result->setCredentialData(identifier, authenticator);
+ }
+ credential_map[name] = result;
+ }
+ }
+}
+
+LLPointer<LLCredential> LLSecAPIBasicHandler::loadFromCredentialMap(const std::string& storage, const std::string& grid, const std::string& userkey)
+{
+ if (storage == DEFAULT_CREDENTIAL_STORAGE)
+ {
+ LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+ }
+
+ LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid);
+
+ LLSD credential = getProtectedData(storage, grid);
+ if (credential.isMap() && credential.has(userkey) && credential[userkey].has("identifier"))
+ {
+ LLSD identifier = credential[userkey]["identifier"];
+ LLSD authenticator;
+ if (credential[userkey].has("authenticator"))
+ {
+ authenticator = credential[userkey]["authenticator"];
+ }
+ result->setCredentialData(identifier, authenticator);
+ }
+
+ return result;
+}
+
+// add item to map of credentials from specific storage
+void LLSecAPIBasicHandler::addToCredentialMap(const std::string& storage, LLPointer<LLCredential> cred, bool save_authenticator)
+{
+ if (storage == DEFAULT_CREDENTIAL_STORAGE)
+ {
+ LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+ }
+
+ std::string user_id = cred->userID();
+ LLSD credential = LLSD::emptyMap();
+ credential["identifier"] = cred->getIdentifier();
+ if (save_authenticator)
+ {
+ credential["authenticator"] = cred->getAuthenticator();
+ }
+ LL_DEBUGS("SECAPI") << "Saving Credential " << cred->getGrid() << ":" << cred->userID() << " " << save_authenticator << LL_ENDL;
+ addToProtectedMap(storage, cred->getGrid(), user_id, credential);
+
+ _writeProtectedData();
+}
+
+// remove item from map of credentials from specific storage
+void LLSecAPIBasicHandler::removeFromCredentialMap(const std::string& storage, LLPointer<LLCredential> cred)
+{
+ if (storage == DEFAULT_CREDENTIAL_STORAGE)
+ {
+ LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+ }
+
+ LLSD undefVal;
+ removeFromProtectedMap(storage, cred->getGrid(), cred->userID());
+ cred->setCredentialData(undefVal, undefVal);
+ _writeProtectedData();
+}
+
+// remove item from map of credentials from specific storage
+void LLSecAPIBasicHandler::removeFromCredentialMap(const std::string& storage, const std::string& grid, const std::string& userkey)
+{
+ if (storage == DEFAULT_CREDENTIAL_STORAGE)
+ {
+ LL_ERRS() << "Storing maps in default, single-items storage is not allowed" << LL_ENDL;
+ }
+
+ LLSD undefVal;
+ LLPointer<LLCredential> cred = loadFromCredentialMap(storage, grid, userkey);
+ removeFromProtectedMap(storage, grid, userkey);
+ cred->setCredentialData(undefVal, undefVal);
+ _writeProtectedData();
+}
+
+// remove item from map of credentials from specific storage
+void LLSecAPIBasicHandler::removeCredentialMap(const std::string& storage, const std::string& grid)
+{
+ deleteProtectedData(storage, grid);
+ _writeProtectedData();
+}
+
// load the legacy hash for agni, and decrypt it given the
// mac address
std::string LLSecAPIBasicHandler::_legacyLoadPassword()
@@ -1656,15 +1815,18 @@ std::string LLSecAPIBasicCredential::userID() const
}
else if ((std::string)mIdentifier["type"] == "agent")
{
- return (std::string)mIdentifier["first_name"] + "_" + (std::string)mIdentifier["last_name"];
+ std::string id = (std::string)mIdentifier["first_name"] + "_" + (std::string)mIdentifier["last_name"];
+ LLStringUtil::toLower(id);
+ return id;
}
else if ((std::string)mIdentifier["type"] == "account")
{
- return (std::string)mIdentifier["account_name"];
+ std::string id = (std::string)mIdentifier["account_name"];
+ LLStringUtil::toLower(id);
+ return id;
}
return "unknown";
-
}
// return a printable user identifier
diff --git a/indra/newview/llsechandler_basic.h b/indra/newview/llsechandler_basic.h
index c35617f564..426b5d392a 100644
--- a/indra/newview/llsechandler_basic.h
+++ b/indra/newview/llsechandler_basic.h
@@ -211,8 +211,9 @@ class LLSecAPIBasicCredential : public LLCredential
public:
LLSecAPIBasicCredential(const std::string& grid) : LLCredential(grid) {}
virtual ~LLSecAPIBasicCredential() {}
- // return a value representing the user id, (could be guid, name, whatever)
- virtual std::string userID() const;
+ // return a value representing the user id, used for server and voice
+ // (could be guid, name in format "name_resident", whatever)
+ virtual std::string userID() const;
// printible string identifying the credential.
virtual std::string asString() const;
@@ -246,7 +247,10 @@ public:
// exists, it'll be loaded. If not, one will be created (but not
// persisted)
virtual LLPointer<LLCertificateStore> getCertificateStore(const std::string& store_id);
-
+
+ // protectedData functions technically should be pretected or private,
+ // they are not because of llsechandler_basic_test imlementation
+
// persist data in a protected store
virtual void setProtectedData(const std::string& data_type,
const std::string& data_id,
@@ -259,19 +263,64 @@ public:
// delete a protected data item from the store
virtual void deleteProtectedData(const std::string& data_type,
const std::string& data_id);
-
+
+ // persist data in a protected store's map
+ virtual void addToProtectedMap(const std::string& data_type,
+ const std::string& data_id,
+ const std::string& map_elem,
+ const LLSD& data);
+
+ // remove data from protected store's map
+ virtual void removeFromProtectedMap(const std::string& data_type,
+ const std::string& data_id,
+ const std::string& map_elem);
+
// credential management routines
virtual LLPointer<LLCredential> createCredential(const std::string& grid,
const LLSD& identifier,
const LLSD& authenticator);
-
+
+ // load single credencial from default storage
virtual LLPointer<LLCredential> loadCredential(const std::string& grid);
+ // save credencial to default storage
virtual void saveCredential(LLPointer<LLCredential> cred, bool save_authenticator);
virtual void deleteCredential(LLPointer<LLCredential> cred);
-
+
+ // has map of credentials declared as specific storage
+ virtual bool hasCredentialMap(const std::string& storage,
+ const std::string& grid);
+
+ // load map of credentials from specific storage
+ virtual void loadCredentialMap(const std::string& storage,
+ const std::string& grid,
+ credential_map_t& credential_map);
+
+ // load single username from map of credentials from specific storage
+ virtual LLPointer<LLCredential> loadFromCredentialMap(const std::string& storage,
+ const std::string& grid,
+ const std::string& userid);
+
+ // add item to map of credentials from specific storage
+ virtual void addToCredentialMap(const std::string& storage,
+ LLPointer<LLCredential> cred,
+ bool save_authenticator);
+
+ // remove item from map of credentials from specific storage
+ virtual void removeFromCredentialMap(const std::string& storage,
+ LLPointer<LLCredential> cred);
+
+ // remove item from map of credentials from specific storage
+ virtual void removeFromCredentialMap(const std::string& storage,
+ const std::string& grid,
+ const std::string& userid);
+
+ virtual void removeCredentialMap(const std::string& storage,
+ const std::string& grid);
+
+
protected:
void _readProtectedData();
void _writeProtectedData();
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index bef27cfb99..77aa7b36b9 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -236,7 +236,8 @@ LLSLURL LLStartUp::sStartSLURL;
static LLPointer<LLCredential> gUserCredential;
static std::string gDisplayName;
-static BOOL gRememberPassword = TRUE;
+static bool gRememberPassword = true;
+static bool gRememberUser = true;
static U64 gFirstSimHandle = 0;
static LLHost gFirstSim;
@@ -701,19 +702,23 @@ bool idle_startup()
else if (gSavedSettings.getBOOL("AutoLogin"))
{
// Log into last account
- gRememberPassword = TRUE;
- gSavedSettings.setBOOL("RememberPassword", TRUE);
+ gRememberPassword = true;
+ gRememberUser = true;
+ gSavedSettings.setBOOL("RememberPassword", TRUE);
+ gSavedSettings.setBOOL("RememberUser", TRUE);
show_connect_box = false;
}
else if (gSavedSettings.getLLSD("UserLoginInfo").size() == 3)
{
// Console provided login&password
gRememberPassword = gSavedSettings.getBOOL("RememberPassword");
+ gRememberUser = gSavedSettings.getBOOL("RememberUser");
show_connect_box = false;
}
else
{
gRememberPassword = gSavedSettings.getBOOL("RememberPassword");
+ gRememberUser = gSavedSettings.getBOOL("RememberUser");
show_connect_box = TRUE;
}
@@ -781,10 +786,7 @@ bool idle_startup()
// Show the login dialog
login_show();
// connect dialog is already shown, so fill in the names
- if (gUserCredential.notNull() && !LLPanelLogin::isCredentialSet())
- {
- LLPanelLogin::setFields( gUserCredential, gRememberPassword);
- }
+ LLPanelLogin::populateFields( gUserCredential, gRememberUser, gRememberPassword);
LLPanelLogin::giveFocus();
// MAINT-3231 Show first run dialog only for Desura viewer
@@ -873,7 +875,7 @@ bool idle_startup()
{
// TODO if not use viewer auth
// Load all the name information out of the login view
- LLPanelLogin::getFields(gUserCredential, gRememberPassword);
+ LLPanelLogin::getFields(gUserCredential, gRememberUser, gRememberPassword);
// end TODO
// HACK: Try to make not jump on login
@@ -885,14 +887,21 @@ bool idle_startup()
// STATE_LOGIN_SHOW state if we've gone backwards
mLoginStatePastUI = true;
- // save the credentials
- std::string userid = "unknown";
- if(gUserCredential.notNull())
- {
- userid = gUserCredential->userID();
- gSecAPIHandler->saveCredential(gUserCredential, gRememberPassword);
- }
- gSavedSettings.setBOOL("RememberPassword", gRememberPassword);
+ // save the credentials
+ std::string userid = "unknown";
+ if (gUserCredential.notNull())
+ {
+ userid = gUserCredential->userID();
+ if (gRememberUser)
+ {
+ gSecAPIHandler->addToCredentialMap("login_list", gUserCredential, gRememberPassword);
+ // Legacy viewers use this method to store user credentials, newer viewers
+ // reuse it to be compatible and to remember last session
+ gSecAPIHandler->saveCredential(gUserCredential, gRememberPassword);
+ }
+ }
+ gSavedSettings.setBOOL("RememberPassword", gRememberPassword);
+ gSavedSettings.setBOOL("RememberUser", gRememberUser);
LL_INFOS("AppInit") << "Attempting login as: " << userid << LL_ENDL;
gDebugInfo["LoginName"] = userid;
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index 495c9c1f44..023d1a685c 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -62,9 +62,8 @@ static const S32 HPAD = 25;
static const S32 BTN_HPAD = 8;
LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal)
- : LLToastPanel(notification),
+ : LLCheckBoxToastPanel(notification),
mDefaultOption( 0 ),
- mCheck(NULL),
mCaution(notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH),
mLabel(notification->getName()),
mLineEditor(NULL)
@@ -347,20 +346,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
button_left += button_width + BTN_HPAD;
}
- std::string ignore_label;
-
- if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE)
- {
- setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label);
- }
- if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY)
- {
- setCheckBox(LLNotifications::instance().getGlobalString("skipnexttimesessiononly"), ignore_label);
- }
- else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
- {
- setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label);
- }
+ setCheckBoxes(HPAD, VPAD);
// *TODO: check necessity of this code
//gFloaterView->adjustToFitScreen(this, FALSE);
@@ -380,46 +366,6 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
LLTransientFloaterMgr::GLOBAL, this);
}
-bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std::string& check_control )
-{
- mCheck = LLUICtrlFactory::getInstance()->createFromFile<LLCheckBoxCtrl>("alert_check_box.xml", this, LLPanel::child_registry_t::instance());
-
- if(!mCheck)
- {
- return false;
- }
-
- const LLFontGL* font = mCheck->getFont();
- const S32 LINE_HEIGHT = font->getLineHeight();
-
- std::vector<std::string> lines;
- boost::split(lines, check_title, boost::is_any_of("\n"));
-
- // Extend dialog for "check next time"
- S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * HPAD;
- S32 check_width = S32(font->getWidth(lines[0]) + 0.99f) + 16; // use width of the first line
- max_msg_width = llmax(max_msg_width, check_width);
- S32 dialog_width = max_msg_width + 2 * HPAD;
-
- S32 dialog_height = LLToastPanel::getRect().getHeight();
- dialog_height += LINE_HEIGHT * lines.size();
- dialog_height += LINE_HEIGHT / 2;
-
- LLToastPanel::reshape( dialog_width, dialog_height, FALSE );
-
- S32 msg_x = (LLToastPanel::getRect().getWidth() - max_msg_width) / 2;
-
- // set check_box's attributes
- LLRect check_rect;
- mCheck->setRect(check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2, max_msg_width, LINE_HEIGHT*lines.size()));
- mCheck->setLabel(check_title);
- mCheck->setCommitCallback(boost::bind(&LLToastAlertPanel::onClickIgnore, this, _1));
-
- LLToastPanel::addChild(mCheck);
-
- return true;
-}
-
void LLToastAlertPanel::setVisible( BOOL visible )
{
// only make the "ding" sound if it's newly visible
@@ -562,16 +508,3 @@ void LLToastAlertPanel::onButtonPressed( const LLSD& data, S32 button )
mNotification->respond(response); // new notification reponse
}
-
-void LLToastAlertPanel::onClickIgnore(LLUICtrl* ctrl)
-{
- // checkbox sometimes means "hide and do the default" and
- // other times means "warn me again". Yuck. JC
- BOOL check = ctrl->getValue().asBoolean();
- if (mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
- {
- // question was "show again" so invert value to get "ignore"
- check = !check;
- }
- mNotification->setIgnored(check);
-}
diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h
index d1be5e018e..21310822c4 100644
--- a/indra/newview/lltoastalertpanel.h
+++ b/indra/newview/lltoastalertpanel.h
@@ -46,7 +46,7 @@ class LLLineEditor;
*/
class LLToastAlertPanel
- : public LLToastPanel
+ : public LLCheckBoxToastPanel
{
LOG_CLASS(LLToastAlertPanel);
public:
@@ -75,13 +75,11 @@ public:
virtual void draw();
virtual void setVisible( BOOL visible );
- bool setCheckBox( const std::string&, const std::string& );
void setCaution(BOOL val = TRUE) { mCaution = val; }
// If mUnique==TRUE only one copy of this message should exist
void setUnique(BOOL val = TRUE) { mUnique = val; }
void setEditTextArgs(const LLSD& edit_args);
- void onClickIgnore(LLUICtrl* ctrl);
void onButtonPressed(const LLSD& data, S32 button);
private:
@@ -106,7 +104,6 @@ private:
std::vector<ButtonData> mButtonData;
S32 mDefaultOption;
- LLCheckBoxCtrl* mCheck;
BOOL mCaution;
BOOL mUnique;
LLUIString mLabel;
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index a2116817a2..65684dc2fd 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -33,6 +33,7 @@
// library includes
#include "lldbstrings.h"
+#include "llcheckboxctrl.h"
#include "lllslconstants.h"
#include "llnotifications.h"
#include "lluiconstants.h"
@@ -55,7 +56,7 @@ const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL;
LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal;
LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images)
-: LLToastPanel(notification),
+: LLCheckBoxToastPanel(notification),
LLInstanceTracker<LLToastNotifyPanel, LLUUID, LLInstanceTrackerReplaceOnCollision>(notification->getID())
{
init(rect, show_images);
@@ -409,7 +410,17 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
//.xml file intially makes info panel only follow left/right/top. This is so that when control buttons are added the info panel
//can shift upward making room for the buttons inside mControlPanel. After the buttons are added, the info panel can then be set to follow 'all'.
mInfoPanel->setFollowsAll();
- snapToMessageHeight(mTextBox, LLToastPanel::MAX_TEXT_LENGTH);
+
+ // Add checkboxes if nessesary.
+ setCheckBoxes(HPAD * 3, VPAD * 4, mInfoPanel);
+
+ // Snap to message, then to checkbox if present
+ snapToMessageHeight(mTextBox, LLToastPanel::MAX_TEXT_LENGTH);
+ if (mCheck)
+ {
+ S32 new_panel_height = mCheck->getRect().getHeight() + getRect().getHeight();
+ reshape(getRect().getWidth(), new_panel_height);
+ }
// reshape the panel to its previous size
if (current_rect.notEmpty())
diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h
index e4a75acfda..a5a637c6fa 100644
--- a/indra/newview/lltoastnotifypanel.h
+++ b/indra/newview/lltoastnotifypanel.h
@@ -47,7 +47,7 @@ class LLNotificationForm;
* @deprecated this class will be removed after all toast panel types are
* implemented in separate classes.
*/
-class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker<LLToastNotifyPanel, LLUUID, LLInstanceTrackerReplaceOnCollision>
+class LLToastNotifyPanel: public LLCheckBoxToastPanel, public LLInstanceTracker<LLToastNotifyPanel, LLUUID, LLInstanceTrackerReplaceOnCollision>
{
public:
/**
diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp
index 7c624d5b50..977c6ac802 100644
--- a/indra/newview/lltoastpanel.cpp
+++ b/indra/newview/lltoastpanel.cpp
@@ -27,6 +27,7 @@
#include "llviewerprecompiledheaders.h"
#include "lldbstrings.h"
+#include "llcheckboxctrl.h"
#include "llpanelgenerictip.h"
#include "llpanelonlinestatus.h"
#include "llnotifications.h"
@@ -34,6 +35,8 @@
#include "lltoastpanel.h"
#include "lltoastscriptquestion.h"
+#include <boost/algorithm/string.hpp>
+
//static
const S32 LLToastPanel::MIN_PANEL_HEIGHT = 40; // VPAD(4)*2 + ICON_HEIGHT(32)
// 'magic numbers', consider initializing (512+20) part from xml/notifications
@@ -145,3 +148,97 @@ LLToastPanel* LLToastPanel::buidPanelFromNotification(
return res;
}
+
+LLCheckBoxToastPanel::LLCheckBoxToastPanel(const LLNotificationPtr& p_ntf)
+: LLToastPanel(p_ntf),
+mCheck(NULL)
+{
+
+}
+
+void LLCheckBoxToastPanel::setCheckBoxes(const S32 &h_pad, const S32 &v_pad, LLView *parent_view)
+{
+ std::string ignore_label;
+ LLNotificationFormPtr form = mNotification->getForm();
+
+ if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE)
+ {
+ setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+ }
+ if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY)
+ {
+ setCheckBox(LLNotifications::instance().getGlobalString("skipnexttimesessiononly"), ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+ }
+ else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
+ {
+ setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+ }
+ else if (form->getIgnoreType() == LLNotificationForm::IGNORE_MEDIA_PLAYMUTE)
+ {
+ setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+ }
+}
+
+bool LLCheckBoxToastPanel::setCheckBox(const std::string& check_title,
+ const std::string& check_control,
+ const commit_signal_t::slot_type& cb,
+ const S32 &h_pad,
+ const S32 &v_pad,
+ LLView *parent_view)
+{
+ mCheck = LLUICtrlFactory::getInstance()->createFromFile<LLCheckBoxCtrl>("alert_check_box.xml", this, LLPanel::child_registry_t::instance());
+
+ if (!mCheck)
+ {
+ return false;
+ }
+
+ const LLFontGL* font = mCheck->getFont();
+ const S32 LINE_HEIGHT = font->getLineHeight();
+
+ std::vector<std::string> lines;
+ boost::split(lines, check_title, boost::is_any_of("\n"));
+
+ // Extend dialog for "check next time"
+ S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * h_pad;
+ S32 check_width = S32(font->getWidth(lines[0]) + 0.99f) + 16; // use width of the first line
+ max_msg_width = llmax(max_msg_width, check_width);
+ S32 dialog_width = max_msg_width + 2 * h_pad;
+
+ S32 dialog_height = LLToastPanel::getRect().getHeight();
+ dialog_height += LINE_HEIGHT * lines.size();
+ dialog_height += LINE_HEIGHT / 2;
+
+ LLToastPanel::reshape(dialog_width, dialog_height, FALSE);
+
+ S32 msg_x = (LLToastPanel::getRect().getWidth() - max_msg_width) / 2;
+
+ // set check_box's attributes
+ LLRect check_rect;
+ mCheck->setRect(check_rect.setOriginAndSize(msg_x, v_pad + BTN_HEIGHT + LINE_HEIGHT / 2, max_msg_width, LINE_HEIGHT*lines.size()));
+ mCheck->setLabel(check_title);
+ mCheck->setCommitCallback(cb);
+
+ if (parent_view)
+ {
+ // assume that width and height autoadjusts to toast
+ parent_view->addChild(mCheck);
+ }
+ else
+ {
+ LLToastPanel::addChild(mCheck);
+ }
+
+ return true;
+}
+
+void LLCheckBoxToastPanel::onCommitCheckbox(LLUICtrl* ctrl)
+{
+ BOOL check = ctrl->getValue().asBoolean();
+ if (mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
+ {
+ // question was "show again" so invert value to get "ignore"
+ check = !check;
+ }
+ mNotification->setIgnored(check);
+}
diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h
index 6a9b72a5ae..f4c758ade9 100644
--- a/indra/newview/lltoastpanel.h
+++ b/indra/newview/lltoastpanel.h
@@ -64,4 +64,23 @@ protected:
S32 computeSnappedToMessageHeight(LLTextBase* message, S32 maxLineCount);
};
+class LLCheckBoxCtrl;
+
+// Wrapper with support for 'don't ask again' checkbox
+class LLCheckBoxToastPanel : public LLToastPanel
+{
+public:
+ LLCheckBoxToastPanel(const LLNotificationPtr& p_ntf);
+ virtual ~LLCheckBoxToastPanel() {};
+
+ // set checkboxes acording to defaults from form
+ void setCheckBoxes(const S32 &h_pad, const S32 &v_pad, LLView *parent_view = NULL);
+ // set single checkbox
+ bool setCheckBox(const std::string&, const std::string&, const commit_signal_t::slot_type& cb, const S32 &h_pad, const S32 &v_pad, LLView *parent_view = NULL);
+protected:
+ void onCommitCheckbox(LLUICtrl* ctrl);
+
+ LLCheckBoxCtrl* mCheck;
+};
+
#endif /* LL_TOASTPANEL_H */
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index f66211ef34..7d77a8983f 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -1728,6 +1728,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv(
const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
if(gInventory.isObjectDescendentOf(item->getUUID(), outbox_id))
{
+ // Legacy
return ACCEPT_NO;
}
@@ -2154,6 +2155,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory(
const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
if(gInventory.isObjectDescendentOf(category->getUUID(), outbox_id))
{
+ // Legacy
return ACCEPT_NO;
}
diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp
index f6eb290bc3..3fcf193dec 100644
--- a/indra/newview/lltoolmgr.cpp
+++ b/indra/newview/lltoolmgr.cpp
@@ -355,7 +355,7 @@ bool LLToolMgr::inBuildMode()
bool LLToolMgr::canAccessMarketplace()
{
- return (LLMarketplaceData::instance().getSLMStatus() != MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT) || gSavedSettings.getBOOL("InventoryOutboxDisplayBoth");
+ return (LLMarketplaceData::instance().getSLMStatus() != MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT);
}
void LLToolMgr::toggleMarketplace(const LLSD& sdname)
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index f475ab7d66..846a8e62a1 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -69,6 +69,7 @@
#include "llfloaterevent.h"
#include "llfloaterflickr.h"
#include "llfloaterfonttest.h"
+#include "llfloaterforgetuser.h"
#include "llfloatergesture.h"
#include "llfloatergodtools.h"
#include "llfloatergridstatus.h"
@@ -235,6 +236,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("experience_search", "floater_experience_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiencePicker>);
LLFloaterReg::add("font_test", "floater_font_test.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFontTest>);
+ LLFloaterReg::add("forget_username", "floater_forget_user.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterForgetUser>);
LLFloaterReg::add("gestures", "floater_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGesture>);
LLFloaterReg::add("god_tools", "floater_god_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGodTools>);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 61857d6fb1..394af27dc6 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1745,7 +1745,7 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge,
{
std::string type_name = userdata.asString();
- if (("inbox" == type_name) || ("outbox" == type_name) || ("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
+ if (("inbox" == type_name) || ("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
{
LLFolderType::EType preferred_type = LLFolderType::lookup(type_name);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 1566736f17..8ef37b9143 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -401,23 +401,20 @@ void set_merchant_SLM_menu()
void check_merchant_status(bool force)
{
- if (!gSavedSettings.getBOOL("InventoryOutboxDisplayBoth"))
+ if (force)
{
- if (force)
- {
- // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status()
- LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED);
- }
- // Hide SLM related menu item
- gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(FALSE);
-
- // Also disable the toolbar button for Marketplace Listings
- LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings");
- gToolBarView->enableCommand(command->id(), false);
-
- // Launch an SLM test connection to get the merchant status
- LLMarketplaceData::instance().initializeSLM(boost::bind(&set_merchant_SLM_menu));
+ // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status()
+ LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED);
}
+ // Hide SLM related menu item
+ gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(FALSE);
+
+ // Also disable the toolbar button for Marketplace Listings
+ LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings");
+ gToolBarView->enableCommand(command->id(), false);
+
+ // Launch an SLM test connection to get the merchant status
+ LLMarketplaceData::instance().initializeSLM(boost::bind(&set_merchant_SLM_menu));
}
void init_menus()
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index bd73c234a6..a5f99676b4 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -8686,7 +8686,8 @@ void LLPipeline::renderDeferredLighting()
const LLViewerObject *vobj = drawablep->getVObj();
if(vobj && vobj->getAvatar()
- && (vobj->getAvatar()->isTooComplex() || vobj->getAvatar()->isInMuteList()))
+ && (vobj->getAvatar()->isTooComplex() || vobj->getAvatar()->isInMuteList())
+ || (vobj && dist_vec(vobj->getPosition(), LLViewerCamera::getInstance()->getOrigin()) > RenderFarClip))
{
continue;
}
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 5aba0546f3..9b18dbc2e2 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -144,7 +144,6 @@ with the same filename but different name
<texture name="Command_MiniCart_Icon" file_name="toolbar_icons/mini_cart.png" preload="true" />
<texture name="Command_MiniMap_Icon" file_name="toolbar_icons/mini_map.png" preload="true" />
<texture name="Command_Move_Icon" file_name="toolbar_icons/move.png" preload="true" />
- <texture name="Command_Outbox_Icon" file_name="toolbar_icons/outbox.png" preload="true" />
<texture name="Command_People_Icon" file_name="toolbar_icons/people.png" preload="true" />
<texture name="Command_Picks_Icon" file_name="toolbar_icons/picks.png" preload="true" />
<texture name="Command_Places_Icon" file_name="toolbar_icons/places.png" preload="true" />
diff --git a/indra/newview/skins/default/xui/en/floater_forget_user.xml b/indra/newview/skins/default/xui/en/floater_forget_user.xml
new file mode 100644
index 0000000000..f2e894733f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_forget_user.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="258"
+ layout="topleft"
+ name="groups"
+ help_topic="forget_username"
+ title="REMEMBERED USERNAMES"
+ width="280">
+ <scroll_list
+ height="173"
+ layout="topleft"
+ left="12"
+ name="user_list"
+ top="24"
+ width="256">
+ <scroll_list.columns
+ name="user"
+ width="248" />
+ </scroll_list>
+ <button
+ height="20"
+ label="Forget"
+ label_selected="Forget"
+ layout="topleft"
+ left_delta="90"
+ name="forget"
+ top_pad="8"
+ width="80" />
+ <check_box
+ height="20"
+ label="Also delete local data for this username"
+ layout="topleft"
+ left="15"
+ name="delete_data"
+ top_pad="5"
+ width="260"
+ initial_value="1"
+ tooltip="Deletes local files: chat history, last session screenshot, browser cookies, teleport history, toolbar settings, e t c"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
deleted file mode 100644
index 7802f65902..0000000000
--- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
+++ /dev/null
@@ -1,156 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<floater
- positioning="cascading"
- can_close="true"
- can_resize="true"
- height="440"
- help_topic="floater_merchant_outbox"
- min_width="300"
- min_height="200"
- name="floater_merchant_outbox"
- save_rect="true"
- save_visibility="false"
- reuse_instance="true"
- title="MERCHANT OUTBOX"
- width="333">
- <string name="OutboxFolderCount0"></string>
- <string name="OutboxFolderCount1">1 folder</string>
- <string name="OutboxFolderCountN">[NUM] folders</string>
- <string name="OutboxImporting">Sending folders...</string>
- <string name="OutboxInitializing">Initializing...</string>
- <panel
- name="panel_1"
- follows="all"
- layout="topleft"
- left="0"
- top="0"
- label=""
- height="440"
- width="333">
- <panel
- name="panel_2"
- follows="all"
- left="10"
- bottom="370"
- width="313"
- top="0"
- bg_opaque_color="InventoryBackgroundColor">
- <panel
- name="outbox_inventory_placeholder_panel"
- follows="all"
- layout="topleft"
- top="0"
- left="0"
- width="308"
- height="370"
- bg_opaque_color="InventoryBackgroundColor">
- <text
- name="outbox_inventory_placeholder_title"
- type="string"
- follows="top|left|right"
- layout="topleft"
- top="10"
- left="0"
- width="308"
- height="25"
- wrap="true"
- halign="center"
- font="SansSerifBold">
- Loading...
- </text>
- <text
- name="outbox_inventory_placeholder_text"
- type="string"
- follows="top|left|right"
- layout="topleft"
- top="35"
- left="0"
- width="308"
- height="130"
- wrap="true"
- halign="left" />
- </panel>
- </panel>
- <panel
- name="panel_3"
- follows="bottom|left|right"
- left="10"
- bottom="435"
- width="313"
- top="370">
- <panel
- name="outbox_generic_drag_target"
- mouse_opaque="false"
- follows="all"
- top="5"
- left="5"
- width="303"
- height="25"
- background_visible="false"
- bg_alpha_color="EmphasisColor_35"
- border="true"
- bevel_style="in"
- visible="true">
- <text
- name="text_1"
- type="string"
- follows="all"
- layout="topleft"
- top="6"
- height="20"
- left="5"
- width="293"
- halign="center"
- font="SansSerifMedium"
- font_shadow="hard"
- valign="top">
- Drag items here to create folders
- </text>
- </panel>
- <text
- name="outbox_folder_count"
- type="string"
- follows="all"
- layout="topleft"
- top="40"
- left="5"
- width="150"
- height="20"
- wrap="true"
- halign="left"
- valign="center"
- font="SansSerif"/>
- <button
- label="Send to Marketplace"
- tool_tip="Push to my Marketplace Storefront"
- is_toggle="false"
- name="outbox_import_btn"
- follows="bottom|right"
- tab_stop="false"
- halign="center"
- top="37"
- left="160"
- height="25"
- width="150"
- enabled="false" />
- </panel>
- <layout_stack name="import_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false">
- <layout_panel />
- <layout_panel height="24" auto_resize="false">
- <layout_stack orientation="horizontal" left="0" height="24" top="0" width="333" follows="all">
- <layout_panel width="0" />
- <layout_panel width="24" auto_resize="false">
- <loading_indicator
- height="24"
- layout="topleft"
- left="0"
- top="0"
- width="24" />
- </layout_panel>
- <layout_panel width="0" />
- </layout_stack>
- </layout_panel>
- <layout_panel />
- </layout_stack>
- </panel>
-</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_trash.xml b/indra/newview/skins/default/xui/en/floater_preview_trash.xml
index 9e50e89ac9..3fa71e7bfe 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_trash.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_trash.xml
@@ -14,7 +14,7 @@
reuse_instance="true"
can_minimize="false">
<inventory_panel
- name="inventory_outbox"
+ name="inventory_trash"
start_folder.name="Trash"
show_empty_message="false"
start_folder.type="trash"
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index ab42b76b3b..af185d43b0 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -154,13 +154,16 @@
<menu_item_call.on_click
function="Tools.StopAllAnimations" />
</menu_item_call>
- <menu_item_call
+ <menu_item_check
label="Walk / run / fly..."
name="WalkRunFly">
- <menu_item_call.on_click
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="moveview" />
+ <menu_item_check.on_click
function="Floater.ToggleOrBringToFront"
parameter="moveview" />
- </menu_item_call>
+ </menu_item_check>
</menu>
<menu
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index ab80e0fc46..874fbe19fd 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -2259,6 +2259,7 @@ Unable to create output file: [FILE]
icon="alertmodal.tga"
name="DoNotSupportBulkAnimationUpload"
type="alertmodal">
+ <unique/>
[APP_NAME] does not currently support bulk upload of BVH format animation files.
<tag>fail</tag>
</notification>
@@ -3440,6 +3441,9 @@ Display settings have been set to recommended levels because of a change to the
icon="alertmodal.tga"
name="ErrorMessage"
type="alertmodal">
+ <unique>
+ <context>ERROR_MESSAGE</context>
+ </unique>
[ERROR_MESSAGE]
<tag>fail</tag>
<usetemplate
@@ -6164,6 +6168,20 @@ Are you sure you want to permanently delete the contents of your Lost And Found?
<notification
icon="alertmodal.tga"
+ name="ConfirmReplaceLink"
+ type="alertmodal">
+You're about to replace '[TYPE]' body part link with the item which doesn't match the type.
+Are you sure you want to proceed?
+ <tag>confirm</tag>
+ <usetemplate
+ ignoretext="Confirm before I replace link"
+ name="okcancelignore"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="CopySLURL"
type="alertmodal">
The following SLurl has been copied to your clipboard:
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index 7759d4fdb2..d601b36ce5 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -57,19 +57,15 @@
combo_editor.prevalidate_callback="ascii"
tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
name="username_combo"
- width="232">
+ width="206">
<combo_box.combo_editor
text_pad_left="8"
bg_image_always_focused="true"/>
- <combo_box.combo_button
- visible="false" />
- <combo_box.drop_down_button
- visible="false" />
</combo_box>
<line_editor
follows="left|top"
height="32"
- left_pad="-11"
+ left_pad="15"
max_length_chars="16"
text_pad_left="8"
name="password_edit"
@@ -119,36 +115,49 @@
width="120"
height="32"
left_pad="15"
- bottom_delta="0" />
+ bottom_delta="0" />
+ <text
+ follows="left|top"
+ font="SansSerifLarge"
+ font.style="BOLD"
+ text_color="EmphasisColor"
+ height="34"
+ name="sign_up_text"
+ left_pad="10"
+ width="200"
+ valign="center">
+ Sign up
+ </text>
<check_box
- control_name="RememberPassword"
follows="left|top"
font="SansSerifMedium"
left="185"
- bottom_delta="21"
+ bottom_delta="21"
height="24"
label="Remember me"
check_button.bottom="3"
- name="remember_check"
+ name="remember_name"
+ tooltip="Already recorded user can be forgotten from preferences."
width="145" />
- <text
+ <check_box
+ control_name="RememberPassword"
follows="left|top"
font="SansSerifMedium"
text_color="EmphasisColor"
height="16"
- name="forgot_password_text"
- left="408"
+ left="408"
bottom_delta="0"
- width="200">
- Forgotten password
- </text>
+ label="Remember password"
+ check_button.bottom="3"
+ name="remember_check"
+ width="145" />
<combo_box
allow_text_entry="false"
font="SansSerifTiny"
follows="left|top"
height="26"
left="588"
- bottom_delta="10"
+ bottom_delta="8"
max_chars="128"
label="Select grid"
layout="topleft"
@@ -159,12 +168,13 @@
font="SansSerifMedium"
text_color="EmphasisColor"
height="16"
- name="sign_up_text"
+ name="forgot_password_text"
left="778"
- bottom_delta="-10"
- width="200">
- Sign up
- </text>
+ bottom_delta="-8"
+ width="120"
+ halign="center">
+ Password help
+ </text>
</layout_panel>
<layout_panel
height="172"
diff --git a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml
deleted file mode 100644
index b2d8bb874b..0000000000
--- a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<inventory_panel
- name="inventory_outbox"
- start_folder.name="Outbox"
- show_empty_message="false"
- start_folder.type="outbox"
- follows="all" layout="topleft"
- top="0" left="0" height="165" width="308"
- top_pad="0"
- bg_opaque_color="DkGray2"
- bg_alpha_color="DkGray2"
- background_visible="true"
- border="false"
- bevel_style="none"
- show_item_link_overlays="true"
- tool_tip="Drag and drop items here to prepare them for sale on your storefront"
- scroll.reserve_scroll_corner="false">
- <folder folder_arrow_image="Folder_Arrow"
- folder_indentation="8"
- item_height="20"
- item_top_pad="4"
- selection_image="Rounded_Square"
- left_pad="5"
- icon_pad="2"
- icon_width="16"
- text_pad="1"
- text_pad_right="4"
- arrow_size="12"
- max_folder_item_overlap="2"/>
- <item allow_wear="false"/>
-</inventory_panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index 8296438d4c..d0518aa245 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -248,14 +248,27 @@
top_pad="5"
width="237"/>
<button
+ follows="top|left"
+ layout="topleft"
+ label="Remembered Usernames"
+ name="remembered_usernames"
height="20"
- label="Default Creation Permissions"
+ left="30"
+ top_pad="16"
+ width="200">
+ <button.commit_callback
+ function="Pref.RememberedUsernames" />
+ </button>
+ <button
+ follows="top|left"
layout="topleft"
+ label="Default Creation Permissions"
name="default_creation_permissions"
+ height="20"
left="30"
- top_pad = "20"
- width="250">
- <button.commit_callback
- function="Pref.PermsDefault" />
+ top_pad="16"
+ width="200">
+ <button.commit_callback
+ function="Pref.PermsDefault" />
</button>
</panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 292c2a6293..3a311db25c 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2821,7 +2821,7 @@ If you continue to receive this message, please contact Second Life support for
<string name="BuyingCosts">Buying this costs L$ [AMOUNT]</string>
<string name="UnknownFileExtension">
Unknown file extension .%s
-Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh
+Expected .wav, .tga, .bmp, .jpg, .jpeg, or .anim
</string>
<string name="MuteObject2">Block</string>
<string name="MuteAvatar">Block</string>
@@ -4098,7 +4098,6 @@ Try enclosing path to the editor with double quotes.
<string name="Command_MarketplaceListings_Label">Marketplace</string>
<string name="Command_MiniMap_Label">Mini-map</string>
<string name="Command_Move_Label">Walk / run / fly</string>
- <string name="Command_Outbox_Label">Merchant outbox</string>
<string name="Command_People_Label">People</string>
<string name="Command_Picks_Label">Picks</string>
<string name="Command_Places_Label">Places</string>
@@ -4130,7 +4129,6 @@ Try enclosing path to the editor with double quotes.
<string name="Command_MarketplaceListings_Tooltip">Sell your creation</string>
<string name="Command_MiniMap_Tooltip">Show nearby people</string>
<string name="Command_Move_Tooltip">Moving your avatar</string>
- <string name="Command_Outbox_Tooltip">Transfer items to your marketplace for sale</string>
<string name="Command_People_Tooltip">Friends, groups, and nearby people</string>
<string name="Command_Picks_Tooltip">Places to show as favorites in your profile</string>
<string name="Command_Places_Tooltip">Places you've saved</string>
diff --git a/indra/newview/skins/default/xui/es/floater_buy_currency.xml b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
index 2c8848265f..dbff3fcf0e 100644
--- a/indra/newview/skins/default/xui/es/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
@@ -60,7 +60,7 @@ no el objeto.
</text>
<button label="Comprar ahora" name="buy_btn"/>
<button label="Cancelar" name="cancel_btn"/>
- <text left="5" name="info_cannot_buy" right="-5">
+ <text name="info_cannot_buy" left="150" font="SansSerifBig">
No se pudo hacer la compra
</text>
<button label="Ir a la web" name="error_web"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
index 148a5a35d2..c295172abf 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
@@ -60,7 +60,7 @@ le Lindex...
</text>
<button label="Acheter" name="buy_btn"/>
<button label="Annuler" name="cancel_btn"/>
- <text left="5" name="info_cannot_buy" right="-5" width="200">
+ <text name="info_cannot_buy" left="160" width="200">
Achat impossible
</text>
<button label="Accéder au Web" name="error_web"/>
diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency.xml b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
index 743969f557..53a2057455 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
@@ -60,7 +60,7 @@ l&apos;oggetto.
</text>
<button label="Acquista" name="buy_btn"/>
<button label="Annulla" name="cancel_btn"/>
- <text left="5" name="info_cannot_buy" right="-5">
+ <text name="info_cannot_buy" left="160" font="SansSerifBig">
Non in grado di acquistare
</text>
<button label="Continua sul Web" name="error_web"/>
diff --git a/indra/newview/tests/llsecapi_test.cpp b/indra/newview/tests/llsecapi_test.cpp
index d7e87ed52e..a1005c654c 100644
--- a/indra/newview/tests/llsecapi_test.cpp
+++ b/indra/newview/tests/llsecapi_test.cpp
@@ -60,12 +60,21 @@ LLPointer<LLCertificate> LLSecAPIBasicHandler::getCertificate(X509* openssl_cert
LLPointer<LLCertificateChain> LLSecAPIBasicHandler::getCertificateChain(const X509_STORE_CTX* chain) { return NULL; }
LLPointer<LLCertificateStore> LLSecAPIBasicHandler::getCertificateStore(const std::string& store_id) { return NULL; }
void LLSecAPIBasicHandler::setProtectedData(const std::string& data_type, const std::string& data_id, const LLSD& data) {}
+void LLSecAPIBasicHandler::addToProtectedMap(const std::string& data_type, const std::string& data_id, const std::string& map_elem, const LLSD& data) {}
+void LLSecAPIBasicHandler::removeFromProtectedMap(const std::string& data_type, const std::string& data_id, const std::string& map_elem) {}
LLSD LLSecAPIBasicHandler::getProtectedData(const std::string& data_type, const std::string& data_id) { return LLSD(); }
void LLSecAPIBasicHandler::deleteProtectedData(const std::string& data_type, const std::string& data_id) {}
LLPointer<LLCredential> LLSecAPIBasicHandler::createCredential(const std::string& grid, const LLSD& identifier, const LLSD& authenticator) { return NULL; }
LLPointer<LLCredential> LLSecAPIBasicHandler::loadCredential(const std::string& grid) { return NULL; }
void LLSecAPIBasicHandler::saveCredential(LLPointer<LLCredential> cred, bool save_authenticator) {}
void LLSecAPIBasicHandler::deleteCredential(LLPointer<LLCredential> cred) {}
+bool LLSecAPIBasicHandler::hasCredentialMap(const std::string& storage, const std::string& grid) { return false; }
+void LLSecAPIBasicHandler::loadCredentialMap(const std::string& storage, const std::string& grid, credential_map_t& credential_map) {}
+LLPointer<LLCredential> LLSecAPIBasicHandler::loadFromCredentialMap(const std::string& storage, const std::string& grid, const std::string& userkey) { return NULL; }
+void LLSecAPIBasicHandler::addToCredentialMap(const std::string& storage, LLPointer<LLCredential> cred, bool save_authenticator) {}
+void LLSecAPIBasicHandler::removeFromCredentialMap(const std::string& storage, LLPointer<LLCredential> cred) {}
+void LLSecAPIBasicHandler::removeFromCredentialMap(const std::string& storage, const std::string& grid, const std::string& userkey) {}
+void LLSecAPIBasicHandler::removeCredentialMap(const std::string& storage, const std::string& grid) {}
// -------------------------------------------------------------------------------------------
// TUT