WordPress Zero Spam - Version 5.2.7

Version Description

Download this release

Release Info

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

Code changes from version 5.2.6 to 5.2.7

assets/css/admin.css CHANGED
@@ -2,6 +2,19 @@
2
  --zerospam-primary: #840012;
3
  }
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  .zerospam-flag {
6
  display: inline-block;
7
  margin-right: 8px;
@@ -307,13 +320,7 @@
307
  }
308
 
309
  .zerospam-callout-col {
310
- flex-grow: 1;
311
  padding: 30px;
312
- }
313
-
314
- .zerospam-callout-col:last-child {
315
- flex-shrink: 0;
316
- max-width: 600px;
317
  width: 100%;
318
  }
319
  }
2
  --zerospam-primary: #840012;
3
  }
4
 
5
+ .zerospam-new-window-link::after {
6
+ background-image: url('../img/icon-new-window.svg');
7
+ background-position: center;
8
+ background-repeat: no-repeat;
9
+ background-size: contain;
10
+ content: '';
11
+ display: inline-block;
12
+ height: 11px;
13
+ margin-left: 3px;
14
+ vertical-align: middle;
15
+ width: 11px;
16
+ }
17
+
18
  .zerospam-flag {
19
  display: inline-block;
20
  margin-right: 8px;
320
  }
321
 
322
  .zerospam-callout-col {
 
323
  padding: 30px;
 
 
 
 
 
324
  width: 100%;
325
  }
326
  }
assets/img/icon-new-window.svg ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+ <title>icon-new-window</title>
4
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
5
+ <g id="icon-new-window" fill="#2271B1" fill-rule="nonzero">
6
+ <path d="M2,0 C0.9069372,0 0,0.9069372 0,2 L0,16 C0,17.093063 0.9069372,18 2,18 L16,18 C17.093063,18 18,17.093063 18,16 L18,9 L16,9 L16,16 L2,16 L2,2 L9,2 L9,0 L2,0 Z M11,0 L11,2 L14.585938,2 L5.2929688,11.292969 L6.7070312,12.707031 L16,3.4140625 L16,7 L18,7 L18,0 L11,0 Z" id="Shape"></path>
7
+ </g>
8
+ </g>
9
+ </svg>
core/admin/class-admin.php CHANGED
@@ -33,12 +33,7 @@ class Admin {
33
  add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ) );
34
  add_action( 'admin_enqueue_scripts', array( $this, 'scripts' ) );
35
  add_action( 'wp_dashboard_setup', array( $this, 'register_dashboard_widget' ) );
36
-
37
- // Check first-time config.
38
- $configured = get_option( 'zerospam_configured' );
39
- if ( ! $configured ) {
40
- add_action( 'admin_notices', array( $this, 'not_configured_notice' ) );
41
- }
42
  }
43
 
44
  /**
@@ -119,26 +114,78 @@ class Admin {
119
  /**
120
  * Display not configured notice
121
  */
122
- public function not_configured_notice() {
123
- $message = sprintf(
124
- wp_kses(
125
- /* translators: %s: url */
126
- __( 'Thanks for installing WordPress Zero Spam! Visit the <a href="%1$s">setting page</a> to configure your site\'s protection level or <strong><a href="%2$s">click here</a> to automatically configure recommended settings</strong>. For enhanced protection, get a <a href="%3$s" target="_blank">Zero Spam premium license</a>.', 'zerospam' ),
127
- array(
128
- 'strong' => array(),
129
- 'a' => array(
130
- 'href' => array(),
131
- 'target' => array(),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  ),
133
- )
134
- ),
135
- esc_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings' ) ),
136
- esc_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=auto-configure' ) ),
137
- esc_url( ZEROSPAM_URL . 'product/premium/' )
138
- );
139
-
140
- $class = 'notice notice-success';
141
- printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), $message );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  }
143
 
144
  /**
33
  add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ) );
34
  add_action( 'admin_enqueue_scripts', array( $this, 'scripts' ) );
35
  add_action( 'wp_dashboard_setup', array( $this, 'register_dashboard_widget' ) );
36
+ add_action( 'admin_notices', array( $this, 'admin_notices' ) );
 
 
 
 
 
37
  }
38
 
39
  /**
114
  /**
115
  * Display not configured notice
116
  */
117
+ public function admin_notices() {
118
+ $messages = array();
119
+
120
+ // Check Zero Spam license key.
121
+ $zerospam_protection = \ZeroSpam\Core\Settings::get_settings( 'zerospam' );
122
+ if ( 'enabled' === $zerospam_protection ) {
123
+ $zerospam_license_key = \ZeroSpam\Core\Settings::get_settings( 'zerospam_license' );
124
+ if ( ! $zerospam_license_key ) {
125
+ $messages['license'] = array(
126
+ 'type' => 'error',
127
+ 'dismissible' => false,
128
+ 'content' => sprintf(
129
+ wp_kses(
130
+ /* translators: %1$s: Replaced with the Zero Spam settings page URL */
131
+ __( 'Zero Spam Enhanced Protection is currenlty enabled, but <strong>missing a valid license key</strong>. <a href="%1$s">Add your license key</a> to enable enhanced site protection.', 'zerospam' ),
132
+ array(
133
+ 'strong' => array(),
134
+ 'a' => array(
135
+ 'href' => array(),
136
+ 'target' => array(),
137
+ ),
138
+ )
139
+ ),
140
+ esc_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings' ) ),
141
+ esc_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=auto-configure' ) ),
142
+ esc_url( ZEROSPAM_URL . 'product/premium/' )
143
+ ),
144
+ );
145
+ }
146
+ }
147
+
148
+ // Check if the plugin has been auto-configured.
149
+ $configured = get_option( 'zerospam_configured' );
150
+ if ( ! $configured ) {
151
+ $messages['configuration'] = array(
152
+ 'type' => 'info',
153
+ 'dismissible' => true,
154
+ 'content' => sprintf(
155
+ wp_kses(
156
+ /* translators: %1$s: Replaced with the Zero Spam settings page URL */
157
+ __( '<strong>Thanks for installing WordPress Zero Spam!</strong> Visit the <a href="%1$s">setting page</a> to configure your site\'s protection level or <strong><a href="%2$s">click here</a> to automatically configure recommended settings</strong>. For enhanced protection, get a <a href="%3$s" target="_blank">Zero Spam premium license</a>.', 'zerospam' ),
158
+ array(
159
+ 'strong' => array(),
160
+ 'a' => array(
161
+ 'href' => array(),
162
+ 'target' => array(),
163
+ ),
164
+ )
165
  ),
166
+ esc_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings' ) ),
167
+ esc_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=auto-configure' ) ),
168
+ esc_url( ZEROSPAM_URL . 'product/premium/' )
169
+ ),
170
+ );
171
+ }
172
+
173
+ if ( $messages ) {
174
+ $classes = array( 'notice' );
175
+ foreach ( $messages as $key => $message ) {
176
+ $classes[] = 'notice-' . $message['type'];
177
+ if ( $message['dismissible'] ) {
178
+ $classes[] = 'is-dismissible';
179
+ }
180
+
181
+ printf(
182
+ '<div class="%1$s"><p>%2$s</p></div>',
183
+ esc_attr( implode( ' ', $classes ) ),
184
+ // @codingStandardsIgnoreLine
185
+ $message['content']
186
+ );
187
+ }
188
+ }
189
  }
