Mozilla/mozilla/profile/src/nsProfileAccess.cpp
sspitzer%netscape.com ab2976920e a fix the scary message about how migration will kill your 4.x profile.
it just copies, it doesn't not alter the 4.x profile

turn on the profile debugging printfs for everyone, so that we can get
better info in bug reports.  (perhaps this should be using PR_LOG?)

only migrate the 4.x profile info when the user runs -installer

fix the bug where we do automigration on linux, even if their is no ~/.netscape directory

force DEBUG builds to launch the Profile Manager if there were no profile
command line arguments.

a=ben,selmer


git-svn-id: svn://10.0.0.236/trunk@59686 18797224-902f-48f8-a5cc-f745e15eee43
2000-02-03 23:43:16 +00:00

1068 lines
32 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*/
#include "nsProfileAccess.h"
#include "nsProfile.h"
#include "pratom.h"
#include "prmem.h"
#include "plstr.h"
#include "prenv.h"
#include "nsIEnumerator.h"
#include "prprf.h"
#include "nsSpecialSystemDirectory.h"
#include "nsCOMPtr.h"
#include "nsIComponentManager.h"
#include "nsIFileSpec.h"
#include "nsFileStream.h"
#include "nsEscape.h"
#define REGISTRY_YES_STRING "yes"
#define REGISTRY_NO_STRING "no"
// strings for items in the registry we'll be getting or setting
#define REGISTRY_PROFILE_SUBTREE_STRING "Profiles"
#define REGISTRY_CURRENT_PROFILE_STRING "CurrentProfile"
#define REGISTRY_NC_SERVICE_DENIAL_STRING "NCServiceDenial"
#define REGISTRY_NC_PROFILE_NAME_STRING "NCProfileName"
#define REGISTRY_NC_USER_EMAIL_STRING "NCEmailAddress"
#define REGISTRY_NC_HAVE_PREG_INFO_STRING "NCHavePregInfo"
#define REGISTRY_HAVE_PREG_INFO_STRING "HavePregInfo"
#define REGISTRY_MIGRATED_STRING "migrated"
#define REGISTRY_DIRECTORY_STRING "directory"
#define REGISTRY_NEED_MIGRATION_STRING "NeedMigration"
#define REGISTRY_VERSION_STRING "Version"
#define REGISTRY_VERSION_1_0 "1.0"
#define MAX_PERSISTENT_DATA_SIZE 1000
#define NUM_HEX_BYTES 8
#define ISHEX(c) ( ((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F') )
#if defined (XP_UNIX)
#define USER_ENVIRONMENT_VARIABLE "USER"
#define HOME_ENVIRONMENT_VARIABLE "HOME"
#define PROFILE_NAME_ENVIRONMENT_VARIABLE "PROFILE_NAME"
#define PROFILE_HOME_ENVIRONMENT_VARIABLE "PROFILE_HOME"
#elif defined (XP_BEOS)
#endif
// IID and CIDs of all the services needed
static NS_DEFINE_CID(kRegistryCID, NS_REGISTRY_CID);
/*
* Constructor/Destructor
* FillProfileInfo reads the registry and fills profileStructs
*/
nsProfileAccess::nsProfileAccess()
{
m_registry = null_nsCOMPtr();
mCount = 0;
mNumProfiles = 0;
mNumOldProfiles = 0;
m4xCount = 0;
mCurrentProfile = nsnull;
mVersion = nsnull;
mHavePREGInfo = nsnull;
mFixRegEntries = PR_FALSE;
mProfileDataChanged = PR_FALSE;
mForgetProfileCalled = PR_FALSE;
mProfiles = new nsVoidArray();
m4xProfiles = new nsVoidArray();
FillProfileInfo();
}
// On the way out, close the registry if it is
// still opened and free up the resources.
nsProfileAccess::~nsProfileAccess()
{
PRBool openalready = PR_FALSE;
m_registry->IsOpen( &openalready);
if (openalready)
m_registry->Close();
// Release all resources.
CRTFREEIF(mCurrentProfile);
CRTFREEIF(mVersion);
CRTFREEIF(mHavePREGInfo);
FreeProfileMembers(mProfiles, mProfiles->Count());
FreeProfileMembers(m4xProfiles, m4xProfiles->Count());
}
// Free up the member profile structs
void
nsProfileAccess::FreeProfileMembers(nsVoidArray *profiles, PRInt32 numElems)
{
PRInt32 index = 0;
ProfileStruct* aProfile;
for (index = 0; index < numElems; index++)
{
aProfile = (ProfileStruct *) profiles->ElementAt(index);
delete aProfile;
}
if (profiles)
delete profiles;
}
// Close the registry.
nsresult
nsProfileAccess::CloseRegistry()
{
nsresult rv = NS_OK;
rv = m_registry->Close();
return rv;
}
// Open the registry.
// If already opened, just use it.
nsresult
nsProfileAccess::OpenRegistry()
{
nsresult rv;
PRBool openalready = PR_FALSE;
if (!m_registry) {
rv = nsComponentManager::CreateInstance(kRegistryCID,
nsnull,
NS_GET_IID(nsIRegistry),
getter_AddRefs(m_registry));
if (NS_FAILED(rv)) return rv;
if (!m_registry) return NS_ERROR_FAILURE;
}
// Open the registry
rv = m_registry->IsOpen( &openalready);
if (NS_FAILED(rv)) return rv;
if (!openalready)
rv = m_registry->OpenDefault();
return rv;
}
// Given the name of the profile, the structure that
// contains the relavant profile information will be filled.
// Caller must free up the profile struct.
nsresult
nsProfileAccess::GetValue(const char* profileName, ProfileStruct** aProfile)
{
PRInt32 index = 0;
index = FindProfileIndex(profileName);
if (index >= 0)
{
*aProfile = (ProfileStruct *) PR_Malloc(sizeof(ProfileStruct));
if (!*aProfile)
return NS_ERROR_OUT_OF_MEMORY;
ProfileStruct* profileItem = (ProfileStruct *) (mProfiles->ElementAt(index));
(*aProfile)->profileName = nsnull;
(*aProfile)->profileLocation = nsnull;
(*aProfile)->isMigrated = nsnull;
(*aProfile)->NCProfileName = nsnull;
(*aProfile)->NCDeniedService = nsnull;
(*aProfile)->NCEmailAddress = nsnull;
(*aProfile)->NCHavePregInfo = nsnull;
(*aProfile)->profileName = nsCRT::strdup(profileItem->profileName);
(*aProfile)->profileLocation = nsCRT::strdup(profileItem->profileLocation);
(*aProfile)->isMigrated = nsCRT::strdup(profileItem->isMigrated);
if (profileItem->NCProfileName)
(*aProfile)->NCProfileName = nsCRT::strdup(profileItem->NCProfileName);
if (profileItem->NCDeniedService)
(*aProfile)->NCProfileName = nsCRT::strdup(profileItem->NCDeniedService);
if (profileItem->NCEmailAddress)
(*aProfile)->NCProfileName = nsCRT::strdup(profileItem->NCEmailAddress);
if (profileItem->NCHavePregInfo)
(*aProfile)->NCProfileName = nsCRT::strdup(profileItem->NCHavePregInfo);
}
else
*aProfile = nsnull;
return NS_OK;
}
// This method writes all changes to the array of the
// profile structs. If it is an existing profile, it
// will be updated. If it is a new profile, it gets added
// to the list.
nsresult
nsProfileAccess::SetValue(ProfileStruct* aProfile)
{
PRInt32 index = 0;
index = FindProfileIndex(aProfile->profileName);
if (index >= 0)
{
ProfileStruct* profileItem = (ProfileStruct *) (mProfiles->ElementAt(index));
PRInt32 length = PL_strlen(aProfile->profileLocation);
profileItem->profileLocation = (char *) PR_Realloc(profileItem->profileLocation, length+1);
PL_strcpy(profileItem->profileLocation, aProfile->profileLocation);
length = PL_strlen(aProfile->isMigrated);
profileItem->isMigrated = (char *) PR_Realloc(profileItem->isMigrated, length+1);
PL_strcpy(profileItem->isMigrated, aProfile->isMigrated);
profileItem->updateProfileEntry = PR_TRUE;
if (aProfile->NCProfileName)
{
length = PL_strlen(aProfile->NCProfileName);
profileItem->NCProfileName = (char *) PR_Realloc(profileItem->NCProfileName, length+1);
PL_strcpy(profileItem->NCProfileName, aProfile->NCProfileName);
}
if (aProfile->NCDeniedService)
{
length = PL_strlen(aProfile->NCDeniedService);
profileItem->NCDeniedService = (char *) PR_Realloc(profileItem->NCDeniedService, length+1);
PL_strcpy(profileItem->NCDeniedService, aProfile->NCDeniedService);
}
if (aProfile->NCEmailAddress)
{
length = PL_strlen(aProfile->NCEmailAddress);
profileItem->NCEmailAddress = (char *) PR_Realloc(profileItem->NCEmailAddress, length+1);
PL_strcpy(profileItem->NCEmailAddress, aProfile->NCEmailAddress);
}
if (aProfile->NCHavePregInfo)
{
length = PL_strlen(aProfile->NCHavePregInfo);
profileItem->NCHavePregInfo = (char *) PR_Realloc(profileItem->NCHavePregInfo, length+1);
PL_strcpy(profileItem->NCHavePregInfo, aProfile->NCHavePregInfo);
}
}
else
{
ProfileStruct* profileItem = new ProfileStruct();
if (!profileItem)
return NS_ERROR_OUT_OF_MEMORY;
profileItem->profileName = nsnull;
profileItem->profileLocation = nsnull;
profileItem->isMigrated = nsnull;
profileItem->NCProfileName = nsnull;
profileItem->NCDeniedService = nsnull;
profileItem->NCEmailAddress = nsnull;
profileItem->NCHavePregInfo = nsnull;
profileItem->profileName = nsCRT::strdup(aProfile->profileName);
profileItem->profileLocation = nsCRT::strdup(aProfile->profileLocation);
profileItem->isMigrated = nsCRT::strdup(aProfile->isMigrated);
profileItem->updateProfileEntry = PR_TRUE;
if (aProfile->NCProfileName)
profileItem->NCProfileName = nsCRT::strdup(aProfile->NCProfileName);
if (aProfile->NCDeniedService)
profileItem->NCProfileName = nsCRT::strdup(aProfile->NCDeniedService);
if (aProfile->NCEmailAddress)
profileItem->NCEmailAddress = nsCRT::strdup(aProfile->NCEmailAddress);
if (aProfile->NCHavePregInfo)
profileItem->NCHavePregInfo = nsCRT::strdup(aProfile->NCHavePregInfo);
if (!mProfiles)
mProfiles = new nsVoidArray();
mProfiles->AppendElement((void*)profileItem);
mCount++;
}
return NS_OK;
}
// Enumerates through the registry for profile
// information. Reads in the data into the array
// of profile structs. After this, all the callers
// requesting profile info will get thier data from
// profiles array. All the udates will be done to this
// data structure to reflect the latest status.
// Data will be flushed at the end.
nsresult
nsProfileAccess::FillProfileInfo()
{
nsresult rv = NS_OK;
// Make the fail: thing work
mProfiles = nsnull;
rv = OpenRegistry();
if (NS_FAILED(rv)) return rv;
// Enumerate all subkeys (immediately) under the given node.
nsCOMPtr<nsIEnumerator> enumKeys;
nsRegistryKey profilesTreeKey;
rv = m_registry->GetSubtree(nsIRegistry::Common, REGISTRY_PROFILE_SUBTREE_STRING, &profilesTreeKey);
if (NS_FAILED(rv))
{
rv = m_registry->AddSubtree(nsIRegistry::Common, REGISTRY_PROFILE_SUBTREE_STRING, &profilesTreeKey);
if (NS_FAILED(rv)) return rv;
}
// Get the current profile
rv = m_registry->GetString(profilesTreeKey, REGISTRY_CURRENT_PROFILE_STRING, &mCurrentProfile);
// Get the profile version
rv = m_registry->GetString(profilesTreeKey, REGISTRY_VERSION_STRING, &mVersion);
if (mVersion == nsnull)
{
mFixRegEntries = PR_TRUE;
mVersion = nsCRT::strdup(REGISTRY_VERSION_1_0);
mProfileDataChanged = PR_TRUE;
}
// Get the preg info
rv = m_registry->GetString(profilesTreeKey, REGISTRY_HAVE_PREG_INFO_STRING, &mHavePREGInfo);
if (mHavePREGInfo == nsnull)
{
mHavePREGInfo = nsCRT::strdup(REGISTRY_NO_STRING);
mProfileDataChanged = PR_TRUE;
}
rv = m_registry->EnumerateSubtrees( profilesTreeKey, getter_AddRefs(enumKeys));
if (NS_FAILED(rv)) return rv;
rv = enumKeys->First();
if (NS_FAILED(rv)) return rv;
mCount = 0;
mNumProfiles = 0;
mNumOldProfiles = 0;
while( (NS_OK != enumKeys->IsDone()) )
{
nsCOMPtr<nsISupports> base;
rv = enumKeys->CurrentItem( getter_AddRefs(base) );
if (NS_FAILED(rv)) return rv;
// Get specific interface.
nsCOMPtr <nsIRegistryNode> node;
nsIID nodeIID = NS_IREGISTRYNODE_IID;
rv = base->QueryInterface( nodeIID, getter_AddRefs(node));
if (NS_FAILED(rv)) return rv;
// Get node name.
nsXPIDLCString profile;
nsXPIDLCString isMigrated;
nsXPIDLCString NCProfileName;
nsXPIDLCString NCDeniedService;
nsXPIDLCString NCEmailAddress;
nsXPIDLCString NCHavePregInfo;
char* directory = nsnull;
rv = node->GetName( getter_Copies(profile) );
if (NS_FAILED(rv)) return rv;
if (profile)
{
nsRegistryKey profKey;
rv = m_registry->GetSubtree(profilesTreeKey, profile, &profKey);
if (NS_FAILED(rv)) return rv;
rv = m_registry->GetString(profKey, REGISTRY_DIRECTORY_STRING, &directory);
if (NS_FAILED(rv)) return rv;
if (mFixRegEntries)
FixRegEntry(&directory);
rv = m_registry->GetString(profKey, REGISTRY_MIGRATED_STRING, getter_Copies(isMigrated));
if (NS_FAILED(rv)) return rv;
rv = m_registry->GetString(profKey, REGISTRY_NC_PROFILE_NAME_STRING, getter_Copies(NCProfileName));
rv = m_registry->GetString(profKey, REGISTRY_NC_SERVICE_DENIAL_STRING, getter_Copies(NCDeniedService));
rv = m_registry->GetString(profKey, REGISTRY_NC_USER_EMAIL_STRING, getter_Copies(NCEmailAddress));
rv = m_registry->GetString(profKey, REGISTRY_NC_HAVE_PREG_INFO_STRING, getter_Copies(NCHavePregInfo));
ProfileStruct* profileItem = new ProfileStruct();
if (!profileItem)
return NS_ERROR_OUT_OF_MEMORY;
profileItem->profileName = nsnull;
profileItem->profileLocation = nsnull;
profileItem->isMigrated = nsnull;
profileItem->NCProfileName = nsnull;
profileItem->NCDeniedService = nsnull;
profileItem->NCEmailAddress = nsnull;
profileItem->NCHavePregInfo = nsnull;
profileItem->updateProfileEntry = PR_TRUE;
profileItem->profileName = nsCRT::strdup(profile);
profileItem->profileLocation = nsCRT::strdup(directory);
profileItem->isMigrated = nsCRT::strdup(isMigrated);
if (NCProfileName)
profileItem->NCProfileName = nsCRT::strdup(NCProfileName);
if (NCDeniedService)
profileItem->NCDeniedService = nsCRT::strdup(NCDeniedService);
if (NCEmailAddress)
profileItem->NCEmailAddress = nsCRT::strdup(NCEmailAddress);
if (NCHavePregInfo)
profileItem->NCHavePregInfo = nsCRT::strdup(NCHavePregInfo);
if (PL_strcmp(isMigrated, REGISTRY_YES_STRING) == 0)
mNumProfiles++;
else if (PL_strcmp(isMigrated, REGISTRY_NO_STRING) == 0)
mNumOldProfiles++;
if (!mProfiles)
mProfiles = new nsVoidArray();
mProfiles->AppendElement((void*)profileItem);
mCount++;
CRTFREEIF(directory);
}
rv = enumKeys->Next();
}
mFixRegEntries = PR_FALSE;
rv = CloseRegistry();
return rv;
}
// Return the number of 5x profiles.
// A member variable mNumProfiles is used
// to keep track of 5x profiles.
void
nsProfileAccess::GetNumProfiles(PRInt32 *numProfiles)
{
*numProfiles = mNumProfiles;
}
// Return the number of 4x (>=4.5 & < 5.0) profiles.
// A member variable mNumOldProfiles is used
// to keep track of 4x profiles.
void
nsProfileAccess::GetNum4xProfiles(PRInt32 *numProfiles)
{
*numProfiles = mNumOldProfiles;
}
// If the application can't find the current profile,
// the first profile will be used as the current profile.
// This routine returns the first 5x profile.
// Caller must free up the string (firstProfile).
void
nsProfileAccess::GetFirstProfile(char **firstProfile)
{
PRInt32 index = 0;
*firstProfile = nsnull;
for(index = 0; index < mCount; index++)
{
ProfileStruct* profileItem = (ProfileStruct *) (mProfiles->ElementAt(index));
if (PL_strcmp(profileItem->isMigrated, REGISTRY_YES_STRING) == 0)
{
*firstProfile = nsCRT::strdup(profileItem->profileName);
break;
}
}
}
// Set the current profile. Opearting directly on the tree.
// A separate struct should be maintained for the top level info.
// That way we can eliminate additional registry access. For
// now, we depend on registry operations.
// Capture the current profile information into mCurrentProfile.
void
nsProfileAccess::SetCurrentProfile(const char *profileName)
{
CRTFREEIF(mCurrentProfile);
mCurrentProfile = nsCRT::strdup(profileName);
mProfileDataChanged = PR_TRUE;
}
// Return the current profile value.
// If mCurrent profile is already set, that value is returned.
// If there is only one profile that value is set to CurrentProfile.
void
nsProfileAccess::GetCurrentProfile(char **profileName)
{
*profileName = nsnull;
if (mCurrentProfile)
{
if ((PL_strcmp(mCurrentProfile,"") != 0) || mForgetProfileCalled)
{
*profileName = nsCRT::strdup(mCurrentProfile);
}
}
// If there are profiles and profileName is not
// set yet. Get the first one and set it as Current Profile.
if (mNumProfiles > 0 && (*profileName == nsnull))
{
GetFirstProfile(profileName);
SetCurrentProfile(*profileName);
}
}
// Delete a profile from profile structs
void
nsProfileAccess::RemoveSubTree(const char* profileName)
{
// delete this entry from the mProfiles array
// by moving the pointers with something like memmove
// decrement mCount if it works.
PRInt32 index = 0;
PRBool isOldProfile = PR_FALSE;
index = FindProfileIndex(profileName);
if (index >= 0)
{
ProfileStruct* profileItem = (ProfileStruct *) (mProfiles->ElementAt(index));
if (PL_strcmp(profileItem->isMigrated, REGISTRY_NO_STRING) == 0)
isOldProfile = PR_TRUE;
mProfiles->RemoveElementAt(index);
mCount--;
if (isOldProfile)
mNumOldProfiles--;
else
mNumProfiles--;
if (PL_strcmp(profileName, mCurrentProfile) == 0)
PL_strcpy(mCurrentProfile,"");
}
}
// Fix registry incompatabilities with previous builds
void
nsProfileAccess::FixRegEntry(char** dirName)
{
nsSimpleCharString decodedDirName;
PRBool haveHexBytes = PR_TRUE;
// Decode the directory name to return the ordinary string
nsInputStringStream stream(*dirName);
nsPersistentFileDescriptor descriptor;
char bigBuffer[MAX_PERSISTENT_DATA_SIZE + 1];
// The first 8 bytes of the data should be a hex version of the data size to follow.
PRInt32 bytesRead = NUM_HEX_BYTES;
bytesRead = stream.read(bigBuffer, bytesRead);
if (bytesRead != NUM_HEX_BYTES)
haveHexBytes = PR_FALSE;
if (haveHexBytes)
{
bigBuffer[NUM_HEX_BYTES] = '\0';
for (int i = 0; i < NUM_HEX_BYTES; i++)
{
if (!(ISHEX(bigBuffer[i])))
{
haveHexBytes = PR_FALSE;
break;
}
}
}
if (haveHexBytes)
{
//stream(dirName);
PR_sscanf(bigBuffer, "%x", (PRUint32*)&bytesRead);
if (bytesRead > MAX_PERSISTENT_DATA_SIZE)
{
// Try to tolerate encoded values with no length header
bytesRead = NUM_HEX_BYTES + stream.read(bigBuffer + NUM_HEX_BYTES, MAX_PERSISTENT_DATA_SIZE - NUM_HEX_BYTES);
}
else
{
// Now we know how many bytes to read, do it.
bytesRead = stream.read(bigBuffer, bytesRead);
}
// Make sure we are null terminated
bigBuffer[bytesRead]='\0';
descriptor.SetData(bigBuffer, bytesRead);
descriptor.GetData(decodedDirName);
*dirName = nsCRT::strdup(decodedDirName);
}
}
// Return the index of a given profiel from the arraf of profile structs.
PRInt32
nsProfileAccess::FindProfileIndex(const char* profileName)
{
PRInt32 retval = -1;
PRInt32 index = 0;
for (index=0; index < mCount; index++)
{
ProfileStruct* profileItem = (ProfileStruct *) (mProfiles->ElementAt(index));
if (PL_strcmp(profileName, profileItem->profileName) == 0)
{
retval = index;
break;
}
}
return retval;
}
// Flush profile information from the data structure to the registry.
nsresult
nsProfileAccess::UpdateRegistry()
{
nsresult rv;
if (!mProfileDataChanged)
{
return NS_OK;
}
rv = OpenRegistry();
if (NS_FAILED(rv)) return rv;
// Enumerate all subkeys (immediately) under the given node.
nsCOMPtr<nsIEnumerator> enumKeys;
nsRegistryKey profilesTreeKey;
// Get the major subtree
rv = m_registry->GetSubtree(nsIRegistry::Common, REGISTRY_PROFILE_SUBTREE_STRING, &profilesTreeKey);
if (NS_FAILED(rv)) return rv;
// Set the current profile
rv = m_registry->SetString(profilesTreeKey, REGISTRY_CURRENT_PROFILE_STRING, mCurrentProfile);
if (NS_FAILED(rv)) return rv;
// Set the registry version
rv = m_registry->SetString(profilesTreeKey, REGISTRY_VERSION_STRING, mVersion);
if (NS_FAILED(rv)) return rv;
// Set preg info
rv = m_registry->SetString(profilesTreeKey, REGISTRY_HAVE_PREG_INFO_STRING, mHavePREGInfo);
if (NS_FAILED(rv)) return rv;
rv = m_registry->EnumerateSubtrees(profilesTreeKey, getter_AddRefs(enumKeys));
if (NS_FAILED(rv)) return rv;
rv = enumKeys->First();
if (NS_FAILED(rv)) return rv;
while( (NS_OK != enumKeys->IsDone()) )
{
nsCOMPtr<nsISupports> base;
rv = enumKeys->CurrentItem( getter_AddRefs(base) );
if (NS_FAILED(rv)) return rv;
// Get specific interface.
nsCOMPtr <nsIRegistryNode> node;
nsIID nodeIID = NS_IREGISTRYNODE_IID;
rv = base->QueryInterface( nodeIID, getter_AddRefs(node));
if (NS_FAILED(rv)) return rv;
// Get node name.
nsXPIDLCString profile;
nsXPIDLCString isMigrated;
nsXPIDLCString directory;
rv = node->GetName( getter_Copies(profile) );
if (NS_FAILED(rv)) return rv;
PRInt32 index = 0;
index = FindProfileIndex(profile);
if (index < 0)
{
// This profile is deleted.
rv = m_registry->RemoveSubtree(profilesTreeKey, profile);
if (NS_FAILED(rv)) return rv;
}
else
{
nsRegistryKey profKey;
ProfileStruct* profileItem = (ProfileStruct *) (mProfiles->ElementAt(index));
rv = m_registry->GetSubtree(profilesTreeKey, profile, &profKey);
if (NS_FAILED(rv)) return rv;
rv = m_registry->SetString(profKey, REGISTRY_DIRECTORY_STRING, profileItem->profileLocation);
if (NS_FAILED(rv)) return rv;
rv = m_registry->SetString(profKey, REGISTRY_MIGRATED_STRING, profileItem->isMigrated);
if (NS_FAILED(rv)) return rv;
rv = m_registry->SetString(profKey, REGISTRY_NC_PROFILE_NAME_STRING, profileItem->NCProfileName);
rv = m_registry->SetString(profKey, REGISTRY_NC_SERVICE_DENIAL_STRING, profileItem->NCDeniedService);
rv = m_registry->SetString(profKey, REGISTRY_NC_USER_EMAIL_STRING, profileItem->NCEmailAddress);
rv = m_registry->SetString(profKey, REGISTRY_NC_HAVE_PREG_INFO_STRING, profileItem->NCHavePregInfo);
profileItem->updateProfileEntry = PR_FALSE;
}
rv = enumKeys->Next();
}
// Take care of new nodes
for (int i = 0; i < mCount; i++)
{
ProfileStruct* profileItem = (ProfileStruct *) (mProfiles->ElementAt(i));
if (profileItem->updateProfileEntry)
{
nsRegistryKey profKey;
rv = m_registry->AddSubtree(profilesTreeKey, profileItem->profileName, &profKey);
if (NS_FAILED(rv)) return rv;
rv = m_registry->SetString(profKey, REGISTRY_DIRECTORY_STRING, profileItem->profileLocation);
if (NS_FAILED(rv)) return rv;
rv = m_registry->SetString(profKey, REGISTRY_MIGRATED_STRING, profileItem->isMigrated);
if (NS_FAILED(rv)) return rv;
rv = m_registry->SetString(profKey, REGISTRY_NC_PROFILE_NAME_STRING, profileItem->NCProfileName);
rv = m_registry->SetString(profKey, REGISTRY_NC_SERVICE_DENIAL_STRING, profileItem->NCDeniedService);
rv = m_registry->SetString(profKey, REGISTRY_NC_USER_EMAIL_STRING, profileItem->NCEmailAddress);
rv = m_registry->SetString(profKey, REGISTRY_NC_HAVE_PREG_INFO_STRING, profileItem->NCHavePregInfo);
profileItem->updateProfileEntry = PR_FALSE;
}
}
rv = CloseRegistry();
mProfileDataChanged = PR_FALSE;
return rv;
}
// Return the list of profiles, 4x and 5x.
// For 4x profiles text "- migrate" is appended
// to inform the JavaScript about the migration status.
void
nsProfileAccess::GetProfileList(char **profileListStr)
{
nsCAutoString profileList("");
for (PRInt32 index=0; index < mCount; index++)
{
ProfileStruct* profileItem = (ProfileStruct *) (mProfiles->ElementAt(index));
if (index != 0)
{
profileList += ",";
}
profileList += profileItem->profileName;
if (PL_strcmp(profileItem->isMigrated, REGISTRY_NO_STRING) == 0)
profileList += " - migrate";
}
*profileListStr = nsCRT::strdup((const char *)profileList);
}
// Return a boolean based on the profile existence.
PRBool
nsProfileAccess::ProfileExists(const char *profileName)
{
PRBool exists = PR_FALSE;
for (PRInt32 index=0; index < mCount; index++)
{
ProfileStruct* profileItem = (ProfileStruct *) (mProfiles->ElementAt(index));
if (PL_strcmp(profileItem->profileName, profileName) == 0)
{
exists = PR_TRUE;
break;
}
}
return exists;
}
// Capture the 4x profile information from the old registry (4x)
nsresult
nsProfileAccess::Get4xProfileInfo(const char *registryName)
{
nsresult rv = NS_OK;
mNumOldProfiles = 0;
#if defined(XP_PC) || defined(XP_MAC)
nsCOMPtr <nsIRegistry> oldReg;
rv = nsComponentManager::CreateInstance(kRegistryCID,
nsnull,
NS_GET_IID(nsIRegistry),
getter_AddRefs(oldReg));
if (NS_FAILED(rv)) return rv;
rv = oldReg->Open(registryName);
if (NS_FAILED(rv)) return rv;
// Enumerate 4x tree and create an array of that information.
// Enumerate all subkeys (immediately) under the given node.
nsCOMPtr<nsIEnumerator> enumKeys;
rv = oldReg->EnumerateSubtrees(nsIRegistry::Users,
getter_AddRefs(enumKeys));
if (NS_FAILED(rv)) return rv;
rv = enumKeys->First();
if (NS_FAILED(rv)) return rv;
// Enumerate subkeys till done.
while( (NS_OK != enumKeys->IsDone()))
{
nsCOMPtr<nsISupports> base;
rv = enumKeys->CurrentItem(getter_AddRefs(base));
if (NS_FAILED(rv)) return rv;
// Get specific interface.
nsCOMPtr <nsIRegistryNode> node;
nsIID nodeIID = NS_IREGISTRYNODE_IID;
rv = base->QueryInterface( nodeIID, getter_AddRefs(node));
if (NS_FAILED(rv)) return rv;
char *profile = nsnull;
rv = node->GetName(&profile);
if (NS_FAILED(rv)) return rv;
PRBool exists = PR_FALSE;;
exists = ProfileExists(profile);
if (exists)
{
rv = enumKeys->Next();
if (NS_FAILED(rv)) return rv;
continue;
}
nsRegistryKey key;
rv = oldReg->GetSubtree(nsIRegistry::Users, profile, &key);
if (NS_FAILED(rv)) return rv;
nsXPIDLCString profLoc;
rv = oldReg->GetString( key, "ProfileLocation", getter_Copies(profLoc));
if (NS_FAILED(rv)) return rv;
#if defined(DEBUG_profile)
printf("oldProflie Location = %s\n", profLoc);
#endif
ProfileStruct* profileItem = new ProfileStruct();
if (!profileItem)
return NS_ERROR_OUT_OF_MEMORY;
profileItem->profileName = nsnull;
profileItem->profileLocation = nsnull;
profileItem->isMigrated = nsnull;
profileItem->NCProfileName = nsnull;
profileItem->NCDeniedService = nsnull;
profileItem->NCEmailAddress = nsnull;
profileItem->NCHavePregInfo = nsnull;
profileItem->updateProfileEntry = PR_TRUE;
profileItem->profileName = nsCRT::strdup(nsUnescape(profile));
profileItem->profileLocation = nsCRT::strdup(profLoc);
profileItem->isMigrated = nsCRT::strdup(REGISTRY_NO_STRING);
if (!m4xProfiles)
m4xProfiles = new nsVoidArray();
m4xProfiles->AppendElement((void*)profileItem);
mNumOldProfiles++;
rv = enumKeys->Next();
if (NS_FAILED(rv)) return rv;
}
oldReg->Close();
#elif defined (XP_BEOS)
#else
/* XP_UNIX */
char *unixProfileName = PR_GetEnv(PROFILE_NAME_ENVIRONMENT_VARIABLE);
char *unixProfileDirectory = PR_GetEnv(PROFILE_HOME_ENVIRONMENT_VARIABLE);
if (!unixProfileName || !unixProfileDirectory || (PL_strlen(unixProfileName) == 0) || (PL_strlen(unixProfileDirectory) == 0)) {
unixProfileName = PR_GetEnv(USER_ENVIRONMENT_VARIABLE);
unixProfileDirectory = PR_GetEnv(HOME_ENVIRONMENT_VARIABLE);
}
PRBool exists = PR_FALSE;;
exists = ProfileExists(unixProfileName);
if (exists)
{
return NS_OK;
}
if (unixProfileName && unixProfileDirectory) {
nsCAutoString profileLocation(unixProfileDirectory);
profileLocation += "/.netscape";
nsCOMPtr<nsIFileSpec> users4xDotNetscapeDirectory;
rv = NS_NewFileSpec(getter_AddRefs(users4xDotNetscapeDirectory));
if (NS_FAILED(rv)) return rv;
rv = users4xDotNetscapeDirectory->SetNativePath((const char *)profileLocation);
if (NS_FAILED(rv)) return rv;
rv = users4xDotNetscapeDirectory->Exists(&exists);
if (NS_FAILED(rv)) return rv;
#ifdef DEBUG
printf("%s exists: %d\n",(const char *)profileLocation, exists);
#endif
if (exists) {
ProfileStruct* profileItem = new ProfileStruct();
if (!profileItem)
return NS_ERROR_OUT_OF_MEMORY;
profileItem->profileName = nsnull;
profileItem->profileLocation = nsnull;
profileItem->isMigrated = nsnull;
profileItem->NCProfileName = nsnull;
profileItem->NCDeniedService = nsnull;
profileItem->NCEmailAddress = nsnull;
profileItem->NCHavePregInfo = nsnull;
profileItem->updateProfileEntry = PR_TRUE;
profileItem->profileName = nsCRT::strdup(nsUnescape(unixProfileName));
profileItem->profileLocation = nsCRT::strdup((const char *)profileLocation);
profileItem->isMigrated = nsCRT::strdup(REGISTRY_NO_STRING);
if (!m4xProfiles)
m4xProfiles = new nsVoidArray();
m4xProfiles->AppendElement((void*)profileItem);
mNumOldProfiles++;
}
else {
#ifdef DEBUG
printf("no 4.x profile\n");
#endif
}
}
#endif
m4xCount = mNumOldProfiles;
if (m4xCount > 0) {
UpdateProfileArray();
}
return rv;
}
// Update the mozregistry with the 4x profile names
// and thier locations. Entry REGISTRY_MIGRATED_STRING is set to REGISTRY_NO_STRING
// to differentiate these profiles from 5x profiles.
nsresult
nsProfileAccess::UpdateProfileArray()
{
nsresult rv = NS_OK;
for (PRInt32 idx = 0; idx < m4xCount; idx++)
{
ProfileStruct* profileItem = (ProfileStruct *) (m4xProfiles->ElementAt(idx));
nsFileSpec profileDir(profileItem->profileLocation);
PRBool exists;
exists = ProfileExists(profileItem->profileName);
if (NS_FAILED(rv)) return rv;
// That profile already exists...
// move on.....
if (exists) {
continue;
}
nsXPIDLCString profileDirString;
nsCOMPtr<nsIFileSpec>spec;
rv = NS_NewFileSpecWithSpec(profileDir, getter_AddRefs(spec));
if (NS_FAILED(rv)) return rv;
rv = spec->GetPersistentDescriptorString(getter_Copies(profileDirString));
if (NS_SUCCEEDED(rv) && profileDirString)
{
PRInt32 length = PL_strlen(profileDirString);
profileItem->profileLocation = (char *) PR_Realloc(profileItem->profileLocation, length+1);
PL_strcpy(profileItem->profileLocation, profileDirString);
SetValue(profileItem);
}
}
mProfileDataChanged = PR_TRUE;
return rv;
}
// Set the PREG flag to indicate if that info exists
void
nsProfileAccess::SetPREGInfo(const char* pregInfo)
{
mHavePREGInfo = nsCRT::strdup(pregInfo);
}
//Get the for PREG info.
void
nsProfileAccess::GetPREGInfo(const char *profileName, char **info)
{
*info = nsnull;
PRInt32 index = 0;
index = FindProfileIndex(profileName);
if (index >= 0 )
{
ProfileStruct* profileItem = (ProfileStruct *) (mProfiles->ElementAt(index));
if (profileItem->NCHavePregInfo)
*info = nsCRT::strdup(profileItem->NCHavePregInfo);
else
*info = nsCRT::strdup(REGISTRY_NO_STRING);
}
}