/***************************************************************************
*   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 "utils.h"
#include <qstring.h>
#include <qapplication.h>
#include <iostream>
#include <qfile.h>
#include <qprocess.h>
#include <qstring.h>
#include <klocale.h>
#include <ksimpleconfig.h>
#include <qdir.h>
#include <kstddirs.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <netdb.h> // name resolving
#include <arpa/inet.h>
#include <qregexp.h>
#include <kmessagebox.h>

//END INCLUDES

Utils::Utils( KVpncConfig* config, QObject *parent, const char *name )
		: QObject( parent, name )
{
	env = new QStringList();
	*env << "LC_ALL=C" << "LANG=C" << "PATH=/bin:/usr/bin:/usr/sbin:/sbin";
	this->config = config;
	retrieveValidNetworkdevice = false;
}

Utils::~Utils()
{
	// 	if(createProcess!=0)
	// 		delete createProcess;
	//
	// 	if (NetworkDeviceTestProcess!=0)
	// 		delete NetworkDeviceTestProcess;
}

bool Utils::isValidIPv4Address( QString Address )
{
	if ( Address.contains( '.' ) != 3 )
		return false;
	else {
		//std::cout << "test1 succeed.\n";
		QString addr = Address;
		int part0 = addr.section( '.', 0, 0 ).toInt();
		int part1 = addr.section( '.', 1, 1 ).toInt();
		int part2 = addr.section( '.', 2, 2 ).toInt();
		int part3 = addr.section( '.', 3, 3 ).toInt();

		//std::cout << "part0 " << part0 << ", part1 " << part1 <<  ", part2 " << part2 << ", part3 " << part3 << "\n";

		if ( ( part0 > 1 && part0 < 255 ) &&
		        ( part1 >= 0 && part1 < 255 ) &&
		        ( part2 >= 0 && part2 < 255 ) &&
		        ( part3 >= 0 && part3 < 255 ) )
			return true;
		else
			return false;
	}
}

bool Utils::isValidIPv4NetworkAddress( QString Address )
{
	if ( isValidIPv4Address( Address ) ) {
		if ( Address.section( '.', 3, 3 ).toInt() == 0 )
			return true;
		else
			return false;
	} else
		return false;
}

bool Utils::isValidIPv4BroadcastAddress( QString Address )
{
	if ( isValidIPv4Address( Address ) ) {
		if ( Address.section( '.', 3, 3 ).toInt() == 255 )
			return true;
		else
			return false;
	} else
		return false;
	return false;
}

bool Utils::isValidIPv4Netmask(QString Netmask)
{
	if ( Netmask.contains( '.' ) != 3 )
		return false;
	else {
		//std::cout << "test1 succeed.\n";
		QString addr = Netmask;
		int part0 = addr.section( '.', 0, 0 ).toInt();
		int part1 = addr.section( '.', 1, 1 ).toInt();
		int part2 = addr.section( '.', 2, 2 ).toInt();
		int part3 = addr.section( '.', 3, 3 ).toInt();

		//std::cout << "part0 " << part0 << ", part1 " << part1 <<  ", part2 " << part2 << ", part3 " << part3 << "\n";

		if ( ( part0 > 254 && part0 <= 255 ) &&
		        ( part1 > 254 && part1 <= 255 ) &&
		        ( part2 >= 0 && part2 <= 255 ) &&
		        ( part3 >= 0 && part3 <= 253 ) )
			return true;
		else
			return false;
	}
}

bool Utils::tunDevExists()
{
	if ( QFile ( "/dev/net/tun" ).exists() )
		return true;
	else
		return false;
}

bool Utils::createTunDev()
{
	createProcess = new QProcess( this );
	connect( createProcess, SIGNAL( readyReadStdout() ), this, SLOT( readStdOutCreateTunDev() ) );
	connect( createProcess, SIGNAL( readyReadStderr() ), this, SLOT( readStdErrCreateTunDev() ) );

	// step one: create directory
	if ( !QDir ( "/dev/net" ).exists() ) {
		createProcess->addArgument( "mkdir" );
		//createProcess->addArgument("-p");
		createProcess->addArgument( "/dev/net" );


		if ( !createProcess->start(env) ) {
			kdError() << "Unable to create tunnel device file!" << endl;
			return false;
		} else {
			// 		while(createProcess->isRunning())
			// 		{ };
			sleep ( 2 );
		}
	}

	// step two: create device node
	createProcess->clearArguments();
	createProcess->addArgument( "/bin/mknod" );
	createProcess->addArgument( "/dev/net/tun" );
	createProcess->addArgument( "c" );
	createProcess->addArgument( "10" );
	createProcess->addArgument( "200" );

	if ( !createProcess->start(env) ) {
		kdError() << "Unable to create tunnel device file!" << endl;
		return false;
	} else
		return true;

	return false;
}

bool Utils::loadKernelModule( QString Name, QApplication *app )
{
	if ( !Name.isEmpty() ) {
		modprobeSuccess = true;
		ModprobeProcess = new QProcess( this );
		ModprobeProcess->addArgument( "/sbin/modprobe" );
		ModprobeProcess->addArgument( Name );

		connect( ModprobeProcess, SIGNAL( readyReadStdout() ), this, SLOT( readStdOutLoadKernelModule() ) );
		connect( ModprobeProcess, SIGNAL( readyReadStderr() ), this, SLOT( readStdErrLoadKernelModule() ) );
		if ( !ModprobeProcess->start( env ) ) {
			kdError() << "Unable to start kernel module loading process!" << endl;
			return false;
		} else {
			while ( ModprobeProcess->isRunning() )
				app->processEvents();
			return modprobeSuccess;
		}

	} else
		return false;
}

bool Utils::unloadKernelModule( QString Name, QApplication *app , bool force)
{
	if ( !Name.isEmpty() ) {
		modprobeSuccess = true;
		ModprobeProcess = new QProcess( this );
		ModprobeProcess->addArgument( "/sbin/rmmod" );

		if (force == true)
			ModprobeProcess->addArgument( "-f" );

		ModprobeProcess->addArgument( Name );

		connect( ModprobeProcess, SIGNAL( readyReadStdout() ), this, SLOT( readStdOutLoadKernelModule() ) );
		connect( ModprobeProcess, SIGNAL( readyReadStderr() ), this, SLOT( readStdErrLoadKernelModule() ) );
		if ( !ModprobeProcess->start( env ) ) {
			kdError() << "Unable to start kernel module loading process!" << endl;
			return false;
		} else {
			while ( ModprobeProcess->isRunning() )
				app->processEvents();
			return modprobeSuccess;
		}

	} else
		return false;
}

bool Utils::doChmod( QString file, QString mode )
{
	QProcess * chmodProcess = new QProcess( this );
	chmodProcess->addArgument( "/bin/chmod" );
	chmodProcess->addArgument( mode );
	chmodProcess->addArgument( file );

	if ( !chmodProcess->start(env) ) {
		// KMessageBox::sorry( this, i18n( "\"%1\" start failed!" ).arg( "PppdUpScript" ) );
		config->appendLogEntry( i18n( "Chmod of %1 failed!" ).arg( file ), config->error );
		return false;
	} else {
		if ( config->KvpncDebugLevel > 0 )
			config->appendLogEntry ( i18n( "chmod of %1 (%2) started." ).arg( file ).arg( mode ) , config->debug );
		while ( chmodProcess->isRunning() )
			config->appPointer->QApplication::processEvents();
		//config->appendLogEntry ( i18n( "\"%1\" finished." ).arg("chmod"),config->info );
		return true;
	}
}

bool Utils::resolvConfAvailable()
{
	bool resolvConfAvailable=false;
	if (QFile("/sbin/resolvconf").exists() && QFile("/etc/init.d/resolvconf").exists())
		resolvConfAvailable=true;
	else
		resolvConfAvailable=false;
	return resolvConfAvailable;
}

QPtrList<ToolInfo>* Utils::getToolList()
{
	QPtrList<ToolInfo> *ToolList = new QPtrList<ToolInfo>();

	//TODO move to KVpncConfig
	QStringList *ToolNamesList = new QStringList();
	ToolNamesList->append( "vpnc" );
	ToolNamesList->append( "vpnclient" );
	ToolNamesList->append( "racoon" );
	ToolNamesList->append( "racoonctl" );
	ToolNamesList->append( "ipsec" ); // freeswan
	ToolNamesList->append( "pppd" );
	ToolNamesList->append( "pptp" );
	ToolNamesList->append( "l2tpd" );
	ToolNamesList->append( "xl2tpd" );
	ToolNamesList->append( "openl2tpd" );
	ToolNamesList->append( "setkey" );
	ToolNamesList->append( "iptables" );
	ToolNamesList->append( "openssl" );
	ToolNamesList->append( "openvpn" );
	ToolNamesList->append( "kill" );
	ToolNamesList->append( "killall" );
	ToolNamesList->append( "ping" );
	ToolNamesList->append( "ip" );
	ToolNamesList->append( "ifconfig" );
	ToolNamesList->append( "route" );
	ToolNamesList->append( "pkcs11-tool" );
	ToolNamesList->append( "bash" );
	ToolNamesList->append( "vtund" );
	ToolNamesList->append( "cisco_cert_mgr" );
	ToolNamesList->append( "tail" );
	ToolNamesList->append( "ssh" );
	ToolNamesList->append( "ksshaskpass" );
	ToolNamesList->append( "gnome-ssh-askpass" );

	ToolInfo *currentTool;
	for ( QStringList::Iterator it = ToolNamesList->begin(); it != ToolNamesList->end(); it++ ) {
		//std::cout << "tool: " << *it << std::endl;

		currentTool = new ToolInfo( *it );
		currentTool->programsInPath =config->programsInPath;
		if ( currentTool->Name == "vpnc" )
			currentTool->TryPath_first = config->pathToVpnc;
		else if (currentTool->Name == "vpnclient")
			currentTool->TryPath_first = config->pathToCiscoVpnc;
		else	if ( currentTool->Name == "ipsec" )
			currentTool->TryPath_first = config->pathToIpsec;
		else	if ( currentTool->Name == "racoon" )
			currentTool->TryPath_first = config->pathToRacoon;
		else	if ( currentTool->Name == "racoonctl" )
			currentTool->TryPath_first = config->pathToRacoonctl;
		else	if ( currentTool->Name == "setkey" )
			currentTool->TryPath_first = config->pathToSetkey;
		else	if ( currentTool->Name == "openvpn" )
			currentTool->TryPath_first = config->pathToOpenvpn;
		else	if ( currentTool->Name == "openssl" )
			currentTool->TryPath_first = config->pathToOpenssl;
		else	if ( currentTool->Name == "pppd" )
			currentTool->TryPath_first = config->pathToPppd;
		else	if ( currentTool->Name == "iptables" )
			currentTool->TryPath_first = config->pathToIptables;
		else	if ( currentTool->Name == "kill" )
			currentTool->TryPath_first = config->pathToKill;
		else	if ( currentTool->Name == "killall" )
			currentTool->TryPath_first = config->pathToKillall;
		else	if ( currentTool->Name == "ping" )
			currentTool->TryPath_first = config->pathToPing;
		else	if ( currentTool->Name == "ip" )
			currentTool->TryPath_first = config->pathToIp;
		else	if ( currentTool->Name == "ifconfig" )
			currentTool->TryPath_first = config->pathToIfconfig;
		else	if ( currentTool->Name == "route" )
			currentTool->TryPath_first = config->pathToRoute;
		else	if ( currentTool->Name == "pptp" )
			currentTool->TryPath_first = config->pathToPptp;
		else	if ( currentTool->Name == "l2tpd" )
			currentTool->TryPath_first = config->pathToL2tpd;
		else	if ( currentTool->Name == "pkcs11-tool" )
			currentTool->TryPath_first = config->pathToPkcs11Tool;
		else	if ( currentTool->Name == "bash" )
			currentTool->TryPath_first = config->InterpreterShell;
		else	if ( currentTool->Name == "vtund" )
			currentTool->TryPath_first = config->pathToVtund;
		else if ( currentTool->Name == "cisco_cert_mgr" )
			currentTool->TryPath_first = config->pathToCiscoCertMgr;
		else if ( currentTool->Name == "tail" )
			currentTool->TryPath_first = config->pathToTail;
		else if ( currentTool->Name == "ssh" )
			currentTool->TryPath_first = config->pathToSsh;
		else if ( currentTool->Name == "ksshaskpass" )
			currentTool->TryPath_first = config->pathToKsshAskpass;
		else if ( currentTool->Name == "gnome-ssh-askpass" )
			currentTool->TryPath_first = config->pathToGnomeSshAskpass;

		ToolList->append( currentTool );
		currentTool->collectToolInfo();
		//currentTool=0L;
		// 			std::cout << "tool: " << currentTool->Name << std::endl;
		// 			std::cout << "Version: " << currentTool->Version << std::endl;
		// 			std::cout << "Path: " << currentTool->PathToExec << std::endl << std::endl;
	}
	ToolList->sort();

	return ToolList;

}

ToolInfo* Utils::getToolInfo( QString name )
{
	ToolInfo * Tool = 0;
	for ( Tool = config->ToolList->first();Tool;Tool = config->ToolList->next() ) {
		if ( Tool->Name == name )
			break;
	}
	return Tool;
}

QString Utils::resolveName( QString Name )
{
	resolvedIP = "";
	resolveFinished = false;

	struct hostent * server_entry;

	// get ip address to server name
	if ( ( server_entry = gethostbyname( Name.ascii() ) ) == NULL )
	{
		std::cout << "gethostbyname failed" << std::endl;
	}
	else
		resolvedIP = QString( inet_ntoa( *( struct in_addr* ) server_entry->h_addr_list[ 0 ] ) );
	return resolvedIP;
}

QString Utils::removeSpecialCharsForFilename( QString filename )
{
	filename.replace( QRegExp( "[*]+" ), "_" );
	filename.replace( QRegExp( "[+] +" ), "_" );
	filename.replace( QRegExp( "[$]+" ), "_" );
	filename.replace( QRegExp( ":+" ), "_" );
	filename.replace( QRegExp( "ï¿œ" ), "_" );
	filename.replace( QRegExp( "ï¿œ" ), "_" );
	filename.replace( QRegExp( "+" ), "_" );
	filename.replace( QRegExp( "ï¿œ" ), "_" );
	filename.replace( QRegExp( "ï¿œ" ), "_" );
	filename.replace( QRegExp( "ï¿œ" ), "_" );
	filename.replace( QRegExp( "ï¿œ" ), "_" );
	filename.replace( "\\" , "_" );
	filename.replace( "/" , "_" );
	filename.replace( QRegExp( ";+" ), "_" );
	filename.replace( QRegExp( " " ), "_" );
	filename.replace( QRegExp( "_+" ), "_" );
	filename.replace(  ")" , "_" );
	filename.replace(  "(" , "_" );
	filename.replace(  " " , "_" );
	return filename;
}

QStringList Utils::getOpenvpnCiphers()
{
	OpenvpnCiphers.clear();
	retrieveOpenvpnCiphers = false;

	ToolInfo *OpenvpnInfo = getToolInfo ( "openvpn" );
	QString pathToOpenvpn = OpenvpnInfo->PathToExec;

	if ( pathToOpenvpn.isEmpty() )
		return OpenvpnCiphers;

	OpenvpnCiphersProcess = new QProcess( this );
	OpenvpnCiphersProcess->addArgument( pathToOpenvpn );
	OpenvpnCiphersProcess->addArgument( "--show-ciphers" );

	connect( OpenvpnCiphersProcess, SIGNAL( readyReadStdout() ), this, SLOT( readStdOutRetriveOpenvpnCiphers() ) );
	connect( OpenvpnCiphersProcess, SIGNAL( readyReadStderr() ), this, SLOT( readStdErrRetriveOpenvpnCiphers() ) );

	if ( !OpenvpnCiphersProcess->start( env ) ) {
		kdError() << "Unable to fetch openvpn ciphers!" << endl;
		return false;
	} else {
		while ( OpenvpnCiphersProcess->isRunning() )
			config->appPointer->processEvents();


		disconnect( OpenvpnCiphersProcess, SIGNAL( readyReadStdout() ), this, SLOT( readStdOutRetriveOpenvpnCiphers() ) );
		disconnect( OpenvpnCiphersProcess, SIGNAL( readyReadStderr() ), this, SLOT( readStdErrRetriveOpenvpnCiphers() ) );

	}
	return OpenvpnCiphers;
}

Utils::IpsecAlgos Utils::getIpsecAlgos()
{

	IpsecAlgos salgos;
	salgos.IpsecIkeEncryptionAlgorithms.clear();
	salgos.IpsecIkeHashAlgorithms.clear();
	salgos.IpsecIkeDhGroups.clear();
	salgos.IpsecEspEncryptionAlgorithms.clear();
	salgos.IpsecEspAuthenticationAlgorithms.clear();
	salgos.IpsecCompressionAlgorithms.clear();
	IpsecAlgoCurrent="";
	retrieveIpsecAlgos = false;

	ToolInfo *IpsecInfo = getToolInfo ( "ipsec" );
	QString pathToIpsec = IpsecInfo->PathToExec;

	if ( pathToIpsec.isEmpty() )
		return salgos;

	IpsecAlgosProcess = new QProcess( this );
	IpsecAlgosProcess->addArgument( pathToIpsec);
	IpsecAlgosProcess->addArgument( "auto" );
	IpsecAlgosProcess->addArgument( "--status" );

	connect( IpsecAlgosProcess, SIGNAL( readyReadStdout() ), this, SLOT( readStdOutRetriveIpsecAlgos() ) );
	connect( IpsecAlgosProcess, SIGNAL( readyReadStderr() ), this, SLOT( readStdErrRetriveIpsecAlgos() ) );

	if ( !IpsecAlgosProcess->start( env ) ) {
		kdError() << "Unable to fetch ipsec algos!" << endl;
		return salgos;
	} else {
		while ( IpsecAlgosProcess->isRunning() )
			config->appPointer->processEvents();


		disconnect( IpsecAlgosProcess, SIGNAL( readyReadStdout() ), this, SLOT( readStdOutRetriveIpsecAlgos() ) );
		disconnect( IpsecAlgosProcess, SIGNAL( readyReadStderr() ), this, SLOT( readStdErrRetriveIpsecAlgos() ) );

	}
	return salgos;
}

Utils::PppdCapabilities Utils::checkPppdCapabilities()
{
		pppdcap.pppdHasMppeRequiredSupport=false;
		pppdcap.pppdHasRequireMppeSupport=false;
		pppdcap.pppdHasReplacedefaultrouteSupport=false;
		pppdcap.pppdHasMppeSupport=false;
		pppdcap.oldPppdStyle=false;
		pppdcap.pppdOk=false;

		// test mppe support of pppd
		testPppdRequireMppe=true;
		testPppdReplacedefaultroute=false;
		testPppdMppeRequiredSupport=false;
		testOldPppdStyle=false;
		testPppdRequireMppe=false;
		testPppdMppeRequired=false;


		/* get pppd info */
		int pppd_version_major = 0;
		int pppd_version_minor = 0;
		int pppd_version_subminor = 0;

		ToolInfo *Tool = Utils ( config ).getToolInfo ( "pppd" );
		if ( !Tool->Version.isEmpty() )
		{
			pppd_version_major = ( Tool->Version.section ( '.', 0, 0 ) ).toInt();
			pppd_version_minor = ( Tool->Version.section ( '.', 1, 1 ) ).toInt();
			pppd_version_subminor = ( Tool->Version.section ( '.', 2, 2 ) ).toInt();
			if ( config->KvpncDebugLevel > 5 )
			{
				config->appendLogEntry ( i18n ( "pppd version (major): \"%1\"" ).arg ( pppd_version_major ) , config->debug );
				config->appendLogEntry ( i18n ( "pppd version (minor): \"%1\"" ).arg ( pppd_version_minor ) , config->debug );
				config->appendLogEntry ( i18n ( "pppd version (subminor): \"%1\"" ).arg ( pppd_version_subminor ) , config->debug );
			}
		}

		if ( pppd_version_major <2 || (pppd_version_major ==2 && pppd_version_minor < 4  )  )
		{
			// pppd < 2.4.0
			if ( config->KvpncDebugLevel > 5 )
				config->appendLogEntry ( i18n ( "pppd version is lower than 2.4.0" ) , config->debug );
			
			pppdcap.RequireMppeOption="";
			pppdcap.Require128BitMppeOption="";
			pppdcap.RefuseMppeOption="";
			pppdcap.Refuse40BitMppeOption="";
			pppdcap.Refuse128BitMppeOption="";

			pppdcap.RequireStatelessOption="";
			pppdcap.RequireStatefulOption="";
			pppdcap.MppeOptionsInALine = false;
			pppdcap.RequireAuthMschapOption="";
			pppdcap.RequireAuthMschapv2Option="";
			pppdcap.RequireAuthPapOption="";
		}

		if  (pppd_version_major ==2 && pppd_version_minor == 4  && (pppd_version_subminor == 0  || pppd_version_subminor == 0 ) )
		{
			// pppd == 2.4.0/2.4.1
			if ( config->KvpncDebugLevel > 5 )
				config->appendLogEntry ( i18n ( "pppd version is 2.4.0" ) , config->debug );
			
			pppdcap.RequireMppeOption="mppe-40";
			pppdcap.Require128BitMppeOption="mppe-128";
			pppdcap.RefuseMppeOption="";
			pppdcap.Refuse40BitMppeOption="";
			pppdcap.Refuse128BitMppeOption="";

			pppdcap.RequireStatelessOption="mppe-stateless";
			pppdcap.RequireStatefulOption="";
			pppdcap.MppeOptionsInALine = false;
			pppdcap.RequireAuthChapOption="";
			pppdcap.RequireAuthChapOption+="require-chap\n";
			pppdcap.RequireAuthChapOption+="refuse-chapms\n";
			pppdcap.RequireAuthChapOption+="refuse-chapms-v2\n";
			pppdcap.RequireAuthChapOption+="refuse-pap\n";
			pppdcap.RequireAuthChapOption+="refuse-eap";
			pppdcap.RequireAuthMschapOption="";
// 			pppdcap.RequireAuthMschapOption+="refuse-chap\n";
			pppdcap.RequireAuthMschapOption+="require-chapms\n";
// 			pppdcap.RequireAuthMschapOption+="require-chapms-v2\n";
			pppdcap.RequireAuthMschapOption+="refuse-pap\n";
			pppdcap.RequireAuthMschapOption+="refuse-eap";
			pppdcap.RequireAuthMschapv2Option="";
// 			pppdcap.RequireAuthMschapv2Option+="refuse-chap\n";
// 			pppdcap.RequireAuthMschapv2Option+="refuse-chapms\n";
			pppdcap.RequireAuthMschapv2Option+="require-chapms-v2\n";
			pppdcap.RequireAuthMschapv2Option+="refuse-pap\nrefuse-eap";
			pppdcap.RequireAuthPapOption="";
			pppdcap.RequireAuthPapOption+="require-pap\n";
			pppdcap.RequireAuthPapOption+="refuse-chap\n";
			pppdcap.RequireAuthPapOption+="refuse-chapms-v2\n";
			pppdcap.RequireAuthPapOption+="refuse-chapms-v2\n";
			pppdcap.RequireAuthPapOption+="refuse-eap";
		}

		if ( ( pppd_version_major ==2 && pppd_version_minor == 4 && pppd_version_subminor >= 2) || pppd_version_major >2  )
		{
			// pppd >= 2.4.2
			if ( config->KvpncDebugLevel > 5 )
				config->appendLogEntry ( i18n ( "pppd version is >= 2.4.2, good" ) , config->debug );
			
			pppdcap.RequireMppeOption="require-mppe";
			pppdcap.Require128BitMppeOption="require-mppe-128";
			pppdcap.RefuseMppeOption="nomppe";
			pppdcap.Refuse40BitMppeOption="nomppe-40";
			pppdcap.Refuse128BitMppeOption="nomppe-128";

			pppdcap.RequireStatelessOption="nomppe-stateful";
			pppdcap.RequireStatefulOption="";
			pppdcap.MppeOptionsInALine = false;
			pppdcap.RequireAuthChapOption="";
			pppdcap.RequireAuthChapOption+="refuse-pap\n";
			pppdcap.RequireAuthChapOption+="refuse-mschap\n";
			pppdcap.RequireAuthChapOption+="refuse-mschap-v2\n";
			pppdcap.RequireAuthChapOption+="refuse-eap";
			pppdcap.RequireAuthMschapOption="";
			pppdcap.RequireAuthMschapOption+="refuse-pap\n";
// 			pppdcap.RequireAuthMschapOption+="refuse-chap\n";
// 			pppdcap.RequireAuthMschapOption+="refuse-mschap-v2\n";
			pppdcap.RequireAuthMschapOption+="refuse-eap";
			pppdcap.RequireAuthMschapv2Option="";
			pppdcap.RequireAuthMschapv2Option+="refuse-pap\n";
// 			pppdcap.RequireAuthMschapv2Option+="refuse-chap\n";
// 			pppdcap.RequireAuthMschapv2Option+="refuse-mschap\n";
			pppdcap.RequireAuthMschapv2Option+="refuse-eap";
			pppdcap.RequireAuthPapOption="";
			pppdcap.RequireAuthPapOption+="refuse-mschap\n";
			pppdcap.RequireAuthPapOption+="refuse-mschap-v2\n";
			pppdcap.RequireAuthPapOption+="refuse-chap\n";
			pppdcap.RequireAuthPapOption+="refuse-eap";
		}


		/* mppe test */

		pppdcap.pppdHasMppeRequiredSupport=true;
		pppdcap.pppdHasRequireMppeSupport=true;
		pppdcap.pppdHasMppeSupport=true;
		// first: new style
		testOldPppdStyle = false;
		testPppdRequireMppe=true;
		testPppdMppeRequired=false;
		TestPppdProcess = new QProcess ( this );
		TestPppdProcess->addArgument ( config->pathToPppd );
		TestPppdProcess->addArgument ( "/dev/null" );
		TestPppdProcess->addArgument ( "require-mppe" );

		TestPppdProcess->setCommunication ( QProcess::Stdin | QProcess::Stdout | QProcess::Stderr | QProcess::DupStderr );
		TestPppdProcess->closeStdin ();

		connect ( TestPppdProcess, SIGNAL ( readyReadStdout() ), this, SLOT ( readPppdtestProcessOutput() ) );
