← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 19:05:14 2015
Reported on Fri Jul 31 19:08:09 2015

Filename/var/www/foswiki11/lib/Foswiki/LoginManager.pm
StatementsExecuted 120 statements in 4.47ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
111590µs812µsFoswiki::LoginManager::::makeLoginManagerFoswiki::LoginManager::makeLoginManager
21186µs673µsFoswiki::LoginManager::::_LOGINFoswiki::LoginManager::_LOGIN
11169µs88µsFoswiki::LoginManager::::newFoswiki::LoginManager::new
11144µs39.0msFoswiki::LoginManager::::loadSessionFoswiki::LoginManager::loadSession
51141µs55µsFoswiki::LoginManager::::endRenderingHandlerFoswiki::LoginManager::endRenderingHandler
11127µs34µsFoswiki::LoginManager::::finishFoswiki::LoginManager::finish
11113µs38.9msFoswiki::LoginManager::::userLoggedInFoswiki::LoginManager::userLoggedIn
11112µs25µsFoswiki::LoginManager::::BEGIN@51Foswiki::LoginManager::BEGIN@51
11112µs17µsFoswiki::LoginManager::::checkAccessFoswiki::LoginManager::checkAccess
11110µs38µsFoswiki::LoginManager::::BEGIN@68Foswiki::LoginManager::BEGIN@68
1118µs14µsFoswiki::LoginManager::::BEGIN@52Foswiki::LoginManager::BEGIN@52
1118µs20µsFoswiki::LoginManager::::BEGIN@53Foswiki::LoginManager::BEGIN@53
1117µs102µsFoswiki::LoginManager::::BEGIN@54Foswiki::LoginManager::BEGIN@54
1117µs7µsFoswiki::LoginManager::::completeFoswiki::LoginManager::complete
1117µs7µsFoswiki::LoginManager::::setSessionValueFoswiki::LoginManager::setSessionValue
1115µs5µsFoswiki::LoginManager::::clearSessionValueFoswiki::LoginManager::clearSessionValue
1114µs4µsFoswiki::LoginManager::::BEGIN@56Foswiki::LoginManager::BEGIN@56
1114µs4µsFoswiki::LoginManager::::getCGISessionFoswiki::LoginManager::getCGISession
3323µs3µsFoswiki::LoginManager::::__ANON__[:225]Foswiki::LoginManager::__ANON__[:225]
0000s0sFoswiki::LoginManager::::_AUTHENTICATEDFoswiki::LoginManager::_AUTHENTICATED
0000s0sFoswiki::LoginManager::::_CANLOGINFoswiki::LoginManager::_CANLOGIN
0000s0sFoswiki::LoginManager::::_IP2SIDFoswiki::LoginManager::_IP2SID
0000s0sFoswiki::LoginManager::::_LOGINURLFoswiki::LoginManager::_LOGINURL
0000s0sFoswiki::LoginManager::::_LOGOUTFoswiki::LoginManager::_LOGOUT
0000s0sFoswiki::LoginManager::::_LOGOUTURLFoswiki::LoginManager::_LOGOUTURL
0000s0sFoswiki::LoginManager::::_SESSION_VARIABLEFoswiki::LoginManager::_SESSION_VARIABLE
0000s0sFoswiki::LoginManager::::_addSessionCookieToResponseFoswiki::LoginManager::_addSessionCookieToResponse
0000s0sFoswiki::LoginManager::::_dispLogonFoswiki::LoginManager::_dispLogon
0000s0sFoswiki::LoginManager::::_myScriptURLREFoswiki::LoginManager::_myScriptURLRE
0000s0sFoswiki::LoginManager::::_real_traceFoswiki::LoginManager::_real_trace
0000s0sFoswiki::LoginManager::::_rewriteFORMFoswiki::LoginManager::_rewriteFORM
0000s0sFoswiki::LoginManager::::_rewriteURLFoswiki::LoginManager::_rewriteURL
0000s0sFoswiki::LoginManager::::_skinSelectFoswiki::LoginManager::_skinSelect
0000s0sFoswiki::LoginManager::::expireDeadSessionsFoswiki::LoginManager::expireDeadSessions
0000s0sFoswiki::LoginManager::::forceAuthenticationFoswiki::LoginManager::forceAuthentication
0000s0sFoswiki::LoginManager::::getSessionValueFoswiki::LoginManager::getSessionValue
0000s0sFoswiki::LoginManager::::getSessionValuesFoswiki::LoginManager::getSessionValues
0000s0sFoswiki::LoginManager::::getUserFoswiki::LoginManager::getUser
0000s0sFoswiki::LoginManager::::isValidLoginNameFoswiki::LoginManager::isValidLoginName
0000s0sFoswiki::LoginManager::::loginUrlFoswiki::LoginManager::loginUrl
0000s0sFoswiki::LoginManager::::redirectToLoggedOutUrlFoswiki::LoginManager::redirectToLoggedOutUrl
0000s0sFoswiki::LoginManager::::rewriteRedirectUrlFoswiki::LoginManager::rewriteRedirectUrl
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# See bottom of file for license and copyright information
2
3=begin TML
4
5---+ package Foswiki::LoginManager
6
7The package is also a Factory for login managers and also the base class
8for all login managers.
9
10On it's own, an object of this class is used when you specify 'none' in
11the security setup section of
12[[%SCRIPTURL{"configure"}%][configure]]. When it is used,
13logins are not supported. If you want to authenticate users then you should
14consider TemplateLogin or ApacheLogin, which are subclasses of this class.
15
16If you are building a new login manager, then you should write a new subclass
17of this class, implementing the methods marked as *VIRTUAL*. There are already
18examples in the =lib/Foswiki/LoginManager= directory.
19
20The class has extensive tracing, which is enabled by
21$Foswiki::cfg{Trace}{LoginManager}. The tracing is done in such a way as to
22let the perl optimiser optimise out the trace function as a no-op if tracing
23is disabled.
24
25Here's an overview of how it works:
26
27Early in Foswiki::new, the login manager is created. The creation of the login manager does two things:
28 1 If sessions are in use, it loads CGI::Session but doesn't initialise the session yet.
29 1 Creates the login manager object
30Slightly later in Foswiki::new, loginManager->loadSession is called.
31 1 Calls loginManager->getUser to get the username *before* the session is created
32 * Foswiki::LoginManager::ApacheLogin looks at REMOTE_USER (only for authenticated scripts)
33 * Foswiki::LoginManager::TemplateLogin just returns undef
34 1 If the NO_FOSWIKI_SESSION environment variable is defined, then no session is created and the username is returned. This might be defined for search engine bots, depending on how the web server is configured
35 1 Reads the FOSWIKISID cookie to get the SID (or the FOSWIKISID parameters in the CGI query if cookies aren't available, or IP2SID mapping if that's enabled).
36 1 Creates the CGI::Session object, and the session is thereby read.
37 1 If the username still isn't known, reads it from the cookie. Thus Foswiki::LoginManager::ApacheLogin overrides the cookie using REMOTE_USER, and Foswiki::LoginManager::TemplateLogin *always* uses the session.
38
39Later again in Foswiki::new, plugins are given a chance to *override* the username found from the loginManager.
40
41The last step in Foswiki::new is to find the user, using whatever user mapping manager is in place.
42
43---++ ObjectData =twiki=
44
45The Foswiki object this login manager is attached to.
46
47=cut
48
49package Foswiki::LoginManager;
50
51225µs238µs
# spent 25µs (12+13) within Foswiki::LoginManager::BEGIN@51 which was called: # once (12µs+13µs) by Foswiki::Users::BEGIN@64 at line 51
use strict;
# spent 25µs making 1 call to Foswiki::LoginManager::BEGIN@51 # spent 13µs making 1 call to strict::import
52222µs219µs
# spent 14µs (8+5) within Foswiki::LoginManager::BEGIN@52 which was called: # once (8µs+5µs) by Foswiki::Users::BEGIN@64 at line 52
use warnings;
# spent 14µs making 1 call to Foswiki::LoginManager::BEGIN@52 # spent 5µs making 1 call to warnings::import
53224µs232µs
# spent 20µs (8+12) within Foswiki::LoginManager::BEGIN@53 which was called: # once (8µs+12µs) by Foswiki::Users::BEGIN@64 at line 53
use Assert;
# spent 20µs making 1 call to Foswiki::LoginManager::BEGIN@53 # spent 12µs making 1 call to Assert::import
54233µs2196µs
# spent 102µs (7+94) within Foswiki::LoginManager::BEGIN@54 which was called: # once (7µs+94µs) by Foswiki::Users::BEGIN@64 at line 54
use Error qw( :try );
# spent 102µs making 1 call to Foswiki::LoginManager::BEGIN@54 # spent 94µs making 1 call to Error::import
55
56287µs14µs
# spent 4µs within Foswiki::LoginManager::BEGIN@56 which was called: # once (4µs+0s) by Foswiki::Users::BEGIN@64 at line 56
use Foswiki::Sandbox ();
# spent 4µs making 1 call to Foswiki::LoginManager::BEGIN@56
57
58# Marker chars
591900nsour $M1 = chr(5);
601300nsour $M2 = chr(6);
611100nsour $M3 = chr(7);
62
63# Some session keys are secret (not to be given to the browser) and
64# others read only (not to be changed from the browser)
6512µsour %secretSK = ( STRIKEONESECRET => 1, VALID_ACTIONS => 1 );
6614µsour %readOnlySK = ( %secretSK, AUTHUSER => 1, SUDOFROMAUTHUSER => 1 );
67
6823.96ms266µs
# spent 38µs (10+28) within Foswiki::LoginManager::BEGIN@68 which was called: # once (10µs+28µs) by Foswiki::Users::BEGIN@64 at line 68
use constant TRACE => $Foswiki::cfg{Trace}{LoginManager} || 0;
# spent 38µs making 1 call to Foswiki::LoginManager::BEGIN@68 # spent 28µs making 1 call to constant::import
69
70=begin TML
71
72---++ StaticMethod makeLoginManager( $session ) -> $Foswiki::LoginManager
73
74Factory method, used to generate a new Foswiki::LoginManager object
75for the given session.
76
77=cut
78
79
# spent 812µs (590+222) within Foswiki::LoginManager::makeLoginManager which was called: # once (590µs+222µs) by Foswiki::Users::new at line 107 of /var/www/foswiki11/lib/Foswiki/Users.pm
sub makeLoginManager {
801800ns my $session = shift;
81
8213µs13µs ASSERT( $session->isa('Foswiki') ) if DEBUG;
# spent 3µs making 1 call to Assert::ASSERTS_OFF
83
84 #user is trying to sudo login - use BaseUserMapping
8514µs125µs if ( $session->{request}->param('sudo') ) {
# spent 25µs making 1 call to Foswiki::Request::param
86
87 #promote / login to internal wiki admin
88 $session->enterContext('sudo_login');
89 }
90
9114µs13µs if ( $Foswiki::cfg{UseClientSessions}
# spent 3µs making 1 call to Foswiki::inContext
92 && !$session->inContext('command_line') )
93 {
94
95 my $sessionname;
96 my $use = 'use Foswiki::LoginManager::Session';
97 if ( $Foswiki::cfg{Sessions}{UseIPMatching} ) {
98 $use .= ' qw(-ip_match)';
99 }
100 $use .= '; use CGI::Cookie ()';
101 eval $use;
102 throw Error::Simple($@) if $@;
103 if ( $session->{request}->https() ) {
104 $sessionname = 'SFOSWIKISID';
105 }
106 else {
107 $sessionname = 'FOSWIKISID';
108 }
109 if ( $Foswiki::LoginManager::Session::VERSION eq '4.10' ) {
110
111 # 4.10 is broken; see Item1989
112 $Foswiki::LoginManager::Session::NAME = $sessionname;
113 }
114 else {
115 Foswiki::LoginManager::Session->name($sessionname);
116 }
117 }
118
1191200ns my $mgr;
12012µs if ( $Foswiki::cfg{LoginManager} eq 'none' ) {
121
122 # No login manager; just use default behaviours
123 $mgr = new Foswiki::LoginManager($session);
124 }
125 else {
126
127 # Rename from old "Client" to new "LoginManager" - see TWikibug:Item3375
12812µs $Foswiki::cfg{LoginManager} =~ s/::Client::/::LoginManager::/;
1291900ns my $loginManager = $Foswiki::cfg{LoginManager};
13011µs12µs if ( $session->inContext('sudo_login') )
# spent 2µs making 1 call to Foswiki::inContext
131 { #TODO: move selection into BaseUserMapper
132 $loginManager = 'Foswiki::LoginManager::TemplateLogin';
133 }
134123µs eval "require $loginManager";
# spent 80µs executing statements in string eval
1351300ns die $@ if $@;
13615µs1120µs $mgr = $loginManager->new($session);
# spent 120µs making 1 call to Foswiki::LoginManager::ApacheLogin::new
137 }
13813µs return $mgr;
139}
140
141=begin TML
142
143---++ ClassMethod new ($session, $impl)
144
145Construct the user management object
146
147=cut
148
149# protected: Construct new client object.
150
# spent 88µs (69+19) within Foswiki::LoginManager::new which was called: # once (69µs+19µs) by Foswiki::LoginManager::ApacheLogin::new at line 41 of /var/www/foswiki11/lib/Foswiki/LoginManager/ApacheLogin.pm
sub new {
15111µs my ( $class, $session ) = @_;
15217µs my $this = bless(
153 {
154 session => $session,
155 twiki => $session, # backwards compatibility
156 _haveCookie => 0,
157 },
158 $class
159 );
160
161 # make sure the filePermission setting has got a sensible default
16212µs $Foswiki::cfg{Session}{filePermission} = 0600
163 unless defined $Foswiki::cfg{Session}{filePermission};
164
16512µs15µs $session->leaveContext('can_login');
# spent 5µs making 1 call to Foswiki::leaveContext
166124µs map { $this->{_authScripts}{$_} = 1; }
167 split( /[\s,]+/, $Foswiki::cfg{AuthScripts} );
168
169#Item 11564: ensure that the user adding the login script to AuthScripts does not result in infinite loops
1701700ns delete $this->{_authScripts}{login};
1711600ns delete $this->{_authScripts}{logon};
172
173 # register tag handlers and values
17412µs13µs Foswiki::registerTagHandler( 'LOGINURL', \&_LOGINURL );
# spent 3µs making 1 call to Foswiki::registerTagHandler
17511µs12µs Foswiki::registerTagHandler( 'LOGIN', \&_LOGIN );
# spent 2µs making 1 call to Foswiki::registerTagHandler
17612µs12µs Foswiki::registerTagHandler( 'LOGOUT', \&_LOGOUT );
# spent 2µs making 1 call to Foswiki::registerTagHandler
17712µs12µs Foswiki::registerTagHandler( 'LOGOUTURL', \&_LOGOUTURL );
# spent 2µs making 1 call to Foswiki::registerTagHandler
17811µs12µs Foswiki::registerTagHandler( 'SESSION_VARIABLE', \&_SESSION_VARIABLE );
# spent 2µs making 1 call to Foswiki::registerTagHandler
17911µs12µs Foswiki::registerTagHandler( 'AUTHENTICATED', \&_AUTHENTICATED );
# spent 2µs making 1 call to Foswiki::registerTagHandler
18012µs12µs Foswiki::registerTagHandler( 'CANLOGIN', \&_CANLOGIN );
# spent 2µs making 1 call to Foswiki::registerTagHandler
181
18214µs return $this;
183}
184
185=begin TML
186
187---++ ObjectMethod finish()
188Break circular references.
189
190=cut
191
192# Note to developers; please undef *all* fields in the object explicitly,
193# whether they are references or not. That way this method is "golden
194# documentation" of the live fields in the object.
195
# spent 34µs (27+7) within Foswiki::LoginManager::finish which was called: # once (27µs+7µs) by Foswiki::Users::finish at line 162 of /var/www/foswiki11/lib/Foswiki/Users.pm
sub finish {
1961500ns my $this = shift;
19718µs17µs $this->complete(); # call to flush the session if not already done
# spent 7µs making 1 call to Foswiki::LoginManager::complete
19818µs undef $this->{_authScripts};
19912µs undef $this->{_cgisession};
2001500ns undef $this->{_haveCookie};
2011800ns undef $this->{_MYSCRIPTURL};
20214µs undef $this->{session};
203}
204
205=begin TML
206
207---++ ClassMethod _real_trace ($session, $impl)
208
209Construct the user management object
210
211=cut
212
213sub _real_trace {
214 my ( $this, $mess ) = @_;
215 my $id =
216 'SESSION ' . ( $this->{_cgisession} ? $this->{_cgisession}->id() : '?' );
217 $id .= '(c)' if $this->{_haveCookie};
218 print STDERR "$id: $mess\n";
219}
220
2211400nsif (TRACE) {
222 *_trace = \&_real_trace;
223}
224else {
225412µs
# spent 3µs within Foswiki::LoginManager::__ANON__[/var/www/foswiki11/lib/Foswiki/LoginManager.pm:225] which was called 3 times, avg 967ns/call: # once (2µs+0s) by Foswiki::LoginManager::loadSession at line 288 # once (700ns+0s) by Foswiki::LoginManager::ApacheLogin::getUser at line 145 of /var/www/foswiki11/lib/Foswiki/LoginManager/ApacheLogin.pm # once (600ns+0s) by Foswiki::LoginManager::loadSession at line 297
*_trace = sub { undef };
226}
227
228=begin TML
229
230---++ ClassMethod _IP2SID ($session, $impl)
231
232 read/write IP to SID map, return SID
233
234=cut
235
236sub _IP2SID {
237 my ( $this, $sid ) = @_;
238
239 my $ip = $this->{session}->{request}->address;
240
241 return unless $ip; # no IP address, can't map
242
243 my %ips;
244 my $IPMAP;
245 if ( open( $IPMAP, '<', $Foswiki::cfg{WorkingDir} . '/tmp/ip2sid' ) ) {
246 local $/ = undef;
247 %ips = map { split( /:/, $_ ) } split( /\r?\n/, <$IPMAP> );
248 close($IPMAP);
249 }
250 if ($sid) {
251
252 # known SID, map the IP addr to it
253 $ips{$ip} = $sid;
254 open( $IPMAP, '>', $Foswiki::cfg{WorkingDir} . '/tmp/ip2sid' )
255 || die
256"Failed to open ip2sid map for write. Ask your administrator to make sure that the {Sessions}{Dir} is writable by the webserver user.";
257 print $IPMAP map { "$_:$ips{$_}\n" } keys %ips;
258 close($IPMAP);
259 }
260 else {
261
262 # Return the SID for this IP address
263 $sid = $ips{$ip};
264 }
265 return $sid;
266}
267
268=begin TML
269
270---++ ObjectMethod loadSession($defaultUser, $pwchecker) -> $login
271
272Get the client session data, using the cookie and/or the request URL.
273Set up appropriate session variables in the session object and return
274the login name.
275
276$pwchecker is a pointer to an object that implements checkPassword
277
278$defaultUser is a username to use if one is not available from other
279sources. The username passed when you create a Foswiki instance is
280passed in here.
281
282=cut
283
284
# spent 39.0ms (44µs+38.9) within Foswiki::LoginManager::loadSession which was called: # once (44µs+38.9ms) by Foswiki::Users::loadSession at line 144 of /var/www/foswiki11/lib/Foswiki/Users.pm
sub loadSession {
28511µs my ( $this, $defaultUser, $pwchecker ) = @_;
2861800ns my $session = $this->{session};
287
28812µs12µs _trace( $this, "loadSession\n" );
289
2901400ns $defaultUser = $Foswiki::cfg{DefaultUserLogin}
291 unless ( defined($defaultUser) );
292
293 # Try and get the user from the webserver. This is referred to as
294 # the "webserver user". the webserver user is authenticated by some
295 # means beyond foswiki e.g. Basic Auth
29612µs113µs my $authUser = $this->getUser($this);
# spent 13µs making 1 call to Foswiki::LoginManager::ApacheLogin::getUser
29712µs1600ns _trace( $this, "Webserver says user is $authUser" ) if ($authUser);
298
299 # If the NO_FOSWIKI_SESSION environment variable is defined, then
300 # do not create the session. This might be defined if the request
301 # is made by a search engine bot, depending on how the web server
302 # is configured
303
3041900ns return $authUser if $ENV{NO_FOSWIKI_SESSION};
305
30612µs12µs if ( $Foswiki::cfg{UseClientSessions}
# spent 2µs making 1 call to Foswiki::inContext
307 && !$session->inContext('command_line') )
308 {
309
310 $this->{_haveCookie} = $session->{request}->header('Cookie');
311
312 _trace( $this,
313 $this->{_haveCookie}
314 ? "Cookie $this->{_haveCookie}"
315 : "No cookie " );
316
317 # Item3568: CGI::Session from 4.0 already does the -d and creates the
318 # sessions directory if it does not exist. For performance reasons we
319 # only test for and create session file directory for older
320 # CGI::Session
321 my $sessionDir = "$Foswiki::cfg{WorkingDir}/tmp";
322 if ( $Foswiki::LoginManager::Session::VERSION < 4.0 ) {
323 unless (
324 -d $sessionDir
325 || ( mkdir( $Foswiki::cfg{WorkingDir} )
326 && mkdir($sessionDir) )
327 )
328 {
329 die "Could not create $sessionDir for storing sessions";
330 }
331 }
332
333 # force an appropriate umask
334 my $oldUmask =
335 umask(
336 oct(777) - ( ( $Foswiki::cfg{Session}{filePermission} + 0 ) ) &
337 oct(777) );
338
339 #my $umask = sprintf('%04o', umask() );
340 #$oldUmask = sprintf('%04o', $oldUmask );
341 #my $filePerm = sprintf('%04o', $Foswiki::cfg{Session}{filePermission}+0 );
342 #print STDERR "login manager changes $oldUmask to $umask from $filePerm\n";
343
344 # First, see if there is a cookied session, creating a new session
345 # if necessary.
346 if ( $Foswiki::cfg{Sessions}{MapIP2SID} ) {
347
348 # map the end user IP address to a session ID
349
350 my $sid = $this->_IP2SID();
351 if ($sid) {
352 $this->{_cgisession} = Foswiki::LoginManager::Session->new(
353 undef, $sid,
354 {
355 Directory => $sessionDir,
356 UMask => $Foswiki::cfg{Session}{filePermission}
357 }
358 );
359 }
360 else {
361
362 # The IP address was not mapped; create a new session
363
364 $this->{_cgisession} = Foswiki::LoginManager::Session->new(
365 undef, undef,
366 {
367 Directory => $sessionDir,
368 UMask => $Foswiki::cfg{Session}{filePermission}
369 }
370 );
371 _trace( $this, "New IP2SID session" );
372 $this->_IP2SID( $this->{_cgisession}->id() );
373 }
374 }
375 else {
376
377 # IP mapping is off; use the request cookie
378
379 $this->{_cgisession} = Foswiki::LoginManager::Session->new(
380 undef,
381 $session->{request},
382 {
383 Directory => $sessionDir,
384 UMask => $Foswiki::cfg{Session}{filePermission}
385 }
386 );
387 }
388
389 # restore old umask
390 umask($oldUmask);
391
392 die Foswiki::LoginManager::Session->errstr()
393 unless $this->{_cgisession};
394
395 # Get the authorised user stored in the session
396
397 my $sessionUser = Foswiki::Sandbox::untaintUnchecked(
398 $this->{_cgisession}->param('AUTHUSER') );
399
400 _trace( $this, "AUTHUSER is $sessionUser" ) if defined $sessionUser;
401
402 # An admin user stored in the session can override the webserver
403 # user; handy for sudo
404
405 $authUser = $sessionUser
406 if ( !defined($authUser)
407 || $sessionUser && $sessionUser eq $Foswiki::cfg{AdminUserLogin} );
408 }
4091500ns if ( !$authUser ) {
410
411 # if we couldn't get the login manager or the http session to tell
412 # us who the user is, check the username and password URI params.
413 #
414 # Note that this code only applies to scripts other than login.
415 # The login script is handled separately.
416
417 my $script = $session->{request}->base_action();
418
419 my $login;
420 my $pass;
421
422 if ( defined $Foswiki::cfg{Session}{AcceptUserPwParam}
423 && $script =~ m/$Foswiki::cfg{Session}{AcceptUserPwParam}/ )
424 {
425 if (
426 $Foswiki::cfg{Session}{AcceptUserPwParamOnGET}
427 || ( defined $session->{request}->method()
428 && uc( $session->{request}->method() ) eq 'POST' )
429 )
430 {
431 $login = $session->{request}->param('username');
432 $pass = $session->{request}->param('password');
433 $session->{request}->delete( 'username', 'password' );
434 }
435 }
436
437 if ( $login && defined $pass && $pwchecker ) {
438 my $validation = $pwchecker->checkPassword( $login, $pass );
439 unless ($validation) {
440 my $res = $session->{response};
441 my $err = "ERROR: (401) Can't login as $login";
442
443 # Item1953: You might think that this is needed:
444 # $res->header( -type => 'text/html', -status => '401' );
445 # throw Foswiki::EngineException( 401, $err, $res );
446 # but it would be wrong, because it would require the
447 # exception to be handled before the session object is
448 # properly initialised, which would cause an error.
449 # Instead, we do this, and let the caller handle the error.
450 undef $login;
451 }
452 $authUser = $login || $defaultUser;
453 _trace( $this, "URI params say user is $authUser" );
454 }
455 else {
456
457 # Last ditch attempt; if a user was passed in to this function,
458 # then use it (it is normally {remoteUser} from the session
459 # object)
460 $authUser = $defaultUser;
461 _trace( $this, "Falling back to $authUser" ) if $authUser;
462
463 }
464 }
465
466 # We should have a user at this point; or $defaultUser if there
467 # was no better information available.
468
469 # is this a logout?
47013µs115µs if ( ( $authUser && $authUser ne $Foswiki::cfg{DefaultUserLogin} )
# spent 15µs making 1 call to Foswiki::Request::param
471 && ( $session->{request} && $session->{request}->param('logout') ) )
472 {
473
474 # SMELL: is there any way to get evil data into the CGI session such
475 # that this untaint is less than safe?
476 my $sudoUser = Foswiki::Sandbox::untaintUnchecked(
477 $this->{_cgisession}->param('SUDOFROMAUTHUSER') );
478
479 if ($sudoUser) {
480 _trace( $this, "User is logging out to $sudoUser" );
481 $session->logEvent( 'sudo logout', '',
482 'from ' . ( $authUser || '' ), $sudoUser );
483 $this->{_cgisession}->clear('SUDOFROMAUTHUSER');
484 $authUser = $sudoUser;
485 }
486 else {
487 $authUser =
488 $this->redirectToLoggedOutUrl( $authUser, $defaultUser );
489 }
490 }
49114µs16µs $session->{request}->delete('logout');
# spent 6µs making 1 call to Foswiki::Request::delete
492
49315µs138.9ms $this->userLoggedIn($authUser);
# spent 38.9ms making 1 call to Foswiki::LoginManager::userLoggedIn
494
49511µs if ( $this->{_cgisession} ) {
496 $session->{prefs}->setInternalPreferences(
497 SESSIONID => $this->{_cgisession}->id(),
498 SESSIONVAR => $CGI::Session::NAME
499 );
500
501 # Restore CGI Session parameters
502 for ( $this->{_cgisession}->param ) {
503 my $value = $this->{_cgisession}->param($_);
504 $session->{prefs}->setInternalPreferences( $_ => $value );
505 $this->_trace( "Setting internal preference $_ to "
506 . ( $value ? $value : 'null' ) );
507 }
508
509 # May end up doing this several times; but this is the only place
510 # if should really need to be done, unless someone allocates a
511 # new response object.
512 $this->_addSessionCookieToResponse();
513 }
514
51513µs return $authUser;
516}
517
518=begin TML
519
520---++ ObjectMethod redirectToLoggedOutUrl($authUser, $defaultUser)
521
522Helper method, called by loadSession, to redirect to the non-authenticated url and return the non-authenticated "default user" login name.
523
524$authUser is the currently logged in user, derived from the request's username.
525
526$defaultUser is a username to use if one is not available from other
527sources. The username passed when you create a Foswiki instance is
528passed in here.
529
530=cut
531
532sub redirectToLoggedOutUrl {
533 my ( $this, $authUser, $defaultUser ) = @_;
534 _trace( $this, "User is logging out" );
535
536 my $session = $this->{session};
537 $defaultUser = $Foswiki::cfg{DefaultUserLogin}
538 unless ( defined($defaultUser) );
539
540 $session->logEvent( 'logout', ' ', "AUTHENTICATION LOGOUT - $authUser - " );
541
542 #TODO: consider if we should risk passing on the urlparams on logout
543 my $path_info = $session->{request}->path_info();
544 if ( my $topic = $session->{request}->param('topic') )
545 { #we should at least respect the ?topic= request
546 my $topicRequest = Foswiki::Sandbox::untaintUnchecked(
547 $session->{request}->param('topic') );
548 my ( $web, $topic ) =
549 $this->{session}->normalizeWebTopicName( undef, $topicRequest );
550 $path_info = '/' . $web . '/' . $topic;
551 }
552
553 if ( $path_info =~ m/['"]/ ) {
554 $path_info = substr( $path_info, 0, ( ( pos $path_info ) - 1 ) );
555 }
556
557 my $redirectUrl;
558 if ($path_info) {
559 $redirectUrl = $session->{request}->url() . $path_info;
560 }
561 else {
562 $redirectUrl = $session->{request}->referer();
563 }
564
565 #lets avoid infinite loops
566 $session->{request}->delete('logout');
567 $authUser = $defaultUser;
568 $session->redirect( $redirectUrl, 0 );
569
570 return $authUser;
571}
572
573=begin TML
574
575---++ ObjectMethod checkAccess()
576
577Check if the script being run in this session is authorised for execution.
578If not, throw an access control exception.
579
580=cut
581
582
# spent 17µs (12+6) within Foswiki::LoginManager::checkAccess which was called: # once (12µs+6µs) by Foswiki::UI::__ANON__[/var/www/foswiki11/lib/Foswiki/UI.pm:318] at line 315 of /var/www/foswiki11/lib/Foswiki/UI.pm
sub checkAccess {
583
58411µs return unless ( $Foswiki::cfg{UseClientSessions} );
585
5861400ns my $this = shift;
5871900ns my $session = $this->{session};
588
58918µs16µs return if $session->inContext('command_line');
# spent 6µs making 1 call to Foswiki::inContext
590
591 unless ( $session->inContext('authenticated')
592 || $Foswiki::cfg{LoginManager} eq 'none' )
593 {
594
595 # This checks the *base_action* which is the action in the
596 # request *before* any request cache was restored. Otherwise
597 # you can end up with an infinite loop - see
598 # Foswiki:Development.FoswikiRedirectCache
599 my $action = $session->{request}->base_action();
600
601 if ( defined $action && $this->{_authScripts}{$action} ) {
602 my $topic = $session->{topicName};
603 my $web = $session->{webName};
604 require Foswiki::AccessControlException;
605 throw Foswiki::AccessControlException( $action, $session->{user},
606 $web, $topic, $action . ' requires authentication' );
607 }
608 }
609}
610
611=begin TML
612
613---++ ObjectMethod complete()
614
615Complete processing after the client's HTTP request has been responded
616to. Flush the user's session (if any) to disk.
617
618=cut
619
620
# spent 7µs within Foswiki::LoginManager::complete which was called: # once (7µs+0s) by Foswiki::LoginManager::finish at line 197
sub complete {
6211800ns my $this = shift;
622
6231700ns if ( $this->{_cgisession} ) {
624 $this->{_cgisession}->flush();
625 die $this->{_cgisession}->errstr()
626 if $this->{_cgisession}->errstr();
627 }
628
629110µs return unless ( $Foswiki::cfg{Sessions}{ExpireAfter} > 0 );
630
631 expireDeadSessions();
632}
633
634=begin TML
635
636---++ StaticMethod expireDeadSessions()
637
638Delete sessions and passthrough files that are sitting around but are really expired.
639This *assumes* that the sessions are stored as files.
640
641This is a static method, but requires Foswiki::cfg. It is designed to be
642run from a session or from a cron job.
643
644=cut
645
646sub expireDeadSessions {
647 my $time = time() || 0;
648 my $exp = $Foswiki::cfg{Sessions}{ExpireAfter} || 36000; # 10 hours
649 $exp = -$exp if $exp < 0;
650
651 opendir( D, "$Foswiki::cfg{WorkingDir}/tmp" ) || return;
652 foreach my $file ( readdir(D) ) {
653
654 # Validate
655 next unless $file =~ /^((passthru|cgisess)_[0-9a-f]{32})$/;
656 $file = $1; # untaint validated file name
657
658 my @stat = stat("$Foswiki::cfg{WorkingDir}/tmp/$file");
659
660 # CGI::Session updates the session file each time a browser views a
661 # topic setting the access and expiry time as values in the file. This
662 # also sets the mtime (modification time) for the file which is all
663 # we need. We know that the expiry time is mtime +
664 # $Foswiki::cfg{Sessions}{ExpireAfter} so we do not need to waste
665 # execution time opening and reading the file. We just check the
666 # mtime. As a fallback we also check ctime. Files are deleted when
667 # they expire.
668 my $lat = $stat[9] || $stat[10] || 0;
669 unlink "$Foswiki::cfg{WorkingDir}/tmp/$file"
670 if ( $time - $lat >= $exp );
671 next;
672 }
673 closedir D;
674}
675
676=begin TML
677
678---++ ObjectMethod userLoggedIn( $login, $wikiname)
679
680Called when the user is known. It's invoked from Foswiki::UI::Register::finish
681for instance,
682 1 when the user follows the link in their verification email message
683 2 or when the session store is read
684 3 when the user authenticates (via templatelogin / sudo)
685
686 * =$login= - string login name
687 * =$wikiname= - string wikiname
688
689=cut
690
691
# spent 38.9ms (13µs+38.9) within Foswiki::LoginManager::userLoggedIn which was called: # once (13µs+38.9ms) by Foswiki::LoginManager::loadSession at line 493
sub userLoggedIn {
69211µs my ( $this, $authUser, $wikiName ) = @_;
693
6941800ns my $session = $this->{session};
69514µs138.9ms if ( $session->{users} ) {
# spent 38.9ms making 1 call to Foswiki::Users::getCanonicalUserID
696 $session->{user} = $session->{users}->getCanonicalUserID($authUser);
697 }
698 return
69916µs12µs if $session->inContext('command_line')
# spent 2µs making 1 call to Foswiki::inContext
700 || $session->{remoteUser}
701 && $authUser
702 && $authUser eq $session->{remoteUser}; # same user
703
704 if ( $Foswiki::cfg{UseClientSessions} ) {
705
706 # create new session if necessary
707 unless ( $this->{_cgisession} ) {
708
709 # force an appropriate umask
710 my $oldUmask =
711 umask(
712 oct(777) - ( ( $Foswiki::cfg{Session}{filePermission} + 0 ) ) &
713 oct(777) );
714
715 $this->{_cgisession} = Foswiki::LoginManager::Session->new(
716 undef,
717 $session->{request},
718 {
719 Directory => "$Foswiki::cfg{WorkingDir}/tmp",
720 UMask => $Foswiki::cfg{Session}{filePermission}
721 }
722 );
723
724 # restore old umask
725 umask($oldUmask);
726
727 die Foswiki::LoginManager::Session->errstr()
728 unless $this->{_cgisession};
729 }
730 }
731 if ( $authUser && $authUser ne $Foswiki::cfg{DefaultUserLogin} ) {
732 _trace( $this,
733 'Authenticated; converting from '
734 . ( $session->{remoteUser} || 'undef' ) . ' to '
735 . $authUser );
736
737 # SMELL: right now anyone that makes a template login url can log
738 # in multiple times - should i forbid it
739 if ( $Foswiki::cfg{UseClientSessions} ) {
740 if ( defined( $session->{remoteUser} )
741 && $session->inContext('sudo_login') )
742 {
743 $session->logEvent( 'sudo login', '',
744 'from ' . ( $session->{remoteUser} || '' ), $authUser );
745 $this->{_cgisession}
746 ->param( 'SUDOFROMAUTHUSER', $session->{remoteUser} );
747 }
748
749 # SMELL: these are bare logins, so if and when there are
750 # multiple usermappings, this would need to include cUID..
751 $this->{_cgisession}->param( 'AUTHUSER', $authUser );
752 }
753 $session->enterContext('authenticated');
754 }
755 else {
756 _trace( $this, "Session is NOT authenticated" );
757
758 # if we are not authenticated, expire any existing session
759 $this->{_cgisession}->clear( ['AUTHUSER'] )
760 if ( $Foswiki::cfg{UseClientSessions} );
761 $session->leaveContext('authenticated');
762 }
763 if ( $Foswiki::cfg{UseClientSessions} ) {
764
765 # flush the session, to try to fix Item1820 and Item2234
766 $this->{_cgisession}->flush();
767 die $this->{_cgisession}->errstr() if $this->{_cgisession}->errstr();
768 }
769}
770
771=begin TML
772
773---++ ObjectMethod _myScriptURLRE ($thisl)
774
- -
777=cut
778
779# get an RE that matches a local script URL
780sub _myScriptURLRE {
781 my $this = shift;
782
783 my $s = $this->{_MYSCRIPTURL};
784 unless ($s) {
785 $s = quotemeta( $this->{session}->getScriptUrl( 1, $M1, $M2, $M3 ) );
786 $s =~ s@\\$M1@[^/]*?@go;
787 $s =~ s@\\$M2@[^/]*?@go;
788 $s =~ s@\\$M3@[^#\?/]*@go;
789
790 # now add alternates for the various script-specific overrides
791 foreach my $v ( values %{ $Foswiki::cfg{ScriptUrlPaths} } ) {
792 my $over = $v;
793
794 # escape non-alphabetics
795 $over =~ s/(\W)/\\$1/g;
796 $s .= '|' . $over;
797 }
798 $this->{_MYSCRIPTURL} = "($s)";
799 }
800 return $s;
801}
802
803=begin TML
804
805---++ ObjectMethod _rewriteURL ($this, $url) -> $url
806
807=cut
808
809# Rewrite a URL inserting the session id
810sub _rewriteURL {
811 my ( $this, $url ) = @_;
812
813 return $url unless $url;
814
815 my $sessionId = $this->{_cgisession}->id();
816 return $url unless $sessionId;
817 return $url if $url =~ m/\?$Foswiki::LoginManager::Session::NAME=/;
818
819 my $s = _myScriptURLRE($this);
820
821 # If the URL has no colon in it, or it matches the local script
822 # URL, it must be an internal URL and therefore needs the session.
823 if ( $url !~ /:/ || $url =~ /^$s/ ) {
824
825 # strip off the anchor
826 my $anchor = '';
827 if ( $url =~ s/(#.*)// ) {
828 $anchor = $1;
829 }
830
831 # strip off existing params
832 my $params = "?$Foswiki::LoginManager::Session::NAME=$sessionId";
833
834 # implicit untaint is OK because recombined with url later
835 if ( $url =~ s/\?(.*)$// ) {
836 $params .= ';' . $1;
837 }
838
839 # rebuild the URL
840 $url .= $params . $anchor;
841 } # otherwise leave it untouched
842
843 return $url;
844}
845
846=begin TML
847
848---++ ObjectMethod _rewriteFORM ($thisl)
849
850
851=cut
852
853# Catch all FORMs and add a hidden Session ID variable.
854# Only do this if the form is pointing to an internal link.
855# This occurs if there are no colons in its target, if it has
856# no target, or if its target matches a getScriptUrl URL.
857# '$rest' is the bit of the initial form tag up to the closing >
858sub _rewriteFORM {
859 my ( $this, $url, $rest ) = @_;
860
861 return $url . $rest unless $this->{_cgisession};
862
863 my $s = _myScriptURLRE($this);
864
865 if ( $url !~ /:/ || $url =~ /^($s)/ ) {
866 $rest .= CGI::hidden(
867 -name => $Foswiki::LoginManager::Session::NAME,
868 -value => $this->{_cgisession}->id()
869 );
870 }
871 return $url . $rest;
872}
873
874=begin TML
875
876---++ ObjectMethod endRenderingHandler()
877
878This handler is called by getRenderedVersion just before the plugins
879postRenderingHandler. So it is passed all HTML text just before it is
880printed.
881
882*DEPRECATED* Use postRenderingHandler instead.
883
884=cut
885
886
# spent 55µs (41+14) within Foswiki::LoginManager::endRenderingHandler which was called 5 times, avg 11µs/call: # 5 times (41µs+14µs) by Foswiki::Render::getRenderedVersion at line 1464 of /var/www/foswiki11/lib/Foswiki/Render.pm, avg 11µs/call
sub endRenderingHandler {
88756µs return unless ( $Foswiki::cfg{UseClientSessions} );
888
88952µs my $this = shift;
890523µs514µs return if $this->{session}->inContext('command_line');
# spent 14µs making 5 calls to Foswiki::inContext, avg 3µs/call
891
892 # If cookies are not turned on and transparent CGI session IDs are,
893 # grab every URL that is an internal link and pass a CGI variable
894 # with the session ID
895 unless ( $this->{_haveCookie} || !$Foswiki::cfg{Sessions}{IDsInURLs} ) {
896
897 # rewrite internal links to include the transparent session ID
898 # Doesn't catch Javascript, because there are just so many ways
899 # to generate links from JS.
900 # SMELL: this would probably be done better using javascript
901 # that handles navigation away from this page, and uses the
902 # rules to rewrite any relative URLs at that time.
903
904 # a href= rewriting
905 $_[0] =~
906s/(<a[^>]*(?<=\s)href=(["']))(.*?)(\2)/$1.$this->_rewriteURL($3).$4/geoi;
907
908 # form action= rewriting
909 # SMELL: Forms that have no target are also implicit internal
910 # links, but are not handled. Does this matter>
911 $_[0] =~
912s/(<form[^>]*(?<=\s)(?:action)=(["']))(.*?)(\2[^>]*>)/$1._rewriteFORM( $this,$3, $4)/geoi;
913 }
914
915 # And, finally, the logon stuff
916 $_[0] =~ s/%SESSIONLOGON%/_dispLogon( $this )/geo;
917 $_[0] =~ s/%SKINSELECT%/_skinSelect( $this )/geo;
918}
919
920sub _addSessionCookieToResponse {
921 my $this = shift;
922
923 my $cookie = CGI::Cookie->new(
924 -name => $Foswiki::LoginManager::Session::NAME,
925 -value => $this->{_cgisession}->id(),
926 -path => '/',
927 -domain => $Foswiki::cfg{Sessions}{CookieRealm} || '',
928 -httponly => 1,
929 -secure => $this->{session}->{request}->secure,
930 );
931
932 # An expiry time is only set if the session has the REMEMBER variable
933 # in it. This is to prevent accidentally remembering cookies with
934 # login managers where the authority is cached in the browser and
935 # *not* in the session. Otherwise another user might be able to login
936 # on the same machine and inherit the authorities of a prior user.
937 if ( $Foswiki::cfg{Sessions}{ExpireCookiesAfter}
938 && $this->getSessionValue('REMEMBER') )
939 {
940 require Foswiki::Time;
941 my $exp = Foswiki::Time::formatTime(
942 time() + $Foswiki::cfg{Sessions}{ExpireCookiesAfter},
943 '$wday, $day-$month-$ye $hours:$minutes:$seconds GMT'
944 );
945
946 $cookie->expires($exp);
947 }
948
949 $this->{session}->{response}->cookies( [$cookie] );
950}
951
952=begin TML
953
954---++ ObjectMethod rewriteRedirectUrl( $url ) ->$url
955
956Rewrite the URL used in a redirect if necessary to include any session
957identification.
958 * =$url= - target of the redirection.
959
960=cut
961
962sub rewriteRedirectUrl {
963
964 my ( $this, $url ) = @_;
965
966 return $url unless $this->{_cgisession};
967
968 if ( $Foswiki::cfg{Sessions}{IDsInURLs} && !$this->{_haveCookie} ) {
969 $url = _rewriteURL( $this, $url );
970 }
971
972 # This usually won't be important, but just in case they haven't
973 # yet received the cookie and happen to be redirecting, be sure
974 # they do have the cookie.
975 $this->_addSessionCookieToResponse();
976
977 return $url;
978}
979
980=begin TML
981
982---++ ObjectMethod getSessionValues() -> \%values
983
984Get a name->value hash of all the defined session variables
985
986=cut
987
988sub getSessionValues {
989 my ($this) = @_;
990
991 return unless $this->{_cgisession};
992
993 return $this->{_cgisession}->param_hashref();
994}
995
996=begin TML
997
998---++ ObjectMethod getCGISession()
999Get the currect CGI session object
1000
1001=cut
1002
1003
# spent 4µs within Foswiki::LoginManager::getCGISession which was called: # once (4µs+0s) by Foswiki::Users::getCGISession at line 421 of /var/www/foswiki11/lib/Foswiki/Users.pm
sub getCGISession {
10041700ns my $this = shift;
100519µs return $this->{_cgisession};
1006}
1007
1008=begin TML
1009
1010---++ ObjectMethod getSessionValue( $name ) -> $value
1011
1012Get the value of a session variable.
1013
1014=cut
1015
1016sub getSessionValue {
1017 my ( $this, $key ) = @_;
1018 return unless $this->{_cgisession};
1019
1020 return $this->{_cgisession}->param($key);
1021}
1022
1023=begin TML
1024
1025---++ ObjectMethod setSessionValue( $name, $value )
1026
1027Set the value of a session variable.
1028
1029=cut
1030
1031
# spent 7µs within Foswiki::LoginManager::setSessionValue which was called: # once (7µs+0s) by Foswiki::Func::setSessionValue at line 377 of /var/www/foswiki11/lib/Foswiki/Func.pm
sub setSessionValue {
103212µs my ( $this, $key, $value ) = @_;
1033
10341700ns if ( $this->{_cgisession}
1035 && defined( $this->{_cgisession}->param( $key, $value ) ) )
1036 {
1037 return 1;
1038 }
1039
104015µs return;
1041}
1042
1043=begin TML
1044
1045---++ ObjectMethod clearSessionValue( $name ) -> $boolean
1046
1047Clear the value of a session variable.
1048We do not allow setting of AUTHUSER.
1049
1050=cut
1051
1052
# spent 5µs within Foswiki::LoginManager::clearSessionValue which was called: # once (5µs+0s) by Foswiki::Func::clearSessionValue at line 394 of /var/www/foswiki11/lib/Foswiki/Func.pm
sub clearSessionValue {
105312µs my ( $this, $key ) = @_;
1054
1055 # We do not allow clearing of AUTHUSER.
10561900ns if ( $this->{_cgisession}
1057 && $key ne 'AUTHUSER'
1058 && defined( $this->{_cgisession}->param($key) ) )
1059 {
1060 $this->{_cgisession}->clear( [ $_[1] ] );
1061
1062 return 1;
1063 }
1064
106515µs return;
1066}
1067
1068=begin TML
1069
1070---++ ObjectMethod forceAuthentication() -> boolean
1071
1072*VIRTUAL METHOD* implemented by subclasses
1073
1074Triggered by an access control violation, this method tests
1075to see if the current session is authenticated or not. If not,
1076it does whatever is needed so that the user can log in, and returns 1.
1077
1078If the user has an existing authenticated session, the function simply drops
1079though and returns 0.
1080
1081=cut
1082
1083sub forceAuthentication {
1084 return 0;
1085}
1086
1087=begin TML
1088
1089---++ ObjectMethod loginUrl( ... ) -> $url
1090
1091*VIRTUAL METHOD* implemented by subclasses
1092
1093Return a full URL suitable for logging in.
1094 * =...= - url parameters to be added to the URL, in the format required by Foswiki::getScriptUrl()
1095
1096=cut
1097
1098sub loginUrl {
1099 return '';
1100}
1101
1102=begin TML
1103
1104---++ ObjectMethod getUser()
1105
1106Should be implemented by subclasses
1107
1108If there is some other means of getting a username - for example,
1109Apache has remote_user() - then return it. Otherwise, return undef and
1110the username stored in the session will be used.
1111
1112This method of getting the user *assumes* that the identified user
1113has been authenticated in some way (for example, by the web server)
1114
1115=cut
1116
1117sub getUser {
1118 return;
1119}
1120
1121=begin TML
1122
1123---++ ObjectMethod isValidLoginName( $name ) -> $boolean
1124
1125Check for a valid login name (not an existance check, just syntax).
1126Default behaviour is to check the login name against
1127$Foswiki::cfg{LoginNameFilterIn}
1128
1129=cut
1130
1131sub isValidLoginName {
1132 my ( $this, $name ) = @_;
1133
1134 # this function was erroneously marked as static
1135 ASSERT( !ref($name) ) if DEBUG;
1136 return $name =~ /$Foswiki::cfg{LoginNameFilterIn}/;
1137}
1138
1139=begin TML
1140
1141---++ ObjectMethod _LOGIN ($thisl)
1142
1143
1144=cut
1145
1146
# spent 673µs (86+587) within Foswiki::LoginManager::_LOGIN which was called 2 times, avg 337µs/call: # 2 times (86µs+587µs) by Foswiki::_expandMacroOnTopicRendering at line 3160 of /var/www/foswiki11/lib/Foswiki.pm, avg 337µs/call
sub _LOGIN {
1147
1148 #my( $session, $params, $topic, $web ) = @_;
114921µs my $session = shift;
115027µs224µs my $this = $session->getLoginManager();
# spent 24µs making 2 calls to Foswiki::getLoginManager, avg 12µs/call
1151
115224µs26µs return '' if $session->inContext('authenticated');
# spent 6µs making 2 calls to Foswiki::inContext, avg 3µs/call
1153
115427µs2169µs my $url = $this->loginUrl();
# spent 169µs making 2 calls to Foswiki::LoginManager::ApacheLogin::loginUrl, avg 85µs/call
11552800ns if ($url) {
1156214µs4222µs my $text = $session->templates->expandTemplate('LOG_IN');
# spent 212µs making 2 calls to Foswiki::Templates::expandTemplate, avg 106µs/call # spent 10µs making 2 calls to Foswiki::templates, avg 5µs/call
1157222µs2167µs return CGI::a( { href => $url }, $text );
# spent 167µs making 2 calls to CGI::a, avg 83µs/call
1158 }
1159 return '';
1160}
1161
1162=begin TML
1163
1164---++ ObjectMethod _LOGOUTURL ($thisl)
1165
1166
1167=cut
1168
1169sub _LOGOUTURL {
1170 my ( $session, $params, $topic, $web ) = @_;
1171 my $this = $session->getLoginManager();
1172
1173 return $session->getScriptUrl(
1174 0, 'view',
1175 $session->{prefs}->getPreference('BASEWEB'),
1176 $session->{prefs}->getPreference('BASETOPIC'),
1177 'logout' => 1
1178 );
1179}
1180
1181=begin TML
1182
1183---++ ObjectMethod _LOGOUT ($thisl)
1184
1185
1186=cut
1187
1188sub _LOGOUT {
1189 my ( $session, $params, $topic, $web ) = @_;
1190 my $this = $session->getLoginManager();
1191
1192 return '' unless $session->inContext('authenticated');
1193
1194 my $url = _LOGOUTURL(@_);
1195 if ($url) {
1196 my $text = $session->templates->expandTemplate('LOG_OUT');
1197 return CGI::a( { href => $url }, $text );
1198 }
1199 return '';
1200}
1201
1202=begin TML
1203
1204---++ ObjectMethod _AUTHENTICATED ($thisl)
1205
1206
1207=cut
1208
1209sub _AUTHENTICATED {
1210 my ( $session, $params ) = @_;
1211 my $this = $session->getLoginManager();
1212
1213 if ( $session->inContext('authenticated') ) {
1214 return $params->{then} || 1;
1215 }
1216 else {
1217 return $params->{else} || 0;
1218 }
1219}
1220
1221=begin TML
1222
1223---++ ObjectMethod _CANLOGIN ($thisl)
1224
1225=cut
1226
1227sub _CANLOGIN {
1228 my ( $session, $params ) = @_;
1229 my $this = $session->getLoginManager();
1230 if ( $session->inContext('can_login') ) {
1231 return $params->{then} || 1;
1232 }
1233 else {
1234 return $params->{else} || 0;
1235 }
1236}
1237
1238=begin TML
1239
1240---++ ObjectMethod _SESSION_VARIABLE ($thisl)
1241
1242=cut
1243
1244sub _SESSION_VARIABLE {
1245 my ( $session, $params ) = @_;
1246 my $this = $session->getLoginManager();
1247 my $name = $params->{_DEFAULT};
1248
1249 if ( defined $name ) {
1250 if ( defined( $params->{set} ) ) {
1251 unless ( $readOnlySK{$name} ) {
1252 $this->setSessionValue( $name, $params->{set} );
1253 }
1254 }
1255 elsif ( defined( $params->{clear} ) ) {
1256 unless ( $readOnlySK{$name} ) {
1257 $this->clearSessionValue($name);
1258 }
1259 }
1260 elsif ( !$secretSK{$name} ) {
1261 my $val = $this->getSessionValue($name);
1262 $val = '' unless defined $val;
1263 return $val;
1264 }
1265 }
1266 return '';
1267}
1268
1269=begin TML
1270
1271---++ ObjectMethod _LOGINURL ($thisl)
1272
1273=cut
1274
1275sub _LOGINURL {
1276 my ( $session, $params ) = @_;
1277 my $this = $session->{users}->getLoginManager();
1278 return $this->loginUrl();
1279}
1280
1281=begin TML
1282
1283---++ ObjectMethod _dispLogon ($thisl)
1284
1285=cut
1286
1287sub _dispLogon {
1288 my $this = shift;
1289
1290 return '' unless $this->{_cgisession};
1291
1292 my $session = $this->{session};
1293 my $topic = $session->{topicName};
1294 my $web = $session->{webName};
1295 my $sessionId = $this->{_cgisession}->id();
1296
1297 my $urlToUse = $this->loginUrl();
1298
1299 unless ( $this->{_haveCookie} || !$Foswiki::cfg{Sessions}{IDsInURLs} ) {
1300 $urlToUse = _rewriteURL( $this, $urlToUse );
1301 }
1302
1303 my $text = $session->templates->expandTemplate('LOG_IN');
1304 return CGI::a( { class => 'foswikiAlert', href => $urlToUse }, $text );
1305}
1306
1307=begin TML
1308
1309---++ PrivateMethod _skinSelect ()
1310
1311Internal use only
1312TODO: what does it do?
1313
1314=cut
1315
1316sub _skinSelect {
1317 my $this = shift;
1318 my $session = $this->{session};
1319 my $skins = $session->{prefs}->getPreference('SKINS');
1320 my $skin = $session->getSkin();
1321 my @skins = split( /,/, $skins );
1322 unshift( @skins, 'default' );
1323 my $options = '';
1324 foreach my $askin (@skins) {
1325 $askin =~ s/\s//go;
1326 if ( $askin eq $skin ) {
1327 $options .=
1328 CGI::option( { selected => 'selected', name => $askin }, $askin );
1329 }
1330 else {
1331 $options .= CGI::option( { name => $askin }, $askin );
1332 }
1333 }
1334 return CGI::Select( { name => 'stickskin' }, $options );
1335}
1336
133715µs1;
1338__END__