-theme`.
* @var string $plugin The product's title.
* @var string $wp_user_id An optional WP user ID that this admin notice is for.
* }
* @return bool
*/
public function freemius_show_admin_notice( $show, $msg ) {
if ( $this->settings()->CurrentUserCan( 'edit' ) ) {
return $show;
}
return false;
}
/**
* Changes some of the strings that freemius outputs with out own.
*
* @method adjust_freemius_strings
* @since 4.0.0
*/
public function adjust_freemius_strings() {
// only update these messages if using premium plugin.
if ( ( ! wsal_freemius()->is_premium() ) || ( ! method_exists( wsal_freemius(), 'override_il8n' ) ) ) {
return;
}
wsal_freemius()->override_i18n(
array(
'few-plugin-tweaks' => __( 'You need to activate the licence key to use WP Activity Log Premium. %2$s', 'wp-security-audit-log' ),
'optin-x-now' => __( 'Activate the licence key now', 'wp-security-audit-log' ),
)
);
}
/**
* Limited License Activation Error.
*
* @param string $error - Error Message.
* @return string
*/
public function limited_license_activation_error( $error ) {
$site_count = null;
preg_match( '!\d+!', $error, $site_count );
// Check if this is an expired error.
if ( strpos( $error, 'expired' ) !== false ) {
/* Translators: Expired message and time */
$error = sprintf( esc_html__( '%s You need to renew your license to continue using premium features.', 'wp-security-audit-log' ), preg_replace('/\([^)]+\)/','', $error ) );
}
elseif ( ! empty( $site_count[0] ) ) {
/* Translators: Number of sites */
$error = sprintf( esc_html__( 'The license is limited to %s sub-sites. You need to upgrade your license to cover all the sub-sites on this network.', 'wp-security-audit-log' ), $site_count[0] );
}
return $error;
}
/**
* Start to trigger the events after installation.
*
* @internal
*/
public function init() {
// Load dependencies.
if ( ! isset( $this->alerts ) ) {
$this->alerts = new WSAL_AlertManager( $this );
}
if ( ! isset( $this->constants ) ) {
$this->constants = new WSAL_ConstantManager();
}
$this->sensors = new WSAL_SensorManager( $this );
if ( is_admin() ) {
$this->views = new WSAL_ViewManager( $this );
$this->widgets = new WSAL_WidgetManager( $this );
}
// Start listening to events.
if ( ! empty( $this->sensors ) && $this->sensors instanceof WSAL_SensorManager ) {
$this->sensors->HookEvents();
}
if ( is_admin() ) {
if ( $this->settings()->IsArchivingEnabled() ) {
// Check the current page.
$get_page = filter_input( INPUT_GET, 'page', FILTER_SANITIZE_STRING );
if ( ( ! isset( $get_page ) || 'wsal-auditlog' !== $get_page ) && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) ) {
$selected_db = get_transient( 'wsal_wp_selected_db' );
$selected_db_user = (int) get_transient( 'wsal_wp_selected_db_user' );
if ( $selected_db && ( get_current_user_id() === $selected_db_user ) ) {
// Delete the transient.
delete_transient( 'wsal_wp_selected_db' );
delete_transient( 'wsal_wp_selected_db_user' );
}
}
}
// Hide plugin.
if ( $this->settings()->IsIncognito() ) {
add_action( 'admin_head', array( $this, 'HidePlugin' ) );
add_filter( 'all_plugins', array( $this, 'wsal_hide_plugin' ) );
}
// Update routine.
$old_version = $this->GetOldVersion();
$new_version = $this->GetNewVersion();
if ( $old_version !== $new_version ) {
$this->Update( $old_version, $new_version );
}
}
/**
* Action: `wsal_init`
*
* Action hook to mark that WSAL has initialized.
*
* @param WpSecurityAuditLog $this – Instance of main plugin class.
*/
do_action( 'wsal_init', $this );
}
/**
* Plugin Deactivation Actions.
*
* This function runs on plugin deactivation to send
* deactivation email.
*
* @since 3.3.1
*/
public function deactivate_actions() {
/**
* Allow short circuiting of the deactivation email sending by using
* this filter to return true here instead of default false.
*
* @since 3.5.2
*
* @var bool
*/
if ( apply_filters( 'wsal_filter_prevent_deactivation_email_delivery', false ) ) {
return;
}
// Send deactivation email.
if ( class_exists( 'WSAL_Utilities_Emailer' ) ) {
// Get email template.
WSAL_Utilities_Emailer::send_deactivation_email();
}
}
/**
* Disable Custom Field through ajax.
*
* @internal
*/
public function AjaxDisableCustomField() {
// Die if user does not have permission to disable.
if ( ! $this->settings()->CurrentUserCan( 'edit' ) ) {
echo '' . esc_html__( 'Error: You do not have sufficient permissions to disable this custom field.', 'wp-security-audit-log' ) . '
';
die();
}
// Set filter input args.
$filter_input_args = array(
'disable_nonce' => FILTER_SANITIZE_STRING,
'notice' => FILTER_SANITIZE_STRING,
);
// Filter $_POST array for security.
$post_array = filter_input_array( INPUT_POST, $filter_input_args );
if ( ! isset( $post_array['disable_nonce'] ) || ! wp_verify_nonce( $post_array['disable_nonce'], 'disable-custom-nonce' . $post_array['notice'] ) ) {
die();
}
$excluded_meta_raw = $this->GetGlobalSetting( 'excluded-custom' );
$excluded_meta = [];
if ( isset( $excluded_meta_raw ) && '' != $excluded_meta_raw ) {
$excluded_meta = explode(',', $excluded_meta_raw);
}
array_push( $excluded_meta, esc_html( $post_array['notice'] ) );
$this->SetGlobalSetting( 'excluded-custom', implode(',', array_unique( $excluded_meta ) ) );
// Exclude object link.
$exclude_objects_link = add_query_arg(
array(
'page' => 'wsal-settings',
'tab' => 'exclude-objects',
),
network_admin_url( 'admin.php' )
);
echo wp_sprintf(
'' . __( 'Custom Field %1$s is no longer being monitored.
Enable the monitoring of this custom field again from the', 'wp-security-audit-log' ) . ' %3$s%4$s
',
$post_array['notice'],
$exclude_objects_link,
__( 'Excluded Objects', 'wp-security-audit-log' ),
__( ' tab in the plugin settings', 'wp-security-audit-log' )
);
die;
}
/**
* Disable Alert through ajax.
*
* @internal
*/
public function AjaxDisableByCode() {
// Die if user does not have permission to disable.
if ( ! $this->settings()->CurrentUserCan( 'edit' ) ) {
echo '' . esc_html__( 'Error: You do not have sufficient permissions to disable this alert.', 'wp-security-audit-log' ) . '
';
die();
}
// Set filter input args.
$filter_input_args = array(
'disable_nonce' => FILTER_SANITIZE_STRING,
'code' => FILTER_SANITIZE_STRING,
);
// Filter $_POST array for security.
$post_array = filter_input_array( INPUT_POST, $filter_input_args );
if ( ! isset( $post_array['disable_nonce'] ) || ! wp_verify_nonce( $post_array['disable_nonce'], 'disable-alert-nonce' . $post_array['code'] ) ) {
die();
}
$s_alerts = $this->GetGlobalSetting( 'disabled-alerts' );
if ( isset( $s_alerts ) && '' != $s_alerts ) {
$s_alerts .= ',' . esc_html( $post_array['code'] );
} else {
$s_alerts = esc_html( $post_array['code'] );
}
$this->SetGlobalSetting( 'disabled-alerts', $s_alerts );
echo wp_sprintf( '' . __( 'Alert %1$s is no longer being monitored.
%2$s', 'wp-security-audit-log' ) . '
', esc_html( $post_array['code'] ), __( 'You can enable this alert again from the Enable/Disable Alerts node in the plugin menu.', 'wp-security-audit-log' ) );
die;
}
/**
* Render plugin stuff in page footer.
*
* @internal
*/
public function render_footer() {
// Register common script.
wp_register_script(
'wsal-common',
$this->GetBaseUrl() . '/js/common.js',
array( 'jquery' ),
filemtime( $this->GetBaseDir() . '/js/common.js' ),
true
);
// live events disabled in free version of the plugin
$live_events_enabled = false;
// Set data array for common script.
$script_data = array(
'ajaxURL' => admin_url( 'admin-ajax.php' ),
'liveEvents' => $live_events_enabled,
'installing' => __( 'Installing, please wait', 'wp-security-audit-log' ),
'already_installed' => __( 'Already installed', 'wp-security-audit-log' ),
'installed' => __( 'Extension installed', 'wp-security-audit-log' ),
'activated' => __( 'Extension activated', 'wp-security-audit-log' ),
'failed' => __( 'Install failed', 'wp-security-audit-log' ),
);
wp_localize_script( 'wsal-common', 'wsalCommonData', $script_data );
// Enqueue script.
wp_enqueue_script( 'wsal-common' );
}
/**
* Load the rest of the system.
*
* @internal
*/
public function load_wsal() {
require_once 'classes/Alert.php';
require_once 'classes/AbstractLogger.php';
require_once 'classes/AbstractSensor.php';
require_once 'classes/AbstractMetaDataSensor.php';
require_once 'classes/AlertManager.php';
require_once 'classes/ConstantManager.php';
require_once 'classes/Loggers/Database.php';
require_once 'classes/SensorManager.php';
require_once 'classes/Sensors/Public.php';
require_once 'classes/Settings.php';
if ( is_admin() ) {
// Initiate settings object if not set.
if ( ! $this->settings ) {
$this->settings = new WSAL_Settings( $this );
}
// Setting the pruning date with the old value or the default value.
$pruning_date = $this->settings()->GetPruningDate();
$this->settings()->SetPruningDate( $pruning_date );
// Load translations.
load_plugin_textdomain( 'wp-security-audit-log', false, basename( dirname( __FILE__ ) ) . '/languages/' );
}
}
/**
* Install all assets required for a useable system.
* @throws Freemius_Exception
*/
public function Install() {
$installation_errors = false;
// Check for minimum PHP version.
if ( version_compare( PHP_VERSION, self::MIN_PHP_VERSION ) < 0 ) {
/* Translators: %s: PHP Version */
$installation_errors = sprintf( esc_html__( 'You are using a version of PHP that is older than %s, which is no longer supported.', 'wp-security-audit-log' ), esc_html( self::MIN_PHP_VERSION ) );
$installation_errors .= '
';
$installation_errors .= __( 'Contact us on plugins@wpwhitesecurity.com to help you switch the version of PHP you are using.', 'wp-security-audit-log' );
}
if ( self::is_plugin_active( 'mainwp/mainwp.php' ) ) {
/* Translators: %s: Activity Log for MainWP plugin hyperlink */
$installation_errors = sprintf( __( 'Please install the %s plugin on the MainWP dashboard.', 'wp-security-audit-log' ), '' . __( 'Activity Log for MainWP', 'wp-security-audit-log' ) . '' ) . ' ';
/* Translators: %s: Getting started guide hyperlink */
$installation_errors .= sprintf( __( 'The WP Activity Log should be installed on the child sites only. Refer to the %s for more information.', 'wp-security-audit-log' ), '' . __( 'getting started guide', 'wp-security-audit-log' ) . '' );
}
if ( $installation_errors ) {
?>
setup();
$this->init();
// disable database sensor during the creation of tables
WSAL_Sensors_Database::$enabled = false;
// On first install this won't be loaded because not premium, add it
// now so it installs.
$this->load_sessions_extension_db_adapter();
// run any installs.
self::getConnector()->installAll();
self::getConnector()->getAdapter( 'Occurrence' )->create_indexes();
self::getConnector()->getAdapter( 'Meta' )->create_indexes();
if ( $this->settings()->IsArchivingEnabled() ) {
$this->settings()->SwitchToArchiveDB();
self::getConnector()->getAdapter( 'Occurrence' )->create_indexes();
self::getConnector()->getAdapter( 'Meta' )->create_indexes();
}
// If system already installed, do updates now (if any).
$old_version = $this->GetOldVersion();
$new_version = $this->GetNewVersion();
if ( $old_version !== $new_version ) {
$this->Update( $old_version, $new_version );
}
// Install cleanup hook (remove older one if it exists).
wp_clear_scheduled_hook( 'wsal_cleanup' );
wp_schedule_event( current_time( 'timestamp' ) + 600, 'hourly', 'wsal_cleanup' );
// WSAL Audit Log page redirect option in anonymous mode.
if ( 'anonymous' === $this->GetGlobalSetting( 'freemius_state', 'anonymous' ) ) {
$this->SetGlobalSetting( 'redirect_on_activate', true );
}
// Run on each install to check MainWP Child plugin.
$this->settings()->set_mainwp_child_stealth_mode();
// re-enable the database sensor after the tables are created
WSAL_Sensors_Database::$enabled = true;
}
/**
* Run some code that updates critical components required for a newer version.
*
* @param string $old_version The old version.
* @param string $new_version The new version.
*
* @throws Freemius_Exception
*/
public function Update( $old_version, $new_version ) {
// Update version in db.
$this->SetGlobalSetting( 'version', $new_version );
if ( '0.0.0' === $old_version ) {
// set some initial plugins settings (only the ones that bypass the regular settings retrieval at some
// point) - e.g. disabled events
$this->SetGlobalSetting( 'disabled-alerts', implode( ',', $this->settings()->always_disabled_alerts ) );
}
// Do version-to-version specific changes.
if ( '0.0.0' !== $old_version && -1 === version_compare( $old_version, $new_version ) ) {
// Dismiss privacy notice.
if ( empty( $this->views ) ) {
$this->views = new WSAL_ViewManager( $this );
}
$this->views->FindByClassName( 'WSAL_Views_AuditLog' )->DismissNotice( 'wsal-privacy-notice-3.2' );
/**
* Delete advert transient on every update.
*
* @since 3.2.4
*/
if ( wsal_freemius()->is_free_plan() ) {
$delete_transient_fn = $this->IsMultisite() ? 'delete_site_transient' : 'delete_transient'; // Check for multisite.
$delete_transient_fn( 'wsal-is-advert-dismissed' ); // Delete advert transient.
}
/**
* MainWP Child Stealth Mode Update
*
* This update only needs to run if the stealth mode option
* does not exist on free version.
*
* @since 3.2.3.3
*/
if ( ! $this->GetGlobalBooleanSetting( 'mwp-child-stealth-mode', false ) ) {
$this->settings()->set_mainwp_child_stealth_mode();
}
// remove obsolete options from the database
if ( version_compare( $new_version, '4.1.4', '>=' ) ) {
$this->DeleteSettingByName( WpSecurityAuditLog::OPTIONS_PREFIX . 'addon_available_notice_dismissed' );
// Remove old file scanning options.
global $wpdb;
$plugin_options = $wpdb->get_results( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE 'wsal_local_files_%'" );
if ( ! empty( $plugin_options ) ) {
foreach( $plugin_options as $option ) {
$this->DeleteSettingByName( $option->option_name );
}
}
}
if ( version_compare( $new_version, '4.1.5', '>=' ) ) {
// remove 'system' entry from the front-end events array as it was removed along with 404 tracking
$frontend_events = WSAL_Settings::get_frontend_events();
if ( array_key_exists( 'system', $frontend_events ) ) {
unset( $frontend_events['system'] );
WSAL_Settings::set_frontend_events( $frontend_events );
}
// remove all settings related to 404 tracking
$not_found_page_related_settings = [
'log-404',
'purge-404-log',
'log-404-referrer',
'log-visitor-404',
'purge-visitor-404-log',
'log-visitor-404-referrer',
'excluded-urls'
];
foreach ( $not_found_page_related_settings as $setting_name ) {
$this->DeleteSettingByName( WpSecurityAuditLog::OPTIONS_PREFIX . $setting_name );
}
// remove cron job for purging 404 logs
if ( $schedule_time = wp_next_scheduled( 'wsal_log_files_pruning' ) ) {
wp_unschedule_event($schedule_time, 'wsal_log_files_pruning', [] );
}
}
if ( version_compare( $new_version, '4.2.0', '>=' ) ) {
// delete custom logging dir path from the settings
$this->DeleteSettingByName( WpSecurityAuditLog::OPTIONS_PREFIX . 'custom-logging-dir' );
// delete dev options from the settings
$this->DeleteSettingByName( WpSecurityAuditLog::OPTIONS_PREFIX . 'dev-options' );
}
}
}
/**
* Migrate data from old plugin.
*/
public function Migrate() {
global $wpdb;
static $mig_types = array(
3000 => 5006,
);
// Load data.
$sql = 'SELECT * FROM ' . $wpdb->base_prefix . 'wordpress_auditlog_events';
$events = array();
foreach ( $wpdb->get_results( $sql, ARRAY_A ) as $item ) {
$events[ $item['EventID'] ] = $item;
}
$sql = 'SELECT * FROM ' . $wpdb->base_prefix . 'wordpress_auditlog';
$auditlog = $wpdb->get_results( $sql, ARRAY_A );
// Migrate using db logger.
foreach ( $auditlog as $entry ) {
$data = array(
'ClientIP' => $entry['UserIP'],
'UserAgent' => '',
'CurrentUserID' => $entry['UserID'],
);
if ( $entry['UserName'] ) {
$data['Username'] = base64_decode( $entry['UserName'] );
}
$mesg = $events[ $entry['EventID'] ]['EventDescription'];
$date = strtotime( $entry['EventDate'] );
$type = $entry['EventID'];
if ( isset( $mig_types[ $type ] ) ) {
$type = $mig_types[ $type ];
}
// Convert message from '%s' to '%Arg1%' format.
$c = 0;
$n = '%s';
$l = strlen( $n );
while ( ( $pos = strpos( $mesg, $n ) ) !== false ) {
$mesg = substr_replace( $mesg, '%MigratedArg' . ( $c++ ) . '%', $pos, $l );
}
$data['MigratedMesg'] = $mesg;
// Generate new meta data args.
$temp = unserialize( base64_decode( $entry['EventData'] ) );
foreach ( (array) $temp as $i => $item ) {
$data[ 'MigratedArg' . $i ] = $item;
}
// send event data to logger!
foreach ( $this->alerts->GetLoggers() as $logger ) {
$logger->Log( $type, $data, $date, $entry['BlogId'], true );
}
}
// Migrate settings.
$this->settings()->SetAllowedPluginViewers(
get_option( 'WPPH_PLUGIN_ALLOW_ACCESS' )
);
$s = get_option( 'wpph_plugin_settings' );
$this->settings()->SetViewPerPage( max( $s->showEventsViewList, 5 ) );
$this->settings()->SetWidgetsEnabled( $s->showDW );
}
/**
* The current plugin version (according to plugin file metadata).
*
* @return string
*/
public function GetNewVersion() {
$version = get_plugin_data( __FILE__, false, false );
return isset( $version['Version'] ) ? $version['Version'] : '0.0.0';
}
/**
* The plugin version as stored in DB (will be the old version during an update/install).
*
* @return string
*/
public function GetOldVersion() {
return $this->GetGlobalSetting( 'version', '0.0.0' );
}
/**
* To be called in admin header for hiding plugin form Plugins list.
*
* @internal
*/
public function HidePlugin() {
if ( ! $this->_settings->CurrentUserCan( 'view' ) ) {
$selectr = '';
$plugins = array( 'wp-security-audit-log', 'wp-security-audit-log-premium' );
foreach ( $plugins as $value ) {
$selectr .= '.wp-list-table.plugins tr[data-slug="' . $value . '"], ';
}
?>
GetClassFileClassName() instead.
*/
public function GetClassFileClassName( $file ) {
return $this->autoloader->GetClassFileClassName( $file );
}
/**
* Return whether we are running on multisite or not.
*
* @return boolean
*/
public function IsMultisite() {
return function_exists( 'is_multisite' ) && is_multisite();
}
/**
* Get a global option.
*
* Deprecated function. It is only kept for the extension plugins. Nothing in the main plugin uses it, not even
* the upgrade process.
*
* @param string $option - Option name.
* @param mixed $default - (Optional) Value returned when option is not set (defaults to false).
* @param string $prefix - (Optional) A prefix used before option name.
* @return mixed - Option's value or $default if option not set.
*
* @deprecated 4.1.3 Use WpSecurityAuditLog::GetGlobalSetting instead
* @see WpSecurityAuditLog::GetGlobalSetting()
*/
public function GetGlobalOption( $option, $default = false, $prefix = '' ) {
return $this->GetGlobalSetting( $option, $default );
}
/**
* Get a global setting.
*
* @param string $option - Option name.
* @param mixed $default - (Optional) Value returned when option is not set (defaults to false).
*
* @return mixed - Option's value or $default if option not set.
*/
public function GetGlobalSetting( $option, $default = false ) {
$this->include_options_helper();
return $this->options_helper->get_option_value( $option, $default );
}
/**
* Set a global option.
*
* Deprecated function. It is only kept for the extension plugins. Nothing in the main plugin uses it, not even
* the upgrade process.
*
* @param string $option - Option name.
* @param mixed $value - New value for option.
* @param string $prefix - (Optional) A prefix used before option name.
*
* @deprecated 4.1.3 Use WpSecurityAuditLog::SetGlobalSetting instead
* @see WpSecurityAuditLog::SetGlobalSetting()
*/
public function SetGlobalOption( $option, $value, $prefix = '' ) {
$this->SetGlobalSetting( $option, $value );
}
/**
* Set a global setting.
*
* @param string $option - Option name.
* @param mixed $value - New value for option.
*
* @return bool
*/
public function SetGlobalSetting( $option, $value ) {
$this->include_options_helper();
return $this->options_helper->set_option_value( $option, $value );
}
/**
* Get a global boolean setting. It takes care of the conversion between string and boolean.
*
* @param string $option - Option name.
* @param boolean $default - (Optional) Value returned when option is not set (defaults to false).
* @return boolean - Option's value or $default if option not set.
* @since 4.1.3
*/
public function GetGlobalBooleanSetting( $option, $default = false ) {
$result = $this->GetGlobalSetting( $option, \WSAL\Helpers\Options::string_to_bool( $default ) );
return \WSAL\Helpers\Options::string_to_bool( $result );
}
/**
* Sets a global boolean setting. It takes care of the conversion between string and boolean.
*
* @param string $option - Option name.
* @param mixed $value - New value for option.
* @since 4.1.3
*/
public function SetGlobalBooleanSetting( $option, $value ) {
$boolean_value = \WSAL\Helpers\Options::string_to_bool( $value );
$this->SetGlobalSetting( $option, \WSAL\Helpers\Options::bool_to_string( $boolean_value ) );
}
/**
* Run cleanup routines.
*/
public function CleanUp() {
foreach ( $this->_cleanup_hooks as $hook ) {
call_user_func( $hook );
}
}
/**
* Clear last 30 day's failed login alert usernames.
*/
public function delete_failed_logins() {
// Set the dates.
list( $y, $m, $d ) = explode( '-', date( 'Y-m-d' ) );
// Site id.
$site_id = function_exists( 'get_current_blog_id' ) ? get_current_blog_id() : 0;
// New occurrence object.
$occurrence = new WSAL_Models_Occurrence();
$alerts = $occurrence->check_alert_1003(
array(
1003,
$site_id,
mktime( 0, 0, 0, $m - 1, $d, $y ) + 1,
mktime( 0, 0, 0, $m, $d, $y ),
)
);
// Alerts exists then continue.
if ( ! empty( $alerts ) ) {
foreach ( $alerts as $alert ) {
// Flush the usernames meta data.
$alert->UpdateMetaValue( 'Users', array() );
}
}
}
/**
* Add callback to be called when a cleanup operation is required.
*
* @param callable $hook - Hook name.
*/
public function AddCleanupHook( $hook ) {
$this->_cleanup_hooks[] = $hook;
}
/**
* Remove a callback from the cleanup callbacks list.
*
* @param callable $hook - Hook name.
*/
public function RemoveCleanupHook( $hook ) {
while ( ( $pos = array_search( $hook, $this->_cleanup_hooks ) ) !== false ) {
unset( $this->_cleanup_hooks[ $pos ] );
}
}
/**
* DB connection.
*
* @param mixed $config DB configuration.
* @param bool $reset - True if reset.
*
* @return WSAL_Connector_ConnectorInterface
* @throws Freemius_Exception
*/
public static function getConnector( $config = null, $reset = false ) {
return WSAL_Connector_ConnectorFactory::getConnector( $config, $reset );
}
/**
* Do we have an existing installation? This only applies for version 1.0 onwards.
*
* @return boolean
* @throws Freemius_Exception
*/
public function IsInstalled() {
return self::getConnector()->isInstalled();
}
/**
* Whether the old plugin was present or not.
*
* @return boolean
* @throws Freemius_Exception
*/
public function CanMigrate() {
return self::getConnector()->canMigrate();
}
/**
* Absolute URL to plugin directory WITHOUT final slash.
*
* @return string
*/
public function GetBaseUrl() {
return plugins_url( '', __FILE__ );
}
/**
* Full path to plugin directory WITH final slash.
*
* @return string
*/
public function GetBaseDir() {
return plugin_dir_path( __FILE__ );
}
/**
* Plugin directory name.
*
* @return string
*/
public function GetBaseName() {
return plugin_basename( __FILE__ );
}
/**
* Load default configuration / data.
*/
public function load_defaults() {
require_once 'defaults.php';
}
/**
* WSAL-Notifications-Extension Functions.
*
* @param string $opt_prefix - Option prefix.
*
* @return array|null
*/
public function GetNotificationsSetting( $opt_prefix ) {
$this->include_options_helper();
return $this->options_helper->GetNotificationsSetting( self::OPTIONS_PREFIX . $opt_prefix );
}
/**
* Get notification.
*
* @param int $id - Option ID.
*
* @return string|null
*/
public function GetNotification( $id ) {
$this->include_options_helper();
return $this->options_helper->GetNotification($id);
}
/**
* Deletes setting by name.
*
* @param string $name - Option name not including the plugin prefix.
*
* @return bool
*/
public function DeleteSettingByName( $name ) {
if ( empty( $this->options_helper ) ) {
$this->include_options_helper();
}
return $this->options_helper->delete_option( $name );
}
/**
* Count notifications.
*
* @param string $opt_prefix - Option prefix.
*
* @return int
*/
public function CountNotifications( $opt_prefix ) {
$this->include_options_helper();
return $this->options_helper->CountNotifications( $opt_prefix );
}
/**
* Update global option.
*
* Deprecated function. It is only kept for the extension plugins. Nothing in the main plugin uses it, not even
* the upgrade process.
*
* @param string $option - Option name.
* @param mixed $value - Option value.
*
* @return bool|int
*
* @deprecated 4.1.3 Use WpSecurityAuditLog::SetGlobalSetting instead
* @see WpSecurityAuditLog::SetGlobalSetting()
*/
public function UpdateGlobalOption( $option, $value ) {
return $this->SetGlobalSetting( $option, $value );
}
/**
* Method: Render login page message.
*
* @param string $message - Login message.
*
* @return string
*/
public function render_login_page_message( $message ) {
// Set WSAL Settings.
$wsal_settings = new WSAL_Settings( $this );
// Check if the option is enabled.
$login_message_enabled = $wsal_settings->is_login_page_notification();
if ( $login_message_enabled ) {
// Get login message.
$message = $wsal_settings->get_login_page_notification_text();
// Default message.
if ( ! $message ) {
$message = '' . wp_kses( __( 'For security and auditing purposes, a record of all of your logged-in actions and changes within the WordPress dashboard will be recorded in an activity log with the WP Activity Log plugin. The audit log also includes the IP address where you accessed this site from.', 'wp-security-audit-log' ), $this->allowed_html_tags ) . '
';
} else {
$message = '' . $message . '
';
}
}
// Return message.
return $message;
}
/**
* Extend WP cron time intervals for scheduling.
*
* @param array $schedules - Array of schedules.
* @return array
*/
public function recurring_schedules( $schedules ) {
$schedules['sixhours'] = array(
'interval' => 21600,
'display' => __( 'Every 6 hours', 'wp-security-audit-log' ),
);
$schedules['fortyfiveminutes'] = array(
'interval' => 2700,
'display' => __( 'Every 45 minutes', 'wp-security-audit-log' ),
);
$schedules['thirtyminutes'] = array(
'interval' => 1800,
'display' => __( 'Every 30 minutes', 'wp-security-audit-log' ),
);
$schedules['fifteenminutes'] = array(
'interval' => 900,
'display' => __( 'Every 15 minutes', 'wp-security-audit-log' ),
);
$schedules['tenminutes'] = array(
'interval' => 600,
'display' => __( 'Every 10 minutes', 'wp-security-audit-log' ),
);
$schedules['oneminute'] = array(
'interval' => 60,
'display' => __( 'Every 1 minute', 'wp-security-audit-log' ),
);
return $schedules;
}
/**
* Prints error for deprecated functions.
*
* @param string $method — Method deprecated.
* @param string $version — Version since deprecated.
*/
public function wsal_deprecate( $method, $version ) {
if ( WP_DEBUG ) {
/* translators: 1. Deprecated method name 2. Version since deprecated */
trigger_error( sprintf( esc_html__( 'Method %1$s is deprecated since version %2$s!', 'wp-security-audit-log' ), $method, $version ) );
}
}
/**
* Uninstall routine for the plugin.
*/
public static function uninstall() {
if ( ! class_exists( 'WSAL_Uninstall' ) ) {
require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'classes/Uninstall.php';
}
WSAL_Uninstall::uninstall();
}
/**
* Sync premium freemius transient on daily basis.
*/
public function sync_premium_freemius() {
$is_fs_premium_opt = 'fs_wsalp';
$is_fs_premium = get_option( $is_fs_premium_opt );
if ( ! wsal_freemius()->is_registered() ) {
if ( 'no' !== $is_fs_premium ) {
update_option( $is_fs_premium_opt, 'no' );
}
} else {
$has_active_valid_license = wsal_freemius()->has_active_valid_license() ? 'yes' : 'no';
if ( $has_active_valid_license !== $is_fs_premium ) {
update_option( $is_fs_premium_opt, $has_active_valid_license );
}
}
}
/**
* Get premium freemius transient.
*
* @return boolean
*/
public static function is_premium_freemius() {
return get_option( 'fs_wsalp' );
}
/**
* Error Logger
*
* Logs given input into debug.log file in debug mode.
*
* @param mixed $message - Error message.
*/
public function wsal_log( $message ) {
if ( WP_DEBUG === true ) {
if ( is_array( $message ) || is_object( $message ) ) {
error_log( print_r( $message, true ) );
} else {
error_log( $message );
}
}
}
/**
* Hide WSAL plugin from plugin list
*
* @param array $plugins All plugins.
* @return array
*/
public function wsal_hide_plugin( $plugins ) {
global $pagenow;
// Check current page, bail early if this isn't the plugins page.
if ( 'plugins.php' !== $pagenow ) {
return $plugins;
}
// Find WSAL by plugin basename.
if ( array_key_exists( WSAL_BASE_NAME, $plugins ) ) {
// Remove WSAL plugin from plugin list page.
unset( $plugins[ WSAL_BASE_NAME ] );
}
return $plugins;
}
/**
* Use filter to hide freemius submenu items.
*
* @param boolean $is_visible Default visibility.
* @param string $submenu_id Menu slug.
*
* @return boolean New visibility.
*/
public function hide_freemius_submenu_items( $is_visible, $submenu_id ) {
if ( 'contact' === $submenu_id ) {
$is_visible = false;
}
return $is_visible;
}
/**
* Temporary autoloader for WSAL classes that somehow bypassed regular means of including
* them during the plugin runtime.
*
* As far as we know, only the UserSessionsTracking object will fall into this autoloader.
*
* We could optimize the code below by caching the list of extension folders.
*
* @param string $class Fully qualified class name.
*
* @return bool
*/
public static function autoloader( $class ) {
if ( ! preg_match( '/^WSAL_/', $class ) ) {
return false;
}
$base_path = plugin_dir_path( __FILE__ );
$subfolders = array();
$matches = explode( '_', $class );
if ( count( $matches ) > 2 ) {
// remove first (WSAL) and last one (actual file name)
array_shift( $matches );
array_pop( $matches );
$subfolders = $matches;
// workaround for MySQL adapter classes
if ( count( $subfolders ) == 2 && $subfolders[0] === 'Adapters' && $subfolders[1] === 'MySQL' ) {
$class .= 'Adapter';
}
}
// use last part of the class name as the actual file name to look for
$file_name = substr( $class, strrpos( $class, '_' ) + 1 );
// try the main "classes" folder first
$partial_path_to_file = 'classes' . DIRECTORY_SEPARATOR . implode( DIRECTORY_SEPARATOR, $subfolders ) . DIRECTORY_SEPARATOR . $file_name . '.php';
$path_to_file = $base_path . $partial_path_to_file;
if ( file_exists( $path_to_file ) ) {
require_once $path_to_file;
return true;
}
if ( ! function_exists( 'list_files' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
if ( file_exists( $base_path . 'extensions' ) ) {
$extension_folders = list_files( $base_path . 'extensions', 1 );
foreach ( $extension_folders as $extension_folder ) {
if ( ! is_dir( $extension_folder ) ) {
continue;
}
$path_to_file = $extension_folder . $partial_path_to_file;
if ( file_exists( $path_to_file ) ) {
require_once $path_to_file;
return true;
}
}
}
}
/**
* @see @see https://trello.com/c/1OCd5iKc/589-wieserdk-al4mwp-cannot-retrieve-events-when-admin-url-is-changed
* @return bool
*/
private static function is_admin_blocking_plugins_support_enabled() {
// only meant for 404 pages, but may run before is_404 can be used
$is_404 = did_action( 'wp' ) ? is_404() : true;
if ( ! $is_404 ) {
return false;
}
// this is called very early so we need to load some settings manually
spl_autoload_register( array( __CLASS__, 'autoloader' ) );
require_once 'classes/Helpers/Options.php';
/*
* We assume settings have already been migrated (in version 4.1.3) to WordPress options table. We might
* miss some 404 events until the plugin upgrade runs, but that is a very rare edge case. The same applies
* to loading of 'admin-blocking-plugins-support' option further down.
*
* We do not need to worry about the missed 404s after version 4.1.5 as they were completely removed.
*/
$options_helper = new \WSAL\Helpers\Options( self::OPTIONS_PREFIX );
$is_stealth_mode = $options_helper->get_option_value('mwp-child-stealth-mode', 'no');
if ('yes' !== $is_stealth_mode ) {
// only intended if MainWP stealth mode is active
return false;
}
// allow if the admin blocking support settings is active
return ('yes' === $options_helper->get_option_value( 'admin-blocking-plugins-support', 'no' ) );
}
/**
* Loads everything necessary to use DB adapter from the sessions extension.
*
* @since 4.1.4.1
*/
public function load_sessions_extension_db_adapter() {
if ( file_exists( plugin_dir_path( __FILE__ ) . 'extensions/user-sessions/user-sessions.php' ) ) {
$this->maybe_add_sessions_trackers_early();
require_once plugin_dir_path( __FILE__ ) . 'extensions/user-sessions/user-sessions.php';
$sessions = new WSAL_UserSessions_Plugin();
$sessions->require_adapter_classes();
}
}
/**
* Runs on premium version activation and installs database tables of the premium extensions (sessions table at
* the time of introducing this function).
*
* @since 4.1.4.1
*/
public function on_freemius_premium_version_activation() {
$this->load_sessions_extension_db_adapter();
self::getConnector()->installSingle( 'WSAL_Adapters_MySQL_Session' );
}
/**
* Dequeue JS files which have been added by other plugin to all admin pages and cause conflicts.
* See https://github.com/WPWhiteSecurity/wp-security-audit-log-premium/issues/1246 and
* https://trello.com/c/pWrQn1Be/742-koenhavelaertsflintgrpcom-reports-ui-does-not-load-with-plugin-installed
*
* @since 4.1.5
*/
public function dequeue_conflicting_scripts() {
global $current_screen;
// Only dequeue on our admin pages.
if ( isset( $current_screen->base ) && strpos( $current_screen->base, 'wp-activity-log' ) === 0 ) {
wp_deregister_script( 'dateformat' );
}
}
}
// Begin load sequence.
WpSecurityAuditLog::GetInstance();
if ( is_admin() && ! WpSecurityAuditLog::is_plugin_active( plugin_basename( __FILE__ ) ) ) {
WpSecurityAuditLog::load_freemius();
if ( ! apply_filters( 'wsal_disable_freemius_sdk', false ) ) {
wsal_freemius()->add_action( 'after_uninstall', array( 'WpSecurityAuditLog', 'uninstall' ) );
}
}
} else {
wsal_freemius()->set_basename( true, __FILE__ );
}