WordPress Zero Spam - Version 4.7.0

Version Description

  • Various performance enhancements
  • Updates to the admin tables
  • Improved UI
  • Added functionality & option to permanently auto-block after X spam detections
  • Added ability to share spam detections with WordPress Zero Spam to strengthen it's ability to detect spammers
Download this release

Release Info

Developer bmarshall511
Plugin Icon 128x128 WordPress Zero Spam
Version 4.7.0
Comparing to
See all releases

Code changes from version 4.6.0 to 4.7.0

assets/css/admin-blocked-ips.css CHANGED
@@ -5,8 +5,7 @@
5
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
6
  display: flex;
7
  flex-wrap: wrap;
8
- margin-left: -10px;
9
- margin-right: -10px;
10
  padding: 20px;
11
  }
12
 
5
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
6
  display: flex;
7
  flex-wrap: wrap;
8
+ margin-top: 10px;
 
9
  padding: 20px;
10
  }
11
 
assets/css/admin-dashboard.css CHANGED
@@ -1,52 +1,3 @@
1
- .wpzerospam-callout {
2
- align-items: center;
3
- background: #fff;
4
- border: 1px solid #ccd0d4;
5
- box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
6
- display: flex;
7
- flex-wrap: wrap;
8
- padding: 20px;
9
- }
10
-
11
- .wpzerospam-callout h2 {
12
- font-size: 18px;
13
- margin-bottom: 10px;
14
- }
15
-
16
- .wpzerospam-callout p {
17
- font-size: 14px;
18
- margin-top: 0;
19
- }
20
-
21
- .wpzerospam-callout-actions {
22
- display: block;
23
- width: 100%;
24
- }
25
-
26
- .wpzerospam-callout-actions a.button {
27
- display: block;
28
- margin-bottom: 3px;
29
- text-align: center;
30
- width: 100%;
31
- }
32
-
33
- .wpzerospam-callout-actions a:last-child {
34
- margin-bottom: 0;
35
- }
36
-
37
- @media (min-width: 960px) {
38
- .wpzerospam-callout {
39
- flex-wrap: nowrap;
40
- }
41
-
42
- .wpzerospam-callout-actions {
43
- display: flex;
44
- flex-wrap: wrap;
45
- margin-left: 50px;
46
- width: auto;
47
- }
48
- }
49
-
50
  .wpzerospam-blocked-ip-option {
51
  margin-bottom: 0.3rem;
52
  }
@@ -105,6 +56,40 @@
105
  padding: 12px;
106
  }