// 		connect ( TestPppdProcess, SIGNAL ( readyReadStderr() ), this, SLOT ( readPppdtestProcessOutput() ) );
		
		if ( !TestPppdProcess->start ( env ) )
		{
			config->appendLogEntry ( i18n ( "unable to start proc (%1)!" ).arg ( i18n ( "Test require-mppe support of pppd" ) ) , KVpncConfig::error );
			pppdcap.pppdOk=false;
		}
		else
		{
			pppdcap.pppdOk=true;
			while ( TestPppdProcess->isRunning() )
				config->appPointer->processEvents();


			if (pppdcap.pppdHasRequireMppeSupport)
			{
				if ( config->KvpncDebugLevel > 0 )
					config->appendLogEntry ( "pppdHasRequireMppeSupport: true", config->debug );
				pppdcap.RequireMppeOption="require-mppe";
				pppdcap.Require128BitMppeOption="require-mppe-128";
				pppdcap.RefuseMppeOption="nomppe";
				pppdcap.Refuse40BitMppeOption="nomppe-40";
				pppdcap.Refuse128BitMppeOption="nomppe-128";
			}
			else
				config->appendLogEntry ( "pppdHasRequireMppeSupport: false", config->debug );

			disconnect ( TestPppdProcess, SIGNAL ( readyReadStdout() ), this, SLOT ( readPppdtestProcessOutput() ) );
			disconnect ( TestPppdProcess, SIGNAL ( readyReadStderr() ), this, SLOT ( readPppdtestProcessOutput() ) );
		}

		delete TestPppdProcess;
		testPppdRequireMppe=false;
		testPppdMppeRequired=true;

		
		TestPppdProcess = new QProcess ( this );
		TestPppdProcess->addArgument ( config->pathToPppd );
		TestPppdProcess->addArgument ( "/dev/null" );
		TestPppdProcess->addArgument ( "mppe");
		TestPppdProcess->addArgument ( "required" );

		TestPppdProcess->setCommunication ( QProcess::Stdin | QProcess::Stdout | QProcess::Stderr | QProcess::DupStderr );
		TestPppdProcess->closeStdin ();

		connect ( TestPppdProcess, SIGNAL ( readyReadStdout() ), this, SLOT ( readPppdtestProcessOutput() ) );
