33 #include "qgpgmecryptoconfig.h"
37 #include <tdemessagebox.h>
38 #include <tdelocale.h>
41 #include <tdetempfile.h>
44 #include <tqtextcodec.h>
48 static bool s_duringClear =
false;
50 static const int GPGCONF_FLAG_GROUP = 1;
51 static const int GPGCONF_FLAG_OPTIONAL = 2;
52 static const int GPGCONF_FLAG_LIST = 4;
53 static const int GPGCONF_FLAG_RUNTIME = 8;
54 static const int GPGCONF_FLAG_DEFAULT = 16;
55 static const int GPGCONF_FLAG_DEFAULT_DESC = 32;
56 static const int GPGCONF_FLAG_NOARG_DESC = 64;
57 static const int GPGCONF_FLAG_NO_CHANGE = 128;
61 : mComponents( 7 ), mParsed( false )
63 mComponents.setAutoDelete(
true );
66 QGpgMECryptoConfig::~QGpgMECryptoConfig()
70 void QGpgMECryptoConfig::runGpgConf(
bool showErrors )
74 KProcIO proc( TQTextCodec::codecForName(
"utf8" ) );
76 proc <<
"--list-components";
78 TQObject::connect( &proc, TQT_SIGNAL( readReady(KProcIO*) ),
79 this, TQT_SLOT( slotCollectStdOut(KProcIO*) ) );
83 if ( !proc.start( TDEProcess::Block ) )
86 rc = ( proc.normalExit() ) ? proc.exitStatus() : -2 ;
89 if ( showErrors && rc != 0 ) {
90 TQString wmsg = i18n(
"<qt>Failed to execute gpgconf:<br>%1</qt>");
92 wmsg = wmsg.arg( i18n(
"program not found" ) );
94 wmsg = wmsg.arg( i18n(
"program cannot be executed" ) );
96 wmsg = wmsg.arg( strerror(rc) );
97 kdWarning(5150) << wmsg << endl;
98 KMessageBox::error(0, wmsg);
103 void QGpgMECryptoConfig::slotCollectStdOut( KProcIO* proc )
107 while( ( result = proc->readln(line) ) != -1 ) {
110 TQStringList lst = TQStringList::split(
':', line,
true );
111 if ( lst.count() >= 2 ) {
114 kdWarning(5150) <<
"Parse error on gpgconf --list-components output: " << line << endl;
123 TQDictIterator<QGpgMECryptoConfigComponent> it( mComponents );
125 for( ; it.current(); ++it )
126 names.push_back( it.currentKey() );
134 return mComponents.find( name );
139 TQDictIterator<QGpgMECryptoConfigComponent> it( mComponents );
140 for( ; it.current(); ++it )
141 it.current()->sync( runtime );
146 s_duringClear =
true;
148 s_duringClear =
false;
154 QGpgMECryptoConfigComponent::QGpgMECryptoConfigComponent(
QGpgMECryptoConfig*,
const TQString& name,
const TQString& description )
155 : mGroups( 7 ), mName( name ), mDescription( description )
157 mGroups.setAutoDelete(
true );
161 QGpgMECryptoConfigComponent::~QGpgMECryptoConfigComponent()
165 void QGpgMECryptoConfigComponent::runGpgConf()
169 KProcIO proc( TQTextCodec::codecForName(
"utf8" ) );
171 proc <<
"--list-options";
176 TQObject::connect( &proc, TQT_SIGNAL( readReady(KProcIO*) ),
177 this, TQT_SLOT( slotCollectStdOut(KProcIO*) ) );
182 if ( !proc.start( TDEProcess::Block ) )
185 rc = ( proc.normalExit() ) ? proc.exitStatus() : -1 ;
188 kdWarning(5150) <<
"Running 'gpgconf --list-options " << mName <<
"' failed. " << strerror( rc ) <<
", but try that command to see the real output" << endl;
190 if ( mCurrentGroup && !mCurrentGroup->mEntries.isEmpty() )
191 mGroups.insert( mCurrentGroupName, mCurrentGroup );
195 void QGpgMECryptoConfigComponent::slotCollectStdOut( KProcIO* proc )
199 while( ( result = proc->readln(line) ) != -1 ) {
202 const TQStringList lst = TQStringList::split(
':', line,
true );
203 if ( lst.count() >= 10 ) {
204 const int flags = lst[1].toInt();
205 const int level = lst[2].toInt();
208 if ( flags & GPGCONF_FLAG_GROUP ) {
209 if ( mCurrentGroup && !mCurrentGroup->mEntries.isEmpty() )
210 mGroups.insert( mCurrentGroupName, mCurrentGroup );
213 mCurrentGroup =
new QGpgMECryptoConfigGroup( lst[0], lst[3], level );
214 mCurrentGroupName = lst[0];
217 if ( !mCurrentGroup ) {
218 mCurrentGroup =
new QGpgMECryptoConfigGroup(
"<nogroup>", TQString(), 0 );
219 mCurrentGroupName =
"<nogroup>";
221 mCurrentGroup->mEntries.insert( lst[0],
new QGpgMECryptoConfigEntry( lst ) );
234 TQDictIterator<QGpgMECryptoConfigGroup> it( mGroups );
236 for( ; it.current(); ++it )
237 names.push_back( it.currentKey() );
243 return mGroups.find( name );
246 void QGpgMECryptoConfigComponent::sync(
bool runtime )
249 tmpFile.setAutoDelete(
true );
251 TQValueList<QGpgMECryptoConfigEntry *> dirtyEntries;
254 TQDictIterator<QGpgMECryptoConfigGroup> groupit( mGroups );
255 for( ; groupit.current(); ++groupit ) {
256 TQDictIterator<QGpgMECryptoConfigEntry> it( groupit.current()->mEntries );
257 for( ; it.current(); ++it ) {
258 if ( it.current()->isDirty() ) {
260 TQString line = it.currentKey();
261 if ( it.current()->isSet() ) {
263 line += it.current()->outputString();
268 TQCString line8bit = line.utf8();
269 tmpFile.file()->writeBlock( line8bit.data(), line8bit.size()-1 );
270 dirtyEntries.append( it.current() );
275 if ( dirtyEntries.isEmpty() )
279 TQString commandLine =
"gpgconf";
281 commandLine +=
" --runtime";
282 commandLine +=
" --change-options ";
283 commandLine += TDEProcess::quote( mName );
284 commandLine +=
" < ";
285 commandLine += TDEProcess::quote( tmpFile.name() );
291 proc.setUseShell(
true );
296 if ( !proc.start( TDEProcess::Block ) )
299 rc = ( proc.normalExit() ) ? proc.exitStatus() : -1 ;
303 TQString wmsg = i18n(
"Could not start gpgconf\nCheck that gpgconf is in the PATH and that it can be started" );
304 kdWarning(5150) << wmsg << endl;
305 KMessageBox::error(0, wmsg);
309 TQString wmsg = i18n(
"Error from gpgconf while saving configuration: %1" ).arg( TQString::fromLocal8Bit( strerror( rc ) ) );
310 kdWarning(5150) << k_funcinfo <<
":" << strerror( rc ) << endl;
311 KMessageBox::error(0, wmsg);
315 TQValueList<QGpgMECryptoConfigEntry *>::Iterator it = dirtyEntries.begin();
316 for( ; it != dirtyEntries.end(); ++it ) {
317 (*it)->setDirty(
false );
324 QGpgMECryptoConfigGroup::QGpgMECryptoConfigGroup(
const TQString & name,
const TQString& description,
int level )
327 mDescription( description ),
328 mLevel( static_cast<
Kleo::CryptoConfigEntry::Level>( level ) )
330 mEntries.setAutoDelete(
true );
333 TQStringList QGpgMECryptoConfigGroup::entryList()
const
335 TQDictIterator<QGpgMECryptoConfigEntry> it( mEntries );
337 for( ; it.current(); ++it )
338 names.push_back( it.currentKey() );
344 return mEntries.find( name );
349 static TQString gpgconf_unescape(
const TQString& str )
352 return KURL::decode_string( str, 106 );
355 static TQString gpgconf_escape(
const TQString& str )
358 TQString enc = KURL::encode_string( str, 106 );
360 enc.replace(
',',
"%2c" );
364 static TQString urlpart_encode(
const TQString& str )
367 enc.replace(
'%',
"%25" );
368 enc.replace(
':',
"%3a" );
373 static TQString urlpart_decode(
const TQString& str )
375 return KURL::decode_string( str );
383 return Kleo::CryptoConfigEntry::ArgType_None;
385 return Kleo::CryptoConfigEntry::ArgType_String;
387 return Kleo::CryptoConfigEntry::ArgType_Int;
389 return Kleo::CryptoConfigEntry::ArgType_UInt;
391 return Kleo::CryptoConfigEntry::ArgType_Path;
393 return Kleo::CryptoConfigEntry::ArgType_LDAPURL;
396 return Kleo::CryptoConfigEntry::ArgType_None;
400 QGpgMECryptoConfigEntry::QGpgMECryptoConfigEntry(
const TQStringList& parsedLine )
403 assert( parsedLine.count() >= 10 );
404 TQStringList::const_iterator it = parsedLine.begin();
406 mFlags = (*it++).toInt();
407 mLevel = (*it++).toInt();
408 mDescription = *it++;
411 mRealArgType = (*it++).toInt();
412 mArgType = knownArgType( mRealArgType, ok );
413 if ( !ok && !(*it).isEmpty() ) {
415 mRealArgType = (*it).toInt();
416 mArgType = knownArgType( mRealArgType, ok );
419 kdWarning(5150) <<
"Unsupported datatype: " << parsedLine[4] <<
" : " << *it <<
" for " << parsedLine[0] << endl;
425 if ( mFlags & GPGCONF_FLAG_DEFAULT ) {
427 mDefaultValue = stringToValue( value,
true );
433 if ( !(*it).isEmpty() ) {
436 mValue = stringToValue( value,
true );
439 mValue = mDefaultValue;
445 TQVariant QGpgMECryptoConfigEntry::stringToValue(
const TQString& str,
bool unescape )
const
447 bool isString = isStringType();
450 if ( argType() == ArgType_None ) {
452 const TQVariant v = str.isEmpty() ? 0U : str.toUInt( &ok ) ;
454 kdWarning(5150) <<
"list-of-none should have an unsigned int as value:" << str << endl;
457 TQValueList<TQVariant> lst;
458 TQStringList items = TQStringList::split(
',', str );
459 for( TQStringList::const_iterator valit = items.begin(); valit != items.end(); ++valit ) {
460 TQString val = *valit;
462 if ( val.isEmpty() ) {
466 else if ( unescape ) {
468 kdWarning(5150) <<
"String value should start with '\"' : " << val << endl;
472 lst << TQVariant( unescape ? gpgconf_unescape( val ) : val );
479 return TQVariant( TQString() );
480 else if ( unescape ) {
481 Q_ASSERT( val[0] ==
'"' );
485 return TQVariant( unescape ? gpgconf_unescape( val ) : val );
489 QGpgMECryptoConfigEntry::~QGpgMECryptoConfigEntry()
492 if ( !s_duringClear && mDirty )
493 kdWarning(5150) <<
"Deleting a QGpgMECryptoConfigEntry that was modified (" << mDescription <<
")\n"
494 <<
"You forgot to call sync() (to commit) or clear() (to discard)" << endl;
498 bool QGpgMECryptoConfigEntry::isOptional()
const
500 return mFlags & GPGCONF_FLAG_OPTIONAL;
503 bool QGpgMECryptoConfigEntry::isReadOnly()
const
505 return mFlags & GPGCONF_FLAG_NO_CHANGE;
508 bool QGpgMECryptoConfigEntry::isList()
const
510 return mFlags & GPGCONF_FLAG_LIST;
513 bool QGpgMECryptoConfigEntry::isRuntime()
const
515 return mFlags & GPGCONF_FLAG_RUNTIME;
518 bool QGpgMECryptoConfigEntry::isSet()
const
523 bool QGpgMECryptoConfigEntry::boolValue()
const
525 Q_ASSERT( mArgType == ArgType_None );
526 Q_ASSERT( !isList() );
527 return mValue.toBool();
530 TQString QGpgMECryptoConfigEntry::stringValue()
const
532 return toString(
false );
535 int QGpgMECryptoConfigEntry::intValue()
const
537 Q_ASSERT( mArgType == ArgType_Int );
538 Q_ASSERT( !isList() );
539 return mValue.toInt();
542 unsigned int QGpgMECryptoConfigEntry::uintValue()
const
544 Q_ASSERT( mArgType == ArgType_UInt );
545 Q_ASSERT( !isList() );
546 return mValue.toUInt();
549 static KURL parseURL(
int mRealArgType,
const TQString& str )
551 if ( mRealArgType == 33 ) {
553 TQStringList items = TQStringList::split(
':', str,
true );
554 if ( items.count() == 5 ) {
555 TQStringList::const_iterator it = items.begin();
557 url.setProtocol(
"ldap" );
558 url.setHost( urlpart_decode( *it++ ) );
559 url.setPort( (*it++).toInt() );
561 url.setUser( urlpart_decode( *it++ ) );
562 url.setPass( urlpart_decode( *it++ ) );
563 url.setQuery( urlpart_decode( *it ) );
566 kdWarning(5150) <<
"parseURL: malformed LDAP server: " << str << endl;
573 static TQString splitURL(
int mRealArgType,
const KURL& url )
575 if ( mRealArgType == 33 ) {
577 Q_ASSERT( url.protocol() ==
"ldap" );
578 return urlpart_encode( url.host() ) +
":" +
579 TQString::number( url.port() ) +
":" +
580 urlpart_encode( url.user() ) +
":" +
581 urlpart_encode( url.pass() ) +
":" +
584 urlpart_encode( KURL::decode_string( url.query().mid(1) ) );
589 KURL QGpgMECryptoConfigEntry::urlValue()
const
591 Q_ASSERT( mArgType == ArgType_Path || mArgType == ArgType_URL || mArgType == ArgType_LDAPURL );
592 Q_ASSERT( !isList() );
593 TQString str = mValue.toString();
594 if ( mArgType == ArgType_Path )
600 return parseURL( mRealArgType, str );
603 unsigned int QGpgMECryptoConfigEntry::numberOfTimesSet()
const
605 Q_ASSERT( mArgType == ArgType_None );
606 Q_ASSERT( isList() );
607 return mValue.toUInt();
610 TQStringList QGpgMECryptoConfigEntry::stringValueList()
const
612 Q_ASSERT( isStringType() );
613 Q_ASSERT( isList() );
614 return mValue.toStringList();
617 TQValueList<int> QGpgMECryptoConfigEntry::intValueList()
const
619 Q_ASSERT( mArgType == ArgType_Int );
620 Q_ASSERT( isList() );
621 TQValueList<int> ret;
622 TQValueList<TQVariant> lst = mValue.toList();
623 for( TQValueList<TQVariant>::const_iterator it = lst.begin(); it != lst.end(); ++it ) {
624 ret.append( (*it).toInt() );
629 TQValueList<unsigned int> QGpgMECryptoConfigEntry::uintValueList()
const
631 Q_ASSERT( mArgType == ArgType_UInt );
632 Q_ASSERT( isList() );
633 TQValueList<unsigned int> ret;
634 TQValueList<TQVariant> lst = mValue.toList();
635 for( TQValueList<TQVariant>::const_iterator it = lst.begin(); it != lst.end(); ++it ) {
636 ret.append( (*it).toUInt() );
641 KURL::List QGpgMECryptoConfigEntry::urlValueList()
const
643 Q_ASSERT( mArgType == ArgType_Path || mArgType == ArgType_URL || mArgType == ArgType_LDAPURL );
644 Q_ASSERT( isList() );
645 TQStringList lst = mValue.toStringList();
648 for( TQStringList::const_iterator it = lst.begin(); it != lst.end(); ++it ) {
649 if ( mArgType == ArgType_Path ) {
654 ret << parseURL( mRealArgType, *it );
660 void QGpgMECryptoConfigEntry::resetToDefault()
664 if ( mFlags & GPGCONF_FLAG_DEFAULT ) {
665 mValue = mDefaultValue;
667 else if ( mArgType == ArgType_None ) {
677 void QGpgMECryptoConfigEntry::setBoolValue(
bool b )
679 Q_ASSERT( mArgType == ArgType_None );
680 Q_ASSERT( !isList() );
688 void QGpgMECryptoConfigEntry::setStringValue(
const TQString& str )
690 mValue = stringToValue( str,
false );
694 if ( str.isEmpty() && !isOptional() )
701 void QGpgMECryptoConfigEntry::setIntValue(
int i )
703 Q_ASSERT( mArgType == ArgType_Int );
704 Q_ASSERT( !isList() );
710 void QGpgMECryptoConfigEntry::setUIntValue(
unsigned int i )
717 void QGpgMECryptoConfigEntry::setURLValue(
const KURL& url )
719 TQString str = splitURL( mRealArgType, url );
720 if ( str.isEmpty() && !isOptional() )
728 void QGpgMECryptoConfigEntry::setNumberOfTimesSet(
unsigned int i )
730 Q_ASSERT( mArgType == ArgType_None );
731 Q_ASSERT( isList() );
737 void QGpgMECryptoConfigEntry::setStringValueList(
const TQStringList& lst )
740 if ( lst.isEmpty() && !isOptional() )
747 void QGpgMECryptoConfigEntry::setIntValueList(
const TQValueList<int>& lst )
749 TQValueList<TQVariant> ret;
750 for( TQValueList<int>::const_iterator it = lst.begin(); it != lst.end(); ++it ) {
751 ret << TQVariant( *it );
754 if ( ret.isEmpty() && !isOptional() )
761 void QGpgMECryptoConfigEntry::setUIntValueList(
const TQValueList<unsigned int>& lst )
763 TQValueList<TQVariant> ret;
764 for( TQValueList<unsigned int>::const_iterator it = lst.begin(); it != lst.end(); ++it ) {
765 ret << TQVariant( *it );
767 if ( ret.isEmpty() && !isOptional() )
775 void QGpgMECryptoConfigEntry::setURLValueList(
const KURL::List& urls )
778 for( KURL::List::const_iterator it = urls.begin(); it != urls.end(); ++it ) {
779 lst << splitURL( mRealArgType, *it );
782 if ( lst.isEmpty() && !isOptional() )
789 TQString QGpgMECryptoConfigEntry::toString(
bool escape )
const
792 if ( isStringType() ) {
793 if ( mValue.isNull() )
795 else if ( isList() ) {
796 TQStringList lst = mValue.toStringList();
798 for( TQStringList::iterator it = lst.begin(); it != lst.end(); ++it ) {
799 if ( !(*it).isNull() )
800 *it = gpgconf_escape( *it ).prepend(
"\"" );
803 TQString res = lst.join(
"," );
804 kdDebug(5150) <<
"toString: " << res << endl;
807 TQString res = mValue.toString();
809 res = gpgconf_escape( res ).prepend(
"\"" );
815 if ( mArgType == ArgType_None ) {
816 return mValue.toBool() ? TQString::fromLatin1(
"1" ) : TQString();
818 Q_ASSERT( mArgType == ArgType_Int || mArgType == ArgType_UInt );
819 return mValue.toString();
824 if ( mArgType == ArgType_None )
825 return TQString::number( numberOfTimesSet() );
827 TQValueList<TQVariant> lst = mValue.toList();
828 for( TQValueList<TQVariant>::const_iterator it = lst.begin(); it != lst.end(); ++it ) {
829 ret << (*it).toString();
831 return ret.join(
"," );
834 TQString QGpgMECryptoConfigEntry::outputString()
const
837 return toString(
true );
840 bool QGpgMECryptoConfigEntry::isStringType()
const
842 return ( mArgType == Kleo::CryptoConfigEntry::ArgType_String
843 || mArgType == Kleo::CryptoConfigEntry::ArgType_Path
844 || mArgType == Kleo::CryptoConfigEntry::ArgType_URL
845 || mArgType == Kleo::CryptoConfigEntry::ArgType_LDAPURL );
848 void QGpgMECryptoConfigEntry::setDirty(
bool b )
853 #include "qgpgmecryptoconfig.moc"
Kleo::CryptoConfigGroup * group(const TQString &name) const
virtual TQStringList componentList() const
Returns the list of known components (e.g.
For docu, see kleo/cryptoconfig.h.
ArgType
Type of the argument.
Crypto config for one component (e.g.
Group containing a set of config options.
virtual Kleo::CryptoConfigComponent * component(const TQString &name) const
virtual void sync(bool runtime)
Write back changes.
CryptoConfig implementation around the gpgconf command-line tool For method docu, see kleo/cryptoconf...
Description of a single option.
QGpgMECryptoConfig()
Constructor.
TQStringList groupList() const
Returns the list of groups that are known about.
virtual void clear()
Tells the CryptoConfig to discard any cached information, including all components, groups and entries.