/***********************************************************************
 *
 *  Copyright (C) 2005-2006 Novell, Inc. All Rights Reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; version 2.1
 *  of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, Novell, Inc.
 *
 *  To contact Novell about this file by physical or electronic mail,
 *  you may find current contact information at www.novell.com.
 *
 ***********************************************************************/

#include "ProfileManager.h"



// Private functions....

ProfileManager::ProfileManager()
{
	isInitialized = 0;
	libnss = NULL;
	libplc = NULL;

	profileName = NULL;
	profilePath = NULL;
	libraryPath = NULL;
	masterPassword = NULL;


}


char * ProfileManager::GetFirefoxProfilePath(char *profileName)
{

#ifdef WIN32

	char profileDir[MAX_PATH] = "";
	char partialPath[] = "Application Data\\Mozilla\\Firefox";
	char profilePath[MAX_PATH];
	char line[1024];

	DWORD pathSize = MAX_PATH;
	char *finalProfilePath = NULL;
	unsigned int i;
	HANDLE token;

		
	// Get current user's profile directory
	if( OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == FALSE )
	{
		PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Failed to get current process token ");
		return 0;
	}
	
	if( GetUserProfileDirectory(token, profileDir, &pathSize) == FALSE )
	{
		PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Failed to get user profile directory");
		return 0;
	}
	
	PrintMessage(MESG_DEBUG, "\n GetFirefoxProfilePath : User Profile directory = %s", profileDir);
	
	// Get firefox profile directory
	strcpy(profilePath, profileDir);
	strcat(profilePath,"\\");
	strcat(profilePath,partialPath);
	strcat(profilePath,"\\profiles.ini");
	
	PrintMessage(MESG_DEBUG, "\n GetFirefoxProfilePath : Firefox profile.ini path = %s ", profilePath);


#else  // Linux platform....

	char profileDir[]  ="/.mozilla/firefox";
	char profileFile[] ="/.mozilla/firefox/profiles.ini";
	
	char line[1024];
	char *profilePath = NULL;
	char *homeDir = NULL;
	char *finalProfilePath = NULL;
	unsigned int i;
	
	// Get home directory
	homeDir = getenv("HOME");
	
	if(homeDir == NULL )
	{
	    PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Unable to get home directory ");
	    return 0;
	}	

	profilePath = (char*) malloc( strlen(homeDir) + strlen(profileFile) + 3 );
	if( profilePath == NULL )
	{
	    PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Insufficient memory ");
	    return 0;
	}
	strcpy(profilePath,homeDir);
	strcat(profilePath,profileFile);

	PrintMessage(MESG_DEBUG, "\n GetFirefoxProfilePath : Firefox profile dir path = %s ", profilePath);

#endif

	// Open the firefox profile setting file
	FILE *profile = fopen(profilePath, "r");
	
	if( profile == NULL )
	{
		PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Unable to find firefox profile file : %s ", profilePath);
		return NULL;
	}

	// Find out the profile path for given profile name
	char *temp;
	int isProfileFound = 0;
	int isRelative = 1;
	char *path = NULL;

	while(fgets(line, 1024, profile))
	{
		// Remove trailing end of line character
		line[strlen(line)-1]= 0;
		
		// Convert to smaller case until "=" found....
		for(i=0; i<strlen(line); i++)
		{
			if( line[i] == '=' )
				break;

			if( line[i] >=65 && line[i]<=90 )
				line[i]+=32;
		} 		

		if( isProfileFound )
		{
			
			temp = strchr(line,'=') + 1;
		
			// check for IsRelative=
			if( strstr(line, "isrelative=") != NULL )
			{
				// Is the value greater than 0 ( ascii 48 )
				isRelative = (*temp > 48)? 1 : 0 ;
				continue;
			}
			
			// check for Path=
			if( strstr(line, "path=") != NULL )
			{
				path =  (char*) malloc(strlen(temp) + 1);
				if( !path )
				{
				    PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Insufficient memory ");
					fclose(profile);
					return 0;
				}

				strcpy(path,temp);
				continue;
			}
		
			// Break once you encounter next profile
			if( strstr(line, "profile") != NULL )
			{
				break;
			}
			

		}
		
		
		if( strstr(line, "name=") != NULL )
		{
			temp = strchr(line,'=') + 1;
			
			if( STRCMPI(temp, profileName) == 0 )
			{
				PrintMessage(MESG_DEBUG, "\n GetFirefoxProfilePath : Profile name [%s] found ", profileName);
				isProfileFound = 1;
			}
		}

		
	}

	fclose(profile);

	if( !isProfileFound )
	{
		PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Specified Profile [%s] not present ", profileName);
		return NULL;
	}

	if( !path )
	{
		PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Profile [%s] path not found ", profileName);
		return NULL;
	}

	if( isRelative )
	{
		#ifdef WIN32
			// if path contains '/' then make it '\\'
			char *slash = strstr(path,"/");
				
			if( slash != NULL )
				*slash = '\\';
				
			int totalLen = strlen(profileDir) + strlen(partialPath) + strlen(path) + 3 ;
			finalProfilePath = (char *) malloc(totalLen);
			
			if( finalProfilePath )
			{
				strcpy(finalProfilePath,profileDir);
				strcat(finalProfilePath,"\\");
				strcat(finalProfilePath,partialPath);
				strcat(finalProfilePath,"\\");
				strcat(finalProfilePath,path);

				PrintMessage(MESG_DEBUG, "\n Final profile path is : %s ", finalProfilePath);
			}
				
		#else // Linux platform

			int totalLen = strlen(homeDir) + strlen(profileDir) +  strlen(path) + 2 ;
			finalProfilePath = (char *) malloc(totalLen);

			if( finalProfilePath )
			{
				strcpy(finalProfilePath,homeDir);
				strcat(finalProfilePath,profileDir);
				strcat(finalProfilePath,"/");
				strcat(finalProfilePath,path);

				PrintMessage(MESG_DEBUG, "\n Final profile path is : %s ", finalProfilePath);
			}

		#endif
	
		if(path)
			free(path);
	}
	else
	{
		finalProfilePath = path;
		
	}

	if( !finalProfilePath)
	{
		PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Insufficient memory ");
		return NULL;
	}

	// check if profile directory exists.....
	if( !IsDirectoryExists(finalProfilePath) )
	{	
		PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Profile directory [%s] does not exist", finalProfilePath);
		free(finalProfilePath);
		return NULL;
	}


	return finalProfilePath;
}



