/*****************************************************************************
 * Copyright (C) 2004-2009 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 package 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 package; if not, write to the Free Software               *
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
 *****************************************************************************/

#include "utils.h"

#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QRegExp>
#include <QtGui/QApplication>
#include <QtAlgorithms>

#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>

#include <arpa/inet.h>
#include <netdb.h> // name resolving
#include <unistd.h>
#include <iostream>

Utils::Utils(KVpncConfig* GlobalConfig, QObject *parent)
        : QObject(parent)
{
    env = new QStringList();
    *env << "LC_ALL=C" << "LANG=C" << "PATH=/bin:/usr/bin:/usr/sbin:/sbin";
    this->GlobalConfig = GlobalConfig;
    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 {
        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();

        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 {
        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();

        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()
{
    // step one: create directory
    if (!QDir("/dev/net").exists()) {
        QDir devdir("/dev/");
        if (!devdir.mkdir("net")) {
            kError() << "Unable to create /dev/net!" << endl;
            return false;
        }
    }

    // step two: create device node

    createProcess = new QProcess();
    QString proc = "/bin/mknod";
    QStringList args;
    args.clear();
    args.append("/dev/net/tun");
    args.append("c");
    args.append("10");
    args.append("200");

    connect(createProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutCreateTunDev()));
    connect(createProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrCreateTunDev()));

    createProcess->setEnvironment(*env);
    createProcess->start(proc, args);
    if (!createProcess->waitForStarted()) {
        kError() << "Unable to create tunnel device file!" << endl;
        disconnect(createProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutCreateTunDev()));
        disconnect(createProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrCreateTunDev()));
        delete createProcess;
        return true;
        return false;
    } else {
        if (GlobalConfig->KvpncDebugLevel > 3)
            GlobalConfig->appendLogEntry(i18n("\"%1\" started." , QString("mknod")), KVpncEnum::debug);
        createProcess->waitForFinished();
        if (GlobalConfig->KvpncDebugLevel > 3)
            GlobalConfig->appendLogEntry(i18n("\"%1\" finished." , QString("mknod")), KVpncEnum::debug);
        disconnect(createProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutCreateTunDev()));
        disconnect(createProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrCreateTunDev()));
        delete createProcess;
        return true;
    }
    return false;
}

bool Utils::loadKernelModule(QString Name, QApplication *)
{
    if (!Name.isEmpty()) {
        modprobeSuccess = true;
        ModprobeProcess = new QProcess(this);
        QString proc = "/sbin/modprobe";
        QStringList args;
        args.append(Name);

        connect(ModprobeProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutLoadKernelModule()));
        connect(ModprobeProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrLoadKernelModule()));
        ModprobeProcess->setEnvironment(*env);
        ModprobeProcess->start(proc, args);
        if (!ModprobeProcess->waitForStarted()) {
            kError() << "Unable to start kernel module loading process!" << endl;
            disconnect(ModprobeProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutLoadKernelModule()));
            disconnect(ModprobeProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrLoadKernelModule()));
            delete ModprobeProcess;
            return false;
        } else {
            if (GlobalConfig->KvpncDebugLevel > 3)
                GlobalConfig->appendLogEntry(i18n("\"%1\" started." , QString("modprobe")), KVpncEnum::debug);
			while ( ModprobeProcess->state() == QProcess::Running ) {
				if (GlobalConfig->appPointer->hasPendingEvents())
					GlobalConfig->appPointer->processEvents();
				usleep(250);
			}
            disconnect(ModprobeProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutLoadKernelModule()));
            disconnect(ModprobeProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrLoadKernelModule()));
			delete ModprobeProcess;
            if (GlobalConfig->KvpncDebugLevel > 3)
                GlobalConfig->appendLogEntry(i18n("\"%1\" finished." , QString("modprobe")), KVpncEnum::debug);
            return modprobeSuccess;
        }

    } else
        return false;
}

bool Utils::unloadKernelModule(QString Name, QApplication * , bool force)
{
    if (!Name.isEmpty()) {
        modprobeSuccess = true;
        ModprobeProcess = new QProcess(this);
        QString proc = "/sbin/rmmod";
        QStringList args;
        if (force == true)
            args.append("-f");

        args.append(Name);

        connect(ModprobeProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutLoadKernelModule()));
        connect(ModprobeProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrLoadKernelModule()));
        ModprobeProcess->setEnvironment(*env);
        ModprobeProcess->start(proc, args);
        if (!ModprobeProcess->waitForStarted()) {
            kError() << "Unable to start kernel module loading process!" << endl;
            return false;
        } else {
			while ( ModprobeProcess->state() == QProcess::Running ) {
				if (GlobalConfig->appPointer->hasPendingEvents())
					GlobalConfig->appPointer->processEvents();
				usleep(250);
			}
			disconnect(ModprobeProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutLoadKernelModule()));
			disconnect(ModprobeProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrLoadKernelModule()));
			delete ModprobeProcess;
            return modprobeSuccess;
        }

    } else
        return false;
}

