/*****************************************************************************
 * Copyright (C) 2010 S.R.Haque <srhaque@theiet.org>                         *
 * Christoph Thielecke <crissi99@gmx.de> (contains code from kvpnc.cpp)      *
 *                                                                           *
 * 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 <QtCore/QProcess>
#include <kmessagebox.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>
#include <unistd.h>
#include "PptpHandler.h"
#include "enterpassworddialog.h"
#include "kvpnc.h"
#include "kvpncconfig.h"
#include "utils.h"

PptpHandler::PptpHandler(
    KVpnc *ui,
    KVpncConfig *config):
        HandlerBase(ui, config, "PPTP", "pppd, pptp", false),
        PptpProcess(0)
{
    if (!ui->pppdCapabilitiesCollected) {
        debugMessage(3, i18n("Collecting pppd capabilities..."));
        GlobalConfig->pppdcap = Utils(GlobalConfig).checkPppdCapabilities();
        GlobalConfig->appPointer->restoreOverrideCursor();
        pppdHasReplacedefaultrouteSupport = GlobalConfig->pppdcap.pppdHasReplacedefaultrouteSupport;
        ui->pppdCapabilitiesCollected = true;
    }
}

bool PptpHandler::vpnStart(bool authenticationRetry)
{
    // Everything step of our logic is guarded by the error state. The error
    // state starts as zero for no error, and is set to the line where any
    // problem is caught.
    unsigned errorLine = 0;

    if (!errorLine) {
        // looking for pppd
        if (!Utils(GlobalConfig).getToolInfo(IpsecType)->found) {
            reportError(i18n("Unable to find \"%1\" at \"%2\".", IpsecType, GlobalConfig->pathToPppd));
            errorLine = __LINE__;
        } else {
            debugMessage(0, i18n("Found helper %1 at %2", IpsecType, GlobalConfig->pathToPppd));
        }
    }

    if (!errorLine) {
        if (!getAuthenticationData(authenticationRetry)) {
            errorMessage(i18n("Authentication data dialog cancelled."));
            errorLine = __LINE__;
        }
    }

    if (!errorLine) {

        debugMessage(3,  i18n ( "Checking gre support" ) );
        bool gresupportfound = false;
        QString procnetdev = "";
        QFile f ( "/proc/net/dev" );
        if ( f.open ( IO_ReadOnly ) ) {
            QTextStream procnetdevstream ( &f );
            QString procnetdevcontent = QString(procnetdevstream.read());
            QStringList procnetdev_content_list = QStringList::split("\n", procnetdevcontent);
            QString line = "";
            for ( QStringList::Iterator it = procnetdev_content_list.begin(); it != procnetdev_content_list.end(); ++it ) {
                line = *it; // line of text excluding '\n'
                if ( line.contains ( "gre0", false ) ) {
                    gresupportfound = true;
                    break;
                }
            }
            f.close();
        }
        if ( !gresupportfound ) {
            QString procmodules = "";
            QFile f2 ( "/proc/modules" );
            if ( f2.open ( IO_ReadOnly ) ) {
                QTextStream procmodulesstream ( &f2 );
                QString procmodulescontent = QString(procmodulesstream.read());
                QStringList procmodules_content_list = QStringList::split("\n", procmodulescontent);
                QString line = "";
                for ( QStringList::Iterator it2 = procmodules_content_list.begin(); it2 != procmodules_content_list.end(); ++it2 ) {
                    line = *it2; // line of text excluding '\n'
                    if ( line.contains ( "ip_gre", false ) ) {
                        gresupportfound = true;
                        break;
                    }
                }
                f2.close();
            }
        }
        if ( gresupportfound ) {
            debugMessage(0,  i18n ( "Support for %1 found (compiled into kernel or kernel module already loaded).", QString("GRE")) );
        } else {
            if (!kernelModuleLoad("ip_gre")) {
                errorLine = __LINE__;
            }
        }
    }


    //   if ( GlobalConfig->currentProfile->getRemoteNetAddr().isEmpty() || GlobalConfig->currentProfile->getRemoteNetMask() .isEmpty() )
    //   {
    //    errorMessage( i18n( "Remote network is missing, please fill in in profile dialog." ) );
    //    ok = false;
    //    setStatusDisconnected(__LINE__);
    //    return;
    //   }


    if (!errorLine) {
        if (GlobalConfig->currentProfile->getRequireMppe()) {
            if (!GlobalConfig->pppdcap.pppdHasMppeRequiredSupport && !GlobalConfig->pppdcap.pppdHasRequireMppeSupport) {
                errorMessage(i18n("pppd: (%1) has no MPPE support. STOP." , QString(GlobalConfig->pathToPppd)));
                errorLine = __LINE__;
            } else {
                if (GlobalConfig->pppdcap.pppdHasMppeRequiredSupport)
                    debugMessage(3, i18n("pppd: (%1) has MPPE support: %2" , QString(GlobalConfig->pathToPppd) , QString("mppe required")));
                else if (GlobalConfig->pppdcap.pppdHasRequireMppeSupport)
                    debugMessage(3, i18n("pppd: (%1) has MPPE support: %2", QString(GlobalConfig->pathToPppd), QString("require-mppe")));
            }
        }
    }

// here we go
    if (!errorLine) {

        gui->setPppdDevice("ppp0");
        if (GlobalConfig->currentProfile->getExecuteCmdBeforeConnect())
            executeCommandBeforeConnect();
    }

    if (!errorLine) {
        QString tmpInterface;
        QString LocalIP;
        NetworkInterface iface(GlobalConfig, kapp);
        if (GlobalConfig->currentProfile->getNetworkDevice() == "default" || GlobalConfig->currentProfile->getNetworkDevice() == "") {
            tmpInterface = iface.getDefaultInterface();
            debugMessage(0, i18n("Default interface: \"%1\"." , tmpInterface) );
            LocalIP = iface.getInterfaceIP(iface.getDefaultInterface());
            debugMessage(0, i18n("IP address of default interface: \"%1\"." , LocalIP) );
        } else {
            QString device = GlobalConfig->currentProfile->getNetworkDevice();
            //QString device = PppdDevice;
            tmpInterface = GlobalConfig->currentProfile->getNetworkDevice();
            LocalIP = iface.getInterfaceIP(device);
        }
        if (tmpInterface.isEmpty()) {
            tmpInterface = iface.getDefaultInterface();
            LocalIP = iface.getInterfaceIP(iface.getDefaultInterface());
            if (tmpInterface.isEmpty()) {
                debugMessage(0, i18n("No default interface found, using \"lo\"."));
                tmpInterface = "lo"; // no default interface found :(
            } else {
                debugMessage(0, i18n("No default interface given, tried default interface, got success, using \"%1\"." , tmpInterface));
            }
        }

        if (LocalIP.isEmpty()) {
            debugMessage(0, i18n("No IP for default interface found, using \"127.0.0.1\"."));
            LocalIP = "127.0.0.1"; // no IP for default interface found :(
        }

        GlobalConfig->OldDefaultDev =  iface.getDefaultInterface();
        GlobalConfig->OldDefaultGw = iface.getGatewayOfDefaultInterface();

        debugMessage(3, i18n("Old default device: %1, old default gw: %2" , QString(GlobalConfig->OldDefaultDev), GlobalConfig->OldDefaultGw));


        OldDefaultroute = tmpPath + "default-route." + GlobalConfig->currentProfile->getName(); // default-route.<id>
        PptpGateway = tmpPath + "gateway." + GlobalConfig->currentProfile->getName(); // gateway.<id>
        GlobalConfig->Pppd_pid_file = "/var/run/ppp-" + GlobalConfig->currentProfile->getName() + ".pid"; // /var/run/ppp-<id>.pid

        // write pppd peer script
        QString PppdPeerScript = "/etc/ppp/peers/kvpnc." + GlobalConfig->currentProfile->getName(); // /etc/ppp/peers/<id>
        debugMessage(0, "pppd peer script: " + PppdPeerScript + "\n");

        QFile file(PppdPeerScript);
        QTextStream stream(&file);
        if (file.open(QIODevice::WriteOnly)) {
            stream << "# generated by kvpnc. Do not edit it." << "\n";
            stream << "# profile: " + GlobalConfig->currentProfile->getName() << "\n";
            stream << "" << "\n";
            stream << "\n";
            stream << "# name of tunnel, used to select lines in secrets files\n";
            stream << "remotename " + GlobalConfig->currentProfile->getName() + "\n";
            stream << "\n";
            stream << "# name of tunnel, used to name /var/run pid file\n";
            stream << "linkname kvpnc." + GlobalConfig->currentProfile->getName() + "\n";
            stream << "\n";
            stream << "# name of tunnel, passed to ip-up scripts\n";
            stream << "ipparam kvpnc." + GlobalConfig->currentProfile->getName() + "\n";
            stream << "\n";
            stream << "# data stream for pppd to use\n";
            QString pptpdebug = "";
            if (GlobalConfig->enableDebugPptpd == true) {
                pptpdebug = " --debug ";
                debugMessage(2, i18n("Enabling debug for pptpd."));
            }
            stream << "pty \"" << GlobalConfig->pathToPptp << " " << pptpdebug << "--loglevel " << QString().setNum(GlobalConfig->PptpLogLevel)  << " " << GlobalConfig->currentProfile->getGateway() << " --nolaunchpppd\"\n";
            stream << "\n";

            stream << "# domain and username, used to select lines in secrets files\n";
            if (GlobalConfig->currentProfile->getUseNtDomainName() && !GlobalConfig->currentProfile->getNtDomainName().isEmpty()) {
                stream << "name \"" + GlobalConfig->currentProfile->getNtDomainName() + "\\\\" + GlobalConfig->currentProfile->getUserName() + "\"\n";
                debugMessage(0, i18n("Using (NT) domain name \"%1\"." , GlobalConfig->currentProfile->getNtDomainName()));
            } else
                stream << "name \"" + GlobalConfig->currentProfile->getUserName() + "\"\n";
            stream << "\n";

            if (GlobalConfig->currentProfile->getUseDnsServer() && !GlobalConfig->currentProfile->getDnsServer().isEmpty()) {
                stream << "# set own dns server\n";
                stream << "ms-dns " + GlobalConfig->currentProfile->getDnsServer() + "\n";
                stream << "\n";
            } else {
                if (GlobalConfig->currentProfile->getUseDnsUpdate()) {
                    stream << "# retrieve DNS from peer\n";
                    stream << "usepeerdns\n";
                    stream << "\n";
                }
            }

            if (GlobalConfig->currentProfile->getRequireMppe()) {
                stream << "# use MPPE encryption\n";

                stream << GlobalConfig->pppdcap.RequireMppeOption;
                if (!GlobalConfig->pppdcap.MppeOptionsInALine)
                    stream << "\n";

                if (GlobalConfig->currentProfile->getAllowStatefulMode()) {
                    stream << GlobalConfig->pppdcap.RequireStatefulOption;
                    if (!GlobalConfig->pppdcap.MppeOptionsInALine)
                        stream << "\n";
                } else {
                    stream << GlobalConfig->pppdcap.RequireStatelessOption;
                    if (!GlobalConfig->pppdcap.MppeOptionsInALine)
                        stream << "\n";
                }



                if (GlobalConfig->currentProfile->getRefuse128BitEncryption()) {
                    stream << GlobalConfig->pppdcap.Refuse128BitMppeOption;
                    if (!GlobalConfig->pppdcap.MppeOptionsInALine)
                        stream << "\n";
                } else {
                    stream << GlobalConfig->pppdcap.Require128BitMppeOption;
                    if (!GlobalConfig->pppdcap.MppeOptionsInALine)
                        stream << "\n";
                }


                if (GlobalConfig->currentProfile->getRefuse40BitEncryption()) {
                    stream << GlobalConfig->pppdcap.Refuse40BitMppeOption;
                    if (!GlobalConfig->pppdcap.MppeOptionsInALine)
                        stream << "\n";
                }


                stream << "\n";
            } else {
                stream << "# disable MPPE encryption\n";
                stream << GlobalConfig->pppdcap.RefuseMppeOption;
                if (!GlobalConfig->pppdcap.MppeOptionsInALine)
                    stream << "\n";
                stream << "\n";
            }

            stream << "# we do not require the peer to authenticate itself\n";
            stream << "noauth\n";
            stream << "\n";

            if (GlobalConfig->enableDebugPppd) {
                stream << "# enable debug\n";
                stream << "debug\n";
                stream << "\n";
            }

            stream << "# we want to see what happen\n";
            stream << "nodetach\n";
            stream << "\n";

            stream << "# lock the device\n";
            stream << "lock\n";
            stream << "\n";

            if (GlobalConfig->currentProfile->getUseNoBsdComp()) {
                stream << "# Do not use BSD compression\n";
                stream << "nobsdcomp\n";
                stream << "\n";
            } else {
                stream << "# Use BSD compression\n";
                stream << "bsdcomp 9\n";
                stream << "\n";
            }

            if (GlobalConfig->currentProfile->getUseNoDeflate()) {
                stream << "# Do not use deflate method\n";
                stream << "nodeflate\n";
                stream << "\n";
            } else {
                stream << "# Use deflate method\n";
                // FIXME make values dynamically
                stream << "deflate 9\n";
                stream << "\n";
            }

            if (!GlobalConfig->currentProfile->getReplaceDefaultRoute()) {
                stream << "# do not replace defaultroute\n";
                stream << "defaultroute";
                stream << "\n";
            } else {
                if (GlobalConfig->currentProfile->getReplaceDefaultRoute()) {
                    stream << "# replace defaultroute\n";
                    stream << "defaultroute\n";
                    if (GlobalConfig->pppdcap.pppdHasReplacedefaultrouteSupport)
                        stream << "replacedefaultroute\n";
                }
                stream << "\n";
            }


            if (GlobalConfig->currentProfile->getUseMtu()) {
                stream << "# userdefined MTU\n";
                stream << "mtu " + QString().setNum(GlobalConfig->currentProfile->getMtu()) + "\n";
                stream << "\n";
            } else {
                stream << "# default MTU\n";
                stream << "mtu 1500" << "\n";
                stream << "\n";
            }

            if (GlobalConfig->currentProfile->getUseMru()) {
                stream << "# userdefined MRU\n";
                stream << "mru " + QString().setNum(GlobalConfig->currentProfile->getMru()) + "\n";
                stream << "\n";
            } else {
                stream << "# default MRU\n";
                stream << "mru 1500" << "\n";
                stream << "\n";
            }

            if (GlobalConfig->currentProfile->getUseNoIpDefault()) {
                stream << "# Use no IP by default\n";
                stream << "noipdefault\n";
                stream << "\n";
            }

            if (GlobalConfig->currentProfile->getDisableMPPEComp()) {
                stream << "# disable Microsoft Point-to-Point Compression (MPPC) (i.e. for compatibility with watchguard firebox)\n";
                //      if ( !pppdcap.oldPppdStyle || pppdcap.pppdHasRequireMppe128Support )
                stream << "nopcomp\n";
                //      else
                //       stream << "nomppc\n";
                stream << "\n";
            }

            if (GlobalConfig->currentProfile->getDisableCcp()) {
                stream << "# Disable CCP (Compression Control Protocol) negotiation\n";
                stream << "noccp\n";
                stream << "\n";
            }

            if (GlobalConfig->currentProfile->getDisableHeaderCompression()) {
                stream << "# disable TCP header compression\n";
                stream << "novj\n";
                stream << "\n";
            }

            if (GlobalConfig->currentProfile->getDisableMagicNumberNegotiation()) {
                stream << "# disable magic number negotiation\n";
                stream << "nomagic\n";
                stream << "\n";
            }

            if (GlobalConfig->currentProfile->getDisableIpx()) {
                stream << "# disable IPX\n";
                stream << "noipx\n";
                stream << "\n";
            }

            if (GlobalConfig->currentProfile->getDisableProtocolFieldCompression()) {
                stream << "# disable protocol field compression\n";
                stream << "nopcomp\n";
                stream << "\n";
            }

            if (GlobalConfig->currentProfile->getDisableAddressControlCompression()) {
                stream << "# disable address control compression\n";
                stream << "noaccomp\n";
                stream << "\n";
            }

            if (GlobalConfig->currentProfile->getUseVirtualIP()) {
                stream << "# use virtual IP addresses\n";
                stream << "# <client ip>:<server ip>\n";
                stream << GlobalConfig->currentProfile->getLocalVirtualIP() << ":" << GlobalConfig->currentProfile->getRemoteVirtualIP() << "\n";
            }

            stream << "# kernel level debug\n";
            stream << "kdebug " << GlobalConfig->PppdKernelLogLevel << "\n";


            if (GlobalConfig->currentProfile->getRequireEap()) {
                stream << "# force EAP\n";
                stream << "require-eap\n";
            } else {
                stream << "# refuse EAP\n";
                stream << "refuse-eap\n";
            }


            if (GlobalConfig->currentProfile->getAuthMethod() == "chap" ||
                    GlobalConfig->currentProfile->getAuthMethod() == "mschap" ||
                    GlobalConfig->currentProfile->getAuthMethod() == "mschap-v2") {
                debugMessage(0, i18n("Authentication method: %1" , GlobalConfig->currentProfile->getAuthMethod()));

                if (GlobalConfig->currentProfile->getAuthMethod() == "chap") {
                    stream << "# use chap" << "\n";
                    stream << GlobalConfig->pppdcap.RequireAuthChapOption << "\n";
                }

                if (GlobalConfig->currentProfile->getAuthMethod() == "mschap") {
                    stream << "# use mschap" << "\n";
                    stream << GlobalConfig->pppdcap.RequireAuthMschapOption << "\n";
                }

                if (GlobalConfig->currentProfile->getAuthMethod() == "mschap-v2") {
                    stream << "# use mschap-v2" << "\n";
                    stream << GlobalConfig->pppdcap.RequireAuthMschapv2Option << "\n";
                }

                stream << "\n";
            }
            if (GlobalConfig->currentProfile->getAuthMethod() == "pap") {

                //      logMessage ( i18n ( "Creating of %1 failed." , "pppd secrets file" ), KVpncEnum::error );
                debugMessage(0, i18n("Authentication method: %1" , GlobalConfig->currentProfile->getAuthMethod()));

                stream << "# use pap" << "\n";
                stream << GlobalConfig->pppdcap.RequireAuthPapOption << "\n";
            }
            pppdSecretsAdd();

            file.close();
        } else {
            reportError(i18n("Failed to create \"%1\"." , file.fileName()));
            errorLine = __LINE__;
        }
    }


    /*
                if (GlobalConfig->currentProfile->getAuthMethod() != "chap" && GlobalConfig->currentProfile->getAuthMethod() != "chap")
                GlobalConfig->currentProfile->setAuthMethod("chap");*/


    if (!errorLine) {

        QString scriptFilename = tmpPath + "pppd." + GlobalConfig->currentProfile->getName() + ".backup_default_route.sh";
        QFile pppdbackupdefaultroutefile(scriptFilename);
        QTextStream scriptStream(&pppdbackupdefaultroutefile);
        if (pppdbackupdefaultroutefile.open(QIODevice::WriteOnly)) {
            scriptStream <<  "#!" << GlobalConfig->InterpreterShell << "\n";
            scriptStream << "# generated by kvpnc. Do not edit it." << "\n";
            scriptStream << "# profile: " + GlobalConfig->currentProfile->getName() << "\n\n";
            scriptStream << GlobalConfig->pathToIp << " route show | grep default | head -n1 > " << OldDefaultroute << "\n";
            pppdbackupdefaultroutefile.close();

        } else {
            reportError(i18n("Failed to create \"%1\"." , scriptFilename));
            errorLine = __LINE__;
        }
    }

    if (!errorLine) {
        QProcess process(this);
        QStringList args;
        args.append(tmpPath + "pppd." + GlobalConfig->currentProfile->getName() + ".backup_default_route.sh");
        process.setEnvironment(*env);
        process.start(GlobalConfig->InterpreterShell, args);
        if (!process.waitForStarted()) {
            reportError(i18n("\"%1\" (%2) start failed." , QString("PppdBackupDefaultRouteScript"), QString(tmpPath + "pppd." + GlobalConfig->currentProfile->getName() + ".backup_default_route.sh")), QString(), KVpncEnum::info);
        } else {
            debugMessage(2, i18n("\"%1\" (%2) started.", QString("PppdBackupDefaultRouteScript") , tmpPath + "pppd." + GlobalConfig->currentProfile->getName() + ".backup_default_route.sh") );
            waitForFinished(&process, 100);

            debugMessage(2, i18n("\"%1\" (%2) finished.", QString("PppdBackupDefaultRouteScript"), tmpPath + "pppd." + GlobalConfig->currentProfile->getName() + ".up") );
        }

        // load the module 'ppp_mppe'
        QFile modprobe_confFile("/etc/modprobe.conf");
        if (modprobe_confFile.exists()) {
            QString modprobe_confFileContent = "";
            bool ppp_compress_18_found = false;
            if (modprobe_confFile.open(QIODevice::ReadOnly)) {
                QStringList contentlist = QString(modprobe_confFile.readAll()).split("\n");
                for (int i = 0; i < contentlist.size(); ++i) {
                    QString line = contentlist.at(i);
                    if (line.contains("ppp-compress-18", Qt::CaseInsensitive)) {
                        ppp_compress_18_found = true;
                        break;
                    }
                }
                modprobe_confFile.close();
                if (!ppp_compress_18_found) {
                    if (!modprobe_confFile.open(QIODevice::WriteOnly | QIODevice::Append)) {
                        errorMessage(i18n("%1 cannot be opened for appending." , QString("/etc/modprobe.conf")));
                    } else {

                        QTextStream stream(&modprobe_confFile);
                        if (!kernelModuleLoad("ppp_mppe")) {
                            debugMessage(0, i18n("Loading module \"%1\" failed, adding \"ppp_mppe_mppc\" to %2." , QString("ppp_mppe") , QString("/etc/modprobe.conf")));
                            stream << "\n" << "# added by kvpnc, do not edit it.\n" << "alias ppp-compress-18 ppp_mppe_mppc\n";
                        } else {
                            debugMessage(0, i18n("Loading module \"%1\" succeeded, adding \"ppp_mppe\" to %2." , QString("ppp_mppe") , QString("/etc/modprobe.conf")));
                            stream << "\n" << "# added by kvpnc, do not edit it.\n" << "alias ppp-compress-18 ppp_mppe\n";
                        }

                        modprobe_confFile.close();

                        debugMessage(0, i18n("%1 found \"%2\" alias missing. KVpnc has been added it." , QString("/etc/modprobe.conf") , QString("ppp-compress-18")));
                    }
                }
            }
        }
    }

    if (!errorLine) {
        if (!kernelModuleLoad("ppp-compress-18") && !kernelModuleLoad("ppp_mppe")) {
            errorMessage(i18n("Loading module \"%1\" and \"%2\" has failed: stop." , QString("ppp-compress-18") , QString("ppp_mppe")));
            errorLine = __LINE__;
        }
    }

    if (!errorLine) {

        //sleep(2);
        debugMessage(0, "pppd: " + GlobalConfig->pathToPppd + "\n");
        QStringList args;

        args.append("call");
        args.append(QString("kvpnc." + GlobalConfig->currentProfile->getName()));

        //args.append( GlobalConfig->InterpreterShell );
        //args.append( "/home/crissi/pppd.sh" );

        setenv("DNS_UPDATE", (GlobalConfig->currentProfile->getUseDnsUpdate() ? "Yes" : "NO"), 1);

        debugMessage(0, i18n("Setting DNS_UPDATE \"%1\"." , QString(qgetenv("DNS_UPDATE"))));

        PptpProcess = new HelperProcess(this, GlobalConfig->pathToPppd, args, *env,
                                        SLOT(readFromStdout_pptp()),
                                        SLOT(readFromStderr_pptp()),
                                        0, 0);
        if (!PptpProcess || !PptpProcess->start()) {
            errorLine = __LINE__;
        }
    }

    if (!errorLine) {
        debugMessage(0, i18n("Trying to connect to server \"%1\" with user \"%2\"...\n" , GlobalConfig->currentProfile->getGateway() , GlobalConfig->currentProfile->getUserName()));
    } else {
        errorMessage(i18n("Error at line %1.", errorLine));
    }
    return 0 == errorLine;
} // pptp

