27#include <tdeprocess.h> 
   30#include <tqtextcodec.h> 
   40  runGpg( 
"--version", 0 );
 
   41  int eol = output.find( 
'\n' );
 
   43    int pos = output.findRev( 
' ', eol - 1 );
 
   45      mVersion = output.mid( pos + 1, eol - pos - 1 );
 
   46      kdDebug(5100) << 
"found GnuPG " << mVersion << endl;
 
   58BaseG::encrypt( Block& block, 
const KeyIDList& recipients )
 
   60  return encsign( block, recipients, 0 );
 
   65BaseG::clearsign( Block& block, 
const TQString &passphrase )
 
   67  return encsign( block, KeyIDList(), passphrase );
 
   72BaseG::encsign( Block& block, 
const KeyIDList& recipients,
 
   73                const TQString &passphrase )
 
   78  if (!recipients.isEmpty() && !passphrase.isEmpty())
 
   79    cmd = 
"--batch --armor --sign --encrypt --textmode";
 
   80  else if(!recipients.isEmpty())
 
   81    cmd = 
"--batch --armor --encrypt --textmode";
 
   82  else if (!passphrase.isEmpty())
 
   83    cmd = 
"--batch --escape-from --clearsign";
 
   86    kdDebug(5100) << 
"kpgpbase: Neither recipients nor passphrase specified." << endl;
 
   90  if (!passphrase.isEmpty())
 
   93  if(!recipients.isEmpty())
 
   95    cmd += 