190
 
191
  /**
core/admin/class-settings.php CHANGED
@@ -231,7 +231,7 @@ class Settings {
231
 
232
  add_settings_field(
233
  $key,
234
- $setting['title'],
235
  array( $this, 'settings_field' ),
236
  'wpzerospam',
237
  'zerospam_' . $setting['section'],
231
 
232
  add_settings_field(
233
  $key,
234
+ ! empty( $setting['title'] ) ? $setting['title'] : false,
235
  array( $this, 'settings_field' ),
236
  'wpzerospam',
237
  'zerospam_' . $setting['section'],
core/admin/tables/class-logtable.php CHANGED
@@ -137,9 +137,11 @@ class LogTable extends WP_List_Table {
137
  }
138
 
139
  /**
140
- * Prepare log items
141
  */
142
- public function prepare_items( $args = array() ) {
 
 
143
  $this->process_bulk_action();
144
 
145
  $columns = $this->get_columns();
@@ -148,79 +150,129 @@ class LogTable extends WP_List_Table {
148
 
149
  $per_page = 50;
150
  $current_page = $this->get_pagenum();
151
- $offset = $per_page * ( $current_page - 1 );
152
- $order = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( $_REQUEST['order'] ) : 'desc';
153
- $orderby = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( $_REQUEST['orderby'] ) : 'date_recorded';
154
-
155
- $log_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
156
- $country = ! empty( $_REQUEST['country'] ) ? sanitize_text_field( $_REQUEST['country'] ) : false;
157
- $user_ip = ! empty( $_REQUEST['s'] ) ? sanitize_text_field( $_REQUEST['s'] ) : false;
158
-
159
- $query_args = array(
160
- 'limit' => $per_page,
161
- 'offset' => $offset,
162
- 'order' => $order,
163
- 'orderby' => $orderby,
164
- 'where' => array(),
165
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
167
  if ( $log_type ) {
168
- $query_args['where']['log_type'] = array(
169
- 'value' => $log_type,
170
- );
 
 
171
  }
172
 
173
  if ( $user_ip ) {
174
- $query_args['where']['user_ip'] = array(
175
- 'value' => $user_ip,
176
- );
177
  }
178
 
179
- if ( $country ) {
180
- $query_args['where']['country'] = array(
181
- 'value' => $country,
182
- );
183
  }
184
 
185
- $data = ZeroSpam\Includes\DB::query( 'log', $query_args );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  if ( ! $data ) {
187
  return false;
188
  }
189
 
190
- $this->items = $data;
 
191
 
192
- unset( $query_args['limit'] );
193
- unset( $query_args['offset'] );
194
- $data = ZeroSpam\Includes\DB::query( 'log', $query_args );
195
- $total_items = count( $data );
 
 
 
196
 
197
  $this->set_pagination_args(
198
  array(
199
  'total_items' => $total_items,
200
  'per_page' => $per_page,
201
- 'total_pages' => ceil( $total_items / $per_page ),
202
- 'orderby' => $orderby,
203
- 'order' => $order,
204
  )
205
  );
206
 
207
  $this->_column_headers = array( $columns, $hidden, $sortable );
 
208
 
209
  $paging_options = array();
210
- if ( ! empty( $query_args['where'] ) ) {
211
- foreach ( $query_args['where'] as $key => $value ) {
212
- switch( $key ) {
213
- case 'log_type':
214
- $paging_options['type'] = $value['value'];
215
- break;
216
- case 'user_ip':
217
- $paging_options['s'] = $value['value'];
218
- break;
219
- }
220
- }
221
  }
222
 
223
- $_SERVER['REQUEST_URI'] = add_query_arg( $paging_options, $_SERVER['REQUEST_URI'] );
 
 
 
 
 
 
 
 
224
  }
225
 
226
  /**
137
  }
138
 
139
  /**
140
+ * Get the data
141
  */
142
+ public function prepare_items() {
143
+ global $wpdb;
144
+
145
  $this->process_bulk_action();
146
 
147
  $columns = $this->get_columns();
150
 
151
  $per_page = 50;
152
  $current_page = $this->get_pagenum();
153
+ $offset = 1 === $current_page ? false : $per_page * $current_page;
154
+ // @codingStandardsIgnoreLine
155
+ $order = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['order'] ) ) : 'desc';
156
+ // @codingStandardsIgnoreLine
157
+ $orderby = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) ) : 'date_added';
158
+
159
+ // @codingStandardsIgnoreLine
160
+ $log_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['type'] ) ) : false;
161
+ // @codingStandardsIgnoreLine
162
+ $country = ! empty( $_REQUEST['country'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['country'] ) ) : false;
163
+ // @codingStandardsIgnoreLine
164
+ $user_ip = ! empty( $_REQUEST['s'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ) : false;
165
+
166
+ // Define the database table.
167
+ $database_table = $wpdb->prefix . \ZeroSpam\Includes\DB::$tables['log'];
168
+
169
+ // Prepare the select statements.
170
+ $select_array = array( '*' );
171
+
172
+ // Order & add extra select statements.
173
+ switch ( $orderby ) {
174
+ case 'user_ip':
175
+ $order_statement = "ORDER BY user_ip $order";
176
+ break;
177
+ case 'country':
178
+ $order_statement = "ORDER BY country $order";
179
+ break;
180
+ case 'region':
181
+ $order_statement = "ORDER BY country $order";
182
+ break;
183
+ case 'date_recorded':
184
+ $order_statement = "ORDER BY date_recorded $order";
185
+ break;
186
+ case 'log_type':
187
+ $order_statement = "ORDER BY log_type $order";
188
+ break;
189
+ }
190
+
191
+ // Where.
192
+ $where_array = array();
193
 
194
  if ( $log_type ) {
195
+ $where_array[] = "log_type = '$log_type'";
196
+ }
197
+
198
+ if ( $country ) {
199
+ $where_array[] = "country = '$country'";
200
  }
201
 
202
  if ( $user_ip ) {
203
+ $where_array[] = "user_ip = '$user_ip'";
 
 
204
  }
205
 
206
+ // Limit.
207
+ $limit_statement = "LIMIT $per_page";
208
+ if ( $offset ) {
209
+ $limit_statement .= ", $offset";
210
  }
211
 
212
+ // Create the query.
213
+ $database_query = 'SELECT ';
214
+
215
+ $select_statement = implode( ', ', $select_array );
216
+ $database_query .= $select_statement . ' ';
217
+
218
+ $database_query .= "FROM $database_table ";
219
+
220
+ if ( $where_array ) {
221
+ $database_query .= 'WHERE ';
222
+ $database_query .= implode( ' AND ', $where_array );
223
+ }
224
+
225
+ if ( ! empty( $order_statement ) ) {
226
+ $database_query .= $order_statement . ' ';
227
+ }
228
+
229
+ $database_query .= $limit_statement;
230
+
231
+ // @codingStandardsIgnoreLine
232
+ $data = $wpdb->get_results( $database_query, ARRAY_A );
233
+
234
  if ( ! $data ) {
235
  return false;
236
  }
237
 
238
+ // Get total number of rows.
239
+ $count_query = "SELECT COUNT(*) FROM $database_table ";
240
 
241
+ if ( $where_array ) {
242
+ $count_query .= 'WHERE ';
243
+ $count_query .= implode( ' AND ', $where_array );
244
+ }
245
+
246
+ // @codingStandardsIgnoreLine
247
+ $total_items = $wpdb->get_var( $count_query );
248
 
249
  $this->set_pagination_args(
250
  array(
251
  'total_items' => $total_items,
252
  'per_page' => $per_page,
253
+ 'total_pages' => ceil( $total_items / $per_page ),
254
+ 'orderby' => $orderby,
255
+ 'order' => $order,
256
  )
257
  );
258
 
259
  $this->_column_headers = array( $columns, $hidden, $sortable );
260
+ $this->items = $data;
261
 
262
  $paging_options = array();
263
+ if ( $log_type ) {
264
+ $paging_options['log_type'] = $log_type;
 
 
 
 
 
 
 
 
 
265
  }
266
 
267
+ if ( $country ) {
268
+ $paging_options['country'] = $country;
269
+ }
270
+
271
+ if ( $user_ip ) {
272
+ $paging_options['s'] = $user_ip;
273
+ }
274
+ // @codingStandardsIgnoreLine
275
+ $_SERVER['REQUEST_URI'] = add_query_arg( $paging_options, wp_unslash( $_SERVER['REQUEST_URI'] ) );
276
  }
