/***************************************************************************
                          keyservers.cpp  -  description
                             -------------------
    begin                : Tue Nov 26 2002
    copyright          : (C) 2002 by Jean-Baptiste Mardelle
    email                : bj@altern.org

    updated to handle gpg21 : Sun Jul 30 10:18:29 CEST 2017
    copyright          : (C) 2017 by Emanoil Kotsev
    email              : deloptes@yahoo.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdlib.h>

#include <tqfile.h>
#include <tqcheckbox.h>
#include <tdeapplication.h>
#include <kiconloader.h>
#include <kcombobox.h>
#include <kdialogbase.h>
#include <tdemessagebox.h>
#include <tqtextcodec.h>
#include <tqlayout.h>
#include <tqlabel.h>
#include <tqdialog.h>
#include <tqpushbutton.h>
#include <tqbuttongroup.h>
#include <tqhbuttongroup.h>
#include <tqvbuttongroup.h>
#include <tqregexp.h>
#include <tqcursor.h>

#include <tdelocale.h>
#include <tdeprocess.h>
#include <tdeprocio.h>
#include <tdelistview.h>
#include <kstatusbar.h>
#include <tdeconfig.h>
#include <klineedit.h>
#include <tdesimpleconfig.h>
#include <tdeaction.h>
#include <kdebug.h>


#include "kgpgsettings.h"
#include "searchres.h"
#include "detailedconsole.h"
#include "keyservers.h"

keyServer::keyServer(TQWidget *parent, const char *name,bool modal,bool autoClose):KDialogBase( Swallow, i18n("Key Server"), Close, Close, parent, name,modal)
{
	autoCloseWindow=autoClose;
	config=new TDESimpleConfig ("kgpgrc");
	page=new keyServerWidget();
	setMainWidget(page);

        syncCombobox();
        page->kLEimportid->setFocus();
	currentKey = TQString();
	hashMap.clear();

        connect(page->Buttonimport,TQ_SIGNAL(clicked()),this,TQ_SLOT(slotImport()));
        connect(page->Buttonsearch,TQ_SIGNAL(clicked()),this,TQ_SLOT(slotSearch()));
        connect(page->Buttonexport,TQ_SIGNAL(clicked()),this,TQ_SLOT(slotPreExport()));
        connect(this,TQ_SIGNAL(okClicked()),this,TQ_SLOT(slotOk()));

	if (KgpgInterface::getGpgVersion() < 210 ) { // was removed in 2.1
		connect(page->cBproxyI,TQ_SIGNAL(toggled(bool)),this,TQ_SLOT(slotEnableProxyI(bool)));
		connect(page->cBproxyE,TQ_SIGNAL(toggled(bool)),this,TQ_SLOT(slotEnableProxyE(bool)));
	}

	connect(page->kLEimportid,  TQ_SIGNAL( textChanged ( const TQString & )), this,  TQ_SLOT( slotTextChanged( const TQString &)));
	if (KgpgInterface::getGpgVersion() < 210 ) { // was removed in 2.1
		page->cBproxyI->setChecked(KGpgSettings::useProxy());
		page->cBproxyE->setChecked(KGpgSettings::useProxy());
		const char *httpproxy = getenv("http_proxy");
		if (httpproxy) {
			page->cBproxyI->setEnabled(true);
			page->cBproxyE->setEnabled(true);
			page->kLEproxyI->setText(httpproxy);
			page->kLEproxyE->setText(httpproxy);
		}
	}

        TDEProcIO *encid=new TDEProcIO(TQTextCodec::codecForLocale());
        *encid << "gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--with-colon"<<"--list-keys";
        TQObject::connect(encid, TQ_SIGNAL(processExited(TDEProcess *)),this, TQ_SLOT(slotprocresult(TDEProcess *)));
        TQObject::connect(encid, TQ_SIGNAL(readReady(TDEProcIO *)),this, TQ_SLOT(slotprocread(TDEProcIO *)));
        encid->start(TDEProcess::NotifyOnExit,true);
        page->Buttonimport->setEnabled( !page->kLEimportid->text().isEmpty());
        page->Buttonsearch->setEnabled( !page->kLEimportid->text().isEmpty());
	setMinimumSize(sizeHint());
}


keyServer::~keyServer()
{}


void keyServer::slotTextChanged( const TQString &text)
{
//	kdDebug(2100) << k_funcinfo << endl;
    page->Buttonimport->setEnabled( !text.isEmpty());
    page->Buttonsearch->setEnabled( !text.isEmpty());

}
void keyServer::slotEnableProxyI(bool on)
{
        page->kLEproxyI->setEnabled(on);
}

void keyServer::slotEnableProxyE(bool on)
{
        page->kLEproxyE->setEnabled(on);
}

void keyServer::slotprocread(TDEProcIO *p)
{
//	kdDebug(2100) << k_funcinfo << endl;
        ///////////////////////////////////////////////////////////////// extract  encryption keys
        TQString tst;
	//TQPixmap pixkeySingle(TDEGlobal::iconLoader()->loadIcon("kgpg_key1",TDEIcon::Small,20));
        while (p->readln(tst)!=-1) {
//		kdDebug(2100) << k_funcinfo << "Read one public key line: " << tst << endl;
		if ( tst.startsWith("pub")  ) {
			currentKey = tst.section(':',4,4).right(8);
			TQStringList lst; lst << tst;
			hashMap.insert(currentKey,tst);
		}
		else {
			hashMap.find(currentKey).data().append(tst);
		}
	}
}

void keyServer::slotprocresult(TDEProcess *) {

	TQMap<TQString,TQString> hashImportList;

	TQMap<TQString,TQStringList>::Iterator ite;
	for (ite = hashMap.begin(); ite != hashMap.end(); ite++) {
		TQString fullname,id;
		bool dead;

		for (TQStringList::Iterator it = ite.data().begin(); it != ite.data().end(); it++) {
			TQString line =  (*it);
//			kdDebug(2100) << k_funcinfo << "Export line: " <<line<< endl;
			if (line.startsWith("pub")) {
				const TQString trust=line.section(':',1,1);
                        switch( trust[0] ) {
                        case 'i':
                                dead=true;
                                break;
                        case 'd':
                                dead=true;
                                break;
                        case 'r':
                                dead=true;
                                break;
                        case 'e':
                                dead=true;
                                break;
                        default:
                                dead=false;
                                break;
                        }
				fullname = line.section(':',9,9);
				id = "0x"+line.section(':',4,4).right(8);
			}
			if ( line.startsWith("uid") && fullname.isEmpty() ) {
				fullname = line.section(':',9,9);
			}
		}
//		if (fullname.length()>35) {
//			fullname.remove(35,fullname.length());
//			fullname+="...";
//		}

		TQString tst;
		if (fullname.find("<",0)!=-1) {
			tst=fullname.section('<',0,0);
		}

		if (!tst.isEmpty()) {
			fullname = tst;
		}

		if ((!dead) && (!fullname.isEmpty())) {
			if ( hashImportList.find(id) == hashImportList.end() ) {
				hashImportList.insert(fullname,id);
			}
		}
	}

	for (TQMap<TQString,TQString>::Iterator ite = hashImportList.begin(); ite != hashImportList.end() ; ite++) {
	//	page->kCBexportkey->insertItem(pixkeySingle,id+": "+tst);
		page->kCBexportkey->insertItem(ite.data()+": "+ite.key());
	}

}

void keyServer::slotSearch()
{
//	kdDebug(2100) << k_funcinfo << endl;
        if (page->kCBimportks->currentText().isEmpty())
                return;

        if (page->kLEimportid->text().isEmpty()) {
                KMessageBox::sorry(this,i18n("You must enter a search string."));
                return;
        }

	currentKey = TQString();
	//listpop = new KeyServer( this,"result",WType_Dialog | WShowModal);
	hashMap.clear();
	invalidKeys.clear();
	keyNumbers=0;
	count=0;
	readmessage=TQString();

	dialogServer=new KDialogBase(KDialogBase::Swallow, i18n("Import Key From Keyserver"),  KDialogBase::Ok | KDialogBase::Close,KDialogBase::Ok,this,0,true);

	dialogServer->setButtonText(KDialogBase::Ok,i18n("&Import"));
	dialogServer->enableButtonOK(false);
	listpop=new searchRes();
	listpop->kLVsearch->setColumnWidthMode(0,TQListView::Manual);
	listpop->kLVsearch->setColumnWidthMode(1,TQListView::Manual);
	listpop->kLVsearch->setColumnWidth(0,150);
	listpop->kLVsearch->setColumnWidth(1,130);
        listpop->statusText->setText(i18n("Connecting to the server..."));
        connect(listpop->kLVsearch,TQ_SIGNAL(selectionChanged()),this,TQ_SLOT(transferKeyID()));
        connect(dialogServer,TQ_SIGNAL(okClicked()),this,TQ_SLOT(preimport()));
        connect(listpop->kLVsearch,TQ_SIGNAL(doubleClicked(TQListViewItem *,const TQPoint &,int)),dialogServer,TQ_SIGNAL(okClicked()));

        connect(dialogServer,TQ_SIGNAL(closeClicked()),this,TQ_SLOT(handleQuit()));
        connect( listpop , TQ_SIGNAL( destroyed() ) , this, TQ_SLOT( abortSearch()));

        searchproc=new TDEProcIO(TQTextCodec::codecForLocale());
        TQString keyserv=page->kCBimportks->currentText();

	*searchproc<<"gpg"<<"--utf8-strings"/*<<"--no-tty"*/;
	if (KgpgInterface::getGpgVersion() < 210 ) { // was removed in 2.1
		if (page->cBproxyI->isChecked()) {
			searchproc->setEnvironment("http_proxy",page->kLEproxyI->text());
			*searchproc<<	"--keyserver-options"<<"honor-http-proxy";
		}
		else {
			*searchproc<<	"--keyserver-options"<<"no-honor-http-proxy";
		}
	}
	*searchproc<<"--keyserver"<<keyserv<<"--command-fd=0"<<"--with-colon";
	*searchproc<<"--status-fd=2"<<"--search-keys"<<page->kLEimportid->text().stripWhiteSpace();

        keyNumbers=0;
	TQApplication::setOverrideCursor(TQCursor(TQt::BusyCursor));
        TQObject::connect(searchproc, TQ_SIGNAL(processExited(TDEProcess *)),this, TQ_SLOT(slotsearchresult(TDEProcess *)));
        TQObject::connect(searchproc, TQ_SIGNAL(readReady(TDEProcIO *)),this, TQ_SLOT(slotsearchread(TDEProcIO *)));
	searchproc->setUsePty(TDEProcess::Stdout,false); // EKO: very important line - it took me a day to find out why I should use it
        searchproc->start(TDEProcess::NotifyOnExit,true);

	dialogServer->setMainWidget(listpop);
	listpop->setMinimumSize(listpop->sizeHint());
	listpop->setMinimumWidth(550);
        dialogServer->exec();
}

