Framework for looking up contacts directly in nepomuk in addition to going through...
[kdepim.git] / libkpgp / kpgpbase6.cpp
blob6db78507c4026eb2ce4e6a6be95bdcf3fa0300dc
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>
26 #include <klocale.h>
27 #include <kdebug.h>
29 #define PGP6 "pgp"
31 namespace Kpgp {
33 Base6::Base6()
34 : Base2()
39 Base6::~Base6()
44 int
45 Base6::decrypt( Block& block, const char *passphrase )
47 int index, index2;
49 clear();
50 input = block.text();
51 int exitStatus = run( PGP6 " +batchmode +language=C -f", passphrase);
52 if( !output.isEmpty() )
53 block.setProcessedText( output );
54 block.setError( error );
56 if(exitStatus == -1) {
57 errMsg = i18n("error running PGP");
58 status = ERROR;
59 block.setStatus( status );
60 return status;
63 // encrypted message
64 if( error.contains("File is encrypted.") )
66 //kDebug( 5326 ) <<"kpgpbase: message is encrypted";
67 status |= ENCRYPTED;
68 if((index = error.indexOf("Key for user ID")) != -1 )
70 // Find out the key for which the phrase is needed
71 index = error.indexOf(':', index) + 2;
72 index2 = error.indexOf('\n', index);
73 block.setRequiredUserId( error.mid(index, index2 - index) );
74 //kDebug( 5326 ) <<"Base: key needed is \"" << block.requiredUserId() <<"\"!";
76 // Test output length to find out, if the passphrase is
77 // bad. If someone knows a better way, please fix this.
78 /// ### This could be done by forcing PGP6 to be more verbose
79 /// by adding an additional '+verbose=2' to the command line
80 if (!passphrase || !output.length())
82 errMsg = i18n("Bad passphrase; could not decrypt.");
83 //kDebug( 5326 ) <<"Base: passphrase is bad";
84 status |= BADPHRASE;
85 status |= ERROR;
88 else if( error.contains("You do not have the secret key needed to decrypt this file.") )
90 errMsg = i18n("You do not have the secret key for this message.");
91 //kDebug( 5326 ) <<"Base: no secret key for this message";
92 status |= NO_SEC_KEY;
93 status |= ERROR;
97 // signed message
99 // Examples (made with PGP 6.5.8)
100 /* Example no. 1 (signed with unknown key):
101 * File is signed. signature not checked.
102 * Signature made 2001/11/25 11:55 GMT
103 * key does not meet validity threshold.
105 * WARNING: Because this public key is not certified with a trusted
106 * signature, it is not known with high confidence that this public key
107 * actually belongs to: "(KeyID: 0x475027BD)".
109 /* Example no. 2 (signed with untrusted key):
110 * File is signed. Good signature from user "Joe User <joe@foo.bar>".
111 * Signature made 2001/12/05 13:09 GMT
113 * WARNING: Because this public key is not certified with a trusted
114 * signature, it is not known with high confidence that this public key
115 * actually belongs to: "Joe User <joe@foo.bar>".
117 /* Example no. 3 (signed with trusted key):
118 * File is signed. Good signature from user "Joe User <joe@foo.bar>".
119 * Signature made 2001/12/05 13:09 GMT
121 if(((index = error.indexOf("File is signed.")) != -1 )
122 || (error.contains("Good signature") ))
124 //kDebug( 5326 ) <<"Base: message is signed";
125 status |= SIGNED;
126 // determine the signature date
127 if( ( index2 = error.indexOf( "Signature made", index ) ) != -1 )
129 index2 += 15;
130 int eol = error.indexOf( '\n', index2 );
131 block.setSignatureDate( error.mid( index2, eol-index2 ) );
132 kDebug( 5326 ) <<"Message was signed on '" << block.signatureDate() <<"'";
134 else
135 block.setSignatureDate( QByteArray() );
136 // determine signature status and signature key
137 if( error.contains("signature not checked") )
139 index = error.indexOf("KeyID:",index);
140 block.setSignatureKeyId( error.mid(index+9,8) );
141 block.setSignatureUserId( QString() );
142 status |= UNKNOWN_SIG;
143 status |= GOODSIG;
145 else if((index = error.indexOf("Good signature")) != -1 )
147 status |= GOODSIG;
148 // get signer
149 index = error.indexOf('"',index)+1;
150 index2 = error.indexOf('"', index);
151 block.setSignatureUserId( error.mid(index, index2-index) );
153 // get key ID of signer
154 index = error.indexOf("KeyID:",index2);
155 if (index == -1)
156 block.setSignatureKeyId( QByteArray() );
157 else
158 block.setSignatureKeyId( error.mid(index+9,8) );
160 else if( error.contains("Can't find the right public key") )
162 // #### fix this hack
163 // #### This doesn't happen with PGP 6.5.8 because it seems to
164 // #### automatically create an empty pubring if it doesn't exist.
165 status |= UNKNOWN_SIG;
166 status |= GOODSIG; // this is a hack...
167 block.setSignatureUserId( i18n("??? (file ~/.pgp/pubring.pkr not found)") );
168 block.setSignatureKeyId( "???" );
170 else
172 status |= ERROR;
173 block.setSignatureUserId( QString() );
174 block.setSignatureKeyId( QByteArray() );
177 //kDebug( 5326 ) <<"status =" << status;
178 block.setStatus( status );
179 return status;
183 Key*
184 Base6::readPublicKey( const KeyID& keyID,
185 const bool readTrust /* = false */,
186 Key* key /* = 0 */ )
188 status = 0;
189 int exitStatus = run( PGP6 " +batchmode -compatible +verbose=0 +language=C -kvvc "
190 "0x" + keyID, 0, true );
192 if(exitStatus != 0) {
193 status = ERROR;
194 return 0;
197 key = parseSingleKey( output, key );
199 if( key == 0 )
201 return 0;
204 if( readTrust )
206 exitStatus = run( PGP6 " +batchmode -compatible +verbose=0 +language=C -kc "
207 "0x" + keyID, 0, true );
209 if(exitStatus != 0) {
210 status = ERROR;
211 return 0;
214 parseTrustDataForKey( key, output );
217 return key;
221 KeyList
222 Base6::publicKeys( const QStringList & patterns )
224 return doGetPublicKeys( PGP6 " +batchmode -compatible +verbose=0 "
225 "+language=C -kvvc", patterns );
230 QStrList
231 Base6::pubKeys()
233 int index, index2;
234 int exitStatus = 0;
235 int compatibleMode = 1;
237 status = 0;
238 exitStatus = run("pgp +batchmode +language=C -kv -f");
240 if(exitStatus != 0) {
241 status = ERROR;
242 return 0;
245 //truncate trailing "\n"
246 if (error.length() > 1) error.truncate(error.length()-1);
248 QStrList publicKeys;
249 index = error.indexOf("bits/keyID",1); // skip first to "\n"
250 if (index ==-1)
252 index = error.indexOf("Type bits",1); // skip first to "\n"
253 if (index == -1)
254 return 0;
255 else
256 compatibleMode = 0;
259 while( (index = error.indexOf("\n",index)) != -1 )
261 //parse line
262 QCString line;
263 if( (index2 = error.indexOf("\n",index+1)) != -1 )
264 // skip last line
266 int index3;
267 if (compatibleMode)
269 int index_pub = error.indexOf("pub ",index);
270 int index_sec = error.indexOf("sec ",index);
271 if (index_pub < 0)
272 index3 = index_sec;
273 else if (index_sec < 0)
274 index3 = index_pub;
275 else
276 index3 = (index_pub < index_sec ? index_pub : index_sec);
278 else
280 int index_rsa = error.indexOf("RSA ",index);
281 int index_dss = error.indexOf("DSS ",index);
282 if (index_rsa < 0)
283 index3 = index_dss;
284 else if (index_dss < 0)
285 index3 = index_rsa;
286 else
287 index3 = (index_rsa < index_dss ? index_rsa : index_dss);
290 if( (index3 >index2) || (index3 == -1) )
292 // second address for the same key
293 line = error.mid(index+1,index2-index-1);
294 line = line.trimmed();
295 } else {
296 // line with new key
297 int index4 = error.indexOf(QRegExp("/\\d{2}/\\d{2} "), index);
298 line = error.mid(index4+7,index2-index4-7);
300 //kDebug( 5326 ) <<"Base: found key for" << (const char *)line;
302 // don't add PGP's comments to the key list
303 if (strncmp(line.data(),"*** KEY EXPIRED ***",19) &&
304 !line.contains(QRegExp("^expires \\d{4}/\\d{2}/\\d{2}")) &&
305 strncmp(line.data(),"*** DEFAULT SIGNING KEY ***",27)) {
306 publicKeys.append(line);
309 else
310 break;
311 index = index2;
314 // Also look for pgp key groups
315 exitStatus = run("pgp +batchmode +language=C -gv -f");
317 if(exitStatus != 0) {
318 status = ERROR;
319 return 0;
322 index = 0;
323 while ( (index = error.indexOf("\n >", index)) != -1 ) {
324 QCString line;
325 index += 4;
326 index2 = error.indexOf(" \"", index);
327 line = error.mid(index, index2-index+1).trimmed();
329 //kDebug( 5326 ) <<"Base6: found key group for" << line;
330 publicKeys.append(line);
333 return publicKeys;
338 KeyList
339 Base6::secretKeys( const QStringList & patterns )
341 return publicKeys( patterns );
346 Base6::isVersion6()
348 int exitStatus = run( PGP6, 0, true );
350 if(exitStatus == -1) {
351 errMsg = i18n("error running PGP");
352 status = ERROR;
353 return 0;
356 if( error.contains("Version 6") )
358 //kDebug( 5326 ) <<"kpgpbase: pgp version 6.x detected";
359 return 1;
362 //kDebug( 5326 ) <<"kpgpbase: not pgp version 6.x";
363 return 0;
367 Key*
368 Base6::parseKeyData( const QByteArray& output, int& offset, Key* key /* = 0 */ )
369 // This function parses the data for a single key which is output by PGP 6
370 // with the following command line arguments:
371 // +batchmode -compatible +verbose=0 +language=C -kvvc
372 // It expects the key data to start at offset and returns the start of
373 // the next key's data in offset.
375 if( ( strncmp( output.data() + offset, "DSS", 3 ) != 0 ) &&
376 ( strncmp( output.data() + offset, "RSA", 3 ) != 0 ) )
378 kDebug( 5326 ) <<"Unknown key type or corrupt key data.";
379 return 0;
382 Subkey *subkey = 0;
383 bool firstLine = true;
384 bool canSign = false;
385 bool canEncr = false;
386 bool fpr = false;
388 while( true )
390 int eol;
392 // search the end of the current line
393 if( ( eol = output.indexOf( '\n', offset ) ) == -1 )
394 break;
396 //kDebug( 5326 ) <<"Parsing:" << output.mid(offset, eol-offset);
398 if( firstLine && ( !strncmp( output.data() + offset, "DSS", 3 ) ||
399 !strncmp( output.data() + offset, "RSA", 3 ) ) )
400 { // line contains primary key data
401 // Example 1:
402 // RSA 1024 0xE2D074D3 2001/09/09 Test Key <testkey@xyz>
403 // Example 2 (disabled key):
404 // RSA@ 1024 0x8CCB2C1B 2001/11/04 Disabled Test Key <disabled@xyz>
405 // Example 3 (expired key):
406 // RSA 1024 0x7B94827D 2001/09/09 *** KEY EXPIRED ***
407 // Example 4 (revoked key):
408 // RSA 1024 0x956721F9 2001/09/09 *** KEY REVOKED ***
409 // Example 5 (default signing key):
410 // RSA 1024 0x12345678 2001/09/09 *** DEFAULT SIGNING KEY ***
411 // Example 6 (expiring key):
412 // RSA 2048 0xC11DB2E5 2000/02/24 expires 2001/12/31
413 // Example 7 (complex example):
414 // DSS 1024 0x80E104A7 2000/06/05 expires 2002/05/31
415 // DSS 1024 0x80E104A7 2001/06/27 *** KEY REVOKED ***expires 2002/06/27
416 // DH 1024 0x80E104A7 2000/06/05 *** KEY REVOKED ****** KEY EXPIRED ***
417 //kDebug( 5326 )<<"Primary key data:";
418 bool sign = false;
419 bool encr = false;
421 // set default key capabilities
422 if( !strncmp( output.data() + offset, "DSS", 3 ) )
423 sign = true;
424 if( !strncmp( output.data() + offset, "RSA", 3 ) )
426 sign = true;
427 encr = true;
430 int pos, pos2;
432 if( key == 0 )
433 key = new Key();
434 else
435 key->clear();
437 subkey = new Subkey( "", false );
438 key->addSubkey( subkey );
439 // expiration date defaults to never
440 subkey->setExpirationDate( -1 );
442 // Key Flags
443 switch( output[offset+3] )
445 case ' ': // nothing special
446 break;
447 case '@': // disabled key
448 subkey->setDisabled( true );
449 key->setDisabled( true );
450 break;
451 default:
452 kDebug( 5326 ) <<"Unknown key flag.";
455 // Key Length
456 pos = offset + 4;
457 while( output[pos] == ' ' )
458 pos++;
459 pos2 = output.indexOf( ' ', pos );
460 subkey->setKeyLength( output.mid( pos, pos2-pos ).toUInt() );
461 //kDebug( 5326 ) <<"Key Length:"<<subkey->keyLength();
463 // Key ID
464 pos = pos2 + 1;
465 while( output[pos] == ' ' )
466 pos++;
467 pos += 2; // skip the '0x'
468 pos2 = output.indexOf( ' ', pos );
469 subkey->setKeyID( output.mid( pos, pos2-pos ) );
470 //kDebug( 5326 ) <<"Key ID:"<<subkey->keyID();
472 // Creation Date
473 pos = pos2 + 1;
474 while( output[pos] == ' ' )
475 pos++;
476 pos2 = output.indexOf( ' ', pos );
477 int year = output.mid( pos, 4 ).toInt();
478 int month = output.mid( pos+5, 2 ).toInt();
479 int day = output.mid( pos+8, 2 ).toInt();
480 QDateTime dt( QDate( year, month, day ), QTime( 00, 00 ) );
481 QDateTime epoch( QDate( 1970, 01, 01 ), QTime( 00, 00 ) );
482 // The calculated creation date isn't exactly correct because QDateTime
483 // doesn't know anything about timezones and always assumes local time
484 // although epoch is of course UTC. But as PGP 6 anyway doesn't print
485 // the time this doesn't matter too much.
486 subkey->setCreationDate( epoch.secsTo( dt ) );
488 // User ID or key properties
489 pos = pos2 + 1;
490 while( output[pos] == ' ' )
491 pos++;
492 while( pos < eol )
493 { // loop over User ID resp. key properties
494 if( !strncmp( output.data() + pos, "*** KEY REVOKED ***", 19 ) )
496 sign = false;
497 encr = false;
498 subkey->setRevoked( true );
499 key->setRevoked( true );
500 pos += 19;
501 //kDebug( 5326 ) <<"Key was revoked.";
503 else if( !strncmp( output.data() + pos, "*** KEY EXPIRED ***", 19 ) )
505 sign = false;
506 encr = false;
507 subkey->setExpired( true );
508 key->setExpired( true );
509 pos += 19;
510 //kDebug( 5326 ) <<"Key has expired.";
512 else if( !strncmp( output.data() + pos, "expires ", 8 ) )
514 pos += 8;
515 int year = output.mid( pos, 4 ).toInt();
516 int month = output.mid( pos+5, 2 ).toInt();
517 int day = output.mid( pos+8, 2 ).toInt();
518 QDateTime dt( QDate( year, month, day ), QTime( 00, 00 ) );
519 // Here the same comments as for the creation date are valid.
520 subkey->setExpirationDate( epoch.secsTo( dt ) );
521 pos += 10;
522 //kDebug( 5326 ) <<"Key expires...";
524 else if( !strncmp( output.data() + pos, "*** DEFAULT SIGNING KEY ***", 27 ) )
526 pos += 27;
527 //kDebug( 5326 ) <<"Key is default signing key.";
529 else
531 QByteArray uid = output.mid( pos, eol-pos );
532 key->addUserID( uid );
533 pos = eol;
534 //kDebug( 5326 ) <<"User ID:"<<uid;
537 // set key capabilities of the primary subkey
538 subkey->setCanEncrypt( encr );
539 subkey->setCanSign( sign );
540 subkey->setCanCertify( sign );
541 // remember the global key capabilities
542 canSign = sign;
543 canEncr = encr;
545 else if( !strncmp( output.data() + offset, "DSS", 3 ) ||
546 !strncmp( output.data() + offset, " DH", 3 ) ||
547 !strncmp( output.data() + offset, "RSA", 3 ) )
548 { // line contains secondary key data (or data for the next key)
549 if( fpr )
550 break; // here begins the next key's data
551 //kDebug( 5326 )<<"Secondary key data:";
553 if( key == 0 )
554 break;
556 bool sign = false;
557 bool encr = false;
559 // set default key capabilities
560 if( !strncmp( output.data() + offset, "DSS", 3 ) )
561 sign = true;
562 if( !strncmp( output.data() + offset, " DH", 3 ) )
563 encr = true;
564 if( !strncmp( output.data() + offset, "RSA", 3 ) )
566 sign = true;
567 encr = true;
570 int pos, pos2;
572 // Key Length of secondary key (ignored)
573 pos = offset + 4;
574 while( output[pos] == ' ' )
575 pos++;
576 pos2 = output.indexOf( ' ', pos );
578 // Key ID (ignored as it is anyway equal to the primary key id)
579 pos = pos2 + 1;
580 while( output[pos] == ' ' )
581 pos++;
582 pos2 = output.indexOf( ' ', pos );
584 // Creation Date of secondary key (ignored)
585 pos = pos2 + 1;
586 while( output[pos] == ' ' )
587 pos++;
588 pos2 = output.indexOf( ' ', pos );
590 // User ID or key properties
591 pos = pos2 + 1;
592 while( output[pos] == ' ' )
593 pos++;
594 while( pos < eol )
595 { // loop over User ID resp. key properties
596 if( !strncmp( output.data() + pos, "*** KEY REVOKED ***", 19 ) )
598 sign = false;
599 encr = false;
600 pos += 19;
601 //kDebug( 5326 ) <<"Key was revoked.";
603 else if( !strncmp( output.data() + pos, "*** KEY EXPIRED ***", 19 ) )
605 sign = false;
606 encr = false;
607 pos += 19;
608 //kDebug( 5326 ) <<"Key has expired.";
610 else if( !strncmp( output.data() + pos, "expires ", 8 ) )
612 pos += 18; // skip the expiration date
613 //kDebug( 5326 ) <<"Key expires...";
615 else if( !strncmp( output.data() + pos, "*** DEFAULT SIGNING KEY ***", 27 ) )
617 pos += 27;
618 //kDebug( 5326 ) <<"Key is default signing key.";
620 else
622 QByteArray uid = output.mid( pos, eol-pos );
623 key->addUserID( uid );
624 pos = eol;
625 //kDebug( 5326 ) <<"User ID:"<<uid;
628 // store the global key capabilities
629 canSign = canSign || sign;
630 canEncr = canEncr || encr;
632 else if( !strncmp( output.data() + offset, "Unknown type", 12 ) )
633 { // line contains key data of unknown type (ignored)
634 kDebug( 5326 )<<"Unknown key type.";
636 else if( output[offset] == ' ' )
637 { // line contains additional key data
638 if( key == 0 )
639 break;
640 //kDebug( 5326 )<<"Additional key data:";
642 int pos = offset + 1;
643 while( output[pos] == ' ' )
644 pos++;
646 if( !strncmp( output.data() + pos, "Key fingerprint = ", 18 ) )
647 { // line contains a fingerprint
648 // Example:
649 // Key fingerprint = D0 6C BB 3A F5 16 82 C4 F3 A0 8A B3 7B 16 99 70
651 fpr = true; // we found a fingerprint
653 pos += 18;
654 QByteArray fingerprint = output.mid( pos, eol-pos );
655 // remove white space from the fingerprint
656 for ( int idx = 0 ; (idx = fingerprint.indexOf(' ', idx)) != -1; )
657 fingerprint.replace( idx, 1, "" );
659 //kDebug( 5326 )<<"Fingerprint:"<<fingerprint;
660 assert( subkey != 0 );
661 subkey->setFingerprint( fingerprint );
663 else
664 { // line contains an additional user id
665 // Example:
666 // Test key (2nd user ID) <abc@xyz>
668 //kDebug( 5326 )<<"User ID:"<<output.mid( pos, eol-pos );
669 key->addUserID( output.mid( pos, eol-pos ) );
672 else if( !strncmp( output.data() + offset, "sig", 3 ) )
673 { // line contains signature data (ignored)
674 //kDebug( 5326 )<<"Signature.";
676 else // end of key data
677 break;
679 firstLine = false;
680 offset = eol + 1;
683 if( key != 0 )
685 // set the global key capabilities
686 key->setCanEncrypt( canEncr );
687 key->setCanSign( canSign );
688 key->setCanCertify( canSign );
689 //kDebug( 5326 )<<"Key capabilities:"<<(canEncr?"E":"")<<(canSign?"SC":"");
692 return key;
696 Key*
697 Base6::parseSingleKey( const QByteArray& output, Key* key /* = 0 */ )
699 int offset;
701 // search start of header line
702 if( !strncmp( output.data(), "Type bits", 9 ) )
703 offset = 9;
704 else
706 offset = output.indexOf( "\nType bits" );
707 if( offset == -1 )
708 return 0;
709 else
710 offset += 10;
713 // key data begins in the next line
714 offset = output.indexOf( '\n', offset ) + 1;
715 if( offset == 0 )
716 return 0;
718 key = parseKeyData( output, offset, key );
720 //kDebug( 5326 ) <<"finished parsing keys";
722 return key;
726 KeyList
727 Base6::parseKeyList( const QByteArray& output, bool secretKeys )
729 kDebug( 5326 ) <<"Kpgp::Base6::parseKeyList()";
730 KeyList keys;
731 Key *key = 0;
732 int offset;
734 // search start of header line
735 if( !strncmp( output.data(), "Type bits", 9 ) )
736 offset = 0;
737 else
739 offset = output.indexOf( "\nType bits" ) + 1;
740 if( offset == 0 )
741 return keys;
744 // key data begins in the next line
745 offset = output.indexOf( '\n', offset ) + 1;
746 if( offset == -1 )
747 return keys;
751 key = parseKeyData( output, offset );
752 if( key != 0 )
754 key->setSecret( secretKeys );
755 keys.append( key );
758 while( key != 0 );
760 //kDebug( 5326 ) <<"finished parsing keys";
762 return keys;
766 void
767 Base6::parseTrustDataForKey( Key* key, const QByteArray& str )
769 if( ( key == 0 ) || str.isEmpty() )
770 return;
772 QByteArray keyID = "0x" + key->primaryKeyID();
773 UserIDList userIDs = key->userIDs();
775 // search the start of the trust data
776 int offset = str.indexOf( "\n\n KeyID" );
777 if( offset == -1 )
778 return;
780 offset = str.indexOf( '\n', offset ) + 1;
781 if( offset == 0 )
782 return;
784 bool ultimateTrust = false;
785 if( !strncmp( str.data() + offset+13, "ultimate", 8 ) )
786 ultimateTrust = true;
788 while( true )
789 { // loop over all trust information about this key
791 int eol;
793 // search the end of the current line
794 if( ( eol = str.indexOf( '\n', offset ) ) == -1 )
795 break;
797 if( str[offset+23] != ' ' )
798 { // line contains a validity value for a user ID
800 // determine the validity
801 Validity validity = KPGP_VALIDITY_UNKNOWN;
802 if( !strncmp( str.data() + offset+23, "complete", 8 ) )
803 if( ultimateTrust )
804 validity = KPGP_VALIDITY_ULTIMATE;
805 else
806 validity = KPGP_VALIDITY_FULL;
807 else if( !strncmp( str.data() + offset+23, "marginal", 8 ) )
808 validity = KPGP_VALIDITY_MARGINAL;
809 else if( !strncmp( str.data() + offset+23, "invalid", 7 ) )
810 validity = KPGP_VALIDITY_UNDEFINED;
812 // determine the user ID
813 int pos = offset + 33;
814 QString uid = str.mid( pos, eol-pos );
816 // set the validity of the corresponding user ID
817 for( UserIDList::Iterator it = userIDs.begin(); it != userIDs.end(); ++it )
818 if( (*it)->text() == uid )
820 kDebug( 5326 )<<"Setting the validity of"<<uid<<" to"<<validity;
821 (*it)->setValidity( validity );
822 break;
826 offset = eol + 1;
831 } // namespace Kpgp