/***************************************************************************
*   Copyright (C) 2004 by Christoph Thielecke                             *
*   crissi99@gmx.de                                                       *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
*   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.,                                       *
*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
***************************************************************************/
//BEGIN INCLUDES
#include <kmessagebox.h>
#include <kio/netaccess.h>
#include <ktempfile.h>
#include <klocale.h>
#include <kconfig.h>
#include <kdialogbase.h>
#include <kurlrequester.h>
#include <kcombobox.h>
#include <tqstringlist.h>
#include <tqfile.h>
#include <tqurl.h>
#include <kurl.h>
#include <tqtextstream.h>
#include <tqcheckbox.h>
#include <tqfileinfo.h>
#include <string>

#include <iostream>

#include "importprofiledialog.h"
#include "importcertificatedialog.h"
#include "utils.h"
#include "ciscopasswddecoder.h"
//END INCLUDES

ImportProfileDialog::ImportProfileDialog(KVpncConfig *GlobalConfig, TQWidget *parent, const TQString& caption, TQString file)
		: KDialogBase( parent, "Import_Cisco_PCF_profile", true, caption,
		               KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true )
{
	decodeEncPasswd = false;
	if (!file.isEmpty())
		filename = file;
	else
		filename = "";
	importOk = false;
	this->GlobalConfig= GlobalConfig;

	main = new ImportProfileDialogBase(this);
	setMainWidget(main);
	main->setMinimumSize(main->sizeHint());

	main->FilenameUrlrequester->setFilter( "*.pcf" );
	main->FilenameUrlrequester->setURL(filename);

}


ImportProfileDialog::~ImportProfileDialog()
{
	delete main;
}

void ImportProfileDialog::accept()
{

	//filename="/etc/CiscoSystemsVPNClient/Profiles/hs_harz.pcf";
	filename = main->FilenameUrlrequester->url();
	if ( !filename.isEmpty() )
	{
		f = new TQFile(filename);
		canAccept();
	}

	else
	{
		KMessageBox::sorry( 0, i18n( "File name can not be empty!" ), i18n( "Empty File Name" ) );
	}
}


