Typesetter/include/tool/Session.php

1234 lines
28 KiB
PHP
Raw Permalink Normal View History

2021-09-08 19:52:21 +02:00
<?php
namespace gp\tool;
defined('is_running') or die('Not an entry point...');
gp_defined('gp_lock_time',900); // = 15 minutes
class Session{
private static $singleton;
private $logged_in = false;
private $session_id;
private $session_file;
public static function Init(){
return self::getInstance();
}
/**
* Get singleton instance
* @return \gp\tool\Session
*/
public static function getInstance(){
if( !isset(self::$singleton) ){
self::$singleton = new static();
}
return self::$singleton;
}
public function __construct(){
self::SetConstants();
if( isset($_COOKIE[gp_session_cookie]) ){
self::CheckPosts();
$this->Start($_COOKIE[gp_session_cookie]);
}
$cmd = \gp\tool::GetCommand();
switch( $cmd ){
case 'logout':
$this->LogOut();
return;
case 'login':
$this->LogIn();
return;
}
if( $this->logged_in ){
$this->Prepare();
}
if( $cmd === 'ClearErrors' ){
self::ClearErrors();
}
}
public static function SetConstants(){
global $config;
gp_defined('gp_session_cookie',self::SessionCookie($config['gpuniq']));
gp_defined('gp_installation_cookie',self::SessionCookie('g-'.$config['gpuniq']));
}
public function LogIn(){
global $langmessage;
if( $this->logged_in ){
return;
}
// check nonce
// expire the nonce after 10 minutes
$nonce = $_POST['login_nonce'];
if( !\gp\tool\Nonce::Verify('login_nonce', $nonce, true, 300) ){
msg($langmessage['OOPS'] . ' (Expired Nonce)');
return;
}
if( !self::HasCookies() ){
msg($langmessage['COOKIES_REQUIRED']);
return false;
}
//delete the entry in $sessions if we're going to create another one with login
if( isset($_COOKIE[gp_session_cookie]) ){
self::CleanSession($_COOKIE[gp_session_cookie]);
}
$users = \gp\tool\Files::Get('_site/users');
$username = self::GetLoginUser($users, $nonce);
if( $username === false ){
self::IncorrectLogin('1');
return false;
}
$users[$username] += array(
'attempts' => 0,
'granted' => '', // 'editing' will be set EditingValue()
);
$userinfo = $users[$username];
//Check Attempts
if( $userinfo['attempts'] >= 5 ){
$timeDiff = (time() - $userinfo['lastattempt']) / 60; //minutes
if( $timeDiff < 10 ){
msg($langmessage['LOGIN_BLOCK'], ceil(10 - $timeDiff));
return false;
}
}
//check against password sent to a user's email address from the forgot_password form
$passed = self::PasswordPassed($userinfo, $nonce);
//if passwords don't match
if( $passed !== true ){
self::IncorrectLogin('2');
self::UpdateAttempts($users, $username);
return false;
}
//will be saved in UpdateAttempts
if( isset($userinfo['newpass']) ){
unset($userinfo['newpass']);
}
$session_id = self::create($userinfo, $username, $sessions);
if( !$session_id ){
msg($langmessage['OOPS'] . ' (Data Not Saved)');
self::UpdateAttempts($users, $username, true);
return false;
}
if( $this->Start($session_id, $sessions) ){
msg($langmessage['logged_in']);
}
//need to save the user info regardless of success or not
//also saves file_name in users.php
$users[$username] = $userinfo;
self::UpdateAttempts($users, $username, true);
//redirect to prevent resubmission
$this->Redirect();
}
/**
* Return true if we can confirm there are cookies
* Return false and attempt to set a cookie otherwise
*
*/
public static function HasCookies(){
global $config;
self::SetConstants();
if( array_key_exists(gp_session_cookie, $_COOKIE) ||
array_key_exists(gp_installation_cookie, $_COOKIE)
){
return true;
}
\gp\tool\Session::cookie(gp_installation_cookie,'2');
return false;
}
/**
* Redirect user after login
*
*/
public function Redirect(){
global $gp_index;
if( !$this->logged_in ){
return;
}
$redirect = false;
if( isset($_REQUEST['file']) ){
$redirect = \gp\tool::ArrayKey($_REQUEST['file'], $gp_index );
}
if( $redirect === false ){
$redirect = 'Admin';
}
$url = \gp\tool::GetUrl($redirect, '', false);
\gp\tool::Redirect($url);
}
/**
* Return the username for the login request
*
*/
public static function GetLoginUser( $users, $nonce ){
$_POST += array(
'user_sha' => '',
'username' => '',
'login_nonce' => '',
);
if( gp_require_encrypt && empty($_POST['user_sha']) ){
return false;
}
foreach($users as $username => $info){
$sha_user = sha1($nonce.$username);
if( !gp_require_encrypt
&& !empty($_POST['username'])
&& $_POST['username'] == $username
){
return $username;
}
if( $sha_user === $_POST['user_sha'] ){
return $username;
}
}
return false;
}
/**
* Check the posted password
* Check against reset password if set
*
*/
public static function PasswordPassed(&$userinfo, $nonce){
if( gp_require_encrypt && !empty($_POST['password']) ){
return false;
}
//if not encrypted with js
if( !empty($_POST['password']) ){
$_POST['pass_md5'] = sha1($nonce . md5($_POST['password']));
$_POST['pass_sha'] = sha1($nonce . sha1($_POST['password']));
$_POST['pass_sha512'] = \gp\tool::hash($_POST['password'], 'sha512', 50);
}
$pass_algo = self::PassAlgo($userinfo);
if( !empty($userinfo['newpass']) && self::CheckPassword($userinfo['newpass'], $nonce, $pass_algo) ){
$userinfo['password'] = $userinfo['newpass'];
return true;
}
//check password
if( self::CheckPassword($userinfo['password'], $nonce, $pass_algo) ){
return true;
}
return false;
}
/**
* Return the algorithm used by the user for passwords
*
*/
public static function PassAlgo($userinfo){
global $config;
if( isset($userinfo['passhash']) ){
return $userinfo['passhash'];
}
return $config['passhash'];
}
/**
* Check password, choose between plaintext, md5 encrypted or sha-1 encrypted
* @param string $user_pass
* @param string $nonce
* @param string $pass_algo Password hashing algorithm
*
*/
public static function CheckPassword($user_pass, $nonce, $pass_algo){
global $config;
$posted_pass = false;
switch($pass_algo){
case 'md5':
$posted_pass = $_POST['pass_md5'];
$user_pass = sha1($nonce . $user_pass);
break;
case 'sha1':
$posted_pass = $_POST['pass_sha'];
$user_pass = sha1($nonce . $user_pass);
break;
case 'sha512':
//javascript only loops through sha512 50 times
$posted_pass = \gp\tool::hash($_POST['pass_sha512'], 'sha512', 950);
break;
case 'password_hash':
if( !function_exists('password_verify') ){
msg('This version of PHP does not have password_verify(). '
. 'To fix, reset your password at /Admin_Preferences and '
. 'select "sha512" for the "Password Algorithm"');
return false;
}
return password_verify($_POST['pass_sha512'], $user_pass);
}
if( $posted_pass && $posted_pass === $user_pass ){
return true;
}
return false;
}
public static function IncorrectLogin($i){
global $langmessage;
msg($langmessage['incorrect_login'] . ' (' . $i . ')');
$url = \gp\tool::GetUrl('Admin', 'cmd=forgotten');
msg($langmessage['forgotten_password'], $url);
}
/**
* Set the value of $userinfo['file_name']
*
*/
public static function SetSessionFileName($userinfo,$username){
global $dataDir;
if( isset($userinfo['file_name']) ){
return $userinfo;
}
do{
$new_file_name = 'gpsess_' . \gp\tool::RandomString(40) . '.php';
$new_file = $dataDir . '/data/_sessions/' . $new_file_name;
}while( \gp\tool\Files::Exists($new_file) );
$userinfo['file_name'] = $new_file_name;
return $userinfo;
}
public function LogOut(){
global $langmessage;
if( empty($_GET['verified']) ){
return;
}
if( !\gp\tool\Nonce::Verify('post', $_GET['verified'], true) ){
return;
}
if( !$this->logged_in ){
return false;
}
if( !isset($_COOKIE[gp_session_cookie]) ){
return false;
}
$session_id = $_COOKIE[gp_session_cookie];
self::Unlock($session_id);
self::cookie(gp_session_cookie);
self::CleanSession($session_id);
$this->logged_in = false;
msg($langmessage['LOGGED_OUT']);
}
/**
* Remove the admin session lock
*
*/
public static function Unlock($session_id){
return \gp\tool\Files::Unlock('admin', sha1(sha1($session_id)));
}
public static function CleanSession($session_id){
//remove the session_id from session_ids.php
$sessions = self::GetSessionIds();
unset($sessions[$session_id]);
self::SaveSessionIds($sessions);
}
/**
* Set a session cookie
* Attempt to use httponly if available
*
*/
public static function Cookie($name, $value='', $expires = false){
global $dirPrefix;
$cookiePath = empty($dirPrefix) ? '/' : $dirPrefix;
$cookiePath = \gp\tool::HrefEncode($cookiePath, false);
$secure = (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on');
$domain = \gp\tool::ServerName(true);
if( !$domain || strpos($domain, '.') === false ){
$domain = '';
}
if( strpos($domain, ':') !== false ){
$domain = substr($domain, 0, strrpos($domain, ':'));
}
// expire if value is empty
// cookies are set with either www removed from the domain or with an empty string
if( empty($value) ){
$expires = time()-2592000;
setcookie($name, $value, $expires, $cookiePath, $domain, $secure, true);
setcookie($name, $value, $expires, $cookiePath, $domain, false, true);
return;
}
// get expiration and set
if( $expires === false ){
$expires = time()+2592000; //30 days
}elseif( $expires === true ){
$expires = 0; //expire at end of session
}
setcookie($name, $value, $expires, $cookiePath, $domain, $secure, true);
}
/**
* Update the number of login attempts and the time of the last attempt for a $username
*
*/
public static function UpdateAttempts($users,$username,$reset = false){
if( $reset ){
$users[$username]['attempts'] = 0;
}else{
$users[$username]['attempts']++;
}
$users[$username]['lastattempt'] = time();
\gp\tool\Files::SaveData('_site/users', 'users', $users);
}
/**
* called when a user logs in
*
*/
public static function create(&$user_info, $username, &$sessions){
global $dataDir, $langmessage;
//update the session files to .php files
//changes to $userinfo will be saved by UpdateAttempts() below
$user_info = self::SetSessionFileName($user_info, $username);
$user_file_name = $user_info['file_name'];
$user_file = $dataDir . '/data/_sessions/' . $user_file_name;
//use an existing session_id if the new login matches an existing session (uid and file_name)
$sessions = self::GetSessionIds();
$uid = self::auth_browseruid();
$session_id = false;
foreach($sessions as $sess_temp_id => $sess_temp_info){
if( isset($sess_temp_info['uid']) &&
$sess_temp_info['uid'] == $uid &&
$sess_temp_info['file_name'] == $user_file_name
){
$session_id = $sess_temp_id;
}
}
//create a unique session id if needed
if( $session_id === false ){
do{
$session_id = \gp\tool::RandomString(40);
}while( isset($sessions[$session_id]) );
}
$expires = !isset($_POST['remember']);
self::cookie(gp_session_cookie, $session_id, $expires);
//save session id
$sessions[$session_id] = array();
$sessions[$session_id]['file_name'] = $user_file_name;
$sessions[$session_id]['uid'] = $uid;
//$sessions[$session_id]['time'] = time(); //for session locking
if( !self::SaveSessionIds($sessions) ){
return false;
}
//make sure the user's file exists
$new_data = self::SessionData($user_file,$checksum);
$new_data['username'] = $username;
$new_data['granted'] = $user_info['granted'];
if( isset($user_info['editing']) ){
$new_data['editing'] = $user_info['editing'];
}
\gp\admin\Tools::EditingValue($new_data);
// may needt to extend the cookie life later
if( isset($_POST['remember']) ){
$new_data['remember'] = time();
}else{
unset($new_data['remember']);
}
\gp\tool\Files::SaveData($user_file, 'gpAdmin', $new_data);
return $session_id;
}
/**
* Return the contents of the session_ids.php data file
* @return array array of all sessions
*/
public static function GetSessionIds(){
return \gp\tool\Files::Get('_site/session_ids', 'sessions');
}
/**
* Save $sessions to the session_ids.php data file
* @param $sessions array array of all sessions
* @return bool
*/
public static function SaveSessionIds($sessions){
while( $current = current($sessions) ){
$key = key($sessions);
//delete if older than
if( isset($current['time']) && $current['time'] > 0 && ($current['time'] < (time() - 1209600)) ){
//if( $current['time'] < time() - 2592000 ){ //one month
unset($sessions[$key]);
$continue = true;
}else{
next($sessions);
}
}
//clean
return \gp\tool\Files::SaveData('_site/session_ids', 'sessions', $sessions);
}
/**
* Determine if $session_id represents a valid session and if so start the session
*
*/
public function Start($session_id, $sessions = false ){
global $langmessage, $dataDir;
//get the session file
if( !$sessions ){
$sessions = self::GetSessionIds();
if( !isset($sessions[$session_id]) ){
self::cookie(gp_session_cookie); //make sure the cookie is deleted
msg($langmessage['Session Expired'] . ' (timeout)');
return false;
}
}
$sess_info = $sessions[$session_id];
//check ~ip, ~user agent ...
if( gp_browser_auth && !empty($sess_info['uid']) ){
$auth_uid = self::auth_browseruid();
if( $sess_info['uid'] != $auth_uid ){
self::cookie(gp_session_cookie); //make sure the cookie is deleted
msg($langmessage['Session Expired'] . ' (browser auth)');
return false;
}
}
$session_file = $dataDir . '/data/_sessions/' . $sess_info['file_name'];
if( ($session_file === false) || !\gp\tool\Files::Exists($session_file) ){
self::cookie(gp_session_cookie); //make sure the cookie is deleted
msg($langmessage['Session Expired'] . ' (invalid)');
return false;
}
$this->session_id = $session_id;
$this->session_file = $session_file;
$this->logged_in = true;
return true;
}
public function Prepare(){
global $langmessage, $wbMessageBuffer;
static $locked_message = false;
//prevent browser caching when editing
Header( 'Last-Modified: ' . gmdate( 'D, j M Y H:i:s' ) . ' GMT' );
Header( 'Expires: ' . gmdate( 'D, j M Y H:i:s', time() ) . ' GMT' );
Header( 'Cache-Control: no-store, no-cache, must-revalidate'); // HTTP/1.1
Header( 'Cache-Control: post-check=0, pre-check=0', false );
Header( 'Pragma: no-cache' ); // HTTP/1.0
$GLOBALS['gpAdmin'] = self::SessionData($this->session_file,$checksum);
//lock to prevent conflicting edits
if( gp_lock_time > 0 &&
( !empty($GLOBALS['gpAdmin']['editing']) || !empty($GLOBALS['gpAdmin']['granted']) )
){
$expires = gp_lock_time;
if( !\gp\tool\Files::Lock('admin', sha1(sha1($this->session_id)), $expires) ){
msg($langmessage['site_locked'] . ' ' . sprintf($langmessage['lock_expires_in'], ceil($expires / 60)));
$locked_message = true;
$GLOBALS['gpAdmin']['locked'] = true;
}else{
unset($GLOBALS['gpAdmin']['locked']);
}
}
//extend cookie?
if( isset($GLOBALS['gpAdmin']['remember']) ){
$elapsed = time() - $GLOBALS['gpAdmin']['remember'];
if( $elapsed > 604800 ){ //7 days
$GLOBALS['gpAdmin']['remember'] = time();
self::cookie(gp_session_cookie, $this->session_id);
}
}
register_shutdown_function(array('\\gp\\tool\\Session', 'close'), $this->session_file, $checksum);
//make sure forms have admin nonce
ob_start(array('\\gp\\tool\\Session', 'AdminBuffer'));
\gp\tool\Output::$lang_values += array(
'cancel' => 'ca',
'update' => 'up',
'caption' => 'cp',
'Width' => 'Width',
'Height' => 'Height',
'save' => 'Save',
'Saved' => 'Saved',
'Saving' => 'Saving',
'Close' => 'Close',
'Page' => 'Page',
'theme_content' => 'Extra',
'Publish Draft' => 'PublishDraft',
'Publish' => 'Publish',
'Dismiss' => 'Dismiss',
'Dismiss Draft' => 'DismissDraft',
'Select Image' => 'SelectImage',
'edit' => 'edit',
'Expand Editor' => 'ExpandEditor',
'Shrink Editor' => 'ShrinkEditor',
'Hide Admin UI' => 'HideAdminUI',
'Show Admin UI' => 'ShowAdminUI',
'options' => 'options',
'Copy' => 'Copy',
'Copy to Clipboard' => 'CopyToClipboard',
'Manage Sections' => 'ManageSections',
'Sections' => 'Sections',
'Section Attributes' => 'SectionAttributes',
'Available Classes' => 'AvailableClasses',
'Attribute' => 'Attribute',
'Add Attribute' => 'AddAttribute',
'Value' => 'Value',
'Visibility' => 'Visibility',
'remove' => 'remove',
'delete' => 'del',
'Move Behind' => 'MoveBehind',
'Section %s' => 'Section',
'generic_delete_confirm' => 'generic_delete_confirm',
'Ctrl Key' => 'ctrlKey',
'Shift Key' => 'shiftKey',
'Alt Key' => 'altKey',
);
\gp\tool::LoadComponents('sortable, autocomplete, gp-admin, gp-admin-css, fontawesome, popper');
\gp\admin\Tools::VersionsAndCheckTime();
\gp\tool\Output::$inline_vars += array(
'gpRem' => \gp\admin\Tools::CanRemoteInstall(),
);
//prepend messages from message buffer
if( isset($GLOBALS['gpAdmin']['message_buffer']) && count($GLOBALS['gpAdmin']['message_buffer']) ){
$wbMessageBuffer = array_merge($GLOBALS['gpAdmin']['message_buffer'], $wbMessageBuffer);
unset($GLOBALS['gpAdmin']['message_buffer']);
}
//alias
if( isset($_COOKIE['gp_alias']) ){
$GLOBALS['gpAdmin']['useralias'] = $_COOKIE['gp_alias'];
}else{
$GLOBALS['gpAdmin']['useralias'] = $GLOBALS['gpAdmin']['username'];
}
}
/**
* Perform admin only changes to the content buffer
* This will happen before \gp\tool\Output::BufferOut()
*
*/
public static function AdminBuffer($buffer){
global $wbErrorBuffer, $gp_admin_html;
//add $gp_admin_html to the document
if( strpos($buffer, '<!-- get_head_placeholder ' . gp_random . ' -->') !== false ){
$buffer = \gp\tool\Output::AddToBody(
$buffer,
'<div id="gp_admin_html">'
. $gp_admin_html . \gp\tool\Output::$editlinks
. '</div><div id="gp_admin_fixed"></div>'
);
}
// Add a generic admin nonce field to each post form
// Admin nonces are also added with javascript if needed
$count = preg_match_all('#<form[^<>]*method=[\'"]post[\'"][^<>]*>#i', $buffer, $matches);
if( $count ){
$nonce = \gp\tool\Nonce::Create('post',true);
$matches[0] = array_unique($matches[0]);
foreach($matches[0] as $match){
//make sure it's a local action
if( preg_match('#action=[\'"]([^\'"]+)[\'"]#i', $match, $sub_matches) ){
$action = $sub_matches[1];
if( substr($action, 0, 2) === '//' ){
continue;
}elseif( strpos($action, '://') ){
continue;
}
}
$replacement = '<input type="hidden" name="verified" value="' . $nonce . '"/>';
$pos = strpos($buffer,$match)+strlen($match);
$buffer = substr_replace($buffer, $replacement, $pos, 0);
}
}
return $buffer;
}
/**
* Get the session data from a user session file
* @param string $session_file The full path to the user's session file
* @param string $checksum
* @return array The user's session data
*/
public static function SessionData($session_file, &$checksum){
$gpAdmin = \gp\tool\Files::Get($session_file, 'gpAdmin');
$checksum = '';
if( isset($gpAdmin['checksum']) ){
$checksum = $gpAdmin['checksum'];
}
return $gpAdmin + self::gpui_defaults();
}
public static function gpui_defaults(){
return array(
'gpui_cmpct' => 0,
'gpui_tx' => 10,
'gpui_ty' => 39,
'gpui_ckx' => 20,
'gpui_cky' => 240,
'gpui_exp' => 1,
'gpui_vis' => 'cur',
'gpui_thw' => 250,
);
}
/**
* Prevent XSS attacks for logged in users by
* making sure the request contains a valid nonce
*
*/
public static function CheckPosts(){
if( count($_POST) == 0 ){
return;
}
if( empty($_POST['verified']) ){
self::StripPost('XSS Verification Parameter Error');
return;
}
if( !\gp\tool\Nonce::Verify('post', $_POST['verified'], true) ){
self::StripPost('XSS Verification Parameter Mismatch');
return;
}
}
/**
* Unset all $_POST values
*
*/
public static function StripPost($message){
global $langmessage, $post_quarantine;
msg($langmessage['OOPS'] . ' (' . $message . ')');
$post_quarantine = $_POST;
foreach($_POST as $key => $value){
unset($_POST[$key]);
}
}
/**
* Save any changes to the $gpAdmin array
* @param string $file Session file path
* @param string $checksum_read The original checksum of the $gpAdmin array
*
*/
public static function Close($file, $checksum_read){
global $gpAdmin;
self::FatalNotices();
self::Cron();
self::LayoutInfo();
unset($gpAdmin['checksum']);
$checksum = \gp\tool::ArrayHash($gpAdmin);
//nothing changed
if( $checksum === $checksum_read ){
return;
}
if( !isset($gpAdmin['username']) ){
trigger_error('username not set');
die();
}
$gpAdmin['checksum'] = $checksum; //store the new checksum
\gp\tool\Files::SaveData($file, 'gpAdmin', $gpAdmin);
}
/**
* Update layout information if needed
*
*/
public static function LayoutInfo(){
global $page, $gpLayouts, $get_all_gadgets_called;
if( !\gp\tool\Output::$template_included ){
return;
}
$layout = $page->gpLayout;
if( !isset($gpLayouts[$layout]) ){
return;
}
$layout_info =& $gpLayouts[$layout];
//template.php file not modified
$template_file = realpath($page->theme_dir . '/template.php');
$template_mod = filemtime($template_file);
if( isset($layout_info['template_mod']) && $layout_info['template_mod'] >= $template_mod ){
return;
}
$contents = ob_get_contents();
//charset
if( strpos($contents, 'charset=') === false ){
return;
}
//get just the head of the buffer to see if we need to add charset
$pos = strpos($contents, '</head');
unset($layout_info['doctype']);
if( $pos > 0 ){
$head = substr($contents, 0, $pos);
$layout_info['doctype'] = self::DoctypeMeta($head);
}
$layout_info['all_gadgets'] = $get_all_gadgets_called;
//save
$layout_info['template_mod'] = $template_mod;
\gp\admin\Tools::SavePagesPHP();
}
/**
* Determine if CMS needs to add a <meta charset> tag
* Look at the beginning of the document to see what kind of doctype the current template is using
* See http://www.w3schools.com/tags/tag_doctype.asp for description of different doctypes
*
*/
public static function DoctypeMeta($doc_start){
//charset already set
if( stripos($doc_start,'charset=') !== false ){
return '';
}
// html5
// spec states this should be "the first element child of the head element"
if( stripos($doc_start, '<!doctype html>') !== false ){
return '<meta charset="UTF-8" />';
}
return '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
}
/**
* Perform regular tasks
* Once an hour only when admin is logged in
*
*/
public static function Cron(){
$cron_info = \gp\tool\Files::Get('_site/cron_info');
$file_stats = \gp\tool\Files::$last_stats;
$file_stats += array('modified' => 0);
if( (time() - $file_stats['modified']) < 3600 ){
return;
}
self::CleanTemp();
\gp\tool\Files::SaveData('_site/cron_info', 'cron_info', $cron_info);
}
/**
* Clean old files and folders from the temporary folder
* Delete after 36 hours (129600 seconds)
*
*/
public static function CleanTemp(){
global $dataDir;
$temp_folder = $dataDir . '/data/_temp';
$files = \gp\tool\Files::ReadDir($temp_folder, false);
foreach($files as $file){
if( $file == 'index.html'){
continue;
}
$full_path = $temp_folder . '/' . $file;
$mtime = (int)filemtime($full_path);
$diff = time() - $mtime;
if( $diff < 129600 ){
continue;
}
\gp\tool\Files::RmAll($full_path);
}
}
/**
* Output the UI variables as a Javascript Object
*
*/
public static function GPUIVars(){
global $gpAdmin, $page, $config;
$defaults = self::gpui_defaults();
$js = array();
foreach($defaults as $key => $value){
if( isset($gpAdmin[$key]) ){
$value = $gpAdmin[$key];
}
$renamed_key = substr($key, 5);
$js[$renamed_key] = $value;
}
//default layout (admin layout)
if( $page->gpLayout && $page->gpLayout == $config['gpLayout'] ){
$js['dlayout'] = true;
}else{
$js['dlayout'] = false;
}
echo 'var gpui=' . json_encode($js) . ';';
}
/**
* Code modified from dokuwiki
* /dokuwiki/inc/auth.php
*
* Builds a pseudo UID from browser and IP data
*
* This is neither unique nor unfakable - still it adds some
* security. Using the first part of the IP makes sure
* proxy farms like AOLs are stil okay.
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @return string a MD5 sum of various browser headers
*/
public static function auth_browseruid(){
$uid = '';
if( isset($_SERVER['HTTP_USER_AGENT']) ){
$uid .= $_SERVER['HTTP_USER_AGENT'];
}
if( isset($_SERVER['HTTP_ACCEPT_ENCODING']) ){
$uid .= $_SERVER['HTTP_ACCEPT_ENCODING'];
}
if( isset($_SERVER['HTTP_ACCEPT_CHARSET']) ){
$uid .= $_SERVER['HTTP_ACCEPT_CHARSET'];
}
$ip = self::clientIP();
$uid .= substr($ip, 0, strpos($ip, '.'));
//ie8 will report ACCEPT_LANGUAGE as en-us and en-US depending on the type of request (normal, ajax)
$uid = strtolower($uid);
return md5($uid);
}
/**
* Return the IP of the client
* Modified from ClientIP method in Dokuwiki
*
* Honours X-Forwarded-For and X-Real-IP Proxy Headers
*
* Tries to return a routable public address, prefering the ones suplied in the X headers
*
*/
public static function ClientIP(){
$ips = [];
$add_ip = function($ips, $ip_key){
if( !isset($_SERVER[$ip_key]) ){
return $ips;
}
// some IPv4/v6 regexps borrowed from Feyd
// see: http://forums.devnetwork.net/viewtopic.php?f=38&t=53479
$dec_octet = '(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|[0-9])';
$hex_digit = '[A-Fa-f0-9]';
$h16 = "{$hex_digit}{1,4}";
$IPv4Address = "$dec_octet\\.$dec_octet\\.$dec_octet\\.$dec_octet";
$ls32 = "(?:$h16:$h16|$IPv4Address)";
$IPv6Address =
"(?:(?:{$IPv4Address})|(?:".
"(?:$h16:){6}$ls32" .
"|::(?:$h16:){5}$ls32" .
"|(?:$h16)?::(?:$h16:){4}$ls32" .
"|(?:(?:$h16:){0,1}$h16)?::(?:$h16:){3}$ls32" .
"|(?:(?:$h16:){0,2}$h16)?::(?:$h16:){2}$ls32" .
"|(?:(?:$h16:){0,3}$h16)?::(?:$h16:){1}$ls32" .
"|(?:(?:$h16:){0,4}$h16)?::$ls32" .
"|(?:(?:$h16:){0,5}$h16)?::$h16" .
"|(?:(?:$h16:){0,6}$h16)?::" .
")(?:\\/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))?)";
$new_ips = explode(',',str_replace(' ','',$_SERVER[$ip_key]));
// remove any non-IP stuff
foreach($new_ips as $ip){
if( preg_match("/^$IPv4Address$/",$ip,$match) || preg_match("/^$IPv6Address$/",$ip,$match)) {
$ips[] = $match[0];
}
}
return $ips;
};
$ips = $add_ip($ips,'REMOTE_ADDR');
$ips = $add_ip($ips,'HTTP_X_FORWARDED_FOR');
$ips = $add_ip($ips,'HTTP_X_REAL_IP');
$ips = array_values(array_unique($ips));
// for some strange reason we don't have a IP
if( empty($ips) ){
return '0.0.0.0';
}
// decide which IP to use, trying to avoid local addresses
$ips = array_reverse($ips);
foreach($ips as $ip){
if( !preg_match('/^(::1|[fF][eE]80:|127\.|10\.|192\.168\.|172\.((1[6-9])|(2[0-9])|(3[0-1]))\.)/',$ip) ){
return $ip;
}
}
// use the first (last) address
return end($ips);
}
/**
* Re-enable components that were disabled because of fatal errors
*
*/
public static function ClearErrors(){
\gp\admin\Tools\Errors::ClearAll();
$title = \gp\tool::WhichPage();
\gp\tool::Redirect(\gp\tool::GetUrl($title, '', false));
}
/**
* Notify the admin if there have been any fatal errors
*
*/
public static function FatalNotices(){
global $dataDir, $page;
if( !\gp\admin\Tools::HasPermission('Admin_Errors') ){
return;
}
if( is_object($page)
&& property_exists($page, 'requested')
&& strpos($page->requested, 'Admin/Errors') !== false
){
return;
}
$dir = $dataDir . '/data/_site';
$files = scandir($dir);
$has_fatal = false;
foreach($files as $file){
if( strpos($file, 'fatal_') === false ){
continue;
}
$has_fatal = true;
}
if( !$has_fatal ){
return;
}
$msg = 'Warning: One or more components have caused fatal errors. <br/>';
$msg .= \gp\tool::Link(
'Admin/Errors',
'More Information',
'',
'style="white-space:nowrap"'
);
$msg .= ' &nbsp; ';
$msg .= \gp\tool::Link(
(isset($page) ? $page->requested : 'Admin'),
'Clear All Errors',
'cmd=ClearErrors',
'', //cannot be creq
'ClearErrors'
);
msg($msg);
}
public static function SessionCookie($uniq){
return 'gpEasy_'.substr(sha1($uniq),12,12);
}
}