<?php

namespace WPS\WPS_Limit_Login;

if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

class Plugin {

	use Singleton;

	public $default_options = array(
		/* Are we behind a proxy? */
		'wps_limit_login_client_type'        => WPS_LIMIT_LOGIN_REMOTE_ADDR,

		/* Lock out after this many tries */
		'wps_limit_login_allowed_retries'    => 3,

		/* Lock out for this many seconds */
		'wps_limit_login_lockout_duration'   => 1200, // 20 minutes

		/* Long lock out after this many lockouts */
		'wps_limit_login_allowed_lockouts'   => 2,

		/* Long lock out for this many seconds */
		'wps_limit_login_long_duration'      => 86400, // 24 hours,

		/* Reset failed attempts after this many seconds */
		'wps_limit_login_valid_duration'     => 43200, // 12 hours

		/* Also limit malformed/forged cookies? */
		'cookies'                            => true,

		/* Notify on lockout. Values: '', 'email' */
		'wps_limit_lockout_notify'           => '',

		/* If notify by email, do so after this number of lockouts */
		'wps_limit_login_notify_email_after' => 2,

		'wps_limit_login_whitelist'        => array(),
		'wps_limit_login_blacklist'        => array(),
		'wps_limit_login_show_credit_link' => true,
	);
	/**
	 * Admin options page slug
	 * @var string
	 */
	private $_options_page_slug = 'wps-limit-login';

	/**
	 * Errors messages
	 *
	 * @var array
	 */
	public $_errors = array();

	protected function init() {

		if ( is_multisite() ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		$this->network_mode = is_multisite() && is_plugin_active_for_network( WPS_LIMIT_LOGIN_BASENAME );

		if ( $this->network_mode ) {
			$this->allow_local_options = get_site_option( 'wps_limit_login_allow_local_options', false );
			$this->use_local_options   = $this->allow_local_options && get_option( 'wps_limit_login_use_local_options', false );
		} else {
			$this->allow_local_options = true;
			$this->use_local_options   = true;
		}

		add_action( 'wp_login_failed', array( $this, 'wp_login_failed' ) );
		add_filter( 'wp_authenticate_user', array( $this, 'wp_authenticate_user' ), 99999, 2 );

		add_filter( 'shake_error_codes', array( $this, 'failure_shake' ) );
		add_action( 'login_head', array( $this, 'add_error_message' ) );
		add_action( 'login_errors', array( $this, 'fixup_error_messages' ) );

		if ( $this->network_mode ) {
			add_action( 'network_admin_menu', array( $this, 'network_admin_menu' ) );
		}

		if ( $this->allow_local_options ) {
			add_action( 'admin_menu', array( $this, 'admin_menu' ) );
		}

		// Add notices for XMLRPC request
		add_filter( 'xmlrpc_login_error', array( $this, 'xmlrpc_error_messages' ) );

		// Add notices to woocommerce login page
		add_action( 'wp_head', array( $this, 'add_wc_notices' ) );

		/*
		* This action should really be changed to the 'authenticate' filter as
		* it will probably be deprecated. That is however only available in
		* later versions of WP.
		*/
		add_action( 'wp_authenticate', array( $this, 'track_credentials' ), 10, 2 );
		add_action( 'authenticate', array( $this, 'authenticate_filter' ), 5, 3 );

		if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
			add_action( 'init', array( $this, 'check_xmlrpc_lock' ) );
		}

		add_action( 'wp_ajax_wps-limit-login-unlock', array( $this, 'ajax_unlock' ) );

		add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_enqueue_scripts' ) );
		add_filter( 'wps_limit_login_whitelist_ip', array( $this, 'check_whitelist_ips' ), 10, 2 );
		add_filter( 'wps_limit_login_blacklist_ip', array( $this, 'check_blacklist_ips' ), 10, 2 );
		add_action( 'login_form', array( $this, 'login_form' ) );
		add_action( 'login_enqueue_scripts', array( $this, 'login_enqueue_scripts' ) );
		add_action( 'admin_init', array( $this, 'reinitialize' ) );

		add_action( 'admin_init', array( __CLASS__, 'load_plugin' ) );
		if ( is_multisite() ) {
			add_filter( 'network_admin_plugin_action_links_' . WPS_LIMIT_LOGIN_BASENAME, array(
				$this,
				'plugin_action_links'
			) );
		}
		add_filter( 'plugin_action_links_' . WPS_LIMIT_LOGIN_BASENAME, array( $this, 'plugin_action_links' ) );

		add_action( 'wp_dashboard_setup', array( $this, 'add_dashboard_widgets' ) );

		add_filter( 'admin_footer_text', array( __CLASS__, 'admin_footer_text' ), 1 );
		add_filter( 'admin_footer', array( __CLASS__, 'admin_footer' ) );
		add_action( 'wp_ajax_wpslimitlogin_rated', array( __CLASS__, 'wpslimitlogin_rated' ) );
		add_filter( 'wps_bidouille_not_display_pub_array', array( __CLASS__, 'wps_bidouille_not_display_pub_array' ) );
	}

	public function check_xmlrpc_lock() {
		if ( is_user_logged_in() || $this->is_ip_whitelisted() ) {
			return false;
		}

		if ( $this->is_ip_blacklisted() || ! $this->is_limit_login_ok() ) {
			status_header( 403, 'Forbidden' );
			exit;
		}
	}

	/**
	 * @param $allow
	 * @param $ip
	 *
	 * @return bool
	 */
	public function check_whitelist_ips( $allow, $ip ) {
		return $this->ip_in_range( $ip, (array) $this->get_option( 'wps_limit_login_whitelist' ) );
	}

	/**
	 * @param $allow
	 * @param $ip
	 *
	 * @return bool
	 */
	public function check_blacklist_ips( $allow, $ip ) {
		return $this->ip_in_range( $ip, (array) $this->get_option( 'wps_limit_login_blacklist' ) );
	}

	/**
	 * @param $ip
	 * @param $list
	 *
	 * @return bool
	 */
	public function ip_in_range( $ip, $list ) {
		foreach ( $list as $range ) {
			if ( strpos( $range, '/' ) !== false ) {
				// $range is in IP/NETMASK format
				list( $range, $netmask ) = explode( '/', $range, 2 );
				if ( strpos( $netmask, '.' ) !== false ) {
					// $netmask is a 255.255.0.0 format
					$netmask     = str_replace( '*', '0', $netmask );
					$netmask_dec = ip2long( $netmask );

					return ( ( ip2long( $ip ) & $netmask_dec ) == ( ip2long( $range ) & $netmask_dec ) );
				} else {
					// $netmask is a CIDR size block
					// fix the range argument
					$x = explode( '.', $range );
					while ( count( $x ) < 4 ) {
						$x[] = '0';
					}
					list( $a, $b, $c, $d ) = $x;
					$range     = sprintf( "%u.%u.%u.%u", empty( $a ) ? '0' : $a, empty( $b ) ? '0' : $b, empty( $c ) ? '0' : $c, empty( $d ) ? '0' : $d );
					$range_dec = ip2long( $range );
					$ip_dec    = ip2long( $ip );
					# Strategy 1 - Create the netmask with 'netmask' 1s and then fill it to 32 with 0s
					#$netmask_dec = bindec(str_pad('', $netmask, '1') . str_pad('', 32-$netmask, '0'));
					# Strategy 2 - Use math to create it
					$wildcard_dec = pow( 2, ( 32 - $netmask ) ) - 1;
					$netmask_dec  = ~$wildcard_dec;

					return ( ( $ip_dec & $netmask_dec ) == ( $range_dec & $netmask_dec ) );
				}
			} else {
				// range might be 255.255.*.* or 1.2.3.0-1.2.3.255
				if ( strpos( $range, '*' ) !== false ) { // a.b.*.* format
					// Just convert to A-B format by setting * to 0 for A and 255 for B
					$lower = str_replace( '*', '0', $range );
					$upper = str_replace( '*', '255', $range );
					$range = "$lower-$upper";
				}
				if ( strpos( $range, '-' ) !== false ) { // A-B format
					list( $lower, $upper ) = explode( '-', $range, 2 );
					$lower_dec = (float) sprintf( "%u", ip2long( $lower ) );
					$upper_dec = (float) sprintf( "%u", ip2long( $upper ) );
					$ip_dec    = (float) sprintf( "%u", ip2long( $ip ) );

					return ( ( $ip_dec >= $lower_dec ) && ( $ip_dec <= $upper_dec ) );
				}

				if ( $range === $ip ) {
					return true;
				}
			}

		}

		return false;
	}

	/**
	 * @param $error
	 *
	 * @return \IXR_Error
	 */
	public function xmlrpc_error_messages( $error ) {

		if ( ! class_exists( 'IXR_Error' ) ) {
			return $error;
		}

		if ( ! $this->is_limit_login_ok() ) {
			return new \IXR_Error( 403, $this->error_msg() );
		}

		$ip      = $this->get_address();
		$retries = $this->get_option( 'wps_limit_login_retries' );
		$valid   = $this->get_option( 'wps_limit_login_retries_valid' );

		/* Should we show retries remaining? */

		if ( ! is_array( $retries ) || ! is_array( $valid ) ) {
			/* no retries at all */
			return $error;
		}
		if ( ! isset( $retries[ $ip ] ) || ! isset( $valid[ $ip ] ) || time() > $valid[ $ip ] ) {
			/* no: no valid retries */
			return $error;
		}
		if ( ( $retries[ $ip ] % $this->get_option( 'wps_limit_login_allowed_retries' ) ) == 0 ) {
			/* no: already been locked out for these retries */
			return $error;
		}

		$remaining = max( ( $this->get_option( 'wps_limit_login_allowed_retries' ) - ( $retries[ $ip ] % $this->get_option( 'wps_limit_login_allowed_retries' ) ) ), 0 );

		return new \IXR_Error( 403, sprintf( _n( "<strong>%d</strong> attempt remaining.", "<strong>%d</strong> attempts remaining.", $remaining, 'wps-limit-login' ), $remaining ) );
	}

	/**
	 * Errors on WooCommerce account page
	 */
	public function add_wc_notices() {

		global $wps_limit_login_just_lockedout;

		if ( ! function_exists( 'is_account_page' ) || ! function_exists( 'wc_add_notice' ) ) {
			return false;
		}

		/*
		* During lockout we do not want to show any other error messages (like
		* unknown user or empty password).
		*/
		if ( empty( $_POST ) && ! $this->is_limit_login_ok() && ! $wps_limit_login_just_lockedout ) {
			if ( is_account_page() ) {
				wc_add_notice( $this->error_msg(), 'error' );
			}
		}

	}

	/**
	 * @param $user
	 * @param $username
	 * @param $password
	 *
	 * @return WP_Error | WP_User
	 */
	public function authenticate_filter( $user, $username, $password ) {

		if ( ! empty( $username ) && ! empty( $password ) ) {

			$ip = $this->get_address();

			// Check if ip is blacklisted
			if ( ! $this->is_ip_whitelisted( $ip ) && $this->is_ip_blacklisted( $ip ) ) {

				remove_filter( 'login_errors', array( $this, 'fixup_error_messages' ) );
				remove_filter( 'login_head', array( $this, 'add_error_message' ) );
				remove_filter( 'wp_login_failed', array( $this, 'wp_login_failed' ) );
				remove_filter( 'wp_authenticate_user', array( $this, 'wp_authenticate_user' ), 99999 );
				remove_filter( 'login_head', array( $this, 'add_error_message' ) );
				remove_filter( 'login_errors', array( $this, 'fixup_error_messages' ) );

				remove_filter( 'authenticate', 'wp_authenticate_username_password', 20 );
				remove_filter( 'authenticate', 'wp_authenticate_email_password', 20 );

				$user = new \WP_Error();
				$user->add( 'ip_blacklisted', __( '<strong>ERROR</strong>: Too many failed login attempts.', 'wps-limit-login' ) );

			} elseif ( $this->is_ip_whitelisted( $ip ) ) {

				remove_filter( 'wp_login_failed', array( $this, 'wp_login_failed' ) );
				remove_filter( 'wp_authenticate_user', array( $this, 'wp_authenticate_user' ), 99999 );
				remove_filter( 'login_head', array( $this, 'add_error_message' ) );
				remove_filter( 'login_errors', array( $this, 'fixup_error_messages' ) );

			}

		}

		return $user;
	}

	/**
	 * Enqueue css
	 */
	public static function admin_enqueue_scripts( $hook ) {

		if ( false === strpos( $hook, 'wps-limit-login' ) ) {
			return;
		}

		wp_enqueue_style( 'wps-limit-login-fa', WPS_LIMIT_LOGIN_URL . 'assets/fontawesome/web-fonts-with-css/fontawesome-all.min.css' );
		wp_enqueue_script( 'wps-limit-login-fa', WPS_LIMIT_LOGIN_URL . 'assets/fontawesome/fontawesome-all.min.js', array(), false, true );

		wp_enqueue_style( 'wps-limit-login', WPS_LIMIT_LOGIN_URL . 'assets/css/style.css' );

		wp_enqueue_style( 'plugin-install' );

		wp_enqueue_script( 'plugin-install' );
		wp_enqueue_script( 'updates' );
		add_thickbox();
	}

	/**
	 * Add admin options page
	 */
	public function network_admin_menu() {
		add_submenu_page( 'settings.php', 'WPS Limit Login', 'WPS Limit Login', 'manage_options', $this->_options_page_slug, array(
			$this,
			'options_page'
		) );
	}

	public function admin_menu() {
		add_options_page( 'WPS Limit Login', 'WPS Limit Login', 'manage_options', $this->_options_page_slug, array(
			$this,
			'options_page'
		) );
	}

	/**
	 * Get the correct options page URI
	 *
	 * @return mixed
	 */
	public function get_wps_limit_login_options_page_uri() {
		if ( is_network_admin() ) {
			return network_admin_url( 'settings.php?page=wps-limit-login' );
		}

		return menu_page_url( $this->_options_page_slug, false );
	}

	/**
	 * Get option by name
	 *
	 * @param $option_name
	 *
	 * @return null
	 */
	public function get_option( $option_name, $local = null ) {
		if ( is_null( $local ) ) {
			$local = $this->use_local_options;
		}

		$func  = $local ? 'get_option' : 'get_site_option';
		$value = $func( $option_name, null );

		if ( is_null( $value ) && isset( $this->default_options[ $option_name ] ) ) {
			$value = $this->default_options[ $option_name ];
		}

		return $value;
	}

	/**
	 * @param $option_name
	 * @param $value
	 * @param null $local
	 *
	 * @return mixed
	 */
	public function update_option( $option_name, $value, $local = null ) {
		if ( is_null( $local ) ) {
			$local = $this->use_local_options;
		}

		$func = $local ? 'update_option' : 'update_site_option';

		return $func( $option_name, $value );
	}

	/**
	 * @param $option_name
	 * @param $value
	 * @param null $local
	 *
	 * @return mixed
	 */
	public function add_option( $option_name, $value, $local = null ) {
		if ( is_null( $local ) ) {
			$local = $this->use_local_options;
		}

		$func = $local ? 'add_option' : 'add_site_option';

		return $func( $option_name, $value, '', 'no' );
	}

	/**
	 * Setup main options
	 */
	public function sanitize_options() {
		if ( $this->get_option( 'wps_limit_login_notify_email_after' ) > $this->get_option( 'wps_limit_login_allowed_lockouts' ) ) {
			$this->update_option( 'wps_limit_login_notify_email_after', $this->get_option( 'wps_limit_login_allowed_lockouts' ) );
		}

		if ( isset( $_POST['lockout_notify_email'] ) ) {
			$this->update_option( 'wps_limit_lockout_notify', 'email' );
		} else {
			$this->update_option( 'wps_limit_lockout_notify', '' );
		}

		$ctype = $this->get_option( 'wps_limit_login_client_type' );
		if ( $ctype != WPS_LIMIT_LOGIN_REMOTE_ADDR && $ctype != 'HTTP_X_FORWARDED_FOR' ) {
			$this->update_option( 'wps_limit_login_client_type', WPS_LIMIT_LOGIN_REMOTE_ADDR );
		}
	}

	/**
	 * Check if it is ok to login
	 *
	 * @return bool
	 */
	public function is_limit_login_ok() {

		$ip = $this->get_address();

		/* Check external whitelist filter */
		if ( $this->is_ip_whitelisted( $ip ) ) {
			return true;
		}

		/* lockout active? */
		$lockouts = $this->get_option( 'wps_limit_login_lockouts' );

		return ( ! is_array( $lockouts ) || ! isset( $lockouts[ $ip ] ) || time() >= $lockouts[ $ip ] );
	}

	/**
	 * Action when login attempt failed
	 *
	 * Increase nr of retries (if necessary). Reset valid value. Setup
	 * lockout if nr of retries are above threshold. And more!
	 *
	 * A note on external whitelist: retries and statistics are still counted and
	 * notifications done as usual, but no lockout is done.
	 *
	 * @param $username
	 *
	 * @return bool
	 */
	public function wp_login_failed( $username ) {

		$ip = $this->get_address();

		/* if currently locked-out, do not add to retries */
		$lockouts = $this->get_option( 'wps_limit_login_lockouts' );

		if ( ! is_array( $lockouts ) ) {
			$lockouts = array();
		}

		if ( isset( $lockouts[ $ip ] ) && time() < $lockouts[ $ip ] ) {
			return false;
		}

		/* Get the arrays with retries and retries-valid information */
		$retries = $this->get_option( 'wps_limit_login_retries' );
		$valid   = $this->get_option( 'wps_limit_login_retries_valid' );

		if ( ! is_array( $retries ) ) {
			$retries = array();
			$this->add_option( 'wps_limit_login_retries', $retries );
		}

		if ( ! is_array( $valid ) ) {
			$valid = array();
			$this->add_option( 'wps_limit_login_retries_valid', $valid );
		}

		/* Check validity and add one to retries */
		if ( isset( $retries[ $ip ] ) && isset( $valid[ $ip ] ) && time() < $valid[ $ip ] ) {
			$retries[ $ip ] ++;
		} else {
			$retries[ $ip ] = 1;
		}
		$valid[ $ip ] = time() + $this->get_option( 'wps_limit_login_valid_duration' );

		/* lockout? */
		if ( $retries[ $ip ] % $this->get_option( 'wps_limit_login_allowed_retries' ) != 0 ) {
			/*
			* Not lockout (yet!)
			* Do housecleaning (which also saves retry/valid values).
			*/
			$this->cleanup( $retries, null, $valid );

			return false;
		}

		$whitelisted = $this->is_ip_whitelisted( $ip );

		$retries_long = $this->get_option( 'wps_limit_login_allowed_retries' ) * $this->get_option( 'wps_limit_login_allowed_lockouts' );

		/*
		* Note that retries and statistics are still counted and notifications
		* done as usual for whitelisted ips , but no lockout is done.
		*/
		if ( $whitelisted ) {
			if ( $retries[ $ip ] >= $retries_long ) {
				unset( $retries[ $ip ] );
				unset( $valid[ $ip ] );
			}
		} else {
			global $wps_limit_login_just_lockedout;
			$wps_limit_login_just_lockedout = true;

			/* setup lockout, reset retries as needed */
			if ( $retries[ $ip ] >= $retries_long ) {
				/* long lockout */
				$lockouts[ $ip ] = time() + $this->get_option( 'wps_limit_login_long_duration' );
				unset( $retries[ $ip ] );
				unset( $valid[ $ip ] );
			} else {
				/* normal lockout */
				$lockouts[ $ip ] = time() + $this->get_option( 'wps_limit_login_lockout_duration' );
			}
		}

		$this->cleanup( $retries, $lockouts, $valid );

		$this->notify( $username );

		$wps_limit_lockouts_total = $this->get_option( 'wps_limit_lockouts_total' );
		if ( $wps_limit_lockouts_total === false || ! is_numeric( $wps_limit_lockouts_total ) ) {
			$this->add_option( 'wps_limit_lockouts_total', 1 );
		} else {
			$this->update_option( 'wps_limit_lockouts_total', $wps_limit_lockouts_total + 1 );
		}
	}

	/**
	 * Handle notification in event of lockout
	 *
	 * @param $user
	 *
	 * @return bool
	 */
	public function notify( $user ) {
		$args = explode( ',', $this->get_option( 'wps_limit_lockout_notify' ) );

		if ( empty( $args ) ) {
			return false;
		}

		foreach ( $args as $mode ) {
			switch ( trim( $mode ) ) {
				case 'email':
					$this->notify_email( $user );
					break;
			}
		}

		$this->notify_log( $user );
	}

	/**
	 * Email notification of lockout to admin (if configured)
	 *
	 * @param $user
	 *
	 * @return bool
	 */
	public function notify_email( $user ) {
		$ip          = $this->get_address();
		$whitelisted = $this->is_ip_whitelisted( $ip );

		$retries = $this->get_option( 'wps_limit_login_retries' );
		if ( ! is_array( $retries ) ) {
			$retries = array();
		}

		/* check if we are at the right nr to do notification */
		if ( isset( $retries[ $ip ] ) && ( ( $retries[ $ip ] / $this->get_option( 'wps_limit_login_allowed_retries' ) ) % $this->get_option( 'wps_limit_login_notify_email_after' ) ) != 0 ) {
			return false;
		}

		/* Format message. First current lockout duration */
		if ( ! isset( $retries[ $ip ] ) ) {
			/* longer lockout */
			$count    = $this->get_option( 'wps_limit_login_allowed_retries' )
			            * $this->get_option( 'wps_limit_login_allowed_lockouts' );
			$lockouts = $this->get_option( 'wps_limit_login_allowed_lockouts' );
			$time     = round( $this->get_option( 'wps_limit_login_long_duration' ) / 3600 );
			$when     = sprintf( _n( '%d hour', '%d hours', $time, 'wps-limit-login' ), $time );
		} else {
			/* normal lockout */
			$count    = $retries[ $ip ];
			$lockouts = floor( $count / $this->get_option( 'wps_limit_login_allowed_retries' ) );
			$time     = round( $this->get_option( 'wps_limit_login_lockout_duration' ) / 60 );
			$when     = sprintf( _n( '%d minute', '%d minutes', $time, 'wps-limit-login' ), $time );
		}

		$blogname = $this->use_local_options ? get_option( 'blogname' ) : get_site_option( 'site_name' );
		$blogname = htmlspecialchars_decode( $blogname, ENT_QUOTES );

		if ( $whitelisted ) {
			$subject = sprintf( __( "[%s - WPS Limit Login] Failed login attempts from whitelisted IP"
					, 'wps-limit-login' )
				, $blogname );
		} else {
			$subject = sprintf( __( "[%s - WPS Limit Login] Too many failed login attempts"
					, 'wps-limit-login' )
				, $blogname );
		}

		$message = sprintf( __( "%d failed login attempts (%d lockout(s)) from IP: %s"
				, 'wps-limit-login' ) . "\r\n\r\n"
			, $count, $lockouts, $ip );
		if ( $user != '' ) {
			$message .= sprintf( __( "Last user attempted: %s", 'wps-limit-login' )
			                     . "\r\n\r\n", $user );
		}
		if ( $whitelisted ) {
			$message .= __( "IP was NOT blocked because of external whitelist.", 'wps-limit-login' );
		} else {
			$message .= sprintf( __( "IP was blocked for %s", 'wps-limit-login' ), $when );
		}

		$admin_email = $this->use_local_options ? get_option( 'admin_email' ) : get_site_option( 'admin_email' );

		@wp_mail( $admin_email, $subject, $message );
	}

	/**
	 * Logging of lockout (if configured)
	 *
	 * @param $user_login
	 *
	 * @return bool
	 */
	public function notify_log( $user_login ) {

		if ( ! $user_login ) {
			return false;
		}

		$log = $option = $this->get_option( 'wps_limit_login_logged' );
		if ( ! is_array( $log ) ) {
			$log = array();
		}
		$ip = $this->get_address();

		/* can be written much simpler, if you do not mind php warnings */
		if ( ! isset( $log[ $ip ] ) ) {
			$log[ $ip ] = array();
		}

		if ( ! isset( $log[ $ip ][ $user_login ] ) ) {
			$log[ $ip ][ $user_login ] = array( 'counter' => 0 );
		} elseif ( ! is_array( $log[ $ip ][ $user_login ] ) ) {
			$log[ $ip ][ $user_login ] = array(
				'counter' => $log[ $ip ][ $user_login ],
			);
		}

		$log[ $ip ][ $user_login ]['counter'] ++;
		$log[ $ip ][ $user_login ]['date'] = time();

		if ( isset( $_POST['woocommerce-login-nonce'] ) ) {
			$gateway = 'WooCommerce';
		} elseif ( isset( $GLOBALS['wp_xmlrpc_server'] ) && is_object( $GLOBALS['wp_xmlrpc_server'] ) ) {
			$gateway = 'XMLRPC';
		} else {
			$gateway = 'WP Login';
		}

		$log[ $ip ][ $user_login ]['gateway'] = $gateway;

		if ( $option === false ) {
			$this->add_option( 'wps_limit_login_logged', $log );
		} else {
			$this->update_option( 'wps_limit_login_logged', $log );
		}
	}

	/**
	 * Check if IP is whitelisted.
	 *
	 * This function allow external ip whitelisting using a filter. Note that it can
	 * be called multiple times during the login process.
	 *
	 * Note that retries and statistics are still counted and notifications
	 * done as usual for whitelisted ips , but no lockout is done.
	 *
	 * Example:
	 * function my_ip_whitelist($allow, $ip) {
	 *    return ($ip == 'my-ip') ? true : $allow;
	 * }
	 * add_filter('wps_limit_login_whitelist_ip', 'my_ip_whitelist', 10, 2);
	 *
	 * @param null $ip
	 *
	 * @return bool
	 */
	public function is_ip_whitelisted( $ip = null ) {

		if ( is_null( $ip ) ) {
			$ip = $this->get_address();
		}

		$whitelisted = apply_filters( 'wps_limit_login_whitelist_ip', false, $ip );

		return ( $whitelisted === true );
	}

	public function is_ip_blacklisted( $ip = null ) {

		if ( is_null( $ip ) ) {
			$ip = $this->get_address();
		}

		$blacklisted = apply_filters( 'wps_limit_login_blacklist_ip', false, $ip );

		return ( $blacklisted === true );
	}

	/**
	 * Filter: allow login attempt? (called from wp_authenticate())
	 *
	 * @param $user WP_User
	 * @param $password
	 *
	 * @return \WP_Error
	 */
	public function wp_authenticate_user( $user, $password ) {

		if ( is_wp_error( $user ) ||
		     $this->check_whitelist_ips( false, $this->get_address() ) ||
		     $this->is_limit_login_ok()
		) {

			return $user;
		}

		$error = new \WP_Error();

		global $wps_limit_login_my_error_shown;
		$wps_limit_login_my_error_shown = true;

		if ( $this->is_ip_blacklisted( $this->get_address() ) ) {
			$error->add( 'ip_blacklisted', __( '<strong>ERROR</strong>: Too many failed login attempts.', 'wps-limit-login' ) );
		} else {
			// This error should be the same as in "shake it" filter below
			$error->add( 'too_many_retries', $this->error_msg() );
		}

		return $error;
	}

	/**
	 * Filter: add this failure to login page "Shake it!"
	 *
	 * @param $error_codes
	 *
	 * @return array
	 */
	public function failure_shake( $error_codes ) {
		$error_codes[] = 'too_many_retries';

		return $error_codes;
	}

	/**
	 * Keep track of if user or password are empty, to filter errors correctly
	 *
	 * @param $user
	 * @param $password
	 */
	public function track_credentials( $user, $password ) {
		global $wps_limit_login_notempty_credentials;

		$wps_limit_login_notempty_credentials = ( ! empty( $user ) && ! empty( $password ) );
	}

	/**
	 * Should we show errors and messages on this page?
	 *
	 * @return bool
	 */
	public function login_show_msg() {
		if ( isset( $_GET['key'] ) ) {
			/* reset password */
			return false;
		}

		$action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : '';

		return ( $action != 'lostpassword' && $action != 'retrievepassword'
		         && $action != 'resetpass' && $action != 'rp'
		         && $action != 'register' );
	}

	/**
	 * Construct informative error message
	 *
	 * @return string
	 */
	public function error_msg() {
		$ip       = $this->get_address();
		$lockouts = $this->get_option( 'wps_limit_login_lockouts' );

		$msg = __( '<strong>ERROR</strong>: Too many failed login attempts.', 'wps-limit-login' ) . ' ';

		if ( ! is_array( $lockouts ) || ! isset( $lockouts[ $ip ] ) || time() >= $lockouts[ $ip ] ) {
			/* Huh? No timeout active? */
			$msg .= __( 'Please try again later.', 'wps-limit-login' );

			return $msg;
		}

		$when = ceil( ( $lockouts[ $ip ] - time() ) / 60 );
		if ( $when > 60 ) {
			$when = ceil( $when / 60 );
			$msg  .= sprintf( _n( 'Please try again in %d hour.', 'Please try again in %d hours.', $when, 'wps-limit-login' ), $when );
		} else {
			$msg .= sprintf( _n( 'Please try again in %d minute.', 'Please try again in %d minutes.', $when, 'wps-limit-login' ), $when );
		}

		return $msg;
	}

	/**
	 * Add a message to login page when necessary
	 */
	public function add_error_message() {
		global $error, $wps_limit_login_my_error_shown;

		if ( ! $this->login_show_msg() || $wps_limit_login_my_error_shown ) {
			return false;
		}

		$msg = $this->get_message();

		if ( $msg != '' ) {
			$wps_limit_login_my_error_shown = true;
			$error                          .= $msg;
		}

		return false;
	}

	/**
	 * Fix up the error message before showing it
	 *
	 * @param $content
	 *
	 * @return string
	 */
	public function fixup_error_messages( $content ) {
		global $wps_limit_login_just_lockedout, $wps_limit_login_notempty_credentials, $wps_limit_login_my_error_shown;

		if ( ! $this->login_show_msg() ) {
			return $content;
		}

		/*
		* During lockout we do not want to show any other error messages (like
		* unknown user or empty password).
		*/
		if ( ! $this->is_limit_login_ok() && ! $wps_limit_login_just_lockedout ) {
			return $this->error_msg();
		}

		/*
		* We want to filter the messages 'Invalid username' and
		* 'Invalid password' as that is an information leak regarding user
		* account names (prior to WP 2.9?).
		*
		* Also, if more than one error message, put an extra <br /> tag between
		* them.
		*/
		$msgs = explode( "<br />\n", $content );

		if ( strlen( end( $msgs ) ) == 0 ) {
			/* remove last entry empty string */
			array_pop( $msgs );
		}

		$count         = count( $msgs );
		$my_warn_count = $wps_limit_login_my_error_shown ? 1 : 0;

		if ( $wps_limit_login_notempty_credentials && $count > $my_warn_count ) {
			/* Replace error message, including ours if necessary */
			$content = __( '<strong>ERROR</strong>: Incorrect username or password.', 'wps-limit-login' ) . "<br />\n";

			if ( $wps_limit_login_my_error_shown || $this->get_message() ) {
				$content .= "<br />\n" . $this->get_message() . "<br />\n";
			}

			return $content;
		} elseif ( $count <= 1 ) {
			return $content;
		}

		$new = '';
		while ( $count -- > 0 ) {
			$new .= array_shift( $msgs ) . "<br />\n";
			if ( $count > 0 ) {
				$new .= "<br />\n";
			}
		}

		return $new;
	}

	public function fixup_error_messages_wc( \WP_Error $error ) {
		$error->add( 1, __( 'WC Error' ) );
	}

	/**
	 * Return current (error) message to show, if any
	 *
	 * @return string
	 */
	public function get_message() {
		/* Check external whitelist */
		if ( $this->is_ip_whitelisted() ) {
			return '';
		}

		/* Is lockout in effect? */
		if ( ! $this->is_limit_login_ok() ) {
			return $this->error_msg();
		}

		return $this->retries_remaining_msg();
	}

	/**
	 * Construct retries remaining message
	 *
	 * @return string
	 */
	public function retries_remaining_msg() {
		$ip      = $this->get_address();
		$retries = $this->get_option( 'wps_limit_login_retries' );
		$valid   = $this->get_option( 'wps_limit_login_retries_valid' );

		/* Should we show retries remaining? */

		if ( ! is_array( $retries ) || ! is_array( $valid ) ) {
			/* no retries at all */
			return '';
		}
		if ( ! isset( $retries[ $ip ] ) || ! isset( $valid[ $ip ] ) || time() > $valid[ $ip ] ) {
			/* no: no valid retries */
			return '';
		}
		if ( ( $retries[ $ip ] % $this->get_option( 'wps_limit_login_allowed_retries' ) ) == 0 ) {
			/* no: already been locked out for these retries */
			return '';
		}

		$remaining = max( ( $this->get_option( 'wps_limit_login_allowed_retries' ) - ( $retries[ $ip ] % $this->get_option( 'wps_limit_login_allowed_retries' ) ) ), 0 );

		return sprintf( _n( "<strong>%d</strong> attempt remaining.", "<strong>%d</strong> attempts remaining.", $remaining, 'wps-limit-login' ), $remaining );
	}

	/**
	 * Get correct remote address
	 *
	 * @param string $type_name
	 *
	 * @return string
	 */
	public function get_address( $type_name = '' ) {

		if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
			return $_SERVER['REMOTE_ADDR'];
		}

		return $type_name;
	}

	/**
	 * Clean up old lockouts and retries, and save supplied arrays
	 *
	 * @param null $retries
	 * @param null $lockouts
	 * @param null $valid
	 *
	 * @return bool
	 */
	public function cleanup( $retries = null, $lockouts = null, $valid = null ) {
		$now      = time();
		$lockouts = ! is_null( $lockouts ) ? $lockouts : $this->get_option( 'wps_limit_login_lockouts' );

		/* remove old lockouts */
		if ( is_array( $lockouts ) ) {
			foreach ( $lockouts as $ip => $lockout ) {
				if ( $lockout < $now ) {
					unset( $lockouts[ $ip ] );
				}
			}
			$this->update_option( 'wps_limit_login_lockouts', $lockouts );
		}

		/* remove retries that are no longer valid */
		$valid   = ! is_null( $valid ) ? $valid : $this->get_option( 'wps_limit_login_retries_valid' );
		$retries = ! is_null( $retries ) ? $retries : $this->get_option( 'wps_limit_login_retries' );
		if ( ! is_array( $valid ) || ! is_array( $retries ) ) {
			return false;
		}

		foreach ( $valid as $ip => $lockout ) {
			if ( $lockout < $now ) {
				unset( $valid[ $ip ] );
				unset( $retries[ $ip ] );
			}
		}

		/* go through retries directly, if for some reason they've gone out of sync */
		foreach ( $retries as $ip => $retry ) {
			if ( ! isset( $valid[ $ip ] ) ) {
				unset( $retries[ $ip ] );
			}
		}

		$this->update_option( 'wps_limit_login_retries', $retries );
		$this->update_option( 'wps_limit_login_retries_valid', $valid );
	}

	/**
	 * Render admin options page
	 */
	public function options_page() {
		$this->use_local_options = ! is_network_admin();
		$this->cleanup();

		if ( ! empty( $_POST ) ) {
			check_admin_referer( 'wps-limit-login-settings' );

			if ( false === strpos( $_POST['_wp_http_referer'], 'tab=whitelist' ) && false === strpos( $_POST['_wp_http_referer'], 'tab=blacklist' ) ) {

				if ( is_network_admin() ) {
					$this->update_option( 'wps_limit_login_allow_local_options', ! empty( $_POST['allow_local_options'] ) );
				} elseif ( $this->network_mode ) {
					$this->update_option( 'wps_limit_login_use_local_options', empty( $_POST['use_global_options'] ) );
				}

				/* Should we clear log? */
				if ( isset( $_POST['clear_log'] ) ) {

					$log      = $this->get_option( 'wps_limit_login_logged' );
					$lockouts = (array) $this->get_option( 'wps_limit_login_lockouts' );

					if ( ! empty( $log ) ) {
						foreach ( $log as $ip => $user_info ) {
							if ( empty( $lockouts[ $ip ] ) ) {
								unset( $log[ $ip ] );
							}
						}
					}

					$this->update_option( 'wps_limit_login_logged', $log );
					self::show_error( __( 'Cleared IP log', 'wps-limit-login' ) );
				}

				/* Should we reset counter? */
				if ( isset( $_POST['reset_total'] ) ) {
					$this->update_option( 'wps_limit_lockouts_total', 0 );
					self::show_error( __( 'Reset lockout count', 'wps-limit-login' ) );
				}

				/* Should we restore current lockouts? */
				if ( isset( $_POST['reset_current'] ) ) {
					$this->update_option( 'wps_limit_login_lockouts', array() );
					self::show_error( __( 'Cleared current lockouts', 'wps-limit-login' ) );
				}

				/* Should we update options? */
				if ( isset( $_POST['update_options'] ) ) {
					if ( isset ( $_POST['allowed_retries'] ) ) {
						$this->update_option( 'wps_limit_login_allowed_retries', (int) $_POST['allowed_retries'] );
					}
					if ( isset ( $_POST['lockout_duration'] ) ) {
						$this->update_option( 'wps_limit_login_lockout_duration', (int) $_POST['lockout_duration'] * 60 );
					}
					if ( isset ( $_POST['allowed_lockouts'] ) ) {
						$this->update_option( 'wps_limit_login_allowed_lockouts', (int) $_POST['allowed_lockouts'] );
					}
					if ( isset ( $_POST['long_duration'] ) ) {
						$this->update_option( 'wps_limit_login_long_duration', (int) $_POST['long_duration'] * 3600 );
					}
					if ( isset ( $_POST['valid_duration'] ) ) {
						$this->update_option( 'wps_limit_login_valid_duration', (int) $_POST['valid_duration'] * 3600 );
					}
					if ( isset ( $_POST['notify_email_after'] ) ) {
						$this->update_option( 'wps_limit_login_notify_email_after', (int) $_POST['notify_email_after'] );
					}

					$wps_limit_login_show_credit_link = ( ! empty( $_POST['show_credit_link'] ) ) ? $_POST['show_credit_link'] : '';
					$this->update_option( 'wps_limit_login_show_credit_link', $wps_limit_login_show_credit_link );

					$this->sanitize_options();

					self::show_error( __( 'Options saved.', 'wps-limit-login' ) );
				}
			} elseif ( false !== strpos( $_POST['_wp_http_referer'], 'tab=whitelist' ) ) {

				/* Should we update options? */
				if ( isset( $_POST['update_options'] ) ) {

					$wps_limit_login_white_list_ips = ( ! empty( $_POST['wps_limit_login_whitelist_ips'] ) ) ? explode( "\n", str_replace( "\r", "", stripslashes( $_POST['wps_limit_login_whitelist_ips'] ) ) ) : array();

					if ( ! empty( $wps_limit_login_white_list_ips ) ) {
						foreach ( $wps_limit_login_white_list_ips as $key => $ip ) {
							if ( '' == $ip ) {
								unset( $wps_limit_login_white_list_ips[ $key ] );
							}
						}
					}
					$this->update_option( 'wps_limit_login_whitelist', $wps_limit_login_white_list_ips );

					self::show_error( __( 'Options saved.', 'wps-limit-login' ) );
				}
			} elseif ( false !== strpos( $_POST['_wp_http_referer'], 'tab=blacklist' ) ) {

				/* Should we update options? */
				if ( isset( $_POST['update_options'] ) ) {

					$wps_limit_login_blacklist_ips = ( ! empty( $_POST['wps_limit_login_blacklist_ips'] ) ) ? explode( "\n", str_replace( "\r", "", stripslashes( $_POST['wps_limit_login_blacklist_ips'] ) ) ) : array();

					if ( ! empty( $wps_limit_login_blacklist_ips ) ) {
						foreach ( $wps_limit_login_blacklist_ips as $key => $ip ) {
							if ( '' == $ip ) {
								unset( $wps_limit_login_blacklist_ips[ $key ] );
							}
						}
					}
					$this->update_option( 'wps_limit_login_blacklist', $wps_limit_login_blacklist_ips );

					self::show_error( __( 'Options saved.', 'wps-limit-login' ) );
				}
			}
		}

		include_once( WPS_LIMIT_LOGIN_DIR . '/admin_page/options.php' );
	}

	public function ajax_unlock() {
		check_ajax_referer( 'wps-limit-login-unlock', 'nonce' );
		$ip = ( isset( $_POST['ip'] ) ) ? $_POST['ip'] : '';

		$lockouts = (array) $this->get_option( 'wps_limit_login_lockouts' );

		if ( isset( $lockouts[ $ip ] ) ) {
			unset( $lockouts[ $ip ] );
			$this->update_option( 'wps_limit_login_lockouts', $lockouts );
		}

		//save to log
		$user_login = ( isset( $_POST['username'] ) ) ? $_POST['username'] : '';
		$log        = $this->get_option( 'wps_limit_login_logged' );

		if ( isset( $log[ $ip ][ $user_login ] ) ) {
			if ( ! is_array( $log[ $ip ][ $user_login ] ) ) {
				$log[ $ip ][ $user_login ] = array(
					'counter' => $log[ $ip ][ $user_login ],
				);
			}
			$log[ $ip ][ $user_login ]['unlocked'] = true;

			$this->update_option( 'wps_limit_login_logged', $log );
		}

		wp_send_json_success();
	}

	/**
	 * Show error message
	 *
	 * @param $msg
	 *
	 * @return bool
	 */
	public static function show_error( $msg ) {
		if ( empty( $msg ) ) {
			return false;
		}

		echo '<div id="message" class="updated fade"><p>' . $msg . '</p></div>';
	}

	/**
	 * @param $log
	 *
	 * @return array
	 */
	public static function sorted_log_by_date( $log ) {
		$new_log = array();

		if ( ! is_array( $log ) || empty( $log ) ) {
			return $new_log;
		}

		foreach ( $log as $ip => $users ) {
			if ( empty( $users ) ) {
				continue;
			}

			foreach ( $users as $user_name => $info ) {
				if ( ! is_array( $info ) ) {
					continue;
				}

				$new_log[ $info['date'] ] = array(
					'ip'       => $ip,
					'username' => $user_name,
					'counter'  => $info['counter'],
					'gateway'  => ( isset( $info['gateway'] ) ) ? $info['gateway'] : '-',
					'unlocked' => ! empty( $info['unlocked'] ),
				);
			}
		}

		krsort( $new_log );

		return $new_log;
	}

	public function login_form() {
		$wps_limit_login_show_credit_link = $this->get_option( 'wps_limit_login_show_credit_link' );
		if ( $wps_limit_login_show_credit_link != 'true' && '1' != $wps_limit_login_show_credit_link ) {
			return false;
		}

		echo '<p class="wps-limit-login-credits"><img src="' . WPS_LIMIT_LOGIN_URL . 'assets/img/logo-icon-32.png' . '" /><br />' . __( 'Login form protected by', 'wps-limit-login' ) . ' <br /><a href="https://wordpress.org/plugins/wps-limit-login/" target="_blank">WPS Limit Login</a></p>';
	}

	public function login_enqueue_scripts() { ?>
        <style type="text/css">
            .login #login_error {
                background-color: #dc3232 !important;
                color: #fff;
                margin: 0 0 20px !important;
                border: 5px solid rgba(0, 0, 0, 0.2) !important;
                font-size: 16px;
            }

            .wps-limit-login-credits {
                text-align: center;
                position: fixed;
                bottom: 0;
                background: #303f4c;
                color: #fff;
                padding: 10px !important;
                width: 272px;
                display: block;
                margin: 0 auto !important;
                border-radius: 4px 4px 0px 0px;
                box-shadow: 0px 0px 3px #000;
                border: 1px solid #fff;
                border-bottom: 0;
                -webkit-box-sizing: border-box;
                -moz-box-sizing: border-box;
                box-sizing: border-box;
            }

            .wps-limit-login-credits a {
                color: #95be22;
            }

            .interim-login .wps-limit-login-credits {
                position: relative;
                margin-bottom: 15px !important;
                border-bottom: 1px solid #fff;
                border-radius: 4px;
            }

            @media screen and (max-height: 840px) {
                .wps-limit-login-credits {
                    position: relative;
                    margin-bottom: 15px !important;
                    border-bottom: 1px solid #fff;
                    border-radius: 4px;
                }
            }
        </style>
		<?php
	}

	/**
	 *
	 * Reinitialise settings plugins
	 *
	 * @return bool
	 */
	public function reinitialize() {
		if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'], 'reinitialize' ) ) {
			return false;
		}

		if ( ! isset( $_GET['action'] ) || $_GET['action'] !== 'reinitialize' ) {
			return false;
		}

		foreach ( $this->default_options as $option => $value ) {
			if ( 'wps_limit_login_whitelist' === $option || 'wps_limit_login_blacklist' === $option ) {
				continue;
			}
			$this->update_option( $option, $value );
		}

		wp_redirect( admin_url( 'options-general.php?page=wps-limit-login' ) );
		exit;
	}

	public static function activate() {
		add_option( 'wps_limit_login_activated', 1 );
	}

	public static function load_plugin() {

		if ( is_admin() && get_option( 'wps_limit_login_activated' ) == 1 ) {

			delete_option( 'wps_limit_login_activated' );

			if ( is_multisite()
			     && is_super_admin()
			     && is_plugin_active_for_network( WPS_LIMIT_LOGIN_BASENAME ) ) {

				$redirect = network_admin_url( 'settings.php?page=wps-limit-login' );
			} else {
				$redirect = admin_url( 'options-general.php?page=wps-limit-login' );
			}

			wp_safe_redirect( $redirect );
			die;
		}
	}

	/**
	 * @param $links
	 *
	 * @return mixed
	 */
	public function plugin_action_links( $links ) {
		if ( is_network_admin() && is_plugin_active_for_network( WPS_LIMIT_LOGIN_BASENAME ) ) {
			array_unshift( $links, '<a href="' . network_admin_url( 'settings.php?page=wps-limit-login' ) . '">' . __( 'Settings' ) . '</a>' );
		} else {
			array_unshift( $links, '<a href="' . admin_url( 'options-general.php?page=wps-limit-login' ) . '">' . __( 'Settings' ) . '</a>' );
		}

		return $links;
	}

	public function dashboard_widget_function( $post, $callback_args ) {
		$log = $this->get_option( 'wps_limit_login_logged' );
		$log = Plugin::sorted_log_by_date( $log );

		if ( ! is_array( $log ) || empty( $log ) ) {
			_e( 'No lockouts yet', 'wps-limit-login' );

			return false;
		}

		_e( 'List of the last 5 lockouts:', 'wps-limit-login' );

		ob_start();

		$i = 0;
		foreach ( $log as $date => $user_info ) :
			if ( $i > 5 ) {
				break;
			}
			echo '<p>' . date_i18n( 'd/m/Y H:i:s', $date ) . ' - ' . esc_html( $user_info['ip'] ) . ' - ' . $user_info['username'] . ' (' . $user_info['counter'] . ' ' . _n( 'lockout', 'lockouts', $user_info['counter'], 'wps-limit-login' ) . ')' . '</p>';
			$i ++;
		endforeach; ?>

		<?php
		echo ob_get_clean();

		echo '<a class="button button-primary" href="' . admin_url( 'options-general.php?page=wps-limit-login&tab=log' ) . '">' . __( 'See all lockouts', 'wps-limit-login' ) . '</a>';

	}

	public function add_dashboard_widgets() {
		wp_add_dashboard_widget( 'wps_limit_logindashboard_widget', 'WPS Limit Login', array(
			$this,
			'dashboard_widget_function'
		) );
	}

	public static function admin_footer() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return false;
		}

		$current_screen = get_current_screen();

		if ( false === strpos( $current_screen->base, 'wps-limit' ) ) {
			return false;
		}

		echo "<script>
            jQuery( 'a.wc-rating-link' ).click( function() {
                jQuery.post( '" . admin_url( 'admin-ajax.php', 'relative' ) . "', { action: 'wpslimitlogin_rated', _ajax_nonce: jQuery( this ).data('nonce') } );
                jQuery( this ).parent().text( jQuery( this ).data( 'rated' ) );
            });</script>";
	}

	public static function admin_footer_text( $footer_text ) {
		if ( ! current_user_can( 'manage_options' ) ) {
			return $footer_text;
		}

		$current_screen = get_current_screen();

		if ( false === strpos( $current_screen->base, 'wps-limit' ) ) {
			return $footer_text;
		}

		if ( ! get_option( 'wpslimitlogin_admin_footer_text_rated' ) ) {
			$footer_text = sprintf(
				__( 'If you like %1$s please leave us a %2$s rating. A huge thanks in advance!', 'wps-limit-login' ),
				sprintf( '<strong>%s</strong>', esc_html__( 'WPS Limit Login', 'wps-limit-login' ) ),
				'<a href="https://wordpress.org/support/plugin/wps-limit-login/reviews?rate=5#new-post" target="_blank" class="wc-rating-link" data-nonce="' . wp_create_nonce( 'wpslimitloginrated' ) . '" data-rated="' . esc_attr__( 'Thanks :)', 'wps-limit-login' ) . '">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
			);
		}

		return $footer_text;
	}

	/**
	 * Triggered when clicking the rating footer.
	 */
	public static function wpslimitlogin_rated() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( - 1 );
		}

		check_ajax_referer( 'wpslimitloginrated' );

		update_option( 'wpslimitlogin_admin_footer_text_rated', 1 );
		wp_die();
	}

	/**
	 * @param $array
	 *
	 * @return array
	 */
	public static function wps_bidouille_not_display_pub_array( $array ) {
		$array[] = 'settings_page_wps-limit-login';

		return $array;
	}
}