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;
58 BaseG::encrypt( Block& block,
const KeyIDList& recipients )
60 return encsign( block, recipients, 0 );
65 BaseG::clearsign( Block& block,
const char *passphrase )
67 return encsign( block, KeyIDList(), passphrase );
72 BaseG::encsign( Block& block,
const KeyIDList& recipients,
73 const char *passphrase )
78 if(!recipients.isEmpty() && passphrase != 0)
79 cmd =
"--batch --armor --sign --encrypt --textmode";
80 else if(!recipients.isEmpty())
81 cmd =
"--batch --armor --encrypt --textmode";
82 else if(passphrase != 0)
83 cmd =
"--batch --escape-from --clearsign";
86 kdDebug(5100) <<
"kpgpbase: Neither recipients nor passphrase specified." << endl;
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 != 0 )
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 );
208 BaseG::decrypt( Block& block,
const char *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 != 0 )
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";
316 index2 = error.find(
"key ID ", index2) + 7;
317 block.setSignatureKeyId( error.mid(index2,8) );
318 kdDebug(5100) <<
"Message was signed with key '" << block.signatureKeyId() <<
"'\n";
320 index = error.find(
'\n', index2)+1;
322 if ((error.find(
"Key matching expected", index) != -1)
323 || (error.find(
"Can't check signature", index) != -1))
325 status |= UNKNOWN_SIG;
327 block.setSignatureUserId( TQString() );
329 else if( error.find(
"Good signature", index) != -1 )
333 index = error.find(
'"',index);
334 index2 = error.find(
'\n',index+1);
335 index2 = error.findRev(
'"', index2-1);
336 block.setSignatureUserId( error.mid( index+1, index2-index-1 ) );
338 else if( error.find(
"BAD signature", index) != -1 )
343 index = error.find(
'"',index);
344 index2 = error.find(
'\n',index+1);
345 index2 = error.findRev(
'"', index2-1);
346 block.setSignatureUserId( error.mid( index+1, index2-index-1 ) );
348 else if( error.find(
"Can't find the right public key", index) != -1 )
353 status |= UNKNOWN_SIG;
355 block.setSignatureUserId( i18n(
"??? (file ~/.gnupg/pubring.gpg not found)") );
360 block.setSignatureUserId( TQString() );
364 block.setStatus( status );
370 BaseG::readPublicKey(
const KeyID& keyID,
371 const bool readTrust ,
378 exitStatus = runGpg(
"--batch --list-public-keys --with-fingerprint --with-colons --fixed-list-mode 0x" + keyID, 0,
true );
380 exitStatus = runGpg(
"--batch --list-public-keys --with-fingerprint --with-colons --fixed-list-mode --no-expensive-trust-checks 0x" + keyID, 0,
true );
382 if(exitStatus != 0) {
389 if( !strncmp( output.data(),
"pub:", 4 ) )
392 offset = output.find(
"\npub:" );
399 key = parseKeyData( output, offset, key );
406 BaseG::publicKeys(
const TQStringList & patterns )
412 TQCString cmd =
"--batch --list-public-keys --with-fingerprint --with-colons "
413 "--fixed-list-mode --no-expensive-trust-checks";
414 for ( TQStringList::ConstIterator it = patterns.begin();
415 it != patterns.end(); ++it ) {
417 cmd += KProcess::quote( *it ).local8Bit();
420 exitStatus = runGpg( cmd, 0,
true );
422 if(exitStatus != 0) {
428 KeyList publicKeys = parseKeyList(output,
false);
438 BaseG::secretKeys(
const TQStringList & patterns )
444 TQCString cmd =
"--batch --list-secret-keys --with-fingerprint --with-colons "
446 for ( TQStringList::ConstIterator it = patterns.begin();
447 it != patterns.end(); ++it ) {
449 cmd += KProcess::quote( *it ).local8Bit();
452 exitStatus = runGpg( cmd, 0,
true );
454 if(exitStatus != 0) {
460 KeyList secretKeys = parseKeyList(output,
true);
470 BaseG::signKey(
const KeyID& keyID,
const char *passphrase)
477 cmd +=
" --sign-key 0x";
481 exitStatus = runGpg(cmd.data(), passphrase);
491 BaseG::getAsciiPublicKey(
const KeyID& keyID)
499 exitStatus = runGpg(
"--batch --armor --export 0x" + keyID, 0,
true);
501 if(exitStatus != 0) {
511 BaseG::parseKeyData(
const TQCString& output,
int& offset, Key* key )
522 if( ( strncmp( output.data() + offset,
"pub:", 4 ) != 0 )
523 && ( strncmp( output.data() + offset,
"sec:", 4 ) != 0 ) ) {
533 bool firstKey =
true;
539 if( ( eol = output.find(
'\n', index ) ) == -1 )
542 bool bIsPublicKey =
false;
543 if( ( bIsPublicKey = !strncmp( output.data() + index,
"pub:", 4 ) )
544 || !strncmp( output.data() + index,
"sec:", 4 ) )
553 key->setSecret( !bIsPublicKey );
555 Subkey *subkey =
new Subkey( TQCString(), !bIsPublicKey );
558 int pos2 = output.find(
':', pos );
559 for(
int field = 2; field <= 12; field++ )
566 switch( output[pos] )
571 subkey->setInvalid(
true );
572 key->setInvalid(
true );
575 subkey->setDisabled(
true );
576 key->setDisabled(
true );
579 subkey->setRevoked(
true );
580 key->setRevoked(
true );
583 subkey->setExpired(
true );
584 key->setExpired(
true );
596 kdDebug(5100) <<
"Unknown trust value\n";
602 subkey->setKeyLength( output.mid( pos, pos2-pos ).toUInt() );
606 subkey->setKeyAlgorithm( output.mid( pos, pos2-pos ).toUInt() );
609 keyID = output.mid( pos, pos2-pos );
610 subkey->setKeyID( keyID );
614 subkey->setCreationDate( output.mid( pos, pos2-pos ).toLong() );
618 subkey->setExpirationDate( output.mid( pos, pos2-pos ).toLong() );
620 subkey->setExpirationDate( -1 );
628 for(
int i=pos; i<pos2; i++ )
632 subkey->setCanEncrypt(
true );
635 subkey->setCanSign(
true );
638 subkey->setCanCertify(
true );
641 key->setCanEncrypt(
true );
644 key->setCanSign(
true );
647 key->setCanCertify(
true );
650 kdDebug(5100) <<
"Unknown key capability\n";
655 pos2 = output.find(
':', pos );
657 key->addSubkey( subkey );
659 else if( !strncmp( output.data() + index,
"uid:", 4 ) )
663 UserID *userID =
new UserID(
"" );
666 int pos2 = output.find(
':', pos );
667 for(
int field=2; field <= 10; field++ )
674 switch( output[pos] )
677 userID->setInvalid(
true );
680 userID->setRevoked(
true );
684 userID->setValidity( KPGP_VALIDITY_UNDEFINED );
687 userID->setValidity( KPGP_VALIDITY_NEVER );
690 userID->setValidity( KPGP_VALIDITY_MARGINAL );
693 userID->setValidity( KPGP_VALIDITY_FULL );
696 userID->setValidity( KPGP_VALIDITY_ULTIMATE );
699 kdDebug(5100) <<
"Unknown trust value\n";
712 TQCString uid = output.mid( pos, pos2-pos );
716 for (
int idx = 0 ; (idx = uid.find(
"\\x", idx )) >= 0 ; ++idx ) {
718 str[0] = (char) TQString( uid.mid( idx + 2, 2 ) ).toShort( 0, 16 );
719 uid.replace( idx, 4, str );
721 TQString uidString = TQString::fromUtf8( uid.data() );
724 for (
unsigned int i = 0; i + 1 < uidString.length(); ++i ) {
725 if ( uidString[i].unicode() == 0xdbff &&
726 uidString[i+1].row() == 0xde ) {
735 kdDebug(5100) <<
"User Id '" << uid
736 <<
"' doesn't seem to be utf-8 encoded." << endl;
740 int nonAsciiCount = 0, asciiCount = 0;
744 for(
signed char* ch = (
signed char*)uid.data();
745 *ch && ( *ch !=
'(' ) && ( *ch !=
'<' );
747 if( ( ( *ch >=
'A' ) && ( *ch <=
'Z' ) )
748 || ( ( *ch >=
'a' ) && ( *ch <=
'z' ) ) )
753 kdDebug(5100) <<
"ascii-nonAscii ratio : " << asciiCount
754 <<
":" << nonAsciiCount << endl;
755 if( nonAsciiCount > asciiCount ) {
757 kdDebug(5100) <<
"Assume koi8-r encoding." << endl;
758 TQTextCodec *codec = TQTextCodec::codecForName(
"KOI8-R");
759 uidString = codec->toUnicode( uid.data() );
767 if( ( uidString.length() >= 2 )
768 && ( uidString[0].lower() == uidString[0] )
769 && ( uidString[1].upper() == uidString[1] ) ) {
772 kdDebug(5100) <<
"No, it doesn't seem to be koi8-r. "
773 "Use CP 1251 instead." << endl;
774 TQTextCodec *codec = TQTextCodec::codecForName(
"CP1251");
775 uidString = codec->toUnicode( uid.data() );
780 kdDebug(5100) <<
"Assume latin1 encoding." << endl;
781 uidString = TQString::fromLatin1( uid.data() );
784 userID->setText( uidString );
788 pos2 = output.find(
':', pos );
792 key->addUserID( userID );
794 else if( !strncmp( output.data() + index,
"fpr:", 4 ) )
803 for(
int i = 0; i < 8; i++ )
804 pos = output.find(
':', pos ) + 1;
805 int pos2 = output.find(
':', pos );
807 key->setFingerprint( keyID, output.mid( pos, pos2-pos ) );
821 BaseG::parseKeyList(
const TQCString& output,
bool secretKeys )
828 if( !strncmp( output.data(),
"pub:", 4 )
829 || !strncmp( output.data(),
"sec:", 4 ) )
833 offset = output.find(
"\nsec:" );
835 offset = output.find(
"\npub:" );
843 key = parseKeyData( output, offset );