line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Spoon::Base; |
2
|
10
|
|
|
10
|
|
48600
|
use Spiffy 0.24 -Base; |
|
10
|
|
|
|
|
68331
|
|
|
10
|
|
|
|
|
100
|
|
3
|
10
|
|
|
10
|
|
50838
|
use Spiffy qw(-yaml); |
|
10
|
|
|
10
|
|
26
|
|
|
10
|
|
|
10
|
|
360
|
|
|
10
|
|
|
|
|
61
|
|
|
10
|
|
|
|
|
22
|
|
|
10
|
|
|
|
|
320
|
|
|
10
|
|
|
|
|
55
|
|
|
10
|
|
|
|
|
22
|
|
|
10
|
|
|
|
|
50
|
|
4
|
10
|
|
|
10
|
|
3209
|
use Spiffy qw(WWW XXX YYY ZZZ); |
|
10
|
|
|
|
|
23
|
|
|
10
|
|
|
|
|
49
|
|
5
|
|
|
|
|
|
|
# WWW - Creating a wrapper sub to require() IO::All caused spurious segfaults |
6
|
10
|
|
|
10
|
|
12613
|
use IO::All 0.32; |
|
10
|
|
|
|
|
175320
|
|
|
10
|
|
|
|
|
128
|
|
7
|
|
|
|
|
|
|
our @EXPORT = qw(io trace WWW XXX YYY ZZZ); |
8
|
|
|
|
|
|
|
our @EXPORT_OK = qw(conf); |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
field used_classes => []; |
11
|
|
|
|
|
|
|
field 'encoding'; |
12
|
|
|
|
|
|
|
const plugin_base_directory => './plugin'; |
13
|
|
|
|
|
|
|
field using_debug => 0; |
14
|
|
|
|
|
|
|
field config_class => 'Spoon::Config'; |
15
|
|
|
|
|
|
|
|
16
|
61
|
|
|
61
|
1
|
650
|
sub hub { |
17
|
61
|
100
|
66
|
|
|
1350
|
return $Spoon::Base::HUB |
18
|
|
|
|
|
|
|
if defined($Spoon::Base::HUB) and not @_; |
19
|
5
|
50
|
|
|
|
21
|
Carp::confess "Too late to create a new hub. One already exists" |
20
|
|
|
|
|
|
|
if defined $Spoon::Base::HUB; |
21
|
|
|
|
|
|
|
|
22
|
5
|
|
|
|
|
7
|
my ($args, @config_files); |
23
|
|
|
|
|
|
|
{ |
24
|
10
|
|
|
10
|
|
2160
|
no warnings; |
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
2850
|
|
|
5
|
|
|
|
|
7
|
|
25
|
5
|
|
|
5
|
|
31
|
local *paired_arguments = sub { qw(-config_class) }; |
|
5
|
|
|
|
|
80
|
|
26
|
5
|
|
|
|
|
54
|
($args, @config_files) = $self->parse_arguments(@_); |
27
|
|
|
|
|
|
|
} |
28
|
5
|
50
|
33
|
|
|
159
|
my $config_class = $args->{-config_class} || |
29
|
|
|
|
|
|
|
$self->can('config_class') |
30
|
|
|
|
|
|
|
? $self->config_class |
31
|
|
|
|
|
|
|
: 'Spoon::Config'; |
32
|
5
|
50
|
|
|
|
958
|
eval "require $config_class"; die $@ if $@; |
|
5
|
|
|
|
|
32
|
|
33
|
5
|
|
|
|
|
31
|
my $config = $config_class->new(@config_files); |
34
|
5
|
|
|
|
|
131
|
my $hub_class = $config->hub_class; |
35
|
5
|
|
|
|
|
280
|
eval "require $hub_class"; |
36
|
5
|
|
|
|
|
43
|
my $hub = $hub_class->new( |
37
|
|
|
|
|
|
|
config => $config, |
38
|
|
|
|
|
|
|
config_files => \@config_files, |
39
|
|
|
|
|
|
|
); |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
5
|
|
|
5
|
0
|
11
|
sub destroy_hub { |
43
|
5
|
|
|
|
|
15
|
undef $Spoon::Base::HUB; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
27
|
|
|
27
|
1
|
65
|
sub init { } |
47
|
|
|
|
|
|
|
|
48
|
0
|
|
|
0
|
1
|
0
|
sub assert { |
49
|
0
|
0
|
|
|
|
0
|
die "Assertion failed" unless shift; |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub trace() { |
53
|
0
|
|
|
0
|
1
|
0
|
require Spoon::Trace; |
54
|
10
|
|
|
10
|
|
54
|
no warnings; |
|
10
|
|
|
|
|
17
|
|
|
10
|
|
|
|
|
1167
|
|
55
|
0
|
|
|
|
|
0
|
*trace = \ &Spoon::Trace::trace; |
56
|
0
|
|
|
|
|
0
|
goto &trace; |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
0
|
|
|
0
|
1
|
0
|
sub t { |
60
|
0
|
|
|
|
|
0
|
trace->mark; |
61
|
0
|
|
|
|
|
0
|
return $self; |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub conf() { |
65
|
0
|
|
|
0
|
1
|
0
|
my ($name, $default) = @_; |
66
|
0
|
|
|
|
|
0
|
my $package = caller; |
67
|
10
|
|
|
10
|
|
51
|
no strict 'refs'; |
|
10
|
|
|
|
|
33
|
|
|
10
|
|
|
|
|
3120
|
|
68
|
0
|
|
|
|
|
0
|
*{$package . '::' . $name} = sub { |
69
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
70
|
0
|
0
|
|
|
|
0
|
return $self->{$name} |
71
|
|
|
|
|
|
|
if exists $self->{$name}; |
72
|
0
|
0
|
|
|
|
0
|
$self->{$name} = exists($self->hub->config->{$name}) |
73
|
|
|
|
|
|
|
? $self->hub->config->{$name} |
74
|
|
|
|
|
|
|
: $default; |
75
|
0
|
|
|
|
|
0
|
}; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
0
|
|
|
0
|
1
|
0
|
sub clone { |
79
|
0
|
|
|
|
|
0
|
return bless {%$self}, ref $self; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
1
|
|
|
1
|
1
|
2
|
sub is_in_cgi { |
83
|
1
|
|
|
|
|
7
|
defined $ENV{GATEWAY_INTERFACE}; |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
0
|
|
|
0
|
1
|
0
|
sub is_in_test { |
87
|
0
|
|
|
|
|
0
|
defined $ENV{SPOON_TEST}; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
0
|
|
|
0
|
1
|
0
|
sub have_plugin { |
91
|
0
|
0
|
|
|
|
0
|
my $hub = $self->class_id eq 'hub' |
92
|
|
|
|
|
|
|
? $self |
93
|
|
|
|
|
|
|
: $self->hub; |
94
|
0
|
|
|
|
|
0
|
local $@; |
95
|
0
|
|
|
|
|
0
|
eval { $hub->load_class(shift) } |
|
0
|
|
|
|
|
0
|
|
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
0
|
|
|
0
|
1
|
0
|
sub plugin_directory { |
99
|
0
|
|
|
|
|
0
|
my $dir = join '/', |
100
|
|
|
|
|
|
|
$self->plugin_base_directory, |
101
|
|
|
|
|
|
|
$self->class_id, |
102
|
|
|
|
|
|
|
; |
103
|
0
|
0
|
|
|
|
0
|
mkdir $dir unless -d $dir; |
104
|
0
|
|
|
|
|
0
|
return $dir; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
1
|
|
|
1
|
0
|
18
|
sub debug { |
108
|
10
|
|
|
10
|
|
70
|
no warnings; |
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
4252
|
|
109
|
1
|
50
|
|
|
|
8
|
if ($self->is_in_cgi) { |
110
|
0
|
0
|
|
|
|
0
|
eval 'use CGI::Carp qw(fatalsToBrowser)'; die $@ if $@; |
|
0
|
|
|
|
|
0
|
|
111
|
0
|
|
|
0
|
|
0
|
$SIG{__DIE__} = sub { CGI::Carp::confess(@_) } |
112
|
0
|
|
|
|
|
0
|
} |
113
|
|
|
|
|
|
|
else { |
114
|
1
|
|
|
|
|
9
|
require Carp; |
115
|
0
|
|
|
0
|
|
0
|
$SIG{__DIE__} = sub { Carp::confess(@_) } |
116
|
1
|
|
|
|
|
14
|
} |
117
|
1
|
50
|
|
|
|
5
|
$self->using_debug(1) |
118
|
|
|
|
|
|
|
if ref $self; |
119
|
1
|
|
|
|
|
3
|
return $self; |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
our ($UPPER, $LOWER, $ALPHA, $NUM, $ALPHANUM, $WORD, $WIKIWORD); |
123
|
|
|
|
|
|
|
push @EXPORT_OK, qw($UPPER $LOWER $ALPHA $NUM $ALPHANUM $WORD $WIKIWORD); |
124
|
|
|
|
|
|
|
our %EXPORT_TAGS = (char_classes => [@EXPORT_OK]); |
125
|
|
|
|
|
|
|
if ($] < 5.008) { |
126
|
|
|
|
|
|
|
$UPPER = 'A-Z\xc0-\xde'; |
127
|
|
|
|
|
|
|
$LOWER = 'a-z\xdf-\xff'; |
128
|
|
|
|
|
|
|
$ALPHA = $UPPER . $LOWER; |
129
|
|
|
|
|
|
|
$NUM = '0-9'; |
130
|
|
|
|
|
|
|
$ALPHANUM = $ALPHA . $NUM; |
131
|
|
|
|
|
|
|
$WORD = $ALPHANUM . '_'; |
132
|
|
|
|
|
|
|
$WIKIWORD = $WORD; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
else { |
135
|
|
|
|
|
|
|
$UPPER = '\p{UppercaseLetter}'; |
136
|
|
|
|
|
|
|
$LOWER = '\p{LowercaseLetter}'; |
137
|
|
|
|
|
|
|
$ALPHA = '\p{Letter}'; |
138
|
|
|
|
|
|
|
$NUM = '\p{Number}'; |
139
|
|
|
|
|
|
|
$ALPHANUM = '\p{Letter}\p{Number}\pM'; |
140
|
|
|
|
|
|
|
$WORD = '\p{Letter}\p{Number}\p{ConnectorPunctuation}\pM'; |
141
|
|
|
|
|
|
|
$WIKIWORD = "$UPPER$LOWER$NUM" . '\p{ConnectorPunctuation}\pM'; |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
|
144
|
0
|
|
|
0
|
1
|
0
|
sub env_check { |
145
|
0
|
|
|
|
|
0
|
my $variable = shift; |
146
|
0
|
0
|
|
|
|
0
|
die "Environment variable '$variable' not set" |
147
|
|
|
|
|
|
|
unless defined $ENV{$variable}; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
0
|
|
|
0
|
1
|
0
|
sub dumper_to_file { |
151
|
0
|
|
|
|
|
0
|
my $path = shift; |
152
|
0
|
|
|
|
|
0
|
require Data::Dumper; |
153
|
10
|
|
|
10
|
|
59
|
no warnings; |
|
10
|
|
|
|
|
18
|
|
|
10
|
|
|
|
|
7832
|
|
154
|
0
|
|
|
|
|
0
|
local $Data::Dumper::Indent = 1; |
155
|
0
|
0
|
|
|
|
0
|
local $Data::Dumper::Terse = (@_ == 1) ? 1 : 0; |
156
|
0
|
|
|
|
|
0
|
local $Data::Dumper::Sortkeys = 1; |
157
|
0
|
|
|
|
|
0
|
io("$path")->assert->print(Data::Dumper::Dumper(@_)); |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
# Codecs and Escaping |
161
|
|
|
|
|
|
|
my $has_utf8; |
162
|
6
|
|
|
6
|
1
|
10
|
sub has_utf8 { |
163
|
6
|
50
|
|
|
|
23
|
$has_utf8 = shift if @_; |
164
|
6
|
100
|
|
|
|
52
|
return $has_utf8 if defined($has_utf8); |
165
|
2
|
50
|
|
|
|
33
|
$has_utf8 = $] < 5.008 ? 0 : 1; |
166
|
2
|
50
|
|
|
|
76
|
require Encode if $has_utf8; |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
|
169
|
6
|
|
|
6
|
1
|
15349
|
sub utf8_decode { |
170
|
6
|
50
|
33
|
|
|
27
|
$_[0] = Encode::decode('utf8', $_[0]) |
|
|
|
33
|
|
|
|
|
171
|
|
|
|
|
|
|
if $self->has_utf8 and |
172
|
|
|
|
|
|
|
defined $_[0] and |
173
|
|
|
|
|
|
|
not Encode::is_utf8($_[0]); |
174
|
6
|
|
|
|
|
242
|
return $_[0]; |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
|
177
|
0
|
|
|
0
|
1
|
0
|
sub utf8_encode { |
178
|
0
|
0
|
0
|
|
|
0
|
$_[0] = Encode::encode('utf8', $_[0]) |
179
|
|
|
|
|
|
|
if $self->has_utf8 and |
180
|
|
|
|
|
|
|
defined $_[0]; |
181
|
0
|
|
|
|
|
0
|
return $_[0]; |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
0
|
|
|
0
|
1
|
0
|
sub uri_escape { |
185
|
0
|
|
|
|
|
0
|
require CGI::Util; |
186
|
0
|
|
|
|
|
0
|
my $data = shift; |
187
|
0
|
|
|
|
|
0
|
$self->utf8_encode($data); |
188
|
0
|
|
|
|
|
0
|
return CGI::Util::escape($data); |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
0
|
|
|
0
|
1
|
0
|
sub uri_unescape { |
192
|
0
|
|
|
|
|
0
|
require CGI::Util; |
193
|
0
|
|
|
|
|
0
|
my $data = shift; |
194
|
0
|
|
|
|
|
0
|
$data = CGI::Util::unescape($data); |
195
|
0
|
|
|
|
|
0
|
$self->utf8_decode($data); |
196
|
0
|
|
|
|
|
0
|
return $data; |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
# WWW - The CGI.pm version is broken in Chinese |
200
|
10
|
|
|
10
|
1
|
91
|
sub html_escape { |
201
|
10
|
|
|
|
|
15
|
my $val = shift; |
202
|
10
|
|
|
|
|
17
|
$val =~ s/&/&/g; |
203
|
10
|
|
|
|
|
13
|
$val =~ s/</g; |
204
|
10
|
|
|
|
|
10
|
$val =~ s/>/>/g; |
205
|
10
|
|
|
|
|
11
|
$val =~ s/\(/(/g; |
206
|
10
|
|
|
|
|
12
|
$val =~ s/\)/)/g; |
207
|
10
|
|
|
|
|
11
|
$val =~ s/"/"/g; |
208
|
10
|
|
|
|
|
14
|
$val =~ s/'/'/g; |
209
|
10
|
|
|
|
|
51
|
return $val; |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
0
|
|
|
0
|
1
|
|
sub html_unescape { |
213
|
0
|
|
|
|
|
|
CGI::unescapeHTML(shift); |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
0
|
|
|
0
|
1
|
|
sub base64_encode { |
217
|
0
|
|
|
|
|
|
require MIME::Base64; |
218
|
0
|
|
|
|
|
|
MIME::Base64::encode_base64(@_); |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
0
|
|
|
0
|
0
|
|
sub base64_decode { |
222
|
0
|
|
|
|
|
|
require MIME::Base64; |
223
|
0
|
|
|
|
|
|
MIME::Base64::decode_base64(@_); |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
# XXX Move to IO::All. Make more robust. Use Damian's prompting module. |
227
|
|
|
|
|
|
|
package IO::All; |
228
|
|
|
|
|
|
|
|
229
|
0
|
|
|
0
|
0
|
|
sub prompt { |
230
|
0
|
|
|
|
|
|
print shift; |
231
|
0
|
|
|
|
|
|
io('-')->chomp->getline; |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
__END__ |