Filename | /usr/local/src/github.com/foswiki/core/lib/Foswiki/Access/TopicACLAccess.pm |
Statements | Executed 1811 statements in 9.54ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 9.48ms | 9.96ms | BEGIN@22 | Foswiki::Access::TopicACLAccess::
56 | 1 | 1 | 5.09ms | 60.9s | haveAccess | Foswiki::Access::TopicACLAccess::
132 | 4 | 1 | 2.52ms | 60.8s | _getACL | Foswiki::Access::TopicACLAccess::
40 | 1 | 1 | 79µs | 79µs | CORE:subst (opcode) | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 29µs | 33µs | new | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 24µs | 78µs | BEGIN@19 | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 21µs | 29µs | BEGIN@18 | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 21µs | 21µs | BEGIN@13 | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 20µs | 124µs | BEGIN@16 | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 12µs | 12µs | BEGIN@23 | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 10µs | 10µs | BEGIN@24 | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 10µs | 10µs | BEGIN@21 | Foswiki::Access::TopicACLAccess::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for license and copyright information | ||||
2 | |||||
3 | =pod | ||||
4 | |||||
5 | ---+ package Foswiki::Access::TopicACLAccess | ||||
6 | |||||
7 | Implements the traditional, longstanding ACL in topic preference style. | ||||
8 | |||||
9 | =cut | ||||
10 | |||||
11 | package Foswiki::Access::TopicACLAccess; | ||||
12 | |||||
13 | 2 | 68µs | 1 | 21µs | # spent 21µs within Foswiki::Access::TopicACLAccess::BEGIN@13 which was called:
# once (21µs+0s) by Foswiki::Access::BEGIN@2 at line 13 # spent 21µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@13 |
14 | 1 | 12µs | @ISA = qw(Foswiki::Access); | ||
15 | |||||
16 | 2 | 52µs | 2 | 228µs | # spent 124µs (20+104) within Foswiki::Access::TopicACLAccess::BEGIN@16 which was called:
# once (20µs+104µs) by Foswiki::Access::BEGIN@2 at line 16 # spent 124µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@16
# spent 104µs making 1 call to constant::import |
17 | |||||
18 | 2 | 47µs | 2 | 37µs | # spent 29µs (21+8) within Foswiki::Access::TopicACLAccess::BEGIN@18 which was called:
# once (21µs+8µs) by Foswiki::Access::BEGIN@2 at line 18 # spent 29µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@18
# spent 8µs making 1 call to strict::import |
19 | 2 | 50µs | 2 | 133µs | # spent 78µs (24+55) within Foswiki::Access::TopicACLAccess::BEGIN@19 which was called:
# once (24µs+55µs) by Foswiki::Access::BEGIN@2 at line 19 # spent 78µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@19
# spent 55µs making 1 call to Assert::import |
20 | |||||
21 | 2 | 40µs | 1 | 10µs | # spent 10µs within Foswiki::Access::TopicACLAccess::BEGIN@21 which was called:
# once (10µs+0s) by Foswiki::Access::BEGIN@2 at line 21 # spent 10µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@21 |
22 | 2 | 211µs | 1 | 9.96ms | # spent 9.96ms (9.48+478µs) within Foswiki::Access::TopicACLAccess::BEGIN@22 which was called:
# once (9.48ms+478µs) by Foswiki::Access::BEGIN@2 at line 22 # spent 9.96ms making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@22 |
23 | 2 | 53µs | 1 | 12µs | # spent 12µs within Foswiki::Access::TopicACLAccess::BEGIN@23 which was called:
# once (12µs+0s) by Foswiki::Access::BEGIN@2 at line 23 # spent 12µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@23 |
24 | 2 | 1.63ms | 1 | 10µs | # spent 10µs within Foswiki::Access::TopicACLAccess::BEGIN@24 which was called:
# once (10µs+0s) by Foswiki::Access::BEGIN@2 at line 24 # spent 10µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@24 |
25 | |||||
26 | # spent 33µs (29+4) within Foswiki::Access::TopicACLAccess::new which was called:
# once (29µs+4µs) by Foswiki::Access::new at line 34 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Access.pm | ||||
27 | 1 | 3µs | my ( $class, $session ) = @_; | ||
28 | 1 | 5µs | 1 | 4µs | ASSERT( $session->isa('Foswiki') ) if DEBUG; # spent 4µs making 1 call to Assert::ASSERTS_OFF |
29 | 1 | 12µs | my $this = bless( { session => $session }, $class ); | ||
30 | |||||
31 | 1 | 9µs | return $this; | ||
32 | } | ||||
33 | |||||
34 | =begin TML | ||||
35 | |||||
36 | ---++ ObjectMethod haveAccess($mode, $User, $web, $topic, $attachment) -> $boolean | ||||
37 | ---++ ObjectMethod haveAccess($mode, $User, $meta) -> $boolean | ||||
38 | ---++ ObjectMethod haveAccess($mode, $User, $address) -> $boolean | ||||
39 | |||||
40 | * =$mode= - 'VIEW', 'CHANGE', 'CREATE', etc. (defaults to VIEW) | ||||
41 | * =$cUID= - Canonical user id (defaults to current user) | ||||
42 | Check if the user has the given mode of access to the topic. This call | ||||
43 | may result in the topic being read. | ||||
44 | |||||
45 | =cut | ||||
46 | |||||
47 | # spent 60.9s (5.09ms+60.9) within Foswiki::Access::TopicACLAccess::haveAccess which was called 56 times, avg 1.09s/call:
# 56 times (5.09ms+60.9s) by Foswiki::Meta::haveAccess at line 1836 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Meta.pm, avg 1.09s/call | ||||
48 | 56 | 183µs | my ( $this, $mode, $cUID, $param1, $param2, $param3 ) = @_; | ||
49 | 56 | 80µs | $mode ||= 'VIEW'; | ||
50 | 56 | 74µs | $cUID ||= $this->{session}->{user}; | ||
51 | |||||
52 | 56 | 145µs | my $session = $this->{session}; | ||
53 | 56 | 106µs | undef $this->{failure}; | ||
54 | |||||
55 | 56 | 66µs | my $meta; | ||
56 | |||||
57 | 56 | 244µs | if ( ref($param1) eq '' ) { | ||
58 | |||||
59 | #scalar - treat as web, topic | ||||
60 | $meta = Foswiki::Meta->load( $session, $param1, $param2 ); | ||||
61 | ASSERT( not defined($param3) ) | ||||
62 | if DEBUG | ||||
63 | ; #attachment ACL not currently supported in traditional topic ACL | ||||
64 | } | ||||
65 | else { | ||||
66 | 56 | 254µs | if ( ref($param1) eq 'Foswiki::Address' ) { | ||
67 | $meta = | ||||
68 | Foswiki::Meta->load( $session, $param1->web(), $param1->topic() ); | ||||
69 | } | ||||
70 | else { | ||||
71 | 56 | 86µs | $meta = $param1; | ||
72 | } | ||||
73 | } | ||||
74 | 56 | 264µs | 56 | 192µs | ASSERT( $meta->isa('Foswiki::Meta') ) if DEBUG; # spent 192µs making 56 calls to Assert::ASSERTS_OFF, avg 3µs/call |
75 | |||||
76 | print STDERR "Check $mode access $cUID to " . $meta->getPath() . "\n" | ||||
77 | if MONITOR; | ||||
78 | |||||
79 | # super admin is always allowed | ||||
80 | 56 | 548µs | 56 | 84.9ms | if ( $session->{users}->isAdmin($cUID) ) { # spent 84.9ms making 56 calls to Foswiki::Users::isAdmin, avg 1.52ms/call |
81 | print STDERR "$cUID - ADMIN\n" if MONITOR; | ||||
82 | 23 | 131µs | return 1; | ||
83 | } | ||||
84 | |||||
85 | 33 | 129µs | $mode = uc($mode); | ||
86 | |||||
87 | 33 | 57µs | my ( $allow, $deny ); | ||
88 | 33 | 112µs | if ( $meta->{_topic} ) { | ||
89 | |||||
90 | 33 | 311µs | 33 | 72.5ms | my $allow = $this->_getACL( $meta, 'ALLOWTOPIC' . $mode ); # spent 72.5ms making 33 calls to Foswiki::Access::TopicACLAccess::_getACL, avg 2.20ms/call |
91 | 33 | 212µs | 33 | 1.07ms | my $deny = $this->_getACL( $meta, 'DENYTOPIC' . $mode ); # spent 1.07ms making 33 calls to Foswiki::Access::TopicACLAccess::_getACL, avg 32µs/call |
92 | |||||
93 | # Check DENYTOPIC | ||||
94 | 33 | 56µs | if ( defined($deny) ) { | ||
95 | if ( scalar(@$deny) != 0 ) { | ||||
96 | if ( $session->{users}->isInUserList( $cUID, $deny ) ) { | ||||
97 | $this->{failure} = | ||||
98 | $session->i18n->maketext('access denied on topic'); | ||||
99 | print STDERR 'a ' . $this->{failure}, "\n" if MONITOR; | ||||
100 | return 0; | ||||
101 | } | ||||
102 | } | ||||
103 | else { | ||||
104 | |||||
105 | # If DENYTOPIC is empty, don't deny _anyone_ | ||||
106 | print STDERR "DENYTOPIC is empty\n" if MONITOR; | ||||
107 | return 1; | ||||
108 | } | ||||
109 | } | ||||
110 | |||||
111 | # Check ALLOWTOPIC. If this is defined the user _must_ be in it | ||||
112 | 33 | 48µs | if ( defined($allow) && scalar(@$allow) != 0 ) { | ||
113 | if ( $session->{users}->isInUserList( $cUID, $allow ) ) { | ||||
114 | print STDERR "in ALLOWTOPIC\n" if MONITOR; | ||||
115 | return 1; | ||||
116 | } | ||||
117 | $this->{failure} = | ||||
118 | $session->i18n->maketext('access not allowed on topic'); | ||||
119 | print STDERR 'b ' . $this->{failure}, "\n" if MONITOR; | ||||
120 | return 0; | ||||
121 | } | ||||
122 | 33 | 222µs | 33 | 2.63ms | $meta = $meta->getContainer(); # Web # spent 2.63ms making 33 calls to Foswiki::Meta::getContainer, avg 80µs/call |
123 | } | ||||
124 | |||||
125 | 33 | 101µs | if ( $meta->{_web} ) { | ||
126 | |||||
127 | # Check DENYWEB, but only if DENYTOPIC is not set (even if it | ||||
128 | # is empty - empty means "don't deny anybody") | ||||
129 | 33 | 97µs | unless ( defined($deny) ) { | ||
130 | 33 | 306µs | 33 | 60.7s | $deny = $this->_getACL( $meta, 'DENYWEB' . $mode ); # spent 60.7s making 33 calls to Foswiki::Access::TopicACLAccess::_getACL, avg 1.84s/call |
131 | 33 | 201µs | 20 | 294µs | if ( defined($deny) # spent 294µs making 20 calls to Foswiki::Users::isInUserList, avg 15µs/call |
132 | && $session->{users}->isInUserList( $cUID, $deny ) ) | ||||
133 | { | ||||
134 | $this->{failure} = | ||||
135 | $session->i18n->maketext('access denied on web'); | ||||
136 | print STDERR 'c ' . $this->{failure}, "\n" if MONITOR; | ||||
137 | return 0; | ||||
138 | } | ||||
139 | } | ||||
140 | |||||
141 | # Check ALLOWWEB. If this is defined and not overridden by | ||||
142 | # ALLOWTOPIC, the user _must_ be in it. | ||||
143 | 33 | 268µs | 33 | 2.34ms | $allow = $this->_getACL( $meta, 'ALLOWWEB' . $mode ); # spent 2.34ms making 33 calls to Foswiki::Access::TopicACLAccess::_getACL, avg 71µs/call |
144 | |||||
145 | 33 | 74µs | if ( defined($allow) && scalar(@$allow) != 0 ) { | ||
146 | unless ( $session->{users}->isInUserList( $cUID, $allow ) ) { | ||||
147 | $this->{failure} = | ||||
148 | $session->i18n->maketext('access not allowed on web'); | ||||
149 | print STDERR 'd ' . $this->{failure}, "\n" if MONITOR; | ||||
150 | return 0; | ||||
151 | } | ||||
152 | } | ||||
153 | |||||
154 | } | ||||
155 | else { | ||||
156 | |||||
157 | # No web, we are checking at the root. Check DENYROOT and ALLOWROOT. | ||||
158 | $deny = $this->_getACL( $meta, 'DENYROOT' . $mode ); | ||||
159 | |||||
160 | if ( defined($deny) | ||||
161 | && $session->{users}->isInUserList( $cUID, $deny ) ) | ||||
162 | { | ||||
163 | $this->{failure} = | ||||
164 | $session->i18n->maketext('access denied on root'); | ||||
165 | print STDERR 'e ' . $this->{failure}, "\n" if MONITOR; | ||||
166 | return 0; | ||||
167 | } | ||||
168 | |||||
169 | $allow = $this->_getACL( $meta, 'ALLOWROOT' . $mode ); | ||||
170 | |||||
171 | if ( defined($allow) && scalar(@$allow) != 0 ) { | ||||
172 | unless ( $session->{users}->isInUserList( $cUID, $allow ) ) { | ||||
173 | $this->{failure} = | ||||
174 | $session->i18n->maketext('access not allowed on root'); | ||||
175 | print STDERR 'f ' . $this->{failure}, "\n" if MONITOR; | ||||
176 | return 0; | ||||
177 | } | ||||
178 | } | ||||
179 | } | ||||
180 | |||||
181 | if (MONITOR) { | ||||
182 | print STDERR "OK, permitted\n"; | ||||
183 | print STDERR 'ALLOW: ' . join( ',', @$allow ) . "\n" if defined $allow; | ||||
184 | print STDERR 'DENY: ' . join( ',', @$deny ) . "\n" if defined $deny; | ||||
185 | } | ||||
186 | 33 | 296µs | return 1; | ||
187 | } | ||||
188 | |||||
189 | # Get an ACL preference. Returns a reference to a list of cUIDs, or undef. | ||||
190 | # If the preference is defined but is empty, then a reference to an | ||||
191 | # empty list is returned. | ||||
192 | # This function canonicalises the parsing of a users list. Is this the right | ||||
193 | # place for it? | ||||
194 | # spent 60.8s (2.52ms+60.8) within Foswiki::Access::TopicACLAccess::_getACL which was called 132 times, avg 461ms/call:
# 33 times (695µs+60.7s) by Foswiki::Access::TopicACLAccess::haveAccess at line 130, avg 1.84s/call
# 33 times (734µs+71.8ms) by Foswiki::Access::TopicACLAccess::haveAccess at line 90, avg 2.20ms/call
# 33 times (617µs+1.72ms) by Foswiki::Access::TopicACLAccess::haveAccess at line 143, avg 71µs/call
# 33 times (476µs+593µs) by Foswiki::Access::TopicACLAccess::haveAccess at line 91, avg 32µs/call | ||||
195 | 132 | 335µs | my ( $this, $meta, $mode ) = @_; | ||
196 | |||||
197 | 132 | 278µs | if ( defined $meta->{_topic} && !defined $meta->{_loadedRev} ) { | ||
198 | |||||
199 | # Lazy load the latest version. | ||||
200 | 7 | 47µs | 7 | 34.7ms | $meta->loadVersion(); # spent 34.7ms making 7 calls to Foswiki::Meta::loadVersion, avg 4.95ms/call |
201 | } | ||||
202 | |||||
203 | 132 | 790µs | 132 | 60.8s | my $text = $meta->getPreference($mode); # spent 60.8s making 132 calls to Foswiki::Meta::getPreference, avg 460ms/call |
204 | 132 | 576µs | return undef unless defined $text; | ||
205 | |||||
206 | # Remove HTML tags (compatibility, inherited from Users.pm | ||||
207 | 40 | 274µs | 40 | 79µs | $text =~ s/(<[^>]*>)//g; # spent 79µs making 40 calls to Foswiki::Access::TopicACLAccess::CORE:subst, avg 2µs/call |
208 | |||||
209 | # Dump the users web specifier if userweb | ||||
210 | my @list = grep { /\S/ } map { | ||||
211 | 40 | 104µs | s/^($Foswiki::cfg{UsersWebName}|%USERSWEB%|%MAINWEB%)\.//; | ||
212 | $_ | ||||
213 | } split( /[,\s]+/, $text ); | ||||
214 | |||||
215 | #print STDERR "getACL($mode): ".join(', ', @list)."\n"; | ||||
216 | |||||
217 | 40 | 272µs | return \@list; | ||
218 | } | ||||
219 | |||||
220 | 1 | 6µs | 1; | ||
221 | __END__ | ||||
# spent 79µs within Foswiki::Access::TopicACLAccess::CORE:subst which was called 40 times, avg 2µs/call:
# 40 times (79µs+0s) by Foswiki::Access::TopicACLAccess::_getACL at line 207, avg 2µs/call |