Eggplant 301 Redirects - Version 2.60

Version Description

  • 2021/02/13
  • added 404 error log
  • fixed some bugs
  • made sure all DB queries use prepare() function
  • PRO version is now available for purchase from free
Download this release

Release Info

Developer WebFactory
Plugin Icon 128x128 Eggplant 301 Redirects
Version 2.60
Comparing to
See all releases

Code changes from version 2.55 to 2.60

css/eps_redirect.css CHANGED
@@ -2,11 +2,72 @@
2
  /*--------------------- Entries Table ----------------------*/
3
  /*----------------------------------------------------------*/
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  .eps-table {
6
  width: 100%;
7
  table-layout: fixed;
8
  }
9
 
 
 
 
 
 
 
 
 
10
  .eps-table .eps-table tr,
11
  #eps-redirect-save tr {
12
  background: #fefefe;
@@ -38,19 +99,19 @@
38
 
39
  .eps-table th a:link,
40
  .eps-table th a:visited {
41
- color: white;
42
  text-decoration: none;
43
  }
44
 
45
  .eps-table th {
46
  padding: 6px 10px;
47
- background: #2a95c5;
48
- color: #ffffff;
49
  }
50
 
51
  .eps-table td.redirect-small,
52
  .eps-table th.redirect-small {
53
- width: 40px;
54
  text-align: center;
55
  padding-left: 4px;
56
  padding-right: 4px;
@@ -247,6 +308,7 @@ a.button.eps-redirect-remove:hover {
247
  background: white;
248
  box-shadow: 1px 1px 6px #f4f4f4;
249
  padding: 20px;
 
250
  }
251
 
252
  #donate-box {
@@ -330,6 +392,13 @@ a.button.eps-redirect-remove:hover {
330
  border-left: 3px solid #940000;
331
  color: #940000;
332
  }
 
 
 
 
 
 
 
333
  /*----------------------------------------------------------*/
334
  /*-------------------- media queries ---------------------*/
335
  /*----------------------------------------------------------*/
@@ -381,3 +450,164 @@ a.button.eps-redirect-remove:hover {
381
  line-height: 23px;
382
  margin: 0;
383
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /*--------------------- Entries Table ----------------------*/
3
  /*----------------------------------------------------------*/
4
 
5
+ h1 img {
6
+ max-height: 30px;
7
+ padding-right: 10px;
8
+ vertical-align: bottom;
9
+ }
10
+
11
+ #eps-tabs-wrapper {
12
+ float: left;
13
+ width: 70%;
14
+ display: block;
15
+ }
16
+
17
+ #eps-sidebar-wrapper {
18
+ float: right;
19
+ width: 27%;
20
+ margin: 45px 0 0 0;
21
+ box-sizing: border-box;
22
+ }
23
+
24
+ @media screen and (max-width: 1055px) {
25
+ #eps-tabs-wrapper {
26
+ width: 100%;
27
+ float: none;
28
+ clear: both;
29
+ }
30
+
31
+ #eps-sidebar-wrapper {
32
+ display: none;
33
+ }
34
+ }
35
+
36
+ .text-center {
37
+ text-align: center;
38
+ }
39
+
40
+ .nav-tab-wrapper .pro-ad {
41
+ color: #ffffff;
42
+ background: #FF6246;
43
+ }
44
+
45
+ .sidebar-box {
46
+ box-shadow: 0 1px 1px rgb(0 0 0 / 4%);
47
+ background: white;
48
+ margin-bottom: 30px;
49
+ padding: 15px;
50
+ font-size: 14px;
51
+ line-height: 1.5;
52
+ }
53
+
54
+ .sidebar-box.pro-ad-box {
55
+ border: 2px solid #FF6246;
56
+ }
57
+
58
  .eps-table {
59
  width: 100%;
60
  table-layout: fixed;
61
  }
62
 
63
+ table.striped th {
64
+ font-weight: bold;
65
+ }
66
+
67
+ table.striped a:hover {
68
+ text-decoration: underline;
69
+ }
70
+
71
  .eps-table .eps-table tr,
72
  #eps-redirect-save tr {
73
  background: #fefefe;
99
 
100
  .eps-table th a:link,
101
  .eps-table th a:visited {
102
+ color: #000;
103
  text-decoration: none;
104
  }
105
 
106
  .eps-table th {
107
  padding: 6px 10px;
108
+ background: #fff;
109
+ color: #000;
110
  }
111
 
112
  .eps-table td.redirect-small,
113
  .eps-table th.redirect-small {
114
+ width: 60px;
115
  text-align: center;
116
  padding-left: 4px;
117
  padding-right: 4px;
308
  background: white;
309
  box-shadow: 1px 1px 6px #f4f4f4;
310
  padding: 20px;
311
+ font-size: 14px;
312
  }
313
 
314
  #donate-box {
392
  border-left: 3px solid #940000;
393
  color: #940000;
394
  }
395
+
396
+ .redirect-hits a {
397
+ color: black;
398
+ text-decoration: none;
399
+ vertical-align: bottom;
400
+ padding-left: 6px;
401
+ }
402
  /*----------------------------------------------------------*/
403
  /*-------------------- media queries ---------------------*/
404
  /*----------------------------------------------------------*/
450
  line-height: 23px;
451
  margin: 0;
452
  }
453
+
454
+ .log-ad-box {
455
+ padding: 15px;
456
+ border-left: 3px solid #FF6246;
457
+ background: #f9f9f9;
458
+ margin: 0 0 15px 0;
459
+ max-width: 750px;
460
+ font-size: 14px;
461
+ line-height: 1.6;
462
+ }
463
+
464
+ .eps-pro-dialog .ui-dialog-titlebar {
465
+ display: none;
466
+ }
467
+
468
+ .eps-pro-dialog .logo img {
469
+ max-height: 55px;
470
+ }
471
+
472
+ .eps-pro-dialog .logo {
473
+ text-align: center;
474
+ background: #f8f8f8;
475
+ margin: -16px -16px 0 -16px;
476
+ padding: 15px;
477
+ }
478
+
479
+ .eps-pro-dialog .footer {
480
+ text-align: center;
481
+ background: #f8f8f8;
482
+ margin: 0 -16px -16px -16px;
483
+ padding: 20px;
484
+ }
485
+
486
+ .eps-pro-dialog .logo span {
487
+ display: block;
488
+ font-size: 18px;
489
+ margin: 10px;
490
+ }
491
+
492
+ .eps-pro-dialog .logo span b {
493
+ border-bottom: 3px solid #FF6246;
494
+ }
495
+
496
+ #eps-pro-table {
497
+ width: 100%;
498
+ margin: 10px auto 0 auto;
499
+ border-collapse: collapse;
500
+ }
501
+
502
+ #eps-pro-table td {
503
+ padding: 4px 10px 4px 34px;
504
+ border: none;
505
+ font-size: 14px;
506
+ }
507
+
508
+ #eps-pro-table tr:last-child td {
509
+ text-align: center;
510
+ }
511
+
512
+ #eps-pro-table .dashicons-yes {
513
+ color: #FF6246;
514
+ }
515
+
516
+ #eps-pro-table .dashicons {
517
+ padding-right: 8px;
518
+ margin-left: -27px;
519
+ }
520
+
521
+ .center {
522
+ text-align: center;
523
+ }
524
+
525
+ .prices del {
526
+ color: #00000099;
527
+ }
528
+
529
+ .prices span {
530
+ font-weight: 600;
531
+ font-size: 40px;
532
+ color: #FF6246;
533
+ line-height: 1;
534
+ display: inline-block;
535
+ padding-bottom: 15px;
536
+ }
537
+
538
+ #eps-pro-table tr:first-child td {
539
+ color: #000;
540
+ font-size: 18px;
541
+ font-weight: 800 !important;
542
+ padding: 10px 0;
543
+ text-align: center;
544
+ }
545
+
546
+ .row-banner td {
547
+ font-size: 14px;
548
+ border-left: 4px solid #FF6246;
549
+ }
550
+
551
+ .row-banner p {
552
+ font-size: 14px;
553
+ max-width: 900px;
554
+ margin: 1em auto;
555
+ }
556
+
557
+ .row-banner a {
558
+ color: black !important;
559
+ text-decoration: none;
560
+ }
561
+
562
+ .row-banner a:hover {
563
+ text-decoration: underline;
564
+ }
565
+
566
+ .pro-ad-box p b {
567
+ border-bottom: 3px solid #FF6246;
568
+ }
569
+
570
+ .pro-ad-box img {
571
+ max-height: 45px;
572
+ }
573
+
574
+ x#eps-pro-table tr td:nth-child(2) {
575
+ background-color: #ffde66;
576
+ }
577
+
578
+ x#eps-pro-table tr td:last-child {
579
+ background-color: #ffde66;
580
+ }
581
+
582
+ #eps-pro-table tr:last-child td {
583
+ padding: 20px 0 25px 0;
584
+ }
585
+
586
+ #eps-pro-table tr:last-child td span {
587
+ display: block;
588
+ padding: 0 0 5px 0;
589
+ }
590
+
591
+ #eps-features {
592
+ width: 100%;
593
+ padding: 20px 0 0 0;
594
+ }
595
+
596
+ #eps-features td {
597
+ padding: 10px 20px;
598
+ }
599
+
600
+ a.button.button-buy {
601
+ padding: 11px 40px;
602
+ color: white;
603
+ background: #FF6246;
604
+ font-weight: 600;
605
+ border: none;
606
+ }
607
+
608
+ a.button.button-buy:hover {
609
+ box-shadow: 0px 0px 10px 0px rgb(255 39 0 / 52%);
610
+ background: #FF6246;
611
+ color: white;
612
+ border: none;
613
+ }
eps-301-redirects.php CHANGED
@@ -1,13 +1,17 @@
1
  <?php
2
  /*
3
  Plugin Name: 301 Redirects
4
- Description: Easily create and manage 301 redirects.
5
- Version: 2.55
6
  Author: WebFactory Ltd
7
  Author URI: https://www.webfactoryltd.com/
 
8
  Text Domain: eps-301-redirects
 
 
 
9
 
10
- Copyright 2015 - 2021 Web factory Ltd (email: 301redirects@webfactoryltd.com)
11
 
12
  This program is free software; you can redistribute it and/or modify
13
  it under the terms of the GNU General Public License, version 2, as
@@ -28,11 +32,11 @@ if (!defined('ABSPATH')) {
28
  die('Do not open this file directly.');
29
  }
30
 
31
- if (!defined('EPS_REDIRECT_PRO')) {
32
 
33
  define('EPS_REDIRECT_PATH', plugin_dir_path(__FILE__));
34
  define('EPS_REDIRECT_URL', plugins_url() . '/eps-301-redirects/');
35
- define('EPS_REDIRECT_VERSION', '2.45');
36
  define('EPS_REDIRECT_PRO', false);
37
 
38
  include(EPS_REDIRECT_PATH . 'eps-form-elements.php');
@@ -64,11 +68,6 @@ if (!defined('EPS_REDIRECT_PRO')) {
64
  if (is_admin()) {
65
 
66
  if (isset($_GET['page']) && $_GET['page'] == $EPS_Redirects_Plugin->config('page_slug')) {
67
- // actions
68
- add_action('activated_plugin', array($this, 'activation_error'));
69
- add_action('admin_footer_text', array($this, 'set_ajax_url'));
70
-
71
- // Other
72
  add_action('admin_init', array($this, 'clear_cache'));
73
  }
74
 
@@ -76,7 +75,9 @@ if (!defined('EPS_REDIRECT_PRO')) {
76
  add_action('wp_ajax_eps_redirect_delete_entry', array($this, 'ajax_eps_delete_entry'));
77
  add_action('wp_ajax_eps_redirect_get_inline_edit_entry', array($this, 'ajax_get_inline_edit_entry'));
78
  add_action('wp_ajax_eps_redirect_save', array($this, 'ajax_save_redirect'));
 
79
  add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($this, 'plugin_action_links'));
 
80
  } else {
81
  if (defined('WP_CLI') && WP_CLI) {
82
  } else {
@@ -88,7 +89,7 @@ if (!defined('EPS_REDIRECT_PRO')) {
88
 
89
  function plugin_action_links($links)
90
  {
91
- $settings_link = '<a href="' . admin_url('options-general.php?page=eps_redirects') . '" title="' . __('Configure Redirects', 'eps-301-redirects') . '">' . __('Configure Redirects', 'eps-301-redirects') . '</a>';
92
 
93
  array_unshift($links, $settings_link);
94
 
@@ -96,6 +97,23 @@ if (!defined('EPS_REDIRECT_PRO')) {
96
  } // plugin_action_links
97
 
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  /**
100
  *
101
  * DO_REDIRECT
@@ -145,6 +163,29 @@ if (!defined('EPS_REDIRECT_PRO')) {
145
  }
146
  }
147
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  /**
149
  *
150
  * FORMAT FROM URL
@@ -251,6 +292,7 @@ if (!defined('EPS_REDIRECT_PRO')) {
251
  ob_start();
252
  $dfrom = urldecode($redirect->url_from);
253
  $dto = urldecode($redirect->url_to);
 
254
  include(EPS_REDIRECT_PATH . 'templates/template.redirect-entry.php');
255
  $html = ob_get_contents();
256
  ob_end_clean();
@@ -275,7 +317,7 @@ if (!defined('EPS_REDIRECT_PRO')) {
275
  {
276
  global $wpdb;
277
  $table_name = $wpdb->prefix . "redirects";
278
- $query = "SELECT id FROM $table_name WHERE url_from = '" . $redirect['url_from'] . "'";
279
  $result = $wpdb->get_row($query);
280
  return ($result) ? $result : false;
281
  }
@@ -365,10 +407,10 @@ if (!defined('EPS_REDIRECT_PRO')) {
365
  $orderby = (in_array(strtolower($orderby), array('id', 'url_from', 'url_to', 'count'))) ? $orderby : 'id';
366
  $order = (in_array(strtolower($order), array('asc', 'desc'))) ? $order : 'desc';
367
 
368
- $query = "SELECT *
369
  FROM $table_name
370
- WHERE status != 404 " . (($active_only) ? "AND status != 'inactive'" : null) . "
371
- ORDER BY $orderby $order";
372
  //die($query);
373
  $results = $wpdb->get_results($query);
374
 
@@ -391,9 +433,8 @@ if (!defined('EPS_REDIRECT_PRO')) {
391
  {
392
  global $wpdb;
393
  $table_name = $wpdb->prefix . "redirects";
394
- $results = $wpdb->get_results(
395
- "SELECT * FROM $table_name WHERE id = " . intval($redirect_id) . " LIMIT 1"
396
- );
397
  return array_shift($results);
398
  }
399
 
@@ -411,7 +452,8 @@ if (!defined('EPS_REDIRECT_PRO')) {
411
  {
412
  global $wpdb;
413
  $table_name = $wpdb->prefix . "redirects";
414
- $results = $wpdb->query("UPDATE $table_name SET $field = $field + 1 WHERE id = $id");
 
415
  return $results;
416
  }
417
 
@@ -431,10 +473,12 @@ if (!defined('EPS_REDIRECT_PRO')) {
431
  $html = '';
432
  if (empty($redirects)) return false;
433
  ob_start();
 
434
  foreach ($redirects as $redirect) {
435
  $dfrom = urldecode($redirect->url_from);
436
  $dto = urldecode($redirect->url_to);
437
  include(EPS_REDIRECT_PATH . 'templates/template.redirect-entry.php');
 
438
  }
439
  $html = ob_get_contents();
440
  ob_end_clean();
@@ -547,33 +591,29 @@ public function clear_cache()
547
  }
548
 
549
 
550
-
551
- /**
552
- *
553
- * SET_AJAX_URL
554
- *
555
- * This function will output a variable containing the admin ajax url for use in javascript.
556
- *
557
- * @author WebFactory Ltd
558
- *
559
- */
560
- public static function set_ajax_url()
561
  {
562
- //echo '<script>var eps_redirect_ajax_url = "' . admin_url('admin-ajax.php') . '"</script>';
563
- }
564
-
565
 
 
566
 
