Newsletter - Version 5.3.2

Version Description

  • Security panel reorganized
  • Added Akismet spam check
Download this release

Release Info

Developer satollo
Plugin Icon 128x128 Newsletter
Version 5.3.2
Comparing to
See all releases

Code changes from version 5.2.8 to 5.3.2

includes/controls.php CHANGED
@@ -814,6 +814,9 @@ class NewsletterControls {
814
 
815
  function textarea($name, $width = '100%', $height = '50') {
816
  $value = $this->get_value($name);
 
 
 
817
  echo '<textarea id="options-' . esc_attr($name) . '" class="dynamic" name="options[' . esc_attr($name) . ']" wrap="off" style="width:' . esc_attr($width) . ';height:' . esc_attr($height) . '">';
818
  echo esc_html($value);
819
  echo '</textarea>';
@@ -1186,7 +1189,7 @@ class NewsletterControls {
1186
  }
1187
  echo '<script type="text/javascript">
1188
  jQuery(document).ready(function(){
1189
- $(".tnp-controls-color").wpColorPicker();
1190
  jQuery("textarea.dynamic").focus(function() {
1191
  jQuery("textarea.dynamic").css("height", "50px");
1192
  jQuery(this).css("height", "400px");
814
 
815
  function textarea($name, $width = '100%', $height = '50') {
816
  $value = $this->get_value($name);
817
+ if (is_array($value)) {
818
+ $value = implode("\n", $value);
819
+ }
820
  echo '<textarea id="options-' . esc_attr($name) . '" class="dynamic" name="options[' . esc_attr($name) . ']" wrap="off" style="width:' . esc_attr($width) . ';height:' . esc_attr($height) . '">';
821
  echo esc_html($value);
822
  echo '</textarea>';
1189
  }
1190
  echo '<script type="text/javascript">
1191
  jQuery(document).ready(function(){
1192
+ jQuery(".tnp-controls-color").wpColorPicker();
1193
  jQuery("textarea.dynamic").focus(function() {
1194
  jQuery("textarea.dynamic").css("height", "50px");
1195
  jQuery(this).css("height", "400px");
includes/module.php CHANGED
@@ -1132,17 +1132,45 @@ class NewsletterModule {
1132
  return $text;
1133
  }
1134
 
1135
- public static function antibot_form_check() {
1136
- return strtolower($_SERVER['REQUEST_METHOD']) == 'post' && isset($_POST['ts']) && time() - $_POST['ts'] < 30;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1137
  }
1138
 
1139
- public static function request_to_antibot_form($submit_label = 'Continue...') {
1140
  header('Content-Type: text/html;charset=UTF-8');
1141
  header('X-Robots-Tag: noindex,nofollow,noarchive');
1142
  header('Cache-Control: no-cache,no-store,private');
1143
  echo "<!DOCTYPE html>\n";
1144
- echo '<html><head></head><body>';
1145
- echo '<form method="post" action="https://www.domain.tld" id="form" style="width: 1px; height: 1px; overflow: hidden">';
 
 
 
 
 
 
 
 
1146
  foreach ($_REQUEST as $name => $value) {
1147
  if ($name == 'submit')
1148
  continue;
@@ -1167,12 +1195,25 @@ class NewsletterModule {
1167
  echo '<input type="hidden" name="nhr" value="' . esc_attr($_SERVER['HTTP_REFERER']) . '">';
1168
  }
1169
  echo '<input type="hidden" name="ts" value="' . time() . '">';
 
 
 
 
 
 
 
 
 
 
1170
  echo '<noscript><input type="submit" value="';
1171
  echo esc_attr($submit_label);
1172
  echo '"></noscript></form>';
1173
  echo '<script>';
1174
  echo 'document.getElementById("form").action="' . home_url('/') . '";';
1175
- echo 'document.getElementById("form").submit();</script>';
 
 
 
1176
  echo '</body></html>';
1177
  die();
1178
  }
@@ -1211,12 +1252,13 @@ class NewsletterModule {
1211
  }
1212
  return (int) $var;
1213
  }
1214
-
1215
  static function sanitize_ip($ip) {
1216
- if (empty($ip)) return $ip;
 
1217
  return preg_replace('/[^0-9a-fA-F:., ]/', '', $ip);
1218
  }
1219
-
1220
  static function get_remote_ip() {
1221
  return self::sanitize_ip($_SERVER['REMOTE_ADDR']);
1222
  }
1132
  return $text;
1133
  }
1134
 
1135
+ public static function antibot_form_check($captcha = false) {
1136
+ if (strtolower($_SERVER['REQUEST_METHOD']) != 'post') return false;
1137
+
1138
+ if (!isset($_POST['ts']) || time() - $_POST['ts'] > 60) {
1139
+ return false;
1140
+ }
1141
+ if ($captcha) {
1142
+ $n1 = (int) $_POST['n1'];
1143
+ if (empty($n1)) {
1144
+ return false;
1145
+ }
1146
+ $n2 = (int) $_POST['n2'];
1147
+ if (empty($n2)) {
1148
+ return false;
1149
+ }
1150
+ $n3 = (int) $_POST['n3'];
1151
+ if ($n1 + $n2 != $n3) {
1152
+ return false;
1153
+ }
1154
+ }
1155
+
1156
+ return true;
1157
  }
1158
 
1159
+ public static function request_to_antibot_form($submit_label = 'Continue...', $captcha = false) {
1160
  header('Content-Type: text/html;charset=UTF-8');
1161
  header('X-Robots-Tag: noindex,nofollow,noarchive');
1162
  header('Cache-Control: no-cache,no-store,private');
1163
  echo "<!DOCTYPE html>\n";
1164
+ echo '<html><head>'
1165
+ . '<style type="text/css">'
1166
+ . 'form {margin: 200px auto 0 auto !important; width: 350px !important; padding: 10px !important; font-family: "Open Sans", sans-serif; background: #ECF0F1; border-radius: 5px; padding: 50px !important; border: none !important;}'
1167
+ . 'p {text-align: center; padding: 10px; color: #7F8C8D;}'
1168
+ . 'input[type=text] {width: 50px; padding: 10px 10px; border: none; border-radius: 2px; margin: 0px 5px;}'
1169
+ . 'input[type=submit] {text-align: center; border: none; padding: 10px 15px; font-family: "Open Sans", sans-serif; background-color: #27AE60; color: white; cursor: pointer;}'
1170
+ . '</style>'
1171
+ . '</head><body>';
1172
+ echo '<form method="post" action="https://www.domain.tld" id="form">';
1173
+ echo '<div style="width: 1px; height: 1px; overflow: hidden">';
1174
  foreach ($_REQUEST as $name => $value) {
1175
  if ($name == 'submit')
1176
  continue;
1195
  echo '<input type="hidden" name="nhr" value="' . esc_attr($_SERVER['HTTP_REFERER']) . '">';
1196
  }
1197
  echo '<input type="hidden" name="ts" value="' . time() . '">';
1198
+ echo '</div>';
1199
+ if ($captcha) {
1200
+ echo '<p>Math question</p>';
1201
+ echo '<input type="text" name="n1" value="' . rand(1, 9) . '" readonly style="width: 50px">';
1202
+ echo '+';
1203
+ echo '<input type="text" name="n2" value="' . rand(1, 9) . '" readonly style="width: 50px">';
1204
+ echo '=';
1205
+ echo '<input type="text" name="n3" value="?" style="width: 50px">';
1206
+ echo '&nbsp;<input type="submit" value="', esc_attr($submit_label), '">';
1207
+ }
1208
  echo '<noscript><input type="submit" value="';
1209
  echo esc_attr($submit_label);
1210
  echo '"></noscript></form>';
1211
  echo '<script>';
1212
  echo 'document.getElementById("form").action="' . home_url('/') . '";';
1213
+ if (!$captcha) {
1214
+ echo 'document.getElementById("form").submit();';
1215
+ }
1216
+ echo '</script>';
1217
  echo '</body></html>';
1218
  die();
1219
  }
1252
  }
1253
  return (int) $var;
1254
  }
1255
+
1256
  static function sanitize_ip($ip) {
1257
+ if (empty($ip))
1258
+ return $ip;
1259
  return preg_replace('/[^0-9a-fA-F:., ]/', '', $ip);
1260
  }
1261
+
1262
  static function get_remote_ip() {
1263
  return self::sanitize_ip($_SERVER['REMOTE_ADDR']);
1264
  }
plugin.php CHANGED
@@ -4,7 +4,7 @@
4
  Plugin Name: Newsletter
5
  Plugin URI: https://www.thenewsletterplugin.com/plugins/newsletter
6
  Description: Newsletter is a cool plugin to create your own subscriber list, to send newsletters, to build your business. <strong>Before update give a look to <a href="https://www.thenewsletterplugin.com/category/release">this page</a> to know what's changed.</strong>
7
- Version: 5.2.7
8
  Author: Stefano Lissa & The Newsletter Team
9
  Author URI: https://www.thenewsletterplugin.com
10
  Disclaimer: Use at your own risk. No warranty expressed or implied is provided.
@@ -14,7 +14,7 @@
14
  */
15
 
16
  // Used as dummy parameter on css and js links
17
- define('NEWSLETTER_VERSION', '5.2.7');
18
 
19
  global $wpdb, $newsletter;
20
 
4
  Plugin Name: Newsletter
5
  Plugin URI: https://www.thenewsletterplugin.com/plugins/newsletter
6
  Description: Newsletter is a cool plugin to create your own subscriber list, to send newsletters, to build your business. <strong>Before update give a look to <a href="https://www.thenewsletterplugin.com/category/release">this page</a> to know what's changed.</strong>
7
+ Version: 5.3.2
8
  Author: Stefano Lissa & The Newsletter Team
9
  Author URI: https://www.thenewsletterplugin.com
10
  Disclaimer: Use at your own risk. No warranty expressed or implied is provided.
14
  */
15
 
16
  // Used as dummy parameter on css and js links
17
+ define('NEWSLETTER_VERSION', '5.3.2');
18
 
19
  global $wpdb, $newsletter;
20
 
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
  Tags: newsletter,email,subscription,mass mail,list build,email marketing,direct mailing,automation,automated
3
  Requires at least: 3.4.0
4
  Tested up to: 4.9.4
5
- Stable tag: 5.2.7
6
  Contributors: satollo,webagile,michael-travan
7
 
8
  Add a real newsletter system to your blog. For free. With unlimited newsletters and subscribers.
@@ -14,6 +14,7 @@ send and track e-mails, headache-free. It just works out of box!
14
 
15
  = Main Features =
16
 
 
17
  * **Responsive email Drag & Drop composer**
18
  * **Unlimited subscribers** with statistics
19
  * **Unlimited newsletter** with tracking
@@ -88,7 +89,30 @@ Thank you, The Newsletter Team
88
 
89
  == Changelog ==
90
 
91
- = NEXT =
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
  * Improved block layout
94
  * Added filter on profile url
2
  Tags: newsletter,email,subscription,mass mail,list build,email marketing,direct mailing,automation,automated
3
  Requires at least: 3.4.0
4
  Tested up to: 4.9.4
5
+ Stable tag: 5.3.2
6
  Contributors: satollo,webagile,michael-travan
7
 
8
  Add a real newsletter system to your blog. For free. With unlimited newsletters and subscribers.
14
 
15
  = Main Features =
16
 
17
+ * Subscription spam check with domain/ip black lists, Akismet, captcha
18
  * **Responsive email Drag & Drop composer**
19
  * **Unlimited subscribers** with statistics
20
  * **Unlimited newsletter** with tracking
89
 
90
  == Changelog ==
91
 
92
+ = 5.3.2 =
93
+
94
+ * Security panel reorganized
95
+ * Added Akismet spam check
96
+
97
+ = 5.3.1 =
98
+
99
+ * Name and last name check for spam
100
+ * 404 responses on error condition
101
+ * jQuery fix
102
+ * Email cleanup on admin edit panel
103
+ * Name check for spam on subscription
104
+
105
+ = 5.3.0 =
106
+
107
+ * CAPTCHA system
108
+ * IP black list
109
+ * Email address black list
110
+
111
+ = 5.2.8 =
112
+
113
+ * Redirect fix
114
+
115
+ = 5.2.7 =
116
 
117
  * Improved block layout
118
  * Added filter on profile url
statistics/statistics.php CHANGED
@@ -119,8 +119,7 @@ class NewsletterStatistics extends NewsletterModule {
119
 
120
  $wpdb->query($wpdb->prepare("update " . NEWSLETTER_SENT_TABLE . " set open=2, ip=%s where email_id=%d and user_id=%d limit 1", $ip, $email_id, $user_id));
121
 
122
- wp_safe_redirect(apply_filters('newsletter_redirect_url', $url, $email, $user));
123
-
124
  die();
125
  }
126
 
119
 
120
  $wpdb->query($wpdb->prepare("update " . NEWSLETTER_SENT_TABLE . " set open=2, ip=%s where email_id=%d and user_id=%d limit 1", $ip, $email_id, $user_id));
121
 
122
+ header('Location: ' . apply_filters('newsletter_redirect_url', $url, $email, $user));
 
123
  die();
124
  }
125
 
subscription/antibot.php ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('ABSPATH'))
3
+ exit;
4
+
5
+ @include_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
6
+ $controls = new NewsletterControls();
7
+ $module = NewsletterSubscription::instance();
8
+
9
+ // TODO: Remove and use the $module->options.
10
+ $options = get_option('newsletter', array());
11
+
12
+ if ($controls->is_action()) {
13
+
14
+ if ($controls->is_action('save')) {
15
+
16
+ $blacklist = trim($controls->data['ip_blacklist']);
17
+ if (empty($blacklist))
18
+ $blacklist = array();
19
+ else {
20
+ $blacklist = preg_split("/\\r\\n/", $blacklist);
21
+ $blacklist = array_map('trim', $blacklist);
22
+ $blacklist = array_map('strtolower', $blacklist);
23
+ $blacklist = array_filter($blacklist);
24
+
25
+ $controls->data['ip_blacklist'] = $blacklist;
26
+ }
27
+
28
+ $blacklist = trim($controls->data['address_blacklist']);
29
+ if (empty($blacklist))
30
+ $blacklist = array();
31
+ else {
32
+ $blacklist = preg_split("/\\r\\n/", $blacklist);
33
+ $blacklist = array_map('trim', $blacklist);
34
+ $blacklist = array_map('strtolower', $blacklist);
35
+ $blacklist = array_filter($blacklist);
36
+
37
+ $controls->data['address_blacklist'] = $blacklist;
38
+ }
39
+
40
+ $module->merge_options($controls->data);
41
+ $controls->add_message_saved();
42
+ }
43
+ } else {
44
+ $controls->data = get_option('newsletter', array());
45
+ }
46
+ ?>
47
+
48
+ <div class="wrap" id="tnp-wrap">
49
+
50
+ <?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
51
+
52
+ <div id="tnp-heading">
53
+
54
+ <h2><?php _e('Security', 'newsletter') ?></h2>
55
+ <?php $controls->page_help('https://www.thenewsletterplugin.com/documentation/antiflood') ?>
56
+
57
+ </div>
58
+
59
+ <div id="tnp-body">
60
+
61
+ <form method="post" action="">
62
+ <?php $controls->init(); ?>
63
+
64
+
65
+ <p>
66
+ <?php $controls->button_save() ?>
67
+ </p>
68
+
69
+ <div id="tabs">
70
+ <ul>
71
+ <li><a href="#tabs-general"><?php _e('Security', 'newsletter') ?></a></li>
72
+ <li><a href="#tabs-blacklists"><?php _e('Blacklists', 'newsletter') ?></a></li>
73
+ </ul>
74
+
75
+ <div id="tabs-general">
76
+
77
+
78
+ <table class="form-table">
79
+ <tr>
80
+ <th><?php _e('Disable antibot/antispam?', 'newsletter') ?></th>
81
+ <td>
82
+ <?php $controls->yesno('antibot_disable'); ?>
83
+ <p class="description">
84
+ <?php _e('Disable for ajax form submission', 'newsletter'); ?>
85
+ </p>
86
+ </td>
87
+ </tr>
88
+
89
+ <tr>
90
+ <th>Akismet</th>
91
+ <td>
92
+ <?php
93
+ $controls->select('akismet', array(
94
+ 0 => __('Disabled', 'newsletter'),
95
+ 1 => __('Enabled', 'newsletter')
96
+ ));
97
+ ?>
98
+ <?php $controls->help('https://www.thenewsletterplugin.com/documentation/antiflood') ?>
99
+ </td>
100
+ </tr>
101
+
102
+ <tr>
103
+ <th><?php _e('Antiflood', 'newsletter') ?></th>
104
+ <td>
105
+ <?php
106
+ $controls->select('antiflood', array(
107
+ 0 => __('Disabled', 'newsletter'),
108
+ 5 => '5 ' . __('seconds', 'newsletter'),
109
+ 10 => '10 ' . __('seconds', 'newsletter'),
110
+ 15 => '15 ' . __('seconds', 'newsletter'),
111
+ 30 => '30 ' . __('seconds', 'newsletter'),
112
+ 60 => '1 ' . __('minute', 'newsletter'),
113
+ 120 => '2 ' . __('minutes', 'newsletter'),
114
+ 300 => '5 ' . __('minutes', 'newsletter'),
115
+ 600 => '10 ' . __('minutes', 'newsletter'),
116
+ 900 => '15 ' . __('minutes', 'newsletter'),
117
+ 1800 => '30 ' . __('minutes', 'newsletter')
118
+ ));
119
+ ?>
120
+ <?php $controls->help('https://www.thenewsletterplugin.com/documentation/antiflood') ?>
121
+ </td>
122
+ </tr>
123
+ <tr>
124
+ <th><?php _e('Captcha', 'newsletter') ?></th>
125
+ <td>
126
+ <?php
127
+ $controls->enabled('captcha');
128
+ ?>
129
+ </td>
130
+ </tr>
131
+ <?php /*
132
+ <tr>
133
+ <th><?php _e('Domain check', 'newsletter') ?></th>
134
+ <td>
135
+ <?php
136
+ $controls->yesno('domain_check');
137
+ ?>
138
+ </td>
139
+ </tr>
140
+ */ ?>
141
+
142
+ </table>
143
+
144
+
145
+ </div>
146
+
147
+ <div id="tabs-blacklists">
148
+ <table class="form-table">
149
+ <tr>
150
+ <th><?php _e('IP black list', 'newsletter') ?></th>
151
+ <td>
152
+ <?php
153
+ $controls->textarea('ip_blacklist');
154
+ ?>
155
+ <?php $controls->help('https://www.thenewsletterplugin.com/documentation/antiflood') ?>
156
+ </td>
157
+ </tr>
158
+ <tr>
159
+ <th><?php _e('Address black list', 'newsletter') ?></th>
160
+ <td>
161
+ <?php
162
+ $controls->textarea('address_blacklist');
163
+ ?>
164
+ <?php $controls->help('https://www.thenewsletterplugin.com/documentation/antiflood') ?>
165
+ </td>
166
+ </tr>
167
+ </table>
168
+ </div>
169
+
170
+ </div>
171
+
172
+ <p>
173
+ <?php $controls->button_save() ?>
174
+ </p>
175
+
176
+ </form>
177
+ </div>
178
+
179
+ <?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
180
+
181
+ </div>
subscription/languages/en_US.php CHANGED
@@ -14,6 +14,11 @@ $options = array();
14
 
15
  $options['noconfirmation'] = 0;
16
  $options['antiflood'] = 10;
 
 
 
 
 
17
  $options['notify_email'] = get_option('admin_email');
18
 
19
  // Profile page
14
 
15
  $options['noconfirmation'] = 0;
16
  $options['antiflood'] = 10;
17
+ $options['ip_blacklist'] = array();
18
+ $options['address_blacklist'] = array();
19
+ $options['domain_check'] = 0;
20
+ $options['akismet'] = 0;
21
+ $options['captcha'] = 0;
22
  $options['notify_email'] = get_option('admin_email');
23
 
24
  // Profile page
subscription/options.php CHANGED
@@ -253,36 +253,6 @@ if (empty($controls->data['page'])) {
253
  <?php $controls->preferences(); ?>
254
  </td>
255
  </tr>
256
- <tr>
257
- <th><?php _e('Disable antibot/antispam?', 'newsletter') ?></th>
258
- <td>
259
- <?php $controls->yesno('antibot_disable'); ?>
260
- <p class="description">
261
- <?php _e ('Disable for ajax form submission', 'newsletter'); ?>
262
- </p>
263
- </td>
264
- </tr>
265
- <tr>
266
- <th><?php _e('Antiflood', 'newsletter') ?></th>
267
- <td>
268
- <?php
269
- $controls->select('antiflood', array(
270
- 0 => __('Disabled', 'newsletter'),
271
- 5 => '5 ' . __('seconds', 'newsletter'),
272
- 10 => '10 ' . __('seconds', 'newsletter'),
273
- 15 => '15 ' . __('seconds', 'newsletter'),
274
- 30 => '30 ' . __('seconds', 'newsletter'),
275
- 60 => '1 ' . __('minute', 'newsletter'),
276
- 120 => '2 ' . __('minutes', 'newsletter'),
277
- 300 => '5 ' . __('minutes', 'newsletter'),
278
- 600 => '10 ' . __('minutes', 'newsletter'),
279
- 900 => '15 ' . __('minutes', 'newsletter'),
280
- 1800 => '30 ' . __('minutes', 'newsletter')
281
- ));
282
- ?>
283
- <?php $controls->help('https://www.thenewsletterplugin.com/documentation/antiflood') ?>
284
- </td>
285
- </tr>
286
  </table>
287
 
288
  <h3>Special cases</h3>
@@ -313,10 +283,10 @@ if (empty($controls->data['page'])) {
313
 
314
 
315
  <div id="tabs-3">
316
-
317
  <p><?php _e('Only for double opt-in mode.', 'newsletter') ?></p>
318
  <?php $controls->panel_help('https://www.thenewsletterplugin.com/documentation/subscription#activation') ?>
319
-
320
  <table class="form-table">
321
  <tr>
322
  <th><?php _e('Activation message', 'newsletter') ?></th>
@@ -367,7 +337,7 @@ if (empty($controls->data['page'])) {
367
 
368
  <tr>
369
  <th><?php _e('Conversion tracking code', 'newsletter') ?>
370
- <?php $controls->help('https://www.thenewsletterplugin.com/documentation/subscription#conversion') ?></th>
371
  <td>
372
  <?php $controls->textarea('confirmed_tracking'); ?>
373
  </td>
253
  <?php $controls->preferences(); ?>
254
  </td>
255
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  </table>
257
 
258
  <h3>Special cases</h3>
283
 
284
 
285
  <div id="tabs-3">
286
+
287
  <p><?php _e('Only for double opt-in mode.', 'newsletter') ?></p>
288
  <?php $controls->panel_help('https://www.thenewsletterplugin.com/documentation/subscription#activation') ?>
289
+
290
  <table class="form-table">
291
  <tr>
292
  <th><?php _e('Activation message', 'newsletter') ?></th>
337
 
338
  <tr>
339
  <th><?php _e('Conversion tracking code', 'newsletter') ?>
340
+ <?php $controls->help('https://www.thenewsletterplugin.com/documentation/subscription#conversion') ?></th>
341
  <td>
342
  <?php $controls->textarea('confirmed_tracking'); ?>
343
  </td>
subscription/subscription.php CHANGED
@@ -23,7 +23,7 @@ class NewsletterSubscription extends NewsletterModule {
23
 
24
  function __construct() {
25
 
26
- parent::__construct('subscription', '2.0.3');
27
 
28
  // Must be called after the Newsletter::hook_init, since some constants are defined
29
  // there.
@@ -80,6 +80,19 @@ class NewsletterSubscription extends NewsletterModule {
80
  wp_localize_script('newsletter-subscription', 'newsletter', $data);
81
  }
82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  function hook_wp_loaded() {
84
  global $newsletter, $wpdb;
85
 
@@ -90,7 +103,7 @@ class NewsletterSubscription extends NewsletterModule {
90
  if (!$user || $user->status != 'C') {
91
  die('Subscriber not found or not active.');
92
  }
93
-
94
  $email = $this->get_email_from_request();
95
  if (!$email) {
96
  die('Newsletter not found');
@@ -104,9 +117,9 @@ class NewsletterSubscription extends NewsletterModule {
104
  if (!$list || $list['status'] == 0) {
105
  die('Private list.');
106
  }
107
-
108
  $url = $_REQUEST['redirect'];
109
-
110
  $this->set_user_list($user, $list_id, $_REQUEST['value']);
111
  NewsletterStatistics::instance()->add_click(wp_sanitize_redirect($url), $user->id, $email->id);
112
  wp_safe_redirect($url);
@@ -125,30 +138,126 @@ class NewsletterSubscription extends NewsletterModule {
125
  // normal subscription
126
  case 's':
127
  case 'subscribe':
128
- // Flood check
129
- if (!empty($this->options['antiflood'])) {
130
- $ip = (string) $_SERVER['REMOTE_ADDR'];
131
- $email = $this->is_email($_REQUEST['ne']);
132
- $updated = $wpdb->get_var($wpdb->prepare("select updated from " . NEWSLETTER_USERS_TABLE . " where ip=%s or email=%s order by updated desc limit 1", $ip, $email));
133
-
134
- if ($updated && time() - $updated < $this->options['antiflood']) {
135
- die('Too quick');
136
- }
 
 
 
 
 
 
 
137
  }
138
 
139
- if (!empty($this->options['antibot_disable']) || $this->antibot_form_check()) {
140
- $user = $this->subscribe();
141
 
142
- if ($user->status == 'E')
143
- $this->show_message('error', $user->id);
144
- if ($user->status == 'C')
145
- $this->show_message('confirmed', $user->id);
146
- if ($user->status == 'A')
147
- $this->show_message('already_confirmed', $user->id);
148
- if ($user->status == 'S')
149
- $this->show_message('confirmation', $user->id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  } else {
151
- $this->request_to_antibot_form('Subscribe');
 
 
 
 
152
  }
153
  die();
154
 
@@ -299,6 +408,7 @@ class NewsletterSubscription extends NewsletterModule {
299
 
300
  function admin_menu() {
301
  $this->add_menu_page('options', 'List building');
 
302
  $this->add_admin_page('profile', 'Subscription Form');
303
  $this->add_admin_page('forms', 'Forms');
304
  $this->add_admin_page('lists', 'Lists');
23
 
24
  function __construct() {
25
 
26
+ parent::__construct('subscription', '2.0.4');
27
 
28
  // Must be called after the Newsletter::hook_init, since some constants are defined
29
  // there.
80
  wp_localize_script('newsletter-subscription', 'newsletter', $data);
81
  }
82
 
83
+ function ip_match($ip, $range) {
84
+ if (strpos($range, '/')) {
85
+ list ($subnet, $bits) = explode('/', $range);
86
+ $ip = ip2long($ip);
87
+ $subnet = ip2long($subnet);
88
+ $mask = -1 << (32 - $bits);
89
+ $subnet &= $mask; # nb: in case the supplied subnet wasn't correctly aligned
90
+ return ($ip & $mask) == $subnet;
91
+ } else {
92
+ return strpos($range, $ip) === 0;
93
+ }
94
+ }
95
+
96
  function hook_wp_loaded() {
97
  global $newsletter, $wpdb;
98
 
103
  if (!$user || $user->status != 'C') {
104
  die('Subscriber not found or not active.');
105
  }
106
+
107
  $email = $this->get_email_from_request();
108
  if (!$email) {
109
  die('Newsletter not found');
117
  if (!$list || $list['status'] == 0) {
118
  die('Private list.');
119
  }
120
+
121
  $url = $_REQUEST['redirect'];
122
+
123
  $this->set_user_list($user, $list_id, $_REQUEST['value']);
124
  NewsletterStatistics::instance()->add_click(wp_sanitize_redirect($url), $user->id, $email->id);
125
  wp_safe_redirect($url);
138
  // normal subscription
139
  case 's':
140
  case 'subscribe':
141
+
142
+ $ip = $this->get_remote_ip();
143
+ $email = $this->normalize_email($_REQUEST['ne']);
144
+ $first_name = '';
145
+ if (isset($_REQUEST['nn'])) $first_name = $this->normalize_name($_REQUEST['nn']);
146
+
147
+ $last_name = '';
148
+ if (isset($_REQUEST['ns'])) $last_name = $this->normalize_name($_REQUEST['ns']);
149
+
150
+ $full_name = trim($first_name . ' ' . $last_name);
151
+
152
+ $antibot_logger = new NewsletterLogger('antibot');
153
+
154
+ if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
155
+ $antibot_logger->fatal($email . ' - ' . $ip . ' - HTTP method invalid');
156
+ die('Invalid');
157
  }
158
 
159
+ $captcha = !empty($this->options['captcha']);
 
160
 
161
+ if (!empty($this->options['antibot_disable']) || $this->antibot_form_check($captcha)) {
162
+
163
+
164
+ if (stripos($full_name, 'http://') !== false || stripos($full_name, 'https://') !== false) {
165
+ $antibot_logger->fatal($email . ' - ' . $ip . ' - Name with http: ' . $full_name);
166
+ header("HTTP/1.0 404 Not Found");
167
+ die();
168
+ }
169
+
170
+
171
+
172
+ // Cannot check for administrator here, too early.
173
+ if (true) {
174
+
175
+ $this->logger->debug('Subscription of: ' . $email);
176
+ // if ($this->options['domain_check']) {
177
+ // $this->logger->debug('Domain checking');
178
+ // list($local, $domain) = explode('@', $email);
179
+ //
180
+ // $hosts = array();
181
+ // if (!getmxrr($domain, $hosts)) {
182
+ // $antibot_logger->fatal($email . ' - ' . $ip . ' - MX check failed');
183
+ // die('Blocked 0');
184
+ // }
185
+ // }
186
+
187
+ if (!empty($this->options['ip_blacklist'])) {
188
+ $this->logger->debug('IP blacklist check');
189
+ foreach ($this->options['ip_blacklist'] as $item) {
190
+ if ($this->ip_match($ip, $item)) {
191
+ $antibot_logger->fatal($email . ' - ' . $ip . ' - IP blacklisted');
192
+ header("HTTP/1.0 404 Not Found");
193
+ die();
194
+ }
195
+ }
196
+ }
197
+
198
+ if (!empty($this->options['address_blacklist'])) {
199
+ $this->logger->debug('Address blacklist check');
200
+ $rev_email = strrev($email);
201
+ foreach ($this->options['address_blacklist'] as $item) {
202
+ if (strpos($rev_email, strrev($item)) === 0) {
203
+ $antibot_logger->fatal($email . ' - ' . $ip . ' - Address blacklisted');
204
+ header("HTTP/1.0 404 Not Found");
205
+ die();
206
+ }
207
+ }
208
+ }
209
+
210
+ // Akismet check
211
+ if (!empty($this->options['akismet']) && class_exists('Akismet')) {
212
+ $this->logger->debug('Akismet check');
213
+ $request = 'blog=' . urlencode(home_url()) . '&referrer=' . urlencode($_SERVER['HTTP_REFERER']) .
214
+ '&user_agent=' . urlencode($_SERVER['HTTP_USER_AGENT']) .
215
+ '&comment_type=signup' .
216
+ '&comment_author_email=' . urlencode($email) .
217
+ '&user_ip=' . urlencode($_SERVER['REMOTE_ADDR']);
218
+ if (!empty($full_name)) {
219
+ $request .= '&comment_author=' . urlencode($full_name);
220
+ }
221
+
222
+ $response = Akismet::http_post($request, 'comment-check');
223
+
224
+ if ($response && $response[1] == 'true') {
225
+ $antibot_logger->fatal($email . ' - ' . $ip . ' - Akismet blocked');
226
+ header("HTTP/1.0 404 Not Found");
227
+ die();
228
+ }
229
+ }
230
+
231
+ // Flood check
232
+ if (!empty($this->options['antiflood'])) {
233
+ $this->logger->debug('Antiflood check');
234
+ $email = $this->is_email($_REQUEST['ne']);
235
+ $updated = $wpdb->get_var($wpdb->prepare("select updated from " . NEWSLETTER_USERS_TABLE . " where ip=%s or email=%s order by updated desc limit 1", $ip, $email));
236
+
237
+ if ($updated && time() - $updated < $this->options['antiflood']) {
238
+ $antibot_logger->fatal($email . ' - ' . $ip . ' - Antiflood triggered');
239
+ header("HTTP/1.0 404 Not Found");
240
+ die('Too quick');
241
+ }
242
+ }
243
+
244
+ $user = $this->subscribe();
245
+
246
+ if ($user->status == 'E')
247
+ $this->show_message('error', $user->id);
248
+ if ($user->status == 'C')
249
+ $this->show_message('confirmed', $user->id);
250
+ if ($user->status == 'A')
251
+ $this->show_message('already_confirmed', $user->id);
252
+ if ($user->status == 'S')
253
+ $this->show_message('confirmation', $user->id);
254
+ }
255
  } else {
256
+ // Temporary store data
257
+ //$data_key = wp_generate_password(16, false, false);
258
+ //set_transient('newsletter_' . $data_key, $_REQUEST, 60);
259
+ //$this->antibot_redirect($data_key);
260
+ $this->request_to_antibot_form('Subscribe', $captcha);
261
  }
262
  die();
263
 
408
 
409
  function admin_menu() {
410
  $this->add_menu_page('options', 'List building');
411
+ $this->add_menu_page('antibot', 'Security');
412
  $this->add_admin_page('profile', 'Subscription Form');
413
  $this->add_admin_page('forms', 'Forms');
414
  $this->add_admin_page('lists', 'Lists');
tnp-header.php CHANGED
@@ -58,7 +58,9 @@ $warning |= empty($status_options['mail']);
58
  <ul>
59
  <li><a href="?page=newsletter_subscription_options"><i class="fa fa-sign-in"></i> <?php _e('Subscription', 'newsletter') ?>
60
  <small><?php _e('The subscription process in detail', 'newsletter') ?></small></a></li>
61
-
 
 
62
 
63
  <li>
64
  <a href="?page=newsletter_subscription_profile"><i class="fa fa-check-square-o"></i> <?php _e('Subscription Form Fields, Buttons, Labels', 'newsletter') ?>
58
  <ul>
59
  <li><a href="?page=newsletter_subscription_options"><i class="fa fa-sign-in"></i> <?php _e('Subscription', 'newsletter') ?>
60
  <small><?php _e('The subscription process in detail', 'newsletter') ?></small></a></li>
61
+
62
+ <li><a href="?page=newsletter_subscription_antibot"><i class="fa fa-lock"></i> <?php _e('Security', 'newsletter') ?>
63
+ <small><?php _e('Spam subscriptions control', 'newsletter') ?></small></a></li>
64
 
65
  <li>
66
  <a href="?page=newsletter_subscription_profile"><i class="fa fa-check-square-o"></i> <?php _e('Subscription Form Fields, Buttons, Labels', 'newsletter') ?>
users/edit.php CHANGED
@@ -13,7 +13,10 @@ if ($controls->is_action('save')) {
13
  $email = $module->normalize_email($controls->data['email']);
14
  if (empty($email)) {
15
  $controls->errors = __('Wrong email address', 'newsletter');
 
 
16
  }
 
17
 
18
  if (empty($controls->errors)) {
19
  $user = $module->get_user($controls->data['email']);
13
  $email = $module->normalize_email($controls->data['email']);
14
  if (empty($email)) {
15
  $controls->errors = __('Wrong email address', 'newsletter');
16
+ } else {
17
+ $controls->data['email'] = $email;
18
  }
19
+
20
 
21
  if (empty($controls->errors)) {
22
  $user = $module->get_user($controls->data['email']);