kpgpbase5.cpp
00001 /* 00002 kpgpbase5.cpp 00003 00004 Copyright (C) 2001,2002 the KPGP authors 00005 See file AUTHORS.kpgp for details 00006 00007 This file is part of KPGP, the KDE PGP/GnuPG support library. 00008 00009 KPGP is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 2 of the License, or 00012 (at your option) any later version. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software Foundation, 00016 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 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> /* strncmp */ 00027 #include <assert.h> 00028 00029 #include <tqregexp.h> 00030 #include <tqdatetime.h> 00031 00032 #include <tdelocale.h> 00033 #include <kprocess.h> 00034 #include <kdebug.h> 00035 00036 00037 namespace Kpgp { 00038 00039 Base5::Base5() 00040 : Base() 00041 { 00042 } 00043 00044 00045 Base5::~Base5() 00046 { 00047 } 00048 00049 00050 int 00051 Base5::encrypt( Block& block, const KeyIDList& recipients ) 00052 { 00053 return encsign( block, recipients, 0 ); 00054 } 00055 00056 00057 int 00058 Base5::clearsign( Block& block, const char *passphrase ) 00059 { 00060 return encsign( block, KeyIDList(), passphrase ); 00061 } 00062 00063 00064 int 00065 Base5::encsign( Block& block, const KeyIDList& recipients, 00066 const char *passphrase ) 00067 { 00068 TQCString cmd; 00069 int exitStatus = 0; 00070 int index; 00071 // used to work around a bug in pgp5. pgp5 treats files 00072 // with non ascii chars (umlauts, etc...) as binary files, but 00073 // we want a clear signature 00074 bool signonly = false; 00075 00076 if(!recipients.isEmpty() && passphrase != 0) 00077 cmd = "pgpe +batchmode -afts "; 00078 else if(!recipients.isEmpty()) 00079 cmd = "pgpe +batchmode -aft "; 00080 else if(passphrase != 0) 00081 { 00082 cmd = "pgps +batchmode -abft "; 00083 signonly = true; 00084 } 00085 else 00086 { 00087 errMsg = i18n("Neither recipients nor passphrase specified."); 00088 return OK; 00089 } 00090 00091 if(passphrase != 0) 00092 cmd += addUserId(); 00093 00094 if(!recipients.isEmpty()) 00095 { 00096 if(Module::getKpgp()->encryptToSelf()) 00097 { 00098 cmd += " -r 0x"; 00099 cmd += Module::getKpgp()->user(); 00100 } 00101 00102 for( KeyIDList::ConstIterator it = recipients.begin(); 00103 it != recipients.end(); ++it ) { 00104 cmd += " -r 0x"; 00105 cmd += (*it); 00106 } 00107 } 00108 00109 clear(); 00110 input = block.text(); 00111 00112 if (signonly) 00113 { 00114 input.append("\n"); 00115 input.replace(TQRegExp("[ \t]+\n"), "\n"); //strip trailing whitespace 00116 } 00117 //We have to do this otherwise it's all in vain 00118 00119 exitStatus = run(cmd.data(), passphrase); 00120 block.setError( error ); 00121 00122 if(exitStatus != 0) 00123 status = ERROR; 00124 00125 // now parse the returned info 00126 if(error.find("Cannot unlock private key") != -1) 00127 { 00128 errMsg = i18n("The passphrase you entered is invalid."); 00129 status |= ERROR; 00130 status |= BADPHRASE; 00131 } 00132 //if(!ignoreUntrusted) 00133 //{ 00134 TQCString aStr; 00135 index = -1; 00136 while((index = error.find("WARNING: The above key",index+1)) != -1) 00137 { 00138 int index2 = error.find("But you previously",index); 00139 int index3 = error.find("WARNING: The above key",index+1); 00140 if(index2 == -1 || (index2 > index3 && index3 != -1)) 00141 { 00142 // the key wasn't valid, no encryption to this person 00143 // extract the person 00144 index2 = error.find('\n',index); 00145 index3 = error.find('\n',index2+1); 00146 aStr += error.mid(index2+1, index3-index2-1); 00147 aStr += ", "; 00148 } 00149 } 00150 if(!aStr.isEmpty()) 00151 { 00152 aStr.truncate(aStr.length()-2); 00153 if(error.find("No valid keys found") != -1) 00154 errMsg = i18n("The key(s) you want to encrypt your message " 00155 "to are not trusted. No encryption done."); 00156 else 00157 errMsg = i18n("The following key(s) are not trusted:\n%1\n" 00158 "Their owner(s) will not be able to decrypt the message.") 00159 .arg(TQString(aStr)); 00160 status |= ERROR; 00161 status |= BADKEYS; 00162 } 00163 //} 00164 if((index = error.find("No encryption keys found for")) != -1) 00165 { 00166 index = error.find(':',index); 00167 int index2 = error.find('\n',index); 00168 00169 errMsg = i18n("Missing encryption key(s) for:\n%1") 00170 .arg(TQString(error.mid(index,index2-index))); 00171 // errMsg = TQString("Missing encryption key(s) for: %1") 00172 // .arg(error.mid(index,index2-index)); 00173 status |= ERROR; 00174 status |= MISSINGKEY; 00175 } 00176 00177 if(signonly) { 00178 // dash-escape the input 00179 if (input[0] == '-') 00180 input = "- " + input; 00181 for ( int idx = 0 ; (idx = input.find("\n-", idx)) >= 0 ; idx += 4 ) 00182 input.replace(idx, 2, "\n- -"); 00183 00184 output = "-----BEGIN PGP SIGNED MESSAGE-----\n\n" + input + "\n" + output; 00185 } 00186 00187 block.setProcessedText( output ); 00188 block.setStatus( status ); 00189 return status; 00190 } 00191 00192 00193 int 00194 Base5::decrypt( Block& block, const char *passphrase ) 00195 { 00196 int exitStatus = 0; 00197 00198 clear(); 00199 input = block.text(); 00200 exitStatus = run("pgpv -f +batchmode=1", passphrase); 00201 if( !output.isEmpty() ) 00202 block.setProcessedText( output ); 00203 block.setError( error ); 00204 00205 if(exitStatus == -1) { 00206 errMsg = i18n("Error running PGP"); 00207 status = RUN_ERR; 00208 block.setStatus( status ); 00209 return status; 00210 } 00211 00212 // lets parse the returned information. 00213 int index; 00214 00215 index = error.find("Cannot decrypt message"); 00216 if(index != -1) 00217 { 00218 //kdDebug(5100) << "message is encrypted" << endl; 00219 status |= ENCRYPTED; 00220 00221 // ok. we have an encrypted message. Is the passphrase bad, 00222 // or do we not have the secret key? 00223 if(error.find("Need a pass phrase") != -1) 00224 { 00225 if(passphrase != 0) 00226 { 00227 errMsg = i18n("Bad passphrase; could not decrypt."); 00228 kdDebug(5100) << "Base: passphrase is bad" << endl; 00229 status |= BADPHRASE; 00230 status |= ERROR; 00231 } 00232 } 00233 else 00234 { 00235 // we don't have the secret key 00236 status |= NO_SEC_KEY; 00237 status |= ERROR; 00238 errMsg = i18n("You do not have the secret key needed to decrypt this message."); 00239 kdDebug(5100) << "Base: no secret key for this message" << endl; 00240 } 00241 // check for persons 00242 #if 0 00243 // ##### FIXME: This information is anyway currently not used 00244 // I'll change it to always determine the recipients. 00245 index = error.find("can only be decrypted by:"); 00246 if(index != -1) 00247 { 00248 index = error.find('\n',index); 00249 int end = error.find("\n\n",index); 00250 00251 mRecipients.clear(); 00252 int index2; 00253 while( (index2 = error.find('\n',index+1)) <= end ) 00254 { 00255 TQCString item = error.mid(index+1,index2-index-1); 00256 item.stripWhiteSpace(); 00257 mRecipients.append(item); 00258 index = index2; 00259 } 00260 } 00261 #endif 00262 } 00263 index = error.find("Good signature"); 00264 if(index != -1) 00265 { 00266 //kdDebug(5100) << "good signature" << endl; 00267 status |= SIGNED; 00268 status |= GOODSIG; 00269 00270 // get key ID of signer 00271 index = error.find("Key ID ", index) + 7; 00272 block.setSignatureKeyId( error.mid(index, 8) ); 00273 00274 // get signer 00275 index = error.find('"',index) + 1; 00276 int index2 = error.find('"', index); 00277 block.setSignatureUserId( error.mid(index, index2-index) ); 00278 00280 block.setSignatureDate( "" ); 00281 } 00282 index = error.find("BAD signature"); 00283 if(index != -1) 00284 { 00285 //kdDebug(5100) << "BAD signature" << endl; 00286 status |= SIGNED; 00287 status |= ERROR; 00288 00289 // get key ID of signer 00290 index = error.find("Key ID ", index) + 7; 00291 block.setSignatureKeyId( error.mid(index, 8) ); 00292 00293 // get signer 00294 index = error.find('"',index) + 1; 00295 int index2 = error.find('"', index); 00296 block.setSignatureUserId( error.mid(index, index2-index) ); 00297 00299 block.setSignatureDate( "" ); 00300 } 00301 index = error.find("Signature by unknown key"); 00302 if(index != -1) 00303 { 00304 index = error.find("keyid: 0x",index) + 9; 00305 block.setSignatureKeyId( error.mid(index, 8) ); 00306 block.setSignatureUserId( TQString() ); 00307 // FIXME: not a very good solution... 00308 status |= SIGNED; 00309 status |= GOODSIG; 00310 00312 block.setSignatureDate( "" ); 00313 } 00314 00315 //kdDebug(5100) << "status = " << status << endl; 00316 block.setStatus( status ); 00317 return status; 00318 } 00319 00320 00321 Key* 00322 Base5::readPublicKey( const KeyID& keyId, const bool readTrust, Key* key ) 00323 { 00324 int exitStatus = 0; 00325 00326 status = 0; 00327 exitStatus = run( "pgpk -ll 0x" + keyId, 0, true ); 00328 00329 if(exitStatus != 0) { 00330 status = ERROR; 00331 return 0; 00332 } 00333 00334 key = parseSingleKey( output, key ); 00335 00336 if( key == 0 ) 00337 { 00338 return 0; 00339 } 00340 00341 if( readTrust ) 00342 { 00343 exitStatus = run( "pgpk -c 0x" + keyId, 0, true ); 00344 00345 if(exitStatus != 0) { 00346 status = ERROR; 00347 return 0; 00348 } 00349 00350 parseTrustDataForKey( key, output ); 00351 } 00352 00353 return key; 00354 } 00355 00356 00357 KeyList 00358 Base5::publicKeys( const TQStringList & patterns ) 00359 { 00360 int exitStatus = 0; 00361 00362 TQCString cmd = "pgpk -ll"; 00363 for ( TQStringList::ConstIterator it = patterns.begin(); 00364 it != patterns.end(); ++it ) { 00365 cmd += " "; 00366 cmd += TDEProcess::quote( *it ).local8Bit(); 00367 } 00368 status = 0; 00369 exitStatus = run( cmd, 0, true ); 00370 00371 if(exitStatus != 0) { 00372 status = ERROR; 00373 return KeyList(); 00374 } 00375 00376 // now we need to parse the output for public keys 00377 KeyList keys = parseKeyList( output, false ); 00378 00379 // sort the list of public keys 00380 keys.sort(); 00381 00382 return keys; 00383 } 00384 00385 00386 KeyList 00387 Base5::secretKeys( const TQStringList & patterns ) 00388 { 00389 int exitStatus = 0; 00390 00391 status = 0; 00392 TQCString cmd = "pgpk -ll"; 00393 for ( TQStringList::ConstIterator it = patterns.begin(); 00394 it != patterns.end(); ++it ) { 00395 cmd += " "; 00396 cmd += TDEProcess::quote( *it ).local8Bit(); 00397 } 00398 status = 0; 00399 exitStatus = run( cmd, 0, true ); 00400 00401 if(exitStatus != 0) { 00402 status = ERROR; 00403 return KeyList(); 00404 } 00405 00406 // now we need to parse the output for secret keys 00407 KeyList keys = parseKeyList( output, true ); 00408 00409 // sort the list of public keys 00410 keys.sort(); 00411 00412 return keys; 00413 } 00414 00415 00416 TQCString Base5::getAsciiPublicKey(const KeyID& keyID) 00417 { 00418 int exitStatus = 0; 00419 00420 if (keyID.isEmpty()) 00421 return TQCString(); 00422 00423 status = 0; 00424 exitStatus = run( "pgpk -xa 0x" + keyID, 0, true ); 00425 00426 if(exitStatus != 0) { 00427 status = ERROR; 00428 return TQCString(); 00429 } 00430 00431 return output; 00432 } 00433 00434 00435 int 00436 Base5::signKey(const KeyID& keyID, const char *passphrase) 00437 { 00438 TQCString cmd; 00439 int exitStatus = 0; 00440 00441 if(passphrase == 0) return false; 00442 00443 cmd = "pgpk -s -f +batchmode=1 0x"; 00444 cmd += keyID; 00445 cmd += addUserId(); 00446 00447 status = 0; 00448 exitStatus = run(cmd.data(), passphrase); 00449 00450 if (exitStatus != 0) 00451 status = ERROR; 00452 00453 return status; 00454 } 00455 00456 //-- private functions -------------------------------------------------------- 00457 00458 Key* 00459 Base5::parseKeyData( const TQCString& output, int& offset, Key* key /* = 0 */ ) 00460 // This function parses the data for a single key which is output by PGP 5 00461 // with the following command line: 00462 // pgpk -ll 00463 // It expects the key data to start at offset and returns the start of 00464 // the next key's data in offset. 00465 { 00466 if( ( strncmp( output.data() + offset, "pub", 3 ) != 0 ) && 00467 ( strncmp( output.data() + offset, "sec", 3 ) != 0 ) ) 00468 { 00469 kdDebug(5100) << "Unknown key type or corrupt key data.\n"; 00470 return 0; 00471 } 00472 00473 if( key == 0 ) 00474 key = new Key(); 00475 else 00476 key->clear(); 00477 00478 Subkey *subkey = 0; 00479 bool primaryKey = true; 00480 00481 while( true ) 00482 { 00483 int eol; 00484 00485 // search the end of the current line 00486 eol = output.find( '\n', offset ); 00487 if( ( eol == -1 ) || ( eol == offset ) ) 00488 break; 00489 00490 //kdDebug(5100) << "Parsing: " << output.mid(offset, eol-offset) << endl; 00491 00492 if( !strncmp( output.data() + offset, "pub", 3 ) || 00493 !strncmp( output.data() + offset, "sec", 3 ) || 00494 !strncmp( output.data() + offset, "sub", 3 ) ) 00495 { // line contains key data 00496 //kdDebug(5100)<<"Key data:\n"; 00497 int pos, pos2; 00498 00499 subkey = new Subkey( "", false ); 00500 key->addSubkey( subkey ); 00501 00502 // Key Flags 00503 /* From the PGP 5 manual page for pgpk: 00504 Following this column is a single character which 00505 describes other attributes of the object: 00506 00507 @ The object is disabled 00508 + The object is axiomatically trusted (i.e., it's 00509 your key) 00510 */ 00511 switch( output[offset+3] ) 00512 { 00513 case ' ': // nothing special 00514 break; 00515 case '@': // disabled key 00516 subkey->setDisabled( true ); 00517 key->setDisabled( true ); 00518 break; 00519 default: // all other flags are ignored 00520 //kdDebug(5100) << "Unknown key flag.\n"; 00521 ; 00522 } 00523 00524 // Key Length 00525 pos = offset + 4; 00526 while( output[pos] == ' ' ) 00527 pos++; 00528 pos2 = output.find( ' ', pos ); 00529 subkey->setKeyLength( output.mid( pos, pos2-pos ).toUInt() ); 00530 //kdDebug(5100) << "Key Length: "<<subkey->keyLength()<<endl; 00531 00532 // Key ID 00533 pos = pos2 + 1; 00534 while( output[pos] == ' ' ) 00535 pos++; 00536 pos += 2; // skip the '0x' 00537 pos2 = output.find( ' ', pos ); 00538 subkey->setKeyID( output.mid( pos, pos2-pos ) ); 00539 //kdDebug(5100) << "Key ID: "<<subkey->keyID()<<endl; 00540 00541 // Creation Date 00542 pos = pos2 + 1; 00543 while( output[pos] == ' ' ) 00544 pos++; 00545 pos2 = output.find( ' ', pos ); 00546 int year = output.mid( pos, 4 ).toInt(); 00547 int month = output.mid( pos+5, 2 ).toInt(); 00548 int day = output.mid( pos+8, 2 ).toInt(); 00549 TQDateTime dt( TQDate( year, month, day ), TQTime( 00, 00 ) ); 00550 TQDateTime epoch( TQDate( 1970, 01, 01 ), TQTime( 00, 00 ) ); 00551 // The calculated creation date isn't exactly correct because TQDateTime 00552 // doesn't know anything about timezones and always assumes local time 00553 // although epoch is of course UTC. But as PGP 5 anyway doesn't print 00554 // the time this doesn't matter too much. 00555 subkey->setCreationDate( epoch.secsTo( dt ) ); 00556 00557 // Expiration Date 00558 // if the primary key has been revoked the expiration date is not printed 00559 if( primaryKey || !key->revoked() ) 00560 { 00561 pos = pos2 + 1; 00562 while( output[pos] == ' ' ) 00563 pos++; 00564 pos2 = output.find( ' ', pos ); 00565 if( output[pos] == '-' ) 00566 { // key doesn't expire 00567 subkey->setExpirationDate( -1 ); 00568 } 00569 else if( !strncmp( output.data() + pos, "*REVOKED*", 9 ) ) 00570 { // key has been revoked 00571 subkey->setRevoked( true ); 00572 key->setRevoked( true ); 00573 } 00574 else 00575 { 00576 int year = output.mid( pos, 4 ).toInt(); 00577 int month = output.mid( pos+5, 2 ).toInt(); 00578 int day = output.mid( pos+8, 2 ).toInt(); 00579 TQDateTime dt( TQDate( year, month, day ), TQTime( 00, 00 ) ); 00580 subkey->setCreationDate( epoch.secsTo( dt ) ); 00581 // has the key already expired? 00582 if( TQDateTime::currentDateTime() >= dt ) 00583 { 00584 subkey->setExpired( true ); 00585 key->setExpired( true ); 00586 } 00587 } 00588 } 00589 else if( key->revoked() ) 00590 subkey->setRevoked( true ); 00591 00592 // Key algorithm (RSA, DSS, Diffie-Hellman) 00593 bool sign = false; 00594 bool encr = false; 00595 pos = pos2 + 1; 00596 while( output[pos] == ' ' ) 00597 pos++; 00598 pos2 = output.find( ' ', pos ); 00599 if( !strncmp( output.data() + pos, "RSA", 3 ) ) 00600 { 00601 sign = true; 00602 encr = true; 00603 } 00604 else if( !strncmp( output.data() + pos, "DSS", 3 ) ) 00605 sign = true; 00606 else if( !strncmp( output.data() + pos, "Diffie-Hellman", 14 ) ) 00607 encr = true; 00608 else 00609 kdDebug(5100)<<"Unknown key algorithm\n"; 00610 00611 // set key capabilities of the subkey 00612 subkey->setCanEncrypt( encr ); 00613 subkey->setCanSign( sign ); 00614 subkey->setCanCertify( sign ); 00615 00616 if( primaryKey ) 00617 { 00618 // Global key capabilities 00619 bool canSign = false; 00620 bool canEncr = false; 00621 pos = pos2 + 1; 00622 while( output[pos] == ' ' ) 00623 pos++; 00624 pos2 = eol; 00625 if( !strncmp( output.data() + pos, "Sign & Encrypt", 14 ) ) 00626 { 00627 canSign = true; 00628 canEncr = true; 00629 } 00630 else if( !strncmp( output.data() + pos, "Sign only", 9 ) ) 00631 canSign = true; 00632 else if( !strncmp( output.data() + pos, "Encrypt only", 12 ) ) 00633 canEncr = true; 00634 else 00635 kdDebug(5100)<<"Unknown key capability\n"; 00636 00637 // set the global key capabilities 00638 if( !key->expired() && !key->revoked() ) 00639 { 00640 key->setCanEncrypt( canEncr ); 00641 key->setCanSign( canSign ); 00642 key->setCanCertify( canSign ); 00643 } 00644 //kdDebug(5100)<<"Key capabilities: "<<(key->canEncrypt()?"E":"")<<(key->canSign()?"SC":"")<<endl; 00645 primaryKey = false; 00646 } 00647 } 00648 else if( !strncmp( output.data() + offset, "f16", 3 ) || 00649 !strncmp( output.data() + offset, "f20", 3 ) ) 00650 { // line contains a fingerprint 00651 /* Examples: 00652 f16 Fingerprint16 = DE 2A 77 08 78 64 7C 42 72 75 B1 A7 3E 42 3F 79 00653 f20 Fingerprint20 = 226F 4B63 6DA2 7389 91D1 2A49 D58A 3EC1 5214 181E 00654 00655 */ 00656 int pos = output.find( '=', offset+3 ) + 2; 00657 TQCString fingerprint = output.mid( pos, eol-pos ); 00658 // remove white space from the fingerprint 00659 for ( int idx = 0 ; (idx = fingerprint.find(' ', idx)) >= 0 ; ) 00660 fingerprint.replace( idx, 1, "" ); 00661 assert( subkey != 0 ); 00662 subkey->setFingerprint( fingerprint ); 00663 //kdDebug(5100)<<"Fingerprint: "<<fingerprint<<endl; 00664 } 00665 else if( !strncmp( output.data() + offset, "uid", 3 ) ) 00666 { // line contains a uid 00667 int pos = offset+5; 00668 TQCString uid = output.mid( pos, eol-pos ); 00669 key->addUserID( uid ); 00670 // displaying of uids which contain non-ASCII characters is broken in 00671 // PGP 5.0i; it shows these characters as \ooo and truncates the uid 00672 // because it doesn't take the 3 extra characters per non-ASCII char 00673 // into account. Example (with an UTF-8 encoded ö): 00674 // uid Ingo Kl\303\266cker <ingo.kloecker@epo 00675 // because of this and because we anyway don't know which charset was 00676 // used to encode the uid we don't try to decode it 00677 } 00678 else if ( !strncmp( output.data() + offset, "sig", 3 ) || 00679 !strncmp( output.data() + offset, "SIG", 3 ) || 00680 !strncmp( output.data() + offset, "ret", 3 ) ) 00681 { // line contains a signature 00682 // SIG = sig with own key; ret = sig with revoked key 00683 // we ignore it for now 00684 } 00685 00686 offset = eol + 1; 00687 } 00688 00689 return key; 00690 } 00691 00692 00693 Key* 00694 Base5::parseSingleKey( const TQCString& output, Key* key /* = 0 */ ) 00695 { 00696 int offset; 00697 00698 // search start of header line 00699 if( !strncmp( output.data(), "Type Bits", 9 ) ) 00700 offset = 0; 00701 else 00702 { 00703 offset = output.find( "\nType Bits" ) + 1; 00704 if( offset == 0 ) 00705 return 0; 00706 } 00707 00708 // key data begins in the next line 00709 offset = output.find( '\n', offset ) + 1; 00710 if( offset == -1 ) 00711 return 0; 00712 00713 key = parseKeyData( output, offset, key ); 00714 00715 //kdDebug(5100) << "finished parsing keys" << endl; 00716 00717 return key; 00718 } 00719 00720 00721 KeyList 00722 Base5::parseKeyList( const TQCString& output, bool onlySecretKeys ) 00723 { 00724 KeyList keys; 00725 Key *key = 0; 00726 int offset; 00727 00728 // search start of header line 00729 if( !strncmp( output.data(), "Type Bits", 9 ) ) 00730 offset = 0; 00731 else 00732 { 00733 offset = output.find( "\nType Bits" ) + 1; 00734 if( offset == 0 ) 00735 return keys; 00736 } 00737 00738 // key data begins in the next line 00739 offset = output.find( '\n', offset ) + 1; 00740 if( offset == -1 ) 00741 return keys; 00742 00743 do 00744 { 00745 key = parseKeyData( output, offset ); 00746 if( key != 0 ) 00747 { 00748 // if only secret keys should be read test if the key is secret 00749 if( !onlySecretKeys || !key->secret() ) 00750 keys.append( key ); 00751 // skip the blank line which separates the keys 00752 offset++; 00753 } 00754 } 00755 while( key != 0 ); 00756 00757 //kdDebug(5100) << "finished parsing keys" << endl; 00758 00759 return keys; 00760 } 00761 00762 00763 void 00764 Base5::parseTrustDataForKey( Key* key, const TQCString& str ) 00765 { 00766 if( ( key == 0 ) || str.isEmpty() ) 00767 return; 00768 00769 TQCString keyID = "0x" + key->primaryKeyID(); 00770 UserIDList userIDs = key->userIDs(); 00771 00772 // search the start of the trust data 00773 int offset = str.find( "\n\n KeyID" ) + 9; 00774 if( offset == -1 + 9 ) 00775 return; 00776 00777 offset = str.find( '\n', offset ) + 1; 00778 if( offset == -1 + 1 ) 00779 return; 00780 00781 bool ultimateTrust = false; 00782 if( !strncmp( str.data() + offset+13, "ultimate", 8 ) ) 00783 ultimateTrust = true; 00784 00785 while( true ) 00786 { // loop over all trust information about this key 00787 00788 int eol; 00789 00790 // search the end of the current line 00791 if( ( eol = str.find( '\n', offset ) ) == -1 ) 00792 break; 00793 00794 if( str[offset+23] != ' ' ) 00795 { // line contains a validity value for a user ID 00796 00797 // determine the validity 00798 Validity validity = KPGP_VALIDITY_UNKNOWN; 00799 if( !strncmp( str.data() + offset+23, "complete", 8 ) ) 00800 if( ultimateTrust ) 00801 validity = KPGP_VALIDITY_ULTIMATE; 00802 else 00803 validity = KPGP_VALIDITY_FULL; 00804 else if( !strncmp( str.data() + offset+23, "marginal", 8 ) ) 00805 validity = KPGP_VALIDITY_MARGINAL; 00806 else if( !strncmp( str.data() + offset+23, "invalid", 7 ) ) 00807 validity = KPGP_VALIDITY_UNDEFINED; 00808 00809 // determine the user ID 00810 int pos = offset + 33; 00811 TQString uid = str.mid( pos, eol-pos ); 00812 00813 // set the validity of the corresponding user ID 00814 for( UserIDListIterator it( userIDs ); it.current(); ++it ) 00815 if( (*it)->text() == uid ) 00816 { 00817 kdDebug(5100)<<"Setting the validity of "<<uid<<" to "<<validity<<endl; 00818 (*it)->setValidity( validity ); 00819 break; 00820 } 00821 } 00822 00823 offset = eol + 1; 00824 } 00825 } 00826 00827 00828 } // namespace Kpgp