277
 
278
  /**
core/class-settings.php CHANGED
@@ -289,7 +289,6 @@ class Settings {
289
  'value' => ! empty( $options['ip_whitelist'] ) ? $options['ip_whitelist'] : false,
290
  );
291
 
292
- $recommended_blocked_email_domains = \ZeroSpam\Core\Utilities::blocked_email_domains();
293
  self::$settings['blocked_email_domains'] = array(
294
  'title' => __( 'Blocked Email Domains', 'zerospam' ),
295
  'desc' => __( 'Enter a list of email domains that should be blocked, one per line.', 'zerospam' ),
@@ -298,7 +297,6 @@ class Settings {
298
  'field_class' => 'regular-text code',
299
  'placeholder' => '',
300
  'value' => ! empty( $options['blocked_email_domains'] ) ? $options['blocked_email_domains'] : false,
301
- 'recommended' => $recommended_blocked_email_domains ? implode( "\n", $recommended_blocked_email_domains ) : '',
302
  );
303
 
304
  self::$settings['update_blocked_email_domains'] = array(
289
  'value' => ! empty( $options['ip_whitelist'] ) ? $options['ip_whitelist'] : false,
290
  );
291
 
 
292
  self::$settings['blocked_email_domains'] = array(
293
  'title' => __( 'Blocked Email Domains', 'zerospam' ),
294
  'desc' => __( 'Enter a list of email domains that should be blocked, one per line.', 'zerospam' ),
297
  'field_class' => 'regular-text code',
298
  'placeholder' => '',
299
  'value' => ! empty( $options['blocked_email_domains'] ) ? $options['blocked_email_domains'] : false,
 
300
  );
301
 
302
  self::$settings['update_blocked_email_domains'] = array(
core/class-utilities.php CHANGED
@@ -239,8 +239,6 @@ class Utilities {
239
  /**
240
  * Write an entry to a log file in the uploads directory.
241
  *
242
- * @since 5.1.0
243
- *
244
  * @param mixed $entry String or array of the information to write to the log.
245
  * @param string $mode Optional. The type of write. See 'mode' at https://www.php.net/manual/en/function.fopen.php.
246
  * @param string $file Optional. The file basename for the .log file.
@@ -637,12 +635,34 @@ class Utilities {
637
  }
638
 
639
  /**
640
- * Remote get
 
 
 
641
  */