// 		connect ( TestPppdProcess, SIGNAL ( readyReadStderr() ), this, SLOT ( readPppdtestProcessOutput() ) );
		
		if ( !TestPppdProcess->start ( env ) )
		{
			config->appendLogEntry ( i18n ( "unable to start proc (%1)!" ).arg ( i18n ( "Test mppe required support of pppd" ) ), KVpncConfig::error );
			pppdcap.pppdOk=false;
		}
		else
		{
			pppdcap.pppdOk=true;
			while ( TestPppdProcess->isRunning() )
				config->appPointer->processEvents();

			if (pppdcap.pppdHasMppeRequiredSupport)
			{
				if ( config->KvpncDebugLevel > 0 )
						config->appendLogEntry ( "PppdMppeRequired: true", config->debug );

				pppdcap.MppeOptionsInALine = true;

				pppdcap.RequireMppeOption="mppe required";
				pppdcap.Require128BitMppeOption="";
				pppdcap.RefuseMppeOption="nomppe";
				pppdcap.Refuse40BitMppeOption=",no40";
				pppdcap.Refuse128BitMppeOption=",no128";
				pppdcap.RequireStatefulOption="";
				pppdcap.RequireStatelessOption=",stateless";

			}
			else
				config->appendLogEntry ( "PppdMppeRequired: false", config->debug );
			

			disconnect ( TestPppdProcess, SIGNAL ( readyReadStdout() ), this, SLOT ( readPppdtestProcessOutput() ) );
			disconnect ( TestPppdProcess, SIGNAL ( readyReadStderr() ), this, SLOT ( readPppdtestProcessOutput() ) );
		}

		
		delete TestPppdProcess;
		testPppdMppeRequired=false;




		if (pppdcap.pppdHasRequireMppeSupport || pppdcap.pppdHasMppeRequiredSupport)
		{
			pppdcap.pppdHasMppeSupport = true;
			if ( config->KvpncDebugLevel > 0 )
				config->appendLogEntry ( i18n ( " %1 has MPPE support." ) .arg ( config->pathToPppd ), config->debug );
		}
		else
		{
			if ( config->KvpncDebugLevel > 0 )
				config->appendLogEntry ( i18n ( " %1 has no MPPE support." ) .arg ( config->pathToPppd ), config->debug );

		}

		
		/* defaultroute test */
		//unrecognized option 'replacedefaultroute'
		// test defaultroute support of pppd
		testPppdReplacedefaultroute = false;
		TestPppdProcess = new QProcess ( this );
		TestPppdProcess->addArgument ( config->pathToPppd );
		TestPppdProcess->addArgument ( "replacedefaultroute" );
		TestPppdProcess->setCommunication ( QProcess::Stdin | QProcess::Stdout | QProcess::Stderr | QProcess::DupStderr );
		TestPppdProcess->closeStdin ();

		connect ( TestPppdProcess, SIGNAL ( readyReadStdout() ), this, SLOT ( readPppdtestProcessOutput() ) );
