* Admin: session-list is generated now from egw_access_log table independent of readablity of sessions files in filesystem

- session_(dla|action) is stored in egw_access_log table
- notifications refresh via ajax set notification_heartbeat timestamp in egw_access_log
- if notification_heartbeat is set (happens only for browser sessions with popup notification) sessions get removed from session list one minute after browser is closed
- new static method egw_session::notifications_active($account_id) to check if given user has an open browser with notifications popup checking, to ensure popup notifications can fall back to email
--> REQUIRES DATABASE UPDATE / SETUP
This commit is contained in:
Ralf Becker 2011-04-13 14:11:09 +00:00
parent aecfe9d768
commit 5495491e78
15 changed files with 363 additions and 349 deletions

View File

@ -1,17 +1,17 @@
<?php
/**
* eGgroupWare admin - accesslog
* EGgroupware admin - access- and session-log
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @package admin
* @copyright (c) 2009 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2009-11 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
/**
* Show eGroupware access log
* Show EGroupware access- and session-log
*/
class admin_accesslog
{
@ -22,6 +22,7 @@ class admin_accesslog
*/
public $public_functions = array(
'index' => true,
'sessions' => true,
);
/**
@ -46,10 +47,6 @@ class admin_accesslog
*/
function __construct()
{
if ($GLOBALS['egw']->acl->check('access_log_access',1,'admin'))
{
$GLOBALS['egw']->redirect_link('/index.php');
}
$this->so = new so_sql(self::APP,self::TABLE,null,'',true);
}
@ -63,34 +60,81 @@ class admin_accesslog
*/
function get_rows($query,&$rows,&$readonlys)
{
$heartbeat_limit = egw_session::heartbeat_limit();
if ($query['session_list']) // filter active sessions
{
$query['col_filter']['lo'] = null; // not logged out
$query['col_filter'][0] = 'session_dla > '.(int)(time() - $GLOBALS['egw_info']['server']['sessions_timeout']);
$query['col_filter'][1] = "(notification_heartbeat IS NULL OR notification_heartbeat > $heartbeat_limit)";
}
$total = $this->so->get_rows($query,$rows,$readonlys);
$no_kill = !$GLOBALS['egw']->acl->check('current_sessions_access',8,'admin') && !$query['session_list'];
foreach($rows as &$row)
{
$row['sessionstatus'] = lang('success');
if (stripos($row['sessionid'],'blocked') !== False || stripos($row['sessionid'],'bad login') !== False)
if ($row['notification_heartbeat'] > $heartbeat_limit)
{
$row['sessionstatus'] = $row['sessionid'];
$row['sessionstatus'] = lang('active');
}
if (stripos($row['session_php'],'blocked') !== false ||
stripos($row['session_php'],'bad login') !== false ||
strpos($row['sessioin_php'],' ') !== false)
{
$row['sessionstatus'] = $row['session_php'];
}
if ($row['lo']) {
$row['total'] = ($row['lo'] - $row['li']) / 60;
$row['sessionstatus'] = lang('logged out');
}
// eg. for bad login or password
if (!$row['account_id']) $row['alt_loginid'] = $row['loginid'];
$readonlys['kill['.$row['sessionid'].']'] = $no_kill;
$readonlys['delete['.$row['sessionid'].']'] = $query['session_list'];
// do not allow to kill or select own session
if ($GLOBALS['egw']->session->sessionid_access_log == $row['sessionid'] && $query['session_list'])
{
$readonlys['kill['.$row['sessionid'].']'] = $readonlys['selected['.$row['sessionid'].']'] = true;
}
// do not allow to delete access log off active sessions
if (!$row['lo'] && $row['session_dla'] > time()-$GLOBALS['egw_info']['server']['sessions_timeout'] && !$query['session_list'])
{
$readonlys['delete['.$row['sessionid'].']'] = $readonlys['selected['.$row['sessionid'].']'] = true;
}
unset($row['session_php']); // for security reasons, do NOT give real PHP sessionid to UI
}
$GLOBALS['egw_info']['flags']['app_header'] = lang('Admin').' - '.lang('View Access Log').
if ($query['session_list'])
{
$rows['no_total'] = $rows['no_lo'] = true;
}
$GLOBALS['egw_info']['flags']['app_header'] = lang('Admin').' - '.
($query['session_list'] ? lang('View sessions') : lang('View Access Log')).
($query['col_filter']['account_id'] ? ': '.common::grab_owner_name($query['col_filter']['account_id']) : '');
return $total;
}
/**
* Display the accesslog
* Display the access log or session list
*
* @param array $content
* @param array $content=null
* @param string $msg=''
* @param boolean $sessions_list=false
*/
function index(array $content=null)
function index(array $content=null, $msg='', $sessions_list=false)
{
//_debug_array($content);
if (is_array($content)) $sessions_list = $content['nm']['session_list'];
// check if user has access to requested functionality
if ($GLOBALS['egw']->acl->check($sessions_list ? 'current_sessions_access' : 'access_log_access',1,'admin'))
{
$GLOBALS['egw']->redirect_link('/index.php');
}
if(!isset($content))
{
@ -114,32 +158,71 @@ class admin_accesslog
{
$content['nm']['col_filter']['account_id'] = (int)$_GET['account_id'];
}
if ($sessions_list)
{
$content['nm']['order'] = 'session_dla';
$content['nm']['options-selectcols'] = array(
'lo' => false,
'total' => false,
);
}
$content['nm']['session_list'] = $sessions_list;
}
elseif(isset($content['nm']['rows']['delete']))
elseif(isset($content['nm']['rows']['delete']) || isset($content['delete']))
{
list($sessionid) = each($content['nm']['rows']['delete']);
unset($content['nm']['rows']['delete']);
if (isset($content['nm']['rows']['delete']))
{
list($sessionid) = each($content['nm']['rows']['delete']);
unset($content['nm']['rows']['delete']);
}
else
{
unset($content['delete']);
$sessionid = $content['nm']['rows']['selected'];
}
if ($sessionid && $this->so->delete(array('sessionid' => $sessionid)))
{
$content['msg'] = lang('%1 log entries deleted.',1);
$msg = lang('%1 log entries deleted.',1);
}
else
{
$content['msg'] = lang('Error deleting log entry!');
$msg = lang('Error deleting log entry!');
}
}
elseif(isset($content['delete']))
elseif(isset($content['nm']['rows']['kill']) || isset($content['kill']))
{
unset($content['delete']);
if (($deleted = $this->so->delete(array('sessionid' => $content['nm']['rows']['selected']))))
if (isset($content['nm']['rows']['kill']))
{
$content['msg'] = lang('%1 log entries deleted.',$deleted);
list($sessionid) = each($content['nm']['rows']['kill']);
$sessionid = array($sessionid);
unset($content['nm']['rows']['kill']);
}
else
{
$content['msg'] = lang('Error deleting log entry!');
unset($content['kill']);
$sessionid = $content['nm']['rows']['selected'];
}
if (($key = array_search($GLOBALS['egw']->session->sessionid_access_log, $sessionid)))
{
unset($sessionid[$key]); // dont allow to kill own sessions
}
if ($GLOBALS['egw']->acl->check('current_sessions_access',8,'admin'))
{
$msg = lang('Permission denied!');
}
else
{
foreach((array)$sessionid as $id)
{
$GLOBALS['egw']->session->destroy($id);
}
$msg = lang('%1 sessions killed',count($sessionid));
}
}
$readonlys['kill'] = !$sessions_list;
$readonlys['delete'] = $sessions_list;
$content['msg'] = $msg;
$content['percent'] = 100.0 * $GLOBALS['egw']->db->query(
'SELECT ((SELECT COUNT(*) FROM '.self::TABLE.' WHERE lo != 0) / COUNT(*)) FROM '.self::TABLE,
__LINE__,__FILE__)->fetchColumn();
@ -149,4 +232,15 @@ class admin_accesslog
'nm' => $content['nm'],
));
}
/**
* Display session list
*
* @param array $content=null
* @param string $msg=''
*/
function sessions(array $content=null, $msg='')
{
return $this->index(null,$msg,true);
}
}

