1 /*
2 configuration.cpp - wraps gpgme configuration components
3 Copyright (C) 2010 Klarälvdalens Datakonsult AB
4 2016 Bundesamt für Sicherheit in der Informationstechnik
5 Software engineering by Intevation GmbH
6
7 This file is part of GPGME++.
8
9 GPGME++ is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public
11 License as published by the Free Software Foundation; either
12 version 2 of the License, or (at your option) any later version.
13
14 GPGME++ 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
17 GNU Library General Public License for more details.
18
19 You should have received a copy of the GNU Library General Public License
20 along with GPGME++; see the file COPYING.LIB. If not, write to the
21 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "configuration.h"
30 #include "error.h"
31 #include "util.h"
32
33 #include <gpgme.h>
34
35 #include <iterator>
36 #include <algorithm>
37 #include <ostream>
38 #include <cstring>
39 #include <assert.h>
40
41 using namespace GpgME;
42 using namespace GpgME::Configuration;
43
44 typedef std::shared_ptr< std::remove_pointer<gpgme_conf_opt_t>::type > shared_gpgme_conf_opt_t;
45 typedef std::weak_ptr< std::remove_pointer<gpgme_conf_opt_t>::type > weak_gpgme_conf_opt_t;
46
47 typedef std::shared_ptr< std::remove_pointer<gpgme_conf_arg_t>::type > shared_gpgme_conf_arg_t;
48 typedef std::weak_ptr< std::remove_pointer<gpgme_conf_arg_t>::type > weak_gpgme_conf_arg_t;
49
50 typedef std::shared_ptr< std::remove_pointer<gpgme_ctx_t>::type > shared_gpgme_ctx_t;
51 typedef std::weak_ptr< std::remove_pointer<gpgme_ctx_t>::type > weak_gpgme_ctx_t;
52
53 namespace
54 {
55 struct nodelete {
operator ()__anon3e2ebe6a0111::nodelete56 template <typename T> void operator()(T *) {}
57 };
58 }
59
60 // static
load(Error & returnedError)61 std::vector<Component> Component::load(Error &returnedError)
62 {
63
64 //
65 // 1. get a context:
66 //
67 gpgme_ctx_t ctx_native = nullptr;
68 if (const gpgme_error_t err = gpgme_new(&ctx_native)) {
69 returnedError = Error(err);
70 return std::vector<Component>();
71 }
72 const shared_gpgme_ctx_t ctx(ctx_native, &gpgme_release);
73
74 //
75 // 2. load the config:
76 //
77 gpgme_conf_comp_t conf_list_native = nullptr;
78 if (const gpgme_error_t err = gpgme_op_conf_load(ctx_native, &conf_list_native)) {
79 returnedError = Error(err);
80 return std::vector<Component>();
81 }
82 shared_gpgme_conf_comp_t head(conf_list_native, &gpgme_conf_release);
83
84 //
85 // 3. convert to vector<Component>:
86 //
87 std::vector<Component> result;
88
89 while (head) {
90 // secure 'head->next' (if any) against memleaks:
91 shared_gpgme_conf_comp_t next;
92 if (head->next) {
93 next.reset(head->next, &gpgme_conf_release);
94 }
95
96 // now prevent double-free of next.get() and following:
97 head->next = nullptr;
98
99 // now add a new Component to 'result' (may throw):
100 result.resize(result.size() + 1);
101 result.back().comp.swap(head); // .comp = std::move( head );
102 head.swap(next); // head = std::move( next );
103 }
104
105 return result;
106 }
107
save() const108 Error Component::save() const
109 {
110
111 if (isNull()) {
112 return Error(make_error(GPG_ERR_INV_ARG));
113 }
114
115 //
116 // 1. get a context:
117 //
118 gpgme_ctx_t ctx_native = nullptr;
119 if (const gpgme_error_t err = gpgme_new(&ctx_native)) {
120 return Error(err);
121 }
122 const shared_gpgme_ctx_t ctx(ctx_native, &gpgme_release);
123
124 //
125 // 2. save the config:
126 //
127 return Error(gpgme_op_conf_save(ctx.get(), comp.get()));
128 }
129
name() const130 const char *Component::name() const
131 {
132 return comp ? comp->name : nullptr;
133 }
134
description() const135 const char *Component::description() const
136 {
137 return comp ? comp->description : nullptr ;
138 }
139
programName() const140 const char *Component::programName() const
141 {
142 return comp ? comp->program_name : nullptr ;
143 }
144
option(unsigned int idx) const145 Option Component::option(unsigned int idx) const
146 {
147 gpgme_conf_opt_t opt = nullptr;
148 if (comp) {
149 opt = comp->options;
150 }
151 while (opt && idx) {
152 opt = opt->next;
153 --idx;
154 }
155 if (opt) {
156 return Option(comp, opt);
157 }
158 return Option();
159 }
160
option(const char * name) const161 Option Component::option(const char *name) const
162 {
163 gpgme_conf_opt_t opt = nullptr;
164 if (comp) {
165 opt = comp->options;
166 }
167 using namespace std; // for strcmp
168 while (opt && strcmp(name, opt->name) != 0) {
169 opt = opt->next;
170 }
171 if (opt) {
172 return Option(comp, opt);
173 }
174 return Option();
175 }
176
numOptions() const177 unsigned int Component::numOptions() const
178 {
179 unsigned int result = 0;
180 for (gpgme_conf_opt_t opt = comp ? comp->options : nullptr ; opt ; opt = opt->next) {
181 ++result;
182 }
183 return result;
184 }
185
options() const186 std::vector<Option> Component::options() const
187 {
188 std::vector<Option> result;
189 for (gpgme_conf_opt_t opt = comp ? comp->options : nullptr ; opt ; opt = opt->next) {
190 result.push_back(Option(comp, opt));
191 }
192 return result;
193 }
194
mygpgme_conf_arg_copy(gpgme_conf_arg_t other,gpgme_conf_type_t type)195 static gpgme_conf_arg_t mygpgme_conf_arg_copy(gpgme_conf_arg_t other, gpgme_conf_type_t type)
196 {
197 gpgme_conf_arg_t result = nullptr, last = nullptr;
198 for (gpgme_conf_arg_t a = other ; a ; a = a->next) {
199 gpgme_conf_arg_t arg = nullptr;
200 const gpgme_error_t err
201 = gpgme_conf_arg_new(&arg, type,
202 a->no_arg ? nullptr :
203 type == GPGME_CONF_STRING ? a->value.string :
204 /* else */ static_cast<void *>(&a->value));
205 if (err) {
206 gpgme_conf_arg_release(result, type);
207 return nullptr;
208 }
209 assert(arg);
210 if (result) {
211 last->next = arg;
212 } else {
213 result = arg;
214 }
215 last = arg;
216 }
217 return result;
218 }
219
parent() const220 Component Option::parent() const
221 {
222 return Component(comp.lock());
223 }
224
flags() const225 unsigned int Option::flags() const
226 {
227 return isNull() ? 0 : opt->flags;
228 }
229
level() const230 Level Option::level() const
231 {
232 return isNull() ? Internal : static_cast<Level>(opt->level) ;
233 }
234
name() const235 const char *Option::name() const
236 {
237 return isNull() ? nullptr : opt->name ;
238 }
239
description() const240 const char *Option::description() const
241 {
242 return isNull() ? nullptr : opt->description ;
243 }
244
argumentName() const245 const char *Option::argumentName() const
246 {
247 return isNull() ? nullptr : opt->argname ;
248 }
249
type() const250 Type Option::type() const
251 {
252 return isNull() ? NoType : static_cast<Type>(opt->type) ;
253 }
254
alternateType() const255 Type Option::alternateType() const
256 {
257 return isNull() ? NoType : static_cast<Type>(opt->alt_type) ;
258 }
259
260 #if 0
261 static Option::Variant argument_to_variant(gpgme_conf_type_t type, bool list, gpgme_conf_arg_t arg)
262 {
263 assert(arg);
264 switch (type) {
265 case GPGME_CONF_NONE:
266 if (list) {
267 // return the count (number of times set):
268 return arg->value.count;
269 } else {
270 return none;
271 }
272 case GPGME_CONF_INT32:
273 if (list) {
274 std::vector<int> result;
275 for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
276 result.push_back(a->value.int32);
277 }
278 return result;
279 } else {
280 return arg->value.int32;
281 }
282 case GPGME_CONF_UINT32:
283 if (list) {
284 std::vector<unsigned int> result;
285 for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
286 result.push_back(a->value.uint32);
287 }
288 return result;
289 } else {
290 return arg->value.uint32;
291 }
292 case GPGME_CONF_FILENAME:
293 case GPGME_CONF_LDAP_SERVER:
294 case GPGME_CONF_KEY_FPR:
295 case GPGME_CONF_PUB_KEY:
296 case GPGME_CONF_SEC_KEY:
297 case GPGME_CONF_ALIAS_LIST:
298 // these should not happen in alt_type, but fall through
299 case GPGME_CONF_STRING:
300 if (list) {
301 std::vector<const char *> result;
302 for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
303 result.push_back(a->value.string);
304 }
305 return result;
306 } else {
307 return arg->value.string;
308 }
309 }
310 assert(!"Option: unknown alt_type!");
311 return Option::Variant();
312 }
313
314 namespace
315 {
316 inline const void *to_void_star(const char *s)
317 {
318 return s;
319 }
320 inline const void *to_void_star(const std::string &s)
321 {
322 return s.c_str();
323 }
324 inline const void *to_void_star(const int &i)
325 {
326 return &i; // const-&: sic!
327 }
328 inline const void *to_void_star(const unsigned int &i)
329 {
330 return &i; // const-&: sic!
331 }
332
333 struct VariantToArgumentVisitor : boost::static_visitor<gpgme_conf_arg_t> {
334 static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value)
335 {
336 gpgme_conf_arg_t arg = 0;
337 #ifdef HAVE_GPGME_CONF_ARG_NEW_WITH_CONST_VALUE
338 if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) {
339 return 0;
340 }
341 #else
342 if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, const_cast<void *>(value))) {
343 return 0;
344 }
345 #endif
346 else {
347 return arg;
348 }
349 }
350
351 gpgme_conf_arg_t operator()(bool v) const
352 {
353 return v ? make_argument(0) : 0 ;
354 }
355
356 gpgme_conf_arg_t operator()(const char *s) const
357 {
358 return make_argument(s ? s : "");
359 }
360
361 gpgme_conf_arg_t operator()(const std::string &s) const
362 {
363 return operator()(s.c_str());
364 }
365
366 gpgme_conf_arg_t operator()(int i) const
367 {
368 return make_argument(&i);
369 }
370
371 gpgme_conf_arg_t operator()(unsigned int i) const
372 {
373 return make_argument(&i);
374 }
375
376 template <typename T>
377 gpgme_conf_arg_t operator()(const std::vector<T> &value) const
378 {
379 gpgme_conf_arg_t result = 0;
380 gpgme_conf_arg_t last = 0;
381 for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) {
382 if (gpgme_conf_arg_t arg = make_argument(to_void_star(*it))) {
383 if (last) {
384 last = last->next = arg;
385 } else {
386 result = last = arg;
387 }
388 }
389 }
390 return result;
391 }
392
393 };
394 }
395
396 static gpgme_conf_arg_t variant_to_argument(const Option::Variant &value)
397 {
398 VariantToArgumentVisitor v;
399 return apply_visitor(v, value);
400 }
401
402 optional<Option::Variant> Option::defaultValue() const
403 {
404 if (isNull()) {
405 return optional<Variant>();
406 } else {
407 return argument_to_variant(opt->alt_type, opt->flags & GPGME_CONF_LIST, opt->default_value);
408 }
409 }
410 #endif
411
defaultValue() const412 Argument Option::defaultValue() const
413 {
414 if (isNull()) {
415 return Argument();
416 } else {
417 return Argument(comp.lock(), opt, opt->default_value, false);
418 }
419 }
420
defaultDescription() const421 const char *Option::defaultDescription() const
422 {
423 return isNull() ? nullptr : opt->default_description ;
424 }
425
noArgumentValue() const426 Argument Option::noArgumentValue() const
427 {
428 if (isNull()) {
429 return Argument();
430 } else {
431 return Argument(comp.lock(), opt, opt->no_arg_value, false);
432 }
433 }
434
noArgumentDescription() const435 const char *Option::noArgumentDescription() const
436 {
437 return isNull() ? nullptr : opt->no_arg_description ;
438 }
439
activeValue() const440 Argument Option::activeValue() const
441 {
442 if (isNull()) {
443 return Argument();
444 } else {
445 return Argument(comp.lock(), opt, opt->value, false);
446 }
447 }
448
currentValue() const449 Argument Option::currentValue() const
450 {
451 if (isNull()) {
452 return Argument();
453 }
454 const gpgme_conf_arg_t arg =
455 opt->change_value ? opt->new_value ? opt->new_value : opt->default_value :
456 opt->value ? opt->value :
457 /* else */ opt->default_value ;
458 return Argument(comp.lock(), opt, arg, false);
459 }
460
newValue() const461 Argument Option::newValue() const
462 {
463 if (isNull()) {
464 return Argument();
465 } else {
466 return Argument(comp.lock(), opt, opt->new_value, false);
467 }
468 }
469
set() const470 bool Option::set() const
471 {
472 if (isNull()) {
473 return false;
474 } else if (opt->change_value) {
475 return opt->new_value;
476 } else {
477 return opt->value;
478 }
479 }
480
dirty() const481 bool Option::dirty() const
482 {
483 return !isNull() && opt->change_value ;
484 }
485
setNewValue(const Argument & argument)486 Error Option::setNewValue(const Argument &argument)
487 {
488 if (isNull()) {
489 return Error(make_error(GPG_ERR_INV_ARG));
490 } else if (argument.isNull()) {
491 return resetToDefaultValue();
492 } else if (const gpgme_conf_arg_t arg = mygpgme_conf_arg_copy(argument.arg, opt->alt_type)) {
493 return Error(gpgme_conf_opt_change(opt, 0, arg));
494 } else {
495 return Error(make_error(GPG_ERR_ENOMEM));
496 }
497 }
498
resetToActiveValue()499 Error Option::resetToActiveValue()
500 {
501 if (isNull()) {
502 return Error(make_error(GPG_ERR_INV_ARG));
503 } else {
504 return Error(gpgme_conf_opt_change(opt, 1, nullptr));
505 }
506 }
507
resetToDefaultValue()508 Error Option::resetToDefaultValue()
509 {
510 if (isNull()) {
511 return Error(make_error(GPG_ERR_INV_ARG));
512 } else {
513 return Error(gpgme_conf_opt_change(opt, 0, nullptr));
514 }
515 }
516
make_argument(gpgme_conf_type_t type,const void * value)517 static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value)
518 {
519 gpgme_conf_arg_t arg = nullptr;
520 if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) {
521 return nullptr;
522 } else {
523 return arg;
524 }
525 }
526
createNoneArgument(bool set) const527 Argument Option::createNoneArgument(bool set) const
528 {
529 if (isNull() || alternateType() != NoType) {
530 return Argument();
531 } else {
532 if (set) {
533 return createNoneListArgument(1);
534 }
535 }
536 return Argument();
537 }
538
createStringArgument(const char * value) const539 Argument Option::createStringArgument(const char *value) const
540 {
541 if (isNull() || alternateType() != StringType) {
542 return Argument();
543 } else {
544 return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
545 }
546 }
547
createStringArgument(const std::string & value) const548 Argument Option::createStringArgument(const std::string &value) const
549 {
550 if (isNull() || alternateType() != StringType) {
551 return Argument();
552 } else {
553 return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value.c_str()), true);
554 }
555 }
556
createIntArgument(int value) const557 Argument Option::createIntArgument(int value) const
558 {
559 if (isNull() || alternateType() != IntegerType) {
560 return Argument();
561 } else {
562 return Argument(comp.lock(), opt, make_argument(GPGME_CONF_INT32, &value), true);
563 }
564 }
565
createUIntArgument(unsigned int value) const566 Argument Option::createUIntArgument(unsigned int value) const
567 {
568 if (isNull() || alternateType() != UnsignedIntegerType) {
569 return Argument();
570 } else {
571 return Argument(comp.lock(), opt, make_argument(GPGME_CONF_UINT32, &value), true);
572 }
573 }
574
575 namespace
576 {
to_void_star(const char * s)577 const void *to_void_star(const char *s)
578 {
579 return s;
580 }
to_void_star(const std::string & s)581 const void *to_void_star(const std::string &s)
582 {
583 return s.c_str();
584 }
to_void_star(const int & i)585 const void *to_void_star(const int &i)
586 {
587 return &i; // const-&: sic!
588 }
to_void_star(const unsigned int & i)589 const void *to_void_star(const unsigned int &i)
590 {
591 return &i; // const-&: sic!
592 }
593
594 template <typename T>
make_argument(gpgme_conf_type_t type,const std::vector<T> & value)595 gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const std::vector<T> &value)
596 {
597 gpgme_conf_arg_t result = nullptr;
598 gpgme_conf_arg_t last = nullptr;
599 for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) {
600 if (gpgme_conf_arg_t arg = make_argument(type, to_void_star(*it))) {
601 if (last) {
602 last = last->next = arg;
603 } else {
604 result = last = arg;
605 }
606 }
607 }
608 return result;
609 }
610 }
611
createNoneListArgument(unsigned int value) const612 Argument Option::createNoneListArgument(unsigned int value) const
613 {
614 if (value) {
615 return Argument(comp.lock(), opt, make_argument(GPGME_CONF_NONE, &value), true);
616 }
617 return Argument();
618 }
619
createStringListArgument(const std::vector<const char * > & value) const620 Argument Option::createStringListArgument(const std::vector<const char *> &value) const
621 {
622 return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
623 }
624
createStringListArgument(const std::vector<std::string> & value) const625 Argument Option::createStringListArgument(const std::vector<std::string> &value) const
626 {
627 return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
628 }
629
createIntListArgument(const std::vector<int> & value) const630 Argument Option::createIntListArgument(const std::vector<int> &value) const
631 {
632 return Argument(comp.lock(), opt, make_argument(GPGME_CONF_INT32, value), true);
633 }
634
createUIntListArgument(const std::vector<unsigned int> & value) const635 Argument Option::createUIntListArgument(const std::vector<unsigned int> &value) const
636 {
637 return Argument(comp.lock(), opt, make_argument(GPGME_CONF_UINT32, value), true);
638 }
639
Argument(const shared_gpgme_conf_comp_t & comp,gpgme_conf_opt_t opt,gpgme_conf_arg_t arg,bool owns)640 Argument::Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg, bool owns)
641 : comp(comp),
642 opt(opt),
643 arg(owns ? arg : mygpgme_conf_arg_copy(arg, opt ? opt->alt_type : GPGME_CONF_NONE))
644 {
645
646 }
647
648 #if 0
649 Argument::Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg)
650 : comp(comp),
651 opt(opt),
652 arg(mygpgme_conf_arg_copy(arg, opt ? opt->alt_type : GPGME_CONF_NONE))
653 {
654
655 }
656 #endif
657
Argument(const Argument & other)658 Argument::Argument(const Argument &other)
659 : comp(other.comp),
660 opt(other.opt),
661 arg(mygpgme_conf_arg_copy(other.arg, opt ? opt->alt_type : GPGME_CONF_NONE))
662 {
663
664 }
665
~Argument()666 Argument::~Argument()
667 {
668 gpgme_conf_arg_release(arg, opt ? opt->alt_type : GPGME_CONF_NONE);
669 }
670
parent() const671 Option Argument::parent() const
672 {
673 return Option(comp.lock(), opt);
674 }
675
boolValue() const676 bool Argument::boolValue() const
677 {
678 return numberOfTimesSet();
679 }
680
numElements() const681 unsigned int Argument::numElements() const
682 {
683 if (isNull()) {
684 return 0;
685 }
686 unsigned int result = 0;
687 for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
688 ++result;
689 }
690 return result;
691 }
692
stringValue(unsigned int idx) const693 const char *Argument::stringValue(unsigned int idx) const
694 {
695 if (isNull() || opt->alt_type != GPGME_CONF_STRING) {
696 return nullptr;
697 }
698 gpgme_conf_arg_t a = arg;
699 while (a && idx) {
700 a = a->next;
701 --idx;
702 }
703 return a ? a->value.string : nullptr ;
704 }
705
intValue(unsigned int idx) const706 int Argument::intValue(unsigned int idx) const
707 {
708 if (isNull() || opt->alt_type != GPGME_CONF_INT32) {
709 return 0;
710 }
711 gpgme_conf_arg_t a = arg;
712 while (a && idx) {
713 a = a->next;
714 --idx;
715 }
716 return a ? a->value.int32 : 0 ;
717 }
718
uintValue(unsigned int idx) const719 unsigned int Argument::uintValue(unsigned int idx) const
720 {
721 if (isNull() || opt->alt_type != GPGME_CONF_UINT32) {
722 return 0;
723 }
724 gpgme_conf_arg_t a = arg;
725 while (a && idx) {
726 a = a->next;
727 --idx;
728 }
729 return a ? a->value.uint32 : 0 ;
730 }
731
numberOfTimesSet() const732 unsigned int Argument::numberOfTimesSet() const
733 {
734 if (isNull() || opt->alt_type != GPGME_CONF_NONE) {
735 return 0;
736 }
737 return arg->value.count;
738 }
739
stringValues() const740 std::vector<const char *> Argument::stringValues() const
741 {
742 if (isNull() || opt->alt_type != GPGME_CONF_STRING) {
743 return std::vector<const char *>();
744 }
745 std::vector<const char *> result;
746 for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
747 result.push_back(a->value.string);
748 }
749 return result;
750 }
751
intValues() const752 std::vector<int> Argument::intValues() const
753 {
754 if (isNull() || opt->alt_type != GPGME_CONF_INT32) {
755 return std::vector<int>();
756 }
757 std::vector<int> result;
758 for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
759 result.push_back(a->value.int32);
760 }
761 return result;
762 }
763
uintValues() const764 std::vector<unsigned int> Argument::uintValues() const
765 {
766 if (isNull() || opt->alt_type != GPGME_CONF_UINT32) {
767 return std::vector<unsigned int>();
768 }
769 std::vector<unsigned int> result;
770 for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
771 result.push_back(a->value.uint32);
772 }
773 return result;
774 }
775
operator <<(std::ostream & os,Level level)776 std::ostream &Configuration::operator<<(std::ostream &os, Level level)
777 {
778 switch (level) {
779 case Basic: return os << "Basic";
780 case Advanced: return os << "Advanced";
781 case Expert: return os << "Expert";
782 case Invisible: return os << "Invisible";
783 case Internal: return os << "Internal";
784 case NumLevels: ;
785 }
786 return os << "<unknown>";
787 }
788
operator <<(std::ostream & os,Type type)789 std::ostream &Configuration::operator<<(std::ostream &os, Type type)
790 {
791 switch (type) {
792 case NoType: return os << "None";
793 case StringType: return os << "String";
794 case IntegerType: return os << "Integer";
795 case UnsignedIntegerType: return os << "UnsignedInteger";
796 case FilenameType: return os << "Filename";
797 case LdapServerType: return os << "LdapServer";
798 case KeyFingerprintType: return os << "KeyFingerprint";
799 case PublicKeyType: return os << "PublicKey";
800 case SecretKeyType: return os << "SecretKey";
801 case AliasListType: return os << "AliasList";
802 case MaxType: ;
803 }
804 return os << "<unknown>";
805 }
806
operator <<(std::ostream & os,Flag f)807 std::ostream &Configuration::operator<<(std::ostream &os, Flag f)
808 {
809 unsigned int flags = f;
810 std::vector<const char *> s;
811 if (flags & Group) {
812 s.push_back("Group");
813 }
814 if (flags & Optional) {
815 s.push_back("Optional");
816 }
817 if (flags & List) {
818 s.push_back("List");
819 }
820 if (flags & Runtime) {
821 s.push_back("Runtime");
822 }
823 if (flags & Default) {
824 s.push_back("Default");
825 }
826 if (flags & DefaultDescription) {
827 s.push_back("DefaultDescription");
828 }
829 if (flags & NoArgumentDescription) {
830 s.push_back("NoArgumentDescription");
831 }
832 if (flags & NoChange) {
833 s.push_back("NoChange");
834 }
835 flags &= ~(Group | Optional | List | Runtime | Default | DefaultDescription | NoArgumentDescription | NoChange);
836 if (flags) {
837 s.push_back("other flags(");
838 }
839 std::copy(s.begin(), s.end(),
840 std::ostream_iterator<const char *>(os, "|"));
841 if (flags) {
842 os << flags << ')';
843 }
844 return os;
845 }
846
operator <<(std::ostream & os,const Component & c)847 std::ostream &Configuration::operator<<(std::ostream &os, const Component &c)
848 {
849 os << "Component["
850 << "\n name : " << protect(c.name())
851 << "\n description: " << protect(c.description())
852 << "\n programName: " << protect(c.programName())
853 << "\n options : \n";
854 const std::vector<Option> options = c.options();
855 std::copy(options.begin(), options.end(),
856 std::ostream_iterator<Option>(os, "\n"));
857 os << "\n]";
858 return os;
859 }
860
operator <<(std::ostream & os,const Option & o)861 std::ostream &Configuration::operator<<(std::ostream &os, const Option &o)
862 {
863 return os << "Option["
864 << "\n name: : " << protect(o.name())
865 << "\n description : " << protect(o.description())
866 << "\n argName : " << protect(o.argumentName())
867 << "\n flags : " << static_cast<Flag>(o.flags())
868 << "\n level : " << o.level()
869 << "\n type : " << o.type()
870 << "\n alt_type : " << o.alternateType()
871 << "\n default_val : " << o.defaultValue()
872 << "\n default_desc: " << protect(o.defaultDescription())
873 << "\n no_arg_value: " << o.noArgumentValue()
874 << "\n no_arg_desc : " << protect(o.noArgumentDescription())
875 << "\n active_value: " << o.activeValue()
876 << "\n new_value : " << o.newValue()
877 << "\n --> cur_val : " << o.currentValue()
878 << "\n set : " << o.set()
879 << "\n dirty : " << o.dirty()
880 << "\n]"
881 ;
882 }
883
operator <<(std::ostream & os,const Argument & a)884 std::ostream &Configuration::operator<<(std::ostream &os, const Argument &a)
885 {
886 const Option o = a.parent();
887 const bool list = o.flags() & List;
888 os << "Argument[";
889 if (a) {
890 switch (o.alternateType()) {
891 case NoType:
892 if (list) {
893 os << a.numberOfTimesSet() << 'x';
894 } else {
895 os << a.boolValue();
896 }
897 break;
898 default:
899 case StringType:
900 if (list) {
901 const std::vector<const char *> v = a.stringValues();
902 os << v.size() << ':';
903 // can't use std::copy + ostream_iterator here, since we need the protect() call
904 bool first = true;
905 std::for_each(v.begin(), v.end(), [&first, &os](const char *s) {
906 if (first) {
907 first = false;
908 } else {
909 os << ',';
910 }
911 os << protect(s);
912 });
913 } else {
914 os << protect(a.stringValue());
915 }
916 break;
917 case IntegerType:
918 if (list) {
919 const std::vector<int> v = a.intValues();
920 os << v.size() << ':';
921 std::copy(v.begin(), v.end(),
922 std::ostream_iterator<int>(os, ","));
923 } else {
924 os << a.intValue();
925 }
926 break;
927 case UnsignedIntegerType:
928 if (list) {
929 const std::vector<unsigned int> v = a.uintValues();
930 os << v.size() << ':';
931 std::copy(v.begin(), v.end(),
932 std::ostream_iterator<unsigned int>(os, ","));
933 } else {
934 os << a.intValue();
935 }
936 break;
937 }
938 }
939 return os << ']';
940 }
941