char* ProfileManager::GetFirefoxLibPath()
{
	char *firefoxPath = NULL;

#ifdef WIN32

	char regSubKey[]    = "SOFTWARE\\Clients\\StartMenuInternet\\firefox.exe\\shell\\open\\command";
	char pathValue[MAX_PATH] ="";
	DWORD pathSize = MAX_PATH;
	DWORD valueType;
	HKEY rkey;

	// Open firefox registry key
	if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, regSubKey, 0, KEY_READ, &rkey) != ERROR_SUCCESS )
	{
		PrintMessage(MESG_ERROR, "\n GetFirefoxLibPath : Failed to open the firefox registry key : HKCU\\%s", regSubKey );
		return NULL;
	}

	// Read the firefox path value
	if( RegQueryValueEx(rkey, NULL, 0,  &valueType, (unsigned char*)&pathValue, &pathSize) != ERROR_SUCCESS )
	{
		PrintMessage(MESG_ERROR, "\n GetFirefoxLibPath : Failed to read the firefox path value from registry ");
		RegCloseKey(rkey);
		return NULL;
	} 
	
	if( pathSize <= 0 || pathValue[0] == 0)
	{
		PrintMessage(MESG_ERROR, "\n GetFirefoxLibPath : Path value read from the registry is empty");
		RegCloseKey(rkey);
		return NULL;
	}	

	RegCloseKey(rkey);

	// This path may contain extra double quote....
	if( pathValue[0] == '\"' )
	{
		for(unsigned int i=0; i< strlen(pathValue)-1 ; i++)
			pathValue[i] = pathValue[i+1];
	}

	PrintMessage(MESG_DEBUG, "\n GetFirefoxLibPath : Path value read from registry is %s", pathValue);

	StrLwr(pathValue);	
	char *firefox = strstr(pathValue, "firefox.exe");

	if( firefox == NULL )
	{
		PrintMessage(MESG_ERROR, "\n GetFirefoxLibPath : Path value read from registry is invalid");
		return NULL;
	}

	// remove the firefox.exe from the end...
	*(firefox-1) = 0;
	
	firefoxPath = (char*) malloc( strlen(pathValue) + 1);
	
	if( firefoxPath )
	{
		strcpy(firefoxPath, pathValue);

		if( !IsDirectoryExists(firefoxPath) )
		{
			free(firefoxPath);
			return NULL;
		}
	}


