GIF94;
| Path : /var/www/wordpress/wp-content/plugins/oxymade/includes/ |
| Current File : /var/www/wordpress/wp-content/plugins/oxymade/includes/class-oxymade-logger.php |
<?php
/**
* OxyMade Logger Class
*
* Handles controlled logging with levels and sensitive data redaction
*
* @package OxyMade
* @since 0.1.6
*/
namespace OxyMade\Includes;
class Logger {
const DEBUG = 1;
const INFO = 2;
const WARNING = 3;
const ERROR = 4;
private static $instance = null;
private static $log_level = self::ERROR;
private static $log_file = null;
/**
* Initialize logger
*
* @return self Logger instance
*/
public static function init() {
if (null === self::$instance) {
self::$instance = new self();
}
// Set log level based on WP_DEBUG
if (defined('WP_DEBUG') && WP_DEBUG) {
self::$log_level = self::DEBUG;
} elseif (defined('OXYMADE_LOG_LEVEL')) {
self::$log_level = OXYMADE_LOG_LEVEL;
}
// Set custom log file if defined
if (defined('OXYMADE_LOG_FILE')) {
self::$log_file = OXYMADE_LOG_FILE;
}
return self::$instance;
}
/**
* Log debug message
*
* @param string $message Log message
* @param array $context Additional context data
* @return void
*/
public static function debug($message, $context = array()) {
if (self::$log_level <= self::DEBUG) {
self::log('DEBUG', $message, $context);
}
}
/**
* Log info message
*
* @param string $message Log message
* @param array $context Additional context data
* @return void
*/
public static function info($message, $context = array()) {
if (self::$log_level <= self::INFO) {
self::log('INFO', $message, $context);
}
}
/**
* Log warning message
*
* @param string $message Log message
* @param array $context Additional context data
* @return void
*/
public static function warning($message, $context = array()) {
if (self::$log_level <= self::WARNING) {
self::log('WARNING', $message, $context);
}
}
/**
* Log error message
*
* @param string $message Log message
* @param array $context Additional context data
* @return void
*/
public static function error($message, $context = array()) {
if (self::$log_level <= self::ERROR) {
self::log('ERROR', $message, $context);
}
}
/**
* Internal logging method
*
* @param string $level Log level
* @param string $message Log message
* @param array $context Additional context data
* @return void
*/
private static function log($level, $message, $context = array()) {
// Sanitize message - remove sensitive data
$message = self::sanitize_log_message($message);
// Build log entry
$log_entry = sprintf(
'[%s] [OxyMade %s] %s',
current_time('Y-m-d H:i:s'),
$level,
$message
);
// Add context if present
if (!empty($context)) {
$sanitized_context = self::sanitize_log_context($context);
$log_entry .= ' | Context: ' . wp_json_encode($sanitized_context);
}
// Add backtrace for errors in debug mode
if ($level === 'ERROR' && self::$log_level === self::DEBUG) {
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
$log_entry .= ' | Backtrace: ' . wp_json_encode($backtrace);
}
// Write to log
if (self::$log_file) {
error_log($log_entry . "\n", 3, self::$log_file);
} else {
error_log($log_entry);
}
}
/**
* Sanitize log message to remove sensitive data
*
* @param string $message Message to sanitize
* @return string Sanitized message
*/
private static function sanitize_log_message($message) {
// Remove potential tokens/keys
$patterns = array(
'/pt_[a-zA-Z0-9]{20,}/', // SureCart tokens
'/sk_[a-zA-Z0-9]{20,}/', // Secret keys
'/api_key=[a-zA-Z0-9]+/', // API keys in URLs
'/password=[^&\s]+/', // Passwords in URLs
'/token=[a-zA-Z0-9]+/', // Tokens in URLs
'/Authorization:\s*Bearer\s+\S+/', // Auth headers
'/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/', // Email addresses
);
$replacements = array(
'pt_***REDACTED***',
'sk_***REDACTED***',
'api_key=***REDACTED***',
'password=***REDACTED***',
'token=***REDACTED***',
'Authorization: Bearer ***REDACTED***',
'***EMAIL_REDACTED***',
);
return preg_replace($patterns, $replacements, $message);
}
/**
* Sanitize log context to remove sensitive data
*
* @param array $context Context data
* @return array Sanitized context
*/
private static function sanitize_log_context($context) {
$sensitive_keys = array(
'password', 'token', 'api_key', 'secret',
'nonce', 'auth', 'authorization', 'credentials'
);
$sanitized = array();
foreach ($context as $key => $value) {
$key_lower = strtolower($key);
$is_sensitive = false;
foreach ($sensitive_keys as $sensitive) {
if (strpos($key_lower, $sensitive) !== false) {
$is_sensitive = true;
break;
}
}
if ($is_sensitive) {
$sanitized[$key] = '***REDACTED***';
} elseif (is_array($value)) {
$sanitized[$key] = self::sanitize_log_context($value);
} else {
$sanitized[$key] = $value;
}
}
return $sanitized;
}
/**
* Get recent logs
*
* @param int $count Number of log lines to retrieve
* @return array|false Array of log lines or false on failure
*/
public static function get_recent_logs($count = 100) {
if (!current_user_can('manage_options')) {
return false;
}
if (!self::$log_file || !file_exists(self::$log_file)) {
return array();
}
$lines = file(self::$log_file);
return array_slice($lines, -$count);
}
/**
* Clear logs
*
* @return bool True on success, false on failure
*/
public static function clear_logs() {
if (!current_user_can('manage_options')) {
return false;
}
if (self::$log_file && file_exists(self::$log_file)) {
return unlink(self::$log_file);
}
return true;
}
/**
* Get current log level
*
* @return int Current log level
*/
public static function get_log_level() {
return self::$log_level;
}
/**
* Set log level
*
* @param int $level Log level constant
* @return void
*/
public static function set_log_level($level) {
if (in_array($level, array(self::DEBUG, self::INFO, self::WARNING, self::ERROR), true)) {
self::$log_level = $level;
}
}
/**
* Get log level name
*
* @param int $level Log level constant
* @return string Log level name
*/
public static function get_log_level_name($level) {
switch ($level) {
case self::DEBUG:
return 'DEBUG';
case self::INFO:
return 'INFO';
case self::WARNING:
return 'WARNING';
case self::ERROR:
return 'ERROR';
default:
return 'UNKNOWN';
}
}
}