107
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  @media (min-width: 768px) {
109
  .wpzerospam-box {
110
  width: calc(100% / 3 - 18px);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  .wpzerospam-blocked-ip-option {
2
  margin-bottom: 0.3rem;
3
  }
56
  padding: 12px;
57
  }
58
 
59
+ .wpzerospam-list {
60
+ margin: 0;
61
+ padding: 0;
62
+ list-style: none;
63
+ }
64
+
65
+ .wpzerospam-list li {
66
+ display: flex;
67
+ }
68
+
69
+ .wpzerospam-list-cell,
70
+ .wpzerospam-list .wpzerospam-country-flag {
71
+ flex-shrink: 0;
72
+ }
73
+
74
+ .wpzerospam-list .wpzerospam-country-flag {
75
+ margin-right: 8px;
76
+ width: 16px;
77
+ }
78
+
79
+ .wpzerospam-list-cell {
80
+ width: 130px;
81
+ }
82
+
83
+ .wpzerospam-list-cell-small {
84
+ text-align: right;
85
+ width: 30px;
86
+ }
87
+
88
+ .wpzerospam-action {
89
+ flex-grow: 1;
90
+ text-align: right;
91
+ }
92
+
93
  @media (min-width: 768px) {
94
  .wpzerospam-box {
95
  width: calc(100% / 3 - 18px);
assets/css/admin.css ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .wpzerospam-callout {
2
+ align-items: center;
3
+ background: #fff;
4
+ border: 1px solid #ccd0d4;
5
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
6
+ display: flex;
7
+ flex-wrap: wrap;
8
+ padding: 20px;
9
+ }
10
+
11
+ .wpzerospam-callout h2 {
12
+ font-size: 18px;
13
+ margin-bottom: 10px;
14
+ }
15
+
16
+ .wpzerospam-callout p {
17
+ font-size: 14px;
18
+ margin-top: 0;
19
+ }
20
+
21
+ .wpzerospam-callout-actions {
22
+ display: block;
23
+ width: 100%;
24
+ }
25
+
26
+ .wpzerospam-callout-actions a.button {
27
+ display: block;
28
+ margin-bottom: 3px;
29
+ text-align: center;
30
+ width: 100%;
31
+ }
32
+
33
+ .wpzerospam-callout-actions a:last-child {
34
+ margin-bottom: 0;
35
+ }
36
+
37
+ @media (min-width: 960px) {
38
+ .wpzerospam-callout {
39
+ flex-wrap: nowrap;
40
+ }
41
+
42
+ .wpzerospam-callout-actions {
43
+ display: flex;
44
+ flex-wrap: wrap;
45
+ margin-left: 50px;
46
+ width: auto;
47
+ }
48
+ }
49
+
50
+ .wpzerospam-country-flag {
51
+ vertical-align: text-bottom;
52
+ }
53
+
54
+ .wpzerospam-blocked {
55
+ color: #ca4a1f;
56
+ }
57
+
58
+ .wpzerospam-blocked::before {
59
+ background-image: url('../img/icon.svg');
60
+ background-position: center;
61
+ background-repeat: no-repeat;
62
+ background-size: contain;
63
+ content: '';
64
+ display: inline-block;
65
+ height: 16px;
66
+ margin-right: 3px;
67
+ vertical-align: top;
68
+ width: 16px;
69
+ }
assets/img/icon.svg ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="512px" height="478px" viewBox="0 0 512 478" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+ <!-- Generator: Sketch 58 (84663) - https://sketch.com -->
4
+ <title>under-construction</title>
5
+ <desc>Created with Sketch.</desc>
6
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7
+ <g id="under-construction" transform="translate(256.000000, 239.000000) scale(-1, 1) translate(-256.000000, -239.000000) " fill-rule="nonzero">
8
+ <path d="M241,0 L96,0 C87.716,0 81,6.716 81,15 L81,127 C81,135.284 87.716,142 96,142 L241,142 C249.284,142 256,135.284 256,127 L256,15 C256,6.716 249.284,0 241,0 Z" id="Path" fill="#BE0000"></path>
9
+ <path d="M176,112 L15,112 C6.716,112 0,118.716 0,127 L0,239 C0,247.284 6.716,254 15,254 L176,254 C184.284,254 191,247.284 191,239 L191,127 C191,118.716 184.284,112 176,112 Z" id="Path" fill="#FF7038"></path>
10
+ <path d="M351,127 L351,239 C351,247.28 344.28,254 336,254 L176,254 L176,112 L336,112 C344.28,112 351,118.72 351,127 Z" id="Path" fill="#FF2929"></path>
11
+ <path d="M351,127 L351,239 C351,247.28 344.28,254 336,254 L256,254 L256,112 L336,112 C344.28,112 351,118.72 351,127 Z" id="Path" fill="#BE0000"></path>
12
+ <path d="M512,127 L512,239 C512,247.28 505.28,254 497,254 L336,254 L336,112 L497,112 C505.28,112 512,118.72 512,127 Z" id="Path" fill="#63000D"></path>
13
+ <path d="M111,239 L111,351 C111,359.28 104.28,366 96,366 L15,366 C6.72,366 0,359.28 0,351 L0,239 L111,239 Z" id="Path" fill="#FF2929"></path>
14
+ <path d="M271,239 L271,351 C271,359.28 264.28,366 256,366 L96,366 L96,239 L271,239 Z" id="Path" fill="#BE0000"></path>
15
+ <path d="M431,239 L431,351 C431,359.28 424.28,366 416,366 L256,366 L256,239 L431,239 Z" id="Path" fill="#840012"></path>
16
+ <path d="M512,239 L512,351 C512,359.28 505.28,366 497,366 L416,366 L416,239 L512,239 Z" id="Path" fill="#BE0000"></path>
17
+ <path d="M191,351 L191,463 C191,471.28 184.28,478 176,478 L15,478 C6.72,478 0,471.28 0,463 L0,351 L191,351 Z" id="Path" fill="#FFA17C"></path>
18
+ <path d="M351,351 L351,463 C351,471.28 344.28,478 336,478 L176,478 L176,351 L351,351 Z" id="Path" fill="#FF2929"></path>
19
+ <path d="M351,351 L351,463 C351,471.28 344.28,478 336,478 L256,478 L256,351 L351,351 Z" id="Path" fill="#BE0000"></path>
20
+ <path d="M512,351 L512,463 C512,471.28 505.28,478 497,478 L336,478 L336,351 L512,351 Z" id="Path" fill="#63000D"></path>
21
+ </g>
22
+ </g>
23
+ </svg>
classes/class-wpzerospam-log-table.php CHANGED
@@ -56,6 +56,32 @@ class WPZeroSpam_Log_Table extends WP_List_Table {
56
  return $sortable_columns;
57
  }
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  // Checkbox column
60
  function column_cb( $item ){
61
  return sprintf(
@@ -69,13 +95,18 @@ class WPZeroSpam_Log_Table extends WP_List_Table {
69
  function column_default( $item, $column_name ) {
70
  switch( $column_name ) {
71
  case 'actions':
72
- return '<a href="' . admin_url( 'admin.php?page=wordpress-zero-spam-blocked-ips&ip=' . $item->user_ip ) . '" class="button">' . __( 'Configure IP Block', 'wpzerospam' ) . '</a>';
 
 
 
 
 
73
  break;
74
  case 'log_id':
75
  return $item->log_id;
76
  break;
77
  case 'log_type':
78
- return $item->log_type;
79
  break;
80
  case 'user_ip':
81
  return '<a href="https://whatismyipaddress.com/ip/' . $item->user_ip .'" target="_blank" rel="noopener noreferrer">' . $item->user_ip . '</a>';
@@ -87,7 +118,8 @@ class WPZeroSpam_Log_Table extends WP_List_Table {
87
  if ( ! $item->country ) {
88
  return 'N/A';
89
  }
90
- return wpzerospam_get_location( $item->country );
 
91
  break;
92
  case 'region':
93
  $region = wpzerospam_get_location( $item->country, $item->region );
@@ -132,7 +164,7 @@ class WPZeroSpam_Log_Table extends WP_List_Table {
132
 
133
  echo '<div class="wpzerospam-details-item">';
134
  echo '<div class="wpzerospam-details-label">' . __( 'Type', 'wpzerospam' ) . '</div>';
135
- echo '<div class="wpzerospam-details-data">' . $item->log_type . '</div>';
136
  echo '</div>';
137
 
138
  if ( $item->country ) {
@@ -393,19 +425,36 @@ class WPZeroSpam_Log_Table extends WP_List_Table {
393
  $hidden = $this->get_hidden_columns();
394
  $sortable = $this->get_sortable_columns();
395
 
396
- $data = wpzerospam_get_log();
397
- usort( $data, [ &$this, 'sort_data' ] );
398
-
399
  $per_page = 50;
400
  $current_page = $this->get_pagenum();
401
- $total_items = count( $data );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
 
403
  $this->set_pagination_args([
404
  'total_items' => $total_items,
405
- 'per_page' => $per_page
 
 
 
406
  ]);
407
 
408
- $data = array_slice ( $data, ( ( $current_page - 1 ) * $per_page ), $per_page );
409
 
410
  $this->_column_headers = [ $columns, $hidden, $sortable ];
411
  $this->items = $data;
56
  return $sortable_columns;
57
  }
58
 
59
+ function extra_tablenav( $which ) {
60
+ global $cat_id;
61
+
62
+ if ( 'top' !== $which ) {
63
+ return;
64
+ }
65
+ ?>
66
+ <div class="alignleft actions">
67
+ <?php
68
+ echo '<label class="screen-reader-text" for="filter-by-type">' . __( 'Filter by type' ) . '</label>';
69
+ $options = wpzerospam_types();
70
+ $current_type = ! empty( $_POST['type'] ) ? sanitize_text_field( $_POST['type'] ) : false;
71
+ ?>
72
+ <select name="type" id="filter-by-type">
73
+ <option value=""><?php _e( 'All types', 'wpzerospam' ); ?></option>
74
+ <?php foreach( $options as $key => $value ): ?>
75
+ <option<?php if ( $current_type == $key ): ?> selected="selected" <?php endif; ?> value="<?php echo $key; ?>"><?php echo $value; ?></option>
76
+ <?php endforeach; ?>
77
+ </select>
78
+ <?php
79
+ submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
80
+ ?>
81
+ </div>
82
+ <?php
83
+ }
84
+
85
  // Checkbox column
86
  function column_cb( $item ){
87
  return sprintf(
95
  function column_default( $item, $column_name ) {
96
  switch( $column_name ) {
97
  case 'actions':
98
+ $blocked_status = wpzerospam_get_blocked_ips( $item->user_ip );
99
+ if ( $blocked_status && wpzerospam_is_blocked( $blocked_status ) ) {
100
+ return '<span class="wpzerospam-blocked">' . __( 'Blocked', 'wpzerospam' ) . '</span>';
101
+ } else {
102
+ return '<a class="button" href="' . admin_url( 'admin.php?page=wordpress-zero-spam-blocked-ips&ip=' . $item->user_ip ) . '">' . __( 'Configure IP Block', 'wpzerospam' ) . '</a>';
103
+ }
104
  break;
105
  case 'log_id':
106
  return $item->log_id;
107
  break;
108
  case 'log_type':
109
+ return '<span class="wpzerospam-' . $item->log_type . '">' . wpzerospam_types( $item->log_type ) . '</span>';
110
  break;
111
  case 'user_ip':
112
  return '<a href="https://whatismyipaddress.com/ip/' . $item->user_ip .'" target="_blank" rel="noopener noreferrer">' . $item->user_ip . '</a>';
118
  if ( ! $item->country ) {
119
  return 'N/A';
120
  }
121
+
122
+ return '<img class="wpzerospam-country-flag" width="16" src="https://hatscripts.github.io/circle-flags/flags/' . strtolower( $item->country ) . '.svg" alt="' . wpzerospam_get_location( $item->country ) .'" /> ' . wpzerospam_get_location( $item->country );
123
  break;
124
  case 'region':
125
  $region = wpzerospam_get_location( $item->country, $item->region );
164
 
165
  echo '<div class="wpzerospam-details-item">';
166
  echo '<div class="wpzerospam-details-label">' . __( 'Type', 'wpzerospam' ) . '</div>';
167
+ echo '<div class="wpzerospam-details-data">' . wpzerospam_types( $item->log_type ) . '</div>';
168
  echo '</div>';
169
 
170
  if ( $item->country ) {
425
  $hidden = $this->get_hidden_columns();
426
  $sortable = $this->get_sortable_columns();
427
 
 
 
 
428
  $per_page = 50;
429
  $current_page = $this->get_pagenum();
430
+ $offset = $per_page * ( $current_page - 1 );
431
+ $order = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( $_REQUEST['order'] ) : 'desc';
432
+ $orderby = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( $_REQUEST['orderby'] ) : 'date_recorded';
433
+
434
+ $type = ! empty( $_POST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
435
+
436
+ $data = wpzerospam_get_log([
437
+ 'limit' => $per_page,
438
+ 'offset' => $offset,
439
+ 'order' => $order,
440
+ 'orderby' => $orderby,
441
+ 'type' => $type
442
+ ]);
443
+ if ( ! $data ) { return false; }
444
+
445
+ usort( $data, [ &$this, 'sort_data' ] );
446
+
447
+ $total_items = wpzerospam_get_log( 'total' );
448
 
449
  $this->set_pagination_args([
450
  'total_items' => $total_items,
451
+ 'per_page' => $per_page,
452
+ 'total_pages' => ceil( $total_items / $per_page ),
453
+ 'orderby' => $orderby,
454
+ 'order' => $order
455
  ]);
456
 
457
+ //$data = array_slice ( $data, ( ( $current_page - 1 ) * $per_page ), $per_page );
458
 
459
  $this->_column_headers = [ $columns, $hidden, $sortable ];
460
  $this->items = $data;
inc/admin.php CHANGED
@@ -13,7 +13,25 @@ function wpzerospam_admin_menu() {
13
  'manage_options',
14
  'wordpress-zero-spam',
15
  'wpzerospam_dashboard',
16
- 'dashicons-shield'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  );
18
 
19
  add_submenu_page(
@@ -45,11 +63,52 @@ function wpzerospam_admin_menu() {
45
  }
46
  add_action( 'admin_menu', 'wpzerospam_admin_menu' );
47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  function wpzerospam_blacklist_page() {
49
  if ( ! current_user_can( 'manage_options' ) ) { return; }
50
  ?>
51
  <div class="wrap">
52
  <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
 
 
 
53
  <?php
54
  /**
55
  * Blocked IP table
@@ -80,7 +139,6 @@ function wpzerospam_blacklist_page() {
80
  <?php
81
  }
82
 
83
- add_action( 'admin_action_add_blocked_ip', 'wpzerospam_add_blocked_ip_action' );
84
  function wpzerospam_add_blocked_ip_action() {
85
  if ( ! empty( $_POST ) ) {
86
  $ip = sanitize_text_field( $_POST['blocked_ip'] );
@@ -132,12 +190,16 @@ function wpzerospam_add_blocked_ip_action() {
132
  wp_redirect( $_SERVER['HTTP_REFERER'] . '&success=1' );
133
  exit();
134
  }
 
135
 
136
  function wpzerospam_blocked_ips_page() {
137
  if ( ! current_user_can( 'manage_options' ) ) { return; }
138
  ?>
139
  <div class="wrap">
140
  <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
 
 
 
141
  <?php if ( ! empty( $_GET['error'] ) ): ?>
142
  <div class="notice notice-error is-dismissible">
143
  <p><strong>
@@ -165,7 +227,7 @@ function wpzerospam_blocked_ips_page() {
165
  <?php endif; ?>
166
  <form method="post" action="<?php echo admin_url( 'admin.php' ); ?>">
167
  <input type="hidden" name="action" value="add_blocked_ip" />
168
- <div class="wpzerospam-add-ip-container<?php if( ! empty( $_REQUEST['ip'] ) ): ?> wpzerospam-add-ip-container-highlight<?php endif; ?>">
169
  <h2><?php _e( 'Add Blocked IP', 'wpzerospam' ); ?></h2>
170
  <div class="wpzerospam-add-ip-field">
171
  <label for="blocked-ip"><?php _e( 'IP Address', 'wpzerospam' ); ?></label>
@@ -202,7 +264,6 @@ function wpzerospam_blocked_ips_page() {
202
  </div>
203
  </form>
204
 
205
-
206
  <?php
207
  /**
208
  * Blocked IP table
@@ -245,17 +306,7 @@ function wpzerospam_dashboard() {
245
  <div class="wrap">
246
  <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
247
 
248
- <div class="wpzerospam-callout">
249
- <div class="wpzerospam-callout-content">
250
- <h2><?php _e( 'Are you a fan of the <a href="https://benmarshall.me/wordpress-zero-spam/?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=admin" target="_blank">WordPress Zero Spam</a> plugin? Show your support.', 'wpzerospam' ); ?></h2>
251
- <p><?php _e( 'Help support the continued development of the WordPress Zero Spam plugin by <a href="https://benmarshall.me/donate?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=admin" target="_blank">donating today</a>. Your donation goes towards the time it takes to develop new features &amp; updates, but also helps provide pro bono work for nonprofits. <a href="https://benmarshall.me/donate?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=admin" target="_blank">Learn more</a>.', 'wpzerospam' ); ?></p>
252
- </div>
253
- <div class="wpzerospam-callout-actions">
254
- <a href="https://github.com/bmarshall511/wordpress-zero-spam/issues" class="button" target="_blank"><?php _e( 'Submit Bug/Feature Request' ); ?></a>
255
- <a href="https://github.com/bmarshall511/wordpress-zero-spam" class="button" target="_blank"><?php _e( 'Fork on Github' ); ?></a>
256
- <a href="https://benmarshall.me/donate?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=admin" class="button button-primary" target="_blank"><?php _e( 'Show your Support &mdash; Donate' ); ?></a>
257
- </div>
258
- </div>
259
 
260
  <h2><?php _e( 'Statistics', 'wpzerospam' ); ?></h2>
261
  <div class="wpzerospam-boxes">
@@ -264,34 +315,6 @@ function wpzerospam_dashboard() {
264
  <?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . '/templates/countries-pie-chart.php'; ?>
265
  <?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . '/templates/regions-pie-chart.php'; ?>
266
  </div>
267
-
268
- <h2><?php _e( 'Spam Detections Log', 'wpzerospam' ); ?></h2>
269
- <?php
270
- /**
271
- * Log table
272
- */
273
- require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . '/classes/class-wpzerospam-log-table.php';
274
-
275
- $table_data = new WPZeroSpam_Log_Table();
276
-
277
- // Setup page parameters
278
- $current_page = $table_data->get_pagenum();
279
- $current_page = (isset($current_page)) ? $current_page : 1;
280
- $paged = ( isset( $_GET['page'] ) ) ? absint( $_GET['page'] ) : $current_page;
281
- $paged = ( isset( $_GET['paged'] ) ) ? absint( $_GET['paged'] ) : $current_page;
282
- $paged = ( isset( $args['paged'] ) ) ? $args['paged'] : $paged;
283
-
284
- // Fetch, prepare, sort, and filter our data...
285
- $table_data->prepare_items();
286
- ?>
287
- <form id="log-table" method="post">
288
- <?php wp_nonce_field( 'wpzerospam_nonce', 'wpzerospam_nonce' ); ?>
289
-
290
- <?php # Current page ?>
291
- <input type="hidden" name="paged" value="<?php echo $paged; ?>" />
292
-
293
- <?php $table_data->display(); ?>
294
- </form>
295
  </div>
296
  <?php
297
  }
@@ -301,6 +324,9 @@ function wpzerospam_options_page() {
301
  ?>
302
  <div class="wrap">
303
  <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
 
 
 
304
  <form action="options.php" method="post">
305
  <?php
306
  // Output security fields for the registered setting "wpzerospam"
@@ -325,6 +351,7 @@ function wpzerospam_validate_options( $input ) {
325
  if ( empty( $input['auto_block_ips'] ) ) { $input['auto_block_ips'] = 'disabled'; }
326
  if ( empty( $input['auto_block_period'] ) ) { $input['auto_block_period'] = 0; }
327
  if ( empty( $input['botscout_api'] ) ) { $input['botscout'] = false; }
 
328
 
329
  if ( empty( $input['verify_cf7'] ) ) {
330
  $input['verify_cf7'] = 'disabled';
@@ -358,6 +385,10 @@ function wpzerospam_validate_options( $input ) {
358
  $input['strip_comment_links'] = 'disabled';
359
  }
360
 
 
 
 
 
361
  if ( empty( $input['strip_comment_author_links'] ) ) {
362
  $input['strip_comment_author_links'] = 'disabled';
363
  }
@@ -367,7 +398,7 @@ function wpzerospam_validate_options( $input ) {
367
  }
368
 
369
  return $input;
370
- }
371
 
372
  /**
373
  * Add settings link to plugin description
@@ -394,9 +425,53 @@ function wpzerospam_admin_init() {
394
  register_setting( 'wpzerospam', 'wpzerospam', 'wpzerospam_validate_options' );
395
 
396
  add_settings_section( 'wpzerospam_general_settings', __( 'General Settings', 'wpzerospam' ), 'wpzerospam_general_settings_cb', 'wpzerospam' );
 
397
  add_settings_section( 'wpzerospam_onsite', __( 'On-site Spam Prevention', 'wpzerospam' ), 'wpzerospam_onsite_cb', 'wpzerospam' );
398
  add_settings_section( 'wpzerospam_spam_checks', __( 'Integrations & Third-party APIs', 'wpzerospam' ), 'wpzerospam_spam_checks_cb', 'wpzerospam' );
399
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
400
  // Option to strips links in comments
401
  add_settings_field( 'strip_comment_links', __( 'Strip Comment Links', 'wpzerospam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_onsite', [
402
  'label_for' => 'strip_comment_links',
@@ -450,29 +525,6 @@ function wpzerospam_admin_init() {
450
  ]
451
  ]);
452
 
453
- // Determines is spam detected IPs should automatically be blocked
454
- add_settings_field( 'auto_block_ips', __( 'Auto-block IPs', 'wpzerospam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
455
- 'label_for' => 'auto_block_ips',
456
- 'type' => 'checkbox',
457
- 'multi' => false,
458
- 'desc' => 'Auto-blocks IPs addresses that trigger a spam detection.',
459
- 'options' => [
460
- 'enabled' => __( 'Enabled', 'wpzerospam' )
461
- ]
462
- ]);
463
-
464
- if ( 'enabled' == $options['auto_block_ips'] ) {
465
- // Number of minutes a IP should be blocked after a auto-block
466
- add_settings_field( 'auto_block_period', __( 'Auto-block Period', 'wpzerospam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
467
- 'label_for' => 'auto_block_period',
468
- 'type' => 'number',
469
- 'desc' => 'Number of minutes a user will be blocked from viewing the site after being auto-blocked.',
470
- 'class' => 'small-text',
471
- 'placeholder' => '30',
472
- 'suffix' => __( 'minutes', 'wpzerospam' )
473
- ]);
474
- }
475
-
476
  // How to handle blocks
477
  add_settings_field( 'block_handler', __( 'Blocked IPs', 'wpzerospam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
478
  'label_for' => 'block_handler',
@@ -662,6 +714,9 @@ add_action( 'admin_init', 'wpzerospam_admin_init' );
662
  function wpzerospam_general_settings_cb() {
663
  }
664
 
 
 
 
665
  function wpzerospam_spam_checks_cb() {
666
  }
667
 
13
  'manage_options',
14
  'wordpress-zero-spam',
15
  'wpzerospam_dashboard',
16
+ 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNTEycHgiIGhlaWdodD0iNDc4cHgiIHZpZXdCb3g9IjAgMCA1MTIgNDc4IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPCEtLSBHZW5lcmF0b3I6IFNrZXRjaCA1OCAoODQ2NjMpIC0gaHR0cHM6Ly9za2V0Y2guY29tIC0tPgogICAgPHRpdGxlPlJlY3RhbmdsZTwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxwYXRoIGQ9Ik0xNSwxMTIgTDI1Ni4yMjAwNTIsMTEyIEwyNTYuMjIwMDUyLDExMiBMMjU2LjIyMDA1MiwxNSBDMjU2LjIyMDA1Miw2LjcxNTcyODc1IDI2Mi45MzU3ODEsLTUuNTgzNjMxNDJlLTE1IDI3MS4yMjAwNTIsMCBMNDE2LDAgQzQyNC4yODQyNzEsLTMuMDk1MzQzOTdlLTE0IDQzMSw2LjcxNTcyODc1IDQzMSwxNSBMNDMxLDExMiBMNDMxLDExMiBMNDk3LDExMiBDNTA1LjI4NDI3MSwxMTIgNTEyLDExOC43MTU3MjkgNTEyLDEyNyBMNTEyLDQ2MyBDNTEyLDQ3MS4yODQyNzEgNTA1LjI4NDI3MSw0NzggNDk3LDQ3OCBMMTUsNDc4IEM2LjcxNTcyODc1LDQ3OCAxLjAxNDUzMDYzZS0xNSw0NzEuMjg0MjcxIDAsNDYzIEwwLDEyNyBDNi4zNDMzODAzMmUtMTUsMTE4LjcxNTcyOSA2LjcxNTcyODc1LDExMiAxNSwxMTIgWiIgaWQ9IlJlY3RhbmdsZSIgZmlsbD0iIzYzMDAwRCI+PC9wYXRoPgogICAgPC9nPgo8L3N2Zz4='
17
+ );
18
+
19
+ add_submenu_page(
20
+ 'wordpress-zero-spam',
21
+ __( 'WordPress Zero Spam Dashboard', 'wpzerospam' ),
22
+ __( 'Dashboard', 'wpzerospam' ),
23
+ 'manage_options',
24
+ 'wordpress-zero-spam',
25
+ 'wpzerospam_dashboard'
26
+ );
27
+
28
+ add_submenu_page(
29
+ 'wordpress-zero-spam',
30
+ __( 'Spam Detections', 'wpzerospam' ),
31
+ __( 'Spam Detections', 'wpzerospam' ),
32
+ 'manage_options',
33
+ 'wordpress-zero-spam-detections',
34
+ 'wpzerospam_spam_detections_page'
35
  );
36
 
37
  add_submenu_page(
63
  }
64
  add_action( 'admin_menu', 'wpzerospam_admin_menu' );
65
 
66
+ function wpzerospam_spam_detections_page() {
67
+ if ( ! current_user_can( 'manage_options' ) ) { return; }
68
+ ?>
69
+ <div class="wrap">
70
+ <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
71
+
72
+ <?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . '/inc/callout.php'; ?>
73
+
74
+ <?php
75
+ /**
76
+ * Log table
77
+ */
78
+ require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . '/classes/class-wpzerospam-log-table.php';
79
+
80
+ $table_data = new WPZeroSpam_Log_Table();
81
+
82
+ // Setup page parameters
83
+ $current_page = $table_data->get_pagenum();
84
+ $current_page = (isset($current_page)) ? $current_page : 1;
85
+ $paged = ( isset( $_GET['page'] ) ) ? absint( $_GET['page'] ) : $current_page;
86
+ $paged = ( isset( $_GET['paged'] ) ) ? absint( $_GET['paged'] ) : $current_page;
87
+ $paged = ( isset( $args['paged'] ) ) ? $args['paged'] : $paged;
88
+
89
+ // Fetch, prepare, sort, and filter our data...
90
+ $table_data->prepare_items();
91
+ ?>
92
+ <form id="log-table" method="post">
93
+ <?php wp_nonce_field( 'wpzerospam_nonce', 'wpzerospam_nonce' ); ?>
94
+
95
+ <?php # Current page ?>
96
+ <input type="hidden" name="paged" value="<?php echo $paged; ?>" />
97
+
98
+ <?php $table_data->display(); ?>
99
+ </form>
100
+ </div>
101
+ <?php
102
+ }
103
+
104
  function wpzerospam_blacklist_page() {
105
  if ( ! current_user_can( 'manage_options' ) ) { return; }
106
  ?>
107
  <div class="wrap">
108
  <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
109
+
110
+ <?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . '/inc/callout.php'; ?>
111
+
112
  <?php
113
  /**
114
  * Blocked IP table
139
  <?php
140
  }
141
 
 
142
  function wpzerospam_add_blocked_ip_action() {
143
  if ( ! empty( $_POST ) ) {
144
  $ip = sanitize_text_field( $_POST['blocked_ip'] );
190
  wp_redirect( $_SERVER['HTTP_REFERER'] . '&success=1' );
191
  exit();
192
  }
193
+ add_action( 'admin_action_add_blocked_ip', 'wpzerospam_add_blocked_ip_action' );
194
 
195
  function wpzerospam_blocked_ips_page() {
196
  if ( ! current_user_can( 'manage_options' ) ) { return; }
197
  ?>
198
  <div class="wrap">
199
  <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
200
+
201
+ <?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . '/inc/callout.php'; ?>
202
+
203
  <?php if ( ! empty( $_GET['error'] ) ): ?>
204
  <div class="notice notice-error is-dismissible">
205
  <p><strong>
227
  <?php endif; ?>
228
  <form method="post" action="<?php echo admin_url( 'admin.php' ); ?>">
229
  <input type="hidden" name="action" value="add_blocked_ip" />
230
+ <div class="wpzerospam-callout wpzerospam-add-ip-container<?php if( ! empty( $_REQUEST['ip'] ) ): ?> wpzerospam-add-ip-container-highlight<?php endif; ?>">
231
  <h2><?php _e( 'Add Blocked IP', 'wpzerospam' ); ?></h2>
232
  <div class="wpzerospam-add-ip-field">
233
  <label for="blocked-ip"><?php _e( 'IP Address', 'wpzerospam' ); ?></label>
264
  </div>
265
  </form>
266
 
 
267
  <?php
268
  /**
269
  * Blocked IP table
306
  <div class="wrap">
307
  <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
308
 
309
+ <?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . '/inc/callout.php'; ?>
 
 
 
 
 
 
 
 
 
 
310
 
311
  <h2><?php _e( 'Statistics', 'wpzerospam' ); ?></h2>
312
  <div class="wpzerospam-boxes">
315
  <?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . '/templates/countries-pie-chart.php'; ?>
316
  <?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . '/templates/regions-pie-chart.php'; ?>
317
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
  </div>
319
  <?php
320
  }
324
  ?>
325
  <div class="wrap">
326
  <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
327
+
328
+ <?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . '/inc/callout.php'; ?>
329
+
330
  <form action="options.php" method="post">
331
  <?php
332
  // Output security fields for the registered setting "wpzerospam"
351
  if ( empty( $input['auto_block_ips'] ) ) { $input['auto_block_ips'] = 'disabled'; }
352
  if ( empty( $input['auto_block_period'] ) ) { $input['auto_block_period'] = 0; }
353
  if ( empty( $input['botscout_api'] ) ) { $input['botscout'] = false; }
354
+ if ( empty( $input['auto_block_permanently'] ) ) { $input['auto_block_permanently'] = 3; }
355
 
356
  if ( empty( $input['verify_cf7'] ) ) {
357
  $input['verify_cf7'] = 'disabled';
385
  $input['strip_comment_links'] = 'disabled';
386
  }
387
 
388
+ if ( empty( $input['share_detections'] ) ) {
389
+ $input['share_detections'] = 'disabled';
390
+ }
391
+
392
  if ( empty( $input['strip_comment_author_links'] ) ) {
393
  $input['strip_comment_author_links'] = 'disabled';
394
  }
398
  }
399
 
400
  return $input;
401
+ }
402
 
403
  /**
404
  * Add settings link to plugin description
425
  register_setting( 'wpzerospam', 'wpzerospam', 'wpzerospam_validate_options' );
426
 
427
  add_settings_section( 'wpzerospam_general_settings', __( 'General Settings', 'wpzerospam' ), 'wpzerospam_general_settings_cb', 'wpzerospam' );
428
+ add_settings_section( 'wpzerospam_autoblocks', __( 'Auto-block Settings', 'wpzerospam' ), 'wpzerospam_autoblock_settings_cb', 'wpzerospam' );
429
  add_settings_section( 'wpzerospam_onsite', __( 'On-site Spam Prevention', 'wpzerospam' ), 'wpzerospam_onsite_cb', 'wpzerospam' );
430
  add_settings_section( 'wpzerospam_spam_checks', __( 'Integrations & Third-party APIs', 'wpzerospam' ), 'wpzerospam_spam_checks_cb', 'wpzerospam' );
431
 
432
+ // Determines is spam detections should be shared with WordPress Zero Spam
433
+ add_settings_field( 'share_detections', __( 'Share Spam Detections', 'wpzerospam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
434
+ 'label_for' => 'share_detections',
435
+ 'type' => 'checkbox',
436
+ 'multi' => false,
437
+ 'desc' => 'Help support WordPress Zero Spam and strenghten its ability to detect spammers by sharing spam detections. The only data that\'s shared is the IP address, type & site where the spam was detected. <strong>Absolutely no personal data is shared.</strong>',
438
+ 'options' => [
439
+ 'enabled' => __( 'Enabled', 'wpzerospam' )
440
+ ]
441
+ ]);
442
+
443
+ // Determines is spam detected IPs should automatically be blocked
444
+ add_settings_field( 'auto_block_ips', __( 'Auto-block IPs', 'wpzerospam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_autoblocks', [
445
+ 'label_for' => 'auto_block_ips',
446
+ 'type' => 'checkbox',
447
+ 'multi' => false,
448
+ 'desc' => 'Auto-blocks IPs addresses that trigger a spam detection.',
449
+ 'options' => [
450
+ 'enabled' => __( 'Enabled', 'wpzerospam' )
451
+ ]
452
+ ]);
453
+
454
+ if ( 'enabled' == $options['auto_block_ips'] ) {
455
+ // Number of minutes a IP should be blocked after a auto-block
456
+ add_settings_field( 'auto_block_period', __( 'Auto-block Period', 'wpzerospam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_autoblocks', [
457
+ 'label_for' => 'auto_block_period',
458
+ 'type' => 'number',
459
+ 'desc' => 'Number of minutes a user will be blocked from viewing the site after being auto-blocked.',
460
+ 'class' => 'small-text',
461
+ 'placeholder' => '30',
462
+ 'suffix' => __( 'minutes', 'wpzerospam' )
463
+ ]);
464
+ }
465
+
466
+ // Number of spam attempts before the IP is permanently blocked
467
+ add_settings_field( 'auto_block_permanently', __( 'Permanently Auto-block', 'wpzerospam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_autoblocks', [
468
+ 'label_for' => 'auto_block_permanently',
469
+ 'type' => 'number',
470
+ 'desc' => 'Number of spam detections before an IP is permanently blocked.',
471
+ 'class' => 'small-text',
472
+ 'placeholder' => 3
473
+ ]);
474
+
475
  // Option to strips links in comments
476
  add_settings_field( 'strip_comment_links', __( 'Strip Comment Links', 'wpzerospam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_onsite', [
477
  'label_for' => 'strip_comment_links',
525
  ]
526
  ]);
527
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
528
  // How to handle blocks
529
  add_settings_field( 'block_handler', __( 'Blocked IPs', 'wpzerospam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
530
  'label_for' => 'block_handler',
714
  function wpzerospam_general_settings_cb() {
715
  }
716
 
717
+ function wpzerospam_autoblock_settings_cb() {
718
+ }
719
+
720
  function wpzerospam_spam_checks_cb() {
721
  }
722
 
inc/callout.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Plugin callout
4
+ *
5
+ * @package WordPressZeroSpam
6
+ * @since 4.6.0
7
+ */
8
+ ?>
9
+
10
+ <div class="wpzerospam-callout">
11
+ <div class="wpzerospam-callout-content">
12
+ <h2><?php _e( 'Are you a fan of the <a href="https://benmarshall.me/wordpress-zero-spam/?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=admin" target="_blank">WordPress Zero Spam</a> plugin? Show your support.', 'wpzerospam' ); ?></h2>
13
+ <p><?php _e( 'Help support the continued development of the WordPress Zero Spam plugin by <a href="https://benmarshall.me/donate?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=admin" target="_blank">donating today</a>. Your donation goes towards the time it takes to develop new features &amp; updates, but also helps provide pro bono work for nonprofits. <a href="https://benmarshall.me/donate?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=admin" target="_blank">Learn more</a>.', 'wpzerospam' ); ?></p>
14
+ </div>
15
+ <div class="wpzerospam-callout-actions">
16
+ <a href="https://github.com/bmarshall511/wordpress-zero-spam/issues" class="button" target="_blank"><?php _e( 'Submit Bug/Feature Request' ); ?></a>
17
+ <a href="https://github.com/bmarshall511/wordpress-zero-spam" class="button" target="_blank"><?php _e( 'Fork on Github' ); ?></a>
18
+ <a href="https://benmarshall.me/donate?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=admin" class="button button-primary" target="_blank"><?php _e( 'Show your Support &mdash; Donate' ); ?></a>
19
+ </div>
20
+ </div>
inc/helpers.php CHANGED
@@ -48,13 +48,59 @@ if ( ! function_exists( 'wpzerospam_get_ip_info' ) ) {
48
  }
49
 
50
  /**
51
- * Handles what happens when spam is detected
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  */
53
  if ( ! function_exists( 'wpzerospam_get_log' ) ) {
54
- function wpzerospam_get_log( $args = [] ) {
55
  global $wpdb;
56
 
57
- return $wpdb->get_results( 'SELECT * FROM ' . wpzerospam_tables( 'log' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  }
59
  }
60
 
@@ -64,17 +110,28 @@ if ( ! function_exists( 'wpzerospam_get_log' ) ) {
64
  if ( ! function_exists( 'wpzerospam_spam_detected' ) ) {
65
  function wpzerospam_spam_detected( $type, $data = [], $handle_error = true ) {
66
  $options = wpzerospam_options();
 
67
 
 
68
  wpzerospam_log_spam( $type, $data );
69
 
70
- // Check if the IP should be auto-blocked
71
- if ( 'enabled' == $options['auto_block_ips'] ) {
 
 
 
 
 
 
 
 
 
72
 
73
  $start_block = current_time( 'mysql' );
74
  $end_block = new DateTime( $start_block );
75
  $end_block->add( new DateInterval( 'PT' . $options['auto_block_period'] . 'M' ) );
76
 
77
- wpzerospam_update_blocked_ip( wpzerospam_ip(), [
78
  'blocked_type' => 'temporary',
79
  'start_block' => $start_block,
80
  'end_block' => $end_block->format('Y-m-d G:i:s'),
@@ -183,16 +240,6 @@ if ( ! function_exists( 'wpzerospam_log_spam' ) ) {
183
 
184
  $options = wpzerospam_options();
185
 
186
- // Check if spam logging is enabled, also check if type is 'denied'
187
- // (blocked IP address) & logging of blocked IPs is enabled.
188
- if (
189
- 'enabled' != $options['log_spam'] ||
190
- ( 'denied' == $type && 'enabled' != $options['log_blocked_ips'] )
191
- ) {
192
- // Logging disabled
193
- return false;
194
- }
195
-
196
  if ( ! empty( $data['ip'] ) ) {
197
  $ip_address = $data['ip'];
198
  unset( $data['ip'] );
@@ -200,6 +247,23 @@ if ( ! function_exists( 'wpzerospam_log_spam' ) ) {
200
  $ip_address = wpzerospam_ip();
201
  }
202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  $current_url = wpzerospam_current_url();
204
  $location_info = wpzerospam_get_ip_info( $ip_address );
205
 
@@ -404,6 +468,7 @@ if ( ! function_exists( 'wpzerospam_options' ) ) {
404
  if ( empty( $options['verify_comments'] ) ) { $options['verify_comments'] = 'enabled'; }
405
  if ( empty( $options['verify_registrations'] ) ) { $options['verify_registrations'] = 'enabled'; }
406
  if ( empty( $options['log_blocked_ips'] ) ) { $options['log_blocked_ips'] = 'disabled'; }
 
407
 
408
  if ( empty( $options['botscout_api'] ) ) { $options['botscout_api'] = false; }
409
 
@@ -411,6 +476,10 @@ if ( ! function_exists( 'wpzerospam_options' ) ) {
411
  $options['verify_cf7'] = 'enabled';
412
  }
413
 
 
 
 
 
414
  if ( empty( $options['verify_gform'] ) ) {
415
  $options['verify_gform'] = 'enabled';
416
  }
@@ -475,6 +544,45 @@ if ( ! function_exists( 'wpzerospam_ip' ) ) {
475
  }
476
  }
477
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  /**
479
  * Checks to see if the current user has access to the site
480
  */
@@ -487,7 +595,14 @@ if ( ! function_exists( 'wpzerospam_check_access' ) ) {
487
  // Ignore admin dashboard & login page checks
488
  if (
489
  is_admin() || wpzerospam_is_login() ||
490
- ( ! is_singular() && ! is_page() && ! is_single() && ! is_archive() && ! is_home() && ! is_front_page() )
 
 
 
 
 
 
 
491
  ) {
492
  return $access;
493
  }
@@ -544,47 +659,9 @@ if ( ! function_exists( 'wpzerospam_check_access' ) ) {
544
  return $access;
545
  }
546
 
547
- // IP address was found in the blocked IPs list, determine the type and if
548
- // it should still be blocked.
549
- if ( 'permanent' == $is_blocked->blocked_type ) {
550
  $access['access'] = false;
551
  $access['reason'] = $is_blocked->reason;
552
- } else {
553
- $todays_date = new DateTime( current_time( 'mysql' ) );
554
-
555
- if ( ! empty( $is_blocked->start_block ) || ! empty( $is_blocked->end_block ) ) {
556
- $start_block = ! empty( $is_blocked->start_block ) ? new DateTime( $is_blocked->start_block ): false;
557
- $end_block = ! empty( $is_blocked->end_block ) ? new DateTime( $is_blocked->end_block ): false;
558
-
559
- // @TODO - I'm sure there's a better way to handle this
560
- if (
561
- $start_block && $end_block &&
562
- $todays_date->getTimestamp() >= $start_block->getTimestamp() &&
563
- $todays_date->getTimestamp() <= $end_block->getTimestamp()
564
- ) {
565
- $access['access'] = false;
566
- $access['ip'] = $ip;
567
- $access['reason'] = $is_blocked->reason;
568
- } elseif (
569
- $start_block && ! $end_block &&
570
- $todays_date->getTimestamp() >= $start_block->getTimestamp()
571
- ) {
572
- $access['access'] = false;
573
- $access['ip'] = $ip;
574
- $access['reason'] = $is_blocked->reason;
575
- } elseif (
576
- ! $start_block && $end_block &&
577
- $todays_date->getTimestamp() <= $end_block->getTimestamp()
578
- ) {
579
- $access['access'] = false;
580
- $access['ip'] = $ip;
581
- $access['reason'] = $is_blocked->reason;
582
- }
583
- } else {
584
- $access['access'] = false;
585
- $access['ip'] = $ip;
586
- $access['reason'] = $is_blocked->reason;
587
- }
588
  }
589
 
590
  return $access;
@@ -882,3 +959,34 @@ if ( ! function_exists( 'wpzerospam_get_blacklist' ) ) {
882
  return $wpdb->get_results( 'SELECT * FROM ' . wpzerospam_tables( 'blacklist' ) );
883
  }
884
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  }
49
 
50
  /**
51
+ * Returns an array of spam detection types
52
+ */
53
+ if ( ! function_exists( 'wpzerospam_types' ) ) {
54
+ function wpzerospam_types( $key = false ) {
55
+ $types = apply_filters( 'wpzerospam_types', [ 'blocked' => __( 'Access Blocked', 'wpzerospam' ) ] );
56
+
57
+ if ( $key ) {
58
+ if ( ! empty( $types[ $key ] ) ) {
59
+ return $types[ $key ];
60
+ }
61
+
62
+ return $key;
63
+ }
64
+
65
+ return $types;
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Returns spam detections from the database
71
  */
72
  if ( ! function_exists( 'wpzerospam_get_log' ) ) {
73
+ function wpzerospam_get_log( $args = false ) {
74
  global $wpdb;
75
 
76
+ if( 'total' == $args ) {
77
+ return $wpdb->get_var( 'SELECT COUNT(log_id) FROM ' . wpzerospam_tables( 'log' ));
78
+ }
79
+
80
+ $sql = 'SELECT * FROM ' . wpzerospam_tables( 'log' );
81
+ if ( is_array( $args ) ) {
82
+ if ( ! empty( $args['type'] ) ) {
83
+ $sql .= ' WHERE log_type = "' . $args['type'] . '"';
84
+ }
85
+
86
+ if ( ! empty( $args['orderby'] ) ) {
87
+ $sql .= ' ORDER BY ' . $args['orderby'];
88
+ }
89
+
90
+ if ( ! empty( $args['order'] ) ) {
91
+ $sql .= ' ' . $args['order'];
92
+ }
93
+
94
+ if ( ! empty( $args['limit'] ) ) {
95
+ $sql .= ' LIMIT ' . $args['limit'];
96
+ }
97
+
98
+ if ( ! empty( $args['offset'] ) ) {
99
+ $sql .= ', ' . $args['offset'];
100
+ }
101
+ }
102
+
103
+ return $wpdb->get_results( $sql );
104
  }
105
  }
106
 
110
  if ( ! function_exists( 'wpzerospam_spam_detected' ) ) {
111
  function wpzerospam_spam_detected( $type, $data = [], $handle_error = true ) {
112
  $options = wpzerospam_options();
113
+ $ip = wpzerospam_ip();
114
 
115
+ // Log the spam sttempt
116
  wpzerospam_log_spam( $type, $data );
117
 
118
+ // Check if number attempts should result in a permanent block
119
+ $blocked_ip = wpzerospam_get_blocked_ips( $ip );
120
+ if ( $blocked_ip && $blocked_ip->attempts >= $options['auto_block_permanently'] ) {
121
+ // Permanently block the IP
122
+ wpzerospam_update_blocked_ip( $ip , [
123
+ 'blocked_type' => 'permanent',
124
+ 'reason' => $type . ' (permanently auto-blocked)'
125
+ ]);
126
+
127
+ // Check if the IP should be temporarily auto-blocked
128
+ } elseif ( 'enabled' == $options['auto_block_ips'] ) {
129
 
130
  $start_block = current_time( 'mysql' );
131
  $end_block = new DateTime( $start_block );
132
  $end_block->add( new DateInterval( 'PT' . $options['auto_block_period'] . 'M' ) );
133
 
134
+ wpzerospam_update_blocked_ip( $ip , [
135
  'blocked_type' => 'temporary',
136
  'start_block' => $start_block,
137
  'end_block' => $end_block->format('Y-m-d G:i:s'),
240
 
241
  $options = wpzerospam_options();
242
 
 
 
 
 
 
 
 
 
 
 
243
  if ( ! empty( $data['ip'] ) ) {
244
  $ip_address = $data['ip'];
245
  unset( $data['ip'] );
247
  $ip_address = wpzerospam_ip();
248
  }
249
 
250
+ // Check is the spam detection should be shared
251
+ if ( 'enabled' == $options['share_detections'] ) {
252
+ wpzerospam_send_detection([
253
+ 'ip' => $ip_address,
254
+ 'type' => $type
255
+ ]);
256
+ }
257
+
258
+ // Check if spam logging is enabled, also check if type is 'denied'
259
+ // (blocked IP address) & logging of blocked IPs is enabled.
260
+ if ( 'enabled' != $options['log_spam'] ||
261
+ ( 'blocked' == $type && 'enabled' != $options['log_blocked_ips'] )
262
+ ) {
263
+ // Logging disabled
264
+ return false;
265
+ }
266
+
267
  $current_url = wpzerospam_current_url();
268
  $location_info = wpzerospam_get_ip_info( $ip_address );
269
 
468
  if ( empty( $options['verify_comments'] ) ) { $options['verify_comments'] = 'enabled'; }
469
  if ( empty( $options['verify_registrations'] ) ) { $options['verify_registrations'] = 'enabled'; }
470
  if ( empty( $options['log_blocked_ips'] ) ) { $options['log_blocked_ips'] = 'disabled'; }
471
+ if ( empty( $options['auto_block_permanently'] ) ) { $options['auto_block_permanently'] = 3; }
472
 
473
  if ( empty( $options['botscout_api'] ) ) { $options['botscout_api'] = false; }
474
 
476
  $options['verify_cf7'] = 'enabled';
477
  }
478
 
479
+ if ( empty( $options['share_detections'] ) ) {
480
+ $options['share_detections'] = 'enabled';
481
+ }
482
+
483
  if ( empty( $options['verify_gform'] ) ) {
484
  $options['verify_gform'] = 'enabled';
485
  }
544
  }
545
  }
546
 
547
+ /**
548
+ * Return true/false if the IP is currently blocked
549
+ */
550
+ if ( ! function_exists( 'wpzerospam_is_blocked' ) ) {
551
+ function wpzerospam_is_blocked( $blocked_ip_entry ) {
552
+ if ( 'permanent' == $blocked_ip_entry->blocked_type ) {
553
+ return true;
554
+ }
555
+
556
+ $todays_date = new DateTime( current_time( 'mysql' ) );
557
+
558
+ if ( ! empty( $blocked_ip_entry->start_block ) || ! empty( $blocked_ip_entry->end_block ) ) {
559
+ $start_block = ! empty( $blocked_ip_entry->start_block ) ? new DateTime( $blocked_ip_entry->start_block ): false;
560
+ $end_block = ! empty( $is_blocked->end_block ) ? new DateTime( $is_blocked->end_block ): false;
561
+
562
+ // @TODO - I'm sure there's a better way to handle this
563
+ if (
564
+ (
565
+ $start_block && $end_block &&
566
+ $todays_date->getTimestamp() >= $start_block->getTimestamp() &&
567
+ $todays_date->getTimestamp() <= $end_block->getTimestamp()
568
+ ) || (
569
+ $start_block && ! $end_block &&
570
+ $todays_date->getTimestamp() >= $start_block->getTimestamp()
571
+ ) || (
572
+ ! $start_block && $end_block &&
573
+ $todays_date->getTimestamp() <= $end_block->getTimestamp()
574
+ )
575
+ ) {
576
+ return true;
577
+ }
578
+ } else {
579
+ return true;
580
+ }
581
+
582
+ return false;
583
+ }
584
+ }
585
+
586
  /**
587
  * Checks to see if the current user has access to the site
588
  */
595
  // Ignore admin dashboard & login page checks
596
  if (
597
  is_admin() || wpzerospam_is_login() ||
598
+ (
599
+ ! is_singular() &&
600
+ ! is_page() &&
601
+ ! is_single() &&
602
+ ! is_archive() &&
603
+ ! is_home() &&
604
+ ! is_front_page()
605
+ )
606
  ) {
607
  return $access;
608
  }
659
  return $access;
660
  }
661
 
662
+ if ( wpzerospam_is_blocked( $is_blocked ) ) {
 
 
663
  $access['access'] = false;
664
  $access['reason'] = $is_blocked->reason;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
665
  }
666
 
667
  return $access;
959
  return $wpdb->get_results( 'SELECT * FROM ' . wpzerospam_tables( 'blacklist' ) );
960
  }
961
  }
962
+
963
+ /**
964
+ * Sends a spam detection to the WordPress Zero Spam database
965
+ */
966
+ if ( ! function_exists( 'wpzerospam_send_detection' ) ) {
967
+ function wpzerospam_send_detection( $data ) {
968
+ $api_url = 'https://benmarshall.me/wp-json/wpzerospamapi/v1/detection/';
969
+
970
+ if (
971
+ empty( $data['ip'] ) ||
972
+ empty( $data['type'] )
973
+ ) {
974
+ return false;
975
+ }
976
+
977
+ $request = wp_remote_post( $api_url, [
978
+ 'method' => 'POST',
979
+ 'body' => [
980
+ 'ip' => $data['ip'],
981
+ 'type' => $data['type'],
982
+ 'site' => site_url()
983
+ ],
984
+ 'sslverify' => true
985
+ ]);
986
+ if ( is_wp_error( $request ) ) {
987
+ return false;
988
+ }
989
+
990
+ return wp_remote_retrieve_body( $request );
991
+ }
992
+ }
inc/scripts.php CHANGED
@@ -11,6 +11,14 @@
11
  */
12
  if ( ! function_exists( 'wpzerospam_admin_scripts' ) ) {
13
  function wpzerospam_admin_scripts( $hook_suffix ) {
 
 
 
 
 
 
 
 
14
  wp_register_script(
15
  'wpzerospam-admin-tables',
16
  plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
@@ -28,9 +36,9 @@ if ( ! function_exists( 'wpzerospam_admin_scripts' ) ) {
28
  WORDPRESS_ZERO_SPAM_VERSION
29
  );
30
 
31
-
32
  // Handle registering & enqueuing scripts based on the current admin page
33
  switch( $hook_suffix ) {
 
34
  case 'wp-zero-spam_page_wordpress-zero-spam-blacklisted':
35
  wp_enqueue_script( 'wpzerospam-admin-tables' );
36
  wp_enqueue_style( 'wpzerospam-admin-tables' );
@@ -61,11 +69,11 @@ if ( ! function_exists( 'wpzerospam_admin_scripts' ) ) {
61
  false,
62
  WORDPRESS_ZERO_SPAM_VERSION
63
  );
64
-
65
- wp_enqueue_script( 'wpzerospam-admin-tables' );
66
- wp_enqueue_style( 'wpzerospam-admin-tables' );
67
  break;
68
  case 'wp-zero-spam_page_wordpress-zero-spam-blocked-ips':
 
 
 
69
  // Enqueue the JS for the WordPress Zero Spam blocked IPs page
70
  wp_enqueue_script(
71
  'wpzerospam-admin-blocked-ips',
11
  */
12
  if ( ! function_exists( 'wpzerospam_admin_scripts' ) ) {
13
  function wpzerospam_admin_scripts( $hook_suffix ) {
14
+ wp_enqueue_style(
15
+ 'wpzerospam-admin',
16
+ plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
17
+ '/assets/css/admin.css',
18
+ false,
19
+ WORDPRESS_ZERO_SPAM_VERSION
20
+ );
21
+
22
  wp_register_script(
23
  'wpzerospam-admin-tables',
24
  plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
36
  WORDPRESS_ZERO_SPAM_VERSION
37
  );
38
 
 
39
  // Handle registering & enqueuing scripts based on the current admin page
40
  switch( $hook_suffix ) {
41
+ case 'wp-zero-spam_page_wordpress-zero-spam-detections':
42
  case 'wp-zero-spam_page_wordpress-zero-spam-blacklisted':
43
  wp_enqueue_script( 'wpzerospam-admin-tables' );
44
  wp_enqueue_style( 'wpzerospam-admin-tables' );
69
  false,
70
  WORDPRESS_ZERO_SPAM_VERSION
71
  );
 
 
 
72
  break;
73
  case 'wp-zero-spam_page_wordpress-zero-spam-blocked-ips':
74
+ wp_enqueue_script( 'wpzerospam-admin-tables' );
75
+ wp_enqueue_style( 'wpzerospam-admin-tables' );
76
+
77
  // Enqueue the JS for the WordPress Zero Spam blocked IPs page
78
  wp_enqueue_script(
79
  'wpzerospam-admin-blocked-ips',
integrations/buddypress/buddypress.php CHANGED
@@ -6,6 +6,14 @@
6
  * @since 4.1.0
7
  */
8
 
 
 
 
 
 
 
 
 
9
  /**
10
  * Validation for BuddyPress registrations
11
  */
6
  * @since 4.1.0
7
  */
8
 
9
+ /**
10
+ * Add the 'bp_registration' spam type
11
+ */
12
+ add_filter( 'wpzerospam_types', function( $types ) {
13
+ $types = array_merge( $types, [ 'bp_registration' => 'BuddyPress Registration' ] );
14
+ return $types;
15
+ });
16
+
17
  /**
18
  * Validation for BuddyPress registrations
19
  */
integrations/comments/comments.php CHANGED
@@ -6,6 +6,14 @@
6
  * @since 4.3.7
7
  */
8
 
 
 
 
 
 
 
 
 
9
  /**
10
  * Preprocess comment fields
11
  */
6
  * @since 4.3.7
7
  */
8
 
9
+ /**
10
+ * Add the 'comment' spam type
11
+ */
12
+ add_filter( 'wpzerospam_types', function( $types ) {
13
+ $types = array_merge( $types, [ 'comment' => 'Comment' ] );
14
+ return $types;
15
+ });
16
+
17
  /**
18
  * Preprocess comment fields
19
  */
integrations/contact-form-7/contact-form-7.php CHANGED
@@ -6,6 +6,14 @@
6
  * @since 4.3.7
7
  */
8
 
 
 
 
 
 
 
 
 
9
  /**
10
  * Validation for CF7 submissions
11
  */
6
  * @since 4.3.7
7
  */
8
 
9
+ /**
10
+ * Add the 'cf7' spam type
11
+ */
12
+ add_filter( 'wpzerospam_types', function( $types ) {
13
+ $types = array_merge( $types, [ 'cf7' => 'Contact Form 7' ] );
14
+ return $types;
15
+ });
16
+
17
  /**
18
  * Validation for CF7 submissions
19
  */
integrations/fluentform/fluentform.php CHANGED
@@ -6,6 +6,14 @@
6
  * @since 4.4.0
7
  */
8
 
 
 
 
 
 
 
 
 
9
  /**
10
  * Validation for Fluent Form submissions
11
  */
6
  * @since 4.4.0
7
  */
8
 
9
+ /**
10
+ * Add the 'fluentform' spam type
11
+ */
12
+ add_filter( 'wpzerospam_types', function( $types ) {
13
+ $types = array_merge( $types, [ 'fluentform' => 'Fluent Forms' ] );
14
+ return $types;
15
+ });
16
+
17
  /**
18
  * Validation for Fluent Form submissions
19
  */
integrations/gravity-forms/gravity-forms.php CHANGED
@@ -6,6 +6,14 @@
6
  * @since 4.1.0
7
  */
8
 
 
 
 
 
 
 
 
 
9
  /**
10
  * Validation for CF7 submissions
11
  */
6
  * @since 4.1.0
7
  */
8
 
9
+ /**
10
+ * Add the 'fluentform' spam type
11
+ */
12
+ add_filter( 'wpzerospam_types', function( $types ) {
13
+ $types = array_merge( $types, [ 'gform' => 'Gravity Forms' ] );
14
+ return $types;
15
+ });
16
+
17
  /**
18
  * Validation for CF7 submissions
19
  */
integrations/ninja-forms/ninja-forms.php CHANGED
@@ -6,6 +6,14 @@
6
  * @since 4.3.7
7
  */
8
 
 
 
 
 
 
 
 
 
9
  /**
10
  * Validation for Ninja Forms submissions
11
  */
6
  * @since 4.3.7
7
  */
8
 
9
+ /**
10
+ * Add the 'ninja_forms' spam type
11
+ */
12
+ add_filter( 'wpzerospam_types', function( $types ) {
13
+ $types = array_merge( $types, [ 'ninja_forms' => 'Ninja Forms' ] );
14
+ return $types;
15
+ });
16
+
17
  /**
18
  * Validation for Ninja Forms submissions
19
  */
integrations/registrations/registrations.php CHANGED
@@ -6,6 +6,14 @@
6
  * @since 4.3.7
7
  */
8
 
 
 
 
 
 
 
 
 
9
  /**
10
  * Preprocess registration fields
11
  */
6
  * @since 4.3.7
7
  */
8
 
9
+ /**
10
+ * Add the 'registration' spam type
11
+ */
12
+ add_filter( 'wpzerospam_types', function( $types ) {
13
+ $types = array_merge( $types, [ 'registration' => 'Registration' ] );
14
+ return $types;
15
+ });
16
+
17
  /**
18
  * Preprocess registration fields
19
  */
integrations/wpforms/wpforms.php CHANGED
@@ -6,6 +6,14 @@
6
  * @since 4.1.0
7
  */
8
 
 
 
 
 
 
 
 
 
9
  /**
10
  * Validation for WPForms submissions
11
  *
6
  * @since 4.1.0
7
  */
8
 
9
+ /**
10
+ * Add the 'wpform' spam type
11
+ */
12
+ add_filter( 'wpzerospam_types', function( $types ) {
13
+ $types = array_merge( $types, [ 'wpform' => 'WPForms' ] );
14
+ return $types;
15
+ });
16
+
17
  /**
18
  * Validation for WPForms submissions
19
  *
readme.txt CHANGED
@@ -5,7 +5,7 @@ Donate link: https://benmarshall.me/donate/?utm_source=wordpress_zero_spam&utm_m
5
  Requires at least: 5.2
6
  Tested up to: 5.4.2
7
  Requires PHP: 7.1
8
- Stable tag: 4.6.0
9
  License: GNU GPLv3
10
  License URI: https://choosealicense.com/licenses/gpl-3.0/
11
 
@@ -17,15 +17,13 @@ Why force users to prove that they're humans by filling out captchas? Let bots p
17
 
18
  WordPress Zero Spam blocks spam submissions including comments, registrations and more automatically without any config or setup. Just install, activate, and enjoy a spam-free site.
19
 
20
- WordPress Zero Spam was initially built based on the work by [David Walsh](http://davidwalsh.name/wordpress-comment-spam).
21
-
22
  = Plugin Features =
23
 
24
  * **No captcha**, spam isn't a users' problem
25
  * **No moderation queues**, spam isn't a administrators' problem
26
  * **Blocks 99.9% of spam** submissions
27
  * **Blocks spammy IPs** from ever seeing your site
28
- * **Checks known spam blacklists** to prevent access ([Stop Forum Spam](https://www.stopforumspam.com/), [BotScout](https://botscout.com/))
29
  * **Auto-block IPs** when a spam detection is triggered
30
  * **Manually block IPs** either temporarily or permanently
31
  * **Developer-friendly**, integrate with any theme, plugin or form
@@ -44,24 +42,34 @@ WordPress Zero Spam was initially built based on the work by [David Walsh](http:
44
  * [Contact Form by WPForms](https://wordpress.org/plugins/wpforms-lite/) submissions
45
  * [WP Fluent Forms](https://wordpress.org/plugins/fluentform/) submissions
46
 
47
- While WordPress Zero Spam block 99.9% of the spam that comes through, there's still some other things you can do as a site owner to [stop WordPress spam](https://benmarshall.me/stop-wordpress-spam/).
 
 
 
 
48
 
49
- This plugin does not support Jetpack Comments. For more information, see [https://wordpress.org/support/topic/incompatible-with-jetpack-comments](https://wordpress.org/support/topic/incompatible-with-jetpack-comments). If you're running something other than one of the supported plugins above, it won't detect spam submissions without some additional integration.
 
 
50
 
51
- Feel free to report any [bugs/feature requests here](https://github.com/bmarshall511/wordpress-zero-spam/issues).
52
 
53
- Have a question, comment or suggestion? Feel free to [contact me](https://benmarshall.me/contact/?utm_source=wordpress.org&utm_medium=plugin&utm_campaign=wordpress_zero_spam), follow me [on Twitter](https://twitter.com/bmarshall0511) or [visit my site](https://benmarshall.me/?utm_source=wordpress.org&utm_medium=plugin&utm_campaign=wordpress_zero_spam).
54
 
55
  == Installation ==
56
 
57
- 1. Upload the entire wordpress-zero-spam folder to the `/wp-content/plugins/` directory.
58
- 2. Activate the plugin through the Plugins screen (Plugins > Installed Plugins).
59
- 3. Visit the plugin setting to configure as needed (Settings > WP Zero Spam).
60
 
61
  For more information, see the [plugin’s website](https://benmarshall.me/wordpress-zero-spam).
62
 
63
  == Frequently Asked Questions ==
64
 
 
 
 
 
65
  = Why aren't spammy comments being blocked? =
66
 
67
  WordPress Zero Spam relies on the default core form id (`#commentform`) in order to detect comments. Verify your comment forms have this ID or add the class `wpzerospam` to them so the plugin knows to it should attempt to detect spam comments.
@@ -86,15 +94,19 @@ Example with `wpzerospam` class:
86
 
87
  Yes, that's what does the magic and keeps spam bots out.
88
 
 
 
 
 
89
  = What action hooks are available? =
90
 
91
- * `wpzerospam_comment_spam` - Fires when a spam comment is detected.
92
- * `wpzerospam_registration_spam` - Fires when a spam registration is detected.
93
- * `wpzerospam_cf7_spam` - Fires when a spam submission is made with a CF7 form.
94
- * `wpzerospam_gform_spam` - Fires when a spam submission is made with a Gravity Form.
95
- * `wpzerospam_ninja_forms_spam` - Fires when a spam submission is made with a Ninja Form.
96
- * `wpzerospam_bp_registration_spam` - Fires when a BuddyPress spam registration is detected.
97
- * `wpzerospam_wpform_spam` - Fires when a spam submission is made with a WPForm.
98
  * `wpzerospam_fluentform_spam` - Fires when a spam submission is made with a WP Fluent Form
99
 
100
  == Screenshots ==
@@ -105,6 +117,14 @@ Yes, that's what does the magic and keeps spam bots out.
105
 
106
  == Changelog ==
107
 
 
 
 
 
 
 
 
 
108
  = 4.6.0 =
109
 
110
  * Added option to strip links from comments
5
  Requires at least: 5.2
6
  Tested up to: 5.4.2
7
  Requires PHP: 7.1
8
+ Stable tag: 4.7.0
9
  License: GNU GPLv3
10
  License URI: https://choosealicense.com/licenses/gpl-3.0/
11
 
17
 
18
  WordPress Zero Spam blocks spam submissions including comments, registrations and more automatically without any config or setup. Just install, activate, and enjoy a spam-free site.
19
 
 
 
20
  = Plugin Features =
21
 
22
  * **No captcha**, spam isn't a users' problem
23
  * **No moderation queues**, spam isn't a administrators' problem
24
  * **Blocks 99.9% of spam** submissions
25
  * **Blocks spammy IPs** from ever seeing your site
26
+ * **Checks known spam blacklists** ([Stop Forum Spam](https://www.stopforumspam.com/), [BotScout](https://botscout.com/))
27
  * **Auto-block IPs** when a spam detection is triggered
28
  * **Manually block IPs** either temporarily or permanently
29
  * **Developer-friendly**, integrate with any theme, plugin or form
42
  * [Contact Form by WPForms](https://wordpress.org/plugins/wpforms-lite/) submissions
43
  * [WP Fluent Forms](https://wordpress.org/plugins/fluentform/) submissions
44
 
45
+ WordPress Zero Spam is great at blocking spam &mdash; as a site owner there's more you can do to [stop WordPress spam](https://benmarshall.me/stop-wordpress-spam/) in its tracks.
46
+
47
+ = Issues/Feature Requests =
48
+
49
+ **Something not working as expected?** I wanna hear about it. Have an idea on how to improve the plugin? I'm all ears.
50
 
51
+ * [Submit an issue or feature request](https://github.com/bmarshall511/wordpress-zero-spam/issues) on GitHub
52
+ * [Contact me directly](https://benmarshall.me/contact/?utm_source=wordpress.org&utm_medium=plugin&utm_campaign=wordpress_zero_spam) on my site
53
+ * [Follow me](https://twitter.com/bmarshall0511) on Twitter
54
 
55
+ = Show Your Support =
56
 
57
+ WordPress Zero Spam is free &mdash; completely free & always will be. No premium versions or addons you've gotta buy to access additional features. Help support it's development by [donating](https://benmarshall.me/donate/?utm_source=wordpress.org&utm_medium=plugin&utm_campaign=wordpress_zero_spam) today.
58
 
59
  == Installation ==
60
 
61
+ 1. Upload the entire wordpress-zero-spam folder to the */wp-content/plugins/* directory.
62
+ 2. Activate the plugin through the Plugins screen (*Plugins > Installed Plugins*).
63
+ 3. Visit the plugin setting to configure as needed (*Settings > WP Zero Spam*).
64
 
65
  For more information, see the [plugin’s website](https://benmarshall.me/wordpress-zero-spam).
66
 
67
  == Frequently Asked Questions ==
68
 
69
+ = Does WordPress Zero Spam work for Jetpack comments? =
70
+
71
+ No. For more information, see [https://wordpress.org/support/topic/incompatible-with-jetpack-comments](https://wordpress.org/support/topic/incompatible-with-jetpack-comments).
72
+
73
  = Why aren't spammy comments being blocked? =
74
 
75
  WordPress Zero Spam relies on the default core form id (`#commentform`) in order to detect comments. Verify your comment forms have this ID or add the class `wpzerospam` to them so the plugin knows to it should attempt to detect spam comments.
94
 
95
  Yes, that's what does the magic and keeps spam bots out.
96
 
97
+ = What filters are available? =
98
+
99
+ * `wpzerospam_types` - Returns an array of available spam detection types
100
+
101
  = What action hooks are available? =
102
 
103
+ * `wpzerospam_comment_spam` - Fires when a spam comment is detected
104
+ * `wpzerospam_registration_spam` - Fires when a spam registration is detected
105
+ * `wpzerospam_cf7_spam` - Fires when a spam submission is made with a CF7 form
106
+ * `wpzerospam_gform_spam` - Fires when a spam submission is made with a Gravity Form
107
+ * `wpzerospam_ninja_forms_spam` - Fires when a spam submission is made with a Ninja Form
108
+ * `wpzerospam_bp_registration_spam` - Fires when a BuddyPress spam registration is detected
109
+ * `wpzerospam_wpform_spam` - Fires when a spam submission is made with a WPForm
110
  * `wpzerospam_fluentform_spam` - Fires when a spam submission is made with a WP Fluent Form
111
 
112
  == Screenshots ==
117
 
118
  == Changelog ==
119
 
120
+ = 4.7.0 =
121
+
122
+ * Various performance enhancements
123
+ * Updates to the admin tables
124
+ * Improved UI
125
+ * Added functionality & option to permanently auto-block after X spam detections
126
+ * Added ability to share spam detections with WordPress Zero Spam to strengthen it's ability to detect spammers
127
+
128
  = 4.6.0 =
129
 
130
  * Added option to strip links from comments
templates/ip-list.php CHANGED
@@ -29,7 +29,7 @@ $chart_limit = 20;
29
  arsort( $ips );
30
  endif;
31
  ?>
32
- <ol>
33
  <?php
34
  $cnt = 0;
35
  foreach( $ips as $ip => $ary ):
@@ -37,11 +37,31 @@ $chart_limit = 20;
37
  if ( $cnt > $chart_limit ) { break; }
38
  ?>
39
  <li>
40
- <a href="https://whatismyipaddress.com/ip/<?php echo $ip; ?>" target="_blank" rel="noopener noreferrer"><strong><?php echo $ip; ?></strong></a>
41
  <?php if ( ! empty( $ary['country'] ) ): ?>
42
- (<?php echo wpzerospam_get_location( $ary['country'] ); ?>)
43
  <?php endif; ?>
44
- &mdash; <?php echo $ary['count']; ?></li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  <?php endforeach; ?>
46
  </ol>
47
  <?php else: ?>
29
  arsort( $ips );
30
  endif;
31
  ?>
32
+ <ol class="wpzerospam-list">
33
  <?php
34
  $cnt = 0;
35
  foreach( $ips as $ip => $ary ):
37
  if ( $cnt > $chart_limit ) { break; }
38
  ?>
39
  <li>
 
40
  <?php if ( ! empty( $ary['country'] ) ): ?>
41
+ <img class="wpzerospam-country-flag" width="16" src="https://hatscripts.github.io/circle-flags/flags/<?php echo strtolower( $ary['country'] ); ?>.svg" alt="<?php echo wpzerospam_get_location( $ary['country'] ); ?>" />
42
  <?php endif; ?>
43
+ <a href="https://whatismyipaddress.com/ip/<?php echo $ip; ?>" target="_blank" rel="noopener noreferrer" class="wpzerospam-list-cell"><strong><?php echo $ip; ?></strong></a>
44
+ <span class="wpzerospam-list-cell">
45
+ <?php if ( ! empty( $ary['country'] ) ): ?>
46
+ <?php echo wpzerospam_get_location( $ary['country'] ); ?>
47
+ <?php endif; ?>
48
+ </span>
49
+ <span class="wpzerospam-list-cell-small">
50
+ <?php echo $ary['count']; ?>
51
+ </span>
52
+ <span class="wpzerospam-action">
53
+ <?php
54
+ $blocked_status = wpzerospam_get_blocked_ips( $ip );
55
+ if ( $blocked_status && wpzerospam_is_blocked( $blocked_status ) ):
56
+ ?>
57
+ <span class="wpzerospam-blocked"><?php _e( 'Blocked', 'wpzerospam' ); ?></span>
58
+ <?php else: ?>
59
+ <a href="<?php echo admin_url( 'admin.php?page=wordpress-zero-spam-blocked-ips&ip=' . $ip ); ?>">
60
+ <?php _e( 'Configure IP Block', 'wpzerospam' ); ?>
61
+ </a>
62
+ <?php endif; ?>
63
+ </span>
64
+ </li>
65
  <?php endforeach; ?>
66
  </ol>
67
  <?php else: ?>
templates/spam-line-chart.php CHANGED
@@ -42,10 +42,10 @@
42
  data: <?php echo json_encode( $data ); ?>,
43
  backgroundColor: 'rgba(88, 0, 15, 0.5)',
44
  borderColor: '#63000D',
45
- borderWidth: 4,
46
  pointBorderWidth: 2,
47
  pointBackgroundColor: '#58000f',
48
- pointRadius: 5,
49
  fill: false,
50
  }],
51
  },
42
  data: <?php echo json_encode( $data ); ?>,
43
  backgroundColor: 'rgba(88, 0, 15, 0.5)',
44
  borderColor: '#63000D',
45
+ borderWidth: 2,
46
  pointBorderWidth: 2,
47
  pointBackgroundColor: '#58000f',
48
+ pointRadius: 2,
49
  fill: false,
50
  }],
51
  },
wordpress-zero-spam.php CHANGED
@@ -13,7 +13,7 @@
13
  * Plugin Name: WordPress Zero Spam
14
  * Plugin URI: https://benmarshall.me/wordpress-zero-spam
15
  * Description: Tired of all the useless and bloated WordPress spam plugins? The WordPress Zero Spam plugin makes blocking spam a cinch. <strong>Just install, activate and say goodbye to spam.</strong> Based on work by <a href="http://davidwalsh.name/wordpress-comment-spam" target="_blank">David Walsh</a>.
16
- * Version: 4.6.0
17
  * Requires at least: 5.2
18
  * Requires PHP: 7.2
19
  * Author: Ben Marshall
@@ -31,7 +31,7 @@ defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
31
  // Define plugin constants
32
  define( 'WORDPRESS_ZERO_SPAM', __FILE__ );
33
  define( 'WORDPRESS_ZERO_SPAM_DB_VERSION', '0.2' );
34
- define( 'WORDPRESS_ZERO_SPAM_VERSION', '4.6.0' );
35
 
36
  /**
37
  * Helpers
@@ -57,49 +57,52 @@ function wpzerospam_install() {
57
  $blocked_table = wpzerospam_tables( 'blocked' );
58
  $blacklist_table = wpzerospam_tables( 'blacklist' );
59
 
60
- $sql = '';
61
- if ( $wpdb->get_var( 'SHOW TABLES LIKE \'' . $log_table . '\'' ) != $log_table ) {
62
- $sql .= "CREATE TABLE $log_table (
63
- log_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
64
- log_type VARCHAR(255) NOT NULL,
65
- user_ip VARCHAR(255) NOT NULL,
66
- date_recorded DATETIME NOT NULL,
67
- page_url VARCHAR(255) NULL DEFAULT NULL,
68
- submission_data LONGTEXT NULL DEFAULT NULL,
69
- country VARCHAR(2) NULL DEFAULT NULL,
70
- region VARCHAR(255) NULL DEFAULT NULL,
71
- city VARCHAR(255) NULL DEFAULT NULL,
72
- latitude VARCHAR(255) NULL DEFAULT NULL,
73
- longitude VARCHAR(255) NULL DEFAULT NULL,
74
- PRIMARY KEY (`log_id`)) $charset_collate;";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  }
76
 
77
- if ( $wpdb->get_var( 'SHOW TABLES LIKE \'' . $blocked_table . '\'' ) != $blocked_table ) {
78
- $sql .= "CREATE TABLE $blocked_table (
79
- blocked_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
80
- blocked_type ENUM('permanent','temporary') NOT NULL DEFAULT 'temporary',
81
- user_ip VARCHAR(255) NOT NULL,
82
- date_added DATETIME NOT NULL,
83
- start_block DATETIME NULL DEFAULT NULL,
84
- end_block DATETIME NULL DEFAULT NULL,
85
- reason VARCHAR(255) NULL DEFAULT NULL,
86
- attempts BIGINT UNSIGNED NOT NULL,
87
- PRIMARY KEY (`blocked_id`)) $charset_collate;";
88
- }
89
-
90
- if ( $wpdb->get_var( 'SHOW TABLES LIKE \'' . $blacklist_table . '\'' ) != $blacklist_table ) {
91
- $sql .= "CREATE TABLE $blacklist_table (
92
- blacklist_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
93
- user_ip VARCHAR(255) NOT NULL,
94
- last_updated DATETIME NOT NULL,
95
- blacklist_service VARCHAR(255) NULL DEFAULT NULL,
96
- blacklist_data LONGTEXT NULL DEFAULT NULL,
97
- PRIMARY KEY (`blacklist_id`)) $charset_collate;";
98
- }
99
 
100
- if( $sql ) {
101
- require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
102
- dbDelta( $sql );
103
  }
104
 
105
  update_option( 'wpzerospam_db_version', WORDPRESS_ZERO_SPAM_DB_VERSION );
13
  * Plugin Name: WordPress Zero Spam
14
  * Plugin URI: https://benmarshall.me/wordpress-zero-spam
15
  * Description: Tired of all the useless and bloated WordPress spam plugins? The WordPress Zero Spam plugin makes blocking spam a cinch. <strong>Just install, activate and say goodbye to spam.</strong> Based on work by <a href="http://davidwalsh.name/wordpress-comment-spam" target="_blank">David Walsh</a>.
16
+ * Version: 4.7.0
17
  * Requires at least: 5.2
18
  * Requires PHP: 7.2
19
  * Author: Ben Marshall
31
  // Define plugin constants
32
  define( 'WORDPRESS_ZERO_SPAM', __FILE__ );
33
  define( 'WORDPRESS_ZERO_SPAM_DB_VERSION', '0.2' );
34
+ define( 'WORDPRESS_ZERO_SPAM_VERSION', '4.7.0' );
35
 
36
  /**
37
  * Helpers
57
  $blocked_table = wpzerospam_tables( 'blocked' );
58
  $blacklist_table = wpzerospam_tables( 'blacklist' );
59
 
60
+ $sql = "CREATE TABLE $log_table (
61
+ log_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
62
+ log_type VARCHAR(255) NOT NULL,
63
+ user_ip VARCHAR(39) NOT NULL,
64
+ date_recorded DATETIME NOT NULL,
65
+ page_url VARCHAR(255) NULL DEFAULT NULL,
66
+ submission_data LONGTEXT NULL DEFAULT NULL,
67
+ country VARCHAR(2) NULL DEFAULT NULL,
68
+ region VARCHAR(255) NULL DEFAULT NULL,
69
+ city VARCHAR(255) NULL DEFAULT NULL,
70
+ latitude VARCHAR(255) NULL DEFAULT NULL,
71
+ longitude VARCHAR(255) NULL DEFAULT NULL,
72
+ PRIMARY KEY (`log_id`)) $charset_collate;";
73
+
74
+ $sql .= "CREATE TABLE $blocked_table (
75
+ blocked_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
76
+ blocked_type ENUM('permanent','temporary') NOT NULL DEFAULT 'temporary',
77
+ user_ip VARCHAR(39) NOT NULL,
78
+ date_added DATETIME NOT NULL,
79
+ start_block DATETIME NULL DEFAULT NULL,
80
+ end_block DATETIME NULL DEFAULT NULL,
81
+ reason VARCHAR(255) NULL DEFAULT NULL,
82
+ attempts BIGINT UNSIGNED NOT NULL,
83
+ PRIMARY KEY (`blocked_id`)) $charset_collate;";
84
+
85
+ $sql .= "CREATE TABLE $blacklist_table (
86
+ blacklist_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
87
+ user_ip VARCHAR(39) NOT NULL,
88
+ last_updated DATETIME NOT NULL,
89
+ blacklist_service VARCHAR(255) NULL DEFAULT NULL,
90
+ blacklist_data LONGTEXT NULL DEFAULT NULL,
91
+ PRIMARY KEY (`blacklist_id`)) $charset_collate;";
92
+
93
+ require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
94
+ dbDelta( $sql );
95
+
96
+ if ( $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $blocked_table ) ) === $blocked_table ) {
97
+ $wpdb->query( "DELETE $blocked_table FROM $blocked_table AS t1 INNER JOIN $blocked_table AS t2 WHERE t1.blocked_id < t2.blocked_id AND t1.user_ip = t2.user_ip;" );
98
+
99
+ $wpdb->query( "ALTER TABLE $blocked_table ADD UNIQUE `user_ip` (`user_ip`(39));" );
100
  }
101
 
102
+ if ( $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $blacklist_table ) ) === $blacklist_table ) {
103
+ $wpdb->query( "DELETE $blacklist_table FROM $blacklist_table AS t1 INNER JOIN $blacklist_table AS t2 WHERE t1.blacklist_id < t2.blacklist_id AND t1.user_ip = t2.user_ip;" );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
+ $wpdb->query( "ALTER TABLE $blacklist_table ADD UNIQUE `user_ip` (`user_ip`(39));" );
 
 
106
  }
107
 
108
  update_option( 'wpzerospam_db_version', WORDPRESS_ZERO_SPAM_DB_VERSION );