#else  // Linux platform...

	char path[]="/opt/MozillaFirefox/lib";
	
	firefoxPath = (char*) malloc( strlen(path) + 1);
	
	if( firefoxPath )
	{
		strcpy(firefoxPath, path);
	}

#endif

	PrintMessage(MESG_DEBUG, "\n GetFirefoxLibPath : Firefox library path = [%s] ", firefoxPath);
	
	return firefoxPath;

}



HMODULE ProfileManager::PMLoadLibrary(char *firefoxDir, char *libName)
{
char *loadPath;
HMODULE libtmp = NULL;

	if( firefoxDir != NULL )
		loadPath = ( char*) malloc(strlen(firefoxDir) + strlen(libName) + 2);
	else
		loadPath = ( char*) malloc(strlen(libName) + 1);
	
	if( !loadPath )
	{
		PrintMessage(MESG_ERROR, "\n\n LoadLibrary : Insufficient memory");
		return 0;
	}
	
	if( firefoxDir != NULL )
	{
		strcpy(loadPath, firefoxDir);
		strcat(loadPath, "/");
		strcat(loadPath, libName);
	}
	else
	{
		strcpy(loadPath, libName);
	}

	libtmp = LOADLIBRARY(loadPath);

	if( !libtmp )
	{
		PrintMessage(MESG_DEBUG, "\n\n LoadLibrary : Failed to load library %s ", loadPath);
		free(loadPath);
		return 0;
	}

	free(loadPath);

	return libtmp;
}

//
//   Checks if store is available...
//
int ProfileManager::IsStoreAvailable()
{
	
	PrintMessage(MESG_DEBUG, "\n IsStoreAvailable : Checking if firefox and its libraries are present ");
	


	libraryPath = GetFirefoxLibPath();
	
	if( !libraryPath )
	{
		PrintMessage(MESG_ERROR, "\n IsStoreAvailable : Failed to find firefox profile or library path ");
		return FPM_FALSE;        
	}

	// First check if firefox binary is present....
	// Because on NLD, NSS library is no longer shipped with firefox.
	// Hence NSS libraries will still be there even if firefox is removed :)
#ifdef WIN32

	char *firefox_bin_file = (char*) malloc(strlen(libraryPath)+ strlen("firefox.exe") + 2);
	if( !firefox_bin_file )
	{
		PrintMessage(MESG_ERROR, "\n IsStoreAvailable : Insufficient memory..malloc failed \n");
		return FPM_FALSE;        
	}

	strcpy(firefox_bin_file,libraryPath);
	strcat(firefox_bin_file,"\\firefox.exe");

	FILE *firefox_bin = fopen(firefox_bin_file,"r");
	
	if( firefox_bin == NULL)
	{
		PrintMessage(MESG_ERROR, "\n IsStoreAvailable : Failed to find firefox binary file %s\n", firefox_bin_file);
		free(firefox_bin_file);
		return FPM_FALSE;  
	}
	
	free(firefox_bin_file);
	fclose(firefox_bin);

#else

	FILE *firefox_bin = fopen("/usr/bin/firefox","r");
	
	if( firefox_bin == NULL)
	{
		PrintMessage(MESG_ERROR, "\n IsStoreAvailable : Failed to find firefox binary file /usr/bin/firefox \n");
		return FPM_FALSE;  
	}

	fclose(firefox_bin);
#endif




	// Next try to load from the library path then try to load from default lib path
	
	// Here we have to first load all dependent libraries and then
	// load main library , otherwise face the problems...:)
	if( PMLoadLibrary(libraryPath, NSPR_LIBRARY_NAME) )
	{
		if((libplc=PMLoadLibrary(libraryPath, PLC_LIBRARY_NAME)) )
		{
			if( PMLoadLibrary(libraryPath, PLDS_LIBRARY_NAME) )
			{
				if( PMLoadLibrary(libraryPath, SOFTN_LIBRARY_NAME) )
					libnss=PMLoadLibrary(libraryPath, NSS_LIBRARY_NAME);
			}
		}
	}
	else  // try to load library from default library path
	{
		if( PMLoadLibrary(NULL, NSPR_LIBRARY_NAME) )
		{
			if((libplc=PMLoadLibrary(NULL, PLC_LIBRARY_NAME)) )
			{
				if( PMLoadLibrary(NULL, PLDS_LIBRARY_NAME) )
				{
					if( PMLoadLibrary(NULL, SOFTN_LIBRARY_NAME) )
						libnss=PMLoadLibrary(NULL, NSS_LIBRARY_NAME);
				}
			}
		}
	}

	if( !libnss || !libplc ) 
	{
		PrintMessage(MESG_ERROR, "\n IsStoreAvailable : Failed to load the required firefox library");
		return FPM_FALSE;
	}

	// Free the library
	if( libnss != NULL )
	{
		PrintMessage(MESG_DEBUG, "\n IsStoreAvailable : Freeing library libnss.dll");
		FREELIBRARY(libnss);
	}

	if( libplc != NULL )
	{
		PrintMessage(MESG_DEBUG, "\n IsStoreAvailable : Freeing library libplc.dll");
		FREELIBRARY(libplc);
	}

	return FPM_TRUE;
}







