26 #include <tdelocale.h>
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;
58 BaseG::encrypt( Block& block,
const KeyIDList& recipients )
60 return encsign( block, recipients, 0 );
65 BaseG::clearsign( Block& block,
const TQString &passphrase )
67 return encsign( block, KeyIDList(), passphrase );
72 BaseG::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 );
208 BaseG::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 );
386 BaseG::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 );
422 BaseG::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);
454 BaseG::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);
486 BaseG::signKey(
const KeyID& keyID,
const TQString &passphrase)
493 cmd +=
" --sign-key 0x";
497 exitStatus = runGpg(cmd.data(), passphrase);
507 BaseG::getAsciiPublicKey(
const KeyID& keyID)
515 exitStatus = runGpg(
"--batch --armor --export 0x" + keyID, 0,
true);
517 if(exitStatus != 0) {
527 BaseG::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 ) );
837 BaseG::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 );