/*
 * 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.
 */

#ifndef _User_hh
#define _User_hh

#include <string>

#include "Entry.hh"
#include "AddressBook.hh"
#include "AuthoritiesDB.hh"

#define CERTIFICATES_PATH "Certificates"
#define CA_PATH "CA"
#define CRL_PATH "CRL"
#define P12_PATH "P12"

#define ADDRESSBOOK_FILENAME "AddressBook.conf"
#define PREFERENCES_FILENAME "Preferences.conf"
#define CA_FILENAME "Authorities.conf"
#define PKCS12_FILENAME "P12.conf"


namespace Cryptonit
{

    class User
    {

    private:
	/** This variable contains the user's data */
	Entry* info;

	/** This variable contains the user name */
	std::string login;

	/** User system home directory */
	std::string homeDir;

	/** User configuration file, from which we have loaded it. */
	std::string configFile;

	/** Address book file name */
	std::string addressBookFile;

	/** Certificate Auhtorities file */
	std::string caFile;

	/** User PKCS#12 file */
	std::string p12File;

	/** Directory where certificates are stored */
	std::string certificatesDir;

	/** Directory where CA certificates are stored */
	std::string caCertificatesDir;

	/** Directory where PKCS#12 are stored */
	std::string p12Dir;

	/** Directory were CRL are stored */
	std::string crlDir;


    public: 

	/** User Adress Book */
	AddressBook* addressBook;

	/** CA Database */
	AuthoritiesDB* authorities;


	/** Construct an empty user.
	 *  Call create() method if you want to initialize
	 *  all files and directories.
	 */
	User();


	/** Initialize a User object.
	 *  All of his preferences are loaded, but
	 *  not the AddressBook nor the AuthoritiesDB; at this
	 *  time you have to load it manually.
	 *  All fields are contruscted with the login name.
	 *
	 * @param userLogin : user name
	 *
	 * @note: you can call isUserValid() if you want to test
	 *        the existence of all directories and files.
	 */
	User( const std::string userLogin );


	/** Copy constructor 
	 */
	User( const User &u );
    

	/** Destruct the user.
	 *  Save AddressBook and AuhtoritiesDB on disk.
	 */
	~User();
    
	
	/** Create a new user, if it does not exist, with the
	 *  need directories and files.
	 *
	 *  @param login : the user name
	 */
	bool create( const std::string login );


	/** Remove a user and erase from disk all of his
	 *  data (addressbook, preferences, certificates...
	 */
	void remove();


	/** Write User information in a specified file.
	 *
	 *  @param filename : filename
	 */
	bool saveToFile( const std::string filename ="");
      

	/** Get the login of the user.
	 *
	 */
	std::string getLogin();


	/** Set the login of the user.
	 *
	 * @param _login : the login of the user.
	 */
	void setLogin( const std::string userLogin );
	

	/** Set the login of the user.
	 *
	 * @param _login : the login of the user.
	 */
	void setLogin( const char* userLogin );
	

	/** Return the useer home dir.
	 */
	std::string getHome();


	/** Set the user home dir.
	 *
	 * @param home : home directory
	 */
	void setHome( const std::string home );


	/** Get the data of the user.
	 *
	 */
	Entry* getUserInfos();


	/** Set the data of the user.
	 *
	 * @param userInfo : Entry class
	 */
	void setUserInfo( Entry* userInfo );
	
	/** Return the value of a specified info field.
	 *
	 * @param infoName : the field information name.
	 */
	std::string getInfo( const std::string infoName );

	
	/** Return the values of a specified info field.
	 *
	 * @param infoName : the field information name.
	 */
	std::vector<std::string> getInfos( const std::string infoName );


	/** Set a specific data of the user.
	 *
	 * @param infoName : the field to set.
	 * @param infoValue : the value to set.
	 */
	bool setInfo( const std::string infoName, const std::string infoValue ); 