void PptpHandler::vpnStop()
{
    OldDefaultroute = tmpPath + "default-route." + GlobalConfig->currentProfile->getName(); // default-route.<id>
    if (PptpProcess) {
        delete PptpProcess;
        PptpProcess = 0;
    }

    // write pppd.<profile>.down
    QFile downfile(tmpPath + "pppd." + GlobalConfig->currentProfile->getName() + ".down");
    QTextStream downstream(&downfile);
    if (downfile.open(QIODevice::WriteOnly)) {
        downstream <<  "#!" << GlobalConfig->InterpreterShell << "\n";
        downstream << "# generated by kvpnc. Do not edit it." << "\n";
        downstream << "# profile: " + GlobalConfig->currentProfile->getName() << "\n\n";
        /* update dns? */
        if (GlobalConfig->currentProfile->getUseDnsUpdate()) {
            //downstream << "chmod u+w  /etc/resolv.conf\n";
            downstream << "if [ -x /sbin/resolvconf ] ; then\n";
            downstream << " dev=$1\n";
            downstream << " if [ -z $dev ] ; then\n";
            downstream << "  dev=\"ppp0\"\n";
            downstream << " fi\n";
            downstream << " /sbin/resolvconf -d $dev\n";

            downstream << " nameserver=\"$(cat /etc/resolv.conf | grep nameserver | head -n1 | sed -e 's/nameserver //')\"\n";
            downstream << " if [ -z $nameserver ] ; then\n";
            downstream << "  nameserver=\"$(cat " << tmpPath + "resolv.conf." + GlobalConfig->currentProfile->getName() << " | grep nameserver | head -n1 | sed -e 's/nameserver //')\"\n";
            downstream << " fi" << "\n";

            downstream << "else" << "\n";
            downstream << "cat " << tmpPath + "resolv.conf." + GlobalConfig->currentProfile->getName() << " > /etc/resolv.conf\n";
            downstream << "fi" << "\n";
        } else {
            /* dont update dns */
        }

        if (GlobalConfig->currentProfile->getReplaceDefaultRoute()) {
            //       downstream << GlobalConfig->pathToIp + " route del " + GlobalConfig->currentProfile->getGateway() + "/32 via " << GlobalConfig->OldDefaultGw << " dev " << GlobalConfig->OldDefaultDev << "\n";
            downstream << GlobalConfig->pathToRoute << " del default" << "\n";
            if (! pppdHasReplacedefaultrouteSupport) {
                downstream << GlobalConfig->pathToIp << " route add  $(cat " << OldDefaultroute << ")" << "\n";
            }
        }

        debugMessage(3, i18n("Removing extra route: %1 over %2 gw %3", QString(GlobalConfig->currentProfile->getGateway()) , GlobalConfig->OldDefaultDev, GlobalConfig->OldDefaultGw));

        downstream << GlobalConfig->pathToIp + " route del " + GlobalConfig->currentProfile->getGateway() + "/32 via " << GlobalConfig->OldDefaultGw << " dev " << GlobalConfig->OldDefaultDev << "\n";


        downfile.close();

        QProcess pppdDownProcess(this);
        QString proc = GlobalConfig->InterpreterShell;
        QStringList args;
        args.append(tmpPath + "pppd." + GlobalConfig->currentProfile->getName() + ".down");
        pppdDownProcess.setEnvironment(*env);
        pppdDownProcess.start(proc, args);
        if (!pppdDownProcess.waitForStarted()) {
            reportError(i18n("Failed to start \"%1\"." , QString("PppdDownScript")), QString(), KVpncEnum::info);
        } else {
            debugMessage(1, i18n("\"%1\" started." , QString("PppdDownScript"), QString(tmpPath + "pppd." + GlobalConfig->currentProfile->getName() + ".down")) );
            waitForFinished(&pppdDownProcess, 100);

            debugMessage(1, i18n("\"%1\" (%2) finished." , QString("PppdDownScript"), QString(tmpPath + "pppd." + GlobalConfig->currentProfile->getName() + ".down")));

            if (! pppdHasReplacedefaultrouteSupport && GlobalConfig->currentProfile->getReplaceDefaultRoute())
                debugMessage(1, i18n("Default route was restored."));

            if (GlobalConfig->currentProfile->getUseDnsUpdate() && Utils(GlobalConfig).resolvConfAvailable()) {
                debugMessage(1, i18n("resolvconf restored the old /etc/resolv.conf."));
            } else {
                if (GlobalConfig->currentProfile->getUseDnsUpdate())
                    debugMessage(1, i18n("/etc/resolv.conf was restored."));
            }
        }
    } else {
        errorMessage(i18n("\"%1\" could not be written.", QString(i18n("pppd down file"))));

    }
    pppdSecretsRemove();
    connectCounter = 0;
}