void keyServer::handleQuit()
{
//	kdDebug(2100) << k_funcinfo << endl;
	if (searchproc->isRunning())
	{
	    TQApplication::restoreOverrideCursor();
	    searchproc->closePty();
	    disconnect(searchproc,0,0,0);
	    searchproc->kill();
	}
	dialogServer->close();
}


void keyServer::abortSearch()
{
//	kdDebug(2100) << k_funcinfo << endl;
        if (dialogServer) {
                delete dialogServer;
                dialogServer=0L;
        }
}

void keyServer::preimport()
{
//	kdDebug(2100) << k_funcinfo << endl;
        transferKeyID();
        if (listpop->kLEID->text().isEmpty()) {
                KMessageBox::sorry(this,i18n("You must choose a key."));
                return;
        }
        page->kLEimportid->setText(listpop->kLEID->text());
        dialogServer->close();
        slotImport();
}

void keyServer::transferKeyID()
{
//	kdDebug(2100) << k_funcinfo << endl;
        if (!listpop->kLVsearch->firstChild())
                return;
        TQString kid,keysToSearch;
	listpop->kLEID->clear();
	TQPtrList< TQListViewItem >searchList=listpop->kLVsearch->selectedItems();

	for ( uint i = 0; i < searchList.count(); ++i )
	{
                if ( searchList.at(i) )
		keysToSearch.append(" "+searchList.at(i)->text(3));
	}
//	kdDebug(2100)<<keysToSearch<<endl;
	listpop->kLEID->setText(keysToSearch.stripWhiteSpace());
}

