/home/ivoiecob/email.hirewise-va.com/system/Logger.php
<?php
/**
* This code is licensed under AGPLv3 license or Afterlogic Software License
* if commercial version of the product was purchased.
* For full statements of the licenses see LICENSE-AFTERLOGIC and LICENSE-AGPL3 files.
*/
namespace Aurora\System;
use DateTime;
use DateTimeImmutable;
use Illuminate\Support\Str;
/**
* @license https://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
* @license https://afterlogic.com/products/common-licensing Afterlogic Software License
* @copyright Copyright (c) 2019, Afterlogic Corp.
*
* @category Core
*/
class Logger
{
/**
* @var string
*/
public static $sEventLogPrefix = 'event-';
/**
* @var string
*/
public static $sErrorLogPrefix = 'error-';
/**
* @param string $sDesc
* @param string $sModuleName
*/
public static function LogEvent($sDesc, $sModuleName = '')
{
$oSettings = &Api::GetSettings();
if ($oSettings && $oSettings->EnableEventLogging) {
$sDate = gmdate('H:i:s');
$iIp = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'unknown';
$sUserId = Api::getAuthenticatedUserId();
self::Log('Event: ' . $sUserId . ' > ' . $sDesc);
self::LogOnly('[' . $sDate . '][' . $iIp . '][' . $sUserId . '][' . $sModuleName . '] > ' . $sDesc, self::GetLogFileDir() . self::GetLogFileName(self::$sEventLogPrefix));
}
}
/**
* @param mixed $mObject
* @param int $iLogLevel = \Aurora\System\Enums\LogLevel::Full
* @param string $sFilePrefix = ''
*/
public static function LogObject($mObject, $iLogLevel = Enums\LogLevel::Full, $sFilePrefix = '')
{
self::Log(print_r($mObject, true), $iLogLevel, $sFilePrefix);
}
/**
* @param Exceptions\Exception $mObject
* @param int $iLogLevel = \Aurora\System\Enums\LogLevel::Error
* @param string $sFilePrefix = ''
*/
public static function LogException($mObject, $iLogLevel = Enums\LogLevel::Error, $sFilePrefix = '')
{
$sMessage = '';
$oSettings = & Api::GetSettings();
// if ($oSettings && $oSettings->GetValue('LogStackTrace', false))
// {
// $sMessage = (string) $mObject;
// }
// else
// {
$sMessage = 'Exception: ' . (string) $mObject . ', Code: ' . $mObject->getCode() . ', Message: ' . $mObject->getMessage();
// }
if (0 < \count(Api::$aSecretWords)) {
$sMessage = \str_replace(Api::$aSecretWords, '*******', $sMessage);
}
self::Log($sMessage, $iLogLevel, $sFilePrefix);
}
/**
* @param string $sFilePrefix = ''
*
* @return string
*/
public static function GetLogFileName($sFilePrefix = '', $iTimestamp = 0)
{
$oSettings = & Api::GetSettings();
$sFileName = "log.txt";
if ($oSettings && $oSettings->LogFileName) {
$fCallback = ($iTimestamp === 0)
? function ($matches) {
return date($matches[1]);
}
: function ($matches) use ($iTimestamp) {
return date($matches[1], $iTimestamp);
};
$sFileName = preg_replace_callback('/\{([\w|-]*)\}/', $fCallback, $oSettings->LogFileName);
}
return $sFilePrefix . $sFileName;
}
public static function getLogFileDateFormat()
{
$result = '';
$oSettings = & Api::GetSettings();
if ($oSettings && $oSettings->LogFileName) {
preg_match('/\{([\w|-]*)\}/', $oSettings->LogFileName, $matches);
if (isset($matches[1])) {
$result = $matches[1];
}
}
return $result;
}
public static function GetLogFileDir()
{
static $bDir = null;
static $sLogDir = null;
if (null === $sLogDir) {
$oSettings = & Api::GetSettings();
if ($oSettings) {
$sS = $oSettings->GetValue('LogCustomFullPath', '');
$sLogDir = empty($sS) ? Api::DataPath() . '/logs/' : rtrim(trim($sS), '\\/') . '/';
}
}
if (null === $bDir) {
$bDir = true;
if (!@is_dir($sLogDir)) {
@mkdir($sLogDir, 0777);
}
}
return $sLogDir;
}
/**
* @return \MailSo\Log\Logger
*/
public static function SystemLogger()
{
static $oLogger = null;
if (null === $oLogger) {
$oLogger = \MailSo\Log\Logger::NewInstance();
$oLogger->Add(
\MailSo\Log\Drivers\Callback::NewInstance(function ($sDesc) {
self::Log($sDesc);
})->DisableTimePrefix()->DisableGuidPrefix()
);
$oLogger->AddForbiddenType(\MailSo\Log\Enumerations\Type::TIME);
$oSettings = & Api::GetSettings();
$oLogger->bLogStackTrace = ($oSettings && $oSettings->GetValue('LogStackTrace', false));
}
return $oLogger;
}
/**
* @param string $sDesc
* @param string $sLogFile
*/
private static function dbDebugBacktrace($sDesc, $sLogFile)
{
static $iDbBacktraceCount = null;
if (null === $iDbBacktraceCount) {
$oSettings = & Api::GetSettings();
$iDbBacktraceCount = (int) $oSettings->GetValue('DBDebugBacktraceLimit', 0);
if (!function_exists('debug_backtrace') || version_compare(PHP_VERSION, '5.4.0') < 0) {
$iDbBacktraceCount = 0;
}
}
if (0 < $iDbBacktraceCount && is_string($sDesc) &&
(false !== strpos($sDesc, 'DB[') || false !== strpos($sDesc, 'DB ERROR'))) {
$bSkip = true;
$sLogData = '';
$iCount = $iDbBacktraceCount;
foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 20) as $aData) {
if ($aData && isset($aData['function']) && !in_array(strtolower($aData['function']), array(
'log', 'logonly', 'logend', 'logevent', 'logexception', 'logobject', 'dbdebugbacktrace'))) {
$bSkip = false;
}
if (!$bSkip) {
$iCount--;
if (isset($aData['class'], $aData['type'], $aData['function'])) {
$sLogData .= $aData['class'] . $aData['type'] . $aData['function'];
} elseif (isset($aData['function'])) {
$sLogData .= $aData['function'];
}
if (isset($aData['file'])) {
$sLogData .= ' ../' . basename($aData['file']);
}
if (isset($aData['line'])) {
$sLogData .= ' *' . $aData['line'];
}
$sLogData .= "\n";
}
if (0 === $iCount) {
break;
}
}
if (0 < strlen($sLogData)) {
try {
@error_log('[' . \MailSo\Log\Logger::Guid() . '][DB/backtrace]' . AU_API_CRLF . trim($sLogData) . AU_API_CRLF, 3, $sLogFile);
} catch (\Exception $oE) {
}
}
}
}
/**
* @param string $sDesc
* @param int $iLogLevel = \Aurora\System\Enums\LogLevel::Full
* @param string $sFilePrefix = ''
*/
public static function Log($sDesc, $iLogLevel = Enums\LogLevel::Full, $sFilePrefix = '')
{
static $bIsFirst = true;
$oSettings = &Api::GetSettings();
if ($oSettings && $oSettings->EnableLogging && $iLogLevel <= $oSettings->LoggingLevel) {
try {
$oAuthenticatedUser = Api::getAuthenticatedUser();
} catch (\Exception $oEx) {
$oAuthenticatedUser = false;
}
$sFirstPrefix = "";
if ($oAuthenticatedUser) {
$sFirstPrefix = $oAuthenticatedUser->WriteSeparateLog ? $oAuthenticatedUser->PublicId . '-' : '';
}
$sLogFile = self::GetLogFileDir() . self::GetLogFileName($sFirstPrefix . $sFilePrefix);
$sGuid = \MailSo\Log\Logger::Guid();
$aMicro = explode('.', microtime(true));
$sDate = gmdate('H:i:s.') . str_pad((isset($aMicro[1]) ? substr($aMicro[1], 0, 2) : '0'), 2, '0');
if ($bIsFirst) {
$sUri = Utils::RequestUri();
$bIsFirst = false;
$sPost = (is_array($_POST) && count($_POST) > 0) ? '[POST(' . count($_POST) . ')]' : '[GET]';
self::LogOnly(AU_API_CRLF . '[' . $sDate . '][' . $sGuid . '] ' . $sPost . '[ip:' . (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'unknown') . '] ' . $sUri, $sLogFile);
if ($oSettings->GetValue('LogPostView', false)) {
self::LogOnly('[' . $sDate . '][' . $sGuid . '] POST > ' . print_r($_POST, true), $sLogFile);
} else {
self::LogOnly('[' . $sDate . '][' . $sGuid . '] POST > [' . implode(', ', array_keys($_POST)) . ']', $sLogFile);
}
self::LogOnly('[' . $sDate . '][' . $sGuid . ']', $sLogFile);
}
self::LogOnly('[' . $sDate . '][' . $sGuid . '] ' . (is_string($sDesc) ? $sDesc : print_r($sDesc, true)), $sLogFile);
}
}
/**
* @param string $sDesc
* @param string $sLogFile
*/
public static function LogOnly($sDesc, $sLogFile)
{
if (0 < \count(Api::$aSecretWords)) {
$sDesc = \str_replace(Api::$aSecretWords, '*******', $sDesc);
}
try {
@error_log($sDesc . AU_API_CRLF, 3, $sLogFile);
} catch (\Exception $oE) {
}
self::dbDebugBacktrace($sDesc, $sLogFile);
}
public static function LogSql($sDesc, $iLogLevel = Enums\LogLevel::Full)
{
if (Api::$bUseDbLog) {
$oSettings = &Api::GetSettings();
if ($oSettings && $oSettings->EnableLogging && $iLogLevel <= $oSettings->LoggingLevel) {
$sLogFile = self::GetLogFileDir() . self::GetLogFileName('sql-');
$sGuid = \MailSo\Log\Logger::Guid();
$aMicro = explode('.', microtime(true));
$sDate = gmdate('H:i:s.') . str_pad((isset($aMicro[1]) ? substr($aMicro[1], 0, 2) : '0'), 2, '0');
self::LogOnly('[' . $sDate . '][' . $sGuid . '] ' . $sDesc, $sLogFile);
}
}
}
public static function ClearLog($sFileFullPath)
{
return (@file_exists($sFileFullPath)) ? @unlink($sFileFullPath) : true;
}
public static function RemoveSeparateLogs()
{
$sLogDir = self::GetLogFileDir();
if (is_dir($sLogDir)) {
$aLogFiles = array_diff(scandir($sLogDir), array('..', '.'));
$aUsers = \Aurora\Modules\Core\Module::getInstance()->GetUsersWithSeparateLog();
foreach ($aLogFiles as $sFileName) {
foreach ($aUsers as $sUserPublicId) {
if (Str::startsWith($sFileName, $sUserPublicId)) {
self::ClearLog($sLogDir . $sFileName);
}
}
}
}
}
public static function RemoveOldLogs()
{
$oSettings = &Api::GetSettings();
if ($oSettings) {
$bRemoveOldLogs = $oSettings->GetValue('RemoveOldLogs', true);
$iRemoveOldLogsDays = (int) $oSettings->GetValue('RemoveOldLogsDays', 2);
$sLogDir = self::GetLogFileDir();
if (is_dir($sLogDir) && $bRemoveOldLogs) {
$aLogFiles = glob($sLogDir . '*.txt');
$nowDateTime = new \DateTimeImmutable(date(self::getLogFileDateFormat()));
$dateTimeToRemove = $nowDateTime->sub(new \DateInterval(sprintf('P%dD', $iRemoveOldLogsDays)));
foreach ($aLogFiles as $sFileName) {
$aPathInfo = pathinfo($sFileName);
preg_match('/\w+\-([\d\-]+)$/', $aPathInfo['filename'], $matches, 0);
if (isset($matches[1])) {
$fileDateTime = new \DateTimeImmutable($matches[1]);
if ($fileDateTime <= $dateTimeToRemove) {
if (file_exists($sFileName)) {
unlink($sFileName);
}
}
}
}
}
}
}
public static function GetLoggerGuid()
{
$oSettings = &Api::GetSettings();
if ($oSettings && $oSettings->EnableLogging) {
return \MailSo\Log\Logger::Guid();
}
return '';
}
}