/*
 * The Cryptonit security software suite is developped by IDEALX
 * Cryptonit Team (http://IDEALX.org/ and http://cryptonit.org).
 *
 * Copyright 2003-2006 IDEALX
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 as published by the Free Software Foundation.
 * 
 * This program 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
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301, USA. 
 *
 * In addition, as two special exceptions:
 *
 * 1) IDEALX S.A.S gives permission to:
 *  * link the code of portions of his program with the OpenSSL library under
 *    certain conditions described in each source file
 *  * distribute linked combinations including the two, with respect to the
 *    OpenSSL license and with the GPL
 *
 * You must obey the GNU General Public License in all respects for all of the
 * code used other than OpenSSL. If you modify file(s) with this exception,
 * you may extend this exception to your version of the file(s), but you are
 * not obligated to do so. If you do not wish to do so, delete this exception
 * statement from your version, in all files (this very one along with all
 * source files).

 * 2) IDEALX S.A.S acknowledges that portions of his sourcecode uses (by the
 * way of headers inclusion) some work published by 'RSA Security Inc.'. Those
 * portions are "derived from the RSA Security Inc. PKCS #11Cryptographic
 * Token Interface (Cryptoki)" as described in each individual source file.
 */

#include "ContactInfo.hh"

#include <iostream>


namespace Cryptonit
{

