|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #+##############################################################################  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # File: Config/Validator.pm                                                    #  | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Description: schema based configuration validation                           #  | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #-##############################################################################  | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # module definition  | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Config::Validator;  | 
| 
14
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
 
 | 
7741
 | 
 use strict;  | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
110
 | 
    | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
360
 | 
    | 
| 
15
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
 
 | 
74
 | 
 use warnings;  | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
    | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
964
 | 
    | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $VERSION  = "1.4";  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $REVISION = sprintf("%d.%02d", q$Revision: 1.36 $ =~ /(\d+)\.(\d+)/);  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # used modules  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
23
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
 
 | 
5895
 | 
 use No::Worries::Die qw(dief);  | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
229706
 | 
    | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
79
 | 
    | 
| 
24
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
 
 | 
1309
 | 
 use No::Worries::Export qw(export_control);  | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
    | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
67
 | 
    | 
| 
25
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
 
 | 
1084
 | 
 use Scalar::Util qw(blessed reftype);  | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
    | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1518
 | 
    | 
| 
26
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
 
 | 
6653
 | 
 use URI::Escape qw(uri_escape uri_unescape);  | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37316
 | 
    | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
90768
 | 
    | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # global variables  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our(  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $_Known,         # hash reference of known schemas used by _check_type()  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $_BuiltIn,       # hash reference of built-in schemas (to validate schemas)  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     %_RE,            # hash of commonly used regular expressions  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     %_DurationScale, # hash of duration suffixes  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     %_SizeScale,     # hash of size suffixes  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 %_DurationScale = (  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     ms => 0.001,  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      s => 1,  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      m => 60,  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      h => 60 * 60,  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      d => 60 * 60 * 24,  | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 %_SizeScale = (  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      b => 1,  | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     kb => 1024,  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     mb => 1024 * 1024,  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     gb => 1024 * 1024 * 1024,  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     tb => 1024 * 1024 * 1024 * 1024,  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #+++############################################################################  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # regular expressions                                                          #  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #---############################################################################  | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _init_regexp () {  | 
| 
63
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
 
 | 
34
 | 
     my($label, $byte, $hex4, $ipv4, $ipv6, @tail);  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # simple ones  | 
| 
66
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37
 | 
     $_RE{boolean} = q/true|false/;  | 
| 
67
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
     $_RE{integer} = q/[\+\-]?\d+/;  | 
| 
68
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
44
 | 
     $_RE{number} = q/[\+\-]?(?=\d|\.\d)\d*(?:\.\d*)?(?:[Ee][\+\-]?\d+)?/;  | 
| 
69
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
     $_RE{duration} = q/(?:\d+(?:ms|s|m|h|d))+|\d+/;  | 
| 
70
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1668
 | 
     $_RE{size} = q/\d+[bB]?|(?:\d+\.)?\d+[kKmMgGtT][bB]/;  | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # complex ones  | 