void keyServer::slotsearchread(TDEProcIO *p)
{
//	kdDebug(2100) << k_funcinfo << endl;
	TQString required = TQString();

	while (p->readln(required,true)!=-1) {
	//	kdDebug(2100) << "\tRead one search key line: " << required << endl;
		if (required.find("keysearch.prompt")!=-1) {
			p->setComm(TDEProcess::Stdin);
			if (KgpgInterface::getGpgVersion() < 210) {
				if (count != 1) {
					p->writeStdin(TQString("N"));
				}
				else {
					p->writeStdin(TQString("Q"));
					p->closeWhenDone();
				}
			}
			else {
				p->writeStdin(TQString("N")); // in 2.1 pressing N ends the session if output is empty
//				if (count == 1)
//					p->closeWhenDone();
			}
			p->setComm(TDEProcess::Stdout);
			required = TQString();
			continue;
		}
		if ( required.isEmpty() ) {
			continue;
		}
		if ( required.find("GOT_IT")!=-1 ) {
			required = TQString();
			continue;
		}

		if ( required.startsWith("info") ) {
			count = required.section(':',2,2).toInt();
			required = TQString();
			continue;
		}
		if ( required.startsWith("pub") ) {
			currentKey = required.section(':',1,1).right(8);
			if ( hashMap.find(currentKey) == hashMap.end() ) {
				TQStringList lst; lst.append(required.simplifyWhiteSpace());
				hashMap.insert(currentKey,lst);
				count--;
			}
			else {
				hashMap.find(currentKey).data().append(required.simplifyWhiteSpace());
			}
			required = TQString();
		}
		else {
			hashMap.find(currentKey).data().append(required.simplifyWhiteSpace());
			required = TQString();
		}
	}
}

