33#include "qgpgmecryptoconfig.h"
37#include <tdemessagebox.h>
41#include <tdetempfile.h>
44#include <tqtextcodec.h>
48static bool s_duringClear =
false;
50static const int GPGCONF_FLAG_GROUP = 1;
51static const int GPGCONF_FLAG_OPTIONAL = 2;
52static const int GPGCONF_FLAG_LIST = 4;
53static const int GPGCONF_FLAG_RUNTIME = 8;
54static const int GPGCONF_FLAG_DEFAULT = 16;
55static const int GPGCONF_FLAG_DEFAULT_DESC = 32;
56static const int GPGCONF_FLAG_NOARG_DESC = 64;
57static const int GPGCONF_FLAG_NO_CHANGE = 128;
61 : mComponents( 7 ), mParsed( false )
63 mComponents.setAutoDelete(
true );
66QGpgMECryptoConfig::~QGpgMECryptoConfig()
70void QGpgMECryptoConfig::runGpgConf(
bool showErrors )
74 KProcIO proc( TQTextCodec::codecForName(
"utf8" ) );
76 proc <<
"--list-components";
78 TQObject::connect( &proc, TQ_SIGNAL( readReady(KProcIO*) ),
79 this, TQ_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);
103void QGpgMECryptoConfig::slotCollectStdOut( KProcIO* proc )
107 while( ( result = proc->readln(line) ) != -1 ) {
110 TQStringList lst = TQStringList::split(
':', line,
true );
111 if ( lst.count() >= 2 ) {
112 mComponents.insert( lst[0],
new QGpgMECryptoConfigComponent(
this, lst[0], lst[1] ) );
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;
154QGpgMECryptoConfigComponent::QGpgMECryptoConfigComponent(
QGpgMECryptoConfig*,
const TQString& name,
const TQString& description )
155 : mGroups( 7 ), mName( name ), mDescription( description )
157 mGroups.setAutoDelete(
true );
161QGpgMECryptoConfigComponent::~QGpgMECryptoConfigComponent()
165void QGpgMECryptoConfigComponent::runGpgConf()
169 KProcIO proc( TQTextCodec::codecForName(
"utf8" ) );
171 proc <<
"--list-options";
176 TQObject::connect( &proc, TQ_SIGNAL( readReady(KProcIO*) ),
177 this, TQ_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 );
195void 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 );
246void 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 );
324QGpgMECryptoConfigGroup::QGpgMECryptoConfigGroup(
const TQString & name,
const TQString& description,
int level )
327 mDescription( description ),
328 mLevel( static_cast<Kleo::CryptoConfigEntry::Level>( level ) )
330 mEntries.setAutoDelete(
true );
335 TQDictIterator<QGpgMECryptoConfigEntry> it( mEntries );
337 for( ; it.current(); ++it )
338 names.push_back( it.currentKey() );
344 return mEntries.find( name );
349static TQString gpgconf_unescape(
const TQString& str )
352 return KURL::decode_string( str, 106 );
355static TQString gpgconf_escape(
const TQString& str )
358 TQString enc = KURL::encode_string( str, 106 );
360 enc.replace(
',',
"%2c" );
364static TQString urlpart_encode(
const TQString& str )
367 enc.replace(
'%',
"%25" );
368 enc.replace(
':',
"%3a" );
373static 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;
400QGpgMECryptoConfigEntry::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;
445TQVariant 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 );
489QGpgMECryptoConfigEntry::~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;
500 return mFlags & GPGCONF_FLAG_OPTIONAL;
505 return mFlags & GPGCONF_FLAG_NO_CHANGE;
510 return mFlags & GPGCONF_FLAG_LIST;
515 return mFlags & GPGCONF_FLAG_RUNTIME;
525 Q_ASSERT( mArgType == ArgType_None );
527 return mValue.toBool();
532 return toString(
false );
537 Q_ASSERT( mArgType == ArgType_Int );
539 return mValue.toInt();
544 Q_ASSERT( mArgType == ArgType_UInt );
546 return mValue.toUInt();
549static 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;
573static 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) ) );
591 Q_ASSERT( mArgType == ArgType_Path || mArgType == ArgType_URL || mArgType == ArgType_LDAPURL );
593 TQString str = mValue.toString();
594 if ( mArgType == ArgType_Path )
600 return parseURL( mRealArgType, str );
605 Q_ASSERT( mArgType == ArgType_None );
607 return mValue.toUInt();
612 Q_ASSERT( isStringType() );
614 return mValue.toStringList();
619 Q_ASSERT( mArgType == ArgType_Int );
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() );
631 Q_ASSERT( mArgType == ArgType_UInt );
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() );
643 Q_ASSERT( mArgType == ArgType_Path || mArgType == ArgType_URL || mArgType == ArgType_LDAPURL );
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 );
664 if ( mFlags & GPGCONF_FLAG_DEFAULT ) {
665 mValue = mDefaultValue;
667 else if ( mArgType == ArgType_None ) {
677void QGpgMECryptoConfigEntry::setBoolValue(
bool b )
679 Q_ASSERT( mArgType == ArgType_None );
688void QGpgMECryptoConfigEntry::setStringValue(
const TQString& str )
690 mValue = stringToValue( str,
false );
694 if ( str.isEmpty() && !isOptional() )
701void QGpgMECryptoConfigEntry::setIntValue(
int i )
703 Q_ASSERT( mArgType == ArgType_Int );
710void QGpgMECryptoConfigEntry::setUIntValue(
unsigned int i )
717void QGpgMECryptoConfigEntry::setURLValue(
const KURL& url )
719 TQString str = splitURL( mRealArgType, url );
720 if ( str.isEmpty() && !isOptional() )
728void QGpgMECryptoConfigEntry::setNumberOfTimesSet(
unsigned int i )
730 Q_ASSERT( mArgType == ArgType_None );
737void QGpgMECryptoConfigEntry::setStringValueList(
const TQStringList& lst )
740 if ( lst.isEmpty() && !isOptional() )
747void 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() )
761void 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() )
775void 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() )
789TQString QGpgMECryptoConfigEntry::toString(
bool escape )
const
792 if ( isStringType() ) {
793 if ( mValue.isNull() )
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 )
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(
"," );
834TQString QGpgMECryptoConfigEntry::outputString()
const
837 return toString(
true );
840bool 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 );
848void QGpgMECryptoConfigEntry::setDirty(
bool b )
853#include "qgpgmecryptoconfig.moc"
Crypto config for one component (e.g.
Description of a single option.
virtual bool isList() const =0
virtual ArgType argType() const =0
Argument type.
virtual TQStringList stringValueList() const =0
Return value as a list of strings (mostly meaningful for String, Path and URL argtypes,...
virtual bool isOptional() const =0
virtual KURL::List urlValueList() const =0
Return value as a list of URLs (only meaningful for Path and URL argtypes, if isList()).
ArgType
Type of the argument.
virtual TQString stringValue() const =0
Return value as a string (available for all argtypes) The returned string can be empty (explicitely s...
virtual unsigned int uintValue() const =0
Return value as an unsigned int.
virtual bool boolValue() const =0
Return value as a bool (only allowed for ArgType_None).
virtual int intValue() const =0
Return value as a signed int.
virtual KURL urlValue() const =0
Return value as a URL (only meaningful for Path and URL argtypes).
virtual TQValueList< unsigned int > uintValueList() const =0
Return value as a list of unsigned ints.
virtual unsigned int numberOfTimesSet() const =0
Return number of times the option is set (only valid for ArgType_None, if isList()).
virtual bool isRuntime() const =0
virtual TQValueList< int > intValueList() const =0
Return value as a list of signed ints.
virtual void resetToDefault()=0
Reset an option to its default value.
virtual bool isSet() const =0
Return true if the option is set, i.e.
virtual bool isReadOnly() const =0
Group containing a set of config options.
virtual TQStringList entryList() const =0
Returns the list of entries that are known by this group.
TQStringList groupList() const
Returns the list of groups that are known about.
TQString name() const
Return the internal name of this component.
Kleo::CryptoConfigGroup * group(const TQString &name) const
CryptoConfig implementation around the gpgconf command-line tool For method docu, see kleo/cryptoconf...
virtual TQStringList componentList() const
Returns the list of known components (e.g.
virtual void sync(bool runtime)
Write back changes.
virtual Kleo::CryptoConfigComponent * component(const TQString &name) const
virtual void clear()
Tells the CryptoConfig to discard any cached information, including all components,...
QGpgMECryptoConfig()
Constructor.