567
- public function activation_error()
568
- {
569
- file_put_contents(EPS_REDIRECT_PATH . '/error_activation.html', ob_get_contents());
570
- }
571
 
 
 
 
 
572
 
573
- public static function check_404()
574
- { }
575
- }
576
 
 
 
 
577
 
578
 
579
  /**
@@ -599,19 +639,17 @@ if (!function_exists('eps_view')) {
599
  }
600
  }
601
 
602
-
603
  // Run the plugin.
604
  $EPS_Redirects = new EPS_Redirects();
605
  } else {
606
- if (EPS_REDIRECT_PRO === true) {
607
  add_action('admin_notices', 'eps_redirects_pro_conflict');
608
- function eps_redirects_pro_conflict()
609
- {
 
610
  printf(
611
  '<div class="%s"><p>%s</p></div>',
612
  "error",
613
- "ERROR: Please de-activate the non-Pro version of EPS 301 Redirects First!"
614
  );
615
  }
616
- }
617
  }
1
  <?php
2
  /*
3
  Plugin Name: 301 Redirects
4
+ Description: Easily create and manage redirect rules.
5
+ Version: 2.60
6
  Author: WebFactory Ltd
7
  Author URI: https://www.webfactoryltd.com/
8
+ Plugin URI: https://wp301redirects.com/
9
  Text Domain: eps-301-redirects
10
+ Requires at least: 3.6
11
+ Tested up to: 5.6
12
+ Requires PHP: 5.2
13
 
14
+ Copyright 2015 - 2021 WebFactory Ltd (email: 301redirects@webfactoryltd.com)
15
 
16
  This program is free software; you can redistribute it and/or modify
17
  it under the terms of the GNU General Public License, version 2, as
32
  die('Do not open this file directly.');
33
  }
34
 
35
+ if (!defined('WF301_PLUGIN_FILE')) {
36
 
37
  define('EPS_REDIRECT_PATH', plugin_dir_path(__FILE__));
38
  define('EPS_REDIRECT_URL', plugins_url() . '/eps-301-redirects/');
39
+ define('EPS_REDIRECT_VERSION', '2.60');
40
  define('EPS_REDIRECT_PRO', false);
41
 
42
  include(EPS_REDIRECT_PATH . 'eps-form-elements.php');
68
  if (is_admin()) {
69
 
70
  if (isset($_GET['page']) && $_GET['page'] == $EPS_Redirects_Plugin->config('page_slug')) {
 
 
 
 
 
71
  add_action('admin_init', array($this, 'clear_cache'));
72
  }
73
 
75
  add_action('wp_ajax_eps_redirect_delete_entry', array($this, 'ajax_eps_delete_entry'));
76
  add_action('wp_ajax_eps_redirect_get_inline_edit_entry', array($this, 'ajax_get_inline_edit_entry'));
77
  add_action('wp_ajax_eps_redirect_save', array($this, 'ajax_save_redirect'));
78
+ add_action('wp_ajax_eps_dismiss_pointer', array($this, 'dismiss_pointer_ajax'));
79
  add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($this, 'plugin_action_links'));
80
+ add_filter('admin_footer_text', array($this, 'admin_footer_text'));
81
  } else {
82
  if (defined('WP_CLI') && WP_CLI) {
83
  } else {
89
 
90
  function plugin_action_links($links)
91
  {
92
+ $settings_link = '<a href="' . admin_url('options-general.php?page=eps_redirects') . '" title="' . __('Manage Redirects', 'eps-301-redirects') . '">' . __('Manage Redirects', 'eps-301-redirects') . '</a>';
93
 
94
  array_unshift($links, $settings_link);
95
 
97
  } // plugin_action_links
98
 
99
 
100
+ // permanently dismiss a pointer
101
+ function dismiss_pointer_ajax() {
102
+ check_ajax_referer('eps_dismiss_pointer');
103
+
104
+ $pointers = get_option('eps_pointers');
105
+ $pointer = trim($_POST['pointer_name']);
106
+
107
+ if (empty($pointers) || empty($pointers[$pointer])) {
108
+ wp_send_json_error();
109
+ }
110
+
111
+ unset($pointers[$pointer]);
112
+ update_option('eps_pointers', $pointers);
113
+
114
+ wp_send_json_success();
115
+ } // dismiss_pointer_ajax
116
+
117
  /**
118
  *
119
  * DO_REDIRECT
163
  }
164
  }
165
 
166
+ // additional powered by text in admin footer; only on 301 page
167
+ function admin_footer_text($text) {
168
+ if (!$this->is_plugin_page()) {
169
+ return $text;
170
+ }
171
+
172
+ $text = '<i><a href="https://wp301redirects.com/?ref=free-eps-301-redirects" title="Visit WP 301 Redirects site for more info" target="_blank">WP 301 Redirects</a> v' . EPS_REDIRECT_VERSION . ' by <a href="https://www.webfactoryltd.com/" title="Visit our site to get more great plugins" target="_blank">WebFactory Ltd</a>. Please <a target="_blank" href="https://wordpress.org/support/plugin/eps-301-redirects/reviews/#new-post" title="Rate the plugin">rate the plugin <span>★★★★★</span></a> to help us spread the word. Thank you!</i>';
173
+
174
+ return $text;
175
+ } // admin_footer_text
176
+
177
+
178
+ // test if we're on plugin's page
179
+ function is_plugin_page() {
180
+ $current_screen = get_current_screen();
181
+
182
+ if ($current_screen->id == 'settings_page_eps_redirects') {
183
+ return true;
184
+ } else {
185
+ return false;
186
+ }
187
+ } // is_plugin_page
188
+
189
  /**
190
  *
191
  * FORMAT FROM URL
292
  ob_start();
293
  $dfrom = urldecode($redirect->url_from);
294
  $dto = urldecode($redirect->url_to);
295
+ $i=0;
296
  include(EPS_REDIRECT_PATH . 'templates/template.redirect-entry.php');
297
  $html = ob_get_contents();
298
  ob_end_clean();
317
  {
318
  global $wpdb;
319
  $table_name = $wpdb->prefix . "redirects";
320
+ $query = $wpdb->prepare("SELECT id FROM $table_name WHERE url_from = %s", $redirect['url_from']);
321
  $result = $wpdb->get_row($query);
322
  return ($result) ? $result : false;
323
  }
407
  $orderby = (in_array(strtolower($orderby), array('id', 'url_from', 'url_to', 'count'))) ? $orderby : 'id';
408
  $order = (in_array(strtolower($order), array('asc', 'desc'))) ? $order : 'desc';
409
 
410
+ $query = $wpdb->prepare("SELECT *
411
  FROM $table_name
412
+ WHERE 1 = %d AND status != 404 " . (($active_only) ? "AND status != 'inactive'" : null) . "
413
+ ORDER BY $orderby $order", 1);
414
  //die($query);
415
  $results = $wpdb->get_results($query);
416
 
433
  {
434
  global $wpdb;
435
  $table_name = $wpdb->prefix . "redirects";
436
+ $query = $wpdb->prepare("SELECT * FROM $table_name WHERE id = %d LIMIT 1", intval($redirect_id));
437
+ $results = $wpdb->get_results($query);
 
438
  return array_shift($results);
439
  }
440
 
452
  {
453
  global $wpdb;
454
  $table_name = $wpdb->prefix . "redirects";
455
+ $id = intval($id);
456
+ $results = $wpdb->query("UPDATE $table_name SET count = count + 1 WHERE id = $id");
457
  return $results;
458
  }
459
 
473
  $html = '';
474
  if (empty($redirects)) return false;
475
  ob_start();
476
+ $i = 1;
477
  foreach ($redirects as $redirect) {
478
  $dfrom = urldecode($redirect->url_from);
479
  $dto = urldecode($redirect->url_to);
480
  include(EPS_REDIRECT_PATH . 'templates/template.redirect-entry.php');
481
+ $i++;
482
  }
483
  $html = ob_get_contents();
484
  ob_end_clean();
591
  }
592
 
593
 
594
+ public static function check_404()
 
 
 
 
 
 
 
 
 
 
595
  {
596
+ if (!is_404()) {
597
+ return;
598
+ }
599
 
600
+ $log404 = get_option('eps_redirects_404_log', array());
601
 
602
+ if (!is_array($log404)) {
603
+ $log404 = array();
604
+ }
 
605
 
606
+ $last['timestamp'] = current_time('timestamp');
607
+ $last['url'] = @strip_tags($_SERVER['REQUEST_URI']);
608
+ $last['user_agent'] = @strip_tags($_SERVER['HTTP_USER_AGENT']);
609
+ array_unshift($log404, $last);
610
 
611
+ $max = abs(apply_filters('eps_301_max_404_logs', 50));
612
+ $log404 = array_slice($log404, 0, $max);
 
613
 
614
+ update_option('eps_redirects_404_log', $log404);
615
+ } // check_404
616
+ } // EPS_redirects
617
 
618
 
619
  /**
639
  }
640
  }
641
 
 
642
  // Run the plugin.
643
  $EPS_Redirects = new EPS_Redirects();
644
  } else {
 
645
  add_action('admin_notices', 'eps_redirects_pro_conflict');
646
+ function eps_redirects_pro_conflict() {
647
+ $deactivate = 'plugins.php?action=deactivate&plugin=eps-301-redirects/eps-301-redirects.php&plugin_status=all&paged=1';
648
+ $deactivate = wp_nonce_url($deactivate, 'deactivate-plugin_eps-301-redirects/eps-301-redirects.php');
649
  printf(
650
  '<div class="%s"><p>%s</p></div>',
651
  "error",
652
+ '<b>WARNING</b>: <a href="' . admin_url($deactivate) . '">Deactivate</a> the 301 Redirects free plugin. PRO version is active. You can\'t use both at the same time.'
653
  );
654
  }
 
655
  }
error_activation.html DELETED
File without changes
images/icon-eps-redirects.jpg DELETED
Binary file
images/wp-301-logo-full.png ADDED
Binary file
images/wp-301-logo.png ADDED
Binary file
js/eps-admin-pointers.js ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * EPS 301 Redirects
3
+ * Backend GUI pointers
4
+ * (c) WebFactory Ltd
5
+ */
6
+
7
+
8
+ jQuery(document).ready(function($){
9
+ if (typeof eps_pointers == 'undefined') {
10
+ return;
11
+ }
12
+
13
+ $.each(eps_pointers, function(index, pointer) {
14
+ if (index.charAt(0) == '_') {
15
+ return true;
16
+ }
17
+ $(pointer.target).pointer({
18
+ content: '<h3>301 Redirects</h3><p>' + pointer.content + '</p>',
19
+ position: {
20
+ edge: pointer.edge,
21
+ align: pointer.align
22
+ },
23
+ width: 320,
24
+ close: function() {
25
+ $.post(ajaxurl, {
26
+ pointer_name: index,
27
+ _ajax_nonce: eps_pointers._nonce_dismiss_pointer,
28
+ action: 'eps_dismiss_pointer'
29
+ });
30
+ }
31
+ }).pointer('open');
32
+ });
33
+ });
js/scripts.js CHANGED
@@ -5,8 +5,6 @@
5
 
