From ff7a3079f86faee949991c8db01780178ff2ccbd Mon Sep 17 00:00:00 2001 From: "sspitzer%netscape.com" Date: Mon, 6 Dec 1999 18:27:26 +0000 Subject: [PATCH] new files. not part of the build yet. git-svn-id: svn://10.0.0.236/trunk@55428 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/profile/src/nsProfileAccess.cpp | 944 ++++++++++++++++++++++++ mozilla/profile/src/nsProfileAccess.h | 96 +++ 2 files changed, 1040 insertions(+) create mode 100644 mozilla/profile/src/nsProfileAccess.cpp create mode 100644 mozilla/profile/src/nsProfileAccess.h diff --git a/mozilla/profile/src/nsProfileAccess.cpp b/mozilla/profile/src/nsProfileAccess.cpp new file mode 100644 index 00000000000..9bc9c243289 --- /dev/null +++ b/mozilla/profile/src/nsProfileAccess.cpp @@ -0,0 +1,944 @@ +/* -*- 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. + */ + +#include "nsProfileAccess.h" +#include "nsProfile.h" + +#include "pratom.h" +#include "prmem.h" +#include "plstr.h" +#include "prenv.h" + +#include "NSReg.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" + +// kill me now. +#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_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; + + 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, mCount); + FreeProfileMembers(m4xProfiles, m4xCount); +} + +// Free up the member profile structs +void +nsProfileAccess::FreeProfileMembers(ProfileStruct *profiles[], PRInt32 numElems) +{ + PRInt32 index = 0; + + for (index=0; index < numElems; index++) + { + CRTFREEIF(profiles[index]->profileName); + CRTFREEIF(profiles[index]->profileLocation); + CRTFREEIF(profiles[index]->isMigrated); + CRTFREEIF(profiles[index]->NCProfileName); + CRTFREEIF(profiles[index]->NCDeniedService); + + PR_FREEIF(profiles[index]); + } + +} + +// 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, + nsIRegistry::GetIID(), + 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; + + (*aProfile)->profileName = nsnull; + (*aProfile)->profileLocation = nsnull; + (*aProfile)->isMigrated = nsnull; + (*aProfile)->NCProfileName = nsnull; + (*aProfile)->NCDeniedService = nsnull; + + (*aProfile)->profileName = nsCRT::strdup(mProfiles[index]->profileName); + (*aProfile)->profileLocation = nsCRT::strdup(mProfiles[index]->profileLocation); + (*aProfile)->isMigrated = nsCRT::strdup(mProfiles[index]->isMigrated); + + if (mProfiles[index]->NCProfileName) + (*aProfile)->NCProfileName = nsCRT::strdup(mProfiles[index]->NCProfileName); + if (mProfiles[index]->NCDeniedService) + (*aProfile)->NCProfileName = nsCRT::strdup(mProfiles[index]->NCDeniedService); + } + 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) + { + PRInt32 length = PL_strlen(aProfile->profileLocation); + mProfiles[index]->profileLocation = (char *) PR_Realloc(mProfiles[index]->profileLocation, length+1); + PL_strcpy(mProfiles[index]->profileLocation, aProfile->profileLocation); + + length = PL_strlen(aProfile->isMigrated); + mProfiles[index]->isMigrated = (char *) PR_Realloc(mProfiles[index]->isMigrated, length+1); + PL_strcpy(mProfiles[index]->isMigrated, aProfile->isMigrated); + + mProfiles[index]->updateProfileEntry = PR_TRUE; + + if (aProfile->NCProfileName) + { + length = PL_strlen(aProfile->NCProfileName); + mProfiles[index]->NCProfileName = (char *) PR_Realloc(mProfiles[index]->NCProfileName, length+1); + PL_strcpy(mProfiles[index]->NCProfileName, aProfile->NCProfileName); + } + if (aProfile->NCDeniedService) + { + length = PL_strlen(aProfile->NCDeniedService); + mProfiles[index]->NCDeniedService = (char *) PR_Realloc(mProfiles[index]->NCDeniedService, length+1); + PL_strcpy(mProfiles[mCount]->NCDeniedService, aProfile->NCDeniedService); + } + } + else + { + mProfiles[mCount] = (ProfileStruct *) PR_Malloc(sizeof(ProfileStruct)); + if (!mProfiles[mCount]) + return NS_ERROR_OUT_OF_MEMORY; + + mProfiles[mCount]->profileName = nsnull; + mProfiles[mCount]->profileLocation = nsnull; + mProfiles[mCount]->isMigrated = nsnull; + mProfiles[mCount]->NCProfileName = nsnull; + mProfiles[mCount]->NCDeniedService = nsnull; + + mProfiles[mCount]->profileName = nsCRT::strdup(aProfile->profileName); + mProfiles[mCount]->profileLocation = nsCRT::strdup(aProfile->profileLocation); + mProfiles[mCount]->isMigrated = nsCRT::strdup(aProfile->isMigrated); + mProfiles[mCount]->updateProfileEntry = PR_TRUE; + + if (aProfile->NCProfileName) + mProfiles[index]->NCProfileName = nsCRT::strdup(aProfile->NCProfileName); + if (aProfile->NCDeniedService) + mProfiles[mCount]->NCProfileName = nsCRT::strdup(aProfile->NCDeniedService); + + 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[0] = nsnull; + + rv = OpenRegistry(); + if (NS_FAILED(rv)) return rv; + + // Enumerate all subkeys (immediately) under the given node. + nsCOMPtr 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 base; + + rv = enumKeys->CurrentItem( getter_AddRefs(base) ); + if (NS_FAILED(rv)) return rv; + + // Get specific interface. + nsCOMPtr 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; + 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)); + + mProfiles[mCount] = (ProfileStruct *) PR_Malloc(sizeof(ProfileStruct)); + if (!mProfiles[mCount]) + return NS_ERROR_OUT_OF_MEMORY; + + mProfiles[mCount]->profileName = nsnull; + mProfiles[mCount]->profileLocation = nsnull; + mProfiles[mCount]->isMigrated = nsnull; + mProfiles[mCount]->NCProfileName = nsnull; + mProfiles[mCount]->NCDeniedService = nsnull; + mProfiles[mCount]->updateProfileEntry = PR_TRUE; + + mProfiles[mCount]->profileName = nsCRT::strdup(profile); + mProfiles[mCount]->profileLocation = nsCRT::strdup(directory); + mProfiles[mCount]->isMigrated = nsCRT::strdup(isMigrated); + + if (NCProfileName) + mProfiles[mCount]->NCProfileName = nsCRT::strdup(NCProfileName); + if (NCDeniedService) + mProfiles[mCount]->NCDeniedService = nsCRT::strdup(NCDeniedService); + + + if (PL_strcmp(isMigrated, REGISTRY_YES_STRING) == 0) + mNumProfiles++; + else if (PL_strcmp(isMigrated, REGISTRY_NO_STRING) == 0) + mNumOldProfiles++; + + 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++) + { + if (PL_strcmp(mProfiles[index]->isMigrated, REGISTRY_YES_STRING) == 0) + { + *firstProfile = nsCRT::strdup(mProfiles[index]->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) +{ + 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; + PRInt32 i = 0; + PRBool isOldProfile = PR_FALSE; + + index = FindProfileIndex(profileName); + + if (index >= 0) + { + if (PL_strcmp(mProfiles[index]->isMigrated, REGISTRY_NO_STRING) == 0) + isOldProfile = PR_TRUE; + + PRInt32 movePositions = mCount - index; + for (i=0; i < movePositions; i++,index++) + nsCRT::memmove(&mProfiles[index], &mProfiles[index+1], sizeof(ProfileStruct *)); + + 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++) + { + if (PL_strcmp(profileName, mProfiles[index]->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 enumKeys; + nsRegistryKey profilesTreeKey; + + // Get the major subtree + rv = m_registry->GetSubtree(nsIRegistry::Common, REGISTRY_PROFILE_SUBTREE_STRING, &profilesTreeKey); + if (NS_FAILED(rv)) return rv; + + // Get the current profile + rv = m_registry->SetString(profilesTreeKey, REGISTRY_CURRENT_PROFILE_STRING, mCurrentProfile); + if (NS_FAILED(rv)) return rv; + + // Get the current profile + rv = m_registry->SetString(profilesTreeKey, REGISTRY_VERSION_STRING, mVersion); + if (NS_FAILED(rv)) return rv; + + // Get the current profile + 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 base; + + rv = enumKeys->CurrentItem( getter_AddRefs(base) ); + if (NS_FAILED(rv)) return rv; + + // Get specific interface. + nsCOMPtr 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; + + rv = m_registry->GetSubtree(profilesTreeKey, profile, &profKey); + if (NS_FAILED(rv)) return rv; + + rv = m_registry->SetString(profKey, REGISTRY_DIRECTORY_STRING, mProfiles[index]->profileLocation); + if (NS_FAILED(rv)) return rv; + + rv = m_registry->SetString(profKey, REGISTRY_MIGRATED_STRING, mProfiles[index]->isMigrated); + if (NS_FAILED(rv)) return rv; + + rv = m_registry->SetString(profKey, REGISTRY_NC_PROFILE_NAME_STRING, mProfiles[index]->NCProfileName); + rv = m_registry->SetString(profKey, REGISTRY_NC_SERVICE_DENIAL_STRING, mProfiles[index]->NCDeniedService); + + mProfiles[index]->updateProfileEntry = PR_FALSE; + } + rv = enumKeys->Next(); + } + + // Take care of new nodes + for (int i = 0; i < mCount; i++) + { + if (mProfiles[i]->updateProfileEntry) + { + nsRegistryKey profKey; + + rv = m_registry->AddSubtree(profilesTreeKey, mProfiles[i]->profileName, &profKey); + if (NS_FAILED(rv)) return rv; + + rv = m_registry->SetString(profKey, REGISTRY_DIRECTORY_STRING, mProfiles[i]->profileLocation); + if (NS_FAILED(rv)) return rv; + + rv = m_registry->SetString(profKey, REGISTRY_MIGRATED_STRING, mProfiles[i]->isMigrated); + if (NS_FAILED(rv)) return rv; + + mProfiles[i]->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++) + { + if (index != 0) + { + profileList += ","; + } + profileList += mProfiles[index]->profileName; + + if (PL_strcmp(mProfiles[index]->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++) + { + if (PL_strcmp(mProfiles[index]->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 oldReg; + rv = nsComponentManager::CreateInstance(kRegistryCID, + nsnull, + nsIRegistry::GetIID(), + 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 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 base; + rv = enumKeys->CurrentItem(getter_AddRefs(base)); + if (NS_FAILED(rv)) return rv; + + // Get specific interface. + nsCOMPtr 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; + + 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 + + m4xProfiles[mNumOldProfiles] = (ProfileStruct *) PR_Malloc(sizeof(ProfileStruct)); + if (!m4xProfiles[mNumOldProfiles]) + return NS_ERROR_OUT_OF_MEMORY; + + m4xProfiles[mNumOldProfiles]->profileName = nsnull; + m4xProfiles[mNumOldProfiles]->profileLocation = nsnull; + m4xProfiles[mNumOldProfiles]->isMigrated = nsnull; + m4xProfiles[mNumOldProfiles]->NCProfileName = nsnull; + m4xProfiles[mNumOldProfiles]->NCDeniedService = nsnull; + m4xProfiles[mNumOldProfiles]->updateProfileEntry = PR_TRUE; + + m4xProfiles[mNumOldProfiles]->profileName = nsCRT::strdup(nsUnescape(profile)); + m4xProfiles[mNumOldProfiles]->profileLocation = nsCRT::strdup(profLoc); + m4xProfiles[mNumOldProfiles]->isMigrated = nsCRT::strdup(REGISTRY_NO_STRING); + + 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); + } + + if (unixProfileName && unixProfileDirectory) { + + m4xProfiles[mNumOldProfiles] = (ProfileStruct *) PR_Malloc(sizeof(ProfileStruct)); + if (!m4xProfiles[mNumOldProfiles]) + return NS_ERROR_OUT_OF_MEMORY; + + m4xProfiles[mNumOldProfiles]->profileName = nsnull; + m4xProfiles[mNumOldProfiles]->profileLocation = nsnull; + m4xProfiles[mNumOldProfiles]->isMigrated = nsnull; + m4xProfiles[mNumOldProfiles]->NCProfileName = nsnull; + m4xProfiles[mNumOldProfiles]->NCDeniedService = nsnull; + m4xProfiles[mNumOldProfiles]->updateProfileEntry = PR_TRUE; + + m4xProfiles[mNumOldProfiles]->profileName = nsCRT::strdup(nsUnescape(unixProfileName)); + m4xProfiles[mNumOldProfiles]->profileLocation = nsCRT::strdup(unixProfileDirectory); + + PRInt32 length = PL_strlen(unixProfileDirectory) + PL_strlen("/.netscape"); + m4xProfiles[mNumOldProfiles]->profileLocation = (char *) PR_Realloc(m4xProfiles[mNumOldProfiles]->profileLocation, length+1); + PL_strcpy(m4xProfiles[mNumOldProfiles]->profileLocation, unixProfileDirectory); + PL_strcat(m4xProfiles[mNumOldProfiles]->profileLocation, "/.netscape"); + + m4xProfiles[mNumOldProfiles]->isMigrated = nsCRT::strdup(REGISTRY_NO_STRING); + + mNumOldProfiles++; + } +#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++) + { + nsFileSpec profileDir(m4xProfiles[idx]->profileLocation); + + PRBool exists; + exists = ProfileExists(m4xProfiles[idx]->profileName); + if (NS_FAILED(rv)) return rv; + + // That profile already exists... + // move on..... + if (exists) { + continue; + } + + nsXPIDLCString profileDirString; + nsCOMPtrspec; + 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); + m4xProfiles[idx]->profileLocation = (char *) PR_Realloc(m4xProfiles[idx]->profileLocation, length+1); + + PL_strcpy(m4xProfiles[idx]->profileLocation, profileDirString); + + SetValue(m4xProfiles[idx]); + } + } + + 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(char **info) +{ + *info = nsnull; + + if (mHavePREGInfo) + *info = nsCRT::strdup(mHavePREGInfo); +} + diff --git a/mozilla/profile/src/nsProfileAccess.h b/mozilla/profile/src/nsProfileAccess.h new file mode 100644 index 00000000000..b50c75e9759 --- /dev/null +++ b/mozilla/profile/src/nsProfileAccess.h @@ -0,0 +1,96 @@ +/* -*- 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. + */ + +#ifndef __nsProfileAccess_h___ +#define __nsProfileAccess_h___ + +#include "nsCOMPtr.h" +#include "nsISupports.h" +#include "nsString.h" +#include "nsIRegistry.h" +#include "nsXPIDLString.h" + +#define _MAX_NUM_PROFILES 100 +#define _MAX_4X_PROFILES 50 + +//typedef struct _profile_struct ProfileStruct; +typedef struct _profile_struct { + char* profileName; + char* profileLocation; + char* isMigrated; + char* NCProfileName; + char* NCDeniedService; + PRBool updateProfileEntry; +}ProfileStruct; + +class nsProfileAccess +{ + +private: + nsCOMPtr m_registry; + + ProfileStruct *mProfiles[_MAX_NUM_PROFILES]; + PRInt32 mCount; + char* mCurrentProfile; + char* mVersion; + PRBool mFixRegEntries; + char* mHavePREGInfo; + PRInt32 m4xCount; + + nsresult OpenRegistry(); + nsresult CloseRegistry(); + +public: + PRBool mProfileDataChanged; + PRBool mForgetProfileCalled; + PRInt32 mNumProfiles; + PRInt32 mNumOldProfiles; + ProfileStruct *m4xProfiles[_MAX_4X_PROFILES]; + + nsProfileAccess(); + virtual ~nsProfileAccess(); + + nsresult SetValue(ProfileStruct* aProfile); + nsresult FillProfileInfo(); + + void GetNumProfiles(PRInt32 *numProfiles); + void GetNum4xProfiles(PRInt32 *numProfiles); + void GetFirstProfile(char **firstProfile); + + void SetCurrentProfile(const char *profileName); + void GetCurrentProfile(char **profileName); + + void RemoveSubTree(const char* profileName); + void FixRegEntry(char** dirName); + + nsresult HavePregInfo(char **info); + nsresult GetValue(const char* profileName, ProfileStruct** aProfile); + PRInt32 FindProfileIndex(const char* profileName); + + nsresult UpdateRegistry(); + void GetProfileList(char **profileListStr); + PRBool ProfileExists(const char *profileName); + nsresult Get4xProfileInfo(const char *registryName); + nsresult UpdateProfileArray(); + void SetPREGInfo(const char* pregInfo); + void GetPREGInfo(char** pregInfo); + void FreeProfileMembers(ProfileStruct *aProfile[], PRInt32 numElems); +}; + +#endif // __nsProfileAccess_h___ +