View File

@ -83,7 +83,7 @@ class admin_prefs_sidebox_hooks
if (! $GLOBALS['egw']->acl->check('current_sessions_access',1,'admin'))
{
$file['View Sessions'] = egw::link('/index.php','menuaction=admin.uicurrentsessions.list_sessions');
$file['View Sessions'] = egw::link('/index.php','menuaction=admin.admin_accesslog.sessions');
}
if (! $GLOBALS['egw']->acl->check('access_log_access',1,'admin'))

View File

@ -1,71 +0,0 @@
<?php
/**************************************************************************\
* eGroupWare - Administration *
* http://www.egroupware.org *
* This file written by Joseph Engo <jengo@phpgroupware.org> *
* -------------------------------------------- *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; either version 2 of the License, or (at your *
* option) any later version. *
\**************************************************************************/
/* $Id$ */
class bocurrentsessions
{
var $ui;
var $so;
var $public_functions = array(
'kill' => True
);
function total()
{
return $GLOBALS['egw']->session->session_count();
}
function list_sessions($start,$order,$sort)
{
$values = $GLOBALS['egw']->session->session_list($start,$sort,$order);
while (list(,$value) = @each($values))
{
if (strpos($value['session_lid'],'@') !== false)
{
$t = explode('@',$value['session_lid']);
$session_lid = $t[0];
}
else
{
$session_lid = $value['session_lid'];
}
$tmp = time() - $value['session_dla'];
$secs = $tmp % 60;
$mins = (($tmp - $secs) % 3600) / 60;
$hours = ($tmp - ($mins * 60) - $secs) / 3600;
$_values[] = array(
'session_id' => $value['session_id'],
'session_lid' => $session_lid,
'session_ip' => $value['session_ip'],
'session_logintime' => $GLOBALS['egw']->common->show_date($value['session_logintime']),
'session_action' => $value['session_action'],
'session_dla' => $value['session_dla'],
'session_idle' => str_pad($hours, 2, '0', STR_PAD_LEFT) . ':' . str_pad($mins, 2, '0', STR_PAD_LEFT) . ':' . str_pad($secs, 2, '0', STR_PAD_LEFT)
);
}
return $_values;
}
function kill()
{
if ($_GET['ksession'] &&
($GLOBALS['sessionid'] != $_GET['ksession']) &&
! $GLOBALS['egw']->acl->check('current_sessions_access',8,'admin'))
{
$GLOBALS['egw']->session->destroy($_GET['ksession'],0);
}
$this->ui =& CreateObject('admin.uicurrentsessions');
$this->ui->list_sessions();
}
}

View File

@ -1,162 +0,0 @@
<?php
/**************************************************************************\
* eGroupWare - Administration *
* http://www.egroupware.org *
* This file written by Joseph Engo <jengo@phpgroupware.org> *
* -------------------------------------------- *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; either version 2 of the License, or (at your *
* option) any later version. *
\**************************************************************************/
/* $Id$ */
class uicurrentsessions
{
var $template;
var $bo;
var $public_functions = array(
'list_sessions' => True,
'kill' => True
);
function uicurrentsessions()
{
if ($GLOBALS['egw']->acl->check('current_sessions_access',1,'admin'))
{
$GLOBALS['egw']->redirect_link('/index.php');
}
$this->template =& CreateObject('phpgwapi.Template',EGW_APP_TPL);
$this->bo =& CreateObject('admin.bocurrentsessions');
$this->nextmatchs =& CreateObject('phpgwapi.nextmatchs');
}
function header()
{
$GLOBALS['egw']->common->egw_header();
echo parse_navbar();
}
function store_location($info)
{
$GLOBALS['egw']->session->appsession('currentsessions_session_data','admin',$info);
}
function list_sessions()
{
$info = $GLOBALS['egw']->session->appsession('currentsessions_session_data','admin');
if (! is_array($info))
{
$info = array(
'start' => 0,
'sort' => 'DESC',
'order' => 'session_dla'
);
$this->store_location($info);
}
if (isset($_REQUEST['start']) || $_REQUEST['sort'] || $_REQUEST['order'])
{
if ($_REQUEST['start'] == 0 || $_REQUEST['start'] && $_REQUEST['start'] != $info['start'])
{
$info['start'] = $_REQUEST['start'];
}
if ($_REQUEST['sort'] && $_REQUEST['sort'] != $info['sort'])
{
$info['sort'] = $_REQUEST['sort'];
}
if ($_REQUEST['order'] && $_REQUEST['order'] != $info['order'])
{
$info['order'] = $_REQUEST['order'];
}
$this->store_location($info);
}
$GLOBALS['egw_info']['flags']['app_header'] = lang('Admin').' - '.lang('List of current users');
$this->header();
$this->template->set_file('current','currentusers.tpl');
$this->template->set_block('current','list','list');
$this->template->set_block('current','row','row');
$can_view_action = !$GLOBALS['egw']->acl->check('current_sessions_access',2,'admin');
$can_view_ip = !$GLOBALS['egw']->acl->check('current_sessions_access',4,'admin');
$can_kill = !$GLOBALS['egw']->acl->check('current_sessions_access',8,'admin');
$total = $this->bo->total();
$this->template->set_var('left_next_matchs',$this->nextmatchs->left('/admin/currentusers.php',$info['start'],$total));
$this->template->set_var('right_next_matchs',$this->nextmatchs->right('/admin/currentusers.php',$info['start'],$total));
$this->template->set_var('start_total',$this->nextmatchs->show_hits($total,$info['start']));
$this->template->set_var('sort_loginid',$this->nextmatchs->show_sort_order($info['sort'],'session_lid',$info['order'],
'/admin/currentusers.php',lang('LoginID')));
$this->template->set_var('sort_ip',$this->nextmatchs->show_sort_order($info['sort'],'session_ip',$info['order'],
'/admin/currentusers.php',lang('IP')));
$this->template->set_var('sort_login_time',$this->nextmatchs->show_sort_order($info['sort'],'session_logintime',$info['order'],
'/admin/currentusers.php',lang('Login Time')));
$this->template->set_var('sort_action',$this->nextmatchs->show_sort_order($info['sort'],'session_action',$info['order'],
'/admin/currentusers.php',lang('Action')));
$this->template->set_var('sort_idle',$this->nextmatchs->show_sort_order($info['sort'],'session_dla',$info['order'],
'/admin/currentusers.php',lang('idle')));
$this->template->set_var('lang_kill',lang('Kill'));
$values = $this->bo->list_sessions($info['start'],$info['order'],$info['sort']);
while (list(,$value) = @each($values))
{
$this->nextmatchs->template_alternate_row_color($this->template);
$this->template->set_var('row_loginid',$value['session_lid']);
$this->template->set_var('row_ip',$can_view_ip?$value['session_ip']:'&nbsp;');
$this->template->set_var('row_logintime',$value['session_logintime']);
$this->template->set_var('row_idle',$value['session_idle']);
if ($value['session_action'] && $can_view_action)
{
$this->template->set_var('row_action',$GLOBALS['egw']->strip_html($value['session_action']));
}
else
{
$this->template->set_var('row_action','&nbsp;');
}
if ($value['session_id'] != $GLOBALS['egw_info']['user']['sessionid'] && $can_kill)
{
$this->template->set_var('row_kill','<a href="' . $GLOBALS['egw']->link('/index.php','menuaction=admin.uicurrentsessions.kill&ksession='
. $value['session_id'] . '&kill=true') . '">' . lang('Kill').'</a>');
}
else
{
$this->template->set_var('row_kill','&nbsp;');
}
$this->template->parse('rows','row',True);
}
$this->template->pfp('out','list');
}
function kill()
{
if ($GLOBALS['egw']->acl->check('current_sessions_access',8,'admin'))
{
$GLOBALS['egw']->redirect_link('/index.php');
}
$GLOBALS['egw_info']['flags']['app_header'] = lang('Admin').' - '.lang('Kill session');
$this->header();
$this->template->set_file('form','kill_session.tpl');
$this->template->set_var('lang_message',lang('Are you sure you want to kill this session ?'));
$this->template->set_var('link_no','<a href="' . $GLOBALS['egw']->link('/index.php','menuaction=admin.uicurrentsessions.list_sessions') . '">' . lang('No') . '</a>');
$this->template->set_var('link_yes','<a href="' . $GLOBALS['egw']->link('/index.php','menuaction=admin.bocurrentsessions.kill&ksession=' . $_GET['ksession']) . '">' . lang('Yes') . '</a>');
$this->template->pfp('out','form');
}
}