// Public functions...


int ProfileManager::ProfileInit(char *profileName)
{

	if( isInitialized == FPM_TRUE)
	{
		PrintMessage(MESG_DEBUG, "\n ProfileInit : Firefox profile [%s] is already initialized ", profileName);
		return FPM_TRUE;
	}


	profilePath = GetFirefoxProfilePath(profileName);
	libraryPath = GetFirefoxLibPath();

	if( !profilePath  || !libraryPath )
	{
		PrintMessage(MESG_ERROR, "\n ProfileInit : Failed to find firefox profile or library path ");
		return FPM_PROFILE_NOT_PRESENT;        
	}

	PrintMessage(MESG_DEBUG, "\n Profile path = [%s] ", profilePath);
	PrintMessage(MESG_DEBUG, "\n Library path = [%s] ", libraryPath);

	// First try to load from the library path then try to load from default lib path
	
	// Here we have to first load all dependent libraries and then
	// load main library , otherwise face the problems...:)
	if( PMLoadLibrary(libraryPath, NSPR_LIBRARY_NAME) )
	{
		if((libplc=PMLoadLibrary(libraryPath, PLC_LIBRARY_NAME)) )
		{
			if( PMLoadLibrary(libraryPath, PLDS_LIBRARY_NAME) )
			{
				if( PMLoadLibrary(libraryPath, SOFTN_LIBRARY_NAME) )
					libnss=PMLoadLibrary(libraryPath, NSS_LIBRARY_NAME);
			}
		}
	}
	else  // try to load library from default library path
	{
		if( PMLoadLibrary(NULL, NSPR_LIBRARY_NAME) )
		{
			if((libplc=PMLoadLibrary(NULL, PLC_LIBRARY_NAME)) )
			{
				if( PMLoadLibrary(NULL, PLDS_LIBRARY_NAME) )
				{
					if( PMLoadLibrary(NULL, SOFTN_LIBRARY_NAME) )
						libnss=PMLoadLibrary(NULL, NSS_LIBRARY_NAME);
				}
			}
		}
	}

	if( !libnss || !libplc ) 
	{
		PrintMessage(MESG_ERROR, "\n ProfileInit : Failed to load the required firefox library");
		return FPM_LIBRARY_LOAD_FAILED;
	}
	

	PrintMessage(MESG_DEBUG, "\n ProfileInit : Required libraries are loaded from firefox path successfully..");


	// Get all the functions from NSS library
	NSSInit				   = (NSS_Init) GETPROCADDRESS(libnss, "NSS_Init");
	NSSShutdown			   = (NSS_Shutdown)GETPROCADDRESS(libnss, "NSS_Shutdown");
	//PK11SetPasswordFunc    = (PK11_SetPasswordFunc) GETPROCADDRESS(libnss, "PK11_SetPasswordFunc");
	PK11GetInternalKeySlot = (PK11_GetInternalKeySlot) GETPROCADDRESS(libnss, "PK11_GetInternalKeySlot");
	PK11FreeSlot           = (PK11_FreeSlot) GETPROCADDRESS(libnss, "PK11_FreeSlot");
	PK11Authenticate       = (PK11_Authenticate) GETPROCADDRESS(libnss, "PK11_Authenticate");
	PK11SDRDecrypt         = (PK11SDR_Decrypt) GETPROCADDRESS(libnss, "PK11SDR_Decrypt");
	PK11SDREncrypt         = (PK11SDR_Encrypt) GETPROCADDRESS(libnss, "PK11SDR_Encrypt");
	PK11CheckUserPassword  = (PK11_CheckUserPassword) GETPROCADDRESS(libnss, "PK11_CheckUserPassword");

	if( !NSSInit || !NSSShutdown || !PK11GetInternalKeySlot || !PK11Authenticate || !PK11SDRDecrypt || !PK11SDREncrypt || !PK11FreeSlot || !PK11CheckUserPassword)
	{
		PrintMessage(MESG_ERROR, "\n\n ProfileInit : Failed to get function address for library %s ", NSS_LIBRARY_NAME);
		ProfileExit();
		return FPM_LIBRARY_LOAD_FAILED;
	}

	// Get all the functions from PLC library
	PLBase64Encode     = ( PL_Base64Encode ) GETPROCADDRESS(libplc, "PL_Base64Encode");
	PLBase64Decode     = ( PL_Base64Decode ) GETPROCADDRESS(libplc, "PL_Base64Decode");

	if( !PLBase64Encode || !PLBase64Decode )
	{
		PrintMessage(MESG_ERROR, "\nProfileInit :  Failed to get function address for library %s ", PLC_LIBRARY_NAME);
		ProfileExit();
		return FPM_LIBRARY_LOAD_FAILED;
	}

	
	// Initialize the NSS library
	if( (*NSSInit) (profilePath) != SECSuccess )
	{
		PrintMessage(MESG_ERROR, "\n ProfileInit : Initialization failed , Make sure key3.db and cert8.db");
		PrintMessage(MESG_ERROR, "\n files are present in the specified directory\n");
		ProfileExit();

		return FPM_LIBRARY_INIT_FAILED;
	}

	
	PrintMessage(MESG_DEBUG, "\n ProfileInit : NSS_Init success..");

	// Copy the profile name for later use
	this->profileName = (char*) malloc(strlen(profileName)+1);
	if( !this->profileName )
	{
		PrintMessage(MESG_ERROR, "\n ProfileInit :  Insufficient memory..");
		return FPM_INSUFFICIENT_MEMORY;        
	}
	
	strcpy(this->profileName, profileName);


	// TODO
	// Read the preference from the config file present in the profile...

	isInitialized = FPM_TRUE;

	// Setup the function pointers...
	void *funList[9];
	
	funList[0] = (void*)NULL ; //PK11SetPasswordFunc;
	funList[1] = (void*)PK11GetInternalKeySlot;
	funList[2] = (void*)PK11FreeSlot;
	funList[3] = (void*)PK11Authenticate;
	funList[4] = (void*)PK11CheckUserPassword;
	funList[5] = (void*)PK11SDRDecrypt;
	funList[6] = (void*)PK11SDREncrypt;
	funList[7] = (void*)PLBase64Encode;
	funList[8] = (void*)PLBase64Decode;
	
	signonManager.SetupFunctions(funList);

	return FPM_TRUE;
}