bool Utils::doChmod(QString file, QString mode)
{
    if (file.isEmpty() || mode.isEmpty())
        return false;
    QProcess *chmodProcess = new QProcess(this);
    QString proc = "chmod";
    QStringList args;
    args.append(mode);
    args.append(file);

    chmodProcess->setEnvironment(*env);
    chmodProcess->start(proc, args);
    if (!chmodProcess->waitForStarted()) {
        // KMessageBox::sorry( this, i18n( "\"%1\" start failed!" , QString("chmod" )) );
        GlobalConfig->appendLogEntry(i18n("Chmod of %1 failed." ,  file), KVpncEnum::error);
        delete chmodProcess;
        return false;
    } else {
        if (GlobalConfig->KvpncDebugLevel > 3)
            GlobalConfig->appendLogEntry(i18n("chmod of %1 (%2) started." ,  file ,  mode) , KVpncEnum::debug);
        chmodProcess->waitForFinished();
        if (GlobalConfig->KvpncDebugLevel > 3)
            GlobalConfig->appendLogEntry(i18n("\"%1\" finished." , QString("chmod")), KVpncEnum::debug);
        delete chmodProcess;
        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;
}

QList<ToolInfo *>* Utils::getToolList()
{
    QList<ToolInfo *> *ToolList = new QList<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");
	ToolNamesList->append("racoonctl");
	ToolNamesList->append("netstat");
	
	ToolInfo *currentTool;
	QList<QString>::iterator it;
	for (it = ToolNamesList->begin(); it != ToolNamesList->end(); ++it) {
		currentTool = new ToolInfo(*it);
		currentTool->programsInPath = GlobalConfig->programsInPath;
		if (currentTool->Name == "vpnc")
			currentTool->TryPath_first = GlobalConfig->pathToVpnc;
		else if (currentTool->Name == "vpnclient")
			currentTool->TryPath_first = GlobalConfig->pathToCiscoVpnc;
		else if (currentTool->Name == "ipsec")
			currentTool->TryPath_first = GlobalConfig->pathToIpsec;
		else if (currentTool->Name == "racoon")
			currentTool->TryPath_first = GlobalConfig->pathToRacoon;
		else if (currentTool->Name == "racoonctl")
			currentTool->TryPath_first = GlobalConfig->pathToRacoonctl;
		else if (currentTool->Name == "setkey")
			currentTool->TryPath_first = GlobalConfig->pathToSetkey;
		else if (currentTool->Name == "openvpn")
			currentTool->TryPath_first = GlobalConfig->pathToOpenvpn;
		else if (currentTool->Name == "openssl")
			currentTool->TryPath_first = GlobalConfig->pathToOpenssl;
		else if (currentTool->Name == "pppd")
			currentTool->TryPath_first = GlobalConfig->pathToPppd;
		else if (currentTool->Name == "iptables")
			currentTool->TryPath_first = GlobalConfig->pathToIptables;
		else if (currentTool->Name == "kill")
			currentTool->TryPath_first = GlobalConfig->pathToKill;
		else if (currentTool->Name == "killall")
			currentTool->TryPath_first = GlobalConfig->pathToKillall;
		else if (currentTool->Name == "ping")
			currentTool->TryPath_first = GlobalConfig->pathToPing;
		else if (currentTool->Name == "ip")
			currentTool->TryPath_first = GlobalConfig->pathToIp;
		else if (currentTool->Name == "ifconfig")
			currentTool->TryPath_first = GlobalConfig->pathToIfconfig;
		else if (currentTool->Name == "route")
			currentTool->TryPath_first = GlobalConfig->pathToRoute;
		else if (currentTool->Name == "pptp")
			currentTool->TryPath_first = GlobalConfig->pathToPptp;
		else if (currentTool->Name == "l2tpd")
			currentTool->TryPath_first = GlobalConfig->pathToL2tpd;
		else if (currentTool->Name == "pkcs11-tool")
			currentTool->TryPath_first = GlobalConfig->pathToPkcs11Tool;
		else if (currentTool->Name == "bash")
			currentTool->TryPath_first = GlobalConfig->InterpreterShell;
		else if (currentTool->Name == "vtund")
			currentTool->TryPath_first = GlobalConfig->pathToVtund;
		else if (currentTool->Name == "cisco_cert_mgr")
			currentTool->TryPath_first = GlobalConfig->pathToCiscoCertMgr;
		else if (currentTool->Name == "tail")
			currentTool->TryPath_first = GlobalConfig->pathToTail;
		else if (currentTool->Name == "ssh")
			currentTool->TryPath_first = GlobalConfig->pathToSsh;
		else if (currentTool->Name == "ksshaskpass")
			currentTool->TryPath_first = GlobalConfig->pathToKsshAskpass;
		else if (currentTool->Name == "gnome-ssh-askpass")
			currentTool->TryPath_first = GlobalConfig->pathToGnomeSshAskpass;
		else if (currentTool->Name == "racoonctl")
			currentTool->TryPath_first = GlobalConfig->pathToRacoonctl;
		else if (currentTool->Name == "netstat")
			currentTool->TryPath_first = GlobalConfig->pathToNetstat;

		currentTool->collectToolInfo();
        ToolList->append(currentTool);
        
        //currentTool=0L;
    }
    qSort(ToolList->begin(), ToolList->end());
    return ToolList;

}

ToolInfo* Utils::getToolInfo(QString name)
{
    ToolInfo * Tool = 0;
    for (int toolIdx = 0; toolIdx < GlobalConfig->ToolList->size(); ++toolIdx) {
        Tool = GlobalConfig->ToolList->at(toolIdx);
        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.toAscii())) != NULL) {
        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);
    QString proc = pathToOpenvpn;
    QStringList args;
    args.append("--show-ciphers");

    connect(OpenvpnCiphersProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutRetrieveOpenvpnCiphers()));
    connect(OpenvpnCiphersProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrRetrieveOpenvpnCiphers()));

    OpenvpnCiphersProcess->setEnvironment(*env);
    OpenvpnCiphersProcess->start(proc, args);
    if (!OpenvpnCiphersProcess->waitForStarted()) {
        kError() << "Unable to fetch openvpn ciphers!" << endl;
        return OpenvpnCiphers;
    } else {
        OpenvpnCiphersProcess->waitForFinished();


        disconnect(OpenvpnCiphersProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutRetrieveOpenvpnCiphers()));
        disconnect(OpenvpnCiphersProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrRetrieveOpenvpnCiphers()));

    }
    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);
    QString proc = pathToIpsec;
    QStringList args;
    args.append("auto");
    args.append("--status");

    connect(IpsecAlgosProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutRetrieveIpsecAlgos()));
    connect(IpsecAlgosProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrRetrieveIpsecAlgos()));

    IpsecAlgosProcess->setEnvironment(*env);
    IpsecAlgosProcess->start(proc, args);
    if (!IpsecAlgosProcess->waitForStarted()) {
        kError() << "Unable to fetch ipsec algos!" << endl;
        return salgos;
    } else {
        IpsecAlgosProcess->waitForFinished();


        disconnect(IpsecAlgosProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutRetrieveIpsecAlgos()));
        disconnect(IpsecAlgosProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrRetrieveIpsecAlgos()));

    }
    return salgos;
}

