libkpgp

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 <qregexp.h>
00030 #include <qdatetime.h>
00031 
00032 #include <klocale.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   QCString 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(QRegExp("[ \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     QCString 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(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(error.mid(index,index2-index));
00171 //    errMsg = QString("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     QCString 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( QString::null );
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 QStringList & patterns )
00359 {
00360   int exitStatus = 0;
00361 
00362   QCString cmd = "pgpk -ll";
00363   for ( QStringList::ConstIterator it = patterns.begin();
00364         it != patterns.end(); ++it ) {
00365     cmd += " ";
00366     cmd += KProcess::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 QStringList & patterns )
00388 {
00389   int exitStatus = 0;
00390 
00391   status = 0;
00392   QCString cmd = "pgpk -ll";
00393   for ( QStringList::ConstIterator it = patterns.begin();
00394         it != patterns.end(); ++it ) {
00395     cmd += " ";
00396     cmd += KProcess::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 QCString Base5::getAsciiPublicKey(const KeyID& keyID)
00417 {
00418   int exitStatus = 0;
00419 
00420   if (keyID.isEmpty())
00421     return QCString();
00422 
00423   status = 0;
00424   exitStatus = run( "pgpk -xa 0x" + keyID, 0, true );
00425 
00426   if(exitStatus != 0) {
00427     status = ERROR;
00428     return QCString();
00429   }
00430 
00431   return output;
00432 }
00433 
00434 
00435 int
00436 Base5::signKey(const KeyID& keyID, const char *passphrase)
00437 {
00438   QCString 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 QCString& 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       QDateTime dt( QDate( year, month, day ), QTime( 00, 00 ) );
00550       QDateTime epoch( QDate( 1970, 01, 01 ), QTime( 00, 00 ) );
00551       // The calculated creation date isn't exactly correct because QDateTime
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           QDateTime dt( QDate( year, month, day ), QTime( 00, 00 ) );
00580           subkey->setCreationDate( epoch.secsTo( dt ) );
00581           // has the key already expired?
00582           if( QDateTime::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       QCString 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       QCString 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 &ouml;):
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 QCString& 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 QCString& 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 QCString& str )
00765 {
00766   if( ( key == 0 ) || str.isEmpty() )
00767     return;
00768 
00769   QCString 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       QString 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
KDE Home | KDE Accessibility Home | Description of Access Keys