6
  jQuery(document).ready(function($) {
7
  /**
8
- *
9
- *
10
  * Loads the relevant sub-selector based on the primary selector.
11
  */
12
  $(document).on('change', 'select.type-select', function() {
@@ -21,8 +19,6 @@ jQuery(document).ready(function($) {
21
  });
22
 
23
  /**
24
- *
25
- *
26
  * When a select box is changed, send that new value to our input.
27
  */
28
  $(document).on('change', 'select.url-selector', function() {
@@ -33,12 +29,8 @@ jQuery(document).ready(function($) {
33
  });
34
 
35
  /**
36
- *
37
  * Edit a Redirect
38
- *
39
  * Gets the redirect edit form, and replaces the row.
40
- *
41
- *
42
  */
43
  $('.eps-table').on('click', '.redirect-actions a.eps-redirect-edit', function(
44
  e
@@ -75,13 +67,8 @@ jQuery(document).ready(function($) {
75
  });
76
 
77
  /**
78
- *
79
- *
80
  * Cancel an Edit.
81
- *
82
  * Cancels the Edit implement on a redirect entry.
83
- *
84
- *
85
  */
86
  $('.eps-table').on('click', 'a.eps-redirect-cancel', function(e) {
87
  e.preventDefault();
@@ -91,12 +78,8 @@ jQuery(document).ready(function($) {
91
  });
92
 
93
  /**
94
- *
95
- *
96
  * AJAX Save a New or Existing Redirect.
97
- *
98
  * Checks for a form submission, then handles it VIA ajax.
99
- *
100
  */
101
  $('.eps-table').on('submit', '#eps-redirect-save', function(e) {
102
  e.preventDefault();
@@ -147,11 +130,8 @@ jQuery(document).ready(function($) {
147
  });
148
 
149
  /**
150
- *
151
  * New Redirect.
152
- *
153
  * Get a new blank edit form for a new redirect.
154
- *
155
  * We expect to receive an id of 0 returned from the Ajax query.
156
  *
157
  */
@@ -182,25 +162,28 @@ jQuery(document).ready(function($) {
182
  // If it's a new blank form.. why have an id?
183
  alert('Something strange happened. A new entry could not be loaded.');
184
  }
185
- $(this).prop('disabled', false);
186
- $(this).attr('disabled', false); // Disable button to disallow multiple submissions.
187
  },
188
  error: function() {
189
  // failed request; give feedback to user
190
  alert('A new entry form could not be loaded.');
191
- $(this).prop('disabled', false);
192
- $(this).attr('disabled', false); // Disable button to disallow multiple submissions.
193
  }
194
  });
195
  });
196
 
197
  /**
198
- *
199
- *
200
  * Delete an entry.
201
  */
202
  $('.redirect-actions a.eps-redirect-remove').on('click', function(e) {
203
  e.preventDefault();
 
 
 
 
 
204
  if ($(this).attr('disabled')) return false;
205
 
206
  $(this).prop('disabled', true);
@@ -220,8 +203,6 @@ jQuery(document).ready(function($) {
220
  });
221
 
222
  /**
223
- *
224
- *
225
  * Tabs
226
  */
227
  $('#eps-tab-nav .eps-tab-nav-item').on('click', function(e) {
@@ -238,4 +219,67 @@ jQuery(document).ready(function($) {
238
  $(this).addClass('active');
239
  //return false;
240
  });
241
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  jQuery(document).ready(function($) {
7
  /**
 
 
8
  * Loads the relevant sub-selector based on the primary selector.
9
  */
10
  $(document).on('change', 'select.type-select', function() {
19
  });
20
 
21
  /**
 
 
22
  * When a select box is changed, send that new value to our input.
23
  */
24
  $(document).on('change', 'select.url-selector', function() {
29
  });
30
 
31
  /**
 
32
  * Edit a Redirect
 
33
  * Gets the redirect edit form, and replaces the row.
 
 
34
  */
35
  $('.eps-table').on('click', '.redirect-actions a.eps-redirect-edit', function(
36
  e
67
  });
68
 
69
  /**
 
 
70
  * Cancel an Edit.
 
71
  * Cancels the Edit implement on a redirect entry.
 
 
72
  */
73
  $('.eps-table').on('click', 'a.eps-redirect-cancel', function(e) {
74
  e.preventDefault();
78
  });
79
 
80
  /**
 
 
81
  * AJAX Save a New or Existing Redirect.
 
82
  * Checks for a form submission, then handles it VIA ajax.
 
83
  */
84
  $('.eps-table').on('submit', '#eps-redirect-save', function(e) {
85
  e.preventDefault();
130
  });
131
 
132
  /**
 
133
  * New Redirect.
 
134
  * Get a new blank edit form for a new redirect.
 
135
  * We expect to receive an id of 0 returned from the Ajax query.
136
  *
137
  */
162
  // If it's a new blank form.. why have an id?
163
  alert('Something strange happened. A new entry could not be loaded.');
164
  }
165
+ $('#eps-redirect-new').removeProp('disabled');
166
+ $('#eps-redirect-new').attr('disabled', false); // Disable button to disallow multiple submissions.
167
  },
168
  error: function() {
169
  // failed request; give feedback to user
170
  alert('A new entry form could not be loaded.');
171
+ $('#eps-redirect-new').removeProp('disabled');
172
+ $('#eps-redirect-new').attr('disabled', false); // Disable button to disallow multiple submissions.
173
  }
174
  });
175
  });
176
 
177
  /**
 
 
178
  * Delete an entry.
179
  */
180
  $('.redirect-actions a.eps-redirect-remove').on('click', function(e) {
181
  e.preventDefault();
182
+
183
+ if (!confirm('Are you sure you want to delete this redirect rule? There is no undo!')) {
184
+ return false;
185
+ }
186
+
187
  if ($(this).attr('disabled')) return false;
188
 
189
  $(this).prop('disabled', true);
203
  });
204
 
205
  /**
 
 
206
  * Tabs
207
  */
208
  $('#eps-tab-nav .eps-tab-nav-item').on('click', function(e) {
219
  $(this).addClass('active');
220
  //return false;
221
  });
222
+
223
+ // PRO related stuff
224
+ $('.nav-tab-wrapper a.pro-ad').on('click', function(e) {
225
+ e.preventDefault();
226
+ pro_feature = 'tab';
227
+
228
+ $('#eps-pro-dialog').dialog('open');
229
+
230
+ $('#eps-pro-table .button-buy').each(function(ind, el) {
231
+ tmp = $(el).data('href-org');
232
+ tmp = tmp.replace('pricing-table', pro_feature);
233
+ $(el).attr('href', tmp);
234
+ });
235
+
236
+ return false;
237
+ });
238
+
239
+ $('#wpwrap').on('click', '.open-301-pro-dialog', function(e) {
240
+ e.preventDefault();
241
+
242
+ $('#eps-pro-dialog').dialog('open');
243
+
244
+ pro_feature = $(this).data('pro-feature');
245
+ if (!pro_feature) {
246
+ pro_feature = 'unknown';
247
+ }
248
+
249
+ $('#eps-pro-table .button-buy').each(function(ind, el) {
250
+ tmp = $(el).data('href-org');
251
+ tmp = tmp.replace('pricing-table', pro_feature);
252
+ $(el).attr('href', tmp);
253
+ });
254
+
255
+ return false;
256
+ });
257
+
258
+ $('#eps-pro-dialog').dialog({
259
+ dialogClass: 'wp-dialog eps-pro-dialog',
260
+ modal: true,
261
+ resizable: false,
262
+ width: 800,
263
+ height: 'auto',
264
+ show: 'fade',
265
+ hide: 'fade',
266
+ close: function (event, ui) {
267
+ },
268
+ open: function (event, ui) {
269
+ $(this).siblings().find('span.ui-dialog-title').html('WP 301 Redirects PRO is here!');
270
+ eps_fix_dialog_close(event, ui);
271
+ },
272
+ autoOpen: false,
273
+ closeOnEscape: true,
274
+ });
275
+
276
+ if (eps_301.auto_open_pro_dialog) {
277
+ $('#eps-pro-dialog').dialog('open');
278
+ }
279
+ }); // on ready
280
+
281
+ function eps_fix_dialog_close(event, ui) {
282
+ jQuery('.ui-widget-overlay').bind('click', function () {
283
+ jQuery('#' + event.target.id).dialog('close');
284
+ });
285
+ } // eps_fix_dialog_close
libs/UserAgent/Browsers.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // DO NOT EDIT THIS FILE - IT IS GENERATED BY constant_generator.php
4
+
5
+ namespace epsdonatj\UserAgent;
6
+
7
+ interface Browsers {
8
+
9
+ const ADSBOT_GOOGLE = 'AdsBot-Google';
10
+ const ANDROID_BROWSER = 'Android Browser';
11
+ const APPLEBOT = 'Applebot';
12
+ const BAIDUSPIDER = 'Baiduspider';
13
+ const BINGBOT = 'bingbot';
14
+ const BLACKBERRY_BROWSER = 'BlackBerry Browser';
15
+ const BROWSER = 'Browser';
16
+ const BUNJALLOO = 'Bunjalloo';
17
+ const CAMINO = 'Camino';
18
+ const CHROME = 'Chrome';
19
+ const CURL = 'curl';
20
+ const EDGE = 'Edge';
21
+ const FACEBOOKEXTERNALHIT = 'facebookexternalhit';
22
+ const FEEDVALIDATOR = 'FeedValidator';
23
+ const FIREFOX = 'Firefox';
24
+ const GOOGLEBOT = 'Googlebot';
25
+ const GOOGLEBOT_IMAGE = 'Googlebot-Image';
26
+ const GOOGLEBOT_VIDEO = 'Googlebot-Video';
27
+ const HEADLESSCHROME = 'HeadlessChrome';
28
+ const IEMOBILE = 'IEMobile';
29
+ const KINDLE = 'Kindle';
30
+ const LYNX = 'Lynx';
31
+ const MIDORI = 'Midori';
32
+ const MSIE = 'MSIE';
33
+ const MSNBOT_MEDIA = 'msnbot-media';
34
+ const NETFRONT = 'NetFront';
35
+ const NINTENDOBROWSER = 'NintendoBrowser';
36
+ const OCULUSBROWSER = 'OculusBrowser';
37
+ const OPERA = 'Opera';
38
+ const PUFFIN = 'Puffin';
39
+ const SAFARI = 'Safari';
40
+ const SAMSUNGBROWSER = 'SamsungBrowser';
41
+ const SILK = 'Silk';
42
+ const TIZENBROWSER = 'TizenBrowser';
43
+ const UC_BROWSER = 'UC Browser';
44
+ const VALVE_STEAM_TENFOOT = 'Valve Steam Tenfoot';
45
+ const VIVALDI = 'Vivaldi';
46
+ const WGET = 'Wget';
47
+ const WORDPRESS = 'WordPress';
48
+ const YANDEX = 'Yandex';
49
+ const YANDEXBOT = 'YandexBot';
50
+
51
+ }
52
+
libs/UserAgent/Platforms.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // DO NOT EDIT THIS FILE - IT IS GENERATED BY constant_generator.php
4
+
5
+ namespace epsdonatj\UserAgent;
6
+
7
+ interface Platforms {
8
+
9
+ const MACINTOSH = 'Macintosh';
10
+ const CHROME_OS = 'Chrome OS';
11
+ const LINUX = 'Linux';
12
+ const WINDOWS = 'Windows';
13
+ const ANDROID = 'Android';
14
+ const BLACKBERRY = 'BlackBerry';
15
+ const FREEBSD = 'FreeBSD';
16
+ const IPAD = 'iPad';
17
+ const IPHONE = 'iPhone';
18
+ const IPOD = 'iPod';
19
+ const KINDLE = 'Kindle';
20
+ const KINDLE_FIRE = 'Kindle Fire';
21
+ const NETBSD = 'NetBSD';
22
+ const NEW_NINTENDO_3DS = 'New Nintendo 3DS';
23
+ const NINTENDO_3DS = 'Nintendo 3DS';
24
+ const NINTENDO_DS = 'Nintendo DS';
25
+ const NINTENDO_SWITCH = 'Nintendo Switch';
26
+ const NINTENDO_WII = 'Nintendo Wii';
27
+ const NINTENDO_WIIU = 'Nintendo WiiU';
28
+ const OPENBSD = 'OpenBSD';
29
+ const PLAYBOOK = 'PlayBook';
30
+ const PLAYSTATION_3 = 'PlayStation 3';
31
+ const PLAYSTATION_4 = 'PlayStation 4';
32
+ const PLAYSTATION_VITA = 'PlayStation Vita';
33
+ const SYMBIAN = 'Symbian';
34
+ const TIZEN = 'Tizen';
35
+ const WINDOWS_PHONE = 'Windows Phone';
36
+ const XBOX = 'Xbox';
37
+ const XBOX_ONE = 'Xbox One';
38
+
39
+ }
40
+
libs/UserAgent/UserAgent.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace epsdonatj\UserAgent;
4
+
5
+ class UserAgent implements UserAgentInterface {
6
+
7
+ /**
8
+ * @var string|null
9
+ */
10
+ private $platform;
11
+ /**
12
+ * @var string|null
13
+ */
14
+ private $browser;
15
+ /**
16
+ * @var string|null
17
+ */
18
+ private $browserVersion;
19
+
20
+ /**
21
+ * UserAgent constructor.
22
+ *
23
+ * @param string|null $platform
24
+ * @param string|null $browser
25
+ * @param string|null $browserVersion
26
+ */
27
+ public function __construct( $platform, $browser, $browserVersion ) {
28
+ $this->platform = $platform;
29
+ $this->browser = $browser;
30
+ $this->browserVersion = $browserVersion;
31
+ }
32
+
33
+ /**
34
+ * @return string|null
35
+ * @see \epsdonatj\UserAgent\Platforms for a list of tested platforms
36
+ */
37
+ public function platform() {
38
+ return $this->platform;
39
+ }
40
+
41
+ /**
42
+ * @return string|null
43
+ * @see \epsdonatj\UserAgent\Browsers for a list of tested browsers.
44
+ */
45
+ public function browser() {
46
+ return $this->browser;
47
+ }
48
+
49
+ /**
50
+ * The version string. Formatting depends on the browser.
51
+ *
52
+ * @return string|null
53
+ */
54
+ public function browserVersion() {
55
+ return $this->browserVersion;
56
+ }
57
+ }
libs/UserAgent/UserAgentInterface.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace epsdonatj\UserAgent;
4
+
5
+ interface UserAgentInterface {
6
+
7
+ /**
8
+ * @return string|null
9
+ * @see \epsdonatj\UserAgent\Platforms for a list of tested platforms
10
+ */
11
+ public function platform();
12
+
13
+ /**
14
+ * @return string|null
15
+ * @see \epsdonatj\UserAgent\Browsers for a list of tested browsers.
16
+ */
17
+ public function browser();
18
+
19
+ /**
20
+ * The version string. Formatting depends on the browser.
21
+ *
22
+ * @return string|null
23
+ */
24
+ public function browserVersion();
25
+ }
libs/UserAgent/UserAgentParser.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace epsdonatj\UserAgent;
4
+
5
+ class UserAgentParser {
6
+
7
+ /**
8
+ * Parses a user agent string into its important parts, provide an object
9
+ *
10
+ * @param string|null $u_agent User agent string to parse or null. Uses $_SERVER['HTTP_USER_AGENT'] on NULL
11
+ * @return UserAgent an object with 'browser', 'browserVersion' and 'platform' methods
12
+ * @throws \InvalidArgumentException on not having a proper user agent to parse.
13
+ * @see \epsdonatj\UserAgent\parse_user_agent()
14
+ *
15
+ */
16
+ public function parse( $u_agent = null ) {
17
+ $parsed = parse_user_agent($u_agent);
18
+
19
+ return new UserAgent(
20
+ $parsed[PLATFORM],
21
+ $parsed[BROWSER],
22
+ $parsed[BROWSER_VERSION]
23
+ );
24
+ }
25
+
26
+ /**
27
+ * Parses a user agent string into its important parts
28
+ *
29
+ * @param string|null $u_agent User agent string to parse or null. Uses $_SERVER['HTTP_USER_AGENT'] on NULL
30
+ * @return UserAgent an object with 'browser', 'browserVersion' and 'platform' methods
31
+ * @throws \InvalidArgumentException on not having a proper user agent to parse.
32
+ * @see \epsdonatj\UserAgent\parse_user_agent()
33
+ *
34
+ */
35
+ public function __invoke( $u_agent = null ) {
36
+ return $this->parse($u_agent);
37
+ }
38
+
39
+ }
libs/UserAgentParser.php ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * @author Jesse G. Donat <donatj@gmail.com>
5
+ *
6
+ * @link https://donatstudios.com/PHP-Parser-HTTP_USER_AGENT
7
+ * @link https://github.com/donatj/PhpUserAgent
8
+ *
9
+ * @license MIT https://github.com/donatj/PhpUserAgent/blob/master/LICENSE.md
10
+ */
11
+
12
+ namespace {
13
+
14
+ /**
15
+ * Parses a user agent string into its important parts
16
+ *
17
+ * This method is defined for backwards comparability with the old global method.
18
+ *
19
+ * @param string|null $u_agent User agent string to parse or null. Uses $_SERVER['HTTP_USER_AGENT'] on NULL
20
+ * @return string[] an array with 'browser', 'version' and 'platform' keys
21
+ * @throws \InvalidArgumentException on not having a proper user agent to parse.
22
+ *
23
+ * @deprecated This exists for backwards compatibility with 0.x and will likely be removed in 2.x
24
+ * @see \epsdonatj\UserAgent\parse_user_agent
25
+ */
26
+ function parse_user_agent( $u_agent = null ) {
27
+ return \epsdonatj\UserAgent\parse_user_agent($u_agent);
28
+ }
29
+ }
30
+
31
+ namespace epsdonatj\UserAgent {
32
+
33
+ const PLATFORM = 'platform';
34
+ const BROWSER = 'browser';
35
+ const BROWSER_VERSION = 'version';
36
+
37
+ /**
38
+ * Parses a user agent string into its important parts
39
+ *
40
+ * @param string|null $u_agent User agent string to parse or null. Uses $_SERVER['HTTP_USER_AGENT'] on NULL
41
+ * @return string[] an array with 'browser', 'version' and 'platform' keys
42
+ * @throws \InvalidArgumentException on not having a proper user agent to parse.
43
+ */
44
+ function parse_user_agent( $u_agent = null ) {
45
+ if( $u_agent === null && isset($_SERVER['HTTP_USER_AGENT']) ) {
46
+ $u_agent = (string)$_SERVER['HTTP_USER_AGENT'];
47
+ }
48
+
49
+ if( $u_agent === null ) {
50
+ throw new \InvalidArgumentException('parse_user_agent requires a user agent');
51
+ }
52
+
53
+ $platform = null;
54
+ $browser = null;
55
+ $version = null;
56
+
57
+ $empty = array( PLATFORM => $platform, BROWSER => $browser, BROWSER_VERSION => $version );
58
+
59
+ if( !$u_agent ) {
60
+ return $empty;
61
+ }
62
+
63
+ if( preg_match('/\((.*?)\)/m', $u_agent, $parent_matches) ) {
64
+ preg_match_all(<<<'REGEX'
65
+ /(?P<platform>BB\d+;|Android|Adr|Symbian|CrOS|Tizen|iPhone|iPad|iPod|Linux|(Open|Net|Free)BSD|Macintosh|Windows(\ Phone)?|Silk|linux-gnu|BlackBerry|PlayBook|X11|(New\ )?Nintendo\ (WiiU?|3?DS|Switch)|Xbox(\ One)?)
66
+ (?:\ [^;]*)?
67
+ (?:;|$)/imx
68
+ REGEX
69
+ , $parent_matches[1], $result);
70
+
71
+ $priority = array( 'Xbox One', 'Xbox', 'Windows Phone', 'Tizen', 'Android', 'FreeBSD', 'NetBSD', 'OpenBSD', 'CrOS', 'X11' );
72
+
73
+ $result[PLATFORM] = array_unique($result[PLATFORM]);
74
+ if( count($result[PLATFORM]) > 1 ) {
75
+ if( $keys = array_intersect($priority, $result[PLATFORM]) ) {
76
+ $platform = reset($keys);
77
+ } else {
78
+ $platform = $result[PLATFORM][0];
79
+ }
80
+ } elseif( isset($result[PLATFORM][0]) ) {
81
+ $platform = $result[PLATFORM][0];
82
+ }
83
+ }
84
+
85
+ if( $platform == 'linux-gnu' || $platform == 'X11' ) {
86
+ $platform = 'Linux';
87
+ } elseif( $platform == 'CrOS' ) {
88
+ $platform = 'Chrome OS';
89
+ } elseif( $platform == 'Adr' ) {
90
+ $platform = 'Android';
91
+ }
92
+
93
+ preg_match_all(<<<'REGEX'
94
+ %(?P<browser>Camino|Kindle(\ Fire)?|Firefox|Iceweasel|IceCat|Safari|MSIE|Trident|AppleWebKit|
95
+ TizenBrowser|(?:Headless)?Chrome|YaBrowser|Vivaldi|IEMobile|Opera|OPR|Silk|Midori|Edge|Edg|CriOS|UCBrowser|Puffin|OculusBrowser|SamsungBrowser|
96
+ Baiduspider|Applebot|Googlebot|YandexBot|bingbot|Lynx|Version|Wget|curl|
97
+ Valve\ Steam\ Tenfoot|
98
+ NintendoBrowser|PLAYSTATION\ (\d|Vita)+)
99
+ (?:\)?;?)
100
+ (?:(?:[:/ ])(?P<version>[0-9A-Z.]+)|/(?:[A-Z]*))%ix
101
+ REGEX
102
+ , $u_agent, $result);
103
+
104
+ // If nothing matched, return null (to avoid undefined index errors)
105
+ if( !isset($result[BROWSER][0]) || !isset($result[BROWSER_VERSION][0]) ) {
106
+ if( preg_match('%^(?!Mozilla)(?P<browser>[A-Z0-9\-]+)(/(?P<version>[0-9A-Z.]+))?%ix', $u_agent, $result) ) {
107
+ return array( PLATFORM => $platform ?: null, BROWSER => $result[BROWSER], BROWSER_VERSION => empty($result[BROWSER_VERSION]) ? null : $result[BROWSER_VERSION] );
108
+ }
109
+
110
+ return $empty;
111
+ }
112
+
113
+ if( preg_match('/rv:(?P<version>[0-9A-Z.]+)/i', $u_agent, $rv_result) ) {
114
+ $rv_result = $rv_result[BROWSER_VERSION];
115
+ }
116
+
117
+ $browser = $result[BROWSER][0];
118
+ $version = $result[BROWSER_VERSION][0];
119
+
120
+ $lowerBrowser = array_map('strtolower', $result[BROWSER]);
121
+
122
+ $find = function ( $search, &$key = null, &$value = null ) use ( $lowerBrowser ) {
123
+ $search = (array)$search;
124
+
125
+ foreach( $search as $val ) {
126
+ $xkey = array_search(strtolower($val), $lowerBrowser);
127
+ if( $xkey !== false ) {
128
+ $value = $val;
129
+ $key = $xkey;
130
+
131
+ return true;
132
+ }
133
+ }
134
+
135
+ return false;
136
+ };
137
+
138
+ $findT = function ( array $search, &$key = null, &$value = null ) use ( $find ) {
139
+ $value2 = null;
140
+ if( $find(array_keys($search), $key, $value2) ) {
141
+ $value = $search[$value2];
142
+
143
+ return true;
144
+ }
145
+
146
+ return false;
147
+ };
148
+
149
+ $key = 0;
150
+ $val = '';
151
+ if( $findT(array( 'OPR' => 'Opera', 'UCBrowser' => 'UC Browser', 'YaBrowser' => 'Yandex', 'Iceweasel' => 'Firefox', 'Icecat' => 'Firefox', 'CriOS' => 'Chrome', 'Edg' => 'Edge' ), $key, $browser) ) {
152
+ $version = $result[BROWSER_VERSION][$key];
153
+ } elseif( $find('Playstation Vita', $key, $platform) ) {
154
+ $platform = 'PlayStation Vita';
155
+ $browser = 'Browser';
156
+ } elseif( $find(array( 'Kindle Fire', 'Silk' ), $key, $val) ) {
157
+ $browser = $val == 'Silk' ? 'Silk' : 'Kindle';
158
+ $platform = 'Kindle Fire';
159
+ if( !($version = $result[BROWSER_VERSION][$key]) || !is_numeric($version[0]) ) {
160
+ $version = $result[BROWSER_VERSION][array_search('Version', $result[BROWSER])];
161
+ }
162
+ } elseif( $find('NintendoBrowser', $key) || $platform == 'Nintendo 3DS' ) {
163
+ $browser = 'NintendoBrowser';
164
+ $version = $result[BROWSER_VERSION][$key];
165
+ } elseif( $find('Kindle', $key, $platform) ) {
166
+ $browser = $result[BROWSER][$key];
167
+ $version = $result[BROWSER_VERSION][$key];
168
+ } elseif( $find('Opera', $key, $browser) ) {
169
+ $find('Version', $key);
170
+ $version = $result[BROWSER_VERSION][$key];
171
+ } elseif( $find('Puffin', $key, $browser) ) {
172
+ $version = $result[BROWSER_VERSION][$key];
173
+ if( strlen($version) > 3 ) {
174
+ $part = substr($version, -2);
175
+ if( ctype_upper($part) ) {
176
+ $version = substr($version, 0, -2);
177
+
178
+ $flags = array( 'IP' => 'iPhone', 'IT' => 'iPad', 'AP' => 'Android', 'AT' => 'Android', 'WP' => 'Windows Phone', 'WT' => 'Windows' );
179
+ if( isset($flags[$part]) ) {
180
+ $platform = $flags[$part];
181
+ }
182
+ }
183
+ }
184
+ } elseif( $find(array( 'Applebot', 'IEMobile', 'Edge', 'Midori', 'Vivaldi', 'OculusBrowser', 'SamsungBrowser', 'Valve Steam Tenfoot', 'Chrome', 'HeadlessChrome' ), $key, $browser) ) {
185
+ $version = $result[BROWSER_VERSION][$key];
186
+ } elseif( $rv_result && $find('Trident') ) {
187
+ $browser = 'MSIE';
188
+ $version = $rv_result;
189
+ } elseif( $browser == 'AppleWebKit' ) {
190
+ if( $platform == 'Android' ) {
191
+ $browser = 'Android Browser';
192
+ } elseif( strpos($platform, 'BB') === 0 ) {
193
+ $browser = 'BlackBerry Browser';
194
+ $platform = 'BlackBerry';
195
+ } elseif( $platform == 'BlackBerry' || $platform == 'PlayBook' ) {
196
+ $browser = 'BlackBerry Browser';
197
+ } else {
198
+ $find('Safari', $key, $browser) || $find('TizenBrowser', $key, $browser);
199
+ }
200
+
201
+ $find('Version', $key);
202
+ $version = $result[BROWSER_VERSION][$key];
203
+ } elseif( $pKey = preg_grep('/playstation \d/i', $result[BROWSER]) ) {
204
+ $pKey = reset($pKey);
205
+
206
+ $platform = 'PlayStation ' . preg_replace('/\D/', '', $pKey);
207
+ $browser = 'NetFront';
208
+ }
209
+
210
+ return array( PLATFORM => $platform ?: null, BROWSER => $browser ?: null, BROWSER_VERSION => $version ?: null );
211
+ }
212
+ }
libs/eps-plugin-options.php CHANGED
@@ -51,58 +51,51 @@ if (!class_exists('EPS_Redirects_Plugin_Options')) {
51
  }
52
 
53
  /**
54
- *
55
- * Pull settings from the theme-options.json file.
56
- *
57
  */
58
  private function build_settings()
59
  {
60
- $this->settings = $this->read_settings(EPS_REDIRECT_PATH . 'options.json');
61
- }
62
-
63
- private function read_settings($uri)
64
- {
65
- if (file_exists($uri)) {
66
- if (is_readable($uri)) {
67
- $data = $this->read_json_from_file($uri);
68
- } else {
69
- chmod($uri, 0644);
70
- $data = $this->read_json_from_file($uri);
71
- if ($data) {
72
- $data = array(
73
- 'error' => array(
74
- "title" => "Oops!",
75
- "description" => "An essential file (options.json) could not be read. Please check your folder permissions.",
76
- "callback" => "error",
77
- "fields" => ''
78
- )
79
- );
80
- }
81
- }
82
- } else {
83
- $data = array(
84
- 'error' => array(
85
- "title" => "Oops!",
86
- "description" => "An essential file (options.json) could not be found. Please re-install the plugin.",
87
- "callback" => "error",
88
- "fields" => ''
89
- )
90
- );
91
- }
92
-
 
 
 
 
 
 
 
93
 
94
- return $data;
95
- }
96
-
97
- private function read_json_from_file($uri)
98
- {
99
- try {
100
- $json = file_get_contents($uri);
101
- return json_decode($json, true);
102
- } catch (Exception $e) {
103
- return false;
104
- }
105
- }
106
 
107
  /**
108
  *
@@ -197,8 +190,6 @@ if (!class_exists('EPS_Redirects_Plugin_Options')) {
197
  *
198
  * Outputs the Sections intro HTML. A callback.
199
  *
200
- * TODO: Can this be made more dynamic?
201
- *
202
  * @param $args
203
  *
204
  */
@@ -273,12 +264,37 @@ if (!class_exists('EPS_Redirects_Plugin_Options')) {
273
  }
274
  ?>
275
  <div class="wrap">
276
- <h2><?php echo $this->plugin->name; ?></h2><br>
277
- <?php $this->get_tab_nav($current_tab); ?>
278
- <?php $this->get_tab($current_tab); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  </div>
280
  <?php
281
-
282
  }
283
 
284
  /**
@@ -291,11 +307,11 @@ function get_tab_nav($current = 'general')
291
  {
292
  echo '<h2 class="nav-tab-wrapper">';
293
 
294
-
295
  foreach ($this->settings as $tab => $args) {
296
- $class = ($tab == $current) ? ' nav-tab-active' : '';
 
297
  printf(
298
- "<a class='nav-tab%s' href='?page=%s&tab=%s'>%s</a>",
299
  $class,
300
  $this->plugin->config('option_slug'),
301
  $tab,
@@ -360,5 +376,118 @@ public function tab_exists($tab)
360
  }
361
  return true;
362
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
  }
364
  }
51
  }
52
 
53
  /**
54
+ * Tab menu items
 
 
55
  */
56
  private function build_settings()
57
  {
58
+ $this->settings = array (
59
+ 'redirects' =>
60
+ array (
61
+ 'title' => 'Redirect Rules',
62
+ 'description' => '',
63
+ 'callback' => 'redirects',
64
+ 'fields' => array(),
65
+ ),
66
+ '404s' =>
67
+ array (
68
+ 'title' => '404 Error Log',
69
+ 'description' => '',
70
+ 'callback' => '404s',
71
+ 'fields' => array(),
72
+ ),
73
+ 'import-export' =>
74
+ array (
75
+ 'title' => 'Tools &amp; Options',
76
+ 'description' => '',
77
+ 'callback' => 'import_export',
78
+ 'fields' => array(),
79
+ ),
80
+ 'support' =>
81
+ array (
82
+ 'title' => 'Support',
83
+ 'description' => '',
84
+ 'callback' => 'support',
85
+ 'fields' => array(),
86
+ ),
87
+ 'pro' =>
88
+ array (
89
+ 'title' => 'PRO',
90
+ 'description' => '',
91
+ 'callback' => 'pro',
92
+ 'class' => 'pro-ad',
93
+ 'fields' => array(),
94
+ ),
95
+ );
96
+
97
+ } // build_settings
98
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
  /**
101
  *
190
  *
191
  * Outputs the Sections intro HTML. A callback.
192
  *
 
 
193
  * @param $args
194
  *
195
  */
264
  }
265
  ?>
266
  <div class="wrap">
267
+ <h1><img src="<?php echo EPS_REDIRECT_URL . 'images/wp-301-logo.png' ?>" alt="<?php echo $this->plugin->name; ?>" title="<?php echo $this->plugin->name; ?>"><span><?php echo $this->plugin->name; ?></span></h1><br>
268
+ <div id="eps-tabs-wrapper">
269
+ <?php $this->get_tab_nav($current_tab); ?>
270
+ <?php $this->get_tab($current_tab); ?>
271
+ </div>
272
+ <div id="eps-sidebar-wrapper">
273
+ <div class="sidebar-box pro-ad-box">
274
+ <p class="text-center"><a href="https://wp301redirects.com/?ref=eps-free-sidebar-box" target="_blank"><img src="<?php echo EPS_REDIRECT_URL . 'images/wp-301-logo-full.png'; ?>" alt="WP 301 Redirects PRO" title="WP 301 Redirects PRO"></a><br><b>PRO version</b> is here! Grab the launch discount - <b>all prices are LIFETIME!</b></p>
275
+
276
+ <ul class="plain-list">
277
+ <li>Advanced Redirects Management &amp; URL Matching Rules</li>
278
+ <li>Auto-fix URL Typos (no rules needed)</li>
279
+ <li>Detailed 404 &amp; Redirect Stats + Email Reports</li>
280
+ <li>URL Cloaking + other features for affiliate marketers</li>
281
+ <li>Licenses &amp; Sites Manager (remote SaaS dashboard)</li>
282
+ <li>Remote Site Stats (stats for all your sites in one place)</li>
283
+ <li>White-label Mode + Complete Plugin Rebranding</li>
284
+ <li>Branded PDF Reports</li>
285
+ <li>Email support from plugin developers</li>
286
+ </ul>
287
+
288
+ <p class="text-center"><a href="#" class="open-301-pro-dialog button button-buy" data-pro-feature="sidebar-box">Get PRO Now</a></p>
289
+ </div>
290
+
291
+ <div class="sidebar-box">
292
+ <p>Please <a href="https://wordpress.org/support/plugin/eps-301-redirects/reviews/?filter=5#new-post" target="_blank">rate the plugin ★★★★★</a> to <b>keep it up-to-date &amp; maintained</b>. It only takes a second to rate. Thank you! 👋</p>
293
+ </div>
294
+ </div>
295
  </div>
296
  <?php
297
+ echo $this->pro_dialog();
298
  }
299
 
300
  /**
307
  {
308
  echo '<h2 class="nav-tab-wrapper">';
309
 
 
310
  foreach ($this->settings as $tab => $args) {
311
+ $class = @$args['class'];
312
+ $class .= ($tab == $current) ? ' nav-tab-active' : '';
313
  printf(
314
+ "<a class='nav-tab %s' href='?page=%s&tab=%s'>%s</a>",
315
  $class,
316
  $this->plugin->config('option_slug'),
317
  $tab,
376
  }
377
  return true;
378
  }
379
+
380
+ function pro_dialog() {
381
+ $out = '';
382
+
383
+ $out .= '<div id="eps-pro-dialog" style="display: none;" title="WP 301 Redirects PRO is here!"><span class="ui-helper-hidden-accessible"><input type="text"/></span>';
384
+
385
+ $plugin_url = plugin_dir_url(__FILE__);
386
+
387
+ $out .= '<div class="center logo"><a href="https://wp301redirects.com/?ref=eps-free-pricing-table" target="_blank"><img src="' . EPS_REDIRECT_URL . 'images/wp-301-logo-full.png' . '" alt="WP 301 Redirects PRO" title="WP 301 Redirects PRO"></a><br>';
388
+
389
+ $out .= '<span>Limited PRO Launch Discount - <b>all prices are LIFETIME</b>! Pay once &amp; use forever!</span>';
390
+ $out .= '</div>';
391
+
392
+ $out .= '<table id="eps-pro-table">';
393
+ $out .= '<tr>';
394
+ $out .= '<td class="center">Lifetime Personal License</td>';
395
+ $out .= '<td class="center">Lifetime Team License</td>';
396
+ $out .= '<td class="center">Lifetime Agency License</td>';
397
+ $out .= '</tr>';
398
+
399
+ $out .= '<tr class="prices">';
400
+ $out .= '<td class="center"><del>$79 /year</del><br><span>$49</span> /lifetime</td>';
401
+ $out .= '<td class="center"><del>$159 /year</del><br><span>$59</span> /lifetime</td>';
402
+ $out .= '<td class="center"><del>$299 /year</del><br><span>$99</span> /lifetime</td>';
403
+ $out .= '</tr>';
404
+
405
+ $out .= '<tr>';
406
+ $out .= '<td><span class="dashicons dashicons-yes"></span><b>1 Site License</b></td>';
407
+ $out .= '<td><span class="dashicons dashicons-yes"></span><b>5 Sites License</b></td>';
408
+ $out .= '<td><span class="dashicons dashicons-yes"></span><b>100 Sites License</b></td>';
409
+ $out .= '</tr>';
410
+
411
+ $out .= '<tr>';
412
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Advanced Redirects Management</td>';
413
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Advanced Redirects Management</td>';
414
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Advanced Redirects Management</td>';
415
+ $out .= '</tr>';
416
+
417
+ $out .= '<tr>';
418
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Advanced URL Matching Rules</td>';
419
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Advanced URL Matching Rules</td>';
420
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Advanced URL Matching Rules</td>';
421
+ $out .= '</tr>';
422
+
423
+ $out .= '<tr>';
424
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Auto-fix URL Typos</td>';
425
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Auto-fix URL Typos</td>';
426
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Auto-fix URL Typos</td>';
427
+ $out .= '</tr>';
428
+
429
+ $out .= '<tr>';
430
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Detailed 404 &amp; Redirect Stats</td>';
431
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Detailed 404 &amp; Redirect Stats</td>';
432
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Detailed 404 &amp; Redirect Stats</td>';
433
+ $out .= '</tr>';
434
+
435
+
436
+ $out .= '<tr>';
437
+ $out .= '<td><span class="dashicons dashicons-yes"></span>URL Cloaking</td>';
438
+ $out .= '<td><span class="dashicons dashicons-yes"></span>URL Cloaking</td>';
439
+ $out .= '<td><span class="dashicons dashicons-yes"></span>URL Cloaking</td>';
440
+ $out .= '</tr>';
441
+
442
+
443
+ $out .= '<tr>';
444
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Licenses & Sites Manager (SaaS)</td>';
445
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Licenses & Sites Manager (SaaS)</td>';
446
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Licenses & Sites Manager (SaaS)</td>';
447
+ $out .= '</tr>';
448
+
449
+ $out .= '<tr>';
450
+ $out .= '<td><span class="dashicons dashicons-no"></span>Remote Site Stats</td>';
451
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Remote Site Stats</td>';
452
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Remote Site Stats</td>';
453
+ $out .= '</tr>';
454
+
455
+ $out .= '<tr>';
456
+ $out .= '<td><span class="dashicons dashicons-no"></span>White-label Mode</td>';
457
+ $out .= '<td><span class="dashicons dashicons-yes"></span>White-label Mode</td>';
458
+ $out .= '<td><span class="dashicons dashicons-yes"></span>White-label Mode</td>';
459
+ $out .= '</tr>';
460
+
461
+ $out .= '<tr>';
462
+ $out .= '<td><span class="dashicons dashicons-no"></span>Full Plugin Rebranding</td>';
463
+ $out .= '<td><span class="dashicons dashicons-no"></span>Full Plugin Rebranding</td>';
464
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Full Plugin Rebranding</td>';
465
+ $out .= '</tr>';
466
+
467
+ $out .= '<tr>';
468
+ $out .= '<td><span class="dashicons dashicons-no"></span>Branded PDF Reports</td>';
469
+ $out .= '<td><span class="dashicons dashicons-no"></span>Branded PDF Reports</td>';
470
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Branded PDF Reports</td>';
471
+ $out .= '</tr>';
472
+
473
+ $out .= '<tr>';
474
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Lifetime Updates &amp; Support</td>';
475
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Lifetime Updates &amp; Support</td>';
476
+ $out .= '<td><span class="dashicons dashicons-yes"></span>Lifetime Updates &amp; Support</td>';
477
+ $out .= '</tr>';
478
+
479
+ $out .= '<tr>';
480
+ $out .= '<td><span>one-time payment</span><a class="button button-buy" data-href-org="https://wp301redirects.com/buy/?product=personal-launch&ref=pricing-table" href="https://wp301redirects.com/buy/?product=personal-launch&ref=pricing-table" target="_blank">BUY NOW</a></td>';
481
+ $out .= '<td><span>one-time payment</span><a class="button button-buy" data-href-org="https://wp301redirects.com/buy/?product=team-launch&ref=pricing-table" href="https://wp301redirects.com/buy/?product=team-launch&ref=pricing-table" target="_blank">BUY NOW</a></td>';
482
+ $out .= '<td><span>one-time payment</span><a class="button button-buy" data-href-org="https://wp301redirects.com/buy/?product=agency-launch&ref=pricing-table" href="https://wp301redirects.com/buy/?product=agency-launch&ref=pricing-table" target="_blank">BUY NOW</a></td>';
483
+ $out .= '</tr>';
484
+
485
+ $out .= '</table>';
486
+
487
+ $out .= '<div class="center footer"><b>100% No-Risk Money Back Guarantee!</b> If you don\'t like the plugin over the next 7 days, we will happily refund 100% of your money. No questions asked! Payments are processed by our merchant of records - <a href="https://paddle.com/" target="_blank">Paddle</a>.</div></div>';
488
+
489
+ return $out;
490
+ }
491
+
492
  }
493
  }
example.csv → misc/example-import.csv RENAMED
File without changes
options.json DELETED
@@ -1,26 +0,0 @@
1
- {
2
- "redirects": {
3
- "title": "Redirect Rules",
4
- "description": "",
5
- "callback": "redirects",
6
- "fields": {}
7
- },
8
- "404s": {
9
- "title": "404 Error Log",
10
- "description": "",
11
- "callback": "404s",
12
- "fields": {}
13
- },
14
- "import-export": {
15
- "title": "Import/Export Redirect Rules",
16
- "description": "",
17
- "callback": "import_export",
18
- "fields": {}
19
- },
20
- "support": {
21
- "title": "Support",
22
- "description": "",
23
- "callback": "support",
24
- "fields": {}
25
- }
26
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin.php CHANGED
@@ -103,8 +103,14 @@ class EPS_Redirects_Plugin
103
  public static function _activation()
104
  {
105
  self::_create_redirect_table(); // Maybe create the tables
106
- if (!self::is_current_version()) self::update_self();
 
 
 
 
 
107
  }
 
108
  public static function _deactivation()
109
  { }
110
 
@@ -258,9 +264,6 @@ class EPS_Redirects_Plugin
258
  }
259
 
260
 
261
-
262
-
263
-
264
  /**
265
  *
266
  * plugin_resources
@@ -273,25 +276,49 @@ class EPS_Redirects_Plugin
273
  */
274
  public static function plugin_resources()
275
  {
276
- global $EPS_Redirects_Plugin;
 
 
 
 
 
 
 
 
 
 
 
277
  if (is_admin() && isset($_GET['page']) && $_GET['page'] == $EPS_Redirects_Plugin->config('page_slug')) {
 
 
 
 
 
 
278
  wp_enqueue_script('jquery');
279
 
280
  wp_enqueue_script('eps_redirect_script', EPS_REDIRECT_URL . 'js/scripts.js');
281
  wp_enqueue_style('eps_redirect_styles', EPS_REDIRECT_URL . 'css/eps_redirect.css');
282
 
 
 
 
283
  $js_vars = array(
284
  'nonce_get_entry' => wp_create_nonce('eps_301_get_entry'),
285
  'nonce_save_redirect' => wp_create_nonce('eps_301_save_redirect'),
286
  'nonce_delete_entry' => wp_create_nonce('eps_301_delete_entry'),
287
  'nonce_get_inline_edit_entry' => wp_create_nonce('eps_301_get_inline_edit_entry'),
 
288
  );
289
  wp_localize_script('eps_redirect_script', 'eps_301', $js_vars);
 
 
 
290
  }
291
 
292
  global $wp_rewrite;
293
  if (!isset($wp_rewrite->permalink_structure) || empty($wp_rewrite->permalink_structure)) {
294
- $EPS_Redirects_Plugin->add_admin_message('WARNING: 301 Redirects requires that a permalink structure is set. The Default Wordpress permalink structure is not compatible. Please update the <a href="options-permalink.php" title="Permalinks">Permalink Structure</a>', "error");
295
  }
296
 
297
  global $wpdb;
@@ -302,6 +329,15 @@ class EPS_Redirects_Plugin
302
  }
303
  }
304
 
 
 
 
 
 
 
 
 
 
305
  /**
306
  *
307
  * check_plugin_actions
@@ -331,7 +367,8 @@ class EPS_Redirects_Plugin
331
  $options = eps_dropdown_pages(array('post_type' => $post_type->name));
332
  set_transient('post_type_cache_' . $post_type->name, $options, HOUR_IN_SECONDS);
333
  }
334
- $this->add_admin_message("Success: Cache Refreshed.", "updated");
 
335
  }
336
 
337
  // Save Redirects
@@ -346,6 +383,41 @@ class EPS_Redirects_Plugin
346
  }
347
  }
348
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
349
 
350
  /**
351
  *
@@ -359,7 +431,7 @@ class EPS_Redirects_Plugin
359
  {
360
  $entries = EPS_Redirects::get_all();
361
  $filename = sprintf(
362
- "%s-redirects.csv",
363
  date('Y-m-d')
364
  );
365
  if ($entries) {
@@ -600,19 +672,6 @@ class EPS_Redirects_Plugin
600
  return (isset($this->config[$name])) ? $this->config[$name] : false;
601
  }
602
 
603
- /**
604
- *
605
- *
606
- * Activation and Deactivation Handlers.
607
- *
608
- * @return nothing
609
- * @author WebFactory Ltd
610
- */
611
- public function activation_error()
612
- {
613
- file_put_contents($this->config('path') . '/error_activation.html', ob_get_contents());
614
- }
615
-
616
 
617
  public static function is_current_version()
618
  {
103
  public static function _activation()
104
  {
105
  self::_create_redirect_table(); // Maybe create the tables
106
+ if (!self::is_current_version()) {
107
+ self::update_self();
108
+ }
109
+
110
+ self::reset_pointers();
111
+ delete_option('301-redirects-notices');
112
  }
113
+
114
  public static function _deactivation()
115
  { }
116
 
264
  }
265
 
266
 
 
 
 
267
  /**
268
  *
269
  * plugin_resources
276
  */
277
  public static function plugin_resources()
278
  {
279
+ global $EPS_Redirects_Plugin, $wp_rewrite;
280
+
281
+ $pointers = get_option('eps_pointers');
282
+
283
+ if (is_admin() && $pointers && !empty($wp_rewrite->permalink_structure) && (empty($_GET['page']) || $_GET['page'] != $EPS_Redirects_Plugin->config('page_slug'))) {
284
+ $pointers['_nonce_dismiss_pointer'] = wp_create_nonce('eps_dismiss_pointer');
285
+ wp_enqueue_script('wp-pointer');
286
+ wp_enqueue_script('eps-pointers', plugins_url('js/eps-admin-pointers.js', __FILE__), array('jquery'), EPS_REDIRECT_VERSION, true);
287
+ wp_enqueue_style('wp-pointer');
288
+ wp_localize_script('wp-pointer', 'eps_pointers', $pointers);
289
+ }
290
+
291
  if (is_admin() && isset($_GET['page']) && $_GET['page'] == $EPS_Redirects_Plugin->config('page_slug')) {
292
+ // uncomment if we want to remove pointer after plugin settings are open
293
+ // unset($pointers['welcome']);
294
+ // update_option('eps_pointers', $pointers);
295
+
296
+ $notices = get_option('301-redirects-notices');
297
+
298
  wp_enqueue_script('jquery');
299
 
300
  wp_enqueue_script('eps_redirect_script', EPS_REDIRECT_URL . 'js/scripts.js');
301
  wp_enqueue_style('eps_redirect_styles', EPS_REDIRECT_URL . 'css/eps_redirect.css');
302
 
303
+ wp_enqueue_style('wp-jquery-ui-dialog');
304
+ wp_enqueue_script('jquery-ui-dialog');
305
+
306
  $js_vars = array(
307
  'nonce_get_entry' => wp_create_nonce('eps_301_get_entry'),
308
  'nonce_save_redirect' => wp_create_nonce('eps_301_save_redirect'),
309
  'nonce_delete_entry' => wp_create_nonce('eps_301_delete_entry'),
310
  'nonce_get_inline_edit_entry' => wp_create_nonce('eps_301_get_inline_edit_entry'),
311
+ 'auto_open_pro_dialog' => empty($notices['dismiss_auto_pro_modal']),
312
  );
313
  wp_localize_script('eps_redirect_script', 'eps_301', $js_vars);
314
+
315
+ $notices['dismiss_auto_pro_modal'] = true;
316
+ update_option('301-redirects-notices', $notices);
317
  }
318
 
319
  global $wp_rewrite;
320
  if (!isset($wp_rewrite->permalink_structure) || empty($wp_rewrite->permalink_structure)) {
321
+ $EPS_Redirects_Plugin->add_admin_message('<b>WARNING:</b> 301 Redirects plugin requires that a permalink structure is set. The default (plain) WordPress permalink structure is not compatible with 301 Redirects.<br>Please update the <a href="options-permalink.php" title="Permalinks">Permalink Structure</a>.', "error");
322
  }
323
 
324
  global $wpdb;
329
  }
330
  }
