/*****************************************************************************
 * 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 "manageciscocert.h"

#include <QGroupBox>
#include <QtCore/QStringList>
#include <QtGui/QMenu>


#include <QTreeView>
#include <kcombobox.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kpassworddialog.h>
#include <kpushbutton.h>
#include <kurlrequester.h>
#include <kaction.h>

#include <unistd.h>

#include "displaycertdialog.h"
#include "importcertificatedialog.h"
#include "utils.h"

ManageCiscoCert::ManageCiscoCert(QWidget *parent, const char* caption, KVpncConfig *GlobalConfig) : KDialog(parent)
{
    Q_UNUSED(caption);

    QWidget *page = new QWidget(this);
    ManageCiscoCertWidget = new Ui_ManageCiscoCertBase();
    ManageCiscoCertWidget->setupUi(page);
    setMainWidget(page);

    this->GlobalConfig = GlobalConfig;
	
	
	ManageCiscoCertWidget->CertListView->setColumnCount(3);
	QStringList LabelList;
	LabelList << i18n("#") << i18n("Name") << i18n("Type");
	ManageCiscoCertWidget->CertListView->setHeaderLabels(LabelList);
	connect(ManageCiscoCertWidget->CertListView, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(customContextMenuRequested(const QPoint &)));
	connect(ManageCiscoCertWidget->CertListView, SIGNAL(itemActivated(QTreeWidgetItem *, int)), this, SLOT(itemActivated(QTreeWidgetItem *, int)));
	ManageCiscoCertWidget->CertListView->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ManageCiscoCertWidget->ImportCertFilePushButton, SIGNAL(clicked()), this, SLOT(importCertClicked()));
    connect(ManageCiscoCertWidget->DeleteCertPushButton, SIGNAL(clicked()), this, SLOT(deleteCertClicked()));
    checkList();
}


ManageCiscoCert::~ManageCiscoCert()
{
}

void ManageCiscoCert::deleteCertClicked()
{
	if (ManageCiscoCertWidget->CertListView->topLevelItemCount() > 0 && ManageCiscoCertWidget->CertListView->currentItem() != 0) {
		QTreeWidgetItem *item = ManageCiscoCertWidget->CertListView->currentItem();
		QString CertName = item->text(1);
		QString CertType = item->text(2);
		int result = KMessageBox::questionYesNo(this, i18n("Do you really want to delete the cert \"%1\" (type: %2) from cert store?" , CertName, CertType), i18n("Delete certificate?"));
		//LogOutput->append( "Result: "+ QString().setNum(result) ) ;
		if (result == 3) { // Yes
			DeleteProcess = new QProcess(0);
			QString proc = GlobalConfig->pathToCiscoCertMgr;
			QStringList args;
			if (item->text(2) == i18n("User"))
				args.append("-U");
			if (item->text(2) == i18n("CA"))
				args.append("-R");
			args.append("-op");
			args.append("delete");
			args.append("-ct");
			args.append(item->text(0));
			
			connect(DeleteProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readFromStdout_remove()));
			connect(DeleteProcess, SIGNAL(readyReadStandardError()), this, SLOT(readFromStderr_remove()));
			connect(DeleteProcess, SIGNAL(finished(int, QProcess::ExitStatus)) , this, SLOT(deleteProcessFinished(int, QProcess::ExitStatus)));
			
			QStringList env ;
			env << "LC_ALL=C" << "LANG=C" << "PATH=/bin:/usr/bin:/usr/sbin:/sbin";
			
			DeleteProcess->setEnvironment(env);
			DeleteProcess->start(proc, args);
			if (!DeleteProcess->waitForStarted()) {
				KMessageBox::sorry(this, i18n("Unable to start process (%1)." ,   QString("cisco_cert_mgr")));
				//     GlobalConfig->appPointer->restoreOverrideCursor();
			} else {
				if (GlobalConfig->KvpncDebugLevel > 2)
					GlobalConfig->appendLogEntry(i18n("Process (%1) started." ,  QString("cisco_cert_mgr")), KVpncEnum::debug);
				
				QString password = "";
				
				KPasswordDialog dlg(0);
				dlg.setPrompt(i18n("Certificate password"));
				dlg.setWindowTitle(i18n("Enter password"));
				
				
				if (result == QDialog::Accepted) {
					password = dlg.password();
					
					if (GlobalConfig->KvpncDebugLevel > 2)
						GlobalConfig->appendLogEntry(i18n("Certificate password got from user, send it..."), KVpncEnum::debug);
					
					DeleteProcess->write(QString(password).toUtf8() + "\n");
					DeleteProcess->waitForFinished();
					
					checkList();
				} else {
					
					// nothing
				}
				
			}
			disconnect(DeleteProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readFromStdout_remove()));
			disconnect(DeleteProcess, SIGNAL(readyReadStandardError()), this, SLOT(readFromStderr_remove()));
			disconnect(DeleteProcess, SIGNAL(finished(int, QProcess::ExitStatus)) , this, SLOT(deleteProcessFinished(int, QProcess::ExitStatus)));
			delete DeleteProcess;
			DeleteProcess = 0L;
		}
		checkList();
	}
	
}

void ManageCiscoCert::importCertClicked()
{
    ImportCertificateDialog dlg(this, i18n("Import Certificate...").toAscii(), GlobalConfig);
    dlg.main->ImporttypeComboBox->setCurrentItem("Cisco (proprietary)");
    dlg.typeToggeled(VpnAccountData::ciscoorig);
    dlg.main->ImporttypeComboBox->setEnabled(false);
    dlg.main->P12GroupBox->setTitle(i18n("Import"));
    dlg.main->CertPathTextLabel->hide();
    dlg.main->RacoonCertificatePathUrlrequester->hide();
    dlg.main->PrivateKeyPassGroupBox->setTitle(i18n("Certificate protection"));
    dlg.main->PrivateKeyPassTextLabel->setText(i18n("Certificate password:"));
    dlg.main->PrivateKeyPassAgainTextLabel->setText(i18n("Certificate password again:"));
    dlg.main->FilenameUrlrequester->setFilter("*");
    //int result =
    dlg.exec();

    checkList();
}

void ManageCiscoCert::showCertClicked()
{
	if (ManageCiscoCertWidget->CertListView->topLevelItemCount() > 0 && ManageCiscoCertWidget->CertListView->currentItem() != 0) {
		QTreeWidgetItem *item = ManageCiscoCertWidget->CertListView->currentItem();
        CertDataName = item->text(1);
        CertStartFound = false;

        ShowProcess = new QProcess(0);
        QString proc = GlobalConfig->pathToCiscoCertMgr;
        QStringList args;
        if (item->text(2) == i18n("User")) {
            args.append("-U");
            CertType = i18n("User certificate");
        }
        if (item->text(2) == i18n("CA")) {
            args.append("-R");
            CertType = i18n("CA certificate");
        }
        args.append("-op");
        args.append("view");
        args.append("-ct");
        args.append(item->text(0));

        connect(ShowProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readFromStdout_display()));
        connect(ShowProcess, SIGNAL(readyReadStandardError()), this, SLOT(readFromStderr_display()));
        connect(ShowProcess, SIGNAL(finished(int, QProcess::ExitStatus)) , this, SLOT(showProcessFinished(int, QProcess::ExitStatus)));

        QStringList *env = new QStringList();
        *env << "LC_ALL=C" << "LANG=C" << "PATH=/bin:/usr/bin:/usr/sbin:/sbin";

        GlobalConfig->appPointer->setOverrideCursor(QCursor(Qt::WaitCursor));
        if (GlobalConfig->KvpncDebugLevel > 2)
            GlobalConfig->appendLogEntry(i18n("Getting cert info from Cisco certificate store..."), KVpncEnum::debug);
        ShowProcess->setEnvironment(*env);
        ShowProcess->start(proc, args);
        if (!ShowProcess->waitForStarted()) {

            KMessageBox::sorry(this, i18n("Unable to start process (%1)." ,  QString("cisco_cert_mgr")));
        } else {
            if (GlobalConfig->KvpncDebugLevel > 2)
                GlobalConfig->appendLogEntry(i18n("Process (%1) started." ,  QString("cisco_cert_mgr")), KVpncEnum::debug);
            while (ShowProcess->state() == QProcess::Running) {
                usleep(200);
				if (GlobalConfig->appPointer->hasPendingEvents())
					GlobalConfig->appPointer->processEvents();
            }
        }
    }
}

void ManageCiscoCert::deleteProcessFinished(int, QProcess::ExitStatus)
{
//  delete DeleteProcess;
    checkList();
}

void ManageCiscoCert::showProcessFinished(int, QProcess::ExitStatus)
{
    GlobalConfig->appPointer->restoreOverrideCursor();
    if (GlobalConfig->KvpncDebugLevel > 2)
        GlobalConfig->appendLogEntry(i18n("Done."), KVpncEnum::debug);

    GlobalConfig->slotStatusMsg(i18n("Done."), ID_FLASH_MSG);
    GlobalConfig->slotStatusMsg(i18n("Ready."), ID_STATUS_MSG);
    DisplayCertDialog dlg((QWidget *)0, "Certificate data", GlobalConfig);
    dlg.DisplayCertDialogWidget->CertNameTextLabel->setText(CertDataName);
    dlg.DisplayCertDialogWidget->CertTypeTextLabel->setText(CertType);
    dlg.CertDataList = CertDataList;
    dlg.parseCertData();
    dlg.exec();
    CertDataName = "";
    CertDataList.clear();

    disconnect(ShowProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readFromStdout_display()));
    disconnect(ShowProcess, SIGNAL(readyReadStandardError()), this, SLOT(readFromStderr_display()));
    disconnect(ShowProcess, SIGNAL(finished(int, QProcess::ExitStatus)) , this, SLOT(showProcessFinished(int, QProcess::ExitStatus)));
//  delete ShowProcess;
//  ShowProcess=0L;
}

void ManageCiscoCert::checkList()
{
    GlobalConfig->appPointer->setOverrideCursor(QCursor(Qt::WaitCursor));
    ManageCiscoCertWidget->CertListView->clear();
    GlobalConfig->slotStatusMsg(i18n("Collecting cisco certs from Cisco certificate store..."), ID_STATUS_MSG);
    if (GlobalConfig->KvpncDebugLevel > 2)
        GlobalConfig->appendLogEntry(i18n("Looking for certs in Cisco certificate store..."), KVpncEnum::debug);
    QStringList CiscoCerts  = Utils(GlobalConfig).getCertsFromCiscoCertStore("user");
    if (GlobalConfig->KvpncDebugLevel > 2)
        GlobalConfig->appendLogEntry(i18n("Done."), KVpncEnum::debug);

    GlobalConfig->slotStatusMsg(i18n("Collecting cisco CA certs from Cisco certificate store..."), ID_STATUS_MSG);
    if (GlobalConfig->KvpncDebugLevel > 2)
        GlobalConfig->appendLogEntry(i18n("Looking for CA certs in Cisco certificate store..."), KVpncEnum::debug);
    QStringList CiscoCaCerts  = Utils(GlobalConfig).getCertsFromCiscoCertStore("ca");
    if (GlobalConfig->KvpncDebugLevel > 2)
        GlobalConfig->appendLogEntry(i18n("Done."), KVpncEnum::debug);

    GlobalConfig->slotStatusMsg(i18n("Done."), ID_FLASH_MSG);
    GlobalConfig->slotStatusMsg(i18n("Ready."), ID_STATUS_MSG);
    int current_user_idx = 0;
    int current_ca_idx = 0;
	QList<QTreeWidgetItem *> items;
	QStringList values;
	
    for (QStringList::Iterator it = CiscoCerts.begin(); it != CiscoCerts.end(); ++it) {
		values << QString().setNum(current_user_idx) << QString(*it).trimmed() << i18n("User");
		items.append(new QTreeWidgetItem((QTreeWidget*)0, values));
		values.clear();
        current_user_idx++;
    }
    for (QStringList::Iterator it = CiscoCaCerts.begin(); it != CiscoCaCerts.end(); ++it) {
		values << QString().setNum(current_ca_idx) << QString(*it).trimmed() << i18n("CA");
		items.append(new QTreeWidgetItem((QTreeWidget*)0, values));
		values.clear();
        current_ca_idx++;
    }

	ManageCiscoCertWidget->CertListView->insertTopLevelItems(0, items);

    if (ManageCiscoCertWidget->CertListView->topLevelItemCount() > 0 && ManageCiscoCertWidget->CertListView->currentItem() != 0 && ManageCiscoCertWidget->CertListView->currentItem()->isSelected()) {
        ManageCiscoCertWidget->DeleteCertPushButton->setEnabled(true);
    } else {
        ManageCiscoCertWidget->DeleteCertPushButton->setEnabled(false);
    }
    GlobalConfig->appPointer->restoreOverrideCursor();
}

void ManageCiscoCert::readFromStdout_remove()
{
    QStringList msg_list = QString(DeleteProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString line = msg_list.at(i);

        if (GlobalConfig->KvpncDebugLevel > 2)
            GlobalConfig->appendLogEntry("[cisco_cert_mgr]: " + line, KVpncEnum::debug);
    }
}

void ManageCiscoCert::readFromStderr_remove()
{
    QStringList msg_list = QString(DeleteProcess->readAllStandardError()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString line = msg_list.at(i);
        GlobalConfig->appendLogEntry("[cisco_cert_mgr err]: " + line , KVpncEnum::error);
    }
    checkList();

}

void ManageCiscoCert::readFromStdout_display()
{
    QStringList msg_list = QString(ShowProcess->readAllStandardOutput()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString line = msg_list.at(i);

        if (GlobalConfig->KvpncDebugLevel > 2)
            GlobalConfig->appendLogEntry("[cisco_cert_mgr]: " + line, KVpncEnum::debug);

        if (CertStartFound)
            CertDataList.append(line);
        else {
            if (line.indexOf("Common Name:" , 0, Qt::CaseInsensitive) > -1) {

                if (GlobalConfig->KvpncDebugLevel > 2)
                    GlobalConfig->appendLogEntry(i18n("Cert start found."), KVpncEnum::debug);


                CertStartFound = true;
                CertDataList.append(line);
            }
        }
    }
}

void ManageCiscoCert::readFromStderr_display()
{
    QStringList msg_list = QString(ShowProcess->readAllStandardError()).split('\n');
    for (int i = 0; i < msg_list.size(); ++i) {
        QString line = msg_list.at(i);
        GlobalConfig->appendLogEntry("[cisco_cert_mgr err]: " + line , KVpncEnum::error);
    }

}

void ManageCiscoCert::itemActivated(QTreeWidgetItem *, int)
{
	checkList();
}

void ManageCiscoCert::customContextMenuRequested(const QPoint &pos)
{
	ContextMenu = new QMenu(0);
	QTreeWidgetItem *item = ManageCiscoCertWidget->CertListView->currentItem();
	if (item != 0 && item->isSelected()) {
		KAction *ShowAction = new KAction(this);
		ShowAction->setText(i18n("&Show..."));
		ShowAction->setIcon(KIcon("document-edit"));
		//ShowAction->setShortcut(Qt::Key_S);
		connect(ShowAction, SIGNAL(triggered()), SLOT(showCertClicked()));
		ContextMenu->addAction(ShowAction);

		KAction *DeleteAction = new KAction(this);
		DeleteAction->setText(i18n("&Delete..."));
		DeleteAction->setIcon(KIcon("document-edit"));
		//DeleteAction->setShortcut(Qt::Key_D);
		connect(DeleteAction, SIGNAL(triggered()), SLOT(deleteCertClicked()));
		ContextMenu->addAction(DeleteAction);
	}
	KAction *AddAction = new KAction(this);
	AddAction->setText(i18n("Add..."));
	AddAction->setIcon(KIcon("document-new"));
	//AddAction->setShortcut(Qt::Key_A);
	ContextMenu->addAction(AddAction);
	ContextMenu->show();
	ContextMenu->setGeometry(ManageCiscoCertWidget->CertListView->mapToGlobal(pos).x(), ManageCiscoCertWidget->CertListView->mapToGlobal(pos).y(), ContextMenu->width(), ContextMenu->height());
}