bool PptpHandler::getAuthenticationData(bool AuthRetry)
{
    bool askUsernamePass = false;
    bool requestUsername = false;
    if (AuthRetry) {
        askUsernamePass = true;
        requestUsername = true;
    }

    if (GlobalConfig->currentProfile->getAskUserPasswordOnEachConnect()) {
        debugMessage(4, i18n("User password on each connect forced."));

        askUsernamePass = true;
        requestUsername = true;
    }

    if (!GlobalConfig->haveUserData || GlobalConfig->currentProfile->getAskUserPasswordOnEachConnect()) {
        if (!GlobalConfig->currentProfile->getSaveUserPassword() || GlobalConfig->currentProfile->getUserPassword().isEmpty() || GlobalConfig->currentProfile->getUserName().isEmpty() || askUsernamePass) {


            EnterUsernamePasswordDialog dlg(gui, i18n("Enter Account Data"), false, requestUsername);       // only password

            if (GlobalConfig->currentProfile->getSaveUserPassword()) {
                //dlg.PasswordEdit->setText(GlobalConfig->currentProfile->getUserPassword());
                dlg.SavePasswordCheckBox->setChecked(true);
            }
            if (AuthRetry)
                dlg.UsernameEdit->setText ( GlobalConfig->TmpUsername );
            else
                dlg.UsernameEdit->setText(GlobalConfig->currentProfile->getUserName());
            if (!dlg.UsernameEdit->text().isEmpty()) {                //go straight to pw if username present
                dlg.PasswordEdit->setFocus();
                if (!GlobalConfig->currentProfile->getDontSaveUsername())
                    dlg.SaveUsernameCheckBox->setChecked(true);
            }
            dlg.LabelID->hide();
            dlg.IDEdit->hide();


            if (dlg.exec()) {
                GlobalConfig->TmpUsername = dlg.UsernameEdit->text();
                GlobalConfig->TmpPassword = dlg.PasswordEdit->text();
                bool needSave = false;

                if (GlobalConfig->TmpPassword.isEmpty()) {
                    errorMessage(i18n("Password is empty"));
                    return false;
                }

                if (!GlobalConfig->currentProfile->getDontSaveUsername() && (requestUsername && GlobalConfig->TmpUsername.isEmpty())) {
                    errorMessage(i18n("Username is empty."));
                    return false;
                }

                if (dlg.SaveUsernameCheckBox->isChecked()) {
                    GlobalConfig->currentProfile->setDontSaveUsername(false);
                    GlobalConfig->currentProfile->setUserName(dlg.UsernameEdit->text());
                    needSave = true;
                } else {
                    GlobalConfig->TmpUsername = dlg.UsernameEdit->text();
                    GlobalConfig->currentProfile->setDontSaveUsername(true);
                    needSave = true;
                }

                if (dlg.SavePasswordCheckBox->isChecked()) {
                    GlobalConfig->currentProfile->setSaveUserPassword(true);
                    GlobalConfig->currentProfile->setUserPassword(GlobalConfig->TmpPassword);
                    needSave = true;
                } else {
                    GlobalConfig->currentProfile->setSaveUserPassword(false);
                    needSave = true;
                }
                if (needSave == true)
                    GlobalConfig->saveOptions(true, GlobalConfig->currentProfile->getName());

                GlobalConfig->haveUserData = true;
                debugMessage(0, i18n("Some passwords which were needed were obtained from a password dialog."));
            } else {
                return false;
                debugMessage(0, i18n("Connect canceled because password enter dialog aborted."));
            }
        } else {
            if (!GlobalConfig->currentProfile->getSaveUserPassword() || GlobalConfig->currentProfile->getUserPassword().isEmpty()) {
                GlobalConfig->TmpPassword =  GlobalConfig->currentProfile->getUserPassword() ;
            }


            if (!GlobalConfig->currentProfile->getDontSaveUsername() || GlobalConfig->currentProfile->getUserName().isEmpty()) {                //go straight to pw if username present
                GlobalConfig->TmpUsername = GlobalConfig->currentProfile->getUserName();
            }
        }
    } else {
        debugMessage(4, i18n("User data already collected."));
    }
    return true;
}

