stop-spammers-classic/stop-spammer-registrations-new.php
2026-07-07 01:01:24 -06:00

1045 lines
No EOL
35 KiB
PHP

<?php
/*
Plugin Name: Stop Spammers Classic
Plugin URI: https://damspam.com/
Description: A simplified, restored, and preserved version of the original Stop Spammers plugin.
Version: 2026.6
Requires at least: 5.0
Requires PHP: 5.0
Author: Web Guy
Author URI: https://webguy.io/
License: GPL
License URI: https://www.gnu.org/licenses/gpl.html
*/
if ( !defined( 'ABSPATH' ) ) {
status_header( 404 );
exit;
}
// networking requires a couple of globals
define( 'SS_VERSION', '2026.6' );
define( 'SS_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'SS_PLUGIN_FILE', plugin_dir_path( __FILE__ ) );
define( 'SS_PLUGIN_DATA', wp_upload_dir()['basedir'] . '/data/' );
function ss_assets_version() {
return defined( 'WP_DEBUG' ) && WP_DEBUG ? ( string ) time() : SS_VERSION;
}
// add data folder
function ss_create_data_folder() {
WP_Filesystem();
global $wp_filesystem;
$upload_dir = wp_upload_dir()['basedir'] . '/data';
if ( !$wp_filesystem->is_dir( $upload_dir ) ) {
$wp_filesystem->mkdir( $upload_dir, 0700 );
}
}
register_activation_hook( __FILE__, 'ss_create_data_folder' );
// load admin styles
function ss_styles() {
$version = ss_assets_version();
wp_enqueue_style(
'ss-admin',
plugin_dir_url( __FILE__ ) . 'css/admin.css',
array(),
$version
);
}
add_action( 'admin_print_styles', 'ss_styles' );
// admin notice for users
function ss_admin_notice() {
$user_id = get_current_user_id();
$version_key = str_replace( '.', '_', SS_VERSION );
if ( !get_user_meta( $user_id, 'ss_notice_dismissed_' . $version_key ) && current_user_can( 'manage_options' ) ) {
$admin_url = esc_url( admin_url( add_query_arg( array(), '' ) ) );
$param = strpos( $admin_url, '?' ) !== false ? '&' : '?';
$install_url = esc_url( wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=dam-spam' ), 'install-plugin_dam-spam' ) );
echo wp_kses_post( sprintf( '<div class="notice notice-error"><p><a href="%s%sdismiss&_wpnonce=%s" class="alignright" style="text-decoration:none"><big>✕</big></a><big><strong>Stop Spammers is now Dam Spam</strong></big><p><a href="%s" class="button-primary" style="border-color:#4aa863;background:#4aa863">Install Dam Spam Now</a> &nbsp; <a href="mailto:webguywork@gmail.com" class="button-primary" target="_blank">Get Help</a></p><p>Development for Stop Spammers has ended. It\'s legacy code that is severely dated and unoptimized. Moving forward, it will receive security patches only. For continued development, modernized code, new and improved features, you\'ll need to migrate to Dam Spam. Doing so is extremely easy. Simply install and activate it and all your settings will automatically migrate over in the background.</p></div>', esc_url( $admin_url ), esc_html( $param ), esc_attr( wp_create_nonce( 'ss_dismiss_notice' ) ), $install_url ) );
}
}
add_action( 'admin_notices', 'ss_admin_notice' );
// dismiss admin notice for users
function ss_notice_dismissed() {
$user_id = get_current_user_id();
if ( isset( $_GET['dismiss'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'ss_dismiss_notice' ) ) {
$version_key = str_replace( '.', '_', SS_VERSION );
add_user_meta( $user_id, 'ss_notice_dismissed_' . $version_key, 'true', true );
}
}
add_action( 'admin_init', 'ss_notice_dismissed' );
// WooCommerce warning for users
function ss_wc_admin_notice() {
if ( is_plugin_active( 'woocommerce/woocommerce.php' ) ) {
$user_id = get_current_user_id();
if ( !get_user_meta( $user_id, 'ss_wc_notice_dismissed' ) && current_user_can( 'manage_options' ) ) {
echo '<div class="notice notice-info"><p style="color:purple"><a href="?sswc-dismiss&_wpnonce=' . esc_attr( wp_create_nonce( 'ss_dismiss_wc_notice' ) ) . '" class="alignright" style="text-decoration:none"><big>✕</big></a><big><strong>WooCommerce Detected</strong></big> | We recommend <a href="admin.php?page=ss_options">adjusting these options</a> if you experience any issues using WooCommerce and Stop Spammers together.</p></div>';
}
}
}
add_action( 'admin_notices', 'ss_wc_admin_notice' );
// dismiss WooCommerce warning for users
function ss_wc_notice_dismissed() {
if ( is_plugin_active( 'woocommerce/woocommerce.php' ) ) {
$user_id = get_current_user_id();
if ( isset( $_GET['sswc-dismiss'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'ss_dismiss_wc_notice' ) ) {
add_user_meta( $user_id, 'ss_wc_notice_dismissed', 'true', true );
}
}
}
add_action( 'admin_init', 'ss_wc_notice_dismissed' );
// hook the init event to start work
add_action( 'init', 'ss_init', 0 );
// dummy filters for addons
add_filter( 'ss_addons_allow', 'ss_addons_d', 0 );
add_filter( 'ss_addons_block', 'ss_addons_d', 0 );
add_filter( 'ss_addons_get', 'ss_addons_d', 0 );
// done - the reset will be done in the init event
/*******************************************************************
* How it works:
* 1) Network blog MU installation
* if networked switch then install network filters for options
* all options will redirect to Blog #1 options so no need to set up for each blog
* else
* normal install
* 2) Case when user is logged in
* setup user and comment actions
* if networked
* set up right-now and options to install only on Network Admin page
* else
* install hooks and filters for right-now options screens
* 3) When user is not logged in
* hook template redirect
* hook init
* 4) on template redirect check for bad requests and 404s on exploit items
* 5) on init check for POST or GET
* 6) on post gather post variables and check for spam, logins, or exploits
* 7) on get check for access blocking
* 8) on block
* update counters
* update cache
* update log
* present rejection screen - could contain email request form or CAPTCHA
* 9) on email request form send email to admin requesting Allow List
* 10) on CAPTCHA success add to Good Cache, remove from Bad Cache, update counters, log success
*/
function ss_init() {
remove_action( 'init', 'ss_init' );
add_filter( 'pre_user_login', 'ss_user_reg_filter', 1, 1 );
// incompatible with a Jetpack submit
if ( !empty( $_POST ) && array_key_exists( 'jetpack_protect_num', $_POST ) ) {
return;
}
// eMember trying to log in - disable plugin for eMember logins
if ( function_exists( 'wp_emember_is_member_logged_in' ) ) {
// only eMember function I could find after 30 seconds of Googling
if ( !empty( $_POST ) && array_key_exists( 'login_pwd', $_POST ) ) {
return;
}
}
// set up the Akismet hit
add_action( 'akismet_spam_caught', 'ss_log_akismet' ); // hook Akismet spam
$muswitch = 'N';
if ( function_exists( 'is_multisite' ) && is_multisite() ) {
switch_to_blog( 1 );
$muswitch = get_option( 'ss_muswitch' );
if ( $muswitch != 'N' ) {
$muswitch = 'Y';
}
restore_current_blog();
if ( $muswitch == 'Y' ) {
// install the hooks for options
define( 'SS_MU', $muswitch );
ss_sp_require( 'includes/ss-mu-options.php' );
ssp_global_setup();
}
} else {
define( 'SS_MU', $muswitch );
}
if ( function_exists( 'is_user_logged_in' ) ) {
// check to see if we need to hook the settings
// load the settings if logged in
if ( is_user_logged_in() ) {
remove_filter( 'pre_user_login', 'ss_user_reg_filter', 1 );
if ( current_user_can( 'manage_options' ) ) {
ss_sp_require( 'includes/ss-admin-options.php' );
return;
}
}
}
// user is not logged in - we can do checks
// add the new user hooks
global $wp_version;
if ( !version_compare( $wp_version, "3.1", "<" ) ) { // only in newer versions
add_action( 'user_register', 'ss_new_user_ip' );
add_action( 'wp_login', 'ss_log_user_ip', 10, 2 );
}
// don't do anything else if the eMember is logged in
if ( function_exists( 'wp_emember_is_member_logged_in' ) ) {
if ( wp_emember_is_member_logged_in() ) {
return;
}
}
// can we check for $_GET registrations?
if ( isset( $_POST ) && !empty( $_POST ) ) {
// see if we are returning from a block
if ( array_key_exists( 'ss_block', $_POST ) && array_key_exists( 'kn', $_POST ) ) {
// block form hit
if ( !empty( $_POST['kn'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['kn'] ) ), 'ss_stopspam_block' ) ) {
// call the checker program
sfs_errorsonoff();
$options = ss_get_options();
$stats = ss_get_stats();
$post = get_post_variables();
be_load( 'ss_challenge', ss_get_ip(), $stats, $options, $post );
// if we come back we continue as normal
sfs_errorsonoff( 'off' );
return;
}
}
// need to check that we are not Allow Listed
// don't check if IP is Google, etc.
// check to see if we are doing a post with values
// better way to check for Jetpack
if ( class_exists( 'Jetpack' ) && Jetpack::is_module_active( 'protect' ) ) {
return;
}
$post = get_post_variables();
if ( !empty( $post['email'] ) || !empty( $post['author'] ) || !empty( $post['comment'] ) ) { // must be a login or a comment which require minimum stuff
// remove_filter( 'pre_user_login', 'ss_user_reg_filter', 1 );
// sfs_debug_msg( 'email or author ' . print_r( $post, true ) );
$reason = ss_check_white();
if ( $reason !== false ) {
// sfs_debug_msg( "return from white $reason" );
return;
}
// sfs_debug_msg( 'past white ' );
ss_check_post(); // on POST check if we need to stop comments or logins
} else {
// sfs_debug_msg( 'no email or author ' . print_r( $post, true ) );
}
} else {
// this is a get - check for get addons
$addons = array();
$addons = apply_filters( 'ss_addons_get', $addons );
// these are the allow before addons
// returns array
// [0] = class location
// [1] = class name (also used as counter)
// [2] = addon name
// [3] = addon author
// [4] = addon description
if ( !empty( $addons ) && is_array( $addons ) ) {
foreach ( $addons as $add ) {
if ( !empty( $add ) && is_array( $add ) ) {
$options = ss_get_options();
$stats = ss_get_stats();
$post = get_post_variables();
$reason = be_load( $add, ss_get_ip(), $stats, $options );
if ( $reason !== false ) {
// need to log a passed hit on post here
remove_filter( 'pre_user_login', 'ss_user_reg_filter', 1 );
ss_log_bad( ss_get_ip(), $reason, $add[1], $add );
return;
}
}
}
}
}
add_action( 'template_redirect', 'ss_check_404s' ); // check missed hits for robots scanning for exploits
add_action( 'ss_stop_spam_caught', 'ss_caught_action', 10, 2 ); // hook stop spam - for testing
add_action( 'ss_stop_spam_ok', 'ss_stop_spam_ok', 10, 2 ); // hook stop spam - for testing
// captcha for forms
$options = ss_get_options();
if ( isset( $options['form_captcha_login'] ) and $options['form_captcha_login'] === 'Y' ) {
add_action( 'login_form', 'ss_add_captcha' );
}
if ( isset( $options['form_captcha_registration'] ) and $options['form_captcha_registration'] === 'Y' ) {
add_action( 'register_form', 'ss_add_captcha' );
}
if ( isset( $options['form_captcha_comment'] ) and $options['form_captcha_comment'] === 'Y' ) {
add_action( 'comment_form_after_fields', 'ss_add_captcha' );
}
}
// start of loadable functions
function ss_sp_require( $file ) {
require_once( $file );
}
/************************************************************
* function ss_sfs_check_admin()
* checks to see if the current admin can login
*************************************************************/
function ss_sfs_check_admin() {
ss_sfs_reg_add_user_to_allowlist(); // also saves options
}
function ss_sfs_reg_add_user_to_allowlist() {
$options = ss_get_options();
$stats = ss_get_stats();
$post = get_post_variables();
return be_load( 'ss_addtoallowlist', ss_get_ip(), $stats, $options );
}
function ss_set_stats( &$stats, $addon = array() ) {
// this sets the stats
if ( empty( $addon ) || !is_array( $addon ) ) {
// need to know if the spam count has changed
if ( $stats['spcount'] == 0 || empty( $stats['spdate'] ) ) {
$stats['spdate'] = gmdate( 'Y/m/d', time() + ( get_option( 'gmt_offset' ) * 3600 ) );
}
if ( $stats['spmcount'] == 0 || empty( $stats['spmdate'] ) ) {
$stats['spmdate'] = gmdate( 'Y/m/d', time() + ( get_option( 'gmt_offset' ) * 3600 ) );
}
} else {
// update addon stats
// addon stats are kept in addonstats array in stats
$addonstats = array();
if ( array_key_exists( 'addonstats', $stats ) ) {
$addonstats = $stats['addonstats'];
}
$addstats = array();
if ( array_key_exists( $addon[1], $addonstats ) ) {
$addstats = $addonstats[$addon[1]];
} else {
$addstats = array( 0, $addon );
}
$addstats[0] ++;
$addonstats[$addon[1]] = $addstats;
$stats['addonstats'] = $addonstats;
}
// other checks? - I might start compressing this, since it can get large
update_option( 'ss_stop_sp_reg_stats', $stats );
}
function ss_get_stats() {
$stats = get_option( 'ss_stop_sp_reg_stats' );
if ( !empty( $stats ) && is_array( $stats ) && array_key_exists( 'version', $stats ) && $stats['version'] == SS_VERSION ) {
return $stats;
}
return be_load( 'ss_get_stats', '' );
}
function ss_get_options() {
$options = get_option( 'ss_stop_sp_reg_options' );
$st = array();
if ( !empty( $options ) && is_array( $options ) && array_key_exists( 'version', $options ) && $options['version'] == SS_VERSION ) {
return $options;
}
return be_load( 'ss_get_options', '' );
}
function ss_set_options( $options ) {
update_option( 'ss_stop_sp_reg_options', $options );
}
function ss_get_ip() {
$ip = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
return filter_var( $ip, FILTER_VALIDATE_IP ) ? $ip : '';
}
function ss_admin_menu() {
if ( !function_exists( 'ss_admin_menu_l' ) ) {
ss_sp_require( 'settings/settings.php' );
}
sfs_errorsonoff();
ss_admin_menu_l();
sfs_errorsonoff( 'off' );
}
function ss_check_site_get() {
$options = ss_get_options();
$stats = ss_get_stats();
$post = get_post_variables();
sfs_errorsonoff();
$ret = be_load( 'ss_check_site_get', ss_get_ip(), $stats, $options, $post );
sfs_errorsonoff( 'off' );
return $ret;
}
function ss_check_post() {
sfs_errorsonoff();
$options = ss_get_options();
$stats = ss_get_stats();
$post = get_post_variables();
$ret = be_load( 'ss_check_post', ss_get_ip(), $stats, $options, $post );
sfs_errorsonoff( 'off' );
return $ret;
}
function ss_check_404s() { // check for exploits on 404s
sfs_errorsonoff();
$options = ss_get_options();
$stats = ss_get_stats();
$ret = be_load( 'ss_check_404s', ss_get_ip(), $stats, $options );
sfs_errorsonoff( 'off' );
return $ret;
}
function ss_log_bad( $ip, $reason, $chk, $addon = array() ) {
$options = ss_get_options();
$stats = ss_get_stats();
$post = get_post_variables();
$post['reason'] = $reason;
$post['chk'] = $chk;
$post['addon'] = $addon;
return be_load( 'ss_log_bad', ss_get_ip(), $stats, $options, $post );
}
function ss_log_akismet() {
sfs_errorsonoff();
$options = ss_get_options();
$stats = ss_get_stats();
if ( $options['chkakismet'] != 'Y' ) {
return false;
}
// check whitelists first
$reason = ss_check_white();
if ( $reason !== false ) {
return;
}
// not on Allow Lists
$post = get_post_variables();
$post['reason'] = 'from Akismet';
$post['chk'] = 'chkakismet';
$ansa = be_load( 'ss_log_bad', ss_get_ip(), $stats, $options, $post );
sfs_errorsonoff( 'off' );
return $ansa;
}
function ss_log_good( $ip, $reason, $chk, $addon = array() ) {
$options = ss_get_options();
$stats = ss_get_stats();
$post = get_post_variables();
$post['reason'] = $reason;
$post['chk'] = $chk;
$post['addon'] = $addon;
return be_load( 'ss_log_good', ss_get_ip(), $stats, $options, $post );
}
function ss_check_white() {
sfs_errorsonoff();
$options = ss_get_options();
$stats = ss_get_stats();
$post = get_post_variables();
$ansa = be_load( 'ss_check_white', ss_get_ip(), $stats, $options, $post );
sfs_errorsonoff( 'off' );
return $ansa;
}
function ss_check_white_block() {
sfs_errorsonoff();
$options = ss_get_options();
$stats = ss_get_stats();
$post = get_post_variables();
$post['block'] = true;
$ansa = be_load( 'ss_check_white', ss_get_ip(), $stats, $options, $post );
sfs_errorsonoff( 'off' );
return $ansa;
}
function be_load( $file, $ip, &$stats = array(), &$options = array(), &$post = array() ) {
// all classes have a process() method
// all classes have the same name as the file being loaded
// only executes the file if there is an option set with value 'Y' for the name
if ( empty( $file ) ) {
return false;
}
// load the be_module if does not exist
if ( !class_exists( 'be_module' ) ) {
require_once( 'classes/be_module.class.php' );
}
// if ( $ip == null ) $ip = ss_get_ip();
// for some loads we use an absolute path
// if it is an addon, it has the absolute path to the be_module
if ( is_array( $file ) ) { // add-ons pass their array
// this is an absolute location so load it directly
if ( !file_exists( $file[0] ) ) {
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging for missing addon files
sfs_debug_msg( 'not found ' . print_r( $add, true ) );
return false;
}
// require_once( $file[0] );
// this loads a be_module class
$class = new $file[1]();
$result = $class->process( $ip, $stats, $options, $post );
$class = null;
unset( $class ); // doesn't do anything
// memory_get_usage( true ); // force a garage collection
return $result;
}
$ppath = plugin_dir_path( __FILE__ ) . 'classes/';
$fd = $ppath . $file . '.php';
$fd = str_replace( "/", DIRECTORY_SEPARATOR, $fd ); // Windows fix
if ( !file_exists( $fd ) ) {
// echo "<br><br>Missing $file $fd<br><br>";
$ppath = plugin_dir_path( __FILE__ ) . 'modules/';
$fd = $ppath . $file . '.php';
$fd = str_replace( "/", DIRECTORY_SEPARATOR, $fd ); // Windows fix
}
if ( !file_exists( $fd ) ) {
$ppath = plugin_dir_path( __FILE__ ) . 'modules/countries/';
$fd = $ppath . $file . '.php';
$fd = str_replace( "/", DIRECTORY_SEPARATOR, $fd ); // Windows fix
}
if ( !file_exists( $fd ) ) {
echo '<br><br>Missing ' . esc_html( $file ), esc_html( $fd ) . '<br><br>';
return false;
}
require_once( $fd );
// this loads a be_module class
// sfs_debug_msg( "loading $fd" );
$class = new $file();
$result = $class->process( $ip, $stats, $options, $post );
$class = null;
unset( $class ); // does nothing - take out
return $result;
}
// this should be moved to a dynamic load, perhaps - it is one of the most common things
function get_post_variables() {
if ( isset( $_POST['ss_post_variables_nonce'] ) && !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['ss_post_variables_nonce'] ) ), 'ss_post_variables_action' ) ) {
return array(
'email' => '',
'author' => '',
'pwd' => '',
'comment' => '',
'subject' => '',
'url' => ''
);
}
// for WordPress and other login and comment programs
// need to find: login password comment author email
// copied from stop spammers plugin
// made generic so it also checks "head" and "get" (as well as cookies)
$ansa = array(
'email' => '',
'author' => '',
'pwd' => '',
'comment' => '',
'subject' => '',
'url' => ''
);
if ( empty( $_POST ) || !is_array( $_POST ) ) {
return $ansa;
}
$p = wp_unslash( $_POST );
$search = array(
'email' => array(
'email',
'e-mail',
'user_email',
'email-address',
'your-email'
),
// 'input_' = WooCommerce forms
'author' => array(
'author',
'name',
'username',
'user_login',
'signup_for',
'log',
'user',
'_id',
'your-name'
),
'pwd' => array(
'pwd',
'password',
'psw',
'pass',
'secret'
),
'comment' => array(
'comment',
'message',
'reply',
'body',
'excerpt',
'your-message'
),
'subject' => array(
'subject',
'subj',
'topic',
'your-subject'
),
'url' => array(
'url',
'link',
'site',
'website',
'blog_name',
'blogname',
'your-website'
)
);
$emfound = false;
// rewrite this
foreach ( $search as $var => $sa ) {
foreach ( $sa as $srch ) {
foreach ( $p as $pkey => $pval ) {
// see if the things in $srch live in post
if ( stripos( $pkey, $srch ) !== false ) {
// got a hit
if ( is_array( $pval ) ) {
$pval = wp_json_encode( $pval );
}
$ansa[$var] = $pval;
break;
}
}
if ( !empty( $ansa[$var] ) ) {
break;
}
}
if ( empty( $ansa[$var] ) && $var == 'email' ) { // empty email
// did not get a hit so we need to try again and look for something that looks like an email
foreach ( $p as $pkey => $pval ) {
if ( stripos( $pkey, 'input_' ) ) {
// might have an email
if ( is_array( $pval ) ) {
$pval = wp_json_encode( $pval );
}
if ( strpos( $pval, '@' ) !== false && strrpos( $pval, '.' ) > strpos( $pval, '@' ) ) {
// close enough
$ansa[$var] = $pval;
break;
}
}
}
}
}
// sanitize input - some of this is stored in history and needs to be cleaned up
foreach ( $ansa as $key => $value ) {
// clean the variables even more
$ansa[$key] = sanitize_text_field( $value ); // really clean gets rid of high value characters
}
if ( !empty( $ansa['email'] ) && !is_email( $ansa['email'] ) ) {
$ansa['email'] = '';
}
// truncate fields to prevent excessive storage
$max_lengths = array(
'email' => 80,
'author' => 80,
'pwd' => 32,
'comment' => 999,
'subject' => 80,
'url' => 80
);
foreach ( $max_lengths as $field => $max_length ) {
if ( strlen( $ansa[$field] ) > $max_length ) {
$ansa[$field] = substr( $ansa[$field], 0, $max_length - 3 ) . '...';
}
}
// print_r( $ansa );
// exit;
return $ansa;
}
function ss_addons_d( $config = array() ) {
// dummy function for testing
return $config;
}
function ss_caught_action( $ip = '', $post = array() ) {
// this is hit on spam detect for addons - added this for a template for testing - not needed
// $post has all the standardized post variables plus reason and the chk that found the problem
// good add-on would be a plugin to manage an SQL table where this stuff is stored
}
function ss_stop_spam_ok( $ip = '', $post = array() ) {
// dummy function for testing
// unreports spam
}
function really_clean( $s ) {
// try to get all non-7-bit things out of the string
if ( empty( $s ) ) {
return '';
}
$ss = array_slice( unpack( "c*", "\0" . $s ), 1 );
if ( empty( $ss ) ) {
return $s;
}
$s = '';
for ( $j = 0; $j < count( $ss ); $j ++ ) {
if ( $ss[$j] < 127 && $ss[$j] > 31 ) {
$s .= pack( 'C', $ss[$j] );
}
}
return $s;
}
function load_be_module() {
if ( !class_exists( 'be_module' ) ) {
require_once( 'classes/be_module.class.php' );
}
}
function ss_new_user_ip( $user_id ) {
$ip = ss_get_ip();
// sfs_debug_msg( "Checking reg filter login $x ( ss_user_ip ) = " . $ip . ", method = " . $_SERVER['REQUEST_METHOD'] . ", request = " . print_r( $_REQUEST, true ) );
// check to see if the user is OK
// add the users IP to new users
update_user_meta( $user_id, 'signup_ip', $ip );
}
function ss_sfs_ip_column_head( $column_headers ) {
$column_headers['signup_ip'] = 'IP Address';
return $column_headers;
}
function ss_log_user_ip( $user_login = "", $user = "" ) {
if ( empty( $user ) ) {
return;
}
if ( empty( $user_login ) ) {
return;
}
// add the user's IP to new users
if ( !isset( $user->ID ) ) {
return;
}
$user_id = $user->ID;
// $ip = ss_get_ip();
$ip = isset( $_SERVER['REMOTE_ADDR'] ) ? filter_var( sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ), FILTER_VALIDATE_IP ) : '';
$oldip = get_user_meta( $user_id, 'signup_ip', true );
if ( empty( $oldip ) || $ip != $oldip ) {
update_user_meta( $user_id, 'signup_ip', $ip );
}
}
// add registration date column to Users admin page
class SSRegDate {
public function __construct() {
add_action( 'init', array( &$this, 'init' ) );
}
public function init() {
add_filter( 'manage_users_columns', array( $this, 'users_columns' ) );
add_action( 'manage_users_custom_column', array( $this, 'users_custom_column' ), 10, 3 );
add_filter( 'manage_users_sortable_columns', array( $this, 'users_sortable_columns' ) );
add_filter( 'request', array( $this, 'users_orderby_column' ) );
}
public static function users_columns( $columns ) {
$columns['registerdate'] = 'Registered';
return $columns;
}
public static function users_custom_column( $value, $column_name, $user_id ) {
global $mode;
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading WP core display mode parameter for formatting only
$mode = empty( $_REQUEST['mode'] ) ? 'list' : sanitize_text_field( wp_unslash( $_REQUEST['mode'] ) );
if ( 'registerdate' != $column_name ) {
return $value;
} else {
$user = get_userdata( $user_id );
if ( is_multisite() && ( 'list' == $mode ) ) {
$formatted_date = 'F jS, Y';
} else {
$formatted_date = 'F jS, Y \a\t g:i a';
}
$registered = strtotime( get_date_from_gmt( $user->user_registered ) );
$registerdate = '<span>' . date_i18n( $formatted_date, $registered ) . '</span>' ;
return $registerdate;
}
}
public static function users_sortable_columns( $columns ) {
$custom = array(
'registerdate' => 'registered',
);
return wp_parse_args( $custom, $columns );
}
public static function users_orderby_column( $vars ) {
if ( isset( $vars['orderby'] ) && 'registerdate' == $vars['orderby'] ) {
$vars = array_merge( $vars, array(
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Necessary for user registration date sorting functionality
'meta_key' => 'registerdate',
'orderby' => 'meta_value'
) );
}
return $vars;
}
}
new SSRegDate();
/***********************************
* $user_email = apply_filters( 'user_registration_email', $user_email );
* I am going to start checking this filter for registrations
* add_filter( 'user_registration_email', ss_user_reg_filter, 1, 1 );
***********************************/
function ss_user_reg_filter( $user_login ) {
// the plugin should be all initialized
// check the IP, etc.
sfs_errorsonoff();
$options = ss_get_options();
$stats = ss_get_stats();
// fake out the post variables
$post = get_post_variables();
$post['author'] = $user_login;
$post['addon'] = 'chkRegister'; // not really an add-on - but may be moved out when working
if ( $options['filterregistrations'] != 'Y' ) {
remove_filter( 'pre_user_login', 'ss_user_reg_filter', 1 );
sfs_errorsonoff( 'off' );
return $user_login;
}
// if the suspect is already in the Bad Cache he does not get a second chance?
// prevents looping
$reason = be_load( 'chkbcache', ss_get_ip(), $stats, $options, $post );
sfs_errorsonoff();
if ( $reason !== false ) {
$rejectmessage = $options['rejectmessage'];
$post['reason'] = 'Failed Registration: Bad Cache';
$host['chk'] = 'chkbcache';
$ansa = be_load( 'ss_log_bad', ss_get_ip(), $stats, $options, $post );
wp_die( wp_kses_post( $rejectmessage ), 'Login Access Blocked', array( 'response' => 403 ) );
exit();
}
// check periods
$reason = be_load( 'chkperiods', ss_get_ip(), $stats, $options, $post );
if ( $reason !== false ) {
wp_die( 'Registration Access Blocked', 'Login Access Blocked', array( 'response' => 403 ) );
}
// check the whitelist
$reason = ss_check_white();
sfs_errorsonoff();
if ( $reason !== false ) {
$post['reason'] = 'Passed Registration:' . $reason;
$ansa = be_load( 'ss_log_good', ss_get_ip(), $stats, $options, $post );
sfs_errorsonoff( 'off' );
return $user_login;
}
// check the blacklist
// sfs_debug_msg( "Checking blacklist on registration: /r/n" . print_r( $post, true ) );
$ret = be_load( 'ss_check_post', ss_get_ip(), $stats, $options, $post );
$post['reason'] = 'Passed Registration ' . $ret;
$ansa = be_load( 'ss_log_good', ss_get_ip(), $stats, $options, $post );
return $user_login;
}
// private mode
function ss_login_redirect() {
global $pagenow, $post;
$options = ss_get_options();
if ( get_option( 'ssp_enable_custom_login', '' ) and $options['ss_private_mode'] == "Y" and ( !is_user_logged_in() && $post->post_name != 'login' ) ) {
wp_safe_redirect( site_url( 'login' ) );
exit;
} else if ( $options['ss_private_mode'] == "Y" and ( !is_user_logged_in() && ( $pagenow != 'wp-login.php' and $post->post_name != 'login' ) ) ) {
auth_redirect();
}
}
add_action( 'wp', 'ss_login_redirect' );
function ss_add_captcha() {
$options = ss_get_options();
$html = '';
$captcha_nonce = wp_create_nonce( 'ss_captcha_action' );
switch ( $options['chkcaptcha'] ) {
case 'G':
// reCAPTCHA
$recaptchaapisite = $options['recaptchaapisite'];
$html = wp_enqueue_script( 'ss-recaptcha', 'https://www.google.com/recaptcha/api.js', array(), '1', true, array( 'async' => true, 'defer' => true ) );
$html .= '<input type="hidden" name="ss_captcha_nonce" value="' . esc_attr( $captcha_nonce ) . '">';
$html .= '<input type="hidden" name="recaptcha" value="recaptcha">';
$html .= '<div class="g-recaptcha" data-sitekey="' . esc_attr( $recaptchaapisite ) . '"></div>';
break;
case 'H':
// hCaptcha
$hcaptchaapisite = $options['hcaptchaapisite'];
$html = wp_enqueue_script( 'ss-hcaptcha', 'https://hcaptcha.com/1/api.js', array(), '1', true, array( 'async' => true, 'defer' => true ) );
$html .= '<input type="hidden" name="ss_captcha_nonce" value="' . esc_attr( $captcha_nonce ) . '">';
$html .= '<input type="hidden" name="h-captcha" value="h-captcha">';
$html .= '<div class="h-captcha" data-sitekey="' . esc_attr( $hcaptchaapisite ) . '"></div>';
break;
case 'S':
$solvmediaapivchallenge = $options['solvmediaapivchallenge'];
$html = wp_enqueue_script( 'ss-solvemedia', 'https://api-secure.solvemedia.com/papi/challenge.script?k=' . $solvmediaapivchallenge, array(), '1', true, array( 'async' => true, 'defer' => true ) );
$html .= '<input type="hidden" name="ss_captcha_nonce" value="' . esc_attr( $captcha_nonce ) . '">';
$html .= '<noscript>';
$html .= '<iframe src="https://api-secure.solvemedia.com/papi/challenge.noscript?k=' . esc_attr( $solvmediaapivchallenge ) . '" height="300" width="500" frameborder="0"></iframe><br>';
$html .= '<textarea name="adcopy_challenge" rows="3" cols="40"></textarea>';
$html .= '<input type="hidden" name="adcopy_response" value="manual_challenge">';
$html .= '</noscript>';
break;
}
$allowed_html = array(
'script' => array(
'src' => array(),
'async' => array(),
'defer' => array(),
),
'input' => array(
'type' => array(),
'name' => array(),
'value' => array(),
),
'div' => array(
'class' => array(),
'data-sitekey' => array(),
),
'noscript' => array(),
'iframe' => array(
'src' => array(),
'height' => array(),
'width' => array(),
'frameborder' => array(),
),
'textarea' => array(
'name' => array(),
'rows' => array(),
'cols' => array(),
),
'br' => array(),
);
echo wp_kses( $html, $allowed_html );
}
function ss_captcha_verify() {
static $verified = null;
if ( $verified !== null ) {
return $verified;
}
if ( empty( $_POST ) ) {
$verified = true;
return true;
}
if ( !isset( $_POST['ss_captcha_nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['ss_captcha_nonce'] ) ), 'ss_captcha_action' ) ) {
$verified = '<strong>Error:</strong> Security verification failed.';
return $verified;
}
$options = ss_get_options();
$ip = ss_get_ip();
switch ( $options['chkcaptcha'] ) {
case 'G':
if ( !isset( $_POST['g-recaptcha-response'] ) || empty( $_POST['g-recaptcha-response'] ) ) {
$verified = '<strong>Error:</strong> Please complete the reCAPTCHA.';
return $verified;
}
$secret = $options['recaptchaapisecret'];
$recaptcha_response = sanitize_textarea_field( wp_unslash( $_POST['g-recaptcha-response'] ) );
$response = wp_safe_remote_post( 'https://www.google.com/recaptcha/api/siteverify', array(
'body' => array(
'secret' => $secret,
'response' => $recaptcha_response,
'remoteip' => $ip
)
) );
if ( is_wp_error( $response ) ) {
$verified = '<strong>Error:</strong> Google reCAPTCHA connection failed.';
return $verified;
}
$parsed = json_decode( wp_remote_retrieve_body( $response ) );
if ( !isset( $parsed->success ) || true !== $parsed->success ) {
$verified = '<strong>Error:</strong> Google reCAPTCHA verification failed.';
return $verified;
}
break;
case 'H':
if ( !isset( $_POST['h-captcha-response'] ) || empty( $_POST['h-captcha-response'] ) ) {
$verified = '<strong>Error:</strong> Please complete the hCaptcha.';
return $verified;
}
$secret = $options['hcaptchaapisecret'];
$response = wp_safe_remote_post( 'https://hcaptcha.com/siteverify', array(
'body' => array(
'secret' => $secret,
'response' => sanitize_textarea_field( wp_unslash( $_POST['h-captcha-response'] ) ),
'remoteip' => $ip
)
) );
$parsed = json_decode( wp_remote_retrieve_body( $response ) );
if ( is_wp_error( $response ) || !isset( $parsed->success ) || true !== $parsed->success ) {
$verified = '<strong>Error:</strong> hCaptcha verification failed.';
return $verified;
}
break;
case 'S':
if ( !isset( $_POST['adcopy_challenge'] ) || empty( $_POST['adcopy_challenge'] ) ) {
$verified = '<strong>Error:</strong> Please complete the CAPTCHA.';
return $verified;
}
$response = wp_safe_remote_post( 'https://verify.solvemedia.com/papi/verify/', array(
'body' => array(
'privatekey' => $options['solvmediaapiverify'],
'challenge' => sanitize_textarea_field( wp_unslash( $_POST['adcopy_challenge'] ) ),
'response' => isset( $_POST['adcopy_response'] ) ? sanitize_textarea_field( wp_unslash( $_POST['adcopy_response'] ) ) : '',
'remoteip' => $ip
)
) );
if ( is_wp_error( $response ) || false === strpos( wp_remote_retrieve_body( $response ), 'true' ) ) {
$verified = '<strong>Error:</strong> Solve Media CAPTCHA verification failed.';
return $verified;
}
break;
}
$verified = true;
return true;
}
function ss_login_captcha_verify( $user ) {
$options = ss_get_options();
if ( !isset( $options['form_captcha_login'] ) or $options['form_captcha_login'] !== 'Y' ) {
return $user;
}
$response = ss_captcha_verify();
if ( $response !== true ) {
return new WP_Error( 'ss_captcha_error', $response );
}
return $user;
}
add_filter( 'authenticate', 'ss_login_captcha_verify', 99 );
function ss_registration_captcha_verify( $errors ) {
$options = ss_get_options();
if ( !isset( $options['form_captcha_registration'] ) or $options['form_captcha_registration'] !== 'Y' ) {
return $errors;
}
$response = ss_captcha_verify();
if ( $response !== true ) {
$errors->add( 'ss_captcha_error', $response );
}
return $errors;
}
add_filter( 'registration_errors', 'ss_registration_captcha_verify', 10 );
function ss_comment_captcha_verify( $approved ) {
$options = ss_get_options();
if ( !isset( $options['form_captcha_comment'] ) or $options['form_captcha_comment'] !== 'Y' ) {
return $approved;
}
$response = ss_captcha_verify();
if ( $response !== true ) {
return new WP_Error( 'ss_captcha_error', $response, 403 );
}
return $approved;
}
add_filter( 'pre_comment_approved', 'ss_comment_captcha_verify', 99, 1 );
// action links
function ss_summary_link( $links ) {
$links = array_merge( array( '<a href="' . admin_url( 'admin.php?page=stop_spammers' ) . '">' . 'Settings' . '</a>' ), $links );
return $links;
}
add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), 'ss_summary_link' );
require_once( 'includes/stop-spam-utils.php' );
register_activation_hook( __FILE__, 'ss_activation_check' );
function ss_activation_check() {
if ( is_plugin_active( 'dam-spam/dam-spam.php' ) ) {
deactivate_plugins( 'dam-spam/dam-spam.php' );
}
}
?>