	/** Set a specific data of the user.
	 *
	 * @param infoName : the field to set.
	 * @param infoValue : the value to set.
	 */
	bool setInfos( const std::string infoName, const std::vector<std::string>& infoValues ); 

	/** Set the directory where certificates are stored
	 * @param dir : the directory
	 */
	void setCertificatesDir(std::string dir);


	/** get the certificate dir
	 * @return the directory where certificates are stored.
	 */
	std::string getCertificatesDir();


	/** Set the directory where CA certificates are stored
	 * @param dir : the directory
	 */
	void setCACertificatesDir(std::string dir);


	/** Get the CA certificate dir
	 * @return the directory where certificates are stored.
	 */
	std::string getCACertificatesDir();


	/** Set the directory where PKCS#12 are stored
	 * @param dir : the directory
	 */
	void setP12Dir(std::string dir);


	/** Get the PKCS#12 dir
	 * @return the directory where PKCS#12 are stored.
	 */
	std::string getP12Dir();

	
	/** Set the directory where CRL are stored
	 * @param dir : the directory
	 */
	void setCRLDir(std::string dir);


	/** Get the CRL dir
	 * @return the directory where PKCS#12 are stored.
	 */
	std::string getCRLDir();
	

	/** Get the config file name.
	 */
	std::string getConfigFile() { return configFile; };


	/** Get the addressbook file name.
	 */
	std::string getAddressBookFile()  { return addressBookFile; };


	/** Get the CA file name.
	 */
	std::string getCAFile() { return caFile; };


	/** Get the P12 file name.
	 */
	std::string getP12File() { return p12File; };


	/** Check if a specified user exists, and contains necessary
	 *  files and directories.
	 *
	 * @param login : the user login name.
	 * @note The files validity is not assured.
	 */
	static bool isUserValid( std::string login );


	/** Return a vector with all valid users.
	 *  A user is considered valid if isUserValid() return true.
	 */
	static std::vector<std::string> getValidUsers();


	/** Add a new Identity from a PKCS#12 file. The PKCS#12 is copied into
	 *  his private dir, certificate and CA extracted and added respectivly
	 *  into the AddressBook and the CA Database.
	 *
	 * @param identityName : the new identity name
	 * @param filename : the PKCS#12 source filename
	 * @param password : the PKCS#12 password
	 *
	 * @return -1 : cannot load PKCS12
	 *         -2 : PKCS#12 already exists
	 *         -3 : identity already exists, or not provided
	 *         -4 : cannot write the certificate in the user dir
	 *         -5 : cannot add identity informations into the addressbook
	 *         -6 : cannot write a CA certificate included in the PKCS12 to the user dir
	 *         -7 : cannot copy PKCS12 to user dir
	 */
	int addIdentityFromP12( const std::string identityName,
				const std::string filename, const std::string password );


	/** Add a new Identity from a PKCS#10 file. The request validity is verified
	 *  with the private key. A PKCS#12 is created and copied into the user
	 *  private dir, certificate and CA extracted and added respectivly
	 *  into the AddressBook and the CA Database.
	 *
	 * @param identityName : the new identity name
	 * @param requestFilename : the request sended to the CA
	 * @param certFilename : the certificate signed by the CA
	 * @param privateKeyFilename : the private key generated with the request
	 * @param privateKeyPass : the private key password
	 *
	 * @return -1 : cannot load PKCS8
	 *         -2 : cannot load PKCS10
	 *         -3 : PKCS8 does not match PKCS10
	 *         -4 : cannot load the certificate
	 *         -5 : cannot create the intermediate PKCS12 object
	 *         -6 : cannot create a temporary file for the PKCS12 into P12/
	 *         -7 : cannot write PKCS12 temporary file into P12/
	 *         -5X : addIdentityFromP12() error where X is the error code
	 */
	int addIdentityFromP10( const std::string identityName,
				const std::string requestFilename, const std::string certFilename,
				const std::string privateKeyFilename, const std::string privateKeyPass );

    };
}
#endif