void keyServer::slotsearchresult(TDEProcess *)
{
//	kdDebug(2100) << k_funcinfo << endl;
	TQString nb;

	// check if key is valid
	for (TQMap<TQString,TQStringList>::Iterator ite = hashMap.begin(); ite != hashMap.end() ; ite++) {
		TQStringList::Iterator it;
		bool skip=false;
		// this is to prevent offering to import expired or revoked keys 
		//  first find out if key is revoked or expired
		for (it = ite.data().begin(); it != ite.data().end();  it++ ) {
			TQStringList keyString=TQStringList::split(":",(*it),true);
		//	kdDebug(2100) << k_funcinfo << "Key line: " << (*it) << endl;
			if (keyString[0] == "pub") {
				if (! keyString[6].isEmpty() ) {
					if (keyString[6] == "r") {
						skip = true;
					}
				}
				if (! keyString[5].isEmpty() ) { // expiration date
					TQDate date;
					if (KgpgInterface::getGpgVersion() >= 210 ) {
						TQDateTime timestamp;
						timestamp.setTime_t( keyString[5].toInt() );
						date = timestamp.date();
					}
					else {
						date = TQDate::fromString(keyString[5], TQt::ISODate);
					}
					Q_ASSERT (date.isValid()) /*tqWarning("create date is not valid")*/;
					if (date < TQDate::currentDate() ) {
						skip = true;
					}
				}
			}
		}
		if (skip) {
			invalidKeys<<ite.key();
		}
	}

	for (TQMap<TQString,TQStringList>::Iterator ite = hashMap.begin(); ite != hashMap.end() ; ite++) {
		if (invalidKeys.find(ite.key()) != invalidKeys.end() ) {
			continue;
		}
		// very good our keys is neither revoken nor expired  - we can offer it for download
		for (TQStringList::Iterator it = ite.data().begin(); it != ite.data().end();  it++ ) {
			TQStringList keyString=TQStringList::split(":",(*it),true);
		//	kdDebug(2100) << k_funcinfo << "Processing key line: " << (*it) << endl;
			TQString created;
			if (keyString[0] == "pub") {
				if (! keyString[4].isEmpty() ) {
					TQDate date;
					if (KgpgInterface::getGpgVersion() >= 210 ) {
						TQDateTime timestamp;
						timestamp.setTime_t( keyString[4].toInt() );
						date = timestamp.date();
					}
					else {
						date = TQDate::fromString(keyString[4], TQt::ISODate);
					}
					created=TDEGlobal::locale()->formatDate(date, true);
				}
				kitem=new TDEListViewItem(listpop->kLVsearch,TQString(),TQString(), created, keyString[1]);
				keyNumbers++;
			}
			if (keyString[0] == "uid") {
				TQString keymail,keyname;
				if (! keyString[2].isEmpty() ) {
					TQDate date;
					if (KgpgInterface::getGpgVersion() >= 210 ) {
						TQDateTime timestamp;
						timestamp.setTime_t( keyString[2].toInt() );
						date = timestamp.date();
					}
					else {
						date = TQDate::fromString(keyString[2], TQt::ISODate);
					}
					created=TDEGlobal::locale()->formatDate(date, true);
				}
				if (keyString[1].find("<")!=-1) {
					keymail=keyString[1].section('<',-1,-1);
					if (keymail.endsWith(">")) {
						keymail.truncate(keymail.length()-1);
					}
					keyname=keyString[1].section('<',0,0);
				}
				else {
					keymail=TQString();
					keyname=keyString[1];
				}
				if (kitem != 0 ) {
					kitem->setText(0,keyname);
					//if ( kitem->getText(1).isEmpty() ) kitem->setText(1,keymail);
					TDEListViewItem *subk = new TDEListViewItem(kitem,keyname,keymail,created,TQString());
					subk->setSelectable(false);
				}
			}
		}
	}

	dialogServer->enableButtonOK(true);
	TQApplication::restoreOverrideCursor();
        nb=nb.setNum(keyNumbers);
        //listpop->kLVsearch->setColumnText(0,i18n("Found %1 matching keys").arg(nb));
        listpop->statusText->setText(i18n("Found %1 matching keys").arg(nb));

        if (listpop->kLVsearch->firstChild()!=NULL) {
                listpop->kLVsearch->setSelected(listpop->kLVsearch->firstChild(),true);
		listpop->kLVsearch->setCurrentItem(listpop->kLVsearch->firstChild());
                transferKeyID();
        }
}