331
 
332
+ // reset all pointers to default state - visible
333
+ static function reset_pointers() {
334
+ $pointers = array();
335
+
336
+ $pointers['welcome'] = array('target' => '#menu-settings', 'edge' => 'left', 'align' => 'right', 'content' => 'Thank you for installing the <b style="font-weight: 800;">301 Redirects plugin</b>! Please open <a href="' . admin_url('options-general.php?page=eps_redirects'). '">Settings - 301 Redirects</a> to manage your redirect rules.');
337
+
338
+ update_option('eps_pointers', $pointers);
339
+ } // reset_pointers
340
+
341
  /**
342
  *
343
  * check_plugin_actions
367
  $options = eps_dropdown_pages(array('post_type' => $post_type->name));
368
  set_transient('post_type_cache_' . $post_type->name, $options, HOUR_IN_SECONDS);
369
  }
370
+ self::empty_3rd_party_cache();
371
+ $this->add_admin_message("Success: Cache Emptied.", "updated");
372
  }
373
 
374
  // Save Redirects
383
  }
384
  }
385
 
386
+ static function empty_3rd_party_cache() {
387
+ wp_cache_flush();
388
+ if (function_exists('w3tc_flush_all')) {
389
+ w3tc_flush_all();
390
+ }
391
+ if (function_exists('wp_cache_clear_cache')) {
392
+ wp_cache_clear_cache();
393
+ }
394
+ if (method_exists('LiteSpeed_Cache_API', 'purge_all')) {
395
+ LiteSpeed_Cache_API::purge_all();
396
+ }
397
+ if (class_exists('Endurance_Page_Cache')) {
398
+ $epc = new Endurance_Page_Cache;
399
+ $epc->purge_all();
400
+ }
401
+ if (class_exists('SG_CachePress_Supercacher') && method_exists('SG_CachePress_Supercacher', 'purge_cache')) {
402
+ SG_CachePress_Supercacher::purge_cache(true);
403
+ }
404
+ if (class_exists('SiteGround_Optimizer\Supercacher\Supercacher')) {
405
+ SiteGround_Optimizer\Supercacher\Supercacher::purge_cache();
406
+ }
407
+ if (isset($GLOBALS['wp_fastest_cache']) && method_exists($GLOBALS['wp_fastest_cache'], 'deleteCache')) {
408
+ $GLOBALS['wp_fastest_cache']->deleteCache(true);
409
+ }
410
+ if (is_callable(array('Swift_Performance_Cache', 'clear_all_cache'))) {
411
+ Swift_Performance_Cache::clear_all_cache();
412
+ }
413
+ if (is_callable(array('Hummingbird\WP_Hummingbird', 'flush_cache'))) {
414
+ Hummingbird\WP_Hummingbird::flush_cache(true, false);
415
+ }
416
+ if (function_exists('rocket_clean_domain')) {
417
+ rocket_clean_domain();
418
+ }
419
+ } // empty_cache
420
+
421
 
422
  /**
423
  *
431
  {
432
  $entries = EPS_Redirects::get_all();
433
  $filename = sprintf(
434
+ "%s-redirects-export.csv",
435
  date('Y-m-d')
436
  );
437
  if ($entries) {
672
  return (isset($this->config[$name])) ? $this->config[$name] : false;
673
  }
674
 
 
 
 
 
 
 
 
 
 
 
 
 
 
675
 
676
  public static function is_current_version()
677
  {
readme.txt CHANGED
@@ -1,18 +1,18 @@
1
  === 301 Redirects - Easy Redirect Manager ===
2
  Contributors: WebFactory
3
- Tags: 301 redirect, redirects, redirect, 302 redirect, redirection, 302, seo, 302 redirect, 404, 404 redirect, 301, 307
4
  Requires at least: 4.0
5
  Tested up to: 5.6
6
- Stable tag: 2.55
7
  Requires PHP: 5.2
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
- Easily manage and create 301 & 302 redirects. Simple to use & validate redirects. Includes redirect stats.
12
 
13
  == Description ==
14
 
15
- **301 Redirects** helps you manage and create 301, 302, 307 redirects for your WordPress site to **improve SEO and visitor experience**. With a user-friendly interface, 301 Redirects is easy to install and configure. Perfect for new sites or repairing links after re-organizing your existing WordPress content, or when your site has content that expires and you wish to avoid sending visitors to a 404 page.
16
 
17
  301 Redirects GUI is located in WP Admin Dashboard - Settings - 301 Redirects
18
 
@@ -22,18 +22,20 @@ Easily manage and create 301 & 302 redirects. Simple to use & validate redirects
22
  * Or, set a custom destination URL!
23
  * Retain query strings across redirects
24
  * Super-fast redirection
 
25
  * Import/Export feature for bulk redirects management
26
  * Simple redirect stats so you know how much a redirection is used
27
  * Fully compatible with translation plugins (Weglot, TranslatePress, Gtranslate, Loco Translate) that use lang prefix in URL
28
 
29
  **Need more features?**
30
- <a href="https://wp301redirects.com/">WP 301 Redirects PRO</a> offers wildcard & regular expression URL matching, auto-typo fixing in URLs, complete redirect and 404 log, and a centralized SaaS dashboard to monitor redirects on all your sites from one place.
31
 
32
  **What is a 301 Redirect?**
33
  A redirect is a simple way to re-route traffic coming to a *Requested URL* to different *Destination URL*.
34
 
35
  A 301 redirect indicates that the page requested has been permanently moved to the *Destination URL*, and helps pass on the *Requested URLs* traffic in a search engine friendly manner. Creating a 301 redirect tells search engines that the *Requested URL* has moved permanently, and that the content can now be found on the *Destination URL*. An important feature is that search engines will pass along any clout the *Requested URL* used to have to the *Destination URL*.
36
 
 
37
 
38
  **When Should I use 301 Redirects?**
39
 
@@ -41,6 +43,9 @@ A 301 redirect indicates that the page requested has been permanently moved to t
41
  * Overhauling or re-organizing your existing WordPress content
42
  * You have content that expires (or is otherwise no longer available) and you wish to redirect users elsewhere
43
 
 
 
 
44
 
45
 
46
  == Installation ==
@@ -59,16 +64,23 @@ A 301 redirect indicates that the page requested has been permanently moved to t
59
 
60
  == Changelog ==
61
 
 
 
 
 
 
 
 
62
  = 2.55 =
63
  * 2021/01/30
64
- * Removed promo campaign for PRO version
65
  * Added flyout menu
66
 
67
  = 2.53 =
68
  * 2020/09/29
69
- * More issues fixed related to translation plugins
70
  * Fixed issue with encoding source & target URLs in some situations.
71
- * Added promo campaign for PRO version in November
72
 
73
  = 2.52 =
74
  * 2020/09/07
@@ -100,62 +112,10 @@ A 301 redirect indicates that the page requested has been permanently moved to t
100
  * bug fixes
101
  * compatibility fixes for new versions of PHP and WP
102
 
103
- = 2.3.0 =
104
- Added sorting. Fixed a bug when upgrading from V1 to V2, and the infamous "Invalid Destination" url.
105
-
106
- = 2.2.7 =
107
- That silly bug with the database tables not being created has been squashed. Improved query performance.
108
-
109
- = 2.2.6 =
110
- Added support for custom plugin directories.
111
-
112
- = 2.2.4 =
113
- Support for older versions of PHP.
114
-
115
- = 2.2.3 =
116
- Fixed an issue where the redirect database tables were not being created, causing 'Invalid Destination URL' errors.
117
-
118
- = 2.2.0 =
119
- Minor bug fixes. Greatly improved import feature. Redirects include query strings. Export feature added. Http/Https agnostic. Pro version added with 404 management.
120
-
121
- = 2.1.2 =
122
- Minor bug fixes.
123
-
124
- = 2.1.1 =
125
- Fixed an issue where users with a lot of redirects were being limited, this fix also changed up the admin area. Redirects are now editable via AJAX, and the ‘add new’ form was moved to the top.
126
-
127
- = 2.0.1 =
128
- Fixed an issue where the Automatic Update would not call the import process for pre 2.0 versions.
129
-
130
- = 2.0.0 =
131
- Overhauled the entire plugin. Redirects are stored in their own table. Gracefully migrates older versions.
132
-
133
- = 1.4.0 =
134
- * Performance updates, added a new 'Settings' page.
135
-
136
- = 1.3.5 =
137
- * Fixed a bug with spaces in the url. Added ease of use visual aids.
138
-
139
- = 1.3.4 =
140
- * Fixed nonce validation problem which would prevent saving of new redirects. Special Thanks to Bruce Zlotowitz for all his testing!
141
-
142
- = 1.3.3 =
143
- * Fixed major problem when switching from 1.2 to 1.3+
144
-
145
- = 1.3.1 =
146
- * Added hierarchy to heirarchical post type selects.
147
-
148
- = 1.3 =
149
- * Fixed a bug where duplicate URLs were being overwritten, fixed a bug where you could not completely remove all redirects.
150
-
151
- = 1.2 =
152
- * Fixed some little bugs.
153
-
154
- = 1.1 =
155
- * Minor CSS and usability fixes. Also checking out the SVN!
156
-
157
  = 1.0 =
158
- * Release.
 
 
159
 
160
  == Frequently Asked Questions ==
161
 
@@ -184,9 +144,19 @@ Click the small X beside the redirect you wish to remove.
184
 
185
  =How do I add wildcards. or folder redirects?=
186
 
187
- Unfortunately this is not supported. You should look into .htaccess redirects for these advanced features.
188
 
189
 
190
  =What about query strings?=
191
 
192
- By default, any URL with a query string is considered unique, and will redirect to a unique page (if you so wish). The query string will be added to the Destination URL, which allows you to keep your tracking codes, affiliate codes, and other important data!
 
 
 
 
 
 
 
 
 
 
1
  === 301 Redirects - Easy Redirect Manager ===
2
  Contributors: WebFactory
3
+ Tags: 301 redirect, redirects, redirect, 404 log, redirection, 302 redirect, 302, seo, 302 redirect, 404, 404 redirect, 301, 307, 404 error log
4
  Requires at least: 4.0
5
  Tested up to: 5.6
6
+ Stable tag: 2.60
7
  Requires PHP: 5.2
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
+ Easily manage 301 & 302 redirects. Simple to use & validate redirects. Includes redirect stats & 404 error log.
12
 
13
  == Description ==
14
 
15
+ <a href="https://wp301redirects.com/?ref=wporg">301 Redirects</a> helps you manage and create 301, 302, 307 redirects for your WordPress site to **improve SEO and visitor experience**. With a user-friendly interface, 301 Redirects is easy to use. Perfect for new sites or repairing links after reorganizing your existing WordPress content, or when your site has content that expires and you wish to avoid sending visitors to a 404 page. Use the 404 error log to identify problematic links.
16
 
17
  301 Redirects GUI is located in WP Admin Dashboard - Settings - 301 Redirects
18
 
22
  * Or, set a custom destination URL!
23
  * Retain query strings across redirects
24
  * Super-fast redirection
25
+ * 404 error log
26
  * Import/Export feature for bulk redirects management
27
  * Simple redirect stats so you know how much a redirection is used
28
  * Fully compatible with translation plugins (Weglot, TranslatePress, Gtranslate, Loco Translate) that use lang prefix in URL
29
 
30
  **Need more features?**
31
+ <a href="https://wp301redirects.com/?ref=wporg">WP 301 Redirects PRO</a> offers wildcard & regular expression URL matching, auto-typo fixing in URLs, complete redirect and 404 log, and a centralized SaaS dashboard to monitor redirects on all your sites from one place.
32
 
33
  **What is a 301 Redirect?**
34
  A redirect is a simple way to re-route traffic coming to a *Requested URL* to different *Destination URL*.
35
 
36
  A 301 redirect indicates that the page requested has been permanently moved to the *Destination URL*, and helps pass on the *Requested URLs* traffic in a search engine friendly manner. Creating a 301 redirect tells search engines that the *Requested URL* has moved permanently, and that the content can now be found on the *Destination URL*. An important feature is that search engines will pass along any clout the *Requested URL* used to have to the *Destination URL*.
37
 
38
+ [youtube https://www.youtube.com/watch?v=70Yn_lO_8BA]
39
 
40
  **When Should I use 301 Redirects?**
41
 
43
  * Overhauling or re-organizing your existing WordPress content
44
  * You have content that expires (or is otherwise no longer available) and you wish to redirect users elsewhere
45
 
46
+ **External libraries used in the project**
47
+
48
+ * <a href="https://github.com/donatj/PhpUserAgent">PHP User Agent Parser</a>
49
 
50
 
51
  == Installation ==
64
 
65
  == Changelog ==
66
 
67
+ = 2.60 =
68
+ * 2021/02/13
69
+ * added 404 error log
70
+ * fixed some bugs
71
+ * made sure all DB queries use prepare() function
72
+ * PRO version is now available for purchase from free
73
+
74
  = 2.55 =
75
  * 2021/01/30
76
+ * Removed promo campaign for WP 301 Redirects PRO version
77
  * Added flyout menu
78
 
79
  = 2.53 =
80
  * 2020/09/29
81
+ * More issues fixed related to redirections with translation plugins
82
  * Fixed issue with encoding source & target URLs in some situations.
83
+ * Added promo campaign for WP 301 Redirects PRO version in November
84
 
85
  = 2.52 =
86
  * 2020/09/07
112
  * bug fixes
113
  * compatibility fixes for new versions of PHP and WP
114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  = 1.0 =
116
+ * 2013/05/01
117
+ * initial Release
118
+ * for a complete changelog please visit https://wp301redirects.com/old-changelog.txt
119
 
120
  == Frequently Asked Questions ==
121
 
144
 
145
  =How do I add wildcards. or folder redirects?=
146
 
147
+ Unfortunately this is not supported. You should look into <a href="https://wp301redirects.com/?ref=wporg">WP 301 Redirects PRO</a> for these advanced features.
148
 
149
 
150
  =What about query strings?=
151
 
152
+ By default, any URL with a query string is considered unique, and will redirect to a unique page (if you so wish). The query string will be added to the Destination URL, which allows you to keep your tracking codes, affiliate codes, and other important data! If you want to have full control over query strings, ignore them, add or remove them consider upgrading to <a href="https://wp301redirects.com/?ref=wporg">WP 301 Redirects PRO</a>.
153
+
154
+ =What happens when I deactivate or delete the plugin?=
155
+
156
+ When you deactivate the plugin, obviously, redirects stop working. But, they are not deleted from your database. When you delete the plugin then the redirects are permanently deleted from the database along with any other data stored by the plugin in your database.
157
+
158
+ =Why is the error log limited to the last 50 errors?=
159
+
160
+ By default, the 404 error log is limited to the last (chronologically) fifty 404 errors. Since the log doesn't use a custom database table for storage but rather an array saved in WP options, 50 is a safe number that ensures the log works on all sites, that it doesn't take up too much space in the database and that it doesn't slow down the site.
161
+ The code imposes no limits on the log size and you can easily overwrite the default limit by using the <i>eps_301_max_404_logs</i> filter or by using the following code snippet to raise the limit to 200:
162
+ `add_filter('eps_301_max_404_logs', function($log_max) { return 200; });`
templates/admin-panel-cache.php CHANGED
@@ -14,13 +14,3 @@ if (!defined('ABSPATH')) {
14
  die('Do not open this file directly.');
15
  }
16
  ?>
17
-
18
- <div class="eps-panel eps-margin-top rating-box">
19
- <form method="post" action="">
20
- <?php wp_nonce_field('eps_redirect_nonce', 'eps_redirect_nonce_submit'); ?>
21
- <input type="submit" name="eps_redirect_refresh" id="submit" class="button button-secondary" value="Refresh Cache" />
22
- <small style="vertical-align: sub; margin-left: 10px;" class="eps-grey-text">Refresh the cache if the dropdowns are out of date.</small>
23
- </form>
24
-
25
- <p><br>Please <a href="https://wordpress.org/support/plugin/eps-301-redirects/reviews/?filter=5#new-post" target="_blank">rate the plugin ★★★★★</a> to <b>keep it free &amp; maintained</b>. It only takes a minute to rate. Thank you! 👋</p>
26
- </div>
14
  die('Do not open this file directly.');
15
  }
16
  ?>
 
 
 
 
 
 
 
 
 
 
templates/admin-tab-404s.php CHANGED
@@ -13,15 +13,52 @@
13
  if (!defined('ABSPATH')) {
14
  die('Do not open this file directly.');
15
  }
 
 
16
  ?>
17
 
18
  <div class="wrap">
19
  <?php do_action('eps_redirects_admin_head'); ?>
20
 
21
  <div class="eps-panel eps-margin-top group">
22
- <h1>Coming soon</h1>
23
- <p>This feature will be available in one of the next versions.<br>
24
- Want us to work faster? :) Give us a shout <a href="https://twitter.com/webfactoryltd" target="_blank">@webfactoryltd</a>.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  </div>
26
 
27
  <div class="right">
13
  if (!defined('ABSPATH')) {
14
  die('Do not open this file directly.');
15
  }
16
+
17
+ require EPS_REDIRECT_PATH . '/libs/UserAgentParser.php';
18
  ?>
19
 
20
  <div class="wrap">
21
  <?php do_action('eps_redirects_admin_head'); ?>
22
 
23
  <div class="eps-panel eps-margin-top group">
24
+ <?php
25
+ $log = get_option('eps_redirects_404_log', array());
26
+ if (!sizeof($log)) {
27
+ echo '<p>You currently don\'t have any data in the 404 error log. That means that you either just installed the plugin, or that you never had a 404 error happen which is <b>awesome</b>!</p>';
28
+ } else {
29
+ echo '<div class="log-ad-box">Need a more detailed 404 error log? With more data, more insights, per-day stats &amp; an easier way to create redirect rules from 404 errors? Want to have a centralized log for all your websites in one place? <a href="#" class="open-301-pro-dialog pro-feature" data-pro-feature="404-log-banner">Upgrade to WP 301 Redirects PRO.</a></div>';
30
+ echo '<table class="striped widefat">';
31
+ echo '<tr>';
32
+ echo '<th>Date &amp; Time <span class="dashicons dashicons-arrow-down"></span></th>';
33
+ echo '<th>Target URL</th>';
34
+ echo '<th>User Device</th>';
35
+ echo '<th>User Location</th>';
36
+ echo '<th>Referal URL</th>';
37
+ echo '</tr>';
38
+
39
+ foreach ($log as $l) {
40
+ $ua = \epsdonatj\UserAgent\parse_user_agent($l['user_agent']);
41
+ $agent = trim(@$ua['platform'] . ' ' . @$ua['browser']);
42
+ if (empty($agent)) {
43
+ $agent = '<i>unknown</i>';
44
+ }
45
+ echo '<tr>';
46
+ echo '<td nowrap><abbr title="' . date(get_option('date_format'), $l['timestamp']) . ' @ ' . date(get_option('time_format'), $l['timestamp']) . '">' . human_time_diff(current_time('timestamp'), $l['timestamp']) . ' ago</abbr></td>';
47
+ echo '<td><a target="_blank" href="' . $l['url'] . '">' . $l['url'] . '</a></td>';
48
+ echo '<td nowrap>' . $agent . '</td>';
49
+ echo '<td nowrap><a href="#" class="open-301-pro-dialog pro-feature" data-pro-feature="404-log-user-location">Available in PRO</a></td>';
50
+ echo '<td nowrap><a href="#" class="open-301-pro-dialog pro-feature" data-pro-feature="404-log-referral-url">Available in PRO</a></td>';
51
+ echo '</tr>';
52
+ } // foreach
53
+
54
+ echo '</table>';
55
+
56
+ echo '<p><br><i>By default, the log is limited to the last fifty (chronologically) 404 errors. This is a safe number that ensures the log works on all sites and doesn\'t slow anything down. ';
57
+ echo 'The code imposes no limits on the log size and you can easily overwrite the default limit by using the <code>eps_301_max_404_logs</code> filter.</i> Details are available in the <a href="https://wordpress.org/plugins/eps-301-redirects/#faq-header" target="_blank">FAQ</a>.</p>';
58
+ echo '<p>If your site gets hundreds and thousands of 404 errors a day we suggesting upgrading to <a href="#" class="open-301-pro-dialog pro-feature" data-pro-feature="404-log-footer">WP 301 Redirects PRO</a> as it automatically fixes 404 errors caused by URL typos, provides a more robust log that can handle tens of thousands of entries, and offers more tools to manage 404 errors.</p>';
59
+ } // if 404
60
+ ?>
61
+
62
  </div>
63
 
64
  <div class="right">
templates/admin-tab-import-export.php CHANGED
@@ -20,7 +20,24 @@ if (!defined('ABSPATH')) {
20
  <?php do_action('eps_redirects_admin_head'); ?>
21
 
22
  <div class="eps-panel eps-margin-top">
23
- <h3>Import:</h3>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  <form method="post" action="" class="eps-padding" enctype="multipart/form-data">
25
  <?php wp_nonce_field('eps_redirect_nonce', 'eps_redirect_nonce_submit'); ?>
26
  <input accept="csv" type="file" name="eps_redirect_upload_file" value="">
@@ -30,17 +47,17 @@ if (!defined('ABSPATH')) {
30
  &nbsp;&nbsp;&nbsp;<input type="radio" name="eps_redirect_upload_method" value="update"> Update Duplicates
31
  </p>
32
 
33
- <br><small class="eps-grey-text">Supply Columns: <strong>Status</strong> (301,302,307,inactive), <strong>Request URL</strong>, <strong>Redirect
34
- To</strong> (ID or URL). <a href="<?php echo EPS_REDIRECT_URL . 'example.csv' ?>" target="_blank">Download Example CSV</a></small>
35
  </form>
36
  </div>
37
 
38
  <div class="eps-panel eps-margin-top">
39
- <h3>Export:</h3>
40
  <form method="post" action="">
41
  <?php wp_nonce_field('eps_redirect_nonce', 'eps_redirect_nonce_submit'); ?>
42
  <input type="submit" name="eps_redirect_export" id="submit" class="button button-secondary" value="Export Redirects" />
43
- <br><small class="eps-grey-text">Export a backup copy of your redirects.</small>
44
  </form>
45
  </div>
46
 
20
  <?php do_action('eps_redirects_admin_head'); ?>
21
 
22
  <div class="eps-panel eps-margin-top">
23
+ <h3>Empty Cache</h3>
24
+ <form method="post" action="">
25
+ <?php wp_nonce_field('eps_redirect_nonce', 'eps_redirect_nonce_submit'); ?>
26
+ <input type="submit" name="eps_redirect_refresh" id="submit" class="button button-secondary" value="Empty Cache" />
27
+ <p class="eps-grey-text">Empty the cache if you're having problems with redirect rules or if dropdowns on "add new rule" are out of date.</p>
28
+ </form>
29
+ </div>
30
+
31
+ <div class="eps-panel eps-margin-top">
32
+ <h3>PRO Options</h3>
33
+ <input class="open-301-pro-dialog" data-pro-feature="pro-option-typos" type="checkbox" id="pro-typos"> <label for="pro-typos">Automatically fix URL typos without having to create redirect rules</label><br>
34
+ <input class="open-301-pro-dialog" data-pro-feature="pro-option-permalinks" type="checkbox" id="pro-monitor"> <label for="pro-monitor">Monitor permalink changes on posts &amp; pages and automatically create redirect rules so no traffic is lost</label><br>
35
+ <input class="open-301-pro-dialog" data-pro-feature="pro-option-custom-404" type="checkbox" id="pro-custom-404"> <label for="pro-custom-404">Set a custom 404 page from any page</label>
36
+ <p><a href="#" class="open-301-pro-dialog" data-pro-feature="pro-options">WP 301 Redirects PRO</a> offers advanced options to easily fix 2 most overlooked SEO issues - redirections and 404 errors.<br>If you have more than one site, the centralized Dashboard will save you hours of work with its centralized log for all sites.</p>
37
+ </div>
38
+
39
+ <div class="eps-panel eps-margin-top">
40
+ <h3>Import Redirect Rules</h3>
41
  <form method="post" action="" class="eps-padding" enctype="multipart/form-data">
42
  <?php wp_nonce_field('eps_redirect_nonce', 'eps_redirect_nonce_submit'); ?>
43
  <input accept="csv" type="file" name="eps_redirect_upload_file" value="">
47
  &nbsp;&nbsp;&nbsp;<input type="radio" name="eps_redirect_upload_method" value="update"> Update Duplicates
48
  </p>
49
 
50
+ <p class="eps-grey-text">Supply Columns: <strong>Status</strong> (301,302,307,inactive), <strong>Request URL</strong>, <strong>Redirect
51
+ To</strong> (ID or URL). <a href="<?php echo EPS_REDIRECT_URL . 'misc/example-import.csv' ?>" target="_blank">Download Example CSV</a></p>
52
  </form>
53
  </div>
54
 
55
  <div class="eps-panel eps-margin-top">
56
+ <h3>Export Redirect Rules</h3>
57
  <form method="post" action="">
58
  <?php wp_nonce_field('eps_redirect_nonce', 'eps_redirect_nonce_submit'); ?>
59
  <input type="submit" name="eps_redirect_export" id="submit" class="button button-secondary" value="Export Redirects" />
60
+ <p class="eps-grey-text">Export a backup copy of your redirects.</p>
61
  </form>
62
  </div>
63
 
templates/admin-tab-support.php CHANGED
@@ -21,9 +21,12 @@ if (!defined('ABSPATH')) {
21
  <div class="eps-panel eps-margin-top group">
22
  <h1>Support</h1><br>
23
  <ul class="plain-list">
24
- <li>Support is available through plugin's <a href="https://wordpress.org/support/plugin/eps-301-redirects/" target="_blank">WP.org forum</a> - <b>our average response time is just a few hours</b></li>
 
25
  <li>Please send comments, questions, bugs and feature requests on the <a href="https://wordpress.org/support/plugin/eps-301-redirects/" target="_blank">forum</a> too</li>
26
- <li>You can always catch us on Twitter <a href="https://twitter.com/webfactoryltd/" target="_blank">@webfactoryltd</a></li>
 
 
27
  </ul>
28
  </div>
29
 
21
  <div class="eps-panel eps-margin-top group">
22
  <h1>Support</h1><br>
23
  <ul class="plain-list">
24
+ <li>Support for the free version is available through plugin's <a href="https://wordpress.org/support/plugin/eps-301-redirects/" target="_blank">WP.org forum</a></li>
25
+ <li>For <a href="#" class="open-301-pro-dialog" data-pro-feature="support">PRO users</a>, our priority support is available via email or via the <a href="https://wp301redirects.com/contact/" target="_blank">contact form</a></li>
26
  <li>Please send comments, questions, bugs and feature requests on the <a href="https://wordpress.org/support/plugin/eps-301-redirects/" target="_blank">forum</a> too</li>
27
+ <li>Make sure you check out the <a href="https://wordpress.org/plugins/eps-301-redirects/#faq-header" target="_blank">FAQ</a></li>
28
+ <li><a href="https://docs.wp301redirects.com/" target="_blank">PRO documentation</a></li>
29
+ <li><a href="https://trello.com/b/dSf4gcyz/wp-301-redirects-public-roadmap" target="_blank">Public roadmap</a> - vote for new features and suggest your ideas</li>
30
  </ul>
31
  </div>
32
 
templates/template.redirect-entry-edit.php CHANGED
@@ -1,10 +1,7 @@
1
  <?php
2
  /**
3
- *
4
- *
5
  * Outputs the edit form for a given $redirect_id. If $redirect_id is not set, assume this is a new redirect form.
6
  *
7
- *
8
  * @package EPS 301 Redirects
9
  * @author WebFactory Ltd
10
  */