QString PptpHandler::pingDevice() const {
    return gui->pppdDevice();
}

void PptpHandler::readFromStdout_pptp()
{
    QString source = "[pptp raw]";
    unsigned errorLine = 0;
    DisconnectionReason reason = DISCONNECTION_REASON_FATAL_ERROR;

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

        if ( !msg.isEmpty())
        {
            debugMessage (4, "[pptp raw]: "+msg);
        }


        bool connectSuccess = false;
        bool allowReconnect = false;

        if (msg.indexOf("could not find module", 0, Qt::CaseInsensitive) > -1) {
            reportError(i18n("Module not found."));

            errorLine = __LINE__;
        } else if (msg.indexOf("Connection terminated.", 0, Qt::CaseInsensitive) > -1) {
            //KMessageBox::error(gui, i18n( "Connection has been terminated." ) );
            debugMessage(0, i18n("Connection has been terminated."));
            errorLine = __LINE__;
            allowReconnect = true;
        } else if (msg.indexOf("Modem hangup", 0, Qt::CaseInsensitive) > -1 || msg.indexOf("Modem hung up", 0, Qt::CaseInsensitive) > -1) {
            if (!GlobalConfig->currentProfile->getDoReconnectAfterConnectionLost())
                reportError(i18n("Remote modem has hung up. Connection was terminated."));

            errorLine = __LINE__;
            allowReconnect = true;
        } else if (msg.indexOf("No route to host", 0, Qt::CaseInsensitive) > -1) {
            if (!GlobalConfig->currentProfile->getDoReconnectAfterConnectionLost())
                reportError(i18n("No route to host."));

            errorLine = __LINE__;
            allowReconnect = true;
        } else if (msg.indexOf("authentication failed", 0, Qt::CaseInsensitive) > -1) {
            connectCounter = 0;
            reportError(i18n("Authentication has failed."));

            reason = DISCONNECTION_REASON_AUTHENTICATION_FAILED;
            errorLine = __LINE__;
            //          while(GlobalConfig->status != KVpncEnum::disconnected) {
            //              usleep(500);
            //              if (GlobalConfig->appPointer->hasPendingEvents())
            //                  GlobalConfig->appPointer->processEvents();
            //          }
            //          return;
        } else if (msg.indexOf("peer refused to authenticate", 0, Qt::CaseInsensitive) > -1) {
            connectCounter = 0;
            if (!GlobalConfig->currentProfile->getDoReconnectAfterConnectionLost())
                reportError(i18n("The peer refused to authenticate."));

            reason = DISCONNECTION_REASON_AUTHENTICATION_FAILED;
            errorLine = __LINE__;
            //          while(GlobalConfig->status != KVpncEnum::disconnected) {
            //              usleep(500);
            //              if (GlobalConfig->appPointer->hasPendingEvents())
            //                  GlobalConfig->appPointer->processEvents();
            //          }
        } else if (msg.indexOf("EAP: peer reports authentication failure", 0, Qt::CaseInsensitive) > -1) {
            reportError(i18n("The peer refused to authenticate (it wants EAP). Please check username, password and EAP settings."));

            errorLine = __LINE__;
        } else if (msg.indexOf("MPPE required but peer negotiation failed", 0, Qt::CaseInsensitive) > -1) {
            connectCounter=0;
            reportError(i18n ( "The peer refused to use MPPE encryption. Maybe you have to disable MPPE encryption." ) );

            errorLine = __LINE__;
            reason = DISCONNECTION_REASON_AUTHENTICATION_FAILED;
        } else if (msg.indexOf("Call manager exited with error", 0, Qt::CaseInsensitive) > -1) {
            //KMessageBox::error(gui, i18n( "Call manager exited with a error." ) );
            errorMessage(i18n("Call manager exited with error."));
            errorLine = __LINE__;
        } else if (msg.indexOf("connect: Connection timed out", 0, Qt::CaseInsensitive) > -1) {
            //KMessageBox::error(gui, i18n( "connect: Connection timed out" ) );
            errorMessage(i18n("connect: Connection timed out"));
            errorLine = __LINE__;
            allowReconnect = true;
        } else if (msg.indexOf("Input/output error", 0, Qt::CaseInsensitive) > -1) {
            if ( !GlobalConfig->currentProfile->getDoReconnectAfterConnectionLost() )
                reportError(i18n( "Input/output error" ) );

            errorLine = __LINE__;
            allowReconnect = true;
        } else if (msg.indexOf("Using interface", 0, Qt::CaseInsensitive) > -1) {
            gui->setPppdDevice(msg.right(msg.length() - 16));
            GlobalConfig->currentProfile->setNetworkDevice(gui->pppdDevice());
            //
            //
            //   NetworkInterface iface(GlobalConfig,parent);
            //   TunnelInterfaceIP = iface.getInterfaceIP( PppdDevice );
            //   if (GlobalConfig->VpncDebugLevel > 0 )
            //    debugMessage( "[pppd] "+i18n( "Tunnel IP:" , QString(TunnelInterfaceIP)) );
            //
        } else if (msg.indexOf("tcflush failed: Bad file descriptor", 0, Qt::CaseInsensitive) > -1) {
            if ( !GlobalConfig->currentProfile->getDoReconnectAfterConnectionLost() )
                reportError(i18n("Sending data has failed. Connection was terminated."));

            errorLine = __LINE__;
            allowReconnect = true;
        } else if (msg.indexOf("Modem hangup", 0, Qt::CaseInsensitive) > -1) {
            if (!GlobalConfig->currentProfile->getDoReconnectAfterConnectionLost())
                reportError(i18n("Remote modem has hung up. Connection was terminated."));

            errorLine = __LINE__;
            allowReconnect = true;
        } else if (msg.indexOf("connect: Connection refused", 0, Qt::CaseInsensitive) > -1) {
            if (!GlobalConfig->currentProfile->getDoReconnectAfterConnectionLost())
                reportError(i18n("Connection has been refused. Terminate."));

            errorLine = __LINE__;
            allowReconnect = true;
        } else if (msg.indexOf("primary DNS address", 0, Qt::CaseInsensitive) > -1) {
            // example: primary DNS address 132.210.*.2 secondary DNS address 132.210.**.2
            bool got2dns = false;
            QString DNS1 = msg.section(' ', 3, 3);
            QString DNS2 = msg.section(' ', 7, 7);

            got2dns = Utils(GlobalConfig).isValidIPv4Address(DNS2);

            if (got2dns) {
                TmpDns1 = DNS1;
                TmpDns2 = DNS2;
            } else
                TmpDns1 = DNS2;

            if (got2dns)
                debugMessage(0, i18n("Got DNS1: %1, DNS2: %2"  , QString(DNS1), DNS2) );
            else
                debugMessage(0, i18n("Got DNS1: %1"  , QString(DNS1)) );
        } else if (msg.indexOf("CHAP authentication succeeded", 0, Qt::CaseInsensitive) > -1) {
            debugMessage(0, i18n("CHAP authentication succeeded.\n"));
        } else if (msg.indexOf("MPPE 128-bit stateless compression enabled", 0, Qt::CaseInsensitive) > -1) {
            debugMessage(0, i18n("MPPE 128-bit stateless compression enabled.\n"));
        } else if (msg.indexOf("local", 0, Qt::CaseInsensitive) > -1) {
            //    if (GlobalConfig->KvpncDebugLevel > 0)
            //       logMessage ( i18n( "adr: %1\n"  , QString(msg)), KVpncEnum::debug);
            gui->setTunnelInterfaceIP(msg.simplified().section(' ', 3, 3));
        } else if (msg.indexOf("Loopback detected", 0, Qt::CaseInsensitive) > -1) {
            //    KMessageBox::error ( this, i18n ( "Loopback detected. Reconnecting." ) );
            errorMessage(i18n("Loopback detected. Reconnecting."));
            errorLine = __LINE__;
            reason = DISCONNECTION_REASON_CONFIGURATION_CHANGED;
        } else if (msg.indexOf("remote IP address", 0, Qt::CaseInsensitive) > -1)
            connectSuccess = true;

        // success
        if (connectSuccess) {
            /* TBD
                debugMessage(0, i18n("Tunnel interface IP address: %1"  , QString(TunnelInterfaceIP)));
                            */
            //    debugMessage( QString("connectstring: "+msg) );

            QString pppdev = gui->pppdDevice();
            if (pppdev.isEmpty())
                pppdev = "ppp0";


            // write pppd.<profile>.up
            QFile pppdupfile(tmpPath + "pppd." + GlobalConfig->currentProfile->getName() + ".up");
            QTextStream pppdupstream(&pppdupfile);
            if (pppdupfile.open(QIODevice::WriteOnly)) {
                pppdupstream <<  "#!" << GlobalConfig->InterpreterShell << "\n";
                pppdupstream << "# generated by kvpnc. Do not edit it." << "\n";
                pppdupstream << "# profile: " + GlobalConfig->currentProfile->getName() << "\n\n";
                pppdupstream << "cat /etc/resolv.conf > " << tmpPath + "resolv.conf." + GlobalConfig->currentProfile->getName() << "\n";
                /* update dns? */
                if (GlobalConfig->currentProfile->getUseDnsUpdate()) {
                    pppdupstream << "if [ -x /sbin/resolvconf ] ; then\n";
                    pppdupstream << " echo > /dev/null" << "\n";
                    pppdupstream << "else" << "\n";
                    pppdupstream << " echo \"# generated by kvpnc. Do not edit it.\" > /etc/resolv.conf" << "\n";
                    pppdupstream << "fi\n";

                    QString resolvtemp = "";
                    bool no_nameserver = true;
                    if (!GlobalConfig->currentProfile->getUseDnsServer()) {
                        pppdupstream << "if [ -x /sbin/resolvconf ] ; then\n";
                        pppdupstream << " dev=$1\n";
                        pppdupstream << " if [ -z $dev ] ; then\n";
                        pppdupstream << "  dev=\"ppp0\"\n";
                        pppdupstream << "fi\n";
                        if (!TmpDns1.isEmpty() || !TmpDns2.isEmpty()) {
                            no_nameserver = false;
                            pppdupstream << "if [ -x /sbin/resolvconf ] ; then\n";
                            if (TmpDns2.isEmpty()) {
                                resolvtemp += " nameserver " + TmpDns1 + "\n";
                                pppdupstream << "echo \"nameserver " << TmpDns1 << "\"" << " " << "$dev\" > " + tmpPath + "+resolvconf." + GlobalConfig->currentProfile->getName() + "\n";
                            } else {
                                resolvtemp += " nameserver " + TmpDns1 + "\nnameserver " + TmpDns2 + "\n";
                                pppdupstream << "echo \"nameserver " << TmpDns1 << "\"\nnameserver " << TmpDns2 << " " << "$dev\" > " + tmpPath + "+resolvconf." + GlobalConfig->currentProfile->getName() + "\n";
                            }

                            pppdupstream << "else" << "\n";
                            pppdupstream << "  echo >> /etc/resolv.conf\n";
                            pppdupstream << "  echo \"# generated by kvpnc. Do not edit it.\" > /etc/resolv.conf" << "\n";
                            pppdupstream << "  echo \"# profile: " + GlobalConfig->currentProfile->getName() << "\" >> /etc/resolv.conf" << "\n";
                            pppdupstream << "  echo \"nameserver " << TmpDns1 << "\" >> /etc/resolv.conf" << "\n";
                            if (!TmpDns2.isEmpty())
                                pppdupstream << "  echo \"nameserver " << TmpDns2 << "\" >> /etc/resolv.conf" << "\n";

                        }

                        pppdupstream << "fi" << "\n";

                        pppdupstream << "# " << "\n";
                    }
                    if ((GlobalConfig->currentProfile->getUseDnsServer() && !GlobalConfig->currentProfile->getDnsServer().isEmpty()) || (GlobalConfig->currentProfile->getUseSearchDomainInResolvConf()  && ! !GlobalConfig->currentProfile->getSearchDomainInResolvConf().isEmpty())) {
                        pppdupstream << "if [  -x /sbin/resolvconf ] ; then\n";
                        pppdupstream << " dev=$1\n";
                        pppdupstream << " if [ -z $dev ] ; then\n";
                        pppdupstream << "  dev=\"ppp0\"\n";
                        pppdupstream << " fi\n";

                        if (GlobalConfig->currentProfile->getUseDnsServer() && !GlobalConfig->currentProfile->getDnsServer().isEmpty())
                            resolvtemp += "nameserver " + GlobalConfig->currentProfile->getDnsServer() + "\n";
                        if (GlobalConfig->currentProfile->getUseSearchDomainInResolvConf() && !GlobalConfig->currentProfile->getSearchDomainInResolvConf().isEmpty())
                            resolvtemp += "search " + GlobalConfig->currentProfile->getSearchDomainInResolvConf() + "\n";
                        pppdupstream << "else\n";
                        if (GlobalConfig->currentProfile->getUseDnsServer() && !GlobalConfig->currentProfile->getDnsServer().isEmpty()) {
                            pppdupstream << "echo \"nameserver " << GlobalConfig->currentProfile->getDnsServer() + "\" >> /etc/resolv.conf\n";
                            no_nameserver = false;
                        }
                        if (GlobalConfig->currentProfile->getUseSearchDomainInResolvConf() && !GlobalConfig->currentProfile->getSearchDomainInResolvConf().isEmpty())
                            pppdupstream << "echo \"search " << GlobalConfig->currentProfile->getSearchDomainInResolvConf() + "\" >> /etc/resolv.conf\n";
                        pppdupstream << "fi\n";
                    }


                    pppdupstream << "if [ -x /sbin/resolvconf ] ; then\n";
                    pppdupstream << " echo \"" + resolvtemp + "\" > " + tmpPath + "resolvconf." + GlobalConfig->currentProfile->getName() << "\n";

                    if (no_nameserver == true) {
                        pppdupstream << "   cat   " + tmpPath + "/resolv.conf.before.kvpnc_" + GlobalConfig->currentProfile->getName() + " | grep nameserver >> " + tmpPath + "resolvconf." + GlobalConfig->currentProfile->getName() + "\n";
                    }
                    pppdupstream << " cat   " + tmpPath + "resolvconf." + GlobalConfig->currentProfile->getName() +" | /sbin/resolvconf -a $dev\n";

                    /* crissi: -u seems not nessary */
                    //pppdupstream << " cat   " + tmpPath + "/pppd.resolvconf.tmp | /sbin/resolvconf -u\n";

                    if (!GlobalConfig->holdGeneratedScripts)
                        pppdupstream << " rm -f " + tmpPath + "resolvconf." + GlobalConfig->currentProfile->getName()+ "\n";

                    if (no_nameserver == true) {
                        pppdupstream << "else\n";
                        pppdupstream << "   cat " << tmpPath + "/resolv.conf.before.kvpnc_" + GlobalConfig->currentProfile->getName() + " | grep nameserver >> /etc/resolv.conf\n";
                    }

                    pppdupstream << "fi\n";
                    //pppdupstream << "chmod u-w  /etc/resolv.conf\n";
                } else {
                    /* dont update dns */
                    setenv("DNS_UPDATE", "NO", 1);
                }

                if (GlobalConfig->currentProfile->getReplaceDefaultRoute()) {
                    debugMessage(3, i18n("replacing default route: %1"  , QString(i18n("yes"))));

                    if (! pppdHasReplacedefaultrouteSupport) {
                        //       pppdupstream << GlobalConfig->pathToIp + " route replace default dev " + pppdev + "\n";
                        pppdupstream << GlobalConfig->pathToRoute << " del default " << "\n";
                        pppdupstream << GlobalConfig->pathToRoute << " add default " << pppdev << "\n";
                    }

                    debugMessage(3, i18n("Setting extra route: %1 over %2 gw %3"  , QString(GlobalConfig->currentProfile->getGateway()), GlobalConfig->OldDefaultDev, GlobalConfig->OldDefaultGw));

                    pppdupstream << GlobalConfig->pathToIp + " route add " + GlobalConfig->currentProfile->getGateway() + "/32 via " << GlobalConfig->OldDefaultGw << " dev " << GlobalConfig->OldDefaultDev << "\n";

                    NetworkInterface iface(GlobalConfig , kapp);
                    int defaultroutecount = iface.getDefaultRouteCount();
                    if (defaultroutecount < 1) {
                        //       pppdupstream << GlobalConfig->pathToIp + " route add 0.0.0.0 via " << GlobalConfig->OldDefaultGw << " dev " << pppdev << "\n";
                        pppdupstream << GlobalConfig->pathToRoute << " add default " << pppdev << "\n";

                        debugMessage(4, i18n("default route count: %1" , QString(QString().setNum(defaultroutecount))));

                        debugMessage(2, i18n("No default route found but replace it was requested, adding one over device %1 with gateway %2..." , QString(pppdev), GlobalConfig->NewDefaultGw));

                    }
                    if (defaultroutecount > 1) {
                        pppdupstream << "newdefaultgw=$(" << GlobalConfig->pathToIp << " route show default | grep default | grep -v " + GlobalConfig->OldDefaultGw + ")" << "\n";
                        pppdupstream << "if [ -z $newdefaultgw ]; then" << "\n";
                        pppdupstream << " newdefaultgw=\"" << GlobalConfig->OldDefaultGw << "\"" << "\n";
                        pppdupstream << "fi" << "\n";
                        for (int i = 0; i < defaultroutecount; i++) {
                            pppdupstream << GlobalConfig->pathToRoute << " del default" << "\n";
                        }
                        //       pppdupstream << GlobalConfig->pathToIp + " route add 0.0.0.0 via " << GlobalConfig->OldDefaultGw << " dev " << pppdev << "\n";
                        pppdupstream << GlobalConfig->pathToRoute << " add default " << pppdev << "\n";

                        debugMessage(4, i18n("default route count: %1" , QString(QString().setNum(defaultroutecount))));

                        debugMessage(2, i18n("More than one default route found, deleting all and adding one over device %1 with gateway %2..." , QString(pppdev), GlobalConfig->NewDefaultGw));

                    } else {
                        debugMessage(4, i18n("default route count : %1"   , QString("1")));
                    }


                    //     NetworkInterface iface(GlobalConfig,GlobalConfig->appPointer, this);
                    //     GlobalConfig->NewDefaultGw = iface.getGatewayOfDefaultInterface();
                    //
                    //     if (GlobalConfig->NewDefaultGw != "0.0.0.0")
                    //     {
                    //      if ( GlobalConfig->KvpncDebugLevel > 3 )
                    //       logMessage ( i18n ( "Setting extra route: %1 over %2 gw %3" , QString( "0.0.0.0" ), pppdev , GlobalConfig->NewDefaultGw), KVpncEnum::debug );
                    //      pppdupstream << GlobalConfig->pathToIp + " route add 0.0.0.0 via " << GlobalConfig->NewDefaultGw << " dev " << pppdev << "\n";
                }
                else {
                    debugMessage(3, i18n("replacing default route: %1"  , QString(i18n("no"))));
                }
                pppdupfile.close();
            }


            QProcess pppdUpProcess(this);
            QString proc = GlobalConfig->InterpreterShell;
            QStringList args;
            args.append(tmpPath + "pppd." + GlobalConfig->currentProfile->getName() + ".up");
            pppdUpProcess.setEnvironment(*env);
            pppdUpProcess.start(proc, args);
            if (!pppdUpProcess.waitForStarted()) {
                reportError(i18n("\"%1\" (%2) start failed."  , QString("PppdUpScript") , QString(tmpPath + "pppd." + GlobalConfig->currentProfile->getName() + ".up")), QString(), KVpncEnum::info);
            } else {
                debugMessage(0, i18n("\"%1\" (%2) started." , QString("PppdUpScript")  , QString(tmpPath + "pppd." + GlobalConfig->currentProfile->getName() + ".up")) );
                waitForFinished(&pppdUpProcess, 100);

                debugMessage(0, i18n("\"%1\" (%2) finished."  , QString("PppdUpScript") , QString(tmpPath + "pppd." + GlobalConfig->currentProfile->getName() + ".up")) );
            }

            QString iplocal = QString(qgetenv("IPLOCAL"));
            QString ipremote = QString(qgetenv("IPREMOTE"));
            QString ifname = QString(qgetenv("IFNAME"));
            QString speed = QString(qgetenv("SPEED"));

            debugMessage(2, i18n("Local IP address: , remote IP address: %2, device: %3, speed: %4",
                                 /* TBD QString(gui->TunnelInterfaceIP),*/
                                 ipremote,
                                 ifname,
                                 speed));

            connectSuccess = false;

            successMessage(i18n("%1: Connection established.", source));

            setStatusConnected(__LINE__);
        }
        //   GlobalConfig->appPointer->processEvents();
        if (errorLine) {
            //          while(GlobalConfig->status != KVpncEnum::disconnected) {
            //              usleep(500);
            //              if (GlobalConfig->appPointer->hasPendingEvents())
            //                  GlobalConfig->appPointer->processEvents();
            //          }

            /*
            // remove password entries
            pppdSecretsRemove();
            */
            if ( allowReconnect && GlobalConfig->currentProfile->getDoReconnectAfterConnectionLost() )
            {
                if ( GlobalConfig->currentProfile->getUseReconnectDelay() )
                {
                    debugMessage (0, i18n ( "Waiting %1s for reconnect..." ).arg ( GlobalConfig->currentProfile->getReconnectDelay() ));
                    for ( int time = 0; time <= GlobalConfig->currentProfile->getReconnectDelay() * 1000; time += 200 )
                    {
                        usleep ( 200 );
                        GlobalConfig->appPointer->processEvents();
                    }
                }
                //          if (GlobalConfig->KvpncDebugLevel > 0)
                debugMessage (0, i18n ( "Reconnect after connection lost enabled, reconnecting..." ));
                reason = DISCONNECTION_REASON_CONFIGURATION_CHANGED;
            }
            setStatusDisconnected(errorLine, reason);
            return ;
        }
    }
}

