array( 'name' => t('Automated logout'), 'module' => 'autologout', 'description' => t('Manage the automated logout features') ) ); } /* }}} */ /* {{{ autologout_perm() */ /** * Implementation of hook_perm(). */ function autologout_perm() { _autologout_debug("autologout_perm()"); return array('administer autologout'); } /* }}} */ /* {{{ autologout_block() */ /** * Implementation of hook_block(). */ function autologout_block($op = 'list', $delta = 0, $edit = array()) { global $user; // Turn block off if module turned off, anonymous user, or exluded by role. if (!_autologout_local_settings('enabled') || $user->uid == 0 || _autologout_exclude_by_role()) { return; } switch ($op) { case 'list': $block[0]['info'] = t('Automated Logout info'); return $block; break; case 'configure': if (module_exists('jstimer')) { if (!module_exists('jst_timer')) { drupal_set_message(t('The "Widget: timer" module must also be enabled for the dynamic countdown to work in the automated logout block.'), 'error'); } if (variable_get('jstimer_js_load_option', 0) != 1) { drupal_set_message(t('The Javascript timer module\'s "Javascript load options" setting should be set to "Every page" for the dynamic countdown to work in the automated logout block.'), 'error'); } } case 'save': break; case 'view': $refresh = (int)_autologout_local_settings('refresh_delta'); $timeout = _autologout_local_settings('timeout'); $block['subject'] = filter_xss_admin(_autologout_local_settings('block_title')); if (module_exists('jstimer') && module_exists('jst_timer')) { $logout_message = filter_xss_admin(_autologout_local_settings('logout_message')); $block['content'] = theme('jstimer', 'jst_timer', array( 'interval' => $timeout, 'threshold' => 5, 'format_txt' => filter_xss_admin(variable_get('autologout_jstimer_format', '%hours%:%mins%:%secs%')), 'complete' => $logout_message .' '. ($refresh ? ' '. t('This page will refresh in %refresh seconds.', array('%refresh' => $refresh)) : ''), 'no_js_txt' => t('You will be logged out in !time if this page is not refreshed before then.', array('!time' => format_interval($timeout))) )); } else { $block['content'] = t('You will be logged out in !time if this page is not refreshed before then.', array('!time' => format_interval($timeout))); } $logout_message = filter_xss_admin(_autologout_local_settings('logout_message')); if ( $logout_message != '' ) { $block['content'] .=''; } break; } return $block; } /* }}} */ /* {{{ autologout_help() */ /** * Implementation of hook_help(). */ function autologout_help($path, $arg) { switch ($path) { case 'admin/help#autologout': $output = '
'. t('The Automated Logout module allows you to force users to log out after a given amount of time. You can configure this in the Automated logout settings page.', array('@alo_settings' => url('admin/settings/autologout'))) . '
'; $output .= ''. t('If you have the Javascript timer module enabled, the Automated Logout block will have a live countdown timer.', array('@automatedlogoutblock' => url('admin/build/block'), '@jstimer' => 'http://drupal.org/project/jstimer')) . '
'; return $output; } } /* }}} */ /** * Implementation of hook_boot(). * NOTE: Do as little as possible here. A lot of modules are not loaded at this point. */ function autologout_boot() { if ( !isset($_SESSION['autologout_hits']) ) { $_SESSION['autologout_hits'] = array(); } $_SESSION['autologout_hits'][] = time(); } /* {{{ autologout_init() */ /** * Implementation of hook_init(). */ function autologout_init() { // We have to perform a load in order to assure that the $user->autologout bits are present. global $user; if ($user->uid) { // $user gets modified by reference. autologout_user('load', array(), $user); } else { $user->autologout = 0; return; } // Check for enabled autologout and excluded users. if (_autologout_local_settings('enabled') && !_autologout_exclude_by_role()) { $timeout = (int)_autologout_local_settings('timeout'); $nowtime = time(); if (!isset($_SESSION['lastaccess'])) { $_SESSION['lastaccess'] = $nowtime; } // update lastaccess from any cache hits which wouldn't have been processes by hook_init() if ( isset($_SESSION['autologout_hits']) ) { foreach($_SESSION['autologout_hits'] as $hit) { if ( (int)$hit - (int)$_SESSION['lastaccess'] > 0 ) { // if hit wouldn't have timedout, update lastaccess if ( ((int)$hit - (int)$_SESSION['lastaccess']) < $timeout ) { // rebase lastaccess $_SESSION['lastaccess'] = $hit; } } } } // now normal processing because the cache hits have been accounted for. if ( ($nowtime - (int)$_SESSION['lastaccess']) < $timeout ) { // the timeout has not yet occurred. $_SESSION['lastaccess'] = $nowtime; $_SESSION['autologout_hits'] = array($nowtime); $refresh = (int)_autologout_local_settings('refresh_delta'); if ($refresh >= 0) { $force_refresh = $timeout + $refresh; $this_header = ""; $this_head = drupal_set_html_head($this_header); } } else { // timeout occured, logout and end session unset($_SESSION['lastaccess']); if (_autologout_local_settings('use_watchdog')) { watchdog('autologout', 'User %name automatically logged out.', array('%name' => $user->name)); } // code from core(user.pages.inc), can't use it directly because we need need a custom goto watchdog('user', 'Session closed for %name.', array('%name' => $user->name)); // Destroy the current session: session_destroy(); // Only variables can be passed by reference workaround. $null = NULL; user_module_invoke('logout', $null, $user); // Load the anonymous user $user = drupal_anonymous_user(); $redirect_url = filter_xss_admin(_autologout_local_settings('redirect_url')); if ( $redirect_url != '' ) { drupal_goto($redirect_url); } else { drupal_goto('autologout/logout', drupal_get_destination()); } return; } } // Clear session variable if you are not using autologout function and for anonymous users. if ( isset($_SESSION['autologout_hits']) && (! _autologout_local_settings('enabled') || $user->uid == 0) ) { unset($_SESSION['autologout_hits']); } } /* }}} */ /* {{{ autologout_user() */ /** * Implementation of hook_user(). */ function autologout_user($op, $edit, &$account, $category = NULL) { // Do nothing for anonymous users. if ($account->uid == 0) { return; } if ($op == 'form' && $category == 'account') { if (_autologout_user_in_by_user_role($account)) { $form = array(); $form[$category]['autologout'] = array( '#type' => 'checkbox', '#title' => t('Disable inactivity Automated Logout'), '#default_value' => $account->autologout, '#weight' => 10, ); return $form; } } else if ($op == 'login') { // one session checking $return = _autologout_check_one_session(); if ($return) { _autologout_invalidate_other_sessions($account); } $_SESSION['lastaccess'] = time(); } else if ($op == 'load') { if (_autologout_user_in_by_user_role($account)) { $account->autologout = 0; $result = db_query("SELECT setting FROM {autologout} WHERE uid = %d", $account->uid); while ($row = db_fetch_object($result)) { $account->autologout = (int)$row->setting; } } } else if ($op == 'update') { if (_autologout_user_in_by_user_role($account)) { if (isset($edit['autologout'])) { db_query("DELETE FROM {autologout} WHERE uid = %d", $account->uid); db_query("INSERT INTO {autologout} SET uid = %d, setting = %d", $account->uid, $edit['autologout']); // If they are turning off the disable setting, set lastaccess so they are not immediately logged out. if ($edit['autologout'] == 0) { $_SESSION['lastaccess'] = $nowtime; } } } } else if ($op == 'delete') { db_query("DELETE FROM {autologout} WHERE uid = %d", $account->uid); } return; } /* {{{ autologout_nodeapi() */ /** * Implementation of hook_nodeapi(). */ function autologout_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) { _autologout_debug("autologout_nodeapi($op)"); // if a user is entering data then don't log them out or // they will loose their work. There's nothing more // frustrating than entering alot of info only for a // website to throw it away! switch ($op) { case "insert": case "update": case "execute": case "validate": case "prepare": case "delete": $_SESSION['lastaccess'] = time(); break; } } /* }}} */ /* {{{ autologout_menu() */ /** * Implementation of hook_menu(). */ function autologout_menu() { $items['admin/settings/autologout'] = array( 'title' => t('Automated logout'), 'description' => t('Manage the Automated Logout features'), 'page callback' => 'drupal_get_form', 'page arguments' => array('autologout_admin_settings'), 'access arguments' => array('administer autologout'), 'file' => 'autologout.admin.inc', 'type' => MENU_NORMAL_ITEM ); $items['autologout/logout'] = array( 'title' => t('Automated logout'), 'page callback' => 'autologout_logout', 'access callback' => TRUE, 'type' => MENU_CALLBACK ); return $items; } /* }}} */ /* ========================= */ /* Helper functions follow */ /* ========================= */ /* {{{ _autologout_exclude_by_role() */ /** * _autologout_exclude_by_role() * * Is the user in a role that we exclude from features defined by this module * * @param $account * A drupal "user" object or default FALSE (use global $user) * * @return bool * TRUE if user to be excluded, FALSE otherwise */ function _autologout_exclude_by_role($account = NULL) { global $user; if ($account == NULL) { $account = $user; } foreach (user_roles(TRUE) as $role) { switch (_autologout_local_settings($role)) { case 0: // Enforce for all in this role break; case 1: // Exclude all users in this role if (in_array($role, array_values($account->roles))) { return TRUE; } break; case 2: // Exclude user if user set to disable if (in_array($role, array_values($account->roles))) { if ($account->autologout == 1) { return TRUE; } } break; } } return FALSE; } /* }}} */ /* {{{ _autologout_user_in_by_user_role() */ function _autologout_user_in_by_user_role($account = NULL) { global $user; if ($account == NULL) { $account = $user; } foreach (user_roles(TRUE) as $role) { if (_autologout_local_settings($role) == 2 && in_array($role, array_values($account->roles))) { return TRUE; } } return FALSE; } /* }}} */ /* {{{ _autologout_local_settings() */ /** * _autologout_local_settings($name = FALSE) * * Used to get a modules "settings" value. Note, the "out of box" * settings are defined by the place holder class * * @see autologout_default_settings() * * @param $name * A string of the variable name to get or FALSE return all variables as array * * @return mixed * array of all variables (if param was false) * string the named variabled value */ function _autologout_local_settings($name = FALSE) { // Default settings. $defaults = array( 'enabled' => FALSE, 'timeout' => 3600, 'refresh_delta' => 0, 'use_watchdog' => 1, 'block_title' => t('automatic logout in'), 'logout_message' => t('You have been automatically logged out due to inactivity.'), ); if (!($settings = variable_get('autologout', FALSE))) { $settings = $defaults; } if (FALSE != $name) { if (!isset($settings[$name]) && isset($defaults[$name])) { return $defaults[$name]; } elseif (!isset($settings[$name]) && !isset($defaults[$name])) { return NULL; } else { return $settings[$name]; } } else { return $settings; // return the entire array } } /* }}} */ /** * theme_autologout_generic() * * A general theme function used when HTML is being inserted into * a text string. Allows themers the oppertunity to alter html the * module may want to output to suit their site/theme. * * @param integer $arg * A constant defining what string to return. * @return string * The actual string. */ function theme_autologout_generic($arg = 0) { switch ($arg) { case 0: return '