void keyServer::slotPreExport()
{
//	kdDebug(2100) << k_funcinfo << endl;
	slotExport(TQStringList(page->kCBexportkey->currentText().section(':', 0, 0)));
}

void keyServer::slotExport(TQStringList keyIds)
{
//	kdDebug(2100) << k_funcinfo << endl;
        if (page->kCBexportks->currentText().isEmpty())
                return;
        readmessage=TQString();
        hashMap.clear();
        exportproc=new TDEProcIO(TQTextCodec::codecForLocale());
        TQString keyserv=page->kCBexportks->currentText();

	*exportproc<<"gpg"<<"--utf8-strings";
	if (!page->exportAttributes->isChecked()) {
		*exportproc<<"--export-options"<<"no-include-attributes";
	}
	if (KgpgInterface::getGpgVersion() < 210 ) { // was removed in 2.1
		if (page->cBproxyE->isChecked()) {
			exportproc->setEnvironment("http_proxy",page->kLEproxyE->text());
			*exportproc<<	"--keyserver-options"<<"honor-http-proxy";
		}
		else {
			*exportproc<<	"--keyserver-options"<<"no-honor-http-proxy";
		}
	}
	*exportproc << "--status-fd=2" << "--keyserver" << keyserv << "--send-keys" << keyIds;

        TQObject::connect(exportproc, TQ_SIGNAL(processExited(TDEProcess *)),this, TQ_SLOT(slotexportresult(TDEProcess *)));
        TQObject::connect(exportproc, TQ_SIGNAL(readReady(TDEProcIO *)),this, TQ_SLOT(slotimportread(TDEProcIO *)));
        exportproc->start(TDEProcess::NotifyOnExit,true);
	TQApplication::setOverrideCursor(TQCursor(TQt::BusyCursor));
        importpop = new TQDialog( this,0,true,TQt::WDestructiveClose);
        TQVBoxLayout *vbox=new TQVBoxLayout(importpop,3);
        TQLabel *tex=new TQLabel(importpop);
        tex->setText(i18n("<b>Connecting to the server...</b>"));
        TQPushButton *Buttonabort=new TQPushButton(i18n("&Abort"),importpop);
        vbox->addWidget(tex);
        vbox->addWidget(Buttonabort);
        importpop->setMinimumWidth(250);
        importpop->adjustSize();
        importpop->show();
        connect(importpop,TQ_SIGNAL(destroyed ()),this,TQ_SLOT(abortExport()));
	connect(Buttonabort,TQ_SIGNAL(clicked ()),importpop,TQ_SLOT(close()));
}

void keyServer::abortExport()
{
//	kdDebug(2100) << k_funcinfo << endl;
	TQApplication::restoreOverrideCursor();
        if (exportproc->isRunning())
	{
	    disconnect(exportproc,0,0,0);
	    exportproc->kill();
	}
}

void keyServer::slotexportresult(TDEProcess*)
{
//	kdDebug(2100) << k_funcinfo << endl;
	TQApplication::restoreOverrideCursor();
        KMessageBox::information(0,readmessage);
        if (importpop)
                delete importpop;
}