void PptpHandler::readFromStderr_pptp()
{
    QString source = "[pptp raw]";
    unsigned errorLine = 0;
    DisconnectionReason reason = DISCONNECTION_REASON_FATAL_ERROR;

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

        if ( !msg.isEmpty() )
        {
            debugMessage (4, "[pptp err raw]: "+msg);
        }


        bool error_found = false;
        bool allowReconnect = false;

        if (msg.indexOf("DNS address", 0, Qt::CaseInsensitive) || msg.indexOf("Script /etc/ppp/ip-up started", 0, Qt::CaseInsensitive))
            debugMessage(0, "[pppd] " + msg);
        else
            errorMessage("[pppd err] " + msg);

        if (msg.indexOf("authentication failed", 0, Qt::CaseInsensitive) > -1) {
            reportError(i18n("Authentication has failed."));

            reason = DISCONNECTION_REASON_AUTHENTICATION_FAILED;
            errorLine = __LINE__;
            //             setStatusDisconnected(__LINE__);
            //          while(GlobalConfig->status != KVpncEnum::disconnected) {
            //              usleep(500);
            //              if (GlobalConfig->appPointer->hasPendingEvents())
            //                  GlobalConfig->appPointer->processEvents();
            //          }
        } else if (msg.indexOf("MPPE required but not available", 0, Qt::CaseInsensitive) > -1) {
            if (error_found == false)
                reportError(i18n("MPPE required but not available"));

            errorLine = __LINE__;
            error_found = true;
        } else if (msg.indexOf("peer refused to authenticate", 0, Qt::CaseInsensitive) > -1) {
            if (error_found == false)
                reportError(i18n("The peer refused to authenticate."));

            errorLine = __LINE__;
            error_found = true;
        } else if (msg.indexOf("could not find module", 0, Qt::CaseInsensitive) > -1) {
            if (error_found == false)
                reportError(i18n("Module not found."));

            errorLine = __LINE__;
            error_found = true;
        } else if (msg.indexOf("Connection terminated.", 0, Qt::CaseInsensitive) > -1) {
            if (error_found==false)
                if ( !GlobalConfig->currentProfile->getDoReconnectAfterConnectionLost() )
                    reportError(i18n( "Connection has been terminated." ) );
            debugMessage(0, i18n("Connection has been terminated."));
            errorLine = __LINE__;
            error_found = true;
            allowReconnect = true;
        } else if (msg.indexOf("tcflush failed: Bad file descriptor", 0, Qt::CaseInsensitive) > -1) {
            if (error_found == false)
                if (!GlobalConfig->currentProfile->getDoReconnectAfterConnectionLost())
                    reportError(i18n("Sending data has failed. Connection was terminated."));

            errorLine = __LINE__;
            error_found = true;
            allowReconnect=true;
        } else if (msg.indexOf("MPPE required, but kernel has no support", 0, Qt::CaseInsensitive) > -1) {
            if (error_found == false)
                reportError(i18n("MPPE required, but kernel has no support. Please use a kernel with mppe support."));

            errorLine = __LINE__;
            error_found = true;
        } else if (msg.indexOf("unrecognized option 'mppe'", 0, Qt::CaseInsensitive) > -1) {
            if (error_found == false)
                reportError(i18n("MPPE required, but pppd has no MPPE support. Please install a pppd with MPPE support."));

            errorLine = __LINE__;
            error_found = true;
        } else if (msg.indexOf("Input/output error", 0, Qt::CaseInsensitive) > -1) {
            if (error_found==false)
                if ( !GlobalConfig->currentProfile->getDoReconnectAfterConnectionLost() )
                    reportError(i18n( "Input/output error" ) );

            errorLine = __LINE__;
            error_found = true;
            allowReconnect = true;
        } else if (msg.indexOf("local IP address", 0, Qt::CaseInsensitive) > -1) {
            gui->setTunnelInterfaceIP(msg.simplified().section(' ', 3, 3));
            error_found = true;
        } else if (msg.indexOf("No auth is possible sent", 0, Qt::CaseInsensitive) > -1) {
            if (error_found == false)
                reportError(i18n("No password was send. Please check if there is a password set in user settings."));

            errorLine = __LINE__;
            error_found = true;
        }

        errorMessage(QString("[pppd err] " + msg));

        if (errorLine) {
            if ( allowReconnect && GlobalConfig->currentProfile->getDoReconnectAfterConnectionLost() )
            {
                if ( GlobalConfig->currentProfile->getUseReconnectDelay() )
                {
                    debugMessage (0, i18n ( "Waiting %1s for reconnect..." ).arg ( GlobalConfig->currentProfile->getReconnectDelay() ));
                    for ( int time = 0; time <= GlobalConfig->currentProfile->getReconnectDelay() * 1000; time += 200 )
                    {
                        usleep ( 200 );
                        GlobalConfig->appPointer->processEvents();
                    }
                }
                //          if (GlobalConfig->KvpncDebugLevel > 0)
                debugMessage (0, i18n ( "Reconnect after connection lost enabled, reconnecting..." ));
            }

            setStatusDisconnected(errorLine, reason);
            return ;
        }
        //   GlobalConfig->appPointer->processEvents();
    }
}

