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, 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);
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, 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 );
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"
Crypto config for one component (e.g.
Description of a single option.
ArgType
Type of the argument.
Group containing a set of config options.
For docu, see kleo/cryptoconfig.h.
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.