void ImportProfileDialog::canAccept()
{

	if ( !f->exists() )
	{
		KMessageBox::information( 0, i18n( "File not found." ), i18n( "No File" ) );

		//		emit progress( 100 );
		return ;
	}

	KConfig config( filename, true, false );

	TQStringList grouplist = config.groupList();
	
	if (GlobalConfig->KvpncDebugLevel > 0)
	{
		TQString groups="";
		 for ( TQStringList::Iterator group = grouplist.begin(); group != grouplist.end(); ++group ) 
			groups += TQString(" "+*group);
		GlobalConfig->appendLogEntry(i18n("PCF import: groups found: [ %1 ]").arg(groups), GlobalConfig->debug);
	}
	
	config.setGroup( "main" );

	// sample config

	/*
	[main]
	Description=
	Host = 192.168.13.1
	AuthType=1
	GroupName = hs_harz
	GroupPwd =
	Username = u15119
	SaveUserPassword = 0
	UserPassword =
	NTDomain =
	EnableBackup = 0
	BackupServer =
	EnableMSLogon = 1
	TunnelingMode = 0
	TcpTunnelingPort = 10000
	CertStore = 0
	CertName =
	CertPath =
	CertSubjectName =
	CertSerialHash = 00000000000000000000000000000000
	SendCertChain = 0
	VerifyCertDN =
	DHGroup = 2
	ForceKeepAlives = 0
	PeerTimeout = 90
	EnableLocalLAN = 1 // only reading because we dont want to do this
	EnableSplitDNS = 1
	EnableNAT = 1
	*/
	
	
	VpnAccountData::ConnectionType ConnType = VpnAccountData::cisco;
	TQString ProfileName = TQFileInfo ( f->name().stripWhiteSpace().remove(".pcf").remove(".PCF") ).fileName();
	acc = new VpnAccountData ( ConnType, Utils(this->GlobalConfig).removeSpecialCharsForFilename( ProfileName ));
	
	TQString Description = config.readEntry( "Description", "" );
	
	if (Description.isEmpty())
		Description = config.readEntry("!Description",i18n("Profile imported from file %1.").arg(filename));

	if (!Description.isEmpty())
	{
		if (GlobalConfig->KvpncDebugLevel > 0)
			GlobalConfig->appendLogEntry(i18n("PCF import: description found: %1").arg(Description), GlobalConfig->debug);
		acc->setDescription( Description );
	}
	

	TQString Gateway = config.readEntry( "Host", "" );

	if (Gateway.isEmpty())
		Gateway = config.readEntry( "!Host", "" );

	if (!Gateway.isEmpty())
	{
		if (GlobalConfig->KvpncDebugLevel > 0)
			GlobalConfig->appendLogEntry(i18n("PCF import: gateway found: %1").arg(Gateway), GlobalConfig->debug);
		acc->setGateway( Gateway );
	}
	
	bool useApplicationVersion = false;
	acc->setUseApplicationVersion( useApplicationVersion );

	bool enableBackup = config.readBoolEntry( "EnableBackup" , FALSE );
	TQString BackupServer = config.readEntry( "BackupServer", "" );
	
	TQString GroupName = config.readEntry( "GroupName" , "" );

	if (GroupName.isEmpty())
		GroupName = config.readEntry( "!GroupName", "" );

	if (GroupName.isEmpty())
		GroupName = "importedProfile";

	if (!GroupName.isEmpty())
	{
		if (GlobalConfig->KvpncDebugLevel > 0)
			GlobalConfig->appendLogEntry(i18n("PCF import: group name found: %1").arg(GroupName), GlobalConfig->debug);
		acc->setID( GroupName );
	}
	
	TQString NtDomain = config.readEntry( "NTDomain" );
	if (NtDomain.isEmpty())
		NtDomain = config.readEntry( "!NTDomain", "" );
	
	if (!NtDomain.isEmpty())
	{
		if (GlobalConfig->KvpncDebugLevel > 0)
			GlobalConfig->appendLogEntry(i18n("PCF import: NT domain found: %1").arg(NtDomain), GlobalConfig->debug);
		acc->setNtDomainName( NtDomain );
	}
	
	bool enableMSLogon = config.readBoolEntry( "EnableMSLogon", FALSE );
	bool useNtDomainName = false;
	
	if ( enableMSLogon && !NtDomain.isEmpty() )
		useNtDomainName = true;
		
	TQString CertName = config.readEntry( "CertName", "" );

	if (GlobalConfig->KvpncDebugLevel > 0)
		GlobalConfig->appendLogEntry(i18n("PCF import: certificate name found: %1").arg(CertName), GlobalConfig->debug);

	TQString CertPath = config.readEntry( "CertPath", "" );
	TQString CertSubjectName = config.readEntry( "CertSubjectName", "" );
	TQString CertSerialHash = config.readEntry( "CertSerialHash", "" );
	//	bool SendCertChain = config.readBoolEntry( "SendCertChain" , "" );
	//	bool VerifyCertDN = config.readBoolEntry( "VerifyCertDN", FALSE );
	
	/*
		0 = default, none
		1 = Cisco
	*/
	bool useCertStore=false;
	int CertStore = config.readNumEntry( "CertStore", -1 );
	if (CertStore == 1)
		useCertStore = true;
	if (GlobalConfig->KvpncDebugLevel > 0)
		GlobalConfig->appendLogEntry(i18n("PCF import: certificate should be stored into cisco cert store: %1").arg(TQString().setNum(int(useCertStore))), GlobalConfig->debug);
	
	if (useCertStore)
	{
		// we have to import into the store
		if (!CertName.isEmpty())
		{
			bool CertPathFound = false;
			TQString CertFullPath = CertName;
			if (!TQFile(CertFullPath).exists())
			{
				CertFullPath = CertPath+"/"+CertName;
				if (!TQFile(CertFullPath).exists())
				{
					GlobalConfig->appendLogEntry(i18n("Cisco certificate import: cert not found, skipping."), GlobalConfig->error);
				}
				else
				{
					if (GlobalConfig->KvpncDebugLevel > 0)
						GlobalConfig->appendLogEntry(i18n("Cisco certificate import: cert found at current path."), GlobalConfig->debug);
					CertPathFound = true;
				}
			}
			else
			{
				if (GlobalConfig->KvpncDebugLevel > 0)
						GlobalConfig->appendLogEntry(i18n("Cisco certificate import: cert found at cert path."), GlobalConfig->debug);
				CertPathFound = true;
				
			}
			if (CertPathFound)
			{
				TQStringList OldCiscoCerts  = Utils(GlobalConfig).getCertsFromCiscoCertStore();
				ImportCertificateDialog dlg( this, i18n( "Import certificate..." ).ascii(), GlobalConfig );
				dlg.main->FilenameUrlrequester->setURL(CertFullPath);
				dlg.main->ImporttypeComboBox->setCurrentItem(dlg.ciscouserca); // import user and ca cert
				int result = dlg.exec();
				if (result == TQDialog::Accepted)
				{
					acc->setUseCiscoCertStore(true);
					TQStringList CiscoCerts  = Utils(GlobalConfig).getCertsFromCiscoCertStore();
					for ( TQStringList::Iterator ciscoit = CiscoCerts.begin(); ciscoit != CiscoCerts.end(); ++ciscoit )
					{
						if (OldCiscoCerts.findIndex(TQString(*ciscoit)) < 1 )
						{
							// if it was not in list, then its the new added one.
							acc->setX509Certificate(*ciscoit);
							break;
						}
					}
				}
			}
		}
	}
	{
		acc->setX509Certificate(CertName);
		acc->setCertPath(CertPath);
	}


	int TcpTunnelingPort = config.readNumEntry( "TcpTunnelingPort", 10000 ); //std::cout << "tunneling port: " << TunnelingPort << std::endl;
	/*
	0, the default, specifies IPSec over UDP for NAT transparency
	1 specifies IPSec over TCP for NAT transparency
	*/
	bool useUdp = config.readBoolEntry( "TunnelingMode", 0 );
	acc->setUseUdp( useUdp );
	
	int LocalPort=10000;
	bool useLocalPort = false;
	if (TcpTunnelingPort != 10000)
		useLocalPort = true;
	
	if (useLocalPort && useUdp == false)
	{
		acc->setLocalPort(LocalPort);
		acc->setUseLocalPort(true);
	}
	

	//	bool ForceKeepAlives = config.readBoolEntry( "ForceKeepAlives", FALSE );

	//	bool EnableLocalLAN = config.readBoolEntry( "EnableLocalLAN", FALSE ); // nur auslesen aber immer aus :)
	//	bool EnableSplitDNS = config.readBoolEntry( "EnableSplitDNS", FALSE );


	if (useUdp == false)
	{
		// vpnc does not support TCP :(
		acc->setConnectionType(VpnAccountData::cisco);
	}
	if (useUdp)
	{
		if (GlobalConfig->KvpncDebugLevel > 0)
			GlobalConfig->appendLogEntry(i18n("PCF import: using %1 for tunneling").arg("UDP"), GlobalConfig->debug);
		acc->setUseUdp( true);
	}
	else
	{
		if (GlobalConfig->KvpncDebugLevel > 0)
			GlobalConfig->appendLogEntry(i18n("PCF import: using %1 for tunneling").arg("TCP"), GlobalConfig->debug);
		acc->setUseUdp( false);
	}
	/*
	0, the default, disables IPSec through NAT mode
	1 enables IPSec through NAT mode
	*/
	bool enableNAT = config.readNumEntry("EnableNat", false);
	if (enableNAT)
	{
		if (GlobalConfig->KvpncDebugLevel > 0)
			GlobalConfig->appendLogEntry(i18n("PCF import: enable NAT mode: %1").arg(i18n("yes")), GlobalConfig->debug);
		acc->setUseNat(true);
	}
	else
	{
		if (GlobalConfig->KvpncDebugLevel > 0)
			GlobalConfig->appendLogEntry(i18n("PCF import: enable NAT mode: %1").arg(i18n("no")), GlobalConfig->debug);
		acc->setUseNat(false);
	}
	
	bool useUdpPort= true;

	
// 	if ( TunnelingPort != 10000 )
// 	{
// 		useUdp=true; //FIXME: is this right? I guess its only on udp
// 		useUdpPort = true;
// 	}

	TQString PerfectForwardSecrecy = ""; //TQString("dh"+TQString().setNum(DHGroup));
	//	bool usePerfectForwardSecrety = false;
	bool usePerfectSecrecy = false;
	acc->setPerfectForwardSecrety( PerfectForwardSecrecy );
	acc->setUsePerfectForwardSecrety( usePerfectSecrecy );
	bool useIkeGroup = false;
	TQString IkeGroup;
	int DHGroup = config.readNumEntry( "DHGroup", -1 );
	if (DHGroup != -1 )
	{
		if (GlobalConfig->KvpncDebugLevel > 0)
			GlobalConfig->appendLogEntry(i18n("PCF import: Diffie Hellman group found: %1").arg(TQString().setNum(DHGroup)), GlobalConfig->debug);
 		IkeGroup =  "dh" + TQString().setNum( DHGroup ) ;
		useIkeGroup = true;
		acc->setIkeGroup( IkeGroup );
	}

	int PeerTimeout = config.readNumEntry( "PeerTimeout", -1 );
	if (PeerTimeout > -1 )
	{
		if (GlobalConfig->KvpncDebugLevel > 0)
			GlobalConfig->appendLogEntry(i18n("PCF import: peer timeout found: %1").arg(TQString().setNum(PeerTimeout)), GlobalConfig->debug);
		// read minutes but store seconds
		acc->setPeerTimeout( PeerTimeout*60 );
	}

	TQString Username = config.readEntry( "Username" , "" );
	if (!Username.isEmpty())
	{
		if (GlobalConfig->KvpncDebugLevel > 0)
			GlobalConfig->appendLogEntry(i18n("PCF import: user name  found: %1").arg(Username), GlobalConfig->debug);
		acc->setUserName( Username );
	}
	
	TQString UserPassword = config.readEntry( "UserPassword", "" );
	if (UserPassword.isEmpty())
		UserPassword = config.readEntry( "!UserPassword", "" );
	
	if (!UserPassword.isEmpty())
	{
		if (GlobalConfig->KvpncDebugLevel > 0)
			GlobalConfig->appendLogEntry(i18n("PCF import: clear text user password found: %1").arg(UserPassword), GlobalConfig->debug);
		acc->setUserPassword( UserPassword );
	}

	TQString enc_UserPassword = config.readEntry( "enc_UserPassword", "" );
	if (enc_UserPassword.isEmpty())
		enc_UserPassword = config.readEntry( "!enc_UserPassword", "" );

	if (!enc_UserPassword.isEmpty())
	{
		if (GlobalConfig->KvpncDebugLevel > 0)
			GlobalConfig->appendLogEntry(i18n("PCF import: encrypted user password found: %1").arg(enc_UserPassword), GlobalConfig->debug);
	}
	
	CiscoPasswdDecoder dec (filename);
	TQString userpasswd="";
	TQString grouppasswd="";
	dec.decodePasswords(userpasswd,grouppasswd);
	
	// 	std::cout << "decoded userpasswd: " << userpasswd << std::endl;
	// std::cout << "decoded grouppasswd: " << grouppasswd << std::endl;
	
	bool saveUserPassword = config.readBoolEntry( "SaveUserPassword", FALSE );
	
	if (saveUserPassword == false)
		config.readBoolEntry( "!SaveUserPassword", FALSE );
	
	if ( UserPassword.isEmpty() && userpasswd.isEmpty() )
		saveUserPassword = false;
	
	if (!userpasswd.isEmpty())
	{
		if (GlobalConfig->KvpncDebugLevel > 3)
			GlobalConfig->appendLogEntry(i18n("PCF import: decrypted user password found: %1").arg(userpasswd), GlobalConfig->debug);
		acc->setUserPassword( userpasswd );
	}
	
	if (GlobalConfig->KvpncDebugLevel > 0)
		if (saveUserPassword)
			GlobalConfig->appendLogEntry(i18n("PCF import: save user pass : %1").arg(i18n("yes")), GlobalConfig->debug);
		else
			GlobalConfig->appendLogEntry(i18n("PCF import: save user pass : %1").arg(i18n("no")), GlobalConfig->debug);
	acc->setSaveUserPassword( saveUserPassword );

	bool saveGroupPwd = true;
	TQString GroupPwd = config.readEntry( "GroupPwd" , "" );
	if (GroupPwd.isEmpty())
		GroupPwd = config.readEntry( "!GroupPwd", "" );

	if (!GroupPwd.isEmpty())
	{
		if (GlobalConfig->KvpncDebugLevel > 3)
			GlobalConfig->appendLogEntry(i18n("PCF import: clear text group password found: %1").arg(GroupPwd), GlobalConfig->debug);
		acc->setPreSharedKey( GroupPwd );
	}
	
	TQString enc_GroupPwd = config.readEntry( "enc_GroupPwd", "" );
	
	if (enc_GroupPwd.isEmpty())
		enc_GroupPwd = config.readEntry( "!enc_GroupPwd", "" );
	
	if (!grouppasswd.isEmpty())
	{
		if (GlobalConfig->KvpncDebugLevel > 3)
			GlobalConfig->appendLogEntry(i18n("PCF import: decrypted group password found: %1").arg(grouppasswd), GlobalConfig->debug);
		acc->setPreSharedKey( grouppasswd );
	}
	
	if ( GroupPwd.isEmpty() && grouppasswd.isEmpty())
		saveGroupPwd = false;
	acc->setSavePsk( saveGroupPwd );
	
	if ( Description.isEmpty() )
	{
		Description = ( TQUrl( filename ).fileName() );
		Description = Utils(this->GlobalConfig).removeSpecialCharsForFilename( Description.left( filename.section('/',-1).length() - 4 ));
	}
	
	if ( GroupName.isEmpty() )
	{
		GroupName = Utils(this->GlobalConfig).removeSpecialCharsForFilename( GroupName.left( filename.section('/',-1).length() - 4 ));
	}
	
	/*
	AuthType=
	The authentication type of the user:
	1 = Pre-shared keys (default)
	3 = Digital Certificate using an RSA signature.
	5 = Mutual authentication (hybrid)
	*/
	int AuthType = config.readNumEntry( "AuthType" , -1 );

	if (AuthType==-1)
		AuthType = config.readNumEntry( "!AuthType", -1 );

 	if (GlobalConfig->KvpncDebugLevel > 0)
		if (AuthType ==1)
			GlobalConfig->appendLogEntry(i18n("PCF import: authentication type found: %1").arg(i18n("PSK")), GlobalConfig->debug);
		else if (AuthType ==3)
			GlobalConfig->appendLogEntry(i18n("PCF import: authentication type found: %1").arg(i18n("certificate")), GlobalConfig->debug);
		else if (AuthType ==5)
			GlobalConfig->appendLogEntry(i18n("PCF import: authentication type found: %1").arg(i18n("hybrid")), GlobalConfig->debug);
		else
			GlobalConfig->appendLogEntry(i18n("PCF import: no authentication type found, assuming %1").arg(i18n("PSK")), GlobalConfig->debug);

	if (AuthType == 3 || AuthType == 5)
	{
		// vpnc has no cert support :(
		acc->setConnectionType (VpnAccountData::ciscoorig);
		acc->setAuthType( VpnAccountData::cert);

		if (!CertName.isEmpty())
			acc->setX509Certificate(CertName);
	}
	else if (AuthType == 1 )
		acc->setAuthType( VpnAccountData::psk);
	else
		acc->setAuthType( VpnAccountData::psk);
	
	bool useGlobalIpsecSecret = false;
	acc->setUseGlobalIpsecSecret( useGlobalIpsecSecret );
	
	bool useSingleDes = false;
	acc->setUseSingleDes( useSingleDes );
	
	//acc->setUseAdvancedSettings( useAdvancedSettings );
	acc->setUseAdvancedSettings( true );

	/*
	std::cout << Description
	std::cout << Gateway
	std::cout << AuthType
	std::cout << GroupName
	std::cout << GroupPwd
	std::cout << enc_GroupPwd
	std::cout << Username
	std::cout << saveUserPassword
	std::cout << UserPassword
	std::cout << NtDomain
	std::cout << bool enableBackup
	std::cout << BackupServer
	std::cout << bool enableMSLogon
	std::cout << TunnelingMode
	std::cout << TunnelingPort
	std::cout << CertStore
	std::cout << CertName
	std::cout << CertPath
	std::cout << CertSubjectName
	std::cout << CertSerialHash
	std::cout << SendCertChain
	std::cout << VerifyCertDN
	std::cout << DHGroup
	std::cout << ForceKeepAlives
	std::cout << PeerTimeout
	std::cout << EnableLocalLAN
	std::cout << EnableSplitDNS
	std::cout << saveGroupPwd
	std::cout << usePerfectSecrecy
	std::cout << useSingleDes
	std::cout << useLocalPort
	std::cout << useNtDomainName
	std::cout << useLocalPort
	std::cout << IkeGroup
	std::cout << PerfectForwardSecrecy
	std::cout << useAdvancedSettings
	*/
	/*
	acc.setName( Description );
	acc.setGateway( Gateway );
	acc.setID( GroupName );
	acc.setGroupPassword( GroupPwd );
	acc.setUserName( Username );
	acc.setUserPassword( UserPassword );
	acc.setSaveUserPassword( saveUserPassword );
	acc.setSaveGroupPassword( true );
	//acc.setIkeGroup( TQString IkeGroup );
	acc.setPerfectForwardSecrety( TQString PerfectForwardSecrecy );
	acc.setNtDomainName( TQString Name );
	acc.setApplicationVersion( TQString version );
	acc.setUseSingleDes( bool useSingleDes );
	acc.setLocalPort( int port );
	acc.setUseIkeGroup( bool useIkeGroup);
	acc.setUsePerfectForwardSecrety(bool usePerfectForwardSecrety);
	acc.setUseNtDomainName(bool useNtDomainName);
	acc.setUseApplicationVersion(bool useApplicationVersion);
	acc.setUseLocalPort(bool useLocalPort);
	acc.setUseAdvancedSettings(bool useAdvancedSettings);
	acc.setUseGlobalIpsecSecret(bool useGlobalIpsecSecret);
	*/
	importOk = true;
	//std::cout << "accept" << std::endl;
	TQDialog::accept();
}