void ProfileManager::ProfileExit()
{
	int i;

	PrintMessage(MESG_DEBUG, "\n ProfileExit : Shutting down the profile %s", profileName);

	if( (isInitialized == FPM_TRUE) && NSSShutdown != NULL )
	{	
		PrintMessage(MESG_DEBUG, "\n ProfileExit : invoking NSSShutdown for profile", profileName);
		for(i=0;  (i<5) && ((*NSSShutdown)() == SECFailure); i++ )
		{
			PrintMessage(MESG_DEBUG, "\n ProfileExit %d: NSSShutdown : FAILURE",i);
			//Sleep(500);
		}
		
		if( i != 5)
		{
			PrintMessage(MESG_DEBUG, "\n ProfileExit :NSSShutdown : SUCCESS");
		
		}
		else
			PrintMessage(MESG_DEBUG, "\n ProfileExit : NSSShutdown : FAILURE");
		
	}

	if( libnss != NULL )
	{
		PrintMessage(MESG_DEBUG, "\n ProfileExit : Freeing library libnss.dll");
		FREELIBRARY(libnss);
	}

	if( libplc != NULL )
	{
		PrintMessage(MESG_DEBUG, "\n ProfileExit : Freeing library libplc.dll");
		FREELIBRARY(libplc);
	}

	// clean up signon data...
	signonManager.RemoveSignonData();

	isInitialized = FPM_FALSE;
}






