fixes bug 182490 "New password manager is ignoring valid password entries"

r=morse sr=jst a=asa
This commit is contained in:
darin%netscape.com 2002-12-06 06:36:15 +00:00
parent 1ab335f6b4
commit 68c5a7fa73

View File

@ -68,6 +68,13 @@
#include "nsReadableUtils.h"
#include "nsIObserverService.h"
//#define SINGSIGN_LOGGING
#ifdef SINGSIGN_LOGGING
#define LOG(args) printf args
#else
#define LOG(args)
#endif
// Currently the default is on, so we don't need the code to prompt the
// user if the default is off.
#undef WALLET_PASSWORDMANAGER_DEFAULT_IS_OFF
@ -799,6 +806,153 @@ si_GetURL(const char * passwordRealm) {
return (NULL);
}
/**
* composite URL struct for handling the migration of legacy password entries.
*/
class si_SignonCompositeURLStruct : public si_SignonURLStruct {
public:
si_SignonURLStruct *primaryUrl;
si_SignonURLStruct *legacyUrl;
};
PRIVATE si_SignonCompositeURLStruct * si_composite_url=0;
#if defined(SINGSIGN_LOGGING)
PRIVATE void
si_DumpUserList(nsVoidArray &list)
{
LOG(("dumping user list:\n"));
PRInt32 i, j, user_count = list.Count(), data_count;
for (i=0; i<user_count; ++i) {
si_SignonUserStruct *user = (si_SignonUserStruct *) list[i];
LOG((" user[%d]\n", i));
data_count = user->signonData_list.Count();
for (j=0; j<data_count; ++j) {
si_SignonDataStruct *data = (si_SignonDataStruct *) user->signonData_list[j];
LOG((" (%s,%s)\n",
NS_ConvertUCS2toUTF8(data->name).get(),
NS_ConvertUCS2toUTF8(data->value).get()));
}
}
}
#endif
PRIVATE si_SignonURLStruct *
si_GetCompositeURL(const char *primaryRealm, const char *legacyRealm)
{
si_SignonURLStruct *primaryUrl, *legacyUrl;
primaryUrl = si_GetURL(primaryRealm);
legacyUrl = si_GetURL(legacyRealm);
if (primaryUrl && legacyUrl) {
LOG((">>> building composite URL struct\n"));
if (si_composite_url) {
NS_ERROR("si_composite_url already in use");
return NULL;
}
si_composite_url = new si_SignonCompositeURLStruct;
if (!si_composite_url)
return NULL;
si_composite_url->primaryUrl = primaryUrl;
si_composite_url->legacyUrl = legacyUrl;
si_composite_url->signonUser_list.AppendElements(primaryUrl->signonUser_list);
si_composite_url->signonUser_list.AppendElements(legacyUrl->signonUser_list);
#if defined(SINGSIGN_LOGGING)
si_DumpUserList(si_composite_url->signonUser_list);
#endif
/* need to transfer the chosen_user state variable */
if (primaryUrl->chosen_user)
si_composite_url->chosen_user = primaryUrl->chosen_user;
else if (legacyUrl->chosen_user) {
si_SignonUserStruct *chosen_user = legacyUrl->chosen_user;
PRInt32 index;
/* XXX fixup chosen_user -- THIS SHOULD NOT BE NECESSARY */
index = legacyUrl->signonUser_list.IndexOf(chosen_user);
if (index < 0) {
index = primaryUrl->signonUser_list.IndexOf(chosen_user);
if (index >= 0)
primaryUrl->chosen_user = chosen_user;
legacyUrl->chosen_user = NULL;
}
/* move first element of legacy user list to front */
index = si_composite_url->signonUser_list.IndexOf(chosen_user);
if (index > 0)
si_composite_url->signonUser_list.MoveElement(index, 0);
si_composite_url->chosen_user = chosen_user;
}
else
si_composite_url->chosen_user = NULL;
#if defined(SINGSIGN_LOGGING)
LOG(("after chosen_user fixup [chosen_user=%x]:\n", si_composite_url->chosen_user));
si_DumpUserList(si_composite_url->signonUser_list);
#endif
return si_composite_url;
}
if (primaryUrl)
return primaryUrl;
return legacyUrl;
}
PRIVATE PRInt32
si_SetChosenUser(si_SignonURLStruct *url, si_SignonUserStruct *chosen_user)
{
PRInt32 index;
si_SignonUserStruct *user;
index = url->signonUser_list.IndexOf(chosen_user);
if (index < 0) {
url->chosen_user = NULL;
return -1;
}
url->chosen_user = chosen_user;
return index;
}
PRIVATE void
si_ReleaseCompositeURL(si_SignonURLStruct *url)
{
if (url == si_composite_url) {
si_SignonUserStruct *chosen_user = url->chosen_user;
/* need to transfer the chosen_user state variable */
if (chosen_user) {
PRInt32 index;
/* store chosen_user */
index = si_SetChosenUser(url = si_composite_url->primaryUrl, chosen_user);
if (index >= 0)
si_composite_url->legacyUrl->chosen_user = NULL;
else
index = si_SetChosenUser(url = si_composite_url->legacyUrl, chosen_user);
NS_ASSERTION(index >= 0, "chosen_user not found");
/* need to move chosen_user to front of list */
url->signonUser_list.MoveElement(index, 0);
}
else {
si_composite_url->primaryUrl->chosen_user = NULL;
si_composite_url->legacyUrl->chosen_user = NULL;
}
si_composite_url->primaryUrl = NULL;
si_composite_url->legacyUrl = NULL;
si_composite_url->chosen_user = NULL;
si_composite_url->signonUser_list.Clear();
delete si_composite_url;
si_composite_url = NULL;
}
}
/* Remove a user node from a given URL node */
PRIVATE PRBool
si_RemoveUser(const char *passwordRealm, const nsString& userName, PRBool save, PRBool loginFailure, PRBool notify, PRBool first = PR_FALSE) {
@ -977,13 +1131,15 @@ si_GetFirstNonPasswordData(si_SignonUserStruct* user) {
* This routine is called only if signon pref is enabled!!!
*/
PRIVATE si_SignonUserStruct*
si_GetUser(nsIPrompt* dialog, const char* passwordRealm, PRBool pickFirstUser, const nsString& userText, PRUint32 formNumber) {
si_GetUser(nsIPrompt* dialog, const char* passwordRealm, const char *legacyRealm,
PRBool pickFirstUser, const nsString& userText, PRUint32 formNumber) {
si_SignonURLStruct* url;
si_SignonUserStruct* user = nsnull;
si_SignonDataStruct* data;
/* get to node for this URL */
url = si_GetURL(passwordRealm);
url = si_GetCompositeURL(passwordRealm, legacyRealm);
if (url != NULL) {
/* node for this URL was found */
@ -1092,6 +1248,7 @@ si_GetUser(nsIPrompt* dialog, const char* passwordRealm, PRBool pickFirstUser, c
#endif
}
si_ReleaseCompositeURL(url);
} else {
user = NULL;
}
@ -2190,7 +2347,10 @@ SINGSIGN_RememberSignonData
}
PRIVATE void
si_RestoreSignonData(nsIPrompt* dialog, const char* passwordRealm, const PRUnichar* name, PRUnichar** value, PRUint32 formNumber, PRUint32 elementNumber) {
si_RestoreSignonData(nsIPrompt* dialog,
const char* passwordRealm, const char* legacyRealm,
const PRUnichar* name, PRUnichar** value,
PRUint32 formNumber, PRUint32 elementNumber) {
si_SignonUserStruct* user;
si_SignonDataStruct* data;
nsAutoString correctedName;
@ -2222,11 +2382,14 @@ si_RestoreSignonData(nsIPrompt* dialog, const char* passwordRealm, const PRUnich
/* determine if name has been saved (avoids unlocking the database if not) */
PRBool nameFound = PR_FALSE;
user = si_GetUser(dialog, passwordRealm, PR_FALSE, correctedName, formNumber);
user = si_GetUser(dialog, passwordRealm, legacyRealm, PR_FALSE, correctedName, formNumber);
if (user) {
PRInt32 dataCount = user->signonData_list.Count();
for (PRInt32 i=0; i<dataCount; i++) {
data = NS_STATIC_CAST(si_SignonDataStruct*, user->signonData_list.ElementAt(i));
LOG((" got [name=%s value=%s]\n",
NS_LossyConvertUCS2toASCII(data->name).get(),
NS_LossyConvertUCS2toASCII(data->value).get()));
if(correctedName.Length() && (data->name == correctedName)) {
nameFound = PR_TRUE;
}
@ -2274,11 +2437,14 @@ si_RestoreSignonData(nsIPrompt* dialog, const char* passwordRealm, const PRUnich
/* restore the data from previous time this URL was visited */
user = si_GetUser(dialog, passwordRealm, PR_FALSE, correctedName, formNumber);
user = si_GetUser(dialog, passwordRealm, legacyRealm, PR_FALSE, correctedName, formNumber);
if (user) {
PRInt32 dataCount = user->signonData_list.Count();
for (PRInt32 i=0; i<dataCount; i++) {
data = NS_STATIC_CAST(si_SignonDataStruct*, user->signonData_list.ElementAt(i));
LOG((" got [name=%s value=%s]\n",
NS_LossyConvertUCS2toASCII(data->name).get(),
NS_LossyConvertUCS2toASCII(data->value).get()));
if(correctedName.Length() && (data->name == correctedName)) {
nsAutoString password;
if (NS_SUCCEEDED(si_Decrypt(data->value, password))) {
@ -2294,6 +2460,8 @@ si_RestoreSignonData(nsIPrompt* dialog, const char* passwordRealm, const PRUnich
PUBLIC void
SINGSIGN_RestoreSignonData(nsIPrompt* dialog, nsIURI* passwordRealm, const PRUnichar* name, PRUnichar** value, PRUint32 formNumber, PRUint32 elementNumber) {
LOG(("enter SINGSIGN_RestoreSignonData\n"));
if (!passwordRealm)
return;
@ -2301,13 +2469,14 @@ SINGSIGN_RestoreSignonData(nsIPrompt* dialog, nsIURI* passwordRealm, const PRUni
if (!si_ExtractRealm(passwordRealm, realm))
return;
si_RestoreSignonData(dialog, realm.get(), name, value, formNumber, elementNumber);
if (*value == nsnull) {
// try the old style host-only key format
nsresult rv = passwordRealm->GetHost(realm);
if (NS_SUCCEEDED(rv))
si_RestoreSignonData(dialog, realm.get(), name, value, formNumber, elementNumber);
}
nsCAutoString legacyRealm;
if (NS_FAILED(passwordRealm->GetHost(legacyRealm)))
return;
si_RestoreSignonData(dialog, realm.get(), legacyRealm.get(), name, value, formNumber, elementNumber);
LOG(("exit SINGSIGN_RestoreSignonData [value=%s]\n",
*value ? NS_LossyConvertUCS2toASCII(*value).get() : "(null)"));
}
/*
@ -2356,7 +2525,7 @@ si_RestoreOldSignonDataFromBrowser
user = si_GetSpecificUser(passwordRealm, username, NS_ConvertASCIItoUCS2(USERNAMEFIELD));
} else {
si_LastFormForWhichUserHasBeenSelected = -1;
user = si_GetUser(dialog, passwordRealm, pickFirstUser, NS_ConvertASCIItoUCS2(USERNAMEFIELD), 0);
user = si_GetUser(dialog, passwordRealm, nsnull, pickFirstUser, NS_ConvertASCIItoUCS2(USERNAMEFIELD), 0);
}
if (!user) {
/* leave original username and password from caller unchanged */