Files
Mozilla/mozilla/profile/src/nsProfile.cpp
beard%netscape.com 7146388dfe plugged a memory leak in GetProfileCount()
git-svn-id: svn://10.0.0.236/trunk@44718 18797224-902f-48f8-a5cc-f745e15eee43
1999-08-27 03:48:24 +00:00

2702 lines
62 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 "nsIProfile.h"
#include "nsIPref.h"
#include "pratom.h"
#include "prmem.h"
#include "nsIRegistry.h"
#include "NSReg.h"
#include "nsIFactory.h"
#include "nsIComponentManager.h"
#include "nsIEnumerator.h"
#include "plstr.h"
#include "nsIFileSpec.h"
#include "nsFileSpec.h"
#include "nsString.h"
#include "nsIFileLocator.h"
#include "nsFileLocations.h"
#include "nsEscape.h"
#include "nsIURL.h"
#ifndef NECKO
#include "nsINetService.h"
#else
#include "nsIIOService.h"
#include "nsNeckoUtil.h"
#endif // NECKO
#ifdef XP_PC
#include <direct.h>
#include "nsIPrefMigration.h"
#endif
#ifdef XP_MAC
#include "nsIPrefMigration.h"
#endif
// included for XPlatform coding
#include "nsFileStream.h"
#include "nsSpecialSystemDirectory.h"
#ifdef XP_MAC
#ifdef NECKO
#include "nsIPrompt.h"
#else
#include "nsINetSupport.h"
#endif
#include "nsIStreamListener.h"
#endif
#include "nsIServiceManager.h"
#include "nsCOMPtr.h"
#define _MAX_LENGTH 256
#define _MAX_NUM_PROFILES 50
// PREG information
#define PREG_COOKIE "NS_REG2_PREG"
#define PREG_USERNAME "PREG_USER_NAME"
#define PREG_DENIAL "PREG_USER_DENIAL"
#define PREG_URL "http://seaspace.mcom.com/"
// Globals to hold profile information
#ifdef XP_PC
static char *oldWinReg="nsreg.dat";
#endif
#ifdef XP_MAC
static char *oldMacReg = "Netscape Registry";
#endif
static char gNewProfileData[_MAX_NUM_PROFILES][_MAX_LENGTH] = {{'\0'}};
static int g_Count = 0;
static char gProfiles[_MAX_NUM_PROFILES][_MAX_LENGTH] = {{'\0'}};
static int g_numProfiles = 0;
// we only migrate prefs on windows right now.
#if defined(XP_PC) || defined(XP_MAC)
static char gOldProfiles[_MAX_NUM_PROFILES][_MAX_LENGTH] = {{'\0'}};
static char gOldProfLocations[_MAX_NUM_PROFILES][_MAX_LENGTH] = {{'\0'}};
static int g_numOldProfiles = 0;
#endif
static PRBool renameCurrProfile = PR_FALSE;
// IID and CIDs of all the services needed
static NS_DEFINE_IID(kIProfileIID, NS_IPROFILE_IID);
static NS_DEFINE_CID(kProfileCID, NS_PROFILE_CID);
static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
static NS_DEFINE_CID(kFileLocatorCID, NS_FILELOCATOR_CID);
static NS_DEFINE_CID(kRegistryCID, NS_REGISTRY_CID);
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
#ifndef NECKO
static NS_DEFINE_IID(kINetServiceIID, NS_INETSERVICE_IID);
static NS_DEFINE_IID(kNetServiceCID, NS_NETSERVICE_CID);
#else
static NS_DEFINE_IID(kIIOServiceIID, NS_IIOSERVICE_IID);
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#endif // NECKO
#if defined(XP_PC) || defined(XP_MAC)
static NS_DEFINE_IID(kIPrefMigration_IID, NS_IPrefMigration_IID);
static NS_DEFINE_CID(kPrefMigration_CID, NS_PrefMigration_CID);
#endif
class nsProfile: public nsIProfile {
NS_DECL_ISUPPORTS
private:
static void useDefaultProfileFile(nsProfile *aProfileInst);
static nsProfile *mInstance;
nsIRegistry* m_reg;
public:
nsProfile();
virtual ~nsProfile();
static nsProfile *GetInstance();
// Creates associated user directories on the creation of a new profile
void CreateUserDirectories(const nsFileSpec& profileDir);
// Deletes associated user directories
void DeleteUserDirectories(const nsFileSpec& profileDir);
// Sets profile information recived from the Javascript (routed via core service) into an array
void SetDataArray(nsString data);
// Gets a particular value from the DataArray
char* GetValue(char *name);
// Copies all the registry keys from old profile to new profile
nsresult CopyRegKey(const char *oldProfile, const char *newProfile);
// Fills the global array gProfiles by enumerating registry entries
void GetAllProfiles();
// Initialize/shutdown
NS_IMETHOD Startup(char *registry);
NS_IMETHOD Shutdown();
// Getters
NS_IMETHOD GetProfileDir(const char *profileName, nsFileSpec* profileDir);
NS_IMETHOD GetProfileCount(int *numProfiles);
NS_IMETHOD GetSingleProfile(char **profileName);
NS_IMETHOD GetCurrentProfile(char **profileName);
NS_IMETHOD GetFirstProfile(char **profileName);
NS_IMETHOD GetCurrentProfileDir(nsFileSpec* profileDir);
// Setters
NS_IMETHOD SetProfileDir(const char *profileName, const nsFileSpec& profileDir);
// General
NS_IMETHOD ProfileExists(const char *profileName);
// Migrate 4.x profile information
NS_IMETHOD MigrateProfileInfo();
NS_IMETHOD UpdateMozProfileRegistry();
// Profile Core supporters
NS_IMETHOD CreateNewProfile(char* data);
NS_IMETHOD RenameProfile(const char* aOldName, const char* aNewName);
NS_IMETHOD DeleteProfile(const char* aProfileName, const char *canDeleteFiles);
NS_IMETHOD GetProfileList(nsString& profileList);
NS_IMETHOD StartCommunicator(const char* aProfileName);
NS_IMETHOD GetCurrProfile(nsString& currProfile);
NS_IMETHOD MigrateProfile(const char* aProfileName);
// Cookie processing
NS_IMETHOD GetCookie(nsString& aCookie);
NS_IMETHOD ProcessPRegCookie();
NS_IMETHOD IsPregCookieSet(char **pregSet);
NS_IMETHOD ProcessPREGInfo(char* data);
// Get the count of 4x (unmigrated) profiles
NS_IMETHOD Get4xProfileCount(int *numProfiles);
NS_IMETHOD MigrateAllProfiles();
// Clone a profile with current profile info
NS_IMETHOD CloneProfile(const char* aProfileName);
};
nsProfile* nsProfile::mInstance = nsnull;
static PRInt32 g_InstanceCount = 0;
static PRInt32 g_LockCount = 0;
/*
* Constructor/Destructor
*/
nsProfile::nsProfile()
: m_reg(nsnull)
{
PR_AtomicIncrement(&g_InstanceCount);
NS_INIT_REFCNT();
}
nsProfile::~nsProfile() {
PR_AtomicDecrement(&g_InstanceCount);
mInstance = nsnull;
}
nsProfile *nsProfile::GetInstance()
{
if (mInstance == nsnull) {
mInstance = new nsProfile();
}
return mInstance;
}
/*
* nsISupports Implementation
*/
NS_IMPL_ISUPPORTS(nsProfile, kIProfileIID);
/*
* nsIProfile Implementation
*/
// Creates an instance of the mozRegistry (m_reg)
// or any other registry that would be finalized for 5.0
// Adds subtree Profiles to facilitate profile operations
NS_IMETHODIMP nsProfile::Startup(char *filename)
{
#if defined(DEBUG_profile)
printf("ProfileManager (nsProfile) : Startup : Get Registry handle\n");
#endif
nsresult rv = NS_OK;
rv = nsComponentManager::CreateInstance(kRegistryCID,
nsnull,
nsIRegistry::GetIID(),
(void **) &m_reg);
// Add the root Profiles node in the registry
if (m_reg != nsnull)
{
// Latch onto the registry object.
NS_ADDREF(m_reg);
// Open it against the input file name.
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key key;
rv = m_reg->AddSubtree(nsIRegistry::Common, "Profiles", &key);
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf("Registry : Couldn't add Profiles subtree.\n");
#endif
}
m_reg->Close();
}
else
{
#if defined(DEBUG_profile)
printf("Couldn't open registry.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry Object is NULL.\n");
#endif
return NS_ERROR_FAILURE;
}
return rv;
}
NS_IMETHODIMP nsProfile::Shutdown()
{
NS_RELEASE(m_reg);
return NS_OK;
}
/*
* Getters
*/
// Gets the profiles directory for a given profile
// Sets the given profile to be a current profile
NS_IMETHODIMP nsProfile::GetProfileDir(const char *profileName, nsFileSpec* profileDir)
{
nsresult rv = NS_OK;
#if defined(DEBUG_profile)
printf("ProfileManager : GetProfileDir\n");
#endif
// Check result.
if ( m_reg != nsnull )
{
// Open the registry
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key key;
// Get handle to subtree "Profiles"
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &key);
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key newKey;
// Get handle to <profileName> passed
rv = m_reg->GetSubtree(key, profileName, &newKey);
if (NS_SUCCEEDED(rv))
{
char* encodedProfileDir = nsnull;
// Get the value of entry "directory"
rv = m_reg->GetString( newKey, "directory", &encodedProfileDir );
if (NS_SUCCEEDED(rv))
{
char* isMigrated = nsnull;
char* orgProfileDir = nsnull;
// Use persistent classes to make the directory names XPlatform
nsInputStringStream stream(encodedProfileDir);
nsPersistentFileDescriptor descriptor;
stream >> descriptor;
*profileDir = descriptor;
PR_FREEIF(encodedProfileDir);
orgProfileDir = PL_strdup(profileDir->GetCString());
// Get the value of entry "migrated" to check the nature of the profile
m_reg->GetString( newKey, "migrated", &isMigrated);
// Set this to be a current profile only if it is a 5.0 profile
if (PL_strcmp(isMigrated, "yes") == 0)
{
rv = m_reg->SetString(key, "CurrentProfile", profileName);
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf("Profiles : Couldn't set CurrentProfile Name.\n");
#endif
}
nsFileSpec tmpFileSpec(orgProfileDir);
if (!tmpFileSpec.Exists()) {
// Get profile defaults folder..
nsIFileLocator* locator = nsnull;
rv = nsServiceManager::GetService(kFileLocatorCID, nsIFileLocator::GetIID(), (nsISupports**)&locator);
if (NS_FAILED(rv) || !locator)
return NS_ERROR_FAILURE;
nsIFileSpec* profDefaultsDir;
rv = locator->GetFileLocation(nsSpecialFileSpec::App_ProfileDefaultsFolder50, &profDefaultsDir);
if (NS_FAILED(rv) || !profDefaultsDir)
return NS_ERROR_FAILURE;
nsFileSpec defaultsDirSpec;
profDefaultsDir->GetFileSpec(&defaultsDirSpec);
NS_RELEASE(profDefaultsDir);
// Copy contents from defaults folder.
if (defaultsDirSpec.Exists())
{
defaultsDirSpec.RecursiveCopy(tmpFileSpec);
}
nsServiceManager::ReleaseService(kFileLocatorCID, locator);
}
}
}
else
{
#if defined(DEBUG_profile)
printf("Profiles : Couldn't get Profile directory name.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Profiles : Couldn't get profileName subtree.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry : Couldn't get Profiles subtree.\n");
#endif
}
m_reg->Close();
}
else
{
#if defined(DEBUG_profile)
printf("Couldn't open registry.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry Object is NULL.\n");
#endif
return NS_ERROR_FAILURE;
}
return rv;
}
// Gets the number of profiles
// Location: Common/Profiles
NS_IMETHODIMP nsProfile::GetProfileCount(int *numProfiles)
{
nsresult rv = NS_OK;
#if defined(DEBUG_profile)
printf("ProfileManager : GetProfileCount\n");
#endif
// Check result.
if ( m_reg != nsnull )
{
// Open the registry
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
// Enumerate all subkeys (immediately) under the given node.
nsIEnumerator *enumKeys;
nsIRegistry::Key key;
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &key);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->EnumerateSubtrees( key, &enumKeys );
if (NS_SUCCEEDED(rv))
{
int numKeys=0;
rv = enumKeys->First();
while( NS_SUCCEEDED( rv ) && !enumKeys->IsDone() )
{
nsISupports *base;
rv = enumKeys->CurrentItem( &base );
if (NS_SUCCEEDED(rv))
{
// Get specific interface.
nsIRegistryNode *node;
nsIID nodeIID = NS_IREGISTRYNODE_IID;
rv = base->QueryInterface( nodeIID, (void**)&node );
// Test that result.
if (NS_SUCCEEDED(rv))
{
// Get node name.
char *profile = nsnull;
char *isMigrated = nsnull;
rv = node->GetName( &profile );
if (NS_SUCCEEDED(rv) && (profile))
{
nsIRegistry::Key profKey;
rv = m_reg->GetSubtree(key, profile, &profKey);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->GetString(profKey, "migrated", &isMigrated);
if (NS_SUCCEEDED(rv) && (isMigrated))
{
if (PL_strcmp(isMigrated, "yes") == 0)
{
numKeys++;
}
nsCRT::free(isMigrated);
}
}
}
node->Release();
}
base->Release();
}
rv = enumKeys->Next();
}
*numProfiles = numKeys;
NS_RELEASE(enumKeys);
}
else
{
#if defined(DEBUG_profile)
printf("Profiles : Can't enumerate subtrees.\n" );
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry : Couldn't get Profiles subtree.\n");
#endif
}
m_reg->Close();
}
else
{
#if defined(DEBUG_profile)
printf("Couldn't open registry.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry Object is NULL.\n");
#endif
return NS_ERROR_FAILURE;
}
return rv;
}
// If only a single profile exists
// and returns the name of the single profile.
// Otherwise it returns the name of the first valid profile.
// Commonly used in picking the current profile name if it is not set.
NS_IMETHODIMP nsProfile::GetSingleProfile(char **profileName)
{
nsresult rv = NS_OK;
#if defined(DEBUG_profile)
printf("ProfileManager : GetSingleProfile\n");
#endif
// Check result.
if ( m_reg != nsnull )
{
// Open the registry
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
// Enumerate all subkeys (immediately) under the given node.
nsIEnumerator *enumKeys;
nsIRegistry::Key key;
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &key);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->EnumerateSubtrees( key, &enumKeys );
if (NS_SUCCEEDED(rv))
{
// Go to beginning.
rv = enumKeys->First();
while(NS_SUCCEEDED(rv)&& !enumKeys->IsDone() )
{
nsISupports *base;
rv = enumKeys->CurrentItem( &base );
if (NS_SUCCEEDED(rv))
{
// Get specific interface.
nsIRegistryNode *node;
nsIID nodeIID = NS_IREGISTRYNODE_IID;
rv = base->QueryInterface( nodeIID, (void**)&node );
if (NS_SUCCEEDED(rv))
{
char *isMigrated = nsnull;
nsIRegistry::Key profKey;
// Get node name.
rv = node->GetName( profileName );
// Profiles need to be migrated are not considered as valid profiles
// On finding the valid profile, breaks out of the while loop.
if (NS_SUCCEEDED(rv))
{
rv = m_reg->GetSubtree(key, *profileName, &profKey);
m_reg->GetString(profKey, "migrated", &isMigrated);
if (PL_strcmp(isMigrated, "no") == 0)
{
rv = enumKeys->Next();
continue;
}
else
{
if (NS_SUCCEEDED(rv))
{
rv = m_reg->SetString(key, "CurrentProfile", *profileName);
if (NS_SUCCEEDED(rv))
{
break;
}
else
{
#if defined(DEBUG_profile)
printf("RegistryNode : Can't set Current Profile name.\n" );
#endif
}
}
}
}
else
{
#if defined(DEBUG_profile)
printf("RegistryNode : Couldn't get the node name.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("RegistryNode : Couldn't get the interface.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Profiles : Couldn't get current enumerated item.\n");
#endif
}
rv = enumKeys->Next();
} //end while loop
NS_RELEASE(enumKeys);
}
else
{
#if defined(DEBUG_profile)
printf("Profiles : Couldn't enumerate subtrees.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry : Couldn't get Profiles subtree.\n");
#endif
}
m_reg->Close();
}
else
{
#if defined(DEBUG_profile)
printf("Couldn't open registry.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry Object is NULL.\n");
#endif
return NS_ERROR_FAILURE;
}
return rv;
}
// Returns the name of the current profile i.e., the last used profile
NS_IMETHODIMP nsProfile::GetCurrentProfile(char **profileName)
{
nsresult rv = NS_OK;
#if defined(DEBUG_profile)
printf("ProfileManager : GetCurrentProfile\n");
#endif
// Check result.
if ( m_reg != nsnull )
{
// Open the registry.
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key key;
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &key);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->GetString( key, "CurrentProfile", profileName );
// if fails to get the current profile set the value to null
if (NS_FAILED(rv))
{
profileName = '\0';
#if defined(DEBUG_profile)
printf("Profiles:Can't get Current Profile value.\n" );
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry : Couldn't get Profiles subtree.\n");
#endif
}
m_reg->Close();
}
else
{
#if defined(DEBUG_profile)
printf("Couldn't open registry.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry Object is NULL.\n");
#endif
return NS_ERROR_FAILURE;
}
return rv;
}
// Returns the name of the first profile in the Registry
// This is essentially GetSingleProfile(). Should go away.
// Check for dependencies.
NS_IMETHODIMP nsProfile::GetFirstProfile(char **profileName)
{
nsresult rv = NS_OK;
#if defined(DEBUG_profile)
printf("ProfileManager : GetFirstProfile\n");
#endif
rv = GetSingleProfile(profileName);
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf("Couldn't get the first profile.\n" );
#endif
}
return rv;
}
// Returns the name of the current profile directory
NS_IMETHODIMP nsProfile::GetCurrentProfileDir(nsFileSpec* profileDir)
{
nsresult rv = NS_OK;
#if defined(DEBUG_profile)
printf("ProfileManager : GetCurrentProfileDir\n");
#endif
char *profileName = nsnull;
rv = GetCurrentProfile(&profileName);
if (NS_SUCCEEDED(rv))
{
rv = GetProfileDir(profileName, profileDir);
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf("Couldn't get the profile dir.\n" );
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Couldn't get the current profile.\n" );
#endif
}
if (profileName) {
PR_DELETE(profileName);
}
return rv;
}
/*
* Setters
*/
// Sets the current profile directory
NS_IMETHODIMP nsProfile::SetProfileDir(const char *profileName, const nsFileSpec& profileDir)
{
nsresult rv = NS_OK;
#if defined(DEBUG_profile)
printf("ProfileManager : SetProfileDir\n");
printf("profileName : %s ", profileName);
printf("profileDir : %s\n", profileDir.GetCString());
#endif
// Check result.
if (m_reg != nsnull)
{
// Open the registry.
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key key;
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &key);
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key newKey;
rv = m_reg->AddSubtree(key, profileName, &newKey);
if (NS_SUCCEEDED(rv))
{
// Create a tmp Filespec and create a directory if required
nsFileSpec tmpDir(profileDir);
if (!profileDir.Exists())
{
// nsPersistentFileDescriptor requires an existing
// object. Make it first.
tmpDir.CreateDirectory();
}
// Persistency
nsPersistentFileDescriptor descriptor(profileDir);
char* profileDirString = nsnull;
profileDirString = nsCRT::strdup(profileDir.GetCString());
nsOutputStringStream stream(profileDirString);
stream << descriptor;
// Set the entry "directory" for this profile
if (profileDirString && *profileDirString)
{
rv = m_reg->SetString(newKey, "directory", profileDirString);
CreateUserDirectories(tmpDir);
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf("Couldn't set directory property.\n" );
#endif
}
// A 5.0 profile needs no migration.
// Hence setting migrated flag to "yes"
// Need to change this logic to "migrate" = true/false.
rv = m_reg->SetString( newKey, "migrated", "yes");
}
else
{
#if defined(DEBUG_profile)
printf("NULL value received for directory name.\n" );
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Profiles : Could not add profile name subtree.\n" );
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry : Couldn't get Profiles subtree.\n");
#endif
}
rv = m_reg->SetString(key, "CurrentProfile", profileName);
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf("Couldn't set CurrentProfile name.\n" );
#endif
}
m_reg->Close();
}
else
{
#if defined(DEBUG_profile)
printf("Couldn't open registry.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry Object is NULL.\n");
#endif
return NS_ERROR_FAILURE;
}
return rv;
}
// Creates a new profile
NS_IMETHODIMP nsProfile::CreateNewProfile(char* charData)
{
nsresult rv = NS_OK;
#if defined(DEBUG_profile)
printf("ProfileManager : CreateNewProfile\n");
printf("ProfileManagerData*** : %s\n", charData);
#endif
nsIFileLocator* locator = nsnull;
rv = nsServiceManager::GetService(kFileLocatorCID, nsIFileLocator::GetIID(), (nsISupports**)&locator);
if (NS_FAILED(rv) || !locator)
return NS_ERROR_FAILURE;
nsString data(charData);
// Set the gathered info into an array
SetDataArray(data);
char* dirName = GetValue("ProfileDir");
char* unescapedProfileName = GetValue("ProfileName");
if (!unescapedProfileName || !*unescapedProfileName)
return NS_ERROR_FAILURE;
// Escape profile name to create a valid direrctory,
// if directory value is not provided
char* profileName = nsEscape(unescapedProfileName, url_Path); // temp hack
nsFileSpec dirSpec(dirName);
if (!dirName || !*dirName)
{
// They didn't type a directory path...
// Get current profile, make the new one a sibling...
nsIFileSpec* horribleCOMDirSpecThing;
rv = locator->GetFileLocation(nsSpecialFileSpec::App_DefaultUserProfileRoot50, &horribleCOMDirSpecThing);
if (NS_FAILED(rv) || !horribleCOMDirSpecThing)
return NS_ERROR_FAILURE;
//Append profile name to form a directory name
horribleCOMDirSpecThing->GetFileSpec(&dirSpec);
NS_RELEASE(horribleCOMDirSpecThing);
//dirSpec.SetLeafName(profileName);
//dirSpec += profileName;
}
#if defined(DEBUG_profile)
printf("before SetProfileDir\n");
#endif
if (!dirSpec.Exists())
dirSpec.CreateDirectory();
dirSpec += profileName;
// Set the directory value and add the entry to the registry tree.
// Creates required user directories.
rv = SetProfileDir(unescapedProfileName, dirSpec);
PR_DELETE(unescapedProfileName);
#if defined(DEBUG_profile)
printf("after SetProfileDir\n");
#endif
if (NS_FAILED(rv))
return rv;
// Get profile defaults folder..
nsIFileSpec* profDefaultsDir;
rv = locator->GetFileLocation(nsSpecialFileSpec::App_ProfileDefaultsFolder50, &profDefaultsDir);
if (NS_FAILED(rv) || !profDefaultsDir)
return NS_ERROR_FAILURE;
nsFileSpec defaultsDirSpec;
profDefaultsDir->GetFileSpec(&defaultsDirSpec);
NS_RELEASE(profDefaultsDir);
// Copy contents from defaults folder.
if (defaultsDirSpec.Exists())
{
defaultsDirSpec.RecursiveCopy(dirSpec);
}
nsServiceManager::ReleaseService(kFileLocatorCID, locator);
if (dirName)
{
PR_DELETE(dirName);
}
delete [] profileName;
return NS_OK;
}
// Create required user directories like Mial, News, Cache etc.
void nsProfile::CreateUserDirectories(const nsFileSpec& profileDir)
{
#if defined(DEBUG_profile)
printf("ProfileManager : CreateUserDirectories\n");
#endif
nsFileSpec tmpDir;
tmpDir = profileDir;
tmpDir += "News";
if (!tmpDir.Exists())
{
tmpDir.CreateDirectory();
}
tmpDir = profileDir;
tmpDir += "Mail";
if (!tmpDir.Exists())
{
tmpDir.CreateDirectory();
}
tmpDir = profileDir;
tmpDir += "Cache";
if (!tmpDir.Exists())
{
tmpDir.CreateDirectory();
}
}
// Delete all user directories associated with the a profile
// A FileSpec of the profile's directory is taken as input param
// Probably we should take profile name as param....?
void nsProfile::DeleteUserDirectories(const nsFileSpec& profileDir)
{
#if defined(DEBUG_profile)
printf("ProfileManager : DeleteUserDirectories\n");
#endif
if (profileDir.Exists())
{
profileDir.Delete(PR_TRUE);
}
}
// Set the data stream into an array
void nsProfile::SetDataArray(nsString data)
{
#if defined(DEBUG_profile)
printf("ProfileManager : Setting new profile data\n");
printf("SetDataArray data : %s\n", data.ToNewCString());
#endif
int index = 0;
char *newStr=nsnull;
char *tokstr = data.ToNewCString();
char *token = nsCRT::strtok(tokstr, "%", &newStr);
#if defined(DEBUG_profile)
printf("before while loop\n");
#endif
while (token)
{
#if defined(DEBUG_profile)
printf("subTok : %s\n", token);
#endif
PL_strcpy(gNewProfileData[index], token);
index++;
g_Count = index;
token = nsCRT::strtok(newStr, "%", &newStr);
}
delete[] tokstr;
#if defined(DEBUG_profile)
printf("after while loop\n");
#endif
}
//Get the value associated with the name from Data Array
// i.e., generated from the data passed by the JS reflection
// request to create a new profile (CreateProfile Wizard).
char* nsProfile::GetValue(char *name)
{
int nameLength;
char* value;
value = (char *) PR_Malloc(sizeof(char) * _MAX_LENGTH);
for (int i = 0; i < g_Count; i=i+1)
{
if (gNewProfileData[i])
{
nameLength = PL_strlen(name);
if (PL_strncmp(name, gNewProfileData[i], nameLength) == 0)
{
char* equalsPosition = PL_strchr(gNewProfileData[i], '=');
if (equalsPosition)
{
PL_strcpy(value, 1 + equalsPosition);
return value;
}
}
}
}
#if defined(DEBUG_profile)
printf("after for loop\n");
#endif
return nsnull;
}
// Rename a old profile to new profile.
// Need to add ProfileExists() routine to avoid the illegal rename operation
// Copies all the keys from old profile to new profile.
// Deletes the old profile from the registry
NS_IMETHODIMP nsProfile::RenameProfile(const char* oldName, const char* newName)
{
nsresult rv = NS_OK;
#if defined(DEBUG_profile)
printf("ProfileManager : Renaming profile %s to %s \n", oldName, newName);
#endif
rv = ProfileExists(newName);
// That profile already exists...
if (NS_SUCCEEDED(rv))
{
printf("ProfileManager : Rename Operation failed : Profile exists. Provide a different new name for profile.\n");
return NS_ERROR_FAILURE;
}
char *currProfile = nsnull;
GetCurrentProfile(&currProfile);
// If renaming the current profile set the renameCurrProfile flag to true
// By default the flag is set to false.
if (currProfile)
{
if (PL_strcmp(oldName, currProfile) == 0)
{
renameCurrProfile = PR_TRUE;
#if defined(DEBUG_profile)
printf("ProfileManager : Renaming the current profile\n");
#endif
}
}
// Copy reg keys
CopyRegKey(oldName, newName);
// Delete old profile entry
DeleteProfile(oldName, "false");
// If we renamed current profile, the new profile will be the current profile
if (renameCurrProfile)
{
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key profileRootKey;
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &profileRootKey);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->SetString(profileRootKey, "CurrentProfile", newName);
}
m_reg->Close();
}
renameCurrProfile = PR_FALSE;
}
return rv;
}
// Copy old profile entries to the new profile
// In the process creates new profile subtree.
nsresult nsProfile::CopyRegKey(const char *oldProfile, const char *newProfile)
{
nsIEnumerator *enumKeys;
nsIRegistry::Key sourceKey, destKey, profileRootKey;
nsresult rv = m_reg->OpenDefault();
// Need to add else statements to print the error stages.
if (NS_SUCCEEDED(rv))
{
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &profileRootKey);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->GetSubtree(profileRootKey, (char *) oldProfile, &sourceKey);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->AddSubtree(profileRootKey, (char *) newProfile, &destKey);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->EnumerateValues(sourceKey, &enumKeys );
if (NS_SUCCEEDED(rv)) {
rv = enumKeys->First();
// Enumerate subkeys till done.
while( NS_SUCCEEDED( rv ) && !enumKeys->IsDone() )
{
nsISupports *base;
rv = enumKeys->CurrentItem( &base );
// Test result.
if (NS_SUCCEEDED(rv))
{
// Get specific interface.
nsIRegistryNode *value;
nsIID valueIID = NS_IREGISTRYVALUE_IID;
rv = base->QueryInterface( valueIID, (void**)&value );
// Test that result.
if (NS_SUCCEEDED(rv))
{
// Get node name.
char *entryName;
char *entryValue;
rv = value->GetName( &entryName );
if (NS_SUCCEEDED(rv))
{
rv = m_reg->GetString( sourceKey, entryName, &entryValue);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->SetString(destKey, entryName, entryValue);
}
}
if (entryName)
{
PR_DELETE(entryName);
}
if (entryValue)
{
PR_DELETE(entryValue);
}
}
}
rv = enumKeys->Next();
}
NS_RELEASE(enumKeys);
}
}
}
}
m_reg->Close();
}
return rv;
}
// Delete a profile from the registry
// Not deleting the directories on the harddisk yet.
// 4.x kind of confirmation need to be implemented yet
NS_IMETHODIMP nsProfile::DeleteProfile(const char* profileName, const char* canDeleteFiles)
{
nsresult rv = NS_OK;
#if defined(DEBUG_profile)
printf("ProfileManager : DeleteProfile\n");
#endif
nsFileSpec profileDirSpec;
GetProfileDir(profileName, &profileDirSpec);
// To be more uniform need to change the arragement
// of the following with NS_SUCCEEDED()
// Check result.
if ( m_reg != nsnull )
{
// Open the registry.
rv = m_reg->OpenDefault();
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf("Error opening Registry.\n" );
#endif
return rv;
}
#if defined(DEBUG_profile)
printf("Registry opened OK.\n" );
#endif
nsIRegistry::Key key;
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &key);
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf("Can't obtain subtree Profiles.\n" );
#endif
return rv;
}
// Remove the subtree from the registry.
rv = m_reg->RemoveSubtree(key, profileName);
if (NS_FAILED(rv))
return rv;
else
{
#if defined(DEBUG_profile)
printf("DeleteProfile : deleted profile -> %s <-\n", profileName);
#endif
}
// May need to delete directories, but not so directly.
// DeleteUserDirectories(profileDirSpec);
// Take care of the current profile, if the profile
// just deleted was a current profile.
if (!renameCurrProfile)
{
char *oldCurrProfile = nsnull;
char *newCurrProfile = nsnull;
GetCurrentProfile(&oldCurrProfile);
if (PL_strcmp(profileName, oldCurrProfile) == 0)
{
GetFirstProfile(&newCurrProfile);
#if defined(DEBUG_profile)
printf("DeleteProfile : Old Current profile -> %s <-\n", oldCurrProfile);
printf("DeleteProfile : New Current profile -> %s <-\n", newCurrProfile);
#endif
rv = m_reg->SetString(key, "CurrentProfile", newCurrProfile);
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf("Did not take nsnull successfully\n");
#endif
}
}
}
m_reg->Close();
}
// If user asks for it, delete profile directory
if (PL_strcmp(canDeleteFiles, "true") == 0)
{
DeleteUserDirectories(profileDirSpec);
}
return rv;
}
// Get all profiles fro the registry's Profiles subtree
// All the profiles that need to be migrated will be appended
// with the text " - migrate" (e.g. <unmigratedProfileName> - migrate).
// Need to change this lotic to have True/False to represent the
// migration state.
// Names are stored in the global array gProfiles[].
void nsProfile::GetAllProfiles()
{
nsresult rv = NS_OK;
#if defined(DEBUG_profile)
printf("ProfileManager : GetAllProfiles\n");
#endif
int index = 0;
// Check result.
if ( m_reg != nsnull )
{
// Open the registry.
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
// Enumerate all subkeys (immediately) under the given node.
nsIEnumerator *enumKeys;
nsIRegistry::Key key;
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &key);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->EnumerateSubtrees( key, &enumKeys );
if (NS_SUCCEEDED(rv))
{
rv = enumKeys->First();
// Enumerate subkeys till done.
while( NS_SUCCEEDED( rv ) && !enumKeys->IsDone() )
{
nsISupports *base;
rv = enumKeys->CurrentItem( &base );
if (NS_SUCCEEDED(rv))
{
// Get specific interface.
nsIRegistryNode *node;
nsIID nodeIID = NS_IREGISTRYNODE_IID;
rv = base->QueryInterface( nodeIID, (void**)&node );
// Test that result.
if (NS_SUCCEEDED(rv))
{
// Get node name.
char *profile = nsnull;
char *isMigrated = nsnull;
rv = node->GetName( &profile );
if (NS_SUCCEEDED(rv) && (profile))
{
nsIRegistry::Key profKey;
rv = m_reg->GetSubtree(key, profile, &profKey);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->GetString(profKey, "migrated", &isMigrated);
if (NS_SUCCEEDED(rv) && (isMigrated))
{
if (PL_strcmp(isMigrated, "no") == 0)
{
PL_strcpy(gProfiles[index], profile);
PL_strcat(gProfiles[index], " - migrate");
}
else
{
PL_strcpy(gProfiles[index], profile);
}
#if defined(DEBUG_profile)
printf("proflie%d = %s\n", index, gProfiles[index]);
#endif
}
}
}
node->Release();
}
base->Release();
}
rv = enumKeys->Next();
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf( "Error advancing enumerator, rv=0x%08X\n", (int)rv );
#endif
}
index++;
}
g_numProfiles = index;
NS_RELEASE(enumKeys);
}
}
}
m_reg->Close();
}
}
// Get the list of all profiles
// Populate the input param.
// Essentially calls GetAllProfiles to fill gProfiles[].
// This method is written to support the core service
// call to get the names all profiles.
NS_IMETHODIMP nsProfile::GetProfileList(nsString& profileList)
{
#if defined(DEBUG_profile)
printf("Inside GetProfileList routine.\n" );
#endif
GetAllProfiles();
for (int i=0; i < g_numProfiles; i++)
{
if (i != 0)
{
profileList += ",";
}
profileList += gProfiles[i];
}
return NS_OK;
}
// Start Communicator with a profile of user's choice
// Prefs and FileLocation services are used here.
// FileLocation service to make ir forget about the global profile dir it had.
// Prefs service to kick off the startup to start the app with new profile's prefs.
NS_IMETHODIMP nsProfile::StartCommunicator(const char* profileName)
{
nsresult rv = NS_OK;
#if defined(DEBUG_profile)
printf("ProfileManager : Start AppRunner\n");
#endif
nsIPref *prefs = nsnull;
/*
* Need to load new profile prefs.
*/
rv = nsServiceManager::GetService(kPrefCID,
nsIPref::GetIID(),
(nsISupports **)&prefs);
// First, set the profile to be the current profile.
// So that FileLocation services grabs right directory when it needs to.
if (NS_SUCCEEDED(rv))
{
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key profileRootKey;
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &profileRootKey);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->SetString(profileRootKey, "CurrentProfile", profileName);
}
m_reg->Close();
}
nsIFileLocator* locator = nsnull;
rv = nsServiceManager::GetService(kFileLocatorCID, nsIFileLocator::GetIID(), (nsISupports**)&locator);
if (locator)
{
rv = locator->ForgetProfileDir();
nsServiceManager::ReleaseService(kFileLocatorCID, locator);
}
if (NS_SUCCEEDED(rv))
{
prefs->StartUp();
}
// Release prefs service.
if (prefs) {
nsServiceManager::ReleaseService(kPrefCID, prefs);
}
}
return rv;
}
// Get Current Profile (Support for Core service call).
// Populate the input param with current profile.
NS_IMETHODIMP nsProfile::GetCurrProfile(nsString& currProfile)
{
#if defined(DEBUG_profile)
printf("Inside GetCurrentProfile (JSReflec) routine.\n" );
#endif
char *localCurProf = nsnull;
GetCurrentProfile(&localCurProf);
currProfile += localCurProf;
return NS_OK;
}
// Migrate profile information from the 4x registry to 5x registry.
NS_IMETHODIMP nsProfile::MigrateProfileInfo()
{
nsresult rv = NS_OK;
#if defined(XP_PC) || defined(XP_MAC)
#if defined(DEBUG_profile)
printf("Entered MigrateProfileInfo.\n");
#endif
char oldRegFile[_MAX_LENGTH] = {'\0'};
// Check result.
if ( m_reg != nsnull )
{
/***********************
Get the right registry file. Ideally from File Locations.
File Locations is yet to implement this service.
nsIFileLocator* locator = nsnull;
nsFileSpec oldAppRegistry;
rv = nsServiceManager::GetService(kFileLocatorCID, nsIFileLocator::GetIID(), (nsISupports**)&locator);
if (NS_FAILED(rv) || !locator)
return NS_ERROR_FAILURE;
// Get current profile, make the new one a sibling...
rv = locator->GetFileLocation(nsSpecialFileSpec::App_Registry50, &oldAppRegistry);
nsServiceManager::ReleaseService(kFileLocatorCID, locator);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
oldAppRegistry.SetLeafName(OLD_WINREG);
rv = m_reg->Open(oldAppRegistry.GetCString());
************************/
#ifdef XP_PC
// Registry file has been traditionally stored in the windows directory (XP_PC).
nsSpecialSystemDirectory systemDir(nsSpecialSystemDirectory::Win_WindowsDirectory);
// Append the name of the old registry to the path obtained.
PL_strcpy(oldRegFile, systemDir.GetNativePathCString());
PL_strcat(oldRegFile, oldWinReg);
#endif
#ifdef XP_MAC
nsSpecialSystemDirectory *regLocation = NULL;
regLocation = new nsSpecialSystemDirectory(nsSpecialSystemDirectory::Mac_SystemDirectory);
// Append the name of the old registry to the path obtained.
*regLocation += "Preferences";
*regLocation += oldMacReg;
// WARNING
// regNSPRPath and regFile need to have the same scope
// since the regFile will point to data in regNSPRPath
nsNSPRPath regNSPRPath(*regLocation);
PL_strcpy(oldRegFile, (const char *) regNSPRPath);
#endif
rv = m_reg->Open(oldRegFile);
// Enumerate 4x tree and create an array of that information.
if (NS_SUCCEEDED(rv))
{
// Enumerate all subkeys (immediately) under the given node.
nsIEnumerator *enumKeys;
if (NS_SUCCEEDED(rv))
{
rv = m_reg->EnumerateSubtrees(nsIRegistry::Users, &enumKeys );
if (NS_SUCCEEDED(rv))
{
rv = enumKeys->First();
// Enumerate subkeys till done.
while( NS_SUCCEEDED( rv ) && !enumKeys->IsDone() )
{
nsISupports *base;
rv = enumKeys->CurrentItem( &base );
if (NS_SUCCEEDED(rv))
{
// Get specific interface.
nsIRegistryNode *node;
nsIID nodeIID = NS_IREGISTRYNODE_IID;
rv = base->QueryInterface( nodeIID, (void**)&node );
// Get Node details.
if (NS_SUCCEEDED(rv))
{
// Get node name.
char *profile = nsnull;
rv = node->GetName( &profile );
#if defined(DEBUG_profile)
printf("oldProflie = %s\n", profile);
#endif
nsIRegistry::Key key;
rv = m_reg->GetSubtree(nsIRegistry::Users, profile, &key);
if (NS_SUCCEEDED(rv))
{
PL_strcpy(gOldProfiles[g_numOldProfiles], nsUnescape(profile));
}
char *profLoc = nsnull;
rv = m_reg->GetString( key, "ProfileLocation", &profLoc);
#if defined(DEBUG_profile)
printf("oldProflie Location = %s\n", profLoc);
#endif
if (NS_SUCCEEDED(rv))
{
PL_strcpy(gOldProfLocations[g_numOldProfiles], profLoc);
g_numOldProfiles++;
}
PR_FREEIF(profile);
PR_FREEIF(profLoc);
}
}
rv = enumKeys->Next();
}
NS_RELEASE(enumKeys);
}
}
m_reg->Close();
if (g_numOldProfiles > 0)
{
UpdateMozProfileRegistry();
}
}
}
#endif
return rv;
}
// Update the mozregistry with the 4x profile names
// and thier locations. Entry "migrated" is set to "no"
// to differentiate these profiles from 5x profiles.
// gOldProfiles, gOldProfLocations carried info about
// profile names and locations respectively. They are
// populated inthe routine MigrateProfileInfo()
NS_IMETHODIMP nsProfile::UpdateMozProfileRegistry()
{
nsresult rv = NS_OK;
#if defined(XP_PC) || defined(XP_MAC)
#if defined(DEBUG_profile)
printf("Entered UpdateMozProfileRegistry.\n");
#endif
for (int index = 0; index < g_numOldProfiles; index++)
{
// Check result.
if (m_reg != nsnull)
{
// Open the registry file.
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key key;
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &key);
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key newKey;
rv = m_reg->SetString(key, "NeedMigration", "true");
rv = m_reg->GetSubtree(key, gOldProfiles[index], &newKey);
if (NS_FAILED(rv))
{
rv = m_reg->AddSubtree(key, gOldProfiles[index], &newKey);
if (NS_SUCCEEDED(rv))
{
nsFileSpec profileDir(gOldProfLocations[index]);
nsPersistentFileDescriptor descriptor(profileDir);
char* profileDirString = nsnull;
nsOutputStringStream stream(profileDirString);
stream << descriptor;
if (profileDirString && *profileDirString)
{
rv = m_reg->SetString(newKey, "directory", profileDirString);
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf("Couldn't set directory property.\n" );
#endif
}
rv = m_reg->SetString(newKey, "migrated", "no");
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf("Couldn't add migrate flag.\n" );
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("NULL value received for directory name.\n" );
#endif
}
delete [] profileDirString;
}
else
{
#if defined(DEBUG_profile)
printf("Profiles : Could not add profile subtree.\n" );
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Profiles : Profile name subtree already exists.\n" );
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry : Couldn't get Profiles subtree.\n");
#endif
}
m_reg->Close();
}
else
{
#if defined(DEBUG_profile)
printf("Couldn't open registry.\n");
#endif
}
}
}
#endif
return rv;
}
// Migrate a selected profile
// Set the profile to the current profile....debatable.
// Calls PrefMigration service to do the Copy and Diverge
// of 4x Profile information
NS_IMETHODIMP nsProfile::MigrateProfile(const char* profileName)
{
nsresult rv = NS_OK;
#if defined(XP_PC) || defined(XP_MAC)
#if defined(DEBUG_profile)
printf("Inside Migrate Profile routine.\n" );
#endif
nsFileSpec oldProfDir;
nsFileSpec newProfDir;
GetProfileDir(profileName, &oldProfDir);
// Create new profile dir path
nsIFileLocator* locator = nsnull;
// Get the new directory path the migrated profile to reside.
rv = nsServiceManager::GetService(kFileLocatorCID, nsIFileLocator::GetIID(), (nsISupports**)&locator);
if (NS_FAILED(rv) || !locator)
{
return NS_ERROR_FAILURE;
}
// Get current profile, make the new one a sibling...
nsIFileSpec* newSpec = NS_LocateFileOrDirectory(
nsSpecialFileSpec::App_DefaultUserProfileRoot50);
if (!newSpec)
return NS_ERROR_FAILURE;
newSpec->GetFileSpec(&newProfDir);
NS_RELEASE(newSpec);
newProfDir += profileName;
// Call migration service to do the work.
nsIPrefMigration *pPrefMigrator = nsnull;
rv = nsComponentManager::CreateInstance(kPrefMigration_CID,
nsnull,
kIPrefMigration_IID,
(void**) &pPrefMigrator);
if (NS_SUCCEEDED(rv))
{
pPrefMigrator->ProcessPrefs((char *)oldProfDir.GetCString(),
(char *)newProfDir.GetCString(),
&rv);
}
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
//unmark migrate flag
if (NS_SUCCEEDED(rv))
{
// Check result.
if ( m_reg != nsnull )
{
// Open the registry.
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key key;
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &key);
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key newKey;
rv = m_reg->GetSubtree(key, profileName, &newKey);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->SetString( newKey, "migrated", "yes");
if (NS_SUCCEEDED(rv))
{
rv = m_reg->SetString(key, "CurrentProfile", profileName);
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf("Profiles : Couldn't set CurrentProfile Name.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Profiles : Couldn't set migrate flag.\n");
#endif
}
SetProfileDir(profileName, newProfDir);
}
else
{
#if defined(DEBUG_profile)
printf("Profiles : Couldn't get profileName subtree.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry : Couldn't get Profiles subtree.\n");
#endif
}
m_reg->Close();
}
else
{
#if defined(DEBUG_profile)
printf("Couldn't open registry.\n");
#endif
}
}
}
#endif
return rv;
}
NS_IMETHODIMP nsProfile::GetCookie(nsString& aCookie)
{
#ifndef NECKO
nsINetService *service;
nsIURI *aURL;
nsresult rv = NS_NewURL(&aURL, PREG_URL);
if (NS_FAILED(rv)) return rv;
nsresult res = nsServiceManager::GetService(kNetServiceCID,
kINetServiceIID,
(nsISupports **)&service);
if ((NS_OK == res) && (nsnull != service) && (nsnull != aURL)) {
res = service->GetCookieString(aURL, aCookie);
NS_RELEASE(service);
}
return res;
#else
// XXX NECKO we need to use the cookie module for this info instead of
// XXX the IOService
return NS_ERROR_NOT_IMPLEMENTED;
#endif // NECKO
}
NS_IMETHODIMP nsProfile::ProcessPRegCookie()
{
nsresult rv = NS_OK;
nsString aCookie;
GetCookie(aCookie);
rv = ProcessPREGInfo(aCookie.ToNewCString());
return rv;
}
NS_IMETHODIMP nsProfile::ProcessPREGInfo(char* data)
{
nsresult rv = NS_OK;
nsString aCookie(data);
char *pregCookie = nsnull;
char *profileName = nsnull;
char *service_denial = nsnull;
if ( (aCookie.ToNewCString()) != nsnull )
{
pregCookie = PL_strstr(aCookie.ToNewCString(), PREG_COOKIE);
//In the original scenario you must UnEscape the string
//PL_strstr(nsUnescape(uregCookie),PREG_USERNAME);
if (pregCookie)
{
profileName = PL_strstr(pregCookie, PREG_USERNAME);
service_denial = PL_strstr(pregCookie, PREG_DENIAL);
}
}
else
{
// cookie information is not available
return NS_ERROR_FAILURE;
}
nsAutoString pName;
nsAutoString serviceState;
if (profileName)
pName.SetString(profileName);
if (service_denial)
serviceState.SetString(service_denial);
int profileNameIndex, delimIndex;
int serviceIndex;
nsString userProfileName, userServiceDenial;
if (pName.Length())
{
profileNameIndex = pName.Find("=", 0);
delimIndex = pName.Find("[-]", profileNameIndex-1);
pName.Mid(userProfileName, profileNameIndex+1,delimIndex-(profileNameIndex+1));
printf("\nProfiles : PREG Cookie user profile name = %s\n", userProfileName.ToNewCString());
}
if (serviceState.Length())
{
serviceIndex = serviceState.Find("=", 0);
delimIndex = serviceState.Find("[-]", serviceIndex-1);
serviceState.Mid(userServiceDenial, serviceIndex+1,delimIndex-(serviceIndex+1));
printf("\nProfiles : PREG Cookie netcenter service option = %s\n", userServiceDenial.ToNewCString());
}
// User didn't provide any information.
// No Netcenter info is available.
// User will hit the Preg info screens on the next run.
if ((userProfileName.mLength == 0) && (userServiceDenial.mLength == 0))
return NS_ERROR_FAILURE;
// If user denies registration, ignore the information entered.
if (userServiceDenial.mLength > 0)
userProfileName.SetString("");
char *curProfile = nsnull;
rv = GetCurrentProfile(&curProfile);
if (NS_SUCCEEDED(rv))
{
if (userProfileName.mLength > 0)
rv = RenameProfile(curProfile, userProfileName.ToNewCString());
if (NS_SUCCEEDED(rv))
{
// Check result.
if (m_reg != nsnull)
{
// Open the registry.
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key key;
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &key);
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key newKey;
if (userProfileName.mLength > 0)
{
rv = m_reg->GetSubtree(key, userProfileName.ToNewCString(), &newKey);
if (NS_SUCCEEDED(rv))
{
// Register new info
rv = m_reg->SetString(newKey, "NCProfileName", userProfileName.ToNewCString());
}
else
{
#if defined(DEBUG_profile)
printf("Profiles : Could not set NetCenter properties.\n" );
#endif
}
rv = m_reg->SetString(key, "CurrentProfile", userProfileName.ToNewCString());
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf("Couldn't set CurrentProfile name.\n" );
#endif
}
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry : Couldn't get Profiles subtree.\n");
#endif
}
if (userServiceDenial.mLength > 0)
rv = m_reg->SetString(key, "NCServiceDenial", userServiceDenial.ToNewCString());
rv = m_reg->SetString(key, "HavePregInfo", "true");
if (NS_FAILED(rv))
{
#if defined(DEBUG_profile)
printf("Couldn't set Preg info flag.\n" );
#endif
}
m_reg->Close();
}
else
{
#if defined(DEBUG_profile)
printf("Couldn't open registry.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry Object is NULL.\n");
#endif
return NS_ERROR_FAILURE;
}
}
}
return rv;
}
NS_IMETHODIMP nsProfile::IsPregCookieSet(char **pregSet)
{
nsresult rv = NS_OK;
// Check result.
if (m_reg != nsnull)
{
// Open the registry.
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key key;
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &key);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->GetString(key, "HavePregInfo", pregSet);
}
else
{
#if defined(DEBUG_profile)
printf("Registry : Couldn't get Profiles subtree.\n");
#endif
}
m_reg->Close();
}
else
{
#if defined(DEBUG_profile)
printf("Couldn't open registry.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry Object is NULL.\n");
#endif
return NS_ERROR_FAILURE;
}
return rv;
}
NS_IMETHODIMP nsProfile::ProfileExists(const char *profileName)
{
nsresult rv = NS_OK;
// Check result.
if (m_reg != nsnull)
{
// Open the registry.
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key key;
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &key);
if (NS_SUCCEEDED(rv))
{
nsIRegistry::Key newKey;
// Get handle to <profileName> passed
rv = m_reg->GetSubtree(key, profileName, &newKey);
}
else
{
#if defined(DEBUG_profile)
printf("Registry : Couldn't get Profiles subtree.\n");
#endif
}
m_reg->Close();
}
else
{
#if defined(DEBUG_profile)
printf("Couldn't open registry.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry Object is NULL.\n");
#endif
return NS_ERROR_FAILURE;
}
return rv;
}
// Gets the number of unmigrated 4x profiles
// Location: Common/Profiles
NS_IMETHODIMP nsProfile::Get4xProfileCount(int *numProfiles)
{
nsresult rv = NS_OK;
#if defined(DEBUG_profile)
printf("ProfileManager : Get4xProfileCount\n");
#endif
// Check result.
if ( m_reg != nsnull )
{
// Open the registry
rv = m_reg->OpenDefault();
if (NS_SUCCEEDED(rv))
{
// Enumerate all subkeys (immediately) under the given node.
nsIEnumerator *enumKeys;
nsIRegistry::Key key;
rv = m_reg->GetSubtree(nsIRegistry::Common, "Profiles", &key);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->EnumerateSubtrees( key, &enumKeys );
if (NS_SUCCEEDED(rv))
{
int numKeys=0;
rv = enumKeys->First();
while( NS_SUCCEEDED( rv ) && !enumKeys->IsDone() )
{
nsISupports *base;
rv = enumKeys->CurrentItem( &base );
if (NS_SUCCEEDED(rv))
{
// Get specific interface.
nsIRegistryNode *node;
nsIID nodeIID = NS_IREGISTRYNODE_IID;
rv = base->QueryInterface( nodeIID, (void**)&node );
// Test that result.
if (NS_SUCCEEDED(rv))
{
// Get node name.
char *profile = nsnull;
char *isMigrated = nsnull;
rv = node->GetName( &profile );
if (NS_SUCCEEDED(rv) && (profile))
{
nsIRegistry::Key profKey;
rv = m_reg->GetSubtree(key, profile, &profKey);
if (NS_SUCCEEDED(rv))
{
rv = m_reg->GetString(profKey, "migrated", &isMigrated);
if (NS_SUCCEEDED(rv) && (isMigrated))
{
if (PL_strcmp(isMigrated, "no") == 0)
{
numKeys++;
}
}
}
}
node->Release();
}
base->Release();
}
rv = enumKeys->Next();
}
*numProfiles = numKeys;
NS_RELEASE(enumKeys);
}
else
{
#if defined(DEBUG_profile)
printf("Profiles : Can't enumerate subtrees.\n" );
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry : Couldn't get Profiles subtree.\n");
#endif
}
m_reg->Close();
}
else
{
#if defined(DEBUG_profile)
printf("Couldn't open registry.\n");
#endif
}
}
else
{
#if defined(DEBUG_profile)
printf("Registry Object is NULL.\n");
#endif
return NS_ERROR_FAILURE;
}
return rv;
}
// Migrates all unmigrated profiles
NS_IMETHODIMP nsProfile::MigrateAllProfiles()
{
nsresult rv = NS_OK;
#if defined(XP_PC) || defined(XP_MAC)
for (int i=0; i < g_numOldProfiles; i++)
{
rv = MigrateProfile(gOldProfiles[i]);
}
#endif
return NS_OK;
}
NS_IMETHODIMP nsProfile::CloneProfile(const char* newProfile)
{
nsresult rv = NS_OK;
#if defined(DEBUG_profile)
printf("ProfileManager : CloneProfile\n");
#endif
nsFileSpec currProfileDir;
nsFileSpec newProfileDir;
GetCurrentProfileDir(&currProfileDir);
if (currProfileDir.Exists())
{
nsIFileLocator* locator = nsnull;
rv = nsServiceManager::GetService(kFileLocatorCID, nsIFileLocator::GetIID(), (nsISupports**)&locator);
if (NS_FAILED(rv) || !locator)
return NS_ERROR_FAILURE;
nsIFileSpec* dirSpec;
rv = locator->GetFileLocation(nsSpecialFileSpec::App_DefaultUserProfileRoot50, &dirSpec);
if (NS_FAILED(rv) || !dirSpec)
return NS_ERROR_FAILURE;
//Append profile name to form a directory name
dirSpec->GetFileSpec(&newProfileDir);
NS_RELEASE(dirSpec);
newProfileDir += newProfile;
currProfileDir.RecursiveCopy(newProfileDir);
rv = SetProfileDir(newProfile, newProfileDir);
}
#if defined(DEBUG_profile)
if (NS_SUCCEEDED(rv))
printf("ProfileManager : Cloned CurrentProfile to new Profile ->%s<-\n", newProfile);
#endif
return rv;
}
/***************************************************************************************/
/*********** PROFILE FACTORY ************/
/***************************************************************************************/
// Factory
class nsProfileFactory: public nsIFactory {
NS_DECL_ISUPPORTS
nsProfileFactory() {
NS_INIT_REFCNT();
PR_AtomicIncrement(&g_InstanceCount);
}
virtual ~nsProfileFactory() {
PR_AtomicDecrement(&g_InstanceCount);
}
NS_IMETHOD CreateInstance(nsISupports *aDelegate,
const nsIID &aIID,
void **aResult);
NS_IMETHOD LockFactory(PRBool aLock) {
if (aLock) {
PR_AtomicIncrement(&g_LockCount);
} else {
PR_AtomicDecrement(&g_LockCount);
}
return NS_OK;
};
};
NS_IMPL_ISUPPORTS(nsProfileFactory, nsIFactory::GetIID());
nsresult nsProfileFactory::CreateInstance(nsISupports *aDelegate,
const nsIID &aIID,
void **aResult)
{
if (aDelegate != nsnull) {
return NS_ERROR_NO_AGGREGATION;
}
nsProfile *t = nsProfile::GetInstance();
if (t == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult res = t->QueryInterface(aIID, aResult);
if (NS_FAILED(res)) {
*aResult = nsnull;
}
return res;
}
extern "C" NS_EXPORT nsresult
NSGetFactory(nsISupports* serviceMgr,
const nsCID &aClass,
const char *aClassName,
const char *aProgID,
nsIFactory **aFactory)
{
if (aFactory == nsnull) {
return NS_ERROR_NULL_POINTER;
}
if (aClass.Equals(kProfileCID)) {
nsProfileFactory *factory = new nsProfileFactory();
if (factory == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult res = factory->QueryInterface(nsIFactory::GetIID(), (void **) aFactory);
if (NS_FAILED(res)) {
*aFactory = nsnull;
delete factory;
}
return res;
}
return NS_NOINTERFACE;
}
extern "C" NS_EXPORT PRBool NSCanUnload(nsISupports* serviceMgr)
{
return PRBool(g_InstanceCount == 0 && g_LockCount == 0);
}
extern "C" NS_EXPORT nsresult NSRegisterSelf(nsISupports* aServMgr, const char *path)
{
nsresult rv;
nsCOMPtr<nsIServiceManager> servMgr(do_QueryInterface(aServMgr, &rv));
if (NS_FAILED(rv)) return rv;
nsIComponentManager* compMgr;
rv = servMgr->GetService(kComponentManagerCID,
nsIComponentManager::GetIID(),
(nsISupports**)&compMgr);
if (NS_FAILED(rv)) return rv;
rv = compMgr->RegisterComponent(kProfileCID, nsnull, nsnull, path,
PR_TRUE, PR_TRUE);
(void)servMgr->ReleaseService(kComponentManagerCID, compMgr);
return rv;
}
extern "C" NS_EXPORT nsresult NSUnregisterSelf(nsISupports* aServMgr, const char *path)
{
nsresult rv;
nsCOMPtr<nsIServiceManager> servMgr(do_QueryInterface(aServMgr, &rv));
if (NS_FAILED(rv)) return rv;
nsIComponentManager* compMgr;
rv = servMgr->GetService(kComponentManagerCID,
nsIComponentManager::GetIID(),
(nsISupports**)&compMgr);
if (NS_FAILED(rv)) return rv;
rv = compMgr->UnregisterComponent(kProfileCID, path);
(void)servMgr->ReleaseService(kComponentManagerCID, compMgr);
return rv;
}