void PptpHandler::pptpProcessExited(int, QProcess::ExitStatus)
{
    //  logMessage ( i18n ( "Connection has been terminated." ), KVpncEnum::info );
    //  setStatusDisconnected(__LINE__);

    //  if (QFile("/sbin/resolvconf").exists() && QFile("/etc/init.d/resolvconf").exists())
    //  {
    //
    //    QFile downfile ( tmpPath + "pptpd." + GlobalConfig->currentProfile->getName() + ".down" );
    //    QTextStream downstream ( &downfile );
    //    if ( downfile.open ( QIODevice::WriteOnly ) )
    //    {
    //     downstream <<  "#!"<< GlobalConfig->InterpreterShell << "\n";
    //     downstream << "# generated by kvpnc. Do not edit it." << "\n";
    //     downstream << "# profile: " + GlobalConfig->currentProfile->getName() << "\n\n";
    //
    //     if (QFile("/sbin/resolvconf").exists() && QFile("/etc/init.d/resolvconf").exists())
    //      downstream << "/etc/init.d/resolvconf start\n";
    //     downfile.close();
    //
    //    QProcess pppdDownProcess(this );
    //    QString proc = GlobalConfig->InterpreterShell;
    //    QStringList args;
    //    args.append ( tmpPath + "pptpd." + GlobalConfig->currentProfile->getName() + ".down" );
    //    pppdDownProcess.setEnvironment(*env);
    //    pppdDownProcess.start(proc,args);
    //    if ( !pppdDownProcess->waitForStarted() )
    //    {
    //     KMessageBox::sorry ( this, i18n ( "Failed to start \"%1\"." , "PptpdDownScript" ) );
    //    }
    //    else
    //    {
    //      pppdDownProcess.waitForFinished();
    //    }
    //   }
    //  }
}