int ProfileManager::IsMasterPasswordSet()
{
PK11SlotInfo *slot = 0;
int retValue = 0;
SECStatus status;

	slot = (*PK11GetInternalKeySlot)();
	
	if (!slot) 
	{ 
		PrintMessage(MESG_ERROR, "\n IsMasterPasswordSet PK11_GetInternalKeySlot failed  ...");
		return FPM_FALSE;
	}

	PrintMessage(MESG_DEBUG, "\n  PK11_GetInternalKeySlot SUCCESS ...");

	// Check with empty password....If it succeeds then master password is not set

	status =  (*PK11CheckUserPassword)(slot,"");
	if( status == SECSuccess )
	{
		PrintMessage(MESG_DEBUG, "\n IsMasterPasswordSet : Master password is not set...");
		retValue = FPM_FALSE;
	}
	else if(status == SECWouldBlock ) // password is wrong
		{
			PrintMessage(MESG_DEBUG, "\n IsMasterPasswordSet : Master password is set...");
			retValue = FPM_TRUE;
		}
		else  // something is wrong, may be key3.db is not initialized for crypt
		{
			PrintMessage(MESG_DEBUG, "\n IsMasterPasswordSet : Master password is not set...");
			retValue = FPM_FALSE;
		}

	// Free the slot
	(*PK11FreeSlot) (slot);

	return retValue;
}






int ProfileManager::CheckMasterPassword(char *masterPassword, int doSave)
{
PK11SlotInfo *slot = 0;
int retValue = 0;

	slot = (*PK11GetInternalKeySlot)();
	
	if (!slot) 
	{ 
		PrintMessage(MESG_ERROR, "\n CheckMasterPassword PK11_GetInternalKeySlot failed  ...");
		return FPM_FALSE;
	}

	
	if( (*PK11CheckUserPassword)(slot, masterPassword) == SECSuccess )
	{
		// Store the password for internal use...
		if( doSave )
		{
			PrintMessage(MESG_DEBUG, "\n CheckMasterPassword : saving master password for future use ******...");
		
			this->masterPassword = (char *) malloc( strlen(masterPassword)+1 );
		
			if( !this->masterPassword )
			{
				PrintMessage(MESG_ERROR, "\n  CheckMasterPassword : Insufficient memory");
				(*PK11FreeSlot) (slot);  // Free the slot...
				return FPM_INSUFFICIENT_MEMORY;
			}

			strcpy(this->masterPassword, masterPassword);
		}

		PrintMessage(MESG_DEBUG, "\n CheckMasterPassword : specified master password is correct...");
		retValue = FPM_TRUE;
	}
	else
	{
		PrintMessage(MESG_ERROR, "\n CheckMasterPassword : specified master password is wrong...");
		retValue = FPM_FALSE;
	}

	// Free the slot
	(*PK11FreeSlot) (slot);

	return retValue;
}






