WordPress Zero Spam - Version 5.0.2

Version Description

Download this release

Release Info

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

Code changes from version 5.0.1 to 5.0.2

assets/css/admin.css CHANGED
@@ -1,3 +1,13 @@
 
 
 
 
 
 
 
 
 
 
1
  .zerospam-callout,
2
  .zerospam-modal {
3
  background: #fff;
@@ -143,6 +153,12 @@
143
  width: 50%;
144
  }
145
 
 
 
 
 
 
 
146
  .zerospam-modal input[type="text"],
147
  .zerospam-modal input[type="datetime-local"],
148
  .zerospam-modal select {
@@ -153,6 +169,22 @@
153
  margin-top: 16px;
154
  }
155
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  @media (min-width: 768px) {
157
  .zerospam-callout-col {
158
  width: 50%;
1
+ :root {
2
+ --zerospam-primary: #840012;
3
+ }
4
+
5
+ .zerospam-flag {
6
+ display: inline-block;
7
+ margin-right: 8px;
8
+ vertical-align: sub;
9
+ }
10
+
11
  .zerospam-callout,
12
  .zerospam-modal {
13
  background: #fff;
153
  width: 50%;
154
  }
155
 
156
+ .zerospam-modal form label[for="location-type"],
157
+ .zerospam-modal form label[for="location-key"],
158
+ .zerospam-modal form.zerospam-block-location-form label[for="blocked-type"] {
159
+ width: calc(100% / 3);
160
+ }
161
+
162
  .zerospam-modal input[type="text"],
163
  .zerospam-modal input[type="datetime-local"],
164
  .zerospam-modal select {
169
  margin-top: 16px;
170
  }
171
 
172
+ .zerospam-type-blocked {
173
+ color: var(--zerospam-primary);
174
+ }
175
+
176
+ .zerospam-type-blocked::before {
177
+ background: url('../img/icon.svg');
178
+ background-repeat: no-repeat;
179
+ background-size: contain;
180
+ content: "";
181
+ display: inline-block;
182
+ height: 16px;
183
+ margin-right: 8px;
184
+ vertical-align: sub;
185
+ width: 16px;
186
+ }
187
+
188
  @media (min-width: 768px) {
189
  .zerospam-callout-col {
190
  width: 50%;
assets/img/icon.svg ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ <title>WordPress Zero Spam</title>
4
+ <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
5
+ <g transform="translate(256.000000, 239.000000) scale(-1, 1) translate(-256.000000, -239.000000) " fill-rule="nonzero">
6
+ <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>
7
+ <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>
8
+ <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>
9
+ <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>
10
+ <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>
11
+ <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>
12
+ <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>
13
+ <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>
14
+ <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>
15
+ <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>
16
+ <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>
17
+ <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>
18
+ <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>
19
+ </g>
20
+ </g>
21
+ </svg>
assets/js/admin.js CHANGED
@@ -1,4 +1,50 @@
1
  (function($) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  $(function() {
3
  $( '.zerospam-details-trigger' ).click(function( e ) {
4
  e.preventDefault();
@@ -13,38 +59,19 @@
13
  $('.zerospam-modal').removeClass('is-active');
14
  });
15
 
16
- $('.zerospam-block-trigger').click(function(e) {
17
  e.preventDefault();
18
 
19
- var ip = $(this).data('ip');
20
- $('input[name="blocked_ip"]', $('#zerospam-block-ip')).val('');
21
- if ( ip ) {
22
- $('input[name="blocked_ip"]', $('#zerospam-block-ip')).val(ip);
23
- }
24
 
25
- var reason = $(this).data('reason');
26
- $('input[name="blocked_reason"]', $('#zerospam-block-ip')).val('');
27
- if ( reason ) {
28
- $('input[name="blocked_reason"]', $('#zerospam-block-ip')).val(reason);
29
- }
30
-
31
- var type = $(this).data('type');
32
- $('select[name="blocked_type"]', $('#zerospam-block-ip')).val('temporary');
33
- if ( type ) {
34
- $('select[name="blocked_type"]', $('#zerospam-block-ip')).val(type);
35
- }
36
 
37
- var startDate = $(this).data('start');
38
- $('input[name="blocked_start_date"]', $('#zerospam-block-ip')).val('');
39
- if ( startDate ) {
40
- $('input[name="blocked_start_date"]', $('#zerospam-block-ip')).val(startDate);
41
- }
42
 
43
- var endDate = $(this).data('end');
44
- $('input[name="blocked_end_date"]', $('#zerospam-block-ip')).val('');
45
- if ( endDate ) {
46
- $('input[name="blocked_end_date"]', $('#zerospam-block-ip')).val(endDate);
47
- }
48
 
49
  $('.zerospam-modal').removeClass('is-active');
50
  $('#zerospam-block-ip').addClass('is-active');
1
  (function($) {
2
+ var ZeroSpamAdmin = {
3
+ prepopulateFields: function( $btn ) {
4
+ var ip = $btn.data('ip');
5
+ $('input[name="blocked_ip"]', $('.zerospam-modal-block')).val('');
6
+ if ( ip ) {
7
+ $('input[name="blocked_ip"]', $('.zerospam-modal-block')).val(ip);
8
+ }
9
+
10
+ var keyType = $btn.data('keytype');
11
+ $('select[name="key_type"]', $('.zerospam-modal-block')).val('country_code');
12
+ if ( keyType ) {
13
+ $('select[name="key_type"]', $('.zerospam-modal-block')).val(keyType);
14
+ }
15
+
16
+ var blockedKey = $btn.data('blockedkey');
17
+ $('input[name="blocked_key"]', $('.zerospam-modal-block')).val('');
18
+ if ( blockedKey ) {
19
+ $('input[name="blocked_key"]', $('.zerospam-modal-block')).val(blockedKey);
20
+ }
21
+
22
+ var reason = $btn.data('reason');
23
+ $('input[name="blocked_reason"]', $('.zerospam-modal-block')).val('');
24
+ if ( reason ) {
25
+ $('input[name="blocked_reason"]', $('.zerospam-modal-block')).val(reason);
26
+ }
27
+
28
+ var type = $btn.data('type');
29
+ $('select[name="blocked_type"]', $('.zerospam-modal-block')).val('temporary');
30
+ if ( type ) {
31
+ $('select[name="blocked_type"]', $('.zerospam-modal-block')).val(type);
32
+ }
33
+
34
+ var startDate = $btn.data('start');
35
+ $('input[name="blocked_start_date"]', $('.zerospam-modal-block')).val('');
36
+ if ( startDate ) {
37
+ $('input[name="blocked_start_date"]', $('.zerospam-modal-block')).val(startDate);
38
+ }
39
+
40
+ var endDate = $btn.data('end');
41
+ $('input[name="blocked_end_date"]', $('.zerospam-modal-block')).val('');
42
+ if ( endDate ) {
43
+ $('input[name="blocked_end_date"]', $('.zerospam-modal-block')).val(endDate);
44
+ }
45
+ }
46
+ };
47
+
48
  $(function() {
49
  $( '.zerospam-details-trigger' ).click(function( e ) {
50
  e.preventDefault();
59
  $('.zerospam-modal').removeClass('is-active');
60
  });
61
 
62
+ $('.zerospam-block-location-trigger').click(function(e) {
63
  e.preventDefault();
64
 
65
+ ZeroSpamAdmin.prepopulateFields($(this));
 
 
 
 
66
 
67
+ $('.zerospam-modal').removeClass('is-active');
68
+ $('#zerospam-block-location').addClass('is-active');
69
+ });
 
 
 
 
 
 
 
 
70
 
71
+ $('.zerospam-block-trigger').click(function(e) {
72
+ e.preventDefault();
 
 
 
73
 
74
+ ZeroSpamAdmin.prepopulateFields($(this));
 
 
 
 
75
 
76
  $('.zerospam-modal').removeClass('is-active');
77
  $('#zerospam-block-ip').addClass('is-active');
core/admin/class-dashboard.php CHANGED
@@ -46,12 +46,14 @@ class Dashboard {
46
  'zerospam-error=3',
47
  'zerospam-error=4',
48
  'zerospam-error=5',
 
 
49
  ),
50
  '',
51
  $url['query']
52
  );
53
 
54
- $url = $url['scheme'] . '://' . $url['host'] . ( ! empty( $url['port'] ) ? ':' . $url['port'] : '' ) . $url['path'] . '?' . $url['query'] . ( ! empty( $url['fragment'] ) ? '#' . $url['fragment'] : '' );
55
 
56
  if ( ! isset( $_POST['zerospam'] ) || ! wp_verify_nonce( $_POST['zerospam'], 'zerospam' ) ) {
57
  wp_redirect( $url . '&zerospam-error=1' );
@@ -60,13 +62,33 @@ class Dashboard {
60
 
61
  $record = array();
62
 
63
- $record['user_ip'] = sanitize_text_field( $_POST['blocked_ip'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  $record['blocked_type'] = in_array( sanitize_text_field( $_POST['blocked_type'] ), [ 'permanent', 'temporary' ] ) ? sanitize_text_field( $_POST['blocked_type'] ) : false;
65
  $record['reason'] = sanitize_text_field( $_POST['blocked_reason'] );
66
  $record['start_block'] = sanitize_text_field( $_POST['blocked_start_date'] );
67
  $record['end_block'] = sanitize_text_field( $_POST['blocked_end_date'] );
68
 
69
- if ( ! $record['user_ip'] || ! rest_is_ip_address( $record['user_ip'] ) ) {
70
  wp_safe_redirect( $url . '&zerospam-error=1' );
71
  exit;
72
  }
@@ -141,31 +163,37 @@ class Dashboard {
141
  <div class="notice notice-error is-dismissible">
142
  <p><strong>
143
  <?php
144
- switch( $_GET['zerospam-error'] ):
145
  case 1:
146
- _e( 'Please enter a valid IP address.', 'zerospam' );
147
- break;
148
  case 2:
149
- _e( 'Please select a valid type.', 'zerospam' );
150
- break;
151
  case 3:
152
- _e( 'Please select a date & time when the temporary block should end.', 'zerospam' );
153
- break;
154
  case 4:
155
- _e( 'There was a problem add the IP to the database. Please try again.', 'zerospam' );
156
- break;
157
  case 5:
158
- _e( 'Temporary blocks require an end date.', 'zerospam' );
159
- break;
 
 
 
 
 
 
160
  endswitch;
161
  ?>
162
  </strong></p>
163
- <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php _e( 'Dismiss this notice.', 'zerospam' ); ?></span></button>
164
  </div>
165
  <?php elseif ( ! empty( $_GET['zerospam-success'] ) ): ?>
166
  <div class="notice notice-success is-dismissible">
167
- <p><strong><?php _e( 'The blocked IP has been successfully added.', 'wpzerospam' ); ?></strong></p>
168
- <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php _e( 'Dismiss this notice.', 'zerospam' ); ?>.</span></button>
169
  </div>
170
  <?php endif; ?>
171
 
@@ -178,6 +206,7 @@ class Dashboard {
178
  <div class="nav-tab-wrapper">
179
  <a id="zerospam-settings-tab-log" class="nav-tab<?php if ( 'log' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=log' ) ); ?>"><?php echo __( 'Log', 'zerospam' ); ?></a>
180
  <a id="zerospam-settings-tab-blocked-ips" class="nav-tab<?php if ( 'blocked' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=blocked' ) ); ?>"><?php echo __( 'Blocked IPs', 'zerospam' ); ?></a>
 
181
  </div>
182
 
183
  <div class="zerospam-tabs">
@@ -212,9 +241,29 @@ class Dashboard {
212
  </form>
213
  </div>
214
  <?php endif; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
  </div>
216
 
217
- <div class="zerospam-modal" id="zerospam-block-ip">
218
  <button class="zerospam-close-modal" aria-label="<?php echo esc_attr( __( 'Close Modal', 'zerospam' ) ); ?>"></button>
219
  <div class="zerospam-modal-details">
220
  <div class="zerospam-modal-title">
@@ -227,6 +276,23 @@ class Dashboard {
227
  <?php require ZEROSPAM_PATH . 'includes/templates/admin-block-ip.php'; ?>
228
  </div>
229
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  </div>
231
  <?php
232
  }
46
  'zerospam-error=3',
47
  'zerospam-error=4',
48
  'zerospam-error=5',
49
+ 'zerospam-error=6',
50
+ 'zerospam-error=7',
51
  ),
52
  '',
53
  $url['query']
54
  );
55
 
56
+ $url = $url['scheme'] . '://' . $url['host'] . ( ! empty( $url['port'] ) ? ':' . $url['port'] : '' ) . $url['path'] . '?' . $url['query'];
57
 
58
  if ( ! isset( $_POST['zerospam'] ) || ! wp_verify_nonce( $_POST['zerospam'], 'zerospam' ) ) {
59
  wp_redirect( $url . '&zerospam-error=1' );
62
 
63
  $record = array();
64
 
65
+ // Blocking by IP.
66
+ if ( ! empty( $_POST['blocked_ip'] ) ) {
67
+ $record['user_ip'] = sanitize_text_field( $_POST['blocked_ip'] );
68
+ }
69
+
70
+ // Blocking by custom key.
71
+ if ( ! empty( $_POST['key_type'] ) ) {
72
+ if ( empty( $_POST['blocked_key'] ) ) {
73
+ wp_safe_redirect( $url . '&zerospam-error=6' );
74
+ exit;
75
+ }
76
+
77
+ $record['key_type'] = sanitize_text_field( $_POST['key_type'] );
78
+ $record['blocked_key'] = sanitize_text_field( $_POST['blocked_key'] );
79
+ }
80
+
81
+ if ( empty( $record['user_ip'] ) && empty( $record['key_type'] ) ) {
82
+ wp_safe_redirect( $url . '&zerospam-error=7' );
83
+ exit;
84
+ }
85
+
86
  $record['blocked_type'] = in_array( sanitize_text_field( $_POST['blocked_type'] ), [ 'permanent', 'temporary' ] ) ? sanitize_text_field( $_POST['blocked_type'] ) : false;
87
  $record['reason'] = sanitize_text_field( $_POST['blocked_reason'] );
88
  $record['start_block'] = sanitize_text_field( $_POST['blocked_start_date'] );
89
  $record['end_block'] = sanitize_text_field( $_POST['blocked_end_date'] );
90
 
91
+ if ( ! empty( $record['user_ip'] ) && ! rest_is_ip_address( $record['user_ip'] ) ) {
92
  wp_safe_redirect( $url . '&zerospam-error=1' );
93
  exit;
94
  }
163
  <div class="notice notice-error is-dismissible">
164
  <p><strong>
165
  <?php
166
+ switch( intval( $_GET['zerospam-error'] ) ) :
167
  case 1:
168
+ esc_html_e( 'Please enter a valid IP address.', 'zerospam' );
169
+ break;
170
  case 2:
171
+ esc_html_e( 'Please select a valid type.', 'zerospam' );
172
+ break;
173
  case 3:
174
+ esc_html_e( 'Please select a date & time when the temporary block should end.', 'zerospam' );
175
+ break;
176
  case 4:
177
+ esc_html_e( 'There was a problem adding the record to the database. Please try again.', 'zerospam' );
178
+ break;
179
  case 5:
180
+ esc_html_e( 'Temporary blocks require an end date.', 'zerospam' );
181
+ break;
182
+ case 6:
183
+ esc_html_e( 'You must enter a valid location key (ex. US, TX, etc.).', 'zerospam' );
184
+ break;
185
+ case 7:
186
+ esc_html_e( 'Missing required fields. Please try again.', 'zerospam' );
187
+ break;
188
  endswitch;
189
  ?>
190
  </strong></p>
191
+ <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'zerospam' ); ?></span></button>
192
  </div>
193
  <?php elseif ( ! empty( $_GET['zerospam-success'] ) ): ?>
194
  <div class="notice notice-success is-dismissible">
195
+ <p><strong><?php _e( 'The blocked record has been successfully added.', 'wpzerospam' ); ?></strong></p>
196
+ <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'zerospam' ); ?>.</span></button>
197
  </div>
198
  <?php endif; ?>
199
 
206
  <div class="nav-tab-wrapper">
207
  <a id="zerospam-settings-tab-log" class="nav-tab<?php if ( 'log' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=log' ) ); ?>"><?php echo __( 'Log', 'zerospam' ); ?></a>
208
  <a id="zerospam-settings-tab-blocked-ips" class="nav-tab<?php if ( 'blocked' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=blocked' ) ); ?>"><?php echo __( 'Blocked IPs', 'zerospam' ); ?></a>
209
+ <a id="zerospam-settings-tab-blocked-locations" class="nav-tab<?php if ( 'blocked-locations' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=blocked-locations' ) ); ?>"><?php echo __( 'Blocked Locations', 'zerospam' ); ?></a>
210
  </div>
211
 
212
  <div class="zerospam-tabs">
241
  </form>
242
  </div>
243
  <?php endif; ?>
244
+
245
+ <?php if ( 'blocked-locations' === $active_tab ) : ?>
246
+ <div id="tab-blocked-locations" class="zerospam-tab is-active">
247
+ <h2><?php echo __( 'Blocked Locations', 'zerospam' ); ?></h2>
248
+ <?php
249
+ if ( ! ZeroSpam\Core\Settings::get_settings( 'ipstack_api' ) ) {
250
+ _e( '<strong>Blocking locations is currently disabled.</strong> A valid ipstack API key is required (defined in the plugin settings).', 'zerospam' );
251
+ }
252
+
253
+ $table_data = new ZeroSpam\Core\Admin\Tables\BlockedLocations();
254
+ $table_data->prepare_items();
255
+ ?>
256
+ <form id="zerospam-blocked-table" method="post">
257
+ <?php wp_nonce_field( 'zerospam_nonce', 'zerospam_nonce' ); ?>
258
+ <input type="hidden" name="paged" value="1" />
259
+ <?php $table_data->search_box( __( 'Search IPs', 'zerospam' ), 'search-ip' ); ?>
260
+ <?php $table_data->display(); ?>
261
+ </form>
262
+ </div>
263
+ <?php endif; ?>
264
  </div>
265
 
266
+ <div class="zerospam-modal zerospam-modal-block" id="zerospam-block-ip">
267
  <button class="zerospam-close-modal" aria-label="<?php echo esc_attr( __( 'Close Modal', 'zerospam' ) ); ?>"></button>
268
  <div class="zerospam-modal-details">
269
  <div class="zerospam-modal-title">
276
  <?php require ZEROSPAM_PATH . 'includes/templates/admin-block-ip.php'; ?>
277
  </div>
278
  </div>
279
+
280
+ <div class="zerospam-modal zerospam-modal-block" id="zerospam-block-location">
281
+ <button class="zerospam-close-modal" aria-label="<?php echo esc_attr( __( 'Close Modal', 'zerospam' ) ); ?>"></button>
282
+ <div class="zerospam-modal-details">
283
+ <div class="zerospam-modal-title">
284
+ <h3><?php echo __( 'Add/Update Blocked Location', 'zerospam' ); ?></h3>
285
+ </div>
286
+ <div class="zerospam-modal-subtitle">
287
+
288
+ </div>
289
+
290
+ <?php
291
+ $location_form = true;
292
+ require ZEROSPAM_PATH . 'includes/templates/admin-block-ip.php';
293
+ ?>
294
+ </div>
295
+ </div>
296
  </div>
297
  <?php
298
  }
core/admin/tables/class-blockedlocations.php ADDED
@@ -0,0 +1,322 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Blocked locations class.
4
+ *
5
+ * @package ZeroSpam
6
+ */
7
+
8
+ namespace ZeroSpam\Core\Admin\Tables;
9
+
10
+ use ZeroSpam;
11
+ use WP_List_Table;
12
+
13
+ // Security Note: Blocks direct access to the plugin PHP files.
14
+ defined( 'ABSPATH' ) || die();
15
+
16
+ /**
17
+ * Blocked locations table.
18
+ */
19
+ class BlockedLocations extends WP_List_Table {
20
+
21
+ /**
22
+ * Log table constructor.
23
+ *
24
+ * @since 5.0.0
25
+ * @access public
26
+ */
27
+ public function __construct() {
28
+ global $status, $page;
29
+
30
+ $args = array(
31
+ 'singular' => __( 'WordPress Zero Spam Blocked Location', 'zerospam' ),
32
+ 'plural' => __( 'WordPress Zero Spam Blocked Locations', 'zerospam' ),
33
+ );
34
+ parent::__construct( $args );
35
+ }
36
+
37
+ /**
38
+ * Column values.
39
+ *
40
+ * @since 5.0.0
41
+ * @access public
42
+ */
43
+ public function column_default( $item, $column_name ) {
44
+ switch ( $column_name ) {
45
+ case 'date_added':
46
+ case 'start_block':
47
+ case 'end_block':
48
+ if (
49
+ ! empty( $item['blocked_type'] ) &&
50
+ 'permanent' === $item['blocked_type'] &&
51
+ 'end_block' === $column_name
52
+ ) {
53
+ return 'N/A';
54
+ }
55
+
56
+ if ( empty( $item[ $column_name ] ) || '0000-00-00 00:00:00' === $item[ $column_name ] ) {
57
+ return 'N/A';
58
+ }
59
+
60
+ return gmdate( 'M j, Y g:ia' , strtotime( $item[ $column_name ] ) );
61
+ break;
62
+ case 'location':
63
+ if ( empty( $item['blocked_key'] ) ) {
64
+ return 'N/A';
65
+ }
66
+
67
+ $location = $item['blocked_key'];
68
+ if ( ! empty( $item['key_type'] ) ) {
69
+ $location .= ' (' . $item['key_type'] . ')';
70
+ }
71
+
72
+ return $location;
73
+ break;
74
+ case 'actions':
75
+ ob_start();
76
+ ?>
77
+ <button
78
+ class="button zerospam-block-location-trigger"
79
+ data-keytype="<?php echo esc_attr( $item['key_type'] ); ?>"
80
+ data-blockedkey="<?php echo esc_attr( $item['blocked_key'] ); ?>"
81
+ data-reason="<?php echo esc_attr( $item['reason'] ); ?>"
82
+ data-start="<?php echo esc_attr( gmdate( 'Y-m-d', strtotime( $item['start_block'] ) ) ); ?>T<?php echo esc_attr( gmdate( 'H:i', strtotime( $item['start_block'] ) ) ); ?>"
83
+ data-end="<?php echo esc_attr( gmdate( 'Y-m-d', strtotime( $item['end_block'] ) ) ); ?>T<?php echo esc_attr( gmdate( 'H:i', strtotime( $item['end_block'] ) ) ); ?>"
84
+ data-type="<?php echo esc_attr( $item['blocked_type'] ); ?>"
85
+ >
86
+ <?php _e( 'Update Block', 'zerospam' ); ?>
87
+ </button>
88
+ <?php
89
+ return ob_get_clean();
90
+ break;
91
+ default:
92
+ if ( empty( $item[ $column_name ] ) ) {
93
+ return 'N/A';
94
+ } else {
95
+ return $item[ $column_name ];
96
+ }
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Bulk actions.
102
+ *
103
+ * @since 5.0.0
104
+ * @access public
105
+ */
106
+ public function get_bulk_actions() {
107
+ $actions = array(
108
+ 'delete' => __( 'Delete Selected', 'zerospam' ),
109
+ //'delete_all' => __( 'Delete All Locations', 'zerospam' ),
110
+ );
111
+
112
+ return $actions;
113
+ }
114
+
115
+ /**
116
+ * Hidable columns.
117
+ *
118
+ * @since 5.0.0
119
+ * @access public
120
+ */
121
+ public function get_hidden_columns() {
122
+ return array();
123
+ }
124
+
125
+ /**
126
+ * Prepare log items.
127
+ *
128
+ * @since 5.0.0
129
+ * @access public
130
+ */
131
+ public function prepare_items( $args = array() ) {
132
+ $this->process_bulk_action();
133
+
134
+ $columns = $this->get_columns();
135
+ $hidden = $this->get_hidden_columns();
136
+ $sortable = $this->get_sortable_columns();
137
+
138
+ $per_page = 50;
139
+ $current_page = $this->get_pagenum();
140
+ $offset = $per_page * ( $current_page - 1 );
141
+ $order = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( $_REQUEST['order'] ) : 'desc';
142
+ $orderby = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( $_REQUEST['orderby'] ) : 'date_added';
143
+
144
+ $log_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
145
+ $user_ip = ! empty( $_REQUEST['s'] ) ? sanitize_text_field( $_REQUEST['s'] ) : false;
146
+
147
+ $query_args = array(
148
+ 'limit' => $per_page,
149
+ 'offset' => $offset,
150
+ 'order' => $order,
151
+ 'orderby' => $orderby,
152
+ 'where' => array(
153
+ 'key_type' => array(
154
+ 'value' => array( 'country_code', 'region_code', 'zip', 'city' ),
155
+ 'relation' => 'IN',
156
+ ),
157
+ ),
158
+ );
159
+
160
+ if ( $user_ip ) {
161
+ $query_args['where']['user_ip'] = array(
162
+ 'value' => $user_ip,
163
+ );
164
+ }
165
+
166
+ $data = ZeroSpam\Includes\DB::query( 'blocked', $query_args );
167
+ if ( ! $data ) {
168
+ return false;
169
+ }
170
+
171
+ $this->items = $data;
172
+
173
+ unset( $query_args['limit'] );
174
+ unset( $query_args['offset'] );
175
+ $data = ZeroSpam\Includes\DB::query( 'blocked', $query_args );
176
+ $total_items = count( $data );
177
+
178
+ $this->set_pagination_args(
179
+ array(
180
+ 'total_items' => $total_items,
181
+ 'per_page' => $per_page,
182
+ 'total_pages' => ceil( $total_items / $per_page ),
183
+ 'orderby' => $orderby,
184
+ 'order' => $order,
185
+ )
186
+ );
187
+
188
+ $this->_column_headers = array( $columns, $hidden, $sortable );
189
+
190
+ $paging_options = array();
191
+ if ( ! empty( $query_args['where'] ) ) {
192
+ foreach ( $query_args['where'] as $key => $value ) {
193
+ switch( $key ) {
194
+ case 'blocked_type':
195
+ $paging_options['type'] = $value['value'];
196
+ break;
197
+ case 'user_ip':
198
+ $paging_options['s'] = $value['value'];
199
+ break;
200
+ }
201
+ }
202
+ }
203
+
204
+ $_SERVER['REQUEST_URI'] = add_query_arg( $paging_options, $_SERVER['REQUEST_URI'] );
205
+ }
206
+
207
+ /**
208
+ * Add more filters.
209
+ *
210
+ * @since 5.0.0
211
+ * @access public
212
+ */
213
+ public function extra_tablenav( $which ) {
214
+ if ( 'top' !== $which ) {
215
+ return;
216
+ }
217
+ ?>
218
+ <div class="alignleft actions">
219
+ <?php
220
+ /*
221
+ echo '<label class="screen-reader-text" for="filter-by-type">' . __( 'Filter by type', 'zerospam' ) . '</label>';
222
+ $options = apply_filters( 'zerospam_types', array() );
223
+ $current_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
224
+ ?>
225
+ <select name="type" id="filter-by-type">
226
+ <option value=""><?php _e( 'All types', 'zerospam' ); ?></option>
227
+ <?php foreach ( $options as $key => $value ) : ?>
228
+ <option<?php if ( $current_type === $key ) : ?> selected="selected"<?php endif; ?> value="<?php echo esc_attr( $key ); ?>"><?php echo $value; ?></option>
229
+ <?php endforeach; ?>
230
+ </select>
231
+ <?php
232
+ submit_button( __( 'Filter', 'zerospam' ), '', 'filter_action', false );
233
+ */
234
+ ?>
235
+ <button class="button zerospam-block-location-trigger"><?php echo __( 'Add Blocked Location', 'zerospam' ); ?></button>
236
+ </div>
237
+ <?php
238
+ }
239
+
240
+ /**
241
+ * Define table columns.
242
+ *
243
+ * @since 5.0.0
244
+ * @access public
245
+ */
246
+ public function get_columns() {
247
+ $columns = array(
248
+ 'cb' => '<input type="checkbox" />',
249
+ 'date_added' => __( 'Date', 'zerospam' ),
250
+ 'location' => __( 'Location', 'zerospam' ),
251
+ 'blocked_type' => __( 'Type', 'zerospam' ),
252
+ 'start_block' => __( 'Starts', 'zerospam' ),
253
+ 'end_block' => __( 'Ends', 'zerospam' ),
254
+ 'reason' => __( 'Reason', 'zerospam' ),
255
+ 'actions' => __( 'Actions', 'zerospam' ),
256
+ );
257
+
258
+ return $columns;
259
+ }
260
+
261
+ /**
262
+ * Sortable columns.
263
+ *
264
+ * @since 5.0.0
265
+ * @access public
266
+ */
267
+ public function get_sortable_columns() {
268
+ $sortable_columns = array(
269
+ 'date_added' => array( 'date_added', false ),
270
+ 'blocked_type' => array( 'blocked_type', false ),
271
+ 'start_block' => array( 'start_block', false ),
272
+ 'end_block' => array( 'end_block', false ),
273
+ 'location' => array( 'blocked_key', false ),
274
+ );
275
+
276
+ return $sortable_columns;
277
+ }
278
+
279
+ /**
280
+ * Column contact.
281
+ *
282
+ * @since 5.0.0
283
+ * @access public
284
+ */
285
+ public function column_cb( $item ) {
286
+ return sprintf(
287
+ '<input type="checkbox" name="%1$s[]" value="%2$s" />',
288
+ /*$1%s*/ 'ids',
289
+ /*$2%s*/ $item['blocked_id']
290
+ );
291
+ }
292
+
293
+ /**
294
+ * Process bulk actions.
295
+ *
296
+ * @since 5.0.0
297
+ * @access public
298
+ */
299
+ public function process_bulk_action() {
300
+ global $wpdb;
301
+
302
+ $ids = ( isset( $_REQUEST['ids'] ) ) ? $_REQUEST['ids'] : '';
303
+
304
+ switch( $this->current_action() ) {
305
+ case 'delete':
306
+ $nonce = ( isset( $_REQUEST['zerospam_nonce'] ) ) ? sanitize_text_field( $_REQUEST['zerospam_nonce'] ) : '';
307
+ if ( ! wp_verify_nonce( $nonce, 'zerospam_nonce' ) ) {
308
+ return false;
309
+ }
310
+
311
+ if ( ! empty ( $ids ) && is_array( $ids ) ) {
312
+ foreach ( $ids as $k => $blocked_id ) {
313
+ ZeroSpam\Includes\DB::delete( 'blocked', 'blocked_id', $blocked_id );
314
+ }
315
+ }
316
+ break;
317
+ case 'delete_all':
318
+ //ZeroSpam\Includes\DB::delete_all( 'blocked' );
319
+ break;
320
+ }
321
+ }
322
+ }
core/admin/tables/class-blockedtable.php CHANGED
@@ -50,6 +50,14 @@ class BlockedTable extends WP_List_Table {
50
  case 'date_added':
51
  case 'start_block':
52
  case 'end_block':
 
 
 
 
 
 
 
 
53
  if ( empty( $item[ $column_name ] ) || '0000-00-00 00:00:00' === $item[ $column_name ] ) {
54
  return 'N/A';
55
  } else {
@@ -90,7 +98,7 @@ class BlockedTable extends WP_List_Table {
90
  public function get_bulk_actions() {
91
  $actions = array(
92
  'delete' => __( 'Delete Selected', 'zerospam' ),
93
- 'delete_all' => __( 'Delete All IPs', 'zerospam' ),
94
  );
95
 
96
  return $actions;
@@ -133,7 +141,11 @@ class BlockedTable extends WP_List_Table {
133
  'offset' => $offset,
134
  'order' => $order,
135
  'orderby' => $orderby,
136
- 'where' => array(),
 
 
 
 
137
  );
138
 
139
  if ( $log_type ) {
@@ -300,7 +312,7 @@ class BlockedTable extends WP_List_Table {
300
  }
301
  break;
302
  case 'delete_all':
303
- ZeroSpam\Includes\DB::delete_all( 'blocked' );
304
  break;
305
  }
306
  }
50
  case 'date_added':
51
  case 'start_block':
52
  case 'end_block':
53
+ if (
54
+ ! empty( $item['blocked_type'] ) &&
55
+ 'permanent' === $item['blocked_type'] &&
56
+ 'end_block' === $column_name
57
+ ) {
58
+ return 'N/A';
59
+ }
60
+
61
  if ( empty( $item[ $column_name ] ) || '0000-00-00 00:00:00' === $item[ $column_name ] ) {
62
  return 'N/A';
63
  } else {
98
  public function get_bulk_actions() {
99
  $actions = array(
100
  'delete' => __( 'Delete Selected', 'zerospam' ),
101
+ //'delete_all' => __( 'Delete All IPs', 'zerospam' ),
102
  );
103
 
104
  return $actions;
141
  'offset' => $offset,
142
  'order' => $order,
143
  'orderby' => $orderby,
144
+ 'where' => array(
145
+ 'key_type' => array(
146
+ 'value' => 'ip',
147
+ ),
148
+ ),
149
  );
150
 
151
  if ( $log_type ) {
312
  }
313
  break;
314
  case 'delete_all':
315
+ //ZeroSpam\Includes\DB::delete_all( 'blocked' );
316
  break;
317
  }
318
  }
core/admin/tables/class-logtable.php CHANGED
@@ -45,12 +45,23 @@ class LogTable extends WP_List_Table {
45
  public function column_default( $item, $column_name ) {
46
  switch ( $column_name ) {
47
  case 'log_type':
 
 
 
 
 
 
 
48
  $types = apply_filters( 'zerospam_types', array() );
49
- if ( ! empty( $types[ $item[ $column_name ] ] ) ) {
50
- return $types[ $item[ $column_name ] ];
51
  } else {
52
- return $item[ $column_name ];
53
  }
 
 
 
 
54
  break;
55
  case 'user_ip':
56
  return '<a href="https://www.zerospam.org/ip-lookup/' . urlencode( $item[ $column_name ] ) .'" target="_blank" rel="noopener noreferrer">' . $item[ $column_name ] . '</a>';
@@ -93,6 +104,22 @@ class LogTable extends WP_List_Table {
93
 
94
  return ob_get_clean();
95
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  default:
97
  if ( empty( $item[ $column_name ] ) ) {
98
  return 'N/A';
45
  public function column_default( $item, $column_name ) {
46
  switch ( $column_name ) {
47
  case 'log_type':
48
+ $value = ! empty( $item[ $column_name ] ) ? $item[ $column_name ] : false;
49
+ if ( ! $value ) {
50
+ return 'N/A';
51
+ }
52
+
53
+ $type = '<span class="zerospam-type-' . $value . '">';
54
+
55
  $types = apply_filters( 'zerospam_types', array() );
56
+ if ( ! empty( $types[ $value ] ) ) {
57
+ $type .= $types[ $value ];
58
  } else {
59
+ $type .= $value;
60
  }
61
+
62
+ $type .= '</span>';
63
+
64
+ return $type;
65
  break;
66
  case 'user_ip':
67
  return '<a href="https://www.zerospam.org/ip-lookup/' . urlencode( $item[ $column_name ] ) .'" target="_blank" rel="noopener noreferrer">' . $item[ $column_name ] . '</a>';
104
 
105
  return ob_get_clean();
106
  break;
107
+ case 'country':
108
+ if ( ! empty( $item[ $column_name ] ) ) {
109
+ $country_name = ! empty( $item['country_name'] ) ? $item['country_name'] : false;
110
+ $flag = ZeroSpam\Core\Utilities::country_flag_url( $item[ $column_name ] );
111
+
112
+ $return = '<img src="' . $flag. '" width="16" height="16" alt="' . esc_attr( $country_name . ' (' . $item[ $column_name ] . ')' ) . '" class="zerospam-flag" />';
113
+ if ( $country_name ) {
114
+ $return .= $country_name . ' (' . $item[ $column_name ] . ')';
115
+ } else {
116
+ $return .= $item[ $column_name ];
117
+ }
118
+
119
+ return $return;
120
+ }
121
+ return 'N/A';
122
+ break;
123
  default:
124
  if ( empty( $item[ $column_name ] ) ) {
125
  return 'N/A';
core/class-access.php CHANGED
@@ -46,7 +46,6 @@ class Access {
46
  if ( ! empty( $access['blocked'] ) ) {
47
  $settings = ZeroSpam\Core\Settings::get_settings();
48
 
49
-
50
  if ( ! empty( $access['details'] ) && is_array( $access['details'] ) ) {
51
  if ( ! empty( $settings['share_data']['value'] ) && 'enabled' === $settings['share_data']['value'] ) {
52
  do_action( 'zerospam_share_blocked', $access['details'] );
@@ -93,6 +92,55 @@ class Access {
93
  }
94
  }
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  /**
97
  * Checks if an IP has been blocked.
98
  *
@@ -104,44 +152,30 @@ class Access {
104
  'blocked' => false,
105
  );
106
 
107
- $blocked = ZeroSpam\Includes\DB::blocked( $user_ip );
108
-
109
- if ( $blocked ) {
110
- $today = new \DateTime();
111
-
112
- // Check the start & end dates (all blocks require a start date).
113
- $start_date = new \DateTime();
114
- if ( ! empty( $blocked['start_block'] ) ) {
115
- $start_date = new \DateTime( $blocked['start_block'] );
116
- }
117
-
118
- if ( $today >= $start_date ) {
119
- // Check the end date if temporary block.
120
- if (
121
- ! empty( $blocked['blocked_type'] ) &&
122
- 'temporary' === $blocked['blocked_type']
123
- ) {
124
- // Temporary block.
125
- if ( ! empty( $blocked['end_block'] ) ) {
126
- $end_date = new \DateTime( $blocked['end_block'] );
127
-
128
- if ( $today < $end_date ) {
129
- $access_checks['blocked']['blocked'] = true;
130
- $access_checks['blocked']['type'] = 'blocked';
131
- $access_checks['blocked']['details'] = $blocked;
132
- $access_checks['blocked']['details']['failed'] = 'blocked_ips';
133
- }
134
  }
135
- } else {
136
- // Permanent block.
137
- $access_checks['blocked']['blocked'] = true;
138
- $access_checks['blocked']['type'] = 'blocked';
139
- $access_checks['blocked']['details'] = $blocked;
140
- $access_checks['blocked']['details']['failed'] = 'blocked_ips';
141
  }
142
  }
143
  }
144
 
 
 
 
 
 
 
 
 
 
145
  return $access_checks;
146
  }
147
 
46
  if ( ! empty( $access['blocked'] ) ) {
47
  $settings = ZeroSpam\Core\Settings::get_settings();
48
 
 
49
  if ( ! empty( $access['details'] ) && is_array( $access['details'] ) ) {
50
  if ( ! empty( $settings['share_data']['value'] ) && 'enabled' === $settings['share_data']['value'] ) {
51
  do_action( 'zerospam_share_blocked', $access['details'] );
92
  }
93
  }
94
 
95
+ /**
96
+ * Helper to get blocked record details.
97
+ */
98
+ public function get_blocked_details( $blocked_record, $failed = false ) {
99
+ $access_check = array(
100
+ 'blocked' => false,
101
+ );
102
+
103
+ if ( ! $blocked_record ) {
104
+ return $access_check;
105
+ }
106
+
107
+ $today = new \DateTime();
108
+
109
+ // Check the start & end dates (all blocks require a start date).
110
+ $start_date = new \DateTime();
111
+ if ( ! empty( $blocked_record['start_block'] ) ) {
112
+ $start_date = new \DateTime( $blocked_record['start_block'] );
113
+ }
114
+
115
+ if ( $today >= $start_date ) {
116
+ // Check the end date if temporary block.
117
+ if (
118
+ ! empty( $blocked_record['blocked_type'] ) &&
119
+ 'temporary' === $blocked_record['blocked_type']
120
+ ) {
121
+ // Temporary block.
122
+ if ( ! empty( $blocked_record['end_block'] ) ) {
123
+ $end_date = new \DateTime( $blocked_record['end_block'] );
124
+
125
+ if ( $today < $end_date ) {
126
+ $access_check['blocked'] = true;
127
+ $access_check['type'] = 'blocked';
128
+ $access_check['details'] = $blocked_record;
129
+ $access_check['details']['failed'] = $failed;
130
+ }
131
+ }
132
+ } else {
133
+ // Permanent block.
134
+ $access_check['blocked'] = true;
135
+ $access_check['type'] = 'blocked';
136
+ $access_check['details'] = $blocked_record;
137
+ $access_check['details']['failed'] = $failed;
138
+ }
139
+ }
140
+
141
+ return $access_check;
142
+ }
143
+
144
  /**
145
  * Checks if an IP has been blocked.
146
  *
152
  'blocked' => false,
153
  );
154
 
155
+ // Attempt to get the IP address location & checked if block.
156
+ $location = apply_filters( 'zerospam_get_location', $user_ip );
157
+ if ( $location ) {
158
+ $location_keys = array( 'country_code', 'region_code', 'city', 'zip' );
159
+ foreach ( $location_keys as $key => $loc ) {
160
+ if ( ! empty( $location[ $loc ] ) ) {
161
+ $blocked = ZeroSpam\Includes\DB::blocked( $location[ $loc ], $loc );
162
+ if ( $blocked ) {
163
+ $access_checks['blocked'] = self::get_blocked_details( $blocked, 'blocked_' . $loc );
164
+ break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  }
 
 
 
 
 
 
166
  }
167
  }
168
  }
169
 
170
+ // If passed location blocks, check the IP address.
171
+ if ( ! $access_checks['blocked'] ) {
172
+ // Check the user's IP access.
173
+ $blocked = ZeroSpam\Includes\DB::blocked( $user_ip );
174
+ if ( $blocked ) {
175
+ $access_checks['blocked'] = self::get_blocked_details( $blocked, 'blocked_ip' );
176
+ }
177
+ }
178
+
179
  return $access_checks;
180
  }
181
 
core/class-settings.php CHANGED
@@ -76,7 +76,19 @@ class Settings {
76
  'section' => 'improve',
77
  'type' => 'checkbox',
78
  'options' => array(
79
- 'enabled' => __( 'Become a super contributor by opting in to share non-sensitive plugin data.', 'zerospam' ),
 
 
 
 
 
 
 
 
 
 
 
 
80
  ),
81
  'value' => ! empty( $options['share_data'] ) ? $options['share_data'] : false,
82
  );
@@ -180,7 +192,7 @@ class Settings {
180
 
181
  if ( $key ) {
182
  if ( ! empty( $settings[ $key ]['value'] ) ) {
183
- return $key;
184
  }
185
 
186
  return false;
76
  'section' => 'improve',
77
  'type' => 'checkbox',
78
  'options' => array(
79
+ 'enabled' => sprintf(
80
+ wp_kses(
81
+ __( 'Become a super contributor by opting in to share non-sensitive plugin data. <a href="%s" target="_blank" rel="noreferrer noopener">Learn more</a>.', 'zerospam' ),
82
+ array(
83
+ 'a' => array(
84
+ 'target' => array(),
85
+ 'href' => array(),
86
+ 'rel' => array(),
87
+ ),
88
+ )
89
+ ),
90
+ esc_url( 'https://github.com/bmarshall511/wordpress-zero-spam/wiki/FAQ#what-data-is-shared-when-usage-data-sharing-is-enabled' )
91
+ ),
92
  ),
93
  'value' => ! empty( $options['share_data'] ) ? $options['share_data'] : false,
94
  );
192
 
193
  if ( $key ) {
194
  if ( ! empty( $settings[ $key ]['value'] ) ) {
195
+ return $settings[ $key ]['value'];
196
  }
197
 
198
  return false;
core/class-user.php CHANGED
@@ -11,22 +11,19 @@ namespace ZeroSpam\Core;
11
  defined( 'ABSPATH' ) || die();
12
 
13
  /**
14
- * Admin.
15
- *
16
- * Handles access checks.
17
  *
18
- * @since 5.0.0
19
  */
20
  class User {
21
 
22
  /**
23
  * Gets the current user's IP.
24
- *
25
- * @since 5.0.0
26
- * @access public
27
  */
28
  public static function get_ip() {
29
  $settings = Settings::get_settings();
 
 
30
  if (
31
  ! empty( $settings['debug']['value'] ) &&
32
  'enabled' === $settings['debug']['value'] &&
@@ -35,18 +32,25 @@ class User {
35
  return $settings['debug_ip']['value'];
36
  }
37
 
38
- if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
39
- $ip = $_SERVER['HTTP_CLIENT_IP'];
40
- } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
41
- $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
42
- } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED'] ) ) {
43
- $ip = $_SERVER['HTTP_X_FORWARDED'];
44
- } elseif ( ! empty( $_SERVER['HTTP_FORWARDED_FOR'] ) ) {
45
- $ip = $_SERVER['HTTP_FORWARDED_FOR'];
46
- } elseif ( ! empty( $_SERVER['HTTP_FORWARDED'] ) ) {
47
- $ip = $_SERVER['HTTP_FORWARDED'];
48
  } else {
49
- $ip = $_SERVER['REMOTE_ADDR'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  }
51
 
52
  $ip = explode( ',', $ip );
11
  defined( 'ABSPATH' ) || die();
12
 
13
  /**
14
+ * User class.
 
 
15
  *
16
+ * Handles getting user specific information.
17
  */
18
  class User {
19
 
20
  /**
21
  * Gets the current user's IP.
 
 
 
22
  */
23
  public static function get_ip() {
24
  $settings = Settings::get_settings();
25
+
26
+ // Check if a debugging IP is enabled.
27
  if (
28
  ! empty( $settings['debug']['value'] ) &&
29
  'enabled' === $settings['debug']['value'] &&
32
  return $settings['debug_ip']['value'];
33
  }
34
 
35
+ // Check against Cloudflare IPs.
36
+ if ( ! empty( $_SERVER['HTTP_CF_CONNECTING_IP'] ) ) {
37
+ $ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
 
 
 
 
 
 
 
38
  } else {
39
+
40
+ // Handle all other IPs.
41
+ if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
42
+ $ip = $_SERVER['HTTP_CLIENT_IP'];
43
+ } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
44
+ $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
45
+ } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED'] ) ) {
46
+ $ip = $_SERVER['HTTP_X_FORWARDED'];
47
+ } elseif ( ! empty( $_SERVER['HTTP_FORWARDED_FOR'] ) ) {
48
+ $ip = $_SERVER['HTTP_FORWARDED_FOR'];
49
+ } elseif ( ! empty( $_SERVER['HTTP_FORWARDED'] ) ) {
50
+ $ip = $_SERVER['HTTP_FORWARDED'];
51
+ } else {
52
+ $ip = $_SERVER['REMOTE_ADDR'];
53
+ }
54
  }
55
 
56
  $ip = explode( ',', $ip );
core/class-utilities.php CHANGED
@@ -19,6 +19,15 @@ defined( 'ABSPATH' ) || die();
19
  */
20
  class Utilities {
21
 
 
 
 
 
 
 
 
 
 
22
  /**
23
  * Outputs a honeypot field
24
  *
19
  */
20
  class Utilities {
21
 
22
+ /**
23
+ * Returns a country flag image URL.
24
+ *
25
+ * @access public
26
+ */
27
+ public static function country_flag_url( $country_code ) {
28
+ return 'https://hatscripts.github.io/circle-flags/flags/' . strtolower( $country_code ) . '.svg';
29
+ }
30
+
31
  /**
32
  * Outputs a honeypot field
33
  *
includes/class-db.php CHANGED
@@ -22,7 +22,7 @@ class DB {
22
  /**
23
  * Current DB version.
24
  */
25
- const DB_VERSION = '0.4';
26
 
27
  /**
28
  * DB tables.
@@ -83,7 +83,7 @@ class DB {
83
  blocked_type ENUM('permanent','temporary') NOT NULL DEFAULT 'temporary',
84
  user_ip VARCHAR(39) NOT NULL,
85
  blocked_key VARCHAR(255) NULL,
86
- key_type ENUM('ip','email') NOT NULL DEFAULT 'ip',
87
  date_added DATETIME NOT NULL,
88
  start_block DATETIME NULL DEFAULT NULL,
89
  end_block DATETIME NULL DEFAULT NULL,
@@ -123,7 +123,7 @@ class DB {
123
 
124
  if ( $blocked ) {
125
  // Update the record.
126
- $record['last_updated'] = current_time( 'mysql' );
127
  return $wpdb->update(
128
  $wpdb->prefix . self::$tables['blocked'],
129
  $record,
@@ -251,6 +251,8 @@ class DB {
251
 
252
  if ( is_numeric( $where['value'] ) ) {
253
  $where_stmt .= $where['value'];
 
 
254
  } else {
255
  $where_stmt .= '"' . $where['value'] . '"';
256
  }
22
  /**
23
  * Current DB version.
24
  */
25
+ const DB_VERSION = '0.7';
26
 
27
  /**
28
  * DB tables.
83
  blocked_type ENUM('permanent','temporary') NOT NULL DEFAULT 'temporary',
84
  user_ip VARCHAR(39) NOT NULL,
85
  blocked_key VARCHAR(255) NULL,
86
+ key_type ENUM('ip','email','username','country_code','region_code','zip') NOT NULL DEFAULT 'ip',
87
  date_added DATETIME NOT NULL,
88
  start_block DATETIME NULL DEFAULT NULL,
89
  end_block DATETIME NULL DEFAULT NULL,
123
 
124
  if ( $blocked ) {
125
  // Update the record.
126
+ $record['date_added'] = current_time( 'mysql' );
127
  return $wpdb->update(
128
  $wpdb->prefix . self::$tables['blocked'],
129
  $record,
251
 
252
  if ( is_numeric( $where['value'] ) ) {
253
  $where_stmt .= $where['value'];
254
+ } elseif( is_array( $where['value'] ) ) {
255
+ $where_stmt .= "('" . implode( "','", $where['value'] ) . "')";
256
  } else {
257
  $where_stmt .= '"' . $where['value'] . '"';
258
  }
includes/class-plugin.php CHANGED
@@ -19,6 +19,8 @@ use ZeroSpam\Modules\Zero_Spam;
19
  use ZeroSpam\Modules\Registration\Registration;
20
  use ZeroSpam\Modules\Comments\Comments;
21
  use ZeroSpam\Modules\ContactForm7\ContactForm7;
 
 
22
 
23
  // Security Note: Blocks direct access to the plugin PHP files.
24
  defined( 'ABSPATH' ) || die();
@@ -147,6 +149,17 @@ class Plugin {
147
  new ContactForm7();
148
  }
149
 
 
 
 
 
 
 
 
 
 
 
 
150
  //= new BotScout();
151
  new StopForumSpam();
152
  new ipstack();
19
  use ZeroSpam\Modules\Registration\Registration;
20
  use ZeroSpam\Modules\Comments\Comments;
21
  use ZeroSpam\Modules\ContactForm7\ContactForm7;
22
+ use ZeroSpam\Modules\WooCommerce\WooCommerce;
23
+ use ZeroSpam\Modules\WPForms\WPForms;
24
 
25
  // Security Note: Blocks direct access to the plugin PHP files.
26
  defined( 'ABSPATH' ) || die();
149
  new ContactForm7();
150
  }
151
 
152
+ if ( is_plugin_active( 'woocommerce/woocommerce.php' ) ) {
153
+ new WooCommerce();
154
+ }
155
+
156
+ if (
157
+ is_plugin_active( 'wpforms-lite/wpforms.php' ) ||
158
+ is_plugin_active( 'wpforms/wpforms.php' )
159
+ ) {
160
+ new WPForms();
161
+ }
162
+
163
  //= new BotScout();
164
  new StopForumSpam();
165
  new ipstack();
includes/templates/admin-block-ip.php CHANGED
@@ -7,20 +7,43 @@
7
  */
8
  ?>
9
 
10
- <form method="post" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>">
11
  <?php wp_nonce_field( 'zerospam', 'zerospam' ); ?>
12
  <input type="hidden" name="action" value="add_blocked_ip" />
13
  <input type="hidden" name="redirect" value="<?php echo esc_url( ZeroSpam\Core\Utilities::current_url() ); ?>" />
14
 
15
- <label for="blocked-ip">
16
- <?php _e( 'IP Address', 'zerospam' ); ?>
17
- <input
18
- type="text"
19
- name="blocked_ip"
20
- value="<?php if( ! empty( $_REQUEST['ip'] ) ) : echo esc_attr( $_REQUEST['ip'] ); endif; ?>"
21
- placeholder="e.g. xxx.xxx.x.x"
22
- />
23
- </label>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  <label for="blocked-type"><?php _e( 'Type', 'zerospam' ); ?>
26
  <select id="blocked-type" name="blocked_type">
7
  */
8
  ?>
9
 
10
+ <form method="post" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>"<?php if ( ! empty( $location_form ) ) : ?> class="zerospam-block-location-form"<?php endif; ?>>
11
  <?php wp_nonce_field( 'zerospam', 'zerospam' ); ?>
12
  <input type="hidden" name="action" value="add_blocked_ip" />
13
  <input type="hidden" name="redirect" value="<?php echo esc_url( ZeroSpam\Core\Utilities::current_url() ); ?>" />
14
 
15
+ <?php if ( empty( $location_form ) ) : ?>
16
+ <label for="blocked-ip">
17
+ <?php _e( 'IP Address', 'zerospam' ); ?>
18
+ <input
19
+ type="text"
20
+ name="blocked_ip"
21
+ value="<?php if( ! empty( $_REQUEST['ip'] ) ) : echo esc_attr( $_REQUEST['ip'] ); endif; ?>"
22
+ placeholder="e.g. xxx.xxx.x.x"
23
+ />
24
+ </label>
25
+ <?php else: ?>
26
+ <label for="location-type">
27
+ <?php _e( 'Location Type', 'zerospam' ); ?>
28
+ <select id="location-type" name="key_type">
29
+ <option value="country_code"><?php _e( 'Country Code', 'zerospam' ); ?></option>
30
+ <option value="region_code"><?php _e( 'Region Code', 'zerospam' ); ?></option>
31
+ <option value="city"><?php _e( 'City Name', 'zerospam' ); ?></option>
32
+ <option value="zip"><?php _e( 'Zip/Postal Code', 'zerospam' ); ?></option>
33
+ </select>
34
+ </label>
35
+
36
+ <label for="location-key">
37
+ <?php _e( 'Location Key', 'zerospam' ); ?>
38
+ <input
39
+ id="location-key"
40
+ type="text"
41
+ name="blocked_key"
42
+ value=""
43
+ placeholder="ex. US"
44
+ />
45
+ </label>
46
+ <?php endif; ?>
47
 
48
  <label for="blocked-type"><?php _e( 'Type', 'zerospam' ); ?>
49
  <select id="blocked-type" name="blocked_type">
includes/templates/admin-modal-details.php CHANGED
@@ -37,16 +37,23 @@
37
  do_action( 'zerospam_google_map', $coordinates );
38
  ?>
39
  <ul class="zerospam-modal-list">
40
- <?php if ( ! empty( $item['country_name'] ) || ! empty( $item['country'] ) ) : ?>
41
  <li>
42
  <strong><?php echo __( 'Country', 'zerospam' ); ?></strong>
43
  <span>
44
- <?php if ( ! empty( $item['country_name'] ) ) : ?>
45
- <?php echo $item['country_name']; ?>
46
- <?php endif; ?>
47
- <?php if ( ! empty( $item['country'] ) ) : ?>
48
- (<?php echo $item['country']; ?>)
49
- <?php endif; ?>
 
 
 
 
 
 
 
50
  </span>
51
  </li>
52
  <?php endif; ?>
@@ -97,12 +104,22 @@
97
 
98
  <h4 class="zerospam-modal-headline"><?php echo __( 'Additional Details', 'zerospam' ); ?></h4>
99
  <?php
 
100
  if ( ! empty( $item['submission_data'] ) ) :
101
  $submission_data = json_decode( $item['submission_data'], true );
102
  echo '<ul class="zerospam-modal-list">';
103
  foreach ( $submission_data as $key => $value ) :
104
  ?>
105
- <li><strong><?php echo $key; ?></strong> <span><?php echo $value; ?></span></li>
 
 
 
 
 
 
 
 
 
106
  <?php
107
  endforeach;
108
  echo '</ul>';
37
  do_action( 'zerospam_google_map', $coordinates );
38
  ?>
39
  <ul class="zerospam-modal-list">
40
+ <?php if ( ! empty( $item['country'] ) ) : ?>
41
  <li>
42
  <strong><?php echo __( 'Country', 'zerospam' ); ?></strong>
43
  <span>
44
+ <?php
45
+ $country_name = ! empty( $item['country_name'] ) ? $item['country_name'] : false;
46
+ $flag = ZeroSpam\Core\Utilities::country_flag_url( $item['country'] );
47
+
48
+ $country = '<img src="' . $flag . '" width="16" height="16" alt="' . esc_attr( $country_name . ' (' . $item['country'] . ')' ) . '" class="zerospam-flag" />';
49
+ if ( $country_name ) {
50
+ $country .= $country_name . ' (' . $item['country'] . ')';
51
+ } else {
52
+ $country .= $item['country'];
53
+ }
54
+
55
+ echo $country;
56
+ ?>
57
  </span>
58
  </li>
59
  <?php endif; ?>
104
 
105
  <h4 class="zerospam-modal-headline"><?php echo __( 'Additional Details', 'zerospam' ); ?></h4>
106
  <?php
107
+
108
  if ( ! empty( $item['submission_data'] ) ) :
109
  $submission_data = json_decode( $item['submission_data'], true );
110
  echo '<ul class="zerospam-modal-list">';
111
  foreach ( $submission_data as $key => $value ) :
112
  ?>
113
+ <li>
114
+ <strong><?php echo $key; ?></strong>
115
+ <span>
116
+ <?php if ( is_array( $value ) ) : ?>
117
+ <?php echo wp_json_encode( $value ); ?>
118
+ <?php else : ?>
119
+ <?php echo $value; ?>
120
+ <?php endif; ?>
121
+ </span>
122
+ </li>
123
  <?php
124
  endforeach;
125
  echo '</ul>';
modules/class-ipstack.php CHANGED
@@ -28,6 +28,7 @@ class ipstack {
28
  add_filter( 'zerospam_setting_sections', array( $this, 'sections' ) );
29
  add_filter( 'zerospam_settings', array( $this, 'settings' ) );
30
  add_filter( 'zerospam_log_record', array( $this, 'log_record' ) );
 
31
  }
32
 
33
  /**
28
  add_filter( 'zerospam_setting_sections', array( $this, 'sections' ) );
29
  add_filter( 'zerospam_settings', array( $this, 'settings' ) );
30
  add_filter( 'zerospam_log_record', array( $this, 'log_record' ) );
31
+ add_filter( 'zerospam_get_location', array( $this, 'get_geolocation' ), 10, 1 );
32
  }
33
 
34
  /**
modules/contactform7/class-contactform7.php CHANGED
@@ -114,11 +114,11 @@ class ContactForm7 {
114
  $options = get_option( 'wpzerospam' );
115
 
116
  $settings['verify_contactform7'] = array(
117
- 'title' => __( 'Detect Contact Form 7 Submissions', 'zerospam' ),
118
  'section' => 'contactform7',
119
  'type' => 'checkbox',
120
  'options' => array(
121
- 'enabled' => __( 'Monitor Contact Form 7 form submissions for malicious or automated spambots.', 'zerospam' ),
122
  ),
123
  'value' => ! empty( $options['verify_contactform7'] ) ? $options['verify_contactform7'] : false,
124
  );
114
  $options = get_option( 'wpzerospam' );
115
 
116
  $settings['verify_contactform7'] = array(
117
+ 'title' => __( 'Protect Contact Form 7 Submissions', 'zerospam' ),
118
  'section' => 'contactform7',
119
  'type' => 'checkbox',
120
  'options' => array(
121
+ 'enabled' => __( 'Monitor Contact Form 7 submissions for malicious or automated spambots.', 'zerospam' ),
122
  ),
123
  'value' => ! empty( $options['verify_contactform7'] ) ? $options['verify_contactform7'] : false,
124
  );
modules/registration/class-registration.php CHANGED
@@ -34,7 +34,7 @@ class Registration {
34
  $settings = ZeroSpam\Core\Settings::get_settings();
35
  if ( ! empty( $settings['verify_registrations']['value'] ) && 'enabled' === $settings['verify_registrations']['value'] ) {
36
  add_action( 'register_form', array( $this, 'honeypot' ) );
37
- add_filter( 'registration_errors', array( $this, 'preprocess_registrations' ), 10, 3 );
38
  }
39
  }
40
  }
@@ -57,7 +57,7 @@ class Registration {
57
  * @since 5.0.0
58
  * @access public
59
  */
60
- public function preprocess_registrations( $errors, $sanitized_user_login, $user_email ) {
61
  $settings = ZeroSpam\Core\Settings::get_settings();
62
  $honeypot = ZeroSpam\Core\Utilities::get_honeypot();
63
 
@@ -112,7 +112,7 @@ class Registration {
112
  }
113
 
114
  /**
115
- * Botscout settings.
116
  *
117
  * @since 5.0.0
118
  * @access public
34
  $settings = ZeroSpam\Core\Settings::get_settings();
35
  if ( ! empty( $settings['verify_registrations']['value'] ) && 'enabled' === $settings['verify_registrations']['value'] ) {
36
  add_action( 'register_form', array( $this, 'honeypot' ) );
37
+ add_filter( 'registration_errors', array( $this, 'preprocess_registration' ), 10, 3 );
38
  }
39
  }
40
  }
57
  * @since 5.0.0
58
  * @access public
59
  */
60
+ public function preprocess_registration( $errors, $sanitized_user_login, $user_email ) {
61
  $settings = ZeroSpam\Core\Settings::get_settings();
62
  $honeypot = ZeroSpam\Core\Utilities::get_honeypot();
63
 
112
  }
113
 
114
  /**
115
+ * Registration settings.
116
  *
117
  * @since 5.0.0
118
  * @access public
modules/woocommerce/class-woocommerce.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WooCommerce class.
4
+ *
5
+ * @package ZeroSpam
6
+ */
7
+
8
+ namespace ZeroSpam\Modules\WooCommerce;
9
+
10
+ use ZeroSpam;
11
+
12
+ // Security Note: Blocks direct access to the plugin PHP files.
13
+ defined( 'ABSPATH' ) || die();
14
+
15
+ /**
16
+ * WooCommerce.
17
+ */
18
+ class WooCommerce {
19
+ /**
20
+ * WooCommerce constructor.
21
+ */
22
+ public function __construct() {
23
+ add_filter( 'zerospam_setting_sections', array( $this, 'sections' ) );
24
+ add_filter( 'zerospam_settings', array( $this, 'settings' ) );
25
+ add_filter( 'zerospam_types', array( $this, 'types' ), 10, 1 );
26
+
27
+ $settings = ZeroSpam\Core\Settings::get_settings();
28
+ if ( ! empty( $settings['woocommerce_protection']['value'] ) && 'enabled' === $settings['woocommerce_protection']['value'] ) {
29
+ $settings = ZeroSpam\Core\Settings::get_settings();
30
+ if ( ! empty( $settings['verify_registrations']['value'] ) && 'enabled' === $settings['verify_registrations']['value'] ) {
31
+ add_action( 'woocommerce_register_form', array( $this, 'honeypot' ) );
32
+ add_action( 'woocommerce_register_post', array( $this, 'preprocess_registration' ), 10, 3 );
33
+ }
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Add to the types array.
39
+ */
40
+ public function types( $types ) {
41
+ $types['woocommerce_registration'] = __( 'Registration (WooCommerce)', 'zerospam' );
42
+
43
+ return $types;
44
+ }
45
+
46
+ /**
47
+ * Registration sections.
48
+ */
49
+ public function sections( $sections ) {
50
+ $sections['woocommerce'] = array(
51
+ 'title' => __( 'WooCommerce Settings', 'zerospam' ),
52
+ );
53
+
54
+ return $sections;
55
+ }
56
+
57
+ /**
58
+ * WooCommerce settings.
59
+ */
60
+ public function settings( $settings ) {
61
+ $options = get_option( 'wpzerospam' );
62
+
63
+ $settings['woocommerce_protection'] = array(
64
+ 'title' => __( 'WooCommerce Protection', 'zerospam' ),
65
+ 'section' => 'woocommerce',
66
+ 'type' => 'checkbox',
67
+ 'desc' => __( 'Enables integration with the WooCommerce.', 'zerospam' ),
68
+ 'options' => array(
69
+ 'enabled' => __( 'Enabled', 'zerospam' ),
70
+ ),
71
+ 'value' => ! empty( $options['woocommerce_protection'] ) ? $options['woocommerce_protection'] : false,
72
+ );
73
+
74
+ return $settings;
75
+ }
76
+
77
+ /**
78
+ * Add a 'honeypot' field to the WooCommerce registration form.
79
+ */
80
+ public function honeypot() {
81
+ $honeypot = ZeroSpam\Core\Utilities::get_honeypot();
82
+
83
+ woocommerce_form_field(
84
+ $honeypot,
85
+ array( 'type' => 'hidden' )
86
+ );
87
+ }
88
+
89
+ /**
90
+ * Preprocess registrations.
91
+ */
92
+ public function preprocess_registration( $username, $email, $errors ) {
93
+ $settings = ZeroSpam\Core\Settings::get_settings();
94
+ $honeypot = ZeroSpam\Core\Utilities::get_honeypot();
95
+
96
+ // Check honeypot.
97
+ if (
98
+ ! empty( $_REQUEST[ $honeypot ] )
99
+ ) {
100
+ $message = __( 'You have been flagged as spam/malicious by WordPress Zero Spam.', 'zerospam' );
101
+ if ( ! empty( $settings['registration_spam_message']['value'] ) ) {
102
+ $message = $settings['registration_spam_message']['value'];
103
+ }
104
+ $errors->add( 'zerospam_error', __( $message, 'zerospam' ) );
105
+
106
+ if ( ! empty( $settings['log_blocked_registrations']['value'] ) && 'enabled' === $settings['log_blocked_registrations']['value'] ) {
107
+ $details = array(
108
+ 'user_login' => $username,
109
+ 'user_email' => $email,
110
+ 'failed' => 'honeypot',
111
+ );
112
+ ZeroSpam\Includes\DB::log( 'woocommerce_registration', $details );
113
+ }
114
+ }
115
+
116
+ $errors = apply_filters( 'zerospam_registration_errors', $errors, $username, $email );
117
+
118
+ return $errors;
119
+ }
120
+ }
modules/wpforms/class-wpforms.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WPForms class.
4
+ *
5
+ * @package ZeroSpam
6
+ */
7
+
8
+ namespace ZeroSpam\Modules\WPForms;
9
+
10
+ use ZeroSpam;
11
+
12
+ // Security Note: Blocks direct access to the plugin PHP files.
13
+ defined( 'ABSPATH' ) || die();
14
+
15
+ /**
16
+ * WPForms.
17
+ */
18
+ class WPForms {
19
+ /**
20
+ * WooCommerce constructor.
21
+ */
22
+ public function __construct() {
23
+ add_filter( 'zerospam_setting_sections', array( $this, 'sections' ) );
24
+ add_filter( 'zerospam_settings', array( $this, 'settings' ) );
25
+ add_filter( 'zerospam_types', array( $this, 'types' ), 10, 1 );
26
+
27
+ if ( 'enabled' === ZeroSpam\Core\Settings::get_settings('verify_wpforms') ) {
28
+ add_action( 'wpforms_frontend_output', array( $this, 'honeypot' ), 10, 1 );
29
+ add_action( 'wpforms_process', array( $this, 'preprocess_submission' ), 10, 3 );
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Add to the types array.
35
+ */
36
+ public function types( $types ) {
37
+ $types['wpforms'] = __( 'WPForms', 'zerospam' );
38
+
39
+ return $types;
40
+ }
41
+
42
+ /**
43
+ * Registration sections.
44
+ */
45
+ public function sections( $sections ) {
46
+ $sections['wpforms'] = array(
47
+ 'title' => __( 'WPForms Settings', 'zerospam' ),
48
+ );
49
+
50
+ return $sections;
51
+ }
52
+
53
+ /**
54
+ * WPForms settings.
55
+ *
56
+ * Registers WPForms setting fields.
57
+ *
58
+ * @param array $settings Array of WordPress Zero Spam settings.
59
+ */
60
+ public function settings( $settings ) {
61
+ $options = get_option( 'wpzerospam' );
62
+
63
+ $settings['verify_wpforms'] = array(
64
+ 'title' => __( 'Protect WPForms Submissions', 'zerospam' ),
65
+ 'section' => 'wpforms',
66
+ 'type' => 'checkbox',
67
+ 'options' => array(
68
+ 'enabled' => __( 'Monitor WPForms submissions for malicious or automated spambots.', 'zerospam' ),
69
+ ),
70
+ 'value' => ! empty( $options['verify_wpforms'] ) ? $options['verify_wpforms'] : false,
71
+ );
72
+
73
+ if ( ! empty( $options['verify_wpforms'] ) && 'enabled' === $options['verify_wpforms'] ) {
74
+ $message = __( 'You have been flagged as spam/malicious by WordPress Zero Spam.', 'zerospam' );
75
+ $settings['wpforms_spam_message'] = array(
76
+ 'title' => __( 'WPForms Spam/Malicious Message', 'zerospam' ),
77
+ 'desc' => __( 'Displayed to the user when a submission is detected as spam/malicious.', 'zerospam' ),
78
+ 'section' => 'wpforms',
79
+ 'type' => 'text',
80
+ 'field_class' => 'large-text',
81
+ 'placeholder' => $message,
82
+ 'value' => ! empty( $options['wpforms_spam_message'] ) ? $options['wpforms_spam_message'] : $message,
83
+ );
84
+ }
85
+
86
+ $settings['log_blocked_wpforms'] = array(
87
+ 'title' => __( 'Log Blocked WPForms Submissions', 'zerospam' ),
88
+ 'section' => 'wpforms',
89
+ 'type' => 'checkbox',
90
+ 'desc' => __( 'Enables logging blocked WPForms submissions. High traffic sites should leave this disabled.', 'zerospam' ),
91
+ 'options' => array(
92
+ 'enabled' => __( 'Enabled', 'zerospam' ),
93
+ ),
94
+ 'value' => ! empty( $options['log_blocked_wpforms'] ) ? $options['log_blocked_wpforms'] : false,
95
+ );
96
+
97
+ return $settings;
98
+ }
99
+
100
+ /**
101
+ * Add a 'honeypot' field to the form.
102
+ *
103
+ * @param array $form_data Form data and settings.
104
+ */
105
+ public function honeypot( $form_data ) {
106
+ echo ZeroSpam\Core\Utilities::honeypot_field();
107
+ }
108
+
109
+ /**
110
+ * Preprocess submission.
111
+ */
112
+ public function preprocess_submission( $entry, $form_data ) {
113
+ $settings = ZeroSpam\Core\Settings::get_settings();
114
+ $honeypot = ZeroSpam\Core\Utilities::get_honeypot();
115
+
116
+ // Check honeypot.
117
+ if (
118
+ ! empty( $_REQUEST[ $honeypot ] )
119
+ ) {
120
+ $message = __( 'You have been flagged as spam/malicious by WordPress Zero Spam.', 'zerospam' );
121
+ if ( ! empty( $settings['wpforms_spam_message']['value'] ) ) {
122
+ $message = $settings['wpforms_spam_message']['value'];
123
+ }
124
+
125
+ wpforms()->process->errors[ $form_data['id'] ][0] = $message;
126
+
127
+ if ( ! empty( $settings['log_blocked_wpforms']['value'] ) && 'enabled' === $settings['log_blocked_wpforms']['value'] ) {
128
+ $details = $entry;
129
+ $details = array_merge( $details, $form_data );
130
+
131
+ $details['failed'] = 'honeypot';
132
+ ZeroSpam\Includes\DB::log( 'wpforms', $details );
133
+ }
134
+ }
135
+ }
136
+ }
readme.txt CHANGED
@@ -5,7 +5,7 @@ Donate link: https://www.benmarshall.me/donate/?utm_source=wordpress_zero_spam&u
5
  Requires at least: 5.2
6
  Tested up to: 5.6.2
7
  Requires PHP: 7.3
8
- Stable tag: 5.0.1
9
  License: GNU GPLv3
10
  License URI: https://choosealicense.com/licenses/gpl-3.0/
11
 
@@ -27,6 +27,7 @@ Quit forcing people to answer questions or confusing captchas to prove they're n
27
  * IP blacklist spam checks ([Zero Spam](https://www.zerospam.org), [Stop Forum Spam](https://www.stopforumspam.com/))
28
  * Automatically & manually block IPs temporarily or permanently
29
  * Geolocate IP addresses to see where offenders are coming from
 
30
  * Detailed logging to catch, investigate & block recurring offenders
31
  * Developer-friendly, integrate with any theme, plugin or form
32
 
@@ -34,6 +35,8 @@ Quit forcing people to answer questions or confusing captchas to prove they're n
34
 
35
  * WordPress core comments & user registrations
36
  * [Contact Form 7](https://wordpress.org/plugins/contact-form-7/) submissions
 
 
37
  * and can be easily integrated into any existing theme or plugin
38
 
39
  WordPress Zero Spam is great at blocking spam &mdash; as a site owner there's more you can do to [stop WordPress spam](https://www.benmarshall.me/stop-wordpress-spam/) in its tracks.
@@ -70,6 +73,15 @@ For more information & developer documentation, see the [plugin’s website](htt
70
 
71
  == Changelog ==
72
 
 
 
 
 
 
 
 
 
 
73
  = v5.0.1 =
74
 
75
  * Updated readme file & documentation
5
  Requires at least: 5.2
6
  Tested up to: 5.6.2
7
  Requires PHP: 7.3
8
+ Stable tag: 5.0.2
9
  License: GNU GPLv3
10
  License URI: https://choosealicense.com/licenses/gpl-3.0/
11
 
27
  * IP blacklist spam checks ([Zero Spam](https://www.zerospam.org), [Stop Forum Spam](https://www.stopforumspam.com/))
28
  * Automatically & manually block IPs temporarily or permanently
29
  * Geolocate IP addresses to see where offenders are coming from
30
+ * Block entire countries, regions, zip/postal codes & cities
31
  * Detailed logging to catch, investigate & block recurring offenders
32
  * Developer-friendly, integrate with any theme, plugin or form
33
 
35
 
36
  * WordPress core comments & user registrations
37
  * [Contact Form 7](https://wordpress.org/plugins/contact-form-7/) submissions
38
+ * [WooCommerce](https://woocommerce.com/) registration forms
39
+ * [WPForms](https://wordpress.org/plugins/wpforms-lite/) submissions
40
  * and can be easily integrated into any existing theme or plugin
41
 
42
  WordPress Zero Spam is great at blocking spam &mdash; as a site owner there's more you can do to [stop WordPress spam](https://www.benmarshall.me/stop-wordpress-spam/) in its tracks.
73
 
74
  == Changelog ==
75
 
76
+ = v5.0.2 =
77
+
78
+ * Admin UI enhancements
79
+ * Added support for WooCommerce
80
+ * Added Cloudflare IP address support (https://github.com/bmarshall511/wordpress-zero-spam/issues/220)
81
+ * Update to data sharing option
82
+ * Added ability to block individual locations (country, region, zip & city)
83
+ * Added support for WPForms
84
+
85
  = v5.0.1 =
86
 
87
  * Updated readme file & documentation
uninstall.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Handles uninstalling the plugin
4
  *
5
- * @package WordPressZeroSpam
6
  */
7
 
8
  // Security Note: Blocks direct access to the plugin PHP files.
2
  /**
3
  * Handles uninstalling the plugin
4
  *
5
+ * @package ZeroSpam
6
  */
7
 
8
  // Security Note: Blocks direct access to the plugin PHP files.
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: 5.0.1
17
  * Requires at least: 5.2
18
  * Requires PHP: 7.3
19
  * Author: Ben Marshall
@@ -31,7 +31,7 @@ defined( 'ABSPATH' ) || die();
31
  define( 'ZEROSPAM', __FILE__ );
32
  define( 'ZEROSPAM_PATH', plugin_dir_path( ZEROSPAM ) );
33
  define( 'ZEROSPAM_PLUGIN_BASE', plugin_basename( ZEROSPAM ) );
34
- define( 'ZEROSPAM_VERSION', '5.0.1' );
35
 
36
  add_action( 'plugins_loaded', 'zerospam_load_plugin_textdomain' );
37
 
@@ -67,7 +67,7 @@ function zerospam_load_plugin_textdomain() {
67
  */
68
  function zerospam_fail_php_version() {
69
  /* translators: %s: PHP version */
70
- $message = sprintf( esc_html__( 'WordPress Zero Spam requires PHP version %s+, plugin is currently NOT RUNNING.', 'zerospam' ), '7.2' );
71
  $html_message = sprintf( '<div class="error">%s</div>', wpautop( $message ) );
72
  echo wp_kses_post( $html_message );
73
  }
@@ -83,7 +83,7 @@ function zerospam_fail_php_version() {
83
  */
84
  function zerospam_fail_wp_version() {
85
  /* translators: %s: WordPress version */
86
- $message = sprintf( esc_html__( 'WordPress Zero Spam requires WordPress version %s+. Because you are using an earlier version, the plugin is currently NOT RUNNING.', 'zerospam' ), '5.2' );
87
  $html_message = sprintf( '<div class="error">%s</div>', wpautop( $message ) );
88
  echo wp_kses_post( $html_message );
89
  }
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: 5.0.2
17
  * Requires at least: 5.2
18
  * Requires PHP: 7.3
19
  * Author: Ben Marshall
31
  define( 'ZEROSPAM', __FILE__ );
32
  define( 'ZEROSPAM_PATH', plugin_dir_path( ZEROSPAM ) );
33
  define( 'ZEROSPAM_PLUGIN_BASE', plugin_basename( ZEROSPAM ) );
34
+ define( 'ZEROSPAM_VERSION', '5.0.2' );
35
 
36
  add_action( 'plugins_loaded', 'zerospam_load_plugin_textdomain' );
37
 
67
  */
68
  function zerospam_fail_php_version() {
69
  /* translators: %s: PHP version */
70
+ $message = sprintf( esc_html__( 'WordPress Zero Spam requires PHP version %s+, plugin is currently NOT RUNNING.', 'zerospam' ), '7.3' );
71
  $html_message = sprintf( '<div class="error">%s</div>', wpautop( $message ) );
72
  echo wp_kses_post( $html_message );
73
  }
83
  */
84
  function zerospam_fail_wp_version() {
85
  /* translators: %s: WordPress version */
86
+ $message = sprintf( esc_html__( 'WordPress Zero Spam requires WordPress version %s+. Because you are using an earlier version, the plugin is currently NOT RUNNING.', 'zerospam' ), '5' );
87
  $html_message = sprintf( '<div class="error">%s</div>', wpautop( $message ) );
88
  echo wp_kses_post( $html_message );
89
  }