// 		connect ( TestPppdProcess, SIGNAL ( readyReadStderr() ), this, SLOT ( readPppdtestProcessOutput() ) );


		if ( !TestPppdProcess->start ( env ) )
		{
			config->appendLogEntry ( i18n ( "unable to start proc (%1)!" ).arg ( i18n ( "Test support of replacedefaultroute pppd" ) ) , config->error );
			pppdcap.pppdOk=false;
		}
		else
		{
			while ( TestPppdProcess->isRunning() )
				config->appPointer->processEvents();

			disconnect ( TestPppdProcess, SIGNAL ( readyReadStdout() ), this, SLOT ( readPppdtestProcessOutput() ) );
			disconnect ( TestPppdProcess, SIGNAL ( readyReadStderr() ), this, SLOT ( readPppdtestProcessOutput() ) );

			if ( pppdcap.pppdHasReplacedefaultrouteSupport )
			{
				if ( config->KvpncDebugLevel > 4 )
					config->appendLogEntry ( i18n ( "Test support of replacedefaultroute pppd: %1" ).arg ( i18n ( "succeded" ) ) , config->debug );
			}
			else
			{
				if ( config->KvpncDebugLevel > 4 )
					config->appendLogEntry ( i18n ( "Test support of replacedefaultroute pppd: %1" ).arg ( i18n ( "failed" ) ) , config->debug );
			}
		}


	return pppdcap;
}

