//%2003////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, 2001, 2002  BMC Software, Hewlett-Packard Development
// Company, L. P., IBM Corp., The Open Group, Tivoli Systems.
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
// IBM Corp.; EMC Corporation, The Open Group.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//==============================================================================
//
// Author: Paulo F. Borges (pfborges@wowmail.com)
//
// Modified By: 
//
//%/////////////////////////////////////////////////////////////////////////////


// This file has the DNS-specific routines that will be called to get
// a validation of the CIM information vs. the current test system

// These are the HP-UX specific routines

// Note: some of the properties return information from the /etc/resolv.conf
//		 file. We may have a mismatch when testing the information returned
//		 by the provider against the information returned by the client
//		 in case /etc/resolv.conf is being edited (provider sees one version 
//		 and client sees a different version).


#include <stdlib.h>
#include <ctype.h>
#include "DNSTestClient.h"


PEGASUS_USING_PEGASUS;
PEGASUS_USING_STD;

#define DOMAINNAME 0
#define SEARCHLIST 1
#define ADDRESSES  2

// Verify if string is equal (Upper or Lower case)
Boolean
DNSTestClient::IsEqual(char text[], const char txtcomp[])
{
	Boolean ok = true;
	int i;
	int max = strlen(text);
	char chin, chcmp;
	
	if(!max)
		return false;
	
	for(i=0; i<max; i++) {
		chin = toupper(text[i]);
		chcmp = toupper(txtcomp[i]);
		if(chin != chcmp) {
			ok = false;
			break;
		}
	}
	return ok;
}

// Verify if found string in array
Boolean
DNSTestClient::FindInArray(Array<String> src, String text)
{
	Boolean ok = false;
	int i;
	
	for(i=0; i<src.size(); i++) {
		if(src[i] == text) {
			ok = true;
			break;
		}
	}
	return ok;
}

/*
   GoodCreationClassName method for the DNS Provider Test Client

   Checks the specified value against the expected value and
   returns TRUE if the same, else FALSE
*/
Boolean 
DNSTestClient::goodCreationClassName(const String &ccn, 
                                     Boolean verbose)
{

   // This assumes the only right answer is PG_DNSAdminDomain

   if (verbose)
      cout<<"Checking " << ccn << " against " << CLASS_NAME <<endl;
   return (String::equalNoCase(ccn, CLASS_NAME));
}

/*
   GoodName method for the DNS Provider Test Client

   Checks the specified value against the expected value and
   returns TRUE if the same, else FALSE

   Returns "domain" fields from /etc/resolv.conf file
*/
Boolean 
DNSTestClient::goodName(const String &name, Boolean verbose)
{
    FILE *arq;
    char *ptr;
    char buffer[150];
    String domain;

    domain.clear();
    
    if (verbose)
      cout<<"Checking " << name << " against DNS name"<<endl;
   
    // open resolv.conf file to read informations.
    if((arq = fopen(RESOLV_CONF, "r")) == NULL)
    	return false;
    
    // Retrieve domain information from resolv.conf file
    while(!feof(arq)) {
    	memset(buffer, 0, sizeof(buffer));
    	fscanf(arq, "%s", buffer);

    	if(!strlen(buffer))
    		continue;

    	if(IsEqual(buffer, "domain") ||
           IsEqual(buffer, "search")) {
    		fscanf(arq, "%s", buffer);
    		domain.assign(buffer);
    		break;
    	}
    }
    fclose(arq);

    if (domain.size() == 0)
       return false;  // if can't get data to validate, fail

    if (verbose)
      cout<<" DNS name should be " << domain << endl;
    
    return (String::equalNoCase(name, domain));
}

/* GoodCaption method for the DNS Provider Test Client 

   Checks the specified value against the expected value 
   and returns TRUE if the same, else FALSE 
*/
Boolean 
DNSTestClient::goodCaption(const String &cap, 
                           Boolean verbose)
{

	// This assumes the only right answer is "DNS Admin Domain"

   if (verbose)
      cout<<"Checking Caption " << cap << endl;
   return (String::equalNoCase(cap, CAPTION));
}


/* GoodDescription method for the DNS Provider Test Client 

   Checks the specified value against the expected value 
   and returns TRUE if the same, else FALSE 
*/
Boolean 
DNSTestClient::goodDescription(const String &des, 
                           	   Boolean verbose)
{

	// This assumes the only right answer is 
	// "This is the PG_DNSAdminDomain object"

   if (verbose)
      cout<<"Checking Description " << des << endl;
   return (String::equalNoCase(des, DESCRIPTION));
}

/* GoodNAME_FORMAT method for the DNS Provider Test Client 

   Checks the specified value against the expected value 
   and returns TRUE if the same, else FALSE 
*/
Boolean 
DNSTestClient::goodNameFormat(const String &nf, 
                              Boolean verbose)
{

	// This assumes the only right answer is "IP"

   if (verbose)
      cout<<"Checking NameFormat " << nf << endl;
   return (String::equalNoCase(nf, NAME_FORMAT));
}