    /* Initialization of the AttributeList member. */
    const char* ContactInfo::AttributeList[][3] = {
	// { id, description, long_description },
	// Values from RFC 2256
	{ "objectClass", "Object Class", "" },
	{ "aliasedObjectName", "Aliased Object Name", "" },
	{ "cn", "Full Name", "" },
	{ "sn", "Family Name", "" },
	{ "c", "Country Code", "Two-letter ISO 3166 country code" },
	{ "l", "Locality", "Contains the name of a locality, such as a city, county or other geographic region." },
	{ "st", "State Full Name", "Contains the full name of a state or province." },
	{ "street", "Physical Address", "" },
	{ "o", "Organization Name", "" },
	{ "ou", "Organizational Unit Name", "" },
	{ "title", "Title", "Contains the title, such as \"Vice President\", of a  person in their organizational context." },
	{ "description", "Description", "Human-readable description of the object." },
	{ "businessCategory", "Oragnization Business Category", "This attribute describes the kind of business performed by an organization." },
	{ "postalAddress", "Postal Address", "" },
	{ "postalCode", "Postal Code", "" },
	{ "postOfficeBox", "Post Office Box", "" },
	{ "physicalDeliveryOfficeName", "Physical Delivery Office Name", "" },
	{ "telephoneNumber", "Telephone Number", "" },
	{ "telexNumber", "Telex Number", "" },
	{ "teletexTerminalIdentifier", "Teletex Terminal Identifier", "" },
	{ "facsimileTelephoneNumber", "Facsimile Telephone Number", "" },
	{ "x121Address", "X121 Address", "" },
	{ "internationaliSDNNumber", "International ISDN Number", "" },
	{ "registeredAddress", "Registered Address", "This attribute holds a postal address suitable for reception of telegrams or expedited documents, where it is necessary to have the recipient accept delivery." },
	{ "destinationIndicator", "Destination Indicator", "This attribute is used for the telegram service." },
	{ "preferredDeliveryMethod", "Preferred Delivery Method", "" },
	{ "presentationAddress", "Presentation Address", "This attribute contains an OSI presentation address." },
	{ "supportedApplicationContext", "Supported Application Context", "This attribute contains the identifiers of OSI application contexts." },
	{ "member", "Member", "" },
	{ "owner", "Owner", "" },
	{ "roleOccupant", "Role Occupant", "" },
	{ "seeAlso", "See Also", "" },
	{ "userPassword", "User Password", "" },
	{ "userCertificate", "User Certificate", "User certificated stored in binary form." },
	{ "cACertificate", "CA Certificate", "Certification Authority in binary form." },
	{ "authorityRevocationList", "Authority Revocation List", "Authority Revocation List stored in binary form." },
	{ "certificateRevocationList", "Certificate Revocation List", "Certificate Revocation List stored in binary form" },
	{ "crossCertificatePair", "Cross Certificate Pair", "Cross Certificate Pair stored in binary form" },
	{ "name", "Name", "" },
	{ "givenName", "Given Name", "The givenName attribute is used to hold the part of a person's name which is not their surname nor middle name." },
	{ "initials", "Initials", "This attribute contains the initials of some or all of an individuals names, but not the surname(s)." },
	{ "generationQualifier", "Generation Qualifer", "This attribute contains the part of the name which typically is the suffix, as in \"IIIrd\"." },
	{ "x500UniqueIdentifier", "X500 Unique Identifier", "This attribute is used to distinguish between objects when a distinguished name has been reused." },
	{ "dnQualifier", "DN Qualifier", "This attribute type specifies disambiguating information to add to the relative distinguished name of an entry." },
	{ "enhancedSearchGuide", "Enhanced Search Guide", "This attribute is for use by X.500 clients in constructing search filters." },
	{ "protocolInformation", "Protocol Information", " This attribute is used in conjunction with the presentationAddress attribute, to provide additional information to the OSI network service." },
	{ "distinguishedName", "Distinguished Name", "This attribute type is not used as the name of the object itself, but it is instead a base type from which attributes with DN syntax inherit." },
	{ "uniqueMember", "Unique Member", "" },
	{ "houseIdentifier", "House Identifier", "This attribute is used to identify a building within a location." },
	{ "supportedAlgorithms", "Supported Algorithms", "Supported Algorithms stored in binary form." },
	{ "deltaRevocationList", "Delta Revocation List", "Delta Revocation List stored in binary form." },
	{ "dmdName", "DMD Name", " The value of this attribute specifies a directory management domain (DMD), the administrative authority which operates the directory server." },
	
	// Values from RFC 2798
	{ "carLicense", "Car License", "Vehicle license or registration plate." },
	{ "departmentNumber", "Department Number", "Identifies a department within an organization." },
	{ "displayName", "Display Name", "Preferred name of a person to be used when displaying entries." },
	{ "employeeNumber", "Employee Number", "Numerically identifies an employee within an organization." },
	{ "employeeType", "Employee Type", "Type of employment for a person." },
	{ "jpegPhoto", "JPEG Photograph", "A JPEG image." },
	{ "preferredLanguage", "Preferred Language", "Preferred written or spoken language for a person." },
	{ "userSMIMECertificate", "User S/MIME Certificate", "PKCS#7 SignedData used to support S/MIME." },
	{ "userPKCS12", "User PKCS #12", "PKCS #12 PFX PDU for exchange of personal identity information." },
	
	// Some pertinent values from RFC 1274
	{ "info", "Information", "The Information attribute type specifies any general information pertinent to a person." },
	{ "roomNumber", "Room Number", "The Room Number attribute type specifies the room number of a person." },
	{ "photo", "Photo", "The Photo attribute type specifies a \"photograph\" for a person." },
	{ "userClass", "User Class", "The User Class attribute type specifies a category of computer user." },
	{ "host", "Host", "The Host attribute type specifies a host computer." },
	{ "manager", "Manager", "The Manager attribute type specifies the manager of a person." },
	{ "homeTelephoneNumber", "Home Telephone Number", "The Home Telephone Number attribute type specifies a home telephone number associated with a person, in the international form." },
	{ "secretary", "Secretary", "The Secretary attribute type specifies the secretary of a person." },
	{ "otherMailbox", "Other Mailbox", "The Other Mailbox attribute type specifies values for electronic mailbox types other than X.400 and rfc822." },
	{ "homePostalAddress", "Home Postal Address", "The Home postal address attribute type specifies a home postal address for a person. This should be limited to up to 6 lines of 30 characters each." },
	{ "personalTitle", "Personal Title", "The Personal Title attribute type specifies a personal title for a person. Examples of personal titles are \"Ms\", \"Dr\", \"Prof\" and \"Rev\"." },
	{ "mobile", "Mobile Telephone Number", "The Mobile Telephone Number attribute type specifies a mobile telephone number associated with a person." },
	{ "pager", "Pager Telephone Number", "The Pager Telephone Number attribute type specifies a pager telephone number for a person" },
	{ "mail", "Electronic Mail", "The Electronic Mail attribute type specifies an electronic mail address for a person" },
	{ "co", "Friendly Country Name", "The Friendly Country Name attribute type specifies names of countries in human readable format." },
	{ "uniqueIdentifier", "Unique identifier", "Can be an institution-wide payroll number" },
	{ "organizationalStatus", "Organisational Status", "The Organisational Status attribute type specifies a category by which a person is often referred to in an organisation." },
	{ "mailPreferenceOption", "Mail Preference Option", "An attribute to allow users to indicate a preference for inclusion of their names on mailing lists (electronic or physical).  The absence of such an attribute should be interpreted as if the attribute was present with value \"no-list-inclusion\"." },
	{ "personalSignature", "Personal Signature", "The Personal Signature attribute type allows for a representation of a person's signature." },
	{ "audio", "Audio", "The Audio attribute type allows the storing of sounds in the Directory." },
	
	//added
	{ "mail2", "Email Address" ,"An alternatif email address" },
	{ "street2" , "Physical Address" , "The end of 'street', if street address is too long" },
	{ "www" , "Web uri" , "A web site uri" },
	{ "workStreet" , "Work physical address" , "" },
	{ "workStreet2" , "Work physical address" , "" },
	{ "workLocation" , "Work physical location" , "" },
	{ "workState" , "Work state" ,"" },
	{ "workPostalCode" , "Work postal code" , "" },
	{ "workCountry" , "Work courntry" , ""},
	{ "workWwww" , "Work website URL" , "" },
	{ NULL, NULL, NULL } 
    };


