certmanager Library API Documentation

qgpgmecryptoconfig.cpp

00001 /* 00002 qgpgmecryptoconfig.cpp 00003 00004 This file is part of libkleopatra, the KDE keymanagement library 00005 Copyright (c) 2004 Klarälvdalens Datakonsult AB 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 #include "qgpgmecryptoconfig.h" 00034 #include <kdebug.h> 00035 #include <kprocio.h> 00036 #include <errno.h> 00037 #include <kmessagebox.h> 00038 #include <klocale.h> 00039 00040 #include <assert.h> 00041 #include <ktempfile.h> 00042 #include <qfile.h> 00043 #include <stdlib.h> 00044 #include <qtextcodec.h> 00045 00046 // Just for the Q_ASSERT in the dtor. Not thread-safe, but who would 00047 // have 2 threads talking to gpgconf anyway? :) 00048 static bool s_duringClear = false; 00049 00050 #define GPGCONF_FLAG_GROUP 1 00051 #define GPGCONF_FLAG_OPTIONAL 2 00052 #define GPGCONF_FLAG_LIST 4 00053 #define GPGCONF_FLAG_RUNTIME 8 00054 #define GPGCONF_FLAG_DEFAULT 16 // fixed default value available 00055 #define GPGCONF_FLAG_DEFAULT_DESC 32 // runtime default value available 00056 #define GPGCONF_FLAG_NOARG_DESC 64 // option with optional arg; special meaning if no arg set 00057 // Change size of mFlags bitfield if adding new values here 00058 00059 QGpgMECryptoConfig::QGpgMECryptoConfig() 00060 : mComponents( 7 ), mParsed( false ) 00061 { 00062 mComponents.setAutoDelete( true ); 00063 } 00064 00065 QGpgMECryptoConfig::~QGpgMECryptoConfig() 00066 { 00067 } 00068 00069 void QGpgMECryptoConfig::runGpgConf( bool showErrors ) 00070 { 00071 // Run gpgconf --list-components to make the list of components 00072 00073 KProcIO proc( QTextCodec::codecForName( "utf8" ) ); 00074 proc << "gpgconf"; // must be in the PATH 00075 proc << "--list-components"; 00076 00077 QObject::connect( &proc, SIGNAL( readReady(KProcIO*) ), 00078 this, SLOT( slotCollectStdOut(KProcIO*) ) ); 00079 00080 // run the process: 00081 int rc = 0; 00082 if ( !proc.start( KProcess::Block ) ) 00083 rc = -1; 00084 else 00085 rc = ( proc.normalExit() ) ? proc.exitStatus() : -2 ; 00086 00087 // handle errors, if any (and if requested) 00088 if ( showErrors && rc != 0 ) { 00089 QString wmsg = i18n("<qt>Failed to execute gpgconf:<br>%1</qt>"); 00090 if ( rc == -1 ) 00091 wmsg = wmsg.arg( i18n( "program not found" ) ); 00092 else if ( rc == -2 ) 00093 wmsg = wmsg.arg( i18n( "program cannot be executed" ) ); 00094 else 00095 wmsg = wmsg.arg( strerror(rc) ); 00096 kdWarning(5150) << wmsg << endl; // to see it from test_cryptoconfig.cpp 00097 KMessageBox::error(0, wmsg); 00098 } 00099 mParsed = true; 00100 } 00101 00102 void QGpgMECryptoConfig::slotCollectStdOut( KProcIO* proc ) 00103 { 00104 QString line; 00105 int result; 00106 while( ( result = proc->readln(line) ) != -1 ) { 00107 //kdDebug(5150) << "GOT LINE:" << line << endl; 00108 // Format: NAME:DESCRIPTION 00109 QStringList lst = QStringList::split( ':', line, true ); 00110 if ( lst.count() >= 2 ) { 00111 mComponents.insert( lst[0], new QGpgMECryptoConfigComponent( this, lst[0], lst[1] ) ); 00112 } else { 00113 kdWarning(5150) << "Parse error on gpgconf --list-components output: " << line << endl; 00114 } 00115 } 00116 } 00117 00118 QStringList QGpgMECryptoConfig::componentList() const 00119 { 00120 if ( !mParsed ) 00121 const_cast<QGpgMECryptoConfig*>( this )->runGpgConf( true ); 00122 QDictIterator<QGpgMECryptoConfigComponent> it( mComponents ); 00123 QStringList names; 00124 for( ; it.current(); ++it ) 00125 names.push_back( it.currentKey() ); 00126 return names; 00127 } 00128 00129 Kleo::CryptoConfigComponent* QGpgMECryptoConfig::component( const QString& name ) const 00130 { 00131 if ( !mParsed ) 00132 const_cast<QGpgMECryptoConfig*>( this )->runGpgConf( false ); 00133 return mComponents.find( name ); 00134 } 00135 00136 void QGpgMECryptoConfig::sync( bool runtime ) 00137 { 00138 QDictIterator<QGpgMECryptoConfigComponent> it( mComponents ); 00139 for( ; it.current(); ++it ) 00140 it.current()->sync( runtime ); 00141 } 00142 00143 void QGpgMECryptoConfig::clear() 00144 { 00145 s_duringClear = true; 00146 mComponents.clear(); 00147 s_duringClear = false; 00148 mParsed = false; // next call to componentList/component will need to run gpgconf again 00149 } 00150 00152 00153 QGpgMECryptoConfigComponent::QGpgMECryptoConfigComponent( QGpgMECryptoConfig*, const QString& name, const QString& description ) 00154 : mGroups( 7 ), mName( name ), mDescription( description ) 00155 { 00156 mGroups.setAutoDelete( true ); 00157 runGpgConf(); 00158 } 00159 00160 QGpgMECryptoConfigComponent::~QGpgMECryptoConfigComponent() 00161 { 00162 } 00163 00164 void QGpgMECryptoConfigComponent::runGpgConf() 00165 { 00166 // Run gpgconf --list-options <component>, and create all groups and entries for that component 00167 00168 KProcIO proc( QTextCodec::codecForName( "utf8" ) ); 00169 proc << "gpgconf"; // must be in the PATH 00170 proc << "--list-options"; 00171 proc << mName; 00172 00173 //kdDebug(5150) << "Running gpgconf --list-options " << mName << endl; 00174 00175 QObject::connect( &proc, SIGNAL( readReady(KProcIO*) ), 00176 this, SLOT( slotCollectStdOut(KProcIO*) ) ); 00177 mCurrentGroup = 0; 00178 00179 // run the process: 00180 int rc = 0; 00181 if ( !proc.start( KProcess::Block ) ) 00182 rc = -1; 00183 else 00184 rc = ( proc.normalExit() ) ? proc.exitStatus() : -1 ; 00185 00186 if( rc != 0 ) // Can it really be non-0, when gpg-config --list-components worked? 00187 kdWarning(5150) << k_funcinfo << ":" << strerror( rc ) << endl; 00188 else { 00189 if ( mCurrentGroup && !mCurrentGroup->mEntries.isEmpty() ) // only add non-empty groups 00190 mGroups.insert( mCurrentGroupName, mCurrentGroup ); 00191 } 00192 } 00193 00194 void QGpgMECryptoConfigComponent::slotCollectStdOut( KProcIO* proc ) 00195 { 00196 QString line; 00197 int result; 00198 while( ( result = proc->readln(line) ) != -1 ) { 00199 //kdDebug(5150) << "GOT LINE:" << line << endl; 00200 // Format: NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:ARGDEF:VALUE 00201 QStringList lst = QStringList::split( ':', line, true ); 00202 if ( lst.count() >= 10 ) { 00203 int flags = lst[1].toInt(); 00204 int level = lst[2].toInt(); 00205 if ( level > 2 ) // invisible or internal -> skip it; 00206 continue; 00207 if ( flags & GPGCONF_FLAG_GROUP ) { 00208 if ( mCurrentGroup && !mCurrentGroup->mEntries.isEmpty() ) // only add non-empty groups 00209 mGroups.insert( mCurrentGroupName, mCurrentGroup ); 00210 //else 00211 // kdDebug(5150) << "Discarding empty group " << mCurrentGroupName << endl; 00212 mCurrentGroup = new QGpgMECryptoConfigGroup( lst[3], level ); 00213 mCurrentGroupName = lst[0]; 00214 } else { 00215 // normal entry 00216 if ( !mCurrentGroup ) { // first toplevel entry -> create toplevel group 00217 mCurrentGroup = new QGpgMECryptoConfigGroup( QString::null, 0 ); 00218 mCurrentGroupName = "<nogroup>"; 00219 } 00220 mCurrentGroup->mEntries.insert( lst[0], new QGpgMECryptoConfigEntry( lst ) ); 00221 } 00222 } else { 00223 // This happens on lines like 00224 // dirmngr[31465]: error opening `/home/dfaure/.gnupg/dirmngr_ldapservers.conf': No such file or directory 00225 // so let's not bother the user with it. 00226 //kdWarning(5150) << "Parse error on gpgconf --list-options output: " << line << endl; 00227 } 00228 } 00229 } 00230 00231 QStringList QGpgMECryptoConfigComponent::groupList() const 00232 { 00233 QDictIterator<QGpgMECryptoConfigGroup> it( mGroups ); 00234 QStringList names; 00235 for( ; it.current(); ++it ) 00236 names.push_back( it.currentKey() ); 00237 return names; 00238 } 00239 00240 Kleo::CryptoConfigGroup* QGpgMECryptoConfigComponent::group(const QString& name ) const 00241 { 00242 return mGroups.find( name ); 00243 } 00244 00245 void QGpgMECryptoConfigComponent::sync( bool runtime ) 00246 { 00247 KTempFile tmpFile; 00248 tmpFile.setAutoDelete( true ); 00249 00250 QValueList<QGpgMECryptoConfigEntry *> dirtyEntries; 00251 00252 // Collect all dirty entries 00253 QDictIterator<QGpgMECryptoConfigGroup> groupit( mGroups ); 00254 for( ; groupit.current(); ++groupit ) { 00255 QDictIterator<QGpgMECryptoConfigEntry> it( groupit.current()->mEntries ); 00256 for( ; it.current(); ++it ) { 00257 if ( it.current()->isDirty() ) { 00258 // OK, we can set it.currentKey() to it.current()->outputString() 00259 QString line = it.currentKey(); 00260 if ( it.current()->isSet() ) { // set option 00261 line += ":0:"; 00262 line += it.current()->outputString(); 00263 } else { // unset option 00264 line += ":16:"; 00265 } 00266 line += '\n'; 00267 QCString line8bit = line.utf8(); // encode with utf8, and KProcIO uses utf8 when reading. 00268 tmpFile.file()->writeBlock( line8bit.data(), line8bit.size()-1 /*no 0*/ ); 00269 dirtyEntries.append( it.current() ); 00270 } 00271 } 00272 } 00273 tmpFile.close(); 00274 if ( dirtyEntries.isEmpty() ) 00275 return; 00276 00277 // Call gpgconf --change-options <component> 00278 QString commandLine = "gpgconf"; 00279 if ( runtime ) 00280 commandLine += " --runtime"; 00281 commandLine += " --change-options "; 00282 commandLine += KProcess::quote( mName ); 00283 commandLine += " < "; 00284 commandLine += KProcess::quote( tmpFile.name() ); 00285 00286 //kdDebug(5150) << commandLine << endl; 00287 //system( QCString( "cat " ) + tmpFile.name().latin1() ); // DEBUG 00288 00289 KProcess proc; 00290 proc.setUseShell( true ); 00291 proc << commandLine; 00292 00293 // run the process: 00294 int rc = 0; 00295 if ( !proc.start( KProcess::Block ) ) 00296 rc = -1; 00297 else 00298 rc = ( proc.normalExit() ) ? proc.exitStatus() : -1 ; 00299 00300 if ( rc == -1 ) 00301 { 00302 QString wmsg = i18n( "Could not start gpgconf\nCheck that gpgconf is in the PATH and that it can be started" ); 00303 kdWarning(5150) << wmsg << endl; 00304 KMessageBox::error(0, wmsg); 00305 } 00306 else if( rc != 0 ) // Happens due to bugs in gpgconf (e.g. issues 104/115) 00307 { 00308 QString wmsg = i18n( "Error from gpgconf while saving configuration: %1" ).arg( strerror( rc ) ); 00309 kdWarning(5150) << k_funcinfo << ":" << strerror( rc ) << endl; 00310 KMessageBox::error(0, wmsg); 00311 } 00312 else 00313 { 00314 QValueList<QGpgMECryptoConfigEntry *>::Iterator it = dirtyEntries.begin(); 00315 for( ; it != dirtyEntries.end(); ++it ) { 00316 (*it)->setDirty( false ); 00317 } 00318 } 00319 } 00320 00322 00323 QGpgMECryptoConfigGroup::QGpgMECryptoConfigGroup( const QString& description, int level ) 00324 : mEntries( 29 ), 00325 mDescription( description ), 00326 mLevel( static_cast<Kleo::CryptoConfigEntry::Level>( level ) ) 00327 { 00328 mEntries.setAutoDelete( true ); 00329 } 00330 00331 QStringList QGpgMECryptoConfigGroup::entryList() const 00332 { 00333 QDictIterator<QGpgMECryptoConfigEntry> it( mEntries ); 00334 QStringList names; 00335 for( ; it.current(); ++it ) 00336 names.push_back( it.currentKey() ); 00337 return names; 00338 } 00339 00340 Kleo::CryptoConfigEntry* QGpgMECryptoConfigGroup::entry( const QString& name ) const 00341 { 00342 return mEntries.find( name ); 00343 } 00344 00346 00347 static QString gpgconf_unescape( const QString& str ) 00348 { 00349 // Looks like it's the same rules as KURL. 00350 return KURL::decode_string( str, 106 ); 00351 } 00352 00353 static QString gpgconf_escape( const QString& str ) 00354 { 00355 // Escape special chars (including ':' and '%') 00356 QString enc = KURL::encode_string( str, 106 ); // and convert to utf8 first (to get %12%34 for one special char) 00357 // Also encode commas, for lists. 00358 enc.replace( ',', "%2c" ); 00359 return enc; 00360 } 00361 00362 static QString urlpart_encode( const QString& str ) 00363 { 00364 QString enc( str ); 00365 enc.replace( '%', "%25" ); // first! 00366 enc.replace( ':', "%3a" ); 00367 //kdDebug() << " urlpart_encode: " << str << " -> " << enc << endl; 00368 return enc; 00369 } 00370 00371 static QString urlpart_decode( const QString& str ) 00372 { 00373 return KURL::decode_string( str ); 00374 } 00375 00376 // gpgconf arg type number -> CryptoConfigEntry arg type enum mapping 00377 static Kleo::CryptoConfigEntry::ArgType knownArgType( int argType, bool& ok ) { 00378 ok = true; 00379 switch( argType ) { 00380 case 0: // none 00381 return Kleo::CryptoConfigEntry::ArgType_None; 00382 case 1: // string 00383 return Kleo::CryptoConfigEntry::ArgType_String; 00384 case 2: // int32 00385 return Kleo::CryptoConfigEntry::ArgType_Int; 00386 case 3: // uint32 00387 return Kleo::CryptoConfigEntry::ArgType_UInt; 00388 case 32: // pathname 00389 return Kleo::CryptoConfigEntry::ArgType_Path; 00390 case 33: // ldap server 00391 return Kleo::CryptoConfigEntry::ArgType_LDAPURL; 00392 default: 00393 ok = false; 00394 return Kleo::CryptoConfigEntry::ArgType_None; 00395 } 00396 } 00397 00398 QGpgMECryptoConfigEntry::QGpgMECryptoConfigEntry( const QStringList& parsedLine ) 00399 { 00400 // Format: NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:ARGDEF:VALUE 00401 assert( parsedLine.count() >= 10 ); // called checked for it already 00402 QStringList::const_iterator it = parsedLine.begin(); 00403 ++it; // skip name, stored in group 00404 mFlags = (*it++).toInt(); 00405 mLevel = (*it++).toInt(); 00406 mDescription = (*it++); 00407 bool ok; 00408 // we keep the real (int) arg type, since it influences the parsing (e.g. for ldap urls) 00409 mRealArgType = (*it++).toInt(); 00410 mArgType = knownArgType( mRealArgType, ok ); 00411 if ( !ok && !(*it).isEmpty() ) { 00412 // use ALT-TYPE 00413 mRealArgType = (*it).toInt(); 00414 mArgType = knownArgType( mRealArgType, ok ); 00415 } 00416 if ( !ok ) 00417 kdWarning(5150) << "Unsupported datatype: " << parsedLine[4] << " : " << *it << " for " << parsedLine[0] << endl; 00418 ++it; // done with alt-type 00419 ++it; // skip argname (not useful in GUIs) 00420 00421 mSet = false; 00422 QString value; 00423 if ( mFlags & GPGCONF_FLAG_DEFAULT ) { 00424 value = *it; // get default value 00425 mDefaultValue = stringToValue( value, true ); 00426 } 00427 ++it; // done with DEFAULT 00428 ++it; // ### skip ARGDEF for now. It's only for options with an "optional arg" 00429 //kdDebug(5150) << "Entry " << parsedLine[0] << " val=" << *it << endl; 00430 00431 if ( !(*it).isEmpty() ) { // a real value was set 00432 mSet = true; 00433 value = *it; 00434 mValue = stringToValue( value, true ); 00435 } 00436 else { 00437 mValue = mDefaultValue; 00438 } 00439 00440 mDirty = false; 00441 } 00442 00443 QVariant QGpgMECryptoConfigEntry::stringToValue( const QString& str, bool unescape ) const 00444 { 00445 bool isString = isStringType(); 00446 00447 if ( isList() ) { 00448 QValueList<QVariant> lst; 00449 QStringList items = QStringList::split( ',', str ); 00450 for( QStringList::const_iterator valit = items.begin(); valit != items.end(); ++valit ) { 00451 QString val = *valit; 00452 if ( isString ) { 00453 if ( val.isEmpty() ) { 00454 lst << QString::null; 00455 continue; 00456 } 00457 else if ( unescape ) { 00458 if( val[0] != '"' ) // see README.gpgconf 00459 kdWarning(5150) << "String value should start with '\"' : " << val << endl; 00460 val = val.mid( 1 ); 00461 } 00462 } 00463 lst << QVariant( unescape ? gpgconf_unescape( val ) : val ); 00464 } 00465 return lst; 00466 } else { // not a list 00467 QString val( str ); 00468 if ( isString ) { 00469 if ( val.isEmpty() ) 00470 return QVariant( QString::null ); // not set [ok with lists too?] 00471 else if ( unescape ) { 00472 Q_ASSERT( val[0] == '"' ); // see README.gpgconf 00473 val = val.mid( 1 ); 00474 } 00475 } 00476 return QVariant( unescape ? gpgconf_unescape( val ) : val ); 00477 } 00478 } 00479 00480 QGpgMECryptoConfigEntry::~QGpgMECryptoConfigEntry() 00481 { 00482 #ifndef NDEBUG 00483 if ( !s_duringClear && mDirty ) 00484 kdWarning(5150) << "Deleting a QGpgMECryptoConfigEntry that was modified (" << mDescription << ")\n" 00485 << "You forgot to call sync() (to commit) or clear() (to discard)" << endl; 00486 #endif 00487 } 00488 00489 bool QGpgMECryptoConfigEntry::isOptional() const 00490 { 00491 return mFlags & GPGCONF_FLAG_OPTIONAL; 00492 } 00493 00494 bool QGpgMECryptoConfigEntry::isList() const 00495 { 00496 return mFlags & GPGCONF_FLAG_LIST; 00497 } 00498 00499 bool QGpgMECryptoConfigEntry::isRuntime() const 00500 { 00501 return mFlags & GPGCONF_FLAG_RUNTIME; 00502 } 00503 00504 bool QGpgMECryptoConfigEntry::isSet() const 00505 { 00506 return mSet; 00507 } 00508 00509 bool QGpgMECryptoConfigEntry::boolValue() const 00510 { 00511 Q_ASSERT( mArgType == ArgType_None ); 00512 Q_ASSERT( !isList() ); 00513 return mValue.toBool(); 00514 } 00515 00516 QString QGpgMECryptoConfigEntry::stringValue() const 00517 { 00518 return toString( false ); 00519 } 00520 00521 int QGpgMECryptoConfigEntry::intValue() const 00522 { 00523 Q_ASSERT( mArgType == ArgType_Int ); 00524 Q_ASSERT( !isList() ); 00525 return mValue.toInt(); 00526 } 00527 00528 unsigned int QGpgMECryptoConfigEntry::uintValue() const 00529 { 00530 Q_ASSERT( mArgType == ArgType_UInt ); 00531 Q_ASSERT( !isList() ); 00532 return mValue.toUInt(); 00533 } 00534 00535 static KURL parseURL( int mRealArgType, const QString& str ) 00536 { 00537 if ( mRealArgType == 33 ) { // LDAP server 00538 // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN 00539 QStringList items = QStringList::split( ':', str, true ); 00540 if ( items.count() == 5 ) { 00541 QStringList::const_iterator it = items.begin(); 00542 KURL url; 00543 url.setProtocol( "ldap" ); 00544 url.setHost( urlpart_decode( *it++ ) ); 00545 url.setPort( (*it++).toInt() ); 00546 url.setPath( "/" ); // workaround KURL parsing bug 00547 url.setUser( urlpart_decode( *it++ ) ); 00548 url.setPass( urlpart_decode( *it++ ) ); 00549 url.setQuery( urlpart_decode( *it ) ); 00550 return url; 00551 } else 00552 kdWarning(5150) << "parseURL: malformed LDAP server: " << str << endl; 00553 } 00554 // other URLs : assume wellformed URL syntax. 00555 return KURL( str ); 00556 } 00557 00558 // The opposite of parseURL 00559 static QString splitURL( int mRealArgType, const KURL& url ) 00560 { 00561 if ( mRealArgType == 33 ) { // LDAP server 00562 // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN 00563 Q_ASSERT( url.protocol() == "ldap" ); 00564 return urlpart_encode( url.host() ) + ":" + 00565 QString::number( url.port() ) + ":" + 00566 urlpart_encode( url.user() ) + ":" + 00567 urlpart_encode( url.pass() ) + ":" + 00568 // KURL automatically encoded the query (e.g. for spaces inside it), 00569 // so decode it before writing it out to gpgconf (issue119) 00570 urlpart_encode( KURL::decode_string( url.query().mid(1) ) ); 00571 } 00572 return url.path(); 00573 } 00574 00575 KURL QGpgMECryptoConfigEntry::urlValue() const 00576 { 00577 Q_ASSERT( mArgType == ArgType_Path || mArgType == ArgType_URL || mArgType == ArgType_LDAPURL ); 00578 Q_ASSERT( !isList() ); 00579 QString str = mValue.toString(); 00580 if ( mArgType == ArgType_Path ) 00581 { 00582 KURL url; 00583 url.setPath( str ); 00584 return url; 00585 } 00586 return parseURL( mRealArgType, str ); 00587 } 00588 00589 unsigned int QGpgMECryptoConfigEntry::numberOfTimesSet() const 00590 { 00591 Q_ASSERT( mArgType == ArgType_None ); 00592 Q_ASSERT( isList() ); 00593 return mValue.toUInt(); 00594 } 00595 00596 QStringList QGpgMECryptoConfigEntry::stringValueList() const 00597 { 00598 Q_ASSERT( isStringType() ); 00599 Q_ASSERT( isList() ); 00600 return mValue.toStringList(); 00601 } 00602 00603 QValueList<int> QGpgMECryptoConfigEntry::intValueList() const 00604 { 00605 Q_ASSERT( mArgType == ArgType_Int ); 00606 Q_ASSERT( isList() ); 00607 QValueList<int> ret; 00608 QValueList<QVariant> lst = mValue.toList(); 00609 for( QValueList<QVariant>::const_iterator it = lst.begin(); it != lst.end(); ++it ) { 00610 ret.append( (*it).toInt() ); 00611 } 00612 return ret; 00613 } 00614 00615 QValueList<unsigned int> QGpgMECryptoConfigEntry::uintValueList() const 00616 { 00617 Q_ASSERT( mArgType == ArgType_UInt ); 00618 Q_ASSERT( isList() ); 00619 QValueList<unsigned int> ret; 00620 QValueList<QVariant> lst = mValue.toList(); 00621 for( QValueList<QVariant>::const_iterator it = lst.begin(); it != lst.end(); ++it ) { 00622 ret.append( (*it).toUInt() ); 00623 } 00624 return ret; 00625 } 00626 00627 KURL::List QGpgMECryptoConfigEntry::urlValueList() const 00628 { 00629 Q_ASSERT( mArgType == ArgType_Path || mArgType == ArgType_URL || mArgType == ArgType_LDAPURL ); 00630 Q_ASSERT( isList() ); 00631 QStringList lst = mValue.toStringList(); 00632 00633 KURL::List ret; 00634 for( QStringList::const_iterator it = lst.begin(); it != lst.end(); ++it ) { 00635 if ( mArgType == ArgType_Path ) { 00636 KURL url; 00637 url.setPath( *it ); 00638 ret << url; 00639 } else { 00640 ret << parseURL( mRealArgType, *it ); 00641 } 00642 } 00643 return ret; 00644 } 00645 00646 void QGpgMECryptoConfigEntry::resetToDefault() 00647 { 00648 mSet = false; 00649 mDirty = true; 00650 if ( mFlags & GPGCONF_FLAG_DEFAULT ) 00651 mValue = mDefaultValue; 00652 else if ( mArgType == ArgType_None ) 00653 mValue = false; 00654 } 00655 00656 void QGpgMECryptoConfigEntry::setBoolValue( bool b ) 00657 { 00658 Q_ASSERT( mArgType == ArgType_None ); 00659 Q_ASSERT( !isList() ); 00660 // A "no arg" option is either set or not set. 00661 // Being set means mSet==true + mValue==true, being unset means resetToDefault(), i.e. both false 00662 mValue = b; 00663 mSet = b; 00664 mDirty = true; 00665 } 00666 00667 void QGpgMECryptoConfigEntry::setStringValue( const QString& str ) 00668 { 00669 mValue = stringToValue( str, false ); 00670 // When setting a string to empty (and there's no default), we need to act like resetToDefault 00671 // Otherwise we try e.g. "ocsp-responder:0:" and gpgconf answers: 00672 // "gpgconf: argument required for option ocsp-responder" 00673 if ( str.isEmpty() && !isOptional() ) 00674 mSet = false; 00675 else 00676 mSet = true; 00677 mDirty = true; 00678 } 00679 00680 void QGpgMECryptoConfigEntry::setIntValue( int i ) 00681 { 00682 Q_ASSERT( mArgType == ArgType_Int ); 00683 Q_ASSERT( !isList() ); 00684 mValue = i; 00685 mSet = true; 00686 mDirty = true; 00687 } 00688 00689 void QGpgMECryptoConfigEntry::setUIntValue( unsigned int i ) 00690 { 00691 mValue = i; 00692 mSet = true; 00693 mDirty = true; 00694 } 00695 00696 void QGpgMECryptoConfigEntry::setURLValue( const KURL& url ) 00697 { 00698 QString str = splitURL( mRealArgType, url ); 00699 if ( str.isEmpty() && !isOptional() ) 00700 mSet = false; 00701 else 00702 mSet = true; 00703 mValue = str; 00704 mDirty = true; 00705 } 00706 00707 void QGpgMECryptoConfigEntry::setNumberOfTimesSet( unsigned int i ) 00708 { 00709 Q_ASSERT( mArgType == ArgType_None ); 00710 Q_ASSERT( isList() ); 00711 setUIntValue( i ); 00712 } 00713 00714 void QGpgMECryptoConfigEntry::setStringValueList( const QStringList& lst ) 00715 { 00716 mValue = lst; 00717 if ( lst.isEmpty() && !isOptional() ) 00718 mSet = false; 00719 else 00720 mSet = true; 00721 mDirty = true; 00722 } 00723 00724 void QGpgMECryptoConfigEntry::setIntValueList( const QValueList<int>& lst ) 00725 { 00726 QValueList<QVariant> ret; 00727 for( QValueList<int>::const_iterator it = lst.begin(); it != lst.end(); ++it ) { 00728 ret << QVariant( *it ); 00729 } 00730 mValue = ret; 00731 if ( ret.isEmpty() && !isOptional() ) 00732 mSet = false; 00733 else 00734 mSet = true; 00735 mDirty = true; 00736 } 00737 00738 void QGpgMECryptoConfigEntry::setUIntValueList( const QValueList<unsigned int>& lst ) 00739 { 00740 QValueList<QVariant> ret; 00741 for( QValueList<unsigned int>::const_iterator it = lst.begin(); it != lst.end(); ++it ) { 00742 ret << QVariant( *it ); 00743 } 00744 if ( ret.isEmpty() && !isOptional() ) 00745 mSet = false; 00746 else 00747 mSet = true; 00748 mValue = ret; 00749 mDirty = true; 00750 } 00751 00752 void QGpgMECryptoConfigEntry::setURLValueList( const KURL::List& urls ) 00753 { 00754 QStringList lst; 00755 for( KURL::List::const_iterator it = urls.begin(); it != urls.end(); ++it ) { 00756 lst << splitURL( mRealArgType, *it ); 00757 } 00758 mValue = lst; 00759 if ( lst.isEmpty() && !isOptional() ) 00760 mSet = false; 00761 else 00762 mSet = true; 00763 mDirty = true; 00764 } 00765 00766 QString QGpgMECryptoConfigEntry::toString( bool escape ) const 00767 { 00768 // Basically the opposite of stringToValue 00769 if ( isStringType() ) { 00770 if ( mValue.isNull() ) 00771 return QString::null; 00772 else if ( isList() ) { // string list 00773 QStringList lst = mValue.toStringList(); 00774 if ( escape ) { 00775 for( QStringList::iterator it = lst.begin(); it != lst.end(); ++it ) { 00776 if ( !(*it).isNull() ) 00777 *it = gpgconf_escape( *it ).prepend( "\"" ); 00778 } 00779 } 00780 QString res = lst.join( "," ); 00781 kdDebug(5150) << "toString: " << res << endl; 00782 return res; 00783 } else { // normal string 00784 QString res = mValue.toString(); 00785 if ( escape ) 00786 res = gpgconf_escape( res ).prepend( "\"" ); 00787 return res; 00788 } 00789 } 00790 if ( !isList() ) // non-list non-string 00791 { 00792 if ( mArgType == ArgType_None ) { 00793 return mValue.toBool() ? QString::fromLatin1( "1" ) : QString::null; 00794 } else { // some int 00795 Q_ASSERT( mArgType == ArgType_Int || mArgType == ArgType_UInt ); 00796 return mValue.toString(); // int to string conversion 00797 } 00798 } 00799 00800 // Lists (of other types than strings) 00801 if ( mArgType == ArgType_None ) 00802 return QString::number( numberOfTimesSet() ); 00803 QStringList ret; 00804 QValueList<QVariant> lst = mValue.toList(); 00805 for( QValueList<QVariant>::const_iterator it = lst.begin(); it != lst.end(); ++it ) { 00806 ret << (*it).toString(); // QVariant does the conversion 00807 } 00808 return ret.join( "," ); 00809 } 00810 00811 QString QGpgMECryptoConfigEntry::outputString() const 00812 { 00813 Q_ASSERT( mSet ); 00814 return toString( true ); 00815 } 00816 00817 bool QGpgMECryptoConfigEntry::isStringType() const 00818 { 00819 return ( mArgType == Kleo::CryptoConfigEntry::ArgType_String 00820 || mArgType == Kleo::CryptoConfigEntry::ArgType_Path 00821 || mArgType == Kleo::CryptoConfigEntry::ArgType_URL 00822 || mArgType == Kleo::CryptoConfigEntry::ArgType_LDAPURL ); 00823 } 00824 00825 void QGpgMECryptoConfigEntry::setDirty( bool b ) 00826 { 00827 mDirty = b; 00828 } 00829 00830 #include "qgpgmecryptoconfig.moc"
KDE Logo
This file is part of the documentation for certmanager Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 1 15:18:47 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003