KVpncConfig::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(GlobalConfig).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 (GlobalConfig->KvpncDebugLevel > 5) {
            GlobalConfig->appendLogEntry(i18n("pppd version (major): \"%1\"" , QString(pppd_version_major)) , KVpncEnum::debug);
            GlobalConfig->appendLogEntry(i18n("pppd version (minor): \"%1\"" , QString(pppd_version_minor)) , KVpncEnum::debug);
            GlobalConfig->appendLogEntry(i18n("pppd version (subminor): \"%1\"" , QString(pppd_version_subminor)) , KVpncEnum::debug);
        }
    }

    if (pppd_version_major < 2 || (pppd_version_major == 2 && pppd_version_minor < 4)) {
        // pppd < 2.4.0
        if (GlobalConfig->KvpncDebugLevel > 5)
            GlobalConfig->appendLogEntry(i18n("pppd version is lower than 2.4.0") , KVpncEnum::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 (GlobalConfig->KvpncDebugLevel > 5)
            GlobalConfig->appendLogEntry(i18n("pppd version is 2.4.0") , KVpncEnum::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 (GlobalConfig->KvpncDebugLevel > 5)
            GlobalConfig->appendLogEntry(i18n("pppd version is >= 2.4.2, good") , KVpncEnum::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);
    QString proc = GlobalConfig->pathToPppd;
    QStringList args;
    args.append("/dev/null");
    args.append("require-mppe");

    TestPppdProcess->setProcessChannelMode(QProcess::MergedChannels);

    connect(TestPppdProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readPppdtestProcessOutput()));
//   connect ( TestPppdProcess, SIGNAL ( readyReadStandardError() ), this, SLOT ( readPppdtestProcessOutput() ) );

    TestPppdProcess->setEnvironment(*env);
    TestPppdProcess->start(proc, args);
    if (!TestPppdProcess->waitForStarted()) {
        GlobalConfig->appendLogEntry(i18n("Unable to start proc (%1)." , QString(i18n("test require-mppe support of pppd"))) , KVpncEnum::error);
        pppdcap.pppdOk = false;
    } else {
        pppdcap.pppdOk = true;
        TestPppdProcess->waitForFinished(5000);


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

        disconnect(TestPppdProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readPppdtestProcessOutput()));
        disconnect(TestPppdProcess, SIGNAL(readyReadStandardError()), this, SLOT(readPppdtestProcessOutput()));
    }

    delete TestPppdProcess;
    testPppdRequireMppe = false;
    testPppdMppeRequired = true;


    TestPppdProcess = new QProcess(this);
    proc = GlobalConfig->pathToPppd;
    args.clear();
    args.append("/dev/null");
    args.append("mppe");
    args.append("required");

    TestPppdProcess->setProcessChannelMode(QProcess::MergedChannels);

    connect(TestPppdProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readPppdtestProcessOutput()));