QStringList Utils::getOpenvpnDigests()
{
	OpenvpnDigests.clear();
	retrieveOpenvpnDigests = false;
	OpenvpnDigestCount=0;
	OpenvpnDigestString="";

	ToolInfo *OpenvpnInfo = getToolInfo ( "openvpn" );
	QString pathToOpenvpn = OpenvpnInfo->PathToExec;

	if ( pathToOpenvpn.isEmpty() )
		return OpenvpnDigests;

	OpenvpnDigestProcess = new QProcess( this );
	OpenvpnDigestProcess->addArgument( pathToOpenvpn );
	OpenvpnDigestProcess->addArgument( "--show-digests" );

	connect( OpenvpnDigestProcess, SIGNAL( readyReadStdout() ), this, SLOT( readStdOutRetriveOpenvpnDigests() ) );
	connect( OpenvpnDigestProcess, SIGNAL( readyReadStderr() ), this, SLOT( readStdErrRetriveOpenvpnDigests() ) );

	if ( !OpenvpnDigestProcess->start( env ) ) {
		kdError() << "Unable to fetch openvpn digests!" << endl;
		return false;
	} else {
		while ( OpenvpnDigestProcess->isRunning() )
			config->appPointer->processEvents();

		disconnect( OpenvpnDigestProcess, SIGNAL( readyReadStdout() ), this, SLOT( readStdOutRetriveOpenvpnDigests() ) );
		disconnect( OpenvpnDigestProcess, SIGNAL( readyReadStderr() ), this, SLOT( readStdErrRetriveOpenvpnDigests() ) );

		OpenvpnDigests = QStringList().split("#",OpenvpnDigestString);

		for ( QStringList::Iterator it = OpenvpnDigests.begin(); it != OpenvpnDigests.end(); ++it )
			*it = QString(*it).section(' ',0,0);

	}
	return OpenvpnDigests;
}

Utils::IpsecAlgos Utils::getKernelCrypto()
{
	IpsecAlgos salgos;
	salgos.IpsecIkeEncryptionAlgorithms.clear();
	salgos.IpsecIkeHashAlgorithms.clear();
	salgos.IpsecIkeDhGroups.clear();
	salgos.IpsecEspEncryptionAlgorithms.clear();
	salgos.IpsecEspAuthenticationAlgorithms.clear();
	salgos.IpsecCompressionAlgorithms.clear();
	QString IpsecAlgoNameCurrent="";
	QString IpsecAlgoTypeCurrent="";
	QFile cryptoprocfile( "/proc/crypto" );

	if ( cryptoprocfile.open( IO_ReadOnly ) )
	{
		QTextStream stream( &cryptoprocfile );
		QString line;
		if (config->KvpncDebugLevel > 4)
			std::cout << "Kernel crypto list: " << std::endl;
		while ( !stream.atEnd() ) {
			line = stream.readLine();
			if (line.find("name") > -1 )
			{
				IpsecAlgoNameCurrent = line.section(':',1,1).stripWhiteSpace();
// 				std::cout << "crypto name: " << IpsecAlgoNameCurrent.ascii() << std::endl;
			}
			if (line.find("type") >-1)
			{
				IpsecAlgoTypeCurrent=line.section(':',1,1).stripWhiteSpace();
// 				std::cout << "crypto type: " << IpsecAlgoTypeCurrent.ascii() << std::endl;

				if (IpsecAlgoTypeCurrent != "blkcipher" && IpsecAlgoTypeCurrent == "cipher")
				{
// 					std::cout << "adding cipher algo " << IpsecAlgoNameCurrent << std::endl;
					salgos.IpsecEspEncryptionAlgorithms.append(IpsecAlgoNameCurrent);
				}
				if (IpsecAlgoTypeCurrent == "digest")
				{
// 					std::cout  << "adding digest algo " << IpsecAlgoNameCurrent << std::endl;
					salgos.IpsecEspAuthenticationAlgorithms.append(IpsecAlgoNameCurrent);
				}
				if (IpsecAlgoTypeCurrent == "hash")
				{
// 					std::cout  << "adding hash algo " << IpsecAlgoNameCurrent << std::endl;
					salgos.IpsecIkeHashAlgorithms.append(IpsecAlgoNameCurrent);
				}
				if (IpsecAlgoTypeCurrent == "compression")
				{
// 					std::cout  << "adding compression algo " << IpsecAlgoNameCurrent << std::endl;
					salgos.IpsecCompressionAlgorithms.append(IpsecAlgoNameCurrent);
				}

			}
		}
		cryptoprocfile.close();
		salgos.IpsecIkeEncryptionAlgorithms.sort();
		salgos.IpsecIkeHashAlgorithms.sort();
		salgos.IpsecIkeDhGroups.sort();
		salgos.IpsecEspEncryptionAlgorithms.sort();
		salgos.IpsecEspAuthenticationAlgorithms.sort();
		salgos.IpsecCompressionAlgorithms.sort();
	}
	else
	{
		config->appendLogEntry(i18n("%1 cant be opened!").arg("/proc/crypto"),config->error);
	}
	return salgos;
}

QString Utils::getNameAndPidOfProgramListen( int port )
{
	if ( port == 0 )
		return "";

	ListenPort = port;
	retrieveNameAndPidOfProgramListen = false;

	NameAndPidOfProgramListenProcess = new QProcess( this );
	NameAndPidOfProgramListenProcess->addArgument( config->pathToNetstat );
	NameAndPidOfProgramListenProcess->addArgument( "-ntupl" );

	connect( NameAndPidOfProgramListenProcess, SIGNAL( readyReadStdout() ), this, SLOT( readStdOutGetNameAndPidOfProgramListen() ) );
	connect( NameAndPidOfProgramListenProcess, SIGNAL( readyReadStderr() ), this, SLOT( readStdErrGetNameAndPidOfProgramListen() ) );

	if ( !NameAndPidOfProgramListenProcess->start( env ) ) {
		kdError() << "netstat fails!" << endl;
		return false;
	} else {
		while ( NameAndPidOfProgramListenProcess->isRunning() )
			config->appPointer->processEvents();


		disconnect( NameAndPidOfProgramListenProcess, SIGNAL( readyReadStdout() ), this, SLOT( readStdOutRetriveOpenvpnCiphers() ) );
		disconnect( NameAndPidOfProgramListenProcess, SIGNAL( readyReadStderr() ), this, SLOT( readStdErrRetriveOpenvpnCiphers() ) );

	}
	return NameAndPidOfProgramListen;
}

QString Utils::getEmailAddressOfCert(QString cert)
{
	if (cert.isEmpty())
		return "";

	GetEmailAddressOfCertProcess = new QProcess ( this );
	GetEmailAddressOfCertProcess->setCommunication( QProcess::Stdin | QProcess::Stdout | QProcess::Stderr | QProcess::DupStderr );
	GetEmailAddressOfCertProcess->addArgument( config->pathToOpenssl );
	GetEmailAddressOfCertProcess->addArgument( "x509");
	GetEmailAddressOfCertProcess->addArgument( "-noout");
	GetEmailAddressOfCertProcess->addArgument( "-in");
	GetEmailAddressOfCertProcess->addArgument( cert );
	GetEmailAddressOfCertProcess->addArgument( "-subject");

	connect( GetEmailAddressOfCertProcess, SIGNAL( readyReadStdout() ), this, SLOT( readOutGetEmailAddressOfCert() ) );

	if ( !GetEmailAddressOfCertProcess->start( env ) ) {
		kdError() << "GetEmailAddressOfCertProcess" << endl;
		return false;
	} else {
		while ( GetEmailAddressOfCertProcess->isRunning() )
			config->appPointer->processEvents();
		disconnect( GetEmailAddressOfCertProcess, SIGNAL( readyReadStdout() ), this, SLOT( readOutGetEmailAddressOfCert() ) );
	}

	return EmailAddressOfCert;
}