View File

@ -7,6 +7,7 @@
%1 log entries deleted. admin de %1 Protokolleinträge gelöscht.
%1 not found or not executable !!! admin de %1 nicht gefunden oder nicht ausführbar !!!
%1 rights for %2 and applications %3 admin de %1 Rechte für %2 und Anwendung(en) %3
%1 sessions killed admin de %1 Sitzungen beendet
%1 user %2 admin de %1 Benutzer %2
(default no, leave it off if you dont use it) admin de (Vorgabe Nein, ausgeschaltet lassen, wenn nicht benutzt)
(stored password will not be shown here) admin de (Gespeichertes Passwort wird hier nicht angezeigt)
@ -28,8 +29,8 @@ account preferences admin de Einstellungen der Benutzerkonten
account-id's have to be integers! admin de Konten-ID`s müssen vom Typ Integer (Zahl) sein!
acl manager admin de ACL-Manager
acl rights common de ACL-Rechte
action admin de Aktion
actions admin de Aktionen
action admin de Befehl
actions admin de Befehle
activate wysiwyg-editor admin de WYSIWYG Editor (formatierter Text) aktivieren
add a category admin de Eine Kategorie hinzufügen
add a group admin de Eine Gruppe hinzufügen
@ -160,6 +161,7 @@ delete peer server admin de Server von Serververbund löschen
delete selected entries admin de Ausgewählte Einträge löschen
delete the category admin de Kategorie löschen
delete the group admin de Gruppe löschen
delete the selected entries admin de Die ausgewählten Einträge löschen
delete this category admin de Kategorie löschen
delete this group admin de Gruppe löschen
delete this log entry admin de Diesen Protokolleintrag löschen
@ -330,6 +332,7 @@ kill admin de Beenden
kill session admin de Sitzung beenden
last %1 logins admin de Letze %1 Logins
last %1 logins for %2 admin de Letze %1 Logins für %2
last action admin de Letzte Aktion
last login admin de Letzter Login
last login from admin de Letzer Login von
last submission: admin de Letzte Absendung:

View File

@ -7,6 +7,7 @@
%1 log entries deleted. admin en %1 log entries deleted.
%1 not found or not executable !!! admin en %1 not found or not executable !!!
%1 rights for %2 and applications %3 admin en %1 rights for %2 and applications %3
%1 sessions killed admin en %1 sessions killed
%1 user %2 admin en %1 user %2
(default no, leave it off if you dont use it) admin en (default No, leave it off if you dont use it)
(stored password will not be shown here) admin en (Stored password will not be shown here)
@ -160,6 +161,7 @@ delete peer server admin en Delete peer server
delete selected entries admin en Delete selected entries
delete the category admin en delete the category
delete the group admin en delete the group
delete the selected entries admin en Delete the selected entries
delete this category admin en delete this category
delete this group admin en delete this group
delete this log entry admin en Delete this log entry
@ -330,6 +332,7 @@ kill admin en Kill
kill session admin en Kill session
last %1 logins admin en Last %1 logins
last %1 logins for %2 admin en Last %1 logins for %2
last action admin en Last action
last login admin en last login
last login from admin en last login from
last submission: admin en Last submission:

View File