//   connect ( TestPppdProcess, SIGNAL ( readyReadStandardError() ), this, SLOT ( readPppdtestProcessOutput() ) );

    TestPppdProcess->setEnvironment(*env);
    TestPppdProcess->start(proc, args);
    if (!TestPppdProcess->waitForStarted()) {
        GlobalConfig->appendLogEntry(i18n("Unable to start proc (%1)." , QString(i18n("test mppe required support of pppd"))), KVpncEnum::error);
        pppdcap.pppdOk = false;
    } else {
        pppdcap.pppdOk = true;
		TestPppdProcess->waitForFinished(5000);

        if (pppdcap.pppdHasMppeRequiredSupport) {
            if (GlobalConfig->KvpncDebugLevel > 5)
                GlobalConfig->appendLogEntry("PppdMppeRequired: true", KVpncEnum::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
            if (GlobalConfig->KvpncDebugLevel > 5)
                GlobalConfig->appendLogEntry("PppdMppeRequired: false", KVpncEnum::debug);


        disconnect(TestPppdProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readPppdtestProcessOutput()));
        disconnect(TestPppdProcess, SIGNAL(readyReadStandardError()), this, SLOT(readPppdtestProcessOutput()));
    }


    delete TestPppdProcess;
    testPppdMppeRequired = false;




    if (pppdcap.pppdHasRequireMppeSupport || pppdcap.pppdHasMppeRequiredSupport) {
        pppdcap.pppdHasMppeSupport = true;
        if (GlobalConfig->KvpncDebugLevel > 5)
            GlobalConfig->appendLogEntry(i18n(" %1 has MPPE support." , QString(GlobalConfig->pathToPppd)), KVpncEnum::debug);
    } else {
        if (GlobalConfig->KvpncDebugLevel > 5)
            GlobalConfig->appendLogEntry(i18n(" %1 has no MPPE support." , QString(GlobalConfig->pathToPppd)), KVpncEnum::debug);

    }


    /* defaultroute test */
    //unrecognized option 'replacedefaultroute'
    // test defaultroute support of pppd
    testPppdReplacedefaultroute = false;
    TestPppdProcess = new QProcess(this);
    proc = GlobalConfig->pathToPppd;
    args.clear();
    args.append("replacedefaultroute");
    TestPppdProcess->setProcessChannelMode(QProcess::MergedChannels);

    connect(TestPppdProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readPppdtestProcessOutput()));
