line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Class::Usul::Functions; |
2
|
|
|
|
|
|
|
|
3
|
28
|
|
|
28
|
|
806596
|
use strict; |
|
28
|
|
|
|
|
71
|
|
|
28
|
|
|
|
|
782
|
|
4
|
28
|
|
|
28
|
|
154
|
use warnings; |
|
28
|
|
|
|
|
83
|
|
|
28
|
|
|
|
|
782
|
|
5
|
28
|
|
|
28
|
|
1036
|
use parent 'Exporter::Tiny'; |
|
28
|
|
|
|
|
599
|
|
|
28
|
|
|
|
|
166
|
|
6
|
|
|
|
|
|
|
|
7
|
28
|
|
|
28
|
|
20922
|
use Class::Inspector; |
|
28
|
|
|
|
|
83249
|
|
|
28
|
|
|
|
|
918
|
|
8
|
28
|
|
|
28
|
|
13209
|
use Class::Null; |
|
28
|
|
|
|
|
9130
|
|
|
28
|
|
|
|
|
1061
|
|
9
|
28
|
|
|
|
|
329
|
use Class::Usul::Constants qw( ASSERT DEFAULT_CONFHOME DEFAULT_ENVDIR |
10
|
|
|
|
|
|
|
DIGEST_ALGORITHMS EXCEPTION_CLASS |
11
|
|
|
|
|
|
|
PERL_EXTNS PREFIX UNTAINT_CMDLINE |
12
|
28
|
|
|
28
|
|
1513
|
UNTAINT_IDENTIFIER UNTAINT_PATH UUID_PATH ); |
|
28
|
|
|
|
|
73
|
|
13
|
28
|
|
|
28
|
|
36002
|
use Cwd qw( ); |
|
28
|
|
|
|
|
86
|
|
|
28
|
|
|
|
|
5505
|
|
14
|
|
|
|
|
|
|
use Data::Printer alias => q(_data_dumper), colored => 1, indent => 3, |
15
|
0
|
|
|
|
|
0
|
filters => { 'DateTime' => sub { $_[ 0 ].q() }, |
16
|
8
|
|
|
|
|
27196
|
'File::DataClass::IO' => sub { $_[ 0 ]->pathname }, |
17
|
0
|
|
|
|
|
0
|
'JSON::XS::Boolean' => sub { $_[ 0 ].q() }, |
18
|
0
|
|
|
|
|
0
|
'Type::Tiny' => sub { $_[ 0 ]->display_name }, |
19
|
0
|
|
|
|
|
0
|
'Type::Tiny::Enum' => sub { $_[ 0 ]->display_name }, |
20
|
28
|
|
|
28
|
|
23367
|
'Type::Tiny::Union' => sub { $_[ 0 ]->display_name }, }; |
|
28
|
|
|
|
|
843809
|
|
|
28
|
|
|
|
|
1204
|
|
|
0
|
|
|
|
|
0
|
|
21
|
28
|
|
|
28
|
|
63867
|
use Digest qw( ); |
|
28
|
|
|
|
|
14053
|
|
|
28
|
|
|
|
|
697
|
|
22
|
28
|
|
|
28
|
|
203
|
use Digest::MD5 qw( md5 ); |
|
28
|
|
|
|
|
79
|
|
|
28
|
|
|
|
|
2040
|
|
23
|
28
|
|
|
28
|
|
188
|
use English qw( -no_match_vars ); |
|
28
|
|
|
|
|
77
|
|
|
28
|
|
|
|
|
260
|
|
24
|
28
|
|
|
28
|
|
10591
|
use Fcntl qw( F_SETFL O_NONBLOCK ); |
|
28
|
|
|
|
|
85
|
|
|
28
|
|
|
|
|
1386
|
|
25
|
28
|
|
|
28
|
|
169
|
use File::Basename qw( basename dirname ); |
|
28
|
|
|
|
|
78
|
|
|
28
|
|
|
|
|
1972
|
|
26
|
28
|
|
|
28
|
|
14914
|
use File::DataClass::Functions qw( supported_extensions ); |
|
28
|
|
|
|
|
303071
|
|
|
28
|
|
|
|
|
2201
|
|
27
|
28
|
|
|
28
|
|
20510
|
use File::DataClass::IO qw( ); |
|
28
|
|
|
|
|
2205404
|
|
|
28
|
|
|
|
|
1196
|
|
28
|
28
|
|
|
28
|
|
326
|
use File::HomeDir qw( ); |
|
28
|
|
|
|
|
98
|
|
|
28
|
|
|
|
|
860
|
|
29
|
28
|
|
|
28
|
|
213
|
use File::Spec::Functions qw( canonpath catdir catfile curdir ); |
|
28
|
|
|
|
|
83
|
|
|
28
|
|
|
|
|
2513
|
|
30
|
28
|
|
|
28
|
|
251
|
use List::Util qw( first ); |
|
28
|
|
|
|
|
101
|
|
|
28
|
|
|
|
|
2158
|
|
31
|
28
|
|
|
28
|
|
246
|
use Module::Runtime qw( is_module_name require_module ); |
|
28
|
|
|
|
|
96
|
|
|
28
|
|
|
|
|
331
|
|
32
|
28
|
|
|
28
|
|
2277
|
use Scalar::Util qw( blessed openhandle ); |
|
28
|
|
|
|
|
96
|
|
|
28
|
|
|
|
|
1800
|
|
33
|
28
|
|
|
28
|
|
21119
|
use Socket qw( AF_UNIX SOCK_STREAM PF_UNSPEC ); |
|
28
|
|
|
|
|
118989
|
|
|
28
|
|
|
|
|
5602
|
|
34
|
28
|
|
|
28
|
|
330
|
use Symbol; |
|
28
|
|
|
|
|
84
|
|
|
28
|
|
|
|
|
2131
|
|
35
|
28
|
|
|
28
|
|
258
|
use Sys::Hostname qw( hostname ); |
|
28
|
|
|
|
|
81
|
|
|
28
|
|
|
|
|
2084
|
|
36
|
28
|
|
|
|
|
350
|
use Unexpected::Functions qw( is_class_loaded PathAlreadyExists |
37
|
28
|
|
|
28
|
|
262
|
PathNotFound Tainted Unspecified ); |
|
28
|
|
|
|
|
108
|
|
38
|
28
|
|
|
28
|
|
42252
|
use User::pwent; |
|
28
|
|
|
|
|
122219
|
|
|
28
|
|
|
|
|
189
|
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
our @EXPORT_OK = qw( abs_path app_prefix arg_list assert assert_directory |
41
|
|
|
|
|
|
|
base64_decode_ns base64_encode_ns bsonid bsonid_time |
42
|
|
|
|
|
|
|
bson64id bson64id_time canonicalise class2appdir |
43
|
|
|
|
|
|
|
classdir classfile create_token create_token64 cwdp |
44
|
|
|
|
|
|
|
dash2under data_dumper digest distname elapsed emit |
45
|
|
|
|
|
|
|
emit_err emit_to ensure_class_loaded env_prefix |
46
|
|
|
|
|
|
|
escape_TT exception find_apphome find_source first_char |
47
|
|
|
|
|
|
|
fqdn fullname get_cfgfiles get_user hex2str home2appldir |
48
|
|
|
|
|
|
|
io is_arrayref is_coderef is_hashref is_member is_win32 |
49
|
|
|
|
|
|
|
list_attr_of loginid logname merge_attributes my_prefix |
50
|
|
|
|
|
|
|
nonblocking_write_pipe_pair ns_environment pad |
51
|
|
|
|
|
|
|
prefix2class socket_pair split_on__ split_on_dash |
52
|
|
|
|
|
|
|
squeeze strip_leader sub_name symlink thread_id throw |
53
|
|
|
|
|
|
|
throw_on_error trim unescape_TT untaint_cmdline |
54
|
|
|
|
|
|
|
untaint_identifier untaint_path untaint_string urandom |
55
|
|
|
|
|
|
|
uuid whiten zip chain compose curry fold Y factorial |
56
|
|
|
|
|
|
|
fibonacci product sum ); |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
our %EXPORT_REFS = ( assert => sub { ASSERT }, ); |
59
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( all => [ @EXPORT_OK ], ); |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# Package variables |
62
|
24
|
|
|
24
|
|
26306
|
my $bson_id_count : shared = 0; |
|
24
|
|
|
|
|
32484
|
|
|
24
|
|
|
|
|
221887
|
|
63
|
|
|
|
|
|
|
my $bson2_id_count = 0; |
64
|
|
|
|
|
|
|
my $bson2_prev_time = 0; |
65
|
|
|
|
|
|
|
my $digest_cache; |
66
|
|
|
|
|
|
|
my $host_id = substr md5( hostname ), 0, 3; |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# Private functions |
69
|
|
|
|
|
|
|
my $_base64_char_set = sub { |
70
|
|
|
|
|
|
|
return [ 0 .. 9, 'A' .. 'Z', '_', 'a' .. 'z', '~', '+' ]; |
71
|
|
|
|
|
|
|
}; |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
my $_bsonid_inc = sub { |
74
|
|
|
|
|
|
|
my ($now, $version) = @_; |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
$version or return substr pack( 'N', $bson_id_count++ % 0xFFFFFF ), 1, 3; |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
$bson2_id_count++; $now > $bson2_prev_time and $bson2_id_count = 0; |
79
|
|
|
|
|
|
|
$bson2_prev_time = $now; |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
$version < 2 and return (substr pack( 'n', thread_id() % 0xFF ), 1, 1) |
82
|
|
|
|
|
|
|
.(pack 'n', $bson2_id_count % 0xFFFF); |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
$version < 3 and return (pack 'n', thread_id() % 0xFFFF ) |
85
|
|
|
|
|
|
|
.(pack 'n', $bson2_id_count % 0xFFFF); |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
return (pack 'n', thread_id() % 0xFFFF ) |
88
|
|
|
|
|
|
|
.(substr pack( 'N', $bson2_id_count % 0xFFFFFF ), 1, 3); |
89
|
|
|
|
|
|
|
}; |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
my $_bsonid_time = sub { |
92
|
|
|
|
|
|
|
my ($now, $version) = @_; |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
(not $version or $version < 2) and return pack 'N', $now; |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
$version < 3 and return (substr pack( 'N', $now >> 32 ), 2, 2) |
97
|
|
|
|
|
|
|
.(pack 'N', $now % 0xFFFFFFFF); |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
return (pack 'N', $now >> 32).(pack 'N', $now % 0xFFFFFFFF); |
100
|
|
|
|
|
|
|
}; |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
my $_catpath = sub { |
103
|
|
|
|
|
|
|
return untaint_path( catfile( @_ ) ); |
104
|
|
|
|
|
|
|
}; |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
my $_get_env_var_for_conf = sub { |
107
|
|
|
|
|
|
|
my $file = $ENV{ ($_[ 0 ] || return) }; |
108
|
|
|
|
|
|
|
my $path = $file ? dirname( $file ) : q(); |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
return $path = assert_directory( $path ) ? $path : undef; |
111
|
|
|
|
|
|
|
}; |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
my $_get_pod_content_for_attr = sub { |
114
|
|
|
|
|
|
|
my ($class, $attr) = @_; my $pod; |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
my $src = find_source( $class ) |
117
|
|
|
|
|
|
|
or throw( 'Class [_1] cannot find source', [ $class ] ); |
118
|
|
|
|
|
|
|
my $events = Pod::Eventual::Simple->read_file( $src ); |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
for (my $ev_no = 0, my $max = @{ $events }; $ev_no < $max; $ev_no++) { |
121
|
|
|
|
|
|
|
my $ev = $events->[ $ev_no ]; $ev->{type} eq 'command' or next; |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
$ev->{content} =~ m{ (?: ^|[< ]) $attr (?: [ >]|$ ) }msx or next; |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
$ev_no++ while ($ev = $events->[ $ev_no + 1 ] and $ev->{type} eq 'blank'); |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
$ev and $ev->{type} eq 'text' and $pod = $ev->{content} and last; |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
$pod //= 'Undocumented'; chomp $pod; $pod =~ s{ [\n] }{ }gmx; |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
$pod = squeeze( $pod ); $pod =~ m{ \A (.+) \z }msx and $pod = $1; |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
return $pod; |
135
|
|
|
|
|
|
|
}; |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
my $_index64 = sub { |
138
|
|
|
|
|
|
|
return [ qw(XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX |
139
|
|
|
|
|
|
|
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX |
140
|
|
|
|
|
|
|
XX XX XX XX XX XX XX XX XX XX XX 64 XX XX XX XX |
141
|
|
|
|
|
|
|
0 1 2 3 4 5 6 7 8 9 XX XX XX XX XX XX |
142
|
|
|
|
|
|
|
XX 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
143
|
|
|
|
|
|
|
25 26 27 28 29 30 31 32 33 34 35 XX XX XX XX 36 |
144
|
|
|
|
|
|
|
XX 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
145
|
|
|
|
|
|
|
52 53 54 55 56 57 58 59 60 61 62 XX XX XX 63 XX |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX |
148
|
|
|
|
|
|
|
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX |
149
|
|
|
|
|
|
|
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX |
150
|
|
|
|
|
|
|
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX |
151
|
|
|
|
|
|
|
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX |
152
|
|
|
|
|
|
|
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX |
153
|
|
|
|
|
|
|
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX |
154
|
|
|
|
|
|
|
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX) ]; |
155
|
|
|
|
|
|
|
}; |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
my $_pseudo_random = sub { |
158
|
|
|
|
|
|
|
return join q(), time, rand 10_000, $PID, {}; |
159
|
|
|
|
|
|
|
}; |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
my $_bsonid = sub { |
162
|
|
|
|
|
|
|
my $version = shift; |
163
|
|
|
|
|
|
|
my $now = time; |
164
|
|
|
|
|
|
|
my $time = $_bsonid_time->( $now, $version ); |
165
|
|
|
|
|
|
|
my $pid = pack 'n', $PID % 0xFFFF; |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
return $time.$host_id.$pid.$_bsonid_inc->( $now, $version ); |
168
|
|
|
|
|
|
|
}; |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
my $_find_cfg_in_inc = sub { |
171
|
|
|
|
|
|
|
my ($classdir, $file, $extns) = @_; |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
for my $dir (grep { defined and -d $_ } |
174
|
|
|
|
|
|
|
map { abs_path( catdir( $_, $classdir ) ) } @INC) { |
175
|
|
|
|
|
|
|
for my $extn (@{ $extns // [ supported_extensions() ] }) { |
176
|
|
|
|
|
|
|
my $path = $_catpath->( $dir, $file.$extn ); |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
-f $path and return dirname( $path ); |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
return; |
183
|
|
|
|
|
|
|
}; |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
my $_read_variable = sub { |
186
|
|
|
|
|
|
|
my ($dir, $file, $variable) = @_; my $path; |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
($dir and $file and $variable) or return; |
189
|
|
|
|
|
|
|
is_arrayref( $dir ) and $dir = catdir( @{ $dir } ); |
190
|
|
|
|
|
|
|
$path = io( $_catpath->( $dir, $file ) )->chomp; |
191
|
|
|
|
|
|
|
($path->exists and $path->is_file) or return; |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
return first { length } |
194
|
|
|
|
|
|
|
map { trim( (split '=', $_)[ 1 ] ) } |
195
|
|
|
|
|
|
|
grep { m{ \A \s* $variable \s* [=] }mx } |
196
|
|
|
|
|
|
|
reverse $path->getlines; |
197
|
|
|
|
|
|
|
}; |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
my $_get_file_var = sub { |
200
|
|
|
|
|
|
|
my ($dir, $file, $classdir) = @_; |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
my $path; $path = $_read_variable->( $dir, ".${file}", 'APPLDIR' ) |
203
|
|
|
|
|
|
|
and $path = catdir( $path, 'lib', $classdir ); |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
return $path = assert_directory( $path ) ? $path : undef; |
206
|
|
|
|
|
|
|
}; |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
my $_get_known_file_var = sub { |
209
|
|
|
|
|
|
|
my ($appname, $classdir) = @_; length $appname or return; |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
my $path; $path = $_read_variable->( DEFAULT_ENVDIR(), $appname, 'APPLDIR' ) |
212
|
|
|
|
|
|
|
and $path = catdir( $path, 'lib', $classdir ); |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
return $path = assert_directory( $path ) ? $path : undef; |
215
|
|
|
|
|
|
|
}; |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
# Construction |
218
|
|
|
|
|
|
|
sub _exporter_fail { |
219
|
4
|
|
|
4
|
|
6178
|
my ($class, $name, $value, $globals) = @_; |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
exists $EXPORT_REFS{ $name } |
222
|
4
|
50
|
|
|
|
43
|
and return ( $name => $EXPORT_REFS{ $name }->() ); |
223
|
|
|
|
|
|
|
|
224
|
0
|
|
|
|
|
0
|
throw( 'Subroutine [_1] not found in package [_2]', [ $name, $class ] ); |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
# Public functions |
228
|
|
|
|
|
|
|
sub abs_path ($) { |
229
|
1094
|
100
|
100
|
1094
|
1
|
2508
|
my $v = shift; (defined $v and length $v) or return $v; |
|
1094
|
|
|
|
|
4663
|
|
230
|
|
|
|
|
|
|
|
231
|
962
|
50
|
33
|
|
|
2102
|
is_ntfs() and not -e $v and return untaint_path( $v ); # Hate |
232
|
|
|
|
|
|
|
|
233
|
962
|
|
|
|
|
2424
|
$v = Cwd::abs_path( untaint_path( $v ) ); |
234
|
|
|
|
|
|
|
|
235
|
962
|
50
|
33
|
|
|
2919
|
is_win32() and defined $v and $v =~ s{ / }{\\}gmx; # More hate |
236
|
|
|
|
|
|
|
|
237
|
962
|
|
|
|
|
3632
|
return $v; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
sub app_prefix ($) { |
241
|
97
|
|
100
|
97
|
1
|
570
|
(my $v = lc ($_[ 0 ] // q())) =~ s{ :: }{_}gmx; return $v; |
|
97
|
|
|
|
|
367
|
|
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
sub arg_list (;@) { |
245
|
382
|
100
|
100
|
382
|
1
|
5003
|
return $_[ 0 ] && ref $_[ 0 ] eq 'HASH' ? { %{ $_[ 0 ] } } |
|
285
|
100
|
|
|
|
2546
|
|
246
|
|
|
|
|
|
|
: $_[ 0 ] ? { @_ } |
247
|
|
|
|
|
|
|
: {}; |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
sub assert_directory ($) { |
251
|
222
|
|
|
222
|
1
|
1775
|
my $v = abs_path( $_[ 0 ] ); |
252
|
|
|
|
|
|
|
|
253
|
222
|
100
|
100
|
|
|
1115
|
defined $v and length $v and -d "${v}" and return $v; |
|
|
|
100
|
|
|
|
|
254
|
|
|
|
|
|
|
|
255
|
221
|
|
|
|
|
1004
|
return; |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
sub base64_decode_ns ($) { |
259
|
2
|
50
|
|
2
|
1
|
8
|
my $x = shift; defined $x or return; my @x = split q(), $x; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
9
|
|
260
|
|
|
|
|
|
|
|
261
|
2
|
|
|
|
|
6
|
my $index = $_index64->(); my $j = 0; my $k = 0; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
5
|
|
262
|
|
|
|
|
|
|
|
263
|
2
|
|
|
|
|
3
|
my $len = length $x; my $pad = 64; my @y = (); |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
4
|
|
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
ROUND: { |
266
|
2
|
|
|
|
|
4
|
while ($j < $len) { |
|
2
|
|
|
|
|
6
|
|
267
|
10
|
|
|
|
|
14
|
my @c = (); my $i = 0; |
|
10
|
|
|
|
|
28
|
|
268
|
|
|
|
|
|
|
|
269
|
10
|
|
|
|
|
20
|
while ($i < 4) { |
270
|
40
|
|
|
|
|
61
|
my $uc = $index->[ ord $x[ $j++ ] ]; |
271
|
|
|
|
|
|
|
|
272
|
40
|
50
|
|
|
|
85
|
$uc ne 'XX' and $c[ $i++ ] = 0 + $uc; $j == $len or next; |
|
40
|
100
|
|
|
|
101
|
|
273
|
|
|
|
|
|
|
|
274
|
2
|
50
|
|
|
|
5
|
if ($i < 4) { |
275
|
0
|
0
|
|
|
|
0
|
$i < 2 and last ROUND; $i == 2 and $c[ 2 ] = $pad; $c[ 3 ] = $pad; |
|
0
|
0
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
|
278
|
2
|
|
|
|
|
4
|
last; |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
10
|
50
|
33
|
|
|
40
|
($c[ 0 ] == $pad || $c[ 1 ] == $pad) and last; |
282
|
10
|
|
|
|
|
17
|
$y[ $k++ ] = ( $c[ 0 ] << 2) | (($c[ 1 ] & 0x30) >> 4); |
283
|
10
|
50
|
|
|
|
22
|
$c[ 2 ] == $pad and last; |
284
|
10
|
|
|
|
|
19
|
$y[ $k++ ] = (($c[ 1 ] & 0x0F) << 4) | (($c[ 2 ] & 0x3C) >> 2); |
285
|
10
|
100
|
|
|
|
23
|
$c[ 3 ] == $pad and last; |
286
|
9
|
|
|
|
|
21
|
$y[ $k++ ] = (($c[ 2 ] & 0x03) << 6) | $c[ 3 ]; |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
|
290
|
2
|
|
|
|
|
5
|
return join q(), map { chr $_ } @y; |
|
29
|
|
|
|
|
72
|
|
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub base64_encode_ns (;$) { |
294
|
2
|
50
|
|
2
|
1
|
5
|
my $x = shift; defined $x or return; my @x = split q(), $x; |
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
11
|
|
295
|
|
|
|
|
|
|
|
296
|
2
|
|
|
|
|
7
|
my $basis = $_base64_char_set->(); my $len = length $x; my @y = (); |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
5
|
|
297
|
|
|
|
|
|
|
|
298
|
2
|
|
|
|
|
8
|
for (my $i = 0, my $j = 0; $len > 0; $len -= 3, $i += 3) { |
299
|
10
|
50
|
|
|
|
15
|
my $c1 = ord $x[ $i ]; my $c2 = $len > 1 ? ord $x[ $i + 1 ] : 0; |
|
10
|
|
|
|
|
24
|
|
300
|
|
|
|
|
|
|
|
301
|
10
|
|
|
|
|
18
|
$y[ $j++ ] = $basis->[ $c1 >> 2 ]; |
302
|
10
|
|
|
|
|
19
|
$y[ $j++ ] = $basis->[ (($c1 & 0x3) << 4) | (($c2 & 0xF0) >> 4) ]; |
303
|
|
|
|
|
|
|
|
304
|
10
|
100
|
|
|
|
21
|
if ($len > 2) { |
|
|
50
|
|
|
|
|
|
305
|
9
|
|
|
|
|
13
|
my $c3 = ord $x[ $i + 2 ]; |
306
|
|
|
|
|
|
|
|
307
|
9
|
|
|
|
|
17
|
$y[ $j++ ] = $basis->[ (($c2 & 0xF) << 2) | (($c3 & 0xC0) >> 6) ]; |
308
|
9
|
|
|
|
|
25
|
$y[ $j++ ] = $basis->[ $c3 & 0x3F ]; |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
elsif ($len == 2) { |
311
|
1
|
|
|
|
|
4
|
$y[ $j++ ] = $basis->[ ($c2 & 0xF) << 2 ]; |
312
|
1
|
|
|
|
|
3
|
$y[ $j++ ] = $basis->[ 64 ]; |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
else { # len == 1 |
315
|
0
|
|
|
|
|
0
|
$y[ $j++ ] = $basis->[ 64 ]; |
316
|
0
|
|
|
|
|
0
|
$y[ $j++ ] = $basis->[ 64 ]; |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
2
|
|
|
|
|
18
|
return join q(), @y; |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
sub bsonid (;$) { |
324
|
1
|
|
|
1
|
1
|
5
|
return unpack 'H*', $_bsonid->( $_[ 0 ] ); |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
sub bsonid_time ($) { |
328
|
1
|
|
|
1
|
1
|
5
|
return unpack 'N', substr hex2str( $_[ 0 ] ), 0, 4; |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
sub bson64id (;$) { |
332
|
1
|
|
|
1
|
1
|
373
|
return base64_encode_ns( $_bsonid->( 2 ) ); |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
sub bson64id_time ($) { |
336
|
1
|
|
|
1
|
1
|
5
|
return unpack 'N', substr base64_decode_ns( $_[ 0 ] ), 2, 4; |
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
sub canonicalise ($;$) { |
340
|
58
|
|
|
58
|
1
|
28546
|
my ($base, $relpath) = @_; |
341
|
|
|
|
|
|
|
|
342
|
58
|
50
|
|
|
|
179
|
$base = is_arrayref( $base ) ? catdir( @{ $base } ) : $base; |
|
0
|
|
|
|
|
0
|
|
343
|
58
|
100
|
|
|
|
3360
|
$relpath or return canonpath( untaint_path( $base ) ); |
344
|
|
|
|
|
|
|
|
345
|
33
|
50
|
|
|
|
97
|
my @relpath = is_arrayref( $relpath ) ? @{ $relpath } : $relpath; |
|
0
|
|
|
|
|
0
|
|
346
|
33
|
|
|
|
|
184
|
my $path = canonpath( untaint_path( catdir( $base, @relpath ) ) ); |
347
|
|
|
|
|
|
|
|
348
|
33
|
50
|
|
|
|
1564
|
-d $path and return $path; |
349
|
|
|
|
|
|
|
|
350
|
33
|
|
|
|
|
231
|
return canonpath( untaint_path( catfile( $base, @relpath ) ) ); |
351
|
|
|
|
|
|
|
} |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
sub class2appdir ($) { |
354
|
51
|
|
|
51
|
1
|
1047
|
return lc distname( $_[ 0 ] ); |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
sub classdir ($) { |
358
|
23
|
|
50
|
23
|
1
|
249
|
return catdir( split m{ :: }mx, $_[ 0 ] // q() ); |
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
sub classfile ($) { |
362
|
56
|
|
|
56
|
1
|
663
|
return catfile( split m{ :: }mx, $_[ 0 ].'.pm' ); |
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
sub create_token (;$) { |
366
|
10
|
|
66
|
10
|
1
|
57
|
return digest( $_[ 0 ] // urandom() )->hexdigest; |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
sub create_token64 (;$) { |
370
|
0
|
|
0
|
0
|
1
|
0
|
return digest( $_[ 0 ] // urandom() )->b64digest; |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
sub cwdp () { |
374
|
1
|
|
|
1
|
1
|
610
|
return abs_path( curdir ); |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
sub dash2under (;$) { |
378
|
4
|
|
50
|
4
|
1
|
23
|
(my $v = $_[ 0 ] // q()) =~ s{ [\-] }{_}gmx; return $v; |
|
4
|
|
|
|
|
22
|
|
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
sub data_dumper (;@) { |
382
|
2
|
|
|
2
|
1
|
17
|
_data_dumper( @_ ); return 1; |
|
2
|
|
|
|
|
22601
|
|
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
sub digest ($) { |
386
|
10
|
|
|
10
|
1
|
325
|
my $seed = shift; my ($candidate, $digest); |
|
10
|
|
|
|
|
58
|
|
387
|
|
|
|
|
|
|
|
388
|
10
|
100
|
|
|
|
30
|
if ($digest_cache) { $digest = Digest->new( $digest_cache ) } |
|
7
|
|
|
|
|
60
|
|
389
|
|
|
|
|
|
|
else { |
390
|
3
|
|
|
|
|
21
|
for (DIGEST_ALGORITHMS) { |
391
|
3
|
50
|
|
|
|
8
|
$candidate = $_; $digest = eval { Digest->new( $candidate ) } and last; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
29
|
|
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
|
394
|
3
|
50
|
|
|
|
8612
|
$digest or throw( 'Digest algorithm not found' ); |
395
|
3
|
|
|
|
|
8
|
$digest_cache = $candidate; |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
|
398
|
10
|
|
|
|
|
471
|
$digest->add( $seed ); |
399
|
|
|
|
|
|
|
|
400
|
10
|
|
|
|
|
168
|
return $digest; |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
sub distname ($) { |
404
|
52
|
|
50
|
52
|
1
|
325
|
(my $v = $_[ 0 ] // q()) =~ s{ :: }{-}gmx; return $v; |
|
52
|
|
|
|
|
268
|
|
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
#head2 downgrade |
408
|
|
|
|
|
|
|
# $sv_pv = downgrade $sv_pvgv; |
409
|
|
|
|
|
|
|
#Horrendous Perl bug is promoting C<PV> and C<PVMG> type scalars to |
410
|
|
|
|
|
|
|
#C<PVGV>. Serializing these values with L<Storable> throws a can't |
411
|
|
|
|
|
|
|
#store SCALAR items error. This functions copies the string value of |
412
|
|
|
|
|
|
|
#the input scalar to the output scalar but resets the output scalar |
413
|
|
|
|
|
|
|
#type to C<PV> |
414
|
|
|
|
|
|
|
#sub downgrade (;$) { |
415
|
|
|
|
|
|
|
# my $x = shift // q(); my ($y) = $x =~ m{ (.*) }msx; return $y; |
416
|
|
|
|
|
|
|
#} |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
sub elapsed () { |
419
|
1
|
|
|
1
|
1
|
10
|
return time - $BASETIME; |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
sub emit (;@) { |
423
|
10
|
|
100
|
10
|
1
|
1876
|
my @args = @_; $args[ 0 ] //= q(); chomp( @args ); |
|
10
|
|
|
|
|
41
|
|
|
10
|
|
|
|
|
25
|
|
424
|
|
|
|
|
|
|
|
425
|
10
|
|
|
|
|
45
|
local ($OFS, $ORS) = ("\n", "\n"); |
426
|
|
|
|
|
|
|
|
427
|
10
|
50
|
|
|
|
59
|
return openhandle *STDOUT ? emit_to( *STDOUT, @args ) : undef; |
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
sub emit_err (;@) { |
431
|
3
|
|
50
|
3
|
1
|
3660
|
my @args = @_; $args[ 0 ] //= q(); chomp( @args ); |
|
3
|
|
|
|
|
17
|
|
|
3
|
|
|
|
|
11
|
|
432
|
|
|
|
|
|
|
|
433
|
3
|
|
|
|
|
22
|
local ($OFS, $ORS) = ("\n", "\n"); |
434
|
|
|
|
|
|
|
|
435
|
3
|
50
|
|
|
|
27
|
return openhandle *STDERR ? emit_to( *STDERR, @args ) : undef; |
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
sub emit_to ($;@) { |
439
|
29
|
|
|
29
|
1
|
227
|
my ($handle, @args) = @_; local $OS_ERROR; |
|
29
|
|
|
|
|
401
|
|
440
|
|
|
|
|
|
|
|
441
|
29
|
|
33
|
|
|
153
|
return (print {$handle} @args or throw( 'IO error: [_1]', [ $OS_ERROR ] )); |
442
|
|
|
|
|
|
|
} |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
sub ensure_class_loaded ($;$) { |
445
|
17
|
|
50
|
17
|
1
|
2111
|
my ($class, $opts) = @_; $opts //= {}; |
|
17
|
|
|
|
|
134
|
|
446
|
|
|
|
|
|
|
|
447
|
17
|
50
|
|
|
|
68
|
$class or throw( Unspecified, [ 'class name' ], level => 2 ); |
448
|
|
|
|
|
|
|
|
449
|
17
|
50
|
|
|
|
98
|
is_module_name( $class ) |
450
|
|
|
|
|
|
|
or throw( 'String [_1] invalid classname', [ $class ], level => 2 ); |
451
|
|
|
|
|
|
|
|
452
|
17
|
100
|
66
|
|
|
457
|
not $opts->{ignore_loaded} and is_class_loaded( $class ) and return 1; |
453
|
|
|
|
|
|
|
|
454
|
9
|
|
|
|
|
432
|
eval { require_module( $class ) }; throw_on_error( { level => 3 } ); |
|
9
|
|
|
|
|
51
|
|
|
9
|
|
|
|
|
1073836
|
|
455
|
|
|
|
|
|
|
|
456
|
8
|
50
|
|
|
|
534
|
is_class_loaded( $class ) |
457
|
|
|
|
|
|
|
or throw( 'Class [_1] loaded but package undefined', |
458
|
|
|
|
|
|
|
[ $class ], level => 2 ); |
459
|
|
|
|
|
|
|
|
460
|
8
|
|
|
|
|
406
|
return 1; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
sub env_prefix ($) { |
464
|
51
|
|
|
51
|
1
|
905
|
return uc app_prefix( $_[ 0 ] ); |
465
|
|
|
|
|
|
|
} |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
sub escape_TT (;$$) { |
468
|
1
|
50
|
|
1
|
1
|
6
|
my $v = defined $_[ 0 ] ? $_[ 0 ] : q(); |
469
|
1
|
|
50
|
|
|
9
|
my $fl = ($_[ 1 ] && $_[ 1 ]->[ 0 ]) || '<'; |
470
|
1
|
|
50
|
|
|
10
|
my $fr = ($_[ 1 ] && $_[ 1 ]->[ 1 ]) || '>'; |
471
|
|
|
|
|
|
|
|
472
|
1
|
|
|
|
|
8
|
$v =~ s{ \[\% }{${fl}%}gmx; $v =~ s{ \%\] }{%${fr}}gmx; |
|
1
|
|
|
|
|
5
|
|
473
|
|
|
|
|
|
|
|
474
|
1
|
|
|
|
|
5
|
return $v; |
475
|
|
|
|
|
|
|
} |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
sub exception (;@) { |
478
|
8
|
|
|
8
|
1
|
41650
|
return EXCEPTION_CLASS->caught( @_ ); |
479
|
|
|
|
|
|
|
} |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
sub find_apphome ($;$$) { |
482
|
22
|
|
|
22
|
1
|
70
|
my ($appclass, $default, $extns) = @_; my $path; |
|
22
|
|
|
|
|
45
|
|
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
# 0. Pass the directory in (short circuit the search) |
485
|
22
|
50
|
|
|
|
105
|
$path = assert_directory $default and return $path; |
486
|
|
|
|
|
|
|
|
487
|
22
|
|
|
|
|
94
|
my $app_pref = app_prefix $appclass; |
488
|
22
|
|
|
|
|
94
|
my $appdir = class2appdir $appclass; |
489
|
22
|
|
|
|
|
78
|
my $classdir = classdir $appclass; |
490
|
22
|
|
|
|
|
94
|
my $env_pref = env_prefix $appclass; |
491
|
22
|
|
|
|
|
226
|
my $my_home = File::HomeDir->my_home; |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
# 1a. Environment variable - for application directory |
494
|
22
|
50
|
|
|
|
1101
|
$path = assert_directory $ENV{ "${env_pref}_HOME" } and return $path; |
495
|
|
|
|
|
|
|
# 1b. Environment variable - for config file |
496
|
22
|
50
|
|
|
|
140
|
$path = $_get_env_var_for_conf->( "${env_pref}_CONFIG" ) and return $path; |
497
|
|
|
|
|
|
|
# 2a. Users XDG_DATA_HOME env variable or XDG default share directory |
498
|
22
|
|
33
|
|
|
208
|
$path = $ENV{ 'XDG_DATA_HOME' } // catdir( $my_home, '.local', 'share' ); |
499
|
22
|
50
|
|
|
|
120
|
$path = assert_directory catdir( $path, $appdir ) and return $path; |
500
|
|
|
|
|
|
|
# 2b. Users home directory - dot file containing shell env variable |
501
|
22
|
50
|
|
|
|
107
|
$path = $_get_file_var->( $my_home, $app_pref, $classdir ) and return $path; |
502
|
22
|
50
|
|
|
|
222
|
$path = $_get_file_var->( $my_home, $appdir, $classdir ) and return $path; |
503
|
|
|
|
|
|
|
# 2c. Users home directory - dot directory is apphome |
504
|
22
|
|
|
|
|
151
|
$path = catdir( $my_home, ".${app_pref}" ); |
505
|
22
|
50
|
|
|
|
1524
|
$path = assert_directory $path and return $path; |
506
|
22
|
|
|
|
|
144
|
$path = catdir( $my_home, ".${appdir}" ); |
507
|
22
|
50
|
|
|
|
89
|
$path = assert_directory $path and return $path; |
508
|
|
|
|
|
|
|
# 3. Well known path containing shell env file |
509
|
22
|
50
|
|
|
|
175
|
$path = $_get_known_file_var->( $appdir, $classdir ) and return $path; |
510
|
|
|
|
|
|
|
# 4. Default install prefix |
511
|
22
|
|
|
|
|
64
|
$path = catdir( @{ PREFIX() }, $appdir, 'default', 'lib', $classdir ); |
|
22
|
|
|
|
|
82
|
|
512
|
22
|
50
|
|
|
|
129
|
$path = assert_directory $path and return $path; |
513
|
|
|
|
|
|
|
# 5a. Config file found in @INC - underscore as separator |
514
|
22
|
50
|
|
|
|
126
|
$path = $_find_cfg_in_inc->( $classdir, $app_pref, $extns ) and return $path; |
515
|
|
|
|
|
|
|
# 5b. Config file found in @INC - dash as separator |
516
|
22
|
50
|
|
|
|
90
|
$path = $_find_cfg_in_inc->( $classdir, $appdir, $extns ) and return $path; |
517
|
|
|
|
|
|
|
# 6. Default to /tmp |
518
|
22
|
|
|
|
|
137
|
return untaint_path( DEFAULT_CONFHOME ); |
519
|
|
|
|
|
|
|
} |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
sub find_source ($) { |
522
|
55
|
|
|
55
|
1
|
1607
|
my $class = shift; my $file = classfile( $class ); my $path; |
|
55
|
|
|
|
|
214
|
|
|
55
|
|
|
|
|
177
|
|
523
|
|
|
|
|
|
|
|
524
|
55
|
|
|
|
|
175
|
for (@INC) { |
525
|
165
|
100
|
66
|
|
|
878
|
$path = abs_path( catfile( $_, $file ) ) and -f $path and return $path; |
526
|
|
|
|
|
|
|
} |
527
|
|
|
|
|
|
|
|
528
|
0
|
|
|
|
|
0
|
return; |
529
|
|
|
|
|
|
|
} |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
sub first_char ($) { |
532
|
1
|
|
|
1
|
1
|
6
|
return substr $_[ 0 ], 0, 1; |
533
|
|
|
|
|
|
|
} |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
sub fqdn (;$) { |
536
|
0
|
|
0
|
0
|
1
|
0
|
my $x = shift // hostname; return (gethostbyname( $x ))[ 0 ]; |
|
0
|
|
|
|
|
0
|
|
537
|
|
|
|
|
|
|
} |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
sub fullname () { |
540
|
0
|
|
0
|
0
|
1
|
0
|
my $v = (split m{ \s* , \s * }msx, (get_user()->gecos // q()))[ 0 ]; |
541
|
|
|
|
|
|
|
|
542
|
0
|
|
0
|
|
|
0
|
$v //= q(); $v =~ s{ [\&] }{}gmx; # Coz af25e158-d0c7-11e3-bdcb-31d9eda79835 |
|
0
|
|
|
|
|
0
|
|
543
|
|
|
|
|
|
|
|
544
|
0
|
|
|
|
|
0
|
return untaint_cmdline( $v ); |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
sub get_cfgfiles ($;$$) { |
548
|
22
|
|
|
22
|
1
|
76
|
my ($appclass, $dirs, $extns) = @_; |
549
|
|
|
|
|
|
|
|
550
|
22
|
|
33
|
|
|
91
|
$appclass // throw( Unspecified, [ 'application class' ], level => 2 ); |
551
|
22
|
50
|
50
|
|
|
89
|
is_arrayref( $dirs ) or $dirs = [ $dirs || curdir ]; |
552
|
|
|
|
|
|
|
|
553
|
22
|
|
|
|
|
110
|
my $app_pref = app_prefix $appclass; |
554
|
22
|
|
|
|
|
112
|
my $appdir = class2appdir $appclass; |
555
|
22
|
|
|
|
|
109
|
my $env_pref = env_prefix $appclass; |
556
|
22
|
|
50
|
|
|
167
|
my $suffix = $ENV{ "${env_pref}_CONFIG_LOCAL_SUFFIX" } // '_local'; |
557
|
22
|
|
|
|
|
71
|
my @paths = (); |
558
|
|
|
|
|
|
|
|
559
|
22
|
|
|
|
|
69
|
for my $dir (@{ $dirs }) { |
|
22
|
|
|
|
|
71
|
|
560
|
22
|
|
50
|
|
|
47
|
for my $extn (@{ $extns // [ supported_extensions() ] }) { |
|
22
|
|
|
|
|
160
|
|
561
|
26
|
|
|
|
|
18678
|
for my $path (map { $_catpath->( $dir, $_ ) } "${app_pref}${extn}", |
|
104
|
|
|
|
|
258
|
|
562
|
|
|
|
|
|
|
"${appdir}${extn}", "${app_pref}${suffix}${extn}", |
563
|
|
|
|
|
|
|
"${appdir}${suffix}${extn}") { |
564
|
104
|
50
|
|
|
|
1168
|
-f $path and push @paths, $path; |
565
|
|
|
|
|
|
|
} |
566
|
|
|
|
|
|
|
} |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
|
569
|
22
|
|
|
|
|
160
|
return \@paths; |
570
|
|
|
|
|
|
|
} |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
sub get_user (;$) { |
573
|
6
|
50
|
|
6
|
1
|
23
|
my $user = shift; is_win32() and return Class::Null->new; |
|
6
|
|
|
|
|
25
|
|
574
|
|
|
|
|
|
|
|
575
|
6
|
50
|
33
|
|
|
35
|
defined $user and $user !~ m{ \A \d+ \z }mx and return getpwnam( $user ); |
576
|
|
|
|
|
|
|
|
577
|
6
|
|
33
|
|
|
68
|
return getpwuid( $user // $UID ); |
578
|
|
|
|
|
|
|
} |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
sub hex2str (;$) { |
581
|
2
|
|
50
|
2
|
1
|
1784
|
my @a = split m{}mx, shift // q(); my $str = q(); |
|
2
|
|
|
|
|
8
|
|
582
|
|
|
|
|
|
|
|
583
|
2
|
|
|
|
|
15
|
while (my ($x, $y) = splice @a, 0, 2) { $str .= pack 'C', hex "${x}${y}" } |
|
13
|
|
|
|
|
50
|
|
584
|
|
|
|
|
|
|
|
585
|
2
|
|
|
|
|
18
|
return $str; |
586
|
|
|
|
|
|
|
} |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
sub home2appldir ($) { |
589
|
7
|
100
|
|
7
|
1
|
50
|
$_[ 0 ] or return; my $dir = io( $_[ 0 ] ); |
|
6
|
|
|
|
|
280
|
|
590
|
|
|
|
|
|
|
|
591
|
6
|
|
100
|
|
|
26354
|
$dir = $dir->parent while ($dir ne $dir->parent and $dir !~ m{ lib \z }mx); |
592
|
|
|
|
|
|
|
|
593
|
6
|
100
|
|
|
|
16422
|
return $dir ne $dir->parent ? $dir->parent : undef; |
594
|
|
|
|
|
|
|
} |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
sub io (;@) { |
597
|
211
|
|
|
211
|
1
|
44932
|
return File::DataClass::IO->new( @_ ); |
598
|
|
|
|
|
|
|
} |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
sub is_arrayref (;$) { |
601
|
2607
|
100
|
100
|
2607
|
1
|
39389
|
return $_[ 0 ] && ref $_[ 0 ] eq 'ARRAY' ? 1 : 0; |
602
|
|
|
|
|
|
|
} |
603
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
sub is_coderef (;$) { |
605
|
58
|
100
|
100
|
58
|
1
|
1127
|
return $_[ 0 ] && ref $_[ 0 ] eq 'CODE' ? 1 : 0; |
606
|
|
|
|
|
|
|
} |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
sub is_hashref (;$) { |
609
|
437
|
100
|
100
|
437
|
1
|
6482
|
return $_[ 0 ] && ref $_[ 0 ] eq 'HASH' ? 1 : 0; |
610
|
|
|
|
|
|
|
} |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
sub is_member (;@) { |
613
|
502
|
50
|
|
502
|
1
|
18538
|
my ($candidate, @args) = @_; $candidate or return; |
|
502
|
|
|
|
|
2042
|
|
614
|
|
|
|
|
|
|
|
615
|
502
|
100
|
|
|
|
1698
|
is_arrayref $args[ 0 ] and @args = @{ $args[ 0 ] }; |
|
424
|
|
|
|
|
2001
|
|
616
|
|
|
|
|
|
|
|
617
|
502
|
100
|
|
1454
|
|
4848
|
return (first { $_ eq $candidate } @args) ? 1 : 0; |
|
1454
|
|
|
|
|
7680
|
|
618
|
|
|
|
|
|
|
} |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
sub is_ntfs () { |
621
|
962
|
50
|
33
|
962
|
1
|
1772
|
return is_win32() || lc $OSNAME eq 'cygwin' ? 1 : 0; |
622
|
|
|
|
|
|
|
} |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
sub is_win32 () { |
625
|
2501
|
50
|
|
2501
|
1
|
23765
|
return lc $OSNAME eq 'mswin32' ? 1 : 0; |
626
|
|
|
|
|
|
|
} |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
sub list_attr_of ($;@) { |
629
|
1
|
|
|
1
|
1
|
1352
|
my ($obj, @except) = @_; my $class = blessed $obj; |
|
1
|
|
|
|
|
5
|
|
630
|
|
|
|
|
|
|
|
631
|
1
|
|
|
|
|
5
|
ensure_class_loaded( 'Pod::Eventual::Simple' ); |
632
|
|
|
|
|
|
|
|
633
|
1
|
50
|
|
|
|
4
|
is_member 'new', @except or push @except, 'new'; |
634
|
|
|
|
|
|
|
|
635
|
45
|
|
|
|
|
6607
|
return map { my $attr = $_->[0]; [ @{ $_ }, $obj->$attr ] } |
|
45
|
|
|
|
|
72
|
|
|
45
|
|
|
|
|
696
|
|
636
|
45
|
|
|
|
|
159
|
map { [ $_->[1], $_->[0], $_get_pod_content_for_attr->( @{ $_ } ) ] } |
|
45
|
|
|
|
|
182
|
|
637
|
50
|
100
|
|
|
|
144
|
grep { $_->[0] ne 'Moo::Object' and not is_member $_->[1], @except } |
638
|
50
|
|
|
|
|
1564
|
map { m{ \A (.+) \:\: ([^:]+) \z }mx; [ $1, $2 ] } |
|
50
|
|
|
|
|
146
|
|
639
|
1
|
|
|
|
|
5
|
@{ Class::Inspector->methods( $class, 'full', 'public' ) }; |
|
1
|
|
|
|
|
25
|
|
640
|
|
|
|
|
|
|
} |
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
sub loginid (;$) { |
643
|
6
|
|
50
|
6
|
1
|
31
|
return untaint_cmdline( get_user( $_[ 0 ] )->name || 'unknown' ); |
644
|
|
|
|
|
|
|
} |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
sub logname (;$) { # Deprecated use loginid |
647
|
5
|
|
33
|
5
|
1
|
63
|
return untaint_cmdline( $ENV{USER} || $ENV{LOGNAME} || loginid( $_[ 0 ] ) ); |
648
|
|
|
|
|
|
|
} |
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
sub merge_attributes ($@) { |
651
|
48
|
|
|
48
|
1
|
203
|
my ($dest, @args) = @_; |
652
|
|
|
|
|
|
|
|
653
|
48
|
50
|
|
|
|
242
|
my $attr = is_arrayref( $args[ -1 ] ) ? pop @args : []; |
654
|
|
|
|
|
|
|
|
655
|
48
|
|
66
|
|
|
143
|
for my $k (grep { not exists $dest->{ $_ } or not defined $dest->{ $_ } } |
|
177
|
|
|
|
|
700
|
|
656
|
48
|
|
|
|
|
175
|
@{ $attr }) { |
657
|
173
|
|
|
|
|
358
|
my $i = 0; my $v; |
|
173
|
|
|
|
|
328
|
|
658
|
|
|
|
|
|
|
|
659
|
173
|
|
100
|
|
|
979
|
while (not defined $v and defined( my $src = $args[ $i++ ] )) { |
660
|
203
|
|
|
|
|
795
|
my $class = blessed $src; |
661
|
|
|
|
|
|
|
|
662
|
203
|
100
|
|
|
|
3342
|
$v = $class ? ($src->can( $k ) ? $src->$k() : undef) : $src->{ $k }; |
|
|
100
|
|
|
|
|
|
663
|
|
|
|
|
|
|
} |
664
|
|
|
|
|
|
|
|
665
|
173
|
100
|
|
|
|
15861
|
defined $v and $dest->{ $k } = $v; |
666
|
|
|
|
|
|
|
} |
667
|
|
|
|
|
|
|
|
668
|
48
|
|
|
|
|
215
|
return $dest; |
669
|
|
|
|
|
|
|
} |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
sub my_prefix (;$) { |
672
|
2
|
|
50
|
2
|
1
|
18
|
return split_on__( basename( $_[ 0 ] // q(), PERL_EXTNS ) ); |
673
|
|
|
|
|
|
|
} |
674
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
sub nonblocking_write_pipe_pair () { |
676
|
384
|
50
|
|
384
|
1
|
1045
|
my ($r, $w); pipe $r, $w or throw( 'No pipe' ); |
|
384
|
|
|
|
|
9678
|
|
677
|
|
|
|
|
|
|
|
678
|
384
|
|
|
|
|
1681
|
fcntl $w, F_SETFL, O_NONBLOCK; $w->autoflush( 1 ); |
|
384
|
|
|
|
|
3121
|
|
679
|
|
|
|
|
|
|
|
680
|
384
|
|
|
|
|
32433
|
binmode $r; binmode $w; |
|
384
|
|
|
|
|
1042
|
|
681
|
|
|
|
|
|
|
|
682
|
384
|
|
|
|
|
2170
|
return [ $r, $w ]; |
683
|
|
|
|
|
|
|
} |
684
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
sub ns_environment ($$;$) { |
686
|
6
|
|
|
6
|
1
|
107
|
my ($class, $k, $v) = @_; $k = (env_prefix $class).'_'.(uc $k); |
|
6
|
|
|
|
|
27
|
|
687
|
|
|
|
|
|
|
|
688
|
6
|
50
|
|
|
|
134
|
return defined $v ? $ENV{ $k } = $v : $ENV{ $k }; |
689
|
|
|
|
|
|
|
} |
690
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
sub pad ($$;$$) { |
692
|
7
|
|
|
7
|
1
|
23
|
my ($v, $wanted, $str, $direction) = @_; my $len = $wanted - length $v; |
|
7
|
|
|
|
|
20
|
|
693
|
|
|
|
|
|
|
|
694
|
7
|
100
|
66
|
|
|
31
|
$len > 0 or return $v; (defined $str and length $str) or $str = q( ); |
|
6
|
100
|
|
|
|
33
|
|
695
|
|
|
|
|
|
|
|
696
|
6
|
|
|
|
|
23
|
my $pad = substr( $str x $len, 0, $len ); |
697
|
|
|
|
|
|
|
|
698
|
6
|
100
|
100
|
|
|
45
|
(not $direction or $direction eq 'right') and return $v.$pad; |
699
|
2
|
100
|
|
|
|
40
|
$direction eq 'left' and return $pad.$v; |
700
|
|
|
|
|
|
|
|
701
|
1
|
|
|
|
|
14
|
return (substr $pad, 0, int( (length $pad) / 2 )).$v |
702
|
|
|
|
|
|
|
.(substr $pad, 0, int( 0.99999999 + (length $pad) / 2 )); |
703
|
|
|
|
|
|
|
} |
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
sub prefix2class (;$) { |
706
|
1
|
|
|
1
|
1
|
5
|
return join '::', map { ucfirst } split m{ - }mx, my_prefix( $_[ 0 ] ); |
|
2
|
|
|
|
|
17
|
|
707
|
|
|
|
|
|
|
} |
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
sub socket_pair () { |
710
|
1
|
|
|
1
|
1
|
8
|
my $rdr = gensym; my $wtr = gensym; |
|
1
|
|
|
|
|
25
|
|
711
|
|
|
|
|
|
|
|
712
|
1
|
50
|
|
|
|
59
|
socketpair( $rdr, $wtr, AF_UNIX, SOCK_STREAM, PF_UNSPEC ) |
713
|
|
|
|
|
|
|
or throw( $EXTENDED_OS_ERROR ); |
714
|
1
|
|
|
|
|
10
|
shutdown ( $rdr, 1 ); # No more writing for reader |
715
|
1
|
|
|
|
|
5
|
shutdown ( $wtr, 0 ); # No more reading for writer |
716
|
|
|
|
|
|
|
|
717
|
1
|
|
|
|
|
6
|
return [ $rdr, $wtr ]; |
718
|
|
|
|
|
|
|
} |
719
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
sub split_on__ (;$$) { |
721
|
11
|
|
50
|
11
|
1
|
747
|
return (split m{ _ }mx, $_[ 0 ] // q())[ $_[ 1 ] // 0 ]; |
|
|
|
100
|
|
|
|
|
722
|
|
|
|
|
|
|
} |
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
sub split_on_dash (;$$) { |
725
|
9
|
|
50
|
9
|
1
|
264
|
return (split m{ \- }mx, $_[ 0 ] // q())[ $_[ 1 ] // 0 ]; |
|
|
|
50
|
|
|
|
|
726
|
|
|
|
|
|
|
} |
727
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
sub squeeze (;$) { |
729
|
46
|
|
50
|
46
|
1
|
675
|
(my $v = $_[ 0 ] // q()) =~ s{ \s+ }{ }gmx; return $v; |
|
46
|
|
|
|
|
158
|
|
730
|
|
|
|
|
|
|
} |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
sub strip_leader (;$) { |
733
|
647
|
|
50
|
647
|
1
|
3235
|
(my $v = $_[ 0 ] // q()) =~ s{ \A [^:]+ [:] \s+ }{}msx; return $v; |
|
647
|
|
|
|
|
4222
|
|
734
|
|
|
|
|
|
|
} |
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
sub sub_name (;$) { |
737
|
1
|
|
50
|
1
|
1
|
10
|
my $frame = 1 + ($_[ 0 ] // 0); |
738
|
|
|
|
|
|
|
|
739
|
1
|
|
50
|
|
|
19
|
return (split m{ :: }mx, ((caller $frame)[ 3 ]) // 'main')[ -1 ]; |
740
|
|
|
|
|
|
|
} |
741
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
sub symlink (;$$$) { |
743
|
3
|
|
|
3
|
1
|
11
|
my ($from, $to, $base) = @_; |
744
|
|
|
|
|
|
|
|
745
|
3
|
50
|
66
|
|
|
19
|
defined $base and not CORE::length $base and $base = File::Spec->rootdir; |
746
|
3
|
50
|
|
|
|
10
|
$from or throw( Unspecified, [ 'path from' ] ); |
747
|
3
|
|
|
|
|
12
|
$from = io( $from )->absolute( $base ); |
748
|
3
|
50
|
|
|
|
2697
|
$from->exists or throw( PathNotFound, [ "${from}" ] ); |
749
|
3
|
50
|
|
|
|
213
|
$to or throw( Unspecified, [ 'path to' ] ); |
750
|
3
|
50
|
|
|
|
9
|
$to = io( $to )->absolute( $base ); $to->is_link and $to->unlink; |
|
3
|
|
|
|
|
2722
|
|
751
|
3
|
50
|
|
|
|
228
|
$to->exists and throw( PathAlreadyExists, [ "${to}" ] ); |
752
|
3
|
50
|
|
|
|
150
|
CORE::symlink "${from}", "${to}" |
753
|
|
|
|
|
|
|
or throw( 'Symlink from [_1] to [_2] failed: [_3]', |
754
|
|
|
|
|
|
|
[ "${from}", "${to}", $OS_ERROR ] ); |
755
|
3
|
|
|
|
|
352
|
return "Symlinked ${from} to ${to}"; |
756
|
|
|
|
|
|
|
} |
757
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
sub thread_id () { |
759
|
1
|
50
|
|
1
|
1
|
9
|
return exists $INC{ 'threads.pm' } ? threads->tid() : 0; |
760
|
|
|
|
|
|
|
} |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
sub throw (;@) { |
763
|
165
|
|
|
165
|
1
|
3868
|
EXCEPTION_CLASS->throw( @_ ); |
764
|
|
|
|
|
|
|
} |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
sub throw_on_error (;@) { |
767
|
9
|
|
|
9
|
1
|
62
|
EXCEPTION_CLASS->throw_on_error( @_ ); |
768
|
|
|
|
|
|
|
} |
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
sub trim (;$$) { |
771
|
2
|
|
100
|
2
|
1
|
2185
|
my $chs = $_[ 1 ] // " \t"; (my $v = $_[ 0 ] // q()) =~ s{ \A [$chs]+ }{}mx; |
|
2
|
|
50
|
|
|
61
|
|
772
|
|
|
|
|
|
|
|
773
|
2
|
|
|
|
|
13
|
chomp $v; $v =~ s{ [$chs]+ \z }{}mx; return $v; |
|
2
|
|
|
|
|
40
|
|
|
2
|
|
|
|
|
19
|
|
774
|
|
|
|
|
|
|
} |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
sub unescape_TT (;$$) { |
777
|
1
|
50
|
|
1
|
1
|
4
|
my $v = defined $_[ 0 ] ? $_[ 0 ] : q(); |
778
|
1
|
|
50
|
|
|
6
|
my $fl = ($_[ 1 ] && $_[ 1 ]->[ 0 ]) || '<'; |
779
|
1
|
|
50
|
|
|
7
|
my $fr = ($_[ 1 ] && $_[ 1 ]->[ 1 ]) || '>'; |
780
|
|
|
|
|
|
|
|
781
|
1
|
|
|
|
|
12
|
$v =~ s{ ${fl}\% }{[%}gmx; $v =~ s{ \%${fr} }{%]}gmx; |
|
1
|
|
|
|
|
8
|
|
782
|
|
|
|
|
|
|
|
783
|
1
|
|
|
|
|
6
|
return $v; |
784
|
|
|
|
|
|
|
} |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
sub untaint_cmdline (;$) { |
787
|
59
|
|
|
59
|
1
|
6680
|
return untaint_string( UNTAINT_CMDLINE, $_[ 0 ] ); |
788
|
|
|
|
|
|
|
} |
789
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
sub untaint_identifier (;$) { |
791
|
16
|
|
|
16
|
1
|
1414
|
return untaint_string( UNTAINT_IDENTIFIER, $_[ 0 ] ); |
792
|
|
|
|
|
|
|
} |
793
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
sub untaint_path (;$) { |
795
|
1410
|
|
|
1410
|
1
|
11148
|
return untaint_string( UNTAINT_PATH, $_[ 0 ] ); |
796
|
|
|
|
|
|
|
} |
797
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
sub untaint_string ($;$) { |
799
|
1485
|
|
|
1485
|
1
|
3465
|
my ($regex, $string) = @_; |
800
|
|
|
|
|
|
|
|
801
|
1485
|
100
|
|
|
|
3566
|
defined $string or return; length $string or return q(); |
|
1472
|
50
|
|
|
|
3236
|
|
802
|
|
|
|
|
|
|
|
803
|
1472
|
|
|
|
|
9101
|
my ($untainted) = $string =~ $regex; |
804
|
|
|
|
|
|
|
|
805
|
1472
|
100
|
66
|
|
|
8201
|
(defined $untainted and $untainted eq $string) |
806
|
|
|
|
|
|
|
or throw( Tainted, [ $string ], level => 3 ); |
807
|
|
|
|
|
|
|
|
808
|
1468
|
|
|
|
|
40567
|
return $untainted; |
809
|
|
|
|
|
|
|
} |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
sub urandom (;$$) { |
812
|
2
|
|
50
|
2
|
1
|
1127
|
my ($wanted, $opts) = @_; $wanted //= 64; $opts //= {}; |
|
2
|
|
50
|
|
|
20
|
|
|
2
|
|
|
|
|
17
|
|
813
|
|
|
|
|
|
|
|
814
|
2
|
50
|
|
|
|
16
|
my $default = [ q(), 'dev', $OSNAME eq 'freebsd' ? 'random' : 'urandom' ]; |
815
|
2
|
|
33
|
|
|
21
|
my $io = io( $opts->{source} // $default )->block_size( $wanted ); |
816
|
|
|
|
|
|
|
|
817
|
2
|
|
|
|
|
1799
|
my $red; $io->exists and $io->is_readable and $red = $io->read |
818
|
2
|
50
|
33
|
|
|
12
|
and $red == $wanted and return ${ $io->buffer }; |
|
2
|
|
33
|
|
|
4786
|
|
|
|
|
33
|
|
|
|
|
819
|
|
|
|
|
|
|
|
820
|
0
|
|
|
|
|
0
|
my $res = q(); while (length $res < $wanted) { $res .= $_pseudo_random->() } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
821
|
|
|
|
|
|
|
|
822
|
0
|
|
|
|
|
0
|
return substr $res, 0, $wanted; |
823
|
|
|
|
|
|
|
} |
824
|
|
|
|
|
|
|
|
825
|
|
|
|
|
|
|
sub uuid (;$) { |
826
|
0
|
|
0
|
0
|
1
|
0
|
return io( $_[ 0 ] // UUID_PATH )->chomp->getline; |
827
|
|
|
|
|
|
|
} |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
sub whiten ($) { |
830
|
1
|
|
|
1
|
1
|
2327
|
my $v = unpack "b*", pop; my $pad = " \t" x 8; |
|
1
|
|
|
|
|
5
|
|
831
|
|
|
|
|
|
|
|
832
|
1
|
|
|
|
|
4
|
$v =~ tr{01}{ \t}; $v =~ s{ (.{9}) }{$1\n}gmx; |
|
1
|
|
|
|
|
27
|
|
833
|
|
|
|
|
|
|
|
834
|
1
|
|
|
|
|
9
|
return "${pad}\n${v}"; |
835
|
|
|
|
|
|
|
} |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
sub zip (@) { |
838
|
1
|
|
|
1
|
1
|
2670
|
my $p = @_ / 2; return @_[ map { $_, $_ + $p } 0 .. $p - 1 ]; |
|
1
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
21
|
|
839
|
|
|
|
|
|
|
} |
840
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
# Function composition |
842
|
|
|
|
|
|
|
sub chain (;@) { |
843
|
3
|
|
|
3
|
1
|
20
|
return (fold( sub { my ($x, $y) = @_; $x->$y } )->( shift ))->( @_ ); |
|
3
|
|
|
1
|
|
12
|
|
|
1
|
|
|
|
|
11
|
|
844
|
|
|
|
|
|
|
} |
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
sub compose (&;$) { # Was called build |
847
|
1
|
|
100
|
1
|
1
|
6
|
my ($f, $g) = @_; $g //= sub { @_ }; return sub { $f->( $g->( @_ ) ) }; |
|
3
|
|
|
3
|
|
13
|
|
|
3
|
|
|
|
|
2059
|
|
|
3
|
|
|
|
|
23
|
|
|
3
|
|
|
|
|
24
|
|
848
|
|
|
|
|
|
|
} |
849
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
sub curry (&$;@) { |
851
|
1
|
|
|
1
|
1
|
6
|
my ($f, @args) = @_; return sub { $f->( @args, @_ ) }; |
|
1
|
|
|
1
|
|
1312
|
|
|
1
|
|
|
|
|
9
|
|
852
|
|
|
|
|
|
|
} |
853
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
sub fold (&) { |
855
|
3
|
|
|
3
|
1
|
10
|
my $f = shift; |
856
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
return sub (;$) { |
858
|
3
|
|
|
3
|
|
10
|
my $x = shift; |
859
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
return sub (;@) { |
861
|
3
|
|
|
|
|
9
|
my $y = $x; $y = $f->( $y, shift ) while (@_); return $y; |
|
3
|
|
|
|
|
18
|
|
|
3
|
|
|
|
|
37
|
|
862
|
|
|
|
|
|
|
} |
863
|
3
|
|
|
|
|
18
|
} |
864
|
3
|
|
|
|
|
21
|
} |
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
sub Y (&) { |
867
|
116
|
|
|
116
|
1
|
243
|
my $f = shift; return sub { $f->( Y( $f ) )->( @_ ) }; |
|
116
|
|
|
114
|
|
508
|
|
|
114
|
|
|
|
|
322
|
|
868
|
|
|
|
|
|
|
} |
869
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
sub factorial ($) { |
871
|
|
|
|
|
|
|
return Y( sub (&) { |
872
|
5
|
|
|
5
|
|
14
|
my $fac = shift; |
873
|
|
|
|
|
|
|
|
874
|
|
|
|
|
|
|
return sub ($) { |
875
|
5
|
|
|
|
|
11
|
my $n = shift; |
876
|
|
|
|
|
|
|
|
877
|
5
|
100
|
|
1
|
1
|
25
|
return $n < 2 ? 1 : $n * $fac->( $n - 1 ) } } )->( @_ ); |
|
5
|
|
|
|
|
36
|
|
|
1
|
|
|
|
|
950
|
|
878
|
|
|
|
|
|
|
} |
879
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
sub fibonacci ($) { |
881
|
|
|
|
|
|
|
return Y( sub { |
882
|
109
|
|
|
109
|
|
277
|
my $fib = shift; |
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
return sub { |
885
|
109
|
|
|
|
|
248
|
my $n = shift; |
886
|
|
|
|
|
|
|
|
887
|
109
|
100
|
|
|
|
654
|
return $n == 0 ? 0 |
|
|
100
|
|
|
|
|
|
888
|
|
|
|
|
|
|
: $n == 1 ? 1 |
889
|
109
|
|
|
1
|
1
|
437
|
: $fib->( $n - 1 ) + $fib->( $n - 2 ) } } )->( @_ ); |
|
1
|
|
|
|
|
9
|
|
890
|
|
|
|
|
|
|
} |
891
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
sub product (;@) { |
893
|
4
|
|
|
4
|
1
|
18
|
return ((fold { $_[ 0 ] * $_[ 1 ] })->( 1 ))->( @_ ); |
|
1
|
|
|
1
|
|
12
|
|
894
|
|
|
|
|
|
|
} |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
sub sum (;@) { |
897
|
4
|
|
|
4
|
1
|
16
|
return ((fold { $_[ 0 ] + $_[ 1 ] })->( 0 ))->( @_ ); |
|
1
|
|
|
1
|
|
10
|
|
898
|
|
|
|
|
|
|
} |
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
1; |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
__END__ |
903
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
=pod |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
=head1 Name |
907
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
Class::Usul::Functions - Globally accessible functions |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
=head1 Synopsis |
911
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
package MyBaseClass; |
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
use Class::Usul::Functions qw( functions to import ); |
915
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
=head1 Description |
917
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
Provides globally accessible functions |
919
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
=head1 Subroutines/Methods |
921
|
|
|
|
|
|
|
|
922
|
|
|
|
|
|
|
=head2 C<abs_path> |
923
|
|
|
|
|
|
|
|
924
|
|
|
|
|
|
|
$absolute_untainted_path = abs_path $some_path; |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
Untaints path. Makes it an absolute path and returns it. Returns undef |
927
|
|
|
|
|
|
|
otherwise. Traverses the filesystem |
928
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
=head2 C<app_prefix> |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
$prefix = app_prefix __PACKAGE__; |
932
|
|
|
|
|
|
|
|
933
|
|
|
|
|
|
|
Takes a class name and returns it lower cased with B<::> changed to |
934
|
|
|
|
|
|
|
B<_>, e.g. C<App::Munchies> becomes C<app_munchies> |
935
|
|
|
|
|
|
|
|
936
|
|
|
|
|
|
|
=head2 C<arg_list> |
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
$args = arg_list @rest; |
939
|
|
|
|
|
|
|
|
940
|
|
|
|
|
|
|
Returns a hash ref containing the passed parameter list. Enables |
941
|
|
|
|
|
|
|
methods to be called with either a list or a hash ref as it's input |
942
|
|
|
|
|
|
|
parameters |
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
=head2 C<assert> |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
assert $ioc_object, $condition, $message; |
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
By default does nothing. Does not evaluate the passed parameters. The |
949
|
|
|
|
|
|
|
L<assert|Classs::Usul::Constants/ASSERT> constant can be set via |
950
|
|
|
|
|
|
|
an inherited class attribute to do something useful with whatever parameters |
951
|
|
|
|
|
|
|
are passed to it |
952
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
=head2 C<assert_directory> |
954
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
$untainted_path = assert_directory $path_to_directory; |
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
Untaints directory path. Makes it an absolute path and returns it if it |
958
|
|
|
|
|
|
|
exists. Returns undef otherwise |
959
|
|
|
|
|
|
|
|
960
|
|
|
|
|
|
|
=head2 C<base64_decode_ns> |
961
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
$decoded_value = base64_decode_ns $encoded_value; |
963
|
|
|
|
|
|
|
|
964
|
|
|
|
|
|
|
Decode a scalar value encode using L</base64_encode_ns> |
965
|
|
|
|
|
|
|
|
966
|
|
|
|
|
|
|
=head2 C<base64_encode_ns> |
967
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
$encoded_value = base64_encode_ns $encoded_value; |
969
|
|
|
|
|
|
|
|
970
|
|
|
|
|
|
|
Base 64 encode a scalar value using an output character set that preserves |
971
|
|
|
|
|
|
|
the input values sort order (natural sort) |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
=head2 C<bsonid> |
974
|
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
$bson_id = bsonid; |
976
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
Generate a new C<BSON> id. Returns a 24 character string of hex digits that |
978
|
|
|
|
|
|
|
are reasonably unique across hosts and are in ascending order. Use this |
979
|
|
|
|
|
|
|
to create unique ids for data streams like message queues and file feeds |
980
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
=head2 C<bsonid_time> |
982
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
$seconds_elapsed_since_the_epoch = bsonid_time $bson_id; |
984
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
Returns the time the C<BSON> id was generated as Unix time |
986
|
|
|
|
|
|
|
|
987
|
|
|
|
|
|
|
=head2 C<bson64id> |
988
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
$base64_encoded_extended_bson64_id = bson64id; |
990
|
|
|
|
|
|
|
|
991
|
|
|
|
|
|
|
Like L</bsonid> but better thread long running process support. A custom |
992
|
|
|
|
|
|
|
Base64 encoding is used to reduce the id length |
993
|
|
|
|
|
|
|
|
994
|
|
|
|
|
|
|
=head2 C<bson64id_time> |
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
$seconds_elapsed_since_the_epoch = bson64id_time $bson64_id; |
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
Returns the time the C<BSON64> id was generated as Unix time |
999
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
=head2 C<canonicalise> |
1001
|
|
|
|
|
|
|
|
1002
|
|
|
|
|
|
|
$untainted_canonpath = canonicalise $base, $relpath; |
1003
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
Appends C<$relpath> to C<$base> using L<File::Spec::Functions>. The C<$base> |
1005
|
|
|
|
|
|
|
and C<$relpath> arguments can be an array reference or a scalar. The return |
1006
|
|
|
|
|
|
|
path is untainted and canonicalised |
1007
|
|
|
|
|
|
|
|
1008
|
|
|
|
|
|
|
=head2 C<class2appdir> |
1009
|
|
|
|
|
|
|
|
1010
|
|
|
|
|
|
|
$appdir = class2appdir __PACKAGE__; |
1011
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
Returns lower cased L</distname>, e.g. C<App::Munchies> becomes |
1013
|
|
|
|
|
|
|
C<app-munchies> |
1014
|
|
|
|
|
|
|
|
1015
|
|
|
|
|
|
|
=head2 C<classdir> |
1016
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
$dir_path = classdir __PACKAGE__; |
1018
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
Returns the path (directory) of a given class. Like L</classfile> but |
1020
|
|
|
|
|
|
|
without the I<.pm> extension |
1021
|
|
|
|
|
|
|
|
1022
|
|
|
|
|
|
|
=head2 C<classfile> |
1023
|
|
|
|
|
|
|
|
1024
|
|
|
|
|
|
|
$file_path = classfile __PACKAGE__ ; |
1025
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
Returns the path (file name plus extension) of a given class. Uses |
1027
|
|
|
|
|
|
|
L<File::Spec> for portability, e.g. C<App::Munchies> becomes |
1028
|
|
|
|
|
|
|
C<App/Munchies.pm> |
1029
|
|
|
|
|
|
|
|
1030
|
|
|
|
|
|
|
=head2 C<create_token> |
1031
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
$random_hex = create_token $optional_seed; |
1033
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
Create a random string token using L</digest>. If C<$seed> is defined then add |
1035
|
|
|
|
|
|
|
that to the digest, otherwise add some random data provided by a call to |
1036
|
|
|
|
|
|
|
L</urandom>. Returns a hexadecimal string |
1037
|
|
|
|
|
|
|
|
1038
|
|
|
|
|
|
|
=head2 C<create_token64> |
1039
|
|
|
|
|
|
|
|
1040
|
|
|
|
|
|
|
$random_base64 = create_token64 $optional_seed; |
1041
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
Like L</create_token> but the output is C<base64> encoded |
1043
|
|
|
|
|
|
|
|
1044
|
|
|
|
|
|
|
=head2 C<cwdp> |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
$current_working_directory = cwdp; |
1047
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
Returns the current working directory, physical location |
1049
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
=head2 C<dash2under> |
1051
|
|
|
|
|
|
|
|
1052
|
|
|
|
|
|
|
$string_with_underscores = dash2under 'a-string-with-dashes'; |
1053
|
|
|
|
|
|
|
|
1054
|
|
|
|
|
|
|
Substitutes underscores for dashes |
1055
|
|
|
|
|
|
|
|
1056
|
|
|
|
|
|
|
=head2 C<data_dumper> |
1057
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
data_dumper $thing; |
1059
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
Uses L<Data::Printer> to dump C<$thing> in colour to I<stderr> |
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
=head2 C<digest> |
1063
|
|
|
|
|
|
|
|
1064
|
|
|
|
|
|
|
$digest_object = digest $seed; |
1065
|
|
|
|
|
|
|
|
1066
|
|
|
|
|
|
|
Creates an instance of the first available L<Digest> class and adds the seed. |
1067
|
|
|
|
|
|
|
The constant C<DIGEST_ALGORITHMS> is consulted for the list of algorithms to |
1068
|
|
|
|
|
|
|
search for. Returns the digest object reference |
1069
|
|
|
|
|
|
|
|
1070
|
|
|
|
|
|
|
=head2 C<distname> |
1071
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
$distname = distname __PACKAGE__; |
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
Takes a class name and returns it with B<::> changed to |
1075
|
|
|
|
|
|
|
B<->, e.g. C<App::Munchies> becomes C<App-Munchies> |
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
=head2 C<elapsed> |
1078
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
$elapsed_seconds = elapsed; |
1080
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
Returns the number of seconds elapsed since the process started |
1082
|
|
|
|
|
|
|
|
1083
|
|
|
|
|
|
|
=head2 C<emit> |
1084
|
|
|
|
|
|
|
|
1085
|
|
|
|
|
|
|
emit @lines_of_text; |
1086
|
|
|
|
|
|
|
|
1087
|
|
|
|
|
|
|
Prints to I<STDOUT> the lines of text passed to it. Lines are C<chomp>ed |
1088
|
|
|
|
|
|
|
and then have newlines appended. Throws on IO errors |
1089
|
|
|
|
|
|
|
|
1090
|
|
|
|
|
|
|
=head2 C<emit_err> |
1091
|
|
|
|
|
|
|
|
1092
|
|
|
|
|
|
|
emit_err @lines_of_text; |
1093
|
|
|
|
|
|
|
|
1094
|
|
|
|
|
|
|
Like L</emit> but output to C<STDERR> |
1095
|
|
|
|
|
|
|
|
1096
|
|
|
|
|
|
|
=head2 C<emit_to> |
1097
|
|
|
|
|
|
|
|
1098
|
|
|
|
|
|
|
emit_to $filehandle, @lines_of_text; |
1099
|
|
|
|
|
|
|
|
1100
|
|
|
|
|
|
|
Prints to the specified file handle |
1101
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
=head2 C<ensure_class_loaded> |
1103
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
ensure_class_loaded $some_class, $options_ref; |
1105
|
|
|
|
|
|
|
|
1106
|
|
|
|
|
|
|
Require the requested class, throw an error if it doesn't load |
1107
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
=head2 C<env_prefix> |
1109
|
|
|
|
|
|
|
|
1110
|
|
|
|
|
|
|
$prefix = env_prefix $class; |
1111
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
Returns upper cased C<app_prefix>. Suitable as prefix for environment |
1113
|
|
|
|
|
|
|
variables |
1114
|
|
|
|
|
|
|
|
1115
|
|
|
|
|
|
|
=head2 C<escape_TT> |
1116
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
$text = escape_TT '[% some_stash_key %]'; |
1118
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
The left square bracket causes problems in some contexts. Substitute a |
1120
|
|
|
|
|
|
|
less than symbol instead. Also replaces the right square bracket with |
1121
|
|
|
|
|
|
|
greater than for balance. L<Template::Toolkit> will work with these |
1122
|
|
|
|
|
|
|
sequences too, so unescaping isn't absolutely necessary |
1123
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
=head2 C<exception> |
1125
|
|
|
|
|
|
|
|
1126
|
|
|
|
|
|
|
$e = exception $error; |
1127
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
Expose the C<catch> method in the exception |
1129
|
|
|
|
|
|
|
class L<Class::Usul::Exception>. Returns a new error object |
1130
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
=head2 C<find_apphome> |
1132
|
|
|
|
|
|
|
|
1133
|
|
|
|
|
|
|
$directory_path = find_apphome $appclass, $homedir, $extns |
1134
|
|
|
|
|
|
|
|
1135
|
|
|
|
|
|
|
Returns the path to the applications home directory. Searches the following: |
1136
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
# 0. Pass the directory in (short circuit the search) |
1138
|
|
|
|
|
|
|
# 1a. Environment variable - for application directory |
1139
|
|
|
|
|
|
|
# 1b. Environment variable - for config file |
1140
|
|
|
|
|
|
|
# 2a. Users XDG_DATA_HOME env variable or XDG default share directory |
1141
|
|
|
|
|
|
|
# 2b. Users home directory - dot file containing shell env variable |
1142
|
|
|
|
|
|
|
# 2c. Users home directory - dot directory is apphome |
1143
|
|
|
|
|
|
|
# 3. Well known path containing shell env file |
1144
|
|
|
|
|
|
|
# 4. Default install prefix |
1145
|
|
|
|
|
|
|
# 5a. Config file found in @INC - underscore as separator |
1146
|
|
|
|
|
|
|
# 5b. Config file found in @INC - dash as separator |
1147
|
|
|
|
|
|
|
# 6. Default to /tmp |
1148
|
|
|
|
|
|
|
|
1149
|
|
|
|
|
|
|
=head2 C<find_source> |
1150
|
|
|
|
|
|
|
|
1151
|
|
|
|
|
|
|
$path = find_source $module_name; |
1152
|
|
|
|
|
|
|
|
1153
|
|
|
|
|
|
|
Find absolute path to the source code for the given module |
1154
|
|
|
|
|
|
|
|
1155
|
|
|
|
|
|
|
=head2 C<first_char> |
1156
|
|
|
|
|
|
|
|
1157
|
|
|
|
|
|
|
$single_char = first_char $some_string; |
1158
|
|
|
|
|
|
|
|
1159
|
|
|
|
|
|
|
Returns the first character of C<$string> |
1160
|
|
|
|
|
|
|
|
1161
|
|
|
|
|
|
|
=head2 C<fqdn> |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
$domain_name = fqdn $hostname; |
1164
|
|
|
|
|
|
|
|
1165
|
|
|
|
|
|
|
Call C<gethostbyname> on the supplied hostname whist defaults to this host |
1166
|
|
|
|
|
|
|
|
1167
|
|
|
|
|
|
|
=head2 C<fullname> |
1168
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
$fullname = fullname; |
1170
|
|
|
|
|
|
|
|
1171
|
|
|
|
|
|
|
Returns the untainted first sub field from the gecos attribute of the |
1172
|
|
|
|
|
|
|
object returned by a call to L</get_user>. Returns the null string if |
1173
|
|
|
|
|
|
|
the gecos attribute value is false |
1174
|
|
|
|
|
|
|
|
1175
|
|
|
|
|
|
|
=head2 C<get_cfgfiles> |
1176
|
|
|
|
|
|
|
|
1177
|
|
|
|
|
|
|
$paths = get_cfgfiles $appclass, $dirs, $extns |
1178
|
|
|
|
|
|
|
|
1179
|
|
|
|
|
|
|
Returns an array ref of configurations file paths for the application |
1180
|
|
|
|
|
|
|
|
1181
|
|
|
|
|
|
|
=head2 C<get_user> |
1182
|
|
|
|
|
|
|
|
1183
|
|
|
|
|
|
|
$user_object = get_user $optional_uid_or_name; |
1184
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
Returns the user object from a call to either C<getpwuid> or C<getpwnam> |
1186
|
|
|
|
|
|
|
depending on whether an integer or a string was passed. The L<User::pwent> |
1187
|
|
|
|
|
|
|
package is loaded so objects are returned. On MSWin32 systems returns an |
1188
|
|
|
|
|
|
|
instance of L<Class::Null>. Defaults to the current uid but will lookup the |
1189
|
|
|
|
|
|
|
supplied uid if provided |
1190
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
=head2 C<hex2str> |
1192
|
|
|
|
|
|
|
|
1193
|
|
|
|
|
|
|
$string = hex2str $pairs_of_hex_digits; |
1194
|
|
|
|
|
|
|
|
1195
|
|
|
|
|
|
|
Converts the pairs of hex digits into a string of characters |
1196
|
|
|
|
|
|
|
|
1197
|
|
|
|
|
|
|
=head2 C<home2appldir> |
1198
|
|
|
|
|
|
|
|
1199
|
|
|
|
|
|
|
$appldir = home2appldir $home_dir; |
1200
|
|
|
|
|
|
|
|
1201
|
|
|
|
|
|
|
Strips the trailing C<lib/my_package> from the supplied directory path |
1202
|
|
|
|
|
|
|
|
1203
|
|
|
|
|
|
|
=head2 C<io> |
1204
|
|
|
|
|
|
|
|
1205
|
|
|
|
|
|
|
$io_object_ref = io $path_to_file_or_directory; |
1206
|
|
|
|
|
|
|
|
1207
|
|
|
|
|
|
|
Returns a L<File::DataClass::IO> object reference |
1208
|
|
|
|
|
|
|
|
1209
|
|
|
|
|
|
|
=head2 C<is_arrayref> |
1210
|
|
|
|
|
|
|
|
1211
|
|
|
|
|
|
|
$bool = is_arrayref $scalar_variable |
1212
|
|
|
|
|
|
|
|
1213
|
|
|
|
|
|
|
Tests to see if the scalar variable is an array ref |
1214
|
|
|
|
|
|
|
|
1215
|
|
|
|
|
|
|
=head2 C<is_coderef> |
1216
|
|
|
|
|
|
|
|
1217
|
|
|
|
|
|
|
$bool = is_coderef $scalar_variable |
1218
|
|
|
|
|
|
|
|
1219
|
|
|
|
|
|
|
Tests to see if the scalar variable is a code ref |
1220
|
|
|
|
|
|
|
|
1221
|
|
|
|
|
|
|
=head2 C<is_hashref> |
1222
|
|
|
|
|
|
|
|
1223
|
|
|
|
|
|
|
$bool = is_hashref $scalar_variable |
1224
|
|
|
|
|
|
|
|
1225
|
|
|
|
|
|
|
Tests to see if the scalar variable is a hash ref |
1226
|
|
|
|
|
|
|
|
1227
|
|
|
|
|
|
|
=head2 C<is_member> |
1228
|
|
|
|
|
|
|
|
1229
|
|
|
|
|
|
|
$bool = is_member 'test_value', qw( a_value test_value b_value ); |
1230
|
|
|
|
|
|
|
|
1231
|
|
|
|
|
|
|
Tests to see if the first parameter is present in the list of |
1232
|
|
|
|
|
|
|
remaining parameters |
1233
|
|
|
|
|
|
|
|
1234
|
|
|
|
|
|
|
=head2 C<is_ntfs> |
1235
|
|
|
|
|
|
|
|
1236
|
|
|
|
|
|
|
$bool = is_ntfs; |
1237
|
|
|
|
|
|
|
|
1238
|
|
|
|
|
|
|
Returns true if L</is_win32> is true or the C<$OSNAME> is |
1239
|
|
|
|
|
|
|
L<cygwin|File::DataClass::Constants/CYGWIN> |
1240
|
|
|
|
|
|
|
|
1241
|
|
|
|
|
|
|
=head2 C<is_win32> |
1242
|
|
|
|
|
|
|
|
1243
|
|
|
|
|
|
|
$bool = is_win32; |
1244
|
|
|
|
|
|
|
|
1245
|
|
|
|
|
|
|
Returns true if the C<$OSNAME> is |
1246
|
|
|
|
|
|
|
L<unfortunate|File::DataClass::Constants/MSOFT> |
1247
|
|
|
|
|
|
|
|
1248
|
|
|
|
|
|
|
=head2 C<list_attr_of> |
1249
|
|
|
|
|
|
|
|
1250
|
|
|
|
|
|
|
$attribute_list = list_attr_of $object_ref, @exception_list; |
1251
|
|
|
|
|
|
|
|
1252
|
|
|
|
|
|
|
Lists the attributes of the object reference, including defining class name, |
1253
|
|
|
|
|
|
|
documentation, and current value |
1254
|
|
|
|
|
|
|
|
1255
|
|
|
|
|
|
|
=head2 C<loginid> |
1256
|
|
|
|
|
|
|
|
1257
|
|
|
|
|
|
|
$loginid = loginid; |
1258
|
|
|
|
|
|
|
|
1259
|
|
|
|
|
|
|
Returns the untainted name attribute of the object returned by a call |
1260
|
|
|
|
|
|
|
to L</get_user> or 'unknown' if the name attribute value is false |
1261
|
|
|
|
|
|
|
|
1262
|
|
|
|
|
|
|
=head2 C<logname> |
1263
|
|
|
|
|
|
|
|
1264
|
|
|
|
|
|
|
$logname = logname; |
1265
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
Deprecated. Returns untainted the first true value returned by; the environment |
1267
|
|
|
|
|
|
|
variable C<USER>, the environment variable C<LOGNAME>, and the function |
1268
|
|
|
|
|
|
|
L</loginid> |
1269
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
=head2 C<merge_attributes> |
1271
|
|
|
|
|
|
|
|
1272
|
|
|
|
|
|
|
$dest = merge_attributes $dest, $src, $defaults, $attr_list_ref; |
1273
|
|
|
|
|
|
|
|
1274
|
|
|
|
|
|
|
Merges attribute hashes. The C<$dest> hash is updated and returned. The |
1275
|
|
|
|
|
|
|
C<$dest> hash values take precedence over the C<$src> hash values which |
1276
|
|
|
|
|
|
|
take precedence over the C<$defaults> hash values. The C<$src> hash |
1277
|
|
|
|
|
|
|
may be an object in which case its accessor methods are called |
1278
|
|
|
|
|
|
|
|
1279
|
|
|
|
|
|
|
=head2 C<nonblocking_write_pipe_pair> |
1280
|
|
|
|
|
|
|
|
1281
|
|
|
|
|
|
|
$array_ref = non_blocking_write_pipe; |
1282
|
|
|
|
|
|
|
|
1283
|
|
|
|
|
|
|
Returns a pair of file handles, read then write. The write file handle is |
1284
|
|
|
|
|
|
|
non blocking, binmode is set on both |
1285
|
|
|
|
|
|
|
|
1286
|
|
|
|
|
|
|
=head2 C<my_prefix> |
1287
|
|
|
|
|
|
|
|
1288
|
|
|
|
|
|
|
$prefix = my_prefix $PROGRAM_NAME; |
1289
|
|
|
|
|
|
|
|
1290
|
|
|
|
|
|
|
Takes the basename of the supplied argument and returns the first _ |
1291
|
|
|
|
|
|
|
(underscore) separated field. Supplies basename with |
1292
|
|
|
|
|
|
|
L<extensions|Class::Usul::Constants/PERL_EXTNS> |
1293
|
|
|
|
|
|
|
|
1294
|
|
|
|
|
|
|
=head2 C<ns_environment> |
1295
|
|
|
|
|
|
|
|
1296
|
|
|
|
|
|
|
$value = ns_environment $class, $key, $value; |
1297
|
|
|
|
|
|
|
|
1298
|
|
|
|
|
|
|
An accessor / mutator for the environment variables prefixed by the supplied |
1299
|
|
|
|
|
|
|
class name. Providing a value is optional, always returns the current value |
1300
|
|
|
|
|
|
|
|
1301
|
|
|
|
|
|
|
=head2 C<pad> |
1302
|
|
|
|
|
|
|
|
1303
|
|
|
|
|
|
|
$padded_str = pad $unpadded_str, $wanted_length, $pad_char, $direction; |
1304
|
|
|
|
|
|
|
|
1305
|
|
|
|
|
|
|
Pad a string out to the wanted length with the C<$pad_char> which |
1306
|
|
|
|
|
|
|
defaults to a space. Direction can be; I<both>, I<left>, or I<right> |
1307
|
|
|
|
|
|
|
and defaults to I<right> |
1308
|
|
|
|
|
|
|
|
1309
|
|
|
|
|
|
|
=head2 C<prefix2class> |
1310
|
|
|
|
|
|
|
|
1311
|
|
|
|
|
|
|
$class = prefix2class $PROGRAM_NAME; |
1312
|
|
|
|
|
|
|
|
1313
|
|
|
|
|
|
|
Calls L</my_prefix> with the supplied argument, splits the result on dash, |
1314
|
|
|
|
|
|
|
C<ucfirst>s the list and then C<join>s that with I<::> |
1315
|
|
|
|
|
|
|
|
1316
|
|
|
|
|
|
|
=head2 C<socket_pair> |
1317
|
|
|
|
|
|
|
|
1318
|
|
|
|
|
|
|
($reader, $writer) = @{ socket_pair }; |
1319
|
|
|
|
|
|
|
|
1320
|
|
|
|
|
|
|
Return a C<socketpair> reader then writer. The writer has been closed on the |
1321
|
|
|
|
|
|
|
reader and the reader has been closed on the writer |
1322
|
|
|
|
|
|
|
|
1323
|
|
|
|
|
|
|
=head2 C<split_on__> |
1324
|
|
|
|
|
|
|
|
1325
|
|
|
|
|
|
|
$field = split_on__ $string, $field_no; |
1326
|
|
|
|
|
|
|
|
1327
|
|
|
|
|
|
|
Splits string by _ (underscore) and returns the requested field. Defaults |
1328
|
|
|
|
|
|
|
to field zero |
1329
|
|
|
|
|
|
|
|
1330
|
|
|
|
|
|
|
=head2 C<split_on_dash> |
1331
|
|
|
|
|
|
|
|
1332
|
|
|
|
|
|
|
$field = split_on_dash $string, $field_no; |
1333
|
|
|
|
|
|
|
|
1334
|
|
|
|
|
|
|
Splits string by - (dash) and returns the requested field. Defaults |
1335
|
|
|
|
|
|
|
to field zero |
1336
|
|
|
|
|
|
|
|
1337
|
|
|
|
|
|
|
=head2 C<squeeze> |
1338
|
|
|
|
|
|
|
|
1339
|
|
|
|
|
|
|
$string = squeeze $string_containing_muliple_spacesd; |
1340
|
|
|
|
|
|
|
|
1341
|
|
|
|
|
|
|
Squeezes multiple whitespace down to a single space |
1342
|
|
|
|
|
|
|
|
1343
|
|
|
|
|
|
|
=head2 C<strip_leader> |
1344
|
|
|
|
|
|
|
|
1345
|
|
|
|
|
|
|
$stripped = strip_leader 'my_program: Error message'; |
1346
|
|
|
|
|
|
|
|
1347
|
|
|
|
|
|
|
Strips the leading "program_name: whitespace" from the passed argument |
1348
|
|
|
|
|
|
|
|
1349
|
|
|
|
|
|
|
=head2 C<sub_name> |
1350
|
|
|
|
|
|
|
|
1351
|
|
|
|
|
|
|
$sub_name = sub_name $level; |
1352
|
|
|
|
|
|
|
|
1353
|
|
|
|
|
|
|
Returns the name of the method that calls it |
1354
|
|
|
|
|
|
|
|
1355
|
|
|
|
|
|
|
=head2 C<symlink> |
1356
|
|
|
|
|
|
|
|
1357
|
|
|
|
|
|
|
$message = symlink $from, $to, $base; |
1358
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
It creates a symlink. If either C<$from> or C<$to> is a relative path |
1360
|
|
|
|
|
|
|
then C<$base> is prepended to make it absolute. Returns a message |
1361
|
|
|
|
|
|
|
indicating success or throws an exception on failure |
1362
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
=head2 C<thread_id> |
1364
|
|
|
|
|
|
|
|
1365
|
|
|
|
|
|
|
$tid = thread_id; |
1366
|
|
|
|
|
|
|
|
1367
|
|
|
|
|
|
|
Returns the id of this thread. Returns zero if threads are not loaded |
1368
|
|
|
|
|
|
|
|
1369
|
|
|
|
|
|
|
=head2 C<throw> |
1370
|
|
|
|
|
|
|
|
1371
|
|
|
|
|
|
|
throw 'error_message', [ 'error_arg' ]; |
1372
|
|
|
|
|
|
|
|
1373
|
|
|
|
|
|
|
Expose L<Class::Usul::Exception/throw>. L<Class::Usul::Constants> has a |
1374
|
|
|
|
|
|
|
class attribute I<Exception_Class> which can be set change the class |
1375
|
|
|
|
|
|
|
of the thrown exception |
1376
|
|
|
|
|
|
|
|
1377
|
|
|
|
|
|
|
=head2 C<throw_on_error> |
1378
|
|
|
|
|
|
|
|
1379
|
|
|
|
|
|
|
throw_on_error @args; |
1380
|
|
|
|
|
|
|
|
1381
|
|
|
|
|
|
|
Passes it's optional arguments to L</exception> and if an exception object is |
1382
|
|
|
|
|
|
|
returned it throws it. Returns undefined otherwise. If no arguments are |
1383
|
|
|
|
|
|
|
passed L</exception> will use the value of the global C<$EVAL_ERROR> |
1384
|
|
|
|
|
|
|
|
1385
|
|
|
|
|
|
|
=head2 C<trim> |
1386
|
|
|
|
|
|
|
|
1387
|
|
|
|
|
|
|
$trimmed_string = trim $string_with_leading_and_trailing_whitespace; |
1388
|
|
|
|
|
|
|
|
1389
|
|
|
|
|
|
|
Remove leading and trailing whitespace including trailing newlines. Takes |
1390
|
|
|
|
|
|
|
an additional string used as the character class to remove. Defaults to |
1391
|
|
|
|
|
|
|
space and tab |
1392
|
|
|
|
|
|
|
|
1393
|
|
|
|
|
|
|
=head2 C<unescape_TT> |
1394
|
|
|
|
|
|
|
|
1395
|
|
|
|
|
|
|
$text = unescape_TT '<% some_stash_key %>'; |
1396
|
|
|
|
|
|
|
|
1397
|
|
|
|
|
|
|
Do the reverse of C<escape_TT> |
1398
|
|
|
|
|
|
|
|
1399
|
|
|
|
|
|
|
=head2 C<untaint_cmdline> |
1400
|
|
|
|
|
|
|
|
1401
|
|
|
|
|
|
|
$untainted_cmdline = untaint_cmdline $maybe_tainted_cmdline; |
1402
|
|
|
|
|
|
|
|
1403
|
|
|
|
|
|
|
Returns an untainted command line string. Calls L</untaint_string> with the |
1404
|
|
|
|
|
|
|
matching regex from L<Class::Usul::Constants> |
1405
|
|
|
|
|
|
|
|
1406
|
|
|
|
|
|
|
=head2 C<untaint_identifier> |
1407
|
|
|
|
|
|
|
|
1408
|
|
|
|
|
|
|
$untainted_identifier = untaint_identifier $maybe_tainted_identifier; |
1409
|
|
|
|
|
|
|
|
1410
|
|
|
|
|
|
|
Returns an untainted identifier string. Calls L</untaint_string> with the |
1411
|
|
|
|
|
|
|
matching regex from L<Class::Usul::Constants> |
1412
|
|
|
|
|
|
|
|
1413
|
|
|
|
|
|
|
=head2 C<untaint_path> |
1414
|
|
|
|
|
|
|
|
1415
|
|
|
|
|
|
|
$untainted_path = untaint_path $maybe_tainted_path; |
1416
|
|
|
|
|
|
|
|
1417
|
|
|
|
|
|
|
Returns an untainted file path. Calls L</untaint_string> with the |
1418
|
|
|
|
|
|
|
matching regex from L<Class::Usul::Constants> |
1419
|
|
|
|
|
|
|
|
1420
|
|
|
|
|
|
|
=head2 C<untaint_string> |
1421
|
|
|
|
|
|
|
|
1422
|
|
|
|
|
|
|
$untainted_string = untaint_string $regex, $maybe_tainted_string; |
1423
|
|
|
|
|
|
|
|
1424
|
|
|
|
|
|
|
Returns an untainted string or throws |
1425
|
|
|
|
|
|
|
|
1426
|
|
|
|
|
|
|
=head2 C<urandom> |
1427
|
|
|
|
|
|
|
|
1428
|
|
|
|
|
|
|
$bytes = urandom $optional_length, $optional_provider; |
1429
|
|
|
|
|
|
|
|
1430
|
|
|
|
|
|
|
Returns random bytes. Length defaults to 64. The provider defaults to |
1431
|
|
|
|
|
|
|
F</dev/urandom> and can be any type accepted by L</io>. If the provider exists |
1432
|
|
|
|
|
|
|
and is readable, length bytes are read from it and returned. Otherwise some |
1433
|
|
|
|
|
|
|
bytes from the second best generator are returned |
1434
|
|
|
|
|
|
|
|
1435
|
|
|
|
|
|
|
=head2 C<uuid> |
1436
|
|
|
|
|
|
|
|
1437
|
|
|
|
|
|
|
$uuid = uuid $optional_uuid_proc_filesystem_path; |
1438
|
|
|
|
|
|
|
|
1439
|
|
|
|
|
|
|
Return the contents of F</proc/sys/kernel/random/uuid> |
1440
|
|
|
|
|
|
|
|
1441
|
|
|
|
|
|
|
=head2 C<whiten> |
1442
|
|
|
|
|
|
|
|
1443
|
|
|
|
|
|
|
$encoded = whiten 'plain_text_to_be_obfuscated'; |
1444
|
|
|
|
|
|
|
|
1445
|
|
|
|
|
|
|
Lifted from L<Acme::Bleach> this function encodes the passed scalar as spaces, |
1446
|
|
|
|
|
|
|
tabs, and newlines. The L<encrypt> and L<decrypt> functions take a seed |
1447
|
|
|
|
|
|
|
attribute in their options hash reference. A whitened line of Perl code |
1448
|
|
|
|
|
|
|
would be a suitable value |
1449
|
|
|
|
|
|
|
|
1450
|
|
|
|
|
|
|
=head2 C<zip> |
1451
|
|
|
|
|
|
|
|
1452
|
|
|
|
|
|
|
%hash = zip @list_of_keys, @list_of_values; |
1453
|
|
|
|
|
|
|
|
1454
|
|
|
|
|
|
|
Zips two list of equal size together to form a hash |
1455
|
|
|
|
|
|
|
|
1456
|
|
|
|
|
|
|
=head2 C<chain> |
1457
|
|
|
|
|
|
|
|
1458
|
|
|
|
|
|
|
$result = chain $sub1, $sub2, $sub3 |
1459
|
|
|
|
|
|
|
|
1460
|
|
|
|
|
|
|
Call each sub in turn passing the returned value as the first argument to |
1461
|
|
|
|
|
|
|
the next function call |
1462
|
|
|
|
|
|
|
|
1463
|
|
|
|
|
|
|
=head2 C<compose> |
1464
|
|
|
|
|
|
|
|
1465
|
|
|
|
|
|
|
$code_ref = compose { }, $code_ref; |
1466
|
|
|
|
|
|
|
|
1467
|
|
|
|
|
|
|
Returns a code reference which when called returns the result of calling the |
1468
|
|
|
|
|
|
|
block passing in the result of calling the optional code reference. Delays the |
1469
|
|
|
|
|
|
|
calling of the input code reference until the output code reference is called |
1470
|
|
|
|
|
|
|
|
1471
|
|
|
|
|
|
|
=head2 C<curry> |
1472
|
|
|
|
|
|
|
|
1473
|
|
|
|
|
|
|
$curried_code_ref = curry $code_ref, @args; |
1474
|
|
|
|
|
|
|
$result = $curried_code_ref->( @more_args ); |
1475
|
|
|
|
|
|
|
|
1476
|
|
|
|
|
|
|
Returns a subroutine reference which when called, calls and returns the |
1477
|
|
|
|
|
|
|
initial code reference passing in the original argument list and the |
1478
|
|
|
|
|
|
|
arguments from the curried call. Must be called with a code reference and |
1479
|
|
|
|
|
|
|
at least one argument |
1480
|
|
|
|
|
|
|
|
1481
|
|
|
|
|
|
|
=head2 C<fold> |
1482
|
|
|
|
|
|
|
|
1483
|
|
|
|
|
|
|
*sum = fold { $a + $b } 0; |
1484
|
|
|
|
|
|
|
|
1485
|
|
|
|
|
|
|
Classic reduce function with optional base value |
1486
|
|
|
|
|
|
|
|
1487
|
|
|
|
|
|
|
=head2 C<Y> |
1488
|
|
|
|
|
|
|
|
1489
|
|
|
|
|
|
|
$code_ref = Y( $code_ref ); |
1490
|
|
|
|
|
|
|
|
1491
|
|
|
|
|
|
|
The Y-combinator function |
1492
|
|
|
|
|
|
|
|
1493
|
|
|
|
|
|
|
=head2 C<factorial> |
1494
|
|
|
|
|
|
|
|
1495
|
|
|
|
|
|
|
$result = factorial $n; |
1496
|
|
|
|
|
|
|
|
1497
|
|
|
|
|
|
|
Calculates the factorial for the supplied integer |
1498
|
|
|
|
|
|
|
|
1499
|
|
|
|
|
|
|
=head2 C<fibonacci> |
1500
|
|
|
|
|
|
|
|
1501
|
|
|
|
|
|
|
$result = fibonacci $n; |
1502
|
|
|
|
|
|
|
|
1503
|
|
|
|
|
|
|
Calculates the Fibonacci number for the supplied integer |
1504
|
|
|
|
|
|
|
|
1505
|
|
|
|
|
|
|
=head2 C<product> |
1506
|
|
|
|
|
|
|
|
1507
|
|
|
|
|
|
|
$product = product 1, 2, 3, 4; |
1508
|
|
|
|
|
|
|
|
1509
|
|
|
|
|
|
|
Returns the product of the list of numbers |
1510
|
|
|
|
|
|
|
|
1511
|
|
|
|
|
|
|
=head2 C<sum> |
1512
|
|
|
|
|
|
|
|
1513
|
|
|
|
|
|
|
$total = sum 1, 2, 3, 4; |
1514
|
|
|
|
|
|
|
|
1515
|
|
|
|
|
|
|
Adds the list of values |
1516
|
|
|
|
|
|
|
|
1517
|
|
|
|
|
|
|
=head1 Diagnostics |
1518
|
|
|
|
|
|
|
|
1519
|
|
|
|
|
|
|
None |
1520
|
|
|
|
|
|
|
|
1521
|
|
|
|
|
|
|
=head1 Configuration and Environment |
1522
|
|
|
|
|
|
|
|
1523
|
|
|
|
|
|
|
None |
1524
|
|
|
|
|
|
|
|
1525
|
|
|
|
|
|
|
=head1 Dependencies |
1526
|
|
|
|
|
|
|
|
1527
|
|
|
|
|
|
|
=over 3 |
1528
|
|
|
|
|
|
|
|
1529
|
|
|
|
|
|
|
=item L<Class::Usul::Constants> |
1530
|
|
|
|
|
|
|
|
1531
|
|
|
|
|
|
|
=item L<Data::Printer> |
1532
|
|
|
|
|
|
|
|
1533
|
|
|
|
|
|
|
=item L<Digest> |
1534
|
|
|
|
|
|
|
|
1535
|
|
|
|
|
|
|
=item L<File::HomeDir> |
1536
|
|
|
|
|
|
|
|
1537
|
|
|
|
|
|
|
=item L<List::Util> |
1538
|
|
|
|
|
|
|
|
1539
|
|
|
|
|
|
|
=back |
1540
|
|
|
|
|
|
|
|
1541
|
|
|
|
|
|
|
=head1 Incompatibilities |
1542
|
|
|
|
|
|
|
|
1543
|
|
|
|
|
|
|
The L</home2appldir> method is dependent on the installation path |
1544
|
|
|
|
|
|
|
containing a B<lib> |
1545
|
|
|
|
|
|
|
|
1546
|
|
|
|
|
|
|
The L</uuid> method with only work on a OS with a F</proc> filesystem |
1547
|
|
|
|
|
|
|
|
1548
|
|
|
|
|
|
|
=head1 Bugs and Limitations |
1549
|
|
|
|
|
|
|
|
1550
|
|
|
|
|
|
|
There are no known bugs in this module. |
1551
|
|
|
|
|
|
|
Please report problems to the address below. |
1552
|
|
|
|
|
|
|
Patches are welcome |
1553
|
|
|
|
|
|
|
|
1554
|
|
|
|
|
|
|
=head1 Author |
1555
|
|
|
|
|
|
|
|
1556
|
|
|
|
|
|
|
Peter Flanigan, C<< <pjfl@cpan.org> >> |
1557
|
|
|
|
|
|
|
|
1558
|
|
|
|
|
|
|
=head1 License and Copyright |
1559
|
|
|
|
|
|
|
|
1560
|
|
|
|
|
|
|
Copyright (c) 2017 Peter Flanigan. All rights reserved |
1561
|
|
|
|
|
|
|
|
1562
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
1563
|
|
|
|
|
|
|
under the same terms as Perl itself. See L<perlartistic> |
1564
|
|
|
|
|
|
|
|
1565
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, |
1566
|
|
|
|
|
|
|
but WITHOUT WARRANTY; without even the implied warranty of |
1567
|
|
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE |
1568
|
|
|
|
|
|
|
|
1569
|
|
|
|
|
|
|
=cut |
1570
|
|
|
|
|
|
|
|
1571
|
|
|
|
|
|
|
# Local Variables: |
1572
|
|
|
|
|
|
|
# mode: perl |
1573
|
|
|
|
|
|
|
# tab-width: 3 |
1574
|
|
|
|
|
|
|
# End: |