1390 lines
36 KiB
PHP
1390 lines
36 KiB
PHP
<?php
|
|
/*! pimpmylog - 1.7.9 - 10b502eaf17be208850be61febb044c2fdb86207*/
|
|
/*
|
|
* pimpmylog
|
|
* http://pimpmylog.com
|
|
*
|
|
* Copyright (c) 2015 Potsky, contributors
|
|
* Licensed under the GPLv3 license.
|
|
*/
|
|
?><?php
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Disable direct call
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| People cannot access this page directly in their browser
|
|
|
|
|
*/
|
|
if ( realpath( __FILE__ ) === realpath( $_SERVER[ "SCRIPT_FILENAME" ] ) ) {
|
|
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found');
|
|
die();
|
|
}
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Disable XDebug
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| We do not need xdebug and if enabled, it is really slow !
|
|
|
|
|
*/
|
|
if ( function_exists( 'xdebug_disable' ) ) { xdebug_disable(); }
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Define root directories
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
if ( ! defined( 'PML_BASE' ) ) define( 'PML_BASE' , realpath( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . '..' ) );
|
|
|
|
if ( ! defined( 'PML_CONFIG_BASE' ) ) {
|
|
if ( upgrade_is_composer() ) {
|
|
define( 'PML_CONFIG_BASE' , realpath( PML_BASE . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '.' ) );
|
|
} else {
|
|
define( 'PML_CONFIG_BASE' , PML_BASE );
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| MB fallback functions
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
if ( ! function_exists( 'mb_strlen' ) ) {
|
|
function mb_strlen( $a ) {
|
|
return strlen( $a );
|
|
}
|
|
define( 'MB_SUPPORT' , false );
|
|
} else {
|
|
define( 'MB_SUPPORT' , true );
|
|
}
|
|
|
|
if ( ! function_exists( 'mb_strtolower' ) ) {
|
|
function mb_strtolower( $a , $b = '' ) {
|
|
return strtolower( $a );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'mb_check_encoding' ) ) {
|
|
function mb_check_encoding( $a , $b ) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'mb_substr' ) ) {
|
|
function mb_substr( $a , $b , $c = 9999999 ) {
|
|
return substr( $a , $b , $c );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'mb_convert_encoding' ) ) {
|
|
function mb_convert_encoding( $a , $b , $c ) {
|
|
return utf8_encode( $a );
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Check for Suhosin
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| Suhosin is used in CPanel installations for example and users do not always
|
|
| know what is Suhosin and what it does
|
|
|
|
|
*/
|
|
define( 'SUHOSIN_LOADED' , ( extension_loaded('suhosin') ) );
|
|
define( 'SUHOSIN_URL' , "http://support.pimpmylog.com/kb/configuration/php-installations-with-suhosin-extension-and-exotic-ini-settings" );
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Enable safe mode
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| User can create a file named SAFE_MODE at root directory to tell Pimp My Log
|
|
| to avoid using functions like exec, ini_get, etc...
|
|
|
|
|
| These functions can be forbidden by PHP or Suhosin and are aimed to help
|
|
| user but there are not mandatory.
|
|
|
|
|
*/
|
|
define( 'SAFE_MODE' , file_exists( PML_CONFIG_BASE . DIRECTORY_SEPARATOR . 'SAFE_MODE' ) );
|
|
define( 'TIME_ZONE_SUPPORT_URL' , 'http://support.pimpmylog.com/discussions/problems/46-timezone-uncaught-exception' );
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Disable magic quotes
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| PHP 5.2 and 5.3 can have magic quotes enabled on the whole PHP install.
|
|
| http://support.pimpmylog.com/discussions/problems/56-regex-tester-match-is-not-a-valid-associative-array
|
|
|
|
|
*/
|
|
if (get_magic_quotes_gpc()) {
|
|
$process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
|
|
while (list($key, $val) = each($process)) {
|
|
foreach ($val as $k => $v) {
|
|
unset($process[$key][$k]);
|
|
if (is_array($v)) {
|
|
$process[$key][stripslashes($k)] = $v;
|
|
$process[] = &$process[$key][stripslashes($k)];
|
|
} else {
|
|
$process[$key][stripslashes($k)] = stripslashes($v);
|
|
}
|
|
}
|
|
}
|
|
unset($process);
|
|
}
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Global internal parameters
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| These constants are defined for internal use only, do not change
|
|
|
|
|
*/
|
|
define( 'YEAR' , @date( "Y" ) );
|
|
define( 'PHP_VERSION_REQUIRED' , '5.2' );
|
|
define( 'CONFIG_FILE_MODE' , 0444 );
|
|
define( 'AUTH_CONFIGURATION_FILE' , 'config.auth.user.php' );
|
|
define( 'CONFIG_FILE_NAME' , 'config.user.php' );
|
|
define( 'CONFIG_FILE_NAME_BEFORE_1_5_0' , 'config.user.json' );
|
|
define( 'CONFIG_FILE_TEMP' , 'config.user.tmp.php' );
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Global internal default parameters
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| These constants are defined for internal use only.
|
|
| These constants will overwrite custom global parameters if their are not defined
|
|
| Overwrite them in your configuration file, not in this code directly !
|
|
|
|
|
*/
|
|
define( 'DEFAULT_AUTH_LOG_FILE_COUNT' , 100 );
|
|
define( 'DEFAULT_AUTO_UPGRADE' , false );
|
|
define( 'DEFAULT_CHECK_UPGRADE' , true );
|
|
define( 'DEFAULT_EXPORT' , true );
|
|
define( 'DEFAULT_FILE_SELECTOR' , 'bs' );
|
|
define( 'DEFAULT_FOOTER' , '© <a href="http://www.potsky.com" target="doc">Potsky</a> 2007-' . YEAR . ' - <a href="http://pimpmylog.com" target="doc">Pimp my Log</a>');
|
|
define( 'DEFAULT_FORGOTTEN_YOUR_PASSWORD_URL' , 'http://support.pimpmylog.com/kb/misc/forgotten-your-password' );
|
|
define( 'DEFAULT_GEOIP_URL' , 'http://www.geoiptool.com/en/?IP=%p' );
|
|
define( 'DEFAULT_GOOGLE_ANALYTICS' , 'UA-XXXXX-X' );
|
|
define( 'DEFAULT_HELP_URL' , 'http://pimpmylog.com' );
|
|
define( 'DEFAULT_LOCALE' , 'gb_GB' );
|
|
define( 'DEFAULT_LOGS_MAX' , 50 );
|
|
define( 'DEFAULT_LOGS_REFRESH' , 0 );
|
|
define( 'DEFAULT_MAX_SEARCH_LOG_TIME' , 5 );
|
|
define( 'DEFAULT_NAV_TITLE' , '' );
|
|
define( 'DEFAULT_NOTIFICATION' , true );
|
|
define( 'DEFAULT_NOTIFICATION_TITLE' , 'New logs [%f]' );
|
|
define( 'DEFAULT_PIMPMYLOG_ISSUE_LINK' , 'https://github.com/potsky/PimpMyLog/issues/' );
|
|
define( 'DEFAULT_PIMPMYLOG_VERSION_URL' , 'http://demo.pimpmylog.com/version.js' );
|
|
define( 'DEFAULT_PULL_TO_REFRESH' , true );
|
|
define( 'DEFAULT_SORT_LOG_FILES' , 'default' );
|
|
define( 'DEFAULT_TAG_DISPLAY_LOG_FILES_COUNT' , true );
|
|
define( 'DEFAULT_TAG_NOT_TAGGED_FILES_ON_TOP' , true );
|
|
define( 'DEFAULT_TAG_SORT_TAG' , 'displayiasc' );
|
|
define( 'DEFAULT_TITLE' , 'Pimp my Log' );
|
|
define( 'DEFAULT_TITLE_FILE' , 'Pimp my Log [%f]' );
|
|
define( 'DEFAULT_UPGRADE_MANUALLY_URL' , 'http://pimpmylog.com/getting-started/#update' );
|
|
define( 'DEFAULT_USER_CONFIGURATION_DIR' , 'config.user.d' );
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Lang parameters
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| $locale_numeraljs is an associative array to convert a PHP locale to a
|
|
| javascript locale used by numeralJS
|
|
|
|
|
*/
|
|
$tz_available = DateTimeZone::listIdentifiers();
|
|
$locale_default = 'en_GB';
|
|
$locale_available = array(
|
|
'en_GB' => 'English',
|
|
'fr_FR' => 'Français',
|
|
'pt_BR' => 'Português do Brasil',
|
|
);
|
|
$locale_numeraljs = array(
|
|
'en_GB' => 'en-gb',
|
|
'fr_FR' => 'fr',
|
|
'pt_BR' => 'pt-br',
|
|
);
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Class autoloader
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
function my_autoloader( $ClassName ) {
|
|
@include( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . $ClassName . ".php");
|
|
}
|
|
spl_autoload_register('my_autoloader');
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Functions declarations
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| Will be removed in PML v2.0, all functions will be grouped in classes
|
|
|
|
|
*/
|
|
|
|
/**
|
|
* htmlentities
|
|
*
|
|
* @param string $text the text key
|
|
*
|
|
* @return string the translation
|
|
*/
|
|
function h($text)
|
|
{
|
|
return htmlentities( $text ,ENT_QUOTES,'UTF-8');
|
|
}
|
|
|
|
/**
|
|
* htmlentities for echo
|
|
*
|
|
* @param string $text the text key
|
|
*
|
|
* @return string the translation
|
|
*/
|
|
function _h($text)
|
|
{
|
|
_e( htmlentities( $text ,ENT_QUOTES,'UTF-8') );
|
|
}
|
|
|
|
/**
|
|
* Simply return a localized text or empty string if the key is empty
|
|
* Useful when localize variable which can be empty
|
|
*
|
|
* @param string $text the text key
|
|
*
|
|
* @return string the translation
|
|
*/
|
|
function __($text)
|
|
{
|
|
if ( empty( $text ) )
|
|
return '';
|
|
else
|
|
return gettext( $text );
|
|
}
|
|
|
|
/**
|
|
* Simply echo a localized text
|
|
*
|
|
* @param string $text the text key
|
|
*
|
|
* @return void
|
|
*/
|
|
function _e($text)
|
|
{
|
|
echo __( $text );
|
|
}
|
|
|
|
/**
|
|
* Load all unset constants
|
|
*
|
|
* @return
|
|
*/
|
|
function load_default_constants()
|
|
{
|
|
$defaults = array(
|
|
'AUTH_LOG_FILE_COUNT',
|
|
'AUTO_UPGRADE',
|
|
'CHECK_UPGRADE',
|
|
'DEFAULT_HELP_URL',
|
|
'EXPORT',
|
|
'FILE_SELECTOR',
|
|
'FOOTER',
|
|
'FORGOTTEN_YOUR_PASSWORD_URL',
|
|
'GEOIP_URL',
|
|
'GOOGLE_ANALYTICS',
|
|
'LOCALE',
|
|
'LOGS_MAX',
|
|
'LOGS_REFRESH',
|
|
'MAX_SEARCH_LOG_TIME',
|
|
'NAV_TITLE',
|
|
'NOTIFICATION',
|
|
'NOTIFICATION_TITLE',
|
|
'PIMPMYLOG_ISSUE_LINK',
|
|
'PIMPMYLOG_VERSION_URL',
|
|
'PULL_TO_REFRESH',
|
|
'SORT_LOG_FILES',
|
|
'TAG_SORT_TAG',
|
|
'TAG_NOT_TAGGED_FILES_ON_TOP',
|
|
'TAG_DISPLAY_LOG_FILES_COUNT',
|
|
'TITLE',
|
|
'TITLE_FILE',
|
|
'UPGRADE_MANUALLY_URL',
|
|
'USER_CONFIGURATION_DIR',
|
|
);
|
|
foreach ($defaults as $d) {
|
|
if ( ! defined( $d ) ) {
|
|
if ( defined( 'DEFAULT_' . $d ) ) {
|
|
define( $d , constant( 'DEFAULT_' . $d ) );
|
|
} else {
|
|
die( "Constant 'DEFAULT_$d' is not defined!" );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Try to find the main configuration file path
|
|
* Configuration file can be a PHP file since 1.5.0 or a json file below
|
|
* Both files contains a JSON configuration array but the PHP version is not callable by a guest on web
|
|
*
|
|
* @return string the path in a string or null if not found
|
|
*/
|
|
function get_config_file_path()
|
|
{
|
|
$files = array(
|
|
CONFIG_FILE_NAME,
|
|
CONFIG_FILE_NAME_BEFORE_1_5_0,
|
|
);
|
|
foreach ($files as $f) {
|
|
if ( file_exists( PML_CONFIG_BASE . DIRECTORY_SEPARATOR . $f ) ) {
|
|
return realpath( PML_CONFIG_BASE . DIRECTORY_SEPARATOR . $f );
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Return the configuration file name
|
|
*
|
|
* @param string $path the configuration file path or false if the function has to compute itself
|
|
*
|
|
* @return string the file name or null if configuration not found
|
|
*/
|
|
function get_config_file_name($path = false)
|
|
{
|
|
if ( $path === false ) $path = get_config_file_path();
|
|
if ( is_null( $path ) ) return null;
|
|
return basename( $path );
|
|
}
|
|
|
|
/**
|
|
* Return the configuration array of a configuration file
|
|
*
|
|
* @param string $path the configuration file path or false to let the function load the global configuration
|
|
*
|
|
* @return array the configuration array or null if file is invalid or if configuration file does not exist
|
|
*/
|
|
function get_config_file($path = false)
|
|
{
|
|
if ( $path === false ) $path = get_config_file_path();
|
|
if ( is_null( $path ) ) return null;
|
|
|
|
if ( strtolower( substr( $path , -3 , 3 ) ) === 'php' ) {
|
|
ob_start();
|
|
require $path;
|
|
$string = ob_get_clean();
|
|
} else {
|
|
$string = @file_get_contents( $path );
|
|
}
|
|
|
|
return json_decode( $string , true );
|
|
}
|
|
|
|
/**
|
|
* Load config file
|
|
*
|
|
* @param string $path the configuration file path
|
|
* @param boolean $load_user_configuration_dir do we have to parse all user configuration files ? No for upgrade for example...
|
|
*
|
|
* @return array [ badges , files ]
|
|
*/
|
|
function config_load($load_user_configuration_dir = true)
|
|
{
|
|
$badges = false;
|
|
$files = false;
|
|
|
|
// Read config file
|
|
$config = get_config_file();
|
|
|
|
if ( is_null( $config ) ) {
|
|
return array( $badges , $files );
|
|
}
|
|
|
|
// Get badges
|
|
$badges = $config[ 'badges' ];
|
|
|
|
// Set user constant
|
|
foreach ($config[ 'globals' ] as $cst => $val) {
|
|
if ( $cst == strtoupper( $cst ) ) {
|
|
@define( $cst , $val );
|
|
}
|
|
}
|
|
|
|
// Set unset constants
|
|
load_default_constants();
|
|
|
|
// Set time limit
|
|
@set_time_limit( MAX_SEARCH_LOG_TIME + 2 );
|
|
|
|
// Append files from the USER_CONFIGURATION_DIR
|
|
if ( $load_user_configuration_dir === true ) {
|
|
if ( is_dir( PML_CONFIG_BASE . DIRECTORY_SEPARATOR . USER_CONFIGURATION_DIR ) ) {
|
|
$dir = PML_CONFIG_BASE . DIRECTORY_SEPARATOR . USER_CONFIGURATION_DIR;
|
|
$userfiles = new RegexIterator(
|
|
new RecursiveIteratorIterator(
|
|
new RecursiveDirectoryIterator( $dir , RecursiveDirectoryIterator::SKIP_DOTS ),
|
|
RecursiveIteratorIterator::SELF_FIRST,
|
|
RecursiveIteratorIterator::CATCH_GET_CHILD // Ignore "Permission denied"
|
|
),
|
|
'/^.+\.(json|php)$/i',
|
|
RecursiveRegexIterator::GET_MATCH
|
|
);
|
|
foreach ($userfiles as $userfile) {
|
|
$filepath = realpath( $userfile[0] );
|
|
$c = get_config_file( $filepath );
|
|
if ( ! is_null( $c ) ) {
|
|
foreach ($c as $k => $v) {
|
|
$fileid = get_slug( str_replace( PML_CONFIG_BASE , '' , $filepath ) . '/' . $k );
|
|
$config[ 'files' ][ $fileid ] = $v;
|
|
$config[ 'files' ][ $fileid ]['included_from'] = $filepath;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Oups, there is no file... abort
|
|
if ( ! isset( $config[ 'files' ] ) ) {
|
|
return array( $badges , $files );
|
|
}
|
|
|
|
// Try to generate the files tree if there are globs...
|
|
$files_tmp = $config[ 'files' ];
|
|
$files = array();
|
|
|
|
foreach ($files_tmp as $fileid => $file) {
|
|
|
|
$path = $file['path'];
|
|
$count = max( 1 , @(int) $file['count']);
|
|
$gpaths = glob( $path , GLOB_MARK | GLOB_NOCHECK );
|
|
|
|
if ( count( $gpaths ) == 0 ) {
|
|
}
|
|
else if ( count( $gpaths ) == 1 ) {
|
|
$files[ $fileid ] = $file;
|
|
$files[ $fileid ]['path'] = $gpaths[0];
|
|
}
|
|
else {
|
|
$new_paths = array();
|
|
$i = 1;
|
|
|
|
foreach ($gpaths as $path) {
|
|
$new_paths[ $path ] = filemtime( $path );
|
|
}
|
|
|
|
// The most recent file will be the first
|
|
arsort( $new_paths , SORT_NUMERIC );
|
|
|
|
// The first file id is the ID of the configuration file then others files are suffixed with _2, _3, etc...
|
|
foreach ( $new_paths as $path => $lastmodified ) {
|
|
$ext = ( $i > 1 ) ? '_' . $i : '';
|
|
|
|
$files[ $fileid . $ext ] = $file;
|
|
$files[ $fileid . $ext ]['oid'] = $fileid;
|
|
$files[ $fileid . $ext ]['odisplay'] = $files[ $fileid . $ext ]['display'];
|
|
$files[ $fileid . $ext ]['path'] = $path;
|
|
$files[ $fileid . $ext ]['display'] .= ' > ' . basename( $path );
|
|
if ($i >= $count) {
|
|
break;
|
|
}
|
|
$i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove forbidden files
|
|
if ( Sentinel::isAuthSet() ) { // authentication is enabled on this instance
|
|
|
|
$username = Sentinel::getCurrentUsername();
|
|
$final = array();
|
|
|
|
// Anonymous access only
|
|
if ( is_null( $username ) ) {
|
|
foreach ( $files as $fileid => $file ) {
|
|
$a = $fileid;
|
|
// glob file
|
|
if ( isset( $files[ $fileid ]['oid'] ) ) {
|
|
$a = $files[ $fileid ]['oid'];
|
|
}
|
|
if ( Sentinel::isLogAnonymous( $a ) ) {
|
|
$final[ $fileid ] = $file;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Anonymous access + User access
|
|
else {
|
|
foreach ( $files as $fileid => $file ) {
|
|
$a = $fileid;
|
|
// glob file
|
|
if ( isset( $files[ $fileid ]['oid'] ) ) {
|
|
$a = $files[ $fileid ]['oid'];
|
|
}
|
|
if ( ( Sentinel::userCanOnLogs( $a , 'r' , true , $username ) ) || ( Sentinel::isLogAnonymous( $a ) ) ) {
|
|
$final[ $fileid ] = $file;
|
|
}
|
|
}
|
|
}
|
|
|
|
$files = $final;
|
|
}
|
|
|
|
// Fix missing values with defaults
|
|
foreach ( $files as $fileid => $file ) {
|
|
foreach (array(
|
|
'max' => LOGS_MAX,
|
|
'refresh' => LOGS_REFRESH,
|
|
'notify' => NOTIFICATION,
|
|
) as $fix => $value ) {
|
|
if ( ! isset( $file[ $fix ] ) ) {
|
|
$files[ $fileid ][ $fix ] = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Finally sort files
|
|
if ( ! function_exists( 'display_asc' ) ) { function display_asc($a, $b) { return strcmp( $a["display"] , $b["display"] ); } }
|
|
if ( ! function_exists( 'display_desc' ) ) { function display_desc($a, $b) { return strcmp( $b["display"] , $a["display"] ); } }
|
|
if ( ! function_exists( 'display_insensitive_asc' ) ) { function display_insensitive_asc($a, $b) { return strcmp( $a["display"] , $b["display"] ); } }
|
|
if ( ! function_exists( 'display_insensitive_desc' ) ) { function display_insensitive_desc($a, $b) { return strcmp( $b["display"] , $a["display"] ); } }
|
|
switch ( trim( str_replace( array( '-' , '_' , ' ' , 'nsensitive' ) , '' , SORT_LOG_FILES ) ) ) {
|
|
case 'display':
|
|
case 'displayasc':
|
|
usort( $files , 'display_asc' );
|
|
break;
|
|
case 'displayi':
|
|
case 'displayiasc':
|
|
usort( $files , 'display_insensitive_asc' );
|
|
break;
|
|
case 'displaydesc':
|
|
usort( $files , 'display_desc' );
|
|
break;
|
|
case 'displayidesc':
|
|
usort( $files , 'display_insensitive_desc' );
|
|
break;
|
|
default:
|
|
# do not sort
|
|
break;
|
|
}
|
|
|
|
return array( $badges , $files );
|
|
}
|
|
|
|
/**
|
|
* Check the $files array and fix it with default values
|
|
* If there is a problem, return an array of errors
|
|
* If everything is ok, return true;
|
|
*
|
|
* @param array $files log files
|
|
*
|
|
* @return mixed true if ok, otherwise an array of errors
|
|
*/
|
|
function config_check( $files )
|
|
{
|
|
$errors = array();
|
|
|
|
if ( ! is_array( $files ) ) {
|
|
if ( Sentinel::isAuthSet() ) return false;
|
|
|
|
$errors[] = __( 'No file is defined in <code>files</code> array' );
|
|
|
|
return $errors;
|
|
}
|
|
|
|
if ( count( $files ) === 0 ) {
|
|
if ( Sentinel::isAuthSet() ) return false;
|
|
|
|
$errors[] = __( 'No file is defined in <code>files</code> array' );
|
|
|
|
return $errors;
|
|
}
|
|
|
|
foreach ($files as $file_id => &$file) {
|
|
// error
|
|
foreach ( array( 'display' , 'path' , 'format' ) as $mandatory ) {
|
|
if ( ! isset( $file[ $mandatory ] ) ) {
|
|
$errors[] = sprintf( __( '<code>%s</code> is mandatory for file ID <code>%s</code>' ) , $mandatory , $file_id );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( count($errors) == 0 ) {
|
|
return true;
|
|
} else {
|
|
return $errors;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Extract tags from the confiuration files
|
|
*
|
|
* @param array $files the files configuration array
|
|
*
|
|
* @return array an array of tags with fileids
|
|
*/
|
|
function config_extract_tags( $files ) {
|
|
$tags = array( '_' => array() );
|
|
|
|
foreach ( $files as $fileid => $file ) {
|
|
// Tag found
|
|
if ( isset( $file['tags'] ) ) {
|
|
if ( is_array( $file['tags'] ) ) {
|
|
foreach ( $file['tags'] as $tag ) {
|
|
$tags[ strval( $tag ) ][] = $fileid;
|
|
}
|
|
} else {
|
|
$tags[ strval( $file['tags'] ) ][] = $fileid;
|
|
}
|
|
}
|
|
// No tag
|
|
else {
|
|
$tags[ '_' ][] = $fileid;
|
|
}
|
|
}
|
|
|
|
switch ( trim( str_replace( array( '-' , '_' , ' ' , 'nsensitive' ) , '' , TAG_SORT_TAG ) ) ) {
|
|
case 'display':
|
|
case 'displayasc':
|
|
if ( version_compare( PHP_VERSION , '5.4.0' ) >= 0 ) {
|
|
ksort( $tags , SORT_NATURAL );
|
|
} else {
|
|
ksort( $tags );
|
|
}
|
|
break;
|
|
case 'displayi':
|
|
case 'displayiasc':
|
|
if ( version_compare( PHP_VERSION , '5.4.0' ) >= 0 ) {
|
|
ksort( $tags , SORT_NATURAL | SORT_FLAG_CASE );
|
|
} else {
|
|
ksort( $tags );
|
|
}
|
|
break;
|
|
case 'displaydesc':
|
|
if ( version_compare( PHP_VERSION , '5.4.0' ) >= 0 ) {
|
|
krsort( $tags , SORT_NATURAL );
|
|
} else {
|
|
krsort( $tags );
|
|
}
|
|
break;
|
|
case 'displayidesc':
|
|
if ( version_compare( PHP_VERSION , '5.4.0' ) >= 0 ) {
|
|
krsort( $tags , SORT_NATURAL | SORT_FLAG_CASE );
|
|
} else {
|
|
krsort( $tags );
|
|
}
|
|
break;
|
|
default:
|
|
# do not sort
|
|
break;
|
|
}
|
|
|
|
return $tags;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the list of refresh duration
|
|
* The list is the default one below + :
|
|
* - a custom value defined by user in PHP constant LOGS_REFRESH
|
|
* - a custom value defined by user in all files in PHP array $files
|
|
* The list must by unique and sorted
|
|
*
|
|
* @param array $files log files
|
|
*
|
|
* @return array the list of selectable values
|
|
*/
|
|
function get_refresh_options($files)
|
|
{
|
|
$options = array(
|
|
1 => 1,
|
|
2 => 2,
|
|
3 => 3,
|
|
4 => 4,
|
|
5 => 5,
|
|
10 => 10,
|
|
15 => 15,
|
|
30 => 30,
|
|
45 => 45,
|
|
60 => 60
|
|
);
|
|
$options[ (int) LOGS_REFRESH ] = (int) LOGS_REFRESH;
|
|
foreach ($files as $file_id => $file) {
|
|
$options[ (int) @$file['refresh'] ] = (int) @$file['refresh'];
|
|
}
|
|
unset( $options[0] );
|
|
sort( $options );
|
|
|
|
return $options;
|
|
}
|
|
|
|
/**
|
|
* Get the list of displayed logs count
|
|
* The list is the default one below + :
|
|
* - a custom value defined by user in PHP constant LOGS_MAX
|
|
* - a custom value defined by user in all files in PHP array $files
|
|
* The list must by unique and sorted
|
|
*
|
|
* @param array $files log files
|
|
*
|
|
* @return array the list of selectable values
|
|
*/
|
|
function get_max_options($files)
|
|
{
|
|
$options = array(
|
|
5 => 5,
|
|
10 => 10,
|
|
20 => 20,
|
|
50 => 50,
|
|
100 => 100,
|
|
200 => 200
|
|
);
|
|
$options[ (int) LOGS_MAX ] = (int) LOGS_MAX;
|
|
foreach ($files as $file_id => $file) {
|
|
$options[ (int) @$file['max'] ] = (int) @$file['max'];
|
|
}
|
|
unset( $options[0] );
|
|
sort( $options );
|
|
|
|
return $options;
|
|
}
|
|
|
|
/**
|
|
* Return a human representation of a size
|
|
*
|
|
* @param string $bytes the string representation (can be an int)
|
|
* @param integer $decimals the number of digits in the float part
|
|
*
|
|
* @return string the human size
|
|
*/
|
|
function human_filesize( $bytes , $decimals = 0 )
|
|
{
|
|
$sz = __( 'B KBMBGBTBPB' );
|
|
$factor = floor( ( strlen( $bytes ) - 1 ) / 3 );
|
|
|
|
return sprintf( "%.{$decimals}f" , $bytes / pow( 1024, $factor ) ) . @$sz[ (int)$factor * 2 ];
|
|
}
|
|
|
|
/**
|
|
* Get a Cross Script Request Forgery token
|
|
*
|
|
* @return string a token
|
|
*/
|
|
function csrf_get()
|
|
{
|
|
Session::start();
|
|
if ( ! isset( $_SESSION[ 'csrf_token' ] ) ) {
|
|
$_SESSION[ 'csrf_token' ] = md5( uniqid( '' , true ) );
|
|
}
|
|
Session::write_close();
|
|
|
|
return $_SESSION[ 'csrf_token' ];
|
|
}
|
|
|
|
/**
|
|
* Verify a Cross Script Request Forgery token
|
|
*
|
|
* @return boolean verified ?
|
|
*/
|
|
function csrf_verify()
|
|
{
|
|
Session::start();
|
|
$s = @$_SESSION[ 'csrf_token' ];
|
|
Session::write_close();
|
|
if ( ! isset( $_POST[ 'csrf_token' ] ) )
|
|
return false;
|
|
return ( $s === @$_POST[ 'csrf_token' ] );
|
|
}
|
|
|
|
/**
|
|
* [get_slug description]
|
|
*
|
|
* @param string $string the string to slugify
|
|
* @param string $separator the separator
|
|
*
|
|
* @return string th slugified string
|
|
*/
|
|
function get_slug($string, $separator = '-')
|
|
{
|
|
$accents_regex = '~&([a-z]{1,2})(?:acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml);~i';
|
|
$special_cases = array( '&' => 'and');
|
|
$string = mb_strtolower( trim( $string ), 'UTF-8' );
|
|
$string = str_replace( array_keys($special_cases), array_values( $special_cases), $string );
|
|
$string = preg_replace( $accents_regex, '$1', htmlentities( $string, ENT_QUOTES, 'UTF-8' ) );
|
|
$string = preg_replace("/[^a-z0-9]/u", "$separator", $string);
|
|
$string = preg_replace("/[$separator]+/u", "$separator", $string);
|
|
|
|
return $string;
|
|
}
|
|
|
|
/**
|
|
* Indents a flat JSON string to make it more human-readable.
|
|
* For PHP < 5.4
|
|
*
|
|
* @param string $json The original JSON string to process.
|
|
*
|
|
* @return string Indented version of the original JSON string.
|
|
*/
|
|
function json_indent($json)
|
|
{
|
|
$result = '';
|
|
$pos = 0;
|
|
$strLen = strlen($json);
|
|
$indentStr = ' ';
|
|
$newLine = "\n";
|
|
$prevChar = '';
|
|
$outOfQuotes = true;
|
|
for ($i=0; $i<=$strLen; $i++) {
|
|
$char = substr($json, $i, 1);
|
|
if ($char == '"' && $prevChar != '\\') {
|
|
$outOfQuotes = !$outOfQuotes;
|
|
} elseif (($char == '}' || $char == ']') && $outOfQuotes) {
|
|
$result .= $newLine;
|
|
$pos --;
|
|
for ($j=0; $j<$pos; $j++) {
|
|
$result .= $indentStr;
|
|
}
|
|
}
|
|
$result .= $char;
|
|
if ( ( $char == ',' || $char == '{' || $char == '[' ) && $outOfQuotes ) {
|
|
$result .= $newLine;
|
|
if ($char == '{' || $char == '[') {
|
|
$pos ++;
|
|
}
|
|
for ($j = 0 ; $j < $pos ; $j++) {
|
|
$result .= $indentStr;
|
|
}
|
|
}
|
|
$prevChar = $char;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Remove jsonp callback from a version file
|
|
*
|
|
* @param string $data the json file with callback
|
|
*
|
|
* @return string the json file without callback
|
|
*/
|
|
function clean_json_version($data)
|
|
{
|
|
return str_replace( array( '/*PSK*/pml_version_cb(/*PSK*/' , '/*PSK*/);/*PSK*/' , '/*PSK*/)/*PSK*/' ) , array( '' , '' , '' ) , $data );
|
|
}
|
|
|
|
/**
|
|
* Do nothing for set_error_handler PHP5.2 style
|
|
*
|
|
* @param integer $errno
|
|
* @param string $errstr
|
|
*
|
|
* @return void
|
|
*/
|
|
function dumb_test($errno, $errstr)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* Try to guess who runs the server
|
|
*
|
|
* @return string a user information
|
|
*/
|
|
function get_server_user()
|
|
{
|
|
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
|
|
{
|
|
return '';
|
|
}
|
|
else if ( SAFE_MODE === true )
|
|
{
|
|
// for Suhosin
|
|
return '';
|
|
}
|
|
else
|
|
{
|
|
// for PHP disabled_func
|
|
set_error_handler( "dumb_test" );
|
|
|
|
$a = exec( 'whoami' );
|
|
restore_error_handler();
|
|
|
|
return $a;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tell whether this is a associative array (object in javascript) or not (array in javascript)
|
|
*
|
|
* @param array $arr the array to test
|
|
*
|
|
* @return boolean true if $arr is an associative array
|
|
*/
|
|
function is_assoc($arr)
|
|
{
|
|
return array_keys( $arr ) !== range( 0 , count( $arr ) - 1 );
|
|
}
|
|
|
|
/**
|
|
* Generate a random string
|
|
*
|
|
* @param integer $l the string length
|
|
* @param string $c a list of char in a string taken to generate the string
|
|
*
|
|
* @return string a random string of $l chars
|
|
*/
|
|
function mt_rand_str($l, $c = 'abcdefghijklmnopqrstuvwxyz1234567890_-ABCDEFGHIJKLMNOPQRSTUVWXYZ')
|
|
{
|
|
for ($s = '', $cl = strlen($c)-1, $i = 0; $i < $l; $s .= $c[mt_rand(0, $cl)], ++$i);
|
|
|
|
return $s;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the local ip address of the current client according to proxy and more...
|
|
*
|
|
* @return string an ip address
|
|
*/
|
|
function get_client_ip() {
|
|
$ip = '';
|
|
if ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) {
|
|
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
|
}
|
|
else if ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
|
|
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
|
}
|
|
else if ( isset( $_SERVER['HTTP_X_FORWARDED'] ) ) {
|
|
$ip = $_SERVER['HTTP_X_FORWARDED'];
|
|
}
|
|
else if ( isset( $_SERVER['HTTP_FORWARDED_FOR'] ) ) {
|
|
$ip = $_SERVER['HTTP_FORWARDED_FOR'];
|
|
}
|
|
else if ( isset( $_SERVER['HTTP_FORWARDED'] ) ) {
|
|
$ip = $_SERVER['HTTP_FORWARDED'];
|
|
}
|
|
else if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
|
|
$ip = $_SERVER['REMOTE_ADDR'];
|
|
}
|
|
return $ip;
|
|
}
|
|
|
|
/**
|
|
* Get the current url
|
|
*
|
|
* @param boolean $q include the query string
|
|
*
|
|
* @return string current url
|
|
*/
|
|
function get_current_url( $q = false ) {
|
|
if ( isset( $_SERVER['SERVER_PROTOCOL'] ) ) { // only web, not unittests
|
|
$s = &$_SERVER;
|
|
$ssl = (!empty($s['HTTPS']) && $s['HTTPS'] == 'on') ? true:false;
|
|
$sp = strtolower(@$s['SERVER_PROTOCOL']);
|
|
$protocol = substr($sp, 0, strpos($sp, '/')) . (($ssl) ? 's' : '');
|
|
$port = @$s['SERVER_PORT'];
|
|
$port = ((!$ssl && $port=='80') || ($ssl && $port=='443')) ? '' : ':'.$port;
|
|
$host = isset( $s['HTTP_X_FORWARDED_HOST'] ) ? $s['HTTP_X_FORWARDED_HOST'] : ( isset( $s['HTTP_HOST'] ) ? $s['HTTP_HOST'] : null );
|
|
$host = isset($host) ? $host : @$s['SERVER_NAME'] . $port;
|
|
$uri = $protocol . '://' . $host . @$s['REQUEST_URI'];
|
|
$segments = explode('?', $uri, 2);
|
|
$url = $segments[0];
|
|
if ( $q === true ) {
|
|
if ( isset( $_SERVER['QUERY_STRING'] ) ) {
|
|
$url .= '?' . $_SERVER['QUERY_STRING'];
|
|
}
|
|
}
|
|
return $url;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Tell if the provided IP address is local or not
|
|
*
|
|
* @param string $ip an ipv4 address
|
|
*
|
|
* @return boolean true if address is local
|
|
*/
|
|
function is_not_local_ip( $ip ) {
|
|
$ip = trim( $ip );
|
|
if ( $ip === '127.0.0.1' ) {
|
|
return false;
|
|
}
|
|
return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE);
|
|
}
|
|
|
|
/**
|
|
* Return a 404 error
|
|
*
|
|
* @return void
|
|
*/
|
|
function http404() {
|
|
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found');
|
|
die();
|
|
}
|
|
|
|
/**
|
|
* Return a 403 error
|
|
*
|
|
* @return void
|
|
*/
|
|
function http403() {
|
|
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 403 Forbidden');
|
|
die();
|
|
}
|
|
/**
|
|
* Return a 500 error
|
|
*
|
|
* @return void
|
|
*/
|
|
function http500() {
|
|
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 500 Internal Server Error');
|
|
die();
|
|
}
|
|
|
|
|
|
/**
|
|
* Clean an array recursivly
|
|
*
|
|
* @param array $input the array to clean up
|
|
*
|
|
* @return array the cleaned array
|
|
*/
|
|
function array_filter_recursive($input) {
|
|
foreach ($input as &$value) {
|
|
if (is_array($value)) {
|
|
$value = array_filter_recursive($value);
|
|
}
|
|
else if (is_object($value)) {
|
|
$value = array_filter_recursive((array)$value);
|
|
}
|
|
}
|
|
|
|
return array_filter($input);
|
|
}
|
|
|
|
/**
|
|
* Return the current Pimp My Log Version
|
|
*
|
|
* @return string the version string or empty if not available
|
|
*/
|
|
function get_current_pml_version() {
|
|
$v = '';
|
|
$file = dirname( __FILE__ ) . '/../version.js';
|
|
if ( file_exists( $file ) ) {
|
|
$j = json_decode( clean_json_version( @file_get_contents( $file ) ) , true );
|
|
$v = @$j[ 'version' ];
|
|
}
|
|
return $v;
|
|
}
|
|
|
|
/**
|
|
* Return the current Pimp My Log Version
|
|
*
|
|
* @return string the version string or empty if not available
|
|
*/
|
|
function get_current_pml_version_infos() {
|
|
$i = array();
|
|
$file = dirname( __FILE__ ) . '/../version.js';
|
|
if ( file_exists( $file ) ) {
|
|
$j = json_decode( clean_json_version( @file_get_contents( $file ) ) , true );
|
|
$v = @$j[ 'version' ];
|
|
$i = @$j[ 'changelog' ][ $v ];
|
|
$i['v'] = $v;
|
|
}
|
|
return $i;
|
|
}
|
|
|
|
/**
|
|
* Generate a xml string of the provided array
|
|
*
|
|
* @param array $array the array to convert in XML
|
|
* @param string $node_name the node name for numerical arrays
|
|
*
|
|
* @return string the xml string
|
|
*/
|
|
function generate_xml_from_array( $array, $node_name ) {
|
|
$xml = '';
|
|
if (is_array($array) || is_object($array)) {
|
|
foreach ($array as $key=>$value) {
|
|
if (is_numeric($key)) {
|
|
$key = $node_name;
|
|
}
|
|
|
|
$xml .= '<' . $key . '>' . generate_xml_from_array( $value, $node_name) . '</' . $key . '>';
|
|
}
|
|
} else {
|
|
$xml = htmlspecialchars($array, ENT_QUOTES);
|
|
}
|
|
|
|
return $xml;
|
|
}
|
|
|
|
|
|
/**
|
|
* Return a csv file from an array
|
|
*
|
|
* @param array $array
|
|
*
|
|
* @return null|string
|
|
*/
|
|
function array2csv( $array ) {
|
|
if ( count( $array ) == 0 ) {
|
|
return null;
|
|
}
|
|
ob_start();
|
|
$df = fopen( "php://output" , 'w' );
|
|
fputcsv( $df , array_keys( reset( $array ) ) , "\t" );
|
|
foreach ( $array as $row ) {
|
|
fputcsv( $df , $row , "\t" );
|
|
}
|
|
fclose( $df );
|
|
return ob_get_clean();
|
|
}
|
|
|
|
|
|
/**
|
|
* Return a UTC timestamp from a timestamp computed in a specific timezone
|
|
*
|
|
* @param integer $timestamp the epoch timestamp
|
|
* @param string $tzfrom the timezone where the timesamp has been computed
|
|
*
|
|
* @return integer the epoch in UTC
|
|
*/
|
|
function get_non_UTC_timstamp( $timestamp = null , $tzfrom = null )
|
|
{
|
|
if ( is_null( $tzfrom ) ) {
|
|
$tzfrom = date_default_timezone_get();
|
|
}
|
|
if ( is_null( $timestamp ) ) {
|
|
$timestamp = time();
|
|
}
|
|
|
|
$d = new DateTime( "@" . $timestamp );
|
|
$d->setTimezone( new DateTimeZone( $tzfrom ) );
|
|
|
|
return $timestamp - $d->getOffset();
|
|
}
|
|
|
|
/**
|
|
* Try to guess if Pimp My Log is installed with composer
|
|
*
|
|
* @return boolean
|
|
*/
|
|
function upgrade_is_composer() {
|
|
$a = false;
|
|
|
|
// Catch errors for people who has activated open_basedir restrictions
|
|
set_error_handler( "dumb_test" );
|
|
|
|
if ( basename( PML_BASE ) !== 'pimp-my-log' ) $a = false;
|
|
else if ( ! is_dir( PML_BASE . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'potsky' ) ) $a = false;
|
|
else if ( ! is_dir( PML_BASE . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' ) ) $a = false;
|
|
else if ( ! file_exists( PML_BASE . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'composer.json' ) ) $a = false;
|
|
else $a = true;
|
|
|
|
restore_error_handler();
|
|
|
|
return $a;
|
|
}
|
|
|
|
/**
|
|
* Try to guess if Pimp My Log is installed with git
|
|
*
|
|
* @return boolean
|
|
*/
|
|
function upgrade_is_git() {
|
|
if ( SAFE_MODE === true ) return false;
|
|
|
|
if ( ! is_dir( PML_BASE . DIRECTORY_SEPARATOR . '.git' ) ) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Try to guess if Pimp My Log can pull with git
|
|
*
|
|
* @return mixed
|
|
*/
|
|
function upgrade_can_git_pull() {
|
|
if ( SAFE_MODE === true ) return false;
|
|
|
|
$base = PML_BASE;
|
|
|
|
// Check if git is callable and if all files are not changed
|
|
$a = exec('cd ' . escapeshellarg( $base ) . '; git status -s' , $lines , $code );
|
|
|
|
// Error while executing this comand
|
|
if ( $code !== 0 ) return array( $code , $lines);
|
|
|
|
// Error, files have been modified
|
|
if ( count( $lines ) !== 0 ) return array( $code , $lines);
|
|
|
|
// can write all files with this webserver user ?
|
|
$canwrite = true;
|
|
$lines = array();
|
|
$git = mb_strlen( realpath( $base ) ) + 1;
|
|
$pmlfiles = new RecursiveIteratorIterator(
|
|
new RecursiveDirectoryIterator( $base ),
|
|
RecursiveIteratorIterator::SELF_FIRST
|
|
);
|
|
|
|
foreach ($pmlfiles as $f) {
|
|
|
|
// Ignore all .git/* files
|
|
if ( ( mb_substr( $f->getPathname() , $git , 4 ) ) === '.git' ) continue;
|
|
|
|
// check if this file is writable
|
|
if ( ! $f->isWritable() ) {
|
|
|
|
// check if it ignored or not
|
|
$b = exec( "git ls-files " . escapeshellarg( $f->getPathname() ) );
|
|
if ( ! empty( $b ) ) {
|
|
$canwrite = false;
|
|
$lines[] = $f->getPathname();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( $canwrite === false ) return array( 2706 , $lines );
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Uniq ID
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| We generate a uniq ID for the current user in order to track how many people
|
|
| are currently using Pimp My Log. This value is stored in a cookie in order to
|
|
| keep it
|
|
|
|
|
*/
|
|
if ( isset( $_SERVER['SERVER_PROTOCOL'] ) ) { // only web, not unittests
|
|
if ( ! isset( $_COOKIE['u'] ) ) {
|
|
$uuid = sha1( json_encode( $_SERVER ) . uniqid( '' , true ) );
|
|
setcookie( 'u' , $uuid , time()+60*60*24*3000 , '/' );
|
|
} else {
|
|
$uuid = $_COOKIE['u'];
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Timezone
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
$tz = '';
|
|
if ( isset( $_POST['tz'] ) ) {
|
|
$tz = $_POST['tz'];
|
|
} elseif ( isset( $_GET['tz'] ) ) {
|
|
$tz = $_GET['tz'];
|
|
} elseif ( defined( 'USER_TIME_ZONE' ) ) {
|
|
$tz = USER_TIME_ZONE;
|
|
}
|
|
if ( ! in_array( $tz , $tz_available ) ) {
|
|
$tz = @date('e');
|
|
}
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Define locale and translation
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
$lang = '';
|
|
$locale = $locale_default;
|
|
$localejs = $locale_numeraljs[ $locale_default ];
|
|
|
|
if ( function_exists( 'bindtextdomain' ) ) {
|
|
|
|
if ( isset( $_GET['l'] ) ) {
|
|
$locale = $_GET['l'];
|
|
} elseif ( isset( $_COOKIE['pmllocale'] ) ) {
|
|
$locale = $_COOKIE['pmllocale'];
|
|
} elseif ( defined( 'LOCALE' ) ) {
|
|
$locale = LOCALE;
|
|
} elseif ( isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) {
|
|
@list( $locale, $dumb ) = @explode( ',', $_SERVER['HTTP_ACCEPT_LANGUAGE'], 2 );
|
|
}
|
|
|
|
$locale = str_replace( '-', '_', $locale );
|
|
@list( $lang, $b ) = explode( '_', $locale );
|
|
$locale = strtolower( $lang ).'_'.strtoupper( $b );
|
|
|
|
if ( ! array_key_exists( $locale, $locale_available ) ) {
|
|
$locale = $locale_default;
|
|
}
|
|
|
|
putenv( 'LC_ALL=' . $locale );
|
|
putenv( 'LANGUAGE=' . $locale );
|
|
|
|
if ( ( ! isset( $_COOKIE['pmllocale'] ) ) || ( $_COOKIE['pmllocale'] !== $locale ) ) {
|
|
if ( isset( $_SERVER['SERVER_PROTOCOL'] ) ) { // only web, not unittests
|
|
setcookie( 'pmllocale' , $locale , time()+60*60*24*3000 );
|
|
}
|
|
}
|
|
|
|
if ($lang == 'fr') {
|
|
setlocale( LC_ALL , $locale , $locale . '.utf8' , 'fra' );
|
|
} elseif ($lang == 'de') {
|
|
setlocale( LC_ALL , $locale , $locale . '.utf8' , 'deu_deu' , 'de' , 'ge' );
|
|
} else {
|
|
setlocale( LC_ALL , $locale , $locale . '.utf8' );
|
|
}
|
|
|
|
bindtextdomain( 'messages' , dirname( __FILE__ ) . '/../lang' );
|
|
bind_textdomain_codeset( 'messages' , 'UTF-8' );
|
|
textdomain( 'messages' );
|
|
|
|
define( 'GETTEXT_SUPPORT' , true );
|
|
}
|
|
else {
|
|
/**
|
|
* Fallback function for retrieving texts
|
|
*
|
|
* @param string $text the string to display
|
|
*
|
|
* @return string the same string but not translated!
|
|
*/
|
|
function gettext($text)
|
|
{
|
|
return $text;
|
|
}
|
|
|
|
define( 'GETTEXT_SUPPORT' , false );
|
|
|
|
}
|
|
|
|
?>
|