/*
 * openpgp.cpp - OpenPGP base
 * Copyright (C) 2003  Justin Karneges
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include"openpgp.h"

#include<qptrlist.h>
#include<qstringlist.h>

using namespace OpenPGP;


//----------------------------------------------------------------------------
// Key
//----------------------------------------------------------------------------
Key::Key()
{
}

Key::~Key()
{
}

const QString & Key::keyID() const
{
	return v_keyID;
}

const QString & Key::userID() const
{
	return v_userID;
}

void Key::setKeyID(const QString &s)
{
	v_keyID = s;
}

void Key::setUserID(const QString &s)
{
	v_userID = s;
}


//----------------------------------------------------------------------------
// Request
//----------------------------------------------------------------------------
class Request::Private
{
public:
	Private() {}

	Engine *eng;
	int type;

	QString enc, sig, keyID;
	QDateTime ts;
	int verifyResult;
	QByteArray dec;
	bool badpp;
};

Request::Request(Engine *eng)
:QObject(0)
{
	d = new Private;
	d->eng = eng;
	d->type = None;
	d->badpp = false;
}

Request::~Request()
{
	delete d;
}

int Request::type() const
{
	return d->type;
}

void Request::encrypt(const QByteArray &in, const QStringList &keys)
{
	d->type = Encrypt;
	d->eng->encrypt(this, in, keys);
}

void Request::decrypt(const QString &in)
{
	d->type = Decrypt;
	d->eng->decrypt(this, in);
}

void Request::sign(const QByteArray &in, const QString &keyID)
{
	d->type = Sign;
	d->eng->sign(this, in, keyID);
}

void Request::verify(const QByteArray &in, const QString &sig)
{
	d->type = Verify;
	d->eng->verify(this, in, sig);
}

void Request::submitPassphrase(const QString &str)
{
	d->eng->submitPassphrase(this, str);
}

void Request::op_encryptFinished(bool b, const QString &str)
{
	if(b)
		d->enc = str;
	finished(b);
}

void Request::op_decryptFinished(bool b, const QByteArray &out)
{
	if(b)
		d->dec = out.copy();
	finished(b);
}

void Request::op_signFinished(bool b, const QString &str)
{
	if(b)
		d->sig = str;
	finished(b);
}

void Request::op_verifyFinished(int x, const QString &str, const QDateTime &ts)
{
	bool b;
	if(x != VerifyError) {
		d->keyID = str;
		d->ts = ts;
		d->verifyResult = x;
		b = true;
	}
	else
		b = false;

	finished(b);
}

void Request::op_needPassphrase()
{
	needPassphrase();
}

QString Request::encrypted() const
{
	return d->enc;
}

QByteArray Request::decrypted() const
{
	return d->dec;
}

QString Request::signature() const
{
	return d->sig;
}

QString Request::keyID() const
{
	return d->keyID;
}

QDateTime Request::timestamp() const
{
	return d->ts;
}

int Request::verifyResult() const
{
	return d->verifyResult;
}

void Request::op_setBadPassphrase(bool b)
{
	d->badpp = b;
}

bool Request::badPassphrase() const
{
	return d->badpp;
}


//----------------------------------------------------------------------------
// Engine
//----------------------------------------------------------------------------
Engine::Engine(QObject *parent)
:QObject(parent)
{
}

Engine::~Engine()
{
}

void Engine::encryptFinished(Request *r, bool b, const QString &str)
{
	r->op_encryptFinished(b, str);
}

void Engine::decryptFinished(Request *r, bool b, const QByteArray &out)
{
	r->op_decryptFinished(b, out);
}

void Engine::signFinished(Request *r, bool b, const QString &str)
{
	r->op_signFinished(b, str);
}

void Engine::verifyFinished(Request *r, int x, const QString &str, const QDateTime &ts)
{
	r->op_verifyFinished(x, str, ts);
}

void Engine::needPassphrase(Request *r)
{
	r->op_needPassphrase();
}

void Engine::setBadPassphrase(Request *r, bool b)
{
	r->op_setBadPassphrase(b);
}


//----------------------------------------------------------------------------
// Misc
//----------------------------------------------------------------------------
#include"gnupg.h"
static QPtrList<Engine> createEngineList()
{
	QPtrList<Engine> list;
	list.append(new GnuPG);
	return list;
}

QValueList<EngineItem> OpenPGP::getAllEngines()
{
	QValueList<EngineItem> list;
	QPtrList<Engine> el = createEngineList();
	QPtrListIterator<Engine> it(el);
	for(Engine *e; (e = it.current()); ++it)
		list += qMakePair(e->id(), e->name());
	el.setAutoDelete(true);
	el.clear();
	return list;
}

QValueList<EngineItem> OpenPGP::getAvailableEngines()
{
	QValueList<EngineItem> list;
	QPtrList<Engine> el = createEngineList();
	QPtrListIterator<Engine> it(el);
	for(Engine *e; (e = it.current()); ++it) {
		if(e->checkAvailability())
			list += qMakePair(e->id(), e->name());
	}
	el.setAutoDelete(true);
	el.clear();
	return list;
}

Engine * OpenPGP::createEngine(const QString &id)
{
	if(id == "gpg")
		return (new GnuPG);
	else
		return 0;
}

QString OpenPGP::stripHeaderFooter(const QString &str)
{
	QString s;
	if(str.at(0) != '-')
		return str;
	QStringList lines = QStringList::split('\n', str, true);
	QStringList::ConstIterator it = lines.begin();
	// skip the first line
	++it;
	if(it == lines.end())
		return str;

	// skip the header
	for(; it != lines.end(); ++it) {
		if((*it).isEmpty())
			break;
	}
	if(it == lines.end())
		return str;
	++it;
	if(it == lines.end())
		return str;

	bool first = true;
	for(; it != lines.end(); ++it) {
		if((*it).at(0) == '-')
			break;
		if(!first)
			s += '\n';
		s += (*it);
		first = false;
	}

	return s;
}

QString OpenPGP::addHeaderFooter(const QString &str, int type)
{
	QString stype;
	if(type == 0)
		stype = "MESSAGE";
	else
		stype = "SIGNATURE";

	QString s;
	s += QString("-----BEGIN PGP %1-----\n").arg(stype);
	s += "Version: PGP\n";
	s += "\n";
	s += str + '\n';
	s += QString("-----END PGP %1-----\n").arg(stype);
	return s;
}