642
  public static function remote_get( $endpoint, $args = array() ) {
643
  $response = wp_remote_get( $endpoint, $args );
644
  if ( is_array( $response ) && ! is_wp_error( $response ) ) {
645
  return wp_remote_retrieve_body( $response );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
646
  }
647
 
648
  return false;
239
  /**
240
  * Write an entry to a log file in the uploads directory.
241
  *
 
 
242
  * @param mixed $entry String or array of the information to write to the log.
243
  * @param string $mode Optional. The type of write. See 'mode' at https://www.php.net/manual/en/function.fopen.php.
244
  * @param string $file Optional. The file basename for the .log file.
635
  }
636
 
637
  /**
638
+ * Performs an HTTP request using the GET method and returns its response.
639
+ *
640
+ * @param string $endpoint URL to retrieve.
641
+ * @param array $args Request arguments.
642
  */
643
  public static function remote_get( $endpoint, $args = array() ) {
644
  $response = wp_remote_get( $endpoint, $args );
645
  if ( is_array( $response ) && ! is_wp_error( $response ) ) {
646
  return wp_remote_retrieve_body( $response );
647
+ } elseif ( is_wp_error( $response ) ) {
648
+ self::log( $response->get_error_message() );
649
+ }
650
+
651
+ return false;
652
+ }
653
+
654
+ /**
655
+ * Performs an HTTP request using the POST method and returns its response.
656
+ *
657
+ * @param string $endpoint URL to retrieve.
658
+ * @param array $args Request arguments.
659
+ */
660
+ public static function remote_post( $endpoint, $args = array() ) {
661
+ $response = wp_remote_post( $endpoint, $args );
662
+ if ( is_array( $response ) && ! is_wp_error( $response ) ) {
663
+ return wp_remote_retrieve_body( $response );
664
+ } elseif ( is_wp_error( $response ) ) {
665
+ self::log( $response->get_error_message() );
666
  }
667
 
668
  return false;
includes/class-plugin.php CHANGED
@@ -30,6 +30,7 @@ class Plugin {
30
  $this->init_modules();
31
 
32
  add_filter( 'zerospam_types', array( $this, 'types' ), 10, 1 );
 
33
  }
34
 
35
  /**
@@ -52,6 +53,19 @@ class Plugin {
52
  return self::$instance;
53
  }
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  /**
56
  * Initializes modules
57
  */
30
  $this->init_modules();
31
 
32
  add_filter( 'zerospam_types', array( $this, 'types' ), 10, 1 );
33
+ add_filter( 'zerospam_failed_types', array( $this, 'failed_types' ), 10, 1 );
34
  }
35
 
36
  /**
53
  return self::$instance;
54
  }
55
 
56
+ /**
57
+ * Add to failed types
58
+ *
59
+ * @param array $types Array of failed types.
60
+ */
61
+ public function failed_types( $types ) {
62
+ $types['honeypot'] = __( 'Honeypot', 'zerospam' );
63
+ $types['blocked_email_domain'] = __( 'Blocked Email Domain', 'zerospam' );
64
+ $types['blocked'] = __( 'Blocked IP', 'zerospam' );
65
+
66
+ return $types;
67
+ }
68
+
69
  /**
70
  * Initializes modules
71
  */
includes/templates/admin-callout.php CHANGED
@@ -34,7 +34,7 @@ $settings = \ZeroSpam\Core\Settings::get_settings();
34
  echo sprintf(
35
  wp_kses(
36
  /* translators: %s: Zero Spam API link */
37
- __( '<p><strong>Is some spam still getting through?</strong> Enable enhanced protection with a <strong>Zero Spam API license</strong> &mdash; one of the largest, most comprehensive, constantly-growing global malicious IP databases available.</p><p><a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam</a> is comprised of a global detection network of over 30,000+ apps and sites that monitor traffic and usage in real-time to detect malicious activity. <a href="%1$s" target="_blank" rel="noopener noreferrer"><strong>Subscribe today</strong></a> for enhanced protection.</p>', 'zerospam' ),
38
  array(
39
  'a' => array(
40
  'target' => array(),
@@ -93,7 +93,7 @@ $settings = \ZeroSpam\Core\Settings::get_settings();
93
  <?php endif; ?>
94
  </div>
95
  <div class="zerospam-callout-col zerospam-callout-actions">
96
- <ul>
97
  <?php if ( 'enabled' !== $settings['zerospam']['value'] || empty( $settings['zerospam_license']['value'] ) ) : ?>
98
  <li style="margin-bottom: 20px;">
99
  <a href="<?php echo esc_url( ZEROSPAM_URL ); ?>subscribe/?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=license" target="_blank">
34
  echo sprintf(
35
  wp_kses(
36
  /* translators: %s: Zero Spam API link */
37
+ __( '<p>Enable enhanced protection with a <strong>Zero Spam API license</strong> &mdash; one of the largest, most comprehensive, constantly-growing global malicious IP, email, and username databases available.</p><p><a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam</a> is comprised of a global detection network of over 30,000+ apps and sites that monitor traffic and usage in real-time to detect malicious activity. <a href="%1$s" target="_blank" rel="noopener noreferrer"><strong>Subscribe today</strong></a> for enhanced protection.</p>', 'zerospam' ),
38
  array(
39
  'a' => array(
40
  'target' => array(),
93
  <?php endif; ?>
94
  </div>
95
  <div class="zerospam-callout-col zerospam-callout-actions">
96
+ <ul style="margin-top: 0">
97
  <?php if ( 'enabled' !== $settings['zerospam']['value'] || empty( $settings['zerospam_license']['value'] ) ) : ?>
98
  <li style="margin-bottom: 20px;">
99
  <a href="<?php echo esc_url( ZEROSPAM_URL ); ?>subscribe/?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=license" target="_blank">
includes/templates/admin-modal-details.php CHANGED
@@ -1,15 +1,22 @@
1
  <?php
2
  /**
3
- * Modal details.
4
  *
5
  * @package ZeroSpam
6
- * @since 5.0.0
7
  */
8
 
 
 
 
 
 
 
 
 
9
  ?>
10
  <div class="zerospam-modal-details">
11
  <div class="zerospam-modal-title">
12
- <h3>ID #<?php echo esc_html( $item['log_id'] ); ?></h3>
13
  </div>
14
  <div class="zerospam-modal-subtitle">
15
  <?php
@@ -27,28 +34,68 @@
27
  <strong><?php esc_html_e( 'IP Address', 'zerospam' ); ?></strong>
28
  <span>
29
  <?php
 
 
 
 
 
 
30
  echo sprintf(
31
  wp_kses(
32
- /* translators: %1s: IP URL lookup, %2$2 IP address, %2s: IP address */
33
- __( '<a href="%1$s" target="_blank" rel="noreferrer noopener">%2$s</a>', 'zerospam' ),
34
  array(
35
  'a' => array(
36
  'target' => array(),
37
  'href' => array(),
38
  'rel' => array(),
 
39
  ),
40
  )
41
  ),
42
- esc_url( ZEROSPAM_URL . 'ip-lookup/' . rawurlencode( esc_html( $item['user_ip'] ) ) ),
43
- esc_html( $item['user_ip'] )
44
  );
45
  ?>
46
  </span>
47
  </li>
48
  <li>
49
  <strong><?php esc_html_e( 'Type', 'zerospam' ); ?></strong>
50
- <span><?php echo esc_html( $item['log_type'] ); ?></span>
 
 
 
 
 
 
 
 
 
 
 
 
51
  </li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  </ul>
53
 
54
  <button class="button action zerospam-block-trigger" data-id="<?php echo esc_attr( $item['log_id'] ); ?>">
@@ -140,10 +187,7 @@
140
  <h4 class="zerospam-modal-headline"><?php echo esc_html_e( 'Additional Details', 'zerospam' ); ?></h4>
141
  <?php
142
 
143
- if ( ! empty( $item['submission_data'] ) ) :
144
- // Sanatize the array.
145
- $submission_data = json_decode( $item['submission_data'], true );
146
- $submission_data = \ZeroSpam\Core\Utilities::sanitize_array( $submission_data, 'esc_html' );
147
  echo '<ul class="zerospam-modal-list">';
148
  foreach ( $submission_data as $key => $value ) :
149
  ?>
1
  <?php
2
  /**
3
+ * Detection details modal
4
  *
5
  * @package ZeroSpam
 
6
  */
7
 
8
+ $submission_data = ! empty( $item['submission_data'] ) ? json_decode( $item['submission_data'], true ) : false;
9
+ if ( $submission_data ) :
10
+ $submission_data = \ZeroSpam\Core\Utilities::sanitize_array( $submission_data );
11
+ // Remove type, pulled from the log_type column.
12
+ if ( ! empty( $submission_data['type'] ) ) :
13
+ unset( $submission_data['type'] );
14
+ endif;
15
+ endif;
16
  ?>
17
  <div class="zerospam-modal-details">
18
  <div class="zerospam-modal-title">
19
+ <h3><?php echo esc_html_e( 'Detection ID', 'zerospam' ); ?> #<?php echo esc_html( $item['log_id'] ); ?></h3>
20
  </div>
21
  <div class="zerospam-modal-subtitle">
22
  <?php
34
  <strong><?php esc_html_e( 'IP Address', 'zerospam' ); ?></strong>
35
  <span>
36
  <?php
37
+ $lookup_url = ZEROSPAM_URL . 'ip-lookup/';
38
+ $lookup_url .= rawurlencode( $item['user_ip'] ) . '/';
39
+ $lookup_url .= '?utm_source=' . site_url() . '&';
40
+ $lookup_url .= '?utm_medium=wpzerospam_ip_lookup&';
41
+ $lookup_url .= '?utm_campaign=wpzerospam';
42
+
43
  echo sprintf(
44
  wp_kses(
45
+ /* translators: %1s: Replaced with the IP address, %2$s Replaced with the IP lookup URL */
46
+ __( '%1$s &mdash; <a href="%2$s" target="_blank" rel="noreferrer noopener" class="zerospam-new-window-link">IP Lookup</a>', 'zerospam' ),
47
  array(
48
  'a' => array(
49
  'target' => array(),
50
  'href' => array(),
51
  'rel' => array(),
52
+ 'class' => array(),
53
  ),
54
  )
55
  ),
56
+ esc_html( $item['user_ip'] ),
57
+ esc_url( $lookup_url )
58
  );
59
  ?>
60
  </span>
61
  </li>
62
  <li>
63
  <strong><?php esc_html_e( 'Type', 'zerospam' ); ?></strong>
64
+ <span>
65
+ <?php
66
+ $detection_types = apply_filters( 'zerospam_types', array() );
67
+ if ( ! empty( $detection_types[ $item['log_type'] ] ) ) :
68
+ echo wp_kses(
69
+ $detection_types[ $item['log_type'] ] . ' &mdash; <code>' . $item['log_type'] . '</code>',
70
+ array( 'code' => array() )
71
+ );
72
+ else :
73
+ echo wp_kses( $item['log_type'], array( 'code' => array() ) );
74
+ endif;
75
+ ?>
76
+ </span>
77
  </li>
78
+ <?php if ( $submission_data && ! empty( $submission_data['failed'] ) ) : ?>
79
+ <li>
80
+ <strong><?php esc_html_e( 'Failed', 'zerospam' ); ?></strong>
81
+ <span>
82
+ <?php
83
+ $failed_types = apply_filters( 'zerospam_failed_types', array() );
84
+ if ( ! empty( $failed_types[ $submission_data['failed'] ] ) ) :
85
+ echo wp_kses(
86
+ $failed_types[ $submission_data['failed'] ] . ' &mdash; <code>' . $submission_data['failed'] . '</code>',
87
+ array( 'code' => array() )
88
+ );
89
+ else :
90
+ echo wp_kses( $submission_data['failed'], array( 'code' => array() ) );
91
+ endif;
92
+ ?>
93
+ </span>
94
+ </li>
95
+ <?php
96
+ unset( $submission_data['failed'] );
97
+ endif;
98
+ ?>
99
  </ul>
100
 
101
  <button class="button action zerospam-block-trigger" data-id="<?php echo esc_attr( $item['log_id'] ); ?>">
187
  <h4 class="zerospam-modal-headline"><?php echo esc_html_e( 'Additional Details', 'zerospam' ); ?></h4>
188
  <?php
189
 
190
+ if ( $submission_data ) :
 
 
 
191
  echo '<ul class="zerospam-modal-list">';
192
  foreach ( $submission_data as $key => $value ) :
193
  ?>
modules/class-zerospam.php CHANGED
@@ -7,8 +7,6 @@
7
 
8
  namespace ZeroSpam\Modules;
9
 
10
- use ZeroSpam;
11
-
12
  // Security Note: Blocks direct access to the plugin PHP files.
13
  defined( 'ABSPATH' ) || die();
14
 
@@ -60,6 +58,30 @@ class Zero_Spam {
60
  * @param array $options Array of saved database options.
61
  */
62
  public function settings( $settings, $options ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  $settings['zerospam'] = array(
64
  'title' => __( 'Status', 'zerospam' ),
65
  'section' => 'zerospam',
@@ -91,7 +113,7 @@ class Zero_Spam {
91
  'desc' => sprintf(
92
  wp_kses(
93
  /* translators: %1$s: Replaced with the Zero Spam URL, %2$s: Replaced with the Zero Spam subscription URL */
94
- __( 'Enter your <a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam license key</a> to enable enhanced premium protection. Don\'t have an license key? <a href="%2$s" target="_blank" rel="noopener noreferrer"><strong>Get one now!</strong></a>', 'zerospam' ),
95
  array(
96
  'strong' => array(),
97
  'a' => array(
@@ -159,7 +181,7 @@ class Zero_Spam {
159
  ),
160
  )
161
  ),
162
- esc_url( ZEROSPAM_URL . 'spam-blacklist-api/#utm_source=wordpresszerospam&utm_medium=admin_link&utm_campaign=wordpresszerospam' )
163
  ),
164
  'value' => ! empty( $options['zerospam_confidence_min'] ) ? $options['zerospam_confidence_min'] : 30,
165
  'recommended' => 30,
@@ -210,7 +232,7 @@ class Zero_Spam {
210
  }
211
 
212
  // Attempt to get the geolocation information.
213
- $api_data['location'] = ZeroSpam\Modules\ipstack::get_geolocation( $ip );
214
 
215
  $global_data = self::global_api_data();
216
  $api_data = array_merge( $api_data, $global_data );
@@ -222,4 +244,81 @@ class Zero_Spam {
222
 
223
  wp_remote_post( $endpoint, $args );
224
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  }
7
 
8
  namespace ZeroSpam\Modules;
9
 
 
 
10
  // Security Note: Blocks direct access to the plugin PHP files.
11
  defined( 'ABSPATH' ) || die();
12
 
58
  * @param array $options Array of saved database options.
59
  */
60
  public function settings( $settings, $options ) {
61
+ $settings['zerospam_info'] = array(
62
+ 'section' => 'zerospam',
63
+ 'type' => 'html',
64
+ 'html' => sprintf(
65
+ wp_kses(
66
+ /* translators: %1s: Replaced with the Zero Spam URL, %2$s: Replaced with the DDoD attack wiki URL */
67
+ __( '<h3 style="margin-top: 0">Enabling enhanced protection is highly recommended.</h3><p>Enhanced protection adds additional checks using one of the largest, most comprehensive, constantly-growing global malicious IP, email, and username databases available, the <a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam Blacklist</a>. Once enabled, all visitors will be checked against this blacklist that includes protected forms containing email and username fields &mdash; giving you the peace of mind that submissions are coming from legitimate. It can also help prevent <a href="%2$s" target="_blank" rel="noopener noreferrer">DDoS attacks</a> &amp; fraudsters looking to test stolen credit card numbers.</p>', 'zerospam' ),
68
+ array(
69
+ 'h3' => array(
70
+ 'style' => array(),
71
+ ),
72
+ 'p' => array(),
73
+ 'a' => array(
74
+ 'href' => array(),
75
+ 'class' => array(),
76
+ ),
77
+ 'strong' => array(),
78
+ )
79
+ ),
80
+ esc_url( ZEROSPAM_URL . '?utm_source=' . site_url() . '&utm_medium=admin_zerospam_info&utm_campaign=wpzerospam' ),
81
+ esc_url( 'https://en.wikipedia.org/wiki/Denial-of-service_attack' )
82
+ ),
83
+ );
84
+
85
  $settings['zerospam'] = array(
86
  'title' => __( 'Status', 'zerospam' ),
87
  'section' => 'zerospam',
113
  'desc' => sprintf(
114
  wp_kses(
115
  /* translators: %1$s: Replaced with the Zero Spam URL, %2$s: Replaced with the Zero Spam subscription URL */
116
+ __( 'Enter your <a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam</a> license key for enhanced protection. Don\'t have an license key? <a href="%2$s" target="_blank" rel="noopener noreferrer"><strong>Get one now!</strong></a>', 'zerospam' ),
117
  array(
118
  'strong' => array(),
119
  'a' => array(
181
  ),
182
  )
183
  ),
184
+ esc_url( ZEROSPAM_URL . 'spam-blacklist-api/?utm_source=' . site_url() . '&utm_medium=admin_confidence_score&utm_campaign=wpzerospam' )
185
  ),
186
  'value' => ! empty( $options['zerospam_confidence_min'] ) ? $options['zerospam_confidence_min'] : 30,
187
  'recommended' => 30,
232
  }
233
 
234
  // Attempt to get the geolocation information.
235
+ $api_data['location'] = \ZeroSpam\Modules\ipstack::get_geolocation( $ip );
236
 
237
  $global_data = self::global_api_data();
238
  $api_data = array_merge( $api_data, $global_data );
244
 
245
  wp_remote_post( $endpoint, $args );
246
  }
247
+
248
+ /**
249
+ * Query the Zero Spam Blacklist API
250
+ *
251
+ * @param array $params Array of query parameters.
252
+ */
253
+ public static function query( $params ) {
254
+ if (
255
+ empty( $params['ip'] ) &&
256
+ empty( $params['username'] ) &&
257
+ empty( $params['email'] )
258
+ ) {
259
+ return false;
260
+ }
261
+
262
+ $settings = \ZeroSpam\Core\Settings::get_settings();
263
+
264
+ if ( empty( $settings['zerospam_license']['value'] ) ) {
265
+ return false;
266
+ }
267
+
268
+ $cache_array = array( 'zero_spam' );
269
+ $cache_array = array_merge( $cache_array, $params );
270
+ $cache_key = \ZeroSpam\Core\Utilities::cache_key( $cache_array );
271
+
272
+ $response = wp_cache_get( $cache_key );
273
+ if ( false === $response ) {
274
+ $endpoint = 'https://www.zerospam.org/wp-json/v1/query';
275
+
276
+ $args = array(
277
+ 'body' => array(
278
+ 'license_key' => $settings['zerospam_license']['value'],
279
+ ),
280
+ );
281
+
282
+ if ( ! empty( $params['ip'] ) ) {
283
+ $args['body']['ip'] = $params['ip'];
284
+ }
285
+
286
+ $args['timeout'] = 5;
287
+ if ( ! empty( $settings['zerospam_timeout'] ) ) {
288
+ $args['timeout'] = intval( $settings['zerospam_timeout']['value'] );
289
+ }
290
+
291
+ $response = \ZeroSpam\Core\Utilities::remote_post( $endpoint, $args );
292
+ if ( $response ) {
293
+ // Response should be a JSON string.
294
+ $response = json_decode( $response, true );
295
+
296
+ if (
297
+ ! is_array( $response ) ||
298
+ empty( $response['status'] ) ||
299
+ 'success' !== $response['status'] ||
300
+ empty( $response['result'] )
301
+ ) {
302
+ if ( ! empty( $response['result'] ) ) {
303
+ \ZeroSpam\Core\Utilities::log( $response['result'] );
304
+ } else {
305
+ \ZeroSpam\Core\Utilities::log( __( 'There was a problem querying the Zero Spam Blacklist API.', 'zerospam' ) );
306
+ }
307
+
308
+ return false;
309
+ }
310
+
311
+ $response = $response['result'];
312
+
313
+ $expiration = 14 * DAY_IN_SECONDS;
314
+ if ( ! empty( $settings['zerospam_confidence_min']['value'] ) ) {
315
+ $expiration = $settings['zerospam_confidence_min']['value'] * DAY_IN_SECONDS;
316
+ }
317
+
318
+ wp_cache_set( $cache_key, $response, 'zerospam', $expiration );
319
+ }
320
+ }
321
+
322
+ return $response;
323
+ }
324
  }
modules/davidwalsh/class-davidwalsh.php CHANGED
@@ -29,6 +29,7 @@ class DavidWalsh {
29
  public function init() {
30
  add_filter( 'zerospam_setting_sections', array( $this, 'sections' ) );
31
  add_filter( 'zerospam_settings', array( $this, 'settings' ), 10, 2 );
 
32
 
33
  if (
34
  'enabled' === \ZeroSpam\Core\Settings::get_settings( 'davidwalsh' ) &&
@@ -92,6 +93,17 @@ class DavidWalsh {
92
  return $errors;
93
  }
94
 
 
 
 
 
 
 
 
 
 
 
 
95
  /**
96
  * Admin setting sections
97
  *
29
  public function init() {
30
  add_filter( 'zerospam_setting_sections', array( $this, 'sections' ) );
31
  add_filter( 'zerospam_settings', array( $this, 'settings' ), 10, 2 );
32
+ add_filter( 'zerospam_failed_types', array( $this, 'failed_types' ), 10, 1 );
33
 
34
  if (
35
  'enabled' === \ZeroSpam\Core\Settings::get_settings( 'davidwalsh' ) &&
93
  return $errors;
94
  }
95
 
96
+ /**
97
+ * Add to failed types
98
+ *
99
+ * @param array $types Array of failed types.
100
+ */
101
+ public function failed_types( $types ) {
102
+ $types['david_walsh'] = __( 'David Walsh', 'zerospam' );
103
+
104
+ return $types;
105
+ }
106
+
107
  /**
108
  * Admin setting sections
109
  *
modules/give/class-give.php CHANGED
@@ -145,7 +145,21 @@ class Give {
145
  */
146
  public function settings( $settings, $options ) {
147
  $settings['verify_givewp'] = array(
148
- 'title' => __( 'Protect GiveWP Submissions', 'zerospam' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  'section' => 'givewp',
150
  'type' => 'checkbox',
151
  'options' => array(
145
  */
146
  public function settings( $settings, $options ) {
147
  $settings['verify_givewp'] = array(
148
+ 'title' => sprintf(
149
+ wp_kses(
150
+ /* translators: %s: url */
151
+ __( 'Protect <a href="%s" target="_blank" rel="noreferrer noopener">GiveWP</a> Submissions', 'zerospam' ),
152
+ array(
153
+ 'a' => array(
154
+ 'href' => array(),
155
+ 'class' => array(),
156
+ 'target' => array(),
157
+ 'rel' => array(),
158
+ ),
159
+ )
160
+ ),
161
+ esc_url( 'https://givewp.com/ref/1118/' )
162
+ ),
163
  'section' => 'givewp',
164
  'type' => 'checkbox',
165
  'options' => array(
readme.txt CHANGED
@@ -5,7 +5,7 @@ Donate link: https://www.zerospam.org/subscribe/
5
  Requires at least: 5.2
6
  Tested up to: 5.8.2
7
  Requires PHP: 7.3
8
- Stable tag: 5.2.6
9
  License: GNU GPLv3
10
  License URI: https://choosealicense.com/licenses/gpl-3.0/
11
 
@@ -34,7 +34,7 @@ Quit forcing people to answer questions or confusing captchas to prove they're n
34
  = WordPress Zero Spam also protects =
35
 
36
  * WordPress core comments, user registrations &amp; login attempts
37
- * [GiveWP](https://wordpress.org/plugins/give/) donation submissions
38
  * [Contact Form 7](https://wordpress.org/plugins/contact-form-7/) submissions
39
  * [WPForms](https://wordpress.org/plugins/wpforms-lite/) submissions
40
  * [Formidable Form Builder](https://wordpress.org/plugins/formidable/) submissions
@@ -91,7 +91,6 @@ Some hosts have issues with they way they access files. If you're seeing a `ftp_
91
 
92
  `define('FS_METHOD', 'direct');`
93
 
94
-
95
  If hosting with Pantheon, see their [known issues page](https://pantheon.io/docs/plugins-known-issues#define-fs_method) for more information and what to do to resolve it with their `$_ENV['PANTHEON_ENVIRONMENT']` variable check.
96
 
97
  == Screenshots ==
@@ -104,6 +103,12 @@ If hosting with Pantheon, see their [known issues page](https://pantheon.io/docs
104
 
105
  == Changelog ==
106
 
 
 
 
 
 
 
107
  = v5.2.6 =
108
 
109
  * fix(undefined method): fix for undefined types method
5
  Requires at least: 5.2
6
  Tested up to: 5.8.2
7
  Requires PHP: 7.3
8
+ Stable tag: 5.2.7
9
  License: GNU GPLv3
10
  License URI: https://choosealicense.com/licenses/gpl-3.0/
11
 
34
  = WordPress Zero Spam also protects =
35
 
36
  * WordPress core comments, user registrations &amp; login attempts
37
+ * [GiveWP](https://givewp.com/ref/1118/) donation submissions
38
  * [Contact Form 7](https://wordpress.org/plugins/contact-form-7/) submissions
39
  * [WPForms](https://wordpress.org/plugins/wpforms-lite/) submissions
40
  * [Formidable Form Builder](https://wordpress.org/plugins/formidable/) submissions
91
 
92
  `define('FS_METHOD', 'direct');`
93
 
 
94
  If hosting with Pantheon, see their [known issues page](https://pantheon.io/docs/plugins-known-issues#define-fs_method) for more information and what to do to resolve it with their `$_ENV['PANTHEON_ENVIRONMENT']` variable check.
95
 
96
  == Screenshots ==
103
 
104
  == Changelog ==
105
 
106
+ = v5.2.7 =
107
+
108
+ * perf(settings): performance improvement to settings being loaded
109
+ * style(admin): added check for zero spam license key when enabled
110
+ * style(admin): misc. admin interface improvements
111
+
112
  = v5.2.6 =
113
 
114
  * fix(undefined method): fix for undefined types method
wordpress-zero-spam.php CHANGED
@@ -13,7 +13,7 @@
13
  * Plugin Name: WordPress Zero Spam
14
  * Plugin URI: https://www.highfivery.com/projects/zero-spam/
15
  * Description: Tired of all the worthless and bloated WordPress anti-spam & security plugins? WordPress Zero Spam makes blocking spam &amp; malicious activity a cinch. <strong>Just install, activate, configure, and say goodbye to spam.</strong>
16
- * Version: 5.2.6
17
  * Requires at least: 5.2
18
  * Requires PHP: 7.3
19
  * Author: Highfivery LLC
@@ -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.2.6' );
35
 
36
  if ( defined( 'ZEROSPAM_DEVELOPMENT_URL' ) ) {
37
  define( 'ZEROSPAM_URL', ZEROSPAM_DEVELOPMENT_URL );
13
  * Plugin Name: WordPress Zero Spam
14
  * Plugin URI: https://www.highfivery.com/projects/zero-spam/
15
  * Description: Tired of all the worthless and bloated WordPress anti-spam & security plugins? WordPress Zero Spam makes blocking spam &amp; malicious activity a cinch. <strong>Just install, activate, configure, and say goodbye to spam.</strong>
16
+ * Version: 5.2.7
17
  * Requires at least: 5.2
18
  * Requires PHP: 7.3
19
  * Author: Highfivery LLC
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.2.7' );
35
 
36
  if ( defined( 'ZEROSPAM_DEVELOPMENT_URL' ) ) {
37
  define( 'ZEROSPAM_URL', ZEROSPAM_DEVELOPMENT_URL );