one entry for korganizer in khelpcenters navigation tree is enough
[kdepim.git] / libkpgp / kpgpbase6.cpp
blobf7efb29ccdcefef5549bc3160864dc1b2f5247c5
1 /*
2 kpgpbase6.cpp
4 Copyright (C) 2001,2002 the KPGP authors
5 See file AUTHORS.kpgp for details
7 This file is part of KPGP, the KDE PGP/GnuPG support library.
9 KPGP is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "kpgpbase.h"
21 #include <string.h> /* strncmp */
22 #include <assert.h>
24 #include <QDateTime>
25 //Added by qt3to4:
26 #include <QByteArray>
28 #include <klocale.h>
29 #include <kdebug.h>
31 #define PGP6 "pgp"
33 namespace Kpgp {
35 Base6::Base6()
36 : Base2()
41 Base6::~Base6()
46 int
47 Base6::decrypt( Block& block, const char *passphrase )
49 int index, index2;
50 int exitStatus = 0;
52 clear();
53 input = block.text();
54 exitStatus = run( PGP6 " +batchmode +language=C -f", passphrase);
55 if( !output.isEmpty() )
56 block.setProcessedText( output );
57 block.setError( error );
59 if(exitStatus == -1) {
60 errMsg = i18n("error running PGP");
61 status = ERROR;
62 block.setStatus( status );
63 return status;
66 // encrypted message
67 if( error.contains("File is encrypted.") )
69 //kDebug( 5326 ) <<"kpgpbase: message is encrypted";
70 status |= ENCRYPTED;
71 if((index = error.indexOf("Key for user ID")) != -1 )
73 // Find out the key for which the phrase is needed
74 index = error.indexOf(':', index) + 2;
75 index2 = error.indexOf('\n', index);
76 block.setRequiredUserId( error.mid(index, index2 - index) );
77 //kDebug( 5326 ) <<"Base: key needed is \"" << block.requiredUserId() <<"\"!";
79 // Test output length to find out, if the passphrase is
80 // bad. If someone knows a better way, please fix this.
81 /// ### This could be done by forcing PGP6 to be more verbose
82 /// by adding an additional '+verbose=2' to the command line
83 if (!passphrase || !output.length())
85 errMsg = i18n("Bad passphrase; could not decrypt.");
86 //kDebug( 5326 ) <<"Base: passphrase is bad";
87 status |= BADPHRASE;
88 status |= ERROR;
91 else if( error.contains("You do not have the secret key needed to decrypt this file.") )
93 errMsg = i18n("You do not have the secret key for this message.");
94 //kDebug( 5326 ) <<"Base: no secret key for this message";
95 status |= NO_SEC_KEY;
96 status |= ERROR;
100 // signed message
102 // Examples (made with PGP 6.5.8)
103 /* Example no. 1 (signed with unknown key):
104 * File is signed. signature not checked.
105 * Signature made 2001/11/25 11:55 GMT
106 * key does not meet validity threshold.
108 * WARNING: Because this public key is not certified with a trusted
109 * signature, it is not known with high confidence that this public key
110 * actually belongs to: "(KeyID: 0x475027BD)".
112 /* Example no. 2 (signed with untrusted key):
113 * File is signed. Good signature from user "Joe User <joe@foo.bar>".
114 * Signature made 2001/12/05 13:09 GMT
116 * WARNING: Because this public key is not certified with a trusted
117 * signature, it is not known with high confidence that this public key
118 * actually belongs to: "Joe User <joe@foo.bar>".
120 /* Example no. 3 (signed with trusted key):
121 * File is signed. Good signature from user "Joe User <joe@foo.bar>".
122 * Signature made 2001/12/05 13:09 GMT
124 if(((index = error.indexOf("File is signed.")) != -1 )
125 || (error.contains("Good signature") ))
127 //kDebug( 5326 ) <<"Base: message is signed";
128 status |= SIGNED;
129 // determine the signature date
130 if( ( index2 = error.indexOf( "Signature made", index ) ) != -1 )
132 index2 += 15;
133 int eol = error.indexOf( '\n', index2 );
134 block.setSignatureDate( error.mid( index2, eol-index2 ) );
135 kDebug( 5326 ) <<"Message was signed on '" << block.signatureDate() <<"'";
137 else
138 block.setSignatureDate( QByteArray() );
139 // determine signature status and signature key
140 if( error.contains("signature not checked") )
142 index = error.indexOf("KeyID:",index);
143 block.setSignatureKeyId( error.mid(index+9,8) );
144 block.setSignatureUserId( QString() );
145 status |= UNKNOWN_SIG;
146 status |= GOODSIG;
148 else if((index = error.indexOf("Good signature")) != -1 )
150 status |= GOODSIG;
151 // get signer
152 index = error.indexOf('"',index)+1;
153 index2 = error.indexOf('"', index);
154 block.setSignatureUserId( error.mid(index, index2-index) );
156 // get key ID of signer
157 index = error.indexOf("KeyID:",index2);
158 if (index == -1)
159 block.setSignatureKeyId( QByteArray() );
160 else
161 block.setSignatureKeyId( error.mid(index+9,8) );
163 else if( error.contains("Can't find the right public key") )
165 // #### fix this hack
166 // #### This doesn't happen with PGP 6.5.8 because it seems to
167 // #### automatically create an empty pubring if it doesn't exist.
168 status |= UNKNOWN_SIG;
169 status |= GOODSIG; // this is a hack...
170 block.setSignatureUserId( i18n("??? (file ~/.pgp/pubring.pkr not found)") );
171 block.setSignatureKeyId( "???" );
173 else
175 status |= ERROR;
176 block.setSignatureUserId( QString() );
177 block.setSignatureKeyId( QByteArray() );
180 //kDebug( 5326 ) <<"status =" << status;
181 block.setStatus( status );
182 return status;
186 Key*
187 Base6::readPublicKey( const KeyID& keyID,
188 const bool readTrust /* = false */,
189 Key* key /* = 0 */ )
191 int exitStatus = 0;
193 status = 0;
194 exitStatus = run( PGP6 " +batchmode -compatible +verbose=0 +language=C -kvvc "
195 "0x" + keyID, 0, true );
197 if(exitStatus != 0) {
198 status = ERROR;
199 return 0;
202 key = parseSingleKey( output, key );
204 if( key == 0 )
206 return 0;
209 if( readTrust )
211 exitStatus = run( PGP6 " +batchmode -compatible +verbose=0 +language=C -kc "
212 "0x" + keyID, 0, true );
214 if(exitStatus != 0) {
215 status = ERROR;
216 return 0;
219 parseTrustDataForKey( key, output );
222 return key;
226 KeyList
227 Base6::publicKeys( const QStringList & patterns )
229 return doGetPublicKeys( PGP6 " +batchmode -compatible +verbose=0 "
230 "+language=C -kvvc", patterns );
235 QStrList
236 Base6::pubKeys()
238 int index, index2;
239 int exitStatus = 0;
240 int compatibleMode = 1;
242 status = 0;
243 exitStatus = run("pgp +batchmode +language=C -kv -f");
245 if(exitStatus != 0) {
246 status = ERROR;
247 return 0;
250 //truncate trailing "\n"
251 if (error.length() > 1) error.truncate(error.length()-1);
253 QStrList publicKeys;
254 index = error.indexOf("bits/keyID",1); // skip first to "\n"
255 if (index ==-1)
257 index = error.indexOf("Type bits",1); // skip first to "\n"
258 if (index == -1)
259 return 0;
260 else
261 compatibleMode = 0;
264 while( (index = error.indexOf("\n",index)) != -1 )
266 //parse line
267 QCString line;
268 if( (index2 = error.indexOf("\n",index+1)) != -1 )
269 // skip last line
271 int index3;
272 if (compatibleMode)
274 int index_pub = error.indexOf("pub ",index);
275 int index_sec = error.indexOf("sec ",index);
276 if (index_pub < 0)
277 index3 = index_sec;
278 else if (index_sec < 0)
279 index3 = index_pub;
280 else
281 index3 = (index_pub < index_sec ? index_pub : index_sec);
283 else
285 int index_rsa = error.indexOf("RSA ",index);
286 int index_dss = error.indexOf("DSS ",index);
287 if (index_rsa < 0)
288 index3 = index_dss;
289 else if (index_dss < 0)
290 index3 = index_rsa;
291 else
292 index3 = (index_rsa < index_dss ? index_rsa : index_dss);
295 if( (index3 >index2) || (index3 == -1) )
297 // second address for the same key
298 line = error.mid(index+1,index2-index-1);
299 line = line.trimmed();
300 } else {
301 // line with new key
302 int index4 = error.indexOf(QRegExp("/\\d{2}/\\d{2} "), index);
303 line = error.mid(index4+7,index2-index4-7);
305 //kDebug( 5326 ) <<"Base: found key for" << (const char *)line;
307 // don't add PGP's comments to the key list
308 if (strncmp(line.data(),"*** KEY EXPIRED ***",19) &&
309 !line.contains(QRegExp("^expires \\d{4}/\\d{2}/\\d{2}")) &&
310 strncmp(line.data(),"*** DEFAULT SIGNING KEY ***",27)) {
311 publicKeys.append(line);
314 else
315 break;
316 index = index2;
319 // Also look for pgp key groups
320 exitStatus = run("pgp +batchmode +language=C -gv -f");
322 if(exitStatus != 0) {
323 status = ERROR;
324 return 0;
327 index = 0;
328 while ( (index = error.indexOf("\n >", index)) != -1 ) {
329 QCString line;
330 index += 4;
331 index2 = error.indexOf(" \"", index);
332 line = error.mid(index, index2-index+1).trimmed();
334 //kDebug( 5326 ) <<"Base6: found key group for" << line;
335 publicKeys.append(line);
338 return publicKeys;
343 KeyList
344 Base6::secretKeys( const QStringList & patterns )
346 return publicKeys( patterns );
351 Base6::isVersion6()
353 int exitStatus = 0;
355 exitStatus = run( PGP6, 0, true );
357 if(exitStatus == -1) {
358 errMsg = i18n("error running PGP");
359 status = ERROR;
360 return 0;
363 if( error.contains("Version 6") )
365 //kDebug( 5326 ) <<"kpgpbase: pgp version 6.x detected";
366 return 1;
369 //kDebug( 5326 ) <<"kpgpbase: not pgp version 6.x";
370 return 0;
374 Key*
375 Base6::parseKeyData( const QByteArray& output, int& offset, Key* key /* = 0 */ )
376 // This function parses the data for a single key which is output by PGP 6
377 // with the following command line arguments:
378 // +batchmode -compatible +verbose=0 +language=C -kvvc
379 // It expects the key data to start at offset and returns the start of
380 // the next key's data in offset.
382 if( ( strncmp( output.data() + offset, "DSS", 3 ) != 0 ) &&
383 ( strncmp( output.data() + offset, "RSA", 3 ) != 0 ) )
385 kDebug( 5326 ) <<"Unknown key type or corrupt key data.";
386 return 0;
389 Subkey *subkey = 0;
390 bool firstLine = true;
391 bool canSign = false;
392 bool canEncr = false;
393 bool fpr = false;
395 while( true )
397 int eol;
399 // search the end of the current line
400 if( ( eol = output.indexOf( '\n', offset ) ) == -1 )
401 break;
403 //kDebug( 5326 ) <<"Parsing:" << output.mid(offset, eol-offset);
405 if( firstLine && ( !strncmp( output.data() + offset, "DSS", 3 ) ||
406 !strncmp( output.data() + offset, "RSA", 3 ) ) )
407 { // line contains primary key data
408 // Example 1:
409 // RSA 1024 0xE2D074D3 2001/09/09 Test Key <testkey@xyz>
410 // Example 2 (disabled key):
411 // RSA@ 1024 0x8CCB2C1B 2001/11/04 Disabled Test Key <disabled@xyz>
412 // Example 3 (expired key):
413 // RSA 1024 0x7B94827D 2001/09/09 *** KEY EXPIRED ***
414 // Example 4 (revoked key):
415 // RSA 1024 0x956721F9 2001/09/09 *** KEY REVOKED ***
416 // Example 5 (default signing key):
417 // RSA 1024 0x12345678 2001/09/09 *** DEFAULT SIGNING KEY ***
418 // Example 6 (expiring key):
419 // RSA 2048 0xC11DB2E5 2000/02/24 expires 2001/12/31
420 // Example 7 (complex example):
421 // DSS 1024 0x80E104A7 2000/06/05 expires 2002/05/31
422 // DSS 1024 0x80E104A7 2001/06/27 *** KEY REVOKED ***expires 2002/06/27
423 // DH 1024 0x80E104A7 2000/06/05 *** KEY REVOKED ****** KEY EXPIRED ***
424 //kDebug( 5326 )<<"Primary key data:";
425 bool sign = false;
426 bool encr = false;
428 // set default key capabilities
429 if( !strncmp( output.data() + offset, "DSS", 3 ) )
430 sign = true;
431 if( !strncmp( output.data() + offset, "RSA", 3 ) )
433 sign = true;
434 encr = true;
437 int pos, pos2;
439 if( key == 0 )
440 key = new Key();
441 else
442 key->clear();
444 subkey = new Subkey( "", false );
445 key->addSubkey( subkey );
446 // expiration date defaults to never
447 subkey->setExpirationDate( -1 );
449 // Key Flags
450 switch( output[offset+3] )
452 case ' ': // nothing special
453 break;
454 case '@': // disabled key
455 subkey->setDisabled( true );
456 key->setDisabled( true );
457 break;
458 default:
459 kDebug( 5326 ) <<"Unknown key flag.";
462 // Key Length
463 pos = offset + 4;
464 while( output[pos] == ' ' )
465 pos++;
466 pos2 = output.indexOf( ' ', pos );
467 subkey->setKeyLength( output.mid( pos, pos2-pos ).toUInt() );
468 //kDebug( 5326 ) <<"Key Length:"<<subkey->keyLength();
470 // Key ID
471 pos = pos2 + 1;
472 while( output[pos] == ' ' )
473 pos++;
474 pos += 2; // skip the '0x'
475 pos2 = output.indexOf( ' ', pos );
476 subkey->setKeyID( output.mid( pos, pos2-pos ) );
477 //kDebug( 5326 ) <<"Key ID:"<<subkey->keyID();
479 // Creation Date
480 pos = pos2 + 1;
481 while( output[pos] == ' ' )
482 pos++;
483 pos2 = output.indexOf( ' ', pos );
484 int year = output.mid( pos, 4 ).toInt();
485 int month = output.mid( pos+5, 2 ).toInt();
486 int day = output.mid( pos+8, 2 ).toInt();
487 QDateTime dt( QDate( year, month, day ), QTime( 00, 00 ) );
488 QDateTime epoch( QDate( 1970, 01, 01 ), QTime( 00, 00 ) );
489 // The calculated creation date isn't exactly correct because QDateTime
490 // doesn't know anything about timezones and always assumes local time
491 // although epoch is of course UTC. But as PGP 6 anyway doesn't print
492 // the time this doesn't matter too much.
493 subkey->setCreationDate( epoch.secsTo( dt ) );
495 // User ID or key properties
496 pos = pos2 + 1;
497 while( output[pos] == ' ' )
498 pos++;
499 while( pos < eol )
500 { // loop over User ID resp. key properties
501 if( !strncmp( output.data() + pos, "*** KEY REVOKED ***", 19 ) )
503 sign = false;
504 encr = false;
505 subkey->setRevoked( true );
506 key->setRevoked( true );
507 pos += 19;
508 //kDebug( 5326 ) <<"Key was revoked.";
510 else if( !strncmp( output.data() + pos, "*** KEY EXPIRED ***", 19 ) )
512 sign = false;
513 encr = false;
514 subkey->setExpired( true );
515 key->setExpired( true );
516 pos += 19;
517 //kDebug( 5326 ) <<"Key has expired.";
519 else if( !strncmp( output.data() + pos, "expires ", 8 ) )
521 pos += 8;
522 int year = output.mid( pos, 4 ).toInt();
523 int month = output.mid( pos+5, 2 ).toInt();
524 int day = output.mid( pos+8, 2 ).toInt();
525 QDateTime dt( QDate( year, month, day ), QTime( 00, 00 ) );
526 // Here the same comments as for the creation date are valid.
527 subkey->setExpirationDate( epoch.secsTo( dt ) );
528 pos += 10;
529 //kDebug( 5326 ) <<"Key expires...";
531 else if( !strncmp( output.data() + pos, "*** DEFAULT SIGNING KEY ***", 27 ) )
533 pos += 27;
534 //kDebug( 5326 ) <<"Key is default signing key.";
536 else
538 QByteArray uid = output.mid( pos, eol-pos );
539 key->addUserID( uid );
540 pos = eol;
541 //kDebug( 5326 ) <<"User ID:"<<uid;
544 // set key capabilities of the primary subkey
545 subkey->setCanEncrypt( encr );
546 subkey->setCanSign( sign );
547 subkey->setCanCertify( sign );
548 // remember the global key capabilities
549 canSign = sign;
550 canEncr = encr;
552 else if( !strncmp( output.data() + offset, "DSS", 3 ) ||
553 !strncmp( output.data() + offset, " DH", 3 ) ||
554 !strncmp( output.data() + offset, "RSA", 3 ) )
555 { // line contains secondary key data (or data for the next key)
556 if( fpr )
557 break; // here begins the next key's data
558 //kDebug( 5326 )<<"Secondary key data:";
560 if( key == 0 )
561 break;
563 bool sign = false;
564 bool encr = false;
566 // set default key capabilities
567 if( !strncmp( output.data() + offset, "DSS", 3 ) )
568 sign = true;
569 if( !strncmp( output.data() + offset, " DH", 3 ) )
570 encr = true;
571 if( !strncmp( output.data() + offset, "RSA", 3 ) )
573 sign = true;
574 encr = true;
577 int pos, pos2;
579 // Key Length of secondary key (ignored)
580 pos = offset + 4;
581 while( output[pos] == ' ' )
582 pos++;
583 pos2 = output.indexOf( ' ', pos );
585 // Key ID (ignored as it is anyway equal to the primary key id)
586 pos = pos2 + 1;
587 while( output[pos] == ' ' )
588 pos++;
589 pos2 = output.indexOf( ' ', pos );
591 // Creation Date of secondary key (ignored)
592 pos = pos2 + 1;
593 while( output[pos] == ' ' )
594 pos++;
595 pos2 = output.indexOf( ' ', pos );
597 // User ID or key properties
598 pos = pos2 + 1;
599 while( output[pos] == ' ' )
600 pos++;
601 while( pos < eol )
602 { // loop over User ID resp. key properties
603 if( !strncmp( output.data() + pos, "*** KEY REVOKED ***", 19 ) )
605 sign = false;
606 encr = false;
607 pos += 19;
608 //kDebug( 5326 ) <<"Key was revoked.";
610 else if( !strncmp( output.data() + pos, "*** KEY EXPIRED ***", 19 ) )
612 sign = false;
613 encr = false;
614 pos += 19;
615 //kDebug( 5326 ) <<"Key has expired.";
617 else if( !strncmp( output.data() + pos, "expires ", 8 ) )
619 pos += 18; // skip the expiration date
620 //kDebug( 5326 ) <<"Key expires...";
622 else if( !strncmp( output.data() + pos, "*** DEFAULT SIGNING KEY ***", 27 ) )
624 pos += 27;
625 //kDebug( 5326 ) <<"Key is default signing key.";
627 else
629 QByteArray uid = output.mid( pos, eol-pos );
630 key->addUserID( uid );
631 pos = eol;
632 //kDebug( 5326 ) <<"User ID:"<<uid;
635 // store the global key capabilities
636 canSign = canSign || sign;
637 canEncr = canEncr || encr;
639 else if( !strncmp( output.data() + offset, "Unknown type", 12 ) )
640 { // line contains key data of unknown type (ignored)
641 kDebug( 5326 )<<"Unknown key type.";
643 else if( output[offset] == ' ' )
644 { // line contains additional key data
645 if( key == 0 )
646 break;
647 //kDebug( 5326 )<<"Additional key data:";
649 int pos = offset + 1;
650 while( output[pos] == ' ' )
651 pos++;
653 if( !strncmp( output.data() + pos, "Key fingerprint = ", 18 ) )
654 { // line contains a fingerprint
655 // Example:
656 // Key fingerprint = D0 6C BB 3A F5 16 82 C4 F3 A0 8A B3 7B 16 99 70
658 fpr = true; // we found a fingerprint
660 pos += 18;
661 QByteArray fingerprint = output.mid( pos, eol-pos );
662 // remove white space from the fingerprint
663 for ( int idx = 0 ; (idx = fingerprint.indexOf(' ', idx)) != -1; )
664 fingerprint.replace( idx, 1, "" );
666 //kDebug( 5326 )<<"Fingerprint:"<<fingerprint;
667 assert( subkey != 0 );
668 subkey->setFingerprint( fingerprint );
670 else
671 { // line contains an additional user id
672 // Example:
673 // Test key (2nd user ID) <abc@xyz>
675 //kDebug( 5326 )<<"User ID:"<<output.mid( pos, eol-pos );
676 key->addUserID( output.mid( pos, eol-pos ) );
679 else if( !strncmp( output.data() + offset, "sig", 3 ) )
680 { // line contains signature data (ignored)
681 //kDebug( 5326 )<<"Signature.";
683 else // end of key data
684 break;
686 firstLine = false;
687 offset = eol + 1;
690 if( key != 0 )
692 // set the global key capabilities
693 key->setCanEncrypt( canEncr );
694 key->setCanSign( canSign );
695 key->setCanCertify( canSign );
696 //kDebug( 5326 )<<"Key capabilities:"<<(canEncr?"E":"")<<(canSign?"SC":"");
699 return key;
703 Key*
704 Base6::parseSingleKey( const QByteArray& output, Key* key /* = 0 */ )
706 int offset;
708 // search start of header line
709 if( !strncmp( output.data(), "Type bits", 9 ) )
710 offset = 9;
711 else
713 offset = output.indexOf( "\nType bits" );
714 if( offset == -1 )
715 return 0;
716 else
717 offset += 10;
720 // key data begins in the next line
721 offset = output.indexOf( '\n', offset ) + 1;
722 if( offset == 0 )
723 return 0;
725 key = parseKeyData( output, offset, key );
727 //kDebug( 5326 ) <<"finished parsing keys";
729 return key;
733 KeyList
734 Base6::parseKeyList( const QByteArray& output, bool secretKeys )
736 kDebug( 5326 ) <<"Kpgp::Base6::parseKeyList()";
737 KeyList keys;
738 Key *key = 0;
739 int offset;
741 // search start of header line
742 if( !strncmp( output.data(), "Type bits", 9 ) )
743 offset = 0;
744 else
746 offset = output.indexOf( "\nType bits" ) + 1;
747 if( offset == 0 )
748 return keys;
751 // key data begins in the next line
752 offset = output.indexOf( '\n', offset ) + 1;
753 if( offset == -1 )
754 return keys;
758 key = parseKeyData( output, offset );
759 if( key != 0 )
761 key->setSecret( secretKeys );
762 keys.append( key );
765 while( key != 0 );
767 //kDebug( 5326 ) <<"finished parsing keys";
769 return keys;
773 void
774 Base6::parseTrustDataForKey( Key* key, const QByteArray& str )
776 if( ( key == 0 ) || str.isEmpty() )
777 return;
779 QByteArray keyID = "0x" + key->primaryKeyID();
780 UserIDList userIDs = key->userIDs();
782 // search the start of the trust data
783 int offset = str.indexOf( "\n\n KeyID" );
784 if( offset == -1 )
785 return;
787 offset = str.indexOf( '\n', offset ) + 1;
788 if( offset == 0 )
789 return;
791 bool ultimateTrust = false;
792 if( !strncmp( str.data() + offset+13, "ultimate", 8 ) )
793 ultimateTrust = true;
795 while( true )
796 { // loop over all trust information about this key
798 int eol;
800 // search the end of the current line
801 if( ( eol = str.indexOf( '\n', offset ) ) == -1 )
802 break;
804 if( str[offset+23] != ' ' )
805 { // line contains a validity value for a user ID
807 // determine the validity
808 Validity validity = KPGP_VALIDITY_UNKNOWN;
809 if( !strncmp( str.data() + offset+23, "complete", 8 ) )
810 if( ultimateTrust )
811 validity = KPGP_VALIDITY_ULTIMATE;
812 else
813 validity = KPGP_VALIDITY_FULL;
814 else if( !strncmp( str.data() + offset+23, "marginal", 8 ) )
815 validity = KPGP_VALIDITY_MARGINAL;
816 else if( !strncmp( str.data() + offset+23, "invalid", 7 ) )
817 validity = KPGP_VALIDITY_UNDEFINED;
819 // determine the user ID
820 int pos = offset + 33;
821 QString uid = str.mid( pos, eol-pos );
823 // set the validity of the corresponding user ID
824 for( UserIDList::Iterator it = userIDs.begin(); it != userIDs.end(); ++it )
825 if( (*it)->text() == uid )
827 kDebug( 5326 )<<"Setting the validity of"<<uid<<" to"<<validity;
828 (*it)->setValidity( validity );
829 break;
833 offset = eol + 1;
838 } // namespace Kpgp