summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/llappviewer.cpp15
-rw-r--r--indra/newview/llappviewer.h4
-rw-r--r--indra/newview/llfloaterforgetuser.cpp231
-rw-r--r--indra/newview/llfloaterforgetuser.h9
-rw-r--r--indra/newview/llsecapi.h4
-rw-r--r--indra/newview/llsechandler_basic.cpp13
-rw-r--r--indra/newview/llsechandler_basic.h4
-rw-r--r--indra/newview/llstartup.cpp9
-rw-r--r--indra/newview/llstartup.h1
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml12
10 files changed, 245 insertions, 57 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index bbb726ddb0..b232a8c3bb 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -671,7 +671,8 @@ LLAppViewer::LLAppViewer()
mReportedCrash(false),
mNumSessions(0),
mPurgeCache(false),
- mPurgeOnExit(false),
+ mPurgeCacheOnExit(false),
+ mPurgeUserDataOnExit(false),
mSecondInstance(false),
mSavedFinalSnapshot(false),
mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded.
@@ -1949,7 +1950,7 @@ bool LLAppViewer::cleanup()
LLConversationLog::instance().cache();
}
- if (mPurgeOnExit)
+ if (mPurgeCacheOnExit)
{
LL_INFOS() << "Purging all cache files on exit" << LL_ENDL;
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*");
@@ -1990,6 +1991,14 @@ bool LLAppViewer::cleanup()
}
}
+ if (mPurgeUserDataOnExit)
+ {
+ // Ideally we should not save anything from this session since it is going to be purged now,
+ // but this is a very 'rare' case (user deleting himself), not worth overcomplicating 'save&cleanup' code
+ std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + LLStartUp::getUserId();
+ gDirUtilp->deleteDirAndContents(user_path);
+ }
+
// Delete workers first
// shotdown all worker threads before deleting them in case of co-dependencies
mAppCoreHttp.requestStop();
@@ -4461,7 +4470,7 @@ void LLAppViewer::badNetworkHandler()
// Flush all of our caches on exit in the case of disconnect due to
// invalid packets.
- mPurgeOnExit = TRUE;
+ mPurgeCacheOnExit = TRUE;
std::ostringstream message;
message <<
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 788fe6a19b..1298ba51e2 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -190,6 +190,7 @@ public:
void addOnIdleCallback(const boost::function<void()>& cb); // add a callback to fire (once) when idle
+ void purgeUserDataOnExit() { mPurgeUserDataOnExit = true; }
void purgeCache(); // Clear the local cache.
void purgeCacheImmediate(); //clear local cache immediately.
S32 updateTextureThreads(F32 max_time);
@@ -281,7 +282,8 @@ private:
std::string mSerialNumber;
bool mPurgeCache;
- bool mPurgeOnExit;
+ bool mPurgeCacheOnExit;
+ bool mPurgeUserDataOnExit;
LLViewerJoystick* joystick;
bool mSavedFinalSnapshot;
diff --git a/indra/newview/llfloaterforgetuser.cpp b/indra/newview/llfloaterforgetuser.cpp
index 363951041a..6271ccfa18 100644
--- a/indra/newview/llfloaterforgetuser.cpp
+++ b/indra/newview/llfloaterforgetuser.cpp
@@ -29,11 +29,15 @@
#include "llfloaterforgetuser.h"
+#include "llappviewer.h"
#include "llcheckboxctrl.h"
#include "llfavoritesbar.h"
+#include "llnotificationsutil.h"
#include "llpanellogin.h" // for helper function getUserName() and to repopulate list if nessesary
#include "llscrolllistctrl.h"
#include "llsecapi.h"
+#include "llstartup.h"
+#include "llviewercontrol.h"
#include "llviewernetwork.h"
@@ -54,55 +58,65 @@ LLFloaterForgetUser::~LLFloaterForgetUser()
BOOL LLFloaterForgetUser::postBuild()
{
- // Note, storage works per grid, whatever is selected currently in login screen or logged in.
- // Since login screen can change grid, store the value.
- mGrid = LLGridManager::getInstance()->getGrid();
+ mScrollList = getChild<LLScrollListCtrl>("user_list");
- 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)
+ bool show_grid_marks = gSavedSettings.getBOOL("ForceShowGrid");
+ show_grid_marks |= !LLGridManager::getInstance()->isInProductionGrid();
+
+ std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();
+
+ if (!show_grid_marks)
+ {
+ // Figure out if there are records for more than one grid in storage
+ for (std::map<std::string, std::string>::iterator grid_iter = known_grids.begin();
+ grid_iter != known_grids.end();
+ grid_iter++)
{
- if (cr_iter->second.notNull()) // basic safety
+ if (!grid_iter->first.empty()
+ && grid_iter->first != MAINGRID) // a workaround since 'mIsInProductionGrid' might not be set
{
- 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);
+ if (!gSecAPIHandler->emptyCredentialMap("login_list", grid_iter->first))
+ {
+ show_grid_marks = true;
+ break;
+ }
+
+ // "Legacy" viewer support
+ LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(grid_iter->first);
+ if (cred.notNull())
+ {
+ const LLSD &ident = cred->getIdentifier();
+ if (ident.isMap() && ident.has("type"))
+ {
+ show_grid_marks = true;
+ break;
+ }
+ }
}
- cr_iter++;
}
- scroll_list->selectFirstItem();
+ }
+
+ if (!show_grid_marks)
+ {
+ // just load maingrid
+ loadGridToList(MAINGRID, false);
}
else
{
- LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(mGrid);
- if (cred.notNull())
+ for (std::map<std::string, std::string>::iterator grid_iter = known_grids.begin();
+ grid_iter != known_grids.end();
+ grid_iter++)
{
- const LLSD &ident = cred->getIdentifier();
- if (ident.isMap() && ident.has("type"))
+ if (!grid_iter->first.empty())
{
- 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();
+ loadGridToList(grid_iter->first, true);
}
}
}
- bool enable_button = scroll_list->getFirstSelectedIndex() != -1;
+ mScrollList->selectFirstItem();
+ bool enable_button = mScrollList->getFirstSelectedIndex() != -1;
LLCheckBoxCtrl *chk_box = getChild<LLCheckBoxCtrl>("delete_data");
chk_box->setEnabled(enable_button);
chk_box->set(FALSE);
@@ -117,43 +131,156 @@ void LLFloaterForgetUser::onForgetClicked()
{
mLoginPanelDirty = true;
LLScrollListCtrl *scroll_list = getChild<LLScrollListCtrl>("user_list");
- std::string user_key = scroll_list->getSelectedValue();
+ LLCheckBoxCtrl *chk_box = getChild<LLCheckBoxCtrl>("delete_data");
+ BOOL delete_data = chk_box->getValue();
+ LLSD user_data = scroll_list->getSelectedValue();
+ const std::string user_id = user_data["user_id"];
+ const std::string grid = user_data["grid"];
+ const std::string user_name = user_data["label"]; // for favorites
- // remove creds
- gSecAPIHandler->removeFromCredentialMap("login_list", mGrid, user_key);
+ if (delete_data && user_id == LLStartUp::getUserId() && grid == LLGridManager::getInstance()->getGrid())
+ {
+ // we can't delete data for user that is currently logged in
+ LLNotificationsUtil::add("LoginCantRemoveCurUsername", LLSD(), LLSD(), boost::bind(onConfirmLogout, _1, _2, user_name));
+ return;
+ }
+
+ // key is used for name of user's folder and in credencials
+ // user_name is edentical to favorite's username
+ forgetUser(user_id, user_name, grid, delete_data);
- LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(mGrid);
- if (cred.notNull() && cred->userID() == user_key)
+ // 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);
+ }
+}
+
+//static
+void LLFloaterForgetUser::forgetUser(const std::string &userid, const std::string &fav_id, const std::string &grid, bool delete_data)
+{
+ // Remove creds
+ gSecAPIHandler->removeFromCredentialMap("login_list", grid, userid);
+
+ LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(grid);
+ if (cred.notNull() && cred->userID() == userid)
{
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;
+ std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + userid;
gDirUtilp->deleteDirAndContents(user_path);
- // Clean favorites, label is edentical to username
- LLFavoritesOrderStorage::removeFavoritesRecordOfUser(scroll_list->getSelectedItemLabel(), mGrid);
+ // Clean favorites
+ LLFavoritesOrderStorage::removeFavoritesRecordOfUser(fav_id, grid);
// 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.
}
+}
+// static
+bool LLFloaterForgetUser::onConfirmLogout(const LLSD& notification, const LLSD& response, const std::string &fav_id)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0)
+ {
+ // Remove creds
+ gSecAPIHandler->removeFromCredentialMap("login_list", LLGridManager::getInstance()->getGrid(), LLStartUp::getUserId());
- // Update UI
- scroll_list->deleteSelectedItems();
- scroll_list->selectFirstItem();
- if (scroll_list->getFirstSelectedIndex() == -1)
+ LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
+ if (cred.notNull() && cred->userID() == LLStartUp::getUserId())
+ {
+ gSecAPIHandler->deleteCredential(cred);
+ }
+
+ // Clean favorites
+ LLFavoritesOrderStorage::removeFavoritesRecordOfUser(fav_id, LLGridManager::getInstance()->getGrid());
+
+ // mark data for removal
+ LLAppViewer::instance()->purgeUserDataOnExit();
+ LLAppViewer::instance()->requestQuit();
+ }
+ return false;
+}
+
+void LLFloaterForgetUser::loadGridToList(const std::string &grid, bool show_grid_name)
+{
+ std::string grid_label;
+ if (show_grid_name)
{
- LLButton *button = getChild<LLButton>("forget");
- button->setEnabled(false);
- chk_box->setEnabled(false);
+ grid_label = LLGridManager::getInstance()->getGridId(grid); //login id (shortened label)
+ }
+ if (gSecAPIHandler->hasCredentialMap("login_list", grid))
+ {
+ LLSecAPIHandler::credential_map_t credencials;
+ gSecAPIHandler->loadCredentialMap("login_list", grid, 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
+ {
+ std::string user_label = LLPanelLogin::getUserName(cr_iter->second);
+ LLSD user_data;
+ user_data["user_id"] = cr_iter->first;
+ user_data["label"] = user_label;
+ user_data["grid"] = grid;
+
+ if (show_grid_name)
+ {
+ user_label += " (" + grid_label + ")";
+ }
+
+ LLScrollListItem::Params item_params;
+ item_params.value(user_data);
+ item_params.columns.add()
+ .value(user_label)
+ .column("user")
+ .font(LLFontGL::getFontSansSerifSmall());
+ mScrollList->addRow(item_params, ADD_BOTTOM);
+ }
+ cr_iter++;
+ }
+ }
+ else
+ {
+ // "Legacy" viewer support
+ LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(grid);
+ if (cred.notNull())
+ {
+ const LLSD &ident = cred->getIdentifier();
+ if (ident.isMap() && ident.has("type"))
+ {
+ std::string user_label = LLPanelLogin::getUserName(cred);
+ LLSD user_data;
+ user_data["user_id"] = cred->userID();
+ user_data["label"] = user_label;
+ user_data["grid"] = grid;
+
+ if (show_grid_name)
+ {
+ user_label += " (" + grid_label + ")";
+ }
+
+ LLScrollListItem::Params item_params;
+ item_params.value(user_data);
+ item_params.columns.add()
+ .value(user_label)
+ .column("user")
+ .font(LLFontGL::getFontSansSerifSmall());
+ mScrollList->addRow(item_params, ADD_BOTTOM);
+ }
+ }
}
}
diff --git a/indra/newview/llfloaterforgetuser.h b/indra/newview/llfloaterforgetuser.h
index 119aece2d1..0ab47d3d69 100644
--- a/indra/newview/llfloaterforgetuser.h
+++ b/indra/newview/llfloaterforgetuser.h
@@ -29,6 +29,8 @@
#include "llfloater.h"
+class LLScrollListCtrl;
+
class LLFloaterForgetUser : public LLFloater
{
public:
@@ -37,10 +39,15 @@ public:
BOOL postBuild();
void onForgetClicked();
+ static void forgetUser(const std::string &userid, const std::string &fav_id, const std::string &grid, bool delete_data);
private:
+ static bool onConfirmLogout(const LLSD& notification, const LLSD& response, const std::string &favorites_id);
+ void loadGridToList(const std::string &grid, bool show_grid_name);
+
+ LLScrollListCtrl *mScrollList;
+
bool mLoginPanelDirty;
- std::string mGrid;
};
#endif
diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h
index c0f0a367c7..5cde0d549e 100644
--- a/indra/newview/llsecapi.h
+++ b/indra/newview/llsecapi.h
@@ -491,6 +491,10 @@ public:
virtual bool hasCredentialMap(const std::string& storage,
const std::string& grid)=0;
+ // returns true im map is empty or does not exist
+ virtual bool emptyCredentialMap(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,
diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp
index a8bb54a90e..2932ae45a3 100644
--- a/indra/newview/llsechandler_basic.cpp
+++ b/indra/newview/llsechandler_basic.cpp
@@ -1664,6 +1664,19 @@ bool LLSecAPIBasicHandler::hasCredentialMap(const std::string& storage, const st
return credential.isMap();
}
+// returns true if map is empty or does not exist
+bool LLSecAPIBasicHandler::emptyCredentialMap(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() || credential.emptyMap();
+}
+
// 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)
{
diff --git a/indra/newview/llsechandler_basic.h b/indra/newview/llsechandler_basic.h
index 426b5d392a..0bc7f5230f 100644
--- a/indra/newview/llsechandler_basic.h
+++ b/indra/newview/llsechandler_basic.h
@@ -293,6 +293,10 @@ public:
virtual bool hasCredentialMap(const std::string& storage,
const std::string& grid);
+ // returns true if map is empty or does not exist
+ virtual bool emptyCredentialMap(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,
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 08012686f9..684d3bd421 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2715,6 +2715,15 @@ std::string& LLStartUp::getInitialOutfitName()
return sInitialOutfit;
}
+std::string LLStartUp::getUserId()
+{
+ if (gUserCredential.isNull())
+ {
+ return "";
+ }
+ return gUserCredential->userID();
+}
+
// Loads a bitmap to display during load
void init_start_screen(S32 location_id)
{
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index db37207022..5ce74b8fae 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -115,6 +115,7 @@ public:
static void saveInitialOutfit();
static std::string& getInitialOutfitName();
+ static std::string getUserId();
static bool dispatchURL();
// if we have a SLURL or sim string ("Ahern/123/45") that started
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 70f3139488..d99f5fa7d9 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -3560,6 +3560,18 @@ Already remembered user can be forgotten from Me &gt; Preferences &gt; Advanced
<notification
icon="alertmodal.tga"
+ name="LoginCantRemoveCurUsername"
+ type="alertmodal">
+ <tag>confirm</tag>
+Forgetting the logged-in user requires you to log out.
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="Confirm and log out"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="LoginPacketNeverReceived"
type="alertmodal">
<tag>fail</tag>