1 /*
2 qgpgmenewcryptoconfig.cpp
3
4 This file is part of qgpgme, the Qt API binding for gpgme
5 Copyright (c) 2010 Klarälvdalens Datakonsult AB
6 Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
7 Software engineering by Intevation GmbH
8
9 QGpgME is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
13
14 QGpgME is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
23 In addition, as a special exception, the copyright holders give
24 permission to link the code of this program with any edition of
25 the Qt library by Trolltech AS, Norway (or with modified versions
26 of Qt that use the same license as Qt), and distribute linked
27 combinations including the two. You must obey the GNU General
28 Public License in all respects for all of the code used other than
29 Qt. If you modify this file, you may extend this exception to
30 your version of the file, but you are not obligated to do so. If
31 you do not wish to do so, delete this exception statement from
32 your version.
33 */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include "qgpgmenewcryptoconfig.h"
40
41 #include <QDebug>
42 #include "qgpgme_debug.h"
43
44 #include <QFile>
45 #include <QDir>
46
47 #include "global.h"
48 #include "error.h"
49
50
51 #include <sstream>
52 #include <string>
53 #include <functional>
54 #include <cassert>
55 #include <functional>
56
57 using namespace QGpgME;
58 using namespace GpgME;
59 using namespace GpgME::Configuration;
60
61 namespace
62 {
63 struct Select1St {
64 template <typename U, typename V>
operator ()__anon41f0527f0111::Select1St65 const U &operator()(const std::pair<U, V> &p) const
66 {
67 return p.first;
68 }
69 template <typename U, typename V>
operator ()__anon41f0527f0111::Select1St70 const U &operator()(const QPair<U, V> &p) const
71 {
72 return p.first;
73 }
74 };
75 }
76
77 // Just for the Q_ASSERT in the dtor. Not thread-safe, but who would
78 // have 2 threads talking to gpgconf anyway? :)
79 static bool s_duringClear = false;
80
QGpgMENewCryptoConfig()81 QGpgMENewCryptoConfig::QGpgMENewCryptoConfig()
82 : m_parsed(false)
83 {
84 }
85
~QGpgMENewCryptoConfig()86 QGpgMENewCryptoConfig::~QGpgMENewCryptoConfig()
87 {
88 clear();
89 }
90
reloadConfiguration(bool)91 void QGpgMENewCryptoConfig::reloadConfiguration(bool)
92 {
93 clear();
94
95 Error error;
96 const std::vector<Component> components = Component::load(error);
97 #ifndef NDEBUG
98 {
99 std::stringstream ss;
100 ss << "error: " << error
101 << "components:\n";
102 std::copy(components.begin(), components.end(),
103 std::ostream_iterator<Component>(ss, "\n"));
104 qCDebug(QGPGME_LOG) << ss.str().c_str();
105 }
106 #endif
107 #if 0
108 TODO port?
109 if (error && showErrors) {
110 const QString wmsg = i18n("<qt>Failed to execute gpgconf:<p>%1</p></qt>", QString::fromLocal8Bit(error.asString()));
111 qCWarning(QGPGME_LOG) << wmsg; // to see it from test_cryptoconfig.cpp
112 KMessageBox::error(0, wmsg);
113 }
114 #endif
115 Q_FOREACH(const Component & c, components) {
116 const std::shared_ptr<QGpgMENewCryptoConfigComponent> comp(new QGpgMENewCryptoConfigComponent);
117 comp->setComponent(c);
118 m_componentsByName[ comp->name() ] = comp;
119 }
120 m_parsed = true;
121 }
122
componentList() const123 QStringList QGpgMENewCryptoConfig::componentList() const
124 {
125 if (!m_parsed) {
126 const_cast<QGpgMENewCryptoConfig *>(this)->reloadConfiguration(true);
127 }
128 QStringList result;
129 std::transform(m_componentsByName.begin(), m_componentsByName.end(),
130 std::back_inserter(result),
131 mem_fn(&QGpgMENewCryptoConfigComponent::name));
132 return result;
133 }
134
component(const QString & name) const135 QGpgMENewCryptoConfigComponent *QGpgMENewCryptoConfig::component(const QString &name) const
136 {
137 if (!m_parsed) {
138 const_cast<QGpgMENewCryptoConfig *>(this)->reloadConfiguration(false);
139 }
140 return m_componentsByName.value(name).get();
141 }
142
sync(bool runtime)143 void QGpgMENewCryptoConfig::sync(bool runtime)
144 {
145 Q_FOREACH(const std::shared_ptr<QGpgMENewCryptoConfigComponent> &c, m_componentsByName)
146 c->sync(runtime);
147 }
148
clear()149 void QGpgMENewCryptoConfig::clear()
150 {
151 s_duringClear = true;
152 m_componentsByName.clear();
153 s_duringClear = false;
154 m_parsed = false; // next call to componentList/component will need to run gpgconf again
155 }
156
157 ////
158
QGpgMENewCryptoConfigComponent()159 QGpgMENewCryptoConfigComponent::QGpgMENewCryptoConfigComponent()
160 : CryptoConfigComponent(),
161 m_component()
162 {
163
164 }
165
setComponent(const Component & component)166 void QGpgMENewCryptoConfigComponent::setComponent(const Component &component)
167 {
168 m_component = component;
169 m_groupsByName.clear();
170
171 std::shared_ptr<QGpgMENewCryptoConfigGroup> group;
172
173 const std::vector<Option> options = m_component.options();
174 Q_FOREACH(const Option & o, options)
175 if (o.flags() & Group) {
176 if (group) {
177 m_groupsByName[group->name()] = group;
178 }
179 group.reset(new QGpgMENewCryptoConfigGroup(shared_from_this(), o));
180 } else if (group) {
181 const std::shared_ptr<QGpgMENewCryptoConfigEntry> entry(new QGpgMENewCryptoConfigEntry(group, o));
182 const QString name = entry->name();
183 group->m_entryNames.push_back(name);
184 group->m_entriesByName[name] = entry;
185 } else {
186 qCWarning(QGPGME_LOG) << "found no group for entry" << o.name() << "of component" << name();
187 }
188 if (group) {
189 m_groupsByName[group->name()] = group;
190 }
191
192 }
193
~QGpgMENewCryptoConfigComponent()194 QGpgMENewCryptoConfigComponent::~QGpgMENewCryptoConfigComponent() {}
195
name() const196 QString QGpgMENewCryptoConfigComponent::name() const
197 {
198 return QString::fromUtf8(m_component.name());
199 }
200
description() const201 QString QGpgMENewCryptoConfigComponent::description() const
202 {
203 return QString::fromUtf8(m_component.description());
204 }
205
groupList() const206 QStringList QGpgMENewCryptoConfigComponent::groupList() const
207 {
208 QStringList result;
209 result.reserve(m_groupsByName.size());
210 std::transform(m_groupsByName.begin(), m_groupsByName.end(),
211 std::back_inserter(result),
212 std::mem_fn(&QGpgMENewCryptoConfigGroup::name));
213 return result;
214 }
215
group(const QString & name) const216 QGpgMENewCryptoConfigGroup *QGpgMENewCryptoConfigComponent::group(const QString &name) const
217 {
218 return m_groupsByName.value(name).get();
219 }
220
sync(bool runtime)221 void QGpgMENewCryptoConfigComponent::sync(bool runtime)
222 {
223 Q_UNUSED(runtime) // runtime is always set by engine_gpgconf
224 if (const Error err = m_component.save()) {
225 qCWarning(QGPGME_LOG) << ":"
226 << "Error from gpgconf while saving configuration: %1"
227 << QString::fromLocal8Bit(err.asString());
228 }
229 }
230
231 ////
232
QGpgMENewCryptoConfigGroup(const std::shared_ptr<QGpgMENewCryptoConfigComponent> & comp,const Option & option)233 QGpgMENewCryptoConfigGroup::QGpgMENewCryptoConfigGroup(const std::shared_ptr<QGpgMENewCryptoConfigComponent> &comp, const Option &option)
234 : CryptoConfigGroup(),
235 m_component(comp),
236 m_option(option)
237 {
238 }
239
~QGpgMENewCryptoConfigGroup()240 QGpgMENewCryptoConfigGroup::~QGpgMENewCryptoConfigGroup() {}
241
name() const242 QString QGpgMENewCryptoConfigGroup::name() const
243 {
244 return QString::fromUtf8(m_option.name());
245 }
246
description() const247 QString QGpgMENewCryptoConfigGroup::description() const
248 {
249 return QString::fromUtf8(m_option.description());
250 }
251
path() const252 QString QGpgMENewCryptoConfigGroup::path() const
253 {
254 if (const std::shared_ptr<QGpgMENewCryptoConfigComponent> c = m_component.lock()) {
255 return c->name() + QLatin1Char('/') + name();
256 } else {
257 return QString();
258 }
259 }
260
level() const261 CryptoConfigEntry::Level QGpgMENewCryptoConfigGroup::level() const
262 {
263 // two casts to make SunCC happy:
264 return static_cast<CryptoConfigEntry::Level>(static_cast<unsigned int>(m_option.level()));
265 }
266
entryList() const267 QStringList QGpgMENewCryptoConfigGroup::entryList() const
268 {
269 return m_entryNames;
270 }
271
entry(const QString & name) const272 QGpgMENewCryptoConfigEntry *QGpgMENewCryptoConfigGroup::entry(const QString &name) const
273 {
274 return m_entriesByName.value(name).get();
275 }
276
urlpart_encode(const QString & str)277 static QString urlpart_encode(const QString &str)
278 {
279 QString enc(str);
280 enc.replace(QLatin1Char('%'), QStringLiteral("%25")); // first!
281 enc.replace(QLatin1Char(':'), QStringLiteral("%3a"));
282 //qCDebug(QGPGME_LOG) <<" urlpart_encode:" << str <<" ->" << enc;
283 return enc;
284 }
285
urlpart_decode(const QString & str)286 static QString urlpart_decode(const QString &str)
287 {
288 return QUrl::fromPercentEncoding(str.toLatin1());
289 }
290
291 // gpgconf arg type number -> NewCryptoConfigEntry arg type enum mapping
knownArgType(int argType,bool & ok)292 static QGpgME::CryptoConfigEntry::ArgType knownArgType(int argType, bool &ok)
293 {
294 ok = true;
295 switch (argType) {
296 case 0: // none
297 return QGpgME::CryptoConfigEntry::ArgType_None;
298 case 1: // string
299 return QGpgME::CryptoConfigEntry::ArgType_String;
300 case 2: // int32
301 return QGpgME::CryptoConfigEntry::ArgType_Int;
302 case 3: // uint32
303 return QGpgME::CryptoConfigEntry::ArgType_UInt;
304 case 32: // pathname
305 return QGpgME::CryptoConfigEntry::ArgType_Path;
306 case 33: // ldap server
307 return QGpgME::CryptoConfigEntry::ArgType_LDAPURL;
308 default:
309 ok = false;
310 return QGpgME::CryptoConfigEntry::ArgType_None;
311 }
312 }
313
QGpgMENewCryptoConfigEntry(const std::shared_ptr<QGpgMENewCryptoConfigGroup> & group,const Option & option)314 QGpgMENewCryptoConfigEntry::QGpgMENewCryptoConfigEntry(const std::shared_ptr<QGpgMENewCryptoConfigGroup> &group, const Option &option)
315 : m_group(group), m_option(option)
316 {
317 }
318
319 #if 0
320 QVariant QGpgMENewCryptoConfigEntry::stringToValue(const QString &str, bool unescape) const
321 {
322 const bool isString = isStringType();
323
324 if (isList()) {
325 if (argType() == ArgType_None) {
326 bool ok = true;
327 const QVariant v = str.isEmpty() ? 0U : str.toUInt(&ok);
328 if (!ok) {
329 qCWarning(QGPGME_LOG) << "list-of-none should have an unsigned int as value:" << str;
330 }
331 return v;
332 }
333 QList<QVariant> lst;
334 QStringList items = str.split(',', QString::SkipEmptyParts);
335 for (QStringList::const_iterator valit = items.constBegin(); valit != items.constEnd(); ++valit) {
336 QString val = *valit;
337 if (isString) {
338 if (val.isEmpty()) {
339 lst << QVariant(QString());
340 continue;
341 } else if (unescape) {
342 if (val[0] != '"') { // see README.gpgconf
343 qCWarning(QGPGME_LOG) << "String value should start with '\"' :" << val;
344 }
345 val = val.mid(1);
346 }
347 }
348 lst << QVariant(unescape ? gpgconf_unescape(val) : val);
349 }
350 return lst;
351 } else { // not a list
352 QString val(str);
353 if (isString) {
354 if (val.isEmpty()) {
355 return QVariant(QString()); // not set [ok with lists too?]
356 } else if (unescape) {
357 if (val[0] != '"') { // see README.gpgconf
358 qCWarning(QGPGME_LOG) << "String value should start with '\"' :" << val;
359 }
360 val = val.mid(1);
361 }
362 }
363 return QVariant(unescape ? gpgconf_unescape(val) : val);
364 }
365 }
366 #endif
367
~QGpgMENewCryptoConfigEntry()368 QGpgMENewCryptoConfigEntry::~QGpgMENewCryptoConfigEntry()
369 {
370 #ifndef NDEBUG
371 if (!s_duringClear && m_option.dirty())
372 qCWarning(QGPGME_LOG) << "Deleting a QGpgMENewCryptoConfigEntry that was modified (" << m_option.description() << ")"
373 << "You forgot to call sync() (to commit) or clear() (to discard)";
374 #endif
375 }
376
name() const377 QString QGpgMENewCryptoConfigEntry::name() const
378 {
379 return QString::fromUtf8(m_option.name());
380 }
381
description() const382 QString QGpgMENewCryptoConfigEntry::description() const
383 {
384 return QString::fromUtf8(m_option.description());
385 }
386
path() const387 QString QGpgMENewCryptoConfigEntry::path() const
388 {
389 if (const std::shared_ptr<QGpgMENewCryptoConfigGroup> g = m_group.lock()) {
390 return g->path() + QLatin1Char('/') + name();
391 } else {
392 return QString();
393 }
394 }
395
isOptional() const396 bool QGpgMENewCryptoConfigEntry::isOptional() const
397 {
398 return m_option.flags() & Optional;
399 }
400
isReadOnly() const401 bool QGpgMENewCryptoConfigEntry::isReadOnly() const
402 {
403 return m_option.flags() & NoChange;
404 }
405
isList() const406 bool QGpgMENewCryptoConfigEntry::isList() const
407 {
408 return m_option.flags() & List;
409 }
410
isRuntime() const411 bool QGpgMENewCryptoConfigEntry::isRuntime() const
412 {
413 return m_option.flags() & Runtime;
414 }
415
level() const416 CryptoConfigEntry::Level QGpgMENewCryptoConfigEntry::level() const
417 {
418 // two casts to make SunCC happy:
419 return static_cast<Level>(static_cast<unsigned int>(m_option.level()));
420 }
421
argType() const422 CryptoConfigEntry::ArgType QGpgMENewCryptoConfigEntry::argType() const
423 {
424 bool ok = false;
425 const ArgType type = knownArgType(m_option.type(), ok);
426 if (ok) {
427 return type;
428 } else {
429 return knownArgType(m_option.alternateType(), ok);
430 }
431 }
432
isSet() const433 bool QGpgMENewCryptoConfigEntry::isSet() const
434 {
435 return m_option.set();
436 }
437
boolValue() const438 bool QGpgMENewCryptoConfigEntry::boolValue() const
439 {
440 Q_ASSERT(m_option.alternateType() == NoType);
441 Q_ASSERT(!isList());
442 return m_option.currentValue().boolValue();
443 }
444
stringValue() const445 QString QGpgMENewCryptoConfigEntry::stringValue() const
446 {
447 //return toString( false );
448 Q_ASSERT(m_option.alternateType() == StringType);
449 Q_ASSERT(!isList());
450 return QString::fromUtf8(m_option.currentValue().stringValue());
451 }
452
intValue() const453 int QGpgMENewCryptoConfigEntry::intValue() const
454 {
455 Q_ASSERT(m_option.alternateType() == IntegerType);
456 Q_ASSERT(!isList());
457 return m_option.currentValue().intValue();
458 }
459
uintValue() const460 unsigned int QGpgMENewCryptoConfigEntry::uintValue() const
461 {
462 Q_ASSERT(m_option.alternateType() == UnsignedIntegerType);
463 Q_ASSERT(!isList());
464 return m_option.currentValue().uintValue();
465 }
466
parseURL(int mRealArgType,const QString & str)467 static QUrl parseURL(int mRealArgType, const QString &str)
468 {
469 if (mRealArgType == 33) { // LDAP server
470 // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN
471 QStringList items = str.split(QLatin1Char(':'));
472 if (items.count() == 5) {
473 QStringList::const_iterator it = items.constBegin();
474 QUrl url;
475 url.setScheme(QStringLiteral("ldap"));
476 url.setHost(urlpart_decode(*it++));
477
478 bool ok;
479 const int port = (*it++).toInt(&ok);
480 if (ok) {
481 url.setPort(port);
482 } else if (!it->isEmpty()) {
483 qCWarning(QGPGME_LOG) << "parseURL: malformed LDAP server port, ignoring: \"" << *it << "\"";
484 }
485
486 const QString userName = urlpart_decode(*it++);
487 if (!userName.isEmpty()) {
488 url.setUserName(userName);
489 }
490 const QString passWord = urlpart_decode(*it++);
491 if (!passWord.isEmpty()) {
492 url.setPassword(passWord);
493 }
494 url.setQuery(urlpart_decode(*it));
495 return url;
496 } else {
497 qCWarning(QGPGME_LOG) << "parseURL: malformed LDAP server:" << str;
498 }
499 }
500 // other URLs : assume wellformed URL syntax.
501 return QUrl(str);
502 }
503
504 // The opposite of parseURL
splitURL(int mRealArgType,const QUrl & url)505 static QString splitURL(int mRealArgType, const QUrl &url)
506 {
507 if (mRealArgType == 33) { // LDAP server
508 // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN
509 Q_ASSERT(url.scheme() == QLatin1String("ldap"));
510 return urlpart_encode(url.host()) + QLatin1Char(':') +
511 (url.port() != -1 ? QString::number(url.port()) : QString()) + QLatin1Char(':') + // -1 is used for default ports, omit
512 urlpart_encode(url.userName()) + QLatin1Char(':') +
513 urlpart_encode(url.password()) + QLatin1Char(':') +
514 urlpart_encode(url.query());
515 }
516 return url.path();
517 }
518
urlValue() const519 QUrl QGpgMENewCryptoConfigEntry::urlValue() const
520 {
521 const Type type = m_option.type();
522 Q_ASSERT(type == FilenameType || type == LdapServerType);
523 Q_ASSERT(!isList());
524 if (type == FilenameType) {
525 QUrl url = QUrl::fromLocalFile(m_option.currentValue().stringValue());
526 return url;
527 }
528 return parseURL(type, stringValue());
529 }
530
numberOfTimesSet() const531 unsigned int QGpgMENewCryptoConfigEntry::numberOfTimesSet() const
532 {
533 Q_ASSERT(m_option.alternateType() == NoType);
534 Q_ASSERT(isList());
535 return m_option.currentValue().uintValue();
536 }
537
intValueList() const538 std::vector<int> QGpgMENewCryptoConfigEntry::intValueList() const
539 {
540 Q_ASSERT(m_option.alternateType() == IntegerType);
541 Q_ASSERT(isList());
542 return m_option.currentValue().intValues();
543 }
544
uintValueList() const545 std::vector<unsigned int> QGpgMENewCryptoConfigEntry::uintValueList() const
546 {
547 Q_ASSERT(m_option.alternateType() == UnsignedIntegerType);
548 Q_ASSERT(isList());
549 return m_option.currentValue().uintValues();
550 }
551
stringValueList() const552 QStringList QGpgMENewCryptoConfigEntry::stringValueList() const
553 {
554 Q_ASSERT(isList());
555 const Argument arg = m_option.currentValue();
556 const std::vector<const char *> values = arg.stringValues();
557 QStringList ret;
558 for(const char *value: values) {
559 ret << QString::fromUtf8(value);
560 }
561 return ret;
562 }
563
urlValueList() const564 QList<QUrl> QGpgMENewCryptoConfigEntry::urlValueList() const
565 {
566 const Type type = m_option.type();
567 Q_ASSERT(type == FilenameType || type == LdapServerType);
568 Q_ASSERT(isList());
569 const Argument arg = m_option.currentValue();
570 const std::vector<const char *> values = arg.stringValues();
571 QList<QUrl> ret;
572 Q_FOREACH(const char *value, values)
573 if (type == FilenameType) {
574 QUrl url;
575 url.setPath(QFile::decodeName(value));
576 ret << url;
577 } else {
578 ret << parseURL(type, QString::fromUtf8(value));
579 }
580 return ret;
581 }
582
resetToDefault()583 void QGpgMENewCryptoConfigEntry::resetToDefault()
584 {
585 m_option.resetToDefaultValue();
586 }
587
setBoolValue(bool b)588 void QGpgMENewCryptoConfigEntry::setBoolValue(bool b)
589 {
590 Q_ASSERT(m_option.alternateType() == NoType);
591 Q_ASSERT(!isList());
592 // A "no arg" option is either set or not set.
593 // Being set means createNoneArgument(), being unset means resetToDefault()
594 m_option.setNewValue(m_option.createNoneArgument(b));
595 }
596
setStringValue(const QString & str)597 void QGpgMENewCryptoConfigEntry::setStringValue(const QString &str)
598 {
599 Q_ASSERT(m_option.alternateType() == StringType);
600 Q_ASSERT(!isList());
601 const Type type = m_option.type();
602 // When setting a string to empty (and there's no default), we need to act like resetToDefault
603 // Otherwise we try e.g. "ocsp-responder:0:" and gpgconf answers:
604 // "gpgconf: argument required for option ocsp-responder"
605 if (str.isEmpty() && !isOptional()) {
606 m_option.resetToDefaultValue();
607 } else if (type == FilenameType) {
608 m_option.setNewValue(m_option.createStringArgument(QFile::encodeName(str).constData()));
609 } else {
610 m_option.setNewValue(m_option.createStringArgument(str.toUtf8().constData()));
611 }
612 }
613
setIntValue(int i)614 void QGpgMENewCryptoConfigEntry::setIntValue(int i)
615 {
616 Q_ASSERT(m_option.alternateType() == IntegerType);
617 Q_ASSERT(!isList());
618 m_option.setNewValue(m_option.createIntArgument(i));
619 }
620
setUIntValue(unsigned int i)621 void QGpgMENewCryptoConfigEntry::setUIntValue(unsigned int i)
622 {
623 Q_ASSERT(m_option.alternateType() == UnsignedIntegerType);
624 Q_ASSERT(!isList());
625 m_option.setNewValue(m_option.createUIntArgument(i));
626 }
627
setURLValue(const QUrl & url)628 void QGpgMENewCryptoConfigEntry::setURLValue(const QUrl &url)
629 {
630 const Type type = m_option.type();
631 Q_ASSERT(type == FilenameType || type == LdapServerType);
632 Q_ASSERT(!isList());
633 const QString str = splitURL(type, url);
634 // cf. setStringValue()
635 if (str.isEmpty() && !isOptional()) {
636 m_option.resetToDefaultValue();
637 } else if (type == FilenameType) {
638 m_option.setNewValue(m_option.createStringArgument(QDir::toNativeSeparators(url.toLocalFile()).toUtf8().constData()));
639 } else {
640 m_option.setNewValue(m_option.createStringArgument(str.toUtf8().constData()));
641 }
642 }
643
setNumberOfTimesSet(unsigned int i)644 void QGpgMENewCryptoConfigEntry::setNumberOfTimesSet(unsigned int i)
645 {
646 Q_ASSERT(m_option.alternateType() == NoType);
647 Q_ASSERT(isList());
648 m_option.setNewValue(m_option.createNoneListArgument(i));
649 }
650
setIntValueList(const std::vector<int> & lst)651 void QGpgMENewCryptoConfigEntry::setIntValueList(const std::vector<int> &lst)
652 {
653 Q_ASSERT(m_option.alternateType() == IntegerType);
654 Q_ASSERT(isList());
655 m_option.setNewValue(m_option.createIntListArgument(lst));
656 }
657
setUIntValueList(const std::vector<unsigned int> & lst)658 void QGpgMENewCryptoConfigEntry::setUIntValueList(const std::vector<unsigned int> &lst)
659 {
660 Q_ASSERT(m_option.alternateType() == UnsignedIntegerType);
661 Q_ASSERT(isList());
662 m_option.setNewValue(m_option.createUIntListArgument(lst));
663 }
664
setURLValueList(const QList<QUrl> & urls)665 void QGpgMENewCryptoConfigEntry::setURLValueList(const QList<QUrl> &urls)
666 {
667 const Type type = m_option.type();
668 Q_ASSERT(m_option.alternateType() == StringType);
669 Q_ASSERT(isList());
670 std::vector<std::string> values;
671 values.reserve(urls.size());
672 Q_FOREACH (const QUrl &url, urls)
673 if (type == FilenameType) {
674 values.push_back(QFile::encodeName(url.path()).constData());
675 } else {
676 values.push_back(splitURL(type, url).toUtf8().constData());
677 }
678 m_option.setNewValue(m_option.createStringListArgument(values));
679 }
680
isDirty() const681 bool QGpgMENewCryptoConfigEntry::isDirty() const
682 {
683 return m_option.dirty();
684 }
685
686 #if 0
687 QString QGpgMENewCryptoConfigEntry::toString(bool escape) const
688 {
689 // Basically the opposite of stringToValue
690 if (isStringType()) {
691 if (mValue.isNull()) {
692 return QString();
693 } else if (isList()) { // string list
694 QStringList lst = mValue.toStringList();
695 if (escape) {
696 for (QStringList::iterator it = lst.begin(); it != lst.end(); ++it) {
697 if (!(*it).isNull()) {
698 *it = gpgconf_escape(*it).prepend("\"");
699 }
700 }
701 }
702 QString res = lst.join(",");
703 //qCDebug(QGPGME_LOG) <<"toString:" << res;
704 return res;
705 } else { // normal string
706 QString res = mValue.toString();
707 if (escape) {
708 res = gpgconf_escape(res).prepend("\"");
709 }
710 return res;
711 }
712 }
713 if (!isList()) { // non-list non-string
714 if (mArgType == ArgType_None) {
715 return mValue.toBool() ? QString::fromLatin1("1") : QString();
716 } else { // some int
717 Q_ASSERT(mArgType == ArgType_Int || mArgType == ArgType_UInt);
718 return mValue.toString(); // int to string conversion
719 }
720 }
721
722 // Lists (of other types than strings)
723 if (mArgType == ArgType_None) {
724 return QString::number(numberOfTimesSet());
725 }
726 QStringList ret;
727 QList<QVariant> lst = mValue.toList();
728 for (QList<QVariant>::const_iterator it = lst.constBegin(); it != lst.constEnd(); ++it) {
729 ret << (*it).toString(); // QVariant does the conversion
730 }
731 return ret.join(",");
732 }
733
734 QString QGpgMENewCryptoConfigEntry::outputString() const
735 {
736 Q_ASSERT(mSet);
737 return toString(true);
738 }
739
740 bool QGpgMENewCryptoConfigEntry::isStringType() const
741 {
742 return (mArgType == QGpgME::NewCryptoConfigEntry::ArgType_String
743 || mArgType == QGpgME::NewCryptoConfigEntry::ArgType_Path
744 || mArgType == QGpgME::NewCryptoConfigEntry::ArgType_URL
745 || mArgType == QGpgME::NewCryptoConfigEntry::ArgType_LDAPURL);
746 }
747
748 void QGpgMENewCryptoConfigEntry::setDirty(bool b)
749 {
750 mDirty = b;
751 }
752 #endif
753