void keyServer::slotImport()
{
//	kdDebug(2100) << k_funcinfo << endl;
        if (page->kCBimportks->currentText().isEmpty())
                return;
        if (page->kLEimportid->text().isEmpty()) {
                KMessageBox::sorry(this,i18n("You must select a valid key for import"));
                return;
        }

//	kdDebug(2100) << k_funcinfo << "Asked for import: " <<page->kLEimportid->text() <<endl;

	readmessage=TQString();
	count=0;
	hashMap.clear();
	invalidKeys.clear();
	keysToImport.clear();
	TQString keyserv=page->kCBimportks->currentText();
/*
 *
 * This function is called from search and from signature import
 * so we need to make sure we have a valid keys for import
 * When import is triggered from the search key dialog, we alread have the full ids
 * When import is triggered from the signature import popup, we have names, but only
 * if single signature is select we can import from the server
 *
 * search the keys first and pass the full pub key ids to the importproc
 * to prevent importing pub keys for revocation and normal pub keys together
 * we check to see if key is marked as revoc and look for another key that would
 * be associated with the revoking one, so we skip both key and everything that 
 * belongs to this public key
 *
 * we also check the expiration date and refuse to import expired keys
 *
 */

        TQString keyNames=page->kLEimportid->text();
        keyNames=keyNames.stripWhiteSpace();
        keyNames=keyNames.simplifyWhiteSpace();

	if ( keyNames.startsWith("0x") ) {
		searchproc=new TDEProcIO(TQTextCodec::codecForLocale());
		*searchproc << "gpg"<<"--utf8-strings"<<"--no-secmem-warning";
		if (KgpgInterface::getGpgVersion() < 210 ) { // was removed in 2.1
			if (page->cBproxyI->isChecked()) {
				searchproc->setEnvironment("http_proxy",page->kLEproxyI->text());
				*searchproc << "--keyserver-options"<<"honor-http-proxy";
			}
			else {
				*searchproc << "--keyserver-options"<<"no-honor-http-proxy";
			}
		}
		*searchproc << "--keyserver" << keyserv << "--status-fd=2" /*<<"--debug-level"<<"guru"*/;
		*searchproc << "--command-fd=0" << "--with-colon" << "--search-keys";

		while (!keyNames.isEmpty()) {
			TQString fkeyNames=keyNames.section(' ',0,0);
			keyNames.remove(0,fkeyNames.length());
			keyNames=keyNames.stripWhiteSpace();
			*searchproc<< TQString(TQFile::encodeName(fkeyNames));
		}
		TQObject::connect(searchproc, TQ_SIGNAL(processExited(TDEProcess *)),this, TQ_SLOT(slotksearchprocresult(TDEProcess *)));
		TQObject::connect(searchproc, TQ_SIGNAL(readReady(TDEProcIO *)),this, TQ_SLOT(slotsearchread(TDEProcIO *)));
		TQApplication::setOverrideCursor(TQCursor(TQt::BusyCursor));
		searchproc->setUsePty(TDEProcess::Stdout,false); // EKO: very important line - it took me a day to find out why I should use it
		searchproc->start(TDEProcess::Block,true);
		if (searchproc->isRunning()) {
			searchproc->closePty();
			disconnect(searchproc,0,0,0);
			searchproc->kill();
		}
	}
	else {
		keysToImport = TQStringList::split(" ",keyNames,true);
	}

	importproc=new TDEProcIO(TQTextCodec::codecForLocale());
	*importproc<<"gpg"<<"--utf8-strings";
	if (KgpgInterface::getGpgVersion() < 210 ) { // was removed in 2.1
		if (page->cBproxyI->isChecked()) {
			importproc->setEnvironment("http_proxy",page->kLEproxyI->text());
			*importproc<<	"--keyserver-options"<<"honor-http-proxy";
		}
		else {
			*importproc<<	"--keyserver-options"<<"no-honor-http-proxy";
		}
	}
	*importproc<<"--status-fd=2"<<"--keyserver"<<keyserv<<"--recv-keys";

	for (TQStringList::Iterator it = keysToImport.begin(); it != keysToImport.end();  it++ ) {
		*importproc<< (*it) ;
	}

	TQObject::connect(importproc, TQ_SIGNAL(processExited(TDEProcess *)),this, TQ_SLOT(slotimportresult(TDEProcess *)));
	TQObject::connect(importproc, TQ_SIGNAL(readReady(TDEProcIO *)),this, TQ_SLOT(slotimportread(TDEProcIO *)));

        importproc->start(TDEProcess::NotifyOnExit,true);
	importproc->closeWhenDone();

        importpop = new TQDialog( this,0,true,TQt::WDestructiveClose);
        TQVBoxLayout *vbox=new TQVBoxLayout(importpop,3);
        TQLabel *tex=new TQLabel(importpop);
        tex->setText(i18n("<b>Connecting to the server...</b>"));
        TQPushButton *Buttonabort=new TQPushButton(i18n("&Abort"),importpop);
        vbox->addWidget(tex);
        vbox->addWidget(Buttonabort);
        importpop->setMinimumWidth(250);
        importpop->adjustSize();
        importpop->show();
	connect(Buttonabort,TQ_SIGNAL(clicked()),importpop,TQ_SLOT(close()));
	connect(importpop,TQ_SIGNAL(destroyed ()),this,TQ_SLOT(abortImport()));
}