@ -2,7 +2,7 @@
/**
* eGroupWare - eTemplates for Application admin
* http://www.egroupware.org
* generated by soetemplate::dump4setup() 2011-04-12 09:22
* generated by soetemplate::dump4setup() 2011-04-13 15:34
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package admin
@ -12,11 +12,11 @@
$templ_version=1;
$templ_data[] = array('name' => 'admin.accesslog','template' => '','lang' => '','group' => '0','version' => '1.7.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:4:{i:0;a:1:{s:2:"h1";s:6:",!@msg";}i:1;a:2:{s:1:"A";a:4:{s:4:"type";s:5:"label";s:4:"span";s:13:"all,redItalic";s:5:"align";s:6:"center";s:4:"name";s:3:"msg";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:4:{s:4:"type";s:9:"nextmatch";s:4:"size";s:4:"rows";s:4:"name";s:2:"nm";s:4:"span";s:3:"all";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:3;a:2:{s:1:"A";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:6:"2,,0,0";i:1;a:3:{s:4:"type";s:5:"label";s:5:"label";s:32:"Percent of users that logged out";s:8:"readonly";s:1:"1";}i:2;a:5:{s:4:"type";s:5:"float";s:4:"name";s:7:"percent";s:4:"size";s:4:",,,1";s:5:"label";s:6:": %s %";s:8:"readonly";s:1:"1";}}s:1:"B";a:5:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";s:5:"align";s:5:"right";i:1;a:6:{s:4:"type";s:6:"button";s:4:"name";s:6:"delete";s:4:"size";s:6:"delete";s:5:"label";s:6:"Delete";s:4:"help";s:23:"Delete selected entries";s:7:"onclick";s:46:"return confirm(\'Delete the selected entries\');";}i:2;a:4:{s:4:"type";s:10:"buttononly";s:4:"size";s:9:"arrow_ltr";s:7:"onclick";s:71:"toggle_all(this.form,form::name(\'nm[rows][selected][]\')); return false;";s:4:"span";s:15:",selectAllArrow";}}}}s:4:"rows";i:3;s:4:"cols";i:2;s:4:"size";s:4:"100%";s:7:"options";a:1:{i:0;s:4:"100%";}}}','size' => '100%','style' => '.selectAllArrow { padding-right: 12px; }','modified' => '1240661952',);
$templ_data[] = array('name' => 'admin.accesslog','template' => '','lang' => '','group' => '0','version' => '1.9.001','data' => 'a:1:{i:0;a:5:{s:4:"type";s:4:"grid";s:4:"data";a:4:{i:0;a:1:{s:2:"h1";s:6:",!@msg";}i:1;a:2:{s:1:"A";a:4:{s:4:"span";s:13:"all,redItalic";s:5:"align";s:6:"center";s:4:"name";s:3:"msg";s:4:"type";s:5:"label";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:4:{s:4:"span";s:3:"all";s:4:"name";s:2:"nm";s:4:"size";s:20:"admin.accesslog.rows";s:4:"type";s:9:"nextmatch";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:3;a:2:{s:1:"A";a:4:{s:4:"size";s:6:"2,,0,0";s:4:"type";s:4:"hbox";i:1;a:3:{s:8:"readonly";s:4:"true";s:4:"type";s:5:"label";s:5:"label";s:32:"Percent of users that logged out";}i:2;a:6:{s:4:"type";s:5:"float";s:9:"precision";s:1:"1";s:5:"label";s:6:": %s %";s:8:"readonly";s:4:"true";s:4:"name";s:7:"percent";s:4:"size";s:1:",";}}s:1:"B";a:6:{s:5:"align";s:5:"right";s:4:"type";s:4:"hbox";i:1;a:6:{s:5:"label";s:6:"Delete";s:7:"onclick";s:46:"return confirm(\'Delete the selected entries\');";s:4:"name";s:6:"delete";s:4:"type";s:6:"button";s:4:"size";s:6:"delete";s:4:"help";s:23:"Delete selected entries";}i:2;a:5:{s:4:"type";s:6:"button";s:4:"size";s:5:"close";s:5:"label";s:4:"Kill";s:4:"name";s:4:"kill";s:7:"onclick";s:63:"return confirm(\'Are you sure you want to kill this session ?\');";}s:4:"size";s:1:"3";i:3;a:4:{s:4:"type";s:10:"buttononly";s:4:"size";s:9:"arrow_ltr";s:5:"label";s:10:"Select all";s:7:"onclick";s:61:"toggle_all(this.form,form::name(\'selected[]\')); return false;";}}}}s:4:"cols";i:2;s:4:"rows";i:3;s:4:"size";s:4:"100%";}}','size' => '100%','style' => '.selectAllArrow { padding-right: 12px; }','modified' => '1302686599',);
$templ_data[] = array('name' => 'admin.accesslog.get_rows','template' => '','lang' => '','group' => '0','version' => '1.3.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:2:{s:2:"c1";s:2:"th";s:2:"c2";s:3:"row";}i:1;a:4:{s:1:"A";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:7:"LoginID";s:4:"name";s:7:"loginid";}s:1:"B";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:2:"IP";s:4:"name";s:2:"ip";}s:1:"C";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:9:"Logintime";s:4:"name";s:2:"li";}s:1:"D";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:9:"Logoutime";s:4:"name";s:2:"lo";}}i:2;a:4:{s:1:"A";a:3:{s:4:"type";s:14:"select-account";s:4:"name";s:15:"${row}[loginid]";s:8:"readonly";s:1:"1";}s:1:"B";a:3:{s:4:"type";s:5:"label";s:4:"name";s:10:"${row}[ip]";s:7:"no_lang";s:1:"1";}s:1:"C";a:3:{s:4:"type";s:9:"date-time";s:4:"name";s:10:"${row}[li]";s:8:"readonly";s:1:"1";}s:1:"D";a:3:{s:4:"type";s:9:"date-time";s:4:"name";s:10:"${row}[lo]";s:8:"readonly";s:1:"1";}}}s:4:"rows";i:2;s:4:"cols";i:4;s:4:"size";s:4:"100%";s:7:"options";a:1:{i:0;s:4:"100%";}}}','size' => '100%','style' => '','modified' => '1164479930',);
$templ_data[] = array('name' => 'admin.accesslog.rows','template' => '','lang' => '','group' => '0','version' => '1.7.002','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:3:{s:2:"c1";s:2:"th";s:2:"c2";s:3:"row";s:1:"H";s:2:"1%";}i:1;a:8:{s:1:"A";a:3:{s:4:"type";s:23:"nextmatch-accountfilter";s:4:"size";s:7:"LoginID";s:4:"name";s:10:"account_id";}s:1:"B";a:3:{s:4:"type";s:16:"nextmatch-header";s:5:"label";s:12:"Login-Status";s:4:"name";s:13:"sessionstatus";}s:1:"C";a:3:{s:4:"type";s:16:"nextmatch-header";s:5:"label";s:7:"Loginid";s:4:"name";s:7:"loginid";}s:1:"D";a:3:{s:4:"type";s:16:"nextmatch-header";s:5:"label";s:2:"IP";s:4:"name";s:2:"ip";}s:1:"E";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:5:"Login";s:4:"name";s:2:"li";}s:1:"F";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:6:"Logout";s:4:"name";s:2:"lo";}s:1:"G";a:3:{s:4:"type";s:16:"nextmatch-header";s:5:"label";s:5:"Total";s:4:"name";s:5:"total";}s:1:"H";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";i:1;a:3:{s:4:"type";s:5:"label";s:5:"label";s:6:"Action";s:5:"align";s:6:"center";}i:2;a:4:{s:4:"type";s:10:"buttononly";s:4:"size";s:5:"check";s:5:"label";s:10:"Select all";s:7:"onclick";s:61:"toggle_all(this.form,form::name(\'selected[]\')); return false;";}}}i:2;a:8:{s:1:"A";a:3:{s:4:"type";s:14:"select-account";s:4:"name";s:18:"${row}[account_id]";s:8:"readonly";s:1:"1";}s:1:"B";a:2:{s:4:"type";s:5:"label";s:4:"name";s:21:"${row}[sessionstatus]";}s:1:"C";a:2:{s:4:"type";s:5:"label";s:4:"name";s:15:"${row}[loginid]";}s:1:"D";a:2:{s:4:"type";s:5:"label";s:4:"name";s:10:"${row}[ip]";}s:1:"E";a:3:{s:4:"type";s:9:"date-time";s:4:"name";s:10:"${row}[li]";s:8:"readonly";s:1:"1";}s:1:"F";a:3:{s:4:"type";s:9:"date-time";s:4:"name";s:10:"${row}[lo]";s:8:"readonly";s:1:"1";}s:1:"G";a:4:{s:4:"type";s:13:"date-duration";s:4:"name";s:13:"${row}[total]";s:8:"readonly";s:1:"1";s:4:"size";s:6:",hm,24";}s:1:"H";a:5:{s:4:"type";s:4:"hbox";s:4:"size";s:6:"2,,0,0";i:1;a:6:{s:4:"type";s:6:"button";s:4:"size";s:6:"delete";s:5:"label";s:6:"Delete";s:4:"name";s:28:"delete[$row_cont[sessionid]]";s:4:"help";s:21:"Delete this log entry";s:7:"onclick";s:40:"return confirm(\'Delete this log entry\');";}i:2;a:3:{s:4:"type";s:8:"checkbox";s:4:"size";s:20:"$row_cont[sessionid]";s:4:"name";s:10:"selected[]";}s:5:"align";s:6:"center";}}}s:4:"rows";i:2;s:4:"cols";i:8;s:4:"size";s:4:"100%";s:7:"options";a:1:{i:0;s:4:"100%";}}}','size' => '100%','style' => '','modified' => '1254816462',);
$templ_data[] = array('name' => 'admin.accesslog.rows','template' => '','lang' => '','group' => '0','version' => '1.9.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:6:{s:2:"c1";s:2:"th";s:2:"c2";s:3:"row";s:1:"G";s:10:",@no_total";s:1:"F";s:7:",@no_lo";s:1:"B";s:18:",@no_sessionstatus";s:1:"J";s:2:"1%";}i:1;a:10:{s:1:"A";a:3:{s:4:"type";s:23:"nextmatch-accountfilter";s:4:"size";s:7:"LoginID";s:4:"name";s:10:"account_id";}s:1:"B";a:3:{s:4:"type";s:16:"nextmatch-header";s:5:"label";s:12:"Login-Status";s:4:"name";s:13:"sessionstatus";}s:1:"C";a:3:{s:4:"type";s:16:"nextmatch-header";s:5:"label";s:7:"Loginid";s:4:"name";s:7:"loginid";}s:1:"D";a:3:{s:4:"type";s:16:"nextmatch-header";s:5:"label";s:2:"IP";s:4:"name";s:2:"ip";}s:1:"E";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:5:"Login";s:4:"name";s:2:"li";}s:1:"F";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:6:"Logout";s:4:"name";s:2:"lo";}s:1:"G";a:3:{s:4:"type";s:16:"nextmatch-header";s:5:"label";s:5:"Total";s:4:"name";s:5:"total";}s:1:"H";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:4:"Idle";s:4:"name";s:11:"session_dla";}s:1:"I";a:3:{s:4:"type";s:16:"nextmatch-header";s:5:"label";s:11:"Last action";s:4:"name";s:14:"session_action";}s:1:"J";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";i:1;a:3:{s:4:"type";s:5:"label";s:5:"label";s:7:"Actions";s:5:"align";s:6:"center";}i:2;a:4:{s:4:"type";s:10:"buttononly";s:4:"size";s:5:"check";s:5:"label";s:10:"Select all";s:7:"onclick";s:61:"toggle_all(this.form,form::name(\'selected[]\')); return false;";}}}i:2;a:10:{s:1:"A";a:4:{s:4:"type";s:14:"select-account";s:4:"name";s:18:"${row}[account_id]";s:8:"readonly";s:1:"1";s:5:"label";s:22:"$row_cont[alt_loginid]";}s:1:"B";a:2:{s:4:"type";s:5:"label";s:4:"name";s:21:"${row}[sessionstatus]";}s:1:"C";a:2:{s:4:"type";s:5:"label";s:4:"name";s:15:"${row}[loginid]";}s:1:"D";a:2:{s:4:"type";s:5:"label";s:4:"name";s:10:"${row}[ip]";}s:1:"E";a:3:{s:4:"type";s:9:"date-time";s:4:"name";s:10:"${row}[li]";s:8:"readonly";s:1:"1";}s:1:"F";a:3:{s:4:"type";s:9:"date-time";s:4:"name";s:10:"${row}[lo]";s:8:"readonly";s:1:"1";}s:1:"G";a:4:{s:4:"type";s:13:"date-duration";s:4:"name";s:13:"${row}[total]";s:8:"readonly";s:1:"1";s:4:"size";s:6:",hm,24";}s:1:"H";a:3:{s:4:"type";s:10:"date-since";s:4:"name";s:19:"${row}[session_dla]";s:8:"readonly";s:1:"1";}s:1:"I";a:2:{s:4:"type";s:5:"label";s:4:"name";s:22:"${row}[session_action]";}s:1:"J";a:6:{s:4:"type";s:4:"hbox";s:4:"size";s:6:"3,,0,0";i:1;a:6:{s:4:"type";s:6:"button";s:4:"size";s:6:"delete";s:5:"label";s:6:"Delete";s:4:"name";s:28:"delete[$row_cont[sessionid]]";s:4:"help";s:21:"Delete this log entry";s:7:"onclick";s:40:"return confirm(\'Delete this log entry\');";}i:2;a:5:{s:4:"type";s:6:"button";s:4:"size";s:5:"close";s:5:"label";s:4:"Kill";s:4:"name";s:26:"kill[$row_cont[sessionid]]";s:7:"onclick";s:63:"return confirm(\'Are you sure you want to kill this session ?\');";}s:5:"align";s:6:"center";i:3;a:4:{s:4:"type";s:8:"checkbox";s:4:"size";s:20:"$row_cont[sessionid]";s:4:"name";s:10:"selected[]";s:5:"align";s:5:"right";}}}}s:4:"rows";i:2;s:4:"cols";i:10;s:4:"size";s:4:"100%";s:7:"options";a:1:{i:0;s:4:"100%";}}}','size' => '100%','style' => '','modified' => '1254816462',);
$templ_data[] = array('name' => 'admin.applications','template' => '','lang' => '','group' => '0','version' => '1.7.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:4:{s:4:"type";s:9:"nextmatch";s:4:"size";s:4:"rows";s:4:"span";s:3:"all";s:4:"name";s:2:"nm";}}i:2;a:1:{s:1:"A";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";i:1;a:3:{s:4:"type";s:6:"button";s:5:"label";s:28:"Number applications serially";s:4:"name";s:6:"number";}i:2;a:2:{s:4:"type";s:5:"label";s:5:"label";s:157:"Number the applications serially. If they are not numbered serially, sorting the applications could work wrong. This will not change the application\'s order.";}}}}s:4:"rows";i:2;s:4:"cols";i:1;s:4:"size";s:7:"100%,,0";s:7:"options";a:2:{i:0;s:4:"100%";i:2;s:1:"0";}}}','size' => '100%,,0','style' => '','modified' => '1276610727',);

View File

@ -1,45 +1,58 @@
<?xml version="1.0"?>
<!-- $Id$ -->
<overlay>
<template id="admin.accesslog.rows" template="" lang="" group="0" version="1.7.001">
<template id="admin.accesslog.rows" template="" lang="" group="0" version="1.9.001">
<grid width="100%">
<columns>
<column/>
<column disabled="@no_sessionstatus"/>
<column/>
<column/>
<column/>
<column disabled="@no_lo"/>
<column disabled="@no_total"/>
<column/>
<column/>
<column width="1%"/>
</columns>
<rows>
<row class="th">
<nextmatch-accountfilter options="LoginID" id="account_id"/>
<nextmatch-header label="Login-Status" id="sessionstatus"/>
<nextmatch-header label="Loginid" id="loginid"/>
<nextmatch-header label="IP" id="ip"/>
<nextmatch-sortheader label="Login" id="li"/>
<nextmatch-sortheader label="Logout" id="lo"/>
<nextmatch-header label="Total" id="total"/>
<nextmatch-sortheader label="Idle" id="session_dla"/>
<nextmatch-header label="Last action" id="session_action"/>
<hbox>
<description value="Action" align="center"/>
<description value="Actions" align="center"/>
<buttononly options="check" label="Select all" onclick="toggle_all(this.form,form::name('selected[]')); return false;"/>
</hbox>
</row>
<row class="row">
<menulist>
<menupopup type="select-account" id="${row}[account_id]" readonly="true"/>
<menupopup type="select-account" id="${row}[account_id]" readonly="true" label="$row_cont[alt_loginid]"/>
</menulist>
<description id="${row}[sessionstatus]"/>
<description id="${row}[loginid]"/>
<description id="${row}[ip]"/>
<date-time id="${row}[li]" readonly="true"/>
<date-time id="${row}[lo]" readonly="true"/>
<date-duration id="${row}[total]" readonly="true" options=",hm,24"/>
<date-since id="${row}[session_dla]" readonly="true"/>
<description id="${row}[session_action]"/>
<hbox options="0,0" align="center">
<button image="delete" label="Delete" id="delete[$row_cont[sessionid]]" statustext="Delete this log entry" onclick="return confirm('Delete this log entry');"/>
<checkbox options="$row_cont[sessionid]" id="selected[]"/>
<button image="close" label="Kill" id="kill[$row_cont[sessionid]]" onclick="return confirm('Are you sure you want to kill this session ?');"/>
<checkbox options="$row_cont[sessionid]" id="selected[]" align="right"/>
</hbox>
</row>
</rows>
</grid>
</template>
<template id="admin.accesslog" template="" lang="" group="0" version="1.7.001">
<template id="admin.accesslog" template="" lang="" group="0" version="1.9.001">
<grid width="100%">
<columns>
<column/>
@ -51,16 +64,17 @@
<description/>
</row>
<row>
<nextmatch options="admin.accesslog.rows" id="nm" span="all"/>
<nextmatch span="all" id="nm" options="admin.accesslog.rows"/>
</row>
<row>
<hbox options="0,0">
<description value="Percent of users that logged out" readonly="true"/>
<textbox type="float" id="percent" precision="1" label=": %s %" readonly="true"/>
<description readonly="true" value="Percent of users that logged out"/>
<textbox type="float" precision="1" label=": %s %" readonly="true" id="percent"/>
</hbox>
<hbox align="right">
<button id="delete" image="delete" label="Delete" statustext="Delete selected entries" onclick="return confirm('Delete the selected entries');"/>
<buttononly options="arrow_ltr" onclick="toggle_all(this.form,form::name('nm[rows][selected][]')); return false;" class="selectAllArrow"/>
<button label="Delete" onclick="return confirm('Delete the selected entries');" id="delete" image="delete" statustext="Delete selected entries"/>
<button image="close" label="Kill" id="kill" onclick="return confirm('Are you sure you want to kill this session ?');"/>
<buttononly options="arrow_ltr" label="Select all" onclick="toggle_all(this.form,form::name('selected[]')); return false;"/>
</hbox>
</row>
</rows>

View File

@ -1,38 +0,0 @@
<!-- BEGIN list -->
<br>
<table border="0" width="95%" align="center">
<tr>
{left_next_matchs}
<td align="center">{start_total}</td>
{right_next_matchs}
</tr>
</td>
<table border="0" width="95%" align="center" class="egwGridView_grid">
<tr class="th">
<td>{sort_loginid}</td>
<td>{sort_ip}</td>
<td>{sort_login_time}</td>
<td>{sort_action}</td>
<td>{sort_idle}</td>
<td>{lang_kill}</td>
</tr>
{rows}
</table>
<br>
<!-- END list -->
<!-- BEGIN row -->
<tr bgcolor="{tr_color}">
<td>{row_loginid}</td>
<td>{row_ip}</td>
<td>{row_logintime}</td>
<td>{row_action}</td>
<td>{row_idle}</td>
<td>{row_kill}</td>
</tr>
<!-- END row -->

View File

@ -439,7 +439,7 @@ abstract class egw_framework
{
if( $GLOBALS['egw_info']['user']['apps']['admin'] && $GLOBALS['egw_info']['user']['preferences']['common']['show_currentusers'])
{
$current_users = '<a href="' . egw::link('/index.php','menuaction=admin.uicurrentsessions.list_sessions') . '">' .
$current_users = '<a href="' . egw::link('/index.php','menuaction=admin.admin_accesslog.sessions') . '">' .
lang('Current users') . ': ' . $GLOBALS['egw']->session->session_count() . '</a>';
return $current_users;
}

View File

@ -132,6 +132,13 @@ class egw_session
*/
var $kp3;
/**
* Primary key of egw_access_log row for updates
*
* @var int
*/
var $sessionid_access_log;
/**
* name of XML-RPC/SOAP method called
*
@ -579,7 +586,7 @@ class egw_session
$this->register_session($this->login,$user_ip,$now,$this->session_flags);
if ($this->session_flags != 'A') // dont log anonymous sessions
{
$this->log_access($this->sessionid,$login,$user_ip,$this->account_id);
$this->sessionid_access_log = $this->log_access($this->sessionid,$login,$user_ip,$this->account_id);
}
self::appsession('account_previous_login','phpgwapi',$GLOBALS['egw']->auth->previous_login);
$GLOBALS['egw']->accounts->update_lastlogin($this->account_id,$user_ip);
@ -640,10 +647,11 @@ class egw_session
/**
* Write or update (for logout) the access_log
*
* @param string $sessionid id of session or 0 for unsuccessful logins
* @param string|int $sessionid PHP sessionid or 0 for unsuccessful logins
* @param string $login account_lid (evtl. with domain) or '' for settion the logout-time
* @param string $user_ip ip to log
* @param int $account_id numerical account_id
* @return int $sessionid primary key of egw_access_log for login, null otherwise
*/
private function log_access($sessionid,$login='',$user_ip='',$account_id='')
{
@ -652,17 +660,24 @@ class egw_session
if ($login)
{
$GLOBALS['egw']->db->insert(self::ACCESS_LOG_TABLE,array(
'sessionid' => $sessionid,
'session_php' => $sessionid,
'loginid' => $login,
'ip' => $user_ip,
'li' => $now,
'lo' => 0,
'account_id'=> $account_id,
),false,__LINE__,__FILE__);
$ret = $GLOBALS['egw']->db->get_last_insert_id(self::ACCESS_LOG_TABLE,'sessionid');
}
else
{
$GLOBALS['egw']->db->update(self::ACCESS_LOG_TABLE,array('lo' => $now),array('sessionid' => $sessionid),__LINE__,__FILE__);
$GLOBALS['egw']->db->update(self::ACCESS_LOG_TABLE,array(
'lo' => $now
),is_numeric($sessionid) ? array(
'sessionid' => $sessionid,
) : array(
'session_php' => $sessionid,
),__LINE__,__FILE__);
}
if ($GLOBALS['egw_info']['server']['max_access_log_age'])
{
@ -670,6 +685,8 @@ class egw_session
$GLOBALS['egw']->db->delete(self::ACCESS_LOG_TABLE,"li < $max_age",__LINE__,__FILE__);
}
//error_log(__METHOD__."('$sessionid', '$login', '$user_ip', $account_id) returning ".array2string($ret));
return $ret;
}
/**
@ -861,6 +878,10 @@ class egw_session
{
$this->update_dla();
}
elseif ($GLOBALS['egw_info']['flags']['currentapp'] == 'notifications')
{
$this->update_notification_heartbeat();
}
$this->account_id = $GLOBALS['egw']->accounts->name2id($this->account_lid,'account_lid','u');
if (!$this->account_id)
{
@ -959,6 +980,15 @@ class egw_session
//echo 'DEBUG: Sessions: account_id is empty!<br>'."\n";
return false;
}
// query accesslog-id, if not set in session (session is made persistent after login!)
if (!$this->sessionid_access_log)
{
$this->sessionid_access_log = $GLOBALS['egw']->db->select(self::ACCESS_LOG_TABLE,'sessionid',array(
'session_php' => $this->sessionid,
),__LINE__,__FILE__)->fetchColumn();
//error_log(__METHOD__."() sessionid=$this->sessionid --> sessionid_access_log=$this->sessionid_access_log");
}
if (self::ERROR_LOG_DEBUG) error_log("--> session::verify($sessionid) SUCCESS");
return true;
@ -971,16 +1001,23 @@ class egw_session
* @param string $kp3
* @return boolean true on success, false on error
*/
function destroy($sessionid, $kp3)
function destroy($sessionid, $kp3='')
{
if (!$sessionid && $kp3)
{
return false;
}
$this->log_access($this->sessionid); // log logout-time
$this->log_access($sessionid); // log logout-time
if (self::ERROR_LOG_DEBUG) error_log(__METHOD__."($sessionid,$kp3) parent::destroy()=$ret");
if (is_numeric($sessionid)) // do we have a access-log-id --> get PHP session id
{
$sessionid = $GLOBALS['egw']->db->select(self::ACCESS_LOG_TABLE,'session_php',array(
'sessionid' => $sessionid,
),__LINE__,__FILE__)->fetchColumn();
}
$GLOBALS['egw']->hooks->process(array(
'location' => 'session_destroyed',
'sessionid' => $sessionid,
@ -1006,12 +1043,12 @@ class egw_session
}
else
{
$sessions = self::session_list(0,'','',true);
$this->commit_session(); // close our own session
if (isset($sessions[$sessionid]) && session_module_name() == 'files')
session_id($sessionid);
if (session_start())
{
//echo '<p>'.__METHOD__."($session_id): unlink('".$sessions[$sessionid]['php_session_file']."')</p>\n";
@unlink($sessions[$sessionid]['php_session_file']);
session_destroy();
}
}
return true;
@ -1318,24 +1355,41 @@ class egw_session
}
/**
* Update session_action and session_dla (session last used time),
* Update session_action and session_dla (session last used time)
*/
private function update_dla()
{
if (isset($_GET['menuaction']))
// This way XML-RPC users aren't always listed as xmlrpc.php
if ($this->xmlrpc_method_called)
{
$action = $this->xmlrpc_method_called;
}
elseif (isset($_GET['menuaction']))
{
$action = $_GET['menuaction'];
}
else
{
$action = $_SERVER['PHP_SELF'];
// remove EGroupware path, if not installed in webroot
$egw_path = $GLOBALS['egw_info']['server']['webserver_url'];
if ($egw_path[0] != '/') $egw_path = parse_url($egw_path,PHP_URL_PATH);
if ($egw_path)
{
list(,$action) = explode($egw_path,$action,2);
}
}
// This way XML-RPC users aren't always listed as
// xmlrpc.php
if ($this->xmlrpc_method_called)
// update dla in access-log table, if we have an access-log row (non-anonymous session)
if ($this->sessionid_access_log)
{
$action = $this->xmlrpc_method_called;
$GLOBALS['egw']->db->update(self::ACCESS_LOG_TABLE,array(
'session_dla' => time(),
'session_action' => $action,
'lo' => null, // just in case it was (automatic) timed out before
),array(
'sessionid' => $this->sessionid_access_log,
),__LINE__,__FILE__);
}
$_SESSION[self::EGW_SESSION_VAR]['session_dla'] = time();
@ -1343,6 +1397,23 @@ class egw_session
if (self::ERROR_LOG_DEBUG) error_log(__METHOD__.'() _SESSION['.self::EGW_SESSION_VAR.']='.array2string($_SESSION[self::EGW_SESSION_VAR]));
}
/**
* Update notification_heartbeat time of session
*/
private function update_notification_heartbeat()
{
// update dla in access-log table, if we have an access-log row (non-anonymous session)
if ($this->sessionid_access_log)
{
$GLOBALS['egw']->db->update(self::ACCESS_LOG_TABLE,array(
'notification_heartbeat' => time(),
),array(
'sessionid' => $this->sessionid_access_log,
'lo IS NULL',
),__LINE__,__FILE__);
}
}
/**
* Read the diverse repositories / init classes with data from the just loged in user
*
@ -1471,32 +1542,80 @@ class egw_session
* Get a session list (of the current instance)
*
* @param int $start
* @param string $sort='session_dla' session_lid, session_id, session_started, session_logintime, session_action, or (default) session_dla
* @param string $order='DESC' ASC or DESC
* @param string $sort='DESC' ASC or DESC
* @param string $order='session_dla' session_lid, session_id, session_started, session_logintime, session_action, or (default) session_dla
* @param boolean $all_no_sort=False skip sorting and limiting to maxmatchs if set to true
* @return array with sessions (values for keys as in $sort) or array() if not supported by session-handler
* @return array with sessions (values for keys as in $sort)
*/
public static function session_list($start,$sort='DESC',$order='session_dla',$all_no_sort=False)
{
if (method_exists(self::$session_handler,'session_list'))
$sessions = array();
if (!preg_match('/^[a-z0-9_ ,]+$/i',$order_by=$order.' '.$sort))
{
return call_user_func(array(self::$session_handler,'session_list'),$start,$sort,$order,$all_no_sort);
$order_by = 'session_dla DESC';
}
return array();
foreach($GLOBALS['egw']->db->select(self::ACCESS_LOG_TABLE, '*', array(
'lo' => null,
'session_dla > '.(int)(time() - $GLOBALS['egw_info']['server']['sessions_timeout']),
'(notification_heartbeat IS NULL OR notification_heartbeat > '.self::heartbeat_limit().')',
), __LINE__, __FILE__, $all_no_sort ? false : $start, 'ORDER BY '.$order_by) as $row)
{
$sessions[$row['sessionid']] = $row;
}
return $sessions;
}
/**
* Query number of sessions (not more then once every N secs)
*
* @return int|boolean integer number of sessions or false if not supported by session-handler
* @return int number of active sessions
*/
public static function session_count()
{
if (method_exists(self::$session_handler,'session_count'))
return $GLOBALS['egw']->db->select(self::ACCESS_LOG_TABLE, 'COUNT(*)', array(
'lo' => null,
'session_dla > '.(int)(time() - $GLOBALS['egw_info']['server']['sessions_timeout']),
'(notification_heartbeat IS NULL OR notification_heartbeat > '.self::heartbeat_limit().')',
), __LINE__, __FILE__)->fetchColumn();
}
/**
* Get limit / latest time of heartbeat for session to be active
*
* @return int TS in server-time
*/
public static function heartbeat_limit()
{
static $limit;
if (is_null($limit))
{
return call_user_func(array(self::$session_handler,'session_count'));
$config = config::read('notifications');
if (!($popup_poll_interval = $config['popup_poll_interval']))
{
$popup_poll_interval = 60;
}
$limit = (int)(time() - $popup_poll_interval-10); // 10s grace periode
}
return false;
return $limit;
}
/**
* Check if given user can be reached via notifications
*
* Checks if notifications callback checked in not more then heartbeat_limit() seconds ago
*
* @param int $account_id
* @param int number of active sessions of given user with notifications running
*/
public static function notifications_active($account_id)
{
return $GLOBALS['egw']->db->select(self::ACCESS_LOG_TABLE, 'COUNT(*)', array(
'lo' => null,
'session_dla > '.(int)(time() - $GLOBALS['egw_info']['server']['sessions_timeout']),
'account_id' => $account_id,
'notifications_heartbeat > '.self::heartbeat_limit(),
), __LINE__, __FILE__)->fetchColumn();
}
/*

View File

@ -616,7 +616,23 @@ class schema_proc
$blob_column_included = $auto_column_included = False;
foreach($aTableDef['fd'] as $name => $data)
{
if ($aDefaults && isset($aDefaults[$name])) // use given default
// new auto column with no default or explicit NULL as default (can be an existing column too!)
if ($data['type'] == 'auto' &&
(!isset($old_table_def['fd'][$name]) && (!$aDefaults || !isset($aDefaults[$name])) ||
$aDefaults && strtoupper($aDefaults[$name]) == 'NULL'))
{
$sequence_name = $sTableName.'_'.$name.'_seq';
switch($GLOBALS['egw_setup']->db->Type)
{
case 'mysql':
$value = 'NULL'; break;
case 'pgsql':
$value = "nextval('$sequence_name'::regclass)"; break;
default:
$value = "nextval('$sequence_name')"; break;
}
}
elseif ($aDefaults && isset($aDefaults[$name])) // use given default
{
$value = $aDefaults[$name];
}
@ -690,10 +706,11 @@ class schema_proc
$Ok = $this->RenameTable($sTableName,$tmp_name);
}
$Ok = $Ok && $this->CreateTable($sTableName,$aTableDef) &&
$this->m_odb->query("$extra INSERT INTO $sTableName (".
$this->m_odb->query($sql_copy_data="$extra INSERT INTO $sTableName (".
implode(',',array_keys($aTableDef['fd'])).
") SELEcT $distinct $select FROM $tmp_name",__LINE__,__FILE__) &&
$this->DropTable($tmp_name);
//error_log($sql_copy_data);
if (!$Ok)
{

View File

@ -12,7 +12,7 @@
/* Basic information about this app */
$setup_info['phpgwapi']['name'] = 'phpgwapi';
$setup_info['phpgwapi']['title'] = 'eGroupWare API';
$setup_info['phpgwapi']['version'] = '1.9.007';
$setup_info['phpgwapi']['version'] = '1.9.008';
$setup_info['phpgwapi']['versions']['current_header'] = '1.29';
$setup_info['phpgwapi']['enable'] = 3;
$setup_info['phpgwapi']['app_order'] = 1;
@ -74,3 +74,4 @@ $setup_info['groupdav']['author'] = $setup_info['groupdav']['maintainer'] = arra
$setup_info['groupdav']['license'] = 'GPL';
$setup_info['groupdav']['hooks']['preferences'] = 'groupdav_hooks::menus';
$setup_info['groupdav']['hooks']['settings'] = 'groupdav_hooks::settings';

View File

@ -83,16 +83,20 @@ $phpgw_baseline = array(
),
'egw_access_log' => array(
'fd' => array(
'sessionid' => array('type' => 'char','precision' => '128','nullable' => False),
'loginid' => array('type' => 'varchar','precision' => '64','nullable' => False),
'ip' => array('type' => 'varchar','precision' => '40','nullable' => False),
'li' => array('type' => 'int','precision' => '4','nullable' => False),
'lo' => array('type' => 'int','precision' => '4','default' => '0'),
'account_id' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '0')
'sessionid' => array('type' => 'auto','nullable' => False,'comment' => 'primary key'),
'loginid' => array('type' => 'varchar','precision' => '64','nullable' => False,'comment' => 'username used to login'),
'ip' => array('type' => 'varchar','precision' => '40','nullable' => False,'comment' => 'ip of user'),
'li' => array('type' => 'int','precision' => '8','nullable' => False,'comment' => 'TS if login'),
'lo' => array('type' => 'int','precision' => '8','comment' => 'TD of logout'),
'account_id' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '0','comment' => 'numerical account id'),
'session_dla' => array('type' => 'int','precision' => '8','comment' => 'TS of last user action'),
'session_action' => array('type' => 'varchar','precision' => '64','comment' => 'menuaction or path of last user action'),
'session_php' => array('type' => 'varchar','precision' => '64','nullable' => False,'comment' => 'php session-id or error-message'),
'notification_heartbeat' => array('type' => 'int','precision' => '8','comment' => 'TS of last notification request')
),
'pk' => array(),
'pk' => array('sessionid'),
'fk' => array(),
'ix' => array('li'),
'ix' => array('li','lo','session_dla','notification_heartbeat'),
'uc' => array()
),
'egw_hooks' => array(

View File

@ -173,3 +173,33 @@ function phpgwapi_upgrade1_9_006()
return $GLOBALS['setup_info']['phpgwapi']['currentver'] = '1.9.007';
}
/**
* Add columns for session list (dla, action), make sessionid primary key and TS 64bit
*/
function phpgwapi_upgrade1_9_007()
{
$GLOBALS['egw_setup']->oProc->RefreshTable('egw_access_log',array(
'fd' => array(
'sessionid' => array('type' => 'auto','nullable' => False,'comment' => 'primary key'),
'loginid' => array('type' => 'varchar','precision' => '64','nullable' => False,'comment' => 'username used to login'),
'ip' => array('type' => 'varchar','precision' => '40','nullable' => False,'comment' => 'ip of user'),
'li' => array('type' => 'int','precision' => '8','nullable' => False,'comment' => 'TS if login'),
'lo' => array('type' => 'int','precision' => '8','comment' => 'TD of logout'),
'account_id' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '0','comment' => 'numerical account id'),
'session_dla' => array('type' => 'int','precision' => '8','comment' => 'TS of last user action'),
'session_action' => array('type' => 'varchar','precision' => '64','comment' => 'menuaction or path of last user action'),
'session_php' => array('type' => 'char','precision' => '64','nullable' => False,'comment' => 'php session-id or error-message'),
'notification_heartbeat' => array('type' => 'int','precision' => '8','comment' => 'TS of last notification request')
),
'pk' => array('sessionid'),
'fk' => array(),
'ix' => array('li','lo','session_dla','notification_heartbeat'),
'uc' => array()
),array(
'session_php' => 'sessionid',
'sessionid' => 'NULL', // to NOT copy old sessionid, but create a new sequence
));
return $GLOBALS['setup_info']['phpgwapi']['currentver'] = '1.9.008';
}