00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 #include <config.h>
00021 #endif
00022
00023 #include "kpgpbase.h"
00024 #include "kpgp.h"
00025
00026 #include <string.h>
00027
00028 #include <qdatetime.h>
00029
00030 #include <klocale.h>
00031 #include <kprocess.h>
00032 #include <kdebug.h>
00033
00034 #define PGP2 "pgp"
00035
00036 namespace Kpgp {
00037
00038 Base2::Base2()
00039 : Base()
00040 {
00041 }
00042
00043
00044 Base2::~Base2()
00045 {
00046 }
00047
00048
00049 int
00050 Base2::encrypt( Block& block, const KeyIDList& recipients )
00051 {
00052 return encsign( block, recipients, 0 );
00053 }
00054
00055
00056 int
00057 Base2::clearsign( Block& block, const char *passphrase )
00058 {
00059 return encsign( block, KeyIDList(), passphrase );
00060 }
00061
00062
00063 int
00064 Base2::encsign( Block& block, const KeyIDList& recipients,
00065 const char *passphrase )
00066 {
00067 QCString cmd;
00068 int exitStatus = 0;
00069
00070 if(!recipients.isEmpty() && passphrase != 0)
00071 cmd = PGP2 " +batchmode +language=en +verbose=1 -seat";
00072 else if(!recipients.isEmpty())
00073 cmd = PGP2 " +batchmode +language=en +verbose=1 -eat";
00074 else if(passphrase != 0)
00075 cmd = PGP2 " +batchmode +language=en +verbose=1 -sat";
00076 else
00077 {
00078 kdDebug(5100) << "kpgpbase: Neither recipients nor passphrase specified." << endl;
00079 return OK;
00080 }
00081
00082 if(passphrase != 0)
00083 cmd += addUserId();
00084
00085 if(!recipients.isEmpty()) {
00086 if(Module::getKpgp()->encryptToSelf())
00087 {
00088 cmd += " 0x";
00089 cmd += Module::getKpgp()->user();
00090 }
00091
00092 for( KeyIDList::ConstIterator it = recipients.begin();
00093 it != recipients.end(); ++it ) {
00094 cmd += " 0x";
00095 cmd += (*it);
00096 }
00097 }
00098 cmd += " -f";
00099
00100 clear();
00101 input = block.text();
00102 exitStatus = run(cmd.data(), passphrase);
00103 if( !output.isEmpty() )
00104 block.setProcessedText( output );
00105 block.setError( error );
00106
00107 if(exitStatus != 0)
00108 status = ERROR;
00109
00110 #if 0
00111
00112
00113
00114 if(!recipients.isEmpty())
00115 {
00116 int index = 0;
00117 bool bad = FALSE;
00118 unsigned int num = 0;
00119 QCString badkeys = "";
00120 if (error.find("Cannot find the public key") != -1)
00121 {
00122 index = 0;
00123 num = 0;
00124 while((index = error.find("Cannot find the public key",index))
00125 != -1)
00126 {
00127 bad = TRUE;
00128 index = error.find('\'',index);
00129 int index2 = error.find('\'',index+1);
00130 if (num++)
00131 badkeys += ", ";
00132 badkeys += error.mid(index, index2-index+1);
00133 }
00134 if(bad)
00135 {
00136 badkeys.stripWhiteSpace();
00137 if(num == recipients.count())
00138 errMsg = i18n("Could not find public keys matching the userid(s)\n"
00139 "%1;\n"
00140 "the message is not encrypted.")
00141 .arg( badkeys.data() );
00142 else
00143 errMsg = i18n("Could not find public keys matching the userid(s)\n"
00144 "%1;\n"
00145 "these persons will not be able to read the message.")
00146 .arg( badkeys.data() );
00147 status |= MISSINGKEY;
00148 status |= ERROR;
00149 }
00150 }
00151 if (error.find("skipping userid") != -1)
00152 {
00153 index = 0;
00154 num = 0;
00155 while((index = error.find("skipping userid",index))
00156 != -1)
00157 {
00158 bad = TRUE;
00159 int index2 = error.find('\n',index+16);
00160 if (num++)
00161 badkeys += ", ";
00162 badkeys += error.mid(index+16, index2-index-16);
00163 index = index2;
00164 }
00165 if(bad)
00166 {
00167 badkeys.stripWhiteSpace();
00168 if(num == recipients.count())
00169 errMsg = i18n("Public keys not certified with trusted signature "
00170 "for userid(s)\n"
00171 "%1.\n"
00172 "The message is not encrypted.")
00173 .arg( badkeys.data() );
00174 else
00175 errMsg = i18n("Public keys not certified with trusted signature "
00176 "for userid(s)\n"
00177 "%1;\n"
00178 "these persons will not be able to read the message.")
00179 .arg( badkeys.data() );
00180 status |= BADKEYS;
00181 status |= ERROR;
00182 return status;
00183 }
00184 }
00185 }
00186 #endif
00187 if(passphrase != 0)
00188 {
00189 if(error.find("Pass phrase is good") != -1)
00190 {
00191
00192 status |= SIGNED;
00193 }
00194 if( error.find("Bad pass phrase") != -1)
00195 {
00196 errMsg = i18n("Bad passphrase; could not sign.");
00197 status |= BADPHRASE;
00198 status |= ERR_SIGNING;
00199 status |= ERROR;
00200 }
00201 }
00202 if (error.find("Signature error") != -1)
00203 {
00204 errMsg = i18n("Signing failed: please check your PGP User Identity, "
00205 "the PGP setup, and the key rings.");
00206 status |= NO_SEC_KEY;
00207 status |= ERR_SIGNING;
00208 status |= ERROR;
00209 }
00210 if (error.find("Encryption error") != -1)
00211 {
00212 errMsg = i18n("Encryption failed: please check your PGP setup "
00213 "and the key rings.");
00214 status |= NO_SEC_KEY;
00215 status |= BADKEYS;
00216 status |= ERROR;
00217 }
00218
00219
00220 block.setStatus( status );
00221 return status;
00222 }
00223
00224
00225 int
00226 Base2::decrypt( Block& block, const char *passphrase )
00227 {
00228 int index, index2;
00229 int exitStatus = 0;
00230
00231 clear();
00232 input = block.text();
00233 exitStatus = run(PGP2 " +batchmode +language=en -f", passphrase);
00234 if( !output.isEmpty() )
00235 block.setProcessedText( output );
00236 block.setError( error );
00237
00238
00239
00240 if(error.find("ASCII armor corrupted.") != -1)
00241 {
00242 kdDebug(5100) << "removing ASCII armor header" << endl;
00243 int index1 = input.find("-----BEGIN PGP SIGNED MESSAGE-----");
00244 if(index1 != -1)
00245 index1 = input.find("-----BEGIN PGP SIGNATURE-----", index1);
00246 else
00247 index1 = input.find("-----BEGIN PGP MESSAGE-----");
00248 index1 = input.find('\n', index1);
00249 index2 = input.find("\n\n", index1);
00250 input.remove(index1, index2 - index1);
00251 exitStatus = run(PGP2 " +batchmode +language=en -f", passphrase);
00252 if( !output.isEmpty() )
00253 block.setProcessedText( output );
00254 block.setError( error );
00255 }
00256
00257 if(exitStatus == -1) {
00258 errMsg = i18n("error running PGP");
00259 status = RUN_ERR;
00260 block.setStatus( status );
00261 return status;
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 if(error.find("File is encrypted.") != -1)
00285 {
00286
00287 status |= ENCRYPTED;
00288 if((index = error.find("Key for user ID:")) != -1)
00289 {
00290
00291 index += 17;
00292 index2 = error.find('\n', index);
00293 block.setRequiredUserId( error.mid(index, index2 - index) );
00294
00295
00296 if((passphrase != 0) && (error.find("Bad pass phrase") != -1))
00297 {
00298 errMsg = i18n("Bad passphrase; could not decrypt.");
00299 kdDebug(5100) << "Base: passphrase is bad" << endl;
00300 status |= BADPHRASE;
00301 status |= ERROR;
00302 }
00303 }
00304 else
00305 {
00306
00307 status |= NO_SEC_KEY;
00308 status |= ERROR;
00309 errMsg = i18n("You do not have the secret key needed to decrypt this message.");
00310 kdDebug(5100) << "Base: no secret key for this message" << endl;
00311 }
00312
00313 #if 0
00314
00315
00316 index = error.find("can only be read by:");
00317 if(index != -1)
00318 {
00319 index = error.find('\n',index);
00320 int end = error.find("\n\n",index);
00321
00322 mRecipients.clear();
00323 while( (index2 = error.find('\n',index+1)) <= end )
00324 {
00325 QCString item = error.mid(index+1,index2-index-1);
00326 item.stripWhiteSpace();
00327 mRecipients.append(item);
00328 index = index2;
00329 }
00330 }
00331 #endif
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 if((index = error.find("File has signature")) != -1)
00395 {
00396
00397 index = error.find('\n', index+18) + 1;
00398
00399 status |= SIGNED;
00400
00401 if ((index2 = error.find("Signature made", index)) != -1) {
00402 index2 += 15;
00403 int index3 = error.find("using", index2);
00404 block.setSignatureDate( error.mid(index2, index3-index2-1) );
00405 kdDebug(5100) << "Message was signed on '" << block.signatureDate() << "'\n";
00406 index3 = error.find("key ID ", index3) + 7;
00407 block.setSignatureKeyId( error.mid(index3,8) );
00408 kdDebug(5100) << "Message was signed with key '" << block.signatureKeyId() << "'\n";
00409 }
00410 else {
00411
00412
00413 block.setSignatureDate( "" );
00414 block.setSignatureKeyId( "" );
00415 }
00416
00417 if( ( index2 = error.find("Key matching expected", index) ) != -1)
00418 {
00419 status |= UNKNOWN_SIG;
00420 status |= GOODSIG;
00421 int index3 = error.find("Key ID ", index2) + 7;
00422 block.setSignatureKeyId( error.mid(index3,8) );
00423 block.setSignatureUserId( QString::null );
00424 }
00425 else if( (index2 = error.find("Good signature from", index)) != -1 )
00426 {
00427 status |= GOODSIG;
00428
00429 index = error.find('"',index2+19);
00430 index2 = error.find('"', index+1);
00431 block.setSignatureUserId( error.mid(index+1, index2-index-1) );
00432 }
00433 else if( (index2 = error.find("Bad signature from", index)) != -1 )
00434 {
00435 status |= ERROR;
00436
00437 index = error.find('"',index2+19);
00438 index2 = error.find('"', index+1);
00439 block.setSignatureUserId( error.mid(index+1, index2-index-1) );
00440 }
00441 else if( error.find("Keyring file", index) != -1 )
00442 {
00443
00444 status |= UNKNOWN_SIG;
00445 status |= GOODSIG;
00446
00447 index = error.find('\'', index) + 1;
00448 index2 = error.find('\'', index);
00449 block.setSignatureUserId( i18n("The keyring file %1 does not exist.\n"
00450 "Please check your PGP setup.").arg(error.mid(index, index2-index)) );
00451 }
00452 else
00453 {
00454 status |= ERROR;
00455 block.setSignatureUserId( i18n("Unknown error") );
00456 }
00457 }
00458
00459 block.setStatus( status );
00460 return status;
00461 }
00462
00463
00464 Key*
00465 Base2::readPublicKey( const KeyID& keyID,
00466 const bool readTrust ,
00467 Key* key )
00468 {
00469 int exitStatus = 0;
00470
00471 status = 0;
00472 exitStatus = run( PGP2 " +batchmode +language=en +verbose=0 -kvc -f 0x" +
00473 keyID, 0, true );
00474
00475 if(exitStatus != 0) {
00476 status = ERROR;
00477 return 0;
00478 }
00479
00480 key = parsePublicKeyData( output, key );
00481
00482 if( key == 0 )
00483 {
00484 return 0;
00485 }
00486
00487 if( readTrust )
00488 {
00489 exitStatus = run( PGP2 " +batchmode +language=en +verbose=0 -kc -f",
00490 0, true );
00491
00492 if(exitStatus != 0) {
00493 status = ERROR;
00494 return 0;
00495 }
00496
00497 parseTrustDataForKey( key, error );
00498 }
00499
00500 return key;
00501 }
00502
00503
00504 KeyList
00505 Base2::publicKeys( const QStringList & patterns )
00506 {
00507 return doGetPublicKeys( PGP2 " +batchmode +language=en +verbose=0 -kvc -f",
00508 patterns );
00509 }
00510
00511 KeyList
00512 Base2::doGetPublicKeys( const QCString & cmd, const QStringList & patterns )
00513 {
00514 int exitStatus = 0;
00515 KeyList publicKeys;
00516
00517 status = 0;
00518 if ( patterns.isEmpty() ) {
00519 exitStatus = run( cmd, 0, true );
00520
00521 if ( exitStatus != 0 ) {
00522 status = ERROR;
00523 return KeyList();
00524 }
00525
00526
00527 publicKeys = parseKeyList( output, false );
00528 }
00529 else {
00530 typedef QMap<QCString, Key*> KeyMap;
00531 KeyMap map;
00532
00533 for ( QStringList::ConstIterator it = patterns.begin();
00534 it != patterns.end(); ++it ) {
00535 exitStatus = run( cmd + " " + KProcess::quote( *it ).local8Bit(),
00536 0, true );
00537
00538 if ( exitStatus != 0 ) {
00539 status = ERROR;
00540 return KeyList();
00541 }
00542
00543
00544 publicKeys = parseKeyList( output, false );
00545
00546
00547 while ( !publicKeys.isEmpty() ) {
00548 Key * key = publicKeys.take( 0 );
00549 if ( !map.contains( key->primaryFingerprint() ) )
00550 map.insert( key->primaryFingerprint(), key );
00551 else
00552 delete key;
00553 }
00554 }
00555
00556 for ( KeyMap::ConstIterator it = map.begin(); it != map.end(); ++it ) {
00557 publicKeys.append( it.data() );
00558 }
00559 }
00560
00561
00562 publicKeys.sort();
00563
00564 return publicKeys;
00565 }
00566
00567 KeyList
00568 Base2::secretKeys( const QStringList & patterns )
00569 {
00570 return publicKeys( patterns );
00571 }
00572
00573
00574 int
00575 Base2::signKey(const KeyID& keyID, const char *passphrase)
00576 {
00577 QCString cmd;
00578 int exitStatus = 0;
00579
00580 cmd = PGP2 " +batchmode +language=en -ks -f ";
00581 cmd += addUserId();
00582 cmd += " 0x" + keyID;
00583
00584 status = 0;
00585 exitStatus = run(cmd.data(),passphrase);
00586
00587 if (exitStatus != 0)
00588 status = ERROR;
00589
00590 return status;
00591 }
00592
00593
00594 QCString Base2::getAsciiPublicKey(const KeyID& keyID)
00595 {
00596 int exitStatus = 0;
00597
00598 if (keyID.isEmpty())
00599 return QCString();
00600
00601 status = 0;
00602 exitStatus = run( PGP2 " +batchmode +force +language=en -kxaf 0x" + keyID,
00603 0, true );
00604
00605 if(exitStatus != 0) {
00606 status = ERROR;
00607 return QCString();
00608 }
00609
00610 return output;
00611 }
00612
00613
00614 Key*
00615 Base2::parsePublicKeyData( const QCString& output, Key* key )
00616 {
00617 Subkey *subkey = 0;
00618 int index;
00619
00620
00621 if( !strncmp( output.data(), "pub", 3 ) ||
00622 !strncmp( output.data(), "sec", 3 ) )
00623 index = 0;
00624 else
00625 {
00626
00627
00628
00629
00630
00631 index = output.find( "\npub" );
00632 if( index == -1 )
00633 return 0;
00634 else
00635 index++;
00636 }
00637
00638 while( true )
00639 {
00640 int index2;
00641
00642
00643 if( ( index2 = output.find( '\n', index ) ) == -1 )
00644 break;
00645
00646 if( !strncmp( output.data() + index, "pub", 3 ) ||
00647 !strncmp( output.data() + index, "sec", 3 ) )
00648 {
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658 int pos, pos2;
00659
00660 if( key == 0 )
00661 key = new Key();
00662 else
00663 key->clear();
00664
00665
00666 key->setCanEncrypt( true );
00667 key->setCanSign( true );
00668 key->setCanCertify( true );
00669
00670
00671 subkey = new Subkey( "", false );
00672 key->addSubkey( subkey );
00673
00674 subkey->setCanEncrypt( true );
00675 subkey->setCanSign( true );
00676 subkey->setCanCertify( true );
00677
00678 subkey->setExpirationDate( -1 );
00679
00680
00681 switch( output[index+3] )
00682 {
00683 case ' ':
00684 break;
00685 case '-':
00686 subkey->setDisabled( true );
00687 key->setDisabled( true );
00688 break;
00689 case '>':
00690 subkey->setExpired( true );
00691 key->setExpired( true );
00692 break;
00693 default:
00694 kdDebug(5100) << "Unknown key flag.\n";
00695 }
00696
00697
00698 pos = index + 4;
00699 while( output[pos] == ' ' )
00700 pos++;
00701 pos2 = output.find( '/', pos );
00702 subkey->setKeyLength( output.mid( pos, pos2-pos ).toUInt() );
00703
00704
00705 pos = pos2 + 1;
00706 pos2 = output.find( ' ', pos );
00707 subkey->setKeyID( output.mid( pos, pos2-pos ) );
00708
00709
00710 pos = pos2 + 1;
00711 while( output[pos] == ' ' )
00712 pos++;
00713 pos2 = output.find( ' ', pos );
00714 int year = output.mid( pos, 4 ).toInt();
00715 int month = output.mid( pos+5, 2 ).toInt();
00716 int day = output.mid( pos+8, 2 ).toInt();
00717 QDateTime dt( QDate( year, month, day ), QTime( 00, 00 ) );
00718 QDateTime epoch( QDate( 1970, 01, 01 ), QTime( 00, 00 ) );
00719
00720
00721
00722
00723 subkey->setCreationDate( epoch.secsTo( dt ) );
00724
00725
00726 pos = pos2 + 1;
00727 while( output[pos] == ' ' )
00728 pos++;
00729 QCString uid = output.mid( pos, index2-pos );
00730 if( uid != "*** KEY REVOKED ***" )
00731 key->addUserID( uid );
00732 else
00733 {
00734 subkey->setRevoked( true );
00735 key->setRevoked( true );
00736 }
00737 }
00738 else if( output[index] == ' ' )
00739 {
00740
00741 if( key == 0 )
00742 break;
00743
00744 int pos = index + 1;
00745 while( output[pos] == ' ' )
00746 pos++;
00747
00748 if( !strncmp( output.data() + pos, "Key fingerprint = ", 18 ) )
00749 {
00750
00751
00752
00753 QCString fingerprint = output.mid( pos, index2-pos );
00754
00755 for ( int idx = 0 ; (idx = fingerprint.find(' ', idx)) >= 0 ; )
00756 fingerprint.replace( idx, 1, "" );
00757
00758 subkey->setFingerprint( fingerprint );
00759 }
00760 else if( !strncmp( output.data() + pos, "Expire: ", 8 ) ||
00761 !strncmp( output.data() + pos, "no expire ", 10 ) )
00762 {
00763
00764
00765
00766
00767
00768 if( output[pos] == 'E' )
00769 {
00770
00771 pos += 8;
00772 int year = output.mid( pos, 4 ).toInt();
00773 int month = output.mid( pos+5, 2 ).toInt();
00774 int day = output.mid( pos+8, 2 ).toInt();
00775 QDateTime dt( QDate( year, month, day ), QTime( 00, 00 ) );
00776 QDateTime epoch( QDate( 1970, 01, 01 ), QTime( 00, 00 ) );
00777
00778 subkey->setExpirationDate( epoch.secsTo( dt ) );
00779 pos += 11;
00780 }
00781 else
00782 pos += 10;
00783
00784
00785 if( pos != index2 )
00786 {
00787 if( !strncmp( output.data() + pos, "SIGNature only", 14 ) )
00788 {
00789 subkey->setCanEncrypt( false );
00790 key->setCanEncrypt( false );
00791 }
00792 else if( !strncmp( output.data() + pos, "ENCRyption only", 15 ) )
00793 {
00794 subkey->setCanSign( false );
00795 key->setCanSign( false );
00796 subkey->setCanCertify( false );
00797 key->setCanCertify( false );
00798 }
00799 }
00800 }
00801 else
00802 {
00803
00804
00805
00806 key->addUserID( output.mid( pos, index2-pos ) );
00807 }
00808 }
00809 index = index2 + 1;
00810 }
00811
00812
00813
00814 return key;
00815 }
00816
00817
00818 void
00819 Base2::parseTrustDataForKey( Key* key, const QCString& str )
00820 {
00821 if( ( key == 0 ) || str.isEmpty() )
00822 return;
00823
00824 QCString keyID = key->primaryKeyID();
00825 UserIDList userIDs = key->userIDs();
00826
00827
00828 int index = str.find( '\n' ) + 1;
00829 while( ( index > 0 ) &&
00830 ( strncmp( str.data() + index+2, keyID.data(), 8 ) != 0 ) )
00831 index = str.find( '\n', index ) + 1;
00832
00833 if( index == 0 )
00834 return;
00835
00836 bool ultimateTrust = false;
00837 if( !strncmp( str.data() + index+11, "ultimate", 8 ) )
00838 ultimateTrust = true;
00839
00840 bool firstLine = true;
00841
00842 while( true )
00843 {
00844 int index2;
00845
00846
00847 if( ( index2 = str.find( '\n', index ) ) == -1 )
00848 break;
00849
00850
00851 if( !firstLine && ( str[index+2] != ' ' ) )
00852 break;
00853
00854 if( str[index+21] != ' ' )
00855 {
00856
00857
00858 Validity validity = KPGP_VALIDITY_UNKNOWN;
00859 if( !strncmp( str.data() + index+21, "complete", 8 ) )
00860 if( ultimateTrust )
00861 validity = KPGP_VALIDITY_ULTIMATE;
00862 else
00863 validity = KPGP_VALIDITY_FULL;
00864 else if( !strncmp( str.data() + index+21, "marginal", 8 ) )
00865 validity = KPGP_VALIDITY_MARGINAL;
00866 else if( !strncmp( str.data() + index+21, "never", 8 ) )
00867 validity = KPGP_VALIDITY_NEVER;
00868 else if( !strncmp( str.data() + index+21, "undefined", 8 ) )
00869 validity = KPGP_VALIDITY_UNDEFINED;
00870
00871
00872 int pos = index + 31;
00873 if( str[index+2] == ' ' )
00874 pos++;
00875 QString uid = str.mid( pos, index2-pos );
00876
00877
00878 for( UserIDListIterator it( userIDs ); it.current(); ++it )
00879 if( (*it)->text() == uid )
00880 {
00881 kdDebug(5100)<<"Setting the validity of "<<uid<<" to "<<validity<<endl;
00882 (*it)->setValidity( validity );
00883 break;
00884 }
00885 }
00886
00887 firstLine = false;
00888 index = index2 + 1;
00889 }
00890 }
00891
00892
00893 KeyList
00894 Base2::parseKeyList( const QCString& output, bool secretKeys )
00895 {
00896 kdDebug(5100) << "Kpgp::Base2::parseKeyList()" << endl;
00897 KeyList keys;
00898 Key *key = 0;
00899 Subkey *subkey = 0;
00900 int index;
00901
00902
00903 if( !strncmp( output.data(), "pub", 3 ) ||
00904 !strncmp( output.data(), "sec", 3 ) )
00905 index = 0;
00906 else
00907 {
00908 if( secretKeys )
00909 index = output.find( "\nsec" );
00910 else
00911 index = output.find( "\npub" );
00912 if( index == -1 )
00913 return keys;
00914 else
00915 index++;
00916 }
00917
00918 while( true )
00919 {
00920 int index2;
00921
00922
00923 if( ( index2 = output.find( '\n', index ) ) == -1 )
00924 break;
00925
00926 if( !strncmp( output.data() + index, "pub", 3 ) ||
00927 !strncmp( output.data() + index, "sec", 3 ) )
00928 {
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938 int pos, pos2;
00939
00940 if( key != 0 )
00941 keys.append( key );
00942
00943 key = new Key();
00944 key->setSecret( secretKeys );
00945
00946 key->setCanEncrypt( true );
00947 key->setCanSign( true );
00948 key->setCanCertify( true );
00949
00950 subkey = new Subkey( "", secretKeys );
00951 key->addSubkey( subkey );
00952
00953 subkey->setCanEncrypt( true );
00954 subkey->setCanSign( true );
00955 subkey->setCanCertify( true );
00956
00957 subkey->setExpirationDate( -1 );
00958
00959
00960 switch( output[index+3] )
00961 {
00962 case ' ':
00963 break;
00964 case '-':
00965 subkey->setDisabled( true );
00966 key->setDisabled( true );
00967 break;
00968 case '>':
00969 subkey->setExpired( true );
00970 key->setExpired( true );
00971 break;
00972 default:
00973 kdDebug(5100) << "Unknown key flag.\n";
00974 }
00975
00976
00977 pos = index + 4;
00978 while( output[pos] == ' ' )
00979 pos++;
00980 pos2 = output.find( '/', pos );
00981 subkey->setKeyLength( output.mid( pos, pos2-pos ).toUInt() );
00982
00983
00984 pos = pos2 + 1;
00985 pos2 = output.find( ' ', pos );
00986 subkey->setKeyID( output.mid( pos, pos2-pos ) );
00987
00988
00989 pos = pos2 + 1;
00990 while( output[pos] == ' ' )
00991 pos++;
00992 pos2 = output.find( ' ', pos );
00993 int year = output.mid( pos, 4 ).toInt();
00994 int month = output.mid( pos+5, 2 ).toInt();
00995 int day = output.mid( pos+8, 2 ).toInt();
00996 QDateTime dt( QDate( year, month, day ), QTime( 00, 00 ) );
00997 QDateTime epoch( QDate( 1970, 01, 01 ), QTime( 00, 00 ) );
00998
00999
01000
01001
01002 subkey->setCreationDate( epoch.secsTo( dt ) );
01003
01004
01005 pos = pos2 + 1;
01006 while( output[pos] == ' ' )
01007 pos++;
01008 QCString uid = output.mid( pos, index2-pos );
01009 if( uid != "*** KEY REVOKED ***" )
01010 key->addUserID( uid );
01011 else
01012 {
01013 subkey->setRevoked( true );
01014 key->setRevoked( true );
01015 }
01016 }
01017 else if( output[index] == ' ' )
01018 {
01019
01020 if( key == 0 )
01021 break;
01022
01023 int pos = index + 1;
01024 while( output[pos] == ' ' )
01025 pos++;
01026
01027 if( !strncmp( output.data() + pos, "Key fingerprint = ", 18 ) )
01028 {
01029
01030
01031
01032 int pos2;
01033 pos2 = pos + 18;
01034 QCString fingerprint = output.mid( pos, index2-pos );
01035
01036 for ( int idx = 0 ; (idx = fingerprint.find(' ', idx)) >= 0 ; )
01037 fingerprint.replace( idx, 1, "" );
01038
01039 subkey->setFingerprint( fingerprint );
01040 }
01041 else if( !strncmp( output.data() + pos, "Expire: ", 8 ) ||
01042 !strncmp( output.data() + pos, "no expire ", 10 ) )
01043 {
01044
01045
01046
01047
01048
01049 if( output[pos] == 'E' )
01050 {
01051
01052 pos += 8;
01053 int year = output.mid( pos, 4 ).toInt();
01054 int month = output.mid( pos+5, 2 ).toInt();
01055 int day = output.mid( pos+8, 2 ).toInt();
01056 QDateTime dt( QDate( year, month, day ), QTime( 00, 00 ) );
01057 QDateTime epoch( QDate( 1970, 01, 01 ), QTime( 00, 00 ) );
01058
01059 subkey->setExpirationDate( epoch.secsTo( dt ) );
01060 pos += 11;
01061 }
01062 else
01063 pos += 10;
01064
01065
01066 if( pos != index2 )
01067 {
01068 if( !strncmp( output.data() + pos, "SIGNature only", 14 ) )
01069 {
01070 subkey->setCanEncrypt( false );
01071 key->setCanEncrypt( false );
01072 }
01073 else if( !strncmp( output.data() + pos, "ENCRyption only", 15 ) )
01074 {
01075 subkey->setCanSign( false );
01076 key->setCanSign( false );
01077 subkey->setCanCertify( false );
01078 key->setCanCertify( false );
01079 }
01080 }
01081 }
01082 else
01083 {
01084
01085
01086
01087 key->addUserID( output.mid( pos, index2-pos ) );
01088 }
01089 }
01090
01091 index = index2 + 1;
01092 }
01093
01094 if (key != 0)
01095 keys.append( key );
01096
01097
01098
01099 return keys;
01100 }
01101
01102
01103 }