QStringList Utils::getSmartcardSlots(QString ProviderLib)
{
	SmartcardSlots.clear();

	ToolInfo *Pkcs11ToolInfo = getToolInfo ( "pkcs11-tool" );
	Pkcs11ToolInfo->collectToolInfo();
// 	if (Pkcs11ToolInfo == 0)
// 		return SmartcardSlots;
	QString pathToPkcs11Tool;
	pathToPkcs11Tool = Pkcs11ToolInfo->PathToExec;

	if ( pathToPkcs11Tool.isEmpty() )
		return SmartcardSlots;

	GetSmartcardSlotsProcess = new QProcess( this );
	GetSmartcardSlotsProcess->setCommunication( QProcess::Stdin | QProcess::Stdout | QProcess::Stderr | QProcess::DupStderr );
	GetSmartcardSlotsProcess->addArgument( pathToPkcs11Tool);	
	if (!ProviderLib.isEmpty())
	{
		GetSmartcardSlotsProcess->addArgument( "--module");
		GetSmartcardSlotsProcess->addArgument( ProviderLib );
	}
	GetSmartcardSlotsProcess->addArgument( "-L" );

	connect( GetSmartcardSlotsProcess, SIGNAL( readyReadStdout() ), this, SLOT( readOutGetSmartcardSlots() ) );
	
	if ( !GetSmartcardSlotsProcess->start( env ) ) {
		kdError() << "Unable to fetch smartcard slots via pkcs11-tool!" << endl;
		return false;
	} else {
		while ( GetSmartcardSlotsProcess->isRunning() )
// 			usleep(500);
			config->appPointer->processEvents();

		disconnect( GetSmartcardSlotsProcess, SIGNAL( readyReadStdout() ), this, SLOT( readOutGetSmartcardSlots() ) );

	}
	return SmartcardSlots;
}

QStringList Utils::getSmartcardCertsFromSlot(QString slot,QString IdType,QString ProviderLib)
{
	Pkcs11CertFound=false;
	SmartcardCertsFromSlot.clear();

	if (!IdType.isEmpty())
		this->IdType= IdType;
	else
		this->IdType = "id";

	ToolInfo *Pkcs11ToolInfo = getToolInfo ( "pkcs11-tool" );
	Pkcs11ToolInfo->collectToolInfo();
// 	if (Pkcs11ToolInfo == 0)
// 		return SmartcardSlots;
	QString pathToPkcs11Tool;
	pathToPkcs11Tool = Pkcs11ToolInfo->PathToExec;

	if ( pathToPkcs11Tool.isEmpty() )
		return SmartcardSlots;

	GetSmartcardCertsFromSlotProcess = new QProcess( this );
	GetSmartcardCertsFromSlotProcess->setCommunication( QProcess::Stdin | QProcess::Stdout | QProcess::Stderr | QProcess::DupStderr );
	GetSmartcardCertsFromSlotProcess->addArgument( pathToPkcs11Tool);	
	
	if (!ProviderLib.isEmpty())
	{
		GetSmartcardCertsFromSlotProcess->addArgument( "--module");
		GetSmartcardCertsFromSlotProcess->addArgument( ProviderLib );
	}

	GetSmartcardCertsFromSlotProcess->addArgument( "-O" );

	GetSmartcardCertsFromSlotProcess->addArgument( "--slot" );
	if (!slot.isEmpty())
		GetSmartcardCertsFromSlotProcess->addArgument( slot );
	else
		GetSmartcardCertsFromSlotProcess->addArgument("0");

	connect( GetSmartcardCertsFromSlotProcess, SIGNAL( readyReadStdout() ), this, SLOT( readOutGetSmartcardCertsFromSlot() ) );
	
	if ( !GetSmartcardCertsFromSlotProcess->start( env ) ) {
		kdError() << "Unable to fetch smartcard slots via pkcs11-tool!" << endl;
		return false;
	} else {

		while ( GetSmartcardCertsFromSlotProcess->isRunning() )
// 			usleep(500);
			config->appPointer->processEvents();

		disconnect( GetSmartcardCertsFromSlotProcess, SIGNAL( readyReadStdout() ), this, SLOT( readOutGetSmartcardCertsFromSlot() ) );

	}

	return SmartcardCertsFromSlot;
}

QStringList Utils::getCertsFromCiscoCertStore(QString type)
{

	if (type != "user" && type != "ca" && type != "enrollment")
		type="user";

	if (config->KvpncDebugLevel > 2)
		config->appendLogEntry("getCertsFromCiscoCertStore: "+i18n("type: %1").arg(type),config->debug );

	CertsFromCiscoCertStore.clear();
	CertsFromCiscoCertPos=0;
	
	if ( config->pathToCiscoCertMgr.isEmpty() )
		return CertsFromCiscoCertStore;

	GetCertsFromCiscoCertStoreProcess = new QProcess( this );
	GetCertsFromCiscoCertStoreProcess->setCommunication( QProcess::Stdin | QProcess::Stdout | QProcess::Stderr | QProcess::DupStderr );
	GetCertsFromCiscoCertStoreProcess->addArgument( config->pathToCiscoCertMgr );

	if (type == "user")
		GetCertsFromCiscoCertStoreProcess->addArgument( "-U");
	if (type == "ca")
		GetCertsFromCiscoCertStoreProcess->addArgument( "-R");
	GetCertsFromCiscoCertStoreProcess->addArgument( "-op");
	if (type == "enrollent")
		GetCertsFromCiscoCertStoreProcess->addArgument( "-E");
	GetCertsFromCiscoCertStoreProcess->addArgument( "-op");


	GetCertsFromCiscoCertStoreProcess->addArgument( "list");
	
	connect( GetCertsFromCiscoCertStoreProcess, SIGNAL( readyReadStdout() ), this, SLOT( readOutGetCertsFromCiscoCertStoreSlot() ) );
	
	if ( !GetCertsFromCiscoCertStoreProcess->start( env ) ) {
		kdError() << "Unable to fetch certificates via cisco_cert_mgr!" << endl;
		return false;
	} else {

		while ( GetCertsFromCiscoCertStoreProcess->isRunning() )
// 			usleep(500);
			config->appPointer->processEvents();

		disconnect( GetCertsFromCiscoCertStoreProcess, SIGNAL( readyReadStdout() ), this, SLOT( readOutGetCertsFromCiscoCertStoreSlot() ) );

	}

	return CertsFromCiscoCertStore;
}

bool Utils::getNeedsPassphrase(QString key)
{
	
	if (key.isEmpty() || !QFile(key).exists())
		return false;

	needsPassphrase=false;

	//openssl rsa -noout -in client.key -passin pass:aaa
	
	ToolInfo *OpensslToolInfo = getToolInfo ( "openssl" );
	OpensslToolInfo->collectToolInfo();

	QString pathToOpenssl = OpensslToolInfo->PathToExec;

	if ( pathToOpenssl.isEmpty() )
		return needsPassphrase;

	NeedsPassphraseProcess = new QProcess( this );
	NeedsPassphraseProcess->setCommunication( QProcess::Stdin | QProcess::Stdout | QProcess::Stderr | QProcess::DupStderr );
	NeedsPassphraseProcess->addArgument( pathToOpenssl);
	NeedsPassphraseProcess->addArgument("rsa");
	NeedsPassphraseProcess->addArgument("-noout");
	NeedsPassphraseProcess->addArgument("-in");
	NeedsPassphraseProcess->addArgument(key);
	NeedsPassphraseProcess->addArgument("-passin");
	NeedsPassphraseProcess->addArgument("pass:aaa");
	

	connect( NeedsPassphraseProcess, SIGNAL( readyReadStdout() ), this, SLOT( readOutNeedsPassphrase() ) );
	
	if ( !NeedsPassphraseProcess->start( env ) ) {
		kdError() << "Unable to start openssl!" << endl;
		return false;
	} else {
		while ( NeedsPassphraseProcess->isRunning() )
// 			usleep(500);
			config->appPointer->processEvents();

		disconnect( NeedsPassphraseProcess, SIGNAL( readyReadStdout() ), this, SLOT( readOutNeedsPassphrase() ) );

	}

	return needsPassphrase;
}

QString Utils::getHostname()
{
	Hostname="linux.local";

	GetHostnameProcess = new QProcess( this );
	GetHostnameProcess->addArgument( "hostname" );

	connect( GetHostnameProcess, SIGNAL( readyReadStdout() ), this, SLOT( readStdOutGetHostname() ) );
	connect( GetHostnameProcess, SIGNAL( readyReadStderr() ), this, SLOT( readStdErrGetHostname() ) );
	if ( !GetHostnameProcess->start( env ) ) {
		kdError() << "Unable to start getHostname process!" << endl;
		return false;
	}
	else {
		while ( GetHostnameProcess->isRunning() )
		{
			usleep(200);
		}
		return Hostname;
	}
	
	
}