/* GoodSearchList method for the DNS Provider Test Client 

   Checks the specified values against the expected array 
   values and returns TRUE if the same, else FALSE 

   Returns "search" field from /etc/resolv.conf file
 */
Boolean 
DNSTestClient::goodSearchList(const Array<String> &src, 
                              Boolean verbose)
{
    Boolean ok = false;
	FILE *arq;
	int i, j, ind = 0, count = 0;
    char *ptr;
    char buffer[150];
    Array<String> srclist;

    // open resolv.conf file to retrieve informations
    if((arq = fopen(RESOLV_CONF, "r")) == NULL)
    	return ok;

	// retrieve search list if exists
    while(!feof(arq)) {
    	memset(buffer, 0, sizeof(buffer));
    	fscanf(arq, "%s", buffer);
    	
    	if(!strlen(buffer))
    		continue;
    	
		// Verify if key is search
		if(IsEqual(buffer, "domain")) {
            ind = DOMAINNAME;
			continue;
        }
        else if(IsEqual(buffer, "nameserver")) {
            ind = ADDRESSES;
			continue;
        }
		else if(IsEqual(buffer, "search")) {
    		ind = SEARCHLIST;
    		continue;
    	}
    	else if(ind == SEARCHLIST) {
    		if(verbose)
    			cout << "Reading " << buffer << endl;
    		
			if(!FindInArray(srclist, String(buffer)))
				srclist.append(String(buffer));
		}
		else
			continue;
    }
    fclose(arq);

    if (verbose) {
    	for(i=0; i<srclist.size(); i++)
      		cout<<"Checking " << srclist[i] << " against SearchList "<<endl;
    }
	
	// List all search list
	if (verbose) {
		cout<<"Checking SearchList " << endl;
		for(i = 0; i < src.size(); i++)
      		cout << src[i] << endl;
    }

	// Test size of srclist array
	if(srclist.size() == 0)
        // Search list not exists
		ok = true;  
	else if(src.size() == srclist.size()) {
        // Search list array have same size of source array
		if(verbose)
			cout <<"Searching search list " << endl;
		for(i=0; i<src.size(); i++) {
			for(j=0; j<srclist.size(); j++) {
				if(srclist[j] == src[i]) 
					count++;
			}
		}
		if(count == src.size())
            // Search list is ok
			ok = true;
	}
	return ok;
}

/*
   GoodAddresses method for the DNS Provider Test Client

   Checks the specified values against the expected array values
   and returns TRUE if the same, else FALSE

   Returns "nameserver" field from /etc/resolv.conf file
*/
Boolean 
DNSTestClient::goodAddresses(const Array<String> &addr, 
                             Boolean verbose)
{
	FILE *arq;
	int i, j, ind = 0, count = 0;
    char *ptr;
    char buffer[150];
    Boolean ok = false;
    Array<String> addrlist;
    
    // open resolv.conf file to retrieve informations
    if((arq = fopen(RESOLV_CONF, "r")) == NULL)
    	return ok;
    
	// retrieve addresses list
    while(!feof(arq)) {
    	memset(buffer, 0, sizeof(buffer));
    	fscanf(arq, "%s", buffer);

    	if(!strlen(buffer))
    		continue;

		// Verify if key is search
		if(IsEqual(buffer, "domain")) {
            ind = DOMAINNAME;
			continue;
        }
        else if(IsEqual(buffer, "search")) {
            ind = SEARCHLIST;
			continue;
        }
    	else if(IsEqual(buffer, "nameserver")) {
    		ind = ADDRESSES;
    		continue;
    	}
    	else if(ind == ADDRESSES) {
    		if(verbose)
    			cout << "Reading " << buffer << endl;
    		
			if(!FindInArray(addrlist, String(buffer)))
				addrlist.append(String(buffer));
		}
		else
			continue;
    }
    fclose(arq);

    if (verbose) {
    	for(i=0; i<addrlist.size(); i++)
      		cout<<"Checking " << addrlist[i] << " against Addresses "<<endl;
    }
	
	// List all search list
	if (verbose) {
		cout<<"Checking Addresses " << endl;
		for(i = 0; i < addr.size(); i++)
      		cout << addr[i] << endl;
    }

	if(addrlist.size() == 0)
        // Addresses list array not exists
		ok = true;
	else if(addr.size() == addrlist.size()) {
		if(verbose)
			cout <<"Searching address list " << endl;
		for(i=0; i<addr.size(); i++) {
			for(j=0; j<addrlist.size(); j++) {
				if(addrlist[j] == addr[i]) 
					count++;
			}
		}
		if(count == addr.size())
            // Addresses list array is ok
			ok = true;
	}
   	return ok;
}