//   connect ( TestPppdProcess, SIGNAL ( readyReadStandardError() ), this, SLOT ( readPppdtestProcessOutput() ) );


    TestPppdProcess->setEnvironment(*env);
    TestPppdProcess->start(proc, args);
    if (!TestPppdProcess->waitForStarted()) {
        GlobalConfig->appendLogEntry(i18n("Unable to start proc (%1)." , QString(i18n("test support of replacedefaultroute pppd"))) , KVpncEnum::error);
        pppdcap.pppdOk = false;
    } else {
		TestPppdProcess->waitForFinished(5000);
        disconnect(TestPppdProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readPppdtestProcessOutput()));
        disconnect(TestPppdProcess, SIGNAL(readyReadStandardError()), this, SLOT(readPppdtestProcessOutput()));

        if (pppdcap.pppdHasReplacedefaultrouteSupport) {
            if (GlobalConfig->KvpncDebugLevel > 5)
                GlobalConfig->appendLogEntry(i18n("Test support of replacedefaultroute pppd: %1" , QString(i18n("succeeded"))) , KVpncEnum::debug);
        } else {
            if (GlobalConfig->KvpncDebugLevel > 5)
                GlobalConfig->appendLogEntry(i18n("Test support of replacedefaultroute pppd: %1" , QString(i18n("failed"))) , KVpncEnum::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);
    QString proc = GlobalConfig->pathToOpenvpn;
    QStringList args;
    args.append("--show-digests");

    connect(OpenvpnDigestProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutRetrieveOpenvpnDigests()));
    connect(OpenvpnDigestProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrRetrieveOpenvpnDigests()));

    OpenvpnDigestProcess->setEnvironment(*env);
    OpenvpnDigestProcess->start(proc, args);
    if (!OpenvpnDigestProcess->waitForStarted()) {
        kError() << "Unable to fetch openvpn digests!" << endl;
        return OpenvpnDigests;
    } else {
        OpenvpnDigestProcess->waitForFinished();
        disconnect(OpenvpnDigestProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutRetrieveOpenvpnDigests()));
        disconnect(OpenvpnDigestProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrRetrieveOpenvpnDigests()));

        OpenvpnDigests = OpenvpnDigestString.split("#");

        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(QIODevice::ReadOnly)) {
        QTextStream stream(&cryptoprocfile);
        QString line;
        while (!stream.atEnd()) {
            line = stream.readLine();
            if (line.indexOf("name", Qt::CaseInsensitive) > -1) {
                IpsecAlgoNameCurrent = line.section(':', 1, 1).trimmed();
            }
            if (line.indexOf("type", Qt::CaseInsensitive) > -1) {
                IpsecAlgoTypeCurrent = line.section(':', 1, 1).trimmed();
                if (IpsecAlgoTypeCurrent == "blkcipher" || IpsecAlgoTypeCurrent == "cipher") {
                    salgos.IpsecEspEncryptionAlgorithms.append(IpsecAlgoNameCurrent);
                }
                if (IpsecAlgoTypeCurrent == "digest") {
                    salgos.IpsecEspAuthenticationAlgorithms.append(IpsecAlgoNameCurrent);
                }
                if (IpsecAlgoTypeCurrent == "hash") {
                    salgos.IpsecIkeHashAlgorithms.append(IpsecAlgoNameCurrent);
                }
                if (IpsecAlgoTypeCurrent == "compression") {
                    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 {
        GlobalConfig->appendLogEntry(i18n("%1 cannot be opened.", QString("/proc/crypto")), KVpncEnum::error);
    }
    return salgos;
}

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

    ListenPort = port;
    retrieveNameAndPidOfProgramListen = false;

    NameAndPidOfProgramListenProcess = new QProcess(this);
    QString proc = GlobalConfig->pathToNetstat;
    QStringList args;
    args.append("-ntupl");

    connect(NameAndPidOfProgramListenProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutGetNameAndPidOfProgramListen()));
    connect(NameAndPidOfProgramListenProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrGetNameAndPidOfProgramListen()));

    NameAndPidOfProgramListenProcess->setEnvironment(*env);
    NameAndPidOfProgramListenProcess->start(proc, args);
    if (!NameAndPidOfProgramListenProcess->waitForStarted()) {
        kError() << "netstat fails!" << endl;
        return false;
    } else {
        NameAndPidOfProgramListenProcess->waitForFinished();

        disconnect(NameAndPidOfProgramListenProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutRetrieveOpenvpnCiphers()));
        disconnect(NameAndPidOfProgramListenProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrRetrieveOpenvpnCiphers()));

    }
    return NameAndPidOfProgramListen;
}

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

    GetEmailAddressOfCertProcess = new QProcess(this);
    GetEmailAddressOfCertProcess->setProcessChannelMode(QProcess::MergedChannels);
    QString proc = GlobalConfig->pathToOpenssl;
    QStringList args;
    args.append("x509");
    args.append("-noout");
    args.append("-in");
    args.append(cert);
    args.append("-subject");

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

    GetEmailAddressOfCertProcess->setEnvironment(*env);
    GetEmailAddressOfCertProcess->start(proc, args);
    if (!GetEmailAddressOfCertProcess->waitForStarted()) {
        kError() << "GetEmailAddressOfCertProcess" << endl;
        return false;
    } else {
        GetEmailAddressOfCertProcess->waitForFinished();
        disconnect(GetEmailAddressOfCertProcess, SIGNAL(readyReadStandardOutput()), 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->setProcessChannelMode(QProcess::MergedChannels);
    QString proc = pathToPkcs11Tool;
    QStringList args;
    if (!ProviderLib.isEmpty()) {
        args.append("--module");
        args.append(ProviderLib);
    }
    args.append("-L");

    connect(GetSmartcardSlotsProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutGetSmartcardSlots()));

    GetSmartcardSlotsProcess->setEnvironment(*env);
    GetSmartcardSlotsProcess->start(proc, args);
    if (!GetSmartcardSlotsProcess->waitForStarted()) {
        kError() << "Unable to fetch smartcard slots via pkcs11-tool!" << endl;
        return SmartcardSlots;
    } else {
        GetSmartcardSlotsProcess->waitForFinished();

        disconnect(GetSmartcardSlotsProcess, SIGNAL(readyReadStandardOutput()), 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->setProcessChannelMode(QProcess::MergedChannels);
    QString proc = pathToPkcs11Tool;
    QStringList args;
    if (!ProviderLib.isEmpty()) {
        args.append("--module");
        args.append(ProviderLib);
    }

    args.append("-O");

    args.append("--slot");
    if (!slot.isEmpty())
        args.append(slot);
    else
        args.append("0");

    connect(GetSmartcardCertsFromSlotProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutGetSmartcardCertsFromSlot()));

    GetSmartcardCertsFromSlotProcess->setEnvironment(*env);
    GetSmartcardCertsFromSlotProcess->start(proc, args);
    if (!GetSmartcardCertsFromSlotProcess->waitForStarted()) {
        kError() << "Unable to fetch smartcard slots via pkcs11-tool!" << endl;
        return SmartcardSlots;
    } else {

        GetSmartcardCertsFromSlotProcess->waitForFinished();

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

    }

    return SmartcardCertsFromSlot;
}

QStringList Utils::getCertsFromCiscoCertStore(QString type)
{

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

    if (GlobalConfig->KvpncDebugLevel > 2)
        GlobalConfig->appendLogEntry("getCertsFromCiscoCertStore: " + i18n("type: %1", type), KVpncEnum::debug);

    CertsFromCiscoCertStore.clear();
    CertsFromCiscoCertPos = 0;

    if (GlobalConfig->pathToCiscoCertMgr.isEmpty())
        return CertsFromCiscoCertStore;

    GetCertsFromCiscoCertStoreProcess = new QProcess(this);
    GetCertsFromCiscoCertStoreProcess->setProcessChannelMode(QProcess::MergedChannels);
    QString proc = GlobalConfig->pathToCiscoCertMgr;
    QStringList args;

    if (type == "user")
        args.append("-U");
    if (type == "ca")
        args.append("-R");
    args.append("-op");
    if (type == "enrollent")
        args.append("-E");
    args.append("-op");


    args.append("list");

    connect(GetCertsFromCiscoCertStoreProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutGetCertsFromCiscoCertStoreSlot()));

    GetCertsFromCiscoCertStoreProcess->setEnvironment(*env);
    GetCertsFromCiscoCertStoreProcess->start(proc, args);
    if (!GetCertsFromCiscoCertStoreProcess->waitForStarted()) {
        kError() << "Unable to fetch certificates via cisco_cert_mgr!" << endl;
        return CertsFromCiscoCertStore;
    } else {

        GetCertsFromCiscoCertStoreProcess->waitForFinished();
        disconnect(GetCertsFromCiscoCertStoreProcess, SIGNAL(readyReadStandardOutput()), 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->setProcessChannelMode(QProcess::MergedChannels);
    QString proc = pathToOpenssl;
    QStringList args;
    args.append("rsa");
    args.append("-noout");
    args.append("-in");
    args.append(key);
    args.append("-passin");
    args.append("pass:aaa");


    connect(NeedsPassphraseProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutNeedsPassphrase()));

    NeedsPassphraseProcess->setEnvironment(*env);
    NeedsPassphraseProcess->start(proc, args);
    if (!NeedsPassphraseProcess->waitForStarted()) {
        kError() << "Unable to start openssl!" << endl;
        return false;
    } else {
        NeedsPassphraseProcess->waitForFinished();

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

    }

    return needsPassphrase;
}

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

    GetHostnameProcess = new QProcess(this);
    QString proc = "hostname";
    QStringList args;
    connect(GetHostnameProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutGetHostname()));
    connect(GetHostnameProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdErrGetHostname()));
    GetHostnameProcess->setEnvironment(*env);
    GetHostnameProcess->start(proc, args);
    if (!GetHostnameProcess->waitForStarted()) {
        kError() << "Unable to start getHostname process!" << endl;
        return false;
    } else {
        GetHostnameProcess->waitForFinished();
        return Hostname;
    }

}

