libkdenetwork Library API Documentation

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