/***********************************************************************
 *
 *  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 "DataManager.h"


DataManager::DataManager()
{
	hostList = NULL;
	rejectHostList = NULL;
}



DataManager::~DataManager()
{

}

int DataManager::AddRejectHost(char *hostName)
{
RejectHost *t;

	if( hostName == NULL || hostName[0] == 0 )
	{
		PrintMessage(MESG_ERROR, "\n DataManager : Host name is NULL or empty ");
		// Just ignore this..
		return FPM_TRUE;
	}
	
	// check if the specified host is already present
	for(t=rejectHostList; t ; t = t->next)
	{
		if( STRCMPI(hostName, t->hostName) == 0 )
		{
			PrintMessage(MESG_DEBUG, "\n DataManager : Specified hostname [%s] is already present ", hostName);
			return FPM_TRUE;
		}
	}

	// Create new Host element for new host
	RejectHost *tempHost = (RejectHost *) malloc(sizeof(RejectHost));
	
	if( tempHost )
		tempHost->hostName = (char*) malloc(strlen(hostName) + 1);
	
	if( !tempHost || !tempHost->hostName) 
	{
		PrintMessage(MESG_ERROR, "\n DataManager : Failed to add reject host due to insufficient memory ");
		return FPM_INSUFFICIENT_MEMORY;
	}
	
	strcpy(tempHost->hostName, hostName);
	tempHost->next  = NULL;
	
	if( rejectHostList == NULL )
		rejectHostList = tempHost;
	else
	{   // Add new host at the end
		for(t=rejectHostList; t->next ; t=t->next);

		t->next = tempHost;
	}

	return FPM_TRUE;	


}


//invoked from outside
int DataManager::RemoveRejectHost(char *hostName)
{
	RejectHost *prev = NULL;

	if( !hostName )
	{
		PrintMessage(MESG_ERROR, "\n DataManager : Host name is Null ....");
		return FPM_FALSE;
	}

	// Find out and destroy it..!
	for(RejectHost *t=rejectHostList; t ; prev=t,t=t->next)
	{
		if( STRCMPI(hostName, t->hostName) == 0 )
		{
			// if this is the first node
			if( rejectHostList == t )
				rejectHostList = t->next;
			else 
				prev->next = t->next;

			free(t->hostName);
			free(t);
			return FPM_TRUE;
		}
	}

	PrintMessage(MESG_ERROR, "\n DataManager : Specified hostname[%s] is not present in the reject host list", hostName);
	
	return FPM_FALSE;

}


void DataManager::PrintAllRejectHosts()
{
	
	PrintMessage(MESG_PRINT, "\n\n ******  List of Reject Hosts ******");
		
	for(RejectHost *t=rejectHostList; t ; t=t->next)
		PrintMessage(MESG_PRINT, "\n %s", t->hostName);

}


// internal function
int DataManager::AddHost(char *hostName)
{
Host *host, *t;

	if( hostName == NULL || hostName[0] == 0 )
	{
		PrintMessage(MESG_ERROR, "\n DataManager : Host name is NULL or empty ");
		return FPM_ILLEGAL_HOSTNAME;
	}
	
	// check if the specified host is already present
	for(host=hostList; host ; host = host->next)
	{
		if( STRCMPI(hostName, host->hostName) == 0 )
		{
			PrintMessage(MESG_DEBUG, "\n DataManager : Specified hostname [%s] is already present ", hostName);
			return FPM_TRUE;
		}
	}

	// Create new Host 
	Host *tempHost = (Host *) malloc(sizeof(Host));
	
	if( tempHost )
		tempHost->hostName = (char*) malloc(strlen(hostName) + 1);
	
	if( !tempHost || !tempHost->hostName) 
	{
		PrintMessage(MESG_ERROR, "\n DataManager : Failed to add host due to insufficient memory ");
		return FPM_INSUFFICIENT_MEMORY;
	}
	
	strcpy(tempHost->hostName, hostName);
	tempHost->child = NULL;
	tempHost->next  = NULL;
	
	// Now add the new host to the existing store
	if( hostList == NULL )
		hostList = tempHost;
	else
	{   // Add new host at the end
		for(t=hostList; t->next ; t=t->next);

		t->next = tempHost;
	}

	return FPM_TRUE;
}



// invoked from outside...
int DataManager::ModifyHost(char *oldHostName, char *newHostName)
{
	if( !oldHostName || !newHostName )
	{
		PrintMessage(MESG_ERROR, "\n DataManager : Null parameters passed....");
		return FPM_FALSE;
	}


	for(Host *t=hostList; t ; t=t->next)
	{
		if( STRCMPI(oldHostName, t->hostName) == 0 )
		{
			free(t->hostName);
			t->hostName = (char*) malloc( strlen(newHostName) + 1 );
			
			if( !t->hostName )
			{
				PrintMessage(MESG_ERROR, "\n DataManager : Failed to modify host entry due to insufficient memory ");
				return FPM_FALSE;
			}
			
			strcpy(t->hostName, newHostName);
			return FPM_TRUE;
		}
	}

	PrintMessage(MESG_ERROR, "\n DataManager : Specified hostname[%s] is not present ", oldHostName);
	return FPM_FALSE;

}

int DataManager::AddHost(Host *host)
{

Host *t;

	if( host == NULL )
	{
		PrintMessage(MESG_ERROR, "\n AddHost :  host is NULL....");
		return FPM_FALSE;
	}

	for(t=hostList; t ; t=t->next)
	{
		if( STRCMPI(host->hostName, t->hostName) == 0 )
		{
			PrintMessage(MESG_ERROR, "\n AddHost :  Specified hostname %s is already present..", host->hostName);
			return FPM_FALSE;
		}
	}

	Host *newHost = DuplicateHost(host);
	
	if( newHost == NULL)
	{
		PrintMessage(MESG_ERROR, "\n AddHost : Insufficient memory");
		return FPM_INSUFFICIENT_MEMORY;
	}

	// Add the new host at the end of the list...
	if( hostList == NULL )
		hostList = newHost;
	else
	{
		for(t=hostList; t->next ; t=t->next);
		
		t->next = newHost;
	}

	PrintMessage(MESG_DEBUG, "\n AddHost : Host %s added successfully", newHost->hostName);

	return FPM_TRUE;
}



int DataManager::ModifyHost(Host *host)
{
	Host *prev = NULL;
	
	if( host == NULL )
	{
		PrintMessage(MESG_ERROR, "\n ModifyHost :  host is NULL....");
		return FPM_FALSE;
	}

	// check if the specified host is present
	// If present remove it and add new host ...
	for(Host *t=hostList; t ; prev=t,t=t->next)
	{
		if( STRCMPI(host->hostName, t->hostName) == 0 )
		{
			Host *newHost = DuplicateHost(host);

			if( newHost == NULL )
			{
				PrintMessage(MESG_ERROR, "\n ModifyHost : Insufficient memory");
				return FPM_INSUFFICIENT_MEMORY;
			}

			// if this is the first node
			if( hostList == t )
			{
				hostList = newHost;
				newHost->next = t->next;
			}
			else 
			{
				prev->next = newHost;
				newHost->next = t->next;
			}

			PrintMessage(MESG_DEBUG, "\n ModifyHost : Host %s modified successfully", newHost->hostName);

			return FPM_TRUE;
		}
	}

	PrintMessage(MESG_ERROR, "\n ModifyHost :  Specified host %s is not present", host->hostName);
	
	return FPM_HOSTNAME_NOT_PRESENT;
}




//invoked from outside
int DataManager::RemoveHost(char *hostName)
{
	Host *prev = NULL;

	if( !hostName )
	{
		PrintMessage(MESG_ERROR, "\n DataManager : Host name is Null ....");
		return FPM_ILLEGAL_HOSTNAME;
	}

	// Find out and destroy it..!
	for(Host *t=hostList; t ; prev=t,t=t->next)
	{
		if( STRCMPI(hostName, t->hostName) == 0 )
		{
			// if this is the first node
			if( hostList == t )
				hostList = t->next;
			else 
				prev->next = t->next;

			free(t->hostName);
			free(t);
			return FPM_TRUE;
		}
	}

	PrintMessage(MESG_ERROR, "\n DataManager : Specified hostname[%s] is not present ", hostName);
	
	return FPM_HOSTNAME_NOT_PRESENT;
}


Host* DataManager::DuplicateHost(Host *host)
{
HostElement *prev = NULL;
HostElement *t, *temp;

	Host *newHost = (Host *) malloc(sizeof(Host));
	
	if( newHost )
		newHost->hostName = (char*) malloc(strlen(host->hostName) + 1);

	if( !newHost || !newHost->hostName )
	{
		PrintMessage(MESG_ERROR, "\n DuplicateHost : Insufficient memory");
		return NULL;
	}

	strcpy(newHost->hostName, host->hostName);
	newHost->child = NULL;
	newHost->next = NULL;
	
	for(t=host->child; t ; t = t->next)
	{
		HostElement *nh = (HostElement*) malloc(sizeof(HostElement));
		
		if( nh )
		{
			nh->name = (char*) malloc(strlen(t->name) + 1 );
			nh->value = (char*) malloc(strlen(t->value) + 1);
		}
		
		if( !nh || !nh->name || !nh->value)
			goto duplicate_error;

		nh->isPassword = t->isPassword;
		strcpy(nh->name, t->name);
		strcpy(nh->value, t->value);
		nh->next = NULL;

		if( prev == NULL )
			newHost->child = nh;
		else
			prev->next = nh;

		prev = nh;
	}


	return newHost;

duplicate_error:
	
	// cleanup partially loaded data
	for(t=newHost->child; t ; )
	{
		if(t->name) free(t);
		if(t->value) free(t);
		
		temp = t;
		t = t->next;
		free(temp);
	}


	if(newHost->hostName)
		free(newHost->hostName);
	
	free(newHost);
	
	PrintMessage(MESG_ERROR, "\n DuplicateHost : Insufficient memory");
	return NULL;
}

void DataManager::PrintAllHosts()
{
	PrintMessage(MESG_PRINT, "\n\n List of hosts ");
	
	for(Host *t=hostList; t ; t=t->next)
	{
		PrintMessage(MESG_PRINT, "\n\n %s", t->hostName);
		for(HostElement *h=t->child; h ; h= h->next)
		{
			PrintMessage(MESG_PRINT, "\n %s  : %s ", h->name, h->value);
		}
	}
}




int DataManager::AddHostElement(char *hostName, char *name, char *value, unsigned char isPassword)
{
	Host *host;
	HostElement *h, *t;


	if( !hostName || !name || !value)
	{
		PrintMessage(MESG_ERROR, "\n DataManager : Null parameters passed....");
		return FPM_SIGNON_FILE_INVALID_DATA;
	}

	
	// First find the specified host
	for(host = hostList; host ; host = host->next)
	{
		if( STRCMPI(hostName, host->hostName) == 0 )
			break;
	}


	if( !host )
	{
		PrintMessage(MESG_ERROR, "\n DataManager : Specified hostname[%s] is not present ", hostName);
		return FPM_HOSTNAME_NOT_PRESENT;
	}

	// check if specified name/value pair exist already....
	for(h = host->child; h ; h=h->next)
	{
		if( (STRCMPI(h->name,name) == 0 ) && (strcmp(h->value, value) == 0 ) )
		{
			PrintMessage(MESG_ERROR, "\n DataManager : Specified name/value [%s/%s]pair is already present ", name,value);
			return FPM_TRUE;
		}
	}

	HostElement *temp = (HostElement *) malloc(sizeof(HostElement));
	if( temp )
	{
		temp->name = (char*) malloc( strlen(name)+1 );
		temp->value = (char*) malloc( strlen( value) + 1 );
	}
	
	if( !temp || !temp->name || !temp->value ) 
	{
		PrintMessage(MESG_ERROR, "\n DataManager : Failed to add name/value due to insufficient memory ");
		return FPM_INSUFFICIENT_MEMORY;
	}

	strcpy(temp->name,name);
	strcpy(temp->value, value);
	temp->isPassword = isPassword;
	temp->next = NULL;

	// Now add it to the host...	
	if( host->child == NULL )
	{
		host->child = temp;		
	}
	else
	{
	  for(t = host->child; t->next ; t=t->next);
	  
	  t->next = temp;
	}

	return FPM_TRUE;
}


// invoked from outside..
int DataManager::RemoveHostElement(char *hostName, char *value)
{
	
	Host *host;

	if( !hostName || !value )
	{
		PrintMessage(MESG_ERROR, "\n DataManager : Null parameters passed....");
		return FPM_FALSE;
	}

	// First find the specified hot
	for(host = hostList; host; host = host->next)
	{
		if( STRCMPI(hostName, host->hostName) == 0 )
			break;
	}

	if( !host )
	{
		PrintMessage(MESG_ERROR, "\n DataManager : Specified hostname[%s] is not present ", hostName);
		return FPM_FALSE;
	}

	HostElement *prev = host->child;
	for(HostElement *h = host->child; h ;prev=h, h=h->next)
	{
		if( strcmp(h->value, value) == 0  )
		{

			if( host->child == h )
				host->child = h->next;
			else
				prev->next = h->next;

			free(h->value);
			free(h->name);
			free(h);
			
			return FPM_TRUE;
		}
	}


	return FPM_FALSE;
}


// internal
int DataManager::RemoveAllData()
{
	
	RemoveAllRejectHosts();
	RemoveAllHosts();

	return FPM_TRUE;
}


int DataManager::RemoveAllRejectHosts()
{
RejectHost *t = rejectHostList;	
RejectHost *temp;

	for( ; t; )
	{
		temp = t;
		t= t->next;
		RemoveRejectHost(temp->hostName);
	}

	rejectHostList = NULL;
	
	return FPM_TRUE;
}


int DataManager::RemoveAllHosts()
{
Host *t = hostList;
Host *temp;

	for( ; t ; )
	{
		temp = t;
		t = t->next;

		RemoveHost(temp->hostName);
	}

	hostList = NULL;

	return FPM_TRUE;

}