/* === Slots === */
void Utils::readStdOutCreateTunDev()
{
    QStringList msg_list = QString(createProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);
        kDebug() << "readStdOutCreateTunDev(): " << msg << endl;
    }
}

void Utils::readStdErrCreateTunDev()
{
    QStringList msg_list = QString(createProcess->readAllStandardError()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);
        kError() << "readStdErrCreateTunDev" << msg << endl;
    }

}

void Utils::readStdOutLoadKernelModule()
{
	if (ModprobeProcess) {
		QStringList msg_list = QString(ModprobeProcess->readAllStandardOutput()).split('\n');
		for (int i = 0; i < msg_list.size(); ++i) {
			QString msg = msg_list.at(i);
			kDebug() << "readStdErrreadStdOutLoadKernelModule" << msg << endl;
		}
	}
}

void Utils::readStdErrLoadKernelModule()
{
	if (ModprobeProcess) {
		QStringList msg_list = QString(ModprobeProcess->readAllStandardError()).split('\n');
		for (int i = 0; i < msg_list.size(); ++i) {
			QString msg = msg_list.at(i);
			//  kDebug() << "readStdErrreadStderrLoadKernelModule" << msg << endl;

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

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

			if (msg.indexOf("not permitted", 0 , Qt::CaseInsensitive) > -1) {
				modprobeSuccess = false;
			}
		}
	}
}

void Utils::readStdOutRetrieveOpenvpnCiphers()
{
    QStringList msg_list = QString(OpenvpnCiphersProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);

        if (msg.contains("default key")) {
            OpenvpnCiphers.append(msg.section(' ', 0, 0));
        }
    }
}

void Utils::readStdErrRetrieveOpenvpnCiphers()
{
    QStringList msg_list = QString(OpenvpnCiphersProcess->readAllStandardError()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);


    }
}

void Utils::readStdOutRetrieveIpsecAlgos()
{
    QStringList msg_list = QString(IpsecAlgosProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);
        if (msg.indexOf("000 algorithm", 0, Qt::CaseInsensitive) > -1) {
            if (msg.indexOf("000 algorithm ESP", 0, Qt::CaseInsensitive) > -1) {
                QString Algo = msg.trimmed().section(":", 1, 1).section(",", 1, 1).section("=", 1, 1);
                QString MinKeySize = msg.trimmed().section(":", 1, 1).section(",", 3, 3).section("=", 1, 1);
                QString MaxKeySize = msg.trimmed().section(":", 1, 1).section(",", 4, 4).section("=", 1, 1);
            }
        }
    }
}

void Utils::readStdErrRetrieveIpsecAlgos()
{
    QStringList msg_list = QString(IpsecAlgosProcess->readAllStandardError()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString line = msg_list.at(i);

    }
}