int ProfileManager::GetSignonData( struct Host **host, int doRefresh)
{
int retValue;

	//TODO NAG:
	//check if "remember password" enabled....
	
	 // Reload the signon data from the file...
	 if( doRefresh )
	 {
		retValue = RefreshSignonData();
		*host = signonManager.GetHostInfo();
		return retValue;
	 }

	 // if host list is null read again....
	 // TODO NAG : If there is no data , this will cause refresh to happen every time...

	 if( signonManager.GetHostInfo() == NULL )
	 {
	 	retValue = RefreshSignonData();
		*host = signonManager.GetHostInfo();
		return retValue;
	 }

	 // Just return the previously loaded data
	 *host = signonManager.GetHostInfo();

	 return FPM_TRUE;
}




int ProfileManager::RefreshSignonData()
{

	// First check if master password is correct....
	if( masterPassword )
	{
		// Just check for password , don't save....
		if( CheckMasterPassword(masterPassword, 0 ) != FPM_TRUE )
		{
			PrintMessage(MESG_ERROR, "\n RefreshSignonData : master password is wrong..can't proceed with signon decryption" );
			return FPM_MASTERPASSWORD_WRONG;
		}
	}
	else // check if master password is set...
	{
		// master password is set and its not specified
		if( IsMasterPasswordSet() == FPM_TRUE )
		{
			PrintMessage(MESG_ERROR, "\n RefreshSignonData : master password is set..but its not specified " );
			return FPM_MASTERPASSWORD_WRONG;
		}
	}


	return signonManager.LoadSignonData(profilePath);
}





int ProfileManager::WriteSignonData()
{
	// First check if master password is correct....
	if( masterPassword )
	{
		// Just check for password , don't save....
		if( CheckMasterPassword(masterPassword, 0 ) != FPM_TRUE )
		{
			PrintMessage(MESG_ERROR, "\n WriteSignonData : master password is wrong..can't proceed with signon decryption" );
			return FPM_MASTERPASSWORD_WRONG;
		}
	}
	else // check if master password is set...
	{
		// master password is set and its not specified
		if( IsMasterPasswordSet() == FPM_TRUE )
		{
			PrintMessage(MESG_ERROR, "\n WriteSignonData : master password is set..but its not specified " );
			return FPM_MASTERPASSWORD_WRONG;
		}
	}


	return signonManager.WriteSignonData(profilePath);

}




int ProfileManager::AddHost(struct Host *host, int doUpdate)
{
int retValue;

	if( (retValue = signonManager.AddHost(host)) != FPM_TRUE)
	{
		PrintMessage(MESG_ERROR, "\n AddHost : Failed to add the host %s ", host->hostName);
		return retValue;
	}

	if( doUpdate > 0 )
	{
		PrintMessage(MESG_ERROR, "\n AddHost : Updating the signon file ");
		return WriteSignonData();
	}

	return FPM_TRUE;
}




int ProfileManager::ModifyHost(struct Host *host, int doUpdate)
{
int retValue;

	if( (retValue = signonManager.ModifyHost(host)) != FPM_TRUE)
	{
		PrintMessage(MESG_ERROR, "\n ModifyHost : Failed to modify the host %s ", host->hostName);
		return retValue;
	}


	if( doUpdate > 0)
	{
		PrintMessage(MESG_ERROR, "\n ModifyHost : Updating the signon file ");
		return WriteSignonData();
	}

	return FPM_TRUE;
	
	

}



int ProfileManager::RemoveHost(char *hostName, int doUpdate)
{
int retValue;

	if( (retValue = signonManager.RemoveHost(hostName)) != FPM_TRUE)
	{
		PrintMessage(MESG_ERROR, "\n RemoveHost : Failed to remove the hsot %s ", hostName);
		return retValue;
	}

	if( doUpdate > 0 )
	{
		PrintMessage(MESG_ERROR, "\n RemoveHost : Updating the signon file ");
		return WriteSignonData();
	}

	return FPM_TRUE;
}