/* === Slots === */
void Utils::readStdOutCreateTunDev() {
	QString msg = QString( createProcess->readStderr() );
	kdDebug() << "readStdOutCreateTunDev(): " << msg << endl;
}

void Utils::readStdErrCreateTunDev()
{
	QString msg = QString( createProcess->readStderr() );
	kdError() << "readStdErrCreateTunDev" << msg << endl;

}

void Utils::readStdOutLoadKernelModule()
{
	QString msg = QString( ModprobeProcess->readStdout() );
	kdDebug() << "readStdErrreadStdOutLoadKernelModule" << msg << endl;
}

void Utils::readStdErrLoadKernelModule()
{
	QString msg = QString( ModprobeProcess->readStderr() );
	// 	kdDebug() << "readStdErrreadStderrLoadKernelModule" << msg << endl;

	/* FATAL: Module <Name> not found. */
	if ( msg.find( "not found", 0, FALSE ) > -1 ) {
		modprobeSuccess = false;
	}

	if ( msg.find( "could not find module", 0 , FALSE ) > -1 ) {
		modprobeSuccess = false;
	}

	if ( msg.find( "not permitted", 0 , FALSE ) > -1 ) {
		modprobeSuccess = false;
	}
}

void Utils::readStdOutToolsTest()
{
}

void Utils::readStdErrToolsTest()
{
}

void Utils::readStdOutRetriveOpenvpnCiphers()
{
	while ( OpenvpnCiphersProcess->canReadLineStdout() ) {
		QString msg = QString( OpenvpnCiphersProcess->readLineStdout() );
		if ( msg.contains( "default key" ) ) {
			//std::cout << msg.ascii() << std::endl;
			OpenvpnCiphers.append( msg.section( ' ', 0, 0 ) );
		}
	}
}

void Utils::readStdErrRetriveOpenvpnCiphers()
{
	while ( OpenvpnCiphersProcess->canReadLineStderr() ) {
		QString msg = QString( OpenvpnCiphersProcess->readLineStderr() );

	}
}

void Utils::readStdOutRetriveIpsecAlgos()
{
	while ( IpsecAlgosProcess->canReadLineStdout() ) {
		QString msg = QString( IpsecAlgosProcess->readLineStdout() );
		bool newIpsecAlgoFound=false;
// 		std::cout << "[ipsec algos raw] "<< msg.ascii() << std::endl;
		if (msg.find ( "000 algorithm", 0, -1 ) > -1)
		{
			std::cout << "[ipsec algos line] "<< msg.ascii() << std::endl;
			if (msg.find ( "000 algorithm ESP", 0, -1 ) > -1)
			{

					QString Algo = msg.stripWhiteSpace().section(":",1,1).section(",",1,1).section("=",1,1);
					QString MinKeySize = msg.stripWhiteSpace().section(":",1,1).section(",",3,3).section("=",1,1);
					QString MaxKeySize = msg.stripWhiteSpace().section(":",1,1).section(",",4,4).section("=",1,1);
					std::cout << "IKE encryption algo found: \"" << Algo << "\", Min: " << MinKeySize << ", Max: " << MaxKeySize << std::endl;
// 					QStringList AlgoOptList = QStringList::split("-",AlgoOpt);
// 					for (QStringList::Iterator it = AlgoOptList.begin(); it != AlgoOptList.end(); ++it)
// 					{
// 						std::cout << "IKE encryption algo subtypes found: \"" << Algo << "-" << *it << "\"" << std::endl;
// 					}
				}

		}
	}
}

void Utils::readStdErrRetriveIpsecAlgos()
{
	while ( IpsecAlgosProcess->canReadLineStderr() ) {
		QString msg = QString( IpsecAlgosProcess->readLineStderr() );
		std::cout << "[ipsec algos raw err] "<< msg.ascii() << std::endl;
	}
}

void Utils::readPppdtestProcessOutput()
{
	QString msg = "";
	msg += QString ( TestPppdProcess->readStdout() );
// 	msg += QString ( TestPppdProcess->readStderr() );

// 	if ( msg == "" )
// 		return ;



	/* mppe test */
	if (testPppdRequireMppe)
	{
		if (config->KvpncDebugLevel > 2)
			config->appendLogEntry("Testing require-mppe",config->debug);

		if (config->KvpncDebugLevel > 4)
			config->appendLogEntry("[test pppd raw]: "+msg,config->debug);

		if ( msg.contains ( "unrecognized option 'require-mppe'" ) )
		{
			pppdcap.oldPppdStyle = true;
			pppdcap.pppdHasMppeSupport = false;
			pppdcap.pppdHasRequireMppeSupport=false;

			if ( config->KvpncDebugLevel > 4 )
				config->appendLogEntry ( i18n ( "%1 has  no MPPE support using \"require mppe\"." ) .arg ( config->pathToPppd ), config->debug );
		}
		else
		{
			if ( msg.contains ( "The remote system is required to authenticate itself" ) )
			{
				// old style found
				pppdcap.oldPppdStyle = false;
				pppdcap.pppdHasMppeSupport = true;
				pppdcap.pppdHasRequireMppeSupport=true;

				if ( config->KvpncDebugLevel > 0 )
					config->appendLogEntry ( i18n ( "%1 has MPPE support and uses require mppe." ) .arg ( config->pathToPppd ), config->debug );
			}
		}
	}

	if ( testPppdMppeRequired)
	{
		if (config->KvpncDebugLevel > 2)
			config->appendLogEntry("Testing mppe-required",config->debug);

		if (config->KvpncDebugLevel > 4)
			config->appendLogEntry("[test pppd raw]: "+msg,config->debug);

		// try old style
		if ( msg.contains ( "unrecognized option 'mppe'" ) )
		{
			// no mppe support :(
			pppdcap.oldPppdStyle = false;
			pppdcap.pppdHasMppeSupport = false;
			pppdcap.pppdHasMppeRequiredSupport=false;
			if ( config->KvpncDebugLevel > 4 )
				config->appendLogEntry ( i18n ( "%1 has  no MPPE support using \"mppe-required\"." ) .arg ( config->pathToPppd ), config->debug );
		}
		else
		{
			if ( msg.contains ( "The remote system is required to authenticate itself" ) )
			{
				// old style found
				pppdcap.oldPppdStyle = true;
				pppdcap.pppdHasMppeSupport = true;
				pppdcap.pppdHasMppeRequiredSupport=true;

				if ( config->KvpncDebugLevel > 0 )
					config->appendLogEntry ( i18n ( "%1 has MPPE support and uses mppe-required." ) .arg ( config->pathToPppd ), config->debug );
			}
		}
	}


	/* default route test */
	if ( testPppdReplacedefaultroute )
	{

		if (config->KvpncDebugLevel > 1)
			config->appendLogEntry("[test pppd raw]: "+msg,config->debug);

		if ( msg.contains ( "unrecognized option 'replacedefaultroute'" )   )
		{
			pppdcap.pppdHasReplacedefaultrouteSupport = false;

		if (config->KvpncDebugLevel > 1)
			config->appendLogEntry(i18n("Testing %1: %2").arg("replacedefaultroute").arg(i18n("failed")),config->debug);
		}
		else
		{
			pppdcap.pppdHasReplacedefaultrouteSupport = true;
		if (config->KvpncDebugLevel > 1)
			config->appendLogEntry(i18n("Testing %1: %2").arg("replacedefaultroute").arg(i18n("succeded")),config->debug);
		}
	}


}

void Utils::readStdOutRetriveOpenvpnDigests()
{
	while ( OpenvpnDigestProcess->canReadLineStdout() ) {
		QString msg = QString( OpenvpnDigestProcess->readLineStdout() );
		OpenvpnDigestCount+=1;
		if ( OpenvpnDigestCount > 5 ) {
// 			std::cout << msg.simplifyWhiteSpace().ascii() << std::endl;
			OpenvpnDigestString += msg+"#";
		}
	}
}

void Utils::readStdErrRetriveOpenvpnDigests()
{
	while ( OpenvpnDigestProcess->canReadLineStderr() ) {
		QString msg = QString( OpenvpnDigestProcess->readLineStderr() );

	}
}

