89 var $username =
'guest';
95 var $fullname =
'Guest';
107 var $logged_in =
false;
115 var $just_logged_in =
false;
164 var $date_format_type;
176 var $last_session_start;
183 var $last_session_end;
214 var $login_failed =
false;
236 global $sid, $sysname;
238 $this->roles = array();
239 $this->logged_in =
false;
240 $this->just_logged_in =
false;
241 $this->login_failed =
false;
244 if ( ! isset($_COOKIE[
'sid']) )
return;
245 $sid = $_COOKIE[
'sid'];
248 list( $session_id, $session_key ) = explode(
';', $sid, 2 );
259 if ( function_exists(
'local_session_sql') ) {
260 $sql = local_session_sql();
263 $sql =
"SELECT session.*, usr.* FROM session JOIN usr USING ( user_no )";
265 $sql .=
" WHERE session.session_id = ? AND session.session_key = ? ORDER BY session.session_start DESC LIMIT 2";
267 $qry =
new AwlQuery($sql, $session_id, $session_key);
268 if ( $qry->Exec(
'Session') && 1 == $qry->rows() ) {
270 $qry =
new AwlQuery(
'UPDATE session SET session_end = current_timestamp WHERE session_id=?', $session_id);
271 $qry->Exec(
'Session');
275 setcookie(
'sid',
'', 0,
'/');
276 $this->cause =
'ERR: Other than one session record matches. ' . $qry->rows();
277 $this->
Log(
"WARN: Login $this->cause" );
295 deprecated(
'Session::Log');
297 $argc = func_num_args();
298 $format = func_get_arg(0);
299 if ( $argc == 1 || ($argc == 2 && func_get_arg(1) ==
"0" ) ) {
300 error_log(
"$c->sysabbr: $format" );
304 for( $i=1; $i < $argc; $i++ ) {
305 $args[] = func_get_arg($i);
307 error_log( sprintf(
"%s%s: %s", $c->sysabbr, request_id_str(),
308 vsprintf($format, $args) ));
325 global $debuggroups, $c;
326 deprecated(
'Session::Dbg');
328 $argc = func_num_args();
329 $dgroup = func_get_arg(0);
331 if ( ! (isset($debuggroups[$dgroup]) && $debuggroups[$dgroup]) )
return;
333 $format = func_get_arg(1);
334 if ( $argc == 2 || ($argc == 3 && func_get_arg(2) ==
"0" ) ) {
335 error_log( sprintf(
"%s%s: DBG: %s: %s", $c->sysabbr, request_id_str(),
340 for( $i=2; $i < $argc; $i++ ) {
341 $args[] = func_get_arg($i);
344 error_log( sprintf(
"%s%s: DBG: %s: %s", $c->sysabbr, request_id_str(),
345 $dgroup, vsprintf($format,$args) ));
358 return ( $this->logged_in && isset($this->roles[$whatever]) && $this->roles[$whatever] );
366 $this->roles = array();
367 $qry =
new AwlQuery(
'SELECT role_name FROM role_member m join roles r ON r.role_no = m.role_no WHERE user_no = ? ', $this->user_no );
368 if ( $qry->Exec(
'Session::GetRoles') && $qry->rows() > 0 ) {
369 while( $role = $qry->Fetch() ) {
370 $this->roles[$role->role_name] =
true;
382 foreach( $u AS $k => $v ) {
386 $date_format = ($this->date_format_type ==
'E' ?
'European,ISO' : ($this->date_format_type ==
'U' ?
'US,ISO' :
'ISO'));
387 $qry =
new AwlQuery(
'SET DATESTYLE TO '. $date_format );
391 $this->logged_in =
true;
409 function Login( $username, $password, $authenticated =
false ) {
412 dbg_error_log(
"Login",
" Login: Attempting login for $username" );
413 if ( isset($usr) ) unset($usr);
421 if ( !$authenticated && isset($c->authenticate_hook) && isset($c->authenticate_hook[
'call']) && function_exists($c->authenticate_hook[
'call']) ) {
432 $usr = call_user_func( $c->authenticate_hook[
'call'], $username, $password );
433 if ( $usr ===
false ) unset($usr);
else $authenticated =
true;
436 $sql =
"SELECT * FROM usr WHERE lower(username) = text(?) AND active";
437 $qry =
new AwlQuery( $sql, strtolower($username) );
438 if ( isset($usr) || ($qry->Exec(
'Login',__LINE__,__FILE__) && $qry->rows() == 1 && $usr = $qry->Fetch() ) ) {
439 $user_no = ( method_exists( $usr,
'user_no' ) ? $usr->user_no() : $usr->user_no );
440 if ( $authenticated || session_validate_password( $password, $usr->password ) || check_temporary_passwords( $password, $user_no ) ) {
442 $qry =
new AwlQuery(
"SELECT nextval('session_session_id_seq')" );
443 if ( $qry->Exec(
'Login') && $qry->rows() == 1 ) {
444 $seq = $qry->Fetch();
445 $session_id = $seq->nextval;
446 $session_key = md5( rand(1010101,1999999999) . microtime() );
447 dbg_error_log(
"Login",
" Login: Valid username/password for $username ($user_no)" );
450 $qry =
new AwlQuery(
'UPDATE usr SET last_used = (SELECT session_start FROM session WHERE session.user_no = ? ORDER BY session_id DESC LIMIT 1) WHERE user_no = ?;', $usr->user_no, $usr->user_no);
451 $qry->Exec(
'Session');
454 $sql =
"INSERT INTO session (session_id, user_no, session_key) VALUES( ?, ?, ? )";
455 $qry =
new AwlQuery( $sql, $session_id, $user_no, $session_key );
456 if ( $qry->Exec(
'Login') ) {
458 $sid =
"$session_id;$session_key";
461 setcookie(
'sid',$sid, 0,
'/');
464 dbg_error_log(
"Login",
" Login: New session $session_id started for $username ($user_no)" );
465 $this->just_logged_in =
true;
468 unset($_POST[
'username']);
469 unset($_POST[
'password']);
470 unset($_POST[
'submit']);
471 unset($_GET[
'submit']);
472 unset($GLOBALS[
'submit']);
474 if ( function_exists(
'local_session_sql') ) {
475 $sql = local_session_sql();
478 $sql =
"SELECT session.*, usr.* FROM session JOIN usr USING ( user_no )";
480 $sql .=
" WHERE session.session_id = ? AND session.session_key = ? ORDER BY session.session_start DESC LIMIT 2";
482 $qry =
new AwlQuery($sql, $session_id, $session_key);
483 if ( $qry->Exec(
'Session') && 1 == $qry->rows() ) {
491 $this->cause =
'ERR: Could not create new session.';
494 $this->cause =
'ERR: Could not increment session sequence.';
498 $c->messages[] = i18n(
'Invalid username or password.');
499 if ( isset($c->dbg[
'Login']) || isset($c->dbg[
'ALL']) )
500 $this->cause =
'WARN: Invalid password.';
502 $this->cause =
'WARN: Invalid username or password.';
506 $c->messages[] = i18n(
'Invalid username or password.');
507 if ( isset($c->dbg[
'Login']) || isset($c->dbg[
'ALL']) )
508 $this->cause =
'WARN: Invalid username.';
510 $this->cause =
'WARN: Invalid username or password.';
513 $this->
Log(
"Login failure: $this->cause" );
514 $this->login_failed =
true;
527 $action_target = htmlspecialchars(preg_replace(
'/\?logout.*$/',
'',$_SERVER[
'REQUEST_URI']));
528 dbg_error_log(
"Login",
" RenderLoginPanel: action_target='%s'", $action_target );
529 $userprompt = translate(
"User Name");
530 $pwprompt = translate(
"Password");
531 $gobutton = htmlspecialchars(translate(
"GO!"));
532 $gotitle = htmlspecialchars(translate(
"Enter your username and password then click here to log in."));
533 $temppwprompt = translate(
"If you have forgotten your password then");
534 $temppwbutton = htmlspecialchars(translate(
"Help! I've forgotten my password!"));
535 $temppwtitle = htmlspecialchars(translate(
"Enter a username, if you know it, and click here, to be e-mailed a temporary password."));
538<form action=
"$action_target" method=
"post">
541<th
class=
"prompt">$userprompt:</th>
543<input
class=
"text" type=
"text" name=
"username" size=
"12" /></td>
546<th
class=
"prompt">$pwprompt:</th>
548<input
class=
"password" type=
"password" name=
"password" size=
"12" />
552<th
class=
"prompt"> </th>
554<input type=
"submit" value=
"$gobutton" title=
"$gotitle" name=
"submit" class=
"submit" />
559$temppwprompt: <input type=
"submit" value=
"$temppwbutton" title=
"$temppwtitle" name=
"lostpass" class=
"submit" />
579 global $c, $session, $page_elements;
581 if ( $this->logged_in && $groups ==
"" )
return;
582 if ( ! $this->logged_in ) {
584 if ( function_exists(
"local_index_not_logged_in") ) {
585 local_index_not_logged_in();
588 $login_html = translate(
"<h1>Log On Please</h1><p>For access to the %s you should log on withthe username and password that have been issued to you.</p><p>If you would like to request access, please e-mail %s.</p>");
589 $page_content = sprintf( $login_html, $c->system_name, $c->admin_email );
591 if ( isset($page_elements) && gettype($page_elements) ==
'array' ) {
592 $page_elements[] = $page_content;
593 @include(
"page-renderer.php");
596 @include(
"page-header.php");
598 @include(
"page-footer.php");
602 $valid_groups = explode(
",", $groups);
603 foreach( $valid_groups AS $k => $v ) {
606 $c->messages[] = i18n(
"You are not authorised to use this function.");
607 if ( isset($page_elements) && gettype($page_elements) ==
'array' ) {
608 @include(
"page-renderer.php");
611 @include(
"page-header.php");
612 @include(
"page-footer.php");
631 $password_sent =
false;
634 if ( isset($username) && $username !=
"" ) {
635 $where =
'WHERE active AND lower(usr.username) = :lcusername';
636 $params[
':lcusername'] = strtolower($username);
638 else if ( isset($email_address) && $email_address !=
"" ) {
639 $where =
'WHERE active AND lower(usr.email) = :lcemail';
640 $params[
':lcemail'] = strtolower($email_address);
643 if ( $where !=
'' ) {
644 if ( !isset($body_template) || $body_template ==
"" ) {
645 $body_template = <<<EOTEXT
647@@debugging@@A temporary password has been requested
for @@system_name@@.
649Temporary Password: @@password@@
651This has been applied to the following usernames:
654and will be valid
for 24 hours.
656If you have any problems, please contact the system administrator.
661 $qry =
new AwlQuery(
'SELECT * FROM usr '.$where, $params );
662 $qry->Exec(
'Session::EmailTemporaryPassword');
663 if ( $qry->rows() > 0 ) {
667 while ( $row = $qry->Fetch() ) {
668 $mail =
new EMail(
"Access to $c->system_name" );
669 $mail->SetFrom($c->admin_email );
672 if ( isset($c->debug_email) ) {
673 $debug_to =
"This e-mail would normally be sent to:\n ";
674 $mail->AddTo(
"Tester <$c->debug_email>" );
678 for ( $i=0; $i < 8; $i++ ) {
679 $tmp_passwd .= substr(
'ABCDEFGHIJKLMNOPQRSTUVWXYZ+#.-=*%@0123456789abcdefghijklmnopqrstuvwxyz', rand(0,69), 1);
682 $q2->QDo(
'INSERT INTO tmp_password (user_no, password) VALUES (?, ?)', array($row->user_no, $tmp_passwd));
683 if ( isset($c->debug_email) ) {
684 $debug_to .=
"$row->fullname <$row->email> ";
687 $mail->AddTo(
"$row->fullname <$row->email>" );
689 $usernames .=
" $row->username\n";
691 if ( $mail->To() !=
"" ) {
692 if ( isset($c->debug_email) ) {
693 $debug_to .=
"\n============================================================\n";
697 $qry->Exec(
"Session::SendTemporaryPassword");
698 $body = str_replace(
'@@system_name@@', $c->system_name, $body_template);
699 $body = str_replace(
'@@password@@', $tmp_passwd, $body);
700 $body = str_replace(
'@@usernames@@', $usernames, $body);
701 $body = str_replace(
'@@debugging@@', $debug_to, $body);
702 $mail->SetBody($body);
704 $password_sent =
true;
709 return $password_sent;
721 global $c, $page_elements;
723 $password_sent = $this->
EmailTemporaryPassword( (isset($_POST[
'username'])?$_POST[
'username']:
null), (isset($_POST[
'email_address'])?$_POST[
'email_address']:
null) );
725 if ( ! $password_sent && ((isset($_POST[
'username']) && $_POST[
'username'] !=
"" )
726 || (isset($_POST[
'email_address']) && $_POST[
'email_address'] !=
"" )) ) {
728 $page_content = <<<EOTEXT
730<h1>Unable to Reset Password</h1>
731<p>We were unable to reset your password at
this time. Please contact
732<a href=
"mailto:$c->admin_email">$c->admin_email</a>
733to arrange
for an administrator to reset your password.</p>
738 else if ( $password_sent ) {
739 $page_content = <<<EOTEXT
741<h1>Temporary Password Sent</h1>
742<p>A temporary password has been e-mailed to you. This password
743will be valid
for 24 hours and you will be required to change
744your password after logging in.</p>
745<p><a href=
".">Click here to
return to the login page.</a></p>
750 $page_content = <<<EOTEXT
752<h1>Temporary Password</h1>
753<form action=
"$action_target" method=
"post">
756<th
class=
"prompt" style=
"white-space: nowrap;">Enter your
User Name:</th>
757<td
class=
"entry"><input
class=
"text" type=
"text" name=
"username" size=
"12" /></td>
760<th
class=
"prompt" style=
"white-space: nowrap;">Or your
EMail Address:</th>
761<td
class=
"entry"><input
class=
"text" type=
"text" name=
"email_address" size=
"50" /></td>
764<th
class=
"prompt" style=
"white-space: nowrap;">and click on -></th>
766<input
class=
"submit" type=
"submit" value=
"Send me a temporary password" alt=
"Enter a username, or e-mail address, and click here." name=
"lostpass" />
770<p>Note: If you have multiple accounts with the same e-mail address, they will <em>all</em>
771be assigned a
new temporary password, but only the one(s) that you use that temporary password
772on will have the existing password invalidated.</p>
773<h2>The temporary password will only be valid
for 24 hours.</h2>
774<p>You will need to log on and change your password during
this time.</p>
779 if ( isset($page_elements) && gettype($page_elements) ==
'array' ) {
780 $page_elements[] = $page_content;
781 @include(
"page-renderer.php");
784 @include(
"page-header.php");
786 @include(
"page-footer.php");
790 static function _CheckLogout() {
791 if ( isset($_GET[
'logout']) ) {
792 dbg_error_log(
"Login",
":_CheckLogout: Logging out");
793 if ( isset($_COOKIE[
'sid']) ) {
795 list( $session_id, $session_key ) = explode(
';', $_COOKIE[
'sid'], 2 );
796 $sql =
'DELETE FROM session WHERE session_id = ? AND session_key = ?';
797 $qry =
new AwlQuery( $sql, $session_id, $session_key );
798 $qry->Exec(
'Logout',__LINE__,__FILE__);
800 $sql =
"DELETE FROM session WHERE session_end < current_timestamp - interval '16 hours'";
802 $qry->Exec(
'Expire',__LINE__,__FILE__);
804 setcookie(
'sid',
'', 0,
'/');
805 unset($_COOKIE[
'sid']);
806 unset($GLOBALS[
'sid']);
812 if ( isset($_POST[
'lostpass']) ) {
813 dbg_error_log(
"Login",
":_CheckLogin: User '$_POST[username]' has lost the password." );
816 else if ( isset($_POST[
'username']) && isset($_POST[
'password']) ) {
817 $username = $_POST[
'username'];
819 $this->
Login( $_POST[
'username'], $_POST[
'password'] );
820 @dbg_error_log(
"Login",
":_CheckLogin: User %s - %s (%d) login status is %d", $username, $this->fullname, $this->user_no, $this->logged_in );
822 else if ( !isset($_COOKIE[
'sid']) && isset($c->authenticate_hook[
'server_auth_type']) ) {
826 if ( ( is_array($c->authenticate_hook[
'server_auth_type'])
827 && in_array( strtolower($_SERVER[
'AUTH_TYPE']), array_map(
'strtolower', $c->authenticate_hook[
'server_auth_type'])) )
829 ( !is_array($c->authenticate_hook[
'server_auth_type'])
830 && strtolower($c->authenticate_hook[
'server_auth_type']) == strtolower($_SERVER[
'AUTH_TYPE']) )
832 if (isset($_SERVER[
"REMOTE_USER"]))
833 $this->
Login($_SERVER[
'REMOTE_USER'],
"",
true);
835 $this->
Login($_SERVER[
'REDIRECT_REMOTE_USER'],
"",
true);
847 function FormattedDate( $indate, $type=
'date' ) {
849 if ( preg_match(
'#^\s*$#', $indate ) ) {
853 if ( preg_match(
'#^\d{1,2}[/-]\d{1,2}[/-]\d{2,4}#', $indate ) ) {
857 $yr = substr($indate,0,4);
858 $mo = substr($indate,5,2);
859 $dy = substr($indate,8,2);
860 switch ( $this->date_format_type ) {
862 $out = sprintf(
"%d/%d/%d", $mo, $dy, $yr );
865 $out = sprintf(
"%d/%d/%d", $dy, $mo, $yr );
868 $out = sprintf(
"%d-%02d-%02d", $yr, $mo, $dy );
871 if ( $type ==
'timestamp' ) {
872 $out .= substr($indate,10,6);
887 function BuildConfirmationHash( $method, $varname ) {
892 $confirmation_hash = session_salted_md5( $this->session_start.$varname.$this->session_key,
"" );
893 if ( $method ==
'GET' ) {
894 $confirm = $varname .
'='. urlencode($confirmation_hash);
897 $confirm = sprintf(
'<input type="hidden" name="%s" value="%s">', $varname, htmlspecialchars($confirmation_hash) );
910 function CheckConfirmationHash( $method, $varname ) {
911 if ( $method ==
'GET' && isset($_GET[$varname])) {
912 $hashwegot = $_GET[$varname];
913 dbg_error_log(
'Session',
':CheckConfirmationHash: We got "%s" from GET', $hashwegot );
915 else if ( isset($_POST[$varname]) ) {
916 $hashwegot = $_POST[$varname];
917 dbg_error_log(
'Session',
':CheckConfirmationHash: We got "%s" from POST', $hashwegot );
923 if ( preg_match(
'{^\*(.+)\*.+$}i', $hashwegot, $regs ) ) {
926 dbg_error_log(
'Session',
':CheckConfirmationHash: Salt "%s"', $salt );
927 $test_against = session_salted_md5( $this->session_start.$varname.$this->session_key, $salt ) ;
928 dbg_error_log(
'Session',
':CheckConfirmationHash: Testing against "%s"', $test_against );
930 return ($hashwegot == $test_against);