2021-03-31 15:37:32 +01:00
< ? php
if ( ! defined ( 'sugarEntry' ) || ! sugarEntry ) {
die ( 'Not A Valid Entry Point' );
}
/**
*
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM , Inc . Copyright ( C ) 2004 - 2013 SugarCRM Inc .
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd .
* Copyright ( C ) 2011 - 2018 SalesAgility Ltd .
*
* This program is free software ; you can redistribute it and / or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7 ( a ) : FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM , SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE . See the GNU Affero General Public License for more
* details .
*
* You should have received a copy of the GNU Affero General Public License along with
* this program ; if not , see http :// www . gnu . org / licenses or write to the Free
* Software Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA
* 02110 - 1301 USA .
*
* You can contact SugarCRM , Inc . headquarters at 10050 North Wolfe Road ,
* SW2 - 130 , Cupertino , CA 95014 , USA . or at email address contact @ sugarcrm . com .
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices , as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7 ( b ) of the GNU Affero General Public License version 3 ,
* these Appropriate Legal Notices must retain the display of the " Powered by
* SugarCRM " logo and " Supercharged by SuiteCRM " logo. If the display of the logos is not
* reasonably feasible for technical reasons , the Appropriate Legal Notices must
* display the words " Powered by SugarCRM " and " Supercharged by SuiteCRM " .
*/
/*********************************************************************************
* Description : Defines the English language pack for the base application .
* Portions created by SugarCRM are Copyright ( C ) SugarCRM , Inc .
* All Rights Reserved .
* Contributor ( s ) : ______________________________________ ..
********************************************************************************/
require_once ( 'include/SugarLogger/LoggerManager.php' );
require_once ( 'include/SugarLogger/LoggerTemplate.php' );
/**
* Default SugarCRM Logger
* @ api
*/
class SugarLogger implements LoggerTemplate
{
/**
* properties for the SugarLogger
*/
protected $logfile = 'suitecrm' ;
protected $ext = '.log' ;
protected $dateFormat = '%c' ;
protected $logSize = '10MB' ;
protected $maxLogs = 10 ;
protected $filesuffix = " " ;
protected $date_suffix = " " ;
protected $log_dir = '.' ;
2021-08-30 10:17:18 +01:00
protected $defaultPerms = 0664 ;
2021-03-31 15:37:32 +01:00
/**
* used for config screen
*/
public static $filename_suffix = array (
//bug#50265: Added none option for previous version users
" " => " None " ,
" %m_%Y " => " Month_Year " ,
" %d_%m " => " Day_Month " ,
" %m_%d_%y " => " Month_Day_Year " ,
);
/**
* Let 's us know if we' ve initialized the logger file
*/
protected $initialized = false ;
/**
* Logger file handle
*/
protected $fp = false ;
public function __get (
$key
) {
return $this -> $key ;
}
/**
* Used by the diagnostic tools to get SugarLogger log file information
*/
public function getLogFileNameWithPath ()
{
return $this -> full_log_file ;
}
/**
* Used by the diagnostic tools to get SugarLogger log file information
*/
public function getLogFileName ()
{
return ltrim ( $this -> full_log_file , " ./ " );
}
/**
* Constructor
*
* Reads the config file for logger settings
*/
public function __construct ()
{
$config = SugarConfig :: getInstance ();
$this -> ext = $config -> get ( 'logger.file.ext' , $this -> ext );
$this -> logfile = $config -> get ( 'logger.file.name' , $this -> logfile );
$this -> dateFormat = $config -> get ( 'logger.file.dateFormat' , $this -> dateFormat );
$this -> logSize = $config -> get ( 'logger.file.maxSize' , $this -> logSize );
$this -> maxLogs = $config -> get ( 'logger.file.maxLogs' , $this -> maxLogs );
$this -> filesuffix = $config -> get ( 'logger.file.suffix' , $this -> filesuffix );
2021-08-30 10:17:18 +01:00
$this -> defaultPerms = $config -> get ( 'logger.file.perms' , $this -> defaultPerms );
2021-03-31 15:37:32 +01:00
$log_dir = $config -> get ( 'log_dir' , $this -> log_dir );
$this -> log_dir = $log_dir . ( empty ( $log_dir ) ? '' : '/' );
unset ( $config );
$this -> _doInitialization ();
LoggerManager :: setLogger ( 'default' , 'SugarLogger' );
}
/**
* Handles the SugarLogger initialization
*/
protected function _doInitialization ()
{
if ( $this -> filesuffix && array_key_exists ( $this -> filesuffix , self :: $filename_suffix )) { //if the global config contains date-format suffix, it will create suffix by parsing datetime
$this -> date_suffix = " _ " . date ( str_replace ( " % " , " " , $this -> filesuffix ));
}
$this -> full_log_file = $this -> log_dir . $this -> logfile . $this -> date_suffix . $this -> ext ;
$this -> initialized = $this -> _fileCanBeCreatedAndWrittenTo ();
$this -> rollLog ();
}
/**
* Checks to see if the SugarLogger file can be created and written to
2021-08-30 10:17:18 +01:00
* @ noinspection PhpUndefinedFieldInspection
* @ return bool
2021-03-31 15:37:32 +01:00
*/
protected function _fileCanBeCreatedAndWrittenTo ()
{
2021-08-30 10:17:18 +01:00
if ( is_writable ( $this -> full_log_file )) {
return true ;
}
2021-03-31 15:37:32 +01:00
2021-08-30 10:17:18 +01:00
if ( ! is_file ( $this -> full_log_file )) {
@ touch ( $this -> full_log_file );
if ( $this -> defaultPerms !== false ) {
@ chmod ( $this -> full_log_file , $this -> defaultPerms );
}
return is_writable ( $this -> full_log_file );
2021-03-31 15:37:32 +01:00
}
2021-08-30 10:17:18 +01:00
return false ;
2021-03-31 15:37:32 +01:00
}
/**
* for log () function , it shows a backtrace information in log when
* the 'show_log_trace' config variable is set and true
* @ return string a readable trace string
*/
private function getTraceString ()
{
$ret = '' ;
$trace = debug_backtrace ();
foreach ( $trace as $call ) {
$file = isset ( $call [ 'file' ]) ? $call [ 'file' ] : '???' ;
$line = isset ( $call [ 'line' ]) ? $call [ 'line' ] : '???' ;
$class = isset ( $call [ 'class' ]) ? $call [ 'class' ] : '' ;
$type = isset ( $call [ 'type' ]) ? $call [ 'type' ] : '' ;
$function = isset ( $call [ 'function' ]) ? $call [ 'function' ] : '???' ;
$ret .= " \n Call in { $file } at # { $line } from { $class } { $type } { $function } (...) " ;
}
$ret .= " \n " ;
return $ret ;
}
/**
* Show log
* and show a backtrace information in log when
* the 'show_log_trace' config variable is set and true
* see LoggerTemplate :: log ()
*/
public function log (
$level ,
$message
) {
global $sugar_config ;
if ( ! $this -> initialized ) {
return ;
}
//lets get the current user id or default to -none- if it is not set yet
$userID = ( ! empty ( $GLOBALS [ 'current_user' ] -> id )) ? $GLOBALS [ 'current_user' ] -> id : '-none-' ;
//if we haven't opened a file pointer yet let's do that
if ( ! $this -> fp ) {
$this -> fp = fopen ( $this -> full_log_file , 'ab' );
}
// change to a string if there is just one entry
if ( is_array ( $message ) && count ( $message ) == 1 ) {
$message = array_shift ( $message );
}
// change to a human-readable array output if it's any other array
if ( is_array ( $message )) {
$message = print_r ( $message , true );
}
if ( isset ( $sugar_config [ 'show_log_trace' ]) && $sugar_config [ 'show_log_trace' ]) {
$trace = $this -> getTraceString ();
$message .= ( " \n " . $trace );
}
//write out to the file including the time in the dateFormat the process id , the user id , and the log level as well as the message
fwrite (
$this -> fp ,
strftime ( $this -> dateFormat ) . ' [' . getmypid () . '][' . $userID . '][' . strtoupper ( $level ) . '] ' . $message . " \n "
);
}
/**
* rolls the logger file to start using a new file
*/
protected function rollLog (
$force = false
) {
if ( ! $this -> initialized || empty ( $this -> logSize )) {
return ;
}
// bug#50265: Parse the its unit string and get the size properly
$units = array (
'b' => 1 , //Bytes
'k' => 1024 , //KBytes
'm' => 1024 * 1024 , //MBytes
'g' => 1024 * 1024 * 1024 , //GBytes
);
if ( preg_match ( '/^\s*([0-9]+\.[0-9]+|\.?[0-9]+)\s*(k|m|g|b)(b?ytes)?/i' , $this -> logSize , $match )) {
$rollAt = ( int ) $match [ 1 ] * $units [ strtolower ( $match [ 2 ])];
}
//check if our log file is greater than that or if we are forcing the log to roll if and only if roll size assigned the value correctly
if ( $force || ( $rollAt && filesize ( $this -> full_log_file ) >= $rollAt )) {
//now lets move the logs starting at the oldest and going to the newest
for ( $i = $this -> maxLogs - 2 ; $i > 0 ; $i -- ) {
if ( file_exists ( $this -> log_dir . $this -> logfile . $this -> date_suffix . '_' . $i . $this -> ext )) {
$to = $i + 1 ;
$old_name = $this -> log_dir . $this -> logfile . $this -> date_suffix . '_' . $i . $this -> ext ;
$new_name = $this -> log_dir . $this -> logfile . $this -> date_suffix . '_' . $to . $this -> ext ;
//nsingh- Bug 22548 Win systems fail if new file name already exists. The fix below checks for that.
//if/else branch is necessary as suggested by someone on php-doc ( see rename function ).
sugar_rename ( $old_name , $new_name );
//rename ( $this->logfile . $i . $this->ext, $this->logfile . $to . $this->ext );
}
}
//now lets move the current .log file
sugar_rename ( $this -> full_log_file , $this -> log_dir . $this -> logfile . $this -> date_suffix . '_1' . $this -> ext );
}
}
/**
* This is needed to prevent unserialize vulnerability
*/
public function __wakeup ()
{
// clean all properties
foreach ( get_object_vars ( $this ) as $k => $v ) {
$this -> $k = null ;
}
throw new Exception ( " Not a serializable object " );
}
/**
* Destructor
*
* Closes the SugarLogger file handle
*/
public function __destruct ()
{
if ( $this -> fp ) {
fclose ( $this -> fp );
$this -> fp = false ;
}
}
}