void keyServer::abortImport()
{
//	kdDebug(2100) << k_funcinfo << endl;
	TQApplication::restoreOverrideCursor();
	if (importproc->isRunning())
	{
	    disconnect(importproc,0,0,0);
	    importproc->kill();
	    emit importFinished(TQString());
	}
	if (autoCloseWindow) close();
}

void keyServer::slotksearchprocresult(TDEProcess *) {
//	kdDebug(2100) << k_funcinfo << k_funcinfo << endl;
	// leave only valid keys in the list
	for (TQMap<TQString,TQStringList>::Iterator ite = hashMap.begin(); ite != hashMap.end() ; ite++) {
		bool exp=false;
		bool rev=false;
		for (TQStringList::Iterator it = ite.data().begin(); it != ite.data().end();  it++ ) {
			TQStringList keyString=TQStringList::split(":",(*it),true);
		//	kdDebug(2100) << k_funcinfo << "Read one key line: " << (*it) << endl;
			if (keyString[0] == "pub") {
				if (! keyString[6].isEmpty() ) {
					if (keyString[6] == "r") {
						rev = true;
					}
				}
				if (! keyString[5].isEmpty() ) { // expiration date
					TQDate date;
					if (KgpgInterface::getGpgVersion() >= 210 ) {
						TQDateTime timestamp;
						timestamp.setTime_t( keyString[5].toInt() );
						date = timestamp.date();
					}
					else {
						date = TQDate::fromString(keyString[5], TQt::ISODate);
					}
					Q_ASSERT (date.isValid()) /*tqWarning("create date is not valid")*/;
					if (date < TQDate::currentDate() ) {
						exp = true;
					}
				}
			}
		}
		if (exp || rev) {
			invalidKeys<<ite.key();
			readmessage += "<qt>"+i18n("Public Key")+": <i>0x";
			if (rev) {
				readmessage += ite.key() + " (" + i18n("Revoked");
			}
			if (exp) {
				readmessage += ", "+i18n("Expired");
			}
			readmessage += ")</i><br></qt>\n";
		}
	}

	for (TQMap<TQString,TQStringList>::Iterator ite = hashMap.begin(); ite != hashMap.end() ; ite++) {
		if (invalidKeys.find(ite.key()) == invalidKeys.end() ) {
		// keys are neither revoked nor expired
			for (TQStringList::Iterator it = ite.data().begin(); it != ite.data().end();  it++ ) {
				if ( (*it).startsWith("pub") ) {
					keysToImport << (*it).section(":",1,1);
				}
			}
		}
	}
}