void Utils::readPppdtestProcessOutput()
{
    QStringList msg_list = QString(TestPppdProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);


        /* mppe test */
        if (testPppdRequireMppe) {
            if (GlobalConfig->KvpncDebugLevel > 5)
                GlobalConfig->appendLogEntry("Testing require-mppe", KVpncEnum::debug);

            if (GlobalConfig->KvpncDebugLevel > 5)
                GlobalConfig->appendLogEntry("[test pppd raw]: " + msg, KVpncEnum::debug);

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

                if (GlobalConfig->KvpncDebugLevel > 5)
                    GlobalConfig->appendLogEntry(i18n("%1 has no MPPE support using \"require mppe\"." , QString(GlobalConfig->pathToPppd)), KVpncEnum::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 (GlobalConfig->KvpncDebugLevel > 5)
                        GlobalConfig->appendLogEntry(i18n("%1 has MPPE support and uses require mppe." , QString(GlobalConfig->pathToPppd)), KVpncEnum::debug);
                }
            }
        }

        if (testPppdMppeRequired) {
            if (GlobalConfig->KvpncDebugLevel > 5)
                GlobalConfig->appendLogEntry("Testing mppe-required", KVpncEnum::debug);

            if (GlobalConfig->KvpncDebugLevel > 5)
                GlobalConfig->appendLogEntry("[test pppd raw]: " + msg, KVpncEnum::debug);

            // try old style
            if (msg.contains("unrecognized option 'mppe'")) {
                // no mppe support :(
                pppdcap.oldPppdStyle = false;
                pppdcap.pppdHasMppeSupport = false;
                pppdcap.pppdHasMppeRequiredSupport = false;
                if (GlobalConfig->KvpncDebugLevel > 5)
                    GlobalConfig->appendLogEntry(i18n("%1 has no MPPE support using \"mppe-required\"." , QString(GlobalConfig->pathToPppd)), KVpncEnum::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 (GlobalConfig->KvpncDebugLevel > 5)
                        GlobalConfig->appendLogEntry(i18n("%1 has MPPE support and uses mppe-required." , QString(GlobalConfig->pathToPppd)), KVpncEnum::debug);
                }
            }
        }


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

            if (GlobalConfig->KvpncDebugLevel > 5)
                GlobalConfig->appendLogEntry("[test pppd raw]: " + msg, KVpncEnum::debug);

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

                if (GlobalConfig->KvpncDebugLevel > 5)
                    GlobalConfig->appendLogEntry(i18n("Testing %1: %2", QString("replacedefaultroute"), QString("failed")), KVpncEnum::debug);
            } else {
                pppdcap.pppdHasReplacedefaultrouteSupport = true;
                if (GlobalConfig->KvpncDebugLevel > 5)
                    GlobalConfig->appendLogEntry(i18n("Testing %1: %2", QString("replacedefaultroute"), i18n("succeeded")), KVpncEnum::debug);
            }
        }
    }

}

void Utils::readStdOutRetrieveOpenvpnDigests()
{
    QStringList msg_list = QString(OpenvpnDigestProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);

        OpenvpnDigestCount += 1;
        if (OpenvpnDigestCount > 5) {
            OpenvpnDigestString += msg + "#";
        }
    }
}

void Utils::readStdErrRetrieveOpenvpnDigests()
{
    QStringList msg_list = QString(OpenvpnDigestProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);

    }
}

void Utils::readStdOutGetNameAndPidOfProgramListen()
{
    QString listenPortString = QString().setNum(ListenPort);
    QStringList msg_list = QString(NameAndPidOfProgramListenProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);

        if (msg.contains("/") && msg.contains(listenPortString) && msg.simplified().section(' ', 3, 3).section(':', 1, 1) == listenPortString) {
            NameAndPidOfProgramListen = (msg.simplified().section(' ', 5, 5));
            if (NameAndPidOfProgramListen.contains("LISTEN")) {
                NameAndPidOfProgramListen = (msg.simplified().section(' ', 6, 6));
            }
            break;
        }
    }
}

void Utils::readStdErrGetNameAndPidOfProgramListen()
{
    QStringList msg_list = QString(NameAndPidOfProgramListenProcess->readAllStandardError()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);

    }
}