@@ -28,8 +25,7 @@ $redirect = self::get_redirect($redirect_id);
28
 
29
  <div class="eps-url"><span class="eps-url-root"><?php bloginfo('url'); ?>/&nbsp;</span></div>
30
  <input class="eps-url-input" type="text" name="redirect[url_from][]" value="<?php echo ($redirect) ? esc_attr(stripslashes($redirect->url_from)) : ''; ?>">
31
-
32
  </td>
33
  <td>
34
  <?php echo eps_get_selector($redirect); ?>
35
- </td>
1
  <?php
2
  /**
 
 
3
  * Outputs the edit form for a given $redirect_id. If $redirect_id is not set, assume this is a new redirect form.
4
  *
 
5
  * @package EPS 301 Redirects
6
  * @author WebFactory Ltd
7
  */
25
 
26
  <div class="eps-url"><span class="eps-url-root"><?php bloginfo('url'); ?>/&nbsp;</span></div>
27
  <input class="eps-url-input" type="text" name="redirect[url_from][]" value="<?php echo ($redirect) ? esc_attr(stripslashes($redirect->url_from)) : ''; ?>">
 
28
  </td>
29
  <td>
30
  <?php echo eps_get_selector($redirect); ?>
31
+ </td>
templates/template.redirect-entry.php CHANGED
@@ -32,10 +32,21 @@ $query_args = array('page' => $EPS_Redirects_Plugin->config('page_slug'), 'delet
32
  <td>
33
  <?php echo eps_get_destination($redirect); ?>
34
  </td>
35
- <td class="redirect-hits"><strong><?php echo esc_attr(number_format($redirect->count)); ?></strong></td>
36
  <td class="redirect-actions">
37
  <a class="button eps-redirect-edit" href="#eps-redirect-edit" data-id="<?php echo esc_attr($redirect->id); ?>">Edit</a>
38
  <a class="button eps-redirect-remove" href="<?php echo add_query_arg($query_args, admin_url('/options-general.php')); ?>"
39
  data-id="<?php echo esc_attr($redirect->id); ?>">Delete</a>
40
  </td>
41
  </tr>
 
 
 
 
 
 
 
 
 
 
 
32
  <td>
33
  <?php echo eps_get_destination($redirect); ?>
34
  </td>
35
+ <td class="redirect-hits" nowrap><strong><?php echo esc_attr(number_format($redirect->count)); ?></strong> <a class="open-301-pro-dialog pro-feature" data-pro-feature="redirect-rules-chart-icon-<?php echo $i; ?>" href="#"><span class="dashicons dashicons-chart-area"></span></a></td>
36
  <td class="redirect-actions">
37
  <a class="button eps-redirect-edit" href="#eps-redirect-edit" data-id="<?php echo esc_attr($redirect->id); ?>">Edit</a>
38
  <a class="button eps-redirect-remove" href="<?php echo add_query_arg($query_args, admin_url('/options-general.php')); ?>"
39
  data-id="<?php echo esc_attr($redirect->id); ?>">Delete</a>
40
  </td>
41
  </tr>
42
+ <?php
43
+ if ($i == 5) {
44
+ echo '<tr class="row-banner"><td colspan="5"><a href="#" class="open-301-pro-dialog pro-feature" data-pro-feature="redirect-rules-banner-1"><p><b>Are you tired of adding so many redirect rules one-by-one for each URL?</b><br>
45
+ <b>WP 301 Redirects PRO</b> automatically fixes URL typos, has advanced URL matching rules, and watcher over permalink changes so you don\'t have to write so many rules.</p></a></td></tr>';
46
+ }
47
+
48
+ if ($i == 14) {
49
+ echo '<tr class="row-banner"><td colspan="5"><a href="#" class="open-301-pro-dialog pro-feature" data-pro-feature="redirect-rules-banner-2"><p><b>Need a better way to organize &amp; monitor your redirect rules?</b><br>
50
+ <b>WP 301 Redirects PRO</b> makes it easy to tag &amp; search rules so it\'s always easy to find them. And with advanced stats for redirects &amp; 404 errors you\'ll always know what\'s going on with your traffic.</p></a></td></tr>';
51
+ }
52
+ ?>
uninstall.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //if uninstall not called from WordPress exit
3
+ if (!defined('WP_UNINSTALL_PLUGIN')) {
4
+ exit();
5
+ }
6
+
7
+ global $wpdb;
8
+ $redirect_table = $wpdb->prefix . "redirects";
9
+ $wpdb->query('DROP TABLE IF EXISTS ' . $redirect_table);
10
+
11
+ delete_option('eps_pointers');
12
+ delete_option('eps_redirects_404_log');
13
+ delete_option('301-redirects-notices');
14
+ delete_option('eps_redirects_version');
wf-flyout/config.php CHANGED
@@ -4,14 +4,15 @@ $config = array();
4
  $config['plugin_screen'] = 'settings_page_eps_redirects';
5
  $config['icon_border'] = '1px solid #FF6246';
6
  $config['icon_right'] = '40px';
7
- $config['icon_bottom'] = '50px';
8
  $config['icon_image'] = '301-logo.png';
9
  $config['icon_padding'] = '6px';
10
  $config['icon_size'] = '55px';
11
  $config['menu_accent_color'] = '#FF6246';
12
- $config['custom_css'] = '#wf-flyout .ucp-icon .wff-icon img { max-width: 70%; } #wf-flyout .ucp-icon .wff-icon { line-height: 57px; }';
13
 
14
  $config['menu_items'] = array(
 
15
  array('href' => 'https://wpreset.com/?ref=wff-wp-reset', 'target' => '_blank', 'label' => 'Get WP Reset PRO with 50% off', 'icon' => 'wp-reset.png'),
16
  array('href' => 'https://underconstructionpage.com/?ref=wff-eps-301-redirects&coupon=welcome', 'target' => '_blank', 'label' => 'Create the perfect Under Construction Page', 'icon' => 'ucp.png', 'class' => 'ucp-icon'),
17
  array('href' => 'https://wpsticky.com/?ref=wff-eps-301-redirects', 'target' => '_blank', 'label' => 'Make a menu sticky with WP Sticky', 'icon' => 'dashicons-admin-post'),
4
  $config['plugin_screen'] = 'settings_page_eps_redirects';
5
  $config['icon_border'] = '1px solid #FF6246';
6
  $config['icon_right'] = '40px';
7
+ $config['icon_bottom'] = '40px';
8
  $config['icon_image'] = '301-logo.png';
9
  $config['icon_padding'] = '6px';
10
  $config['icon_size'] = '55px';
11
  $config['menu_accent_color'] = '#FF6246';
12
+ $config['custom_css'] = '#wf-flyout .ucp-icon .wff-icon img { max-width: 70%; } #wf-flyout .ucp-icon .wff-icon { line-height: 57px; } #wf-flyout .wp301-icon .wff-icon img { max-width: 70%; } #wf-flyout .wp301-icon .wff-icon { line-height: 57px; }';
13
 
14
  $config['menu_items'] = array(
15
+ array('href' => '#', 'label' => 'Get WP 301 Redirects PRO Lifetime deal for the price of a 1-year license', 'icon' => '301-logo.png', 'class' => 'open-301-pro-dialog accent wp301-icon', 'data' => 'data-pro-feature="flyout"'),
16
  array('href' => 'https://wpreset.com/?ref=wff-wp-reset', 'target' => '_blank', 'label' => 'Get WP Reset PRO with 50% off', 'icon' => 'wp-reset.png'),
17
  array('href' => 'https://underconstructionpage.com/?ref=wff-eps-301-redirects&coupon=welcome', 'target' => '_blank', 'label' => 'Create the perfect Under Construction Page', 'icon' => 'ucp.png', 'class' => 'ucp-icon'),
18
  array('href' => 'https://wpsticky.com/?ref=wff-eps-301-redirects', 'target' => '_blank', 'label' => 'Make a menu sticky with WP Sticky', 'icon' => 'dashicons-admin-post'),
wf-flyout/wf-flyout.php CHANGED
@@ -124,7 +124,7 @@ if (false == class_exists('wf_flyout')) {
124
 
125
  $out = '';
126
  $icons_url = plugin_dir_url($this->plugin_file) . 'wf-flyout/icons/';
127
- $default_link_item = array('class' => '', 'href' => '#', 'target' => '_blank', 'label' => '', 'icon' => '');
128
 
129
  $out .= '<div id="wff-overlay"></div>';
130
 
@@ -148,7 +148,7 @@ if (false == class_exists('wf_flyout')) {
148
  $item['class'] = trim($item['class']);
149
  }
150
 
151
- $out .= '<a href="' . $item['href'] . '" class="wff-menu-item wff-menu-item-' . $i . ' ' . $item['class'] . '" target="_blank">';
152
  $out .= '<span class="wff-label visible">' . $item['label'] . '</span>';
153
  if (substr($item['icon'], 0, 9) == 'dashicons') {
154
  $out .= '<span class="dashicons ' . $item['icon'] . '"></span>';
124
 
125
  $out = '';
126
  $icons_url = plugin_dir_url($this->plugin_file) . 'wf-flyout/icons/';
127
+ $default_link_item = array('class' => '', 'href' => '#', 'target' => '_blank', 'label' => '', 'icon' => '', 'data' => '');
128
 
129
  $out .= '<div id="wff-overlay"></div>';
130
 
148
  $item['class'] = trim($item['class']);
149
  }
150
 
151
+ $out .= '<a ' . $item['data'] . ' href="' . $item['href'] . '" class="wff-menu-item wff-menu-item-' . $i . ' ' . $item['class'] . '" target="_blank">';
152
  $out .= '<span class="wff-label visible">' . $item['label'] . '</span>';
153
  if (substr($item['icon'], 0, 9) == 'dashicons') {
154
  $out .= '<span class="dashicons ' . $item['icon'] . '"></span>';