line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
################################################################# |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# Hook::Filter::Hooker - Wrap subroutines in a firewalling closure |
4
|
|
|
|
|
|
|
# |
5
|
|
|
|
|
|
|
# $Id: Hooker.pm,v 1.8 2007/05/24 14:58:09 erwan_lemonnier Exp $ |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
# 060302 erwan Created |
8
|
|
|
|
|
|
|
# 070516 erwan Use the rule pool |
9
|
|
|
|
|
|
|
# |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
package Hook::Filter::Hooker; |
12
|
|
|
|
|
|
|
|
13
|
12
|
|
|
12
|
|
231683
|
use strict; |
|
12
|
|
|
|
|
27
|
|
|
12
|
|
|
|
|
459
|
|
14
|
12
|
|
|
12
|
|
92
|
use warnings; |
|
12
|
|
|
|
|
22
|
|
|
12
|
|
|
|
|
406
|
|
15
|
12
|
|
|
12
|
|
88
|
use Carp qw(croak); |
|
12
|
|
|
|
|
22
|
|
|
12
|
|
|
|
|
939
|
|
16
|
12
|
|
|
12
|
|
1429
|
use Data::Dumper; |
|
12
|
|
|
|
|
11787
|
|
|
12
|
|
|
|
|
806
|
|
17
|
12
|
|
|
12
|
|
3772
|
use Symbol; |
|
12
|
|
|
|
|
4549
|
|
|
12
|
|
|
|
|
927
|
|
18
|
12
|
|
|
12
|
|
72
|
use base qw(Exporter); |
|
12
|
|
|
|
|
34
|
|
|
12
|
|
|
|
|
1419
|
|
19
|
12
|
|
|
12
|
|
9470
|
use Hook::Filter::RulePool qw(get_rule_pool); |
|
12
|
|
|
|
|
33
|
|
|
12
|
|
|
|
|
1294
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
our @EXPORT = qw(); |
22
|
|
|
|
|
|
|
our @EXPORT_OK = qw( get_caller_package |
23
|
|
|
|
|
|
|
get_caller_file |
24
|
|
|
|
|
|
|
get_caller_line |
25
|
|
|
|
|
|
|
get_caller_subname |
26
|
|
|
|
|
|
|
get_subname |
27
|
|
|
|
|
|
|
get_arguments |
28
|
|
|
|
|
|
|
filter_sub |
29
|
|
|
|
|
|
|
); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
|
33
|
12
|
|
|
|
|
8728
|
use vars qw( $CALLER_PACKAGE |
34
|
|
|
|
|
|
|
$CALLER_FILE |
35
|
|
|
|
|
|
|
$CALLER_LINE |
36
|
|
|
|
|
|
|
$CALLER_SUBNAME |
37
|
|
|
|
|
|
|
$SUBNAME |
38
|
12
|
|
|
12
|
|
83
|
@ARGUMENTS ); |
|
12
|
|
|
|
|
21
|
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# singleton instance of Hook::Filter::RulePool |
41
|
|
|
|
|
|
|
my $pool = get_rule_pool(); |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
# a hash whose keys are the fully qualified names of all filtered |
44
|
|
|
|
|
|
|
# subroutines, to avoid filtering one twice |
45
|
|
|
|
|
|
|
my %subs; |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
#---------------------------------------------------------------- |
48
|
|
|
|
|
|
|
# |
49
|
|
|
|
|
|
|
# accessors for use in Hook::Filter::Plugins:: modules |
50
|
|
|
|
|
|
|
# |
51
|
|
|
|
|
|
|
|
52
|
2
|
|
|
2
|
1
|
14
|
sub get_caller_package { return $CALLER_PACKAGE; }; |
53
|
2
|
|
|
2
|
1
|
8
|
sub get_caller_file { return $CALLER_FILE; }; |
54
|
2
|
|
|
2
|
1
|
12
|
sub get_caller_line { return $CALLER_LINE; }; |
55
|
14
|
|
|
14
|
1
|
125
|
sub get_caller_subname { return $CALLER_SUBNAME; }; |
56
|
42
|
|
|
42
|
1
|
402
|
sub get_subname { return $SUBNAME; }; |
57
|
7
|
|
|
7
|
1
|
25
|
sub get_arguments { return @ARGUMENTS; }; |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
#---------------------------------------------------------------- |
60
|
|
|
|
|
|
|
# |
61
|
|
|
|
|
|
|
# filter_sub - build a filter closure wrapping calls to the provided sub |
62
|
|
|
|
|
|
|
# |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub filter_sub { |
65
|
45
|
|
|
45
|
1
|
4570
|
my $subname = shift; |
66
|
|
|
|
|
|
|
|
67
|
45
|
100
|
100
|
|
|
375
|
if (!defined $subname || ref \$subname ne "SCALAR" || scalar @_) { |
|
|
|
100
|
|
|
|
|
68
|
4
|
|
|
|
|
7
|
shift @_; |
69
|
4
|
|
|
|
|
18
|
croak "invalid parameter: Hook::Filter::Hooker->filter_sub expects a subroutine name, but got [".Dumper($subname,@_)."]."; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
41
|
100
|
|
|
|
265
|
if ($subname !~ /^(.+)::([^:]+)$/) { |
73
|
1
|
|
|
|
|
134
|
croak "invalid parameter: [$subname] is not a valid subroutine name (must include package name)."; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
40
|
|
|
|
|
132
|
my ($pkg,$func) = ($1,$2); |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# check whether subroutine is already filtered, and skip if so |
79
|
40
|
100
|
|
|
|
127
|
return if (exists $subs{$subname}); |
80
|
|
|
|
|
|
|
|
81
|
38
|
|
|
|
|
101
|
my $filtered_func = *{ qualify_to_ref($func,$pkg) }{CODE}; |
|
38
|
|
|
|
|
136
|
|
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
# create the closure that will replace $func in package $pkg |
84
|
|
|
|
|
|
|
my $filter = sub { |
85
|
52
|
|
|
52
|
|
6341
|
my (@args) = @_; |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# TODO: looking at source for Hook::WrapSub, it might be a good idea to copy/paste some of its code here, to build a valid caller stack |
88
|
|
|
|
|
|
|
# TODO: look at Hook::LexWrap and fix so that caller() work in subroutines |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# set global variables |
91
|
52
|
|
|
|
|
346
|
$CALLER_PACKAGE = (caller(0))[0]; |
92
|
52
|
|
|
|
|
259
|
$CALLER_FILE = (caller(0))[1]; |
93
|
52
|
|
|
|
|
248
|
$CALLER_LINE = (caller(0))[2]; |
94
|
52
|
|
100
|
|
|
303
|
$CALLER_SUBNAME = (caller(1))[3] || ""; |
95
|
52
|
|
|
|
|
92
|
$SUBNAME = $subname; |
96
|
52
|
|
|
|
|
105
|
@ARGUMENTS = @args; |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
# evaluate all rules. if true is returned, forward the call |
99
|
52
|
100
|
|
|
|
179
|
if ($pool->eval_rules) { |
100
|
31
|
100
|
|
|
|
74
|
if (wantarray) { |
101
|
3
|
|
|
|
|
11
|
my @results = $filtered_func->(@args); |
102
|
3
|
|
|
|
|
26
|
return @results; |
103
|
|
|
|
|
|
|
} else { |
104
|
28
|
|
|
|
|
92
|
my $result = $filtered_func->(@args); |
105
|
28
|
|
|
|
|
234
|
return $result; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# the call was blocked. fake a return value (ugly.) |
110
|
21
|
100
|
|
|
|
59
|
if (wantarray) { |
111
|
1
|
|
|
|
|
5
|
return (); |
112
|
|
|
|
|
|
|
} |
113
|
20
|
|
|
|
|
97
|
return; |
114
|
38
|
|
|
|
|
1527
|
}; |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# keep track of already hooked subroutines |
117
|
38
|
|
|
|
|
111
|
$subs{$subname} = 1; |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# replace $package::$func with our closure |
120
|
12
|
|
|
12
|
|
78
|
no strict 'refs'; |
|
12
|
|
|
|
|
21
|
|
|
12
|
|
|
|
|
380
|
|
121
|
12
|
|
|
12
|
|
64
|
no warnings; |
|
12
|
|
|
|
|
22
|
|
|
12
|
|
|
|
|
1036
|
|
122
|
|
|
|
|
|
|
|
123
|
38
|
|
|
|
|
53
|
*{ qualify_to_ref($func,$pkg) } = $filter; |
|
38
|
|
|
|
|
100
|
|
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
1; |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
__END__ |