certmanager/lib

kpgpkeylistjob.cpp

00001 /*
00002     kpgpkeylistjob.cpp
00003 
00004     This file is part of libkleopatra, the KDE keymanagement library
00005     Copyright (c) 2004 Ingo Kloecker <kloecker@kde.org>
00006 
00007     Libkleopatra is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU General Public License as
00009     published by the Free Software Foundation; either version 2 of the
00010     License, or (at your option) any later version.
00011 
00012     Libkleopatra is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021     In addition, as a special exception, the copyright holders give
00022     permission to link the code of this program with any edition of
00023     the Qt library by Trolltech AS, Norway (or with modified versions
00024     of Qt that use the same license as Qt), and distribute linked
00025     combinations including the two.  You must obey the GNU General
00026     Public License in all respects for all of the code used other than
00027     Qt.  If you modify this file, you may extend this exception to
00028     your version of the file, but you are not obligated to do so.  If
00029     you do not wish to do so, delete this exception statement from
00030     your version.
00031 */
00032 
00033 #ifdef HAVE_CONFIG_H
00034 #include <config.h>
00035 #endif
00036 
00037 #include "kpgpkeylistjob.h"
00038 
00039 #include <kpgpbase.h>
00040 #include <kpgpkey.h>
00041 
00042 #include <gpgmepp/key.h>
00043 #include <gpgmepp/keylistresult.h>
00044 
00045 #include <gpgme.h>
00046 
00047 #include <qtimer.h>
00048 
00049 #include <stdlib.h>
00050 #include <string.h>
00051 #include <assert.h>
00052 
00053 Kleo::KpgpKeyListJob::KpgpKeyListJob( Kpgp::Base * pgpBase )
00054   : KeyListJob( 0, "Kleo::KpgpKeyListJob" ),
00055     mPgpBase( pgpBase )
00056 {
00057 }
00058 
00059 Kleo::KpgpKeyListJob::~KpgpKeyListJob() {
00060 }
00061 
00062 // the following function is a verbatim copy from gpgme/key.c
00063 static char *
00064 set_user_id_part (char *tail, const char *buf, size_t len)
00065 {
00066   while (len && (buf[len - 1] == ' ' || buf[len - 1] == '\t'))
00067     len--;
00068   for (; len; len--)
00069     *tail++ = *buf++;
00070   *tail++ = 0;
00071   return tail;
00072 }
00073 
00074 // the following function is a verbatim copy from gpgme/key.c
00075 static void
00076 parse_user_id (char *src, char **name, char **email,
00077            char **comment, char *tail)
00078 {
00079   const char *start = NULL;
00080   int in_name = 0;
00081   int in_email = 0;
00082   int in_comment = 0;
00083 
00084   while (*src)
00085     {
00086       if (in_email)
00087     {
00088       if (*src == '<')
00089         /* Not legal but anyway.  */
00090         in_email++;
00091       else if (*src == '>')
00092         {
00093           if (!--in_email && !*email)
00094         {
00095           *email = tail;
00096           tail = set_user_id_part (tail, start, src - start);
00097         }
00098         }
00099     }
00100       else if (in_comment)
00101     {
00102       if (*src == '(')
00103         in_comment++;
00104       else if (*src == ')')
00105         {
00106           if (!--in_comment && !*comment)
00107         {
00108           *comment = tail;
00109           tail = set_user_id_part (tail, start, src - start);
00110         }
00111         }
00112     }
00113       else if (*src == '<')
00114     {
00115       if (in_name)
00116         {
00117           if (!*name)
00118         {
00119           *name = tail;
00120           tail = set_user_id_part (tail, start, src - start);
00121         }
00122           in_name = 0;
00123         }
00124       in_email = 1;
00125       start = src + 1;
00126     }
00127       else if (*src == '(')
00128     {
00129       if (in_name)
00130         {
00131           if (!*name)
00132         {
00133           *name = tail;
00134           tail = set_user_id_part (tail, start, src - start);
00135         }
00136           in_name = 0;
00137         }
00138       in_comment = 1;
00139       start = src + 1;
00140     }
00141       else if (!in_name && *src != ' ' && *src != '\t')
00142     {
00143       in_name = 1;
00144       start = src;
00145     }
00146       src++;
00147     }
00148 
00149   if (in_name)
00150     {
00151       if (!*name)
00152     {
00153       *name = tail;
00154       tail = set_user_id_part (tail, start, src - start);
00155     }
00156     }
00157 
00158   /* Let unused parts point to an EOS.  */
00159   tail--;
00160   if (!*name)
00161     *name = tail;
00162   if (!*email)
00163     *email = tail;
00164   if (!*comment)
00165     *comment = tail;
00166 }
00167 
00168 gpgme_user_id_t KpgpUserID2GPGMEUserID( const Kpgp::UserID * kUserId )
00169 {
00170   // inspired by _gpgme_key_append_name
00171 
00172   const QCString text = kUserId->text().utf8();
00173   const int src_len = text.length();
00174 
00175   gpgme_user_id_t uid;
00176   /* Allocate enough memory for the _gpgme_user_id struct, for the actual user
00177      id (the text) and for the parsed version. */
00178   uid = (gpgme_user_id_t) malloc( sizeof( *uid ) + 2 * src_len + 3 );
00179   memset( uid, 0, sizeof *uid );
00180   uid->revoked = kUserId->revoked();
00181   uid->invalid = kUserId->invalid();
00182   uid->validity = (gpgme_validity_t) kUserId->validity();
00183 
00184   uid->uid = ((char *) uid) + sizeof (*uid);
00185   char *dst = uid->uid;
00186   memcpy( dst, text.data(), src_len + 1 );
00187 
00188   dst += src_len + 1;
00189   parse_user_id( uid->uid, &uid->name, &uid->email,
00190                  &uid->comment, dst );
00191 
00192   return uid;
00193 }
00194 
00195 gpgme_subkey_t KpgpSubkey2GPGMESubKey( const Kpgp::Subkey * kSubkey )
00196 {
00197   gpgme_subkey_t subkey;
00198 
00199   const QCString fpr = kSubkey->fingerprint();
00200   const unsigned int fpr_len = fpr.length();
00201   const QCString keyId = kSubkey->longKeyID();
00202 
00203   subkey = (gpgme_subkey_t) calloc( 1, sizeof( *subkey ) + fpr_len + 1 );
00204   subkey->revoked = kSubkey->revoked();
00205   subkey->expired = kSubkey->expired();
00206   subkey->disabled = kSubkey->disabled();
00207   subkey->invalid = kSubkey->invalid();
00208   subkey->can_encrypt = kSubkey->canEncrypt();
00209   subkey->can_sign = kSubkey->canSign();
00210   subkey->can_certify = kSubkey->canCertify();
00211   subkey->secret = kSubkey->secret();
00212   subkey->pubkey_algo = (gpgme_pubkey_algo_t) kSubkey->keyAlgorithm();
00213   subkey->length = kSubkey->keyLength();
00214   subkey->keyid = subkey->_keyid;
00215   memcpy( subkey->_keyid, keyId.data(), keyId.length() + 1 );
00216   subkey->fpr = ((char *) subkey) + sizeof( *subkey );
00217   memcpy( subkey->fpr, fpr.data(), fpr_len + 1 );
00218   subkey->timestamp = kSubkey->creationDate();
00219   subkey->expires = kSubkey->expirationDate();
00220 
00221   return subkey;
00222 }
00223 
00224 gpgme_key_t KpgpKey2gpgme_key( const Kpgp::Key * kKey )
00225 {
00226   gpgme_key_t key;
00227 
00228   key = (gpgme_key_t) calloc( 1, sizeof( *key ) );
00229   key->revoked = kKey->revoked();
00230   key->expired = kKey->expired();
00231   key->disabled = kKey->disabled();
00232   key->invalid = kKey->invalid();
00233   key->can_encrypt = kKey->canEncrypt();
00234   key->can_sign = kKey->canSign();
00235   key->can_certify = kKey->canCertify();
00236   key->secret = kKey->secret();
00237   key->protocol = GPGME_PROTOCOL_OpenPGP;
00238   key->owner_trust = GPGME_VALIDITY_UNKNOWN; // FIXME?
00239 
00240   Kpgp::UserIDList kUserIDs = kKey->userIDs();
00241   for ( Kpgp::UserIDListIterator it( kUserIDs ); it.current(); ++it ) {
00242     gpgme_user_id_t uid = KpgpUserID2GPGMEUserID( *it );
00243     if ( !key->uids )
00244       key->uids = uid;
00245     if ( key->_last_uid )
00246       key->_last_uid->next = uid;
00247     key->_last_uid = uid;
00248   }
00249 
00250   Kpgp::SubkeyList kSubkeys = kKey->subkeys();
00251   for ( Kpgp::SubkeyListIterator it( kSubkeys ); it.current(); ++it ) {
00252     gpgme_subkey_t subkey = KpgpSubkey2GPGMESubKey( *it );
00253     if (!key->subkeys)
00254       key->subkeys = subkey;
00255     if (key->_last_subkey)
00256       key->_last_subkey->next = subkey;
00257     key->_last_subkey = subkey;
00258   }
00259 
00260   return key;
00261 }
00262 
00263 GpgME::Error Kleo::KpgpKeyListJob::start( const QStringList & patterns,
00264                                           bool secretOnly ) {
00265   mPatterns = patterns;
00266   mSecretOnly = secretOnly;
00267   QTimer::singleShot( 0, this, SLOT( slotDoIt() ) );
00268   return GpgME::Error( 0 );
00269 }
00270 
00271 void Kleo::KpgpKeyListJob::slotDoIt() {
00272   std::vector<GpgME::Key> keys;
00273   GpgME::KeyListResult res = exec( mPatterns, mSecretOnly, keys );
00274   for ( std::vector<GpgME::Key>::const_iterator it = keys.begin();
00275         it != keys.end(); ++it )
00276     emit nextKey( *it );
00277   emit done();
00278   emit result( res );
00279   deleteLater();
00280 }
00281 
00282 GpgME::KeyListResult Kleo::KpgpKeyListJob::exec( const QStringList & patterns,
00283                                                  bool secretOnly,
00284                                                  std::vector<GpgME::Key> & keys ) {
00285   Kpgp::KeyList kKeys;
00286   if ( secretOnly )
00287     kKeys = mPgpBase->secretKeys( patterns );
00288   else
00289     kKeys = mPgpBase->publicKeys( patterns );
00290 
00291   keys.clear();
00292   for ( Kpgp::KeyListIterator it( kKeys ); it.current(); ++it ) {
00293     keys.push_back( GpgME::Key( KpgpKey2gpgme_key(*it), true ) );
00294   }
00295 
00296   _gpgme_op_keylist_result res;
00297   res.truncated = 0; // key list is not truncated
00298   res._unused = 0;
00299 
00300   return GpgME::KeyListResult( GpgME::Error( 0 ), res );
00301 }
00302 
00303 #include "kpgpkeylistjob.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys