[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kmail-devel
Subject:    PGP 6.x for kmail 1.0.28
From:       Andreas Gungl <a.gungl () gmx ! de>
Date:       2000-02-03 19:21:28
[Download RAW message or body]

Hi,

for all who are interested in PGP 6.x support for kmail 1.0.28 I do
attach the modified files.
The code is mostly the same like in kmail 1.1.33 - but for that
version you better get the files via cvs/cvsup.

Andreas
--=20
    ~
  ' v '
 //   \\
/(     )\  Powered by Penguin.
  ^ ' ^


["kpgp.h" (text/x-c++)]

/** KPGP: Pretty good privacy en-/decryption class
 *        This code is under GPL V2.0
 *
 * @author Lars Knoll <knoll@mpi-hd.mpg.de>
 */
#ifndef KPGP_H
#define KPGP_H

#include <stdio.h>
#include <qstring.h>
#include <qstrlist.h>
#include <qdialog.h>
#include <qwidget.h>
#include <qcombobox.h>
#include <qlayout.h>
#include <qpushbt.h>
#include <qlistbox.h>

class QLineEdit;
class QCursor;
class QCheckBox;
class QGridLayout;

class KSimpleConfig;
class KpgpBase;

class Kpgp
{

private:
  // the class running pgp
  KpgpBase *pgp;

public:
  Kpgp();
  virtual ~Kpgp();

  virtual void readConfig();
  virtual void writeConfig(bool sync);
  virtual void init();

  /** sets the message to en- or decrypt 
    returns TRUE if the message contains any pgp encoded or signed
    parts 
    The format is then:
    frontmatter()
    ----- BEGIN PGP ...
    message()
    ----- END PGP ...
    backmatter()
    */
  virtual bool setMessage(const QString mess);
  /** gets the de- (or en)crypted message */
  virtual const QString message(void) const;
  /** gets the part before the decrypted message */
  virtual const QString frontmatter(void) const;
  /** gets the part after the decrypted message */
  virtual const QString backmatter(void) const;

  /** decrypts the message if the passphrase is good.
    returns false otherwise */
  bool decrypt(void);
  /** encrypt the message for a list of persons. */
  bool encryptFor(const QStrList& receivers, bool sign = TRUE);

protected:
  int doEncSign(QStrList persons, bool sign, bool ignoreUntrusted = false);

public:
  /** sign the message. */
  bool sign(void);
  /** sign a key in the keyring with users signature. */
  bool signKey(QString _key);
  /** get the known public keys. */
  const QStrList* keys(void);
  /** check if we have a public key for given person. */
  bool havePublicKey(QString person);
  /** try to get the public key for this person */
  QString getPublicKey(QString _person);
  /** try to ascii output of the public key of this person */
  QString getAsciiPublicKey(QString _person);
     
  /** is the message encrypted ? */
  bool isEncrypted(void) const;
  /** the persons who can decrypt the message */
  const QStrList* receivers(void) const;
  /** shows the secret key which is needed
    to decrypt the message */
  const QString KeyToDecrypt(void) const;

  /** is the message signed by someone */
  bool isSigned(void) const;
  /** it is signed by ... */
  QString signedBy(void) const;
  /** keyID of signer */
  QString signedByKey(void) const;
  /** is the signature good ? */
  bool goodSignature(void) const;

  /** change the passphrase of the actual secret key */
  bool changePassPhrase(const QString oldPass, const QString newPass);

  /** Set pass phrase */
  void setPassPhrase(const QString pass);

 /** set a user identity to use (if you have more than one...)
   * by default, pgp uses the identity which was generated last. */
  void setUser(const QString user);
  /** Returns the actual user identity. */
  const QString user(void) const;

  /** always encrypt message to oneself? */
  void setEncryptToSelf(bool flag);
  bool encryptToSelf(void) const;

  /** store passphrase in pgp object
    Problem: passphrase stays in memory. 
    Advantage: you can call en-/decrypt without always passing the
    passphrase */
  void setStorePassPhrase(bool);
  bool storePassPhrase(void) const;

  /** clears everything from memory */
  void clear(bool erasePassPhrase = FALSE);

  /** returns the last error that occured */
  const QString lastErrorMsg(void) const;

  /// did we find a pgp executable?
  bool havePGP(void) const;

  // FIXME: key management

  // static methods

  /** return the actual pgp object */
  static Kpgp *getKpgp();

  /** get the kpgp config object */
  static KSimpleConfig *getConfig();

  /** pops up a modal window which asks for the passphrase 
   puts the window on top of the parent, or in the middle of the screen,
   if parent = 0 */
  static const QString askForPass(QWidget *parent = 0);

private:
  // test if the PGP executable is found and if there is a passphrase
  // set or given. Returns TRUE if everything is ok, and FALSE (together
  // with some warning message) if something is missing.
  bool prepare(bool needPassPhrase=FALSE);

  // cleanup passphrase if it should not be stored.
  void cleanupPass(void);

  // transform an adress into canonical form
  QString canonicalAdress(QString _person);

  //Select public key from a list of all public keys
  QString SelectPublicKey(QStrList* pbkeys,const char * caption);

  bool checkForPGP(void);

  static Kpgp *kpgpObject;
  KSimpleConfig *config;

  QStrList publicKeys;
  QString front;
  QString back;
  QString errMsg;

  bool storePass;
  QString passphrase;

  bool havePgp;
  bool havePGP5;
  bool havePassPhrase;
  bool needPublicKeys;
};

// -------------------------------------------------------------------------
class KpgpPass : public QDialog
{
  Q_OBJECT

public:
  /** the passphrase dialog */
  KpgpPass(QWidget *parent = 0, const char *name = 0);
  virtual ~KpgpPass();

  static QString getPassphrase(QWidget *parent = 0);

private:
  QString getPhrase();

  QLineEdit *lineedit; 
  QCursor *cursor;
};

// -------------------------------------------------------------------------
class KpgpKey : public QDialog
{
  Q_OBJECT

public:
  /** the passphrase dialog */
  KpgpKey(QWidget *parent = 0, const char *name = 0, const QStrList *keys = NULL);
  virtual ~KpgpKey();

  static QString getKeyName(QWidget *parent = 0, const QStrList *keys = NULL);

private:
  QString getKey();

  QComboBox *combobox; 
  QPushButton *button;
  QCursor *cursor;
};

// -------------------------------------------------------------------------
class KpgpConfig : public QWidget
{
  Q_OBJECT

public:
  /** a widget for configuring the pgp interface. Can be included into
   a tabdialog. This widget by itself does not provide an apply/cancel
   button mechanism. */
  KpgpConfig(QWidget *parent = 0, const char *name = 0);
  virtual ~KpgpConfig();

  virtual void applySettings();
  QLineEdit* createLabeledEntry(QGridLayout* grid,
				const char* aLabel,
				const char* aText, 
				int gridy, int gridx);
       
protected:
  Kpgp *pgp;
  QLineEdit *pgpUserEdit;
  QCheckBox *storePass;
  QCheckBox *encToSelf;

};

// -------------------------------------------------------------------------
class KpgpSelDlg: public QDialog
{
  Q_OBJECT
public:
  KpgpSelDlg(QStrList* aKeyList, const char* caption=NULL);
  virtual ~KpgpSelDlg() {};

  virtual const QString key(void) const {return mkey;};

protected slots:
  void slotOk();
  void slotCancel();

protected:
  QGridLayout mGrid;
  QListBox mListBox;
  QPushButton mBtnOk, mBtnCancel;
  QString mkey;
  QStrList* mKeyList;
};

#endif


["kpgp.cpp" (text/x-c++)]

#include "kpgp.moc"
#include "kpgpbase.h"

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <assert.h>
#include <stdarg.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>

#include <qregexp.h>
#include <qcursor.h>
#include <qlabel.h>
#include <qlined.h>
#include <qchkbox.h>
#include <qgrpbox.h>
#include <qlayout.h>

#include <kapp.h>
#include <ksimpleconfig.h>
#include <kiconloader.h>
#include <kmsgbox.h>

Kpgp *Kpgp::kpgpObject = 0L;

Kpgp::Kpgp()
  : publicKeys()
{
  kpgpObject=this;

  // open kpgp config file
  QString aStr = kapp->localconfigdir();
  aStr += "/kpgprc";
  config = new KSimpleConfig(aStr);

  init();
}

Kpgp::~Kpgp()
{
  clear(TRUE);
  delete config;
}

// ----------------- public methods -------------------------

void 
Kpgp::init()
{
  havePassPhrase = FALSE;
  passphrase = 0;

  // do we have a pgp executable
  checkForPGP();

  if(havePgp)
  {
    if(havePGP5)
      pgp = new KpgpBase5();
    else
    {
      KpgpBase6 *pgp_v6 = new KpgpBase6();
      if (!pgp_v6->isVersion6())
      {
        delete pgp_v6;
        pgp = new KpgpBase2();
      }
      else pgp = pgp_v6;
    }
  }
  else
  {
    // dummy handler
    pgp = new KpgpBase();
    return;
  }

  // read kpgp config file entries
  readConfig();

  // get public keys
  // No! This takes time since pgp takes some ridicules
  // time to start, blocking everything (pressing any key _on_
  // _the_ _machine_ _where_ _pgp_ _runs: helps; ???)
  // So we will ask for keys when we need them.
  
  //publicKeys = pgp->pubKeys(); This can return 0!!!
  needPublicKeys = true;
}

void 
Kpgp::readConfig()
{
  storePass = config->readBoolEntry("storePass");
}

void
Kpgp::writeConfig(bool sync)
{
  config->writeEntry("storePass",storePass);

  pgp->writeConfig();

  if(sync)
    config->sync();
}

void
Kpgp::setUser(const QString aUser)
{
  pgp->setUser(aUser);
}

const QString 
Kpgp::user(void) const 
{ 
  return pgp->user(); 
}

void 
Kpgp::setEncryptToSelf(bool flag)
{
  pgp->setEncryptToSelf(flag);
}

bool 
Kpgp::encryptToSelf(void) const
{
  return pgp->encryptToSelf();
}

bool 
Kpgp::storePassPhrase(void) const
{
  return storePass;
}

void 
Kpgp::setStorePassPhrase(bool flag)
{
  storePass = flag;
}


bool 
Kpgp::setMessage(const QString mess)
{
  int index;
  int retval = 0;

  clear();

  if(havePgp)
    retval = pgp->setMessage(mess);
  if((index = mess.find("-----BEGIN PGP")) != -1)
  {
    if(!havePgp)
    {
      errMsg = i18n("Couldn't find PGP executable.\n"
			 "Please check your PATH is set correctly.");
      return FALSE;
    }
    if(retval != 0)
      errMsg = pgp->lastErrorMessage();

    // front and backmatter...
    front = mess.left(index);
    index = mess.find("-----END PGP",index);
    index = mess.find("\n",index+1);
    back  = mess.right(mess.size() - index - 1);

    return TRUE;
  }
  //  debug("Kpgp: message does not contain PGP parts");
  return FALSE;
}

const QString 
Kpgp::frontmatter(void) const
{
  return front;
}

const QString
Kpgp::backmatter(void) const
{
  return back;
}

const QString
Kpgp::message(void) const
{
  return pgp->message();
}

bool 
Kpgp::prepare(bool needPassPhrase)
{
  if(!havePgp)
  {
    errMsg = i18n("Could not find PGP executable.\n"
		       "Please check your PATH is set correctly.");
    return FALSE;
  }

  if((pgp->getStatus() & KpgpBase::NO_SEC_KEY))
    return FALSE;

  if(needPassPhrase)
  {
    if(!havePassPhrase)
      setPassPhrase(askForPass());
    if(!havePassPhrase)
    {
      errMsg = i18n("The pass phrase is missing.");
      return FALSE;
    }
  }
  return TRUE;
}

void
Kpgp::cleanupPass(void)
{
  if(!storePass)
  {
    passphrase.replace(QRegExp(".")," ");
    passphrase = 0;
    havePassPhrase = false;
  }
}

bool 
Kpgp::decrypt(void)
{
  int retval;

  // do we need to do anything?
  if(!pgp->isEncrypted()) return TRUE;
  // everything ready
  if(!prepare(TRUE)) return FALSE;
  // ok now try to decrypt the message.
  retval = pgp->decrypt(passphrase);
  // erase the passphrase if we do not want to keep it
  cleanupPass();

  if((retval & KpgpBase::BADPHRASE))
  {
    //debug("Kpgp: bad passphrase");
    havePassPhrase = false;
  }

  if(retval & KpgpBase::ERROR) 
  {
    errMsg = pgp->lastErrorMessage();
    return false;
  }
  return true;
}

bool 
Kpgp::sign(void)
{
  return encryptFor(0, true);
}

bool 
Kpgp::encryptFor(const QStrList& aPers, bool sign)
{
  QStrList persons, noKeyFor;
  char* pers;
  int status = 0;
  errMsg = "";
  int ret;
  QString aStr;

  persons.clear();
  noKeyFor.clear();

  if(!aPers.isEmpty()) 
  {
    QStrListIterator it(aPers);
    while((pers = it.current()))
    {
      QString aStr = getPublicKey(pers);
      if(!aStr.isEmpty()) 
        persons.append(aStr);
      else
	noKeyFor.append(pers);
      ++it;
    }
    if(persons.isEmpty())
    {
      int ret = KMsgBox::yesNo(0,i18n("PGP Warning"),
			       i18n("Could not find the public keys for the\n" 
				    "recipients of this mail.\n"
				    "Message will not be encrypted."),
			       KMsgBox::EXCLAMATION, 
			       i18n("Continue"), i18n("Cancel"));
      if(ret == 2) return false;
    }
    else if(!noKeyFor.isEmpty())
    {
      QString aStr = i18n("Could not find the public keys for\n");
      QStrListIterator it(noKeyFor);
      aStr += it.current();
      ++it;
      while((pers = it.current()))
      {
	aStr += ",\n";
	aStr += pers;
	++it;
      }
      if(it.count() > 1)
	aStr += i18n("These persons will not be able to\n");
      else
	aStr += i18n("This person will not be able to\n");

      aStr += i18n("decrypt the message.");
      int ret = KMsgBox::yesNo(0,i18n("PGP Warning"), aStr,
			       KMsgBox::EXCLAMATION, 
			       i18n("Continue"), i18n("Cancel"));
      if(ret == 2) return false;
    }
  }

  status = doEncSign(persons, sign);

  // check for bad passphrase
  while(status & KpgpBase::BADPHRASE)
  {
    havePassPhrase = false;
    ret = KMsgBox::yesNoCancel(0,i18n("PGP Warning"),
			       i18n("You just entered an invalid passphrase.\n"
				    "Do you wan't to try again, continue and\n" 
				    "leave the message unsigned, "
				    "or cancel sending the message?"),
			       KMsgBox::EXCLAMATION, 
			       i18n("Retry"), i18n("Continue"));
    if(ret == 3) return false;
    if(ret == 2) sign = false;
    // ok let's try once again...
    status = doEncSign(persons, sign);
  }
  // check for bad keys
  if( status & KpgpBase::BADKEYS)
  {
    aStr = pgp->lastErrorMessage();
    aStr += "\n";
    aStr += i18n("Do you wan't to encrypt anyway, leave the\n" 
		 "message as is, or cancel the message?");
    ret = KMsgBox::yesNoCancel(0,i18n("PGP Warning"),
			      aStr, KMsgBox::EXCLAMATION,
			      i18n("Encrypt"), i18n("Continue"));
    if(ret == 3) return false;
    if(ret == 2) 
    {
      pgp->clearOutput();
      return true;
    }
    if(ret == 1) status = doEncSign(persons, sign, true);
  }
  if( status & KpgpBase::MISSINGKEY)
  {
    aStr = pgp->lastErrorMessage();
    aStr += "\n";
    aStr += i18n("Do you wan't to leave the message as is,\n" 
		 "or cancel the message?");
    ret = KMsgBox::yesNo(0,i18n("PGP Warning"),
			      aStr, KMsgBox::EXCLAMATION,
			      i18n("Continue"), i18n("Cancel"));
    if(ret == 2) return false;
    pgp->clearOutput();
    return true;
  }
  if( !(status & KpgpBase::ERROR) ) return true;

  // in case of other errors we end up here.
  errMsg = pgp->lastErrorMessage();
  return false;
  
}

int 
Kpgp::doEncSign(QStrList persons, bool sign, bool ignoreUntrusted)
{
  int retval;

  // to avoid error messages in case pgp is not installed
  if(!havePgp)
    return KpgpBase::OK;

  if(sign)
  {
    if(!prepare(TRUE)) return KpgpBase::ERROR;
    retval = pgp->encsign(&persons, passphrase, ignoreUntrusted);
  }  
  else
  {
    if(!prepare(FALSE)) return KpgpBase::ERROR;
    retval = pgp->encrypt(&persons, ignoreUntrusted);
  }
  // erase the passphrase if we do not want to keep it
  cleanupPass();

  return retval;
}

bool 
Kpgp::signKey(QString _key)
{
  if (!prepare(TRUE)) return FALSE;
  if(pgp->signKey(_key, passphrase) & KpgpBase::ERROR)
  {
    errMsg = pgp->lastErrorMessage();
    return false;
  }
  return true;
}


const QStrList*
Kpgp::keys(void)
{
  if (!prepare()) return NULL;

  if(publicKeys.isEmpty()) publicKeys = pgp->pubKeys();
  return &publicKeys;
}

bool 
Kpgp::havePublicKey(QString _person)
{
  if(!havePgp) return true;
  if (needPublicKeys)
  {
    publicKeys = pgp->pubKeys();
    needPublicKeys=false;
  }

  // do the checking case insensitive
  QString str;
  _person = _person.lower();
  _person = canonicalAdress(_person);

  for(str=publicKeys.first(); str!=0; str=publicKeys.next())
  {
    str = str.lower();
    if(str.contains(_person)) return TRUE;
  }

  // reread the database, if key wasn't found...
  publicKeys = pgp->pubKeys();
  for(str=publicKeys.first(); str!=0; str=publicKeys.next())
  {
    str = str.lower();
    if(str.contains(_person)) return TRUE;
  }

  return FALSE;
}

QString 
Kpgp::getPublicKey(QString _person)
{
  // just to avoid some error messages
  if(!havePgp) return true;
  if (needPublicKeys)
  {
    publicKeys = pgp->pubKeys();
    needPublicKeys=false;
  }
  // do the search case insensitive, but return the correct key.
  QString adress,str,disp_str;
  adress = _person.lower();
  
  // first try the canonical mail adress.
  adress = canonicalAdress(adress);
  for(str=publicKeys.first(); str!=0; str=publicKeys.next())
    if(str.contains(adress)) return str;

  // now check if the key contains the address
  adress = _person.lower();
  for(str=publicKeys.first(); str!=0; str=publicKeys.next())
    if(str.contains(adress)) return str;
  
  // FIXME: let user set the key/ get from keyserver
  // now check if the address contains the key
  adress = _person.lower();
  for(str=publicKeys.first(); str!=0; str=publicKeys.next())
    if(adress.contains(str)) return str;

  // no match until now, let the user choose the key:
  adress = canonicalAdress(adress);
  str= SelectPublicKey(&publicKeys,adress);
  if (!str.isEmpty()) return str;

  return 0;
}

QString 
Kpgp::getAsciiPublicKey(QString _person)
{
  return pgp->getAsciiPublicKey(_person);
}

bool 
Kpgp::isEncrypted(void) const
{
  return pgp->isEncrypted();
}

const QStrList*
Kpgp::receivers(void) const
{
  return pgp->receivers();
}

const QString 
Kpgp::KeyToDecrypt(void) const
{
  //FIXME
  return 0;
}

bool
Kpgp::isSigned(void) const
{
  return pgp->isSigned();
}

QString 
Kpgp::signedBy(void) const
{
  return pgp->signedBy();
}

QString 
Kpgp::signedByKey(void) const
{
  return pgp->signedByKey();
}

bool 
Kpgp::goodSignature(void) const
{
  return pgp->isSigGood();
}

void 
Kpgp::setPassPhrase(const QString aPass)
{
  if (!aPass.isEmpty())
  {
    passphrase = aPass;
    havePassPhrase = TRUE;
  }
  else
  {
    if (!passphrase.isEmpty())
      passphrase.replace(QRegExp(".")," ");
    passphrase = 0;
    havePassPhrase = FALSE;
  }
}

bool 
Kpgp::changePassPhrase(const QString /*oldPass*/, 
		       const QString /*newPass*/)
{
  //FIXME...
  warning(i18n("Sorry, but this feature\nis still missing"));
  return FALSE;
}

void 
Kpgp::clear(bool erasePassPhrase)
{
  if(erasePassPhrase && havePassPhrase && !passphrase.isEmpty())
  {
    passphrase.replace(QRegExp(".")," ");
    passphrase = 0;
  }
  front = 0;
  back = 0;
}

const QString 
Kpgp::lastErrorMsg(void) const
{
  return errMsg;
}

bool 
Kpgp::havePGP(void) const
{
  return havePgp;
}



// ------------------ static methods ----------------------------
Kpgp *
Kpgp::getKpgp()
{
  if (!kpgpObject)
  {
    kpgpObject = new Kpgp;
    kpgpObject->readConfig();
  }
  return kpgpObject;
}

KSimpleConfig *
Kpgp::getConfig()
{
  return getKpgp()->config;
}


const QString
Kpgp::askForPass(QWidget *parent)
{
  return KpgpPass::getPassphrase(parent);
}

// --------------------- private functions -------------------

// check if pgp 2.6.x or 5.0 is installed
// kpgp will prefer to user pgp 5.0
bool 
Kpgp::checkForPGP(void)
{
  // get path
  QString path;
  QStrList pSearchPaths;
  int index = 0;
  int lastindex = -1;

  havePgp=FALSE;

  path = getenv("PATH");
  while((index = path.find(":",lastindex+1)) != -1)
  {
    pSearchPaths.append(path.mid(lastindex+1,index-lastindex-1));
    lastindex = index;
  }
  if(lastindex != (int)path.size() - 2)
    pSearchPaths.append( path.mid(lastindex+1,path.size()-lastindex-1) );

  QStrListIterator it(pSearchPaths);

  // first search for pgp5.0
  while ( it.current() )
  {
    path = it.current();
    path += "/pgpe";
    if ( !access( path, X_OK ) )
    {
      havePgp=TRUE;
      havePGP5=TRUE;
      //debug("Kpgp: found pgp5.0");
      return TRUE;
    }
    ++it;
  }

  // lets try pgp2.6.x
  it.toFirst();
  while ( it.current() )
  {
       path = it.current();
       path += "/pgp";
       if ( !access( path, X_OK ) )
       {
	    havePgp=TRUE;
	    havePGP5=FALSE;
	    //debug("Kpgp: found pgp2.6.x");
	    return TRUE;
       }
       ++it;
  }
  
  debug("Kpgp: no pgp found");
  return FALSE;
}

QString 
Kpgp::canonicalAdress(QString _adress)
{
  int index,index2;

  _adress = _adress.simplifyWhiteSpace();
  _adress = _adress.stripWhiteSpace();

  // just leave pure e-mail adress.
  if((index = _adress.find("<")) != -1)
    if((index2 = _adress.find("@",index+1)) != -1)
      if((index2 = _adress.find(">",index2+1)) != -1)
	return _adress.mid(index,index2-index);
  
  if((index = _adress.find("@")) == -1)
  { 
    // local adress
    char hostname[1024];
    gethostname(hostname,1024);
    QString adress = '<';
    adress += _adress;
    adress += '@';
    adress += hostname;
    adress += '>';
    return adress;
  }
  else
  {
    int index1 = _adress.findRev(" ",index);
    int index2 = _adress.find(" ",index);
    if(index2 == -1) index2 = _adress.length();
    QString adress = "<";
    adress += _adress.mid(index1+1 ,index2-index1-1);
    adress += ">";
    return adress;
  }
}

QString
Kpgp::SelectPublicKey(QStrList* pbkeys,const char *caption)
{
  KpgpSelDlg dlg(pbkeys,caption);
  QString txt ="";

  if (dlg.exec()==QDialog::Rejected) return 0;
  txt = dlg.key();
  if (!txt.isEmpty())
  {
    return txt;
  }
  return 0;
}


//----------------------------------------------------------------------
//  widgets needed by kpgp
//----------------------------------------------------------------------

KpgpPass::KpgpPass(QWidget *parent, const char *name)
  : QDialog(parent, 0, TRUE)
{
  KIconLoader* loader = kapp->getIconLoader();
  QPixmap pixm;

  setCaption(name);
  setFixedSize(264,80);
  cursor = kapp->overrideCursor();
  if(cursor != 0)
    kapp->setOverrideCursor(QCursor(ibeamCursor));
  this->setCursor(QCursor(ibeamCursor));
  QLabel *text = new QLabel(i18n("Please enter your\nPGP passphrase"),this);
  text->move(56,4);
  text->setAutoResize(TRUE);
  QLabel *icon = new QLabel(this);
  pixm = loader->loadIcon("pgp-keys.xpm");
  icon->setPixmap(pixm);
  icon->move(4,8);
  icon->resize(48,48);

  lineedit = new QLineEdit(this);
  lineedit->setEchoMode(QLineEdit::Password);
  lineedit->move(56, 8+text->size().height());
  lineedit->resize(200, lineedit->size().height());
  lineedit->setFocus();

  connect(lineedit,SIGNAL(returnPressed()),this,SLOT(accept()) );  
}

KpgpPass::~KpgpPass()
{
  if(cursor != 0)
    kapp->restoreOverrideCursor();
}

QString 
KpgpPass::getPassphrase(QWidget *parent)
{
  KpgpPass kpgppass(parent, i18n("PGP Security Check"));
  kpgppass.exec();
  return kpgppass.getPhrase().copy();
}

QString
KpgpPass::getPhrase()
{
  return lineedit->text();
}

// ------------------------------------------------------------------------

KpgpKey::KpgpKey(QWidget *parent, const char *name, const QStrList *keys)
  : QDialog(parent, 0, TRUE)
{
  KIconLoader* loader = kapp->getIconLoader();
  QPixmap pixm;

  setCaption(name);
  setFixedSize(350,110);
  this->setCursor(QCursor(arrowCursor));
  cursor = kapp->overrideCursor();
  if(cursor != 0)
    kapp->setOverrideCursor(QCursor(arrowCursor));
  QLabel *text = new QLabel(i18n("Please select the public key to insert"),this);
  text->move(56,4);
  text->setAutoResize(TRUE);
  QLabel *icon = new QLabel(this);
  pixm = loader->loadIcon("pgp-keys.xpm");
  icon->setPixmap(pixm);
  icon->move(4,8);
  icon->resize(48,48);

  combobox = new QComboBox(FALSE, this, "combo");
  if (keys==NULL) debug("keys = NULL");
  combobox->insertStrList(keys);
  combobox->move(56,40);
  combobox->resize(290,20);
  combobox->setFocus();

  button = new QPushButton(i18n("&Insert"),this);
  button->move(145,75);

  connect(button,SIGNAL(clicked()),this,SLOT(accept()) );  
}

KpgpKey::~KpgpKey()
{
  if(cursor != 0)
    kapp->restoreOverrideCursor();
}

QString 
KpgpKey::getKeyName(QWidget *parent, const QStrList *keys = NULL)
{
  KpgpKey pgpkey(parent, i18n("Select key"), keys);
  pgpkey.exec();
  return pgpkey.getKey().copy();
}

QString
KpgpKey::getKey()
{
  return combobox->currentText();
}


// ------------------------------------------------------------------------

KpgpConfig::KpgpConfig(QWidget *parent, const char *name)
  : QWidget(parent, name)
{
  pgp = Kpgp::getKpgp();

  QBoxLayout* box = new QBoxLayout(this, QBoxLayout::TopToBottom, 3);

  QGroupBox *grp = new QGroupBox(i18n("Identity"), this);
  box->addWidget(grp);

  QGridLayout* grid = new QGridLayout(grp, 1, 2, 20, 6);

  pgpUserEdit = createLabeledEntry(grid, 
				   i18n("PGP User Identity:"),
				   pgp->user(), 0, 0);

  grid->setColStretch(0,1);
  grid->setColStretch(1,10);
  grid->activate();

  QGroupBox *grp2 = new QGroupBox(i18n("Options"), this);
  QGridLayout* grid2 = new QGridLayout(grp2, 2, 3, 20, 6);

  storePass=new QCheckBox(
	      i18n("Store passphrase"), grp2);
  storePass->adjustSize();
  storePass->setMinimumSize(storePass->sizeHint());
  grid2->addMultiCellWidget(storePass, 0, 0, 0, 2);

  encToSelf=new QCheckBox(
	      i18n("Always encrypt to self"), grp2);
  encToSelf->adjustSize();
  encToSelf->setMinimumSize(encToSelf->sizeHint());
  grid2->addMultiCellWidget(encToSelf, 1, 1, 0, 2);

  grid2->setColStretch(0,0);
  grid2->setColStretch(1,1);
  grid2->setColStretch(2,0);
  grid2->activate();

  box->addWidget(grp2);

  box->addStretch(10);
  box->activate();

  // set default values
  pgpUserEdit->setText(pgp->user());
  storePass->setChecked(pgp->storePassPhrase()); 
  encToSelf->setChecked(pgp->encryptToSelf());

}

KpgpConfig::~KpgpConfig()
{
}

void 
KpgpConfig::applySettings()
{
  pgp->setUser(pgpUserEdit->text());
  pgp->setStorePassPhrase(storePass->isChecked());
  pgp->setEncryptToSelf(encToSelf->isChecked());

  pgp->writeConfig(true);
}

QLineEdit* 
KpgpConfig::createLabeledEntry(QGridLayout* grid,
			       const char* aLabel,
			       const char* aText, 
			       int gridy, int gridx)
{
  QLabel* label = new QLabel(this);
  QLineEdit* edit = new QLineEdit(this);

  label->setText(aLabel);
  label->adjustSize();
  label->resize((int)label->sizeHint().width(),label->sizeHint().height() + 6);
  label->setMinimumSize(label->size());
  grid->addWidget(label, gridy, gridx++);

  if (aText) edit->setText(aText);
  edit->setMinimumSize(100, label->height()+2);
  edit->setMaximumSize(1000, label->height()+2);
  grid->addWidget(edit, gridy, gridx++);

  return edit;
}


//-----------------------------------------------------------------------------
#define KpgpDlgInherited QDialog
KpgpSelDlg::KpgpSelDlg(QStrList* aKeyList, const char* aCap):
  KpgpDlgInherited(NULL, aCap, TRUE), mGrid(this, 2, 2),
  mListBox(this),
  mBtnOk(i18n("OK"),this),
  mBtnCancel(i18n("Cancel"),this)
{
  const char* key;
  QString caption;

  caption=i18n("Select public key for recipient \"");
  caption += aCap;
  caption += i18n("\"");

  initMetaObject();

  setCaption(aCap ? (const char *)caption : i18n("PGP Key Selection"));

  assert(aKeyList != NULL);
  mKeyList = aKeyList;
  mkey  = 0;

  mBtnOk.adjustSize();
  mBtnOk.setMinimumSize(mBtnOk.size());
  mBtnCancel.adjustSize();
  mBtnCancel.setMinimumSize(mBtnCancel.size());

  mGrid.addMultiCellWidget(&mListBox, 0, 0, 0, 1);
  mGrid.addWidget(&mBtnOk, 1, 0);
  mGrid.addWidget(&mBtnCancel, 1, 1);

  mGrid.setRowStretch(0,10);
  mGrid.setRowStretch(1,0);
  mGrid.setColStretch(0,10);
  mGrid.setColStretch(1,10);
  mGrid.activate();

  connect(&mBtnOk, SIGNAL(clicked()), SLOT(slotOk()));
  connect(&mListBox, SIGNAL(selected(int)), SLOT(slotOk()));
  connect(&mBtnCancel, SIGNAL(clicked()), SLOT(slotCancel()));

  for (key=mKeyList->first(); key; key=mKeyList->next())
  {
    //insert only real keys:
    //    if (!(QString)key.contains("matching key"))
	mListBox.insertItem(key);
  }
}

void KpgpSelDlg::slotOk()
{
  int idx = mListBox.currentItem();

  if (idx>=0) mkey = mListBox.text(idx);
  else mkey = 0;

  accept();
}

void KpgpSelDlg::slotCancel()
{
  mkey = 0;
  reject();
}

["kpgpbase.h" (text/x-c++)]

/** KPGP: Pretty good privacy en-/decryption class
 *        This code is under GPL V2.0
 *
 * @author Lars Knoll <knoll@mpi-hd.mpg.de>
 */
#ifndef KPGPBASE_H
#define KPGPBASE_H

#include <qstring.h>
#include <qstrlist.h>

class KpgpBase
{
public:

  enum{ 
    OK = 0,
      CLEARTEXT   =  0,
      RUN_ERR     =  1,
      ERROR       =  1,
      ENCRYPTED   =  2,
      SIGNED      =  4,
      GOODSIG     =  8,
      ERR_SIGNING = 16,
      UNKNOWN_SIG = 32,
      BADPHRASE   = 64,
      BADKEYS     =128,
      NO_SEC_KEY  =256,
      MISSINGKEY  =512 };
  
  /** virtual class used internally by kpgp */
  KpgpBase();
  virtual ~KpgpBase();
  
  virtual void readConfig();
  virtual void writeConfig(bool sync = false);

  /** set and retrieve the message to handle */
  virtual bool setMessage(const QString mess);
  virtual QString message() const;

  /** manipulating the message */
  virtual int encrypt(const QStrList *, bool = false) { return OK; };
  virtual int sign(const char *) { return OK; };
  virtual int encsign(const QStrList *, const char * = 0,
		      bool = false) { return OK; };
  virtual int decrypt(const char * = 0) { return OK; };
  virtual QStrList pubKeys() { return OK; };
  virtual QString getAsciiPublicKey(QString _person) { return OK; };
  virtual int signKey(const char *, const char *) { return OK; };

  /** various functions to get the status of a message */
  bool isEncrypted() const;
  bool isSigned() const;
  bool isSigGood() const;
  bool unknownSigner() const;
  int getStatus() const;
  QString signedBy() const;
  QString signedByKey() const;
  const QStrList *receivers() const;

  virtual QString lastErrorMessage() const;

  /** functions that modify the behaviour of kpgp */
  void setUser(QString aUser);
  const QString user() const;
  void setEncryptToSelf(bool flag);
  bool encryptToSelf(void) const;

  /// kpgp needs to access this function
  void clearOutput();

protected:
  virtual int run(const char *cmd, const char *passphrase = 0);
  virtual void clear();

  QString addUserId();

  QString input;
  QString output;
  QString info;
  QString errMsg;
  QString pgpUser;
  QString signature;
  QString signatureID;
  QStrList recipients;

  bool flagEncryptToSelf;
  int status;

};

// ---------------------------------------------------------------------------

class KpgpBase2 : public KpgpBase
{

public:
  KpgpBase2();
  virtual ~KpgpBase2();

  virtual int encrypt(const QStrList *recipients,
		      bool ignoreUntrusted = false);
  virtual int sign(const char *passphrase);
  virtual int encsign(const QStrList *recipients, const char *passphrase = 0,
		      bool ingoreUntrusted = false);
  virtual int decrypt(const char *passphrase = 0);
  virtual QStrList pubKeys();
  virtual QString getAsciiPublicKey(QString _person);
  virtual int signKey(const char *key, const char *passphrase);
};


class KpgpBase5 : public KpgpBase
{

public:
  KpgpBase5();
  virtual ~KpgpBase5();

  virtual int encrypt(const QStrList *recipients,
		      bool ignoreUntrusted = false);
  virtual int sign(const char *passphrase);
  virtual int encsign(const QStrList *recipients, const char *passphrase = 0,
		      bool ingoreUntrusted = false);
  virtual int decrypt(const char *passphrase = 0);
  virtual QStrList pubKeys();
  virtual QString getAsciiPublicKey(QString _person);
  virtual int signKey(const char *key, const char *passphrase);
};


class KpgpBase6 : public KpgpBase2
{

public:
  KpgpBase6();
  virtual ~KpgpBase6();

  virtual int decrypt(const char *passphrase = 0);
  virtual QStrList pubKeys();

  virtual int isVersion6();
};

// ---------------------------------------------------------------------------
// inlined functions

inline void
KpgpBase::setUser(QString aUser)
{
  pgpUser = aUser;
}

inline const QString
KpgpBase::user() const
{
  return pgpUser;
}

inline void 
KpgpBase::setEncryptToSelf(bool flag)
{
  flagEncryptToSelf = flag;
}

inline bool 
KpgpBase::encryptToSelf(void) const
{
  return flagEncryptToSelf;
}

inline bool 
KpgpBase::isEncrypted() const
{
  if( status & ENCRYPTED )
    return true;
  return false;
}

inline bool 
KpgpBase::isSigned() const
{
  if( status & SIGNED )
    return true;
  return false;
}

inline bool 
KpgpBase::isSigGood() const
{
  if( status & GOODSIG )
    return true;
  return false;
}

inline bool 
KpgpBase::unknownSigner() const
{
  if( status & UNKNOWN_SIG )
    return true;
  return false;
}

inline const QStrList *
KpgpBase::receivers() const
{
  if(recipients.count() <= 0) return 0;
  return &recipients;
}

inline int
KpgpBase::getStatus() const
{
  return status;
}

inline QString 
KpgpBase::signedBy(void) const
{
  return signature;
}

inline QString 
KpgpBase::signedByKey(void) const
{
  return signatureID;
}

#endif

["kpgpbase.cpp" (text/x-c++)]

#include "kpgpbase.h"
#include "kpgp.h"

#include <kapp.h>
#include <ksimpleconfig.h>

#include <qregexp.h>

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <errno.h>
 
KpgpBase::KpgpBase()
{
  readConfig();
  status = OK;
}

KpgpBase::~KpgpBase()
{
  
}

void 
KpgpBase::readConfig()
{
  KSimpleConfig *config = Kpgp::getConfig();
  pgpUser = config->readEntry("user");
  flagEncryptToSelf = config->readBoolEntry("encryptToSelf");
}

void
KpgpBase::writeConfig(bool sync)
{
  KSimpleConfig *config = Kpgp::getConfig();
  config->writeEntry("user",pgpUser);
  config->writeEntry("encryptToSelf",flagEncryptToSelf);

  if(sync)
    config->sync();
}


bool
KpgpBase::setMessage(const QString mess)
{
  clear();
  input = mess;
  if(input.find("-----BEGIN PGP") != -1)
    decrypt();
}

QString 
KpgpBase::message() const
{
  // do we have a deciphered text?
  if(!output.isEmpty()) return output;

  // no, then return the original one
  //debug("KpgpBase: No output!");
  return input;
}

int
KpgpBase::run(const char *cmd, const char *passphrase)
{
  /* the pipe ppass is used for to pass the password to
   * pgp. passing the password together with the normal input through
   * stdin doesn't seem to work as expected (at least for pgp5.0)
   */
  char str[1024] = "\0";
  int pin[2], pout[2], perr[2], ppass[2];
  int len, status;
  FILE *pass;
  pid_t child_pid, rc;

  if(passphrase)
  {
    pipe(ppass);

    pass = fdopen(ppass[1], "w");
    fwrite(passphrase, sizeof(char), strlen(passphrase), pass);
    fwrite("\n", sizeof(char), 1, pass);
    fclose(pass);
    close(ppass[1]);

    // tell pgp which fd to use for the passphrase
    QString tmp;
    tmp.sprintf("%d",ppass[0]);
    setenv("PGPPASSFD",tmp,1);
    //printf("PGPPASSFD = %s\n",tmp.data());
    //printf("pass = %s\n",passphrase);
  }
  else
    unsetenv("PGPPASSFD");

  //printf("cmd = %s\n",cmd);
  //printf("input = %s\nlength = %d\n",input.data(), input.length());

  info = "";
  output = "";

  pipe(pin);
  pipe(pout);
  pipe(perr);
     
  if(!(child_pid = fork()))
  {
    /*We're the child.*/
    close(pin[1]);
    dup2(pin[0], 0);
    close(pin[0]);
	  
    close(pout[0]);
    dup2(pout[1], 1);
    close(pout[1]);

    close(perr[0]);
    dup2(perr[1], 2);
    close(perr[1]);
	
    execl("/bin/sh", "sh", "-c", cmd, NULL);
    _exit(127);
  }                
     
  /*Only get here if we're the parent.*/
  close(pin[0]);
  close(pout[1]);
  close(perr[1]);

  if (!input.isEmpty()) 
    write(pin[1], input.data(), input.length());
  else
    write(pin[1], "\n", 1);
  close(pin[1]);
 
  if (pout[0] >= 0)
  {
    while ((len=read(pout[0],str,1023))>0)
    {
      str[len] ='\0';
      output += str;
    }
   close(pout[0]);
  }
 
  if (perr[0] >= 0)
  {
    while ((len=read(perr[0],str,1023))>0)
    {
      str[len] ='\0';
      info += str;
    }
    close(perr[0]);
  }
 
  unsetenv("PGPPASSFD");
  if(passphrase)
    close(ppass[0]);
     
  //printf("output = %s\n",output.data());
  //printf("info = %s\n",info.data());

  // we don't want a zombie, do we?  ;-)
  rc = waitpid(0/*child_pid*/, &status, 0);
  if (rc==-1) printf("waitpid: %s\n", strerror(errno));
  
  return OK;
}

QString
KpgpBase::addUserId()
{
  QString cmd;

  if(!pgpUser.isEmpty())
  {
    cmd += " -u \"";
    cmd += pgpUser;
    cmd += "\"";
    return cmd;
  }
  return "";
}

void 
KpgpBase::clear()
{
  input = 0;
  output = 0;
  info = 0;
  errMsg = 0;
  signature = 0;
  signatureID = 0;
  recipients.clear();
  status = OK;
}

void 
KpgpBase::clearOutput()
{
  output = 0;
}

QString 
KpgpBase::lastErrorMessage() const
{
  return errMsg;
}

// -------------------------------------------------------------------------

KpgpBase2::KpgpBase2()
  : KpgpBase()
{
}

KpgpBase2::~KpgpBase2()
{
}

int 
KpgpBase2::encrypt(const QStrList *_recipients, bool /*ignoreUntrusted*/)
{
  return encsign(_recipients, 0);
}

int 
KpgpBase2::sign(const char *passphrase)
{
  return encsign(0, passphrase);
}

int 
KpgpBase2::encsign(const QStrList *_recipients, const char *passphrase,
		   bool /*ignoreUntrusted*/)
{
  QString cmd, pers;
  output = "";

  if(_recipients != 0)
    if(_recipients->count() <= 0)
      _recipients = 0;

  if(_recipients != 0 && passphrase != 0)
    cmd = "pgp +batchmode -seat ";
  else if( _recipients != 0 )
    cmd = "pgp +batchmode -eat";
  else if(passphrase != 0 )
    cmd = "pgp +batchmode -sat ";
  else 
  {
    //debug("kpgpbase: Neither recipients nor passphrase specified.");
    return OK;
  }

  if(passphrase != 0)
    cmd += addUserId();

  if(_recipients != 0)
  {
    QStrListIterator it(*_recipients);
    while( (pers=it.current()) )
    {
      cmd += " \"";
      cmd += pers;
      cmd += "\"";
      ++it;
    }
    if(flagEncryptToSelf)
      cmd += " +EncryptToSelf";
  }
  cmd += " -f";

  status = run(cmd, passphrase);
  if(status == RUN_ERR) return status;

  if(_recipients != 0)
  {
    int index = 0;
    bool bad = FALSE;
    unsigned int num = 0;
    QString badkeys = "";
    while((index = info.find("Cannot find the public key",index)) 
	  != -1)
    {
      bad = TRUE;
      index = info.find("'",index);
      int index2 = info.find("'",index+1);
      badkeys += info.mid(index, index2-index+1) + ", ";
      num++;
    }
    if(bad)
    {
      badkeys.stripWhiteSpace();
      if(num == _recipients->count())
	errMsg.sprintf("Could not find public keys matching the\n" 
		       "userid(s) %s.\n" 
		       "Message is not encrypted.\n",
		       (const char *)badkeys);
      else
	errMsg.sprintf("Could not find public keys matching the\n" 
		       "userid(s) %s. These persons won't be able\n"
		       "to read the message.",
		       (const char *)badkeys);
      status |= MISSINGKEY;
      status |= ERROR;
    }
  }
  if(passphrase != 0)
  {
    if(info.find("Pass phrase is good") != -1)
    {
      //debug("KpgpBase: Good Passphrase!");
      status |= SIGNED;
    }
    if( info.find("Bad pass phrase") != -1)
    {
      errMsg = i18n("Bad pass Phrase; couldn't sign");
      status |= ERR_SIGNING;
      status |= ERROR;
    }
  }
  //debug("status = %d",status);
  return status;
}

int 
KpgpBase2::decrypt(const char *passphrase)
{
  QString cmd;
  int index, index2;
  output = "";


  cmd = "pgp +batchmode -f";

  status = run(cmd, passphrase);

  // pgp2.6 has sometimes problems with the ascii armor pgp5.0 produces
  // this hack can solve parts of the problem
  if(info.find("ASCII armor corrupted.") != -1)
  {
    //debug("removing ASCII armor header");
    int index1 = input.find("-----BEGIN PGP SIGNED MESSAGE-----");
    if(index1 != -1)
      index1 = input.find("-----BEGIN PGP SIGNATURE-----", index1);
    else
      index1 = input.find("-----BEGIN PGP MESSAGE-----");
    index1 = input.find("\n", index1);
    index2 = input.find("\n\n", index1);
    input.remove(index1, index2 - index1);
    status = run(cmd, passphrase);
  }
 
  if(status == RUN_ERR)
  {
    errMsg = i18n("error running pgp");
    return status;
  }

  if( info.find("File contains key") != -1)
  {
    // FIXME: should do something with it...
  }

  if(info.find("You do not have the secret key") != -1)
  {
    //debug("kpgpbase: message is encrypted");
    status |= ENCRYPTED;
    if( info.find("Bad pass phrase") != -1)
    {
      if(passphrase != 0) 
      {
	errMsg = i18n("Bad pass Phrase; couldn't decrypt");
	//debug("KpgpBase: passphrase is bad");
	status |= BADPHRASE;
	status |= ERROR;
      }
    } 
    else
    {
      // no secret key fitting this message
      status |= NO_SEC_KEY;
      status |= ERROR;
      errMsg = i18n("Do not have the secret key for this message");
      //debug("KpgpBase: no secret key for this message");
    }
    // check for persons
    index = info.find("can only be read by:");
    if(index != -1) 
    {
      index = info.find("\n",index);
      int end = info.find("\n\n",index);
      
      recipients.clear();
      while( (index2 = info.find("\n",index+1)) <= end )
      {
	QString item = info.mid(index+1,index2-index-1);
	item.stripWhiteSpace();
	recipients.append(item);
	index = index2;
      }
    }
  }
  if((index = info.find("File has signature")) != -1)
  {
    //debug("KpgpBase: message is signed");
    status |= SIGNED;
    if( info.find("Key matching expected") != -1)
    {
      index = info.find("Key ID ",index);
      signatureID = info.mid(index+7,8);
      signature = i18n("unknown key ID ") + signatureID + " ";
      status |= UNKNOWN_SIG;
      status |= GOODSIG;
    }
    else if( info.find("Good signature") != -1 )
    {
      status |= GOODSIG;
      // get signer
      index = info.find("\"",index);
      index2 = info.find("\"", index+1);
      signature = info.mid(index+1, index2-index-1);
      
      // get key ID of signer
      index = info.find("key ID ",index2);
      signatureID = info.mid(index+7,8);
    }
    else if( info.find("Can't find the right public key") != -1 )
    {
      status |= UNKNOWN_SIG;
      status |= GOODSIG; // this is a hack...
      signature = i18n("??? (file ~/.pgp/pubring.pgp not found)");
      signatureID = "???";
    }
    else
    {
      status |= ERROR;
      signature = "";
      signatureID = "";
    }
  }
  //debug("status = %d",status);
  return status;
}

QStrList
KpgpBase2::pubKeys()
{
  QString cmd;
  int index, index2;

  cmd = "pgp +batchmode -kv -f";
  status = run(cmd);
  if(status == RUN_ERR) return 0;

  //truncate trailing "\n"
  if (output.length() > 1) output.truncate(output.length()-1);

  QStrList publicKeys;
  index = output.find("\n",1)+1; // skip first to "\n"
  while( (index = output.find("\n",index)) != -1)
  {
    //parse line
    QString line;
    if( (index2 = output.find("\n",index+1)) != -1)
      // skip last line
    {
      int index3 = output.find("pub ",index);
      
      if( (index3 >index2) || (index3 == -1) )
      {
	// second adress for the same key
	line = output.mid(index+1,index2-index-1);
	line = line.stripWhiteSpace();	       
	line = line.lower();
      } else {
	// line with new key
	int index3 = output.find(
	  QRegExp("/[0-9][0-9]/[0-9][0-9] "),
	  index);
	line = output.mid(index3+7,index2-index3-7);
	line = line.lower();
      }
      //debug("KpgpBase: found key for %s",(const char *)line);
      publicKeys.append(line);
    }
    index = index2;
  }
  
  return publicKeys;
}

QString KpgpBase2::getAsciiPublicKey(QString _person) {

  QString toexec;
  toexec.sprintf("pgp -kxaf \"%s\"", _person.data());

  status = run(toexec.data());
  if(status == RUN_ERR) return 0;

  return output;
}

int
KpgpBase2::signKey(const char *key, const char *passphrase)
{
  QString cmd;

  cmd = "pgp +batchmode -ks -f";
  cmd += addUserId();
  if(passphrase != 0)
  {
    QString aStr;
    aStr.sprintf(" \"-z%s\"",passphrase);
    cmd += aStr;
  }
  cmd += key;

  return run(cmd);
}

// -------------------------------------------------------------------------

KpgpBase5::KpgpBase5()
  : KpgpBase()
{
}
KpgpBase5::~KpgpBase5()
{
}

int 
KpgpBase5::encrypt(const QStrList *_recipients, bool ignoreUntrusted)
{
  return encsign(_recipients, 0, ignoreUntrusted);
}

int 
KpgpBase5::sign(const char *passphrase)
{
  return encsign( 0, passphrase);
}
  
int 
KpgpBase5::encsign(const QStrList *_recipients, const char *passphrase,
		   bool ignoreUntrusted)
{
  QString in,cmd,pers;
  int index;
  // used to work around a bug in pgp5. pgp5 treats files
  // with non ascii chars (umlauts, etc...) as binary files, but
  // we wan't a clear signature
  bool signonly = false;
  
  output = "";
  
  if(_recipients != 0)
    if(_recipients->isEmpty())
      _recipients = 0;

  if(_recipients != 0 && passphrase != 0)
    cmd = "pgpe -ats -f +batchmode=1";
  else if( _recipients != 0 )
    cmd = "pgpe -at -f +batchmode=1 ";
  else if(passphrase != 0 )
  {
    cmd = "pgps -bat -f +batchmode=1 ";
    signonly = true;
  }
  else 
  {
    errMsg = "Neither recipients nor passphrase specified.";
    return OK;
  }

  if(ignoreUntrusted) cmd += " +NoBatchInvalidKeys=off";

  if(passphrase != 0)
    cmd += addUserId();

  if(_recipients != 0)
  {
    QStrListIterator it(*_recipients);
    while( (pers=it.current()) )
    {
      cmd += " -r \"";
      cmd += pers;
      cmd += "\"";
      ++it;
    }
    if(flagEncryptToSelf)
      cmd += " +EncryptToSelf";
  }

  if (signonly)
  {
    input.append("\n");
    input.replace(QRegExp("[ \t]+\n"), "\n");   //strip trailing whitespace
  }
  //We have to do this otherwise it's all in vain
  
  status = run(cmd, passphrase);
  if(status == RUN_ERR) return status;
  
  // now parse the returned info
  if(info.find("Cannot unlock private key") != -1)
  {
    errMsg = i18n("The passphrase you entered is invalid.");
    status |= ERROR;
    status |= BADPHRASE;
  }
  if(!ignoreUntrusted)
  {
    QString aStr;
    index = -1;
    while((index = info.find("WARNING: The above key",index+1)) != -1)
    {
      int index2 = info.find("But you previously",index);
      int index3 = info.find("WARNING: The above key",index+1);
      if(index2 == -1 || (index2 > index3 && index3 != -1))
      {
	// the key wasn't valid, no encryption to this person
	// extract the person
	index2 = info.find("\n",index);
	index3 = info.find("\n",index2+1);
	aStr += info.mid(index2+1, index3-index2-1);
	aStr += ", ";
      }
    }
    if(!aStr.isEmpty())
    {
      aStr.truncate(aStr.length()-2);
      if(info.find("No valid keys found") != -1)
	errMsg = i18n("The key(s) you wan't to encrypt your message\n"
		      "to are not trusted. No encryption done.");
      else
	errMsg.sprintf(i18n("The following key(s) are not trusted:\n%s\n"
			    "They will not be able to decrypt the message"),
		       aStr.data());
      status |= ERROR;
      status |= BADKEYS;
    }
  }
  if((index = info.find("No encryption keys found for")) != -1)
  {
    index = info.find(":",index);
    int index2 = info.find("\n",index);

    errMsg.sprintf("Missing encryption key(s) for: %s", 
		   info.mid(index,index2-index).data());
    status |= ERROR;
    status |= MISSINGKEY;
  }
  
  if (signonly)
    output = "-----BEGIN PGP SIGNED MESSAGE-----\n\n" + input + "\n" + output;
  return status;
}

int 
KpgpBase5::decrypt(const char *passphrase)
{  
  QString in = "";
  output = "";

  status = run("pgpv -f +batchmode=1", passphrase);
  if(status == RUN_ERR) return status;

  // lets parse the returned information.
  int index;

  index = info.find("Cannot decrypt message");
  if(index != -1)
  {
    //debug("message is encrypted");
    status |= ENCRYPTED;

    // ok. we have an encrypted message. Is the passphrase bad,
    // or do we not have the secret key?
    if(info.find("Need a pass phrase") != -1)
    {
      if(passphrase != 0) 
      {
	errMsg = i18n("Bad pass Phrase; couldn't decrypt");
	//debug("KpgpBase: passphrase is bad");
	status |= BADPHRASE;
	status |= ERROR;
      }
    }
    else
    {
      // we don't have the secret key
      status |= NO_SEC_KEY;
      status |= ERROR;
      errMsg = i18n("Do not have the secret key for this message");
      //debug("KpgpBase:

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic