array( 'label' => __( 'Safety Analytics', 'admin-safety-guard' ), 'icon' => '', 'class' => '', ), 'security-core' => array( 'label' => __( 'Security Core', 'admin-safety-guard' ), 'icon' => '', 'class' => '', 'sub' => array( 'limit-login-attempts' => array( 'label' => __( 'Limit Login Attempts', 'admin-safety-guard' ), ), 'two-factor-auth' => array( 'label' => __( 'Two-Factor Authentication', 'admin-safety-guard' ), ), 'password-protection' => array( 'label' => __( 'Password Protection', 'admin-safety-guard' ), ), 'recaptcha' => array( 'label' => __( 'reCAPTCHA', 'admin-safety-guard' ), ), 'admin-bar' => array( 'label' => __( 'Hide Admin Bar', 'admin-safety-guard' ), ), ), ), 'firewall-malware' => array( 'label' => __( 'Firewall & Malware', 'admin-safety-guard' ), 'icon' => '', 'class' => '', ), 'login-logs-activity' => array( 'label' => __( 'Monitoring & Analytics', 'admin-safety-guard' ), 'icon' => '', 'class' => '', ), 'privacy-hardening' => array( 'label' => __( 'Privacy & Hardening', 'admin-safety-guard' ), 'icon' => '', 'class' => '', ), 'customize' => array( 'label' => __( 'Customization & Access', 'admin-safety-guard' ), 'icon' => '', 'class' => '', ), ) ); } } if ( !function_exists( 'tpsa_settings_fields' ) ) { /** * Returns an associative array of settings fields available for the Secure Admin plugin. * * The array is composed of feature slugs as keys and arrays of 'fields' as values. * Each 'fields' array is composed of field slugs as keys and arrays of 'type', 'label', 'class', 'id', and 'desc' as values. * * @since 1.0.0 * * @filter tpsa_settings_fields * * @return array Associative array of available settings fields. */ function tpsa_settings_fields() { return apply_filters( 'tpsa_settings_fields', array( 'analytics' => array( 'fields' => array(), ), 'admin-bar' => array( 'fields' => array( 'enable' => array( 'type' => 'switch', 'label' => __( 'Hide Admin Bar', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'To enable/disable admin bar', 'admin-safety-guard' ), 'default' => 0, ), 'exclude' => array( 'type' => 'multi-check', 'label' => __( 'Exclude', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'Exclude users', 'admin-safety-guard' ), 'default' => 'light', 'options' => get_tps_all_user_roles(), ), ), ), 'custom-login-url' => array( 'fields' => array( 'enable' => array( 'type' => 'switch', 'label' => __( 'Enable', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'To enable/disable custom login/logut url.', 'admin-safety-guard' ), 'default' => 0, ), 'login-url' => array( 'type' => 'text', 'label' => __( 'Custom Login Url', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'Protect your website by changing the login page URL.', 'admin-safety-guard' ), 'default' => get_tpsa_site_login_path(), ), 'redirect-url' => array( 'type' => 'text', 'label' => __( 'Redirect URL', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'Wp Admin redirect URL. Default: home_url()', 'admin-safety-guard' ), 'default' => '', ), 'logout-url' => array( 'type' => 'text', 'label' => __( 'Redirect URL After Logout', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'Redirect URL after Logout', 'admin-safety-guard' ), 'default' => get_tpsa_site_login_path(), ), ), ), 'limit-login-attempts' => array( 'fields' => array( 'enable' => array( 'type' => 'switch', 'label' => __( 'Enable', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'To enable/disable limit login attempts.', 'admin-safety-guard' ), 'default' => 0, ), 'max-attempts' => array( 'type' => 'number', 'label' => __( 'Max Login Attempts', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'Maximum number of login attempts within 1 day for temporarily blocked IP/user.', 'admin-safety-guard' ), 'default' => 3, ), 'block-for' => array( 'type' => 'number', 'label' => __( 'Lock for', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'Add how many minutes will be locked.', 'admin-safety-guard' ), 'default' => 15, ), 'max-lockout' => array( 'type' => 'number', 'label' => __( 'Max Lockouts', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'Maximum number of lockout within 1 days for temporarily blocked IP/user.', 'admin-safety-guard' ), 'default' => 3, ), 'block-message' => array( 'type' => 'textarea', 'label' => __( 'Blocked Message', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'Blocked users can see this message when they are locked out.', 'admin-safety-guard' ), 'default' => __( 'You have been locked out due to too many login attempts.', 'admin-safety-guard' ), ), 'block-ip-address' => array( 'type' => 'single-repeater', 'label' => __( 'Block with IP Address', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'IP addresses', 'admin-safety-guard' ), 'default' => '', ), ), ), 'login-logs-activity' => array( 'fields' => array( ), ), 'recaptcha' => array( 'fields' => array( 'enable' => array( 'type' => 'switch', 'label' => __( 'Enable', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'To enable/disable reCAPTCHA.', 'admin-safety-guard' ), 'default' => 0, ), 'version' => array( 'type' => 'option', 'label' => __( 'Version', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'Select Google reCAPTCHA version', 'admin-safety-guard' ), 'default' => '', 'options' => array( 'v2' => 'v2', 'v3' => 'v3', ), ), 'site-key' => array( 'type' => 'text', 'label' => __( 'Site Key', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => "Enter you Google reCAPTCHA site key. Get site key", 'default' => '', ), 'secret-key' => array( 'type' => 'text', 'label' => __( 'Secret Key', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => "Enter you Google reCAPTCHA screet key. Get secret key", 'default' => '', ), 'theme' => array( 'type' => 'option', 'label' => __( 'Theme', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'Select your preferred theme', 'admin-safety-guard' ), 'default' => 'light', 'options' => array( 'light' => 'Light Theme', 'dark' => 'Dark Theme', ), ), ), ), 'two-factor-auth' => array( 'fields' => array( 'otp-email' => array( 'type' => 'switch', 'label' => __( 'OTP via Email', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'After entering the correct login credentials, the user will be asked for the OTP. The OTP will be emailed to the user.', 'admin-safety-guard' ), 'default' => 0, ), ), ), 'password-protection' => array( 'fields' => array( 'enable' => array( 'type' => 'switch', 'label' => __( 'Enable', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'To enable/disable password protection.', 'admin-safety-guard' ), 'default' => 0, ), 'password' => array( 'type' => 'password', 'label' => __( 'Set Password', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'Password-protect the entire site to hide the content from public view and search engine bots / crawlers.', 'admin-safety-guard' ), 'default' => '', ), 'password-expiry' => array( 'type' => 'number', 'label' => __( 'Password Access Duration', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'How long visitors can access the site after entering the correct password.', 'admin-safety-guard' ), 'default' => '15', ), 'exclude' => array( 'type' => 'multi-check', 'label' => __( 'Exclude', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'Exclude user from this password protection', 'admin-safety-guard' ), 'default' => 'light', 'options' => array_merge( array( 'all-login-user' => 'All logged in users', ), get_tps_all_user_roles() ), ), ), ), 'privacy-hardening' => array( 'fields' => array( 'xml-rpc-enable' => array( 'type' => 'switch', 'label' => __( 'Disable XML-RPC', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'To disable/enable XML-RPC.', 'admin-safety-guard' ), 'default' => 0, ), ), ), 'customize' => array( 'fields' => array( 'enable' => array( 'type' => 'switch', 'label' => __( 'Enable', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'To enable/disable customizer.', 'admin-safety-guard' ), 'default' => 0, ), 'logo' => array( 'type' => 'upload', 'label' => __( 'Logo', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'Preferred logo size: 84×84 px. Please upload accordingly.', 'admin-safety-guard' ), 'default' => 0, ), 'logo-url' => array( 'type' => 'text', 'label' => __( 'Logo URL', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'Enter logo url', 'admin-safety-guard' ), 'default' => site_url(), ), 'logo-width' => array( 'type' => 'number', 'label' => __( 'Logo Width', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'logo width', 'admin-safety-guard' ), 'default' => 84, ), 'logo-height' => array( 'type' => 'number', 'label' => __( 'Logo Height', 'admin-safety-guard' ), 'class' => '', 'id' => '', 'desc' => __( 'logo height', 'admin-safety-guard' ), 'default' => 84, ), ), ), ) ); } } if ( !function_exists( 'get_tpsa_site_login_path' ) ) { /** * Returns the relative path of the WordPress login URL. * * @since 1.0.0 * * @return string The relative path of the WordPress login URL. */ function get_tpsa_site_login_path() { $site_url = get_site_url(); $login_url = wp_login_url(); // Remove site URL from login URL $relative_path = str_replace( $site_url, '', $login_url ); // Trim any leading/trailing slashes $relative_path = trim( $relative_path, '/' ); return $relative_path; } } if ( !function_exists( 'get_tpsa_prefix' ) ) { /** * Returns the prefix used for options and other identifiers throughout the plugin. * * @since 1.0.0 * * @return string The prefix used by the plugin. */ function get_tpsa_prefix() { return 'tpsa_'; } } /** * Returns the option name used to store the settings for a given screen slug. * * @since 1.0.0 * * @param string $screen_slug The screen slug. * * @return string The option name used to store the settings. */ function get_tpsa_settings_option_name( $screen_slug ) { return get_tpsa_prefix() . $screen_slug . '_settings'; } /** * Returns the full table name with the TPSA prefix. * * This function combines the global WordPress table prefix with the TPSA-specific * prefix and the provided table name to generate the full table name. * * @since 1.0.0 * * @param string $table_name The base name of the table. * * @return string The full table name with the TPSA prefix. */ function get_tpsa_db_table_name( $table_name ) { global $wpdb; $prefix = $wpdb->prefix . TPSA_PREFIX . '_'; return $prefix . $table_name; } function get_tps_all_user_roles() { global $wp_roles; if ( !isset( $wp_roles ) ) { $wp_roles = new WP_Roles(); } $roles = $wp_roles->roles; $role_names = []; foreach ( $roles as $key => $role ) { $role_names[$key] = $role['name']; } return $role_names; } if ( !function_exists( 'tpsm_saved_remote_data' ) ) { /** * Sends the current user's information to a remote server. * * This function retrieves the currently logged-in user's full name, * email address, and the site URL, and sends this data to a specified * remote server endpoint using a POST request. This is intended to * collect user data for integration with a remote service. * * @return void */ function tpsm_saved_remote_data() { $current_user = wp_get_current_user(); // Check if a user is logged in if ( !$current_user || 0 === $current_user->ID ) { return; } // Get full name (first + last or fallback to display name) $full_name = trim( $current_user->first_name . ' ' . $current_user->last_name ); if ( empty( $full_name ) ) { $full_name = $current_user->display_name; } $email_address = $current_user->user_email; $site_url = get_site_url(); wp_remote_post( 'https://themepaste.com/wp-json/v2/collect-email/admin-safety-guard', [ 'headers' => [ 'X-Auth-Token' => 'c7fc312817194d30c79da538204eaec3', 'Content-Type' => 'application/json', ], 'body' => json_encode( [ 'email_address' => $email_address, 'full_name' => $full_name, 'site_url' => $site_url, ] ), ] ); } } if ( !function_exists( 'login_page_templates' ) ) { /** * Returns an associative array of available login page templates. * * The array is composed of template slugs as keys and arrays of 'label' and 'css' as values. * * @since 1.0.0 * * @return array Associative array of available login page templates. */ /** * Get login page templates. * * @return array */ function login_page_templates() { $templates = [ 'default' => ['label' => __( 'WordPress Default', 'admin-safety-guard' ), 'css' => '', 'smalImg' => 'https://placehold.co/200x200', 'bigImg' => 'https://placehold.co/800x600'], 'classic' => ['label' => __( 'Classic Card', 'admin-safety-guard' ), 'css' => 'classic.css', 'smalImg' => 'https://placehold.co/200x200', 'bigImg' => 'https://placehold.co/800x600'], 'glass' => ['label' => __( 'Frosted Glass', 'admin-safety-guard' ), 'css' => 'glass.css', 'smalImg' => 'https://placehold.co/200x200', 'bigImg' => 'https://placehold.co/800x600'], 'split' => ['label' => __( 'Split Hero', 'admin-safety-guard' ), 'css' => 'split.css', 'smalImg' => 'https://placehold.co/200x200', 'bigImg' => 'https://placehold.co/800x600'], 'gradient' => ['label' => __( 'Soft Gradient', 'admin-safety-guard' ), 'css' => 'gradient.css', 'smalImg' => 'https://placehold.co/200x200', 'bigImg' => 'https://placehold.co/800x600'], ]; /** * Filter: Modify the available login templates. * * @param array $templates Associative array of template definitions. */ return apply_filters( 'customize/login_templates', $templates ); } } if ( !function_exists( 'tp_asg_pro_current_prefix' ) ) { function tp_asg_pro_current_prefix() { global $wpdb; return $wpdb->prefix; } } /** * Generate a random DB table prefix string. * * @param int $len Optional length of the prefix. Default is 5. * @return string A random DB table prefix string (e.g. 'abcde_'). */ if ( !function_exists( 'tp_asg_pro_random_prefix' ) ) { function tp_asg_pro_random_prefix( int $len = 5 ) { $chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; $s = ''; $s .= chr( ord( 'a' ) + random_int( 0, 25 ) ); for ( $i = 1; $i < $len; $i++ ) { $s .= $chars[random_int( 0, strlen( $chars ) - 1 )]; } return $s . '_'; } } if ( !function_exists( 'tp_asg_pro_is_prefix_good' ) ) { function tp_asg_pro_is_prefix_good( $prefix ) { // 0) Must end with "_" if ( substr( $prefix, -1 ) !== '_' ) { return false; } $clean = rtrim( $prefix, '_' ); // 1) Basic charset & shape if ( $clean === '' ) { return false; } // Only lowercase letters, digits, underscore (allow uppercase but normalize for checks) if ( !preg_match( '/^[a-zA-Z0-9_]+$/', $clean ) ) { return false; } // Start with a letter (avoid numeric start for readability) if ( !preg_match( '/^[a-zA-Z]/', $clean ) ) { return false; } // No internal double underscores if ( strpos( $clean, '__' ) !== false ) { return false; } // Normalize to lowercase for word checks $lc = strtolower( $clean ); // 2) Length guard (excluding trailing underscore) $len = strlen( $clean ); if ( $len < 3 || $len > 20 ) { // reasonable bounds; MySQL table name limit is 64 but keep prefixes compact return false; } // 3) Require letters + numbers if ( !preg_match( '/[a-z]/i', $clean ) || !preg_match( '/[0-9]/', $clean ) ) { return false; } // 4) Block common/guessable words and environments $bad_words = [ 'wp', 'wordpress', 'blog', 'site', 'cms', 'press', 'db', 'data', 'table', 'admin', 'root', 'superadmin', 'secure', 'security', 'guard', 'shield', 'lock', 'safe', 'safety', 'school', 'college', 'university', 'edu', 'user', 'member', 'login', 'auth', 'test', 'demo', 'sample', 'example', 'sandbox', 'staging', 'stage', 'dev', 'devel', 'prod', 'production', 'alpha', 'beta', 'backup', 'bkp', 'tmp', 'temp', 'cache', 'public', 'private', 'qwerty', 'abc', 'abcd', 'abcde', 'abcd1234', 'test123', 'admin123', ]; foreach ( $bad_words as $w ) { if ( $lc === $w || str_contains( $lc, $w ) ) { return false; } } // 5) Block SQL keywords (simple set) $sql_keywords = [ 'select', 'insert', 'update', 'delete', 'drop', 'create', 'alter', 'grant', 'revoke', 'union', 'where', 'from', 'join', 'table', 'into', 'values', 'set', 'index', 'view', ]; foreach ( $sql_keywords as $kw ) { if ( $lc === $kw || str_contains( $lc, $kw ) ) { return false; } } // 6) Obvious sequences / repeats // 6a) Same char repeated (aaa…) if ( preg_match( '/^([a-z0-9])\1{3,}$/i', $clean ) ) { return false; } // 6b) Strict ascending/descending sequences of length >= 5 (abcde, 12345, edcba) $is_monotonic = function ( $s ) { $n = strlen( $s ); if ( $n < 5 ) { return false; } $asc = true; $desc = true; for ( $i = 1; $i < $n; $i++ ) { $d = ord( $s[$i] ) - ord( $s[$i - 1] ); if ( $d !== 1 ) {$asc = false;} if ( $d !== -1 ) {$desc = false;} if ( !$asc && !$desc ) { return false; } } return $asc || $desc; }; if ( $is_monotonic( preg_replace( '/[^a-z0-9]/i', '', $lc ) ) ) { return false; } // 6c) Common keyboard runs $keyboard_runs = ['qwerty', 'asdf', 'zxcv', '12345', '98765']; foreach ( $keyboard_runs as $run ) { if ( str_contains( $lc, $run ) ) { return false; } } // 7) Entropy-ish check: require variety $letters = array_unique( str_split( preg_replace( '/[^a-z]/', '', $lc ) ) ); $digits = array_unique( str_split( preg_replace( '/[^0-9]/', '', $lc ) ) ); $unique = array_unique( str_split( $lc ) ); if ( ( count( $letters ) < 2 || count( $digits ) < 2 ) && count( $unique ) < 5 ) { return false; } // 8) Specific legacy defaults if ( $lc === 'wp' || $lc === 'wp1' || $lc === 'wp2' || $lc === 'wp3' ) { return false; } return true; } } function tp_svg_google() { return ''; } function tp_svg_facebook() { return ''; } function tp_svg_twitter() { return ''; } function tp_svg_linkedin() { return ''; } if ( !function_exists( 'tpsa_all_features' ) ): function tpsa_all_features() { $features = tpsa_settings_option(); $all_features_list = []; foreach ( $features as $feature_slug => $feature_data ) { if ( isset( $feature_data['sub'] ) ) { $features = $feature_data['sub']; foreach ( $features as $key => $value ) { $all_features_list[] = $key; } } else { $all_features_list[] = $feature_slug; } } return $all_features_list; } endif; if ( !function_exists( 'tpsa_get_features_summary' ) ): /** * Returns a summary of all features in the plugin. * * The summary object contains three properties: * - total: The total number of features. * - active: The number of features that are currently active (i.e. enabled). * - inactive: The number of features that are currently inactive (i.e. disabled). * * @return object Summary object containing the total, active, and inactive feature counts. */ function tpsa_get_features_summary() { $settings_fields = tpsa_settings_fields(); $all_features_list = tpsa_all_features(); $total = 0; $active = 0; $inactive = 0; $all_active_features = []; foreach ( $all_features_list as $feature_slug ) { $total++; if ( isset( $settings_fields[$feature_slug]['fields'] ) ) { $fields = $settings_fields[$feature_slug]['fields']; // If feature has an enable switch if ( isset( $fields['enable'] ) ) { $option_name = get_tpsa_settings_option_name( $feature_slug ); $saved_opts = get_option( $option_name, [] ); if ( !empty( $saved_opts['enable'] ) ) { $active++; $all_active_features[] = $feature_slug; } else { $inactive++; } } } // If no fields exist → always active if ( empty( $settings_fields[$feature_slug]['fields'] ) ) { $active++; $all_active_features[] = $feature_slug; continue; } } return (object) [ 'total' => $total, 'active' => $active, 'inactive' => $inactive, 'all_active_features' => $all_active_features, ]; } endif; if ( !function_exists( 'tpsa_get_security_score' ) ): function tpsa_get_security_score() { $summary = tpsa_get_features_summary(); if ( empty( $summary->total ) ) { return 0; } $raw_score = ( $summary->active / $summary->total ) * 100; // Absolute + safe bounds $score = abs( round( $raw_score ) ); $score = min( 100, max( 0, $score ) ); return $score; } endif; if ( !function_exists( 'tpsa_get_security_label' ) ): function tpsa_get_security_label( $score ) { if ( $score >= 90 ) { return 'Excellent protection'; } elseif ( $score >= 75 ) { return 'Strong protection'; } elseif ( $score >= 50 ) { return 'Moderate protection'; } elseif ( $score >= 30 ) { return 'Weak protection'; } else { return 'Critical risk'; } } endif; if ( !function_exists( 'tp_is_pro_active' ) ) { /** * Checks if the Admin Safety Guard Pro plugin is active. * * @return bool True if the plugin is active, false otherwise. */ function tp_is_pro_active() { $plugin_path = 'admin-safety-guard-pro/admin-safety-guard-pro.php'; if ( !function_exists( 'is_plugin_active' ) ) { include_once ABSPATH . 'wp-admin/includes/plugin.php'; } // Normal activation if ( is_plugin_active( $plugin_path ) ) { return true; } // Network activation (multisite) if ( is_multisite() && is_plugin_active_for_network( $plugin_path ) ) { return true; } return false; } }