    ContactInfo::ContactInfo()
    {
	info = new Entry();
    }


    ContactInfo::ContactInfo( const ContactInfo& src )
    {
	info = new Entry( *(src.info) );
    }


    ContactInfo::ContactInfo( Entry& dsEntry )
    {
	info = new Entry();

	Entry::iterator attribute = dsEntry.begin();

	while( attribute != dsEntry.end() ) {
	    // The isSupportedInfo() test is in the addValues method
	  if( ! addValues( attribute.first(), attribute.second() ) )
#ifdef DEBUG
 	      std::cerr << "Cannot add info " << attribute.first() << std::endl;
#endif 
	  attribute++;
	}
    }


    ContactInfo::~ContactInfo()
    {
	delete info;
    }


    bool ContactInfo::addValue( const std::string name, const std::string& value )
    {
	if( isInfoSupported( name ) )
	    return( info->append( name, new Attribute(value) ) );
	else return false;
    }


    bool ContactInfo::addValues( const std::string name, const std::vector<std::string>& values )
    {
	if( isInfoSupported( name ) )
	    return( info->append( name, new Attribute(values) ) );
	else return false;
    }


    bool ContactInfo::addValues( const std::string name, Attribute* attribute )
    {
	if( isInfoSupported( name ) )
	    return( info->append( name, attribute ) );
	else return false;
    }


    std::vector<std::string> ContactInfo::getValues( std::string name )
    {
	if( isInfoSupported( name ) )
	    return( info->getAttributeValues( name ) );
	else return std::vector<std::string>(0);
    }


    std::string ContactInfo::getFirstValue( std::string name )
    {
	if( isInfoSupported( name ) )
	    return( info->getAttributeFirstValue( name ) );
	else return std::string("");
    }


    std::string ContactInfo::getLastValue( std::string name )
    {
	if( isInfoSupported( name ) )
	    return( info->getAttributeLastValue( name ) );
	else return std::string("");
    }


    bool ContactInfo::isInfoSupported( const std::string infoName )
    {
	unsigned int i = 0;

	for( i = 0; AttributeList[i][0] != NULL ; i++ )
	    if( infoName == AttributeList[i][0] )
		return true;
	return false;

// 	if( AttributeList.size() == 0 ) {
// 	    for( i = 0; ExtAttributeList[i][0] != NULL; i++ )
// 		AttributeList[std::string(ExtAttributeList[i][0])] = true;
// 	}

// 	if( AttributeList[infoName] != 0 )
// 	    return true;
// 	else return false;
    }

}