void Utils::readOutGetEmailAddressOfCert()
{
    QStringList msg_list = QString(GetEmailAddressOfCertProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);
        if (msg.contains("emailAddress")) {
            QStringList fields = msg.split('/');
            for (QStringList::iterator field = fields.begin();  field != fields.end();++field) {
                if (QString(*field).contains("emailAddress")) {
                    // 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()
{
    QStringList msg_list = QString(GetSmartcardSlotsProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);
        if (msg.contains("Slot") && !msg.contains("empty"))
            if (!msg.contains("Slot", Qt::CaseInsensitive) > -1 && msg.indexOf("empty",  Qt::CaseInsensitive)) {
//    KMessageBox::information( 0, i18n( "msg: %1" , QString(msg.trimmed() )), QString("foo") );
                // we put in this format: <id>:<name>
                QString id = msg.trimmed().section(' ', 1, 1);
                QString name = msg.trimmed().remove(QString("Slot " + id)).trimmed();
                QString slot = id + " : " + name;
                SmartcardSlots.append(slot);
            }
    }
}

void Utils::readOutGetSmartcardCertsFromSlot()
{
    QStringList msg_list = QString(GetSmartcardCertsFromSlotProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);
        if (msg.contains("Certificate Object")) {
//    KMessageBox::sorry( 0, QString("msg: "+msg), QString("foo1"),0 );
            Pkcs11CertFound = true;
        }
//   KMessageBox::information( 0, i18n( "msg: %1" , QString( msg )), QString("foo") );
        if (IdType == "id") {
            if (msg.contains("ID:") && Pkcs11CertFound == true) {
                QString msg2 = msg.section(':', 1, 1);
                msg2 = msg2.trimmed();
//     KMessageBox::sorry( 0, QString("id: "+msg), QString("foo"),0 );
                SmartcardCertsFromSlot.append(msg2);
                Pkcs11CertFound = false;
            }
        } else if (IdType == "label") {
            if (msg.contains("label:") && Pkcs11CertFound == true) {
                QString msg2 = msg.section(':', 1, 1);
                msg2 = msg2.trimmed();
//     KMessageBox::sorry( 0, QString("label: "+msg2), QString("foo"),0 );
                SmartcardCertsFromSlot.append(msg2);
                Pkcs11CertFound = false;
            }
        } else if (IdType == "subject") {
            if (msg.contains("Subject:") && Pkcs11CertFound == true) {
                QString msg2 = msg.section(':', 1, 1);
                msg2 = msg2.trimmed();
//     KMessageBox::sorry( 0, QString("subject: "+msg), QString("foo"),0 );
                SmartcardCertsFromSlot.append(msg2);
                Pkcs11CertFound = false;
            }
        }
    }
}

void Utils::readOutGetCertsFromCiscoCertStoreSlot()
{
    QStringList msg_list = QString(GetCertsFromCiscoCertStoreProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);


// 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 (msg.indexOf("Cert #", 0, Qt::CaseInsensitive) > -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;

                for (idx2 = idx + 1;idx2 < (int)msg.length();idx2++)
                    if (!msg.at(idx2).isSpace())
                        break;

                QString common_name = msg.right(msg.length() - idx2);
                if (common_name.length() > 0) {
                    CertsFromCiscoCertStore.append(common_name);
                }
            }
        }
    }
}

void Utils::readOutNeedsPassphrase()
{
    QStringList msg_list = QString(NeedsPassphraseProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);
//   KMessageBox::sorry( 0, QString("msg: "+msg), QString("foo1"),0 );
        if (msg.contains("unable to load Private Key")) {
            needsPassphrase = true;
        }
    }

}

void Utils::readStdOutGetHostname()
{
    QStringList msg_list = QString(GetHostnameProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i).simplified().section(' ', 0, 0);
//   KMessageBox::sorry( 0, QString("msg: "+msg), QString("foo1"),0 );
        if (!msg.isEmpty())
            Hostname = msg;
    }
}

void Utils::readStdErrGetHostname()
{
    QStringList msg_list = QString(GetHostnameProcess->readAllStandardError()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString msg = msg_list.at(i);
        KMessageBox::error(0, QString(msg), QString("getHostname()"), 0);
    }
}


QString Utils::dec2bin(int n)
{
	if (0 == n)
	{
		return "0";
	}
	else
	{
		QString ret ="";
		QString ret2 = dec2bin(n/2);
		ret+= ret2;
		if(n % 2)
			ret +="1";
		else
			ret+= "0";
		return ret;
	}
}

int Utils::dottedIpv4Netmask2NetmaskBytes(QString dottedIpv4Netmask)
{
	if (dottedIpv4Netmask.isEmpty() || dottedIpv4Netmask.contains( '.' ) != 3)
		return 0;
	int byteSetCount =0;
	int part0 = dottedIpv4Netmask.section( '.', 0, 0 ).toInt();
	int part1 = dottedIpv4Netmask.section( '.', 1, 1 ).toInt();
	int part2 = dottedIpv4Netmask.section( '.', 2, 2 ).toInt();
	int part3 = dottedIpv4Netmask.section( '.', 3, 3 ).toInt();
	
// 	std::cout << "part0: " << part0 << std::endl;
// 	std::cout << "part1: " << part1 << std::endl;
// 	std::cout << "part2: " << part2 << std::endl;
// 	std::cout << "part3: " << part3 << std::endl;
	QString block="";
	QString block0 = dec2bin(part0);
	QString block1 = dec2bin(part1);
	QString block2 = dec2bin(part2);
	QString block3 = dec2bin(part3);
	
// 	std::cout << "block0: " << block0 << std::endl;
// 	std::cout << "block1: " << block1 << std::endl;
// 	std::cout << "block2: " << block2 << std::endl;
// 	std::cout << "block3: " << block3 << std::endl;
	block = block0 + block1 +block2 + block3;
// 	std::cout << "block: " << block.ascii() << std::endl;
	
	for (int i=0; i< 31;i++)
	{
		if (block.mid(i,1) == "1")
			byteSetCount++;
	}
	return byteSetCount;
}

#include "utils.moc"