" --set-filename stdin";
 
   97    TQCString pgpUser = Module::getKpgp()->user();
 
   98    if(Module::getKpgp()->encryptToSelf() && !pgpUser.isEmpty()) {
 
  103    for( KeyIDList::ConstIterator it = recipients.begin();
 
  104         it != recipients.end(); ++it ) {
 
  111  input = block.text();
 
  112  exitStatus = runGpg(cmd.data(), passphrase);
 
  113  if( !output.isEmpty() )
 
  114    block.setProcessedText( output );
 
  115  block.setError( error );
 
  117  if( exitStatus != 0 )
 
  120    errMsg = i18n( 
"Unknown error." );
 
  128  if(!recipients.isEmpty())
 
  132    unsigned int num = 0;
 
  133    TQCString badkeys = 
"";
 
  141    while((index = error.find(
"skipped: ",index)) != -1)
 
  144      index = error.find(
'\'',index);
 
  145      int index2 = error.find(
'\'',index+1);
 
  146      badkeys += error.mid(index, index2-index+1) + 
", ";
 
  151      badkeys.stripWhiteSpace();
 
  152      if(num == recipients.count())
 
  153        errMsg = i18n(
"Could not find public keys matching the userid(s)\n" 
  155                      "the message is not encrypted.")
 
  156                     .arg( badkeys.data() );
 
  158        errMsg = i18n(
"Could not find public keys matching the userid(s)\n" 
  160                      "these persons will not be able to read the message.")
 
  161                     .arg( badkeys.data() );
 
  162      status |= MISSINGKEY;
 
  167  if (!passphrase.isEmpty())
 
  181    if( error.find(
"bad passphrase") != -1 )
 
  183      errMsg = i18n(
"Signing failed because the passphrase is wrong.");
 
  185      status |= ERR_SIGNING;
 
  188    else if( error.find(
"unusable secret key") != -1 )
 
  190      errMsg = i18n(
"Signing failed because your secret key is unusable.");
 
  191      status |= ERR_SIGNING;
 
  194    else if( !( status & ERROR ) )
 
  202  block.setStatus( status );
 
  208BaseG::decrypt( Block& block, 
const TQString &passphrase )
 
  214  input = block.text();
 
  215  exitStatus = runGpg(
"--batch --decrypt", passphrase);
 
  216  if( !output.isEmpty() && ( error.find( 
"gpg: quoted printable" ) == -1 ) )
 
  217    block.setProcessedText( output );
 
  218  block.setError( error );
 
  220  if(exitStatus == -1) {
 
  221    errMsg = i18n(
"Error running gpg");
 
  223    block.setStatus( status );
 
  247  if( error.find( 
"gpg: encrypted with" ) != -1 )
 
  251    if( error.find( 
"\ngpg: decryption failed" ) != -1 )
 
  253      if( ( index = error.find( 
"bad passphrase" ) ) != -1 )
 
  255        if (!passphrase.isEmpty())
 
  257          errMsg = i18n( 
"Bad passphrase; could not decrypt." );
 
  258          kdDebug(5100) << 
"Base: passphrase is bad" << endl;
 
  265          index2 = error.findRev(
'"', index) - 1;
 
  266          index = error.findRev(
"      \"", index2) + 7;
 
  269          block.setRequiredUserId( TQString::fromUtf8( error.mid( index, index2 - index + 1 ) ) );
 
  270          kdDebug(5100) << 
"Base: key needed is \"" << block.requiredUserId() << 
"\"!" << endl;
 
  273      else if( error.find( 
"secret key not available" ) != -1 )
 
  276        status |= NO_SEC_KEY;
 
  278        errMsg = i18n(
"You do not have the secret key needed to decrypt this message.");
 
  279        kdDebug(5100) << 
"Base: no secret key for this message" << endl;
 
  286    index = error.find(
"can only be read by:");
 
  289      index = error.find(
'\n',index);
 
  290      int end = error.find(
"\n\n",index);
 
  293      while( (index2 = error.find(
'\n',index+1)) <= end )
 
  295    TQCString item = error.mid(index+1,index2-index-1);
 
  296    item.stripWhiteSpace();
 
  297    mRecipients.append(item);
 
  307  if((index = error.find(
"Signature made")) != -1)
 
  313    index2 = error.find(
"using", index+15);
 
  314    block.setSignatureDate( error.mid(index+15, index2-(index+15)-1) );
 
  315    kdDebug(5100) << 
"Message was signed on '" << block.signatureDate() << 
"'\n";
 
  321    if (error.contains(
"key ID") > 0) {
 
  322        index2 = error.find(
"key ID ", index2) + 7;
 
  323        block.setSignatureKeyId( error.mid(index2,8) );
 
  326        index2 = error.find(
"key ", index2) + 4;
 
  331        int end =  error.find(
"\n", index2);
 
  332        block.setSignatureKeyId( error.mid(index2,end-index2) );
 
  334    kdDebug(5100) << 
"Message was signed with key '" << block.signatureKeyId() << 
"'\n";
 
  336    index = error.find(
'\n', index2)+1;
 
  338    if ((error.find(
"Key matching expected", index) != -1)
 
  339        || (error.find(
"Can't check signature", index) != -1))
 
  341      status |= UNKNOWN_SIG;
 
  343      block.setSignatureUserId( TQString() );
 
  345    else if( error.find(
"Good signature", index) != -1 )
 
  349      index = error.find(
'"',index);
 
  350      index2 = error.find(
'\n',index+1);
 
  351      index2 = error.findRev(
'"', index2-1);
 
  352      block.setSignatureUserId( TQString::fromLocal8Bit( error.mid( index+1, index2-index-1 ) ) );
 
  354    else if( error.find(
"BAD signature", index) != -1 )
 
  359      index = error.find(
'"',index);
 
  360      index2 = error.find(
'\n',index+1);
 
  361      index2 = error.findRev(
'"', index2-1);
 
  362      block.setSignatureUserId( TQString::fromLocal8Bit(  error.mid( index+1, index2-index-1 ) ) );
 
  364    else if( error.find(
"Can't find the right public key", index) != -1 )
 
  369      status |= UNKNOWN_SIG;
 
  371      block.setSignatureUserId( i18n(
"??? (file ~/.gnupg/pubring.gpg not found)") );
 
  376      block.setSignatureUserId( TQString() );
 
  380  block.setStatus( status );
 
  386BaseG::readPublicKey( 
const KeyID& keyID,
 
  387                      const bool readTrust ,
 
  394    exitStatus = runGpg( 
"--batch --list-public-keys --with-fingerprint --with-colons --fixed-list-mode 0x" + keyID, 0, 
true );
 
  396    exitStatus = runGpg( 
"--batch --list-public-keys --with-fingerprint --with-colons --fixed-list-mode --no-expensive-trust-checks 0x" + keyID, 0, 
true );
 
  398  if(exitStatus != 0) {
 
  405  if( !strncmp( output.data(), 
"pub:", 4 ) )
 
  408    offset = output.find( 
"\npub:" );
 
  415  key = parseKeyData( output, offset, key );
 
  422BaseG::publicKeys( 
const TQStringList & patterns )
 
  428  TQCString cmd = 
"--batch --list-public-keys --with-fingerprint --with-colons " 
  429                 "--fixed-list-mode --no-expensive-trust-checks";
 
  430  for ( TQStringList::ConstIterator it = patterns.begin();
 
  431        it != patterns.end(); ++it ) {
 
  433    cmd += TDEProcess::quote( *it ).local8Bit();
 
  436  exitStatus = runGpg( cmd, 0, 
true );
 
  438  if(exitStatus != 0) {
 
  444  KeyList publicKeys = parseKeyList(output, 
false);
 
  454BaseG::secretKeys( 
const TQStringList & patterns )
 
  460  TQCString cmd = 
"--batch --list-secret-keys --with-fingerprint --with-colons " 
  462  for ( TQStringList::ConstIterator it = patterns.begin();
 
  463        it != patterns.end(); ++it ) {
 
  465    cmd += TDEProcess::quote( *it ).local8Bit();
 
  468  exitStatus = runGpg( cmd, 0, 
true );
 
  470  if(exitStatus != 0) {
 
  476  KeyList secretKeys = parseKeyList(output, 
true);
 
  486BaseG::signKey(
const KeyID& keyID, 
const TQString &passphrase)
 
  493  cmd += 
" --sign-key 0x";
 
  497  exitStatus = runGpg(cmd.data(), passphrase);
 
  507BaseG::getAsciiPublicKey(
const KeyID& keyID)
 
  515  exitStatus = runGpg(
"--batch --armor --export 0x" + keyID, 0, 
true);
 
  517  if(exitStatus != 0) {
 
  527BaseG::parseKeyData( 
const TQCString& output, 
int& offset, Key* key  )
 
  538  if(    ( strncmp( output.data() + offset, 
"pub:", 4 ) != 0 )
 
  539      && ( strncmp( output.data() + offset, 
"sec:", 4 ) != 0 ) ) {
 
  549  bool firstKey = 
true;
 
  555    if( ( eol = output.find( 
'\n', index ) ) == -1 )
 
  558    bool bIsPublicKey = 
false;
 
  559    if( ( bIsPublicKey = !strncmp( output.data() + index, 
"pub:", 4 ) )
 
  560        || !strncmp( output.data() + index, 
"sec:", 4 ) )
 
  569      key->setSecret( !bIsPublicKey );
 
  571      Subkey *subkey = 
new Subkey( TQCString(), !bIsPublicKey );
 
  574      int pos2 = output.find( 
':', pos );
 
  575      for( 
int field = 2; field <= 12; field++ )
 
  582            switch( output[pos] )
 
  587              subkey->setInvalid( 
true );
 
  588              key->setInvalid( 
true );
 
  591              subkey->setDisabled( 
true );
 
  592              key->setDisabled( 
true );
 
  595              subkey->setRevoked( 
true );
 
  596              key->setRevoked( 
true );
 
  599              subkey->setExpired( 
true );
 
  600              key->setExpired( 
true );
 
  612              kdDebug(5100) << 
"Unknown trust value\n";
 
  618            subkey->setKeyLength( output.mid( pos, pos2-pos ).toUInt() );
 
  622            subkey->setKeyAlgorithm( output.mid( pos, pos2-pos ).toUInt() );
 
  625          keyID = output.mid( pos, pos2-pos );
 
  626          subkey->setKeyID( keyID );
 
  630            subkey->setCreationDate( output.mid( pos, pos2-pos ).toLong() );
 
  634            subkey->setExpirationDate( output.mid( pos, pos2-pos ).toLong() );
 
  636            subkey->setExpirationDate( -1 ); 
 
  644          for( 
int i=pos; i<pos2; i++ )
 
  648              subkey->setCanEncrypt( 
true );
 
  651              subkey->setCanSign( 
true );
 
  654              subkey->setCanCertify( 
true );
 
  657              key->setCanEncrypt( 
true );
 
  660              key->setCanSign( 
true );
 
  663              key->setCanCertify( 
true );
 
  666              kdDebug(5100) << 
"Unknown key capability\n";
 
  671        pos2 = output.find( 
':', pos );
 
  673      key->addSubkey( subkey );
 
  675    else if( !strncmp( output.data() + index, 
"uid:", 4 ) )
 
  679      UserID *userID = 
new UserID( 
"" );
 
  682      int pos2 = output.find( 
':', pos );
 
  683      for( 
int field=2; field <= 10; field++ )
 
  690            switch( output[pos] )
 
  693              userID->setInvalid( 
true );
 
  696              userID->setRevoked( 
true );
 
  700              userID->setValidity( KPGP_VALIDITY_UNDEFINED );
 
  703              userID->setValidity( KPGP_VALIDITY_NEVER );
 
  706              userID->setValidity( KPGP_VALIDITY_MARGINAL );
 
  709              userID->setValidity( KPGP_VALIDITY_FULL );
 
  712              userID->setValidity( KPGP_VALIDITY_ULTIMATE );
 
  715              kdDebug(5100) << 
"Unknown trust value\n";
 
  728          TQCString uid = output.mid( pos, pos2-pos );
 
  732          for ( 
int idx = 0 ; (idx = uid.find( 
"\\x", idx )) >= 0 ; ++idx ) {
 
  734            str[0] = (char) TQString( uid.mid( idx + 2, 2 ) ).toShort( 0, 16 );
 
  735            uid.replace( idx, 4, str );
 
  737          TQString uidString = TQString::fromUtf8( uid.data() );
 
  740          for ( 
unsigned int i = 0; i + 1 < uidString.length(); ++i ) {
 
  741            if ( uidString[i].unicode() == 0xdbff &&
 
  742                 uidString[i+1].row() == 0xde ) {
 
  751            kdDebug(5100) << 
"User Id '" << uid
 
  752                          << 
"' doesn't seem to be utf-8 encoded." << endl;
 
  756            int nonAsciiCount = 0, asciiCount = 0;
 
  760            for( 
signed char* ch = (
signed char*)uid.data();
 
  761                 *ch && ( *ch != 
'(' ) && ( *ch != 
'<' );
 
  763              if( ( ( *ch >= 
'A' ) && ( *ch <= 
'Z' ) )
 
  764                  || ( ( *ch >= 
'a' ) && ( *ch <= 
'z' ) ) )
 
  769            kdDebug(5100) << 
"ascii-nonAscii ratio : " << asciiCount
 
  770                          << 
":" << nonAsciiCount << endl;
 
  771            if( nonAsciiCount > asciiCount ) {
 
  773              kdDebug(5100) << 
"Assume koi8-r encoding." << endl;
 
  774              TQTextCodec *codec = TQTextCodec::codecForName(
"KOI8-R");
 
  775              uidString = codec->toUnicode( uid.data() );
 
  783              if( ( uidString.length() >= 2 )
 
  784                  && ( uidString[0].lower() == uidString[0] )
 
  785                  && ( uidString[1].upper() == uidString[1] ) ) {
 
  788                kdDebug(5100) << 
"No, it doesn't seem to be koi8-r. " 
  789                                 "Use CP 1251 instead." << endl;
 
  790                TQTextCodec *codec = TQTextCodec::codecForName(
"CP1251");
 
  791                uidString = codec->toUnicode( uid.data() );
 
  796              kdDebug(5100) << 
"Assume latin1 encoding." << endl;
 
  797              uidString = TQString::fromLatin1( uid.data() );
 
  800          userID->setText( uidString );
 
  804        pos2 = output.find( 
':', pos );
 
  808      key->addUserID( userID );
 
  810    else if( !strncmp( output.data() + index, 
"fpr:", 4 ) )
 
  819      for( 
int i = 0; i < 8; i++ )
 
  820        pos = output.find( 
':', pos ) + 1;
 
  821      int pos2 = output.find( 
':', pos );
 
  823      key->setFingerprint( keyID, output.mid( pos, pos2-pos ) );
 
  837BaseG::parseKeyList( 
const TQCString& output, 
bool secretKeys )
 
  844  if(    !strncmp( output.data(), 
"pub:", 4 )
 
  845      || !strncmp( output.data(), 
"sec:", 4 ) )
 
  849      offset = output.find( 
"\nsec:" );
 
  851      offset = output.find( 
"\npub:" );
 
  859    key = parseKeyData( output, offset );