| 
72
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
     $label = q/[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?/;  | 
| 
73
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
     $byte = q/25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d/;  | 
| 
74
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     $hex4 = q/[0-9a-fA-F]{1,4}/;  | 
| 
75
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
52
 | 
     $ipv4 = qq/(($byte)\\.){3}($byte)/;  | 
| 
76
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
148
 | 
     @tail = (  | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ":",  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         "(:($hex4)?|($ipv4))",  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ":(($ipv4)|$hex4(:$hex4)?|)",  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         "(:($ipv4)|:$hex4(:($ipv4)|(:$hex4){0,2})|:)",  | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         "((:$hex4){0,2}(:($ipv4)|(:$hex4){1,2})|:)",  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         "((:$hex4){0,3}(:($ipv4)|(:$hex4){1,2})|:)",  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         "((:$hex4){0,4}(:($ipv4)|(:$hex4){1,2})|:)",  | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
| 
85
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
     $ipv6 = $hex4;  | 
| 
86
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
     foreach my $tail (@tail) {  | 
| 
87
 | 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
249
 | 
         $ipv6 = "$hex4:($ipv6|$tail)";  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
89
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
170
 | 
     $ipv6 = qq/:(:$hex4){0,5}((:$hex4){1,2}|:$ipv4)|$ipv6/;  | 
| 
90
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
47
 | 
     $_RE{hostname} = qq/($label\\.)*$label/;  | 
| 
91
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
     $_RE{ipv4} = $ipv4;  | 
| 
92
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
42
 | 
     $_RE{ipv6} = $ipv6;  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # improve some of them  | 
| 
94
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
     foreach my $name (qw(hostname ipv4 ipv6)) {  | 
| 
95
 | 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
324
 | 
         $_RE{$name} =~ s/\(/(?:/g;  | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # compile them all  | 
| 
98
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
55
 | 
     foreach my $name (keys(%_RE)) {  | 
| 
99
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6059
 | 
         $_RE{$name} = qr/^(?:$_RE{$name})$/;  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 _init_regexp();  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #+++############################################################################  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # helper functions                                                             #  | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #---############################################################################  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # stringify any scalar, including undef  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _string ($) {  | 
| 
116
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
 
 | 
119
 | 
     my($scalar) = @_;  | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
118
 | 
17
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
103
 | 
     return(defined($scalar) ? "$scalar" : "");  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
120
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # format an error  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _errfmt (@);  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _errfmt (@) {  | 
| 
127
 | 
570
 | 
 
 | 
 
 | 
  
570
  
 | 
 
 | 
998
 | 
     my(@errors) = @_;  | 
| 
128
 | 
570
 | 
 
 | 
 
 | 
 
 | 
 
 | 
785
 | 
     my($string, $tmp);  | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
130
 | 
570
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1218
 | 
     return("") unless @errors;  | 
| 
131
 | 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
512
 | 
     $string = shift(@errors);  | 
| 
132
 | 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
661
 | 
     foreach my $error (@errors) {  | 
| 
133
 | 
297
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
678
 | 
         $tmp = ref($error) ? _errfmt(@{ $error }) : $error;  | 
| 
 
 | 
297
 | 
 
 | 
 
 | 
 
 | 
 
 | 
646
 | 
    | 
| 
134
 | 
297
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
768
 | 
         next unless length($tmp);  | 
| 
135
 | 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
393
 | 
         $tmp =~ s/^/  /mg;  | 
| 
136
 | 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
220
 | 
         $string .= "\n" . $tmp;  | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
138
 | 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1028
 | 
     return($string);  | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # expand a duration string and return the corresponding number of seconds  | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub expand_duration ($) {  | 
| 
146
 | 
10
 | 
 
 | 
 
 | 
  
10
  
 | 
  
1
  
 | 
5615
 | 
     my($value) = @_;  | 
| 
147
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
     my($result);  | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
149
 | 
10
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
64
 | 
     if ($value =~ /^(\d+(ms|s|m|h|d))+$/) {  | 
| 
150
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
         $result = 0;  | 
| 
151
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
         while ($value =~ /(\d+)(ms|s|m|h|d)/g) {  | 
| 
152
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
56
 | 
             $result += $1 * $_DurationScale{$2};  | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
155
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         $result = $value;  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
157
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
     return($result);  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # expand a size string and return the corresponding number of bytes  | 
| 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub expand_size ($) {  | 
| 
165
 | 
10
 | 
 
 | 
 
 | 
  
10
  
 | 
  
1
  
 | 
7280
 | 
     my($value) = @_;  | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
167
 | 
10
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
66
 | 
     if ($value =~ /^(.+?)([kmgt]?b)$/i) {  | 
| 
168
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
59
 | 
         return(int($1 * $_SizeScale{lc($2)} + 0.5));  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
170
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
         return($value);  | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # test if a boolean is true or false  | 
| 
176
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub is_true ($) {  | 
| 
179
 | 
347
 | 
 
 | 
 
 | 
  
347
  
 | 
  
1
  
 | 
2062
 | 
     my($value) = @_;  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
181
 | 
347
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
588
 | 
     return(undef) unless defined($value);  | 
| 
182
 | 
343
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
1664
 | 
     return($value and not ref($value) and $value eq "true");  | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub is_false ($) {  | 
| 
186
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
1
  
 | 
11
 | 
     my($value) = @_;  | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
188
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     return(undef) unless defined($value);  | 
| 
189
 | 
4
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
36
 | 
     return($value and not ref($value) and $value eq "false");  | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # return the given thing as a list  | 
| 
194
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub listof ($) {  | 
| 
197
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
1
  
 | 
10
 | 
     my($thing) = @_;  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
199
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     return() unless defined($thing);  | 
| 
200
 | 
4
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     return(@{ $thing }) if ref($thing) eq "ARRAY";  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
    | 
| 
201
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     return($thing);  | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #+++############################################################################  | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # conversion helper functions                                                  #  | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #---############################################################################  | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # string -> hash  | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub string2hash ($) {  | 
| 
215
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
  
1
  
 | 
1579
 | 
     my($string) = @_;  | 
| 
216
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     my(%hash);  | 
| 
217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
218
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     foreach my $kv (split(/\s+/, $string)) {  | 
| 
219
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
44
 | 
         if ($kv =~ /^([^\=]+)=(.*)$/) {  | 
| 
220
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
             $hash{uri_unescape($1)} = uri_unescape($2);  | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
222
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             dief("invalid hash key=value: %s", $kv);  | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
225
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
47
 | 
     return(%hash) if wantarray();  | 
| 
226
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return(\%hash);  | 
| 
227
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
230
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # hash -> string  | 
| 
231
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
232
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
233
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub hash2string (@) {  | 
| 
234
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
1
  
 | 
104
 | 
     my(@args) = @_;  | 
| 
235
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
     my($hash, @kvs);  | 
| 
236
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
237
 | 
5
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
28
 | 
     if (@args == 1 and ref($args[0]) eq "HASH") {  | 
| 
238
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
         $hash = $args[0];  | 
| 
239
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
240
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         $hash = { @args };  | 
| 
241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
242
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     foreach my $key (sort(keys(%{ $hash }))) {  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
    | 
| 
243
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
50
 | 
         push(@kvs, uri_escape($key) . "=" . uri_escape($hash->{$key}));  | 
| 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
245
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
120
 | 
     return(join(" ", @kvs));  | 
| 
246
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
249
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # treeify  | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub treeify ($);  | 
| 
253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub treeify ($) {  | 
| 
254
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
  
1
  
 | 
100
 | 
     my($hash) = @_;  | 
| 
255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
256
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     foreach my $key (grep(/-/, keys(%{ $hash }))) {  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
    | 
| 
257
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
17
 | 
         if ($key =~ /^(\w+)-(.+)$/) {  | 
| 
258
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
             $hash->{$1}{$2} = delete($hash->{$key});  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
260
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             dief("unexpected configuration name: %s", $key);  | 
| 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
263
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     foreach my $value (values(%{ $hash })) {  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
    | 
| 
264
 | 
7
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
20
 | 
         treeify($value) if ref($value) eq "HASH";  | 
| 
265
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
266
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
269
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # return the value of the given option in a treeified hash  | 
| 
270
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
272
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub treeval ($$);  | 
| 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub treeval ($$) {  | 
| 
274
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
  
1
  
 | 
896
 | 
     my($hash, $name) = @_;  | 
| 
275
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
276
 | 
12
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
60
 | 
     return($hash->{$name}) if exists($hash->{$name});  | 
| 
277
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
35
 | 
     if ($name =~ /^(\w+)-(.+)$/) {  | 
| 
278
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
19
 | 
         return() unless $hash->{$1};  | 
| 
279
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
         return(treeval($hash->{$1}, $2));  | 
| 
280
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
281
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return();  | 
| 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #+++############################################################################  | 
| 
285
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
286
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # built-in schemas                                                             #  | 
| 
287
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #---############################################################################  | 
| 
289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
290
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # check that a type is valid  | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _check_type ($$$);  | 
| 
295
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _check_type ($$$) {  | 
| 
296
 | 
58
 | 
 
 | 
 
 | 
  
58
  
 | 
 
 | 
133
 | 
     my($valid, $schema, $data) = @_;  | 
| 
297
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
298
 | 
58
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
247
 | 
     return() if $data =~ /^[a-z46]+$/;  | 
| 
299
 | 
19
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
51
 | 
     return() if $data =~ /^(ref|isa)\(\*\)$/;  | 
| 
300
 | 
19
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
65
 | 
     return() if $data =~ /^(ref|isa)\([\w\:]+\)$/;  | 
| 
301
 | 
16
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
53
 | 
     if ($data =~ /^(list\??|table)\((.+)\)$/) {  | 
| 
302
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37
 | 
         return(_check_type($valid, $schema, $2));  | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
304
 | 
9
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
34
 | 
     if ($data =~ /^valid\((.+)\)$/) {  | 
| 
305
 | 
9
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
44
 | 
         return() if $_Known->{$1};  | 
| 
306
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
         return("unknown schema: $1");  | 
| 
307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
308
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return("unexpected type: $data");  | 
| 
309
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
311
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # schema of a "type"  | 
| 
313
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
314
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
315
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $_BuiltIn->{type} = {  | 
| 
316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     type  => "string",  | 
| 
317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     match => qr/ ^  | 
| 
318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ( anything        # really anything  | 
| 
319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | undef           # undef  | 
| 
320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | undefined       #   "  | 
| 
321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | defined         # not undef  | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | string          # any string  | 
| 
323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | boolean         # either 'true' or 'false'  | 
| 
324
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | number          # any number  | 
| 
325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | integer         # any integer  | 
| 
326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | duration        # any duration, i.e. numbers with hms suffixes  | 
| 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | size            # any size, i.e. number with optional byte-suffix  | 
| 
328
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | hostname        # host name  | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | ipv4            # IPv4 address  | 
| 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | ipv6            # IPv6 address  | 
| 
331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | reference       # any reference, blessed or not  | 
| 
332
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | ref\(\*\)       #   "  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | blessed         # any blessed reference  | 
| 
334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | object          #   "  | 
| 
335
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | isa\(\*\)       #   "  | 
| 
336
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | unblessed       # any reference which is not blessed  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | code            # a code reference (aka ref(CODE))  | 
| 
338
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | regexp          # a regular expression (see is_regexp())  | 
| 
339
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | list            # an homogeneous list  | 
| 
340
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | list\(.+\)      # idem but with the given subtype  | 
| 
341
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | list\?\(.+\)    # shortcut: list?(X) means either X or list(X)  | 
| 
342
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | table           # an homogeneous table  | 
| 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | table\(.+\)     # idem but with the given subtype  | 
| 
344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | struct          # a structure, i.e. a table with known keys  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | ref\(.+\)       # a reference of the given kind  | 
| 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | isa\(.+\)       # an object of the given kind  | 
| 
347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         | valid\(.+\)     # something valid according to the named schema  | 
| 
348
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ) $ /x,  | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     check => \&_check_type,  | 
| 
350
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 };  | 
| 
351
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
352
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
353
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # check that a schema is valid  | 
| 
354
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
355
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _check_schema ($$$);  | 
| 
357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _check_schema ($$$) {  | 
| 
358
 | 
50
 | 
 
 | 
 
 | 
  
50
  
 | 
 
 | 
113
 | 
     my($valid, $schema, $data) = @_;  | 
| 
359
 | 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
78
 | 
     my($field);  | 
| 
360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
361
 | 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
85
 | 
     $field = "min";  | 
| 
362
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     goto unexpected if defined($data->{$field})  | 
| 
363
 | 
50
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
173
 | 
         and not $data->{type} =~ /^(string|number|integer|list.*|table.*)$/;  | 
| 
364
 | 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
79
 | 
     $field = "max";  | 
| 
365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     goto unexpected if defined($data->{$field})  | 
| 
366
 | 
49
 | 
  
 50
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
206
 | 
         and not $data->{type} =~ /^(string|number|integer|list.*|table.*)$/;  | 
| 
367
 | 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
78
 | 
     $field = "match";  | 
| 
368
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     goto unexpected if defined($data->{$field})  | 
| 
369
 | 
49
 | 
  
 50
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
149
 | 
         and not $data->{type} =~ /^(string|table.*)$/;  | 
| 
370
 | 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
80
 | 
     $field = "subtype";  | 
| 
371
 | 
49
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
219
 | 
     if ($data->{type} =~ /^(list|table)$/) {  | 
| 
372
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         goto missing unless defined($data->{$field});  | 
| 
373
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
374
 | 
48
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
135
 | 
         goto unexpected if defined($data->{$field});  | 
| 
375
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
376
 | 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
86
 | 
     $field = "fields";  | 
| 
377
 | 
49
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
166
 | 
     if ($data->{type} =~ /^(struct)$/) {  | 
| 
378
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
14
 | 
         goto missing unless defined($data->{$field});  | 
| 
379
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
380
 | 
46
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
117
 | 
         goto unexpected if defined($data->{$field});  | 
| 
381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
382
 | 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
94
 | 
     return();  | 
| 
383
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   unexpected:  | 
| 
384
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return(sprintf("unexpected schema field for type %s: %s",  | 
| 
385
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
                    $data->{type}, $field));  | 
| 
386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   missing:  | 
| 
387
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return(sprintf("missing schema field for type %s: %s",  | 
| 
388
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                    $data->{type}, $field));  | 
| 
389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
391
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
392
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # schema of a "schema"  | 
| 
393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
394
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
395
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $_BuiltIn->{schema} = {  | 
| 
396
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     type   => "struct",  | 
| 
397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     fields => {  | 
| 
398
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         type     => { type => "list?(valid(type))" },  | 
| 
399
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         subtype  => { type => "valid(schema)",        optional => "true" },  | 
| 
400
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         fields   => { type => "table(valid(schema))", optional => "true" },  | 
| 
401
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         optional => { type => "boolean",              optional => "true" },  | 
| 
402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         min      => { type => "number",               optional => "true" },  | 
| 
403
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         max      => { type => "number",               optional => "true" },  | 
| 
404
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         match    => { type => "regexp",               optional => "true" },  | 
| 
405
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         check    => { type => "code",                 optional => "true" },  | 
| 
406
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     },  | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     check => \&_check_schema,  | 
| 
408
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 };  | 
| 
409
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #+++############################################################################  | 
| 
411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
412
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # options helpers                                                              #  | 
| 
413
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
414
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #---############################################################################  | 
| 
415
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
417
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # schema -> options  | 
| 
418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _options ($$$@);  | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _options ($$$@) {  | 
| 
422
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
     my($valid, $schema, $type, @path) = @_;  | 
| 
423
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my(@list);  | 
| 
424
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
425
 | 
  
0
  
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     $type ||= $schema->{type};  | 
| 
426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # terminal  | 
| 
427
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return(join("-", @path) . "=s") if $type eq "string";  | 
| 
428
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return(join("-", @path) . "=f") if $type eq "number";  | 
| 
429
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return(join("-", @path) . "=i") if $type eq "integer";  | 
| 
430
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return(join("-", @path) . "!")  if $type eq "boolean";  | 
| 
431
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # assumed to come from strings  | 
| 
432
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     return(join("-", @path) . "=s")  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
433
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if $type =~ /^isa\(.+\)$/  | 
| 
434
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         or $type eq "table(string)"  | 
| 
435
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         or $type =~ /^(duration|hostname|ipv[46]|regexp|size)$/;  | 
| 
436
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # recursion  | 
| 
437
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if ($type =~ /^list\?\((.+)\)$/) {  | 
| 
438
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return(map($_ . "\@", _options($valid, $schema, $1, @path)));  | 
| 
439
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
440
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if ($type =~ /^valid\((.+)\)$/) {  | 
| 
441
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         dief("options(): unknown schema: %s", $1) unless $valid->{$1};  | 
| 
442
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return(_options($valid, $valid->{$1}, undef, @path));  | 
| 
443
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
444
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if ($type eq "struct") {  | 
| 
445
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         foreach my $field (keys(%{ $schema->{fields} })) {  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
446
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             push(@list, _options($valid, $schema->{fields}{$field},  | 
| 
447
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                  undef, @path, $field));  | 
| 
448
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
449
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return(@list);  | 
| 
450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
451
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # unsupported  | 
| 
452
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     dief("options(): unsupported type: %s", $type);  | 
| 
453
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
454
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
455
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
456
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # treat the given options as mutually exclusive  | 
| 
457
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
458
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
459
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub mutex ($@) {  | 
| 
460
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my($hash, @options) = @_;  | 
| 
461
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my(@list);  | 
| 
462
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
463
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     foreach my $opt (@options) {  | 
| 
464
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         next unless defined(treeval($hash, $opt));  | 
| 
465
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         push(@list, $opt);  | 
| 
466
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         dief("options %s and %s are mutually exclusive", @list) if @list == 2;  | 
| 
467
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
468
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
469
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
470
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
471
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # if the first option is set, all the others are required  | 
| 
472
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
473
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
474
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub reqall ($$@) {  | 
| 
475
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my($hash, $opt1, @options) = @_;  | 
| 
476
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
477
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     return unless not defined($opt1) or defined(treeval($hash, $opt1));  | 
| 
478
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     foreach my $opt2 (@options) {  | 
| 
479
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         next if defined(treeval($hash, $opt2));  | 
| 
480
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         dief("option %s requires option %s", $opt1, $opt2) if defined($opt1);  | 
| 
481
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         dief("option %s is required", $opt2);  | 
| 
482
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
483
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
484
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
485
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
486
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # if the first option is set, one at least of the others is required  | 
| 
487
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
488
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub reqany ($$@) {  | 
| 
490
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my($hash, $opt1, @options) = @_;  | 
| 
491
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my($req);  | 
| 
492
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
493
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     return unless not defined($opt1) or defined(treeval($hash, $opt1));  | 
| 
494
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     foreach my $opt2 (@options) {  | 
| 
495
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return if defined(treeval($hash, $opt2));  | 
| 
496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
497
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if (@options <= 2) {  | 
| 
498
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $req = join(" or ", @options);  | 
| 
499
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
500
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         push(@options, join(" or ", splice(@options, -2)));  | 
| 
501
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $req = join(", ", @options);  | 
| 
502
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
503
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     dief("option %s requires option %s", $opt1, $req) if defined($opt1);  | 
| 
504
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     dief("option %s is required", $req);  | 
| 
505
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
506
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
507
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #+++############################################################################  | 
| 
508
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
509
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # traverse helpers                                                             #  | 
| 
510
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
511
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #---############################################################################  | 
| 
512
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
513
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
514
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # traverse data  | 
| 
515
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
516
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
517
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _traverse_list ($$$$$$@) {  | 
| 
518
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
5
 | 
     my($callback, $valid, $schema, $reftype, $subtype, $data, @path) = @_;  | 
| 
519
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
520
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     return unless $reftype eq "ARRAY";  | 
| 
521
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     foreach my $val (@{ $data }) {  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
    | 
| 
522
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
         _traverse($callback, $valid, $schema, $subtype,  | 
| 
523
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                   $val, @path, 0);  | 
| 
524
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
525
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
526
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
527
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _traverse_table ($$$$$$@) {  | 
| 
528
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
5
 | 
     my($callback, $valid, $schema, $reftype, $subtype, $data, @path) = @_;  | 
| 
529
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
530
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     return unless $reftype eq "HASH";  | 
| 
531
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     foreach my $key (keys(%{ $data })) {  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
    | 
| 
532
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         _traverse($callback, $valid, $schema, $subtype,  | 
| 
533
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
                   $data->{$key}, @path, $key);  | 
| 
534
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
535
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
536
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
537
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _traverse_struct ($$$$$$@) {  | 
| 
538
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
8
 | 
     my($callback, $valid, $schema, $reftype, $subtype, $data, @path) = @_;  | 
| 
539
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
540
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     return unless $reftype eq "HASH";  | 
| 
541
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     foreach my $key (keys(%{ $schema->{fields} })) {  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
542
 | 
6
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
14
 | 
         next unless exists($data->{$key});  | 
| 
543
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         _traverse($callback, $valid, $schema->{fields}{$key}, undef,  | 
| 
544
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
                   $data->{$key}, @path, $key);  | 
| 
545
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
546
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
547
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
548
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _traverse ($$$$$@);  | 
| 
549
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _traverse ($$$$$@) {  | 
| 
550
 | 
18
 | 
 
 | 
 
 | 
  
18
  
 | 
 
 | 
48
 | 
     my($callback, $valid, $schema, $type, $data, @path) = @_;  | 
| 
551
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
     my($reftype, $subtype);  | 
| 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # set the type if missing  | 
| 
554
 | 
18
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
75
 | 
     $type ||= $schema->{type};  | 
| 
555
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # call the callback and stop unless we are told to continue  | 
| 
556
 | 
18
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
47
 | 
     return unless $callback->($valid, $schema, $type, $_[4], @path);  | 
| 
557
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # terminal  | 
| 
558
 | 
18
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
28986
 | 
     return if $type =~ /^(boolean|number|integer)$/;  | 
| 
559
 | 
12
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
32
 | 
     return if $type =~ /^(duration|size|hostname|ipv[46])$/;  | 
| 
560
 | 
12
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
28
 | 
     return if $type =~ /^(undef|undefined|defined|blessed|unblessed)$/;  | 
| 
561
 | 
12
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
28
 | 
     return if $type =~ /^(anything|string|regexp|object|reference|code)$/;  | 
| 
562
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # recursion  | 
| 
563
 | 
12
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
51
 | 
     $reftype = reftype($data) || "";  | 
| 
564
 | 
12
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
48
 | 
     if ($type =~ /^valid\((.+)\)$/) {  | 
| 
565
 | 
8
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
29
 | 
         dief("traverse(): unknown schema: %s", $1) unless $valid->{$1};  | 
| 
566
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
         _traverse($callback, $valid, $valid->{$1}, undef, $_[4], @path);  | 
| 
567
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
         return;  | 
| 
568
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
569
 | 
4
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     if ($type eq "struct") {  | 
| 
570
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
         _traverse_struct($callback, $valid, $schema,  | 
| 
571
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          $reftype, $subtype, $data, @path);  | 
| 
572
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
         return;  | 
| 
573
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
574
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     if ($type =~ /^list$/) {  | 
| 
575
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         _traverse_list($callback, $valid, $schema->{subtype},  | 
| 
576
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                        $reftype, $subtype, $data, @path);  | 
| 
577
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return;  | 
| 
578
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
579
 | 
2
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     if ($type =~ /^list\((.+)\)$/) {  | 
| 
580
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
         _traverse_list($callback, $valid, $schema,  | 
| 
581
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                        $reftype, $1, $data, @path);  | 
| 
582
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         return;  | 
| 
583
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
584
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5
 | 
     if ($type =~ /^list\?\((.+)\)$/) {  | 
| 
585
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if ($reftype eq "ARRAY") {  | 
| 
586
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             _traverse_list($callback, $valid, $schema,  | 
| 
587
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                            $reftype, $1, $data, @path);  | 
| 
588
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
589
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             _traverse($callback, $valid, $schema,  | 
| 
590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                       $1, $_[4], @path);  | 
| 
591
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
592
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return;  | 
| 
593
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
594
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     if ($type =~ /^table$/) {  | 
| 
595
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         _traverse_table($callback, $valid, $schema->{subtype},  | 
| 
596
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                         $reftype, $subtype, $data, @path);  | 
| 
597
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return;  | 
| 
598
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
599
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     if ($type =~ /^table\((.+)\)$/) {  | 
| 
600
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
         _traverse_table($callback, $valid, $schema,  | 
| 
601
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         $reftype, $1, $data, @path);  | 
| 
602
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         return;  | 
| 
603
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
604
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # unsupported  | 
| 
605
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     dief("traverse(): unsupported type: %s", $type);  | 
| 
606
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
607
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
608
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #+++############################################################################  | 
| 
609
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
610
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # validation helpers                                                           #  | 
| 
611
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
612
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #---############################################################################  | 
| 
613
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
614
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
615
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # test if something is a regular expression  | 
| 
616
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
617
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
618
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 if ($] >= 5.010) {  | 
| 
619
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     require re;  | 
| 
620
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     re->import(qw(is_regexp));  | 
| 
621
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 } else {  | 
| 
622
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     *is_regexp = sub { return(ref($_[0]) eq "Regexp") };  | 
| 
623
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
624
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
625
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
626
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # validate that a value is within a numerical range  | 
| 
627
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
628
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
629
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _validate_range ($$$$) {  | 
| 
630
 | 
44
 | 
 
 | 
 
 | 
  
44
  
 | 
 
 | 
119
 | 
     my($what, $value, $min, $max) = @_;  | 
| 
631
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
632
 | 
44
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
221
 | 
     return(sprintf("%s is not >= %s: %s", $what, $min, $value))  | 
| 
633
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if defined($min) and not $value >= $min;  | 
| 
634
 | 
37
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
156
 | 
     return(sprintf("%s is not <= %s: %s", $what, $max, $value))  | 
| 
635
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if defined($max) and not $value <= $max;  | 
| 
636
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
65
 | 
     return();  | 
| 
637
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
638
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
639
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
640
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # validate a list of homogeneous elements  | 
| 
641
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
642
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
643
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _validate_list ($$$) {  | 
| 
644
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
24
 | 
     my($valid, $schema, $data) = @_;  | 
| 
645
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
     my(@errors, $index, $element);  | 
| 
646
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
647
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
46
 | 
     @errors = _validate_range("size", scalar(@{ $data }),  | 
| 
648
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                               $schema->{min}, $schema->{max})  | 
| 
649
 | 
13
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
43
 | 
         if defined($schema->{min}) or defined($schema->{max});  | 
| 
650
 | 
13
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
36
 | 
     return(@errors) if @errors;  | 
| 
651
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     $index = 0;  | 
| 
652
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     foreach my $tmp (@{ $data }) {  | 
| 
 
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
    | 
| 
653
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
         $element = $tmp; # preserved outside loop  | 
| 
654
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
         @errors = _validate($valid, $schema->{subtype}, $element);  | 
| 
655
 | 
12
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
33
 | 
         goto invalid if @errors;  | 
| 
656
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
         $index++;  | 
| 
657
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
658
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     return();  | 
| 
659
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
   invalid:  | 
| 
660
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return(sprintf("invalid element %d: %s",  | 
| 
661
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                    $index, _string($element)), \@errors);  | 
| 
662
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
663
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
664
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
665
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # validate a table of homogeneous elements  | 
| 
666
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
667
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
668
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _validate_table ($$$) {  | 
| 
669
 | 
44
 | 
 
 | 
 
 | 
  
44
  
 | 
 
 | 
99
 | 
     my($valid, $schema, $data) = @_;  | 
| 
670
 | 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
80
 | 
     my(@errors, $key);  | 
| 
671
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
672
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
     @errors = _validate_range("size", scalar(keys(%{ $data })),  | 
| 
673
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                               $schema->{min}, $schema->{max})  | 
| 
674
 | 
44
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
212
 | 
         if defined($schema->{min}) or defined($schema->{max});  | 
| 
675
 | 
44
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
110
 | 
     return(@errors) if @errors;  | 
| 
676
 | 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
71
 | 
     foreach my $tmp (keys(%{ $data })) {  | 
| 
 
 | 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
140
 | 
    | 
| 
677
 | 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
97
 | 
         $key = $tmp; # preserved outside loop  | 
| 
678
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         @errors = (sprintf("key does not match %s: %s",  | 
| 
679
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                            $schema->{match}, $key))  | 
| 
680
 | 
57
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
170
 | 
             if defined($schema->{match}) and not $key =~ $schema->{match};  | 
| 
681
 | 
57
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
131
 | 
         goto invalid if @errors;  | 
| 
682
 | 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
195
 | 
         @errors = _validate($valid, $schema->{subtype}, $data->{$key});  | 
| 
683
 | 
56
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
179
 | 
         goto invalid if @errors;  | 
| 
684
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
685
 | 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
85
 | 
     return();  | 
| 
686
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   invalid:  | 
| 
687
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return(sprintf("invalid element %s: %s",  | 
| 
688
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
                    $key, _string($data->{$key})), \@errors);  | 
| 
689
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
690
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
691
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
692
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # validate a struct, i.e. a hash with known fields  | 
| 
693
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
694
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
695
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _validate_struct ($$$) {  | 
| 
696
 | 
59
 | 
 
 | 
 
 | 
  
59
  
 | 
 
 | 
111
 | 
     my($valid, $schema, $data) = @_;  | 
| 
697
 | 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
125
 | 
     my(@errors, $key);  | 
| 
698
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
699
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # check the missing fields  | 
| 
700
 | 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
81
 | 
     foreach my $tmp (keys(%{ $schema->{fields} })) {  | 
| 
 
 | 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
262
 | 
    | 
| 
701
 | 
431
 | 
 
 | 
 
 | 
 
 | 
 
 | 
615
 | 
         $key = $tmp; # preserved outside loop  | 
| 
702
 | 
431
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
795
 | 
         next if exists($data->{$key});  | 
| 
703
 | 
342
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
662
 | 
         next if is_true($schema->{fields}{$key}{optional});  | 
| 
704
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
         return(sprintf("missing field: %s", $key));  | 
| 
705
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
706
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # check the existing fields  | 
| 
707
 | 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
116
 | 
     foreach my $tmp (keys(%{ $data })) {  | 
| 
 
 | 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
202
 | 
    | 
| 
708
 | 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
131
 | 
         $key = $tmp; # preserved outside loop  | 
| 
709
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return(sprintf("unexpected field: %s", $key))  | 
| 
710
 | 
88
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
224
 | 
             unless $schema->{fields}{$key};  | 
| 
711
 | 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
230
 | 
         @errors = _validate($valid, $schema->{fields}{$key}, $data->{$key});  | 
| 
712
 | 
87
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
275
 | 
         goto invalid if @errors;  | 
| 
713
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
714
 | 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
122
 | 
     return();  | 
| 
715
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   invalid:  | 
| 
716
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return(sprintf("invalid field %s: %s",  | 
| 
717
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
                    $key, _string($data->{$key})), \@errors);  | 
| 
718
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
719
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
720
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
721
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # validate something using multiple possible types  | 
| 
722
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
723
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
724
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _validate_multiple ($$$@) {  | 
| 
725
 | 
58
 | 
 
 | 
 
 | 
  
58
  
 | 
 
 | 
214
 | 
     my($valid, $schema, $data, @types) = @_;  | 
| 
726
 | 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
114
 | 
     my(@errors, %tmpschema, @tmperrors);  | 
| 
727
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
728
 | 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
82
 | 
     %tmpschema = %{ $schema };  | 
| 
 
 | 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
193
 | 
    | 
| 
729
 | 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
136
 | 
     foreach my $type (@types) {  | 
| 
730
 | 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
131
 | 
         $tmpschema{type} = $type;  | 
| 
731
 | 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
228
 | 
         @tmperrors = _validate($valid, \%tmpschema, $data);  | 
| 
732
 | 
65
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
245
 | 
         return() unless @tmperrors;  | 
| 
733
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
         push(@errors, [ @tmperrors ]);  | 
| 
734
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
735
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     return(sprintf("invalid data (none of the types could be validated): %s",  | 
| 
736
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                    _string($data)), @errors);  | 
| 
737
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
738
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
739
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
740
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # validate data (non-reference types)  | 
| 
741
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
742
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
743
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _validate_data_nonref ($$) {  | 
| 
744
 | 
418
 | 
 
 | 
 
 | 
  
418
  
 | 
 
 | 
927
 | 
     my($schema, $data) = @_;  | 
| 
745
 | 
418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
599
 | 
     my($type, @errors);  | 
| 
746
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
747
 | 
418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
702
 | 
     $type = $schema->{type};  | 
| 
748
 | 
418
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1436
 | 
     if ($type eq "string") {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
749
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         @errors = _validate_range  | 
| 
750
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             ("length", length($data), $schema->{min}, $schema->{max})  | 
| 
751
 | 
67
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
305
 | 
             if defined($schema->{min}) or defined($schema->{max});  | 
| 
752
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         @errors = (sprintf("value does not match %s: %s",  | 
| 
753
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                            $schema->{match}, $data))  | 
| 
754
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if not @errors and defined($schema->{match})  | 
| 
755
 | 
67
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
738
 | 
                 and not $data =~ $schema->{match};  | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
756
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($type =~ /^(boolean|hostname|ipv[46])$/) {  | 
| 
757
 | 
257
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2930
 | 
         goto invalid unless $data =~ $_RE{$type};  | 
| 
758
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # additional hard-coded checks for host names...  | 
| 
759
 | 
136
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
348
 | 
         if ($type eq "hostname") {  | 
| 
760
 | 
13
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
77
 | 
             goto invalid if ".$data." =~ /\.\d+\./;  | 
| 
761
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
             @errors = _validate_range("length", length($data), 1, 255);  | 
| 
762
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
763
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($type =~ /^(integer|number|duration|size)$/) {  | 
| 
764
 | 
94
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
998
 | 
         goto invalid unless $data =~ $_RE{$type};  | 
| 
765
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         @errors = _validate_range  | 
| 
766
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             ("value", $data, $schema->{min}, $schema->{max})  | 
| 
767
 | 
68
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
307
 | 
             if defined($schema->{min}) or defined($schema->{max});  | 
| 
768
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
769
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return(sprintf("unexpected type: %s", $type));  | 
| 
770
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
771
 | 
268
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
833
 | 
     return() unless @errors;  | 
| 
772
 | 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1008
 | 
   invalid:  | 
| 
773
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return(sprintf("invalid %s: %s", $type, $data), \@errors);  | 
| 
774
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
775
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
776
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
777
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # validate data (reference types)  | 
| 
778
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
779
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
780
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ## no critic (ProhibitCascadingIfElse, ProhibitExcessComplexity)  | 
| 
781
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _validate_data_ref ($$$$) {  | 
| 
782
 | 
164
 | 
 
 | 
 
 | 
  
164
  
 | 
 
 | 
349
 | 
     my($valid, $schema, $data, $reftype) = @_;  | 
| 
783
 | 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
261
 | 
     my(@errors, %tmpschema, $blessed);  | 
| 
784
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
785
 | 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
368
 | 
     $blessed = defined(blessed($data));  | 
| 
786
 | 
164
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1190
 | 
     if ($schema->{type} =~ /^(blessed|object|isa\(\*\))$/) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
787
 | 
7
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
61
 | 
         goto invalid unless $blessed;  | 
| 
788
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($schema->{type} eq "unblessed") {  | 
| 
789
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         goto invalid if $blessed;  | 
| 
790
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($schema->{type} eq "code") {  | 
| 
791
 | 
9
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
68
 | 
         goto invalid unless $reftype eq "CODE";  | 
| 
792
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($schema->{type} eq "regexp") {  | 
| 
793
 | 
10
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
85
 | 
         goto invalid unless is_regexp($data);  | 
| 
794
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($schema->{type} eq "list") {  | 
| 
795
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
50
 | 
         goto invalid unless $reftype eq "ARRAY";  | 
| 
796
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
         @errors = _validate_list($valid, $schema, $data);  | 
| 
797
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($schema->{type} =~ /^list\((.+)\)$/) {  | 
| 
798
 | 
10
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
24
 | 
         goto invalid unless $reftype eq "ARRAY";  | 
| 
799
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
         %tmpschema = %{ $schema };  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
42
 | 
    | 
| 
800
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
38
 | 
         $tmpschema{subtype} = { type => $1 };  | 
| 
801
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
         @errors = _validate_list($valid, \%tmpschema, $data);  | 
| 
802
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($schema->{type} eq "table") {  | 
| 
803
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         goto invalid unless $reftype eq "HASH";  | 
| 
804
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         @errors = _validate_table($valid, $schema, $data);  | 
| 
805
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($schema->{type} =~ /^table\((.+)\)$/) {  | 
| 
806
 | 
45
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
138
 | 
         goto invalid unless $reftype eq "HASH";  | 
| 
807
 | 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
83
 | 
         %tmpschema = %{ $schema };  | 
| 
 
 | 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
313
 | 
    | 
| 
808
 | 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
206
 | 
         $tmpschema{subtype} = { type => $1 };  | 
| 
809
 | 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
163
 | 
         @errors = _validate_table($valid, \%tmpschema, $data);  | 
| 
810
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($schema->{type} eq "struct") {  | 
| 
811
 | 
59
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
136
 | 
         goto invalid unless $reftype eq "HASH";  | 
| 
812
 | 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
152
 | 
         @errors = _validate_struct($valid, $schema, $data);  | 
| 
813
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($schema->{type} =~ /^ref\((.+)\)$/) {  | 
| 
814
 | 
14
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
130
 | 
         goto invalid unless $reftype eq $1;  | 
| 
815
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($schema->{type} =~ /^isa\((.+)\)$/) {  | 
| 
816
 | 
7
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
70
 | 
         goto invalid unless $blessed and $data->isa($1);  | 
| 
817
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
818
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return(sprintf("unexpected type: %s", $schema->{type}));  | 
| 
819
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
820
 | 
133
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
389
 | 
     return() unless @errors;  | 
| 
821
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   invalid:  | 
| 
822
 | 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
318
 | 
     return(sprintf("invalid %s: %s", $schema->{type}, $data), \@errors);  | 
| 
823
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
824
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ## use critic  | 
| 
825
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
826
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
827
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # validate something  | 
| 
828
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
829
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
830
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _validate ($$$);  | 
| 
831
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _validate ($$$) {  | 
| 
832
 | 
849
 | 
 
 | 
 
 | 
  
849
  
 | 
 
 | 
1572
 | 
     my($valid, $schema, $data) = @_;  | 
| 
833
 | 
849
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1314
 | 
     my($type, @errors, $reftype, $blessed, %tmpschema);  | 
| 
834
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
835
 | 
849
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1734
 | 
     $type = $schema->{type};  | 
| 
836
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # check multiple types  | 
| 
837
 | 
849
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1916
 | 
     if (ref($type) eq "ARRAY") {  | 
| 
838
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return(_validate_multiple($valid, $schema, $data, @{ $type }));  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
839
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
840
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # check list?(X)  | 
| 
841
 | 
849
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1842
 | 
     if ($type =~ /^list\?\((.+)\)$/) {  | 
| 
842
 | 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
262
 | 
         return(_validate_multiple($valid, $schema, $data, $1, "list($1)"));  | 
| 
843
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
844
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # check valid(X)  | 
| 
845
 | 
791
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1601
 | 
     if ($type =~ /^valid\((.+)\)$/) {  | 
| 
846
 | 
105
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
309
 | 
         return(sprintf("unexpected schema: %s", $1)) unless $valid->{$1};  | 
| 
847
 | 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
409
 | 
         return(_validate($valid, $valid->{$1}, $data));  | 
| 
848
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
849
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # check anything  | 
| 
850
 | 
686
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1338
 | 
     goto good if $type eq "anything";  | 
| 
851
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # check if defined  | 
| 
852
 | 
675
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1375
 | 
     if ($type =~ /^(undef|undefined)$/) {  | 
| 
853
 | 
11
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
44
 | 
         goto invalid if defined($data);  | 
| 
854
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         goto good;  | 
| 
855
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
856
 | 
664
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1388
 | 
     return(sprintf("invalid %s: ", $type))  | 
| 
857
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         unless defined($data);  | 
| 
858
 | 
650
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1501
 | 
     goto good if $type eq "defined";  | 
| 
859
 | 
640
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1539
 | 
     $reftype = reftype($data);  | 
| 
860
 | 
640
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
3385
 | 
     if ($type =~ /^(string|boolean|number|integer)$/ or  | 
| 
861
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $type =~ /^(duration|size|hostname|ipv[46])$/) {  | 
| 
862
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # check reference type (for non-reference)  | 
| 
863
 | 
436
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
970
 | 
         goto invalid if defined($reftype);  | 
| 
864
 | 
418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
929
 | 
         @errors = _validate_data_nonref($schema, $data);  | 
| 
865
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
866
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # check reference type (for reference)  | 
| 
867
 | 
204
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
526
 | 
         goto invalid unless defined($reftype);  | 
| 
868
 | 
171
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
371
 | 
         goto good if $type =~ /^(reference|ref\(\*\))$/;  | 
| 
869
 | 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
439
 | 
         @errors = _validate_data_ref($valid, $schema, $data, $reftype);  | 
| 
870
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
871
 | 
582
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1578
 | 
     return(@errors) if @errors;  | 
| 
872
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   good:  | 
| 
873
 | 
397
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
923
 | 
     @errors = $schema->{check}->($valid, $schema, $data) if $schema->{check};  | 
| 
874
 | 
397
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1122
 | 
     return() unless @errors;  | 
| 
875
 | 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
380
 | 
   invalid:  | 
| 
876
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return(sprintf("invalid %s: %s", $type, $data), \@errors);  | 
| 
877
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
878
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
879
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #+++############################################################################  | 
| 
880
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
881
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # object oriented interface                                                    #  | 
| 
882
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #                                                                              #  | 
| 
883
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #---############################################################################  | 
| 
884
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
885
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
886
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # create a validator object  | 
| 
887
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
888
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
889
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub new : method {  | 
| 
890
 | 
36
 | 
 
 | 
 
 | 
  
36
  
 | 
  
1
  
 | 
11861
 | 
     my($class, $self, @errors);  | 
| 
891
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
892
 | 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
91
 | 
     $class = shift(@_);  | 
| 
893
 | 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
66
 | 
     $self = {};  | 
| 
894
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # find out which schema(s) to use  | 
| 
895
 | 
36
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
153
 | 
     if (@_ == 0) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
896
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
         $self->{schema} = $_BuiltIn;  | 
| 
897
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif (@_ == 1) {  | 
| 
898
 | 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
104
 | 
         $self->{schema}{""} = $_[0];  | 
| 
899
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif (@_ % 2 == 0) {  | 
| 
900
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
         $self->{schema} = { @_ };  | 
| 
901
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
902
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
         dief("new(): unexpected number of arguments: %d", scalar(@_));  | 
| 
903
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
904
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # validate them  | 
| 
905
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     {  | 
| 
906
 | 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
64
 | 
             local $_Known = $self->{schema};  | 
| 
 
 | 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
76
 | 
    | 
| 
907
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             @errors = _validate($_BuiltIn, { type => "table(valid(schema))" },  | 
| 
908
 | 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
136
 | 
                             $self->{schema});  | 
| 
909
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
910
 | 
35
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
165
 | 
     dief("new(): invalid schema: %s", _errfmt(@errors)) if @errors;  | 
| 
911
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # so far so good!  | 
| 
912
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
76
 | 
     bless($self, $class);  | 
| 
913
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
116
 | 
     return($self);  | 
| 
914
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
915
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
916
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
917
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # convert to a list of options  | 
| 
918
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
919
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
920
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub options : method {  | 
| 
921
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my($self, $schema);  | 
| 
922
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
923
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self = shift(@_);  | 
| 
924
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # find out which schema to convert to options  | 
| 
925
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if (@_ == 0) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
926
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         dief("options(): no default schema")  | 
| 
927
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             unless $self->{schema}{""};  | 
| 
928
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $schema = $self->{schema}{""};  | 
| 
929
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif (@_ == 1) {  | 
| 
930
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $schema = shift(@_);  | 
| 
931
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         dief("options(): unknown schema: %s", $schema)  | 
| 
932
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             unless $self->{schema}{$schema};  | 
| 
933
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $schema = $self->{schema}{$schema};  | 
| 
934
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
935
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         dief("options(): unexpected number of arguments: %d", scalar(@_));  | 
| 
936
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
937
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # convert to options  | 
| 
938
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return(_options($self->{schema}, $schema, undef));  | 
| 
939
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
940
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
941
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
942
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # validate the given data  | 
| 
943
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
944
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
945
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub validate : method {  | 
| 
946
 | 
489
 | 
 
 | 
 
 | 
  
489
  
 | 
  
1
  
 | 
210478
 | 
     my($self, $data, $schema, @errors);  | 
| 
947
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
948
 | 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1163
 | 
     $self = shift(@_);  | 
| 
949
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # find out what to validate against  | 
| 
950
 | 
489
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1061
 | 
     if (@_ == 1) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
951
 | 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
754
 | 
         $data = shift(@_);  | 
| 
952
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         dief("validate(): no default schema")  | 
| 
953
 | 
489
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1321
 | 
             unless $self->{schema}{""};  | 
| 
954
 | 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
817
 | 
         $schema = $self->{schema}{""};  | 
| 
955
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif (@_ == 2) {  | 
| 
956
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $data = shift(@_);  | 
| 
957
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $schema = shift(@_);  | 
| 
958
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         dief("validate(): unknown schema: %s", $schema)  | 
| 
959
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             unless $self->{schema}{$schema};  | 
| 
960
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $schema = $self->{schema}{$schema};  | 
| 
961
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
962
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         dief("validate(): unexpected number of arguments: %d", scalar(@_));  | 
| 
963
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
964
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # validate data  | 
| 
965
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     {  | 
| 
966
 | 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
662
 | 
         local $_Known = $self->{schema};  | 
| 
 
 | 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
873
 | 
    | 
| 
967
 | 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1051
 | 
         @errors = _validate($self->{schema}, $schema, $data);  | 
| 
968
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
969
 | 
489
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1568
 | 
     dief("validate(): %s", _errfmt(@errors)) if @errors;  | 
| 
970
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
971
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
972
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
973
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # traverse the given data  | 
| 
974
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
975
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
976
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub traverse : method {  | 
| 
977
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
1
  
 | 
531
 | 
     my($self, $callback, $data, $schema);  | 
| 
978
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
979
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     $self = shift(@_);  | 
| 
980
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # find out what to traverse  | 
| 
981
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
8
 | 
     if (@_ == 2) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
982
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $callback = shift(@_);  | 
| 
983
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $data = shift(@_);  | 
| 
984
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         dief("traverse(): no default schema")  | 
| 
985
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             unless $self->{schema}{""};  | 
| 
986
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $schema = $self->{schema}{""};  | 
| 
987
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif (@_ == 3) {  | 
| 
988
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         $callback = shift(@_);  | 
| 
989
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         $data = shift(@_);  | 
| 
990
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         $schema = shift(@_);  | 
| 
991
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         dief("traverse(): unknown schema: %s", $schema)  | 
| 
992
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
11
 | 
             unless $self->{schema}{$schema};  | 
| 
993
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         $schema = $self->{schema}{$schema};  | 
| 
994
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
995
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         dief("traverse(): unexpected number of arguments: %d", scalar(@_));  | 
| 
996
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
997
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # traverse data  | 
| 
998
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     _traverse($callback, $self->{schema}, $schema, undef, $data);  | 
| 
999
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1000
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1001
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1002
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # export control  | 
| 
1003
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1004
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1005
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub import : method {  | 
| 
1006
 | 
11
 | 
 
 | 
 
 | 
  
11
  
 | 
 
 | 
103
 | 
     my($pkg, %exported);  | 
| 
1007
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1008
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
     $pkg = shift(@_);  | 
| 
1009
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
     foreach my $name (qw(string2hash hash2string treeify treeval  | 
| 
1010
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          expand_duration expand_size  | 
| 
1011
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          is_true is_false is_regexp listof  | 
| 
1012
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          mutex reqall reqany)) {  | 
| 
1013
 | 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
253
 | 
         $exported{$name}++;  | 
| 
1014
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1015
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
61
 | 
     export_control(scalar(caller()), $pkg, \%exported, @_);  | 
| 
1016
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1017
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1018
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
1019
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1020
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __DATA__  |