void Utils::readStdOutGetNameAndPidOfProgramListen()
{
	while ( NameAndPidOfProgramListenProcess->canReadLineStdout() ) {
		QString msg = QString( NameAndPidOfProgramListenProcess->readLineStdout() );
		if ( msg.contains( "/" ) && msg.contains( QString().setNum( ListenPort ) ) && msg.simplifyWhiteSpace().section( ' ', 3, 3 ).section(':',1,1) == QString().setNum( ListenPort )  ) {
			std::cout << msg.ascii() << std::endl;
			NameAndPidOfProgramListen = ( msg.simplifyWhiteSpace().section( ' ', 5, 5 ) );
			if (NameAndPidOfProgramListen.contains( "LISTEN"))
				NameAndPidOfProgramListen = ( msg.simplifyWhiteSpace().section( ' ', 6, 6 ) );
			break;
		}
	}
}

void Utils::readStdErrGetNameAndPidOfProgramListen()
{
	while ( NameAndPidOfProgramListenProcess->canReadLineStderr() ) {
		QString msg = QString( NameAndPidOfProgramListenProcess->readLineStderr() );

	}
}

void Utils::readOutGetEmailAddressOfCert()
{
	while ( GetEmailAddressOfCertProcess->canReadLineStdout() ) {
		QString msg = QString( GetEmailAddressOfCertProcess->readLineStdout() );
		if ( msg.contains( "emailAddress" ) ) {
			std::cout << "msg: " << msg.ascii() << std::endl;
			QStringList fields = QStringList::split( '/', msg);
			for ( QStringList::iterator field = fields.begin();  field != fields.end();++field )
			{
				if (QString (*field).contains("emailAddress"))
				{
					if (config->KvpncDebugLevel > 2)
						std::cout << "field: " << QString(*field).ascii() << std::endl;
					// subject= /C=de/L=WR/O=crissi/CN=Christoph Thielecke/emailAddress=crissi99@gxm.de
					// crissi99@gxm.de
					EmailAddressOfCert = QString(*field).section('=',1,1);
					break;
				}
			}
			break;
		}
	}
}

void Utils::readOutGetSmartcardSlots()
{
	while ( GetSmartcardSlotsProcess->canReadLineStdout() ) {
		QString msg = QString( GetSmartcardSlotsProcess->readLineStdout() );
		
		if ( msg.contains( "Slot" ) && !msg.contains("empty") )
		if ( msg.find( "Slot", 0, FALSE ) > -1 && msg.find( "empty", 0, FALSE ) == -1  )
		{
			//std::cout << msg.ascii() << std::endl;
// 			KMessageBox::information( 0, i18n( "msg: %1" ).arg( msg.stripWhiteSpace() ), QString("foo") );
			// we put in this format: <id>:<name>
			QString id = msg.stripWhiteSpace().section( ' ', 1, 1 );
			QString name = msg.stripWhiteSpace().remove(QString("Slot "+id)).stripWhiteSpace();
			QString slot = id+" : "+name;
			SmartcardSlots.append( slot );
		}
	}
}

void Utils::readOutGetSmartcardCertsFromSlot()
{
	while ( GetSmartcardCertsFromSlotProcess->canReadLineStdout() ) {
		QString msg = QString( GetSmartcardCertsFromSlotProcess->readLineStdout() );
		if ( msg.contains( "Certificate Object" ) ) {
// 			KMessageBox::sorry( 0, QString("msg: "+msg), QString("foo1"),0 );
			Pkcs11CertFound=true;
		}
// 		KMessageBox::information( 0, i18n( "msg: %1" ).arg( msg ), QString("foo") );
		if (IdType == "id")
		{
			if ( msg.contains( "ID:" ) && Pkcs11CertFound==true ) {
				//std::cout << msg.ascii() << std::endl;
				QString msg2 = msg.section( ':', 1, 1 );
				msg2 = msg2.stripWhiteSpace();
// 				KMessageBox::sorry( 0, QString("id: "+msg), QString("foo"),0 );
				SmartcardCertsFromSlot.append( msg2 );
				Pkcs11CertFound=false;
			}
		}
		else if (IdType == "label")
		{
			if ( msg.contains( "label:" ) && Pkcs11CertFound==true ) {
				//std::cout << msg.ascii() << std::endl;
				QString msg2 = msg.section( ':', 1, 1 );
				msg2 = msg2.stripWhiteSpace();
// 				KMessageBox::sorry( 0, QString("label: "+msg2), QString("foo"),0 );
				SmartcardCertsFromSlot.append( msg2 );
				Pkcs11CertFound=false;
			}
		}
		else if (IdType == "subject")
		{
			if ( msg.contains( "Subject:" ) && Pkcs11CertFound==true ) {
				//std::cout << msg.ascii() << std::endl;
				QString msg2 = msg.section( ':', 1, 1 );
				msg2 = msg2.stripWhiteSpace();
// 				KMessageBox::sorry( 0, QString("subject: "+msg), QString("foo"),0 );
				SmartcardCertsFromSlot.append( msg2 );
				Pkcs11CertFound=false;
			}
		}
	}

}

void Utils::readOutGetCertsFromCiscoCertStoreSlot()
{
	while ( GetCertsFromCiscoCertStoreProcess->canReadLineStdout() ) {
		QString msg = QString( GetCertsFromCiscoCertStoreProcess->readLineStdout() );

// samle output :(

// Cisco Systems VPN Client Version 4.8.00 (0490)
// Copyright (C) 1998-2005 Cisco Systems, Inc. All Rights Reserved.
// Client Type(s): Linux
// Running on: Linux 2.6.22-2-686 #1 SMP Fri Aug 31 00:24:01 UTC 2007 i686
// 
// 
//       Cert #          Common Name
//       -------         ------------
// 
//       0               crissi 

// 		if (config->KvpncDebugLevel > 2)
// 			std::cout << "readOutGetCertsFromCiscoCertStoreSlot: " << msg << std::endl;

		if (msg.find("Cert #",0,FALSE) > -1)
			CertsFromCiscoCertPos=1;
		if (CertsFromCiscoCertPos==1 || CertsFromCiscoCertPos ==2 | CertsFromCiscoCertPos ==3)
		{
			CertsFromCiscoCertPos++;
			continue;
		}
		else if (CertsFromCiscoCertPos>=4)
		{
			if (msg.length() > 2)
			{
	// 			"       0               crissi "
				int idx=0; // first non space => 0
				int idx2=0; // second nonspace => c
				for (idx=0;idx<(int)msg.length();idx++)
					if (!msg.at(idx).isSpace())
						break;

// 				if (config->KvpncDebugLevel > 2)
// 					std::cout << "readOutGetCertsFromCiscoCertStoreSlot: idx " << idx << std::endl;

				for (idx2=idx+1;idx2<(int)msg.length();idx2++)
					if (!msg.at(idx2).isSpace())
						break;
// 				if (config->KvpncDebugLevel > 2)
// 					std::cout << "readOutGetCertsFromCiscoCertStoreSlot: idx2 " << idx2 << std::endl;
				QString common_name = msg.right(msg.length()-idx2);
				if (common_name.length() > 0)
				{
// 					if (config->KvpncDebugLevel > 2)
// 						std::cout << "readOutGetCertsFromCiscoCertStoreSlot => cert " << common_name << std::endl;
					CertsFromCiscoCertStore.append( common_name );
				}
			}
		}
	}
}

void Utils::readOutNeedsPassphrase()
{
	while ( NeedsPassphraseProcess->canReadLineStdout() ) {
		QString msg = QString( NeedsPassphraseProcess->readLineStdout() );
// 		KMessageBox::sorry( 0, QString("msg: "+msg), QString("foo1"),0 );
		if ( msg.contains( "unable to load Private Key" ) ) {
			needsPassphrase=true;
		}
	}

}

void Utils::readStdOutGetHostname()
{
	while ( GetHostnameProcess->canReadLineStdout() ) {
		QString msg = QString( GetHostnameProcess->readLineStdout() ).simplifyWhiteSpace().section(' ',0,0);
// 		KMessageBox::sorry( 0, QString("msg: "+msg), QString("foo1"),0 );
		if (!msg.isEmpty())
			Hostname=msg;
	}
}

void Utils::readStdErrGetHostname()
{
	while ( GetHostnameProcess->canReadLineStderr() ) {
		QString msg = QString( GetHostnameProcess->readLineStderr() );
		KMessageBox::error( 0, QString(msg), QString("getHostname()"),0 );
	}
}