Filename | /var/www/foswikidev/core/lib/Foswiki/Access/TopicACLAccess.pm |
Statements | Executed 3298 statements in 3.17ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 5.69ms | 5.97ms | BEGIN@22 | Foswiki::Access::TopicACLAccess::
252 | 1 | 1 | 2.05ms | 2.63ms | haveAccess | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 14µs | 40µs | BEGIN@19 | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 13µs | 13µs | BEGIN@13 | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 10µs | 10µs | new | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 9µs | 38µs | BEGIN@16 | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 9µs | 20µs | BEGIN@18 | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 5µs | 5µs | BEGIN@23 | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 4µs | 4µs | BEGIN@21 | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 4µs | 4µs | BEGIN@24 | Foswiki::Access::TopicACLAccess::
1 | 1 | 1 | 4µs | 4µs | BEGIN@26 | Foswiki::Access::TopicACLAccess::
0 | 0 | 0 | 0s | 0s | _getACL | 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 | 42µs | 1 | 13µs | # spent 13µs within Foswiki::Access::TopicACLAccess::BEGIN@13 which was called:
# once (13µs+0s) by Foswiki::Access::new at line 13 # spent 13µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@13 |
14 | 1 | 7µs | @ISA = qw(Foswiki::Access); | ||
15 | |||||
16 | 2 | 29µs | 2 | 68µs | # spent 38µs (9+29) within Foswiki::Access::TopicACLAccess::BEGIN@16 which was called:
# once (9µs+29µs) by Foswiki::Access::new at line 16 # spent 38µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@16
# spent 29µs making 1 call to constant::import |
17 | |||||
18 | 2 | 28µs | 2 | 31µs | # spent 20µs (9+11) within Foswiki::Access::TopicACLAccess::BEGIN@18 which was called:
# once (9µs+11µs) by Foswiki::Access::new at line 18 # spent 20µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@18
# spent 11µs making 1 call to strict::import |
19 | 2 | 26µs | 2 | 65µs | # spent 40µs (14+25) within Foswiki::Access::TopicACLAccess::BEGIN@19 which was called:
# once (14µs+25µs) by Foswiki::Access::new at line 19 # spent 40µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@19
# spent 25µs making 1 call to Exporter::import |
20 | |||||
21 | 2 | 18µs | 1 | 4µs | # spent 4µs within Foswiki::Access::TopicACLAccess::BEGIN@21 which was called:
# once (4µs+0s) by Foswiki::Access::new at line 21 # spent 4µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@21 |
22 | 2 | 120µs | 1 | 5.97ms | # spent 5.97ms (5.69+279µs) within Foswiki::Access::TopicACLAccess::BEGIN@22 which was called:
# once (5.69ms+279µs) by Foswiki::Access::new at line 22 # spent 5.97ms making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@22 |
23 | 2 | 21µs | 1 | 5µs | # spent 5µs within Foswiki::Access::TopicACLAccess::BEGIN@23 which was called:
# once (5µs+0s) by Foswiki::Access::new at line 23 # spent 5µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@23 |
24 | 2 | 42µs | 1 | 4µs | # spent 4µs within Foswiki::Access::TopicACLAccess::BEGIN@24 which was called:
# once (4µs+0s) by Foswiki::Access::new at line 24 # spent 4µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@24 |
25 | |||||
26 | # spent 4µs within Foswiki::Access::TopicACLAccess::BEGIN@26 which was called:
# once (4µs+0s) by Foswiki::Access::new at line 31 | ||||
27 | 1 | 5µs | if ( $Foswiki::cfg{UseLocale} ) { | ||
28 | require locale; | ||||
29 | import locale(); | ||||
30 | } | ||||
31 | 1 | 852µs | 1 | 4µs | } # spent 4µs making 1 call to Foswiki::Access::TopicACLAccess::BEGIN@26 |
32 | |||||
33 | # spent 10µs within Foswiki::Access::TopicACLAccess::new which was called:
# once (10µs+0s) by Foswiki::Access::new at line 42 of /var/www/foswikidev/core/lib/Foswiki/Access.pm | ||||
34 | 1 | 900ns | my ( $class, $session ) = @_; | ||
35 | ASSERT( $session->isa('Foswiki') ) if DEBUG; | ||||
36 | 1 | 6µs | my $this = bless( { session => $session }, $class ); | ||
37 | |||||
38 | 1 | 6µs | return $this; | ||
39 | } | ||||
40 | |||||
41 | =begin TML | ||||
42 | |||||
43 | ---++ ObjectMethod haveAccess($mode, $User, $web, $topic, $attachment) -> $boolean | ||||
44 | ---++ ObjectMethod haveAccess($mode, $User, $meta) -> $boolean | ||||
45 | ---++ ObjectMethod haveAccess($mode, $User, $address) -> $boolean | ||||
46 | |||||
47 | * =$mode= - 'VIEW', 'CHANGE', 'CREATE', etc. (defaults to VIEW) | ||||
48 | * =$cUID= - Canonical user id (defaults to current user) | ||||
49 | Check if the user has the given mode of access to the topic. This call | ||||
50 | may result in the topic being read. | ||||
51 | |||||
52 | =cut | ||||
53 | |||||
54 | # spent 2.63ms (2.05+571µs) within Foswiki::Access::TopicACLAccess::haveAccess which was called 252 times, avg 10µs/call:
# 252 times (2.05ms+571µs) by Foswiki::Meta::haveAccess at line 1925 of /var/www/foswikidev/core/lib/Foswiki/Meta.pm, avg 10µs/call | ||||
55 | 252 | 190µs | my ( $this, $mode, $cUID, $param1, $param2, $param3 ) = @_; | ||
56 | 252 | 28µs | $mode ||= 'VIEW'; | ||
57 | 252 | 25µs | $cUID ||= $this->{session}->{user}; | ||
58 | |||||
59 | 252 | 92µs | my $session = $this->{session}; | ||
60 | 252 | 95µs | undef $this->{failure}; | ||
61 | |||||
62 | 252 | 168µs | return 1 | ||
63 | if ( defined $Foswiki::cfg{LoginManager} | ||||
64 | && $Foswiki::cfg{LoginManager} eq 'none' ); | ||||
65 | |||||
66 | 252 | 27µs | my $meta; | ||
67 | |||||
68 | 252 | 181µs | if ( ref($param1) eq '' ) { | ||
69 | |||||
70 | #scalar - treat as web, topic | ||||
71 | $meta = Foswiki::Meta->load( $session, $param1, $param2 ); | ||||
72 | ASSERT( not defined($param3) ) | ||||
73 | if DEBUG | ||||
74 | ; #attachment ACL not currently supported in traditional topic ACL | ||||
75 | } | ||||
76 | else { | ||||
77 | 252 | 105µs | if ( ref($param1) eq 'Foswiki::Address' ) { | ||
78 | $meta = | ||||
79 | Foswiki::Meta->load( $session, $param1->web(), $param1->topic() ); | ||||
80 | } | ||||
81 | else { | ||||
82 | 252 | 81µs | $meta = $param1; | ||
83 | } | ||||
84 | } | ||||
85 | ASSERT( $meta->isa('Foswiki::Meta') ) if DEBUG; | ||||
86 | |||||
87 | 252 | 16µs | print STDERR "Check $mode access $cUID to " . $meta->getPath() . "\n" | ||
88 | if MONITOR; | ||||
89 | |||||
90 | # super admin is always allowed | ||||
91 | 252 | 393µs | 252 | 571µs | if ( $session->{users}->isAdmin($cUID) ) { # spent 571µs making 252 calls to Foswiki::Users::isAdmin, avg 2µs/call |
92 | print STDERR "$cUID - ADMIN\n" if MONITOR; | ||||
93 | 252 | 564µs | return 1; | ||
94 | } | ||||
95 | |||||
96 | $mode = uc($mode); | ||||
97 | |||||
98 | my ( $allow, $deny ); | ||||
99 | if ( $meta->{_topic} ) { | ||||
100 | |||||
101 | $allow = $this->_getACL( $meta, 'ALLOWTOPIC' . $mode ); | ||||
102 | $deny = $this->_getACL( $meta, 'DENYTOPIC' . $mode ); | ||||
103 | |||||
104 | # Check DENYTOPIC | ||||
105 | if ( defined($deny) ) { | ||||
106 | if ( scalar(@$deny) != 0 ) { | ||||
107 | if ( $session->{users}->isInUserList( $cUID, $deny ) ) { | ||||
108 | $this->{failure} = | ||||
109 | $session->i18n->maketext('access denied on topic'); | ||||
110 | print STDERR 'a ' . $this->{failure}, "\n" if MONITOR; | ||||
111 | return 0; | ||||
112 | } | ||||
113 | } | ||||
114 | elsif ( $Foswiki::cfg{AccessControlACL}{EnableDeprecatedEmptyDeny} ) | ||||
115 | { | ||||
116 | |||||
117 | # If DENYTOPIC is empty, don't deny _anyone_ | ||||
118 | # DEPRECATED SYNTAX. Recommended replace with "ALLOWTOPIC=*" | ||||
119 | print STDERR "Access allowed: deprecated DENYTOPIC is empty\n" | ||||
120 | if MONITOR; | ||||
121 | return 1; | ||||
122 | } | ||||
123 | } | ||||
124 | |||||
125 | # Check ALLOWTOPIC. If this is defined the user _must_ be in it | ||||
126 | if ( defined($allow) && scalar(@$allow) != 0 ) { | ||||
127 | if ( $session->{users}->isInUserList( $cUID, $allow ) ) { | ||||
128 | print STDERR "in ALLOWTOPIC\n" if MONITOR; | ||||
129 | return 1; | ||||
130 | } | ||||
131 | $this->{failure} = | ||||
132 | $session->i18n->maketext('access not allowed on topic'); | ||||
133 | print STDERR 'b ' . $this->{failure}, "\n" if MONITOR; | ||||
134 | return 0; | ||||
135 | } | ||||
136 | $meta = $meta->getContainer(); # Web | ||||
137 | } | ||||
138 | |||||
139 | if ( $meta->{_web} ) { | ||||
140 | |||||
141 | $deny = $this->_getACL( $meta, 'DENYWEB' . $mode ); | ||||
142 | if ( defined($deny) | ||||
143 | && $session->{users}->isInUserList( $cUID, $deny ) ) | ||||
144 | { | ||||
145 | $this->{failure} = $session->i18n->maketext('access denied on web'); | ||||
146 | print STDERR 'c ' . $this->{failure}, "\n" if MONITOR; | ||||
147 | return 0; | ||||
148 | } | ||||
149 | |||||
150 | # Check ALLOWWEB. If this is defined and not overridden by | ||||
151 | # ALLOWTOPIC, the user _must_ be in it. | ||||
152 | $allow = $this->_getACL( $meta, 'ALLOWWEB' . $mode ); | ||||
153 | |||||
154 | if ( defined($allow) && scalar(@$allow) != 0 ) { | ||||
155 | unless ( $session->{users}->isInUserList( $cUID, $allow ) ) { | ||||
156 | $this->{failure} = | ||||
157 | $session->i18n->maketext('access not allowed on web'); | ||||
158 | print STDERR 'd ' . $this->{failure}, "\n" if MONITOR; | ||||
159 | return 0; | ||||
160 | } | ||||
161 | } | ||||
162 | |||||
163 | } | ||||
164 | else { | ||||
165 | |||||
166 | # No web, we are checking at the root. Check DENYROOT and ALLOWROOT. | ||||
167 | $deny = $this->_getACL( $meta, 'DENYROOT' . $mode ); | ||||
168 | |||||
169 | if ( defined($deny) | ||||
170 | && $session->{users}->isInUserList( $cUID, $deny ) ) | ||||
171 | { | ||||
172 | $this->{failure} = | ||||
173 | $session->i18n->maketext('access denied on root'); | ||||
174 | print STDERR 'e ' . $this->{failure}, "\n" if MONITOR; | ||||
175 | return 0; | ||||
176 | } | ||||
177 | |||||
178 | $allow = $this->_getACL( $meta, 'ALLOWROOT' . $mode ); | ||||
179 | |||||
180 | if ( defined($allow) && scalar(@$allow) != 0 ) { | ||||
181 | unless ( $session->{users}->isInUserList( $cUID, $allow ) ) { | ||||
182 | $this->{failure} = | ||||
183 | $session->i18n->maketext('access not allowed on root'); | ||||
184 | print STDERR 'f ' . $this->{failure}, "\n" if MONITOR; | ||||
185 | return 0; | ||||
186 | } | ||||
187 | } | ||||
188 | } | ||||
189 | |||||
190 | if (MONITOR) { | ||||
191 | print STDERR "OK, permitted\n"; | ||||
192 | print STDERR 'ALLOW: ' . join( ',', @$allow ) . "\n" if defined $allow; | ||||
193 | print STDERR 'DENY: ' . join( ',', @$deny ) . "\n" if defined $deny; | ||||
194 | } | ||||
195 | return 1; | ||||
196 | } | ||||
197 | |||||
198 | # Get an ACL preference. Returns a reference to a list of cUIDs, or undef. | ||||
199 | # If the preference is defined but is empty, then a reference to an | ||||
200 | # empty list is returned. | ||||
201 | # This function canonicalises the parsing of a users list. Is this the right | ||||
202 | # place for it? | ||||
203 | sub _getACL { | ||||
204 | my ( $this, $meta, $mode ) = @_; | ||||
205 | |||||
206 | if ( defined $meta->topic && !defined $meta->getLoadedRev ) { | ||||
207 | |||||
208 | # Lazy load the latest version. | ||||
209 | $meta->loadVersion(); | ||||
210 | } | ||||
211 | |||||
212 | my $text = $meta->getPreference($mode); | ||||
213 | return undef unless defined $text; | ||||
214 | |||||
215 | # Remove HTML tags (compatibility, inherited from Users.pm | ||||
216 | $text =~ s/(<[^>]*>)//g; | ||||
217 | |||||
218 | # Dump the users web specifier if userweb | ||||
219 | my @list = grep { /\S/ } map { | ||||
220 | s/^($Foswiki::cfg{UsersWebName}|%USERSWEB%|%MAINWEB%)\.//; | ||||
221 | $_ | ||||
222 | } split( /[,\s]+/, $text ); | ||||
223 | |||||
224 | #print STDERR "getACL($mode): ".join(', ', @list)."\n"; | ||||
225 | |||||
226 | return \@list; | ||||
227 | } | ||||
228 | |||||
229 | 1 | 3µs | 1; | ||
230 | __END__ |