void keyServer::slotimportresult(TDEProcess*)
{
//	kdDebug(2100) << k_funcinfo << endl;
	TQApplication::restoreOverrideCursor();
        TQString importedNb,importedNbSucess,importedNbProcess,resultMessage, parsedOutput,importedNbUnchanged,importedNbSig;
	TQString notImportesNbSec,importedNbMissing,importedNbRSA,importedNbUid,importedNbSub,importedNbRev,readNbSec;
	TQString importedNbSec,dupNbSec;

        parsedOutput=readmessage;
	TQStringList importedKeys;
	TQApplication::restoreOverrideCursor();

        while (parsedOutput.find("IMPORTED")!=-1) {
                parsedOutput.remove(0,parsedOutput.find("IMPORTED")+8);
                importedKeys+=parsedOutput.section("\n",0,0).stripWhiteSpace();
        }

        if (readmessage.find("IMPORT_RES")!=-1) {
                importedNb=readmessage.section("IMPORT_RES",-1,-1);
                  importedNb=importedNb.stripWhiteSpace();
                importedNbProcess=importedNb.section(" ",0,0);
		importedNbMissing=importedNb.section(" ",1,1);
                importedNbSucess=importedNb.section(" ",2,2);
		importedNbRSA=importedNb.section(" ",3,3);
		importedNbUnchanged=importedNb.section(" ",4,4);
		importedNbUid=importedNb.section(" ",5,5);
		importedNbSub=importedNb.section(" ",6,6);
		importedNbSig=importedNb.section(" ",7,7);
		importedNbRev=importedNb.section(" ",8,8);
		readNbSec=importedNb.section(" ",9,9);
		importedNbSec=importedNb.section(" ",10,10);
		dupNbSec=importedNb.section(" ",11,11);
		notImportesNbSec=importedNb.section(" ",12,12);
                resultMessage=i18n("<qt>%n key processed.<br></qt>","<qt>%n keys processed.<br></qt>",importedNbProcess.toULong());
		if (importedNbUnchanged!="0")
		resultMessage+=i18n("<qt>One key unchanged.<br></qt>","<qt>%n keys unchanged.<br></qt>",importedNbUnchanged.toULong());
		if (importedNbSig!="0")
		resultMessage+=i18n("<qt>One signature imported.<br></qt>","<qt>%n signatures imported.<br></qt>",importedNbSig.toULong());
		if (importedNbMissing!="0")
		resultMessage+=i18n("<qt>One key without ID.<br></qt>","<qt>%n keys without ID.<br></qt>",importedNbMissing.toULong());
		if (importedNbRSA!="0")
		resultMessage+=i18n("<qt>One RSA key imported.<br></qt>","<qt>%n RSA keys imported.<br></qt>",importedNbRSA.toULong());
		if (importedNbUid!="0")
		resultMessage+=i18n("<qt>One user ID imported.<br></qt>","<qt>%n user IDs imported.<br></qt>",importedNbUid.toULong());
		if (importedNbSub!="0")
		resultMessage+=i18n("<qt>One subkey imported.<br></qt>","<qt>%n subkeys imported.<br></qt>",importedNbSub.toULong());
		if (importedNbRev!="0")
		resultMessage+=i18n("<qt>One revocation certificate imported.<br></qt>","<qt>%n revocation certificates imported.<br></qt>",importedNbRev.toULong());
		if (readNbSec!="0")
		resultMessage+=i18n("<qt>One secret key processed.<br></qt>","<qt>%n secret keys processed.<br></qt>",readNbSec.toULong());
		if (importedNbSec!="0")
		resultMessage+=i18n("<qt><b>One secret key imported.</b><br></qt>","<qt><b>%n secret keys imported.</b><br></qt>",importedNbSec.toULong());
		if (dupNbSec!="0")
		resultMessage+=i18n("<qt>One secret key unchanged.<br></qt>","<qt>%n secret keys unchanged.<br></qt>",dupNbSec.toULong());
		if (notImportesNbSec!="0")
		resultMessage+=i18n("<qt>One secret key not imported.<br></qt>","<qt>%n secret keys not imported.<br></qt>",notImportesNbSec.toULong());
		if (importedNbSucess!="0")
		resultMessage+=i18n("<qt><b>One key imported:</b><br></qt>","<qt><b>%n keys imported:</b><br></qt>",importedNbSucess.toULong());
	}
	else {
		resultMessage=i18n("No key imported... \nCheck detailed log for more infos");
	}

	TQString lastID=TQString( importedKeys.last().section(" ",0,0).right(8));
	if ( !lastID.isEmpty() ) {
		//kdDebug(2100)<<"++++++++++imported key"<<lastID<<endl;
		emit importFinished(lastID);
	}

        if (importpop)
                importpop->hide();
	(void) new KDetailedInfo(0,"import_result",resultMessage,readmessage,importedKeys);

        if (importpop)
                delete importpop;
	if (autoCloseWindow) close();
}

void keyServer::slotimportread(TDEProcIO *p)
{
        TQString required;
        while (p->readln(required,true)!=-1)
                readmessage+=required+"\n";
}

void keyServer::syncCombobox()
{
//	kdDebug(2100) << k_funcinfo << endl;
        config->setGroup("Servers");
        TQString serverList=config->readEntry("Server_List");

        TQString optionsServer=KgpgInterface::getGpgSetting("keyserver", KGpgSettings::gpgConfigPath());

	page->kCBexportks->clear();
	page->kCBimportks->clear();

	if (!optionsServer.isEmpty()) {
		page->kCBexportks->insertItem(optionsServer + " " + i18n("(Default)"));
		page->kCBimportks->insertItem(optionsServer + " " + i18n("(Default)"));
	}
	else if ( serverList.isEmpty() )
		serverList = "hkp://pool.sks-keyservers.net"; // same as ini kgpgoptions.cpp
	
	page->kCBexportks->insertStringList(TQStringList::split(",",serverList));
	page->kCBimportks->insertStringList(TQStringList::split(",",serverList));
}

void keyServer::slotOk()
{
        accept();
}


#include "keyservers.moc"
