Version Description
- New: A new, advanced initialization mode which reinforces overall security performance.
- New: Traffic Inspector's algorithms detect and deny any attempt to upload executable files or an .htaccess file via any POST request.
- New: A new setting to disable email notifications about new versions of the plugin.
- New: Search in the traffic log improved. Search in the User agent string and filter out the HTTP method (GET/POST) are available.
- Update: Performance of the logging subsystem is improved.
- Update: In the Smart mode if a user is not logged in, all requests to the admin dashboard are logged.
- Bug fixed: If a user tries to log in with an email address and an incorrect password, the "Invalid username" message is shown.
- Bug fixed: On a multisite installation with websites in subdirectories a user activation link doesn't work.
- Read more
Download this release
Release Info
Developer | Gioni |
Plugin | Cerber Security & Antispam |
Version | 6.5 |
Comparing to | |
See all releases |
Code changes from version 6.2 to 6.5
- assets/admin.css +26 -3
- assets/admin.js +1 -1
- assets/bn2ra.png +0 -0
- cerber-lab.php +22 -7
- cerber-load.php +4976 -0
- cerber-news.php +7 -1
- cerber-tools.php +79 -9
- common.php +229 -77
- dashboard.php +107 -71
- languages/wp-cerber-zh_CN.mo +0 -0
- languages/wp-cerber-zh_CN.po +1771 -0
- languages/wp-cerber.pot +583 -522
- modules/aaa-wp-cerber.php +44 -0
- readme.txt +27 -15
- settings.php +31 -12
- whois.php +1 -1
- wp-cerber.php +51 -4795
assets/admin.css
CHANGED
@@ -357,6 +357,17 @@ td.crb-traffic-details div{
|
|
357 |
#crb-traffic-form select{
|
358 |
width: 100%;
|
359 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
|
361 |
/* IP info like WHOIS details */
|
362 |
|
@@ -455,7 +466,7 @@ p.act-url{
|
|
455 |
border-right: 4px solid rgba(0, 0, 0, 0);
|
456 |
}
|
457 |
|
458 |
-
.red_label, .actv10, .actv11, .actv12, .actv16, .actv17, .actv18, .actv19, .actv41, .actv42, .actv53, .actv54, .actv55, .actv70, .actv71 {
|
459 |
display: inline-block;
|
460 |
padding: 3px 5px 3px 5px;
|
461 |
/*margin: 1px;*/
|
@@ -783,9 +794,9 @@ div#whois:hover {
|
|
783 |
#diagnostic .diag-section {
|
784 |
background-color: #f7f7f7;
|
785 |
border: 2px solid #ccc;
|
786 |
-
width:
|
787 |
max-width:1000px;
|
788 |
-
margin-
|
789 |
padding: 1em;
|
790 |
}
|
791 |
#diagnostic table {
|
@@ -817,6 +828,13 @@ div#whois:hover {
|
|
817 |
width:50%;
|
818 |
}
|
819 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
820 |
|
821 |
.cerber-button span.dashicons-before {
|
822 |
display: inline-block;
|
@@ -900,11 +918,16 @@ table#admin-help tbody td {
|
|
900 |
table#admin-help h3,
|
901 |
table#admin-help img{
|
902 |
margin-top: 30px;
|
|
|
903 |
}
|
904 |
table#admin-help p{
|
905 |
margin-top: 0.5em;
|
906 |
margin-bottom: 1em;
|
907 |
}
|
|
|
|
|
|
|
|
|
908 |
|
909 |
/* Help sign */
|
910 |
|
357 |
#crb-traffic-form select{
|
358 |
width: 100%;
|
359 |
}
|
360 |
+
#crb-traffic-form input[type=submit]{
|
361 |
+
font-weight: bold;
|
362 |
+
margin-top: 10px;
|
363 |
+
}
|
364 |
+
#crb-traffic-form p {
|
365 |
+
padding: 0 !important;
|
366 |
+
}
|
367 |
+
#crb-traffic-form label {
|
368 |
+
font-weight: bold;
|
369 |
+
color: #333;
|
370 |
+
}
|
371 |
|
372 |
/* IP info like WHOIS details */
|
373 |
|
466 |
border-right: 4px solid rgba(0, 0, 0, 0);
|
467 |
}
|
468 |
|
469 |
+
.red_label, .actv10, .actv11, .actv12, .actv16, .actv17, .actv18, .actv19, .actv41, .actv42, .actv53, .actv54, .actv55, .actv56, .actv70, .actv71 {
|
470 |
display: inline-block;
|
471 |
padding: 3px 5px 3px 5px;
|
472 |
/*margin: 1px;*/
|
794 |
#diagnostic .diag-section {
|
795 |
background-color: #f7f7f7;
|
796 |
border: 2px solid #ccc;
|
797 |
+
width: 90%;
|
798 |
max-width:1000px;
|
799 |
+
margin-bottom: 1em;
|
800 |
padding: 1em;
|
801 |
}
|
802 |
#diagnostic table {
|
828 |
width:50%;
|
829 |
}
|
830 |
|
831 |
+
.crb-plain-table {
|
832 |
+
border-collapse: collapse;
|
833 |
+
margin-top: 1em;
|
834 |
+
}
|
835 |
+
.crb-plain-table td{
|
836 |
+
border: 1px solid #eee;
|
837 |
+
}
|
838 |
|
839 |
.cerber-button span.dashicons-before {
|
840 |
display: inline-block;
|
918 |
table#admin-help h3,
|
919 |
table#admin-help img{
|
920 |
margin-top: 30px;
|
921 |
+
margin-bottom: 1em;
|
922 |
}
|
923 |
table#admin-help p{
|
924 |
margin-top: 0.5em;
|
925 |
margin-bottom: 1em;
|
926 |
}
|
927 |
+
table#admin-help span{
|
928 |
+
vertical-align: middle;
|
929 |
+
display: inline-block;
|
930 |
+
}
|
931 |
|
932 |
/* Help sign */
|
933 |
|
assets/admin.js
CHANGED
@@ -3,7 +3,7 @@ jQuery(document).ready(function ($) {
|
|
3 |
/* WP Comments page */
|
4 |
var comtable = 'table.wp-list-table.comments';
|
5 |
|
6 |
-
if (crb_lab_available && $(comtable).length) {
|
7 |
$(comtable + " td.column-author").each(function (index) {
|
8 |
var ip = $(this).find('a').last().text();
|
9 |
var ip_id = cerber_get_id_ip(ip);
|
3 |
/* WP Comments page */
|
4 |
var comtable = 'table.wp-list-table.comments';
|
5 |
|
6 |
+
if (typeof crb_lab_available !== 'undefined' && crb_lab_available && $(comtable).length) {
|
7 |
$(comtable + " td.column-author").each(function (index) {
|
8 |
var ip = $(this).find('a').last().text();
|
9 |
var ip_id = cerber_get_id_ip(ip);
|
assets/bn2ra.png
ADDED
Binary file
|
cerber-lab.php
CHANGED
@@ -511,21 +511,27 @@ function lab_is_cloud_ok(){
|
|
511 |
*/
|
512 |
function lab_save_push( $ip, $reason_id, $details ) {
|
513 |
global $wpdb;
|
514 |
-
|
|
|
515 |
return;
|
516 |
}
|
|
|
517 |
if ($reason_id == 8){
|
518 |
$details = array( 'uri' => $_SERVER['REQUEST_URI'] );
|
519 |
}
|
520 |
if ( is_array( $details ) ) {
|
521 |
$details = serialize( $details );
|
522 |
}
|
|
|
523 |
$wpdb->insert( CERBER_LAB_TABLE, array(
|
524 |
'ip' => $ip,
|
525 |
'reason_id' => $reason_id,
|
526 |
'details' => $details,
|
527 |
'stamp' => time(),
|
528 |
), array( '%s', '%d', '%s', '%d' ) );
|
|
|
|
|
|
|
529 |
}
|
530 |
/**
|
531 |
* Get data for lab
|
@@ -648,10 +654,9 @@ function lab_lab( $with_date = false ) {
|
|
648 |
if ( empty( $key[2] ) || empty( $key[3] ) ) {
|
649 |
return false;
|
650 |
}
|
651 |
-
if ( time() > $key[3] ) {
|
652 |
return false;
|
653 |
}
|
654 |
-
|
655 |
if ( ! $with_date ) {
|
656 |
return true;
|
657 |
}
|
@@ -660,16 +665,17 @@ function lab_lab( $with_date = false ) {
|
|
660 |
$gmt_offset = cerber_get_site_option( 'gmt_offset' ) * 3600;
|
661 |
|
662 |
return date_i18n( $df, $gmt_offset + $key[3] );
|
663 |
-
|
664 |
-
//return $key[3];
|
665 |
}
|
666 |
|
667 |
function lab_indicator(){
|
668 |
-
if (lab_is_cloud_ok()){
|
669 |
$key = lab_get_key();
|
670 |
$sid = 'Site ID: '.$key[0];
|
671 |
-
return '<div title="'.$sid.'" style="float: right; font-weight: normal; font-size: 80%; padding: 0.35em 0.6em 0.35em 0.6em; color: #fff; background-color: #
|
|
|
672 |
}
|
|
|
|
|
673 |
}
|
674 |
|
675 |
/**
|
@@ -882,4 +888,13 @@ function lab_geo_update( $ip = '', $data = array() ) {
|
|
882 |
}
|
883 |
}
|
884 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
885 |
}
|
511 |
*/
|
512 |
function lab_save_push( $ip, $reason_id, $details ) {
|
513 |
global $wpdb;
|
514 |
+
$ip = filter_var( $ip, FILTER_VALIDATE_IP );
|
515 |
+
if ( ! $ip || is_ip_private( $ip ) || cerber_acl_check( $ip, 'W' ) || ! ( crb_get_settings( 'cerberlab' ) || lab_lab() ) ) {
|
516 |
return;
|
517 |
}
|
518 |
+
$reason_id = absint( $reason_id );
|
519 |
if ($reason_id == 8){
|
520 |
$details = array( 'uri' => $_SERVER['REQUEST_URI'] );
|
521 |
}
|
522 |
if ( is_array( $details ) ) {
|
523 |
$details = serialize( $details );
|
524 |
}
|
525 |
+
/*
|
526 |
$wpdb->insert( CERBER_LAB_TABLE, array(
|
527 |
'ip' => $ip,
|
528 |
'reason_id' => $reason_id,
|
529 |
'details' => $details,
|
530 |
'stamp' => time(),
|
531 |
), array( '%s', '%d', '%s', '%d' ) );
|
532 |
+
*/
|
533 |
+
$details = cerber_real_escape( $details );
|
534 |
+
cerber_db_query( 'INSERT INTO ' . CERBER_LAB_TABLE . ' (ip, reason_id, details, stamp) VALUES ("' . $ip . '",' . $reason_id . ',"' . $details . '",' . time() . ')' );
|
535 |
}
|
536 |
/**
|
537 |
* Get data for lab
|
654 |
if ( empty( $key[2] ) || empty( $key[3] ) ) {
|
655 |
return false;
|
656 |
}
|
657 |
+
if ( time() > ( $key[3] + 86400 ) ) { // Plus grace period
|
658 |
return false;
|
659 |
}
|
|
|
660 |
if ( ! $with_date ) {
|
661 |
return true;
|
662 |
}
|
665 |
$gmt_offset = cerber_get_site_option( 'gmt_offset' ) * 3600;
|
666 |
|
667 |
return date_i18n( $df, $gmt_offset + $key[3] );
|
|
|
|
|
668 |
}
|
669 |
|
670 |
function lab_indicator(){
|
671 |
+
if ( lab_is_cloud_ok() && lab_lab() ) {
|
672 |
$key = lab_get_key();
|
673 |
$sid = 'Site ID: '.$key[0];
|
674 |
+
return '<div title="'.$sid.'" style="float: right; font-weight: normal; font-size: 80%; padding: 0.35em 0.6em 0.35em 0.6em; color: #fff; background-color: #29AD16;"><span style="vertical-align: top; line-height: 1;" class="dashicons dashicons-shield-alt"></span></div>';
|
675 |
+
//return '<div title="'.$sid.'" style="float: right; font-weight: normal; font-size: 80%; padding: 0.35em 0.6em 0.35em 0.6em; color: #fff; background-color: #51AE43;"><span style="vertical-align: top; line-height: 1;" class="dashicons dashicons-yes"></span> Cerber Security Cloud Protection is active</div>';
|
676 |
}
|
677 |
+
|
678 |
+
return '';
|
679 |
}
|
680 |
|
681 |
/**
|
888 |
}
|
889 |
}
|
890 |
}
|
891 |
+
}
|
892 |
+
|
893 |
+
function lab_cleanup_cache() {
|
894 |
+
global $wpdb;
|
895 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
896 |
+
return;
|
897 |
+
}
|
898 |
+
$wpdb->query( 'TRUNCATE TABLE ' . CERBER_LAB_NET_TABLE );
|
899 |
+
$wpdb->query( 'TRUNCATE TABLE ' . CERBER_LAB_IP_TABLE );
|
900 |
}
|
cerber-load.php
ADDED
@@ -0,0 +1,4976 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Copyright (C) 2015-18 CERBER TECH INC., http://cerber.tech
|
4 |
+
Copyright (C) 2015-18 Gregory Markov, https://wpcerber.com
|
5 |
+
|
6 |
+
Licenced under the GNU GPL.
|
7 |
+
|
8 |
+
This program is free software; you can redistribute it and/or modify
|
9 |
+
it under the terms of the GNU General Public License as published by
|
10 |
+
the Free Software Foundation; either version 3 of the License, or
|
11 |
+
(at your option) any later version.
|
12 |
+
|
13 |
+
This program is distributed in the hope that it will be useful,
|
14 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
+
GNU General Public License for more details.
|
17 |
+
|
18 |
+
You should have received a copy of the GNU General Public License
|
19 |
+
along with this program; if not, write to the Free Software
|
20 |
+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
21 |
+
|
22 |
+
*/
|
23 |
+
|
24 |
+
/*
|
25 |
+
|
26 |
+
|
27 |
+
|
28 |
+
▄████▄ ▓█████ ██▀███ ▄▄▄▄ ▓█████ ██▀███
|
29 |
+
▒██▀ ▀█ ▓█ ▀ ▓██ ▒ ██▒ ▓█████▄ ▓█ ▀ ▓██ ▒ ██▒
|
30 |
+
▒▓█ ▄ ▒███ ▓██ ░▄█ ▒ ▒██▒ ▄██ ▒███ ▓██ ░▄█ ▒
|
31 |
+
▒▓▓▄ ▄██▒ ▒▓█ ▄ ▒██▀▀█▄ ▒██░█▀ ▒▓█ ▄ ▒██▀▀█▄
|
32 |
+
▒ ▓███▀ ░ ░▒████▒ ░██▓ ▒██▒ ░▓█ ▀█▓ ░▒████▒ ░██▓ ▒██▒
|
33 |
+
░ ░▒ ▒ ░ ░░ ▒░ ░ ░ ▒▓ ░▒▓░ ░▒▓███▀▒ ░░ ▒░ ░ ░ ▒▓ ░▒▓░
|
34 |
+
░ ▒ ░ ░ ░ ░▒ ░ ▒░ ▒░▒ ░ ░ ░ ░ ░▒ ░ ▒░
|
35 |
+
░ ░ ░░ ░ ░ ░ ░ ░░ ░
|
36 |
+
░ ░ ░ ░ ░ ░ ░ ░ ░
|
37 |
+
░ ░
|
38 |
+
|
39 |
+
|
40 |
+
|
41 |
+
|
42 |
+
*========================================================================*
|
43 |
+
| |
|
44 |
+
| ATTENTION! Do not change or edit this file! |
|
45 |
+
| |
|
46 |
+
*========================================================================*
|
47 |
+
|
48 |
+
*/
|
49 |
+
|
50 |
+
// If this file is called directly, abort executing.
|
51 |
+
if ( ! defined( 'WPINC' ) ) {
|
52 |
+
exit;
|
53 |
+
}
|
54 |
+
|
55 |
+
define( 'CERBER_LOG_TABLE', 'cerber_log' );
|
56 |
+
define( 'CERBER_TRAF_TABLE', 'cerber_traffic' );
|
57 |
+
define( 'CERBER_ACL_TABLE', 'cerber_acl' );
|
58 |
+
define( 'CERBER_BLOCKS_TABLE', 'cerber_blocks' );
|
59 |
+
define( 'CERBER_LAB_TABLE', 'cerber_lab' );
|
60 |
+
define( 'CERBER_LAB_IP_TABLE', 'cerber_lab_ip' );
|
61 |
+
define( 'CERBER_LAB_NET_TABLE', 'cerber_lab_net' );
|
62 |
+
define( 'CERBER_GEO_TABLE', 'cerber_countries' );
|
63 |
+
|
64 |
+
define( 'CERBER_MARKER1', 'WP CERBER GROOVE' );
|
65 |
+
|
66 |
+
define( 'WP_LOGIN_SCRIPT', 'wp-login.php' );
|
67 |
+
define( 'WP_REG_URI', 'wp-register.php' );
|
68 |
+
define( 'WP_XMLRPC_SCRIPT', 'xmlrpc.php' );
|
69 |
+
define( 'WP_TRACKBACK_SCRIPT', 'wp-trackback.php' );
|
70 |
+
define( 'WP_PING_SCRIPT', 'wp-trackback.php' );
|
71 |
+
define( 'WP_SIGNUP_SCRIPT', 'wp-signup.php' );
|
72 |
+
|
73 |
+
define( 'GOO_RECAPTCHA_URL', 'https://www.google.com/recaptcha/api/siteverify' );
|
74 |
+
|
75 |
+
define( 'CERBER_REQ_PHP', '5.3.0' );
|
76 |
+
define( 'CERBER_REQ_WP', '4.4' );
|
77 |
+
define( 'CERBER_TECH', 'https://cerber.tech/' );
|
78 |
+
|
79 |
+
require_once( dirname( __FILE__ ) . '/cerber-pluggable.php' );
|
80 |
+
require_once( dirname( __FILE__ ) . '/common.php' );
|
81 |
+
require_once( dirname( __FILE__ ) . '/settings.php' );
|
82 |
+
require_once( dirname( __FILE__ ) . '/cerber-lab.php' );
|
83 |
+
require_once( dirname( __FILE__ ) . '/whois.php' );
|
84 |
+
require_once( dirname( __FILE__ ) . '/jetflow.php' );
|
85 |
+
require_once( dirname( __FILE__ ) . '/cerber-news.php' );
|
86 |
+
|
87 |
+
if ( defined( 'WP_ADMIN' ) || defined( 'WP_NETWORK_ADMIN' ) ) {
|
88 |
+
// Load dashboard stuff
|
89 |
+
require_once( dirname( __FILE__ ) . '/dashboard.php' );
|
90 |
+
}
|
91 |
+
|
92 |
+
// =============================================================================================
|
93 |
+
|
94 |
+
class WP_Cerber {
|
95 |
+
private $remote_ip;
|
96 |
+
private $session_id;
|
97 |
+
private $status = null;
|
98 |
+
private $options;
|
99 |
+
private $locked = null; // IP has been locked out
|
100 |
+
|
101 |
+
private $recaptcha = null; // Can recaptcha be verified with current request
|
102 |
+
private $recaptcha_verified = null; // Is recaptcha successfully verified with current request
|
103 |
+
public $recaptcha_here = null; // Is recaptcha widget enabled on the currently displayed page
|
104 |
+
|
105 |
+
private $uri_prohibited = null;
|
106 |
+
private $deny = null;
|
107 |
+
private $acl = null;
|
108 |
+
|
109 |
+
//private $boot_source_file = '';
|
110 |
+
//private $boot_target_file = '';
|
111 |
+
|
112 |
+
public $garbage = false; // Garbage has been deleted
|
113 |
+
|
114 |
+
final function __construct() {
|
115 |
+
|
116 |
+
$this->session_id = substr(str_shuffle('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'), 0, 24);
|
117 |
+
|
118 |
+
// Load settings with filling missing (not-set) array keys
|
119 |
+
$this->options = crb_get_settings(); // @since 6.3.3
|
120 |
+
$keys = array();
|
121 |
+
//$defaults = array();
|
122 |
+
foreach ( cerber_get_defaults() as $item ) {
|
123 |
+
$keys = array_merge( $keys, array_keys( $item ) );
|
124 |
+
//$defaults = array_merge( $defaults, $item );
|
125 |
+
}
|
126 |
+
foreach ( $keys as $key ) {
|
127 |
+
if ( ! isset( $this->options[ $key ] ) ) {
|
128 |
+
$this->options[ $key ] = null;
|
129 |
+
}
|
130 |
+
}
|
131 |
+
|
132 |
+
if ( defined( 'CERBER_IP_KEY' ) ) {
|
133 |
+
$this->remote_ip = filter_var( $_SERVER[ CERBER_IP_KEY ], FILTER_VALIDATE_IP );
|
134 |
+
}
|
135 |
+
elseif ( $this->options['proxy'] && isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
|
136 |
+
$list = explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] );
|
137 |
+
foreach ( $list as $maybe_ip ) {
|
138 |
+
$this->remote_ip = filter_var( trim( $maybe_ip ), FILTER_VALIDATE_IP );
|
139 |
+
if ( $this->remote_ip ) {
|
140 |
+
break;
|
141 |
+
}
|
142 |
+
}
|
143 |
+
if ( ! $this->remote_ip && isset( $_SERVER['HTTP_X_REAL_IP'] ) ) {
|
144 |
+
$this->remote_ip = filter_var( $_SERVER['HTTP_X_REAL_IP'], FILTER_VALIDATE_IP );
|
145 |
+
}
|
146 |
+
} else {
|
147 |
+
if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
|
148 |
+
$this->remote_ip = $_SERVER['REMOTE_ADDR'];
|
149 |
+
} elseif ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) {
|
150 |
+
$this->remote_ip = $_SERVER['HTTP_X_REAL_IP'];
|
151 |
+
} elseif ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) {
|
152 |
+
$this->remote_ip = $_SERVER['HTTP_CLIENT_IP'];
|
153 |
+
} elseif ( isset( $_SERVER['SERVER_ADDR'] ) ) {
|
154 |
+
$this->remote_ip = $_SERVER['SERVER_ADDR'];
|
155 |
+
}
|
156 |
+
$this->remote_ip = filter_var( $this->remote_ip, FILTER_VALIDATE_IP );
|
157 |
+
}
|
158 |
+
// No IP address was found? Roll back to localhost.
|
159 |
+
if ( ! $this->remote_ip ) {
|
160 |
+
$this->remote_ip = '127.0.0.1';
|
161 |
+
} // including WP-CLI, other way is: if defined('WP_CLI')
|
162 |
+
|
163 |
+
$this->remote_ip = cerber_short_ipv6( $this->remote_ip );
|
164 |
+
|
165 |
+
$this->reCaptchaInit();
|
166 |
+
|
167 |
+
$this->deleteGarbage();
|
168 |
+
|
169 |
+
// Condition to check reCAPTCHA
|
170 |
+
|
171 |
+
add_action( 'login_init', array( $this, 'reCaptchaNow' ) );
|
172 |
+
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* @since 6.3.3
|
177 |
+
*/
|
178 |
+
final public function isURIProhibited() {
|
179 |
+
global $cerber_status;
|
180 |
+
|
181 |
+
if ( isset( $this->uri_prohibited ) ) {
|
182 |
+
return $this->uri_prohibited;
|
183 |
+
}
|
184 |
+
|
185 |
+
if ( cerber_acl_check() == 'W' ) {
|
186 |
+
$this->uri_prohibited = false;
|
187 |
+
return false;
|
188 |
+
}
|
189 |
+
|
190 |
+
$script = cerber_last_uri();
|
191 |
+
if ( substr( $script, - 4 ) != '.php' ) {
|
192 |
+
$script .= '.php'; // Apache MultiViews enabled?
|
193 |
+
}
|
194 |
+
|
195 |
+
if ( $script ) {
|
196 |
+
if ( $script == WP_LOGIN_SCRIPT || $script == WP_SIGNUP_SCRIPT || ( $script == WP_REG_URI && ! get_option( 'users_can_register' ) ) ) { // no direct access
|
197 |
+
if ( !empty( $this->options['wplogin'] ) ) {
|
198 |
+
cerber_log( 50 );
|
199 |
+
cerber_soft_block_add( $this->remote_ip, 2, $script );
|
200 |
+
$this->uri_prohibited = true;
|
201 |
+
return true;
|
202 |
+
}
|
203 |
+
if ( $this->isDeny() || !empty( $this->options['loginnowp'] ) ) {
|
204 |
+
cerber_log( 50 );
|
205 |
+
$this->uri_prohibited = true;
|
206 |
+
return true;
|
207 |
+
}
|
208 |
+
}
|
209 |
+
elseif ( $script == WP_XMLRPC_SCRIPT || $script == WP_TRACKBACK_SCRIPT ) { // no direct access
|
210 |
+
if ( $this->isDeny() || ! empty( $this->options['xmlrpc'] ) ) {
|
211 |
+
cerber_log( 50 ); // @since 5.21
|
212 |
+
$this->uri_prohibited = true;
|
213 |
+
return true;
|
214 |
+
}
|
215 |
+
if ( !cerber_geo_allowed( 'geo_xmlrpc' ) ) {
|
216 |
+
$cerber_status = 16;
|
217 |
+
cerber_log( 71 );
|
218 |
+
$this->uri_prohibited = true;
|
219 |
+
return true;
|
220 |
+
}
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
$this->uri_prohibited = false;
|
225 |
+
|
226 |
+
return $this->uri_prohibited;
|
227 |
+
}
|
228 |
+
|
229 |
+
/**
|
230 |
+
* @since 6.3.3
|
231 |
+
*/
|
232 |
+
final public function CheckProhibitedURI(){
|
233 |
+
if ($this->isURIProhibited()){
|
234 |
+
if ( $this->options['page404'] ) {
|
235 |
+
cerber_404_page();
|
236 |
+
}
|
237 |
+
|
238 |
+
return true;
|
239 |
+
}
|
240 |
+
|
241 |
+
return false;
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* @since 6.3.3
|
246 |
+
*/
|
247 |
+
final public function InspectRequest(){
|
248 |
+
$deny = false;
|
249 |
+
$act = 18;
|
250 |
+
if ( cerber_is_http_post() ) {
|
251 |
+
if (cerber_acl_check(null, 'B')) {
|
252 |
+
$deny = true;
|
253 |
+
$act = 18;
|
254 |
+
}
|
255 |
+
}
|
256 |
+
if ( !$deny && $_FILES ) {
|
257 |
+
$file_names = array();
|
258 |
+
foreach ( $_FILES as $file ) {
|
259 |
+
if ( is_array( $file['name'] ) ) {
|
260 |
+
$file_names = array_merge( $file_names, $file['name'] );
|
261 |
+
}
|
262 |
+
else {
|
263 |
+
$file_names[] = $file['name'];
|
264 |
+
}
|
265 |
+
}
|
266 |
+
foreach ( $file_names as $item ) {
|
267 |
+
if ( $reason = $this->isProhibitedFilename( $item ) ) {
|
268 |
+
$deny = true;
|
269 |
+
$act = $reason;
|
270 |
+
break;
|
271 |
+
}
|
272 |
+
}
|
273 |
+
}
|
274 |
+
if ( $deny ) {
|
275 |
+
cerber_log( $act );
|
276 |
+
cerber_forbidden_page();
|
277 |
+
}
|
278 |
+
}
|
279 |
+
|
280 |
+
/**
|
281 |
+
* @since 6.3.3
|
282 |
+
*/
|
283 |
+
final public function isProhibitedFilename( $file_name ) {
|
284 |
+
$prohibited = array( '.htaccess' );
|
285 |
+
if ( in_array( $file_name, $prohibited ) ) {
|
286 |
+
return 57;
|
287 |
+
}
|
288 |
+
if ( cerber_detect_exec_extension( $file_name, array('js') ) ) {
|
289 |
+
return 56;
|
290 |
+
}
|
291 |
+
|
292 |
+
return false;
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* @since 6.3.3
|
297 |
+
*/
|
298 |
+
final public function isDeny() {
|
299 |
+
if ( ! isset( $this->deny ) ) {
|
300 |
+
$this->acl = cerber_acl_check();
|
301 |
+
if ( $this->acl == 'B' || ! cerber_is_allowed() ) {
|
302 |
+
$this->deny = true;
|
303 |
+
}
|
304 |
+
else {
|
305 |
+
$this->deny = false;
|
306 |
+
}
|
307 |
+
}
|
308 |
+
|
309 |
+
return $this->deny;
|
310 |
+
}
|
311 |
+
|
312 |
+
// TODO: replace it with cerber_get_remote_ip()
|
313 |
+
final public function getRemoteIp() {
|
314 |
+
return $this->remote_ip;
|
315 |
+
}
|
316 |
+
|
317 |
+
final public function getSessionID() {
|
318 |
+
return $this->session_id;
|
319 |
+
}
|
320 |
+
|
321 |
+
final public function getStatus() {
|
322 |
+
if (isset($this->status)) return $this->status;
|
323 |
+
|
324 |
+
$this->status = 0; // Default
|
325 |
+
|
326 |
+
if ( cerber_is_citadel() ) {
|
327 |
+
$this->status = 3;
|
328 |
+
}
|
329 |
+
else {
|
330 |
+
//if ( ! cerber_is_allowed( $this->remote_ip ) ) {
|
331 |
+
if ( cerber_block_check( $this->remote_ip ) ) {
|
332 |
+
$this->status = 2;
|
333 |
+
}
|
334 |
+
else {
|
335 |
+
$tag = cerber_acl_check( $this->remote_ip );
|
336 |
+
if ( $tag == 'W' ) {
|
337 |
+
//$this->status = 4;
|
338 |
+
}
|
339 |
+
elseif ( $tag == 'B' || lab_is_blocked($this->remote_ip, false)) {
|
340 |
+
$this->status = 1;
|
341 |
+
}
|
342 |
+
}
|
343 |
+
}
|
344 |
+
|
345 |
+
return $this->status;
|
346 |
+
}
|
347 |
+
|
348 |
+
/*
|
349 |
+
Return Error message in context
|
350 |
+
*/
|
351 |
+
final public function getErrorMsg() {
|
352 |
+
$status = $this->getStatus();
|
353 |
+
switch ( $status ) {
|
354 |
+
case 1:
|
355 |
+
case 3:
|
356 |
+
return apply_filters( 'cerber_msg_blocked', __( 'You are not allowed to log in. Ask your administrator for assistance.', 'wp-cerber' ) , $status);
|
357 |
+
case 2:
|
358 |
+
$block = cerber_get_block();
|
359 |
+
$min = 1 + ( $block->block_until - time() ) / 60;
|
360 |
+
|
361 |
+
return apply_filters( 'cerber_msg_reached',
|
362 |
+
sprintf( __( 'You have reached the login attempts limit. Please try again in %d minutes.', 'wp-cerber' ), $min ),
|
363 |
+
$min );
|
364 |
+
break;
|
365 |
+
default:
|
366 |
+
return '';
|
367 |
+
}
|
368 |
+
}
|
369 |
+
|
370 |
+
/*
|
371 |
+
Return Remain message in context
|
372 |
+
*/
|
373 |
+
final public function getRemainMsg() {
|
374 |
+
$acl = !$this->options['limitwhite'];
|
375 |
+
$remain = cerber_get_remain_count($this->remote_ip, $acl);
|
376 |
+
if ( $remain < $this->options['attempts'] ) {
|
377 |
+
if ( $remain == 0 ) {
|
378 |
+
$remain = 1; // with some settings or when lockout was manually removed, we need to have 1 attempt.
|
379 |
+
}
|
380 |
+
return apply_filters( 'cerber_msg_remain',
|
381 |
+
sprintf( _n( 'You have only one attempt remaining.', 'You have %d attempts remaining.', $remain, 'wp-cerber' ), $remain ),
|
382 |
+
$remain );
|
383 |
+
}
|
384 |
+
|
385 |
+
return false;
|
386 |
+
}
|
387 |
+
|
388 |
+
final public function getSettings( $name = null ) {
|
389 |
+
if ( ! empty( $name ) ) {
|
390 |
+
if ( isset( $this->options[ $name ] ) ) {
|
391 |
+
return $this->options[ $name ];
|
392 |
+
} else {
|
393 |
+
return false;
|
394 |
+
}
|
395 |
+
}
|
396 |
+
|
397 |
+
return $this->options;
|
398 |
+
}
|
399 |
+
|
400 |
+
/*
|
401 |
+
final public function isProhibited( $username ) {
|
402 |
+
if ( empty( $this->options['prohibited'] ) ) {
|
403 |
+
return false;
|
404 |
+
}
|
405 |
+
|
406 |
+
return in_array( $username, (array) $this->options['prohibited'] );
|
407 |
+
}*/
|
408 |
+
|
409 |
+
/**
|
410 |
+
* Adding reCAPTCHA widgets
|
411 |
+
*
|
412 |
+
*/
|
413 |
+
final public function reCaptchaInit(){
|
414 |
+
|
415 |
+
if ( $this->status == 4 || empty( $this->options['sitekey'] ) || empty( $this->options['secretkey'] )) return;
|
416 |
+
|
417 |
+
// Native WP forms
|
418 |
+
add_action( 'login_form', function () {
|
419 |
+
global $wp_cerber;
|
420 |
+
$wp_cerber->reCaptcha( 'widget', 'recaplogin' );
|
421 |
+
} );
|
422 |
+
add_filter( 'login_form_middle', function ( $value ) {
|
423 |
+
global $wp_cerber;
|
424 |
+
$value .= $wp_cerber->reCaptcha( 'widget', 'recaplogin', false );
|
425 |
+
return $value;
|
426 |
+
});
|
427 |
+
add_action( 'lostpassword_form', function () {
|
428 |
+
global $wp_cerber;
|
429 |
+
$wp_cerber->reCaptcha( 'widget', 'recaplost' );
|
430 |
+
} );
|
431 |
+
add_action( 'register_form', function () {
|
432 |
+
global $wp_cerber;
|
433 |
+
if ( !did_action( 'woocommerce_register_form_start' ) ) {
|
434 |
+
$wp_cerber->reCaptcha( 'widget', 'recapreg' );
|
435 |
+
}
|
436 |
+
} );
|
437 |
+
|
438 |
+
// Support for WooCommerce forms: @since 3.8
|
439 |
+
add_action( 'woocommerce_login_form', function () {
|
440 |
+
global $wp_cerber;
|
441 |
+
$wp_cerber->reCaptcha( 'widget', 'recapwoologin' );
|
442 |
+
} );
|
443 |
+
add_action( 'woocommerce_lostpassword_form', function () {
|
444 |
+
global $wp_cerber;
|
445 |
+
$wp_cerber->reCaptcha( 'widget', 'recapwoolost' );
|
446 |
+
} );
|
447 |
+
add_action( 'woocommerce_register_form', function () {
|
448 |
+
global $wp_cerber;
|
449 |
+
if ( ! did_action( 'woocommerce_register_form_start' ) ) {
|
450 |
+
return;
|
451 |
+
}
|
452 |
+
$wp_cerber->reCaptcha( 'widget', 'recapwooreg' );
|
453 |
+
} );
|
454 |
+
add_filter( 'woocommerce_process_login_errors', function ( $validation_error ) {
|
455 |
+
global $wp_cerber;
|
456 |
+
//$wp_cerber->reCaptchaNow();
|
457 |
+
if ( ! $wp_cerber->reCaptchaValidate('woologin', true) ) {
|
458 |
+
|
459 |
+
return new WP_Error( 'incorrect_recaptcha', $wp_cerber->reCaptchaMsg('woocommerce-login'));
|
460 |
+
}
|
461 |
+
return $validation_error;
|
462 |
+
});
|
463 |
+
add_filter( 'allow_password_reset', function ( $var ) { // Note: 'allow_password_reset' also is fired in WP itself
|
464 |
+
global $wp_cerber;
|
465 |
+
if ( isset( $_POST['wc_reset_password'] ) && did_action( 'woocommerce_init' )) {
|
466 |
+
//$wp_cerber->reCaptchaNow();
|
467 |
+
if ( ! $wp_cerber->reCaptchaValidate( 'woolost' , true) ) {
|
468 |
+
|
469 |
+
return new WP_Error( 'incorrect_recaptcha', $wp_cerber->reCaptchaMsg('woocommerce-lost'));
|
470 |
+
}
|
471 |
+
}
|
472 |
+
return $var;
|
473 |
+
});
|
474 |
+
add_filter( 'woocommerce_process_registration_errors', function ( $validation_error ) {
|
475 |
+
global $wp_cerber;
|
476 |
+
//$wp_cerber->reCaptchaNow();
|
477 |
+
if ( ! $wp_cerber->reCaptchaValidate('wooreg' , true) ) {
|
478 |
+
|
479 |
+
return new WP_Error( 'incorrect_recaptcha', $wp_cerber->reCaptchaMsg('woocommerce-register'));
|
480 |
+
}
|
481 |
+
return $validation_error;
|
482 |
+
});
|
483 |
+
|
484 |
+
}
|
485 |
+
|
486 |
+
/**
|
487 |
+
* Generates reCAPTCHA HTML
|
488 |
+
*
|
489 |
+
* @param string $part 'style' or 'widget'
|
490 |
+
* @param null $option what plugin setting must be set to show the reCAPTCHA
|
491 |
+
* @param bool $echo if false, return the code, otherwise show it
|
492 |
+
*
|
493 |
+
* @return null|string
|
494 |
+
*/
|
495 |
+
final public function reCaptcha( $part = '', $option = null, $echo = true ) {
|
496 |
+
if ( $this->status == 4 || empty( $this->options['sitekey'] ) || empty( $this->options['secretkey'] )
|
497 |
+
|| ( $option && empty( $this->options[ $option ] ) )
|
498 |
+
) {
|
499 |
+
return null;
|
500 |
+
}
|
501 |
+
|
502 |
+
$sitekey = $this->options['sitekey'];
|
503 |
+
$ret = '';
|
504 |
+
|
505 |
+
switch ( $part ) {
|
506 |
+
case 'style': // for default login WP form only - fit it in width nicely.
|
507 |
+
?>
|
508 |
+
<style type="text/css" media="all">
|
509 |
+
#rc-imageselect, .g-recaptcha {
|
510 |
+
transform: scale(0.9);
|
511 |
+
-webkit-transform: scale(0.9);
|
512 |
+
transform-origin: 0 0;
|
513 |
+
-webkit-transform-origin: 0 0;
|
514 |
+
}
|
515 |
+
|
516 |
+
.g-recaptcha {
|
517 |
+
margin: 16px 0 20px 0;
|
518 |
+
}
|
519 |
+
</style>
|
520 |
+
<?php
|
521 |
+
break;
|
522 |
+
case 'widget':
|
523 |
+
if ( ! empty( $this->options[ $option ] ) ) {
|
524 |
+
$this->recaptcha_here = true;
|
525 |
+
|
526 |
+
//if ($this->options['invirecap']) $ret = '<div data-size="invisible" class="g-recaptcha" data-sitekey="' . $sitekey . '" data-callback="now_submit_the_form" id="cerber-recaptcha" data-badge="bottomright"></div>';
|
527 |
+
if ($this->options['invirecap']) {
|
528 |
+
$ret = '<span class="cerber-form-marker"></span><div data-size="invisible" class="g-recaptcha" data-sitekey="' . $sitekey . '" data-callback="now_submit_the_form" id="cerber-recaptcha" data-badge="bottomright"></div>';
|
529 |
+
}
|
530 |
+
else $ret = '<span class="cerber-form-marker"></span><div class="g-recaptcha" data-sitekey="' . $sitekey . '" data-callback="form_button_enabler" id="cerber-recaptcha"></div>';
|
531 |
+
|
532 |
+
//$ret = '<span class="cerber-form-marker g-recaptcha"></span>';
|
533 |
+
|
534 |
+
}
|
535 |
+
break;
|
536 |
+
}
|
537 |
+
if ( $echo ) {
|
538 |
+
echo $ret;
|
539 |
+
$ret = null;
|
540 |
+
}
|
541 |
+
|
542 |
+
return $ret;
|
543 |
+
/*
|
544 |
+
<script type="text/javascript">
|
545 |
+
var onloadCallback = function() {
|
546 |
+
//document.getElementById("wp-submit").disabled = true;
|
547 |
+
grecaptcha.render("c-recaptcha", {"sitekey" : "<?php echo $sitekey; ?>" });
|
548 |
+
//document.getElementById("wp-submit").disabled = false;
|
549 |
+
};
|
550 |
+
</script>
|
551 |
+
<script src = "https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit&hl=<?php echo $lang; ?>" async defer></script>
|
552 |
+
*/
|
553 |
+
}
|
554 |
+
|
555 |
+
/**
|
556 |
+
* Validate reCAPTCHA by calling Google service
|
557 |
+
*
|
558 |
+
* @param string $form Form ID (slug)
|
559 |
+
* @param boolean $force Force validate without pre-checks
|
560 |
+
*
|
561 |
+
* @return bool true on success false on failure
|
562 |
+
*/
|
563 |
+
final public function reCaptchaValidate($form = null, $force = false) {
|
564 |
+
if (!$force) {
|
565 |
+
if ( ! $this->recaptcha || $this->status == 4 ) {
|
566 |
+
return true;
|
567 |
+
}
|
568 |
+
}
|
569 |
+
|
570 |
+
if ($this->recaptcha_verified != null) return $this->recaptcha_verified;
|
571 |
+
|
572 |
+
if ( $form == 'comment' && $this->options['recapcomauth'] && is_user_logged_in()) return true;
|
573 |
+
|
574 |
+
if ( ! $form ) {
|
575 |
+
$form = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : 'login';
|
576 |
+
}
|
577 |
+
|
578 |
+
$forms = array( // known pairs: form => specific plugin setting
|
579 |
+
'lostpassword' => 'recaplost',
|
580 |
+
'register' => 'recapreg',
|
581 |
+
'login' => 'recaplogin',
|
582 |
+
'comment' => 'recapcom',
|
583 |
+
'woologin' => 'recapwoologin',
|
584 |
+
'woolost' => 'recapwoolost',
|
585 |
+
'wooreg' => 'recapwooreg',
|
586 |
+
);
|
587 |
+
|
588 |
+
if ( isset( $forms[ $form ] ) ) {
|
589 |
+
if ( empty( $this->options[ $forms[ $form ] ] ) ) {
|
590 |
+
return true; // no validation is required
|
591 |
+
}
|
592 |
+
}
|
593 |
+
else {
|
594 |
+
return true; // we don't know this form
|
595 |
+
}
|
596 |
+
|
597 |
+
if ( empty( $_POST['g-recaptcha-response'] ) ) {
|
598 |
+
$this->reCaptchaFailed($form);
|
599 |
+
return false;
|
600 |
+
}
|
601 |
+
|
602 |
+
$result = $this->reCaptchaRequest($_POST['g-recaptcha-response']);
|
603 |
+
if ( ! $result ) {
|
604 |
+
cerber_log( 42 );
|
605 |
+
return false;
|
606 |
+
}
|
607 |
+
|
608 |
+
$result = json_decode( $result );
|
609 |
+
$result = obj_to_arr_deep( $result );
|
610 |
+
|
611 |
+
if ( ! empty( $result['success'] ) ) {
|
612 |
+
$this->recaptcha_verified = true;
|
613 |
+
return true;
|
614 |
+
}
|
615 |
+
$this->recaptcha_verified = false;
|
616 |
+
|
617 |
+
if ( ! empty( $result['error-codes'] ) ) {
|
618 |
+
if ( in_array( 'invalid-input-secret', (array) $result['error-codes'] ) ) {
|
619 |
+
cerber_log( 41 );
|
620 |
+
}
|
621 |
+
}
|
622 |
+
|
623 |
+
$this->reCaptchaFailed($form);
|
624 |
+
|
625 |
+
return false;
|
626 |
+
}
|
627 |
+
|
628 |
+
final function reCaptchaFailed($context = '') {
|
629 |
+
cerber_log( 40 );
|
630 |
+
if ($this->options['recaptcha-period'] && $this->options['recaptcha-number'] && $this->options['recaptcha-within']) {
|
631 |
+
$remain = cerber_get_remain_count($this->remote_ip , true, 40, $this->options['recaptcha-number'], $this->options['recaptcha-within']);
|
632 |
+
if ($remain < 1) cerber_block_add( $this->remote_ip, 5 );
|
633 |
+
}
|
634 |
+
}
|
635 |
+
|
636 |
+
/**
|
637 |
+
* A form with possible reCAPTCHA has been submitted.
|
638 |
+
* Allow to process reCAPTCHA by setting a global flag.
|
639 |
+
* Must be called before reCaptchaValidate();
|
640 |
+
*
|
641 |
+
*/
|
642 |
+
final public function reCaptchaNow() {
|
643 |
+
if ( cerber_is_http_post() && $this->options['sitekey'] && $this->options['secretkey'] ) {
|
644 |
+
$this->recaptcha = true;
|
645 |
+
}
|
646 |
+
}
|
647 |
+
|
648 |
+
/**
|
649 |
+
* Make a request to the Google reCaptcha web service
|
650 |
+
*
|
651 |
+
* @param string $response Google specific field from the submitted form (widget)
|
652 |
+
*
|
653 |
+
* @return bool|string Response of the Google service or false on failure
|
654 |
+
*/
|
655 |
+
final public function reCaptchaRequest($response = ''){
|
656 |
+
|
657 |
+
if (!$response) {
|
658 |
+
if (!empty($_POST['g-recaptcha-response'])) $response = $_POST['g-recaptcha-response'];
|
659 |
+
else return false;
|
660 |
+
}
|
661 |
+
|
662 |
+
$curl = @curl_init(); // @since 4.32
|
663 |
+
if (!$curl) {
|
664 |
+
cerber_admin_notice(__( 'ERROR:', 'wp-cerber' ) .' Unable to initialize cURL');
|
665 |
+
return false;
|
666 |
+
}
|
667 |
+
|
668 |
+
$opt = curl_setopt_array($curl, array(
|
669 |
+
CURLOPT_URL => GOO_RECAPTCHA_URL,
|
670 |
+
CURLOPT_POST => true,
|
671 |
+
CURLOPT_POSTFIELDS => array( 'secret' => $this->options['secretkey'], 'response' => $response ),
|
672 |
+
CURLOPT_RETURNTRANSFER => true,
|
673 |
+
));
|
674 |
+
|
675 |
+
if (!$opt) {
|
676 |
+
cerber_admin_notice(__( 'ERROR:', 'wp-cerber' ) .' '. curl_error($curl));
|
677 |
+
curl_close($curl);
|
678 |
+
return false;
|
679 |
+
}
|
680 |
+
|
681 |
+
$result = curl_exec($curl);
|
682 |
+
if (!$result) {
|
683 |
+
cerber_admin_notice(__( 'ERROR:', 'wp-cerber' ) .' '. curl_error($curl));
|
684 |
+
$result = false;
|
685 |
+
}
|
686 |
+
curl_close($curl);
|
687 |
+
|
688 |
+
return $result;
|
689 |
+
|
690 |
+
}
|
691 |
+
|
692 |
+
final public function reCaptchaMsg($context = null){
|
693 |
+
return apply_filters( 'cerber_msg_recaptcha', __( 'Human verification failed. Please click the square box in the reCAPTCHA block below.', 'wp-cerber' ), $context);
|
694 |
+
}
|
695 |
+
|
696 |
+
final public function setLocked() {
|
697 |
+
if ( ! isset( $this->locked ) ) {
|
698 |
+
$this->locked = 1;
|
699 |
+
}
|
700 |
+
}
|
701 |
+
|
702 |
+
final public function isLocked() {
|
703 |
+
if ( ! empty( $this->locked ) ) {
|
704 |
+
return 1;
|
705 |
+
}
|
706 |
+
return 0;
|
707 |
+
}
|
708 |
+
|
709 |
+
final public function deleteGarbage() {
|
710 |
+
global $wpdb;
|
711 |
+
if ( $this->garbage ) {
|
712 |
+
return;
|
713 |
+
}
|
714 |
+
$wpdb->query( 'DELETE FROM ' . CERBER_BLOCKS_TABLE . ' WHERE block_until < ' . time() );
|
715 |
+
$this->garbage = true;
|
716 |
+
}
|
717 |
+
}
|
718 |
+
|
719 |
+
function cerber_init() {
|
720 |
+
static $done = false;
|
721 |
+
|
722 |
+
if ( $done ) {
|
723 |
+
return;
|
724 |
+
}
|
725 |
+
|
726 |
+
cerber_request_time();
|
727 |
+
cerber_upgrade_all();
|
728 |
+
|
729 |
+
global $wp_cerber;
|
730 |
+
$wp_cerber = get_wp_cerber();
|
731 |
+
|
732 |
+
cerber_beast();
|
733 |
+
|
734 |
+
$antibot = cerber_antibot_gene();
|
735 |
+
if ( $antibot && ! empty( $antibot[1] ) ) {
|
736 |
+
foreach ( $antibot[1] as $item ) {
|
737 |
+
setcookie( $item[0], $item[1], time() + 3600, COOKIEPATH );
|
738 |
+
}
|
739 |
+
}
|
740 |
+
|
741 |
+
//global $wp_cerber;
|
742 |
+
//$wp_cerber = get_wp_cerber();
|
743 |
+
|
744 |
+
// Redirection control: no default aliases for redirections
|
745 |
+
if ( crb_get_settings( 'noredirect' ) ) {
|
746 |
+
remove_action( 'template_redirect', 'wp_redirect_admin_locations', 1000 );
|
747 |
+
}
|
748 |
+
|
749 |
+
$done = true;
|
750 |
+
}
|
751 |
+
|
752 |
+
/**
|
753 |
+
* Returns correct WP_Cerber object
|
754 |
+
* Protects and sets global $wp_cerber to the proper object
|
755 |
+
*
|
756 |
+
* @return WP_Cerber
|
757 |
+
* @since 6.0
|
758 |
+
*/
|
759 |
+
function get_wp_cerber(){
|
760 |
+
global $wp_cerber;
|
761 |
+
static $the_wp_cerber = null;
|
762 |
+
|
763 |
+
if ( ! isset( $the_wp_cerber ) ) {
|
764 |
+
$the_wp_cerber = new WP_Cerber();
|
765 |
+
}
|
766 |
+
|
767 |
+
$wp_cerber = $the_wp_cerber;
|
768 |
+
|
769 |
+
return $the_wp_cerber;
|
770 |
+
}
|
771 |
+
|
772 |
+
/**
|
773 |
+
*
|
774 |
+
* Initialize Cerber Security
|
775 |
+
*
|
776 |
+
*/
|
777 |
+
add_action( 'plugins_loaded', function () {
|
778 |
+
|
779 |
+
get_wp_cerber();
|
780 |
+
|
781 |
+
load_plugin_textdomain( 'wp-cerber', false, basename( dirname( __FILE__ ) ) . '/languages' );
|
782 |
+
|
783 |
+
/* @since 5.8.8
|
784 |
+
if ( ! cerber_check_groove() && ! cerber_is_allowed() ) {
|
785 |
+
wp_clear_auth_cookie();
|
786 |
+
}*/
|
787 |
+
|
788 |
+
cerber_init_cron();
|
789 |
+
|
790 |
+
__('> > > Translator of WP Cerber? To get the PRO license for free, drop your contacts here: https://wpcerber.com/contact/','wp-cerber');
|
791 |
+
|
792 |
+
}, 1000 );
|
793 |
+
|
794 |
+
/**
|
795 |
+
* Some additional tasks...
|
796 |
+
*
|
797 |
+
*/
|
798 |
+
add_action( 'shutdown', function () {
|
799 |
+
global $wpdb, $wp_cerber, $cerber_logged, $cerber_status;
|
800 |
+
|
801 |
+
if ( empty( $cerber_logged ) ) {
|
802 |
+
return;
|
803 |
+
}
|
804 |
+
|
805 |
+
// Multiple different malicious activities
|
806 |
+
$black = crb_get_activity_set('black');
|
807 |
+
$no_good = array_intersect( $black, $cerber_logged );
|
808 |
+
if ( ! empty( $no_good ) && cerber_is_allowed() ) {
|
809 |
+
$ip = $wp_cerber->getRemoteIp();
|
810 |
+
$in = implode( ',', $black );
|
811 |
+
$range = time() - 600;
|
812 |
+
$count = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_LOG_TABLE . ' WHERE ip = "' . $ip . '" AND activity IN (' . $in . ') AND stamp > ' . $range );
|
813 |
+
if ( $count >= 3 ) {
|
814 |
+
cerber_soft_block_add( $ip, 7 );
|
815 |
+
$cerber_status = 18;
|
816 |
+
}
|
817 |
+
}
|
818 |
+
|
819 |
+
} );
|
820 |
+
|
821 |
+
/*
|
822 |
+
Display login form if Custom login URL has been requested
|
823 |
+
|
824 |
+
*/
|
825 |
+
add_action( 'init', 'cerber_wp_login_page', 20 );
|
826 |
+
//add_action( 'setup_theme', 'cerber_wp_login_page' ); // @since 5.05
|
827 |
+
function cerber_wp_login_page() {
|
828 |
+
if ( $path = crb_get_settings( 'loginpath' ) ) {
|
829 |
+
if ( cerber_is_login_request() ) {
|
830 |
+
if ( ! defined( 'DONOTCACHEPAGE' ) ) {
|
831 |
+
define( 'DONOTCACHEPAGE', true ); // @since 5.7.6
|
832 |
+
}
|
833 |
+
require( ABSPATH . WP_LOGIN_SCRIPT ); // load default wp-login.php form
|
834 |
+
exit;
|
835 |
+
}
|
836 |
+
}
|
837 |
+
}
|
838 |
+
|
839 |
+
/**
|
840 |
+
* Check if the current HTTP request is a login/register/lost password page request
|
841 |
+
*
|
842 |
+
* @return bool
|
843 |
+
*/
|
844 |
+
function cerber_is_login_request() {
|
845 |
+
if ( $path = crb_get_settings( 'loginpath' ) ) {
|
846 |
+
$request = $_SERVER['REQUEST_URI'];
|
847 |
+
if ( $pos = strpos( $request, '?' ) ) {
|
848 |
+
$request = substr( $request, 0, $pos - 1 ); // @since 4.8
|
849 |
+
}
|
850 |
+
$request = explode( '/', rtrim( $request, '/' ) );
|
851 |
+
$request = end( $request ); // @since 4.8
|
852 |
+
if ( $path == $request && ! cerber_is_rest_url() ) {
|
853 |
+
return true;
|
854 |
+
}
|
855 |
+
}
|
856 |
+
//elseif ( strtolower( cerber_parse_uri( true ) ) == WP_LOGIN_SCRIPT ) {
|
857 |
+
elseif ( cerber_get_uri_script() == WP_LOGIN_SCRIPT ) {
|
858 |
+
return true;
|
859 |
+
}
|
860 |
+
|
861 |
+
return false;
|
862 |
+
}
|
863 |
+
|
864 |
+
/*
|
865 |
+
Create message to show it above login form for any simply GET
|
866 |
+
*/
|
867 |
+
add_action( 'login_head', 'cerber_login_head' );
|
868 |
+
function cerber_login_head() {
|
869 |
+
global $error, $wp_cerber;
|
870 |
+
|
871 |
+
if ( !$allowed = cerber_is_allowed() ) :
|
872 |
+
?>
|
873 |
+
<style type="text/css" media="all">
|
874 |
+
#logidnform {
|
875 |
+
display: none;
|
876 |
+
}
|
877 |
+
</style>
|
878 |
+
<?php
|
879 |
+
endif;
|
880 |
+
|
881 |
+
$wp_cerber->reCaptcha( 'style' );
|
882 |
+
|
883 |
+
if ( !cerber_is_http_get() ) {
|
884 |
+
return;
|
885 |
+
}
|
886 |
+
if ( ! cerber_can_msg() ) {
|
887 |
+
return;
|
888 |
+
}
|
889 |
+
if ( ! $allowed ) {
|
890 |
+
$error = $wp_cerber->getErrorMsg();
|
891 |
+
}
|
892 |
+
elseif ( $msg = $wp_cerber->getRemainMsg() ) {
|
893 |
+
$error = $msg;
|
894 |
+
}
|
895 |
+
}
|
896 |
+
|
897 |
+
/**
|
898 |
+
* Control the process of authentication
|
899 |
+
*
|
900 |
+
* @since 2.9
|
901 |
+
*
|
902 |
+
*/
|
903 |
+
remove_filter( 'authenticate', 'wp_authenticate_username_password', 20 );
|
904 |
+
remove_filter( 'authenticate', 'wp_authenticate_email_password', 20 );
|
905 |
+
add_filter( 'authenticate', 'cerber_auth_control', 20, 3 );
|
906 |
+
function cerber_auth_control( $user, $username, $password ) {
|
907 |
+
global $wp_cerber;
|
908 |
+
|
909 |
+
if ( ! $wp_cerber->reCaptchaValidate() ) {
|
910 |
+
|
911 |
+
return new WP_Error( 'incorrect_recaptcha',
|
912 |
+
'<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
|
913 |
+
$wp_cerber->reCaptchaMsg('login'));
|
914 |
+
}
|
915 |
+
|
916 |
+
// Check for prohibited username
|
917 |
+
//if ( $wp_cerber->isProhibited( $username ) ) {
|
918 |
+
if ( cerber_is_prohibited( $username ) ) {
|
919 |
+
cerber_log( 52, $username );
|
920 |
+
cerber_block_add( null, 4, $username );
|
921 |
+
|
922 |
+
// Create with message that is identical default WP
|
923 |
+
return new WP_Error( 'incorrect_password', sprintf(
|
924 |
+
__( '<strong>ERROR</strong>: The password you entered for the username %s is incorrect.' ),
|
925 |
+
'<strong>' . $username . '</strong>'
|
926 |
+
) );
|
927 |
+
}
|
928 |
+
/*
|
929 |
+
if ( lab_is_blocked($wp_cerber->getRemoteIp()) ) {
|
930 |
+
|
931 |
+
// Create with message which is identical default WP
|
932 |
+
return new WP_Error( 'incorrect_password', sprintf(
|
933 |
+
__( '<strong>ERROR</strong>: The password you entered for the username %s is incorrect.' ),
|
934 |
+
'<strong>' . $username . '</strong>'
|
935 |
+
) );
|
936 |
+
}*/
|
937 |
+
|
938 |
+
$user = wp_authenticate_username_password( $user, $username, $password );
|
939 |
+
$user = wp_authenticate_email_password( $user, $username, $password );
|
940 |
+
|
941 |
+
// @since 4.18 it is replacement for 'wp_login_failed' action hook
|
942 |
+
// see WP function wp_authenticate()
|
943 |
+
$ignore_codes = array( 'empty_username', 'empty_password', 'cerber_denied' );
|
944 |
+
if ( is_wp_error( $user ) && ! in_array( $user->get_error_code(), $ignore_codes ) ) {
|
945 |
+
cerber_login_failed( $username );
|
946 |
+
}
|
947 |
+
|
948 |
+
return $user;
|
949 |
+
}
|
950 |
+
|
951 |
+
/*
|
952 |
+
Block authentication for an existing user if the remote IP is not allowed.
|
953 |
+
Invoking in the 'wp_authenticate_username_password()'
|
954 |
+
*/
|
955 |
+
add_filter( 'wp_authenticate_user', 'cerber_stop_authentication', 9999, 2 ); // fires after user found, with 'authenticate' filter
|
956 |
+
function cerber_stop_authentication( $user, $password ) {
|
957 |
+
global $wp_cerber, $cerber_status;
|
958 |
+
|
959 |
+
$deny = false;
|
960 |
+
|
961 |
+
if ( ! cerber_is_allowed() ) {
|
962 |
+
$deny = true;
|
963 |
+
}
|
964 |
+
elseif ( ! cerber_geo_allowed( 'geo_login' ) ) {
|
965 |
+
$cerber_status = 16;
|
966 |
+
$deny = true;
|
967 |
+
}
|
968 |
+
elseif ( lab_is_blocked( $wp_cerber->getRemoteIp() ) ) {
|
969 |
+
$cerber_status = 15;
|
970 |
+
$deny = true;
|
971 |
+
}
|
972 |
+
|
973 |
+
if ( $deny ) {
|
974 |
+
status_header( 403 );
|
975 |
+
$error = new WP_Error();
|
976 |
+
$error->add( 'cerber_wp_error', $wp_cerber->getErrorMsg() );
|
977 |
+
|
978 |
+
return $error;
|
979 |
+
}
|
980 |
+
|
981 |
+
return $user;
|
982 |
+
}
|
983 |
+
|
984 |
+
/*
|
985 |
+
* Handler for failed login attempts
|
986 |
+
*
|
987 |
+
*/
|
988 |
+
//add_action( 'wp_login_failed', 'cerber_login_failed' ); // @since 4.18
|
989 |
+
function cerber_login_failed( $user_login ) {
|
990 |
+
global $wpdb, $wp_cerber, $cerber_status;
|
991 |
+
static $is_processed = false;
|
992 |
+
|
993 |
+
if ( $is_processed ) return;
|
994 |
+
$is_processed = true;
|
995 |
+
|
996 |
+
$ip = $wp_cerber->getRemoteIp();
|
997 |
+
$acl = cerber_acl_check( $ip );
|
998 |
+
if ( ! cerber_get_user( $user_login ) ) {
|
999 |
+
$no_user = true;
|
1000 |
+
}
|
1001 |
+
else {
|
1002 |
+
$no_user = false;
|
1003 |
+
}
|
1004 |
+
|
1005 |
+
//cerber_failed_work($ip, $acl, $no_user, $user_login);
|
1006 |
+
|
1007 |
+
//if ( ! $wp_cerber->isProcessed() ) {
|
1008 |
+
//if ( ! cerber_get_user( $user_login ) ) {
|
1009 |
+
// $no_user = true;
|
1010 |
+
//}
|
1011 |
+
|
1012 |
+
$ac = 7;
|
1013 |
+
|
1014 |
+
if ( $no_user ) {
|
1015 |
+
$ac = 51;
|
1016 |
+
}
|
1017 |
+
elseif ( ! cerber_is_allowed( $ip ) || $cerber_status == 15 || $cerber_status == 16 ) { // TODO should be refactored together with cerber_stop_authentication
|
1018 |
+
$ac = 53;
|
1019 |
+
}
|
1020 |
+
/*
|
1021 |
+
elseif ( $acl == 'B' ) {
|
1022 |
+
$ac = 14;
|
1023 |
+
}
|
1024 |
+
elseif ( lab_is_blocked($ip, false) ) {
|
1025 |
+
$ac = 53;
|
1026 |
+
}
|
1027 |
+
else {
|
1028 |
+
$ac = 53;
|
1029 |
+
}*/
|
1030 |
+
|
1031 |
+
cerber_log( $ac, $user_login );
|
1032 |
+
|
1033 |
+
//}
|
1034 |
+
|
1035 |
+
|
1036 |
+
// White? Stop further actions.
|
1037 |
+
if ( $acl == 'W' && !crb_get_settings( 'limitwhite' )) {
|
1038 |
+
return;
|
1039 |
+
}
|
1040 |
+
|
1041 |
+
if ( crb_get_settings( 'usefile' ) ) {
|
1042 |
+
cerber_file_log( $user_login, $ip );
|
1043 |
+
}
|
1044 |
+
|
1045 |
+
if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) { // Needs additional researching and, maybe, refactoring
|
1046 |
+
status_header( 403 );
|
1047 |
+
}
|
1048 |
+
|
1049 |
+
// Blacklisted? No more actions are needed.
|
1050 |
+
if ( $acl == 'B' ) {
|
1051 |
+
return;
|
1052 |
+
}
|
1053 |
+
|
1054 |
+
// Must the Citadel mode be activated?
|
1055 |
+
if ( $wp_cerber->getSettings( 'ciperiod' ) && ! cerber_is_citadel() ) {
|
1056 |
+
$range = time() - $wp_cerber->getSettings( 'ciperiod' ) * 60;
|
1057 |
+
$lockouts = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_LOG_TABLE . ' WHERE activity IN (7,51,52) AND stamp > ' . $range );
|
1058 |
+
if ( $lockouts >= $wp_cerber->getSettings( 'cilimit' ) ) {
|
1059 |
+
cerber_enable_citadel();
|
1060 |
+
}
|
1061 |
+
}
|
1062 |
+
|
1063 |
+
if ( $no_user && $wp_cerber->getSettings( 'nonusers' ) ) {
|
1064 |
+
cerber_block_add( $ip, 3, $user_login); // @since 5.7
|
1065 |
+
}
|
1066 |
+
elseif ( cerber_get_remain_count($ip, false) < 1 ) { //Limit on the number of login attempts is reached
|
1067 |
+
cerber_block_add( $ip, 1, '', null, false);
|
1068 |
+
}
|
1069 |
+
|
1070 |
+
}
|
1071 |
+
|
1072 |
+
/**
|
1073 |
+
* Do the work with failed/blocked attempt
|
1074 |
+
*
|
1075 |
+
* @param $ip
|
1076 |
+
* @param $acl
|
1077 |
+
* @param $user_login
|
1078 |
+
*/
|
1079 |
+
function cerber_failed_work($ip, $acl, $no_user, $user_login){
|
1080 |
+
global $wpdb, $wp_cerber;
|
1081 |
+
|
1082 |
+
// White? Stop further actions.
|
1083 |
+
if ( $acl == 'W' && !$wp_cerber->getSettings( 'limitwhite' )) {
|
1084 |
+
return;
|
1085 |
+
}
|
1086 |
+
|
1087 |
+
if ( $wp_cerber->getSettings( 'usefile' ) ) {
|
1088 |
+
cerber_file_log( $user_login, $ip );
|
1089 |
+
}
|
1090 |
+
|
1091 |
+
if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) { // Needs additional researching and, maybe, refactoring
|
1092 |
+
status_header( 403 );
|
1093 |
+
}
|
1094 |
+
|
1095 |
+
// Blacklisted? No more actions are needed.
|
1096 |
+
if ( $acl == 'B' ) {
|
1097 |
+
return;
|
1098 |
+
}
|
1099 |
+
|
1100 |
+
// Must the Citadel mode be activated?
|
1101 |
+
if ( $wp_cerber->getSettings( 'ciperiod' ) && ! cerber_is_citadel() ) {
|
1102 |
+
$range = time() - $wp_cerber->getSettings( 'ciperiod' ) * 60;
|
1103 |
+
$lockouts = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_LOG_TABLE . ' WHERE activity IN (7,51,52) AND stamp > ' . $range );
|
1104 |
+
if ( $lockouts >= $wp_cerber->getSettings( 'cilimit' ) ) {
|
1105 |
+
cerber_enable_citadel();
|
1106 |
+
}
|
1107 |
+
}
|
1108 |
+
|
1109 |
+
if ( $no_user && $wp_cerber->getSettings( 'nonusers' ) ) {
|
1110 |
+
cerber_block_add( $ip, 3, $user_login );
|
1111 |
+
}
|
1112 |
+
elseif ( cerber_get_remain_count($ip, false) <= 1 ) { //Limit on the number of login attempts is reached
|
1113 |
+
cerber_block_add( $ip, 1, '', null, false);
|
1114 |
+
}
|
1115 |
+
}
|
1116 |
+
|
1117 |
+
// Registration -----------------------------------------------------------------------
|
1118 |
+
|
1119 |
+
function cerber_is_registration_prohibited( $sanitized_user_login ) {
|
1120 |
+
global $wp_cerber, $cerber_status;
|
1121 |
+
|
1122 |
+
$code = null;
|
1123 |
+
$msg = null;
|
1124 |
+
|
1125 |
+
if (crb_is_reg_limit_reached()){
|
1126 |
+
$cerber_status = 17;
|
1127 |
+
cerber_log(54);
|
1128 |
+
$code = 'ip_denied';
|
1129 |
+
$msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
|
1130 |
+
apply_filters( 'cerber_msg_denied', __( 'You are not allowed to register.', 'wp-cerber' ), 'register' );
|
1131 |
+
}
|
1132 |
+
elseif ( cerber_is_bot('botsreg') ) {
|
1133 |
+
cerber_log(54); // TODO should be separate code to detect bot activity?
|
1134 |
+
$code = 'bot_detected';
|
1135 |
+
$msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
|
1136 |
+
apply_filters( 'cerber_msg_denied', __( 'You are not allowed to register.', 'wp-cerber' ), 'register' );
|
1137 |
+
}
|
1138 |
+
elseif ( ! $wp_cerber->reCaptchaValidate() ) {
|
1139 |
+
$code = 'incorrect_recaptcha';
|
1140 |
+
$msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
|
1141 |
+
$wp_cerber->reCaptchaMsg('register');
|
1142 |
+
}
|
1143 |
+
elseif ( cerber_is_prohibited( $sanitized_user_login ) ) {
|
1144 |
+
$code = 'prohibited_login';
|
1145 |
+
$msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
|
1146 |
+
apply_filters( 'cerber_msg_prohibited', __( 'Username is not allowed. Please choose another one.', 'wp-cerber' ), 'register' );
|
1147 |
+
}
|
1148 |
+
elseif ( !cerber_is_allowed() || lab_is_blocked($wp_cerber->getRemoteIp()) ) {
|
1149 |
+
cerber_log(54);
|
1150 |
+
$code = 'ip_denied';
|
1151 |
+
$msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
|
1152 |
+
apply_filters( 'cerber_msg_denied', __( 'You are not allowed to register.', 'wp-cerber' ), 'register' );
|
1153 |
+
}
|
1154 |
+
elseif ( ! cerber_geo_allowed( 'geo_register' ) ) {
|
1155 |
+
$cerber_status = 16; // TODO: refactor cerber_log, include this status as a second parameter
|
1156 |
+
cerber_log(54); // TODO should be separate code?
|
1157 |
+
$code = 'country_denied';
|
1158 |
+
$msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
|
1159 |
+
apply_filters( 'cerber_msg_denied', __( 'You are not allowed to register.', 'wp-cerber' ), 'register' );
|
1160 |
+
}
|
1161 |
+
|
1162 |
+
if ( $code ) {
|
1163 |
+
return array( $code, $msg );
|
1164 |
+
}
|
1165 |
+
|
1166 |
+
return null;
|
1167 |
+
}
|
1168 |
+
|
1169 |
+
/**
|
1170 |
+
* Limit on user registrations per IP
|
1171 |
+
*
|
1172 |
+
* @return bool
|
1173 |
+
*/
|
1174 |
+
function crb_is_reg_limit_reached() {
|
1175 |
+
global $wpdb, $wp_cerber;
|
1176 |
+
|
1177 |
+
if ( ! $wp_cerber->getSettings( 'reglimit_min' ) || ! $wp_cerber->getSettings( 'reglimit_num' ) ) {
|
1178 |
+
return false;
|
1179 |
+
}
|
1180 |
+
|
1181 |
+
if ( crb_acl_is_white() ) {
|
1182 |
+
return false;
|
1183 |
+
}
|
1184 |
+
|
1185 |
+
$ip = $wp_cerber->getRemoteIp();
|
1186 |
+
$stamp = absint( time() - 60 * $wp_cerber->getSettings( 'reglimit_min' ) );
|
1187 |
+
$count = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_LOG_TABLE . ' WHERE ip = "' . $ip . '" AND activity = 2 AND stamp > ' . $stamp );
|
1188 |
+
if ( $count > $wp_cerber->getSettings( 'reglimit_num' ) ) {
|
1189 |
+
lab_save_push( $ip, 344, '' );
|
1190 |
+
return true;
|
1191 |
+
}
|
1192 |
+
|
1193 |
+
return false;
|
1194 |
+
}
|
1195 |
+
|
1196 |
+
// Fires in register_new_user()
|
1197 |
+
add_filter( 'registration_errors', 'cerber_pre_new_user', 10, 3 );
|
1198 |
+
function cerber_pre_new_user( $errors, $sanitized_user_login, $user_email ) {
|
1199 |
+
global $wp_cerber, $cerber_status;
|
1200 |
+
|
1201 |
+
$prohibited = cerber_is_registration_prohibited( $sanitized_user_login );
|
1202 |
+
|
1203 |
+
if ($prohibited){
|
1204 |
+
return new WP_Error($prohibited[0], $prohibited[1]);
|
1205 |
+
}
|
1206 |
+
|
1207 |
+
return $errors;
|
1208 |
+
}
|
1209 |
+
|
1210 |
+
// @since 5.3
|
1211 |
+
// Fires in wp_insert_user()
|
1212 |
+
add_filter( 'pre_user_login', function ( $sanitized_user_login ) {
|
1213 |
+
|
1214 |
+
if ( cerber_is_registration_prohibited( $sanitized_user_login ) ) {
|
1215 |
+
return null;
|
1216 |
+
}
|
1217 |
+
|
1218 |
+
/*
|
1219 |
+
if ( ! cerber_is_allowed() ) {
|
1220 |
+
cerber_log( 54 );
|
1221 |
+
|
1222 |
+
return null;
|
1223 |
+
}
|
1224 |
+
if ( ! cerber_geo_allowed( 'geo_register' ) ) {
|
1225 |
+
$cerber_status = 16;
|
1226 |
+
cerber_log( 54 );
|
1227 |
+
|
1228 |
+
return null;
|
1229 |
+
}
|
1230 |
+
*/
|
1231 |
+
return $sanitized_user_login;
|
1232 |
+
}, 9999 );
|
1233 |
+
|
1234 |
+
// Filter out prohibited usernames
|
1235 |
+
add_filter( 'illegal_user_logins', function () {
|
1236 |
+
return (array) crb_get_settings( 'prohibited' );
|
1237 |
+
}, 9999 );
|
1238 |
+
|
1239 |
+
add_filter( 'option_users_can_register', function ( $value ) {
|
1240 |
+
//if ( ! cerber_is_allowed() || !cerber_geo_allowed( 'geo_register' )) {
|
1241 |
+
if ( ! cerber_is_allowed() || crb_is_reg_limit_reached() ) {
|
1242 |
+
return false;
|
1243 |
+
}
|
1244 |
+
|
1245 |
+
return $value;
|
1246 |
+
}, 9999 );
|
1247 |
+
|
1248 |
+
// Lost password form --------------------------------------------------------------------
|
1249 |
+
|
1250 |
+
/**
|
1251 |
+
* Validate reCAPTCHA for the WordPress lost password form
|
1252 |
+
*/
|
1253 |
+
add_action( 'login_form_' . 'lostpassword', 'cerber_lost_captcha' );
|
1254 |
+
function cerber_lost_captcha() {
|
1255 |
+
global $wp_cerber, $cerber_lost;
|
1256 |
+
if ( ! $wp_cerber->reCaptchaValidate() ) {
|
1257 |
+
$_POST['user_login'] = null; // workaround due to lack of any way to control lost password form
|
1258 |
+
$cerber_lost = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' . $wp_cerber->reCaptchaMsg('lostpassword');
|
1259 |
+
}
|
1260 |
+
}
|
1261 |
+
/**
|
1262 |
+
* Display message on the WordPress lost password form screen
|
1263 |
+
*/
|
1264 |
+
add_action( 'lostpassword_form', 'cerber_lost_show_msg' );
|
1265 |
+
function cerber_lost_show_msg() {
|
1266 |
+
global $cerber_lost;
|
1267 |
+
if ( ! $cerber_lost ) {
|
1268 |
+
return;
|
1269 |
+
}
|
1270 |
+
?>
|
1271 |
+
<script type="text/javascript">
|
1272 |
+
//document.getElementById('login_error').style.visibility = "hidden";
|
1273 |
+
document.getElementById('login_error').innerHTML = "<?php echo $cerber_lost; ?>";
|
1274 |
+
</script>
|
1275 |
+
<?php
|
1276 |
+
}
|
1277 |
+
|
1278 |
+
|
1279 |
+
// Comments (commenting) section ----------------------------------------------------------
|
1280 |
+
|
1281 |
+
/**
|
1282 |
+
* If a comment must be marked as spam
|
1283 |
+
*
|
1284 |
+
*/
|
1285 |
+
add_filter( 'pre_comment_approved', function ( $approved, $commentdata ) {
|
1286 |
+
if ( 1 == crb_get_settings( 'spamcomm' ) && ! cerber_is_comment_allowed() ) {
|
1287 |
+
$approved = 'spam';
|
1288 |
+
}
|
1289 |
+
|
1290 |
+
return $approved;
|
1291 |
+
}, 10, 2 );
|
1292 |
+
|
1293 |
+
/**
|
1294 |
+
* If a comment must be denied
|
1295 |
+
*
|
1296 |
+
*/
|
1297 |
+
add_action( 'pre_comment_on_post', function ( $comment_post_ID ) {
|
1298 |
+
global $cerber_status;
|
1299 |
+
|
1300 |
+
$deny = false;
|
1301 |
+
|
1302 |
+
if ( 1 != crb_get_settings( 'spamcomm' ) && ! cerber_is_comment_allowed() ) {
|
1303 |
+
$deny = true;
|
1304 |
+
}
|
1305 |
+
elseif ( ! cerber_geo_allowed( 'geo_comment' ) ) {
|
1306 |
+
$cerber_status = 16;
|
1307 |
+
cerber_log(19);
|
1308 |
+
$deny = true;
|
1309 |
+
}
|
1310 |
+
|
1311 |
+
if ( $deny ) {
|
1312 |
+
setcookie( 'cerber-post-id', $comment_post_ID, time() + 60, '/' );
|
1313 |
+
$comments = get_comments( array( 'number' => '1', 'post_id' => $comment_post_ID ) );
|
1314 |
+
if ( $comments ) {
|
1315 |
+
$loc = get_comment_link( $comments[0]->comment_ID );
|
1316 |
+
} else {
|
1317 |
+
$loc = get_permalink( $comment_post_ID ) . '#cerber-recaptcha-msg';
|
1318 |
+
}
|
1319 |
+
wp_safe_redirect( $loc );
|
1320 |
+
exit;
|
1321 |
+
}
|
1322 |
+
|
1323 |
+
} );
|
1324 |
+
|
1325 |
+
/**
|
1326 |
+
* If submit comments via REST API is not allowed
|
1327 |
+
*
|
1328 |
+
*/
|
1329 |
+
add_filter( 'rest_allow_anonymous_comments', function ( $allowed, $request ) {
|
1330 |
+
global $wp_cerber, $cerber_status;
|
1331 |
+
|
1332 |
+
if ( ! cerber_is_allowed() ) {
|
1333 |
+
$allowed = false;
|
1334 |
+
}
|
1335 |
+
if ( ! cerber_geo_allowed( 'geo_comment' ) ) {
|
1336 |
+
ceber_log(19);
|
1337 |
+
$cerber_status = 16;
|
1338 |
+
$allowed = false;
|
1339 |
+
}
|
1340 |
+
elseif ( lab_is_blocked( $wp_cerber->getRemoteIp() ) ) {
|
1341 |
+
$allowed = false;
|
1342 |
+
}
|
1343 |
+
|
1344 |
+
return $allowed;
|
1345 |
+
}, 10, 2 );
|
1346 |
+
|
1347 |
+
/**
|
1348 |
+
* Check if a submitted comment is allowed
|
1349 |
+
*
|
1350 |
+
* @return bool
|
1351 |
+
*/
|
1352 |
+
function cerber_is_comment_allowed(){
|
1353 |
+
global $wp_cerber;
|
1354 |
+
|
1355 |
+
if (is_admin()) return true;
|
1356 |
+
|
1357 |
+
$deny = null;
|
1358 |
+
|
1359 |
+
if ( ! cerber_is_allowed() ) {
|
1360 |
+
$deny = 19;
|
1361 |
+
}
|
1362 |
+
elseif ( cerber_is_bot('botscomm') ) {
|
1363 |
+
$remain = cerber_get_remain_count( null , true, 16, 3, 60);
|
1364 |
+
if ($remain < 1) cerber_block_add( null, 6, '', 60 );
|
1365 |
+
$deny = 16;
|
1366 |
+
}
|
1367 |
+
elseif ( ! $wp_cerber->reCaptchaValidate( 'comment' , true ) ) {
|
1368 |
+
$deny = 16;
|
1369 |
+
}
|
1370 |
+
elseif ( lab_is_blocked( $wp_cerber->getRemoteIp() ) ) {
|
1371 |
+
$deny = 19;
|
1372 |
+
}
|
1373 |
+
|
1374 |
+
if ( $deny ) {
|
1375 |
+
cerber_log( $deny );
|
1376 |
+
$ret = false;
|
1377 |
+
}
|
1378 |
+
else {
|
1379 |
+
$ret = true;
|
1380 |
+
}
|
1381 |
+
|
1382 |
+
return $ret;
|
1383 |
+
}
|
1384 |
+
|
1385 |
+
/**
|
1386 |
+
* Showing reCAPTCHA widget.
|
1387 |
+
* Displaying error message on the comment form for a human.
|
1388 |
+
*
|
1389 |
+
*/
|
1390 |
+
add_filter( 'comment_form_submit_field', function ( $value ) {
|
1391 |
+
global $wp_cerber, $post;
|
1392 |
+
|
1393 |
+
if ( ! empty( $_COOKIE["cerber-post-id"] ) && absint( $_COOKIE["cerber-post-id"] ) == $post->ID ) {
|
1394 |
+
//echo '<div id="cerber-recaptcha-msg">' . __( 'ERROR:', 'wp-cerber' ) . ' ' . $wp_cerber->reCaptchaMsg( 'comment' ) . '</div>';
|
1395 |
+
echo '<div id="cerber-recaptcha-msg">' . __( 'ERROR:', 'wp-cerber' ) . ' ' . __('Sorry, human verification failed.') . '</div>';
|
1396 |
+
echo '<script type="text/javascript">document.cookie = "cerber-post-id=0;path=/";</script>';
|
1397 |
+
}
|
1398 |
+
|
1399 |
+
$au = $wp_cerber->getSettings( 'recapcomauth' );
|
1400 |
+
if ( ! $au || ( $au && ! is_user_logged_in() ) ) {
|
1401 |
+
$wp_cerber->reCaptcha( 'widget', 'recapcom' );
|
1402 |
+
}
|
1403 |
+
|
1404 |
+
return $value;
|
1405 |
+
} );
|
1406 |
+
|
1407 |
+
|
1408 |
+
// Messages ----------------------------------------------------------------------
|
1409 |
+
|
1410 |
+
/**
|
1411 |
+
* Replace ANY system messages or add notify message above login form if IP is not allowed (blocked or locked out)
|
1412 |
+
*/
|
1413 |
+
add_filter( 'login_errors', 'cerber_login_form_msg' ); // hook on POST if credentials was wrong
|
1414 |
+
function cerber_login_form_msg( $errors ) {
|
1415 |
+
global $error, $wp_cerber;
|
1416 |
+
if ( cerber_can_msg() ) {
|
1417 |
+
if ( ! cerber_is_allowed() ) {
|
1418 |
+
$errors = $wp_cerber->getErrorMsg();
|
1419 |
+
}
|
1420 |
+
elseif ( ! $error && ( $msg = $wp_cerber->getRemainMsg() ) ) {
|
1421 |
+
$errors .= '<p>' . $msg;
|
1422 |
+
}
|
1423 |
+
}
|
1424 |
+
|
1425 |
+
return $errors;
|
1426 |
+
}
|
1427 |
+
|
1428 |
+
add_filter( 'shake_error_codes', 'cerber_login_failure_shake' ); // Shake it, baby!
|
1429 |
+
function cerber_login_failure_shake( $shake_error_codes ) {
|
1430 |
+
$shake_error_codes[] = 'cerber_wp_error';
|
1431 |
+
|
1432 |
+
return $shake_error_codes;
|
1433 |
+
}
|
1434 |
+
|
1435 |
+
/*
|
1436 |
+
Replace default login/logout URL with Custom login page URL
|
1437 |
+
*/
|
1438 |
+
add_filter( 'site_url', 'cerber_login_logout', 9999, 4 );
|
1439 |
+
add_filter( 'network_site_url', 'cerber_login_logout', 9999, 3 );
|
1440 |
+
function cerber_login_logout( $url, $path, $scheme, $blog_id = 0 ) { // $blog_id only for 'site_url'
|
1441 |
+
global $wp_cerber;
|
1442 |
+
if ( $login_path = $wp_cerber->getSettings( 'loginpath' ) ) {
|
1443 |
+
$url = str_replace( WP_LOGIN_SCRIPT, $login_path . '/', $url );
|
1444 |
+
}
|
1445 |
+
|
1446 |
+
return $url;
|
1447 |
+
}
|
1448 |
+
|
1449 |
+
/*
|
1450 |
+
Replace default logout redirect URL with Custom login page URL
|
1451 |
+
*/
|
1452 |
+
add_filter( 'wp_redirect', 'cerber_login_redirect', 9999, 2 );
|
1453 |
+
function cerber_login_redirect( $location, $status ) {
|
1454 |
+
global $wp_cerber;
|
1455 |
+
if ( ($path = $wp_cerber->getSettings( 'loginpath' )) && ( 0 === strpos( $location, WP_LOGIN_SCRIPT . '?' ) ) ) {
|
1456 |
+
$loc = explode( '?', $location );
|
1457 |
+
$location = get_home_url() . '/' . $path . '/?' . $loc[1];
|
1458 |
+
}
|
1459 |
+
|
1460 |
+
return $location;
|
1461 |
+
}
|
1462 |
+
|
1463 |
+
// Access control ========================================================================================
|
1464 |
+
|
1465 |
+
add_action( 'init', function () {
|
1466 |
+
if ( crb_get_settings( 'adminphp' ) && ! is_user_logged_in() ) {
|
1467 |
+
define( 'CONCATENATE_SCRIPTS', false );
|
1468 |
+
}
|
1469 |
+
cerber_access_control();
|
1470 |
+
cerber_antibot_control();
|
1471 |
+
}, 0 );
|
1472 |
+
|
1473 |
+
/**
|
1474 |
+
* Restrict access to vital parts of WP
|
1475 |
+
*
|
1476 |
+
*/
|
1477 |
+
function cerber_access_control() {
|
1478 |
+
global $wp_cerber, $cerber_status;
|
1479 |
+
|
1480 |
+
if ( is_admin() ) {
|
1481 |
+
return;
|
1482 |
+
}
|
1483 |
+
|
1484 |
+
// IPs from the White List are allowed
|
1485 |
+
$acl = cerber_acl_check();
|
1486 |
+
if ( $acl == 'W' ) {
|
1487 |
+
return;
|
1488 |
+
}
|
1489 |
+
|
1490 |
+
//if ( $acl == 'B' || cerber_block_check() ) {
|
1491 |
+
if ( $acl == 'B' || !cerber_is_allowed() ) { // @since 5.8.2
|
1492 |
+
$deny = true;
|
1493 |
+
}
|
1494 |
+
else {
|
1495 |
+
$deny = false;
|
1496 |
+
}
|
1497 |
+
|
1498 |
+
//$opt = $wp_cerber->getSettings();
|
1499 |
+
$opt = crb_get_settings();
|
1500 |
+
/*
|
1501 |
+
$script = cerber_last_uri();
|
1502 |
+
if ( substr( $script, - 4 ) != '.php' ) {
|
1503 |
+
$script .= '.php'; // Apache MultiViews enabled?
|
1504 |
+
}
|
1505 |
+
|
1506 |
+
if ( $script ) {
|
1507 |
+
if ( $script == WP_LOGIN_SCRIPT || $script == WP_SIGNUP_SCRIPT || ( $script == WP_REG_URI && ! get_option( 'users_can_register' ) ) ) { // no direct access
|
1508 |
+
if ( !empty( $opt['wplogin'] ) ) {
|
1509 |
+
cerber_log( 50 );
|
1510 |
+
cerber_soft_block_add( $wp_cerber->getRemoteIp(), 2, $script );
|
1511 |
+
cerber_404_page();
|
1512 |
+
}
|
1513 |
+
if ( $deny || !empty( $opt['loginnowp'] ) ) {
|
1514 |
+
cerber_log( 50 );
|
1515 |
+
cerber_404_page();
|
1516 |
+
}
|
1517 |
+
}
|
1518 |
+
elseif ( $script == WP_XMLRPC_SCRIPT || $script == WP_TRACKBACK_SCRIPT ) { // no direct access
|
1519 |
+
if ( $deny || ! empty( $opt['xmlrpc'] ) ) {
|
1520 |
+
cerber_log( 50 ); // @since 5.21
|
1521 |
+
cerber_404_page();
|
1522 |
+
}
|
1523 |
+
elseif ( !cerber_geo_allowed( 'geo_xmlrpc' ) ) {
|
1524 |
+
$cerber_status = 16;
|
1525 |
+
cerber_log( 71 );
|
1526 |
+
cerber_404_page();
|
1527 |
+
}
|
1528 |
+
}
|
1529 |
+
}
|
1530 |
+
*/
|
1531 |
+
$wp_cerber = get_wp_cerber();
|
1532 |
+
if ( $wp_cerber->isURIProhibited() ) {
|
1533 |
+
cerber_404_page();
|
1534 |
+
}
|
1535 |
+
|
1536 |
+
// REST API
|
1537 |
+
if ( $deny ) {
|
1538 |
+
cerber_block_rest();
|
1539 |
+
}
|
1540 |
+
elseif ( cerber_is_rest_url() ) {
|
1541 |
+
$rest_allowed = true;
|
1542 |
+
if ( ! empty( $opt['norest'] ) ) {
|
1543 |
+
$rest_allowed = false;
|
1544 |
+
if ( $opt['restauth'] && is_user_logged_in() ) {
|
1545 |
+
$rest_allowed = true;
|
1546 |
+
}
|
1547 |
+
elseif ( cerber_is_route_allowed() ) {
|
1548 |
+
$rest_allowed = true;
|
1549 |
+
}
|
1550 |
+
}
|
1551 |
+
/*
|
1552 |
+
$rest_allowed = true;
|
1553 |
+
if ( ! empty( $opt['norest'] ) && ! cerber_is_route_allowed() ) {
|
1554 |
+
$rest_allowed = false;
|
1555 |
+
}*/
|
1556 |
+
if ( $rest_allowed && cerber_is_route_blocked() ) {
|
1557 |
+
$rest_allowed = false;
|
1558 |
+
}
|
1559 |
+
if ( $rest_allowed && ! cerber_geo_allowed( 'geo_restapi' ) ) {
|
1560 |
+
$rest_allowed = false;
|
1561 |
+
$cerber_status = 16;
|
1562 |
+
}
|
1563 |
+
if ( ! $rest_allowed ) {
|
1564 |
+
cerber_block_rest();
|
1565 |
+
}
|
1566 |
+
}
|
1567 |
+
|
1568 |
+
// Some XML-RPC stuff
|
1569 |
+
if ( $deny || ! empty( $opt['xmlrpc'] ) ) {
|
1570 |
+
add_filter( 'xmlrpc_enabled', '__return_false' );
|
1571 |
+
add_filter( 'pings_open', '__return_false' );
|
1572 |
+
add_filter( 'bloginfo_url', 'cerber_pingback_url', 10, 2 );
|
1573 |
+
remove_action( 'wp_head', 'rsd_link', 10 );
|
1574 |
+
remove_action( 'wp_head', 'wlwmanifest_link', 10 );
|
1575 |
+
}
|
1576 |
+
|
1577 |
+
// Feeds
|
1578 |
+
if ( $deny || ! empty( $opt['nofeeds'] ) ) {
|
1579 |
+
remove_action( 'wp_head', 'feed_links', 2 );
|
1580 |
+
remove_action( 'wp_head', 'feed_links_extra', 3 );
|
1581 |
+
|
1582 |
+
remove_action( 'do_feed_rdf', 'do_feed_rdf', 10 );
|
1583 |
+
remove_action( 'do_feed_rss', 'do_feed_rss', 10 );
|
1584 |
+
remove_action( 'do_feed_rss2', 'do_feed_rss2', 10 );
|
1585 |
+
remove_action( 'do_feed_atom', 'do_feed_atom', 10 );
|
1586 |
+
remove_action( 'do_pings', 'do_all_pings', 10 );
|
1587 |
+
|
1588 |
+
add_action( 'do_feed_rdf', 'cerber_404_page', 1 );
|
1589 |
+
add_action( 'do_feed_rss', 'cerber_404_page', 1 );
|
1590 |
+
add_action( 'do_feed_rss2', 'cerber_404_page', 1 );
|
1591 |
+
add_action( 'do_feed_atom', 'cerber_404_page', 1 );
|
1592 |
+
add_action( 'do_feed_rss2_comments', 'cerber_404_page', 1 );
|
1593 |
+
add_action( 'do_feed_atom_comments', 'cerber_404_page', 1 );
|
1594 |
+
}
|
1595 |
+
}
|
1596 |
+
|
1597 |
+
/**
|
1598 |
+
* Antispam & Antibot for forms
|
1599 |
+
*
|
1600 |
+
*/
|
1601 |
+
function cerber_antibot_control(){
|
1602 |
+
global $cerber_status;
|
1603 |
+
|
1604 |
+
if ( !cerber_is_http_post() || cerber_acl_check( null, 'W' ) ) {
|
1605 |
+
return;
|
1606 |
+
}
|
1607 |
+
|
1608 |
+
if ( !cerber_antibot_enabled('botsany') && !cerber_geo_rules('geo_submit')) {
|
1609 |
+
return;
|
1610 |
+
}
|
1611 |
+
|
1612 |
+
// Exceptions -----------------------------------------------------------------------
|
1613 |
+
|
1614 |
+
if ( cerber_is_antibot_exception() ) {
|
1615 |
+
return;
|
1616 |
+
}
|
1617 |
+
|
1618 |
+
// Let's make the checks
|
1619 |
+
|
1620 |
+
$deny = false;
|
1621 |
+
|
1622 |
+
if ( ! cerber_is_allowed() ) {
|
1623 |
+
$deny = true;
|
1624 |
+
cerber_log(18);
|
1625 |
+
}
|
1626 |
+
elseif ( cerber_is_bot( 'botsany' ) ) {
|
1627 |
+
$deny = true;
|
1628 |
+
cerber_log( 17 );
|
1629 |
+
}
|
1630 |
+
elseif ( !cerber_geo_allowed( 'geo_submit' ) ) {
|
1631 |
+
$deny = true;
|
1632 |
+
$cerber_status = 16; // TODO: refactor cerber_log, include this status as a second parameter
|
1633 |
+
cerber_log( 18 );
|
1634 |
+
}
|
1635 |
+
elseif ( lab_is_blocked( null, true ) ) {
|
1636 |
+
$deny = true;
|
1637 |
+
$cerber_status = 18;
|
1638 |
+
cerber_log( 18 );
|
1639 |
+
}
|
1640 |
+
|
1641 |
+
if ($deny){
|
1642 |
+
cerber_forbidden_page();
|
1643 |
+
}
|
1644 |
+
|
1645 |
+
}
|
1646 |
+
|
1647 |
+
/**
|
1648 |
+
* Exception for POST query control
|
1649 |
+
*
|
1650 |
+
* @return bool
|
1651 |
+
*/
|
1652 |
+
function cerber_is_antibot_exception(){
|
1653 |
+
|
1654 |
+
if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
|
1655 |
+
return true;
|
1656 |
+
}
|
1657 |
+
|
1658 |
+
// Admin || AJAX requests by unauthorized users
|
1659 |
+
if ( is_admin() ) {
|
1660 |
+
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
1661 |
+
if (is_user_logged_in()) {
|
1662 |
+
return true;
|
1663 |
+
}
|
1664 |
+
}
|
1665 |
+
else {
|
1666 |
+
return true;
|
1667 |
+
}
|
1668 |
+
}
|
1669 |
+
|
1670 |
+
// Standard WordPress Comments
|
1671 |
+
if ( 0 === strpos( trim( $_SERVER['REQUEST_URI'], '/' ), 'wp-comments-post.php' ) ) {
|
1672 |
+
return true;
|
1673 |
+
}
|
1674 |
+
|
1675 |
+
// XML-RPC
|
1676 |
+
if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
|
1677 |
+
return true;
|
1678 |
+
}
|
1679 |
+
|
1680 |
+
// Trackback
|
1681 |
+
if ( is_trackback() ) {
|
1682 |
+
return true;
|
1683 |
+
}
|
1684 |
+
|
1685 |
+
// Login page
|
1686 |
+
if ( cerber_is_login_request() ) {
|
1687 |
+
return true;
|
1688 |
+
}
|
1689 |
+
|
1690 |
+
// REST API (except Contact Form 7 submission)
|
1691 |
+
if ( cerber_is_rest_url() ) {
|
1692 |
+
if ( false === strpos( $_SERVER['REQUEST_URI'], 'contact-form-7' ) ) {
|
1693 |
+
return true;
|
1694 |
+
}
|
1695 |
+
}
|
1696 |
+
|
1697 |
+
return false;
|
1698 |
+
}
|
1699 |
+
|
1700 |
+
/*
|
1701 |
+
* Disable pingback URL (hide from HEAD)
|
1702 |
+
*/
|
1703 |
+
function cerber_pingback_url( $output, $show ) {
|
1704 |
+
if ( $show == 'pingback_url' ) {
|
1705 |
+
$output = '';
|
1706 |
+
}
|
1707 |
+
|
1708 |
+
return $output;
|
1709 |
+
}
|
1710 |
+
|
1711 |
+
/**
|
1712 |
+
* Disable REST API
|
1713 |
+
*
|
1714 |
+
*/
|
1715 |
+
function cerber_block_rest() {
|
1716 |
+
global $wp_version;
|
1717 |
+
// OLD WP
|
1718 |
+
add_filter( 'json_enabled', '__return_false' );
|
1719 |
+
add_filter( 'json_jsonp_enabled', '__return_false' );
|
1720 |
+
// WP 4.4, deprecated since 4.7
|
1721 |
+
if ( version_compare( $wp_version, '4.7', '<' ) ) {
|
1722 |
+
add_filter( 'rest_enabled', '__return_false', 9999 );
|
1723 |
+
}
|
1724 |
+
// WP 4.7
|
1725 |
+
add_filter( 'rest_jsonp_enabled', '__return_false' );
|
1726 |
+
// Links
|
1727 |
+
remove_action( 'wp_head', 'rest_output_link_wp_head', 10 );
|
1728 |
+
remove_action( 'template_redirect', 'rest_output_link_header', 11 );
|
1729 |
+
// Default REST API hooks from default-filters.php
|
1730 |
+
remove_action( 'init', 'rest_api_init' );
|
1731 |
+
remove_action( 'rest_api_init', 'rest_api_default_filters', 10 );
|
1732 |
+
remove_action( 'rest_api_init', 'register_initial_settings', 10 );
|
1733 |
+
remove_action( 'rest_api_init', 'create_initial_rest_routes', 99 );
|
1734 |
+
remove_action( 'parse_request', 'rest_api_loaded' );
|
1735 |
+
|
1736 |
+
if ( cerber_is_rest_url() ) {
|
1737 |
+
cerber_log( 70 );
|
1738 |
+
//cerber_404_page();
|
1739 |
+
cerber_forbidden_page(); // @since 6.0
|
1740 |
+
}
|
1741 |
+
}
|
1742 |
+
|
1743 |
+
/*
|
1744 |
+
* Redirection control: standard admin/login redirections
|
1745 |
+
*
|
1746 |
+
*/
|
1747 |
+
add_filter( 'wp_redirect', 'cerber_no_redirect', 10, 2 );
|
1748 |
+
function cerber_no_redirect( $location, $status ) {
|
1749 |
+
global $current_user, $wp_cerber;
|
1750 |
+
if ( (!$current_user || $current_user->ID == 0) && $wp_cerber->getSettings( 'noredirect' ) ) {
|
1751 |
+
$str = urlencode( '/wp-admin/' );
|
1752 |
+
$rdr = explode('redirect_to=',$location);
|
1753 |
+
if ( isset($rdr[1]) && strpos( $rdr[1], $str ) ) {
|
1754 |
+
cerber_404_page();
|
1755 |
+
}
|
1756 |
+
}
|
1757 |
+
|
1758 |
+
return $location;
|
1759 |
+
}
|
1760 |
+
|
1761 |
+
/*
|
1762 |
+
* Stop user enumeration
|
1763 |
+
*
|
1764 |
+
*/
|
1765 |
+
add_action( 'template_redirect', 'cerber_canonical', 1 );
|
1766 |
+
function cerber_canonical() {
|
1767 |
+
if ( crb_get_settings( 'stopenum' ) ) {
|
1768 |
+
if ( ! is_admin() && ! empty( $_GET['author'] ) ) {
|
1769 |
+
cerber_404_page();
|
1770 |
+
}
|
1771 |
+
}
|
1772 |
+
}
|
1773 |
+
/*
|
1774 |
+
if ( $wp_cerber->getSettings( 'hashauthor' ) ) {
|
1775 |
+
add_filter( 'request',
|
1776 |
+
function ( $vars ) {
|
1777 |
+
if (isset($vars['author_name']) && !is_admin()) {
|
1778 |
+
$vars['author_name'] = '><';
|
1779 |
+
}
|
1780 |
+
|
1781 |
+
return $vars;
|
1782 |
+
} );
|
1783 |
+
}
|
1784 |
+
*/
|
1785 |
+
|
1786 |
+
/*
|
1787 |
+
Can login form message be shown?
|
1788 |
+
*/
|
1789 |
+
function cerber_can_msg() {
|
1790 |
+
if ( ! isset( $_REQUEST['action'] ) ) {
|
1791 |
+
return true;
|
1792 |
+
}
|
1793 |
+
if ( $_REQUEST['action'] == 'login' ) {
|
1794 |
+
return true;
|
1795 |
+
}
|
1796 |
+
|
1797 |
+
return false;
|
1798 |
+
//if ( !in_array( $action, array( 'postpass', 'logout', 'lostpassword', 'retrievepassword', 'resetpass', 'rp', 'register', 'login' );
|
1799 |
+
}
|
1800 |
+
|
1801 |
+
|
1802 |
+
// Cookies ---------------------------------------------------------------------------------
|
1803 |
+
/*
|
1804 |
+
Mark user with Cerber Groove
|
1805 |
+
@since 1.3
|
1806 |
+
*/
|
1807 |
+
add_action( 'auth_cookie_valid', 'cerber_cookie1', 10, 2 );
|
1808 |
+
function cerber_cookie1( $cookie_elements = null, $user = null ) {
|
1809 |
+
global $current_user;
|
1810 |
+
if ( ! $user ) {
|
1811 |
+
$user = wp_get_current_user();
|
1812 |
+
}
|
1813 |
+
$expire = time() + apply_filters( 'auth_cookie_expiration', 14 * 24 * 3600, $user->ID, true ) + ( 24 * 3600 );
|
1814 |
+
cerber_set_groove( $expire );
|
1815 |
+
}
|
1816 |
+
|
1817 |
+
/*
|
1818 |
+
Mark switched user with Cerber Groove
|
1819 |
+
@since 1.6
|
1820 |
+
*/
|
1821 |
+
add_action( 'set_logged_in_cookie', 'cerber_cookie2', 10, 5 );
|
1822 |
+
function cerber_cookie2( $logged_in_cookie, $expire, $expiration, $user_id, $logged_in ) {
|
1823 |
+
cerber_set_groove( $expire );
|
1824 |
+
}
|
1825 |
+
|
1826 |
+
/*
|
1827 |
+
Track BAD cookies with non-existence user or bad password (hash)
|
1828 |
+
*/
|
1829 |
+
add_action( 'auth_cookie_bad_username', 'cerber_cookie_bad' );
|
1830 |
+
add_action( 'auth_cookie_bad_hash', 'cerber_cookie_bad' );
|
1831 |
+
function cerber_cookie_bad( $cookie_elements ) {
|
1832 |
+
cerber_login_failed( $cookie_elements['username'] );
|
1833 |
+
}
|
1834 |
+
|
1835 |
+
/**
|
1836 |
+
* Is bot detection engine enabled in a given rule_id
|
1837 |
+
*
|
1838 |
+
* @param $location string|array ID of the location
|
1839 |
+
*
|
1840 |
+
* @return bool true if enabled
|
1841 |
+
*/
|
1842 |
+
function cerber_antibot_enabled( $location ) {
|
1843 |
+
|
1844 |
+
if ( crb_get_settings( 'botsnoauth' ) && is_user_logged_in() ) {
|
1845 |
+
return false;
|
1846 |
+
}
|
1847 |
+
|
1848 |
+
if ( is_array( $location ) ) {
|
1849 |
+
foreach ( $location as $loc ) {
|
1850 |
+
if ( crb_get_settings( $loc ) ) {
|
1851 |
+
return true;
|
1852 |
+
}
|
1853 |
+
}
|
1854 |
+
}
|
1855 |
+
else {
|
1856 |
+
if ( crb_get_settings( $location ) ) {
|
1857 |
+
return true;
|
1858 |
+
}
|
1859 |
+
}
|
1860 |
+
|
1861 |
+
return false;
|
1862 |
+
}
|
1863 |
+
|
1864 |
+
/**
|
1865 |
+
* Print out the antibot/antispam jQuery code
|
1866 |
+
*
|
1867 |
+
* @param $location string|array Location (setting)
|
1868 |
+
*/
|
1869 |
+
function cerber_antibot_code($location) {
|
1870 |
+
if ( ! cerber_antibot_enabled( $location ) ) {
|
1871 |
+
return;
|
1872 |
+
}
|
1873 |
+
|
1874 |
+
$values = cerber_antibot_gene();
|
1875 |
+
|
1876 |
+
if ( empty( $values ) || !is_array( $values ) ) {
|
1877 |
+
return;
|
1878 |
+
}
|
1879 |
+
|
1880 |
+
?>
|
1881 |
+
<script type="text/javascript">
|
1882 |
+
jQuery(document).ready(function ($) {
|
1883 |
+
//$( document ).ajaxStart(function() {
|
1884 |
+
//});
|
1885 |
+
|
1886 |
+
<?php // Append form fields directly to the all forms ?>
|
1887 |
+
|
1888 |
+
for (var i = 0; i < document.forms.length; ++i) {
|
1889 |
+
var form = document.forms[i];
|
1890 |
+
<?php
|
1891 |
+
foreach ( $values[0] as $value ) {
|
1892 |
+
echo 'if ($(form).attr("method") != "get") { $(form).append(\'<input type="hidden" name="' . $value[0] . '" value="' . $value[1] . '" />\'); }'."\n";
|
1893 |
+
}
|
1894 |
+
?>
|
1895 |
+
}
|
1896 |
+
|
1897 |
+
<?php // Ordinary submit ?>
|
1898 |
+
|
1899 |
+
$(document).on('submit', 'form', function () {
|
1900 |
+
<?php
|
1901 |
+
foreach ( $values[0] as $value ) {
|
1902 |
+
echo 'if ($(this).attr("method") != "get") { $(this).append(\'<input type="hidden" name="' . $value[0] . '" value="' . $value[1] . '" />\'); }'."\n";
|
1903 |
+
}
|
1904 |
+
?>
|
1905 |
+
return true;
|
1906 |
+
});
|
1907 |
+
|
1908 |
+
<?php // Pure AJAX submit with two different types of form data (object and string) ?>
|
1909 |
+
|
1910 |
+
jQuery.ajaxSetup({
|
1911 |
+
beforeSend: function (e, data) {
|
1912 |
+
|
1913 |
+
//console.log(Object.getOwnPropertyNames(data).sort());
|
1914 |
+
//console.log(data.type);
|
1915 |
+
|
1916 |
+
if (data.type !== 'POST') return;
|
1917 |
+
|
1918 |
+
if (typeof data.data === 'object' && data.data !== null) {
|
1919 |
+
<?php
|
1920 |
+
foreach ( $values[0] as $value ) {
|
1921 |
+
echo 'data.data.append("' . $value[0] . '", "' . $value[1] . '");'."\n";
|
1922 |
+
}
|
1923 |
+
?>
|
1924 |
+
}
|
1925 |
+
else {
|
1926 |
+
data.data = data.data + '<?php
|
1927 |
+
foreach ( $values[0] as $value ) {
|
1928 |
+
echo '&' . $value[0] . '=' . $value[1];
|
1929 |
+
}
|
1930 |
+
?>';
|
1931 |
+
}
|
1932 |
+
}
|
1933 |
+
});
|
1934 |
+
|
1935 |
+
});
|
1936 |
+
</script>
|
1937 |
+
<?php
|
1938 |
+
|
1939 |
+
}
|
1940 |
+
|
1941 |
+
/**
|
1942 |
+
* Generates and saves antibot markers
|
1943 |
+
*
|
1944 |
+
* @return array|bool
|
1945 |
+
*/
|
1946 |
+
function cerber_antibot_gene($recreate = false) {
|
1947 |
+
|
1948 |
+
if ( !crb_get_settings('botsany') && !crb_get_settings('botscomm') && !crb_get_settings('botsreg') ) {
|
1949 |
+
return false;
|
1950 |
+
}
|
1951 |
+
|
1952 |
+
$ret = array();
|
1953 |
+
|
1954 |
+
if (!$recreate) {
|
1955 |
+
$ret = cerber_get_site_option( 'cerber-antibot' );
|
1956 |
+
}
|
1957 |
+
|
1958 |
+
if ( $recreate || !$ret ) {
|
1959 |
+
|
1960 |
+
$ret = array();
|
1961 |
+
|
1962 |
+
$max = rand( 2, 4 );
|
1963 |
+
for ( $i = 1; $i <= $max; $i ++ ) {
|
1964 |
+
$length = rand( 6, 16 );
|
1965 |
+
$string1 = str_shuffle( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-' );
|
1966 |
+
$string2 = str_shuffle( '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.@*_[]' );
|
1967 |
+
$ret[0][] = array( substr( $string1, 0, $length ), substr( $string2, 0, $length ) );
|
1968 |
+
}
|
1969 |
+
|
1970 |
+
$max = rand( 2, 4 );
|
1971 |
+
for ( $i = 1; $i <= $max; $i ++ ) {
|
1972 |
+
$length = rand( 6, 16 );
|
1973 |
+
$string1 = str_shuffle( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-' );
|
1974 |
+
$string2 = str_shuffle( '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.@*_[]' );
|
1975 |
+
$ret[1][] = array( substr( $string1, 0, $length ), substr( $string2, 0, $length ) );
|
1976 |
+
}
|
1977 |
+
|
1978 |
+
update_site_option( 'cerber-antibot', $ret );
|
1979 |
+
}
|
1980 |
+
|
1981 |
+
return $ret;
|
1982 |
+
}
|
1983 |
+
|
1984 |
+
/**
|
1985 |
+
* Is a POST request (a form) submitted by a bot?
|
1986 |
+
*
|
1987 |
+
* @param $location string identificator of a place where we are check for a bot
|
1988 |
+
*
|
1989 |
+
* @return bool
|
1990 |
+
*/
|
1991 |
+
function cerber_is_bot($location = '') {
|
1992 |
+
global $wp_cerber, $cerber_status;
|
1993 |
+
static $ret = null;
|
1994 |
+
|
1995 |
+
if ( isset( $ret ) ) {
|
1996 |
+
return $ret;
|
1997 |
+
}
|
1998 |
+
|
1999 |
+
if ( ! $location || ! cerber_is_http_post() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
|
2000 |
+
$ret = false;
|
2001 |
+
|
2002 |
+
return $ret;
|
2003 |
+
}
|
2004 |
+
|
2005 |
+
// Admin || AJAX requests by unauthorized users
|
2006 |
+
if ( is_admin() ) {
|
2007 |
+
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
2008 |
+
if ( is_user_logged_in() ) {
|
2009 |
+
$ret = false;
|
2010 |
+
}
|
2011 |
+
elseif ( ! empty( $_POST['action'] ) ) {
|
2012 |
+
if ($_POST['action'] == 'heartbeat'){ // WP heartbeat
|
2013 |
+
$ret = false;
|
2014 |
+
}
|
2015 |
+
}
|
2016 |
+
elseif ( crb_get_settings( 'botssafe' ) ) {
|
2017 |
+
$ret = false;
|
2018 |
+
}
|
2019 |
+
}
|
2020 |
+
else {
|
2021 |
+
$ret = false;
|
2022 |
+
}
|
2023 |
+
}
|
2024 |
+
|
2025 |
+
if ($ret !== null) {
|
2026 |
+
return $ret;
|
2027 |
+
}
|
2028 |
+
|
2029 |
+
if ( ! cerber_antibot_enabled( $location ) ) {
|
2030 |
+
$ret = false;
|
2031 |
+
|
2032 |
+
return $ret;
|
2033 |
+
}
|
2034 |
+
|
2035 |
+
// Antibot whitelist
|
2036 |
+
if ( ( $list = crb_get_settings( 'botswhite' ) ) && is_array( $list ) ) {
|
2037 |
+
foreach ( $list as $exception ) {
|
2038 |
+
if ( false !== strpos( trim( $_SERVER['REQUEST_URI'], '/' ), $exception ) ) {
|
2039 |
+
$ret = false;
|
2040 |
+
return $ret;
|
2041 |
+
}
|
2042 |
+
}
|
2043 |
+
}
|
2044 |
+
|
2045 |
+
$antibot = cerber_antibot_gene();
|
2046 |
+
|
2047 |
+
$ret = false;
|
2048 |
+
|
2049 |
+
if ( ! empty( $antibot ) ) {
|
2050 |
+
|
2051 |
+
foreach ( $antibot[0] as $fields ) {
|
2052 |
+
if ( empty( $_POST[ $fields[0] ] ) || $_POST[ $fields[0] ] != $fields[1] ) {
|
2053 |
+
$ret = true;
|
2054 |
+
break;
|
2055 |
+
}
|
2056 |
+
}
|
2057 |
+
|
2058 |
+
if (!$ret){
|
2059 |
+
foreach ( $antibot[1] as $fields ) {
|
2060 |
+
if ( empty( $_COOKIE[ $fields[0] ] ) || $_COOKIE[ $fields[0] ] != $fields[1] ) {
|
2061 |
+
$ret = true;
|
2062 |
+
break;
|
2063 |
+
}
|
2064 |
+
}
|
2065 |
+
}
|
2066 |
+
|
2067 |
+
if ( $ret ) {
|
2068 |
+
$cerber_status = 11;
|
2069 |
+
lab_save_push( $wp_cerber->getRemoteIp(), 333, '' );
|
2070 |
+
}
|
2071 |
+
}
|
2072 |
+
|
2073 |
+
return $ret;
|
2074 |
+
}
|
2075 |
+
|
2076 |
+
function cerber_geo_allowed( $rule_id = '' ) {
|
2077 |
+
|
2078 |
+
if ( !$rule_id || ( defined( 'DOING_CRON' ) && DOING_CRON ) || !lab_lab() ) {
|
2079 |
+
return true;
|
2080 |
+
}
|
2081 |
+
|
2082 |
+
$tag = cerber_acl_check();
|
2083 |
+
if ( $tag == 'W' ) {
|
2084 |
+
return true;
|
2085 |
+
}
|
2086 |
+
|
2087 |
+
$rule = cerber_geo_rules( $rule_id );
|
2088 |
+
$wp_cerber = get_wp_cerber();
|
2089 |
+
if ( $rule && $country = lab_get_country( $wp_cerber->getRemoteIp(), false ) ) {
|
2090 |
+
if ( in_array( $country, $rule['list'] ) ) {
|
2091 |
+
if ( $rule['type'] == 'W' ) {
|
2092 |
+
return true;
|
2093 |
+
}
|
2094 |
+
|
2095 |
+
return false;
|
2096 |
+
}
|
2097 |
+
if ( $rule['type'] == 'W' ) {
|
2098 |
+
return false;
|
2099 |
+
}
|
2100 |
+
|
2101 |
+
return true;
|
2102 |
+
}
|
2103 |
+
|
2104 |
+
return true;
|
2105 |
+
}
|
2106 |
+
|
2107 |
+
/**
|
2108 |
+
* Retrieve and return GEO rule(s) from the DB
|
2109 |
+
*
|
2110 |
+
* @param string $rule_id Slug of a rule
|
2111 |
+
*
|
2112 |
+
* @return bool|array If a rule exists return array of countries
|
2113 |
+
*/
|
2114 |
+
function cerber_geo_rules( $rule_id = '' ) {
|
2115 |
+
global $wpdb;
|
2116 |
+
|
2117 |
+
if (is_multisite()) {
|
2118 |
+
$geo = $wpdb->get_var( 'SELECT meta_value FROM ' . $wpdb->sitemeta . ' WHERE meta_key = "geo_rule_set"' );
|
2119 |
+
}
|
2120 |
+
else {
|
2121 |
+
$geo = $wpdb->get_var( 'SELECT option_value FROM ' . $wpdb->options . ' WHERE option_name = "geo_rule_set"' );
|
2122 |
+
}
|
2123 |
+
|
2124 |
+
if ( $geo ) {
|
2125 |
+
$rules = unserialize( $geo );
|
2126 |
+
if ( $rule_id ) {
|
2127 |
+
if ( ! empty( $rules[ $rule_id ] ) ) {
|
2128 |
+
$ret = $rules[ $rule_id ];
|
2129 |
+
}
|
2130 |
+
else {
|
2131 |
+
$ret = false;
|
2132 |
+
}
|
2133 |
+
}
|
2134 |
+
else {
|
2135 |
+
$ret = $rules;
|
2136 |
+
}
|
2137 |
+
}
|
2138 |
+
else {
|
2139 |
+
$ret = false;
|
2140 |
+
}
|
2141 |
+
|
2142 |
+
return $ret;
|
2143 |
+
}
|
2144 |
+
|
2145 |
+
/**
|
2146 |
+
* Set user session expiration
|
2147 |
+
*
|
2148 |
+
*/
|
2149 |
+
add_filter( 'auth_cookie_expiration', function ( $expire ) {
|
2150 |
+
$time = crb_get_settings( 'auth_expire' );
|
2151 |
+
if ( $time ) {
|
2152 |
+
$expire = 60 * $time;
|
2153 |
+
}
|
2154 |
+
|
2155 |
+
return $expire;
|
2156 |
+
} );
|
2157 |
+
|
2158 |
+
// Track various activity -------------------------------------------------------------------------
|
2159 |
+
|
2160 |
+
add_action( 'wp_login', function ( $login, $user ) {
|
2161 |
+
global $wp_cerber_user_id;
|
2162 |
+
if ( ! empty( $_POST['log'] ) ) { // default WP form
|
2163 |
+
$user_login = htmlspecialchars( $_POST['log'] );
|
2164 |
+
}
|
2165 |
+
else {
|
2166 |
+
$user_login = $login;
|
2167 |
+
}
|
2168 |
+
$wp_cerber_user_id = $user->ID;
|
2169 |
+
cerber_log( 5, $user_login, $user->ID );
|
2170 |
+
}, 10, 2 );
|
2171 |
+
|
2172 |
+
/**
|
2173 |
+
* Catching some cases of authentication without using login form or not a default user login process
|
2174 |
+
*/
|
2175 |
+
add_action( 'set_auth_cookie', function () {
|
2176 |
+
add_action( 'shutdown', function () { // deferred to allow the possible 'wp_login' action be logged first
|
2177 |
+
if ($user_id = get_current_user_id()) {
|
2178 |
+
cerber_log( 5, '', $user_id );
|
2179 |
+
}
|
2180 |
+
} );
|
2181 |
+
} );
|
2182 |
+
|
2183 |
+
/*add_action( 'wp_logout', function() {
|
2184 |
+
global $user_ID;
|
2185 |
+
if ( ! $user_ID ) {
|
2186 |
+
$user = wp_get_current_user();
|
2187 |
+
$user_ID = $user->ID;
|
2188 |
+
}
|
2189 |
+
cerber_log( 6, '', $user_ID );
|
2190 |
+
});*/
|
2191 |
+
|
2192 |
+
add_action( 'clear_auth_cookie', function () {
|
2193 |
+
$uid = get_current_user_id();
|
2194 |
+
if ( $uid ) {
|
2195 |
+
cerber_log( 6, '', $uid );
|
2196 |
+
}
|
2197 |
+
} );
|
2198 |
+
|
2199 |
+
//add_action( 'lostpassword_post', 'cerber_password_post' );
|
2200 |
+
add_action( 'retrieve_password', function ( $user_login ) {
|
2201 |
+
cerber_log( 21, $user_login );
|
2202 |
+
} );
|
2203 |
+
|
2204 |
+
add_action( 'password_reset', 'crb_pass_reset' );
|
2205 |
+
add_action( 'crb_after_reset', 'crb_pass_reset', 10, 2);
|
2206 |
+
|
2207 |
+
function crb_pass_reset( $user, $user_id = null) {
|
2208 |
+
if ( ! $user && $user_id ) {
|
2209 |
+
$user = get_user_by( 'id', $user_id );
|
2210 |
+
}
|
2211 |
+
if ( ! $user ) {
|
2212 |
+
return;
|
2213 |
+
}
|
2214 |
+
cerber_log( 20, $user->user_login, $user->ID );
|
2215 |
+
}
|
2216 |
+
|
2217 |
+
//add_action( 'register_new_user', function ( $user_id ) { // OLD
|
2218 |
+
// Fires in wp_insert_user()
|
2219 |
+
add_action( 'user_register', function ( $user_id ) { // @since 5.6
|
2220 |
+
$cid = get_current_user_id();
|
2221 |
+
if ($user = get_user_by( 'ID', $user_id )) {
|
2222 |
+
if ( $cid && $cid != $user_id ) {
|
2223 |
+
$ac = 1;
|
2224 |
+
}
|
2225 |
+
else {
|
2226 |
+
$ac = 2;
|
2227 |
+
}
|
2228 |
+
cerber_log( $ac, $user->user_login, $user_id );
|
2229 |
+
crb_log_user_ip( $user_id, $cid );
|
2230 |
+
}
|
2231 |
+
});
|
2232 |
+
|
2233 |
+
// Fires after a new user has been created in WP dashboard.
|
2234 |
+
add_action( 'edit_user_created_user', function ( $user_id, $notify = null ) {
|
2235 |
+
if ( $user_id && $user = get_user_by( 'ID', $user_id ) ) {
|
2236 |
+
cerber_log( 1, $user->user_login, $user_id );
|
2237 |
+
crb_log_user_ip( $user_id );
|
2238 |
+
}
|
2239 |
+
}, 10, 2 );
|
2240 |
+
|
2241 |
+
// Log IP address of user registration independently
|
2242 |
+
function crb_log_user_ip( $user_id, $by_user = null ) {
|
2243 |
+
global $wp_cerber;
|
2244 |
+
if ( ! $user_id ) {
|
2245 |
+
return;
|
2246 |
+
}
|
2247 |
+
if ( ! $by_user ) {
|
2248 |
+
$by_user = get_current_user_id();
|
2249 |
+
}
|
2250 |
+
add_user_meta( $user_id, '_crb_reg_', array( 'IP' => $wp_cerber->getRemoteIp(), 'user' => $by_user ) );
|
2251 |
+
}
|
2252 |
+
|
2253 |
+
// Lockouts routines ---------------------------------------------------------------------
|
2254 |
+
|
2255 |
+
/**
|
2256 |
+
* Lock out IP address if it is an alien IP only (browser does not have valid Cerber groove)
|
2257 |
+
*
|
2258 |
+
* @param $ip string IP address to block
|
2259 |
+
* @param integer $reason_id ID of reason of blocking
|
2260 |
+
* @param string $details Reason of blocking
|
2261 |
+
* @param null $duration Duration of blocking
|
2262 |
+
*
|
2263 |
+
* @return bool|false|int
|
2264 |
+
*/
|
2265 |
+
function cerber_soft_block_add( $ip, $reason_id, $details = '', $duration = null ) {
|
2266 |
+
if ( cerber_check_groove() ) {
|
2267 |
+
return false;
|
2268 |
+
}
|
2269 |
+
|
2270 |
+
return cerber_block_add( $ip, $reason_id, $details, $duration );
|
2271 |
+
}
|
2272 |
+
|
2273 |
+
/**
|
2274 |
+
* Lock out IP address
|
2275 |
+
*
|
2276 |
+
* @param $ip string IP address to block
|
2277 |
+
* @param integer $reason_id ID of reason of blocking
|
2278 |
+
* @param string $details Reason of blocking
|
2279 |
+
* @param int $duration Duration of blocking
|
2280 |
+
*
|
2281 |
+
* @return bool|false|int
|
2282 |
+
*/
|
2283 |
+
function cerber_block_add( $ip = '', $reason_id = 1, $details = '', $duration = null ) {
|
2284 |
+
global $wpdb;
|
2285 |
+
|
2286 |
+
$wp_cerber = get_wp_cerber();
|
2287 |
+
|
2288 |
+
//$wp_cerber->setProcessed();
|
2289 |
+
|
2290 |
+
if ( empty($ip) ) {
|
2291 |
+
$ip = $wp_cerber->getRemoteIp();
|
2292 |
+
}
|
2293 |
+
|
2294 |
+
if ( cerber_get_block( $ip ) ) {
|
2295 |
+
return false;
|
2296 |
+
}
|
2297 |
+
|
2298 |
+
if ( cerber_acl_check( $ip ) ) {
|
2299 |
+
return false;
|
2300 |
+
}
|
2301 |
+
|
2302 |
+
$ip_address = $ip;
|
2303 |
+
|
2304 |
+
lab_save_push( $ip, $reason_id, $details );
|
2305 |
+
|
2306 |
+
if ( $wp_cerber->getSettings( 'subnet' ) ) {
|
2307 |
+
$ip = cerber_get_subnet( $ip );
|
2308 |
+
$activity = 11;
|
2309 |
+
}
|
2310 |
+
else {
|
2311 |
+
$activity = 10;
|
2312 |
+
}
|
2313 |
+
|
2314 |
+
/*if ( $wpdb->get_var( $wpdb->prepare( 'SELECT count(ip) FROM ' . CERBER_BLOCKS_TABLE . ' WHERE ip = %s', $ip ) ) ) {
|
2315 |
+
return false;
|
2316 |
+
}*/
|
2317 |
+
|
2318 |
+
$reason = cerber_get_reason( $reason_id );
|
2319 |
+
if ( $details ) {
|
2320 |
+
$reason .= ': <b>' . $details . '</b>';
|
2321 |
+
}
|
2322 |
+
|
2323 |
+
if ( ! $duration ) {
|
2324 |
+
$duration = cerber_calc_duration( $ip );
|
2325 |
+
}
|
2326 |
+
$until = time() + $duration;
|
2327 |
+
|
2328 |
+
//$result = $wpdb->query($wpdb->prepare('INSERT INTO '. CERBER_BLOCKS_TABLE . ' (ip,block_until,reason) VALUES (%s,%d,%s)',$ip,$until,$reason));
|
2329 |
+
$result = $wpdb->insert( CERBER_BLOCKS_TABLE, array(
|
2330 |
+
'ip' => $ip,
|
2331 |
+
'block_until' => $until,
|
2332 |
+
'reason' => $reason
|
2333 |
+
), array( '%s', '%d', '%s' ) );
|
2334 |
+
|
2335 |
+
if ( $result ) {
|
2336 |
+
cerber_log( $activity, null, null, $ip_address );
|
2337 |
+
$wp_cerber->setLocked();
|
2338 |
+
do_action( 'cerber_ip_locked', array( 'IP' => $ip_address, 'reason' => $reason ) );
|
2339 |
+
$result = true;
|
2340 |
+
}
|
2341 |
+
else {
|
2342 |
+
cerber_db_error_log();
|
2343 |
+
$result = false;
|
2344 |
+
}
|
2345 |
+
|
2346 |
+
if ( $wp_cerber->getSettings( 'notify' ) ) {
|
2347 |
+
//$count = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_BLOCKS_TABLE );
|
2348 |
+
$count = cerber_blocked_num();
|
2349 |
+
if ( $count > $wp_cerber->getSettings( 'above' ) ) {
|
2350 |
+
cerber_send_notify( 'lockout', '', $ip_address );
|
2351 |
+
}
|
2352 |
+
}
|
2353 |
+
|
2354 |
+
return $result;
|
2355 |
+
}
|
2356 |
+
|
2357 |
+
function cerber_block_delete( $ip ) {
|
2358 |
+
global $wpdb;
|
2359 |
+
|
2360 |
+
return $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . CERBER_BLOCKS_TABLE . ' WHERE ip = %s', $ip ) );
|
2361 |
+
}
|
2362 |
+
|
2363 |
+
|
2364 |
+
/**
|
2365 |
+
*
|
2366 |
+
* Check if an IP address is currently blocked. With C subnet also.
|
2367 |
+
*
|
2368 |
+
* @param string $ip an IP address
|
2369 |
+
*
|
2370 |
+
* @return bool true if IP is locked out
|
2371 |
+
*/
|
2372 |
+
function cerber_block_check( $ip = '' ) {
|
2373 |
+
|
2374 |
+
// @since 4.8
|
2375 |
+
if (cerber_get_block($ip)) return true;
|
2376 |
+
|
2377 |
+
return false;
|
2378 |
+
}
|
2379 |
+
|
2380 |
+
/**
|
2381 |
+
*
|
2382 |
+
* Return the lockout row for an IP if it is blocked. With C subnet also.
|
2383 |
+
*
|
2384 |
+
* @param string $ip an IP address
|
2385 |
+
*
|
2386 |
+
* @return object|bool object if IP is locked out, false otherwise
|
2387 |
+
*/
|
2388 |
+
function cerber_get_block( $ip = '' ) {
|
2389 |
+
global $wpdb, $wp_cerber;
|
2390 |
+
|
2391 |
+
if ( ! $ip ) {
|
2392 |
+
$wp_cerber = get_wp_cerber();
|
2393 |
+
$ip = $wp_cerber->getRemoteIp();
|
2394 |
+
}
|
2395 |
+
|
2396 |
+
if ( ! filter_var( $ip, FILTER_VALIDATE_IP ) ) {
|
2397 |
+
return false;
|
2398 |
+
}
|
2399 |
+
|
2400 |
+
$where = ' WHERE ip = "' . $ip . '"';
|
2401 |
+
if ( cerber_is_ipv4( $ip ) ) {
|
2402 |
+
$subnet = cerber_get_subnet( $ip );
|
2403 |
+
$where .= ' OR ip = "' . $subnet . '"';
|
2404 |
+
}
|
2405 |
+
if ( $ret = $wpdb->get_row( 'SELECT * FROM ' . CERBER_BLOCKS_TABLE . $where ) ) {
|
2406 |
+
return $ret;
|
2407 |
+
}
|
2408 |
+
|
2409 |
+
return false;
|
2410 |
+
}
|
2411 |
+
|
2412 |
+
/**
|
2413 |
+
* Return the number of currently locked out IPs
|
2414 |
+
*
|
2415 |
+
* @return int the number of currently locked out IPs
|
2416 |
+
* @since 3.0
|
2417 |
+
*/
|
2418 |
+
function cerber_blocked_num() {
|
2419 |
+
global $wpdb;
|
2420 |
+
$count = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_BLOCKS_TABLE );
|
2421 |
+
|
2422 |
+
return absint( $count );
|
2423 |
+
}
|
2424 |
+
|
2425 |
+
/**
|
2426 |
+
* Calculate duration for a lockout of an IP address based on settings
|
2427 |
+
*
|
2428 |
+
* @param string $ip
|
2429 |
+
*
|
2430 |
+
* @return integer Duration in seconds
|
2431 |
+
*/
|
2432 |
+
function cerber_calc_duration( $ip ) {
|
2433 |
+
global $wpdb;
|
2434 |
+
$range = time() - crb_get_settings( 'aglast' ) * 3600;
|
2435 |
+
//$lockouts = $wpdb->get_var( $wpdb->prepare( 'SELECT count(ip) FROM ' . CERBER_LOG_TABLE . ' WHERE ip = %s AND activity IN (10,11) AND stamp > %d', $ip, $range ) );
|
2436 |
+
$lockouts = $wpdb->get_var( 'SELECT COUNT(ip) FROM ' . CERBER_LOG_TABLE . ' WHERE ip = "' . $ip . '" AND activity IN (10,11) AND stamp > ' . $range );
|
2437 |
+
if ( $lockouts >= crb_get_settings( 'aglocks' ) ) {
|
2438 |
+
$ret = crb_get_settings( 'agperiod' ) * 3600;
|
2439 |
+
}
|
2440 |
+
else {
|
2441 |
+
$ret = crb_get_settings( 'lockout' ) * 60;
|
2442 |
+
}
|
2443 |
+
$ret = absint( $ret );
|
2444 |
+
if ( $ret < 60 ) {
|
2445 |
+
$ret = 60;
|
2446 |
+
}
|
2447 |
+
|
2448 |
+
return $ret;
|
2449 |
+
}
|
2450 |
+
|
2451 |
+
/**
|
2452 |
+
* Calculation of remaining attempts
|
2453 |
+
*
|
2454 |
+
* @param $ip string an IP address
|
2455 |
+
* @param $check_acl bool if true will check the White IP ACL first
|
2456 |
+
* @param $activity string comma-separated list of activity IDs to calculate for
|
2457 |
+
* @param $allowed int Allowed attempts within $period
|
2458 |
+
* @param $period int Period for count attempts
|
2459 |
+
*
|
2460 |
+
* @return int Allowed attempts for now
|
2461 |
+
*/
|
2462 |
+
function cerber_get_remain_count( $ip = '', $check_acl = true, $activity = '7,51,52', $allowed = null, $period = null ) {
|
2463 |
+
global $wpdb, $wp_cerber;
|
2464 |
+
if ( ! $ip ) {
|
2465 |
+
$ip = $wp_cerber->getRemoteIp();
|
2466 |
+
}
|
2467 |
+
|
2468 |
+
if ( ! $allowed ) {
|
2469 |
+
$allowed = absint( crb_get_settings( 'attempts' ) );
|
2470 |
+
}
|
2471 |
+
|
2472 |
+
if ( $check_acl && cerber_acl_check( $ip, 'W' ) ) {
|
2473 |
+
return $allowed; // whitelist = infinity attempts
|
2474 |
+
}
|
2475 |
+
|
2476 |
+
if ( ! $period ) {
|
2477 |
+
$period = absint( crb_get_settings( 'period' ) );
|
2478 |
+
}
|
2479 |
+
|
2480 |
+
$range = time() - $period * 60;
|
2481 |
+
// TODO: remove prepare, replace $activity with an array of integer
|
2482 |
+
$attempts = $wpdb->get_var( $wpdb->prepare( 'SELECT count(ip) FROM ' . CERBER_LOG_TABLE . ' WHERE ip = %s AND activity IN (%s) AND stamp > %d', $ip, $activity, $range ) );
|
2483 |
+
|
2484 |
+
if ( ! $attempts ) {
|
2485 |
+
return $allowed;
|
2486 |
+
}
|
2487 |
+
else {
|
2488 |
+
$ret = $allowed - $attempts;
|
2489 |
+
}
|
2490 |
+
$ret = $ret < 0 ? 0 : $ret;
|
2491 |
+
|
2492 |
+
return $ret;
|
2493 |
+
}
|
2494 |
+
|
2495 |
+
/**
|
2496 |
+
* Is a given IP is allowed to do restricted things?
|
2497 |
+
* Here Cerber makes its decision.
|
2498 |
+
*
|
2499 |
+
* @param $ip string IP address
|
2500 |
+
*
|
2501 |
+
* @return bool
|
2502 |
+
*/
|
2503 |
+
function cerber_is_allowed( $ip = '' ) {
|
2504 |
+
|
2505 |
+
if ( ! $ip ) {
|
2506 |
+
$wp_cerber = get_wp_cerber();
|
2507 |
+
$ip = $wp_cerber->getRemoteIp();
|
2508 |
+
}
|
2509 |
+
|
2510 |
+
if ( ! filter_var( $ip, FILTER_VALIDATE_IP ) ) {
|
2511 |
+
return false;
|
2512 |
+
}
|
2513 |
+
|
2514 |
+
// @since 4.7.9
|
2515 |
+
if ( cerber_block_check( $ip ) ) {
|
2516 |
+
return false;
|
2517 |
+
}
|
2518 |
+
|
2519 |
+
$tag = cerber_acl_check( $ip );
|
2520 |
+
if ( $tag == 'W' ) {
|
2521 |
+
return true;
|
2522 |
+
}
|
2523 |
+
if ( $tag == 'B' ) {
|
2524 |
+
return false;
|
2525 |
+
}
|
2526 |
+
|
2527 |
+
/* @since 4.7.9
|
2528 |
+
if ( cerber_block_check( $ip ) ) {
|
2529 |
+
return false;
|
2530 |
+
}*/
|
2531 |
+
|
2532 |
+
if ( cerber_is_citadel() ) {
|
2533 |
+
return false;
|
2534 |
+
}
|
2535 |
+
|
2536 |
+
if ( lab_is_blocked( $ip, false ) ) {
|
2537 |
+
return false;
|
2538 |
+
}
|
2539 |
+
|
2540 |
+
return true;
|
2541 |
+
}
|
2542 |
+
|
2543 |
+
/**
|
2544 |
+
* Check if a given username is not permitted to login or register
|
2545 |
+
*
|
2546 |
+
* @param $username string
|
2547 |
+
*
|
2548 |
+
* @return bool true if username is prohibited
|
2549 |
+
*/
|
2550 |
+
function cerber_is_prohibited( $username ) {
|
2551 |
+
if ( $list = (array) crb_get_settings( 'prohibited' ) ) {
|
2552 |
+
foreach ( $list as $item ) {
|
2553 |
+
if ( mb_substr( $item, 0, 1 ) == '/' && mb_substr( $item, - 1 ) == '/' ) {
|
2554 |
+
$pattern = trim( $item, '/' );
|
2555 |
+
if ( mb_ereg_match( $pattern, $username, 'i' ) ) {
|
2556 |
+
return true;
|
2557 |
+
}
|
2558 |
+
}
|
2559 |
+
elseif ($username === $item){
|
2560 |
+
return true;
|
2561 |
+
}
|
2562 |
+
}
|
2563 |
+
}
|
2564 |
+
|
2565 |
+
return false;
|
2566 |
+
}
|
2567 |
+
|
2568 |
+
// TODO: Merge with $wp_cerber->getStatus();
|
2569 |
+
function cerber_get_status( $ip ) {
|
2570 |
+
global $cerber_status;
|
2571 |
+
|
2572 |
+
if ( ! empty( $cerber_status ) ) {
|
2573 |
+
return absint($cerber_status);
|
2574 |
+
}
|
2575 |
+
|
2576 |
+
if ( cerber_block_check( $ip ) ) {
|
2577 |
+
return 13;
|
2578 |
+
}
|
2579 |
+
|
2580 |
+
$tag = cerber_acl_check( $ip );
|
2581 |
+
if ( $tag == 'W' ) {
|
2582 |
+
return 0;
|
2583 |
+
}
|
2584 |
+
if ( $tag == 'B' ) {
|
2585 |
+
return 14;
|
2586 |
+
}
|
2587 |
+
|
2588 |
+
if ( cerber_is_citadel() ) {
|
2589 |
+
return 12;
|
2590 |
+
}
|
2591 |
+
|
2592 |
+
if ( lab_is_blocked( $ip, false ) ) {
|
2593 |
+
return 15;
|
2594 |
+
}
|
2595 |
+
|
2596 |
+
|
2597 |
+
return 0;
|
2598 |
+
}
|
2599 |
+
|
2600 |
+
// Access lists (ACL) routines --------------------------------------------------------------------------------
|
2601 |
+
|
2602 |
+
// TODO: move to dashboard.php
|
2603 |
+
/**
|
2604 |
+
* Add IP to specified access list
|
2605 |
+
*
|
2606 |
+
* @param $ip string|array single IP address, string with IP network, range or associative range array
|
2607 |
+
* @param $tag string 'B'|'W'
|
2608 |
+
*
|
2609 |
+
* @return bool|int|object Result of operation
|
2610 |
+
*/
|
2611 |
+
function cerber_acl_add( $ip, $tag, $comment = '') {
|
2612 |
+
global $wpdb;
|
2613 |
+
if ( is_string( $ip ) ) {
|
2614 |
+
if ( ! cerber_is_ipv4( $ip ) ) {
|
2615 |
+
$ip = cerber_short_ipv6( $ip );
|
2616 |
+
}
|
2617 |
+
if ( $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(ip) FROM ' . CERBER_ACL_TABLE . ' WHERE ip = %s', $ip ) ) ) {
|
2618 |
+
return false; //__( 'Element is already in list', 'wp-cerber' );
|
2619 |
+
}
|
2620 |
+
$range = cerber_any2range( $ip );
|
2621 |
+
if ( is_array( $range ) ) {
|
2622 |
+
$begin = $range['begin'];
|
2623 |
+
$end = $range['end'];
|
2624 |
+
}
|
2625 |
+
else {
|
2626 |
+
if (cerber_is_ipv4($ip)) {
|
2627 |
+
$begin = ip2long( $ip );
|
2628 |
+
$end = ip2long( $ip );
|
2629 |
+
}
|
2630 |
+
else{
|
2631 |
+
$begin = 0;
|
2632 |
+
$end = 0;
|
2633 |
+
}
|
2634 |
+
}
|
2635 |
+
|
2636 |
+
$result = $wpdb->insert( CERBER_ACL_TABLE, array( 'ip' => $ip,
|
2637 |
+
'ip_long_begin' => $begin,
|
2638 |
+
'ip_long_end' => $end,
|
2639 |
+
'tag' => $tag,
|
2640 |
+
'comments' => $comment
|
2641 |
+
), array( '%s', '%d', '%d', '%s', '%s' ) );
|
2642 |
+
return $result;
|
2643 |
+
}
|
2644 |
+
elseif ( is_array( $ip ) ) {
|
2645 |
+
$range = $ip['range'];
|
2646 |
+
$begin = $ip['begin'];
|
2647 |
+
$end = $ip['end'];
|
2648 |
+
if ( $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(ip) FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin = %d AND ip_long_end = %d', $begin, $end ) ) ) {
|
2649 |
+
return false;
|
2650 |
+
}
|
2651 |
+
|
2652 |
+
$result = $wpdb->insert( CERBER_ACL_TABLE, array( 'ip' => $range,
|
2653 |
+
'ip_long_begin' => $begin,
|
2654 |
+
'ip_long_end' => $end,
|
2655 |
+
'tag' => $tag,
|
2656 |
+
'comments' => $comment
|
2657 |
+
), array( '%s', '%d', '%d', '%s', '%s' ) );
|
2658 |
+
|
2659 |
+
return $result;
|
2660 |
+
|
2661 |
+
//return $wpdb->query( $wpdb->prepare( 'INSERT INTO ' . CERBER_ACL_TABLE . ' (ip, ip_long_begin, ip_long_end, tag) VALUES (%s,%d,%d,%s)', $range, $begin, $end, $tag ) );
|
2662 |
+
}
|
2663 |
+
|
2664 |
+
return false;
|
2665 |
+
}
|
2666 |
+
// TODO: move to dashboard.php
|
2667 |
+
function cerber_add_white( $ip, $comment = '' ) {
|
2668 |
+
return cerber_acl_add( $ip, 'W', $comment );
|
2669 |
+
}
|
2670 |
+
// TODO: move to dashboard.php
|
2671 |
+
function cerber_add_black( $ip, $comment = '') {
|
2672 |
+
return cerber_acl_add( $ip, 'B', $comment );
|
2673 |
+
}
|
2674 |
+
// TODO: move to dashboard.php
|
2675 |
+
function cerber_acl_remove( $ip ) {
|
2676 |
+
global $wpdb;
|
2677 |
+
if ( is_string( $ip ) ) {
|
2678 |
+
return $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . CERBER_ACL_TABLE . ' WHERE ip = %s ', $ip ) );
|
2679 |
+
} elseif ( is_array( $ip ) ) {
|
2680 |
+
return $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin = %d AND ip_long_end = %d', $ip['begin'], $ip['end'] ) );
|
2681 |
+
}
|
2682 |
+
|
2683 |
+
return false;
|
2684 |
+
}
|
2685 |
+
|
2686 |
+
// TODO: move to dashboard.php
|
2687 |
+
/**
|
2688 |
+
* Can a given IP (user input) be added to the blacklist
|
2689 |
+
*
|
2690 |
+
* @param $ip
|
2691 |
+
* @param string $list
|
2692 |
+
*
|
2693 |
+
* @return bool
|
2694 |
+
*/
|
2695 |
+
function cerber_can_be_listed( $ip, $list = 'B' ) {
|
2696 |
+
global $wp_cerber;
|
2697 |
+
if ( $list == 'B' ) {
|
2698 |
+
if ( crb_acl_is_white( $wp_cerber->getRemoteIp() ) ) {
|
2699 |
+
return true;
|
2700 |
+
}
|
2701 |
+
if ( filter_var( $ip, FILTER_VALIDATE_IP ) ) {
|
2702 |
+
if ( cerber_is_myip( $ip ) ) {
|
2703 |
+
return false;
|
2704 |
+
}
|
2705 |
+
}
|
2706 |
+
$range = cerber_any2range( $ip );
|
2707 |
+
if ( cerber_is_ip_in_range( $range ) ) {
|
2708 |
+
return false;
|
2709 |
+
}
|
2710 |
+
|
2711 |
+
return true;
|
2712 |
+
}
|
2713 |
+
|
2714 |
+
return true;
|
2715 |
+
}
|
2716 |
+
|
2717 |
+
/**
|
2718 |
+
* Check ACLs for given IP. Some extra lines for performance reason.
|
2719 |
+
*
|
2720 |
+
* @param string $ip
|
2721 |
+
* @param string $tag
|
2722 |
+
*
|
2723 |
+
* @return bool|string
|
2724 |
+
*/
|
2725 |
+
function cerber_acl_check( $ip = null, $tag = '' ) {
|
2726 |
+
global $wpdb, $wp_cerber;
|
2727 |
+
static $cache; // @since 5.26
|
2728 |
+
|
2729 |
+
if ( ! $ip ) {
|
2730 |
+
$wp_cerber = get_wp_cerber();
|
2731 |
+
$ip = $wp_cerber->getRemoteIp();
|
2732 |
+
//$ip = cerber_get_remote_ip();
|
2733 |
+
}
|
2734 |
+
|
2735 |
+
$key = cerber_get_id_ip( $ip ) . (string)$tag;
|
2736 |
+
|
2737 |
+
if ( isset( $cache[ $key ] ) ) {
|
2738 |
+
return $cache[ $key ];
|
2739 |
+
}
|
2740 |
+
|
2741 |
+
if ( ! cerber_is_ipv4( $ip ) ) {
|
2742 |
+
$ret = cerber_acl_checkV6( $ip, $tag );
|
2743 |
+
$cache[ $key ] = $ret;
|
2744 |
+
return $ret;
|
2745 |
+
}
|
2746 |
+
|
2747 |
+
$long = ip2long( $ip );
|
2748 |
+
|
2749 |
+
if ( $tag ) {
|
2750 |
+
if ( $tag != 'W' && $tag != 'B' ) {
|
2751 |
+
$ret = false;
|
2752 |
+
}
|
2753 |
+
elseif ( $wpdb->get_var( 'SELECT ip FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin <= '.$long.' AND '.$long.' <= ip_long_end AND tag = "'.$tag.'" LIMIT 1' ) ) {
|
2754 |
+
$ret = true;
|
2755 |
+
}
|
2756 |
+
else {
|
2757 |
+
$ret = false;
|
2758 |
+
}
|
2759 |
+
|
2760 |
+
$cache[ $key ] = $ret;
|
2761 |
+
return $ret;
|
2762 |
+
}
|
2763 |
+
else {
|
2764 |
+
// We use two queries because of possible overlapping an IP and its network
|
2765 |
+
if ( $ret = $wpdb->get_var( 'SELECT tag FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin <= ' . $long . ' AND ' . $long . ' <= ip_long_end AND tag = "W" LIMIT 1' ) ) {
|
2766 |
+
$cache[ $key ] = $ret;
|
2767 |
+
return $ret;
|
2768 |
+
}
|
2769 |
+
if ( $ret = $wpdb->get_var( 'SELECT tag FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin <= ' . $long . ' AND ' . $long . ' <= ip_long_end AND tag = "B" LIMIT 1' ) ) {
|
2770 |
+
$cache[ $key ] = $ret;
|
2771 |
+
return $ret;
|
2772 |
+
}
|
2773 |
+
|
2774 |
+
$cache[ $key ] = false;
|
2775 |
+
return false;
|
2776 |
+
}
|
2777 |
+
}
|
2778 |
+
|
2779 |
+
/**
|
2780 |
+
* IPv6 version of cerber_acl_check() without subnets and ranges
|
2781 |
+
*
|
2782 |
+
* @param null $ip
|
2783 |
+
* @param string $tag
|
2784 |
+
*
|
2785 |
+
* @return bool|null|string
|
2786 |
+
*/
|
2787 |
+
function cerber_acl_checkV6( $ip = null, $tag = '' ) {
|
2788 |
+
global $wpdb, $wp_cerber;
|
2789 |
+
if ( ! $ip ) {
|
2790 |
+
$ip = $wp_cerber->getRemoteIp();
|
2791 |
+
}
|
2792 |
+
if ( $tag ) {
|
2793 |
+
if ( $wpdb->get_var( $wpdb->prepare( 'SELECT count(ip) FROM ' . CERBER_ACL_TABLE . ' WHERE ip = %s AND tag = %s', $ip, $tag ) ) ) {
|
2794 |
+
return true;
|
2795 |
+
}
|
2796 |
+
|
2797 |
+
return false;
|
2798 |
+
} else {
|
2799 |
+
if ( $ret = $wpdb->get_var( $wpdb->prepare( 'SELECT tag FROM ' . CERBER_ACL_TABLE . ' WHERE ip = %s', $ip ) ) ) {
|
2800 |
+
return $ret;
|
2801 |
+
}
|
2802 |
+
|
2803 |
+
return false;
|
2804 |
+
}
|
2805 |
+
}
|
2806 |
+
|
2807 |
+
|
2808 |
+
function crb_acl_is_white( $ip = null ){
|
2809 |
+
|
2810 |
+
$acl = cerber_acl_check( $ip );
|
2811 |
+
if ( $acl == 'W' ) {
|
2812 |
+
return true;
|
2813 |
+
}
|
2814 |
+
|
2815 |
+
return false;
|
2816 |
+
}
|
2817 |
+
|
2818 |
+
/*
|
2819 |
+
* Logging directly to the file
|
2820 |
+
*
|
2821 |
+
* CERBER_FAIL_LOG optional, full path including filename to the log file
|
2822 |
+
* CERBER_LOG_FACILITY optional, use to specify what type of program is logging the messages
|
2823 |
+
*
|
2824 |
+
* */
|
2825 |
+
function cerber_file_log( $user_login, $ip ) {
|
2826 |
+
if ( defined( 'CERBER_FAIL_LOG' ) ) {
|
2827 |
+
if ( $log = @fopen( CERBER_FAIL_LOG, 'a' ) ) {
|
2828 |
+
$pid = absint( @posix_getpid() );
|
2829 |
+
@fwrite( $log, date( 'M j H:i:s ' ) . $_SERVER['SERVER_NAME'] . ' Cerber(' . $_SERVER['HTTP_HOST'] . ')[' . $pid . ']: Authentication failure for ' . $user_login . ' from ' . $ip . "\n" );
|
2830 |
+
@fclose( $log );
|
2831 |
+
}
|
2832 |
+
} else {
|
2833 |
+
@openlog( 'Cerber(' . $_SERVER['HTTP_HOST'] . ')', LOG_NDELAY | LOG_PID, defined( 'CERBER_LOG_FACILITY' ) ? CERBER_LOG_FACILITY : LOG_AUTH );
|
2834 |
+
@syslog( LOG_NOTICE, 'Authentication failure for ' . $user_login . ' from ' . $ip );
|
2835 |
+
@closelog();
|
2836 |
+
}
|
2837 |
+
}
|
2838 |
+
|
2839 |
+
/*
|
2840 |
+
Return wildcard - string like subnet Class C
|
2841 |
+
*/
|
2842 |
+
function cerber_get_subnet( $ip ) {
|
2843 |
+
return preg_replace( '/\.\d{1,3}$/', '.*', $ip );
|
2844 |
+
}
|
2845 |
+
|
2846 |
+
/*
|
2847 |
+
Check if given IP address or wildcard or CIDR is valid
|
2848 |
+
*/
|
2849 |
+
function cerber_is_ip_or_net( $ip ) {
|
2850 |
+
if ( filter_var( $ip, FILTER_VALIDATE_IP ) ) {
|
2851 |
+
return true;
|
2852 |
+
}
|
2853 |
+
// WILDCARD: 192.168.1.*
|
2854 |
+
$ip = str_replace( '*', '0', $ip );
|
2855 |
+
//if ( @inet_pton( $ip ) ) {
|
2856 |
+
if ( filter_var( $ip, FILTER_VALIDATE_IP ) ) {
|
2857 |
+
return true;
|
2858 |
+
}
|
2859 |
+
// CIDR: 192.168.1/24
|
2860 |
+
if ( strpos( $ip, '/' ) ) {
|
2861 |
+
$cidr = explode( '/', $ip );
|
2862 |
+
$net = $cidr[0];
|
2863 |
+
$mask = absint( $cidr[1] );
|
2864 |
+
$dots = substr_count( $net, '.' );
|
2865 |
+
if ( $dots < 3 ) {
|
2866 |
+
if ( $dots == 1 ) {
|
2867 |
+
$net .= '.0.0';
|
2868 |
+
} elseif ( $dots == 2 ) {
|
2869 |
+
$net .= '.0';
|
2870 |
+
}
|
2871 |
+
}
|
2872 |
+
if ( ! cerber_is_ipv4( $net ) ) {
|
2873 |
+
return false;
|
2874 |
+
}
|
2875 |
+
if ( ! is_numeric( $mask ) ) {
|
2876 |
+
return false;
|
2877 |
+
}
|
2878 |
+
|
2879 |
+
return true;
|
2880 |
+
}
|
2881 |
+
|
2882 |
+
return false;
|
2883 |
+
}
|
2884 |
+
|
2885 |
+
/**
|
2886 |
+
* Tries to recognize single IP address or IP v4 range (with dash) in a given string.
|
2887 |
+
*
|
2888 |
+
* @param string $string String to recognize IP address in
|
2889 |
+
*
|
2890 |
+
* @return array|bool|string Return single IP address or wildcard or CIDR as a string, and IP range as an array.
|
2891 |
+
*/
|
2892 |
+
function cerber_parse_ip( $string = '' ) {
|
2893 |
+
$string = trim( $string );
|
2894 |
+
if ( cerber_is_ip_or_net( $string ) ) {
|
2895 |
+
return $string;
|
2896 |
+
}
|
2897 |
+
$explode = explode( '-', $string );
|
2898 |
+
if ( ! is_array( $explode ) || ! $explode ) {
|
2899 |
+
return false;
|
2900 |
+
}
|
2901 |
+
$range = array();
|
2902 |
+
$count = 0;
|
2903 |
+
foreach ( $explode as $ip ) {
|
2904 |
+
$ip = trim( $ip );
|
2905 |
+
if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
|
2906 |
+
$range[] = $ip;
|
2907 |
+
$count ++;
|
2908 |
+
if ( $count >= 2 ) {
|
2909 |
+
break;
|
2910 |
+
}
|
2911 |
+
}
|
2912 |
+
}
|
2913 |
+
if ( count( $range ) < 2 ) {
|
2914 |
+
return false;
|
2915 |
+
}
|
2916 |
+
if ( ip2long( $range[1] ) <= ip2long( $range[0] ) ) {
|
2917 |
+
return false;
|
2918 |
+
}
|
2919 |
+
|
2920 |
+
return array(
|
2921 |
+
'range' => $range[0] . ' - ' . $range[1],
|
2922 |
+
'begin_ip' => $range[0],
|
2923 |
+
'end_ip' => $range[1],
|
2924 |
+
'begin' => ip2long( $range[0] ),
|
2925 |
+
'end' => ip2long( $range[1] ),
|
2926 |
+
);
|
2927 |
+
}
|
2928 |
+
|
2929 |
+
/**
|
2930 |
+
* Convert a network wildcard string like x.x.x.* to an IP v4 range
|
2931 |
+
*
|
2932 |
+
* @param $wildcard string
|
2933 |
+
*
|
2934 |
+
* @return array|bool|string False if no wildcard found, otherwise result of cerber_parse_ip()
|
2935 |
+
*/
|
2936 |
+
function cerber_wildcard2range( $wildcard = '' ) {
|
2937 |
+
$begin = str_replace( '*', '0', $wildcard );
|
2938 |
+
$end = str_replace( '*', '255', $wildcard );
|
2939 |
+
if ( ! cerber_is_ipv4( $begin ) ) {
|
2940 |
+
return false;
|
2941 |
+
}
|
2942 |
+
if ( ! cerber_is_ipv4( $end ) ) {
|
2943 |
+
return false;
|
2944 |
+
}
|
2945 |
+
|
2946 |
+
return cerber_parse_ip( $begin . ' - ' . $end );
|
2947 |
+
}
|
2948 |
+
|
2949 |
+
/**
|
2950 |
+
* Convert a CIDR to an IP v4 range
|
2951 |
+
*
|
2952 |
+
* @param $cidr string
|
2953 |
+
*
|
2954 |
+
* @return array|bool|string
|
2955 |
+
*/
|
2956 |
+
function cerber_cidr2range( $cidr = '' ) {
|
2957 |
+
if ( ! strpos( $cidr, '/' ) ) {
|
2958 |
+
return false;
|
2959 |
+
}
|
2960 |
+
$cidr = explode( '/', $cidr );
|
2961 |
+
$net = $cidr[0];
|
2962 |
+
$mask = absint( $cidr[1] );
|
2963 |
+
$dots = substr_count( $net, '.' );
|
2964 |
+
if ( $dots < 3 ) { // not completed CIDR
|
2965 |
+
if ( $dots == 1 ) {
|
2966 |
+
$net .= '.0.0';
|
2967 |
+
} elseif ( $dots == 2 ) {
|
2968 |
+
$net .= '.0';
|
2969 |
+
}
|
2970 |
+
}
|
2971 |
+
if ( ! cerber_is_ipv4( $net ) ) {
|
2972 |
+
return false;
|
2973 |
+
}
|
2974 |
+
if ( ! is_numeric( $mask ) ) {
|
2975 |
+
return false;
|
2976 |
+
}
|
2977 |
+
$begin = long2ip( ( ip2long( $net ) ) & ( ( - 1 << ( 32 - (int) $mask ) ) ) );
|
2978 |
+
$end = long2ip( ( ip2long( $net ) ) + pow( 2, ( 32 - (int) $mask ) ) - 1 );
|
2979 |
+
|
2980 |
+
return cerber_parse_ip( $begin . ' - ' . $end );
|
2981 |
+
}
|
2982 |
+
|
2983 |
+
/**
|
2984 |
+
* Try to recognize an IP range or a single IP in a string.
|
2985 |
+
*
|
2986 |
+
* @param $string string Network wildcard, CIDR or IP range.
|
2987 |
+
*
|
2988 |
+
* @return array|bool|string
|
2989 |
+
*/
|
2990 |
+
function cerber_any2range( $string = '' ) {
|
2991 |
+
// Do not change the order!
|
2992 |
+
$ret = cerber_wildcard2range( $string );
|
2993 |
+
if ( ! $ret ) {
|
2994 |
+
$ret = cerber_cidr2range( $string );
|
2995 |
+
}
|
2996 |
+
if ( ! $ret ) {
|
2997 |
+
$ret = cerber_parse_ip( $string ); // must be last due to checking for cidr and wildcard
|
2998 |
+
}
|
2999 |
+
|
3000 |
+
return $ret;
|
3001 |
+
}
|
3002 |
+
|
3003 |
+
/*
|
3004 |
+
Check for given IP address or subnet belong to this session.
|
3005 |
+
*/
|
3006 |
+
function cerber_is_myip( $ip ) {
|
3007 |
+
global $wp_cerber;
|
3008 |
+
if ( ! is_string( $ip ) ) {
|
3009 |
+
return false;
|
3010 |
+
}
|
3011 |
+
$remote_ip = $wp_cerber->getRemoteIp();
|
3012 |
+
if ( $ip == $remote_ip ) {
|
3013 |
+
return true;
|
3014 |
+
}
|
3015 |
+
if ( $ip == cerber_get_subnet( $remote_ip ) ) {
|
3016 |
+
return true;
|
3017 |
+
}
|
3018 |
+
|
3019 |
+
return false;
|
3020 |
+
}
|
3021 |
+
|
3022 |
+
function cerber_is_ip_in_range( $range, $ip = null ) {
|
3023 |
+
global $wp_cerber;
|
3024 |
+
if ( ! is_array( $range ) ) {
|
3025 |
+
return false;
|
3026 |
+
}
|
3027 |
+
if ( ! $ip ) {
|
3028 |
+
$ip = $wp_cerber->getRemoteIp();
|
3029 |
+
}
|
3030 |
+
$long = ip2long( $ip );
|
3031 |
+
if ( $range['begin'] <= $long && $long <= $range['end'] ) {
|
3032 |
+
return true;
|
3033 |
+
}
|
3034 |
+
|
3035 |
+
return false;
|
3036 |
+
}
|
3037 |
+
|
3038 |
+
/**
|
3039 |
+
* Display 404 page to bump bots and bad guys
|
3040 |
+
*
|
3041 |
+
* @param bool $simple If true force displaying basic 404 page
|
3042 |
+
*/
|
3043 |
+
function cerber_404_page($simple = false) {
|
3044 |
+
global $wp_query;
|
3045 |
+
|
3046 |
+
if ( !$simple ) {
|
3047 |
+
if ( function_exists( 'status_header' ) ) {
|
3048 |
+
status_header( '404' );
|
3049 |
+
}
|
3050 |
+
if ( isset( $wp_query ) && is_object( $wp_query ) ) {
|
3051 |
+
$wp_query->set_404();
|
3052 |
+
}
|
3053 |
+
if ( 0 == crb_get_settings( 'page404' ) ) {
|
3054 |
+
$template = null;
|
3055 |
+
if ( function_exists( 'get_404_template' ) ) {
|
3056 |
+
$template = get_404_template();
|
3057 |
+
}
|
3058 |
+
if ( function_exists( 'apply_filters' ) ) {
|
3059 |
+
$template = apply_filters( 'cerber_404_template', $template );
|
3060 |
+
}
|
3061 |
+
if ( $template && @file_exists( $template ) ) {
|
3062 |
+
include( $template );
|
3063 |
+
exit;
|
3064 |
+
}
|
3065 |
+
}
|
3066 |
+
}
|
3067 |
+
|
3068 |
+
header( 'HTTP/1.0 404 Not Found', true, 404 );
|
3069 |
+
echo '<html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL ' . esc_url( $_SERVER['REQUEST_URI'] ) . ' was not found on this server.</p></body></html>';
|
3070 |
+
cerber_traffic_log(); // do not remove!
|
3071 |
+
exit;
|
3072 |
+
}
|
3073 |
+
/*
|
3074 |
+
Display Forbidden page
|
3075 |
+
*/
|
3076 |
+
function cerber_forbidden_page() {
|
3077 |
+
status_header( '403' );
|
3078 |
+
header( 'HTTP/1.0 403 Access Forbidden', true, 403 );
|
3079 |
+
?>
|
3080 |
+
<!DOCTYPE html>
|
3081 |
+
<html style="height: 100%;">
|
3082 |
+
<meta charset="UTF-8">
|
3083 |
+
<head><title>403 Access Forbidden</title></head>
|
3084 |
+
<body style="height: 100%;">
|
3085 |
+
<div style="display: flex; align-items: center; justify-content: center; height: 70%;">
|
3086 |
+
<div style="background-color: #eee; width: 70%; border: solid 3px #ddd; padding: 1.5em 3em 3em 3em; font-family: Arial, Helvetica, sans-serif;">
|
3087 |
+
<div style="display: table-row;">
|
3088 |
+
<div style="display: table-cell; font-size: 150px; color: red; vertical-align: middle; padding-right: 50px;">
|
3089 |
+
✋
|
3090 |
+
</div>
|
3091 |
+
<div style="display: table-cell; vertical-align: middle;">
|
3092 |
+
<h1><?php _e("We're sorry, you are not allowed to proceed", 'wp-cerber'); ?></h1>
|
3093 |
+
<p>Our server stopped processing your request. Your request looks suspicious or similar to automated
|
3094 |
+
requests from spam posting software.</p>
|
3095 |
+
<p>If you believe you should be able to perform this request, please let us know.</p>
|
3096 |
+
</div>
|
3097 |
+
</div>
|
3098 |
+
</div>
|
3099 |
+
</div>
|
3100 |
+
</body>
|
3101 |
+
</html>
|
3102 |
+
<?php
|
3103 |
+
cerber_traffic_log(); // do not remove!
|
3104 |
+
exit;
|
3105 |
+
}
|
3106 |
+
|
3107 |
+
// Citadel mode -------------------------------------------------------------------------------------
|
3108 |
+
|
3109 |
+
function cerber_enable_citadel() {
|
3110 |
+
global $wp_cerber;
|
3111 |
+
if ( get_transient( 'cerber_citadel' ) ) {
|
3112 |
+
return;
|
3113 |
+
}
|
3114 |
+
set_transient( 'cerber_citadel', true, crb_get_settings( 'ciduration' ) * 60 );
|
3115 |
+
cerber_log( 12 );
|
3116 |
+
|
3117 |
+
// Notify admin
|
3118 |
+
if ( $wp_cerber->getSettings( 'cinotify' ) ) {
|
3119 |
+
cerber_send_notify( 'citadel' );
|
3120 |
+
}
|
3121 |
+
}
|
3122 |
+
|
3123 |
+
function cerber_disable_citadel() {
|
3124 |
+
delete_transient( 'cerber_citadel' );
|
3125 |
+
}
|
3126 |
+
|
3127 |
+
function cerber_is_citadel() {
|
3128 |
+
if ( get_transient( 'cerber_citadel' ) ) {
|
3129 |
+
return true;
|
3130 |
+
}
|
3131 |
+
|
3132 |
+
return false;
|
3133 |
+
}
|
3134 |
+
|
3135 |
+
// Hardening -------------------------------------------------------------------------------------
|
3136 |
+
|
3137 |
+
//if (!cerber_acl_check(cerber_get_ip(),'W') && false) {
|
3138 |
+
|
3139 |
+
/*
|
3140 |
+
if ($hardening['ping']) {
|
3141 |
+
add_filter( 'xmlrpc_methods', 'remove_xmlrpc_pingback' );
|
3142 |
+
function remove_xmlrpc_pingback( $methods ) {
|
3143 |
+
unset($methods['pingback.ping']);
|
3144 |
+
unset($methods['pingback.extensions.getPingbacks']);
|
3145 |
+
return $methods;
|
3146 |
+
}
|
3147 |
+
add_filter( 'wp_headers', 'remove_pingback_header' );
|
3148 |
+
function remove_pingback_header( $headers ) {
|
3149 |
+
unset( $headers['X-Pingback'] );
|
3150 |
+
return $headers;
|
3151 |
+
}
|
3152 |
+
}
|
3153 |
+
*/
|
3154 |
+
//pingback_ping();
|
3155 |
+
|
3156 |
+
|
3157 |
+
/*
|
3158 |
+
// Remove shortlink from HEAD <link rel='shortlink' href='http://адрес-сайта/?p=45' />
|
3159 |
+
remove_action('wp_head', 'wp_shortlink_wp_head', 10, 0 );
|
3160 |
+
*/
|
3161 |
+
|
3162 |
+
/**
|
3163 |
+
*
|
3164 |
+
* Send notification letter
|
3165 |
+
*
|
3166 |
+
* @param string $type Notification type
|
3167 |
+
* @param string|array $msg Additional message
|
3168 |
+
* @param string $ip Remote IP address, if applicable
|
3169 |
+
*
|
3170 |
+
* @return bool
|
3171 |
+
*/
|
3172 |
+
function cerber_send_notify( $type = '', $msg = '', $ip = '' ) {
|
3173 |
+
global $wpdb, $wp_cerber;
|
3174 |
+
if ( ! $type ) {
|
3175 |
+
return false;
|
3176 |
+
}
|
3177 |
+
|
3178 |
+
/*
|
3179 |
+
$super = false;
|
3180 |
+
if ( function_exists( 'is_super_admin' ) ) {
|
3181 |
+
$super = is_super_admin();
|
3182 |
+
}
|
3183 |
+
if ( $type == 'lockout' && !$usper()) {
|
3184 |
+
*/
|
3185 |
+
|
3186 |
+
if ( $type == 'lockout' && !is_admin()) {
|
3187 |
+
$rate = absint( $wp_cerber->getSettings( 'emailrate' ) );
|
3188 |
+
if ( $rate ) {
|
3189 |
+
$last = get_transient( 'cerber_last' );
|
3190 |
+
$period = 60 * 60; // per hour
|
3191 |
+
if ( $last ) {
|
3192 |
+
if ( $last > ( time() - $period / $rate ) ) {
|
3193 |
+
return false;
|
3194 |
+
}
|
3195 |
+
}
|
3196 |
+
set_transient( 'cerber_last', time(), $period );
|
3197 |
+
}
|
3198 |
+
}
|
3199 |
+
|
3200 |
+
$html_mode = false;
|
3201 |
+
|
3202 |
+
$subj = '[' . get_option( 'blogname' ) . '] ' . __( 'WP Cerber notify', 'wp-cerber' ) . ': ';
|
3203 |
+
$body = '';
|
3204 |
+
|
3205 |
+
if ( is_array( $msg ) ) {
|
3206 |
+
$msg = implode( "\n\n", $msg );
|
3207 |
+
}
|
3208 |
+
|
3209 |
+
switch ( $type ) {
|
3210 |
+
case 'citadel':
|
3211 |
+
$max = $wpdb->get_var( 'SELECT MAX(stamp) FROM ' . CERBER_LOG_TABLE . ' WHERE activity = 7' );
|
3212 |
+
if ($max) {
|
3213 |
+
$last_date = cerber_date( $max );
|
3214 |
+
$last = $wpdb->get_row( 'SELECT * FROM ' . CERBER_LOG_TABLE . ' WHERE stamp = ' . $max . ' AND activity = 7' );
|
3215 |
+
}
|
3216 |
+
else $last = null;
|
3217 |
+
|
3218 |
+
if ( ! $last ) { // workaround for the empty log table
|
3219 |
+
$last = new stdClass();
|
3220 |
+
$last->ip = '127.0.0.1';
|
3221 |
+
$last->user_login = 'test';
|
3222 |
+
}
|
3223 |
+
|
3224 |
+
$subj .= __( 'Citadel mode is activated', 'wp-cerber' );
|
3225 |
+
|
3226 |
+
$body = sprintf( __( 'Citadel mode is activated after %d failed login attempts in %d minutes.', 'wp-cerber' ), $wp_cerber->getSettings( 'cilimit' ), $wp_cerber->getSettings( 'ciperiod' ) ) . "\n\n";
|
3227 |
+
$body .= sprintf( __( 'Last failed attempt was at %s from IP %s with user login: %s.', 'wp-cerber' ), $last_date, $last->ip, $last->user_login ) . "\n\n";
|
3228 |
+
$body .= __( 'View activity in dashboard', 'wp-cerber' ) . ': ' . cerber_admin_link( 'activity' ) . "\n\n";
|
3229 |
+
//$body .= __('Change notification settings','wp-cerber').': '.cerber_admin_link();
|
3230 |
+
break;
|
3231 |
+
case 'lockout':
|
3232 |
+
$max = $wpdb->get_var( 'SELECT MAX(stamp) FROM ' . CERBER_LOG_TABLE . ' WHERE activity IN (10,11)' );
|
3233 |
+
if ($max){
|
3234 |
+
$last_date = cerber_date( $max );
|
3235 |
+
$last = $wpdb->get_row( 'SELECT * FROM ' . CERBER_LOG_TABLE . ' WHERE stamp = ' . $max . ' AND activity IN (10,11)' );
|
3236 |
+
}
|
3237 |
+
else $last = null;
|
3238 |
+
if ( ! $last ) { // workaround for the empty log table
|
3239 |
+
$last = new stdClass();
|
3240 |
+
$last->ip = '127.0.0.1';
|
3241 |
+
$last->user_login = 'test';
|
3242 |
+
}
|
3243 |
+
|
3244 |
+
//if ( ! $active = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_BLOCKS_TABLE ) ) {
|
3245 |
+
if ( ! $active = cerber_blocked_num() ) {
|
3246 |
+
$active = 0;
|
3247 |
+
}
|
3248 |
+
//if ( $ip && ( $block = cerber_get_block( $ip ) ) ) {
|
3249 |
+
if ( $last->ip && ( $block = cerber_get_block( $last->ip ) ) ) {
|
3250 |
+
$reason = $block->reason;
|
3251 |
+
}
|
3252 |
+
else {
|
3253 |
+
$reason = __( 'unspecified', 'wp-cerber' );
|
3254 |
+
}
|
3255 |
+
|
3256 |
+
$subj .= __( 'Number of lockouts is increasing', 'wp-cerber' ) . ' (' . $active . ')';
|
3257 |
+
|
3258 |
+
$body = __( 'Number of active lockouts', 'wp-cerber' ) . ': ' . $active . "\n\n";
|
3259 |
+
$body .= sprintf( __( 'Last lockout was added: %s for IP %s', 'wp-cerber' ), $last_date, $last->ip . ' (' . @gethostbyaddr( $last->ip ) . ')' ) . "\n\n";
|
3260 |
+
$body .= __( 'Reason', 'wp-cerber' ) . ': ' . strip_tags($reason) . "\n\n";
|
3261 |
+
$body .= __( 'View activity for this IP', 'wp-cerber' ) . ': ' . cerber_admin_link( 'activity' ) . '&filter_ip=' . $last->ip . "\n\n";
|
3262 |
+
$body .= __( 'View lockouts in dashboard', 'wp-cerber' ) . ': ' . cerber_admin_link( 'lockouts' ) . "\n\n";
|
3263 |
+
break;
|
3264 |
+
case 'new_version':
|
3265 |
+
$subj = __( 'A new version of WP Cerber is available to install', 'wp-cerber' );
|
3266 |
+
$body = __( 'Hi!', 'wp-cerber' ) . "\n\n";
|
3267 |
+
$body .= __( 'A new version of WP Cerber is available to install', 'wp-cerber' ) . "\n\n";
|
3268 |
+
$body .= $msg . "\n\n";
|
3269 |
+
$body .= __( 'Website', 'wp-cerber' ) . ': ' . get_bloginfo( 'name' );
|
3270 |
+
break;
|
3271 |
+
case 'shutdown':
|
3272 |
+
$subj = '[' . get_option( 'blogname' ) . '] ' . __( 'The WP Cerber security plugin has been deactivated', 'wp-cerber' );
|
3273 |
+
$body .= __( 'The WP Cerber security plugin has been deactivated', 'wp-cerber' ) . "\n\n";
|
3274 |
+
if ( ! is_user_logged_in() ) {
|
3275 |
+
$u = __( 'Not logged in', 'wp-cerber' );
|
3276 |
+
} else {
|
3277 |
+
$user = wp_get_current_user();
|
3278 |
+
$u = $user->display_name;
|
3279 |
+
}
|
3280 |
+
$body .= __( 'Website', 'wp-cerber' ) . ': ' . get_bloginfo( 'name' ) . "\n";
|
3281 |
+
$body .= __( 'By user', 'wp-cerber' ) . ': ' . $u . "\n";
|
3282 |
+
$body .= __( 'From IP address', 'wp-cerber' ) . ': ' . $wp_cerber->getRemoteIp() . "\n";
|
3283 |
+
$whois = cerber_ip_whois_info( $wp_cerber->getRemoteIp() );
|
3284 |
+
if ( ! empty( $whois['data']['country'] ) ) {
|
3285 |
+
$body .= __( 'From country', 'wp-cerber' ) . ': ' . cerber_country_name( $whois['data']['country'] );
|
3286 |
+
}
|
3287 |
+
break;
|
3288 |
+
case 'activated':
|
3289 |
+
$subj = '[' . get_option( 'blogname' ) . '] ' . __( 'The WP Cerber security plugin is now active', 'wp-cerber' );
|
3290 |
+
$body .= __( 'WP Cerber is now active and has started protecting your site', 'wp-cerber' ) . "\n\n";
|
3291 |
+
//$body .= __( 'Change notification settings', 'wp-cerber' ) . ': ' . cerber_admin_link('notifications') . "\n\n";
|
3292 |
+
$body .= __( 'Getting Started Guide', 'wp-cerber' ) . "\n\n";
|
3293 |
+
$body .= 'https://wpcerber.com/getting-started/' . "\n\n";
|
3294 |
+
$body .= 'Be in touch with the developer. Subscribe to Cerber\'s newsletter: http://wpcerber.com/subscribe-newsletter/';
|
3295 |
+
//$body .= get_bloginfo( 'name' );
|
3296 |
+
break;
|
3297 |
+
case 'newlurl':
|
3298 |
+
$subj .= __( 'New Custom login URL', 'wp-cerber' );
|
3299 |
+
$body .= $msg;
|
3300 |
+
break;
|
3301 |
+
case 'subs':
|
3302 |
+
$subj .= __( 'A new activity has been recorded', 'wp-cerber' );
|
3303 |
+
$body = __( 'A new activity has been recorded', 'wp-cerber' ) . "\n\n";
|
3304 |
+
$body .= $msg;
|
3305 |
+
break;
|
3306 |
+
case 'report':
|
3307 |
+
$html_mode = true;
|
3308 |
+
$subj = '[' . get_option( 'blogname' ) . '] WP Cerber Security: ' . __( 'Weekly report', 'wp-cerber' );
|
3309 |
+
$body = cerber_generate_report();
|
3310 |
+
$link = cerber_admin_link( 'notifications' );
|
3311 |
+
$body .= '<br/>' . __( 'To change reporting settings visit', 'wp-cerber' ) . ' <a href="' . $link . '">' . $link . '</a>';
|
3312 |
+
if ($msg) {
|
3313 |
+
$body .= nl2br($msg);
|
3314 |
+
}
|
3315 |
+
break;
|
3316 |
+
}
|
3317 |
+
|
3318 |
+
$to_list = cerber_get_email( $type, true );
|
3319 |
+
$to = implode( ', ', $to_list );
|
3320 |
+
|
3321 |
+
$body_filtered = apply_filters( 'cerber_notify_body', $body, array( 'type' => $type,
|
3322 |
+
'IP' => $ip,
|
3323 |
+
'to' => $to,
|
3324 |
+
'subject' => $subj
|
3325 |
+
) );
|
3326 |
+
if ( $body_filtered && is_string( $body_filtered ) ) {
|
3327 |
+
$body = $body_filtered;
|
3328 |
+
}
|
3329 |
+
|
3330 |
+
$footer = '';
|
3331 |
+
|
3332 |
+
if ( $lolink = cerber_get_login_url() ) {
|
3333 |
+
$lourl = urldecode( $lolink );
|
3334 |
+
if ( $html_mode ) {
|
3335 |
+
$lourl = '<a href="' . $lolink . '">' . $lourl . '</a>';
|
3336 |
+
}
|
3337 |
+
$footer .= "\n\n" . __( 'Your login page:', 'wp-cerber' ) . ' ' . $lourl;
|
3338 |
+
}
|
3339 |
+
|
3340 |
+
if ( $type == 'report' && $date = lab_lab(true) ) {
|
3341 |
+
$footer .= "\n\n" . __( 'Your license is valid until', 'wp-cerber' ) . ' ' . $date;
|
3342 |
+
}
|
3343 |
+
|
3344 |
+
$footer .= "\n\n\n" . __( 'This message was sent by', 'wp-cerber' ) . ' WP Cerber Security ' . CERBER_VER . "\n";
|
3345 |
+
$footer .= 'https://wpcerber.com';
|
3346 |
+
|
3347 |
+
if ( $html_mode ) {
|
3348 |
+
add_filter( 'wp_mail_content_type', 'cerber_enable_html' );
|
3349 |
+
$footer = str_replace( "\n", '<br/>', $footer );
|
3350 |
+
}
|
3351 |
+
|
3352 |
+
// Everything is prepared, let's send it out
|
3353 |
+
|
3354 |
+
$result = null;
|
3355 |
+
if ( $to && $subj && $body ) {
|
3356 |
+
if ( ! $html_mode ) {
|
3357 |
+
cerber_pb_send( $subj, $body.$footer );
|
3358 |
+
}
|
3359 |
+
|
3360 |
+
if ( $type == 'report') {
|
3361 |
+
$result = true;
|
3362 |
+
foreach ( $to_list as $email ) {
|
3363 |
+
$lastus = '';
|
3364 |
+
if ( $rec = cerber_get_last_login( null, $email ) ) {
|
3365 |
+
$lastus = sprintf( __( 'Your last sign-in was %s from %s', 'wp-cerber' ), cerber_date( $rec->stamp ), $rec->ip . ' (' . cerber_country_name( $rec->country ) . ')' );
|
3366 |
+
if ( $html_mode ) {
|
3367 |
+
$lastus = '<br/><br/>' . $lastus;
|
3368 |
+
}
|
3369 |
+
else {
|
3370 |
+
$lastus = "\n\n" . $lastus;
|
3371 |
+
}
|
3372 |
+
}
|
3373 |
+
|
3374 |
+
if ( ! wp_mail( $email, $subj, '<html>' . $body . $lastus . $footer . '</html>' ) ) {
|
3375 |
+
$result = false;
|
3376 |
+
}
|
3377 |
+
}
|
3378 |
+
}
|
3379 |
+
else {
|
3380 |
+
if ( function_exists( 'wp_mail' ) ) {
|
3381 |
+
$body = $body . $footer;
|
3382 |
+
if ( $html_mode ) {
|
3383 |
+
$body = '<html>' . $body . '</html>';
|
3384 |
+
}
|
3385 |
+
$result = wp_mail( $to, $subj, $body );
|
3386 |
+
}
|
3387 |
+
}
|
3388 |
+
}
|
3389 |
+
|
3390 |
+
remove_filter('wp_mail_content_type', 'cerber_enable_html');
|
3391 |
+
|
3392 |
+
$params = array( 'type' => $type, 'IP' => $ip, 'to' => $to, 'subject' => $subj );
|
3393 |
+
if ( $result ) {
|
3394 |
+
do_action( 'cerber_notify_sent', $body, $params );
|
3395 |
+
}
|
3396 |
+
else {
|
3397 |
+
do_action( 'cerber_notify_fail', $body, $params );
|
3398 |
+
}
|
3399 |
+
|
3400 |
+
return $result;
|
3401 |
+
}
|
3402 |
+
|
3403 |
+
function cerber_enable_html() {
|
3404 |
+
return 'text/html';
|
3405 |
+
}
|
3406 |
+
|
3407 |
+
/**
|
3408 |
+
* Generates a performance report
|
3409 |
+
*
|
3410 |
+
* @param int $period Days to look back
|
3411 |
+
*
|
3412 |
+
* @return string
|
3413 |
+
*/
|
3414 |
+
function cerber_generate_report($period = 7){
|
3415 |
+
global $wpdb;
|
3416 |
+
|
3417 |
+
$period = absint( $period );
|
3418 |
+
|
3419 |
+
if ( ! $period ) {
|
3420 |
+
$period = 7;
|
3421 |
+
}
|
3422 |
+
|
3423 |
+
$ret = '';
|
3424 |
+
$rows = array();
|
3425 |
+
$stamp = time() - $period * 24 * 3600;
|
3426 |
+
//$in = implode( ',', crb_get_activity_set( 'malicious' ) );
|
3427 |
+
//$link_base = '<a href="' . cerber_activity_link( array( 2 ) ) . '">';
|
3428 |
+
$base_url = cerber_admin_link( 'activity' );
|
3429 |
+
$css_table = 'width: 95%; max-width: 1000px; margin:0 auto; margin-bottom: 10px; background-color: #f5f5f5; text-align: center;';
|
3430 |
+
$css_td = 'padding: 0.5em 0.5em 0.5em 1em; text-align: left;';
|
3431 |
+
$css_boder = 'border-bottom: solid 2px #f9f9f9;';
|
3432 |
+
|
3433 |
+
if (is_multisite()) {
|
3434 |
+
$site_name = get_site_option( 'site_name' );
|
3435 |
+
}
|
3436 |
+
else {
|
3437 |
+
$site_name = get_option( 'blogname' );
|
3438 |
+
}
|
3439 |
+
|
3440 |
+
$ret .= '<div style="' . $css_table . '"><div style="margin:0 auto; text-align: center;"><p style="font-size: 130%; padding-top: 0.5em;">' . $site_name .'</p><p style="padding-bottom: 1em;">'. __('Weekly Report','wp-cerber'). '</p></div></div>';
|
3441 |
+
|
3442 |
+
$kpi_list = cerber_calculate_kpi( $period );
|
3443 |
+
|
3444 |
+
foreach ($kpi_list as $kpi){
|
3445 |
+
$rows[] = '<td style="'.$css_td.' text-align: right;">'.$kpi[1].'</td><td style="padding: 0.5em; text-align: left;">'.$kpi[0].'</td>';
|
3446 |
+
}
|
3447 |
+
|
3448 |
+
$ret .= '<div style="text-align: center; '.$css_table.'"><table style="font-size: 130%; margin:0 auto;"><tr>' . implode( '</tr><tr>', $rows ) . '</tr></table></div>';
|
3449 |
+
|
3450 |
+
// Activities counters
|
3451 |
+
$rows = array();
|
3452 |
+
$rows[] = '<td style="'.$css_td.$css_boder.'" colspan="2"><p style="line-height: 1.5em; font-weight: bold;">'.__('Activity details','wp-cerber').'</p></td>';
|
3453 |
+
$activites = $wpdb->get_results( 'SELECT activity, COUNT(activity) cnt FROM ' . CERBER_LOG_TABLE . ' WHERE stamp > ' . $stamp . ' GROUP by activity ORDER BY cnt DESC' );
|
3454 |
+
if ( $activites ) {
|
3455 |
+
$lables = cerber_get_labels();
|
3456 |
+
foreach ( $activites as $a ) {
|
3457 |
+
$rows[] = '<td style="'.$css_boder.$css_td.'">' . $lables[ $a->activity ] . '</td><td style="padding: 0.5em; text-align: center; width:10%;'.$css_boder.'"><a href="'.$base_url.'&filter_activity='.$a->activity.'">' . $a->cnt . '</a></td>';
|
3458 |
+
}
|
3459 |
+
}
|
3460 |
+
$ret .= '<table style="border-collapse: collapse; '.$css_table.'"><tr>' . implode( '</tr><tr>', $rows ) . '</tr></table>';
|
3461 |
+
|
3462 |
+
// Activities counters
|
3463 |
+
$activites = $wpdb->get_results( 'SELECT user_login, COUNT(user_login) cnt FROM ' . CERBER_LOG_TABLE . ' WHERE activity = 51 AND stamp > ' . $stamp . ' GROUP by user_login ORDER BY cnt DESC LIMIT 10' );
|
3464 |
+
if ( $activites ) {
|
3465 |
+
$rows = array();
|
3466 |
+
$rows[] = '<td style="'.$css_td.$css_boder.'" colspan="2"><p style="line-height: 1.5em; font-weight: bold;">'.__('Attempts to log in with non-existent username','wp-cerber').'</p></td>';
|
3467 |
+
foreach ( $activites as $a ) {
|
3468 |
+
$rows[] = '<td style="'.$css_boder.$css_td.'">' . htmlspecialchars($a->user_login) . '</td><td style="padding: 0.5em; text-align: center; width:10%;'.$css_boder.'"><a href="'.$base_url.'&filter_login='.$a->user_login.'">' . $a->cnt . '</a></td>';
|
3469 |
+
}
|
3470 |
+
$ret .= '<table style="border-collapse: collapse; '.$css_table.'"><tr>' . implode( '</tr><tr>', $rows ) . '</tr></table>';
|
3471 |
+
}
|
3472 |
+
|
3473 |
+
$ret = '<div style="width:100%; padding: 1em; text-align: center; background-color: #f9f9f9;">' . $ret . '</div>';
|
3474 |
+
|
3475 |
+
return $ret;
|
3476 |
+
}
|
3477 |
+
|
3478 |
+
|
3479 |
+
// Maintenance routines ----------------------------------------------------------------
|
3480 |
+
|
3481 |
+
function cerber_init_cron(){
|
3482 |
+
$next_hour = floor( ( time() + 3600 ) / 3600 ) * 3600;
|
3483 |
+
|
3484 |
+
if ( ! wp_next_scheduled( 'cerber_hourly_1' ) ) {
|
3485 |
+
wp_schedule_event( $next_hour + 600, 'hourly', 'cerber_hourly_1' );
|
3486 |
+
}
|
3487 |
+
|
3488 |
+
if ( ! wp_next_scheduled( 'cerber_hourly_2' ) ) {
|
3489 |
+
wp_schedule_event( $next_hour , 'hourly', 'cerber_hourly_2' );
|
3490 |
+
}
|
3491 |
+
|
3492 |
+
if ( ! wp_next_scheduled( 'cerber_daily' ) ) {
|
3493 |
+
wp_schedule_event( $next_hour + 3600, 'daily', 'cerber_daily' );
|
3494 |
+
}
|
3495 |
+
}
|
3496 |
+
|
3497 |
+
add_action( 'cerber_hourly_1', 'cerber_do_hourly' );
|
3498 |
+
function cerber_do_hourly($force = false) {
|
3499 |
+
global $wpdb, $wp_cerber;
|
3500 |
+
|
3501 |
+
if (is_multisite()) {
|
3502 |
+
if ( ! $force && get_site_transient( 'cerber_multisite' ) ) {
|
3503 |
+
return;
|
3504 |
+
}
|
3505 |
+
set_site_transient( 'cerber_multisite', 'executed', 3600 );
|
3506 |
+
}
|
3507 |
+
|
3508 |
+
if ( crb_get_settings( 'cerberlab' ) ) {
|
3509 |
+
lab_check_nodes();
|
3510 |
+
}
|
3511 |
+
|
3512 |
+
$time = time();
|
3513 |
+
$days = absint( crb_get_settings( 'keeplog' ) );
|
3514 |
+
if ( $days > 0 ) {
|
3515 |
+
$wpdb->query( 'DELETE FROM ' . CERBER_LOG_TABLE . ' WHERE stamp < ' . ( $time - $days * 24 * 3600 ) );
|
3516 |
+
}
|
3517 |
+
$days = absint( crb_get_settings( 'tikeeprec' ) );
|
3518 |
+
if ( $days > 0 ) {
|
3519 |
+
$wpdb->query( 'DELETE FROM ' . CERBER_TRAF_TABLE . ' WHERE stamp < ' . ( $time - $days * 24 * 3600 ) );
|
3520 |
+
}
|
3521 |
+
|
3522 |
+
if ( crb_get_settings( 'cerberlab' ) ) {
|
3523 |
+
cerber_push_lab();
|
3524 |
+
}
|
3525 |
+
|
3526 |
+
$wpdb->query( 'DELETE FROM ' . CERBER_LAB_IP_TABLE . ' WHERE expires < ' . $time );
|
3527 |
+
|
3528 |
+
if ( $wp_cerber->getSettings( 'trashafter-enabled') && absint($wp_cerber->getSettings('trashafter'))) {
|
3529 |
+
$list = get_comments( array( 'status' => 'spam' ) );
|
3530 |
+
if ( $list ) {
|
3531 |
+
$time = time() - DAY_IN_SECONDS * absint($wp_cerber->getSettings( 'trashafter' ));
|
3532 |
+
foreach ( $list as $item ) {
|
3533 |
+
if ( $time > strtotime( $item->comment_date_gmt ) ) {
|
3534 |
+
wp_trash_comment( $item->comment_ID );
|
3535 |
+
}
|
3536 |
+
}
|
3537 |
+
}
|
3538 |
+
}
|
3539 |
+
|
3540 |
+
cerber_up_data();
|
3541 |
+
|
3542 |
+
set_site_transient( 'crb_hourly_1', date( 'G' ) , 3600 );
|
3543 |
+
}
|
3544 |
+
|
3545 |
+
add_action( 'cerber_hourly_2', function () {
|
3546 |
+
|
3547 |
+
// Avoid multiple executions on a weird hosting
|
3548 |
+
if ( ( $hour = get_site_transient( 'crb_hourly_2' ) ) && $hour == date( 'G' ) ) {
|
3549 |
+
return;
|
3550 |
+
}
|
3551 |
+
|
3552 |
+
$gmt_offset = get_option( 'gmt_offset' ) * 3600;
|
3553 |
+
|
3554 |
+
if ( crb_get_settings( 'enable-report' )
|
3555 |
+
&& date( 'w', time() + $gmt_offset ) == crb_get_settings( 'wreports-day' )
|
3556 |
+
&& date( 'G', time() + $gmt_offset ) == crb_get_settings( 'wreports-time' )
|
3557 |
+
//&& ! get_site_transient( 'cerber_wreport' )
|
3558 |
+
) {
|
3559 |
+
$result = cerber_send_notify( 'report' );
|
3560 |
+
//set_site_transient( 'cerber_wreport', 'sent', 7200 );
|
3561 |
+
update_site_option( '_cerber_report', array( time(), $result ) );
|
3562 |
+
}
|
3563 |
+
|
3564 |
+
cerber_watchdog( true );
|
3565 |
+
|
3566 |
+
set_site_transient( 'crb_hourly_2', date( 'G' ) , 3600 );
|
3567 |
+
});
|
3568 |
+
|
3569 |
+
add_action( 'cerber_daily', 'cerber_do_daily' );
|
3570 |
+
function cerber_do_daily() {
|
3571 |
+
global $wpdb, $wp_cerber;
|
3572 |
+
|
3573 |
+
cerber_do_hourly( true );
|
3574 |
+
|
3575 |
+
$time = time();
|
3576 |
+
|
3577 |
+
lab_trunc_push();
|
3578 |
+
|
3579 |
+
lab_validate_lic();
|
3580 |
+
|
3581 |
+
$wpdb->query( 'DELETE FROM ' . CERBER_LAB_NET_TABLE . ' WHERE expires < ' . $time );
|
3582 |
+
|
3583 |
+
$wpdb->query( 'OPTIMIZE TABLE ' . CERBER_LOG_TABLE );
|
3584 |
+
$wpdb->query( 'OPTIMIZE TABLE ' . CERBER_TRAF_TABLE );
|
3585 |
+
$wpdb->query( 'OPTIMIZE TABLE ' . CERBER_ACL_TABLE );
|
3586 |
+
$wpdb->query( 'OPTIMIZE TABLE ' . CERBER_BLOCKS_TABLE );
|
3587 |
+
$wpdb->query( 'OPTIMIZE TABLE ' . CERBER_LAB_TABLE );
|
3588 |
+
$wpdb->query( 'OPTIMIZE TABLE ' . CERBER_LAB_IP_TABLE );
|
3589 |
+
$wpdb->query( 'OPTIMIZE TABLE ' . CERBER_LAB_NET_TABLE );
|
3590 |
+
|
3591 |
+
if ( $new = cerber_check_version() ) {
|
3592 |
+
$history = get_site_option( '_cerber_notify_new' );
|
3593 |
+
if ( ! $history || ! is_array( $history ) ) {
|
3594 |
+
$history = array();
|
3595 |
+
}
|
3596 |
+
if ( ! in_array( $new['ver'], $history ) ) {
|
3597 |
+
if ( crb_get_settings( 'notify-new-ver' ) ) {
|
3598 |
+
cerber_send_notify( 'new_version', 'Read more: https://wpcerber.com/?plugin_version=' . $new['ver'] );
|
3599 |
+
}
|
3600 |
+
$history[] = $new['ver'];
|
3601 |
+
update_site_option( '_cerber_notify_new', $history );
|
3602 |
+
}
|
3603 |
+
}
|
3604 |
+
|
3605 |
+
// TODO: implement holding previous values for a while
|
3606 |
+
// cerber_antibot_gene();
|
3607 |
+
}
|
3608 |
+
|
3609 |
+
/**
|
3610 |
+
* Log activity
|
3611 |
+
*
|
3612 |
+
* @param int $activity Activity ID
|
3613 |
+
* @param string $login Login used or any additional information
|
3614 |
+
* @param int $user_id User ID
|
3615 |
+
* @param null $ip IP Address
|
3616 |
+
*
|
3617 |
+
* @return false|int
|
3618 |
+
* @since 3.0
|
3619 |
+
*/
|
3620 |
+
function cerber_log( $activity, $login = '', $user_id = 0, $ip = null ) {
|
3621 |
+
global $wpdb, $user_ID, $cerber_logged;
|
3622 |
+
static $logged = array();
|
3623 |
+
$wp_cerber = get_wp_cerber();
|
3624 |
+
|
3625 |
+
$activity = absint( $activity );
|
3626 |
+
|
3627 |
+
if ( isset( $logged[ $activity ] ) ) {
|
3628 |
+
return false;
|
3629 |
+
}
|
3630 |
+
else {
|
3631 |
+
$logged[ $activity ] = true;
|
3632 |
+
}
|
3633 |
+
|
3634 |
+
$cerber_logged[ $activity ] = $activity;
|
3635 |
+
|
3636 |
+
//$wp_cerber->setProcessed();
|
3637 |
+
|
3638 |
+
if ( empty( $ip ) ) {
|
3639 |
+
$ip = $wp_cerber->getRemoteIp();
|
3640 |
+
}
|
3641 |
+
elseif ( ! filter_var( $ip, FILTER_VALIDATE_IP ) ) {
|
3642 |
+
return false;
|
3643 |
+
}
|
3644 |
+
|
3645 |
+
if ( cerber_is_ipv4( $ip ) ) {
|
3646 |
+
$ip_long = ip2long( $ip );
|
3647 |
+
}
|
3648 |
+
else {
|
3649 |
+
$ip_long = 1;
|
3650 |
+
}
|
3651 |
+
|
3652 |
+
if ( empty( $user_id ) ) {
|
3653 |
+
if ( $user_ID ) {
|
3654 |
+
$user_id = $user_ID;
|
3655 |
+
}
|
3656 |
+
else {
|
3657 |
+
$user_ID = 0;
|
3658 |
+
}
|
3659 |
+
}
|
3660 |
+
|
3661 |
+
$user_id = absint( $user_id );
|
3662 |
+
|
3663 |
+
$stamp = cerber_request_time();
|
3664 |
+
|
3665 |
+
$pos = strpos($_SERVER['REQUEST_URI'],'?');
|
3666 |
+
if ($pos) {
|
3667 |
+
$path = substr( $_SERVER['REQUEST_URI'], 0, $pos );
|
3668 |
+
}
|
3669 |
+
else {
|
3670 |
+
$path = $_SERVER['REQUEST_URI'];
|
3671 |
+
}
|
3672 |
+
$url = strip_tags($_SERVER['HTTP_HOST'] . $path);
|
3673 |
+
|
3674 |
+
$why = 0;
|
3675 |
+
if ($activity != 10 && $activity != 11) {
|
3676 |
+
$why = cerber_get_status($ip);
|
3677 |
+
}
|
3678 |
+
|
3679 |
+
$details = $why .'|0|0|0|'. $url;
|
3680 |
+
|
3681 |
+
$country = lab_get_country( $ip );
|
3682 |
+
|
3683 |
+
/*
|
3684 |
+
$ret = $wpdb->query( $wpdb->prepare( 'INSERT INTO ' . CERBER_LOG_TABLE . ' (ip, ip_long, user_login, user_id, stamp, activity, session_id, country, details) VALUES (%s,%d,%s,%d,%f,%d,%s,%s,%s)', $ip, $ip_long, $login, $user_id, $stamp, $activity, $wp_cerber->getSessionID(), $country, $details ) );
|
3685 |
+
if ( ! $ret ) {
|
3686 |
+
// workaround for a WP bugs like this: WP silently doesn't not insert a row into a table
|
3687 |
+
// https://core.trac.wordpress.org/ticket/32315
|
3688 |
+
$ret = $wpdb->insert( CERBER_LOG_TABLE, array(
|
3689 |
+
'ip' => $ip,
|
3690 |
+
'ip_long' => $ip_long,
|
3691 |
+
'user_login' => $login,
|
3692 |
+
'user_id' => $user_id,
|
3693 |
+
'stamp' => $stamp,
|
3694 |
+
'activity' => $activity,
|
3695 |
+
'session_id' => $wp_cerber->getSessionID(),
|
3696 |
+
'country' => $country,
|
3697 |
+
'details' => $details,
|
3698 |
+
), array( '%s', '%d', '%s', '%d', '%f', '%d' ) );
|
3699 |
+
}*/
|
3700 |
+
|
3701 |
+
// @since 6.3
|
3702 |
+
$login = cerber_real_escape( $login );
|
3703 |
+
$details = cerber_real_escape( $details );
|
3704 |
+
$ret = cerber_db_query('INSERT INTO ' . CERBER_LOG_TABLE . ' (ip, ip_long, user_login, user_id, stamp, activity, session_id, country, details)
|
3705 |
+
VALUES ("'.$ip.'",'.$ip_long.',"'.$login.'",'.$user_id.',"'.$stamp.'",'.$activity.',"'.$wp_cerber->getSessionID().'","'.$country.'","'.$details.'")' );
|
3706 |
+
|
3707 |
+
if ( ! $ret ) {
|
3708 |
+
cerber_watchdog();
|
3709 |
+
}
|
3710 |
+
|
3711 |
+
// Subscriptions - notifications for admin ---------------------------------------------------
|
3712 |
+
|
3713 |
+
$subs = cerber_get_site_option( '_cerber_subs' );
|
3714 |
+
|
3715 |
+
if (!empty($subs)) {
|
3716 |
+
foreach ( $subs as $hash => $sub ) {
|
3717 |
+
|
3718 |
+
// Loop through subscription parameters
|
3719 |
+
if ( ! empty( $sub[0] )) {
|
3720 |
+
if ( ! in_array( $activity, $sub[0] ) ) {
|
3721 |
+
continue;
|
3722 |
+
}
|
3723 |
+
}
|
3724 |
+
if ( ! empty( $sub[1] ) && $sub[1] != $user_id ) {
|
3725 |
+
continue;
|
3726 |
+
}
|
3727 |
+
if ( ! empty( $sub[3] ) && ( $ip_long < $sub[2] || $sub[3] < $ip_long ) ) {
|
3728 |
+
continue;
|
3729 |
+
}
|
3730 |
+
if ( ! empty( $sub[4] ) && $sub[4] != $ip ) {
|
3731 |
+
continue;
|
3732 |
+
}
|
3733 |
+
if ( ! empty( $sub[5] ) && $sub[5] != $login ) {
|
3734 |
+
continue;
|
3735 |
+
}
|
3736 |
+
if ( ! empty( $sub[6] ) && (false === strpos( $ip, $sub[6] )) && (false === mb_strpos( $login, $sub[6] )) ) {
|
3737 |
+
continue;
|
3738 |
+
}
|
3739 |
+
|
3740 |
+
// Some parameter(s) matched, prepare and send notification
|
3741 |
+
|
3742 |
+
$labels = cerber_get_labels( 'activity' );
|
3743 |
+
|
3744 |
+
$msg = __( 'Activity', 'wp-cerber' ) . ': ' . $labels[$activity] . "\n\n";
|
3745 |
+
|
3746 |
+
if ( $country ) {
|
3747 |
+
$coname = ' ('.cerber_country_name( $country ).')';
|
3748 |
+
}
|
3749 |
+
else {
|
3750 |
+
$coname = '';
|
3751 |
+
}
|
3752 |
+
|
3753 |
+
$msg .= __( 'IP', 'wp-cerber' ) . ': ' . $ip . $coname. "\n\n";
|
3754 |
+
|
3755 |
+
if ( $user_id && function_exists('get_userdata')) {
|
3756 |
+
$u = get_userdata( $user_id );
|
3757 |
+
$msg .= __( 'User', 'wp-cerber' ) . ': ' . $u->display_name . "\n\n";
|
3758 |
+
}
|
3759 |
+
|
3760 |
+
if ( $login ) {
|
3761 |
+
$msg .= __( 'Username used', 'wp-cerber' ) . ': ' . $login . "\n\n";
|
3762 |
+
}
|
3763 |
+
|
3764 |
+
if ( ! empty( $sub['6'] ) ) {
|
3765 |
+
$msg .= __( 'Search string', 'wp-cerber' ) . ': ' . $sub['6'] . "\n\n";
|
3766 |
+
}
|
3767 |
+
|
3768 |
+
// Link to the Activity admin page
|
3769 |
+
$args = cerber_subscribe_params();
|
3770 |
+
$i = 0;
|
3771 |
+
$link_params = '';
|
3772 |
+
foreach ($args as $arg => $val){
|
3773 |
+
if (is_array($sub[$i])){
|
3774 |
+
foreach ( $sub[ $i ] as $item ) {
|
3775 |
+
$link_params .= '&' . $arg . '[]=' . $item;
|
3776 |
+
}
|
3777 |
+
}
|
3778 |
+
else {
|
3779 |
+
$link_params .= '&' . $arg . '=' . $sub[ $i ];
|
3780 |
+
}
|
3781 |
+
$i++;
|
3782 |
+
}
|
3783 |
+
$link = cerber_admin_link( 'activity' ) . $link_params;
|
3784 |
+
|
3785 |
+
$msg .= __( 'View activity in dashboard', 'wp-cerber' ) . ': ' . $link;
|
3786 |
+
$msg .= "\n\n" . __( 'To unsubscribe click here', 'wp-cerber' ) . ': ' . cerber_admin_link( 'activity' ) . '&unsubscribeme=' . $hash;
|
3787 |
+
|
3788 |
+
cerber_send_notify( 'subs', $msg, $ip );
|
3789 |
+
|
3790 |
+
break; // Just one notification letter per event
|
3791 |
+
}
|
3792 |
+
}
|
3793 |
+
|
3794 |
+
if ( in_array( $activity, array( 16, 17, 40, 56 ) ) ) {
|
3795 |
+
lab_save_push( $ip, $activity, '' );
|
3796 |
+
}
|
3797 |
+
|
3798 |
+
return $ret;
|
3799 |
+
}
|
3800 |
+
|
3801 |
+
/**
|
3802 |
+
* Get records from the log
|
3803 |
+
*
|
3804 |
+
* @param array $activity
|
3805 |
+
* @param array $user
|
3806 |
+
* @param array $order
|
3807 |
+
* @param string $limit
|
3808 |
+
*
|
3809 |
+
* @return array|null
|
3810 |
+
*/
|
3811 |
+
function cerber_get_log($activity = array(), $user = array(), $order = array(), $limit = ''){
|
3812 |
+
global $wpdb;
|
3813 |
+
|
3814 |
+
$where = array();
|
3815 |
+
if ($activity){
|
3816 |
+
$activity = array_map( 'absint', $activity );
|
3817 |
+
$where[] = 'activity IN ('.implode(', ',$activity).')';
|
3818 |
+
}
|
3819 |
+
|
3820 |
+
if ($user['email']){
|
3821 |
+
$user = get_user_by( 'email', $user['email'] );
|
3822 |
+
$where[] = 'user_id = ' . absint( $user->ID );
|
3823 |
+
}
|
3824 |
+
elseif ($user['id']){
|
3825 |
+
$where[] = 'user_id = '.absint($user['id']);
|
3826 |
+
}
|
3827 |
+
|
3828 |
+
$where_sql = '';
|
3829 |
+
if ( $where ) {
|
3830 |
+
$where_sql = ' WHERE ' . implode( ' AND ', $where );
|
3831 |
+
}
|
3832 |
+
|
3833 |
+
$order_sql = '';
|
3834 |
+
if ( $order ) {
|
3835 |
+
if ( ! empty( $order['DESC'] ) ) {
|
3836 |
+
$order_sql = ' ORDER BY ' . preg_replace( '/[^\w]/', '', $order['DESC'] ) . ' DESC ';
|
3837 |
+
}
|
3838 |
+
elseif ( ! empty( $order['ASC'] ) ) {
|
3839 |
+
$order_sql = ' ORDER BY ' . preg_replace( '/[^\w]/', '', $order['ASC'] ) . ' ASC ';
|
3840 |
+
}
|
3841 |
+
}
|
3842 |
+
|
3843 |
+
$limit_sql = '';
|
3844 |
+
if ( $limit ) {
|
3845 |
+
$limit_sql = ' LIMIT ' . preg_replace( '/[^0-9\.]/', '', $limit );
|
3846 |
+
}
|
3847 |
+
|
3848 |
+
// $row = $wpdb->get_row('SELECT * FROM '.CERBER_LOG_TABLE.' WHERE activity = 5 AND user_id = '.absint($user_id) . ' ORDER BY stamp DESC LIMIT 1');
|
3849 |
+
return $wpdb->get_results( 'SELECT * FROM ' . CERBER_LOG_TABLE . ' ' . $where_sql . $order_sql . $limit_sql );
|
3850 |
+
|
3851 |
+
}
|
3852 |
+
|
3853 |
+
/**
|
3854 |
+
* Return the last login record for a given user
|
3855 |
+
*
|
3856 |
+
* @param $user_id int|null
|
3857 |
+
* @param $user_email string
|
3858 |
+
*
|
3859 |
+
* @return array|null|object|string
|
3860 |
+
*/
|
3861 |
+
function cerber_get_last_login( $user_id, $user_email = '' ) {
|
3862 |
+
if ( $user_id ) {
|
3863 |
+
$u = array( 'id' => $user_id );
|
3864 |
+
}
|
3865 |
+
elseif ( $user_email ) {
|
3866 |
+
$u = array( 'email' => $user_email );
|
3867 |
+
}
|
3868 |
+
|
3869 |
+
if ($u) {
|
3870 |
+
$recs = cerber_get_log( array( 5 ), $u, array( 'DESC' => 'stamp' ), 1 );
|
3871 |
+
return $recs[0];
|
3872 |
+
}
|
3873 |
+
|
3874 |
+
return '';
|
3875 |
+
}
|
3876 |
+
|
3877 |
+
function cerber_count_log($activity = array(), $period = 1) {
|
3878 |
+
global $wpdb;
|
3879 |
+
|
3880 |
+
$period = absint( $period );
|
3881 |
+
if ( ! $period ) {
|
3882 |
+
$period = 1;
|
3883 |
+
}
|
3884 |
+
|
3885 |
+
$stamp = time() - $period * 24 * 3600;
|
3886 |
+
|
3887 |
+
// TODO: replace with SELECT COUNT(DISTINCT session_id)
|
3888 |
+
$ret = $wpdb->get_var('SELECT COUNT(ip) FROM '. CERBER_LOG_TABLE .' WHERE activity IN ('.implode(',',$activity).') AND stamp > '. $stamp);
|
3889 |
+
if (!$ret) $ret = 0;
|
3890 |
+
|
3891 |
+
return $ret;
|
3892 |
+
}
|
3893 |
+
|
3894 |
+
/**
|
3895 |
+
* Create a set of parameters for using it in Subscriptions
|
3896 |
+
* The keys are used to built an URL. Values to calculate a hash.
|
3897 |
+
*
|
3898 |
+
* @return array The set of parameters
|
3899 |
+
*/
|
3900 |
+
function cerber_subscribe_params() {
|
3901 |
+
$begin = 0;
|
3902 |
+
$end = 0;
|
3903 |
+
$ip = 0;
|
3904 |
+
if ( ! empty( $_GET['filter_ip'] ) ) {
|
3905 |
+
$ip = cerber_any2range( $_GET['filter_ip'] );
|
3906 |
+
if ( is_array( $ip ) ) {
|
3907 |
+
$begin = $ip['begin'];
|
3908 |
+
$end = $ip['end'];
|
3909 |
+
$ip = 0;
|
3910 |
+
} elseif ( ! $ip ) {
|
3911 |
+
$ip = 0;
|
3912 |
+
}
|
3913 |
+
}
|
3914 |
+
|
3915 |
+
$filter_activity = ( empty( $_GET['filter_activity'] ) ) ? 0 : $_GET['filter_activity'];
|
3916 |
+
$filter_user = ( empty( $_GET['filter_user'] ) ) ? 0 : $_GET['filter_user'];
|
3917 |
+
$filter_login = ( empty( $_GET['filter_login'] ) ) ? 0 : $_GET['filter_login'];
|
3918 |
+
$search_activity = ( empty( $_GET['search_activity'] ) ) ? 0 : $_GET['search_activity'];
|
3919 |
+
$filter_role = ( empty( $_GET['filter_role'] ) ) ? 0 : $_GET['filter_role'];
|
3920 |
+
|
3921 |
+
if ( ! is_array( $filter_activity ) ) {
|
3922 |
+
$filter_activity = array( $filter_activity );
|
3923 |
+
}
|
3924 |
+
$filter_activity = array_filter( $filter_activity );
|
3925 |
+
|
3926 |
+
// 'begin' and 'end' array keys are not used, added for compatibility
|
3927 |
+
return array( 'filter_activity' => $filter_activity, 'filter_user' => $filter_user, 'being' => $begin, 'end' => $end, 'filter_ip' => $ip, 'filter_login' => $filter_login, 'search_activity' => $search_activity, 'filter_role' => $filter_role );
|
3928 |
+
}
|
3929 |
+
|
3930 |
+
/*
|
3931 |
+
Plugin activation
|
3932 |
+
*/
|
3933 |
+
//register_activation_hook( __FILE__, 'cerber_activate' );
|
3934 |
+
register_activation_hook( cerber_plugin_file(), 'cerber_activate' );
|
3935 |
+
function cerber_activate() {
|
3936 |
+
global $wp_version;
|
3937 |
+
$assets_url = cerber_plugin_dir_url() . 'assets';
|
3938 |
+
|
3939 |
+
//cerber_load_lang();
|
3940 |
+
load_plugin_textdomain( 'wp-cerber', false, basename( dirname( __FILE__ ) ) . '/languages' );
|
3941 |
+
|
3942 |
+
if ( version_compare( CERBER_REQ_PHP, phpversion(), '>' ) ) {
|
3943 |
+
cerber_stop_activating( '<h3>' . sprintf( __( 'The WP Cerber requires PHP %s or higher. You are running', 'wp-cerber' ), CERBER_REQ_PHP ) . ' ' . phpversion() . '</h3>' );
|
3944 |
+
}
|
3945 |
+
|
3946 |
+
if ( version_compare( CERBER_REQ_WP, $wp_version, '>' ) ) {
|
3947 |
+
cerber_stop_activating( '<h3>' . sprintf( __( 'The WP Cerber requires WordPress %s or higher. You are running', 'wp-cerber' ), CERBER_REQ_WP ) . ' ' . $wp_version . '</h3>' );
|
3948 |
+
}
|
3949 |
+
|
3950 |
+
$db_errors = cerber_create_db();
|
3951 |
+
if ( $db_errors ) {
|
3952 |
+
$e = '';
|
3953 |
+
foreach ( $db_errors as $db_error ) {
|
3954 |
+
$e .= '<p>' . implode( '</p><p>', $db_error ) . '</p>';
|
3955 |
+
}
|
3956 |
+
cerber_stop_activating( '<h3>' . __( "Can't activate WP Cerber due to a database error.", 'wp-cerber' ) . '</h3>'.$e);
|
3957 |
+
}
|
3958 |
+
|
3959 |
+
cerber_upgrade_all();
|
3960 |
+
|
3961 |
+
cerber_cookie1();
|
3962 |
+
cerber_disable_citadel();
|
3963 |
+
//cerber_get_groove();
|
3964 |
+
|
3965 |
+
$wp_cerber = get_wp_cerber();
|
3966 |
+
|
3967 |
+
cerber_add_white( cerber_get_subnet( $wp_cerber->getRemoteIp() ) , 'My subnet' ); // Protection for non-experienced user
|
3968 |
+
|
3969 |
+
cerber_htaccess_sync();
|
3970 |
+
|
3971 |
+
cerber_set_boot_mode();
|
3972 |
+
|
3973 |
+
cerber_admin_message(
|
3974 |
+
'<img style="float:left; margin-left:-10px;" src="' . $assets_url . '/icon-128x128.png">' .
|
3975 |
+
'<p style="font-size:120%;">' . __( 'WP Cerber is now active and has started protecting your site', 'wp-cerber' ) . '</p>' .
|
3976 |
+
' <p>' . __( 'Your IP address is added to the', 'wp-cerber' ) . ' ' . __( 'White IP Access List', 'wp-cerber' ) .
|
3977 |
+
|
3978 |
+
' <p style="font-size:120%;"><a href="http://wpcerber.com/getting-started/" target="_blank">' . __( 'Getting Started Guide', 'wp-cerber' ) . '</a></p>' .
|
3979 |
+
|
3980 |
+
//' <p><b>' . __( "It's important to check security settings.", 'wp-cerber' ) . '</b> <a href="http://wpcerber.com/" target="_blank">Read Cerber\'s blog</a> ' .
|
3981 |
+
//' <a href="http://wpcerber.com/subscribe-newsletter/" target="_blank">Subscribe to Cerber\'s newsletter</a></p>' .
|
3982 |
+
|
3983 |
+
' <p> </p><p><span class="dashicons dashicons-admin-settings"></span> <a href="' . cerber_admin_link( 'main' ) . '">' . __( 'Main Settings', 'wp-cerber' ) . '</a>' .
|
3984 |
+
' <span style="margin-left:20px;" class="dashicons dashicons-admin-network"></span> <a href="' . cerber_admin_link( 'acl' ) . '">' . __( 'Access Lists', 'wp-cerber' ) . '</a>' .
|
3985 |
+
' <span style="margin-left:20px;" class="dashicons dashicons-forms"></span> <a href="' . cerber_admin_link( 'antispam' ) . '">' . __( 'Antispam', 'wp-cerber' ) . '</a>' .
|
3986 |
+
' <span style="margin-left:20px;" class="dashicons dashicons-shield-alt"></span> <a href="' . cerber_admin_link( 'hardening' ) . '">' . __( 'Hardening', 'wp-cerber' ) . '</a>' .
|
3987 |
+
' <span style="margin-left:20px;" class="dashicons dashicons-controls-volumeon"></span> <a href="' . cerber_admin_link( 'notifications' ) . '">' . __( 'Notifications', 'wp-cerber' ) . '</a>' .
|
3988 |
+
' <span style="margin-left:20px;" class="dashicons dashicons-admin-tools"></span> <a href="' . cerber_admin_link( 'imex' ) . '">' . __( 'Import settings', 'wp-cerber' ) . '</a>' .
|
3989 |
+
'</p>' );
|
3990 |
+
|
3991 |
+
|
3992 |
+
// Check for existing options
|
3993 |
+
$opt = cerber_get_options();
|
3994 |
+
|
3995 |
+
if ( !empty( $opt ) && is_array( $opt ) ) {
|
3996 |
+
$opt = array_filter( $opt );
|
3997 |
+
if ( ! empty( $opt ) ) {
|
3998 |
+
return;
|
3999 |
+
}
|
4000 |
+
}
|
4001 |
+
|
4002 |
+
cerber_load_defaults();
|
4003 |
+
|
4004 |
+
cerber_send_notify( 'activated' );
|
4005 |
+
|
4006 |
+
$pi = get_file_data( cerber_plugin_file(), array( 'Version' => 'Version' ), 'plugin' );
|
4007 |
+
$pi ['time'] = time();
|
4008 |
+
$pi ['user'] = get_current_user_id();
|
4009 |
+
update_site_option( '_cerber_activated', $pi );
|
4010 |
+
}
|
4011 |
+
|
4012 |
+
/*
|
4013 |
+
Abort activating plugin!
|
4014 |
+
*/
|
4015 |
+
function cerber_stop_activating( $msg ) {
|
4016 |
+
//deactivate_plugins( plugin_basename( __FILE__ ) );
|
4017 |
+
deactivate_plugins( cerber_plug_in() );
|
4018 |
+
wp_die( $msg );
|
4019 |
+
}
|
4020 |
+
|
4021 |
+
/**
|
4022 |
+
* Upgrade database tables, data and plugin settings
|
4023 |
+
*
|
4024 |
+
* @since 3.0
|
4025 |
+
*
|
4026 |
+
*/
|
4027 |
+
function cerber_upgrade_all() {
|
4028 |
+
$ver = cerber_get_site_option( '_cerber_up' );
|
4029 |
+
if ( ! $ver || $ver['v'] != CERBER_VER ) {
|
4030 |
+
cerber_create_db();
|
4031 |
+
cerber_upgrade_db();
|
4032 |
+
cerber_acl_fixer( true );
|
4033 |
+
cerber_push_the_news( CERBER_VER );
|
4034 |
+
cerber_antibot_gene( true );
|
4035 |
+
cerber_upgrade_options();
|
4036 |
+
wp_clear_scheduled_hook( 'cerber_hourly' ); // @since 5.8
|
4037 |
+
update_site_option( '_cerber_up', array( 'v' => CERBER_VER, 't' => time() ) );
|
4038 |
+
}
|
4039 |
+
}
|
4040 |
+
|
4041 |
+
/**
|
4042 |
+
* Creates DB tables if they don't exist
|
4043 |
+
*
|
4044 |
+
* @param bool $recreate If true, recreate some tables completely (with data lost)
|
4045 |
+
*
|
4046 |
+
* @return array Errors
|
4047 |
+
*/
|
4048 |
+
function cerber_create_db($recreate = true) {
|
4049 |
+
global $wpdb;
|
4050 |
+
|
4051 |
+
$wpdb->hide_errors();
|
4052 |
+
$db_errors = array();
|
4053 |
+
$sql = array();
|
4054 |
+
|
4055 |
+
if (!cerber_is_table(CERBER_LOG_TABLE)){
|
4056 |
+
$sql[] = "
|
4057 |
+
CREATE TABLE IF NOT EXISTS " . CERBER_LOG_TABLE . " (
|
4058 |
+
ip varchar(39) CHARACTER SET ascii NOT NULL COMMENT 'Remote IP',
|
4059 |
+
user_login varchar(60) NOT NULL COMMENT 'Username from HTTP request',
|
4060 |
+
user_id bigint(20) unsigned NOT NULL DEFAULT '0',
|
4061 |
+
stamp bigint(20) unsigned NOT NULL COMMENT 'Unix timestamp',
|
4062 |
+
activity int(10) unsigned NOT NULL DEFAULT '0',
|
4063 |
+
KEY ip (ip)
|
4064 |
+
) DEFAULT CHARSET=utf8 COMMENT='Cerber activity log';
|
4065 |
+
";
|
4066 |
+
}
|
4067 |
+
|
4068 |
+
if (!cerber_is_table(CERBER_ACL_TABLE)){
|
4069 |
+
$sql[] = "
|
4070 |
+
CREATE TABLE IF NOT EXISTS " . CERBER_ACL_TABLE . " (
|
4071 |
+
ip varchar(39) CHARACTER SET ascii NOT NULL COMMENT 'IP',
|
4072 |
+
tag char(1) NOT NULL COMMENT 'Type: B or W',
|
4073 |
+
comments varchar(250) NOT NULL,
|
4074 |
+
UNIQUE KEY ip (ip)
|
4075 |
+
) DEFAULT CHARSET=utf8 COMMENT='Cerber IP Access Lists';
|
4076 |
+
";
|
4077 |
+
}
|
4078 |
+
|
4079 |
+
if (!cerber_is_table(CERBER_BLOCKS_TABLE)){
|
4080 |
+
$sql[] = "
|
4081 |
+
CREATE TABLE IF NOT EXISTS " . CERBER_BLOCKS_TABLE . " (
|
4082 |
+
ip varchar(39) CHARACTER SET ascii NOT NULL COMMENT 'Remote IP',
|
4083 |
+
block_until bigint(20) unsigned NOT NULL COMMENT 'Unix timestamp',
|
4084 |
+
reason varchar(250) NOT NULL COMMENT 'Why IP was blocked',
|
4085 |
+
UNIQUE KEY ip (ip)
|
4086 |
+
) DEFAULT CHARSET=utf8 COMMENT='Cerber list of currently blocked IPs';
|
4087 |
+
";
|
4088 |
+
}
|
4089 |
+
|
4090 |
+
if (!cerber_is_table(CERBER_LAB_TABLE)){
|
4091 |
+
$sql[] = "
|
4092 |
+
CREATE TABLE IF NOT EXISTS " . CERBER_LAB_TABLE . " (
|
4093 |
+
ip varchar(39) CHARACTER SET ascii NOT NULL COMMENT 'Remote IP',
|
4094 |
+
reason_id int(11) unsigned NOT NULL DEFAULT '0',
|
4095 |
+
stamp bigint(20) unsigned NOT NULL COMMENT 'Unix timestamp',
|
4096 |
+
details text NOT NULL
|
4097 |
+
) DEFAULT CHARSET=utf8 COMMENT='Cerber lab cache';
|
4098 |
+
";
|
4099 |
+
}
|
4100 |
+
|
4101 |
+
|
4102 |
+
if ($recreate || !cerber_is_table(CERBER_LAB_IP_TABLE)){
|
4103 |
+
if ( $recreate && cerber_is_table( CERBER_LAB_IP_TABLE ) ) {
|
4104 |
+
$sql[] = 'DROP TABLE IF EXISTS ' . CERBER_LAB_IP_TABLE;
|
4105 |
+
}
|
4106 |
+
$sql[] = "
|
4107 |
+
CREATE TABLE IF NOT EXISTS " . CERBER_LAB_IP_TABLE . " (
|
4108 |
+
ip varchar(39) CHARACTER SET ascii NOT NULL COMMENT 'IP',
|
4109 |
+
reputation INT(11) UNSIGNED NOT NULL COMMENT 'Reputation of IP',
|
4110 |
+
expires INT(11) UNSIGNED NOT NULL COMMENT 'Unix timestamp',
|
4111 |
+
PRIMARY KEY (ip)
|
4112 |
+
) DEFAULT CHARSET=utf8 COMMENT='Cerber lab IP cache';
|
4113 |
+
";
|
4114 |
+
}
|
4115 |
+
|
4116 |
+
if ( $recreate || ! cerber_is_table( CERBER_LAB_NET_TABLE ) ) {
|
4117 |
+
if ( $recreate && cerber_is_table( CERBER_LAB_NET_TABLE ) ) {
|
4118 |
+
$sql[] = 'DROP TABLE IF EXISTS ' . CERBER_LAB_NET_TABLE;
|
4119 |
+
}
|
4120 |
+
$sql[] = '
|
4121 |
+
CREATE TABLE IF NOT EXISTS ' . CERBER_LAB_NET_TABLE . ' (
|
4122 |
+
ip varchar(39) CHARACTER SET ascii NOT NULL DEFAULT "" COMMENT "IP address",
|
4123 |
+
ip_long_begin BIGINT UNSIGNED NOT NULL DEFAULT "0",
|
4124 |
+
ip_long_end BIGINT UNSIGNED NOT NULL DEFAULT "0",
|
4125 |
+
country CHAR(3) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "" COMMENT "Country code",
|
4126 |
+
expires INT(11) UNSIGNED NOT NULL DEFAULT "0",
|
4127 |
+
PRIMARY KEY (ip),
|
4128 |
+
UNIQUE KEY begin_end (ip_long_begin, ip_long_end)
|
4129 |
+
) DEFAULT CHARSET=utf8 COMMENT="Cerber lab network cache";
|
4130 |
+
';
|
4131 |
+
}
|
4132 |
+
|
4133 |
+
if (!cerber_is_table(CERBER_GEO_TABLE)){
|
4134 |
+
$sql[] = '
|
4135 |
+
CREATE TABLE IF NOT EXISTS ' . CERBER_GEO_TABLE . ' (
|
4136 |
+
country CHAR(3) NOT NULL DEFAULT "" COMMENT "Country code",
|
4137 |
+
locale CHAR(10) NOT NULL DEFAULT "" COMMENT "Locale i18n",
|
4138 |
+
country_name VARCHAR(250) NOT NULL DEFAULT "" COMMENT "Country name",
|
4139 |
+
PRIMARY KEY (country, locale)
|
4140 |
+
) DEFAULT CHARSET=utf8;
|
4141 |
+
';
|
4142 |
+
}
|
4143 |
+
|
4144 |
+
if (!cerber_is_table(CERBER_TRAF_TABLE)){
|
4145 |
+
$sql[] = '
|
4146 |
+
CREATE TABLE IF NOT EXISTS ' . CERBER_TRAF_TABLE . ' (
|
4147 |
+
ip varchar(39) CHARACTER SET ascii NOT NULL,
|
4148 |
+
ip_long BIGINT UNSIGNED NOT NULL DEFAULT "0",
|
4149 |
+
hostname varchar(250) NOT NULL DEFAULT "",
|
4150 |
+
uri text NOT NULL,
|
4151 |
+
request_fields MEDIUMTEXT NOT NULL,
|
4152 |
+
request_details MEDIUMTEXT NOT NULL,
|
4153 |
+
session_id char(32) CHARACTER SET ascii NOT NULL,
|
4154 |
+
user_id bigint(20) UNSIGNED NOT NULL DEFAULT 0,
|
4155 |
+
stamp decimal(14,4) NOT NULL,
|
4156 |
+
processing int(10) NOT NULL DEFAULT 0,
|
4157 |
+
country char(3) CHARACTER SET ascii NOT NULL DEFAULT "",
|
4158 |
+
request_method char(8) CHARACTER SET ascii NOT NULL,
|
4159 |
+
http_code int(10) UNSIGNED NOT NULL,
|
4160 |
+
wp_id bigint(20) UNSIGNED NOT NULL DEFAULT 0,
|
4161 |
+
wp_type int(10) UNSIGNED NOT NULL DEFAULT 0,
|
4162 |
+
is_bot int(10) UNSIGNED NOT NULL DEFAULT 0,
|
4163 |
+
blog_id int(10) UNSIGNED NOT NULL DEFAULT 0,
|
4164 |
+
KEY stamp (stamp)
|
4165 |
+
) DEFAULT CHARSET=utf8;
|
4166 |
+
';
|
4167 |
+
}
|
4168 |
+
|
4169 |
+
foreach ( $sql as $query ) {
|
4170 |
+
if ( ! $wpdb->query( $query ) && $wpdb->last_error ) {
|
4171 |
+
$db_errors[] = array( $wpdb->last_error, $wpdb->last_query );
|
4172 |
+
}
|
4173 |
+
}
|
4174 |
+
|
4175 |
+
return $db_errors;
|
4176 |
+
}
|
4177 |
+
|
4178 |
+
/**
|
4179 |
+
* Upgrade structure of existing DB tables
|
4180 |
+
*
|
4181 |
+
* @return array Errors during upgrading
|
4182 |
+
* @since 3.0
|
4183 |
+
*/
|
4184 |
+
function cerber_upgrade_db( $force = false ) {
|
4185 |
+
global $wpdb;
|
4186 |
+
$wpdb->hide_errors();
|
4187 |
+
if ($force) $wpdb->suppress_errors();
|
4188 |
+
$db_errors = array();
|
4189 |
+
$sql = array();
|
4190 |
+
|
4191 |
+
// @since 3.0
|
4192 |
+
$sql[] = 'ALTER TABLE ' . CERBER_LOG_TABLE . ' CHANGE stamp stamp DECIMAL(14,4) NOT NULL';
|
4193 |
+
|
4194 |
+
// @since 3.1
|
4195 |
+
if ( $force || ! cerber_is_column( CERBER_LOG_TABLE, 'ip_long' ) ) {
|
4196 |
+
$sql[] = 'ALTER TABLE ' . CERBER_LOG_TABLE . ' ADD ip_long BIGINT UNSIGNED NOT NULL DEFAULT "0" COMMENT "IPv4 long" AFTER ip, ADD INDEX (ip_long)';
|
4197 |
+
}
|
4198 |
+
if ( $force || ! cerber_is_column( CERBER_ACL_TABLE, 'ip_long_begin' ) ) {
|
4199 |
+
$sql[] = 'ALTER TABLE ' . CERBER_ACL_TABLE . " ADD ip_long_begin BIGINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'IPv4 range begin' AFTER ip, ADD ip_long_end BIGINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'IPv4 range end' AFTER ip_long_begin";
|
4200 |
+
}
|
4201 |
+
if ( $force || !cerber_is_index( CERBER_ACL_TABLE, 'ip_begin_end' ) ) {
|
4202 |
+
$sql[] = 'ALTER TABLE ' . CERBER_ACL_TABLE . ' ADD UNIQUE ip_begin_end (ip, ip_long_begin, ip_long_end)';
|
4203 |
+
}
|
4204 |
+
if ( $force || cerber_is_index( CERBER_ACL_TABLE, 'ip' ) ) {
|
4205 |
+
$sql[] = 'ALTER TABLE ' . CERBER_ACL_TABLE . ' DROP INDEX ip';
|
4206 |
+
}
|
4207 |
+
|
4208 |
+
// @since 4.8.2
|
4209 |
+
if ( $force || cerber_is_index( CERBER_ACL_TABLE, 'begin_end' ) ) {
|
4210 |
+
$sql[] = 'ALTER TABLE ' . CERBER_ACL_TABLE . ' DROP INDEX begin_end';
|
4211 |
+
}
|
4212 |
+
if ( $force || !cerber_is_index( CERBER_ACL_TABLE, 'begin_end_tag' ) ) {
|
4213 |
+
$sql[] = 'ALTER TABLE ' . CERBER_ACL_TABLE . ' ADD INDEX begin_end_tag (ip_long_begin, ip_long_end, tag)';
|
4214 |
+
}
|
4215 |
+
|
4216 |
+
// @since 4.9
|
4217 |
+
if ( $force || ! cerber_is_column( CERBER_LOG_TABLE, 'session_id' ) ) {
|
4218 |
+
$sql[] = 'ALTER TABLE ' . CERBER_LOG_TABLE . '
|
4219 |
+
ADD session_id CHAR(32) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "",
|
4220 |
+
ADD country CHAR(3) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "" COMMENT "Country code",
|
4221 |
+
ADD details VARCHAR(250) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "" COMMENT "Details about HTTP request";
|
4222 |
+
';
|
4223 |
+
}
|
4224 |
+
|
4225 |
+
// @since 6.1
|
4226 |
+
if ( $force || !cerber_is_index( CERBER_LOG_TABLE, 'session_index' ) ) {
|
4227 |
+
$sql[] = 'ALTER TABLE ' . CERBER_LOG_TABLE . ' ADD INDEX session_index (session_id)';
|
4228 |
+
}
|
4229 |
+
|
4230 |
+
if (!empty($sql)) {
|
4231 |
+
foreach ( $sql as $query ) {
|
4232 |
+
if ( !$wpdb->query( $query ) && $wpdb->last_error ) {
|
4233 |
+
$db_errors[] = array( $wpdb->last_error, $wpdb->last_query );
|
4234 |
+
}
|
4235 |
+
}
|
4236 |
+
}
|
4237 |
+
|
4238 |
+
// Convert existing data into the new format
|
4239 |
+
|
4240 |
+
cerber_acl_fixer();
|
4241 |
+
|
4242 |
+
if ( $db_errors ) {
|
4243 |
+
update_site_option( '_cerber_db_errors', $db_errors );
|
4244 |
+
}
|
4245 |
+
else {
|
4246 |
+
update_site_option( '_cerber_db_errors', '' );
|
4247 |
+
}
|
4248 |
+
|
4249 |
+
return $db_errors;
|
4250 |
+
}
|
4251 |
+
|
4252 |
+
/**
|
4253 |
+
* Updating old activity log records to the new row format (has been introduced in v 3.1)
|
4254 |
+
*
|
4255 |
+
* @since 4.0
|
4256 |
+
*
|
4257 |
+
*/
|
4258 |
+
function cerber_up_data() {
|
4259 |
+
global $wpdb;
|
4260 |
+
$ips = $wpdb->get_col( 'SELECT DISTINCT ip FROM ' . CERBER_LOG_TABLE . ' WHERE ip_long = 0 LIMIT 50' );
|
4261 |
+
if ( ! $ips ) {
|
4262 |
+
return;
|
4263 |
+
}
|
4264 |
+
foreach ( $ips as $ip ) {
|
4265 |
+
if ( cerber_is_ipv4( $ip ) ) {
|
4266 |
+
$ip_long = ip2long( $ip );
|
4267 |
+
} else {
|
4268 |
+
$ip_long = 1;
|
4269 |
+
}
|
4270 |
+
$wpdb->query( 'UPDATE ' . CERBER_LOG_TABLE . ' SET ip_long = ' . $ip_long . ' WHERE ip = "' . $ip .'" AND ip_long = 0');
|
4271 |
+
}
|
4272 |
+
}
|
4273 |
+
|
4274 |
+
/**
|
4275 |
+
* Upgrade corrupted / from older versions of the plugin rows in ACL
|
4276 |
+
*
|
4277 |
+
* @param bool $ipv6 if true Process IPv6 addresses
|
4278 |
+
*
|
4279 |
+
*/
|
4280 |
+
function cerber_acl_fixer($ipv6 = false){
|
4281 |
+
global $wpdb;
|
4282 |
+
|
4283 |
+
// Repair/update IPs without long values
|
4284 |
+
$rows = $wpdb->get_col( 'SELECT ip FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin = 0 OR ip_long_end = 0' );
|
4285 |
+
if ( ! $rows ) {
|
4286 |
+
return;
|
4287 |
+
}
|
4288 |
+
foreach ( $rows as $ip ) {
|
4289 |
+
if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
|
4290 |
+
continue;
|
4291 |
+
}
|
4292 |
+
$range = cerber_any2range( $ip );
|
4293 |
+
if ( is_array( $range ) ) {
|
4294 |
+
$begin = $range['begin'];
|
4295 |
+
$end = $range['end'];
|
4296 |
+
}
|
4297 |
+
else {
|
4298 |
+
$begin = ip2long( $ip );
|
4299 |
+
$end = ip2long( $ip );
|
4300 |
+
}
|
4301 |
+
|
4302 |
+
$wpdb->query( 'UPDATE ' . CERBER_ACL_TABLE . ' SET ip_long_begin = ' . $begin . ', ip_long_end = ' . $end . ' WHERE ip = "' . $ip .'"');
|
4303 |
+
}
|
4304 |
+
|
4305 |
+
// Convert old IPv6 to all shortened
|
4306 |
+
if ( $ipv6 ) {
|
4307 |
+
$ips = $wpdb->get_col( 'SELECT ip FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin = 0' );
|
4308 |
+
if ( $ips ) {
|
4309 |
+
foreach ( $ips as $ip ) {
|
4310 |
+
if ( ! filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
|
4311 |
+
continue;
|
4312 |
+
}
|
4313 |
+
$short_ip = cerber_short_ipv6( $ip );
|
4314 |
+
if ($short_ip != $ip) {
|
4315 |
+
$wpdb->query( 'UPDATE ' . CERBER_ACL_TABLE . ' SET ip = "' . $short_ip . '" WHERE ip = "' . $ip . '"' );
|
4316 |
+
}
|
4317 |
+
}
|
4318 |
+
}
|
4319 |
+
}
|
4320 |
+
}
|
4321 |
+
|
4322 |
+
add_action( 'deac' . 'tivate_' . cerber_plug_in(), 'cerber_clean' );
|
4323 |
+
function cerber_clean( $ip ) {
|
4324 |
+
wp_clear_scheduled_hook( 'cerber_hourly_1' );
|
4325 |
+
wp_clear_scheduled_hook( 'cerber_hourly_2' );
|
4326 |
+
wp_clear_scheduled_hook( 'cerber_daily' );
|
4327 |
+
|
4328 |
+
cerber_htaccess_clean_up();
|
4329 |
+
cerber_set_boot_mode( 0 );
|
4330 |
+
|
4331 |
+
$pi = get_file_data( cerber_plugin_file(), array( 'Version' => 'Version' ), 'plugin' );
|
4332 |
+
$pi ['v'] = time();
|
4333 |
+
$pi ['u'] = get_current_user_id();
|
4334 |
+
update_site_option( '_cerber_o' . 'ff', $pi );
|
4335 |
+
$f = 'cerb' . 'er_se' . 'nd_not' . 'ify';
|
4336 |
+
$f( 'sh' . 'utd' . 'own' );
|
4337 |
+
}
|
4338 |
+
|
4339 |
+
/*
|
4340 |
+
Fix an issue with the empty user_id field in the comments table.
|
4341 |
+
*/
|
4342 |
+
add_filter( 'preprocess_comment', 'cerber_add_uid' );
|
4343 |
+
function cerber_add_uid( $commentdata ) {
|
4344 |
+
$current_user = wp_get_current_user();
|
4345 |
+
$commentdata['user_ID'] = $current_user->ID;
|
4346 |
+
|
4347 |
+
return $commentdata;
|
4348 |
+
}
|
4349 |
+
|
4350 |
+
/**
|
4351 |
+
* Load jQuery on the page
|
4352 |
+
*
|
4353 |
+
*/
|
4354 |
+
add_action( 'login_enqueue_scripts', 'cerber_login_scripts' );
|
4355 |
+
function cerber_login_scripts() {
|
4356 |
+
if ( cerber_antibot_enabled( array('botsreg', 'botsany') ) ) {
|
4357 |
+
wp_enqueue_script( 'jquery' );
|
4358 |
+
}
|
4359 |
+
}
|
4360 |
+
add_action( 'wp_enqueue_scripts', 'cerber_scripts' );
|
4361 |
+
function cerber_scripts() {
|
4362 |
+
global $wp_cerber;
|
4363 |
+
if ( ( is_singular() && cerber_antibot_enabled( array( 'botscomm', 'botsany' ) ) )
|
4364 |
+
|| ( $wp_cerber->getSettings( 'sitekey' ) && $wp_cerber->getSettings( 'secretkey' ) )
|
4365 |
+
) {
|
4366 |
+
wp_enqueue_script( 'jquery' );
|
4367 |
+
}
|
4368 |
+
}
|
4369 |
+
|
4370 |
+
/**
|
4371 |
+
* Footer stuff
|
4372 |
+
* Explicit rendering reCAPTCHA
|
4373 |
+
*
|
4374 |
+
*/
|
4375 |
+
add_action( 'login_footer', 'cerber_login_foo', 1000 );
|
4376 |
+
function cerber_login_foo( $ip ) {
|
4377 |
+
global $wp_cerber;
|
4378 |
+
|
4379 |
+
cerber_antibot_code(array( 'botsreg', 'botsany' ));
|
4380 |
+
|
4381 |
+
// Universal JS
|
4382 |
+
if (!$wp_cerber->recaptcha_here) return;
|
4383 |
+
|
4384 |
+
$sitekey = $wp_cerber->getSettings('sitekey');
|
4385 |
+
|
4386 |
+
if (!$wp_cerber->getSettings('invirecap')){
|
4387 |
+
// Classic version (visible reCAPTCHA)
|
4388 |
+
echo '<script src = https://www.google.com/recaptcha/api.js?hl='.cerber_recaptcha_lang().' async defer></script>';
|
4389 |
+
}
|
4390 |
+
else {
|
4391 |
+
// Pure JS version with explicit rendering
|
4392 |
+
?>
|
4393 |
+
<script src="https://www.google.com/recaptcha/api.js?onload=init_recaptcha_widgets&render=explicit&hl=<?php echo cerber_recaptcha_lang(); ?>" async defer></script>
|
4394 |
+
<script type='text/javascript'>
|
4395 |
+
|
4396 |
+
document.getElementById("cerber-recaptcha").remove();
|
4397 |
+
|
4398 |
+
var init_recaptcha_widgets = function () {
|
4399 |
+
for (var i = 0; i < document.forms.length; ++i) {
|
4400 |
+
var form = document.forms[i];
|
4401 |
+
var place = form.querySelector('.cerber-form-marker');
|
4402 |
+
if (null !== place) render_recaptcha_widget(form, place);
|
4403 |
+
}
|
4404 |
+
};
|
4405 |
+
|
4406 |
+
function render_recaptcha_widget(form, place) {
|
4407 |
+
var place_id = grecaptcha.render(place, {
|
4408 |
+
'callback': function (g_recaptcha_response) {
|
4409 |
+
HTMLFormElement.prototype.submit.call(form);
|
4410 |
+
},
|
4411 |
+
'sitekey': '<?php echo $sitekey; ?>',
|
4412 |
+
'size': 'invisible',
|
4413 |
+
'badge': 'bottomright'
|
4414 |
+
});
|
4415 |
+
|
4416 |
+
form.onsubmit = function (event) {
|
4417 |
+
event.preventDefault();
|
4418 |
+
grecaptcha.execute(place_id);
|
4419 |
+
};
|
4420 |
+
|
4421 |
+
}
|
4422 |
+
</script>
|
4423 |
+
<?php
|
4424 |
+
}
|
4425 |
+
}
|
4426 |
+
|
4427 |
+
/**
|
4428 |
+
* Inline reCAPTCHA widget
|
4429 |
+
*
|
4430 |
+
*/
|
4431 |
+
add_action( 'wp_footer', 'cerber_foo', 1000 );
|
4432 |
+
function cerber_foo() {
|
4433 |
+
global $wp_cerber;
|
4434 |
+
|
4435 |
+
if (is_singular()) cerber_antibot_code( array( 'botscomm', 'botsany' ) );
|
4436 |
+
|
4437 |
+
if (!$wp_cerber->recaptcha_here) return;
|
4438 |
+
|
4439 |
+
// jQuery version with support visible and invisible reCAPTCHA
|
4440 |
+
// TODO: convert it into pure JS
|
4441 |
+
?>
|
4442 |
+
<script type="text/javascript">
|
4443 |
+
|
4444 |
+
jQuery(document).ready(function ($) {
|
4445 |
+
|
4446 |
+
var recaptcha_ok = false;
|
4447 |
+
var the_recaptcha_widget = $("#cerber-recaptcha");
|
4448 |
+
var is_recaptcha_visible = ($(the_recaptcha_widget).data('size') !== 'invisible');
|
4449 |
+
|
4450 |
+
var the_form = $(the_recaptcha_widget).closest("form");
|
4451 |
+
var the_button = $(the_form).find('input[type="submit"]');
|
4452 |
+
if (!the_button.length) {
|
4453 |
+
the_button = $(the_form).find(':button');
|
4454 |
+
}
|
4455 |
+
|
4456 |
+
// visible
|
4457 |
+
if (the_button.length && is_recaptcha_visible) {
|
4458 |
+
the_button.prop("disabled", true);
|
4459 |
+
the_button.css("opacity", 0.5);
|
4460 |
+
}
|
4461 |
+
|
4462 |
+
window.form_button_enabler = function () {
|
4463 |
+
if (!the_button.length) return;
|
4464 |
+
the_button.prop("disabled", false);
|
4465 |
+
the_button.css( "opacity", 1 );
|
4466 |
+
};
|
4467 |
+
|
4468 |
+
// invisible
|
4469 |
+
if (!is_recaptcha_visible) {
|
4470 |
+
$(the_button).click(function (event) {
|
4471 |
+
if (recaptcha_ok) return;
|
4472 |
+
event.preventDefault();
|
4473 |
+
grecaptcha.execute();
|
4474 |
+
});
|
4475 |
+
}
|
4476 |
+
|
4477 |
+
window.now_submit_the_form = function () {
|
4478 |
+
recaptcha_ok = true;
|
4479 |
+
$(the_button).click(); // this is only way to submit a form that contains "submit" inputs
|
4480 |
+
};
|
4481 |
+
});
|
4482 |
+
</script>
|
4483 |
+
<script src = "https://www.google.com/recaptcha/api.js?hl=<?php echo cerber_recaptcha_lang(); ?>" async defer></script>
|
4484 |
+
<?php
|
4485 |
+
}
|
4486 |
+
|
4487 |
+
|
4488 |
+
// Traffic Logging ======================================================================
|
4489 |
+
|
4490 |
+
//add_action( 'wp', 'cerber_traffic_log' );
|
4491 |
+
add_action( 'shutdown', function () {
|
4492 |
+
cerber_traffic_log();
|
4493 |
+
} );
|
4494 |
+
register_shutdown_function( 'cerber_traffic_log' );
|
4495 |
+
/**
|
4496 |
+
* Traffic Logging
|
4497 |
+
*
|
4498 |
+
* @since 6.0
|
4499 |
+
*/
|
4500 |
+
function cerber_traffic_log(){
|
4501 |
+
global $wpdb, $wp_query, $wp_cerber_user_id, $wp_cerber_start_stamp, $blog_id;
|
4502 |
+
static $logged = false;
|
4503 |
+
|
4504 |
+
if ( $logged ) {
|
4505 |
+
return;
|
4506 |
+
}
|
4507 |
+
|
4508 |
+
$wp_cerber = get_wp_cerber();
|
4509 |
+
|
4510 |
+
$wp_type = 700;
|
4511 |
+
|
4512 |
+
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
4513 |
+
/*
|
4514 |
+
if ( isset( $_POST['action'] ) && $_POST['action'] == 'heartbeat' ) {
|
4515 |
+
return;
|
4516 |
+
}*/
|
4517 |
+
$wp_type = 500;
|
4518 |
+
}
|
4519 |
+
elseif ( is_admin() ) {
|
4520 |
+
$wp_type = 501;
|
4521 |
+
}
|
4522 |
+
elseif ( defined( 'DOING_CRON' ) && DOING_CRON ) {
|
4523 |
+
$wp_type = 502;
|
4524 |
+
}
|
4525 |
+
elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
|
4526 |
+
$wp_type = 515;
|
4527 |
+
}
|
4528 |
+
elseif ( cerber_is_rest_url() ) {
|
4529 |
+
$wp_type = 520;
|
4530 |
+
}
|
4531 |
+
// Public part starts with 600
|
4532 |
+
elseif ( $wp_query && is_object( $wp_query ) ) {
|
4533 |
+
$wp_type = 600;
|
4534 |
+
if ( $wp_query->is_singular ) {
|
4535 |
+
$wp_type = 601;
|
4536 |
+
}
|
4537 |
+
elseif ( $wp_query->is_tag ) {
|
4538 |
+
$wp_type = 603;
|
4539 |
+
}
|
4540 |
+
elseif ( $wp_query->is_category ) {
|
4541 |
+
$wp_type = 604;
|
4542 |
+
}
|
4543 |
+
elseif ( $wp_query->is_search ) {
|
4544 |
+
$wp_type = 605;
|
4545 |
+
}
|
4546 |
+
}
|
4547 |
+
|
4548 |
+
if ( function_exists( 'http_response_code' ) ) { // PHP >= 5.4.0, PHP 7
|
4549 |
+
$http_code = http_response_code();
|
4550 |
+
}
|
4551 |
+
else {
|
4552 |
+
//get_status_header_desc()
|
4553 |
+
// TODO: Add detection for other HTTP codes for PHP 5.3
|
4554 |
+
$http_code = 200;
|
4555 |
+
if ( $wp_type > 600 ) {
|
4556 |
+
if ( $wp_query->is_404 ) {
|
4557 |
+
$http_code = 404;
|
4558 |
+
}
|
4559 |
+
}
|
4560 |
+
}
|
4561 |
+
|
4562 |
+
$user_id = 0;
|
4563 |
+
if ( function_exists( 'get_current_user_id' ) ) {
|
4564 |
+
$user_id = get_current_user_id();
|
4565 |
+
}
|
4566 |
+
if ( ! $user_id && $wp_cerber_user_id ) {
|
4567 |
+
$user_id = absint( $wp_cerber_user_id );
|
4568 |
+
}
|
4569 |
+
|
4570 |
+
if ( ! cerber_to_log( $wp_type, $http_code, $user_id ) ) {
|
4571 |
+
return;
|
4572 |
+
}
|
4573 |
+
|
4574 |
+
$logged = true;
|
4575 |
+
|
4576 |
+
$ua = '';
|
4577 |
+
if ( ! empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
|
4578 |
+
$ua = substr ($_SERVER['HTTP_USER_AGENT'], 0, 1000);
|
4579 |
+
}
|
4580 |
+
|
4581 |
+
$bot = cerber_is_crawler( $ua );
|
4582 |
+
if ( $bot && crb_get_settings( 'tinocrabs' ) ) {
|
4583 |
+
return;
|
4584 |
+
}
|
4585 |
+
|
4586 |
+
$ip = $wp_cerber->getRemoteIp();
|
4587 |
+
$ip_long = 0;
|
4588 |
+
if ( cerber_is_ipv4( $ip ) ) {
|
4589 |
+
$ip_long = ip2long( $ip );
|
4590 |
+
}
|
4591 |
+
|
4592 |
+
$wp_id = 0;
|
4593 |
+
if ( $wp_query && is_object( $wp_query ) ) {
|
4594 |
+
$wp_id = absint( $wp_query->get_queried_object_id() );
|
4595 |
+
}
|
4596 |
+
|
4597 |
+
$session_id = $wp_cerber->getSessionID();
|
4598 |
+
if ( is_ssl() ) {
|
4599 |
+
$scheme = 'https';
|
4600 |
+
}
|
4601 |
+
else {
|
4602 |
+
$scheme = 'http';
|
4603 |
+
}
|
4604 |
+
$uri = $scheme . '://'. $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
4605 |
+
$method = preg_replace( '/[^\w]/', '', $_SERVER['REQUEST_METHOD'] );
|
4606 |
+
|
4607 |
+
// Request fields
|
4608 |
+
|
4609 |
+
$fields = '';
|
4610 |
+
if ( crb_get_settings( 'tifields' ) ) {
|
4611 |
+
$fields = array();
|
4612 |
+
if ( ! empty( $_POST ) ) {
|
4613 |
+
$fields[1] = cerber_prepare_fields( cerber_mask_fields( (array) $_POST ) );
|
4614 |
+
}
|
4615 |
+
if ( ! empty( $_GET ) ) {
|
4616 |
+
$fields[2] = cerber_prepare_fields( (array) $_GET );
|
4617 |
+
}
|
4618 |
+
if ( ! empty( $_FILES ) ) {
|
4619 |
+
$fields[3] = $_FILES;
|
4620 |
+
}
|
4621 |
+
if ( ! empty( $fields ) ) {
|
4622 |
+
$fields = serialize( $fields );
|
4623 |
+
}
|
4624 |
+
else {
|
4625 |
+
$fields = '';
|
4626 |
+
}
|
4627 |
+
}
|
4628 |
+
|
4629 |
+
// Extra request details
|
4630 |
+
|
4631 |
+
$details = array();
|
4632 |
+
if ( $ua ) {
|
4633 |
+
$details[1] = $ua;
|
4634 |
+
}
|
4635 |
+
if ( ! empty( $_SERVER['HTTP_REFERER'] ) ) {
|
4636 |
+
//$ref = mb_substr( $_SERVER['HTTP_REFERER'], 0, 1048576 ); // 1 Mb for ASCII
|
4637 |
+
$details[2] = filter_var( $_SERVER['HTTP_REFERER'], FILTER_SANITIZE_URL );
|
4638 |
+
}
|
4639 |
+
/*
|
4640 |
+
if ( ! empty( $_FILES ) ) {
|
4641 |
+
$details[3] = $_FILES;
|
4642 |
+
}*/
|
4643 |
+
if ( $wp_type == 605 && ! empty( $_GET['s'] ) ) {
|
4644 |
+
$details[4] = $_GET['s'];
|
4645 |
+
}
|
4646 |
+
if ( $wp_type == 515 ) {
|
4647 |
+
// TODO: add a setting to enable it because there is a user/password in the php://input
|
4648 |
+
//$details[5] = file_get_contents('php://input');
|
4649 |
+
}
|
4650 |
+
if ( crb_get_settings( 'tihdrs' ) ) {
|
4651 |
+
$hds = getallheaders();
|
4652 |
+
unset( $hds['Cookie'] );
|
4653 |
+
$details[6] = $hds;
|
4654 |
+
}
|
4655 |
+
if ( crb_get_settings( 'tisenv' ) ) {
|
4656 |
+
$srv = $_SERVER;
|
4657 |
+
unset( $srv['HTTP_COOKIE'] );
|
4658 |
+
$details[7] = $srv;
|
4659 |
+
}
|
4660 |
+
if ( crb_get_settings( 'ticandy' ) && ! empty( $_COOKIE ) ) {
|
4661 |
+
$details[8] = $_COOKIE;
|
4662 |
+
}
|
4663 |
+
if ( !empty( $details ) ) {
|
4664 |
+
/*
|
4665 |
+
foreach ( $details as &$detail ) {
|
4666 |
+
$detail = mb_substr($detail, 0, 1048576); // 1 Mb for ASCII
|
4667 |
+
}*/
|
4668 |
+
$details = cerber_prepare_fields( $details );
|
4669 |
+
$details = serialize($details);
|
4670 |
+
}
|
4671 |
+
else {
|
4672 |
+
$details = '';
|
4673 |
+
}
|
4674 |
+
|
4675 |
+
// Timestamps
|
4676 |
+
if ( ! empty( $wp_cerber_start_stamp ) && is_numeric( $wp_cerber_start_stamp ) ) {
|
4677 |
+
$stamp = (float)$wp_cerber_start_stamp; // define this variable: $wp_cerber_start_stamp = microtime( true ); in wp-config.php
|
4678 |
+
}
|
4679 |
+
else {
|
4680 |
+
$stamp = cerber_request_time();
|
4681 |
+
}
|
4682 |
+
|
4683 |
+
$processing = (int) ( 1000 * ( microtime( true ) - $stamp ) );
|
4684 |
+
|
4685 |
+
$uri = cerber_real_escape($uri);
|
4686 |
+
$fields = cerber_real_escape($fields);
|
4687 |
+
$details = cerber_real_escape($details);
|
4688 |
+
|
4689 |
+
//$uri = $wpdb->remove_placeholder_escape( esc_sql( $uri ) );
|
4690 |
+
//$fields = $wpdb->remove_placeholder_escape( esc_sql( $fields ) );
|
4691 |
+
//$details = $wpdb->remove_placeholder_escape( esc_sql( $details ) );
|
4692 |
+
|
4693 |
+
//$query = $wpdb->prepare( 'INSERT INTO ' . CERBER_TRAF_TABLE . ' (ip, ip_long, uri, request_fields , request_details, session_id, user_id, stamp, processing, request_method, http_code, wp_id, wp_type, is_bot, blog_id ) VALUES ("' .$ip .'", '. $ip_long . ', %s, %s, %s, "' . $session_id . '", ' . $user_id . ', ' . $stamp . ',' . $processing . ', "' . $method . '", ' . $http_code . ',' . $wp_id . ', ' . $wp_type . ', ' . $bot . ', ' . absint($blog_id) . ')', $uri, $fields, $details);
|
4694 |
+
|
4695 |
+
$query = 'INSERT INTO ' . CERBER_TRAF_TABLE . ' (ip, ip_long, uri, request_fields , request_details, session_id, user_id, stamp, processing, request_method, http_code, wp_id, wp_type, is_bot, blog_id ) VALUES ("' . $ip . '", ' . $ip_long . ',"' . $uri . '","' . $fields . '","' . $details . '", "' . $session_id . '", ' . $user_id . ', ' . $stamp . ',' . $processing . ', "' . $method . '", ' . $http_code . ',' . $wp_id . ', ' . $wp_type . ', ' . $bot . ', ' . absint( $blog_id ) . ')';
|
4696 |
+
|
4697 |
+
//$ret = $wpdb->query( $query );
|
4698 |
+
|
4699 |
+
$ret = cerber_db_query( $query );
|
4700 |
+
|
4701 |
+
if (!$ret){
|
4702 |
+
|
4703 |
+
// mysqli_error($wpdb->dbh);
|
4704 |
+
|
4705 |
+
// TODO: Daily software error report
|
4706 |
+
/*
|
4707 |
+
echo mysqli_sqlstate($wpdb->dbh);
|
4708 |
+
echo $wpdb->last_error;
|
4709 |
+
echo "<p>\n";
|
4710 |
+
echo $uri;
|
4711 |
+
echo "<p>\n";
|
4712 |
+
echo '<p>ERR '.$query.$wpdb->last_error;
|
4713 |
+
echo '<p>'.$wpdb->_real_escape( $uri );
|
4714 |
+
*/
|
4715 |
+
}
|
4716 |
+
|
4717 |
+
}
|
4718 |
+
|
4719 |
+
/**
|
4720 |
+
* To log or not to log current request?
|
4721 |
+
*
|
4722 |
+
* @param $wp_type integer
|
4723 |
+
* @param $http_code integer
|
4724 |
+
* @param $user_id integer
|
4725 |
+
*
|
4726 |
+
* @return bool
|
4727 |
+
* @since 6.0
|
4728 |
+
*/
|
4729 |
+
function cerber_to_log($wp_type = 0, $http_code, $user_id){
|
4730 |
+
global $cerber_logged;
|
4731 |
+
|
4732 |
+
$mode = crb_get_settings( 'timode' );
|
4733 |
+
|
4734 |
+
if ($mode == 0) {
|
4735 |
+
return false;
|
4736 |
+
}
|
4737 |
+
if ($mode == 2) {
|
4738 |
+
if ($wp_type < 515) { // Pure admin requests
|
4739 |
+
if ( $wp_type < 502 && ! $user_id ) { // @since 6.3
|
4740 |
+
return true;
|
4741 |
+
}
|
4742 |
+
return false;
|
4743 |
+
}
|
4744 |
+
return true;
|
4745 |
+
}
|
4746 |
+
|
4747 |
+
// Smart mode ---------------------------------------------------------
|
4748 |
+
|
4749 |
+
if ( ! empty( $cerber_logged ) ) {
|
4750 |
+
$tmp = $cerber_logged;
|
4751 |
+
unset( $tmp[7] );
|
4752 |
+
unset( $tmp[51] );
|
4753 |
+
if ( ! empty( $tmp ) ) {
|
4754 |
+
return true;
|
4755 |
+
}
|
4756 |
+
}
|
4757 |
+
|
4758 |
+
if ($wp_type < 515) {
|
4759 |
+
if ( $wp_type < 502 && ! $user_id ) { // @since 6.3
|
4760 |
+
return true;
|
4761 |
+
}
|
4762 |
+
return false;
|
4763 |
+
}
|
4764 |
+
|
4765 |
+
if ( $http_code >= 400 ||
|
4766 |
+
$wp_type < 600 ||
|
4767 |
+
$user_id ||
|
4768 |
+
cerber_is_http_post() ||
|
4769 |
+
isset($_GET['s']) ||
|
4770 |
+
cerber_get_non_wp_fields()){
|
4771 |
+
return true;
|
4772 |
+
}
|
4773 |
+
|
4774 |
+
if ( cerber_get_uri_script() ) {
|
4775 |
+
return true;
|
4776 |
+
}
|
4777 |
+
|
4778 |
+
return false;
|
4779 |
+
}
|
4780 |
+
|
4781 |
+
/**
|
4782 |
+
* Mask sensitive request fields before saving in DB (avoid information leaks)
|
4783 |
+
*
|
4784 |
+
* @param $fields array
|
4785 |
+
*
|
4786 |
+
* @return array
|
4787 |
+
* @since 6.0
|
4788 |
+
*/
|
4789 |
+
function cerber_mask_fields( $fields ) {
|
4790 |
+
$to_mask = array( 'pwd', 'pass', 'password' );
|
4791 |
+
if ($list = (array)crb_get_settings( 'timask' )){
|
4792 |
+
$to_mask = array_merge($to_mask, $list);
|
4793 |
+
}
|
4794 |
+
foreach ( $to_mask as $mask_field ) {
|
4795 |
+
if ( ! empty( $fields[ $mask_field ] ) ) {
|
4796 |
+
$fields[ $mask_field ] = str_pad( '', mb_strlen( $fields[ $mask_field ] ), '*' );
|
4797 |
+
}
|
4798 |
+
}
|
4799 |
+
|
4800 |
+
return $fields;
|
4801 |
+
}
|
4802 |
+
|
4803 |
+
/**
|
4804 |
+
* Recursive prepare values in array for inserting into DB
|
4805 |
+
*
|
4806 |
+
* @param $list
|
4807 |
+
*
|
4808 |
+
* @return mixed
|
4809 |
+
* @since 6.0
|
4810 |
+
*/
|
4811 |
+
function cerber_prepare_fields( $list ) {
|
4812 |
+
foreach ( $list as &$field ) {
|
4813 |
+
if ( is_array( $field ) ) {
|
4814 |
+
cerber_prepare_fields( @$field );
|
4815 |
+
/*
|
4816 |
+
foreach ( $field as &$field_2 ) {
|
4817 |
+
$field_2 = mb_substr( $field_2, 0, 1048576 ); // 1 Mb for ASCII
|
4818 |
+
}*/
|
4819 |
+
}
|
4820 |
+
else {
|
4821 |
+
if ( ! $field ) {
|
4822 |
+
$field = '';
|
4823 |
+
}
|
4824 |
+
$field = mb_substr( $field, 0, 1048576 ); // 1 Mb for ASCII
|
4825 |
+
}
|
4826 |
+
}
|
4827 |
+
|
4828 |
+
$list = stripslashes_deep( $list );
|
4829 |
+
|
4830 |
+
return $list;
|
4831 |
+
}
|
4832 |
+
|
4833 |
+
/**
|
4834 |
+
* Request time
|
4835 |
+
*
|
4836 |
+
* @return mixed
|
4837 |
+
* @since 6.0
|
4838 |
+
*/
|
4839 |
+
function cerber_request_time() {
|
4840 |
+
static $stamp;
|
4841 |
+
|
4842 |
+
if ( ! isset( $stamp ) ) {
|
4843 |
+
if ( ! empty( $_SERVER['REQUEST_TIME_FLOAT'] ) ) { // PHP >= 5.4
|
4844 |
+
$stamp = $_SERVER['REQUEST_TIME_FLOAT'];
|
4845 |
+
$stamp = filter_var( $_SERVER['REQUEST_TIME_FLOAT'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION );
|
4846 |
+
}
|
4847 |
+
else {
|
4848 |
+
$stamp = microtime( true );
|
4849 |
+
}
|
4850 |
+
}
|
4851 |
+
|
4852 |
+
return $stamp;
|
4853 |
+
}
|
4854 |
+
|
4855 |
+
/**
|
4856 |
+
* Return non WP public query fields
|
4857 |
+
*
|
4858 |
+
* @param array $fields An associative array field => value to check
|
4859 |
+
*
|
4860 |
+
* @return array
|
4861 |
+
* @since 6.0
|
4862 |
+
*/
|
4863 |
+
function cerber_get_non_wp_fields($fields = array()) {
|
4864 |
+
global $wp_query;
|
4865 |
+
|
4866 |
+
if ( empty( $fields ) ) {
|
4867 |
+
$get_keys = array_keys( $_GET );
|
4868 |
+
}
|
4869 |
+
else {
|
4870 |
+
$get_keys = array_keys( $fields );
|
4871 |
+
}
|
4872 |
+
|
4873 |
+
if ( empty( $get_keys ) ) {
|
4874 |
+
return array();
|
4875 |
+
}
|
4876 |
+
|
4877 |
+
if ( is_object($wp_query) ) {
|
4878 |
+
$keys = $wp_query->fill_query_vars( array() );
|
4879 |
+
}
|
4880 |
+
else {
|
4881 |
+
$tmp = new WP_Query();
|
4882 |
+
$keys = $tmp->fill_query_vars( array() );
|
4883 |
+
}
|
4884 |
+
|
4885 |
+
$wp_keys = array_keys( $keys ); // WordPress GET fields for frontend
|
4886 |
+
|
4887 |
+
$wp_keys[] = 'redirect_to';
|
4888 |
+
$wp_keys[] = 'reauth';
|
4889 |
+
$wp_keys[] = 'action';
|
4890 |
+
$wp_keys[] = '_wpnonce';
|
4891 |
+
$wp_keys[] = 'loggedout';
|
4892 |
+
|
4893 |
+
// WP Customizer fields
|
4894 |
+
$wp_keys = array_merge($wp_keys, array( 'nonce', '_method', 'wp_customize', 'changeset_uuid', 'customize_changeset_uuid', 'customize_theme', 'theme', 'customize_messenger_channel', 'customize_autosaved' ));
|
4895 |
+
|
4896 |
+
$ret = array_diff( $get_keys, $wp_keys );
|
4897 |
+
|
4898 |
+
if ( ! $ret ) {
|
4899 |
+
$ret = array();
|
4900 |
+
}
|
4901 |
+
|
4902 |
+
return $ret;
|
4903 |
+
|
4904 |
+
}
|
4905 |
+
|
4906 |
+
|
4907 |
+
/**
|
4908 |
+
*
|
4909 |
+
* @since 6.0
|
4910 |
+
*/
|
4911 |
+
function cerber_beast(){
|
4912 |
+
global $cerber_status;
|
4913 |
+
|
4914 |
+
if ( is_admin()
|
4915 |
+
|| ( defined( 'DOING_CRON' ) && DOING_CRON )
|
4916 |
+
|| ( defined( 'WP_CLI' ) && WP_CLI )
|
4917 |
+
) {
|
4918 |
+
return;
|
4919 |
+
}
|
4920 |
+
|
4921 |
+
$wp_cerber = get_wp_cerber();
|
4922 |
+
|
4923 |
+
$wp_cerber->CheckProhibitedURI();
|
4924 |
+
|
4925 |
+
if ( !crb_get_settings( 'tienabled' ) ) {
|
4926 |
+
return;
|
4927 |
+
}
|
4928 |
+
|
4929 |
+
$uri = cerber_purify_uri();
|
4930 |
+
|
4931 |
+
if ( $tiwhite = crb_get_settings( 'tiwhite' ) ) {
|
4932 |
+
foreach ( (array)$tiwhite as $item ) {
|
4933 |
+
if ($item == $uri){
|
4934 |
+
return;
|
4935 |
+
}
|
4936 |
+
}
|
4937 |
+
}
|
4938 |
+
|
4939 |
+
$wp_cerber->InspectRequest();
|
4940 |
+
|
4941 |
+
$uri_script = cerber_get_uri_script();
|
4942 |
+
|
4943 |
+
if ( $uri_script && $script_filename = cerber_script_filename() ) {
|
4944 |
+
// Scaning for executable scripts?
|
4945 |
+
//if ( false === strrpos( $script_filename, $uri ) ) {
|
4946 |
+
if ( !cerber_script_exists( $uri ) ) {
|
4947 |
+
$wp_cerber = get_wp_cerber();
|
4948 |
+
$cerber_status = 13;
|
4949 |
+
cerber_log( 55 );
|
4950 |
+
cerber_soft_block_add( $wp_cerber->getRemoteIp(), 8);
|
4951 |
+
//cerber_404_page( true );
|
4952 |
+
cerber_forbidden_page();
|
4953 |
+
}
|
4954 |
+
// Direct access to a PHP script
|
4955 |
+
if ( ! in_array( $uri_script, cerber_get_wp_scripts() ) ) {
|
4956 |
+
$deny = false;
|
4957 |
+
if ( cerber_acl_check() == 'B' ) {
|
4958 |
+
$deny = true;
|
4959 |
+
$cerber_status = 14;
|
4960 |
+
}
|
4961 |
+
elseif (!cerber_is_allowed() ) {
|
4962 |
+
$deny = true;
|
4963 |
+
$cerber_status = 13;
|
4964 |
+
}
|
4965 |
+
elseif ( lab_is_blocked( null, true ) ) {
|
4966 |
+
$deny = true;
|
4967 |
+
$cerber_status = 15;
|
4968 |
+
}
|
4969 |
+
if ($deny){
|
4970 |
+
cerber_log( 50 );
|
4971 |
+
//cerber_404_page( true );
|
4972 |
+
cerber_forbidden_page();
|
4973 |
+
}
|
4974 |
+
}
|
4975 |
+
}
|
4976 |
+
}
|
cerber-news.php
CHANGED
@@ -129,6 +129,12 @@ function cerber_push_the_news( $version ) {
|
|
129 |
$news['6.2'][] = 'Bug fixed: If the WP REST API is blocked, a request with specially malformed URL can bypass protection. Thanks to Tomasz Wasiak.';
|
130 |
$news['6.2'][] = 'Bug fixed: An IPv4 range in the Access Lists might not work as expected, depending on server/site settings.';
|
131 |
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
|
133 |
if ( ! empty( $news[ $version ] ) ) {
|
134 |
//$text = '<h3>What\'s new in WP Cerber '.$version.'</h3>';
|
@@ -150,7 +156,7 @@ function cerber_push_the_news( $version ) {
|
|
150 |
|
151 |
function cerber_admin_info($msg, $type = 'normal'){
|
152 |
|
153 |
-
$crb_assets_url =
|
154 |
|
155 |
update_site_option('cerber_admin_info',
|
156 |
'<table><tr><td><img style="float:left; margin-left:-10px;" src="'.$crb_assets_url.'icon-128x128.png"></td>'.
|
129 |
$news['6.2'][] = 'Bug fixed: If the WP REST API is blocked, a request with specially malformed URL can bypass protection. Thanks to Tomasz Wasiak.';
|
130 |
$news['6.2'][] = 'Bug fixed: An IPv4 range in the Access Lists might not work as expected, depending on server/site settings.';
|
131 |
|
132 |
+
$news['6.5'][] = 'This version brings a new, advanced and more effective way of loading plugin modules and the plugin security engine. This allows Cerber Security to intercept and inspect suspicious requests more effectively and protect WordPress against attacks that try to exploit a vulnerability in a plugin or a theme. It’s advised to enable loading in Standard mode. To enable this new mode go to the Main Settings plugin admin page and set the Load security engine setting to Standard mode.';
|
133 |
+
$news['6.5'][] = 'Traffic Inspector’s algorithms detect and deny any attempt to upload executable files (including PHP and JavaScript) or .htaccess file via any public form or POST request.';
|
134 |
+
$news['6.5'][] = 'A new setting to disable email notifications about new versions of the plugin. It’s located on the Notification admin page in the Email notifications section.';
|
135 |
+
$news['6.5'][] = 'Search in the traffic log. Now it’s possible to search in the User agent string and filter out the HTTP method (GET/POST).';
|
136 |
+
$news['6.5'][] = 'In the Smart mode if a user is not logged in, all requests to the admin dashboard are logged.';
|
137 |
+
$news['6.5'][] = 'Performance of the logging subsystem is improved: the DB query has been updated.';
|
138 |
|
139 |
if ( ! empty( $news[ $version ] ) ) {
|
140 |
//$text = '<h3>What\'s new in WP Cerber '.$version.'</h3>';
|
156 |
|
157 |
function cerber_admin_info($msg, $type = 'normal'){
|
158 |
|
159 |
+
$crb_assets_url = cerber_plugin_dir_url() . 'assets/';
|
160 |
|
161 |
update_site_option('cerber_admin_info',
|
162 |
'<table><tr><td><img style="float:left; margin-left:-10px;" src="'.$crb_assets_url.'icon-128x128.png"></td>'.
|
cerber-tools.php
CHANGED
@@ -35,7 +35,7 @@
|
|
35 |
*/
|
36 |
function cerber_tools_page() {
|
37 |
|
38 |
-
$tab = cerber_get_tab( 'imex', array( 'imex', 'diagnostic', 'license' ) );
|
39 |
|
40 |
?>
|
41 |
<div class="wrap">
|
@@ -45,9 +45,10 @@ function cerber_tools_page() {
|
|
45 |
<h2 class="nav-tab-wrapper cerber-tabs">
|
46 |
<?php
|
47 |
|
48 |
-
echo '<a href="' . cerber_admin_link('imex') . '" class="nav-tab ' . ( $tab == 'imex' ? 'nav-tab-active' : '') . '"><span class="dashicons dashicons-admin-generic"></span> ' . __('Export & Import') . '</a>';
|
49 |
-
echo '<a href="' . cerber_admin_link('diagnostic') . '" class="nav-tab ' . ( $tab == 'diagnostic' ? 'nav-tab-active' : '') . '"><span class="dashicons dashicons-admin-tools"></span> ' . __('Diagnostic') . '</a>';
|
50 |
-
echo '<a href="' . cerber_admin_link('license') . '" class="nav-tab ' . ( $tab == 'license' ? 'nav-tab-active' : '') . '"><span class="dashicons dashicons-id-alt"></span> ' . __('License') . '</a>';
|
|
|
51 |
|
52 |
echo lab_indicator();
|
53 |
?>
|
@@ -66,6 +67,9 @@ function cerber_tools_page() {
|
|
66 |
case 'license':
|
67 |
cerber_show_lic();
|
68 |
break;
|
|
|
|
|
|
|
69 |
default: cerber_show_imex();
|
70 |
}
|
71 |
|
@@ -202,13 +206,13 @@ function cerber_show_diag(){
|
|
202 |
}
|
203 |
if ($issues) {
|
204 |
$issues = '<p>'.implode('</p><p>',$issues).'</p>';
|
205 |
-
$sections[] = array('<h3>Non-critical issues found</h3>',$issues);
|
206 |
}
|
207 |
?>
|
208 |
<!-- <h3 style="margin-top: 3em;">Diagnostic and maintenance</h3>
|
209 |
<a href="javascript:void(0)" onclick="toggle_visibility('diagnostic'); return false;">Show diagnostic information</a>
|
210 |
-->
|
211 |
-
<form id="diagnostic"
|
212 |
<?php
|
213 |
foreach ($sections as $section){
|
214 |
echo '<div class="diag-section">';
|
@@ -219,7 +223,7 @@ function cerber_show_diag(){
|
|
219 |
?>
|
220 |
<div class="diag-section">
|
221 |
<h3>WordPress info</h3>
|
222 |
-
<div class="diag-text"><?php
|
223 |
</div>
|
224 |
<div class="diag-section">
|
225 |
<h3>Database info</h3>
|
@@ -228,7 +232,7 @@ function cerber_show_diag(){
|
|
228 |
</div>
|
229 |
<div class="diag-section">
|
230 |
<h3>Server info</h3>
|
231 |
-
<textarea name="dia"><?php
|
232 |
echo 'PHP version: ' . phpversion() . "\n";
|
233 |
$server = $_SERVER;
|
234 |
unset($server['HTTP_COOKIE']);
|
@@ -242,8 +246,11 @@ function cerber_show_diag(){
|
|
242 |
<h3>Cerber Cloud status</h3>
|
243 |
<?php
|
244 |
echo lab_status();
|
245 |
-
echo '<p style="text-align: right;"><a class="button button-secondary" href="'.wp_nonce_url(add_query_arg(array('force_check_nodes'=>1)),'control','cerber_nonce').'">Force recheck nodes</a></p>';
|
246 |
?>
|
|
|
|
|
|
|
|
|
247 |
</div>
|
248 |
<?php
|
249 |
if ( $report = get_site_option( '_cerber_report' ) ) {
|
@@ -342,4 +349,67 @@ function cerber_recaptcha_page() {
|
|
342 |
?>
|
343 |
</div>
|
344 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
345 |
}
|
35 |
*/
|
36 |
function cerber_tools_page() {
|
37 |
|
38 |
+
$tab = cerber_get_tab( 'imex', array( 'imex', 'diagnostic', 'license', 'help' ) );
|
39 |
|
40 |
?>
|
41 |
<div class="wrap">
|
45 |
<h2 class="nav-tab-wrapper cerber-tabs">
|
46 |
<?php
|
47 |
|
48 |
+
echo '<a href="' . cerber_admin_link( 'imex' ) . '" class="nav-tab ' . ( $tab == 'imex' ? 'nav-tab-active' : '' ) . '"><span class="dashicons dashicons-admin-generic"></span> ' . __( 'Export & Import' ) . '</a>';
|
49 |
+
echo '<a href="' . cerber_admin_link( 'diagnostic' ) . '" class="nav-tab ' . ( $tab == 'diagnostic' ? 'nav-tab-active' : '' ) . '"><span class="dashicons dashicons-admin-tools"></span> ' . __( 'Diagnostic' ) . '</a>';
|
50 |
+
echo '<a href="' . cerber_admin_link( 'license' ) . '" class="nav-tab ' . ( $tab == 'license' ? 'nav-tab-active' : '' ) . '"><span class="dashicons dashicons-id-alt"></span> ' . __( 'License' ) . '</a>';
|
51 |
+
echo '<a href="' . cerber_admin_link('help',array('page'=>cerber_get_admin_page())) . '" class="nav-tab ' . ( $tab == 'help' ? 'nav-tab-active' : '') . '"><span class="dashicons dashicons-editor-help"></span> ' . __('Help','wp-cerber') . '</a>';
|
52 |
|
53 |
echo lab_indicator();
|
54 |
?>
|
67 |
case 'license':
|
68 |
cerber_show_lic();
|
69 |
break;
|
70 |
+
case 'help':
|
71 |
+
cerber_show_help();
|
72 |
+
break;
|
73 |
default: cerber_show_imex();
|
74 |
}
|
75 |
|
206 |
}
|
207 |
if ($issues) {
|
208 |
$issues = '<p>'.implode('</p><p>',$issues).'</p>';
|
209 |
+
$sections[] = array('<h3><span class="dashicons dashicons-warning"></span> Non-critical issues found</h3>',$issues);
|
210 |
}
|
211 |
?>
|
212 |
<!-- <h3 style="margin-top: 3em;">Diagnostic and maintenance</h3>
|
213 |
<a href="javascript:void(0)" onclick="toggle_visibility('diagnostic'); return false;">Show diagnostic information</a>
|
214 |
-->
|
215 |
+
<form id="diagnostic">
|
216 |
<?php
|
217 |
foreach ($sections as $section){
|
218 |
echo '<div class="diag-section">';
|
223 |
?>
|
224 |
<div class="diag-section">
|
225 |
<h3>WordPress info</h3>
|
226 |
+
<div class="diag-text"><?php cerber_show_wp_diag(); ?></div>
|
227 |
</div>
|
228 |
<div class="diag-section">
|
229 |
<h3>Database info</h3>
|
232 |
</div>
|
233 |
<div class="diag-section">
|
234 |
<h3>Server info</h3>
|
235 |
+
<textarea name="dia" class="code"><?php
|
236 |
echo 'PHP version: ' . phpversion() . "\n";
|
237 |
$server = $_SERVER;
|
238 |
unset($server['HTTP_COOKIE']);
|
246 |
<h3>Cerber Cloud status</h3>
|
247 |
<?php
|
248 |
echo lab_status();
|
|
|
249 |
?>
|
250 |
+
<p style="text-align: right;">
|
251 |
+
<a class="button button-secondary" href="<?php echo wp_nonce_url( add_query_arg( array( 'clean_up_the_cache' => 1 ) ), 'control', 'cerber_nonce' ); ?>">Clean up the cache</a>
|
252 |
+
<a class="button button-secondary" href="<?php echo wp_nonce_url( add_query_arg( array( 'force_check_nodes' => 1 ) ), 'control', 'cerber_nonce' ); ?>">Force recheck nodes</a>
|
253 |
+
</p>
|
254 |
</div>
|
255 |
<?php
|
256 |
if ( $report = get_site_option( '_cerber_report' ) ) {
|
349 |
?>
|
350 |
</div>
|
351 |
<?php
|
352 |
+
}
|
353 |
+
|
354 |
+
function cerber_show_wp_diag(){
|
355 |
+
global $wp_version, $wpdb;
|
356 |
+
|
357 |
+
$ret = array();
|
358 |
+
|
359 |
+
$ret[] = cerber_make_plain_table( array(
|
360 |
+
array('WordPress version', $wp_version),
|
361 |
+
array('Options DB table', $wpdb->prefix.'options'),
|
362 |
+
array('Server platform', PHP_OS),
|
363 |
+
) );
|
364 |
+
|
365 |
+
$uploads = wp_upload_dir();
|
366 |
+
|
367 |
+
$folders = array(
|
368 |
+
array( 'WordPress root folder (ABSPATH) ', ABSPATH ),
|
369 |
+
array( 'Uploads folder', $uploads['path'] ),
|
370 |
+
array( 'Content folder (WP_CONTENT_DIR) ', WP_CONTENT_DIR ),
|
371 |
+
array( 'Plugins folder (WP_PLUGIN_DIR) ', WP_PLUGIN_DIR ),
|
372 |
+
array( 'Must use plugin folder (WPMU_PLUGIN_DIR) ', WPMU_PLUGIN_DIR ),
|
373 |
+
);
|
374 |
+
|
375 |
+
foreach ( $folders as &$folder ) {
|
376 |
+
$folder[2] = '';
|
377 |
+
$folder[3] = '';
|
378 |
+
if ( file_exists( $folder[1] ) ) {
|
379 |
+
if ( wp_is_writable( $folder[1] ) ) {
|
380 |
+
$folder[2] = 'Writable';
|
381 |
+
}
|
382 |
+
$folder[3] = cerber_get_chmod($folder[1]);
|
383 |
+
}
|
384 |
+
else {
|
385 |
+
$folder[2] = 'Not found';
|
386 |
+
}
|
387 |
+
}
|
388 |
+
|
389 |
+
$ret[] = '<p>Folders</p>'.cerber_make_plain_table( $folders );
|
390 |
+
|
391 |
+
$pls = array();
|
392 |
+
$list = get_option('active_plugins');
|
393 |
+
foreach($list as $plugin) {
|
394 |
+
$data = get_plugin_data(WP_PLUGIN_DIR.'/'.$plugin);
|
395 |
+
$pls[] = array($data['Name'], $data['Version']);
|
396 |
+
}
|
397 |
+
|
398 |
+
$ret[] = 'Active plugins<br>'.cerber_make_plain_table( $pls );
|
399 |
+
|
400 |
+
echo implode("<br>",$ret);
|
401 |
+
}
|
402 |
+
|
403 |
+
function cerber_make_plain_table( $data ) {
|
404 |
+
$ret = '<table class="crb-plain-table">';
|
405 |
+
foreach ( $data as $row ) {
|
406 |
+
$ret .= '<tr><td>' . implode( '</td><td>', $row ) . '</td></tr>';
|
407 |
+
}
|
408 |
+
$ret .= '</table>';
|
409 |
+
|
410 |
+
return $ret;
|
411 |
+
}
|
412 |
+
|
413 |
+
function cerber_get_chmod( $file ) {
|
414 |
+
return substr( sprintf( '%o', @fileperms( $file ) ), - 4 );
|
415 |
}
|
common.php
CHANGED
@@ -54,20 +54,28 @@ function cerber_get_wp_scripts(){
|
|
54 |
function cerber_admin_link($tab = '', $args = array()){
|
55 |
//return add_query_arg(array('record_id'=>$record_id,'mode'=>'view_record'),admin_url('admin.php?page=storage'));
|
56 |
|
57 |
-
if (
|
58 |
-
$
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
$
|
63 |
-
|
64 |
-
|
65 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
}
|
67 |
-
|
68 |
-
$page = '
|
|
|
69 |
}
|
70 |
-
else $page = 'cerber-security';
|
71 |
|
72 |
if (!is_multisite()) {
|
73 |
$link = admin_url('admin.php?page='.$page);
|
@@ -247,13 +255,18 @@ function cerber_check_environment(){
|
|
247 |
if ( '' === crb_get_settings( 'tienabled' ) ) {
|
248 |
cerber_admin_notice('Warning: Traffic inspection is disabled');
|
249 |
}
|
250 |
-
if
|
251 |
-
cerber_admin_notice( __( 'ERROR:', 'wp-cerber' ) . ' cURL PHP library is not enabled on your website.');
|
252 |
}
|
253 |
else {
|
254 |
$curl = @curl_init();
|
255 |
-
if (
|
256 |
-
|
|
|
|
|
|
|
|
|
|
|
257 |
}
|
258 |
}
|
259 |
|
@@ -480,7 +493,7 @@ function cerber_is_rest_url(){
|
|
480 |
return true;
|
481 |
}
|
482 |
|
483 |
-
if (isset($cache)) {
|
484 |
return $cache;
|
485 |
}
|
486 |
|
@@ -623,37 +636,67 @@ function cerber_last_uri( $check_php = false ) {
|
|
623 |
}
|
624 |
|
625 |
/**
|
626 |
-
* Return the name of
|
627 |
*
|
628 |
-
* @return bool|string
|
629 |
*/
|
630 |
-
function cerber_get_uri_script(){
|
631 |
-
static $executable = array( 'phtm', 'phtml', 'phps', 'asp', 'aspx', 'shtm', 'shtml' );
|
632 |
-
|
633 |
$last = cerber_last_uri();
|
634 |
-
|
635 |
-
|
636 |
-
$ext = substr( strstr( $last, '.' ), 1 );
|
637 |
-
if ( $second_dot = strpos( $ext, '.' ) ) {
|
638 |
-
$ext = substr( $ext, 0, $second_dot );
|
639 |
}
|
640 |
|
641 |
-
|
642 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
643 |
}
|
644 |
|
645 |
-
$
|
|
|
646 |
|
647 |
-
if ( $
|
648 |
-
return
|
649 |
}
|
650 |
|
651 |
-
|
652 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
653 |
}
|
654 |
|
655 |
-
if (
|
656 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
657 |
}
|
658 |
|
659 |
return false;
|
@@ -692,6 +735,23 @@ function cerber_script_filename() {
|
|
692 |
return preg_replace('/[\/\\\\]+/','/',$_SERVER['SCRIPT_FILENAME']); // Windows server
|
693 |
}
|
694 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
695 |
/*
|
696 |
* Sets of human readable labels for vary activity/logs events
|
697 |
* @since 1.0
|
@@ -741,6 +801,8 @@ function cerber_get_labels($type = 'activity'){
|
|
741 |
$labels[53]=__('Attempt to log in denied','wp-cerber');
|
742 |
$labels[54]=__('Attempt to register denied','wp-cerber');
|
743 |
$labels[55]=__('Probing for vulnerable PHP code','wp-cerber');
|
|
|
|
|
744 |
|
745 |
$labels[70]=__('Request to REST API denied','wp-cerber');
|
746 |
$labels[71]=__('XML-RPC request denied','wp-cerber');
|
@@ -765,11 +827,11 @@ function cerber_get_labels($type = 'activity'){
|
|
765 |
function crb_get_activity_set($slice = 'malicious') {
|
766 |
switch ( $slice ) {
|
767 |
case 'malicious':
|
768 |
-
return array( 10, 11, 16, 17, 40, 50, 51, 52, 53, 54, 55 );
|
769 |
case 'suspicious':
|
770 |
-
return array( 10, 11, 16, 17, 20, 40, 50, 51, 52, 53, 54, 55 );
|
771 |
case 'black':
|
772 |
-
return array( 16, 17, 40, 50, 51, 52, 55 );
|
773 |
}
|
774 |
|
775 |
return array();
|
@@ -1120,31 +1182,36 @@ function cerber_real_escape($string){
|
|
1120 |
}
|
1121 |
|
1122 |
/**
|
1123 |
-
*
|
1124 |
*
|
1125 |
* The reason: https://make.wordpress.org/core/2017/10/31/changed-behaviour-of-esc_sql-in-wordpress-4-8-3/
|
1126 |
*
|
1127 |
-
* @param $query
|
1128 |
*
|
1129 |
-
* @return bool|mysqli_result
|
1130 |
* @since 6.0
|
1131 |
*/
|
1132 |
-
function
|
1133 |
global $wpdb;
|
1134 |
-
|
1135 |
-
|
1136 |
-
|
1137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1138 |
}
|
1139 |
}
|
1140 |
-
|
1141 |
-
$db = $wpdb;
|
1142 |
-
}
|
1143 |
if ( $db->use_mysqli ) {
|
1144 |
$ret = mysqli_query( $db->dbh, $query );
|
1145 |
}
|
1146 |
else {
|
1147 |
-
$ret = mysql_query( $query, $db->dbh );
|
1148 |
}
|
1149 |
|
1150 |
return $ret;
|
@@ -1155,33 +1222,39 @@ function cerber_direct_db_query( $query ) {
|
|
1155 |
*
|
1156 |
* @return bool|wpdb
|
1157 |
*/
|
1158 |
-
function cerber_direct_db_connect(){
|
1159 |
if ( ! defined( 'CRB_ABSPATH' ) ) {
|
1160 |
define( 'CRB_ABSPATH', dirname( __FILE__, 4 ) );
|
1161 |
}
|
1162 |
-
$db_class
|
1163 |
$wp_config = CRB_ABSPATH . '/wp-config.php';
|
1164 |
-
if ( file_exists( $db_class ) && $config =
|
1165 |
-
$
|
1166 |
-
|
1167 |
-
|
1168 |
-
|
1169 |
-
|
1170 |
-
|
1171 |
-
|
1172 |
-
|
1173 |
-
|
1174 |
-
ob_end_clean();
|
1175 |
-
if ( defined( 'DB_USER' ) && defined( 'DB_PASSWORD' ) && defined( 'DB_NAME' ) && defined( 'DB_HOST' ) ) {
|
1176 |
-
include_once( $db_class );
|
1177 |
-
return new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
|
1178 |
-
}
|
1179 |
}
|
1180 |
}
|
1181 |
|
1182 |
return false;
|
1183 |
}
|
1184 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1185 |
/**
|
1186 |
* Set Cerber Groove to logged in user browser
|
1187 |
*
|
@@ -1233,6 +1306,8 @@ function cerber_check_groove( $hash = '' ) {
|
|
1233 |
Get the special public Cerber Sign for using with cookies
|
1234 |
*/
|
1235 |
function cerber_get_groove_x( $regenerate = false ) {
|
|
|
|
|
1236 |
if ( ! $regenerate ) {
|
1237 |
$groove_x = cerber_get_site_option( 'cerber-groove-x' );
|
1238 |
}
|
@@ -1281,8 +1356,15 @@ function cerber_htaccess_sync( $settings = array() ) {
|
|
1281 |
}
|
1282 |
|
1283 |
// Update all rules in a section - adding/deleting
|
1284 |
-
|
1285 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1286 |
}
|
1287 |
|
1288 |
/**
|
@@ -1297,15 +1379,15 @@ function cerber_update_htaccess($marker, $rules = array()){
|
|
1297 |
if ( ! $marker ) {
|
1298 |
return false;
|
1299 |
}
|
1300 |
-
if ( ! $htaccess_file =
|
1301 |
return 'ERROR: Unable to modify the .htaccess file';
|
1302 |
}
|
1303 |
require_once( ABSPATH . 'wp-admin/includes/misc.php' );
|
1304 |
-
if ( !
|
1305 |
return 'ERROR: Apache mod_rewrite is not enabled';
|
1306 |
}
|
1307 |
|
1308 |
-
$result = insert_with_markers( $htaccess_file,
|
1309 |
|
1310 |
if ( $result || $result === 0 ) {
|
1311 |
$result = true;
|
@@ -1317,14 +1399,84 @@ function cerber_update_htaccess($marker, $rules = array()){
|
|
1317 |
return $result;
|
1318 |
}
|
1319 |
|
1320 |
-
|
|
|
|
|
|
|
|
|
|
|
1321 |
require_once( ABSPATH . 'wp-admin/includes/file.php' );
|
1322 |
$home_path = get_home_path();
|
1323 |
-
$
|
1324 |
-
if ( ! is_writable( $
|
1325 |
// should we create the file?
|
1326 |
return false;
|
1327 |
}
|
1328 |
|
1329 |
-
return $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1330 |
}
|
54 |
function cerber_admin_link($tab = '', $args = array()){
|
55 |
//return add_query_arg(array('record_id'=>$record_id,'mode'=>'view_record'),admin_url('admin.php?page=storage'));
|
56 |
|
57 |
+
if (empty($args['page'])) {
|
58 |
+
if ( in_array( $tab, array( 'recaptcha', 'antispam' ) ) ) {
|
59 |
+
$page = 'cerber-recaptcha';
|
60 |
+
$tab = null;
|
61 |
+
}
|
62 |
+
elseif ( in_array( $tab, array( 'imex', 'diagnostic', 'license' ) ) ) {
|
63 |
+
$page = 'cerber-tools';
|
64 |
+
}
|
65 |
+
elseif ( in_array( $tab, array( 'traffic', 'ti_settings' ) ) ) {
|
66 |
+
$page = 'cerber-traffic';
|
67 |
+
}
|
68 |
+
elseif ( in_array( $tab, array( 'geo' ) ) ) {
|
69 |
+
$page = 'cerber-rules';
|
70 |
+
}
|
71 |
+
else {
|
72 |
+
$page = 'cerber-security';
|
73 |
+
}
|
74 |
}
|
75 |
+
else {
|
76 |
+
$page = $args['page'];
|
77 |
+
unset( $args['page'] );
|
78 |
}
|
|
|
79 |
|
80 |
if (!is_multisite()) {
|
81 |
$link = admin_url('admin.php?page='.$page);
|
255 |
if ( '' === crb_get_settings( 'tienabled' ) ) {
|
256 |
cerber_admin_notice('Warning: Traffic inspection is disabled');
|
257 |
}
|
258 |
+
if ( ! in_array( 'curl', get_loaded_extensions() ) ) {
|
259 |
+
cerber_admin_notice( __( 'ERROR:', 'wp-cerber' ) . ' cURL PHP library is not enabled on your website.' );
|
260 |
}
|
261 |
else {
|
262 |
$curl = @curl_init();
|
263 |
+
if ( ! $curl && ( $err_msg = curl_error( $curl ) ) ) {
|
264 |
+
cerber_admin_notice( __( 'ERROR:', 'wp-cerber' ) . ' ' . $err_msg );
|
265 |
+
}
|
266 |
+
curl_close( $curl );
|
267 |
+
}
|
268 |
+
if ( cerber_get_mode() != crb_get_settings( 'boot-mode' ) ) {
|
269 |
+
cerber_admin_notice( __( 'ERROR:', 'wp-cerber' ) . ' ' . 'The plugin is initialized in a different mode that does not match the settings.' );
|
270 |
}
|
271 |
}
|
272 |
|
493 |
return true;
|
494 |
}
|
495 |
|
496 |
+
if ( isset( $cache ) ) {
|
497 |
return $cache;
|
498 |
}
|
499 |
|
636 |
}
|
637 |
|
638 |
/**
|
639 |
+
* Return the name of an executable script in the requested URI if it's present
|
640 |
*
|
641 |
+
* @return bool|string script name or false if executable script is not detected
|
642 |
*/
|
643 |
+
function cerber_get_uri_script() {
|
|
|
|
|
644 |
$last = cerber_last_uri();
|
645 |
+
if ( cerber_detect_exec_extension( $last ) ) {
|
646 |
+
return $last;
|
|
|
|
|
|
|
647 |
}
|
648 |
|
649 |
+
return false;
|
650 |
+
}
|
651 |
+
|
652 |
+
/**
|
653 |
+
* Detects an executable extension in a filename.
|
654 |
+
* Supports double and N fake extensions.
|
655 |
+
*
|
656 |
+
* @param $line string Filename
|
657 |
+
* @param array $extra A list of additional extensions to detect
|
658 |
+
*
|
659 |
+
* @return bool|string An extension if it's found, false otherwise
|
660 |
+
*/
|
661 |
+
function cerber_detect_exec_extension( $line, $extra = array() ) {
|
662 |
+
$executable = array( 'php', 'phtm', 'phtml', 'phps', 'shtm', 'shtml', 'jsp', 'asp', 'aspx', 'exe', 'com', 'cgi', 'pl' );
|
663 |
+
|
664 |
+
if ( $extra ) {
|
665 |
+
$executable = array_merge( $executable, $extra );
|
666 |
}
|
667 |
|
668 |
+
$line = trim( $line );
|
669 |
+
$line = trim( $line, '/' );
|
670 |
|
671 |
+
if ( ! strrpos( $line, '.' ) ) {
|
672 |
+
return false;
|
673 |
}
|
674 |
|
675 |
+
$parts = explode('.', $line);
|
676 |
+
array_shift($parts);
|
677 |
+
|
678 |
+
// First and last are critical for most server environments
|
679 |
+
$first_ext = array_shift($parts);
|
680 |
+
$last_ext = array_pop($parts);
|
681 |
+
|
682 |
+
if ( $first_ext ) {
|
683 |
+
$first_ext = strtolower( $first_ext );
|
684 |
+
if ( in_array( $first_ext, $executable ) ) {
|
685 |
+
return $first_ext;
|
686 |
+
}
|
687 |
+
if ( preg_match( '/php\d+/', $first_ext ) ) {
|
688 |
+
return $first_ext;
|
689 |
+
}
|
690 |
}
|
691 |
|
692 |
+
if ( $last_ext ) {
|
693 |
+
$last_ext = strtolower( $last_ext );
|
694 |
+
if ( in_array( $last_ext, $executable ) ) {
|
695 |
+
return $last_ext;
|
696 |
+
}
|
697 |
+
if ( preg_match( '/php\d+/', $last_ext ) ) {
|
698 |
+
return $last_ext;
|
699 |
+
}
|
700 |
}
|
701 |
|
702 |
return false;
|
735 |
return preg_replace('/[\/\\\\]+/','/',$_SERVER['SCRIPT_FILENAME']); // Windows server
|
736 |
}
|
737 |
|
738 |
+
function cerber_script_exists( $uri ) {
|
739 |
+
$script_filename = cerber_script_filename();
|
740 |
+
if ( is_multisite() && ! is_subdomain_install() ) {
|
741 |
+
$path = explode( '/', $uri );
|
742 |
+
if ( count( $path ) > 1 ) {
|
743 |
+
$last = array_pop( $path );
|
744 |
+
$virtual_sub_folder = array_pop( $path );
|
745 |
+
$uri = implode( '/', $path ) . '/' . $last;
|
746 |
+
}
|
747 |
+
}
|
748 |
+
if ( false === strrpos( $script_filename, $uri ) ) {
|
749 |
+
return false;
|
750 |
+
}
|
751 |
+
|
752 |
+
return true;
|
753 |
+
}
|
754 |
+
|
755 |
/*
|
756 |
* Sets of human readable labels for vary activity/logs events
|
757 |
* @since 1.0
|
801 |
$labels[53]=__('Attempt to log in denied','wp-cerber');
|
802 |
$labels[54]=__('Attempt to register denied','wp-cerber');
|
803 |
$labels[55]=__('Probing for vulnerable PHP code','wp-cerber');
|
804 |
+
$labels[56]=__('Attempt to upload executable file denied', 'wp-cerber' );
|
805 |
+
$labels[57]=__('File upload denied', 'wp-cerber' );
|
806 |
|
807 |
$labels[70]=__('Request to REST API denied','wp-cerber');
|
808 |
$labels[71]=__('XML-RPC request denied','wp-cerber');
|
827 |
function crb_get_activity_set($slice = 'malicious') {
|
828 |
switch ( $slice ) {
|
829 |
case 'malicious':
|
830 |
+
return array( 10, 11, 16, 17, 40, 50, 51, 52, 53, 54, 55, 56 );
|
831 |
case 'suspicious':
|
832 |
+
return array( 10, 11, 16, 17, 20, 40, 50, 51, 52, 53, 54, 55, 56, 70, 71);
|
833 |
case 'black':
|
834 |
+
return array( 16, 17, 40, 50, 51, 52, 55, 56 );
|
835 |
}
|
836 |
|
837 |
return array();
|
1182 |
}
|
1183 |
|
1184 |
/**
|
1185 |
+
* Performs generic direct SQL query to the site DB
|
1186 |
*
|
1187 |
* The reason: https://make.wordpress.org/core/2017/10/31/changed-behaviour-of-esc_sql-in-wordpress-4-8-3/
|
1188 |
*
|
1189 |
+
* @param $query string An SQL query
|
1190 |
*
|
1191 |
+
* @return bool|mysqli_result
|
1192 |
* @since 6.0
|
1193 |
*/
|
1194 |
+
function cerber_db_query( $query ) {
|
1195 |
global $wpdb;
|
1196 |
+
static $db;
|
1197 |
+
|
1198 |
+
if ( ! isset( $db ) || ! is_object( $db ) ) {
|
1199 |
+
// Check for connected DB handler
|
1200 |
+
if ( ! is_object( $wpdb ) || empty( $wpdb->dbh ) ) {
|
1201 |
+
if ( ! $db = cerber_direct_db_connect() ) {
|
1202 |
+
return false;
|
1203 |
+
}
|
1204 |
+
}
|
1205 |
+
else {
|
1206 |
+
$db = $wpdb;
|
1207 |
}
|
1208 |
}
|
1209 |
+
|
|
|
|
|
1210 |
if ( $db->use_mysqli ) {
|
1211 |
$ret = mysqli_query( $db->dbh, $query );
|
1212 |
}
|
1213 |
else {
|
1214 |
+
$ret = mysql_query( $query, $db->dbh ); // For compatibility reason
|
1215 |
}
|
1216 |
|
1217 |
return $ret;
|
1222 |
*
|
1223 |
* @return bool|wpdb
|
1224 |
*/
|
1225 |
+
function cerber_direct_db_connect() {
|
1226 |
if ( ! defined( 'CRB_ABSPATH' ) ) {
|
1227 |
define( 'CRB_ABSPATH', dirname( __FILE__, 4 ) );
|
1228 |
}
|
1229 |
+
$db_class = CRB_ABSPATH . '/wp-includes/wp-db.php';
|
1230 |
$wp_config = CRB_ABSPATH . '/wp-config.php';
|
1231 |
+
if ( file_exists( $db_class ) && $config = file_get_contents( $wp_config ) ) {
|
1232 |
+
$config = str_replace( '<?php', '', $config );
|
1233 |
+
$config = str_replace( '?>', '', $config );
|
1234 |
+
ob_start();
|
1235 |
+
@eval( $config ); // This eval is OK. Getting site DB parameters.
|
1236 |
+
ob_end_clean();
|
1237 |
+
if ( defined( 'DB_USER' ) && defined( 'DB_PASSWORD' ) && defined( 'DB_NAME' ) && defined( 'DB_HOST' ) ) {
|
1238 |
+
require_once( $db_class );
|
1239 |
+
|
1240 |
+
return new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
|
|
|
|
|
|
|
|
|
|
|
1241 |
}
|
1242 |
}
|
1243 |
|
1244 |
return false;
|
1245 |
}
|
1246 |
|
1247 |
+
/**
|
1248 |
+
* Remove comments from a given piece of code
|
1249 |
+
*
|
1250 |
+
* @param string $string
|
1251 |
+
*
|
1252 |
+
* @return mixed
|
1253 |
+
*/
|
1254 |
+
function cerber_remove_comments( $string = '' ) {
|
1255 |
+
return preg_replace( '/#.*/', '', preg_replace( '#//.*#', '', preg_replace( '#/\*(?:[^*]*(?:\*(?!/))*)*\*/#', '', ( $string ) ) ) );
|
1256 |
+
}
|
1257 |
+
|
1258 |
/**
|
1259 |
* Set Cerber Groove to logged in user browser
|
1260 |
*
|
1306 |
Get the special public Cerber Sign for using with cookies
|
1307 |
*/
|
1308 |
function cerber_get_groove_x( $regenerate = false ) {
|
1309 |
+
$groove_x = array();
|
1310 |
+
|
1311 |
if ( ! $regenerate ) {
|
1312 |
$groove_x = cerber_get_site_option( 'cerber-groove-x' );
|
1313 |
}
|
1356 |
}
|
1357 |
|
1358 |
// Update all rules in a section - adding/deleting
|
1359 |
+
return cerber_update_htaccess( CERBER_MARKER1, $rules );
|
1360 |
+
}
|
1361 |
+
|
1362 |
+
/**
|
1363 |
+
* Remove Cerber rules from the .htaccess file
|
1364 |
+
*
|
1365 |
+
*/
|
1366 |
+
function cerber_htaccess_clean_up(){
|
1367 |
+
cerber_update_htaccess( CERBER_MARKER1, array() );
|
1368 |
}
|
1369 |
|
1370 |
/**
|
1379 |
if ( ! $marker ) {
|
1380 |
return false;
|
1381 |
}
|
1382 |
+
if ( ! $htaccess_file = cerber_get_htaccess_file() ) {
|
1383 |
return 'ERROR: Unable to modify the .htaccess file';
|
1384 |
}
|
1385 |
require_once( ABSPATH . 'wp-admin/includes/misc.php' );
|
1386 |
+
if ( ! apache_mod_loaded( 'mod_rewrite', true ) ) {
|
1387 |
return 'ERROR: Apache mod_rewrite is not enabled';
|
1388 |
}
|
1389 |
|
1390 |
+
$result = insert_with_markers( $htaccess_file, CERBER_MARKER1, $rules );
|
1391 |
|
1392 |
if ( $result || $result === 0 ) {
|
1393 |
$result = true;
|
1399 |
return $result;
|
1400 |
}
|
1401 |
|
1402 |
+
/**
|
1403 |
+
* Return .htaccess filename with full path
|
1404 |
+
*
|
1405 |
+
* @return bool|string full filename if the file can be written, false otherwise
|
1406 |
+
*/
|
1407 |
+
function cerber_get_htaccess_file() {
|
1408 |
require_once( ABSPATH . 'wp-admin/includes/file.php' );
|
1409 |
$home_path = get_home_path();
|
1410 |
+
$file = $home_path . '.htaccess';
|
1411 |
+
if ( ! is_writable( $file ) ) {
|
1412 |
// should we create the file?
|
1413 |
return false;
|
1414 |
}
|
1415 |
|
1416 |
+
return $file;
|
1417 |
+
}
|
1418 |
+
|
1419 |
+
/**
|
1420 |
+
* Prepare files (install/deinstall) for different boot modes
|
1421 |
+
*
|
1422 |
+
* @param $mode int A plugin boot mode
|
1423 |
+
* @param $old_mode int
|
1424 |
+
*
|
1425 |
+
* @return bool|WP_Error
|
1426 |
+
* @since 6.3
|
1427 |
+
*/
|
1428 |
+
function cerber_set_boot_mode( $mode = null, $old_mode = null ) {
|
1429 |
+
if ( $mode === null ) {
|
1430 |
+
$mode = crb_get_settings( 'boot-mode' );
|
1431 |
+
}
|
1432 |
+
$source = dirname( cerber_plugin_file() ) . '/modules/aaa-wp-cerber.php';
|
1433 |
+
$target = WPMU_PLUGIN_DIR . '/aaa-wp-cerber.php';
|
1434 |
+
if ( $mode == 1 ) {
|
1435 |
+
if ( file_exists( $target ) ) {
|
1436 |
+
if ( sha1_file( $source, true ) == sha1_file( $target, true ) ) {
|
1437 |
+
return true;
|
1438 |
+
}
|
1439 |
+
}
|
1440 |
+
if ( ! is_dir( WPMU_PLUGIN_DIR ) ) {
|
1441 |
+
if ( ! mkdir( WPMU_PLUGIN_DIR, 0755, true ) ) {
|
1442 |
+
// TODO: try to set permissions for the parent folder
|
1443 |
+
return new WP_Error( 'cerber-boot', __( 'Unable to create the directory', 'wp-cerber' ) . ' ' . WPMU_PLUGIN_DIR );
|
1444 |
+
}
|
1445 |
+
}
|
1446 |
+
if ( ! copy( $source, $target ) ) {
|
1447 |
+
if ( ! wp_is_writable( WPMU_PLUGIN_DIR ) ) {
|
1448 |
+
return new WP_Error( 'cerber-boot', __( 'Destination folder access denied', 'wp-cerber' ) . ' ' . WPMU_PLUGIN_DIR );
|
1449 |
+
}
|
1450 |
+
elseif ( ! file_exists( $source ) ) {
|
1451 |
+
return new WP_Error( 'cerber-boot', __( 'File not found', 'wp-cerber' ) . ' ' . $source );
|
1452 |
+
}
|
1453 |
+
|
1454 |
+
return new WP_Error( 'cerber-boot', __( 'Unable to copy the file', 'wp-cerber' ) . ' ' . $source . ' to the folder ' . WPMU_PLUGIN_DIR );
|
1455 |
+
}
|
1456 |
+
}
|
1457 |
+
else {
|
1458 |
+
if ( file_exists( $target ) ) {
|
1459 |
+
if ( ! unlink( $target ) ) {
|
1460 |
+
return new WP_Error( 'cerber-boot', __( 'Unable to delete the file', 'wp-cerber' ) . ' ' . $target );
|
1461 |
+
}
|
1462 |
+
}
|
1463 |
+
|
1464 |
+
return true;
|
1465 |
+
}
|
1466 |
+
|
1467 |
+
return true;
|
1468 |
+
}
|
1469 |
+
|
1470 |
+
/**
|
1471 |
+
* How the plugin was loaded (initialized)
|
1472 |
+
*
|
1473 |
+
* @return int
|
1474 |
+
* @since 6.3
|
1475 |
+
*/
|
1476 |
+
function cerber_get_mode() {
|
1477 |
+
if ( function_exists( 'cerber_mode' ) && defined( 'CERBER_MODE' ) ) {
|
1478 |
+
return cerber_mode();
|
1479 |
+
}
|
1480 |
+
|
1481 |
+
return 0;
|
1482 |
}
|
dashboard.php
CHANGED
@@ -382,8 +382,7 @@ function cerber_admin_request(){
|
|
382 |
else {
|
383 |
cerber_admin_notice( __( 'Unable to send email to', 'wp-cerber' ) . ' ' . $to );
|
384 |
}
|
385 |
-
|
386 |
-
exit; // mandatory!
|
387 |
}
|
388 |
elseif ( $ip = cerber_get_get( 'lockdelete' ) ) {
|
389 |
if ( cerber_block_delete( $ip ) ) {
|
@@ -396,8 +395,7 @@ function cerber_admin_request(){
|
|
396 |
elseif ( isset( $_GET['subscribe'] ) ) {
|
397 |
$mode = ( 'on' == $_GET['subscribe'] ) ? 'on' : 'off';
|
398 |
cerber_subscribe( $mode );
|
399 |
-
|
400 |
-
exit; // mandatory!
|
401 |
}
|
402 |
elseif ( isset( $_GET['citadel'] ) && $_GET['citadel'] == 'deactivate' ) {
|
403 |
cerber_disable_citadel();
|
@@ -405,15 +403,13 @@ function cerber_admin_request(){
|
|
405 |
elseif ( isset( $_GET['load_settings'] ) && $_GET['load_settings'] == 'default' ) {
|
406 |
cerber_load_defaults();
|
407 |
cerber_admin_message( __( 'Settings saved', 'wp-cerber' ) );
|
408 |
-
|
409 |
-
exit; // mandatory!
|
410 |
}
|
411 |
elseif ( isset( $_GET['force_repair_db'] ) ) {
|
412 |
cerber_create_db();
|
413 |
cerber_upgrade_db( true );
|
414 |
cerber_admin_message( 'Cerber\'s tables has been upgraded' );
|
415 |
-
|
416 |
-
exit; // mandatory!
|
417 |
}
|
418 |
elseif ( isset( $_GET['truncate'] ) ) {
|
419 |
$table = $_GET['truncate'];
|
@@ -424,14 +420,17 @@ function cerber_admin_request(){
|
|
424 |
}
|
425 |
else cerber_admin_message( $wpdb->last_error );
|
426 |
}
|
427 |
-
|
428 |
-
exit; // mandatory!
|
429 |
}
|
430 |
elseif ( isset( $_GET['force_check_nodes'] ) ) {
|
431 |
$best = lab_check_nodes( true );
|
432 |
cerber_admin_message( 'Cerber Lab\'s nodes has been checked. The closest node: ' . $best );
|
433 |
-
|
434 |
-
|
|
|
|
|
|
|
|
|
435 |
}
|
436 |
}
|
437 |
|
@@ -452,6 +451,14 @@ function cerber_admin_request(){
|
|
452 |
|
453 |
}
|
454 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
455 |
/**
|
456 |
* Generate export CSV file using $_GET parameters (via cerber_activity_query())
|
457 |
*
|
@@ -1053,6 +1060,15 @@ function cerber_is_admin_page( $force = true, $params = array() ) {
|
|
1053 |
return false;
|
1054 |
}
|
1055 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1056 |
// Users -------------------------------------------------------------------------------------
|
1057 |
|
1058 |
add_filter('users_list_table_query_args' , function ($args) {
|
@@ -1268,8 +1284,8 @@ function cerber_show_help() {
|
|
1268 |
|
1269 |
<?php echo $support; ?>
|
1270 |
|
1271 |
-
<p><span class="dashicons-before dashicons-book-alt"></span> <a href="https://wpcerber.com/toc/" target="_blank">Read articles on wpcerber.com</a></p>
|
1272 |
-
<p><span class="dashicons-before dashicons-format-chat"></span> <a href="https://wordpress.org/support/plugin/wp-cerber">Get answer on the support forum</a></p>
|
1273 |
|
1274 |
|
1275 |
<form style="margin-top: 2em;" action="https://wpcerber.com" target="_blank">
|
@@ -1277,23 +1293,36 @@ function cerber_show_help() {
|
|
1277 |
<input type="text" style="width: 80%;" name="s" placeholder="Enter term to search"><input type="submit" value="Search" class="button button-primary">
|
1278 |
</form>
|
1279 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1280 |
</td>
|
1281 |
<td>
|
1282 |
<h3>What is IP address of your computer?</h3>
|
1283 |
|
1284 |
<p>To find out your current IP address go to this page: <a href="https://wpcerber.com/what-is-my-ip/">What is my IP</a>. If you see a different IP address on the Activity tab for your login or logout events you probably need to check <b><?php _e('My site is behind a reverse proxy','wp-cerber'); ?></b>.</p>
|
1285 |
<p>
|
1286 |
-
<span class="dashicons-before dashicons-book-alt"> <a href="https://wpcerber.com/wordpress-ip-address-detection/">Solving problem with incorrect IP address detection</a>
|
1287 |
</p>
|
1288 |
|
1289 |
|
1290 |
<h3>Setting up antispam protection</h3>
|
1291 |
|
1292 |
<p>
|
1293 |
-
Cerber antispam and bot detection engine is capable to protect virtually any form on a website. It’s a great alternative to reCAPTCHA.
|
1294 |
</p>
|
1295 |
<p>
|
1296 |
-
<span class="dashicons-before dashicons-book-alt"> <a href="https://wpcerber.com/
|
|
|
|
|
1297 |
</p>
|
1298 |
|
1299 |
|
@@ -1303,13 +1332,18 @@ function cerber_show_help() {
|
|
1303 |
WP Cerber allows you to easily enable desktop and mobile notifications and get notifications instantly and for free. In a desktop browser, you will get popup messages even if you logged out of your WordPress.
|
1304 |
Before you start receiving notifications you need to install a free Pushbullet mobile application on your mobile device or free browser extension available for Chrome, Firefox and Opera.
|
1305 |
</p>
|
1306 |
-
<p><span class="dashicons-before dashicons-book-alt"></span>
|
1307 |
<a href="https://wpcerber.com/wordpress-mobile-and-browser-notifications-pushbullet/">A three steps instruction how to set up push notifications</a>
|
1308 |
</p>
|
1309 |
-
<p><span class="dashicons-before dashicons-book-alt"></span>
|
1310 |
<a href="https://wpcerber.com/wordpress-notifications-made-easy/">How to get alerts for specific activity on your website</a>
|
1311 |
</p>
|
1312 |
|
|
|
|
|
|
|
|
|
|
|
1313 |
</td>
|
1314 |
</tr>
|
1315 |
</table>
|
@@ -1437,7 +1471,7 @@ function cerber_show_dashboard() {
|
|
1437 |
echo '<table class="cerber-margin"><tr><td><h2 style="margin-bottom:0.5em; margin-right: 1em;">' . __( 'Activity', 'wp-cerber' ) . '</h2></td><td>' . $nav_links . '</td></tr></table>';
|
1438 |
|
1439 |
cerber_show_activity( array(
|
1440 |
-
'filter_activity' => array( 1, 2, 5, 10, 11, 12, 16, 17, 18, 19, 40, 41, 42, 50, 51, 52, 53, 54, 55,
|
1441 |
'per_page' => 10,
|
1442 |
'no_navi' => true,
|
1443 |
'no_export' => true,
|
@@ -1512,17 +1546,20 @@ function cerber_show_aside($page){
|
|
1512 |
';
|
1513 |
|
1514 |
// 22.01.2017
|
1515 |
-
|
|
|
1516 |
<span class="dashicons dashicons-awards"></span><span class="dashicons dashicons-awards"></span><span class="dashicons dashicons-awards"></span><br><br>UPGRADE TO PROFESSIONAL VERSION</a>';
|
|
|
1517 |
|
1518 |
-
|
1519 |
|
1520 |
-
|
|
|
1521 |
if (!lab_lab() && !in_array($page,array('geo'))) {
|
1522 |
$aside[] = '<div class="crb-box" id = "crb-donate">
|
1523 |
<div class="crb-box-inner">
|
1524 |
<h3>' . __( 'Donate', 'wp-cerber' ) . '</h3>
|
1525 |
-
<p>
|
1526 |
|
1527 |
<div style="text-align:center;">
|
1528 |
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
|
@@ -1820,23 +1857,6 @@ function cerber_db_diag(){
|
|
1820 |
return $err.implode('<br>',$ret);
|
1821 |
}
|
1822 |
|
1823 |
-
function cerber_wp_diag(){
|
1824 |
-
global $wp_version, $wpdb;
|
1825 |
-
|
1826 |
-
$ret = array();
|
1827 |
-
|
1828 |
-
$ret[] = 'WordPress version: ' . $wp_version;
|
1829 |
-
$ret[] = 'WordPress options table: '.$wpdb->prefix.'options';
|
1830 |
-
$ret[] = '<br>Active plugins:<br>';
|
1831 |
-
$list = get_option('active_plugins');
|
1832 |
-
foreach($list as $plugin) {
|
1833 |
-
$data = get_plugin_data(WP_PLUGIN_DIR.'/'.$plugin);
|
1834 |
-
$ret[] = '- '.$data['Name'].' v. '.$data['Version'];
|
1835 |
-
}
|
1836 |
-
|
1837 |
-
return implode("<br>",$ret);
|
1838 |
-
}
|
1839 |
-
|
1840 |
/**
|
1841 |
* Creates mini report about given database table
|
1842 |
*
|
@@ -1944,9 +1964,9 @@ add_action('customize_controls_print_scripts', 'cerber_admin_head' ); // @since
|
|
1944 |
function cerber_admin_head(){
|
1945 |
global $assets_url, $crb_assets_url, $crb_ajax_loader;
|
1946 |
|
1947 |
-
$assets_url =
|
1948 |
|
1949 |
-
$crb_assets_url =
|
1950 |
$crb_ajax_loader = $crb_assets_url . 'ajax-loader.gif';
|
1951 |
$crb_ajax_nonce = wp_create_nonce( 'crb-ajax-admin' );
|
1952 |
|
@@ -1979,7 +1999,7 @@ function cerber_admin_head(){
|
|
1979 |
if (lab_lab()):
|
1980 |
?>
|
1981 |
<style type="text/css" media="all">
|
1982 |
-
.actv5, .actv10, .actv11, .actv12, .actv16, .actv17, .actv18, .actv19, .actv41, .actv42, .actv53, .actv54, .actv55, .actv70 {
|
1983 |
padding: 0;
|
1984 |
border-left: none;
|
1985 |
background-color: initial;
|
@@ -1996,7 +2016,7 @@ function cerber_admin_head(){
|
|
1996 |
#crb-activity td.acinfo div {
|
1997 |
padding: 0.1em 0 0.1em 0.7em;
|
1998 |
}
|
1999 |
-
.crb10, .crb11, .crb12, .crb16, .crb17, .crb18, .crb19, .crb41, .crb42, .crb51, .crb52, .crb53, .crb54, .crb55, .crb70, .crb71 {
|
2000 |
/*border-left: 4px solid #FF5733;*/
|
2001 |
font-weight: bold;
|
2002 |
border-left: 6px solid #FF5733;
|
@@ -2077,7 +2097,13 @@ function cerber_footer_text2($text){
|
|
2077 |
$pr = '';
|
2078 |
$support = '<a target="_blank" href="https://wordpress.org/support/plugin/wp-cerber">Support Forum</a>';
|
2079 |
}
|
2080 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
2081 |
}
|
2082 |
|
2083 |
/*
|
@@ -2494,7 +2520,7 @@ function crb_country_html($code = null, $ip = null){
|
|
2494 |
|
2495 |
function cerber_traffic_page(){
|
2496 |
|
2497 |
-
$tab = cerber_get_tab( 'traffic', array( 'traffic', 'ti_settings' ) );
|
2498 |
|
2499 |
?>
|
2500 |
<div class="wrap">
|
@@ -2506,7 +2532,7 @@ function cerber_traffic_page(){
|
|
2506 |
|
2507 |
echo '<a href="' . cerber_admin_link('traffic') . '" class="nav-tab ' . ( $tab == 'traffic' ? 'nav-tab-active' : '') . '"><span class="dashicons dashicons-visibility"></span> ' . __('Live traffic') . '</a>';
|
2508 |
echo '<a href="' . cerber_admin_link('ti_settings') . '" class="nav-tab ' . ( $tab == 'ti_settings' ? 'nav-tab-active' : '') . '"><span class="dashicons dashicons-admin-settings"></span> ' . __('Settings') . '</a>';
|
2509 |
-
|
2510 |
|
2511 |
echo lab_indicator();
|
2512 |
?>
|
@@ -2525,6 +2551,9 @@ function cerber_traffic_page(){
|
|
2525 |
case 'ti_settings':
|
2526 |
cerber_show_settings_page( 'traffic' );
|
2527 |
break;
|
|
|
|
|
|
|
2528 |
default:
|
2529 |
cerber_show_activity();
|
2530 |
}
|
@@ -2718,13 +2747,13 @@ function cerber_show_traffic($args = array(), $echo = true){
|
|
2718 |
// POST fields
|
2719 |
|
2720 |
if ( ! empty( $fields[1] ) ) {
|
2721 |
-
$more_details[] = array('', cerber_table_view('
|
2722 |
}
|
2723 |
|
2724 |
// GET fields
|
2725 |
|
2726 |
if ( ! empty( $fields[2] ) ) {
|
2727 |
-
$more_details[] = array('', cerber_table_view('
|
2728 |
}
|
2729 |
|
2730 |
// Files
|
@@ -3015,6 +3044,7 @@ function cerber_traffic_query($args = array()){
|
|
3015 |
}
|
3016 |
if ($search['uri']) $where[] = $wpdb->prepare('log.uri LIKE %s','%'.$search['uri'].'%');
|
3017 |
if ($search['fields']) $where[] = $wpdb->prepare('log.request_fields LIKE %s','%'.$search['fields'].'%');
|
|
|
3018 |
if ($search['date_from']){
|
3019 |
if ($stamp = strtotime('midnight ' . $search['date_from'])){
|
3020 |
$gmt_offset = get_option( 'gmt_offset' ) * 3600;
|
@@ -3083,22 +3113,7 @@ function cerber_traffic_search(){
|
|
3083 |
<div id="crb-traffic-form" style="margin: 0 auto; width: 300px;">
|
3084 |
<input type="hidden" value="cerber-traffic" name="page">
|
3085 |
|
3086 |
-
<p>
|
3087 |
-
<br/><input type="text" name="search_traffic[uri]"></p>
|
3088 |
-
|
3089 |
-
<p>IP address contains or equals
|
3090 |
-
<br/><input type="text" name="search_traffic[ip]"></p>
|
3091 |
-
|
3092 |
-
<p>User ID equals
|
3093 |
-
<br/><input type="number" name="filter_user"></p>
|
3094 |
-
|
3095 |
-
<p>POST or GET fields contain
|
3096 |
-
<br/><input type="text" name="search_traffic[fields]"></p>
|
3097 |
-
|
3098 |
-
<p>HTTP Response Code equals
|
3099 |
-
<br/><input type="number" name="filter_http_code"></p>
|
3100 |
-
|
3101 |
-
<p style="width: 100%;">Activity
|
3102 |
<?php
|
3103 |
$labels = cerber_get_labels('activity');
|
3104 |
unset( $labels[5], $labels[51], $labels[13], $labels[14], $labels[15] );
|
@@ -3107,11 +3122,32 @@ function cerber_traffic_search(){
|
|
3107 |
?>
|
3108 |
</p>
|
3109 |
|
3110 |
-
<p>
|
3111 |
-
<br/><input type="
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3112 |
|
3113 |
-
<p>Date to
|
3114 |
-
<br/><input type="date" name="search_traffic[date_to]" placeholder="month/day/year"></p>
|
3115 |
|
3116 |
<p><input type="submit" class="button button-primary" value="Search"></p>
|
3117 |
</div>
|
@@ -3121,7 +3157,7 @@ function cerber_traffic_search(){
|
|
3121 |
|
3122 |
<?php
|
3123 |
|
3124 |
-
return '<a href="#TB_inline?width=400&height=
|
3125 |
|
3126 |
}
|
3127 |
|
382 |
else {
|
383 |
cerber_admin_notice( __( 'Unable to send email to', 'wp-cerber' ) . ' ' . $to );
|
384 |
}
|
385 |
+
cerber_safe_redirect('testnotify');
|
|
|
386 |
}
|
387 |
elseif ( $ip = cerber_get_get( 'lockdelete' ) ) {
|
388 |
if ( cerber_block_delete( $ip ) ) {
|
395 |
elseif ( isset( $_GET['subscribe'] ) ) {
|
396 |
$mode = ( 'on' == $_GET['subscribe'] ) ? 'on' : 'off';
|
397 |
cerber_subscribe( $mode );
|
398 |
+
cerber_safe_redirect('subscribe');
|
|
|
399 |
}
|
400 |
elseif ( isset( $_GET['citadel'] ) && $_GET['citadel'] == 'deactivate' ) {
|
401 |
cerber_disable_citadel();
|
403 |
elseif ( isset( $_GET['load_settings'] ) && $_GET['load_settings'] == 'default' ) {
|
404 |
cerber_load_defaults();
|
405 |
cerber_admin_message( __( 'Settings saved', 'wp-cerber' ) );
|
406 |
+
cerber_safe_redirect('load_settings');
|
|
|
407 |
}
|
408 |
elseif ( isset( $_GET['force_repair_db'] ) ) {
|
409 |
cerber_create_db();
|
410 |
cerber_upgrade_db( true );
|
411 |
cerber_admin_message( 'Cerber\'s tables has been upgraded' );
|
412 |
+
cerber_safe_redirect('force_repair_db');
|
|
|
413 |
}
|
414 |
elseif ( isset( $_GET['truncate'] ) ) {
|
415 |
$table = $_GET['truncate'];
|
420 |
}
|
421 |
else cerber_admin_message( $wpdb->last_error );
|
422 |
}
|
423 |
+
cerber_safe_redirect('truncate');
|
|
|
424 |
}
|
425 |
elseif ( isset( $_GET['force_check_nodes'] ) ) {
|
426 |
$best = lab_check_nodes( true );
|
427 |
cerber_admin_message( 'Cerber Lab\'s nodes has been checked. The closest node: ' . $best );
|
428 |
+
cerber_safe_redirect('force_check_nodes');
|
429 |
+
}
|
430 |
+
elseif ( isset( $_GET['clean_up_the_cache'] ) ) {
|
431 |
+
lab_cleanup_cache();
|
432 |
+
cerber_admin_message( 'The cache has been cleaned up');
|
433 |
+
cerber_safe_redirect('clean_up_the_cache');
|
434 |
}
|
435 |
}
|
436 |
|
451 |
|
452 |
}
|
453 |
|
454 |
+
function cerber_safe_redirect($args){
|
455 |
+
if (!is_array($args)){
|
456 |
+
$args = array($args);
|
457 |
+
}
|
458 |
+
$args[]='cerber_nonce';
|
459 |
+
wp_safe_redirect(remove_query_arg($args));
|
460 |
+
exit(); // mandatory!
|
461 |
+
}
|
462 |
/**
|
463 |
* Generate export CSV file using $_GET parameters (via cerber_activity_query())
|
464 |
*
|
1060 |
return false;
|
1061 |
}
|
1062 |
|
1063 |
+
function cerber_get_admin_page(){
|
1064 |
+
$ret = '';
|
1065 |
+
if (!empty($_GET['page'])){
|
1066 |
+
$ret = preg_replace('/[^A-Z0-9\_\-]/i','',$_GET['page']);
|
1067 |
+
}
|
1068 |
+
|
1069 |
+
return $ret;
|
1070 |
+
}
|
1071 |
+
|
1072 |
// Users -------------------------------------------------------------------------------------
|
1073 |
|
1074 |
add_filter('users_list_table_query_args' , function ($args) {
|
1284 |
|
1285 |
<?php echo $support; ?>
|
1286 |
|
1287 |
+
<p><span class="dashicons dashicons-before dashicons-book-alt"></span> <a href="https://wpcerber.com/toc/" target="_blank">Read articles on wpcerber.com</a></p>
|
1288 |
+
<p><span class="dashicons dashicons-before dashicons-format-chat"></span> <a href="https://wordpress.org/support/plugin/wp-cerber">Get answer on the support forum</a></p>
|
1289 |
|
1290 |
|
1291 |
<form style="margin-top: 2em;" action="https://wpcerber.com" target="_blank">
|
1293 |
<input type="text" style="width: 80%;" name="s" placeholder="Enter term to search"><input type="submit" value="Search" class="button button-primary">
|
1294 |
</form>
|
1295 |
|
1296 |
+
<h3>Traffic Inspector</h3>
|
1297 |
+
|
1298 |
+
<p>Traffic Inspector is a set of specialized request inspection algorithms that acts as an additional protection layer (firewall) for your WordPress</p>
|
1299 |
+
|
1300 |
+
<p>
|
1301 |
+
<span class="dashicons dashicons-before dashicons-book-alt"></span> <a href="https://wpcerber.com/traffic-inspector-in-a-nutshell/">Traffic Inspector in a nutshell</a>
|
1302 |
+
</p>
|
1303 |
+
<p><span class="dashicons dashicons-before dashicons-book-alt"></span> <a href="https://wpcerber.com/wordpress-traffic-inspector-how-to/">Traffic Inspector and logging how to</a>
|
1304 |
+
</p>
|
1305 |
+
|
1306 |
+
|
1307 |
</td>
|
1308 |
<td>
|
1309 |
<h3>What is IP address of your computer?</h3>
|
1310 |
|
1311 |
<p>To find out your current IP address go to this page: <a href="https://wpcerber.com/what-is-my-ip/">What is my IP</a>. If you see a different IP address on the Activity tab for your login or logout events you probably need to check <b><?php _e('My site is behind a reverse proxy','wp-cerber'); ?></b>.</p>
|
1312 |
<p>
|
1313 |
+
<span class="dashicons dashicons-before dashicons-book-alt"></span> <a href="https://wpcerber.com/wordpress-ip-address-detection/">Solving problem with incorrect IP address detection</a>
|
1314 |
</p>
|
1315 |
|
1316 |
|
1317 |
<h3>Setting up antispam protection</h3>
|
1318 |
|
1319 |
<p>
|
1320 |
+
The Cerber antispam and bot detection engine is capable to protect virtually any form on a website. It’s a great alternative to reCAPTCHA.
|
1321 |
</p>
|
1322 |
<p>
|
1323 |
+
<span class="dashicons dashicons-before dashicons-book-alt"></span> <a href="https://wpcerber.com/how-to-stop-spam-user-registrations-wordpress/">How to stop spam user registrations on your WordPress</a>
|
1324 |
+
</p>
|
1325 |
+
<p><span class="dashicons dashicons-before dashicons-book-alt"></span> <a href="https://wpcerber.com/antispam-for-wordpress-contact-forms/">Antispam protection for contact forms</a>
|
1326 |
</p>
|
1327 |
|
1328 |
|
1332 |
WP Cerber allows you to easily enable desktop and mobile notifications and get notifications instantly and for free. In a desktop browser, you will get popup messages even if you logged out of your WordPress.
|
1333 |
Before you start receiving notifications you need to install a free Pushbullet mobile application on your mobile device or free browser extension available for Chrome, Firefox and Opera.
|
1334 |
</p>
|
1335 |
+
<p><span class="dashicons dashicons-before dashicons-book-alt"></span>
|
1336 |
<a href="https://wpcerber.com/wordpress-mobile-and-browser-notifications-pushbullet/">A three steps instruction how to set up push notifications</a>
|
1337 |
</p>
|
1338 |
+
<p><span class="dashicons dashicons-before dashicons-book-alt"></span>
|
1339 |
<a href="https://wpcerber.com/wordpress-notifications-made-easy/">How to get alerts for specific activity on your website</a>
|
1340 |
</p>
|
1341 |
|
1342 |
+
<h3>WordPress security explained</h3>
|
1343 |
+
<p><span class="dashicons dashicons-before dashicons-book-alt"></span> <a href="https://wpcerber.com/why-recaptcha-does-not-protect-wordpress/">Why does reCAPTCHA not protect WordPress against bots and brute-force attacks?</a></p>
|
1344 |
+
<p><span class="dashicons dashicons-before dashicons-book-alt"></span> <a href="https://wpcerber.com/why-we-need-to-use-custom-login-url/">Why you need to use Custom login URL for your WordPress</a></p>
|
1345 |
+
<p><span class="dashicons-before dashicons-book-alt"></span> <a href="https://wpcerber.com/why-its-important-to-restrict-access-to-rest-api/">Why it's important to restrict access to the WP REST API</a></p>
|
1346 |
+
<p><span class="dashicons-before dashicons-book-alt"></span> <a href="https://wpcerber.com/mitigating-brute-force-dos-and-ddos-attacks/">Brute-force, DoS, and DDoS attacks - what's the difference?</a></p>
|
1347 |
</td>
|
1348 |
</tr>
|
1349 |
</table>
|
1471 |
echo '<table class="cerber-margin"><tr><td><h2 style="margin-bottom:0.5em; margin-right: 1em;">' . __( 'Activity', 'wp-cerber' ) . '</h2></td><td>' . $nav_links . '</td></tr></table>';
|
1472 |
|
1473 |
cerber_show_activity( array(
|
1474 |
+
'filter_activity' => array( 1, 2, 5, 10, 11, 12, 16, 17, 18, 19, 40, 41, 42, 50, 51, 52, 53, 54, 55, 56),
|
1475 |
'per_page' => 10,
|
1476 |
'no_navi' => true,
|
1477 |
'no_export' => true,
|
1546 |
';
|
1547 |
|
1548 |
// 22.01.2017
|
1549 |
+
/*
|
1550 |
+
* $aside[] = '<a class="crb-button-one" style="text-align:center; padding-top: 1.5em; padding-bottom: 1.5em; background-color: #C92E5C;" href="https://wpcerber.com/pro/" target="_blank">
|
1551 |
<span class="dashicons dashicons-awards"></span><span class="dashicons dashicons-awards"></span><span class="dashicons dashicons-awards"></span><br><br>UPGRADE TO PROFESSIONAL VERSION</a>';
|
1552 |
+
*/
|
1553 |
|
1554 |
+
$aside[] = '<a href="https://wpcerber.com/pro/" target="_blank"><img src="'.$crb_assets_url.'bn2ra.png" /></a>';
|
1555 |
|
1556 |
+
}
|
1557 |
+
/*
|
1558 |
if (!lab_lab() && !in_array($page,array('geo'))) {
|
1559 |
$aside[] = '<div class="crb-box" id = "crb-donate">
|
1560 |
<div class="crb-box-inner">
|
1561 |
<h3>' . __( 'Donate', 'wp-cerber' ) . '</h3>
|
1562 |
+
<p>Please consider making a donation to support the continued development and free support of this plugin. Thanks!</p>
|
1563 |
|
1564 |
<div style="text-align:center;">
|
1565 |
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
|
1857 |
return $err.implode('<br>',$ret);
|
1858 |
}
|
1859 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1860 |
/**
|
1861 |
* Creates mini report about given database table
|
1862 |
*
|
1964 |
function cerber_admin_head(){
|
1965 |
global $assets_url, $crb_assets_url, $crb_ajax_loader;
|
1966 |
|
1967 |
+
$assets_url = cerber_plugin_dir_url() . 'assets/';
|
1968 |
|
1969 |
+
$crb_assets_url = cerber_plugin_dir_url() . 'assets/';
|
1970 |
$crb_ajax_loader = $crb_assets_url . 'ajax-loader.gif';
|
1971 |
$crb_ajax_nonce = wp_create_nonce( 'crb-ajax-admin' );
|
1972 |
|
1999 |
if (lab_lab()):
|
2000 |
?>
|
2001 |
<style type="text/css" media="all">
|
2002 |
+
.actv5, .actv10, .actv11, .actv12, .actv16, .actv17, .actv18, .actv19, .actv41, .actv42, .actv53, .actv54, .actv55, .actv56, .actv70 {
|
2003 |
padding: 0;
|
2004 |
border-left: none;
|
2005 |
background-color: initial;
|
2016 |
#crb-activity td.acinfo div {
|
2017 |
padding: 0.1em 0 0.1em 0.7em;
|
2018 |
}
|
2019 |
+
.crb10, .crb11, .crb12, .crb16, .crb17, .crb18, .crb19, .crb41, .crb42, .crb51, .crb52, .crb53, .crb54, .crb55, .crb56, .crb70, .crb71 {
|
2020 |
/*border-left: 4px solid #FF5733;*/
|
2021 |
font-weight: bold;
|
2022 |
border-left: 6px solid #FF5733;
|
2097 |
$pr = '';
|
2098 |
$support = '<a target="_blank" href="https://wordpress.org/support/plugin/wp-cerber">Support Forum</a>';
|
2099 |
}
|
2100 |
+
if (1 == cerber_get_mode()){
|
2101 |
+
$mode = 'in Standard mode';
|
2102 |
+
}
|
2103 |
+
else {
|
2104 |
+
$mode = 'in Legacy mode';
|
2105 |
+
}
|
2106 |
+
return 'WP Cerber Security '.$pr.' '.CERBER_VER.'. '.$mode.' | ' . $support;
|
2107 |
}
|
2108 |
|
2109 |
/*
|
2520 |
|
2521 |
function cerber_traffic_page(){
|
2522 |
|
2523 |
+
$tab = cerber_get_tab( 'traffic', array( 'traffic', 'ti_settings', 'help' ) );
|
2524 |
|
2525 |
?>
|
2526 |
<div class="wrap">
|
2532 |
|
2533 |
echo '<a href="' . cerber_admin_link('traffic') . '" class="nav-tab ' . ( $tab == 'traffic' ? 'nav-tab-active' : '') . '"><span class="dashicons dashicons-visibility"></span> ' . __('Live traffic') . '</a>';
|
2534 |
echo '<a href="' . cerber_admin_link('ti_settings') . '" class="nav-tab ' . ( $tab == 'ti_settings' ? 'nav-tab-active' : '') . '"><span class="dashicons dashicons-admin-settings"></span> ' . __('Settings') . '</a>';
|
2535 |
+
echo '<a href="' . cerber_admin_link('help',array('page'=>cerber_get_admin_page())) . '" class="nav-tab ' . ( $tab == 'help' ? 'nav-tab-active' : '') . '"><span class="dashicons dashicons-editor-help"></span> ' . __('Help','wp-cerber') . '</a>';
|
2536 |
|
2537 |
echo lab_indicator();
|
2538 |
?>
|
2551 |
case 'ti_settings':
|
2552 |
cerber_show_settings_page( 'traffic' );
|
2553 |
break;
|
2554 |
+
case 'help':
|
2555 |
+
cerber_show_help();
|
2556 |
+
break;
|
2557 |
default:
|
2558 |
cerber_show_activity();
|
2559 |
}
|
2747 |
// POST fields
|
2748 |
|
2749 |
if ( ! empty( $fields[1] ) ) {
|
2750 |
+
$more_details[] = array('', cerber_table_view('POST fields',$fields[1]) );
|
2751 |
}
|
2752 |
|
2753 |
// GET fields
|
2754 |
|
2755 |
if ( ! empty( $fields[2] ) ) {
|
2756 |
+
$more_details[] = array('', cerber_table_view('GET fields',$fields[2]) );
|
2757 |
}
|
2758 |
|
2759 |
// Files
|
3044 |
}
|
3045 |
if ($search['uri']) $where[] = $wpdb->prepare('log.uri LIKE %s','%'.$search['uri'].'%');
|
3046 |
if ($search['fields']) $where[] = $wpdb->prepare('log.request_fields LIKE %s','%'.$search['fields'].'%');
|
3047 |
+
if ($search['details']) $where[] = $wpdb->prepare('log.request_details LIKE %s','%'.$search['details'].'%');
|
3048 |
if ($search['date_from']){
|
3049 |
if ($stamp = strtotime('midnight ' . $search['date_from'])){
|
3050 |
$gmt_offset = get_option( 'gmt_offset' ) * 3600;
|
3113 |
<div id="crb-traffic-form" style="margin: 0 auto; width: 300px;">
|
3114 |
<input type="hidden" value="cerber-traffic" name="page">
|
3115 |
|
3116 |
+
<p style="width: 100%;"><label>Activity</label>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3117 |
<?php
|
3118 |
$labels = cerber_get_labels('activity');
|
3119 |
unset( $labels[5], $labels[51], $labels[13], $labels[14], $labels[15] );
|
3122 |
?>
|
3123 |
</p>
|
3124 |
|
3125 |
+
<p><label for="search-traffic-url">URL contains</label>
|
3126 |
+
<br/><input id="search-traffic-url" type="text" name="search_traffic[uri]"></p>
|
3127 |
+
|
3128 |
+
<p><label for="search-traffic-ip">IP address contains or equals</label>
|
3129 |
+
<br/><input id="search-traffic-ip" type="text" name="search_traffic[ip]"></p>
|
3130 |
+
|
3131 |
+
<p><label for="filter-method">Request method</label>
|
3132 |
+
<select id="filter-method" name="filter_method"><option value="0">Any</option><option>GET</option><option>POST</option></select></p>
|
3133 |
+
|
3134 |
+
<p><label for="filter-user">User ID equals</label>
|
3135 |
+
<br/><input id="filter-user" type="number" name="filter_user"></p>
|
3136 |
+
|
3137 |
+
<p><label for="search-traffic-fields">POST or GET fields contain</label>
|
3138 |
+
<br/><input id="search-traffic-fields" type="text" name="search_traffic[fields]"></p>
|
3139 |
+
|
3140 |
+
<p><label for="search-traffic-details">Miscellaneous details contains</label>
|
3141 |
+
<br/><input id="search-traffic-details" type="text" name="search_traffic[details]"></p>
|
3142 |
+
|
3143 |
+
<p><label for="filter-http-code">HTTP Response Code equals</label>
|
3144 |
+
<br/><input id="filter-http-code" type="number" name="filter_http_code"></p>
|
3145 |
+
|
3146 |
+
<p><label for="search-traffic-date-from">Date from</label>
|
3147 |
+
<br/><input id="search-traffic-date-from" type="date" name="search_traffic[date_from]" placeholder="month/day/year"></p>
|
3148 |
|
3149 |
+
<p><label for="search-traffic-date-to">Date to</label>
|
3150 |
+
<br/><input id="search-traffic-date-to" type="date" name="search_traffic[date_to]" placeholder="month/day/year"></p>
|
3151 |
|
3152 |
<p><input type="submit" class="button button-primary" value="Search"></p>
|
3153 |
</div>
|
3157 |
|
3158 |
<?php
|
3159 |
|
3160 |
+
return '<a href="#TB_inline?width=400&height=720&inlineId=cerber-traffic-search" class="thickbox crb-button-tiny crb-button-active" title="Search in the request history">'.__('Advanced search','wp-cerber').'</a>';
|
3161 |
|
3162 |
}
|
3163 |
|
languages/wp-cerber-zh_CN.mo
ADDED
Binary file
|
languages/wp-cerber-zh_CN.po
ADDED
@@ -0,0 +1,1771 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
msgid ""
|
2 |
+
msgstr ""
|
3 |
+
"MIME-Version: 1.0\n"
|
4 |
+
"Content-Type: text/plain; charset=UTF-8\n"
|
5 |
+
"Content-Transfer-Encoding: 8bit\n"
|
6 |
+
"X-Generator: POEditor.com\n"
|
7 |
+
"Project-Id-Version: WP Cerber Security\n"
|
8 |
+
"Language: zh-CN\n"
|
9 |
+
"Plural-Forms: nplurals=1; plural=0;\n"
|
10 |
+
|
11 |
+
#: ../settings.php:73
|
12 |
+
msgid "Limit login attempts"
|
13 |
+
msgstr "限制登入尝试"
|
14 |
+
|
15 |
+
#: ../settings.php:74
|
16 |
+
msgid "Attempts"
|
17 |
+
msgstr "尝试"
|
18 |
+
|
19 |
+
#: ../settings.php:75
|
20 |
+
msgid "Lockout duration"
|
21 |
+
msgstr "锁定时长"
|
22 |
+
|
23 |
+
#: ../settings.php:75 ../settings.php:94
|
24 |
+
msgid "minutes"
|
25 |
+
msgstr "分钟"
|
26 |
+
|
27 |
+
#: ../settings.php:76
|
28 |
+
msgid "Aggressive lockout"
|
29 |
+
msgstr "激进屏蔽"
|
30 |
+
|
31 |
+
#: ../settings.php:79
|
32 |
+
msgid "Site connection"
|
33 |
+
msgstr "网站连接"
|
34 |
+
|
35 |
+
#: ../settings.php:81
|
36 |
+
msgid "Proactive security rules"
|
37 |
+
msgstr "主动安全规则"
|
38 |
+
|
39 |
+
#: ../settings.php:82
|
40 |
+
msgid "Block subnet"
|
41 |
+
msgstr "锁定subnet"
|
42 |
+
|
43 |
+
#: ../settings.php:85
|
44 |
+
msgid "Request wp-login.php"
|
45 |
+
msgstr "请求/wp-login.php/"
|
46 |
+
|
47 |
+
#: ../settings.php:85
|
48 |
+
msgid "Immediately block IP after any request to wp-login.php"
|
49 |
+
msgstr "立即锁定任何请求/wp-login.php/的IP"
|
50 |
+
|
51 |
+
#: ../settings.php:84
|
52 |
+
msgid "Redirect dashboard requests"
|
53 |
+
msgstr "重定向Wordpress控制面板请求"
|
54 |
+
|
55 |
+
#: ../settings.php:88
|
56 |
+
msgid "Custom login page"
|
57 |
+
msgstr "自定义登入页"
|
58 |
+
|
59 |
+
#: ../settings.php:89
|
60 |
+
msgid "Custom login URL"
|
61 |
+
msgstr "自定义登入页URL"
|
62 |
+
|
63 |
+
#: ../settings.php:89
|
64 |
+
msgid "must not overlap with the existing pages or posts slug"
|
65 |
+
msgstr "不能与已存在的页面或文章冲突"
|
66 |
+
|
67 |
+
#: ../settings.php:90
|
68 |
+
msgid "Disable wp-login.php"
|
69 |
+
msgstr "禁用/wp-login.php/"
|
70 |
+
|
71 |
+
#: ../settings.php:90
|
72 |
+
msgid "Block direct access to wp-login.php and return HTTP 404 Not Found Error"
|
73 |
+
msgstr "屏蔽直接接入/wp-login.php/并显示404页面"
|
74 |
+
|
75 |
+
#: ../dashboard.php:1209 ../settings.php:92
|
76 |
+
msgid "Citadel mode"
|
77 |
+
msgstr "要塞模式"
|
78 |
+
|
79 |
+
#: ../settings.php:93
|
80 |
+
msgid "Threshold"
|
81 |
+
msgstr "阈值"
|
82 |
+
|
83 |
+
#: ../settings.php:94
|
84 |
+
msgid "Duration"
|
85 |
+
msgstr "时长"
|
86 |
+
|
87 |
+
#: ../cerber-load.php:3837 ../settings.php:78 ../settings.php:95 ../settings.php:
|
88 |
+
#: 404
|
89 |
+
msgid "Notifications"
|
90 |
+
msgstr "提醒"
|
91 |
+
|
92 |
+
#: ../settings.php:95
|
93 |
+
msgid "Send notification to admin email"
|
94 |
+
msgstr "向管理员邮箱发送提醒"
|
95 |
+
|
96 |
+
#: ../cerber-load.php:3834 ../settings.php:397 ../cerber-tools.php:88 ../cerber-
|
97 |
+
#: tools.php:97 ../cerber-tools.php:178
|
98 |
+
msgid "Access Lists"
|
99 |
+
msgstr "接入列表"
|
100 |
+
|
101 |
+
#: ../dashboard.php:1227 ../dashboard.php:1437 ../cerber-load.php:3593 ..
|
102 |
+
#: /settings.php:97 ../settings.php:388
|
103 |
+
msgid "Activity"
|
104 |
+
msgstr "活动"
|
105 |
+
|
106 |
+
#: ../settings.php:392
|
107 |
+
msgid "Lockouts"
|
108 |
+
msgstr "锁定"
|
109 |
+
|
110 |
+
#: ../settings.php:513 ../settings.php:635
|
111 |
+
msgid "%s allowed retries in %s minutes"
|
112 |
+
msgstr "%s 次重试在 %s 分钟内"
|
113 |
+
|
114 |
+
#: ../settings.php:535 ../settings.php:657
|
115 |
+
msgid "Enable after %s failed login attempts in last %s minutes"
|
116 |
+
msgstr "选项开启于 %s 次登入失败在 %s 分钟内"
|
117 |
+
|
118 |
+
#: ../dashboard.php:93 ../dashboard.php:652 ../dashboard.php:2826 ../cerber-load.
|
119 |
+
#: php:3602
|
120 |
+
msgid "IP"
|
121 |
+
msgstr "IP"
|
122 |
+
|
123 |
+
#: ../dashboard.php:491 ../dashboard.php:655 ../dashboard.php:2824
|
124 |
+
msgid "Date"
|
125 |
+
msgstr "日期"
|
126 |
+
|
127 |
+
#: ../dashboard.php:491 ../dashboard.php:657 ../dashboard.php:2829
|
128 |
+
msgid "Local User"
|
129 |
+
msgstr "本地用户"
|
130 |
+
|
131 |
+
#: ../dashboard.php:491 ../dashboard.php:658 ../cerber-load.php:3610
|
132 |
+
msgid "Username used"
|
133 |
+
msgstr "使用的用户名"
|
134 |
+
|
135 |
+
#: ../dashboard.php:112
|
136 |
+
msgid "Showing last %d records from %d"
|
137 |
+
msgstr "显示最近的 %d 记录从 %d"
|
138 |
+
|
139 |
+
#: ../common.php:708
|
140 |
+
msgid "Logged in"
|
141 |
+
msgstr "登入"
|
142 |
+
|
143 |
+
#: ../common.php:709
|
144 |
+
msgid "Logged out"
|
145 |
+
msgstr "登出"
|
146 |
+
|
147 |
+
#: ../common.php:710
|
148 |
+
msgid "Login failed"
|
149 |
+
msgstr "登入失败"
|
150 |
+
|
151 |
+
#: ../common.php:713
|
152 |
+
msgid "IP blocked"
|
153 |
+
msgstr "IP被锁定"
|
154 |
+
|
155 |
+
#: ../common.php:714
|
156 |
+
msgid "Subnet blocked"
|
157 |
+
msgstr ""
|
158 |
+
|
159 |
+
#: ../common.php:716
|
160 |
+
msgid "Citadel activated!"
|
161 |
+
msgstr "要塞模式已被激活!"
|
162 |
+
|
163 |
+
#: ../dashboard.php:632 ../dashboard.php:836 ../dashboard.php:2662 ../common.php:
|
164 |
+
#: 753
|
165 |
+
msgid "Locked out"
|
166 |
+
msgstr "锁定"
|
167 |
+
|
168 |
+
#: ../common.php:754
|
169 |
+
msgid "IP blacklisted"
|
170 |
+
msgstr "黑名单IP"
|
171 |
+
|
172 |
+
#: ../common.php:731
|
173 |
+
msgid "Password changed"
|
174 |
+
msgstr "密码已更改"
|
175 |
+
|
176 |
+
#: ../dashboard.php:86 ../dashboard.php:159
|
177 |
+
msgid "Remove"
|
178 |
+
msgstr "移除"
|
179 |
+
|
180 |
+
#: ../dashboard.php:390
|
181 |
+
msgid "Lockout for %s was removed"
|
182 |
+
msgstr "%s 的锁定已被移除"
|
183 |
+
|
184 |
+
#: ../dashboard.php:131 ../dashboard.php:627 ../dashboard.php:830 ../dashboard.
|
185 |
+
#: php:1207 ../dashboard.php:2657 ../cerber-load.php:3826 ../settings.php:77 ..
|
186 |
+
#: /settings.php:358
|
187 |
+
msgid "White IP Access List"
|
188 |
+
msgstr "IP白名单"
|
189 |
+
|
190 |
+
#: ../dashboard.php:133 ../dashboard.php:628 ../dashboard.php:833 ../dashboard.
|
191 |
+
#: php:1208 ../dashboard.php:2658
|
192 |
+
msgid "Black IP Access List"
|
193 |
+
msgstr "IP黑名单"
|
194 |
+
|
195 |
+
#: ../dashboard.php:165
|
196 |
+
msgid "List is empty"
|
197 |
+
msgstr "列表为空"
|
198 |
+
|
199 |
+
#: ../dashboard.php:202
|
200 |
+
msgid "Address %s was added to White IP Access List"
|
201 |
+
msgstr "地址 %s 已被加入IP白名单"
|
202 |
+
|
203 |
+
#: ../dashboard.php:216
|
204 |
+
msgid "Address %s was added to Black IP Access List"
|
205 |
+
msgstr "地址 %s 已被加入IP黑名单"
|
206 |
+
|
207 |
+
#: ../cerber-load.php:3075
|
208 |
+
msgid "Citadel mode is activated after %d failed login attempts in %d minutes."
|
209 |
+
msgstr "在 %d 次失败登入尝试后,要塞模式已激活 %d 分钟。"
|
210 |
+
|
211 |
+
#: ../dashboard.php:1592
|
212 |
+
msgid "View Activity"
|
213 |
+
msgstr "查看活动"
|
214 |
+
|
215 |
+
#: ../dashboard.php:2514 ../cerber-tools.php:87 ../cerber-tools.php:96
|
216 |
+
msgid "Settings"
|
217 |
+
msgstr "设置"
|
218 |
+
|
219 |
+
#: ../dashboard.php:1073
|
220 |
+
msgid "Last login"
|
221 |
+
msgstr "最后登入"
|
222 |
+
|
223 |
+
#: ../dashboard.php:1106 ../dashboard.php:1190
|
224 |
+
msgid "Never"
|
225 |
+
msgstr "永不"
|
226 |
+
|
227 |
+
#: ../dashboard.php:1483
|
228 |
+
msgid "Are you sure?"
|
229 |
+
msgstr "确定操作?"
|
230 |
+
|
231 |
+
#: ../dashboard.php:1284 ../settings.php:79
|
232 |
+
msgid "My site is behind a reverse proxy"
|
233 |
+
msgstr "网站基于反向代理"
|
234 |
+
|
235 |
+
#: ../settings.php:83
|
236 |
+
msgid "Non-existent users"
|
237 |
+
msgstr "不存在的用户名"
|
238 |
+
|
239 |
+
#: ../settings.php:83
|
240 |
+
msgid "Immediately block IP when attempting to login with a non-existent username"
|
241 |
+
msgstr "立即锁定尝试通过不存在的用户名登入的IP"
|
242 |
+
|
243 |
+
#: ../settings.php:84
|
244 |
+
msgid "Disable automatic redirecting to the login page when /wp-admin/ is requested by an unauthorized request"
|
245 |
+
msgstr "自动重定向登入页,当/wp-admin/被未知来源所请求"
|
246 |
+
|
247 |
+
#: ../settings.php:344
|
248 |
+
msgid "Make your protection smarter!"
|
249 |
+
msgstr "使保护更加智能!"
|
250 |
+
|
251 |
+
#: ../settings.php:348
|
252 |
+
msgid "Please enable Permalinks to use this feature. Set Permalink Settings to something other than Default."
|
253 |
+
msgstr "要使用该功能,请在Wordpress设置中将固定链接设为默认值以外的格式。"
|
254 |
+
|
255 |
+
#: ../settings.php:351
|
256 |
+
msgid "Be careful when enabling this options. If you forget the custom login URL you will not be able to login."
|
257 |
+
msgstr "谨慎使用该选项,如果忘记自定义的登入页URL,之后将无法登入。"
|
258 |
+
|
259 |
+
#: ../cerber-load.php:3833 ../settings.php:394
|
260 |
+
msgid "Main Settings"
|
261 |
+
msgstr "主要设置"
|
262 |
+
|
263 |
+
#: ../settings.php:406
|
264 |
+
msgid "Help"
|
265 |
+
msgstr "帮助"
|
266 |
+
|
267 |
+
#: ../settings.php:523 ../settings.php:645
|
268 |
+
msgid "Increase lockout duration to %s hours after %s lockouts in the last %s hours"
|
269 |
+
msgstr "增加锁定时长 %s 小时,如果达到 %s 次锁定于 %s 小时内"
|
270 |
+
|
271 |
+
#: ../cerber-load.php:215
|
272 |
+
msgid "You are not allowed to log in. Ask your administrator for assistance."
|
273 |
+
msgstr "已被禁止登入。请向管理员寻求帮助。"
|
274 |
+
|
275 |
+
#: ../cerber-load.php:221
|
276 |
+
msgid "You have reached the login attempts limit. Please try again in %d minutes."
|
277 |
+
msgstr "登入次数已受限。请 %d 分钟后再试。"
|
278 |
+
|
279 |
+
#: ../cerber-load.php:240
|
280 |
+
msgid "You have only one attempt remaining."
|
281 |
+
msgid_plural "You have %d attempts remaining."
|
282 |
+
msgstr[0] "剩余 %d 次尝试机会。"
|
283 |
+
|
284 |
+
#: ../dashboard.php:680
|
285 |
+
msgid "No activity has been logged."
|
286 |
+
msgstr "没有被记录的活动。"
|
287 |
+
|
288 |
+
#: ../dashboard.php:96
|
289 |
+
msgid "Expires"
|
290 |
+
msgstr "到期"
|
291 |
+
|
292 |
+
#: ../dashboard.php:118
|
293 |
+
msgid "No lockouts at the moment. The sky is clear."
|
294 |
+
msgstr "没有被锁定的项目。天空晴好。"
|
295 |
+
|
296 |
+
#: ../dashboard.php:131
|
297 |
+
msgid "These IPs will never be locked out"
|
298 |
+
msgstr "这些IP永不被锁定"
|
299 |
+
|
300 |
+
#: ../dashboard.php:140
|
301 |
+
msgid "Your IP"
|
302 |
+
msgstr "您的IP"
|
303 |
+
|
304 |
+
#: ../cerber-load.php:3076
|
305 |
+
msgid "Last failed attempt was at %s from IP %s with user login: %s."
|
306 |
+
msgstr "最近一次失败的登入尝试在 %s 来自IP %s 登入的用户名为: %s。"
|
307 |
+
|
308 |
+
#: ../cerber-load.php:3805
|
309 |
+
msgid "Can't activate WP Cerber due to a database error."
|
310 |
+
msgstr "数据库错误,未能激活WP Cerber安全插件。"
|
311 |
+
|
312 |
+
#: ../settings.php:530 ../settings.php:652
|
313 |
+
msgid "Notify admin if the number of active lockouts above"
|
314 |
+
msgstr "通知管理员,如果激活的锁定次数超过"
|
315 |
+
|
316 |
+
#: ../settings.php:98 ../settings.php:172 ../settings.php:334
|
317 |
+
msgid "days"
|
318 |
+
msgstr "天"
|
319 |
+
|
320 |
+
#: ../dashboard.php:1160
|
321 |
+
msgid "Cerber Quick View"
|
322 |
+
msgstr "Cerber快览"
|
323 |
+
|
324 |
+
#: ../dashboard.php:114
|
325 |
+
msgid "Hint"
|
326 |
+
msgstr "提示"
|
327 |
+
|
328 |
+
#: ../dashboard.php:114
|
329 |
+
msgid "To view activity, click on the IP"
|
330 |
+
msgstr "点击IP地址,查看其活动"
|
331 |
+
|
332 |
+
#: ../dashboard.php:158 ../dashboard.php:843 ../dashboard.php:870 ../dashboard.
|
333 |
+
#: php:962
|
334 |
+
msgid "Check for activity"
|
335 |
+
msgstr "检查活动"
|
336 |
+
|
337 |
+
#: ../settings.php:82
|
338 |
+
msgid "Always block entire subnet Class C of intruders IP"
|
339 |
+
msgstr ""
|
340 |
+
|
341 |
+
#: ../settings.php:95 ../settings.php:532 ../settings.php:654
|
342 |
+
msgid "Click to send test"
|
343 |
+
msgstr "点击发送测试"
|
344 |
+
|
345 |
+
#: ../settings.php:801 ../settings.php:802
|
346 |
+
msgid "Attention! You have changed the login URL! The new login URL is"
|
347 |
+
msgstr "注意!登入页URL已改变,新的登入页URL是"
|
348 |
+
|
349 |
+
#: ../dashboard.php:1072
|
350 |
+
msgid "Comments"
|
351 |
+
msgstr "留言"
|
352 |
+
|
353 |
+
#: ../common.php:986
|
354 |
+
msgid "Update to version %s of WP Cerber"
|
355 |
+
msgstr "升级WP Cerber到%s"
|
356 |
+
|
357 |
+
#: ../cerber-load.php:3077 ../cerber-load.php:3634
|
358 |
+
msgid "View activity in dashboard"
|
359 |
+
msgstr "在控制面板中查看活动信息"
|
360 |
+
|
361 |
+
#: ../cerber-load.php:3107
|
362 |
+
msgid "Number of active lockouts"
|
363 |
+
msgstr "已激活的锁定数量"
|
364 |
+
|
365 |
+
#: ../cerber-load.php:3111
|
366 |
+
msgid "View lockouts in dashboard"
|
367 |
+
msgstr "在控制面板中查看锁定信息"
|
368 |
+
|
369 |
+
#: ../cerber-load.php:3193
|
370 |
+
msgid "This message was sent by"
|
371 |
+
msgstr "消息来自"
|
372 |
+
|
373 |
+
#: ../dashboard.php:1001 ../cerber-tools.php:43
|
374 |
+
msgid "Tools"
|
375 |
+
msgstr "工具"
|
376 |
+
|
377 |
+
#: ../cerber-tools.php:84
|
378 |
+
msgid "Export settings to the file"
|
379 |
+
msgstr "导出设置文件"
|
380 |
+
|
381 |
+
#: ../cerber-tools.php:85
|
382 |
+
msgid "When you click the button below you will get a configuration file, which you can upload on another site."
|
383 |
+
msgstr "当点击下方按钮,将得到一份设置文件,可上传到其它网站使用。"
|
384 |
+
|
385 |
+
#: ../cerber-tools.php:86
|
386 |
+
msgid "What do you want to export?"
|
387 |
+
msgstr "要导出什么?"
|
388 |
+
|
389 |
+
#: ../cerber-tools.php:89
|
390 |
+
msgid "Download file"
|
391 |
+
msgstr "下载文件"
|
392 |
+
|
393 |
+
#: ../cerber-tools.php:91
|
394 |
+
msgid "Import settings from the file"
|
395 |
+
msgstr "导入设置文件"
|
396 |
+
|
397 |
+
#: ../cerber-tools.php:92
|
398 |
+
msgid "When you click the button below, file will be uploaded and all existing settings will be overridden."
|
399 |
+
msgstr "击下方按钮后,文件将被上传并覆盖现有的设置。"
|
400 |
+
|
401 |
+
#: ../cerber-tools.php:93
|
402 |
+
msgid "Select file to import."
|
403 |
+
msgstr "选择要导入的文件。"
|
404 |
+
|
405 |
+
#: ../cerber-tools.php:93
|
406 |
+
msgid "Maximum upload file size: %s."
|
407 |
+
msgstr "文件上传最大值: %s。"
|
408 |
+
|
409 |
+
#: ../cerber-tools.php:96
|
410 |
+
msgid "What do you want to import?"
|
411 |
+
msgstr "要导入什么?"
|
412 |
+
|
413 |
+
#: ../cerber-tools.php:98
|
414 |
+
msgid "Upload file"
|
415 |
+
msgstr "上传文件"
|
416 |
+
|
417 |
+
#: ../cerber-tools.php:145
|
418 |
+
msgid "No file was uploaded or file is corrupted"
|
419 |
+
msgstr "没有文件被上传,或者文件有误"
|
420 |
+
|
421 |
+
#: ../cerber-tools.php:178
|
422 |
+
msgid "Error while updating"
|
423 |
+
msgstr "上传错误"
|
424 |
+
|
425 |
+
#: ../cerber-tools.php:181
|
426 |
+
msgid "Settings has imported successfully from"
|
427 |
+
msgstr "设置已成功导入自"
|
428 |
+
|
429 |
+
#: ../cerber-tools.php:185
|
430 |
+
msgid "Error while parsing file"
|
431 |
+
msgstr "分析文件出错"
|
432 |
+
|
433 |
+
#: ../dashboard.php:94 ../dashboard.php:653
|
434 |
+
msgid "Hostname"
|
435 |
+
msgstr "主机名"
|
436 |
+
|
437 |
+
#: ../dashboard.php:355
|
438 |
+
msgid "unknown"
|
439 |
+
msgstr "未知"
|
440 |
+
|
441 |
+
#: ../settings.php:98 ../settings.php:330
|
442 |
+
msgid "Keep records for"
|
443 |
+
msgstr "保存记录时长"
|
444 |
+
|
445 |
+
#: ../dashboard.php:1194 ../dashboard.php:1215
|
446 |
+
msgid "active"
|
447 |
+
msgstr "激活"
|
448 |
+
|
449 |
+
#: ../dashboard.php:1194
|
450 |
+
msgid "deactivate"
|
451 |
+
msgstr "取消激活"
|
452 |
+
|
453 |
+
#: ../dashboard.php:1196
|
454 |
+
msgid "not active"
|
455 |
+
msgstr "未激活"
|
456 |
+
|
457 |
+
#: ../dashboard.php:1197 ../dashboard.php:1211
|
458 |
+
msgid "disabled"
|
459 |
+
msgstr "禁用"
|
460 |
+
|
461 |
+
#: ../dashboard.php:1202
|
462 |
+
msgid "failed attempts"
|
463 |
+
msgstr "失败尝试"
|
464 |
+
|
465 |
+
#: ../dashboard.php:1202 ../dashboard.php:1203
|
466 |
+
msgid "in 24 hours"
|
467 |
+
msgstr "在24小时内"
|
468 |
+
|
469 |
+
#: ../dashboard.php:1202 ../dashboard.php:1203
|
470 |
+
msgid "view all"
|
471 |
+
msgstr "查看全部"
|
472 |
+
|
473 |
+
#: ../dashboard.php:1203
|
474 |
+
msgid "lockouts"
|
475 |
+
msgstr "锁定"
|
476 |
+
|
477 |
+
#: ../dashboard.php:1205
|
478 |
+
msgid "Lockouts at the moment"
|
479 |
+
msgstr "现有锁定"
|
480 |
+
|
481 |
+
#: ../dashboard.php:1206
|
482 |
+
msgid "Last lockout"
|
483 |
+
msgstr "最近锁定"
|
484 |
+
|
485 |
+
#: ../dashboard.php:1207 ../dashboard.php:1208 ../dashboard.php:1763
|
486 |
+
msgid "entry"
|
487 |
+
msgid_plural "entries"
|
488 |
+
msgstr[0] "条目"
|
489 |
+
|
490 |
+
#: ../dashboard.php:1478
|
491 |
+
msgid "Confused about some settings?"
|
492 |
+
msgstr "不了解如何设置?"
|
493 |
+
|
494 |
+
#: ../dashboard.php:1479
|
495 |
+
msgid "You can easily load default recommended settings using button below"
|
496 |
+
msgstr "点击下方按钮您可以轻松载入推荐值"
|
497 |
+
|
498 |
+
#: ../dashboard.php:1481
|
499 |
+
msgid "Load default settings"
|
500 |
+
msgstr "载入默认值"
|
501 |
+
|
502 |
+
#: ../dashboard.php:1489
|
503 |
+
msgid "doesn't affect Custom login URL and Access Lists"
|
504 |
+
msgstr "不影响自定义登入页URL和接入列表"
|
505 |
+
|
506 |
+
#: ../common.php:979 ../settings.php:214
|
507 |
+
msgid "New version is available"
|
508 |
+
msgstr "新版可用"
|
509 |
+
|
510 |
+
#. Name of the plugin
|
511 |
+
#: ../dashboard.php:989 ../dashboard.php:1011
|
512 |
+
msgid "WP Cerber"
|
513 |
+
msgstr ""
|
514 |
+
|
515 |
+
#: ../cerber-load.php:3051
|
516 |
+
msgid "WP Cerber notify"
|
517 |
+
msgstr "WP Cerber通知"
|
518 |
+
|
519 |
+
#: ../cerber-load.php:3073
|
520 |
+
msgid "Citadel mode is activated"
|
521 |
+
msgstr "要塞模式已激活"
|
522 |
+
|
523 |
+
#: ../cerber-load.php:3147
|
524 |
+
msgid "New Custom login URL"
|
525 |
+
msgstr "自定义登入页URL"
|
526 |
+
|
527 |
+
#: ../cerber-load.php:3792
|
528 |
+
msgid "The WP Cerber requires PHP %s or higher. You are running"
|
529 |
+
msgstr "WP Cerber安全插件需要PHP版本不低于 %s。您运行的版本"
|
530 |
+
|
531 |
+
#: ../cerber-load.php:3796
|
532 |
+
msgid "The WP Cerber requires WordPress %s or higher. You are running"
|
533 |
+
msgstr "WP Cerber安全插件需要WordPress版本不低于 %s。您运行的版本"
|
534 |
+
|
535 |
+
#: ../settings.php:101
|
536 |
+
msgid "Use file"
|
537 |
+
msgstr "使用文件"
|
538 |
+
|
539 |
+
#: ../settings.php:101
|
540 |
+
msgid "Write failed login attempts to the file"
|
541 |
+
msgstr "将失败的登入记录到文件"
|
542 |
+
|
543 |
+
#: ../dashboard.php:1591
|
544 |
+
msgid "Deactivate"
|
545 |
+
msgstr "取消激活"
|
546 |
+
|
547 |
+
#: ../dashboard.php:97 ../cerber-load.php:3109
|
548 |
+
msgid "Reason"
|
549 |
+
msgstr "原因"
|
550 |
+
|
551 |
+
#: ../dashboard.php:170
|
552 |
+
msgid "Add IP to the list"
|
553 |
+
msgstr "添加IP到列表"
|
554 |
+
|
555 |
+
#: ../dashboard.php:889
|
556 |
+
msgid "Add IP to the Black List"
|
557 |
+
msgstr "添加IP到黑名单"
|
558 |
+
|
559 |
+
#: ../common.php:784
|
560 |
+
msgid "Attempt to access"
|
561 |
+
msgstr "试图接入"
|
562 |
+
|
563 |
+
#: ../common.php:783
|
564 |
+
msgid "Limit on login attempts is reached"
|
565 |
+
msgstr "登入次数已达限制值"
|
566 |
+
|
567 |
+
#: ../common.php:739 ../common.php:785
|
568 |
+
msgid "Attempt to log in with non-existent username"
|
569 |
+
msgstr "试图通过不存在的用户名登入"
|
570 |
+
|
571 |
+
#: ../cerber-load.php:3108
|
572 |
+
msgid "Last lockout was added: %s for IP %s"
|
573 |
+
msgstr "最近一次锁定添加于: %s 来自 IP %s"
|
574 |
+
|
575 |
+
#: ../cerber-load.php:3836 ../settings.php:399
|
576 |
+
msgid "Hardening"
|
577 |
+
msgstr "加固"
|
578 |
+
|
579 |
+
#: ../dashboard.php:866
|
580 |
+
msgid "Abuse email:"
|
581 |
+
msgstr "滥用邮箱:"
|
582 |
+
|
583 |
+
#: ../settings.php:201 ../settings.php:236
|
584 |
+
msgid "Email Address"
|
585 |
+
msgstr "邮箱"
|
586 |
+
|
587 |
+
#: ../settings.php:210
|
588 |
+
msgid "if empty, the admin email %s will be used"
|
589 |
+
msgstr "如果为空,将使用管理员邮箱 %s"
|
590 |
+
|
591 |
+
#: ../settings.php:104
|
592 |
+
msgid "Drill down IP"
|
593 |
+
msgstr ""
|
594 |
+
|
595 |
+
#: ../settings.php:104
|
596 |
+
msgid "Retrieve extra WHOIS information for IP"
|
597 |
+
msgstr ""
|
598 |
+
|
599 |
+
#: ../settings.php:112
|
600 |
+
msgid "Hardening WordPress"
|
601 |
+
msgstr "加固WordPress"
|
602 |
+
|
603 |
+
#: ../settings.php:113
|
604 |
+
msgid "Stop user enumeration"
|
605 |
+
msgstr "停止用户列举"
|
606 |
+
|
607 |
+
#: ../settings.php:115
|
608 |
+
msgid "Disable XML-RPC"
|
609 |
+
msgstr "禁用XML-RPC"
|
610 |
+
|
611 |
+
#: ../settings.php:115
|
612 |
+
msgid "Block access to the XML-RPC server (including Pingbacks and Trackbacks)"
|
613 |
+
msgstr "锁定接入 XML-RPC server (包括Pingbacks和Trackbacks)"
|
614 |
+
|
615 |
+
#: ../settings.php:116
|
616 |
+
msgid "Disable feeds"
|
617 |
+
msgstr "禁用feeds"
|
618 |
+
|
619 |
+
#: ../settings.php:116
|
620 |
+
msgid "Block access to the RSS, Atom and RDF feeds"
|
621 |
+
msgstr "锁定接入 RSS, Atom and RDF feeds"
|
622 |
+
|
623 |
+
#: ../settings.php:117
|
624 |
+
msgid "Disable REST API"
|
625 |
+
msgstr "禁用REST API"
|
626 |
+
|
627 |
+
#: ../settings.php:358
|
628 |
+
msgid "These settings do not affect hosts from the "
|
629 |
+
msgstr "这些设置不会影响"
|
630 |
+
|
631 |
+
#: ../settings.php:882 ../settings.php:894
|
632 |
+
msgid "<strong>ERROR</strong>: please enter a valid email address."
|
633 |
+
msgstr "<strong>错误</strong>: 请输入有效的邮箱地址。"
|
634 |
+
|
635 |
+
#: ../cerber-load.php:3139 ../cerber-load.php:3825
|
636 |
+
msgid "WP Cerber is now active and has started protecting your site"
|
637 |
+
msgstr "WP Cerber现已激活,开始保护您的网站"
|
638 |
+
|
639 |
+
#: ../dashboard.php:98
|
640 |
+
msgid "Action"
|
641 |
+
msgstr "操作"
|
642 |
+
|
643 |
+
#: ../dashboard.php:133
|
644 |
+
msgid "Nobody can log in or register from these IPs"
|
645 |
+
msgstr "这些IP不能登入或注册"
|
646 |
+
|
647 |
+
#: ../dashboard.php:196 ../dashboard.php:208
|
648 |
+
msgid "Incorrect IP address or IP range"
|
649 |
+
msgstr "错误的IP地址或范围"
|
650 |
+
|
651 |
+
#: ../dashboard.php:407 ../dashboard.php:1607
|
652 |
+
msgid "Settings saved"
|
653 |
+
msgstr "设置已保存"
|
654 |
+
|
655 |
+
#: ../dashboard.php:870
|
656 |
+
msgid "Network:"
|
657 |
+
msgstr "网络:"
|
658 |
+
|
659 |
+
#: ../dashboard.php:884
|
660 |
+
msgid "Add network to the Black List"
|
661 |
+
msgstr "添加网络到黑名单"
|
662 |
+
|
663 |
+
#: ../dashboard.php:1590
|
664 |
+
msgid "Attention! Citadel mode is now active. Nobody is able to log in."
|
665 |
+
msgstr "注意!要塞模式现已激活,所有用户都不能登入。"
|
666 |
+
|
667 |
+
#: ../dashboard.php:313 ../dashboard.php:2587 ../whois.php:221 ../whois.php:252 ..
|
668 |
+
#: /common.php:782 ../common.php:1061
|
669 |
+
msgid "Unknown"
|
670 |
+
msgstr "未知"
|
671 |
+
|
672 |
+
#. Author of the plugin
|
673 |
+
#:
|
674 |
+
msgid "Gregory"
|
675 |
+
msgstr ""
|
676 |
+
|
677 |
+
#: ../common.php:194 ../common.php:251 ../common.php:256 ../common.php:261 ..
|
678 |
+
#: /cerber-load.php:523 ../cerber-load.php:535 ../cerber-load.php:542 ../cerber-
|
679 |
+
#: load.php:763 ../cerber-load.php:979 ../cerber-load.php:985 ../cerber-load.php:
|
680 |
+
#: 990 ../cerber-load.php:995 ../cerber-load.php:1001 ../cerber-load.php:1008 ..
|
681 |
+
#: /cerber-load.php:1108 ../cerber-load.php:1245 ../settings.php:780 ../settings.
|
682 |
+
#: php:851
|
683 |
+
msgid "ERROR:"
|
684 |
+
msgstr "错误:"
|
685 |
+
|
686 |
+
#: ../cerber-load.php:552
|
687 |
+
msgid "Human verification failed. Please click the square box in the reCAPTCHA block below."
|
688 |
+
msgstr ""
|
689 |
+
|
690 |
+
#: ../cerber-load.php:775
|
691 |
+
msgid "<strong>ERROR</strong>: The password you entered for the username %s is incorrect."
|
692 |
+
msgstr "<strong>错误</strong>: 用户名%s密码不正确。"
|
693 |
+
|
694 |
+
#: ../cerber-load.php:996
|
695 |
+
msgid "Username is not allowed. Please choose another one."
|
696 |
+
msgstr "该用户名不可用,请更换用户名。"
|
697 |
+
|
698 |
+
#: ../cerber-load.php:3102
|
699 |
+
msgid "unspecified"
|
700 |
+
msgstr "未指定"
|
701 |
+
|
702 |
+
#: ../cerber-load.php:3105
|
703 |
+
msgid "Number of lockouts is increasing"
|
704 |
+
msgstr "被锁定的数量在增加"
|
705 |
+
|
706 |
+
#: ../cerber-load.php:3110
|
707 |
+
msgid "View activity for this IP"
|
708 |
+
msgstr "查看此IP活动"
|
709 |
+
|
710 |
+
#: ../cerber-load.php:3114 ../cerber-load.php:3116
|
711 |
+
msgid "A new version of WP Cerber is available to install"
|
712 |
+
msgstr "新版WP Cerber可供安装"
|
713 |
+
|
714 |
+
#: ../cerber-load.php:3115
|
715 |
+
msgid "Hi!"
|
716 |
+
msgstr ""
|
717 |
+
|
718 |
+
#: ../cerber-load.php:3118 ../cerber-load.php:3129
|
719 |
+
msgid "Website"
|
720 |
+
msgstr ""
|
721 |
+
|
722 |
+
#: ../cerber-load.php:3121 ../cerber-load.php:3122
|
723 |
+
msgid "The WP Cerber security plugin has been deactivated"
|
724 |
+
msgstr "WP Cerber安全插件已取消激活"
|
725 |
+
|
726 |
+
#: ../cerber-load.php:3124
|
727 |
+
msgid "Not logged in"
|
728 |
+
msgstr "未登入"
|
729 |
+
|
730 |
+
#: ../cerber-load.php:3130
|
731 |
+
msgid "By user"
|
732 |
+
msgstr "来源用户"
|
733 |
+
|
734 |
+
#: ../cerber-load.php:3131
|
735 |
+
msgid "From IP address"
|
736 |
+
msgstr "来源IP"
|
737 |
+
|
738 |
+
#: ../cerber-load.php:3134
|
739 |
+
msgid "From country"
|
740 |
+
msgstr "来源国家"
|
741 |
+
|
742 |
+
#: ../cerber-load.php:3138
|
743 |
+
msgid "The WP Cerber security plugin is now active"
|
744 |
+
msgstr "WP Cerber安全插件已激活"
|
745 |
+
|
746 |
+
#: ../cerber-load.php:3826
|
747 |
+
msgid "Your IP address is added to the"
|
748 |
+
msgstr "您的IP地址被加入到"
|
749 |
+
|
750 |
+
#: ../cerber-load.php:3838
|
751 |
+
msgid "Import settings"
|
752 |
+
msgstr "导入设置"
|
753 |
+
|
754 |
+
#: ../settings.php:213
|
755 |
+
msgid "Notification limit"
|
756 |
+
msgstr "通知限制"
|
757 |
+
|
758 |
+
#: ../settings.php:213
|
759 |
+
msgid "notification letters allowed per hour (0 means unlimited)"
|
760 |
+
msgstr "次邮件提醒于每小时 (0 代表不限制)"
|
761 |
+
|
762 |
+
#: ../settings.php:135
|
763 |
+
msgid "User related settings"
|
764 |
+
msgstr ""
|
765 |
+
|
766 |
+
#: ../settings.php:137
|
767 |
+
msgid "Prohibited usernames"
|
768 |
+
msgstr "屏蔽用户名"
|
769 |
+
|
770 |
+
#: ../settings.php:143
|
771 |
+
msgid "Usernames from this list are not allowed to log in or register. Any IP address, have tried to use any of these usernames, will be immediately blocked. Use comma to separate logins."
|
772 |
+
msgstr "列表中的用户名不能登入或注册。任何试图使用这些用户名的IP将被立即锁定。使用逗号分隔多个值。"
|
773 |
+
|
774 |
+
#: ../settings.php:145
|
775 |
+
msgid "User session expire"
|
776 |
+
msgstr "用户线程过期于"
|
777 |
+
|
778 |
+
#: ../settings.php:145
|
779 |
+
msgid "in minutes (leave empty to use default WP value)"
|
780 |
+
msgstr "分钟内(留空使用Wordpress缺省值)"
|
781 |
+
|
782 |
+
#: ../settings.php:175
|
783 |
+
msgid "reCAPTCHA settings"
|
784 |
+
msgstr ""
|
785 |
+
|
786 |
+
#: ../settings.php:176
|
787 |
+
msgid "Site key"
|
788 |
+
msgstr ""
|
789 |
+
|
790 |
+
#: ../settings.php:177
|
791 |
+
msgid "Secret key"
|
792 |
+
msgstr ""
|
793 |
+
|
794 |
+
#: ../settings.php:180
|
795 |
+
msgid "Enable reCAPTCHA for WordPress registration form"
|
796 |
+
msgstr ""
|
797 |
+
|
798 |
+
#: ../settings.php:183
|
799 |
+
msgid "Lost password form"
|
800 |
+
msgstr ""
|
801 |
+
|
802 |
+
#: ../settings.php:186
|
803 |
+
msgid "Login form"
|
804 |
+
msgstr ""
|
805 |
+
|
806 |
+
#: ../settings.php:186
|
807 |
+
msgid "Enable reCAPTCHA for WordPress login form"
|
808 |
+
msgstr ""
|
809 |
+
|
810 |
+
#: ../settings.php:361
|
811 |
+
msgid "Before you can start using reCAPTCHA, you have to obtain Site key and Secret key on the Google website"
|
812 |
+
msgstr ""
|
813 |
+
|
814 |
+
#: ../cerber-lab.php:709 ../settings.php:362
|
815 |
+
msgid "Know more"
|
816 |
+
msgstr "了解更多"
|
817 |
+
|
818 |
+
#: ../dashboard.php:989 ../settings.php:381
|
819 |
+
msgid "WP Cerber Security"
|
820 |
+
msgstr "WP Cerber安全"
|
821 |
+
|
822 |
+
#: ../settings.php:401
|
823 |
+
msgid "Users"
|
824 |
+
msgstr "用户"
|
825 |
+
|
826 |
+
#: ../common.php:706
|
827 |
+
msgid "User created"
|
828 |
+
msgstr "用户创建"
|
829 |
+
|
830 |
+
#: ../dashboard.php:1430 ../common.php:707
|
831 |
+
msgid "User registered"
|
832 |
+
msgstr "用户注册"
|
833 |
+
|
834 |
+
#: ../common.php:734
|
835 |
+
msgid "reCAPTCHA verification failed"
|
836 |
+
msgstr ""
|
837 |
+
|
838 |
+
#: ../common.php:735
|
839 |
+
msgid "reCAPTCHA settings are incorrect"
|
840 |
+
msgstr ""
|
841 |
+
|
842 |
+
#: ../common.php:738
|
843 |
+
msgid "Attempt to access prohibited URL"
|
844 |
+
msgstr "试图通过被屏蔽URL接入"
|
845 |
+
|
846 |
+
#: ../common.php:740 ../common.php:786
|
847 |
+
msgid "Attempt to log in with prohibited username"
|
848 |
+
msgstr "试图通过被屏蔽用户名登入"
|
849 |
+
|
850 |
+
#: ../settings.php:99
|
851 |
+
msgid "Cerber Lab connection"
|
852 |
+
msgstr ""
|
853 |
+
|
854 |
+
#: ../settings.php:99
|
855 |
+
msgid "Send malicious IP addresses to the Cerber Lab"
|
856 |
+
msgstr "向Cerber Lab发送恶意IP地址"
|
857 |
+
|
858 |
+
#: ../settings.php:100
|
859 |
+
msgid "Cerber Lab protocol"
|
860 |
+
msgstr ""
|
861 |
+
|
862 |
+
#: ../settings.php:155 ../settings.php:180
|
863 |
+
msgid "Registration form"
|
864 |
+
msgstr ""
|
865 |
+
|
866 |
+
#: ../settings.php:181
|
867 |
+
msgid "Enable reCAPTCHA for WooCommerce registration form"
|
868 |
+
msgstr ""
|
869 |
+
|
870 |
+
#: ../settings.php:183
|
871 |
+
msgid "Enable reCAPTCHA for WordPress lost password form"
|
872 |
+
msgstr ""
|
873 |
+
|
874 |
+
#: ../settings.php:184
|
875 |
+
msgid "Enable reCAPTCHA for WooCommerce lost password form"
|
876 |
+
msgstr ""
|
877 |
+
|
878 |
+
#: ../settings.php:187
|
879 |
+
msgid "Enable reCAPTCHA for WooCommerce login form"
|
880 |
+
msgstr ""
|
881 |
+
|
882 |
+
#: ../common.php:736
|
883 |
+
msgid "Request to the Google reCAPTCHA service failed"
|
884 |
+
msgstr ""
|
885 |
+
|
886 |
+
#: ../dashboard.php:1422 ../dashboard.php:1452
|
887 |
+
msgid "View all"
|
888 |
+
msgstr "查看全部"
|
889 |
+
|
890 |
+
#: ../dashboard.php:1453
|
891 |
+
msgid "Recently locked out IP addresses"
|
892 |
+
msgstr "最近被锁定的IP地址"
|
893 |
+
|
894 |
+
#: ../cerber-lab.php:707
|
895 |
+
msgid "OK, nail them all"
|
896 |
+
msgstr "允许"
|
897 |
+
|
898 |
+
#: ../cerber-lab.php:708
|
899 |
+
msgid "NO, maybe later"
|
900 |
+
msgstr "现在不"
|
901 |
+
|
902 |
+
#: ../dashboard.php:991 ../dashboard.php:1226 ../dashboard.php:1783 ../settings.
|
903 |
+
#: php:386
|
904 |
+
msgid "Dashboard"
|
905 |
+
msgstr "控制面板"
|
906 |
+
|
907 |
+
#: ../cerber-lab.php:705
|
908 |
+
msgid "Want to make WP Cerber even more powerful?"
|
909 |
+
msgstr ""
|
910 |
+
|
911 |
+
#: ../cerber-lab.php:706
|
912 |
+
msgid "Allow WP Cerber to send locked out malicious IP addresses to Cerber Lab. This helps the plugin team to develop new algorithms for WP Cerber that will defend WordPress against new threats and botnets that are appearing everyday. You can disable the sending in the plugin settings at any time."
|
913 |
+
msgstr "允许向Cerber Lab发送恶意IP地址。可以随时更改此项设置。"
|
914 |
+
|
915 |
+
#: ../dashboard.php:491
|
916 |
+
msgid "IP address"
|
917 |
+
msgstr "IP地址"
|
918 |
+
|
919 |
+
#: ../dashboard.php:491
|
920 |
+
msgid "User login"
|
921 |
+
msgstr "用户登入"
|
922 |
+
|
923 |
+
#: ../dashboard.php:491
|
924 |
+
msgid "User ID"
|
925 |
+
msgstr "用户ID"
|
926 |
+
|
927 |
+
#: ../dashboard.php:676
|
928 |
+
msgid "Export"
|
929 |
+
msgstr "导出"
|
930 |
+
|
931 |
+
#: ../dashboard.php:695
|
932 |
+
msgid "Search for IP or username"
|
933 |
+
msgstr "搜索IP或用户名"
|
934 |
+
|
935 |
+
#: ../dashboard.php:695
|
936 |
+
msgid "Filter"
|
937 |
+
msgstr "过滤"
|
938 |
+
|
939 |
+
#: ../dashboard.php:991
|
940 |
+
msgid "Cerber Dashboard"
|
941 |
+
msgstr "Cerber控制面板"
|
942 |
+
|
943 |
+
#: ../dashboard.php:1001
|
944 |
+
msgid "Cerber tools"
|
945 |
+
msgstr "Cerber工具"
|
946 |
+
|
947 |
+
#: ../dashboard.php:1693
|
948 |
+
msgid "Subscribe"
|
949 |
+
msgstr "订阅"
|
950 |
+
|
951 |
+
#: ../dashboard.php:1694 ../cerber-tools.php:266
|
952 |
+
msgid "Unsubscribe"
|
953 |
+
msgstr "取消订阅"
|
954 |
+
|
955 |
+
#: ../dashboard.php:1722
|
956 |
+
msgid "You've subscribed"
|
957 |
+
msgstr "您已订阅"
|
958 |
+
|
959 |
+
#: ../dashboard.php:1725
|
960 |
+
msgid "You've unsubscribed"
|
961 |
+
msgstr "您未订阅"
|
962 |
+
|
963 |
+
#: ../cerber-load.php:3151 ../cerber-load.php:3152
|
964 |
+
msgid "A new activity has been recorded"
|
965 |
+
msgstr "新活动被记录"
|
966 |
+
|
967 |
+
#: ../cerber-load.php:3606
|
968 |
+
msgid "User"
|
969 |
+
msgstr "用户"
|
970 |
+
|
971 |
+
#: ../cerber-load.php:3614
|
972 |
+
msgid "Search string"
|
973 |
+
msgstr "搜索字符串"
|
974 |
+
|
975 |
+
#: ../cerber-load.php:3635
|
976 |
+
msgid "To unsubscribe click here"
|
977 |
+
msgstr "取消订阅请点击这里"
|
978 |
+
|
979 |
+
#: ../settings.php:103
|
980 |
+
msgid "Preferences"
|
981 |
+
msgstr "参数"
|
982 |
+
|
983 |
+
#: ../settings.php:105
|
984 |
+
msgid "Date format"
|
985 |
+
msgstr "日期格式"
|
986 |
+
|
987 |
+
#: ../settings.php:105
|
988 |
+
msgid "if empty, the default format %s will be used"
|
989 |
+
msgstr "如果留空,默认格式 %s 将被使用"
|
990 |
+
|
991 |
+
#: ../settings.php:219
|
992 |
+
msgid "Push notifications"
|
993 |
+
msgstr "推送通知"
|
994 |
+
|
995 |
+
#: ../settings.php:198
|
996 |
+
msgid "Email notifications"
|
997 |
+
msgstr "邮件提醒"
|
998 |
+
|
999 |
+
#: ../settings.php:205 ../settings.php:241 ../settings.php:298
|
1000 |
+
msgid "Use comma to specify multiple values"
|
1001 |
+
msgstr "使用逗号(,)定义多个值"
|
1002 |
+
|
1003 |
+
#: ../settings.php:226
|
1004 |
+
msgid "All connected devices"
|
1005 |
+
msgstr "全部已连接设备"
|
1006 |
+
|
1007 |
+
#: ../settings.php:227
|
1008 |
+
msgid "No devices found"
|
1009 |
+
msgstr "未找到设备"
|
1010 |
+
|
1011 |
+
#: ../settings.php:229
|
1012 |
+
msgid "Not available"
|
1013 |
+
msgstr "不可用"
|
1014 |
+
|
1015 |
+
#: ../common.php:732
|
1016 |
+
msgid "Password reset requested"
|
1017 |
+
msgstr "密码重置请求"
|
1018 |
+
|
1019 |
+
#: ../common.php:787
|
1020 |
+
msgid "Limit on failed reCAPTCHA verifications is reached"
|
1021 |
+
msgstr ""
|
1022 |
+
|
1023 |
+
#: ../common.php:845
|
1024 |
+
msgid "%s ago"
|
1025 |
+
msgstr "%s之前"
|
1026 |
+
|
1027 |
+
#: ../settings.php:77
|
1028 |
+
msgid "Apply limit login rules to IP addresses in the White IP Access List"
|
1029 |
+
msgstr "IP白名单中的IP也使用限制规则"
|
1030 |
+
|
1031 |
+
#: ../settings.php:86
|
1032 |
+
msgid "Display 404 page"
|
1033 |
+
msgstr "显示404页面"
|
1034 |
+
|
1035 |
+
#: ../settings.php:178
|
1036 |
+
msgid "Invisible reCAPTCHA"
|
1037 |
+
msgstr ""
|
1038 |
+
|
1039 |
+
#: ../settings.php:178
|
1040 |
+
msgid "Enable invisible reCAPTCHA"
|
1041 |
+
msgstr ""
|
1042 |
+
|
1043 |
+
#: ../settings.php:178
|
1044 |
+
msgid "(do not enable it unless you get and enter the Site and Secret keys for the invisible version)"
|
1045 |
+
msgstr ""
|
1046 |
+
|
1047 |
+
#: ../settings.php:189
|
1048 |
+
msgid "Enable reCAPTCHA for WordPress comment form"
|
1049 |
+
msgstr ""
|
1050 |
+
|
1051 |
+
#: ../settings.php:190
|
1052 |
+
msgid "Disable reCAPTCHA for logged in users"
|
1053 |
+
msgstr ""
|
1054 |
+
|
1055 |
+
#: ../settings.php:192
|
1056 |
+
msgid "Limit attempts"
|
1057 |
+
msgstr "限制尝试"
|
1058 |
+
|
1059 |
+
#: ../settings.php:192
|
1060 |
+
msgid "Lock out IP address for %s minutes after %s failed attempts within %s minutes"
|
1061 |
+
msgstr "锁定IP时长 %s 分钟, %s 次错误尝试在 %s 分钟内"
|
1062 |
+
|
1063 |
+
#: ../settings.php:355
|
1064 |
+
msgid "In the Citadel mode nobody is able to log in except IPs from the White IP Access List. Active user sessions will not be affected."
|
1065 |
+
msgstr "要塞模式下,除了白名单中的IP,不允许登入。处于激活状态的用户线程不受影响。"
|
1066 |
+
|
1067 |
+
#: ../dashboard.php:491 ../dashboard.php:656
|
1068 |
+
msgid "Event"
|
1069 |
+
msgstr ""
|
1070 |
+
|
1071 |
+
#: ../common.php:137
|
1072 |
+
msgid "Spam comments denied"
|
1073 |
+
msgstr ""
|
1074 |
+
|
1075 |
+
#: ../common.php:139
|
1076 |
+
msgid "Malicious IP addresses detected"
|
1077 |
+
msgstr ""
|
1078 |
+
|
1079 |
+
#: ../common.php:140
|
1080 |
+
msgid "Lockouts occurred"
|
1081 |
+
msgstr ""
|
1082 |
+
|
1083 |
+
#: ../dashboard.php:1431
|
1084 |
+
msgid "All suspicious activity"
|
1085 |
+
msgstr ""
|
1086 |
+
|
1087 |
+
#: ../cerber-load.php:980 ../cerber-load.php:986 ../cerber-load.php:1002 ..
|
1088 |
+
#: /cerber-load.php:1009
|
1089 |
+
msgid "You are not allowed to register."
|
1090 |
+
msgstr ""
|
1091 |
+
|
1092 |
+
#: ../common.php:717
|
1093 |
+
msgid "Spam comment denied"
|
1094 |
+
msgstr ""
|
1095 |
+
|
1096 |
+
#: ../common.php:742
|
1097 |
+
msgid "Attempt to log in denied"
|
1098 |
+
msgstr ""
|
1099 |
+
|
1100 |
+
#: ../common.php:743
|
1101 |
+
msgid "Attempt to register denied"
|
1102 |
+
msgstr ""
|
1103 |
+
|
1104 |
+
#: ../common.php:134
|
1105 |
+
msgid "Malicious activities mitigated"
|
1106 |
+
msgstr ""
|
1107 |
+
|
1108 |
+
#: ../dashboard.php:1000
|
1109 |
+
msgid "Cerber antispam settings"
|
1110 |
+
msgstr ""
|
1111 |
+
|
1112 |
+
#: ../dashboard.php:1000 ../dashboard.php:1229 ../cerber-load.php:3835 ..
|
1113 |
+
#: /settings.php:189
|
1114 |
+
msgid "Antispam"
|
1115 |
+
msgstr ""
|
1116 |
+
|
1117 |
+
#: ../settings.php:153
|
1118 |
+
msgid "Cerber antispam engine"
|
1119 |
+
msgstr ""
|
1120 |
+
|
1121 |
+
#: ../settings.php:154
|
1122 |
+
msgid "Comment form"
|
1123 |
+
msgstr ""
|
1124 |
+
|
1125 |
+
#: ../settings.php:154
|
1126 |
+
msgid "Protect comment form with bot detection engine"
|
1127 |
+
msgstr ""
|
1128 |
+
|
1129 |
+
#: ../settings.php:155
|
1130 |
+
msgid "Protect registration form with bot detection engine"
|
1131 |
+
msgstr ""
|
1132 |
+
|
1133 |
+
#: ../cerber-tools.php:48
|
1134 |
+
msgid "Export & Import"
|
1135 |
+
msgstr ""
|
1136 |
+
|
1137 |
+
#: ../cerber-tools.php:49
|
1138 |
+
msgid "Diagnostic"
|
1139 |
+
msgstr ""
|
1140 |
+
|
1141 |
+
#: ../cerber-tools.php:50
|
1142 |
+
msgid "License"
|
1143 |
+
msgstr ""
|
1144 |
+
|
1145 |
+
#: ../cerber-tools.php:336
|
1146 |
+
msgid "Antispam and bot detection settings"
|
1147 |
+
msgstr ""
|
1148 |
+
|
1149 |
+
#: ../cerber-load.php:1245
|
1150 |
+
msgid "Sorry, human verification failed."
|
1151 |
+
msgstr ""
|
1152 |
+
|
1153 |
+
#: ../common.php:788
|
1154 |
+
msgid "Bot activity is detected"
|
1155 |
+
msgstr ""
|
1156 |
+
|
1157 |
+
#: ../settings.php:170
|
1158 |
+
msgid "Comment processing"
|
1159 |
+
msgstr ""
|
1160 |
+
|
1161 |
+
#: ../settings.php:171
|
1162 |
+
msgid "If a spam comment detected"
|
1163 |
+
msgstr ""
|
1164 |
+
|
1165 |
+
#: ../settings.php:172
|
1166 |
+
msgid "Trash spam comments"
|
1167 |
+
msgstr ""
|
1168 |
+
|
1169 |
+
#: ../settings.php:172
|
1170 |
+
msgid "Move spam comments to trash after"
|
1171 |
+
msgstr ""
|
1172 |
+
|
1173 |
+
#: ../common.php:718
|
1174 |
+
msgid "Spam form submission denied"
|
1175 |
+
msgstr ""
|
1176 |
+
|
1177 |
+
#: ../settings.php:156
|
1178 |
+
msgid "Other forms"
|
1179 |
+
msgstr ""
|
1180 |
+
|
1181 |
+
#: ../settings.php:156
|
1182 |
+
msgid "Protect all forms on the website with bot detection engine"
|
1183 |
+
msgstr ""
|
1184 |
+
|
1185 |
+
#: ../settings.php:158
|
1186 |
+
msgid "Adjust antispam engine"
|
1187 |
+
msgstr ""
|
1188 |
+
|
1189 |
+
#: ../settings.php:159
|
1190 |
+
msgid "Safe mode"
|
1191 |
+
msgstr ""
|
1192 |
+
|
1193 |
+
#: ../settings.php:159
|
1194 |
+
msgid "Use less restrictive policies (allow AJAX)"
|
1195 |
+
msgstr ""
|
1196 |
+
|
1197 |
+
#: ../dashboard.php:2854 ../settings.php:160
|
1198 |
+
msgid "Logged in users"
|
1199 |
+
msgstr ""
|
1200 |
+
|
1201 |
+
#: ../settings.php:160
|
1202 |
+
msgid "Disable bot detection engine for logged in users"
|
1203 |
+
msgstr ""
|
1204 |
+
|
1205 |
+
#. Name of the plugin
|
1206 |
+
#:
|
1207 |
+
msgid "WP Cerber Security & Antispam"
|
1208 |
+
msgstr ""
|
1209 |
+
|
1210 |
+
#: ../dashboard.php:95 ../dashboard.php:654
|
1211 |
+
msgid "Country"
|
1212 |
+
msgstr ""
|
1213 |
+
|
1214 |
+
#: ../dashboard.php:686
|
1215 |
+
msgid "All events"
|
1216 |
+
msgstr ""
|
1217 |
+
|
1218 |
+
#: ../dashboard.php:997
|
1219 |
+
msgid "Cerber Security Rules"
|
1220 |
+
msgstr ""
|
1221 |
+
|
1222 |
+
#: ../dashboard.php:997 ../dashboard.php:2168
|
1223 |
+
msgid "Security Rules"
|
1224 |
+
msgstr ""
|
1225 |
+
|
1226 |
+
#: ../dashboard.php:1074
|
1227 |
+
msgid "Failed login attempts"
|
1228 |
+
msgstr ""
|
1229 |
+
|
1230 |
+
#: ../dashboard.php:956 ../dashboard.php:1075
|
1231 |
+
msgid "Registered"
|
1232 |
+
msgstr ""
|
1233 |
+
|
1234 |
+
#: ../dashboard.php:1142
|
1235 |
+
msgid "You"
|
1236 |
+
msgstr ""
|
1237 |
+
|
1238 |
+
#: ../common.php:138
|
1239 |
+
msgid "Spam form submissions denied"
|
1240 |
+
msgstr ""
|
1241 |
+
|
1242 |
+
#: ../dashboard.php:1490 ../cerber-load.php:3141 ../cerber-load.php:3828
|
1243 |
+
msgid "Getting Started Guide"
|
1244 |
+
msgstr ""
|
1245 |
+
|
1246 |
+
#: ../dashboard.php:2173
|
1247 |
+
msgid "Countries"
|
1248 |
+
msgstr ""
|
1249 |
+
|
1250 |
+
#: ../dashboard.php:2236
|
1251 |
+
msgid "Permitted for one country"
|
1252 |
+
msgid_plural "Permitted for %d countries"
|
1253 |
+
msgstr[0] ""
|
1254 |
+
|
1255 |
+
#: ../dashboard.php:2247
|
1256 |
+
msgid "No rule"
|
1257 |
+
msgstr ""
|
1258 |
+
|
1259 |
+
#: ../dashboard.php:2459
|
1260 |
+
msgid "Security rules have been updated"
|
1261 |
+
msgstr ""
|
1262 |
+
|
1263 |
+
#. URI of the plugin
|
1264 |
+
#:
|
1265 |
+
msgid "https://wpcerber.com"
|
1266 |
+
msgstr ""
|
1267 |
+
|
1268 |
+
#: ../common.php:719
|
1269 |
+
msgid "Form submission denied"
|
1270 |
+
msgstr ""
|
1271 |
+
|
1272 |
+
#: ../common.php:720
|
1273 |
+
msgid "Comment denied"
|
1274 |
+
msgstr ""
|
1275 |
+
|
1276 |
+
#: ../common.php:746
|
1277 |
+
msgid "Request to REST API denied"
|
1278 |
+
msgstr ""
|
1279 |
+
|
1280 |
+
#: ../common.php:747
|
1281 |
+
msgid "XML-RPC request denied"
|
1282 |
+
msgstr ""
|
1283 |
+
|
1284 |
+
#: ../common.php:751
|
1285 |
+
msgid "Bot detected"
|
1286 |
+
msgstr ""
|
1287 |
+
|
1288 |
+
#: ../common.php:752
|
1289 |
+
msgid "Citadel mode is active"
|
1290 |
+
msgstr ""
|
1291 |
+
|
1292 |
+
#: ../common.php:757
|
1293 |
+
msgid "Malicious activity detected"
|
1294 |
+
msgstr ""
|
1295 |
+
|
1296 |
+
#: ../common.php:758
|
1297 |
+
msgid "Blocked by country rule"
|
1298 |
+
msgstr ""
|
1299 |
+
|
1300 |
+
#: ../common.php:759
|
1301 |
+
msgid "Limit reached"
|
1302 |
+
msgstr ""
|
1303 |
+
|
1304 |
+
#: ../common.php:760
|
1305 |
+
msgid "Multiple suspicious activities"
|
1306 |
+
msgstr ""
|
1307 |
+
|
1308 |
+
#: ../common.php:789
|
1309 |
+
msgid "Multiple suspicious activities were detected"
|
1310 |
+
msgstr ""
|
1311 |
+
|
1312 |
+
#: ../settings.php:113
|
1313 |
+
msgid "Block access to user pages like /?author=n and user data via REST API"
|
1314 |
+
msgstr ""
|
1315 |
+
|
1316 |
+
#: ../settings.php:117
|
1317 |
+
msgid "Block access to the WordPress REST API except the following"
|
1318 |
+
msgstr ""
|
1319 |
+
|
1320 |
+
#: ../settings.php:118
|
1321 |
+
msgid "Allow REST API for logged in users"
|
1322 |
+
msgstr ""
|
1323 |
+
|
1324 |
+
#: ../settings.php:125
|
1325 |
+
msgid "Specify REST API namespaces to be allowed if REST API is disabled. One string per line."
|
1326 |
+
msgstr ""
|
1327 |
+
|
1328 |
+
#: ../settings.php:136
|
1329 |
+
msgid "Registration limit"
|
1330 |
+
msgstr ""
|
1331 |
+
|
1332 |
+
#: ../settings.php:146
|
1333 |
+
msgid "Sort users in dashboard"
|
1334 |
+
msgstr ""
|
1335 |
+
|
1336 |
+
#: ../settings.php:146
|
1337 |
+
msgid "by date of registration"
|
1338 |
+
msgstr "注册日期"
|
1339 |
+
|
1340 |
+
#: ../settings.php:161
|
1341 |
+
msgid "Query whitelist"
|
1342 |
+
msgstr ""
|
1343 |
+
|
1344 |
+
#: ../settings.php:518 ../settings.php:640
|
1345 |
+
msgid "%s allowed registrations in %s minutes from one IP"
|
1346 |
+
msgstr ""
|
1347 |
+
|
1348 |
+
#: ../dashboard.php:2303
|
1349 |
+
msgid "Start typing here to find a country"
|
1350 |
+
msgstr ""
|
1351 |
+
|
1352 |
+
#: ../dashboard.php:2386
|
1353 |
+
msgid "Click on a country name to add it to the list of selected countries"
|
1354 |
+
msgstr ""
|
1355 |
+
|
1356 |
+
#: ../dashboard.php:2410
|
1357 |
+
msgid "Submit forms"
|
1358 |
+
msgstr ""
|
1359 |
+
|
1360 |
+
#: ../dashboard.php:2411
|
1361 |
+
msgid "Post comments"
|
1362 |
+
msgstr ""
|
1363 |
+
|
1364 |
+
#: ../dashboard.php:2412
|
1365 |
+
msgid "Log in to the website"
|
1366 |
+
msgstr ""
|
1367 |
+
|
1368 |
+
#: ../dashboard.php:2413
|
1369 |
+
msgid "Register on the website"
|
1370 |
+
msgstr ""
|
1371 |
+
|
1372 |
+
#: ../dashboard.php:2414
|
1373 |
+
msgid "Use XML-RPC"
|
1374 |
+
msgstr ""
|
1375 |
+
|
1376 |
+
#: ../dashboard.php:2415
|
1377 |
+
msgid "Use REST API"
|
1378 |
+
msgstr ""
|
1379 |
+
|
1380 |
+
#: ../settings.php:171
|
1381 |
+
msgid "Deny it completely"
|
1382 |
+
msgstr ""
|
1383 |
+
|
1384 |
+
#: ../settings.php:171
|
1385 |
+
msgid "Mark it as spam"
|
1386 |
+
msgstr ""
|
1387 |
+
|
1388 |
+
#: ../dashboard.php:1416
|
1389 |
+
msgid "in the last 24 hours"
|
1390 |
+
msgstr ""
|
1391 |
+
|
1392 |
+
#: ../dashboard.php:1784
|
1393 |
+
msgid "Main settings"
|
1394 |
+
msgstr ""
|
1395 |
+
|
1396 |
+
#: ../settings.php:233
|
1397 |
+
msgid "Weekly reports"
|
1398 |
+
msgstr ""
|
1399 |
+
|
1400 |
+
#: ../settings.php:737
|
1401 |
+
msgid "Sunday"
|
1402 |
+
msgstr ""
|
1403 |
+
|
1404 |
+
#: ../settings.php:738
|
1405 |
+
msgid "Monday"
|
1406 |
+
msgstr ""
|
1407 |
+
|
1408 |
+
#: ../settings.php:739
|
1409 |
+
msgid "Tuesday"
|
1410 |
+
msgstr ""
|
1411 |
+
|
1412 |
+
#: ../settings.php:740
|
1413 |
+
msgid "Wednesday"
|
1414 |
+
msgstr ""
|
1415 |
+
|
1416 |
+
#: ../settings.php:741
|
1417 |
+
msgid "Thursday"
|
1418 |
+
msgstr ""
|
1419 |
+
|
1420 |
+
#: ../settings.php:742
|
1421 |
+
msgid "Friday"
|
1422 |
+
msgstr ""
|
1423 |
+
|
1424 |
+
#: ../settings.php:743
|
1425 |
+
msgid "Saturday"
|
1426 |
+
msgstr ""
|
1427 |
+
|
1428 |
+
#: ../settings.php:803 ../settings.php:804
|
1429 |
+
msgid "If you use a caching plugin, you have to add your new login URL to the list of pages not to cache."
|
1430 |
+
msgstr ""
|
1431 |
+
|
1432 |
+
#. translators: preposition of time
|
1433 |
+
#: ../settings.php:753
|
1434 |
+
msgctxt "preposition of time"
|
1435 |
+
msgid "at"
|
1436 |
+
msgstr ""
|
1437 |
+
|
1438 |
+
#: ../cerber-load.php:3157
|
1439 |
+
msgid "Weekly report"
|
1440 |
+
msgstr ""
|
1441 |
+
|
1442 |
+
#: ../cerber-load.php:3160
|
1443 |
+
msgid "To change reporting settings visit"
|
1444 |
+
msgstr ""
|
1445 |
+
|
1446 |
+
#: ../cerber-load.php:3186
|
1447 |
+
msgid "Your login page:"
|
1448 |
+
msgstr ""
|
1449 |
+
|
1450 |
+
#: ../cerber-load.php:3190
|
1451 |
+
msgid "Your license is valid until"
|
1452 |
+
msgstr ""
|
1453 |
+
|
1454 |
+
#: ../cerber-load.php:3301
|
1455 |
+
msgid "Activity details"
|
1456 |
+
msgstr ""
|
1457 |
+
|
1458 |
+
#: ../settings.php:769
|
1459 |
+
msgid "Click to send now"
|
1460 |
+
msgstr ""
|
1461 |
+
|
1462 |
+
#: ../cerber-load.php:642
|
1463 |
+
msgid "> > > Translator of WP Cerber? To get the PRO license for free, drop your contacts here: https://wpcerber.com/contact/"
|
1464 |
+
msgstr ""
|
1465 |
+
|
1466 |
+
#: ../dashboard.php:380
|
1467 |
+
msgid "Email has been sent to"
|
1468 |
+
msgstr ""
|
1469 |
+
|
1470 |
+
#: ../dashboard.php:383
|
1471 |
+
msgid "Unable to send email to"
|
1472 |
+
msgstr ""
|
1473 |
+
|
1474 |
+
#: ../dashboard.php:2239
|
1475 |
+
msgid "Not permitted for one country"
|
1476 |
+
msgid_plural "Not permitted for %d countries"
|
1477 |
+
msgstr[0] ""
|
1478 |
+
|
1479 |
+
#: ../dashboard.php:2390
|
1480 |
+
msgctxt "to is a marker of infinitive, e.g. \"to use it\""
|
1481 |
+
msgid "Selected countries are permitted to %s, other countries are not permitted to"
|
1482 |
+
msgstr ""
|
1483 |
+
|
1484 |
+
#: ../dashboard.php:2393
|
1485 |
+
msgctxt "to is a marker of infinitive, e.g. \"to use it\""
|
1486 |
+
msgid "Selected countries are not permitted to %s, other countries are permitted to"
|
1487 |
+
msgstr ""
|
1488 |
+
|
1489 |
+
#. Description of the plugin
|
1490 |
+
#:
|
1491 |
+
msgid "Protects site from brute force attacks, bots and hackers. Antispam protection with the Cerber antispam engine and reCAPTCHA. Comprehensive control of user activity. Restrict login by IP access lists. Limit login attempts. Know more: <a href=\"https://wpcerber.com\">wpcerber.com</a>."
|
1492 |
+
msgstr ""
|
1493 |
+
|
1494 |
+
#: ../cerber-load.php:3289
|
1495 |
+
msgid "Weekly Report"
|
1496 |
+
msgstr ""
|
1497 |
+
|
1498 |
+
#: ../settings.php:86
|
1499 |
+
msgid "Use 404 template from the active theme"
|
1500 |
+
msgstr ""
|
1501 |
+
|
1502 |
+
#: ../settings.php:86
|
1503 |
+
msgid "Display simple 404 page"
|
1504 |
+
msgstr ""
|
1505 |
+
|
1506 |
+
#: ../settings.php:167
|
1507 |
+
msgid "Enter a part of query string or query path to exclude a request from inspection by the engine. One item per line."
|
1508 |
+
msgstr ""
|
1509 |
+
|
1510 |
+
#: ../settings.php:246
|
1511 |
+
msgid "if empty, email from notification settings will be used"
|
1512 |
+
msgstr ""
|
1513 |
+
|
1514 |
+
#: ../settings.php:234
|
1515 |
+
msgid "Enable reporting"
|
1516 |
+
msgstr ""
|
1517 |
+
|
1518 |
+
#: ../cerber-load.php:3214
|
1519 |
+
msgid "Your last sign-in was %s from %s"
|
1520 |
+
msgstr ""
|
1521 |
+
|
1522 |
+
#: ../cerber-load.php:3315
|
1523 |
+
msgid "Attempts to log in with non-existent username"
|
1524 |
+
msgstr ""
|
1525 |
+
|
1526 |
+
#: ../dashboard.php:169
|
1527 |
+
msgid "IP address, IPv4 address range or subnet"
|
1528 |
+
msgstr ""
|
1529 |
+
|
1530 |
+
#: ../dashboard.php:171
|
1531 |
+
msgid "Optional comment for this entry"
|
1532 |
+
msgstr ""
|
1533 |
+
|
1534 |
+
#: ../dashboard.php:212
|
1535 |
+
msgid "You cannot add your IP address or network"
|
1536 |
+
msgstr ""
|
1537 |
+
|
1538 |
+
#: ../cerber-news.php:159
|
1539 |
+
msgid "Cool!"
|
1540 |
+
msgstr ""
|
1541 |
+
|
1542 |
+
#: ../settings.php:143
|
1543 |
+
msgid "To specify a REGEX pattern wrap a pattern in two forward slashes."
|
1544 |
+
msgstr ""
|
1545 |
+
|
1546 |
+
#: ../dashboard.php:993
|
1547 |
+
msgid "Cerber Traffic Inspector"
|
1548 |
+
msgstr ""
|
1549 |
+
|
1550 |
+
#: ../dashboard.php:993 ../dashboard.php:1212 ../dashboard.php:2508
|
1551 |
+
msgid "Traffic Inspector"
|
1552 |
+
msgstr ""
|
1553 |
+
|
1554 |
+
#: ../dashboard.php:1228
|
1555 |
+
msgid "Traffic"
|
1556 |
+
msgstr ""
|
1557 |
+
|
1558 |
+
#: ../dashboard.php:2513
|
1559 |
+
msgid "Live traffic"
|
1560 |
+
msgstr ""
|
1561 |
+
|
1562 |
+
#: ../dashboard.php:2825
|
1563 |
+
msgid "Request"
|
1564 |
+
msgstr ""
|
1565 |
+
|
1566 |
+
#: ../dashboard.php:2827
|
1567 |
+
msgid "Host Info"
|
1568 |
+
msgstr ""
|
1569 |
+
|
1570 |
+
#: ../dashboard.php:2828
|
1571 |
+
msgid "User Agent"
|
1572 |
+
msgstr ""
|
1573 |
+
|
1574 |
+
#: ../dashboard.php:2853
|
1575 |
+
msgid "All requests"
|
1576 |
+
msgstr ""
|
1577 |
+
|
1578 |
+
#: ../dashboard.php:2855
|
1579 |
+
msgid "Not logged in visitors"
|
1580 |
+
msgstr ""
|
1581 |
+
|
1582 |
+
#: ../dashboard.php:2856
|
1583 |
+
msgid "Form submissions"
|
1584 |
+
msgstr ""
|
1585 |
+
|
1586 |
+
#: ../dashboard.php:2857
|
1587 |
+
msgid "Page Not Found"
|
1588 |
+
msgstr ""
|
1589 |
+
|
1590 |
+
#: ../dashboard.php:2858
|
1591 |
+
msgid "REST API"
|
1592 |
+
msgstr ""
|
1593 |
+
|
1594 |
+
#: ../dashboard.php:2859
|
1595 |
+
msgid "XML-RPC"
|
1596 |
+
msgstr ""
|
1597 |
+
|
1598 |
+
#: ../dashboard.php:2863
|
1599 |
+
msgid "Longer than"
|
1600 |
+
msgstr ""
|
1601 |
+
|
1602 |
+
#: ../dashboard.php:2876
|
1603 |
+
msgid "Refresh"
|
1604 |
+
msgstr ""
|
1605 |
+
|
1606 |
+
#: ../common.php:101
|
1607 |
+
msgid "Check for requests"
|
1608 |
+
msgstr ""
|
1609 |
+
|
1610 |
+
#: ../common.php:1005
|
1611 |
+
msgid "Not specified"
|
1612 |
+
msgstr ""
|
1613 |
+
|
1614 |
+
#: ../settings.php:270
|
1615 |
+
msgid "Logging mode"
|
1616 |
+
msgstr ""
|
1617 |
+
|
1618 |
+
#: ../settings.php:276
|
1619 |
+
msgid "Logging disabled"
|
1620 |
+
msgstr ""
|
1621 |
+
|
1622 |
+
#: ../settings.php:277
|
1623 |
+
msgid "Smart"
|
1624 |
+
msgstr ""
|
1625 |
+
|
1626 |
+
#: ../settings.php:278
|
1627 |
+
msgid "All traffic"
|
1628 |
+
msgstr ""
|
1629 |
+
|
1630 |
+
#: ../settings.php:282
|
1631 |
+
msgid "Ignore crawlers"
|
1632 |
+
msgstr ""
|
1633 |
+
|
1634 |
+
#: ../settings.php:292
|
1635 |
+
msgid "Mask these form fields"
|
1636 |
+
msgstr ""
|
1637 |
+
|
1638 |
+
#: ../settings.php:327
|
1639 |
+
msgid "milliseconds"
|
1640 |
+
msgstr ""
|
1641 |
+
|
1642 |
+
#: ../settings.php:254
|
1643 |
+
msgid "Inspection"
|
1644 |
+
msgstr ""
|
1645 |
+
|
1646 |
+
#: ../settings.php:255
|
1647 |
+
msgid "Enable traffic inspection"
|
1648 |
+
msgstr ""
|
1649 |
+
|
1650 |
+
#: ../settings.php:269
|
1651 |
+
msgid "Logging"
|
1652 |
+
msgstr ""
|
1653 |
+
|
1654 |
+
#: ../settings.php:287
|
1655 |
+
msgid "Save request fields"
|
1656 |
+
msgstr ""
|
1657 |
+
|
1658 |
+
#: ../settings.php:322
|
1659 |
+
msgid "Page generation time threshold"
|
1660 |
+
msgstr ""
|
1661 |
+
|
1662 |
+
#: ../dashboard.php:2845
|
1663 |
+
msgid "No requests have been logged."
|
1664 |
+
msgstr ""
|
1665 |
+
|
1666 |
+
#: ../dashboard.php:1211
|
1667 |
+
msgid "enabled"
|
1668 |
+
msgstr ""
|
1669 |
+
|
1670 |
+
#: ../dashboard.php:1215
|
1671 |
+
msgid "no connection"
|
1672 |
+
msgstr ""
|
1673 |
+
|
1674 |
+
#: ../dashboard.php:3130
|
1675 |
+
msgid "Advanced search"
|
1676 |
+
msgstr ""
|
1677 |
+
|
1678 |
+
#: ../dashboard.php:949
|
1679 |
+
msgid "Last seen"
|
1680 |
+
msgstr ""
|
1681 |
+
|
1682 |
+
#: ../common.php:744 ../common.php:790
|
1683 |
+
msgid "Probing for vulnerable PHP code"
|
1684 |
+
msgstr ""
|
1685 |
+
|
1686 |
+
#: ../dashboard.php:3111
|
1687 |
+
msgid "Any"
|
1688 |
+
msgstr ""
|
1689 |
+
|
1690 |
+
#: ../cerber-load.php:2941
|
1691 |
+
msgid "We're sorry, you are not allowed to proceed"
|
1692 |
+
msgstr ""
|
1693 |
+
|
1694 |
+
#: ../settings.php:260
|
1695 |
+
msgid "Request whitelist"
|
1696 |
+
msgstr ""
|
1697 |
+
|
1698 |
+
#: ../settings.php:266
|
1699 |
+
msgid "Enter a request URI to exclude the request from inspection. One item per line."
|
1700 |
+
msgstr ""
|
1701 |
+
|
1702 |
+
#: ../settings.php:303
|
1703 |
+
msgid "Save request headers"
|
1704 |
+
msgstr ""
|
1705 |
+
|
1706 |
+
#: ../settings.php:309
|
1707 |
+
msgid "Save $_SERVER"
|
1708 |
+
msgstr ""
|
1709 |
+
|
1710 |
+
#: ../settings.php:315
|
1711 |
+
msgid "Save request cookies"
|
1712 |
+
msgstr ""
|
1713 |
+
|
1714 |
+
#: ../settings.php:114
|
1715 |
+
msgid "Protect admin scripts"
|
1716 |
+
msgstr ""
|
1717 |
+
|
1718 |
+
#: ../settings.php:114
|
1719 |
+
msgid "Block unauthorized access to load-scripts.php and load-styles.php"
|
1720 |
+
msgstr ""
|
1721 |
+
|
1722 |
+
#: ../common.php:1382
|
1723 |
+
msgid "Unable to create the directory"
|
1724 |
+
msgstr ""
|
1725 |
+
|
1726 |
+
#: ../common.php:1387
|
1727 |
+
msgid "Destination folder access denied"
|
1728 |
+
msgstr ""
|
1729 |
+
|
1730 |
+
#: ../common.php:1390
|
1731 |
+
msgid "File not found"
|
1732 |
+
msgstr ""
|
1733 |
+
|
1734 |
+
#: ../common.php:1393
|
1735 |
+
msgid "Unable to copy the file"
|
1736 |
+
msgstr ""
|
1737 |
+
|
1738 |
+
#: ../common.php:1399
|
1739 |
+
msgid "Unable to delete the file"
|
1740 |
+
msgstr ""
|
1741 |
+
|
1742 |
+
#: ../settings.php:70
|
1743 |
+
msgid "Plugin initialization"
|
1744 |
+
msgstr ""
|
1745 |
+
|
1746 |
+
#: ../settings.php:71
|
1747 |
+
msgid "Load security engine"
|
1748 |
+
msgstr ""
|
1749 |
+
|
1750 |
+
#: ../settings.php:71
|
1751 |
+
msgid "Legacy mode"
|
1752 |
+
msgstr ""
|
1753 |
+
|
1754 |
+
#: ../settings.php:71
|
1755 |
+
msgid "Standard mode"
|
1756 |
+
msgstr ""
|
1757 |
+
|
1758 |
+
#: ../settings.php:781
|
1759 |
+
msgid "Plugin initialization mode has not been changed"
|
1760 |
+
msgstr ""
|
1761 |
+
|
1762 |
+
#. Name of the plugin
|
1763 |
+
#:
|
1764 |
+
msgid "WP Cerber boot module"
|
1765 |
+
msgstr ""
|
1766 |
+
|
1767 |
+
#. Description of the plugin
|
1768 |
+
#:
|
1769 |
+
msgid "This is a standard boot module for WP Cerber Security & Antispam plugin. It was installed when you set the plugin initialization mode to Standard. Know more: <a href=\"https://wpcerber.com\">wpcerber.com</a>."
|
1770 |
+
msgstr ""
|
1771 |
+
|
languages/wp-cerber.pot
CHANGED
@@ -5,7 +5,7 @@ msgstr ""
|
|
5 |
"Project-Id-Version: WP Cerber\n"
|
6 |
"Report-Msgid-Bugs-To: \n"
|
7 |
"POT-Creation-Date: Tue Sep 08 2015 21:38:11 GMT+0300\n"
|
8 |
-
"POT-Revision-Date:
|
9 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
10 |
"Last-Translator: \n"
|
11 |
"Language-Team: \n"
|
@@ -28,16 +28,16 @@ msgstr ""
|
|
28 |
msgid "Remove"
|
29 |
msgstr ""
|
30 |
|
31 |
-
#: ../dashboard.php:93 ../dashboard.php:
|
32 |
-
#: php:
|
33 |
msgid "IP"
|
34 |
msgstr ""
|
35 |
|
36 |
-
#: ../dashboard.php:94 ../dashboard.php:
|
37 |
msgid "Hostname"
|
38 |
msgstr ""
|
39 |
|
40 |
-
#: ../dashboard.php:95 ../dashboard.php:
|
41 |
msgid "Country"
|
42 |
msgstr ""
|
43 |
|
@@ -45,7 +45,7 @@ msgstr ""
|
|
45 |
msgid "Expires"
|
46 |
msgstr ""
|
47 |
|
48 |
-
#: ../dashboard.php:97 ../
|
49 |
msgid "Reason"
|
50 |
msgstr ""
|
51 |
|
@@ -70,9 +70,9 @@ msgstr ""
|
|
70 |
msgid "No lockouts at the moment. The sky is clear."
|
71 |
msgstr ""
|
72 |
|
73 |
-
#: ../dashboard.php:131 ../dashboard.php:
|
74 |
-
#: php:
|
75 |
-
#: /settings.php:
|
76 |
msgid "White IP Access List"
|
77 |
msgstr ""
|
78 |
|
@@ -80,8 +80,8 @@ msgstr ""
|
|
80 |
msgid "These IPs will never be locked out"
|
81 |
msgstr ""
|
82 |
|
83 |
-
#: ../dashboard.php:133 ../dashboard.php:
|
84 |
-
#: php:
|
85 |
msgid "Black IP Access List"
|
86 |
msgstr ""
|
87 |
|
@@ -93,8 +93,8 @@ msgstr ""
|
|
93 |
msgid "Your IP"
|
94 |
msgstr ""
|
95 |
|
96 |
-
#: ../dashboard.php:158 ../dashboard.php:
|
97 |
-
#: php:
|
98 |
msgid "Check for activity"
|
99 |
msgstr ""
|
100 |
|
@@ -132,8 +132,8 @@ msgstr ""
|
|
132 |
msgid "Address %s was added to Black IP Access List"
|
133 |
msgstr ""
|
134 |
|
135 |
-
#: ../dashboard.php:313 ../dashboard.php:
|
136 |
-
#: /common.php:
|
137 |
msgid "Unknown"
|
138 |
msgstr ""
|
139 |
|
@@ -149,449 +149,449 @@ msgstr ""
|
|
149 |
msgid "Unable to send email to"
|
150 |
msgstr ""
|
151 |
|
152 |
-
#: ../dashboard.php:
|
153 |
#, php-format
|
154 |
msgid "Lockout for %s was removed"
|
155 |
msgstr ""
|
156 |
|
157 |
-
#: ../dashboard.php:
|
158 |
msgid "Settings saved"
|
159 |
msgstr ""
|
160 |
|
161 |
-
#: ../dashboard.php:
|
162 |
msgid "IP address"
|
163 |
msgstr ""
|
164 |
|
165 |
-
#: ../dashboard.php:
|
166 |
msgid "Date"
|
167 |
msgstr ""
|
168 |
|
169 |
-
#: ../dashboard.php:
|
170 |
msgid "Event"
|
171 |
msgstr ""
|
172 |
|
173 |
-
#: ../dashboard.php:
|
174 |
msgid "Local User"
|
175 |
msgstr ""
|
176 |
|
177 |
-
#: ../dashboard.php:
|
178 |
msgid "User login"
|
179 |
msgstr ""
|
180 |
|
181 |
-
#: ../dashboard.php:
|
182 |
msgid "User ID"
|
183 |
msgstr ""
|
184 |
|
185 |
-
#: ../dashboard.php:
|
186 |
msgid "Username used"
|
187 |
msgstr ""
|
188 |
|
189 |
-
#: ../dashboard.php:
|
190 |
-
#:
|
191 |
msgid "Locked out"
|
192 |
msgstr ""
|
193 |
|
194 |
-
#: ../dashboard.php:
|
195 |
msgid "Export"
|
196 |
msgstr ""
|
197 |
|
198 |
-
#: ../dashboard.php:
|
199 |
msgid "No activity has been logged."
|
200 |
msgstr ""
|
201 |
|
202 |
-
#: ../dashboard.php:
|
203 |
msgid "All events"
|
204 |
msgstr ""
|
205 |
|
206 |
-
#: ../dashboard.php:
|
207 |
msgid "Search for IP or username"
|
208 |
msgstr ""
|
209 |
|
210 |
-
#: ../dashboard.php:
|
211 |
msgid "Filter"
|
212 |
msgstr ""
|
213 |
|
214 |
-
#: ../dashboard.php:
|
215 |
msgid "Abuse email:"
|
216 |
msgstr ""
|
217 |
|
218 |
-
#: ../dashboard.php:
|
219 |
msgid "Network:"
|
220 |
msgstr ""
|
221 |
|
222 |
-
#: ../dashboard.php:
|
223 |
msgid "Add network to the Black List"
|
224 |
msgstr ""
|
225 |
|
226 |
-
#: ../dashboard.php:
|
227 |
msgid "Add IP to the Black List"
|
228 |
msgstr ""
|
229 |
|
230 |
-
#: ../dashboard.php:
|
231 |
msgid "Last seen"
|
232 |
msgstr ""
|
233 |
|
234 |
-
#: ../dashboard.php:
|
235 |
msgid "Registered"
|
236 |
msgstr ""
|
237 |
|
238 |
-
#: ../dashboard.php:
|
239 |
msgid "WP Cerber Security"
|
240 |
msgstr ""
|
241 |
|
242 |
#. Name of the plugin
|
243 |
-
#: ../dashboard.php:
|
244 |
msgid "WP Cerber"
|
245 |
msgstr ""
|
246 |
|
247 |
-
#: ../dashboard.php:
|
248 |
msgid "Cerber Dashboard"
|
249 |
msgstr ""
|
250 |
|
251 |
-
#: ../dashboard.php:
|
252 |
-
#: php:
|
253 |
msgid "Dashboard"
|
254 |
msgstr ""
|
255 |
|
256 |
-
#: ../dashboard.php:
|
257 |
msgid "Cerber Traffic Inspector"
|
258 |
msgstr ""
|
259 |
|
260 |
-
#: ../dashboard.php:
|
261 |
msgid "Traffic Inspector"
|
262 |
msgstr ""
|
263 |
|
264 |
-
#: ../dashboard.php:
|
265 |
msgid "Cerber Security Rules"
|
266 |
msgstr ""
|
267 |
|
268 |
-
#: ../dashboard.php:
|
269 |
msgid "Security Rules"
|
270 |
msgstr ""
|
271 |
|
272 |
-
#: ../dashboard.php:
|
273 |
msgid "Cerber antispam settings"
|
274 |
msgstr ""
|
275 |
|
276 |
-
#: ../dashboard.php:
|
277 |
-
#: php:
|
278 |
msgid "Antispam"
|
279 |
msgstr ""
|
280 |
|
281 |
-
#: ../dashboard.php:
|
282 |
msgid "Cerber tools"
|
283 |
msgstr ""
|
284 |
|
285 |
-
#: ../dashboard.php:
|
286 |
msgid "Tools"
|
287 |
msgstr ""
|
288 |
|
289 |
-
#: ../dashboard.php:
|
290 |
msgid "Comments"
|
291 |
msgstr ""
|
292 |
|
293 |
-
#: ../dashboard.php:
|
294 |
msgid "Last login"
|
295 |
msgstr ""
|
296 |
|
297 |
-
#: ../dashboard.php:
|
298 |
msgid "Failed login attempts"
|
299 |
msgstr ""
|
300 |
|
301 |
-
#: ../dashboard.php:
|
302 |
msgid "Never"
|
303 |
msgstr ""
|
304 |
|
305 |
-
#: ../dashboard.php:
|
306 |
msgid "You"
|
307 |
msgstr ""
|
308 |
|
309 |
-
#: ../dashboard.php:
|
310 |
msgid "Cerber Quick View"
|
311 |
msgstr ""
|
312 |
|
313 |
-
#: ../dashboard.php:
|
314 |
msgid "active"
|
315 |
msgstr ""
|
316 |
|
317 |
-
#: ../dashboard.php:
|
318 |
msgid "deactivate"
|
319 |
msgstr ""
|
320 |
|
321 |
-
#: ../dashboard.php:
|
322 |
msgid "not active"
|
323 |
msgstr ""
|
324 |
|
325 |
-
#: ../dashboard.php:
|
326 |
msgid "disabled"
|
327 |
msgstr ""
|
328 |
|
329 |
-
#: ../dashboard.php:
|
330 |
msgid "failed attempts"
|
331 |
msgstr ""
|
332 |
|
333 |
-
#: ../dashboard.php:
|
334 |
msgid "in 24 hours"
|
335 |
msgstr ""
|
336 |
|
337 |
-
#: ../dashboard.php:
|
338 |
msgid "view all"
|
339 |
msgstr ""
|
340 |
|
341 |
-
#: ../dashboard.php:
|
342 |
msgid "lockouts"
|
343 |
msgstr ""
|
344 |
|
345 |
-
#: ../dashboard.php:
|
346 |
msgid "Lockouts at the moment"
|
347 |
msgstr ""
|
348 |
|
349 |
-
#: ../dashboard.php:
|
350 |
msgid "Last lockout"
|
351 |
msgstr ""
|
352 |
|
353 |
-
#: ../dashboard.php:
|
354 |
msgid "entry"
|
355 |
msgid_plural "entries"
|
356 |
msgstr[0] ""
|
357 |
msgstr[1] ""
|
358 |
|
359 |
-
#: ../dashboard.php:
|
360 |
msgid "Citadel mode"
|
361 |
msgstr ""
|
362 |
|
363 |
-
#: ../dashboard.php:
|
364 |
msgid "enabled"
|
365 |
msgstr ""
|
366 |
|
367 |
-
#: ../dashboard.php:
|
368 |
msgid "no connection"
|
369 |
msgstr ""
|
370 |
|
371 |
-
#: ../dashboard.php:
|
372 |
-
#: php:
|
373 |
msgid "Activity"
|
374 |
msgstr ""
|
375 |
|
376 |
-
#: ../dashboard.php:
|
377 |
msgid "Traffic"
|
378 |
msgstr ""
|
379 |
|
380 |
-
#: ../dashboard.php:
|
381 |
msgid "My site is behind a reverse proxy"
|
382 |
msgstr ""
|
383 |
|
384 |
-
#: ../dashboard.php:
|
385 |
msgid "in the last 24 hours"
|
386 |
msgstr ""
|
387 |
|
388 |
-
#: ../dashboard.php:
|
389 |
msgid "View all"
|
390 |
msgstr ""
|
391 |
|
392 |
-
#: ../dashboard.php:
|
393 |
msgid "User registered"
|
394 |
msgstr ""
|
395 |
|
396 |
-
#: ../dashboard.php:
|
397 |
msgid "All suspicious activity"
|
398 |
msgstr ""
|
399 |
|
400 |
-
#: ../dashboard.php:
|
401 |
msgid "Recently locked out IP addresses"
|
402 |
msgstr ""
|
403 |
|
404 |
-
#: ../dashboard.php:
|
405 |
msgid "Confused about some settings?"
|
406 |
msgstr ""
|
407 |
|
408 |
-
#: ../dashboard.php:
|
409 |
msgid "You can easily load default recommended settings using button below"
|
410 |
msgstr ""
|
411 |
|
412 |
-
#: ../dashboard.php:
|
413 |
msgid "Load default settings"
|
414 |
msgstr ""
|
415 |
|
416 |
-
#: ../dashboard.php:
|
417 |
msgid "Are you sure?"
|
418 |
msgstr ""
|
419 |
|
420 |
-
#: ../dashboard.php:
|
421 |
msgid "doesn't affect Custom login URL and Access Lists"
|
422 |
msgstr ""
|
423 |
|
424 |
-
#: ../dashboard.php:
|
425 |
msgid "Getting Started Guide"
|
426 |
msgstr ""
|
427 |
|
428 |
-
#: ../dashboard.php:
|
429 |
msgid "Attention! Citadel mode is now active. Nobody is able to log in."
|
430 |
msgstr ""
|
431 |
|
432 |
-
#: ../dashboard.php:
|
433 |
msgid "Deactivate"
|
434 |
msgstr ""
|
435 |
|
436 |
-
#: ../dashboard.php:
|
437 |
msgid "View Activity"
|
438 |
msgstr ""
|
439 |
|
440 |
-
#: ../dashboard.php:
|
441 |
msgid "Subscribe"
|
442 |
msgstr ""
|
443 |
|
444 |
-
#: ../dashboard.php:
|
445 |
msgid "Unsubscribe"
|
446 |
msgstr ""
|
447 |
|
448 |
-
#: ../dashboard.php:
|
449 |
msgid "You've subscribed"
|
450 |
msgstr ""
|
451 |
|
452 |
-
#: ../dashboard.php:
|
453 |
msgid "You've unsubscribed"
|
454 |
msgstr ""
|
455 |
|
456 |
-
#: ../dashboard.php:
|
457 |
msgid "Main settings"
|
458 |
msgstr ""
|
459 |
|
460 |
-
#: ../dashboard.php:
|
461 |
msgid "Countries"
|
462 |
msgstr ""
|
463 |
|
464 |
-
#: ../dashboard.php:
|
465 |
#, php-format
|
466 |
msgid "Permitted for one country"
|
467 |
msgid_plural "Permitted for %d countries"
|
468 |
msgstr[0] ""
|
469 |
msgstr[1] ""
|
470 |
|
471 |
-
#: ../dashboard.php:
|
472 |
#, php-format
|
473 |
msgid "Not permitted for one country"
|
474 |
msgid_plural "Not permitted for %d countries"
|
475 |
msgstr[0] ""
|
476 |
msgstr[1] ""
|
477 |
|
478 |
-
#: ../dashboard.php:
|
479 |
msgid "No rule"
|
480 |
msgstr ""
|
481 |
|
482 |
-
#: ../dashboard.php:
|
483 |
msgid "Start typing here to find a country"
|
484 |
msgstr ""
|
485 |
|
486 |
-
#: ../dashboard.php:
|
487 |
msgid "Click on a country name to add it to the list of selected countries"
|
488 |
msgstr ""
|
489 |
|
490 |
-
#: ../dashboard.php:
|
491 |
#, php-format
|
492 |
msgctxt "to is a marker of infinitive, e.g. \"to use it\""
|
493 |
msgid "Selected countries are permitted to %s, other countries are not permitted to"
|
494 |
msgstr ""
|
495 |
|
496 |
-
#: ../dashboard.php:
|
497 |
#, php-format
|
498 |
msgctxt "to is a marker of infinitive, e.g. \"to use it\""
|
499 |
msgid "Selected countries are not permitted to %s, other countries are permitted to"
|
500 |
msgstr ""
|
501 |
|
502 |
-
#: ../dashboard.php:
|
503 |
msgid "Submit forms"
|
504 |
msgstr ""
|
505 |
|
506 |
-
#: ../dashboard.php:
|
507 |
msgid "Post comments"
|
508 |
msgstr ""
|
509 |
|
510 |
-
#: ../dashboard.php:
|
511 |
msgid "Log in to the website"
|
512 |
msgstr ""
|
513 |
|
514 |
-
#: ../dashboard.php:
|
515 |
msgid "Register on the website"
|
516 |
msgstr ""
|
517 |
|
518 |
-
#: ../dashboard.php:
|
519 |
msgid "Use XML-RPC"
|
520 |
msgstr ""
|
521 |
|
522 |
-
#: ../dashboard.php:
|
523 |
msgid "Use REST API"
|
524 |
msgstr ""
|
525 |
|
526 |
-
#: ../dashboard.php:
|
527 |
msgid "Security rules have been updated"
|
528 |
msgstr ""
|
529 |
|
530 |
-
#: ../dashboard.php:
|
531 |
msgid "Live traffic"
|
532 |
msgstr ""
|
533 |
|
534 |
-
#: ../dashboard.php:
|
535 |
msgid "Settings"
|
536 |
msgstr ""
|
537 |
|
538 |
-
#: ../dashboard.php:
|
539 |
msgid "Request"
|
540 |
msgstr ""
|
541 |
|
542 |
-
#: ../dashboard.php:
|
543 |
msgid "Host Info"
|
544 |
msgstr ""
|
545 |
|
546 |
-
#: ../dashboard.php:
|
547 |
msgid "User Agent"
|
548 |
msgstr ""
|
549 |
|
550 |
-
#: ../dashboard.php:
|
551 |
msgid "No requests have been logged."
|
552 |
msgstr ""
|
553 |
|
554 |
-
#: ../dashboard.php:
|
555 |
msgid "All requests"
|
556 |
msgstr ""
|
557 |
|
558 |
-
#: ../dashboard.php:
|
559 |
msgid "Logged in users"
|
560 |
msgstr ""
|
561 |
|
562 |
-
#: ../dashboard.php:
|
563 |
msgid "Not logged in visitors"
|
564 |
msgstr ""
|
565 |
|
566 |
-
#: ../dashboard.php:
|
567 |
msgid "Form submissions"
|
568 |
msgstr ""
|
569 |
|
570 |
-
#: ../dashboard.php:
|
571 |
msgid "Page Not Found"
|
572 |
msgstr ""
|
573 |
|
574 |
-
#: ../dashboard.php:
|
575 |
msgid "REST API"
|
576 |
msgstr ""
|
577 |
|
578 |
-
#: ../dashboard.php:
|
579 |
msgid "XML-RPC"
|
580 |
msgstr ""
|
581 |
|
582 |
-
#: ../dashboard.php:
|
583 |
msgid "Longer than"
|
584 |
msgstr ""
|
585 |
|
586 |
-
#: ../dashboard.php:
|
587 |
msgid "Refresh"
|
588 |
msgstr ""
|
589 |
|
590 |
-
#: ../dashboard.php:
|
591 |
msgid "Any"
|
592 |
msgstr ""
|
593 |
|
594 |
-
#: ../dashboard.php:
|
595 |
msgid "Advanced search"
|
596 |
msgstr ""
|
597 |
|
@@ -615,1112 +615,1162 @@ msgstr ""
|
|
615 |
msgid "Gregory"
|
616 |
msgstr ""
|
617 |
|
618 |
-
#: ../
|
619 |
-
msgid "
|
620 |
msgstr ""
|
621 |
|
622 |
-
#: ../
|
623 |
-
|
624 |
-
msgid "You have reached the login attempts limit. Please try again in %d minutes."
|
625 |
msgstr ""
|
626 |
|
627 |
-
#: ../
|
628 |
-
|
629 |
-
msgid "You have only one attempt remaining."
|
630 |
-
msgid_plural "You have %d attempts remaining."
|
631 |
-
msgstr[0] ""
|
632 |
-
msgstr[1] ""
|
633 |
-
|
634 |
-
#: ../wp-cerber.php:546 ../wp-cerber.php:558 ../wp-cerber.php:565 ../wp-cerber.
|
635 |
-
#: php:761 ../wp-cerber.php:977 ../wp-cerber.php:983 ../wp-cerber.php:988 ../wp-
|
636 |
-
#: cerber.php:993 ../wp-cerber.php:999 ../wp-cerber.php:1006 ../wp-cerber.php:
|
637 |
-
#: 1106 ../wp-cerber.php:1243 ../common.php:194 ../common.php:251 ../common.php:
|
638 |
-
#: 255 ../settings.php:837
|
639 |
-
msgid "ERROR:"
|
640 |
msgstr ""
|
641 |
|
642 |
-
#: ../
|
643 |
-
msgid ""
|
644 |
-
"Human verification failed. Please click the square box in the reCAPTCHA "
|
645 |
-
"block below."
|
646 |
msgstr ""
|
647 |
|
648 |
-
#: ../
|
649 |
-
msgid ""
|
650 |
-
"> > > Translator of WP Cerber? To get the PRO license for free, drop your "
|
651 |
-
"contacts here: https://wpcerber.com/contact/"
|
652 |
msgstr ""
|
653 |
|
654 |
-
#: ../
|
655 |
-
|
656 |
-
msgid ""
|
657 |
-
"<strong>ERROR</strong>: The password you entered for the username %s is "
|
658 |
-
"incorrect."
|
659 |
msgstr ""
|
660 |
|
661 |
-
#: ../
|
662 |
-
#: php:
|
663 |
-
|
|
|
|
|
|
|
|
|
664 |
msgstr ""
|
665 |
|
666 |
-
#: ../
|
667 |
-
msgid "
|
668 |
msgstr ""
|
669 |
|
670 |
-
#: ../
|
671 |
-
msgid "
|
672 |
msgstr ""
|
673 |
|
674 |
-
#: ../
|
675 |
-
msgid "
|
676 |
msgstr ""
|
677 |
|
678 |
-
#: ../
|
679 |
-
msgid "
|
680 |
msgstr ""
|
681 |
|
682 |
-
#: ../
|
683 |
-
msgid "
|
684 |
msgstr ""
|
685 |
|
686 |
-
#: ../
|
687 |
-
|
688 |
-
msgid "Citadel mode is activated after %d failed login attempts in %d minutes."
|
689 |
msgstr ""
|
690 |
|
691 |
-
#: ../
|
692 |
-
|
693 |
-
msgid "Last failed attempt was at %s from IP %s with user login: %s."
|
694 |
msgstr ""
|
695 |
|
696 |
-
#: ../
|
697 |
-
msgid "
|
698 |
msgstr ""
|
699 |
|
700 |
-
#: ../
|
701 |
-
msgid "
|
702 |
msgstr ""
|
703 |
|
704 |
-
#: ../
|
705 |
-
msgid "
|
706 |
msgstr ""
|
707 |
|
708 |
-
#: ../
|
709 |
-
msgid "
|
710 |
msgstr ""
|
711 |
|
712 |
-
#: ../
|
713 |
-
|
714 |
-
msgid "Last lockout was added: %s for IP %s"
|
715 |
msgstr ""
|
716 |
|
717 |
-
#: ../
|
718 |
-
msgid "
|
719 |
msgstr ""
|
720 |
|
721 |
-
#: ../
|
722 |
-
msgid "
|
723 |
msgstr ""
|
724 |
|
725 |
-
#: ../
|
726 |
-
msgid "
|
727 |
msgstr ""
|
728 |
|
729 |
-
#: ../
|
730 |
-
msgid "
|
731 |
msgstr ""
|
732 |
|
733 |
-
#: ../
|
734 |
-
msgid "
|
735 |
msgstr ""
|
736 |
|
737 |
-
#: ../
|
738 |
-
msgid "
|
739 |
msgstr ""
|
740 |
|
741 |
-
#: ../
|
742 |
-
msgid "
|
743 |
msgstr ""
|
744 |
|
745 |
-
#: ../
|
746 |
-
msgid "
|
747 |
msgstr ""
|
748 |
|
749 |
-
#: ../
|
750 |
-
msgid "
|
751 |
msgstr ""
|
752 |
|
753 |
-
#: ../
|
754 |
-
msgid "
|
755 |
msgstr ""
|
756 |
|
757 |
-
#: ../
|
758 |
-
msgid "
|
759 |
msgstr ""
|
760 |
|
761 |
-
#: ../
|
762 |
-
msgid "
|
763 |
msgstr ""
|
764 |
|
765 |
-
#: ../
|
766 |
-
msgid "
|
767 |
msgstr ""
|
768 |
|
769 |
-
#: ../
|
770 |
-
msgid "
|
771 |
msgstr ""
|
772 |
|
773 |
-
#: ../
|
774 |
-
msgid "
|
775 |
msgstr ""
|
776 |
|
777 |
-
#: ../
|
778 |
-
msgid "
|
779 |
msgstr ""
|
780 |
|
781 |
-
#: ../
|
782 |
-
msgid "
|
783 |
msgstr ""
|
784 |
|
785 |
-
#: ../
|
786 |
-
msgid "
|
787 |
msgstr ""
|
788 |
|
789 |
-
#: ../
|
790 |
-
msgid "
|
791 |
msgstr ""
|
792 |
|
793 |
-
#: ../
|
794 |
-
|
795 |
-
msgid "Your last sign-in was %s from %s"
|
796 |
msgstr ""
|
797 |
|
798 |
-
#: ../
|
799 |
-
msgid "
|
800 |
msgstr ""
|
801 |
|
802 |
-
#: ../
|
803 |
-
msgid "
|
804 |
msgstr ""
|
805 |
|
806 |
-
#: ../
|
807 |
-
msgid "
|
808 |
msgstr ""
|
809 |
|
810 |
-
#: ../
|
811 |
-
msgid "
|
812 |
msgstr ""
|
813 |
|
814 |
-
#: ../
|
815 |
-
msgid "
|
816 |
msgstr ""
|
817 |
|
818 |
-
#: ../
|
819 |
-
msgid "
|
820 |
msgstr ""
|
821 |
|
822 |
-
#: ../
|
823 |
#, php-format
|
824 |
-
msgid "
|
825 |
msgstr ""
|
826 |
|
827 |
-
#: ../
|
|
|
|
|
|
|
|
|
828 |
#, php-format
|
829 |
-
msgid "
|
830 |
msgstr ""
|
831 |
|
832 |
-
#: ../
|
833 |
-
msgid "
|
834 |
msgstr ""
|
835 |
|
836 |
-
#: ../
|
837 |
-
msgid "
|
838 |
msgstr ""
|
839 |
|
840 |
-
#: ../
|
841 |
-
msgid "
|
842 |
msgstr ""
|
843 |
|
844 |
-
#: ../
|
845 |
-
|
846 |
-
msgid "Access Lists"
|
847 |
msgstr ""
|
848 |
|
849 |
-
#: ../
|
850 |
-
msgid "
|
851 |
msgstr ""
|
852 |
|
853 |
-
#: ../
|
854 |
-
msgid "
|
855 |
msgstr ""
|
856 |
|
857 |
-
#: ../
|
858 |
-
msgid "
|
859 |
msgstr ""
|
860 |
|
861 |
-
#: ../
|
862 |
-
msgid "
|
863 |
msgstr ""
|
864 |
|
865 |
-
#: ../
|
866 |
-
msgid "
|
|
|
|
|
|
|
|
|
867 |
msgstr ""
|
868 |
|
869 |
-
#: ../
|
870 |
-
msgid "
|
871 |
msgstr ""
|
872 |
|
873 |
-
#: ../
|
874 |
-
msgid "
|
875 |
msgstr ""
|
876 |
|
877 |
-
#: ../
|
878 |
-
msgid "
|
879 |
msgstr ""
|
880 |
|
881 |
-
#: ../
|
882 |
-
msgid "
|
883 |
msgstr ""
|
884 |
|
885 |
-
#: ../
|
886 |
-
|
|
|
887 |
msgstr ""
|
888 |
|
889 |
-
#: ../
|
890 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
891 |
msgstr ""
|
892 |
|
893 |
-
#: ../
|
894 |
-
msgid "
|
|
|
|
|
895 |
msgstr ""
|
896 |
|
897 |
-
#: ../
|
898 |
-
|
|
|
|
|
|
|
899 |
msgstr ""
|
900 |
|
901 |
-
#: ../
|
902 |
-
|
|
|
903 |
msgstr ""
|
904 |
|
905 |
-
#: ../
|
906 |
-
msgid "
|
907 |
msgstr ""
|
908 |
|
909 |
-
#: ../
|
910 |
-
msgid "
|
911 |
msgstr ""
|
912 |
|
913 |
-
#: ../
|
914 |
-
msgid "
|
915 |
msgstr ""
|
916 |
|
917 |
-
#: ../
|
918 |
-
msgid "
|
919 |
msgstr ""
|
920 |
|
921 |
-
#: ../
|
922 |
-
msgid "
|
923 |
msgstr ""
|
924 |
|
925 |
-
#: ../
|
926 |
-
|
|
|
927 |
msgstr ""
|
928 |
|
929 |
-
#: ../
|
930 |
-
|
|
|
931 |
msgstr ""
|
932 |
|
933 |
-
#: ../
|
934 |
-
msgid "
|
935 |
msgstr ""
|
936 |
|
937 |
-
#: ../
|
938 |
-
msgid "
|
939 |
msgstr ""
|
940 |
|
941 |
-
#: ../
|
942 |
-
msgid "
|
943 |
msgstr ""
|
944 |
|
945 |
-
#: ../
|
946 |
-
msgid "
|
947 |
msgstr ""
|
948 |
|
949 |
-
#: ../
|
950 |
-
|
|
|
951 |
msgstr ""
|
952 |
|
953 |
-
#: ../
|
954 |
-
msgid "
|
955 |
msgstr ""
|
956 |
|
957 |
-
#: ../
|
958 |
-
msgid "
|
959 |
msgstr ""
|
960 |
|
961 |
-
#: ../
|
962 |
-
msgid "
|
963 |
msgstr ""
|
964 |
|
965 |
-
#: ../
|
966 |
-
msgid "
|
967 |
msgstr ""
|
968 |
|
969 |
-
#: ../
|
970 |
-
msgid "
|
971 |
msgstr ""
|
972 |
|
973 |
-
#: ../
|
974 |
-
msgid "
|
975 |
msgstr ""
|
976 |
|
977 |
-
#: ../
|
978 |
-
msgid "
|
979 |
msgstr ""
|
980 |
|
981 |
-
#: ../
|
982 |
-
msgid "
|
983 |
msgstr ""
|
984 |
|
985 |
-
#: ../
|
986 |
-
msgid "
|
987 |
msgstr ""
|
988 |
|
989 |
-
#: ../
|
990 |
-
msgid "
|
991 |
msgstr ""
|
992 |
|
993 |
-
#: ../
|
994 |
-
msgid "
|
995 |
msgstr ""
|
996 |
|
997 |
-
#: ../
|
998 |
-
msgid "
|
999 |
msgstr ""
|
1000 |
|
1001 |
-
#: ../
|
1002 |
-
msgid "
|
1003 |
msgstr ""
|
1004 |
|
1005 |
-
#: ../
|
1006 |
-
msgid "
|
1007 |
msgstr ""
|
1008 |
|
1009 |
-
#: ../
|
1010 |
-
msgid "
|
1011 |
msgstr ""
|
1012 |
|
1013 |
-
#: ../
|
1014 |
-
msgid "
|
1015 |
msgstr ""
|
1016 |
|
1017 |
-
#: ../
|
1018 |
-
msgid "
|
1019 |
msgstr ""
|
1020 |
|
1021 |
-
#: ../
|
1022 |
-
msgid "
|
1023 |
msgstr ""
|
1024 |
|
1025 |
-
#: ../
|
1026 |
-
msgid "
|
1027 |
msgstr ""
|
1028 |
|
1029 |
-
#: ../
|
1030 |
#, php-format
|
1031 |
-
msgid "%s
|
1032 |
msgstr ""
|
1033 |
|
1034 |
-
#: ../
|
1035 |
-
msgid "
|
|
|
|
|
|
|
|
|
1036 |
msgstr ""
|
1037 |
|
1038 |
-
#: ../
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1039 |
#, php-format
|
1040 |
-
msgid "
|
1041 |
msgstr ""
|
1042 |
|
1043 |
-
#: ../
|
1044 |
-
|
|
|
1045 |
msgstr ""
|
1046 |
|
1047 |
-
#: ../cerber-
|
1048 |
-
msgid "
|
1049 |
msgstr ""
|
1050 |
|
1051 |
-
#: ../cerber-
|
1052 |
-
msgid "
|
1053 |
msgstr ""
|
1054 |
|
1055 |
-
#: ../cerber-
|
1056 |
-
msgid ""
|
1057 |
-
"Allow WP Cerber to send locked out malicious IP addresses to Cerber Lab. "
|
1058 |
-
"This helps the plugin team to develop new algorithms for WP Cerber that will "
|
1059 |
-
"defend WordPress against new threats and botnets that are appearing "
|
1060 |
-
"everyday. You can disable the sending in the plugin settings at any time."
|
1061 |
msgstr ""
|
1062 |
|
1063 |
-
#: ../cerber-
|
1064 |
-
|
|
|
1065 |
msgstr ""
|
1066 |
|
1067 |
-
#: ../cerber-
|
1068 |
-
msgid "
|
1069 |
msgstr ""
|
1070 |
|
1071 |
-
#: ../cerber-
|
1072 |
-
|
|
|
|
|
|
|
|
|
|
|
1073 |
msgstr ""
|
1074 |
|
1075 |
#: ../settings.php:70
|
1076 |
-
msgid "
|
1077 |
msgstr ""
|
1078 |
|
1079 |
#: ../settings.php:71
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1080 |
msgid "Attempts"
|
1081 |
msgstr ""
|
1082 |
|
1083 |
-
#: ../settings.php:
|
1084 |
msgid "Lockout duration"
|
1085 |
msgstr ""
|
1086 |
|
1087 |
-
#: ../settings.php:
|
1088 |
msgid "minutes"
|
1089 |
msgstr ""
|
1090 |
|
1091 |
-
#: ../settings.php:
|
1092 |
msgid "Aggressive lockout"
|
1093 |
msgstr ""
|
1094 |
|
1095 |
-
#: ../settings.php:
|
1096 |
msgid "Apply limit login rules to IP addresses in the White IP Access List"
|
1097 |
msgstr ""
|
1098 |
|
1099 |
-
#: ../settings.php:
|
1100 |
msgid "Site connection"
|
1101 |
msgstr ""
|
1102 |
|
1103 |
-
#: ../settings.php:
|
1104 |
msgid "Proactive security rules"
|
1105 |
msgstr ""
|
1106 |
|
1107 |
-
#: ../settings.php:
|
1108 |
msgid "Block subnet"
|
1109 |
msgstr ""
|
1110 |
|
1111 |
-
#: ../settings.php:
|
1112 |
msgid "Always block entire subnet Class C of intruders IP"
|
1113 |
msgstr ""
|
1114 |
|
1115 |
-
#: ../settings.php:
|
1116 |
msgid "Non-existent users"
|
1117 |
msgstr ""
|
1118 |
|
1119 |
-
#: ../settings.php:
|
1120 |
msgid "Immediately block IP when attempting to login with a non-existent username"
|
1121 |
msgstr ""
|
1122 |
|
1123 |
-
#: ../settings.php:
|
1124 |
msgid "Redirect dashboard requests"
|
1125 |
msgstr ""
|
1126 |
|
1127 |
-
#: ../settings.php:
|
1128 |
msgid ""
|
1129 |
"Disable automatic redirecting to the login page when /wp-admin/ is requested "
|
1130 |
"by an unauthorized request"
|
1131 |
msgstr ""
|
1132 |
|
1133 |
-
#: ../settings.php:
|
1134 |
msgid "Request wp-login.php"
|
1135 |
msgstr ""
|
1136 |
|
1137 |
-
#: ../settings.php:
|
1138 |
msgid "Immediately block IP after any request to wp-login.php"
|
1139 |
msgstr ""
|
1140 |
|
1141 |
-
#: ../settings.php:
|
1142 |
msgid "Display 404 page"
|
1143 |
msgstr ""
|
1144 |
|
1145 |
-
#: ../settings.php:
|
1146 |
msgid "Use 404 template from the active theme"
|
1147 |
msgstr ""
|
1148 |
|
1149 |
-
#: ../settings.php:
|
1150 |
msgid "Display simple 404 page"
|
1151 |
msgstr ""
|
1152 |
|
1153 |
-
#: ../settings.php:
|
1154 |
msgid "Custom login page"
|
1155 |
msgstr ""
|
1156 |
|
1157 |
-
#: ../settings.php:
|
1158 |
msgid "Custom login URL"
|
1159 |
msgstr ""
|
1160 |
|
1161 |
-
#: ../settings.php:
|
1162 |
msgid "must not overlap with the existing pages or posts slug"
|
1163 |
msgstr ""
|
1164 |
|
1165 |
-
#: ../settings.php:
|
1166 |
msgid "Disable wp-login.php"
|
1167 |
msgstr ""
|
1168 |
|
1169 |
-
#: ../settings.php:
|
1170 |
msgid "Block direct access to wp-login.php and return HTTP 404 Not Found Error"
|
1171 |
msgstr ""
|
1172 |
|
1173 |
-
#: ../settings.php:
|
1174 |
msgid "Threshold"
|
1175 |
msgstr ""
|
1176 |
|
1177 |
-
#: ../settings.php:
|
1178 |
msgid "Duration"
|
1179 |
msgstr ""
|
1180 |
|
1181 |
-
#: ../settings.php:
|
1182 |
msgid "Send notification to admin email"
|
1183 |
msgstr ""
|
1184 |
|
1185 |
-
#: ../settings.php:
|
1186 |
msgid "Click to send test"
|
1187 |
msgstr ""
|
1188 |
|
1189 |
-
#: ../settings.php:
|
1190 |
msgid "Keep records for"
|
1191 |
msgstr ""
|
1192 |
|
1193 |
-
#: ../settings.php:
|
1194 |
msgid "days"
|
1195 |
msgstr ""
|
1196 |
|
1197 |
-
#: ../settings.php:
|
1198 |
msgid "Cerber Lab connection"
|
1199 |
msgstr ""
|
1200 |
|
1201 |
-
#: ../settings.php:
|
1202 |
msgid "Send malicious IP addresses to the Cerber Lab"
|
1203 |
msgstr ""
|
1204 |
|
1205 |
-
#: ../settings.php:
|
1206 |
msgid "Cerber Lab protocol"
|
1207 |
msgstr ""
|
1208 |
|
1209 |
-
#: ../settings.php:
|
1210 |
msgid "Use file"
|
1211 |
msgstr ""
|
1212 |
|
1213 |
-
#: ../settings.php:
|
1214 |
msgid "Write failed login attempts to the file"
|
1215 |
msgstr ""
|
1216 |
|
1217 |
-
#: ../settings.php:
|
1218 |
msgid "Preferences"
|
1219 |
msgstr ""
|
1220 |
|
1221 |
-
#: ../settings.php:
|
1222 |
msgid "Drill down IP"
|
1223 |
msgstr ""
|
1224 |
|
1225 |
-
#: ../settings.php:
|
1226 |
msgid "Retrieve extra WHOIS information for IP"
|
1227 |
msgstr ""
|
1228 |
|
1229 |
-
#: ../settings.php:
|
1230 |
msgid "Date format"
|
1231 |
msgstr ""
|
1232 |
|
1233 |
-
#: ../settings.php:
|
1234 |
#, php-format
|
1235 |
msgid "if empty, the default format %s will be used"
|
1236 |
msgstr ""
|
1237 |
|
1238 |
-
#: ../settings.php:
|
1239 |
msgid "Hardening WordPress"
|
1240 |
msgstr ""
|
1241 |
|
1242 |
-
#: ../settings.php:
|
1243 |
msgid "Stop user enumeration"
|
1244 |
msgstr ""
|
1245 |
|
1246 |
-
#: ../settings.php:
|
1247 |
msgid "Block access to user pages like /?author=n and user data via REST API"
|
1248 |
msgstr ""
|
1249 |
|
1250 |
-
#: ../settings.php:
|
1251 |
msgid "Protect admin scripts"
|
1252 |
msgstr ""
|
1253 |
|
1254 |
-
#: ../settings.php:
|
1255 |
msgid "Block unauthorized access to load-scripts.php and load-styles.php"
|
1256 |
msgstr ""
|
1257 |
|
1258 |
-
#: ../settings.php:
|
1259 |
msgid "Disable XML-RPC"
|
1260 |
msgstr ""
|
1261 |
|
1262 |
-
#: ../settings.php:
|
1263 |
msgid "Block access to the XML-RPC server (including Pingbacks and Trackbacks)"
|
1264 |
msgstr ""
|
1265 |
|
1266 |
-
#: ../settings.php:
|
1267 |
msgid "Disable feeds"
|
1268 |
msgstr ""
|
1269 |
|
1270 |
-
#: ../settings.php:
|
1271 |
msgid "Block access to the RSS, Atom and RDF feeds"
|
1272 |
msgstr ""
|
1273 |
|
1274 |
-
#: ../settings.php:
|
1275 |
msgid "Disable REST API"
|
1276 |
msgstr ""
|
1277 |
|
1278 |
-
#: ../settings.php:
|
1279 |
msgid "Block access to the WordPress REST API except the following"
|
1280 |
msgstr ""
|
1281 |
|
1282 |
-
#: ../settings.php:
|
1283 |
msgid "Allow REST API for logged in users"
|
1284 |
msgstr ""
|
1285 |
|
1286 |
-
#: ../settings.php:
|
1287 |
msgid ""
|
1288 |
"Specify REST API namespaces to be allowed if REST API is disabled. One "
|
1289 |
"string per line."
|
1290 |
msgstr ""
|
1291 |
|
1292 |
-
#: ../settings.php:
|
1293 |
msgid "User related settings"
|
1294 |
msgstr ""
|
1295 |
|
1296 |
-
#: ../settings.php:
|
1297 |
msgid "Registration limit"
|
1298 |
msgstr ""
|
1299 |
|
1300 |
-
#: ../settings.php:
|
1301 |
msgid "Prohibited usernames"
|
1302 |
msgstr ""
|
1303 |
|
1304 |
-
#: ../settings.php:
|
1305 |
msgid ""
|
1306 |
"Usernames from this list are not allowed to log in or register. Any IP "
|
1307 |
"address, have tried to use any of these usernames, will be immediately "
|
1308 |
"blocked. Use comma to separate logins."
|
1309 |
msgstr ""
|
1310 |
|
1311 |
-
#: ../settings.php:
|
1312 |
msgid "To specify a REGEX pattern wrap a pattern in two forward slashes."
|
1313 |
msgstr ""
|
1314 |
|
1315 |
-
#: ../settings.php:
|
1316 |
msgid "User session expire"
|
1317 |
msgstr ""
|
1318 |
|
1319 |
-
#: ../settings.php:
|
1320 |
msgid "in minutes (leave empty to use default WP value)"
|
1321 |
msgstr ""
|
1322 |
|
1323 |
-
#: ../settings.php:
|
1324 |
msgid "Sort users in dashboard"
|
1325 |
msgstr ""
|
1326 |
|
1327 |
-
#: ../settings.php:
|
1328 |
msgid "by date of registration"
|
1329 |
msgstr ""
|
1330 |
|
1331 |
-
#: ../settings.php:
|
1332 |
msgid "Cerber antispam engine"
|
1333 |
msgstr ""
|
1334 |
|
1335 |
-
#: ../settings.php:
|
1336 |
msgid "Comment form"
|
1337 |
msgstr ""
|
1338 |
|
1339 |
-
#: ../settings.php:
|
1340 |
msgid "Protect comment form with bot detection engine"
|
1341 |
msgstr ""
|
1342 |
|
1343 |
-
#: ../settings.php:
|
1344 |
msgid "Registration form"
|
1345 |
msgstr ""
|
1346 |
|
1347 |
-
#: ../settings.php:
|
1348 |
msgid "Protect registration form with bot detection engine"
|
1349 |
msgstr ""
|
1350 |
|
1351 |
-
#: ../settings.php:
|
1352 |
msgid "Other forms"
|
1353 |
msgstr ""
|
1354 |
|
1355 |
-
#: ../settings.php:
|
1356 |
msgid "Protect all forms on the website with bot detection engine"
|
1357 |
msgstr ""
|
1358 |
|
1359 |
-
#: ../settings.php:
|
1360 |
msgid "Adjust antispam engine"
|
1361 |
msgstr ""
|
1362 |
|
1363 |
-
#: ../settings.php:
|
1364 |
msgid "Safe mode"
|
1365 |
msgstr ""
|
1366 |
|
1367 |
-
#: ../settings.php:
|
1368 |
msgid "Use less restrictive policies (allow AJAX)"
|
1369 |
msgstr ""
|
1370 |
|
1371 |
-
#: ../settings.php:
|
1372 |
msgid "Disable bot detection engine for logged in users"
|
1373 |
msgstr ""
|
1374 |
|
1375 |
-
#: ../settings.php:
|
1376 |
msgid "Query whitelist"
|
1377 |
msgstr ""
|
1378 |
|
1379 |
-
#: ../settings.php:
|
1380 |
msgid ""
|
1381 |
"Enter a part of query string or query path to exclude a request from "
|
1382 |
"inspection by the engine. One item per line."
|
1383 |
msgstr ""
|
1384 |
|
1385 |
-
#: ../settings.php:
|
1386 |
msgid "Comment processing"
|
1387 |
msgstr ""
|
1388 |
|
1389 |
-
#: ../settings.php:
|
1390 |
msgid "If a spam comment detected"
|
1391 |
msgstr ""
|
1392 |
|
1393 |
-
#: ../settings.php:
|
1394 |
msgid "Deny it completely"
|
1395 |
msgstr ""
|
1396 |
|
1397 |
-
#: ../settings.php:
|
1398 |
msgid "Mark it as spam"
|
1399 |
msgstr ""
|
1400 |
|
1401 |
-
#: ../settings.php:
|
1402 |
msgid "Trash spam comments"
|
1403 |
msgstr ""
|
1404 |
|
1405 |
-
#: ../settings.php:
|
1406 |
msgid "Move spam comments to trash after"
|
1407 |
msgstr ""
|
1408 |
|
1409 |
-
#: ../settings.php:
|
1410 |
msgid "reCAPTCHA settings"
|
1411 |
msgstr ""
|
1412 |
|
1413 |
-
#: ../settings.php:
|
1414 |
msgid "Site key"
|
1415 |
msgstr ""
|
1416 |
|
1417 |
-
#: ../settings.php:
|
1418 |
msgid "Secret key"
|
1419 |
msgstr ""
|
1420 |
|
1421 |
-
#: ../settings.php:
|
1422 |
msgid "Invisible reCAPTCHA"
|
1423 |
msgstr ""
|
1424 |
|
1425 |
-
#: ../settings.php:
|
1426 |
msgid "Enable invisible reCAPTCHA"
|
1427 |
msgstr ""
|
1428 |
|
1429 |
-
#: ../settings.php:
|
1430 |
msgid ""
|
1431 |
"(do not enable it unless you get and enter the Site and Secret keys for the "
|
1432 |
"invisible version)"
|
1433 |
msgstr ""
|
1434 |
|
1435 |
-
#: ../settings.php:
|
1436 |
msgid "Enable reCAPTCHA for WordPress registration form"
|
1437 |
msgstr ""
|
1438 |
|
1439 |
-
#: ../settings.php:
|
1440 |
msgid "Enable reCAPTCHA for WooCommerce registration form"
|
1441 |
msgstr ""
|
1442 |
|
1443 |
-
#: ../settings.php:
|
1444 |
msgid "Lost password form"
|
1445 |
msgstr ""
|
1446 |
|
1447 |
-
#: ../settings.php:
|
1448 |
msgid "Enable reCAPTCHA for WordPress lost password form"
|
1449 |
msgstr ""
|
1450 |
|
1451 |
-
#: ../settings.php:
|
1452 |
msgid "Enable reCAPTCHA for WooCommerce lost password form"
|
1453 |
msgstr ""
|
1454 |
|
1455 |
-
#: ../settings.php:
|
1456 |
msgid "Login form"
|
1457 |
msgstr ""
|
1458 |
|
1459 |
-
#: ../settings.php:
|
1460 |
msgid "Enable reCAPTCHA for WordPress login form"
|
1461 |
msgstr ""
|
1462 |
|
1463 |
-
#: ../settings.php:
|
1464 |
msgid "Enable reCAPTCHA for WooCommerce login form"
|
1465 |
msgstr ""
|
1466 |
|
1467 |
-
#: ../settings.php:
|
1468 |
msgid "Enable reCAPTCHA for WordPress comment form"
|
1469 |
msgstr ""
|
1470 |
|
1471 |
-
#: ../settings.php:
|
1472 |
msgid "Disable reCAPTCHA for logged in users"
|
1473 |
msgstr ""
|
1474 |
|
1475 |
-
#: ../settings.php:
|
1476 |
msgid "Limit attempts"
|
1477 |
msgstr ""
|
1478 |
|
1479 |
-
#: ../settings.php:
|
1480 |
#, php-format
|
1481 |
msgid "Lock out IP address for %s minutes after %s failed attempts within %s minutes"
|
1482 |
msgstr ""
|
1483 |
|
1484 |
-
#: ../settings.php:
|
1485 |
msgid "Email notifications"
|
1486 |
msgstr ""
|
1487 |
|
1488 |
-
#: ../settings.php:
|
1489 |
msgid "Email Address"
|
1490 |
msgstr ""
|
1491 |
|
1492 |
-
#: ../settings.php:
|
1493 |
msgid "Use comma to specify multiple values"
|
1494 |
msgstr ""
|
1495 |
|
1496 |
-
#: ../settings.php:
|
1497 |
#, php-format
|
1498 |
msgid "if empty, the admin email %s will be used"
|
1499 |
msgstr ""
|
1500 |
|
1501 |
-
#: ../settings.php:
|
1502 |
msgid "Notification limit"
|
1503 |
msgstr ""
|
1504 |
|
1505 |
-
#: ../settings.php:
|
1506 |
msgid "notification letters allowed per hour (0 means unlimited)"
|
1507 |
msgstr ""
|
1508 |
|
1509 |
-
#: ../settings.php:
|
1510 |
msgid "Push notifications"
|
1511 |
msgstr ""
|
1512 |
|
1513 |
-
#: ../settings.php:
|
1514 |
msgid "All connected devices"
|
1515 |
msgstr ""
|
1516 |
|
1517 |
-
#: ../settings.php:
|
1518 |
msgid "No devices found"
|
1519 |
msgstr ""
|
1520 |
|
1521 |
-
#: ../settings.php:
|
1522 |
msgid "Not available"
|
1523 |
msgstr ""
|
1524 |
|
1525 |
-
#: ../settings.php:
|
1526 |
msgid "Weekly reports"
|
1527 |
msgstr ""
|
1528 |
|
1529 |
-
#: ../settings.php:
|
1530 |
msgid "Enable reporting"
|
1531 |
msgstr ""
|
1532 |
|
1533 |
-
#: ../settings.php:
|
1534 |
msgid "if empty, email from notification settings will be used"
|
1535 |
msgstr ""
|
1536 |
|
1537 |
-
#: ../settings.php:
|
1538 |
msgid "Inspection"
|
1539 |
msgstr ""
|
1540 |
|
1541 |
-
#: ../settings.php:
|
1542 |
msgid "Enable traffic inspection"
|
1543 |
msgstr ""
|
1544 |
|
1545 |
-
#: ../settings.php:
|
1546 |
msgid "Request whitelist"
|
1547 |
msgstr ""
|
1548 |
|
1549 |
-
#: ../settings.php:
|
1550 |
msgid ""
|
1551 |
"Enter a request URI to exclude the request from inspection. One item per "
|
1552 |
"line."
|
1553 |
msgstr ""
|
1554 |
|
1555 |
-
#: ../settings.php:
|
1556 |
msgid "Logging"
|
1557 |
msgstr ""
|
1558 |
|
1559 |
-
#: ../settings.php:
|
1560 |
msgid "Logging mode"
|
1561 |
msgstr ""
|
1562 |
|
1563 |
-
#: ../settings.php:
|
1564 |
msgid "Logging disabled"
|
1565 |
msgstr ""
|
1566 |
|
1567 |
-
#: ../settings.php:
|
1568 |
msgid "Smart"
|
1569 |
msgstr ""
|
1570 |
|
1571 |
-
#: ../settings.php:
|
1572 |
msgid "All traffic"
|
1573 |
msgstr ""
|
1574 |
|
1575 |
-
#: ../settings.php:
|
1576 |
msgid "Ignore crawlers"
|
1577 |
msgstr ""
|
1578 |
|
1579 |
-
#: ../settings.php:
|
1580 |
msgid "Save request fields"
|
1581 |
msgstr ""
|
1582 |
|
1583 |
-
#: ../settings.php:
|
1584 |
msgid "Mask these form fields"
|
1585 |
msgstr ""
|
1586 |
|
1587 |
-
#: ../settings.php:
|
1588 |
msgid "Save request headers"
|
1589 |
msgstr ""
|
1590 |
|
1591 |
-
#: ../settings.php:
|
1592 |
msgid "Save $_SERVER"
|
1593 |
msgstr ""
|
1594 |
|
1595 |
-
#: ../settings.php:
|
1596 |
msgid "Save request cookies"
|
1597 |
msgstr ""
|
1598 |
|
1599 |
-
#: ../settings.php:
|
1600 |
msgid "Page generation time threshold"
|
1601 |
msgstr ""
|
1602 |
|
1603 |
-
#: ../settings.php:
|
1604 |
msgid "milliseconds"
|
1605 |
msgstr ""
|
1606 |
|
1607 |
-
#: ../settings.php:
|
1608 |
msgid "Make your protection smarter!"
|
1609 |
msgstr ""
|
1610 |
|
1611 |
-
#: ../settings.php:
|
1612 |
msgid ""
|
1613 |
"Please enable Permalinks to use this feature. Set Permalink Settings to "
|
1614 |
"something other than Default."
|
1615 |
msgstr ""
|
1616 |
|
1617 |
-
#: ../settings.php:
|
1618 |
msgid ""
|
1619 |
"Be careful when enabling this options. If you forget the custom login URL "
|
1620 |
"you will not be able to login."
|
1621 |
msgstr ""
|
1622 |
|
1623 |
-
#: ../settings.php:
|
1624 |
msgid ""
|
1625 |
"In the Citadel mode nobody is able to log in except IPs from the White IP "
|
1626 |
"Access List. Active user sessions will not be affected."
|
1627 |
msgstr ""
|
1628 |
|
1629 |
-
#: ../settings.php:
|
1630 |
msgid "These settings do not affect hosts from the "
|
1631 |
msgstr ""
|
1632 |
|
1633 |
-
#: ../settings.php:
|
1634 |
msgid ""
|
1635 |
"Before you can start using reCAPTCHA, you have to obtain Site key and Secret "
|
1636 |
"key on the Google website"
|
1637 |
msgstr ""
|
1638 |
|
1639 |
-
#: ../settings.php:
|
1640 |
msgid "Lockouts"
|
1641 |
msgstr ""
|
1642 |
|
1643 |
-
#: ../settings.php:
|
1644 |
msgid "Users"
|
1645 |
msgstr ""
|
1646 |
|
1647 |
-
#: ../settings.php:
|
1648 |
msgid "Help"
|
1649 |
msgstr ""
|
1650 |
|
1651 |
-
#: ../settings.php:
|
1652 |
#, php-format
|
1653 |
msgid "%s allowed retries in %s minutes"
|
1654 |
msgstr ""
|
1655 |
|
1656 |
-
#: ../settings.php:
|
1657 |
#, php-format
|
1658 |
msgid "%s allowed registrations in %s minutes from one IP"
|
1659 |
msgstr ""
|
1660 |
|
1661 |
-
#: ../settings.php:
|
1662 |
#, php-format
|
1663 |
msgid "Increase lockout duration to %s hours after %s lockouts in the last %s hours"
|
1664 |
msgstr ""
|
1665 |
|
1666 |
-
#: ../settings.php:
|
1667 |
msgid "Notify admin if the number of active lockouts above"
|
1668 |
msgstr ""
|
1669 |
|
1670 |
-
#: ../settings.php:
|
1671 |
#, php-format
|
1672 |
msgid "Enable after %s failed login attempts in last %s minutes"
|
1673 |
msgstr ""
|
1674 |
|
1675 |
-
#: ../settings.php:
|
1676 |
msgid "Sunday"
|
1677 |
msgstr ""
|
1678 |
|
1679 |
-
#: ../settings.php:
|
1680 |
msgid "Monday"
|
1681 |
msgstr ""
|
1682 |
|
1683 |
-
#: ../settings.php:
|
1684 |
msgid "Tuesday"
|
1685 |
msgstr ""
|
1686 |
|
1687 |
-
#: ../settings.php:
|
1688 |
msgid "Wednesday"
|
1689 |
msgstr ""
|
1690 |
|
1691 |
-
#: ../settings.php:
|
1692 |
msgid "Thursday"
|
1693 |
msgstr ""
|
1694 |
|
1695 |
-
#: ../settings.php:
|
1696 |
msgid "Friday"
|
1697 |
msgstr ""
|
1698 |
|
1699 |
-
#: ../settings.php:
|
1700 |
msgid "Saturday"
|
1701 |
msgstr ""
|
1702 |
|
1703 |
#. translators: preposition of time
|
1704 |
-
#: ../settings.php:
|
1705 |
msgctxt "preposition of time"
|
1706 |
msgid "at"
|
1707 |
msgstr ""
|
1708 |
|
1709 |
-
#: ../settings.php:
|
1710 |
msgid "Click to send now"
|
1711 |
msgstr ""
|
1712 |
|
1713 |
-
#: ../settings.php:
|
|
|
|
|
|
|
|
|
1714 |
msgid "Attention! You have changed the login URL! The new login URL is"
|
1715 |
msgstr ""
|
1716 |
|
1717 |
-
#: ../settings.php:
|
1718 |
msgid ""
|
1719 |
"If you use a caching plugin, you have to add your new login URL to the list "
|
1720 |
"of pages not to cache."
|
1721 |
msgstr ""
|
1722 |
|
1723 |
-
#: ../settings.php:
|
1724 |
msgid "<strong>ERROR</strong>: please enter a valid email address."
|
1725 |
msgstr ""
|
1726 |
|
@@ -1797,6 +1847,17 @@ msgstr ""
|
|
1797 |
msgid "Error while parsing file"
|
1798 |
msgstr ""
|
1799 |
|
1800 |
-
#: ../cerber-tools.php:
|
1801 |
msgid "Antispam and bot detection settings"
|
1802 |
msgstr ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
"Project-Id-Version: WP Cerber\n"
|
6 |
"Report-Msgid-Bugs-To: \n"
|
7 |
"POT-Creation-Date: Tue Sep 08 2015 21:38:11 GMT+0300\n"
|
8 |
+
"POT-Revision-Date: Sat Mar 17 2018 10:50:53 GMT+0300\n"
|
9 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
10 |
"Last-Translator: \n"
|
11 |
"Language-Team: \n"
|
28 |
msgid "Remove"
|
29 |
msgstr ""
|
30 |
|
31 |
+
#: ../dashboard.php:93 ../dashboard.php:659 ../dashboard.php:2833 ../cerber-load.
|
32 |
+
#: php:3746
|
33 |
msgid "IP"
|
34 |
msgstr ""
|
35 |
|
36 |
+
#: ../dashboard.php:94 ../dashboard.php:660
|
37 |
msgid "Hostname"
|
38 |
msgstr ""
|
39 |
|
40 |
+
#: ../dashboard.php:95 ../dashboard.php:661
|
41 |
msgid "Country"
|
42 |
msgstr ""
|
43 |
|
45 |
msgid "Expires"
|
46 |
msgstr ""
|
47 |
|
48 |
+
#: ../dashboard.php:97 ../cerber-load.php:3253
|
49 |
msgid "Reason"
|
50 |
msgstr ""
|
51 |
|
70 |
msgid "No lockouts at the moment. The sky is clear."
|
71 |
msgstr ""
|
72 |
|
73 |
+
#: ../dashboard.php:131 ../dashboard.php:634 ../dashboard.php:837 ../dashboard.
|
74 |
+
#: php:1214 ../dashboard.php:2664 ../cerber-load.php:3969 ../settings.php:77 ..
|
75 |
+
#: /settings.php:358
|
76 |
msgid "White IP Access List"
|
77 |
msgstr ""
|
78 |
|
80 |
msgid "These IPs will never be locked out"
|
81 |
msgstr ""
|
82 |
|
83 |
+
#: ../dashboard.php:133 ../dashboard.php:635 ../dashboard.php:840 ../dashboard.
|
84 |
+
#: php:1215 ../dashboard.php:2665
|
85 |
msgid "Black IP Access List"
|
86 |
msgstr ""
|
87 |
|
93 |
msgid "Your IP"
|
94 |
msgstr ""
|
95 |
|
96 |
+
#: ../dashboard.php:158 ../dashboard.php:850 ../dashboard.php:877 ../dashboard.
|
97 |
+
#: php:969
|
98 |
msgid "Check for activity"
|
99 |
msgstr ""
|
100 |
|
132 |
msgid "Address %s was added to Black IP Access List"
|
133 |
msgstr ""
|
134 |
|
135 |
+
#: ../dashboard.php:313 ../dashboard.php:2594 ../whois.php:221 ../whois.php:252 ..
|
136 |
+
#: /common.php:818 ../common.php:1097
|
137 |
msgid "Unknown"
|
138 |
msgstr ""
|
139 |
|
149 |
msgid "Unable to send email to"
|
150 |
msgstr ""
|
151 |
|
152 |
+
#: ../dashboard.php:389
|
153 |
#, php-format
|
154 |
msgid "Lockout for %s was removed"
|
155 |
msgstr ""
|
156 |
|
157 |
+
#: ../dashboard.php:405 ../dashboard.php:1614
|
158 |
msgid "Settings saved"
|
159 |
msgstr ""
|
160 |
|
161 |
+
#: ../dashboard.php:498
|
162 |
msgid "IP address"
|
163 |
msgstr ""
|
164 |
|
165 |
+
#: ../dashboard.php:498 ../dashboard.php:662 ../dashboard.php:2831
|
166 |
msgid "Date"
|
167 |
msgstr ""
|
168 |
|
169 |
+
#: ../dashboard.php:498 ../dashboard.php:663
|
170 |
msgid "Event"
|
171 |
msgstr ""
|
172 |
|
173 |
+
#: ../dashboard.php:498 ../dashboard.php:664 ../dashboard.php:2836
|
174 |
msgid "Local User"
|
175 |
msgstr ""
|
176 |
|
177 |
+
#: ../dashboard.php:498
|
178 |
msgid "User login"
|
179 |
msgstr ""
|
180 |
|
181 |
+
#: ../dashboard.php:498
|
182 |
msgid "User ID"
|
183 |
msgstr ""
|
184 |
|
185 |
+
#: ../dashboard.php:498 ../dashboard.php:665 ../cerber-load.php:3754
|
186 |
msgid "Username used"
|
187 |
msgstr ""
|
188 |
|
189 |
+
#: ../dashboard.php:639 ../dashboard.php:843 ../dashboard.php:2669 ../common.php:
|
190 |
+
#: 789
|
191 |
msgid "Locked out"
|
192 |
msgstr ""
|
193 |
|
194 |
+
#: ../dashboard.php:683
|
195 |
msgid "Export"
|
196 |
msgstr ""
|
197 |
|
198 |
+
#: ../dashboard.php:687
|
199 |
msgid "No activity has been logged."
|
200 |
msgstr ""
|
201 |
|
202 |
+
#: ../dashboard.php:693
|
203 |
msgid "All events"
|
204 |
msgstr ""
|
205 |
|
206 |
+
#: ../dashboard.php:702
|
207 |
msgid "Search for IP or username"
|
208 |
msgstr ""
|
209 |
|
210 |
+
#: ../dashboard.php:702
|
211 |
msgid "Filter"
|
212 |
msgstr ""
|
213 |
|
214 |
+
#: ../dashboard.php:873
|
215 |
msgid "Abuse email:"
|
216 |
msgstr ""
|
217 |
|
218 |
+
#: ../dashboard.php:877
|
219 |
msgid "Network:"
|
220 |
msgstr ""
|
221 |
|
222 |
+
#: ../dashboard.php:891
|
223 |
msgid "Add network to the Black List"
|
224 |
msgstr ""
|
225 |
|
226 |
+
#: ../dashboard.php:896
|
227 |
msgid "Add IP to the Black List"
|
228 |
msgstr ""
|
229 |
|
230 |
+
#: ../dashboard.php:956
|
231 |
msgid "Last seen"
|
232 |
msgstr ""
|
233 |
|
234 |
+
#: ../dashboard.php:963 ../dashboard.php:1082
|
235 |
msgid "Registered"
|
236 |
msgstr ""
|
237 |
|
238 |
+
#: ../dashboard.php:996 ../settings.php:381
|
239 |
msgid "WP Cerber Security"
|
240 |
msgstr ""
|
241 |
|
242 |
#. Name of the plugin
|
243 |
+
#: ../dashboard.php:996 ../dashboard.php:1018
|
244 |
msgid "WP Cerber"
|
245 |
msgstr ""
|
246 |
|
247 |
+
#: ../dashboard.php:998
|
248 |
msgid "Cerber Dashboard"
|
249 |
msgstr ""
|
250 |
|
251 |
+
#: ../dashboard.php:998 ../dashboard.php:1233 ../dashboard.php:1790 ../settings.
|
252 |
+
#: php:386
|
253 |
msgid "Dashboard"
|
254 |
msgstr ""
|
255 |
|
256 |
+
#: ../dashboard.php:1000
|
257 |
msgid "Cerber Traffic Inspector"
|
258 |
msgstr ""
|
259 |
|
260 |
+
#: ../dashboard.php:1000 ../dashboard.php:1219 ../dashboard.php:2515
|
261 |
msgid "Traffic Inspector"
|
262 |
msgstr ""
|
263 |
|
264 |
+
#: ../dashboard.php:1004
|
265 |
msgid "Cerber Security Rules"
|
266 |
msgstr ""
|
267 |
|
268 |
+
#: ../dashboard.php:1004 ../dashboard.php:2175
|
269 |
msgid "Security Rules"
|
270 |
msgstr ""
|
271 |
|
272 |
+
#: ../dashboard.php:1007
|
273 |
msgid "Cerber antispam settings"
|
274 |
msgstr ""
|
275 |
|
276 |
+
#: ../dashboard.php:1007 ../dashboard.php:1236 ../cerber-load.php:3978 ..
|
277 |
+
#: /settings.php:189
|
278 |
msgid "Antispam"
|
279 |
msgstr ""
|
280 |
|
281 |
+
#: ../dashboard.php:1008
|
282 |
msgid "Cerber tools"
|
283 |
msgstr ""
|
284 |
|
285 |
+
#: ../dashboard.php:1008 ../cerber-tools.php:43
|
286 |
msgid "Tools"
|
287 |
msgstr ""
|
288 |
|
289 |
+
#: ../dashboard.php:1079
|
290 |
msgid "Comments"
|
291 |
msgstr ""
|
292 |
|
293 |
+
#: ../dashboard.php:1080
|
294 |
msgid "Last login"
|
295 |
msgstr ""
|
296 |
|
297 |
+
#: ../dashboard.php:1081
|
298 |
msgid "Failed login attempts"
|
299 |
msgstr ""
|
300 |
|
301 |
+
#: ../dashboard.php:1113 ../dashboard.php:1197
|
302 |
msgid "Never"
|
303 |
msgstr ""
|
304 |
|
305 |
+
#: ../dashboard.php:1149
|
306 |
msgid "You"
|
307 |
msgstr ""
|
308 |
|
309 |
+
#: ../dashboard.php:1167
|
310 |
msgid "Cerber Quick View"
|
311 |
msgstr ""
|
312 |
|
313 |
+
#: ../dashboard.php:1201 ../dashboard.php:1222
|
314 |
msgid "active"
|
315 |
msgstr ""
|
316 |
|
317 |
+
#: ../dashboard.php:1201
|
318 |
msgid "deactivate"
|
319 |
msgstr ""
|
320 |
|
321 |
+
#: ../dashboard.php:1203
|
322 |
msgid "not active"
|
323 |
msgstr ""
|
324 |
|
325 |
+
#: ../dashboard.php:1204 ../dashboard.php:1218
|
326 |
msgid "disabled"
|
327 |
msgstr ""
|
328 |
|
329 |
+
#: ../dashboard.php:1209
|
330 |
msgid "failed attempts"
|
331 |
msgstr ""
|
332 |
|
333 |
+
#: ../dashboard.php:1209 ../dashboard.php:1210
|
334 |
msgid "in 24 hours"
|
335 |
msgstr ""
|
336 |
|
337 |
+
#: ../dashboard.php:1209 ../dashboard.php:1210
|
338 |
msgid "view all"
|
339 |
msgstr ""
|
340 |
|
341 |
+
#: ../dashboard.php:1210
|
342 |
msgid "lockouts"
|
343 |
msgstr ""
|
344 |
|
345 |
+
#: ../dashboard.php:1212
|
346 |
msgid "Lockouts at the moment"
|
347 |
msgstr ""
|
348 |
|
349 |
+
#: ../dashboard.php:1213
|
350 |
msgid "Last lockout"
|
351 |
msgstr ""
|
352 |
|
353 |
+
#: ../dashboard.php:1214 ../dashboard.php:1215 ../dashboard.php:1770
|
354 |
msgid "entry"
|
355 |
msgid_plural "entries"
|
356 |
msgstr[0] ""
|
357 |
msgstr[1] ""
|
358 |
|
359 |
+
#: ../dashboard.php:1216 ../settings.php:92
|
360 |
msgid "Citadel mode"
|
361 |
msgstr ""
|
362 |
|
363 |
+
#: ../dashboard.php:1218
|
364 |
msgid "enabled"
|
365 |
msgstr ""
|
366 |
|
367 |
+
#: ../dashboard.php:1222
|
368 |
msgid "no connection"
|
369 |
msgstr ""
|
370 |
|
371 |
+
#: ../dashboard.php:1234 ../dashboard.php:1444 ../cerber-load.php:3737 ..
|
372 |
+
#: /settings.php:97 ../settings.php:388
|
373 |
msgid "Activity"
|
374 |
msgstr ""
|
375 |
|
376 |
+
#: ../dashboard.php:1235
|
377 |
msgid "Traffic"
|
378 |
msgstr ""
|
379 |
|
380 |
+
#: ../dashboard.php:1291 ../settings.php:79
|
381 |
msgid "My site is behind a reverse proxy"
|
382 |
msgstr ""
|
383 |
|
384 |
+
#: ../dashboard.php:1423
|
385 |
msgid "in the last 24 hours"
|
386 |
msgstr ""
|
387 |
|
388 |
+
#: ../dashboard.php:1429 ../dashboard.php:1459
|
389 |
msgid "View all"
|
390 |
msgstr ""
|
391 |
|
392 |
+
#: ../dashboard.php:1437 ../common.php:741
|
393 |
msgid "User registered"
|
394 |
msgstr ""
|
395 |
|
396 |
+
#: ../dashboard.php:1438
|
397 |
msgid "All suspicious activity"
|
398 |
msgstr ""
|
399 |
|
400 |
+
#: ../dashboard.php:1460
|
401 |
msgid "Recently locked out IP addresses"
|
402 |
msgstr ""
|
403 |
|
404 |
+
#: ../dashboard.php:1485
|
405 |
msgid "Confused about some settings?"
|
406 |
msgstr ""
|
407 |
|
408 |
+
#: ../dashboard.php:1486
|
409 |
msgid "You can easily load default recommended settings using button below"
|
410 |
msgstr ""
|
411 |
|
412 |
+
#: ../dashboard.php:1488
|
413 |
msgid "Load default settings"
|
414 |
msgstr ""
|
415 |
|
416 |
+
#: ../dashboard.php:1490
|
417 |
msgid "Are you sure?"
|
418 |
msgstr ""
|
419 |
|
420 |
+
#: ../dashboard.php:1496
|
421 |
msgid "doesn't affect Custom login URL and Access Lists"
|
422 |
msgstr ""
|
423 |
|
424 |
+
#: ../dashboard.php:1497 ../cerber-load.php:3285 ../cerber-load.php:3971
|
425 |
msgid "Getting Started Guide"
|
426 |
msgstr ""
|
427 |
|
428 |
+
#: ../dashboard.php:1597
|
429 |
msgid "Attention! Citadel mode is now active. Nobody is able to log in."
|
430 |
msgstr ""
|
431 |
|
432 |
+
#: ../dashboard.php:1598
|
433 |
msgid "Deactivate"
|
434 |
msgstr ""
|
435 |
|
436 |
+
#: ../dashboard.php:1599
|
437 |
msgid "View Activity"
|
438 |
msgstr ""
|
439 |
|
440 |
+
#: ../dashboard.php:1700
|
441 |
msgid "Subscribe"
|
442 |
msgstr ""
|
443 |
|
444 |
+
#: ../dashboard.php:1701 ../cerber-tools.php:269
|
445 |
msgid "Unsubscribe"
|
446 |
msgstr ""
|
447 |
|
448 |
+
#: ../dashboard.php:1729
|
449 |
msgid "You've subscribed"
|
450 |
msgstr ""
|
451 |
|
452 |
+
#: ../dashboard.php:1732
|
453 |
msgid "You've unsubscribed"
|
454 |
msgstr ""
|
455 |
|
456 |
+
#: ../dashboard.php:1791
|
457 |
msgid "Main settings"
|
458 |
msgstr ""
|
459 |
|
460 |
+
#: ../dashboard.php:2180
|
461 |
msgid "Countries"
|
462 |
msgstr ""
|
463 |
|
464 |
+
#: ../dashboard.php:2243
|
465 |
#, php-format
|
466 |
msgid "Permitted for one country"
|
467 |
msgid_plural "Permitted for %d countries"
|
468 |
msgstr[0] ""
|
469 |
msgstr[1] ""
|
470 |
|
471 |
+
#: ../dashboard.php:2246
|
472 |
#, php-format
|
473 |
msgid "Not permitted for one country"
|
474 |
msgid_plural "Not permitted for %d countries"
|
475 |
msgstr[0] ""
|
476 |
msgstr[1] ""
|
477 |
|
478 |
+
#: ../dashboard.php:2254
|
479 |
msgid "No rule"
|
480 |
msgstr ""
|
481 |
|
482 |
+
#: ../dashboard.php:2310
|
483 |
msgid "Start typing here to find a country"
|
484 |
msgstr ""
|
485 |
|
486 |
+
#: ../dashboard.php:2393
|
487 |
msgid "Click on a country name to add it to the list of selected countries"
|
488 |
msgstr ""
|
489 |
|
490 |
+
#: ../dashboard.php:2397
|
491 |
#, php-format
|
492 |
msgctxt "to is a marker of infinitive, e.g. \"to use it\""
|
493 |
msgid "Selected countries are permitted to %s, other countries are not permitted to"
|
494 |
msgstr ""
|
495 |
|
496 |
+
#: ../dashboard.php:2400
|
497 |
#, php-format
|
498 |
msgctxt "to is a marker of infinitive, e.g. \"to use it\""
|
499 |
msgid "Selected countries are not permitted to %s, other countries are permitted to"
|
500 |
msgstr ""
|
501 |
|
502 |
+
#: ../dashboard.php:2417
|
503 |
msgid "Submit forms"
|
504 |
msgstr ""
|
505 |
|
506 |
+
#: ../dashboard.php:2418
|
507 |
msgid "Post comments"
|
508 |
msgstr ""
|
509 |
|
510 |
+
#: ../dashboard.php:2419
|
511 |
msgid "Log in to the website"
|
512 |
msgstr ""
|
513 |
|
514 |
+
#: ../dashboard.php:2420
|
515 |
msgid "Register on the website"
|
516 |
msgstr ""
|
517 |
|
518 |
+
#: ../dashboard.php:2421
|
519 |
msgid "Use XML-RPC"
|
520 |
msgstr ""
|
521 |
|
522 |
+
#: ../dashboard.php:2422
|
523 |
msgid "Use REST API"
|
524 |
msgstr ""
|
525 |
|
526 |
+
#: ../dashboard.php:2466
|
527 |
msgid "Security rules have been updated"
|
528 |
msgstr ""
|
529 |
|
530 |
+
#: ../dashboard.php:2520
|
531 |
msgid "Live traffic"
|
532 |
msgstr ""
|
533 |
|
534 |
+
#: ../dashboard.php:2521 ../cerber-tools.php:87 ../cerber-tools.php:96
|
535 |
msgid "Settings"
|
536 |
msgstr ""
|
537 |
|
538 |
+
#: ../dashboard.php:2832
|
539 |
msgid "Request"
|
540 |
msgstr ""
|
541 |
|
542 |
+
#: ../dashboard.php:2834
|
543 |
msgid "Host Info"
|
544 |
msgstr ""
|
545 |
|
546 |
+
#: ../dashboard.php:2835
|
547 |
msgid "User Agent"
|
548 |
msgstr ""
|
549 |
|
550 |
+
#: ../dashboard.php:2852
|
551 |
msgid "No requests have been logged."
|
552 |
msgstr ""
|
553 |
|
554 |
+
#: ../dashboard.php:2860
|
555 |
msgid "All requests"
|
556 |
msgstr ""
|
557 |
|
558 |
+
#: ../dashboard.php:2861 ../settings.php:160
|
559 |
msgid "Logged in users"
|
560 |
msgstr ""
|
561 |
|
562 |
+
#: ../dashboard.php:2862
|
563 |
msgid "Not logged in visitors"
|
564 |
msgstr ""
|
565 |
|
566 |
+
#: ../dashboard.php:2863
|
567 |
msgid "Form submissions"
|
568 |
msgstr ""
|
569 |
|
570 |
+
#: ../dashboard.php:2864
|
571 |
msgid "Page Not Found"
|
572 |
msgstr ""
|
573 |
|
574 |
+
#: ../dashboard.php:2865
|
575 |
msgid "REST API"
|
576 |
msgstr ""
|
577 |
|
578 |
+
#: ../dashboard.php:2866
|
579 |
msgid "XML-RPC"
|
580 |
msgstr ""
|
581 |
|
582 |
+
#: ../dashboard.php:2870
|
583 |
msgid "Longer than"
|
584 |
msgstr ""
|
585 |
|
586 |
+
#: ../dashboard.php:2883
|
587 |
msgid "Refresh"
|
588 |
msgstr ""
|
589 |
|
590 |
+
#: ../dashboard.php:3104
|
591 |
msgid "Any"
|
592 |
msgstr ""
|
593 |
|
594 |
+
#: ../dashboard.php:3144
|
595 |
msgid "Advanced search"
|
596 |
msgstr ""
|
597 |
|
615 |
msgid "Gregory"
|
616 |
msgstr ""
|
617 |
|
618 |
+
#: ../common.php:101
|
619 |
+
msgid "Check for requests"
|
620 |
msgstr ""
|
621 |
|
622 |
+
#: ../common.php:134
|
623 |
+
msgid "Malicious activities mitigated"
|
|
|
624 |
msgstr ""
|
625 |
|
626 |
+
#: ../common.php:137
|
627 |
+
msgid "Spam comments denied"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
628 |
msgstr ""
|
629 |
|
630 |
+
#: ../common.php:138
|
631 |
+
msgid "Spam form submissions denied"
|
|
|
|
|
632 |
msgstr ""
|
633 |
|
634 |
+
#: ../common.php:139
|
635 |
+
msgid "Malicious IP addresses detected"
|
|
|
|
|
636 |
msgstr ""
|
637 |
|
638 |
+
#: ../common.php:140
|
639 |
+
msgid "Lockouts occurred"
|
|
|
|
|
|
|
640 |
msgstr ""
|
641 |
|
642 |
+
#: ../common.php:194 ../common.php:251 ../common.php:256 ../common.php:261 ..
|
643 |
+
#: /cerber-load.php:659 ../cerber-load.php:671 ../cerber-load.php:678 ../cerber-
|
644 |
+
#: load.php:906 ../cerber-load.php:1122 ../cerber-load.php:1128 ../cerber-load.
|
645 |
+
#: php:1133 ../cerber-load.php:1138 ../cerber-load.php:1144 ../cerber-load.php:
|
646 |
+
#: 1151 ../cerber-load.php:1251 ../cerber-load.php:1388 ../settings.php:780 ..
|
647 |
+
#: /settings.php:851
|
648 |
+
msgid "ERROR:"
|
649 |
msgstr ""
|
650 |
|
651 |
+
#: ../common.php:740
|
652 |
+
msgid "User created"
|
653 |
msgstr ""
|
654 |
|
655 |
+
#: ../common.php:742
|
656 |
+
msgid "Logged in"
|
657 |
msgstr ""
|
658 |
|
659 |
+
#: ../common.php:743
|
660 |
+
msgid "Logged out"
|
661 |
msgstr ""
|
662 |
|
663 |
+
#: ../common.php:744
|
664 |
+
msgid "Login failed"
|
665 |
msgstr ""
|
666 |
|
667 |
+
#: ../common.php:747
|
668 |
+
msgid "IP blocked"
|
669 |
msgstr ""
|
670 |
|
671 |
+
#: ../common.php:748
|
672 |
+
msgid "Subnet blocked"
|
|
|
673 |
msgstr ""
|
674 |
|
675 |
+
#: ../common.php:750
|
676 |
+
msgid "Citadel activated!"
|
|
|
677 |
msgstr ""
|
678 |
|
679 |
+
#: ../common.php:751
|
680 |
+
msgid "Spam comment denied"
|
681 |
msgstr ""
|
682 |
|
683 |
+
#: ../common.php:752
|
684 |
+
msgid "Spam form submission denied"
|
685 |
msgstr ""
|
686 |
|
687 |
+
#: ../common.php:753
|
688 |
+
msgid "Form submission denied"
|
689 |
msgstr ""
|
690 |
|
691 |
+
#: ../common.php:754
|
692 |
+
msgid "Comment denied"
|
693 |
msgstr ""
|
694 |
|
695 |
+
#: ../common.php:765
|
696 |
+
msgid "Password changed"
|
|
|
697 |
msgstr ""
|
698 |
|
699 |
+
#: ../common.php:766
|
700 |
+
msgid "Password reset requested"
|
701 |
msgstr ""
|
702 |
|
703 |
+
#: ../common.php:768
|
704 |
+
msgid "reCAPTCHA verification failed"
|
705 |
msgstr ""
|
706 |
|
707 |
+
#: ../common.php:769
|
708 |
+
msgid "reCAPTCHA settings are incorrect"
|
709 |
msgstr ""
|
710 |
|
711 |
+
#: ../common.php:770
|
712 |
+
msgid "Request to the Google reCAPTCHA service failed"
|
713 |
msgstr ""
|
714 |
|
715 |
+
#: ../common.php:772
|
716 |
+
msgid "Attempt to access prohibited URL"
|
717 |
msgstr ""
|
718 |
|
719 |
+
#: ../common.php:773 ../common.php:821
|
720 |
+
msgid "Attempt to log in with non-existent username"
|
721 |
msgstr ""
|
722 |
|
723 |
+
#: ../common.php:774 ../common.php:822
|
724 |
+
msgid "Attempt to log in with prohibited username"
|
725 |
msgstr ""
|
726 |
|
727 |
+
#: ../common.php:776
|
728 |
+
msgid "Attempt to log in denied"
|
729 |
msgstr ""
|
730 |
|
731 |
+
#: ../common.php:777
|
732 |
+
msgid "Attempt to register denied"
|
733 |
msgstr ""
|
734 |
|
735 |
+
#: ../common.php:778 ../common.php:826
|
736 |
+
msgid "Probing for vulnerable PHP code"
|
737 |
msgstr ""
|
738 |
|
739 |
+
#: ../common.php:779
|
740 |
+
msgid "Attempt to upload executable file denied"
|
741 |
msgstr ""
|
742 |
|
743 |
+
#: ../common.php:780
|
744 |
+
msgid "File upload denied"
|
745 |
msgstr ""
|
746 |
|
747 |
+
#: ../common.php:782
|
748 |
+
msgid "Request to REST API denied"
|
749 |
msgstr ""
|
750 |
|
751 |
+
#: ../common.php:783
|
752 |
+
msgid "XML-RPC request denied"
|
753 |
msgstr ""
|
754 |
|
755 |
+
#: ../common.php:787
|
756 |
+
msgid "Bot detected"
|
757 |
msgstr ""
|
758 |
|
759 |
+
#: ../common.php:788
|
760 |
+
msgid "Citadel mode is active"
|
761 |
msgstr ""
|
762 |
|
763 |
+
#: ../common.php:790
|
764 |
+
msgid "IP blacklisted"
|
765 |
msgstr ""
|
766 |
|
767 |
+
#: ../common.php:793
|
768 |
+
msgid "Malicious activity detected"
|
769 |
msgstr ""
|
770 |
|
771 |
+
#: ../common.php:794
|
772 |
+
msgid "Blocked by country rule"
|
773 |
msgstr ""
|
774 |
|
775 |
+
#: ../common.php:795
|
776 |
+
msgid "Limit reached"
|
|
|
777 |
msgstr ""
|
778 |
|
779 |
+
#: ../common.php:796
|
780 |
+
msgid "Multiple suspicious activities"
|
781 |
msgstr ""
|
782 |
|
783 |
+
#: ../common.php:819
|
784 |
+
msgid "Limit on login attempts is reached"
|
785 |
msgstr ""
|
786 |
|
787 |
+
#: ../common.php:820
|
788 |
+
msgid "Attempt to access"
|
789 |
msgstr ""
|
790 |
|
791 |
+
#: ../common.php:823
|
792 |
+
msgid "Limit on failed reCAPTCHA verifications is reached"
|
793 |
msgstr ""
|
794 |
|
795 |
+
#: ../common.php:824
|
796 |
+
msgid "Bot activity is detected"
|
797 |
msgstr ""
|
798 |
|
799 |
+
#: ../common.php:825
|
800 |
+
msgid "Multiple suspicious activities were detected"
|
801 |
msgstr ""
|
802 |
|
803 |
+
#: ../common.php:881
|
804 |
#, php-format
|
805 |
+
msgid "%s ago"
|
806 |
msgstr ""
|
807 |
|
808 |
+
#: ../common.php:1015 ../settings.php:214
|
809 |
+
msgid "New version is available"
|
810 |
+
msgstr ""
|
811 |
+
|
812 |
+
#: ../common.php:1022
|
813 |
#, php-format
|
814 |
+
msgid "Update to version %s of WP Cerber"
|
815 |
msgstr ""
|
816 |
|
817 |
+
#: ../common.php:1041
|
818 |
+
msgid "Not specified"
|
819 |
msgstr ""
|
820 |
|
821 |
+
#: ../common.php:1418
|
822 |
+
msgid "Unable to create the directory"
|
823 |
msgstr ""
|
824 |
|
825 |
+
#: ../common.php:1423
|
826 |
+
msgid "Destination folder access denied"
|
827 |
msgstr ""
|
828 |
|
829 |
+
#: ../common.php:1426
|
830 |
+
msgid "File not found"
|
|
|
831 |
msgstr ""
|
832 |
|
833 |
+
#: ../common.php:1429
|
834 |
+
msgid "Unable to copy the file"
|
835 |
msgstr ""
|
836 |
|
837 |
+
#: ../common.php:1435
|
838 |
+
msgid "Unable to delete the file"
|
839 |
msgstr ""
|
840 |
|
841 |
+
#: ../cerber-news.php:159
|
842 |
+
msgid "Cool!"
|
843 |
msgstr ""
|
844 |
|
845 |
+
#: ../cerber-lab.php:705
|
846 |
+
msgid "Want to make WP Cerber even more powerful?"
|
847 |
msgstr ""
|
848 |
|
849 |
+
#: ../cerber-lab.php:706
|
850 |
+
msgid ""
|
851 |
+
"Allow WP Cerber to send locked out malicious IP addresses to Cerber Lab. "
|
852 |
+
"This helps the plugin team to develop new algorithms for WP Cerber that will "
|
853 |
+
"defend WordPress against new threats and botnets that are appearing "
|
854 |
+
"everyday. You can disable the sending in the plugin settings at any time."
|
855 |
msgstr ""
|
856 |
|
857 |
+
#: ../cerber-lab.php:707
|
858 |
+
msgid "OK, nail them all"
|
859 |
msgstr ""
|
860 |
|
861 |
+
#: ../cerber-lab.php:708
|
862 |
+
msgid "NO, maybe later"
|
863 |
msgstr ""
|
864 |
|
865 |
+
#: ../cerber-lab.php:709 ../settings.php:362
|
866 |
+
msgid "Know more"
|
867 |
msgstr ""
|
868 |
|
869 |
+
#: ../cerber-load.php:351
|
870 |
+
msgid "You are not allowed to log in. Ask your administrator for assistance."
|
871 |
msgstr ""
|
872 |
|
873 |
+
#: ../cerber-load.php:357
|
874 |
+
#, php-format
|
875 |
+
msgid "You have reached the login attempts limit. Please try again in %d minutes."
|
876 |
msgstr ""
|
877 |
|
878 |
+
#: ../cerber-load.php:376
|
879 |
+
#, php-format
|
880 |
+
msgid "You have only one attempt remaining."
|
881 |
+
msgid_plural "You have %d attempts remaining."
|
882 |
+
msgstr[0] ""
|
883 |
+
msgstr[1] ""
|
884 |
+
|
885 |
+
#: ../cerber-load.php:688
|
886 |
+
msgid ""
|
887 |
+
"Human verification failed. Please click the square box in the reCAPTCHA "
|
888 |
+
"block below."
|
889 |
msgstr ""
|
890 |
|
891 |
+
#: ../cerber-load.php:785
|
892 |
+
msgid ""
|
893 |
+
"> > > Translator of WP Cerber? To get the PRO license for free, drop your "
|
894 |
+
"contacts here: https://wpcerber.com/contact/"
|
895 |
msgstr ""
|
896 |
|
897 |
+
#: ../cerber-load.php:918
|
898 |
+
#, php-format
|
899 |
+
msgid ""
|
900 |
+
"<strong>ERROR</strong>: The password you entered for the username %s is "
|
901 |
+
"incorrect."
|
902 |
msgstr ""
|
903 |
|
904 |
+
#: ../cerber-load.php:1123 ../cerber-load.php:1129 ../cerber-load.php:1145 ..
|
905 |
+
#: /cerber-load.php:1152
|
906 |
+
msgid "You are not allowed to register."
|
907 |
msgstr ""
|
908 |
|
909 |
+
#: ../cerber-load.php:1139
|
910 |
+
msgid "Username is not allowed. Please choose another one."
|
911 |
msgstr ""
|
912 |
|
913 |
+
#: ../cerber-load.php:1388
|
914 |
+
msgid "Sorry, human verification failed."
|
915 |
msgstr ""
|
916 |
|
917 |
+
#: ../cerber-load.php:3085
|
918 |
+
msgid "We're sorry, you are not allowed to proceed"
|
919 |
msgstr ""
|
920 |
|
921 |
+
#: ../cerber-load.php:3195
|
922 |
+
msgid "WP Cerber notify"
|
923 |
msgstr ""
|
924 |
|
925 |
+
#: ../cerber-load.php:3217
|
926 |
+
msgid "Citadel mode is activated"
|
927 |
msgstr ""
|
928 |
|
929 |
+
#: ../cerber-load.php:3219
|
930 |
+
#, php-format
|
931 |
+
msgid "Citadel mode is activated after %d failed login attempts in %d minutes."
|
932 |
msgstr ""
|
933 |
|
934 |
+
#: ../cerber-load.php:3220
|
935 |
+
#, php-format
|
936 |
+
msgid "Last failed attempt was at %s from IP %s with user login: %s."
|
937 |
msgstr ""
|
938 |
|
939 |
+
#: ../cerber-load.php:3221 ../cerber-load.php:3778
|
940 |
+
msgid "View activity in dashboard"
|
941 |
msgstr ""
|
942 |
|
943 |
+
#: ../cerber-load.php:3246
|
944 |
+
msgid "unspecified"
|
945 |
msgstr ""
|
946 |
|
947 |
+
#: ../cerber-load.php:3249
|
948 |
+
msgid "Number of lockouts is increasing"
|
949 |
msgstr ""
|
950 |
|
951 |
+
#: ../cerber-load.php:3251
|
952 |
+
msgid "Number of active lockouts"
|
953 |
msgstr ""
|
954 |
|
955 |
+
#: ../cerber-load.php:3252
|
956 |
+
#, php-format
|
957 |
+
msgid "Last lockout was added: %s for IP %s"
|
958 |
msgstr ""
|
959 |
|
960 |
+
#: ../cerber-load.php:3254
|
961 |
+
msgid "View activity for this IP"
|
962 |
msgstr ""
|
963 |
|
964 |
+
#: ../cerber-load.php:3255
|
965 |
+
msgid "View lockouts in dashboard"
|
966 |
msgstr ""
|
967 |
|
968 |
+
#: ../cerber-load.php:3258 ../cerber-load.php:3260
|
969 |
+
msgid "A new version of WP Cerber is available to install"
|
970 |
msgstr ""
|
971 |
|
972 |
+
#: ../cerber-load.php:3259
|
973 |
+
msgid "Hi!"
|
974 |
msgstr ""
|
975 |
|
976 |
+
#: ../cerber-load.php:3262 ../cerber-load.php:3273
|
977 |
+
msgid "Website"
|
978 |
msgstr ""
|
979 |
|
980 |
+
#: ../cerber-load.php:3265 ../cerber-load.php:3266
|
981 |
+
msgid "The WP Cerber security plugin has been deactivated"
|
982 |
msgstr ""
|
983 |
|
984 |
+
#: ../cerber-load.php:3268
|
985 |
+
msgid "Not logged in"
|
986 |
msgstr ""
|
987 |
|
988 |
+
#: ../cerber-load.php:3274
|
989 |
+
msgid "By user"
|
990 |
msgstr ""
|
991 |
|
992 |
+
#: ../cerber-load.php:3275
|
993 |
+
msgid "From IP address"
|
994 |
msgstr ""
|
995 |
|
996 |
+
#: ../cerber-load.php:3278
|
997 |
+
msgid "From country"
|
998 |
msgstr ""
|
999 |
|
1000 |
+
#: ../cerber-load.php:3282
|
1001 |
+
msgid "The WP Cerber security plugin is now active"
|
1002 |
msgstr ""
|
1003 |
|
1004 |
+
#: ../cerber-load.php:3283 ../cerber-load.php:3968
|
1005 |
+
msgid "WP Cerber is now active and has started protecting your site"
|
1006 |
msgstr ""
|
1007 |
|
1008 |
+
#: ../cerber-load.php:3291
|
1009 |
+
msgid "New Custom login URL"
|
1010 |
msgstr ""
|
1011 |
|
1012 |
+
#: ../cerber-load.php:3295 ../cerber-load.php:3296
|
1013 |
+
msgid "A new activity has been recorded"
|
1014 |
msgstr ""
|
1015 |
|
1016 |
+
#: ../cerber-load.php:3301
|
1017 |
+
msgid "Weekly report"
|
1018 |
msgstr ""
|
1019 |
|
1020 |
+
#: ../cerber-load.php:3304
|
1021 |
+
msgid "To change reporting settings visit"
|
1022 |
msgstr ""
|
1023 |
|
1024 |
+
#: ../cerber-load.php:3330
|
1025 |
+
msgid "Your login page:"
|
1026 |
msgstr ""
|
1027 |
|
1028 |
+
#: ../cerber-load.php:3334
|
1029 |
+
msgid "Your license is valid until"
|
1030 |
msgstr ""
|
1031 |
|
1032 |
+
#: ../cerber-load.php:3337
|
1033 |
+
msgid "This message was sent by"
|
1034 |
msgstr ""
|
1035 |
|
1036 |
+
#: ../cerber-load.php:3358
|
1037 |
#, php-format
|
1038 |
+
msgid "Your last sign-in was %s from %s"
|
1039 |
msgstr ""
|
1040 |
|
1041 |
+
#: ../cerber-load.php:3433
|
1042 |
+
msgid "Weekly Report"
|
1043 |
+
msgstr ""
|
1044 |
+
|
1045 |
+
#: ../cerber-load.php:3445
|
1046 |
+
msgid "Activity details"
|
1047 |
msgstr ""
|
1048 |
|
1049 |
+
#: ../cerber-load.php:3459
|
1050 |
+
msgid "Attempts to log in with non-existent username"
|
1051 |
+
msgstr ""
|
1052 |
+
|
1053 |
+
#: ../cerber-load.php:3750
|
1054 |
+
msgid "User"
|
1055 |
+
msgstr ""
|
1056 |
+
|
1057 |
+
#: ../cerber-load.php:3758
|
1058 |
+
msgid "Search string"
|
1059 |
+
msgstr ""
|
1060 |
+
|
1061 |
+
#: ../cerber-load.php:3779
|
1062 |
+
msgid "To unsubscribe click here"
|
1063 |
+
msgstr ""
|
1064 |
+
|
1065 |
+
#: ../cerber-load.php:3936
|
1066 |
#, php-format
|
1067 |
+
msgid "The WP Cerber requires PHP %s or higher. You are running"
|
1068 |
msgstr ""
|
1069 |
|
1070 |
+
#: ../cerber-load.php:3940
|
1071 |
+
#, php-format
|
1072 |
+
msgid "The WP Cerber requires WordPress %s or higher. You are running"
|
1073 |
msgstr ""
|
1074 |
|
1075 |
+
#: ../cerber-load.php:3949
|
1076 |
+
msgid "Can't activate WP Cerber due to a database error."
|
1077 |
msgstr ""
|
1078 |
|
1079 |
+
#: ../cerber-load.php:3969
|
1080 |
+
msgid "Your IP address is added to the"
|
1081 |
msgstr ""
|
1082 |
|
1083 |
+
#: ../cerber-load.php:3976 ../settings.php:394
|
1084 |
+
msgid "Main Settings"
|
|
|
|
|
|
|
|
|
1085 |
msgstr ""
|
1086 |
|
1087 |
+
#: ../cerber-load.php:3977 ../settings.php:397 ../cerber-tools.php:88 ../cerber-
|
1088 |
+
#: tools.php:97 ../cerber-tools.php:178
|
1089 |
+
msgid "Access Lists"
|
1090 |
msgstr ""
|
1091 |
|
1092 |
+
#: ../cerber-load.php:3979 ../settings.php:399
|
1093 |
+
msgid "Hardening"
|
1094 |
msgstr ""
|
1095 |
|
1096 |
+
#: ../cerber-load.php:3980 ../settings.php:78 ../settings.php:95 ../settings.php:
|
1097 |
+
#: 404
|
1098 |
+
msgid "Notifications"
|
1099 |
+
msgstr ""
|
1100 |
+
|
1101 |
+
#: ../cerber-load.php:3981
|
1102 |
+
msgid "Import settings"
|
1103 |
msgstr ""
|
1104 |
|
1105 |
#: ../settings.php:70
|
1106 |
+
msgid "Plugin initialization"
|
1107 |
msgstr ""
|
1108 |
|
1109 |
#: ../settings.php:71
|
1110 |
+
msgid "Load security engine"
|
1111 |
+
msgstr ""
|
1112 |
+
|
1113 |
+
#: ../settings.php:71
|
1114 |
+
msgid "Legacy mode"
|
1115 |
+
msgstr ""
|
1116 |
+
|
1117 |
+
#: ../settings.php:71
|
1118 |
+
msgid "Standard mode"
|
1119 |
+
msgstr ""
|
1120 |
+
|
1121 |
+
#: ../settings.php:73
|
1122 |
+
msgid "Limit login attempts"
|
1123 |
+
msgstr ""
|
1124 |
+
|
1125 |
+
#: ../settings.php:74
|
1126 |
msgid "Attempts"
|
1127 |
msgstr ""
|
1128 |
|
1129 |
+
#: ../settings.php:75
|
1130 |
msgid "Lockout duration"
|
1131 |
msgstr ""
|
1132 |
|
1133 |
+
#: ../settings.php:75 ../settings.php:94
|
1134 |
msgid "minutes"
|
1135 |
msgstr ""
|
1136 |
|
1137 |
+
#: ../settings.php:76
|
1138 |
msgid "Aggressive lockout"
|
1139 |
msgstr ""
|
1140 |
|
1141 |
+
#: ../settings.php:77
|
1142 |
msgid "Apply limit login rules to IP addresses in the White IP Access List"
|
1143 |
msgstr ""
|
1144 |
|
1145 |
+
#: ../settings.php:79
|
1146 |
msgid "Site connection"
|
1147 |
msgstr ""
|
1148 |
|
1149 |
+
#: ../settings.php:81
|
1150 |
msgid "Proactive security rules"
|
1151 |
msgstr ""
|
1152 |
|
1153 |
+
#: ../settings.php:82
|
1154 |
msgid "Block subnet"
|
1155 |
msgstr ""
|
1156 |
|
1157 |
+
#: ../settings.php:82
|
1158 |
msgid "Always block entire subnet Class C of intruders IP"
|
1159 |
msgstr ""
|
1160 |
|
1161 |
+
#: ../settings.php:83
|
1162 |
msgid "Non-existent users"
|
1163 |
msgstr ""
|
1164 |
|
1165 |
+
#: ../settings.php:83
|
1166 |
msgid "Immediately block IP when attempting to login with a non-existent username"
|
1167 |
msgstr ""
|
1168 |
|
1169 |
+
#: ../settings.php:84
|
1170 |
msgid "Redirect dashboard requests"
|
1171 |
msgstr ""
|
1172 |
|
1173 |
+
#: ../settings.php:84
|
1174 |
msgid ""
|
1175 |
"Disable automatic redirecting to the login page when /wp-admin/ is requested "
|
1176 |
"by an unauthorized request"
|
1177 |
msgstr ""
|
1178 |
|
1179 |
+
#: ../settings.php:85
|
1180 |
msgid "Request wp-login.php"
|
1181 |
msgstr ""
|
1182 |
|
1183 |
+
#: ../settings.php:85
|
1184 |
msgid "Immediately block IP after any request to wp-login.php"
|
1185 |
msgstr ""
|
1186 |
|
1187 |
+
#: ../settings.php:86
|
1188 |
msgid "Display 404 page"
|
1189 |
msgstr ""
|
1190 |
|
1191 |
+
#: ../settings.php:86
|
1192 |
msgid "Use 404 template from the active theme"
|
1193 |
msgstr ""
|
1194 |
|
1195 |
+
#: ../settings.php:86
|
1196 |
msgid "Display simple 404 page"
|
1197 |
msgstr ""
|
1198 |
|
1199 |
+
#: ../settings.php:88
|
1200 |
msgid "Custom login page"
|
1201 |
msgstr ""
|
1202 |
|
1203 |
+
#: ../settings.php:89
|
1204 |
msgid "Custom login URL"
|
1205 |
msgstr ""
|
1206 |
|
1207 |
+
#: ../settings.php:89
|
1208 |
msgid "must not overlap with the existing pages or posts slug"
|
1209 |
msgstr ""
|
1210 |
|
1211 |
+
#: ../settings.php:90
|
1212 |
msgid "Disable wp-login.php"
|
1213 |
msgstr ""
|
1214 |
|
1215 |
+
#: ../settings.php:90
|
1216 |
msgid "Block direct access to wp-login.php and return HTTP 404 Not Found Error"
|
1217 |
msgstr ""
|
1218 |
|
1219 |
+
#: ../settings.php:93
|
1220 |
msgid "Threshold"
|
1221 |
msgstr ""
|
1222 |
|
1223 |
+
#: ../settings.php:94
|
1224 |
msgid "Duration"
|
1225 |
msgstr ""
|
1226 |
|
1227 |
+
#: ../settings.php:95
|
1228 |
msgid "Send notification to admin email"
|
1229 |
msgstr ""
|
1230 |
|
1231 |
+
#: ../settings.php:95 ../settings.php:532 ../settings.php:654
|
1232 |
msgid "Click to send test"
|
1233 |
msgstr ""
|
1234 |
|
1235 |
+
#: ../settings.php:98 ../settings.php:330
|
1236 |
msgid "Keep records for"
|
1237 |
msgstr ""
|
1238 |
|
1239 |
+
#: ../settings.php:98 ../settings.php:172 ../settings.php:334
|
1240 |
msgid "days"
|
1241 |
msgstr ""
|
1242 |
|
1243 |
+
#: ../settings.php:99
|
1244 |
msgid "Cerber Lab connection"
|
1245 |
msgstr ""
|
1246 |
|
1247 |
+
#: ../settings.php:99
|
1248 |
msgid "Send malicious IP addresses to the Cerber Lab"
|
1249 |
msgstr ""
|
1250 |
|
1251 |
+
#: ../settings.php:100
|
1252 |
msgid "Cerber Lab protocol"
|
1253 |
msgstr ""
|
1254 |
|
1255 |
+
#: ../settings.php:101
|
1256 |
msgid "Use file"
|
1257 |
msgstr ""
|
1258 |
|
1259 |
+
#: ../settings.php:101
|
1260 |
msgid "Write failed login attempts to the file"
|
1261 |
msgstr ""
|
1262 |
|
1263 |
+
#: ../settings.php:103
|
1264 |
msgid "Preferences"
|
1265 |
msgstr ""
|
1266 |
|
1267 |
+
#: ../settings.php:104
|
1268 |
msgid "Drill down IP"
|
1269 |
msgstr ""
|
1270 |
|
1271 |
+
#: ../settings.php:104
|
1272 |
msgid "Retrieve extra WHOIS information for IP"
|
1273 |
msgstr ""
|
1274 |
|
1275 |
+
#: ../settings.php:105
|
1276 |
msgid "Date format"
|
1277 |
msgstr ""
|
1278 |
|
1279 |
+
#: ../settings.php:105
|
1280 |
#, php-format
|
1281 |
msgid "if empty, the default format %s will be used"
|
1282 |
msgstr ""
|
1283 |
|
1284 |
+
#: ../settings.php:112
|
1285 |
msgid "Hardening WordPress"
|
1286 |
msgstr ""
|
1287 |
|
1288 |
+
#: ../settings.php:113
|
1289 |
msgid "Stop user enumeration"
|
1290 |
msgstr ""
|
1291 |
|
1292 |
+
#: ../settings.php:113
|
1293 |
msgid "Block access to user pages like /?author=n and user data via REST API"
|
1294 |
msgstr ""
|
1295 |
|
1296 |
+
#: ../settings.php:114
|
1297 |
msgid "Protect admin scripts"
|
1298 |
msgstr ""
|
1299 |
|
1300 |
+
#: ../settings.php:114
|
1301 |
msgid "Block unauthorized access to load-scripts.php and load-styles.php"
|
1302 |
msgstr ""
|
1303 |
|
1304 |
+
#: ../settings.php:115
|
1305 |
msgid "Disable XML-RPC"
|
1306 |
msgstr ""
|
1307 |
|
1308 |
+
#: ../settings.php:115
|
1309 |
msgid "Block access to the XML-RPC server (including Pingbacks and Trackbacks)"
|
1310 |
msgstr ""
|
1311 |
|
1312 |
+
#: ../settings.php:116
|
1313 |
msgid "Disable feeds"
|
1314 |
msgstr ""
|
1315 |
|
1316 |
+
#: ../settings.php:116
|
1317 |
msgid "Block access to the RSS, Atom and RDF feeds"
|
1318 |
msgstr ""
|
1319 |
|
1320 |
+
#: ../settings.php:117
|
1321 |
msgid "Disable REST API"
|
1322 |
msgstr ""
|
1323 |
|
1324 |
+
#: ../settings.php:117
|
1325 |
msgid "Block access to the WordPress REST API except the following"
|
1326 |
msgstr ""
|
1327 |
|
1328 |
+
#: ../settings.php:118
|
1329 |
msgid "Allow REST API for logged in users"
|
1330 |
msgstr ""
|
1331 |
|
1332 |
+
#: ../settings.php:125
|
1333 |
msgid ""
|
1334 |
"Specify REST API namespaces to be allowed if REST API is disabled. One "
|
1335 |
"string per line."
|
1336 |
msgstr ""
|
1337 |
|
1338 |
+
#: ../settings.php:135
|
1339 |
msgid "User related settings"
|
1340 |
msgstr ""
|
1341 |
|
1342 |
+
#: ../settings.php:136
|
1343 |
msgid "Registration limit"
|
1344 |
msgstr ""
|
1345 |
|
1346 |
+
#: ../settings.php:137
|
1347 |
msgid "Prohibited usernames"
|
1348 |
msgstr ""
|
1349 |
|
1350 |
+
#: ../settings.php:143
|
1351 |
msgid ""
|
1352 |
"Usernames from this list are not allowed to log in or register. Any IP "
|
1353 |
"address, have tried to use any of these usernames, will be immediately "
|
1354 |
"blocked. Use comma to separate logins."
|
1355 |
msgstr ""
|
1356 |
|
1357 |
+
#: ../settings.php:143
|
1358 |
msgid "To specify a REGEX pattern wrap a pattern in two forward slashes."
|
1359 |
msgstr ""
|
1360 |
|
1361 |
+
#: ../settings.php:145
|
1362 |
msgid "User session expire"
|
1363 |
msgstr ""
|
1364 |
|
1365 |
+
#: ../settings.php:145
|
1366 |
msgid "in minutes (leave empty to use default WP value)"
|
1367 |
msgstr ""
|
1368 |
|
1369 |
+
#: ../settings.php:146
|
1370 |
msgid "Sort users in dashboard"
|
1371 |
msgstr ""
|
1372 |
|
1373 |
+
#: ../settings.php:146
|
1374 |
msgid "by date of registration"
|
1375 |
msgstr ""
|
1376 |
|
1377 |
+
#: ../settings.php:153
|
1378 |
msgid "Cerber antispam engine"
|
1379 |
msgstr ""
|
1380 |
|
1381 |
+
#: ../settings.php:154
|
1382 |
msgid "Comment form"
|
1383 |
msgstr ""
|
1384 |
|
1385 |
+
#: ../settings.php:154
|
1386 |
msgid "Protect comment form with bot detection engine"
|
1387 |
msgstr ""
|
1388 |
|
1389 |
+
#: ../settings.php:155 ../settings.php:180
|
1390 |
msgid "Registration form"
|
1391 |
msgstr ""
|
1392 |
|
1393 |
+
#: ../settings.php:155
|
1394 |
msgid "Protect registration form with bot detection engine"
|
1395 |
msgstr ""
|
1396 |
|
1397 |
+
#: ../settings.php:156
|
1398 |
msgid "Other forms"
|
1399 |
msgstr ""
|
1400 |
|
1401 |
+
#: ../settings.php:156
|
1402 |
msgid "Protect all forms on the website with bot detection engine"
|
1403 |
msgstr ""
|
1404 |
|
1405 |
+
#: ../settings.php:158
|
1406 |
msgid "Adjust antispam engine"
|
1407 |
msgstr ""
|
1408 |
|
1409 |
+
#: ../settings.php:159
|
1410 |
msgid "Safe mode"
|
1411 |
msgstr ""
|
1412 |
|
1413 |
+
#: ../settings.php:159
|
1414 |
msgid "Use less restrictive policies (allow AJAX)"
|
1415 |
msgstr ""
|
1416 |
|
1417 |
+
#: ../settings.php:160
|
1418 |
msgid "Disable bot detection engine for logged in users"
|
1419 |
msgstr ""
|
1420 |
|
1421 |
+
#: ../settings.php:161
|
1422 |
msgid "Query whitelist"
|
1423 |
msgstr ""
|
1424 |
|
1425 |
+
#: ../settings.php:167
|
1426 |
msgid ""
|
1427 |
"Enter a part of query string or query path to exclude a request from "
|
1428 |
"inspection by the engine. One item per line."
|
1429 |
msgstr ""
|
1430 |
|
1431 |
+
#: ../settings.php:170
|
1432 |
msgid "Comment processing"
|
1433 |
msgstr ""
|
1434 |
|
1435 |
+
#: ../settings.php:171
|
1436 |
msgid "If a spam comment detected"
|
1437 |
msgstr ""
|
1438 |
|
1439 |
+
#: ../settings.php:171
|
1440 |
msgid "Deny it completely"
|
1441 |
msgstr ""
|
1442 |
|
1443 |
+
#: ../settings.php:171
|
1444 |
msgid "Mark it as spam"
|
1445 |
msgstr ""
|
1446 |
|
1447 |
+
#: ../settings.php:172
|
1448 |
msgid "Trash spam comments"
|
1449 |
msgstr ""
|
1450 |
|
1451 |
+
#: ../settings.php:172
|
1452 |
msgid "Move spam comments to trash after"
|
1453 |
msgstr ""
|
1454 |
|
1455 |
+
#: ../settings.php:175
|
1456 |
msgid "reCAPTCHA settings"
|
1457 |
msgstr ""
|
1458 |
|
1459 |
+
#: ../settings.php:176
|
1460 |
msgid "Site key"
|
1461 |
msgstr ""
|
1462 |
|
1463 |
+
#: ../settings.php:177
|
1464 |
msgid "Secret key"
|
1465 |
msgstr ""
|
1466 |
|
1467 |
+
#: ../settings.php:178
|
1468 |
msgid "Invisible reCAPTCHA"
|
1469 |
msgstr ""
|
1470 |
|
1471 |
+
#: ../settings.php:178
|
1472 |
msgid "Enable invisible reCAPTCHA"
|
1473 |
msgstr ""
|
1474 |
|
1475 |
+
#: ../settings.php:178
|
1476 |
msgid ""
|
1477 |
"(do not enable it unless you get and enter the Site and Secret keys for the "
|
1478 |
"invisible version)"
|
1479 |
msgstr ""
|
1480 |
|
1481 |
+
#: ../settings.php:180
|
1482 |
msgid "Enable reCAPTCHA for WordPress registration form"
|
1483 |
msgstr ""
|
1484 |
|
1485 |
+
#: ../settings.php:181
|
1486 |
msgid "Enable reCAPTCHA for WooCommerce registration form"
|
1487 |
msgstr ""
|
1488 |
|
1489 |
+
#: ../settings.php:183
|
1490 |
msgid "Lost password form"
|
1491 |
msgstr ""
|
1492 |
|
1493 |
+
#: ../settings.php:183
|
1494 |
msgid "Enable reCAPTCHA for WordPress lost password form"
|
1495 |
msgstr ""
|
1496 |
|
1497 |
+
#: ../settings.php:184
|
1498 |
msgid "Enable reCAPTCHA for WooCommerce lost password form"
|
1499 |
msgstr ""
|
1500 |
|
1501 |
+
#: ../settings.php:186
|
1502 |
msgid "Login form"
|
1503 |
msgstr ""
|
1504 |
|
1505 |
+
#: ../settings.php:186
|
1506 |
msgid "Enable reCAPTCHA for WordPress login form"
|
1507 |
msgstr ""
|
1508 |
|
1509 |
+
#: ../settings.php:187
|
1510 |
msgid "Enable reCAPTCHA for WooCommerce login form"
|
1511 |
msgstr ""
|
1512 |
|
1513 |
+
#: ../settings.php:189
|
1514 |
msgid "Enable reCAPTCHA for WordPress comment form"
|
1515 |
msgstr ""
|
1516 |
|
1517 |
+
#: ../settings.php:190
|
1518 |
msgid "Disable reCAPTCHA for logged in users"
|
1519 |
msgstr ""
|
1520 |
|
1521 |
+
#: ../settings.php:192
|
1522 |
msgid "Limit attempts"
|
1523 |
msgstr ""
|
1524 |
|
1525 |
+
#: ../settings.php:192
|
1526 |
#, php-format
|
1527 |
msgid "Lock out IP address for %s minutes after %s failed attempts within %s minutes"
|
1528 |
msgstr ""
|
1529 |
|
1530 |
+
#: ../settings.php:198
|
1531 |
msgid "Email notifications"
|
1532 |
msgstr ""
|
1533 |
|
1534 |
+
#: ../settings.php:201 ../settings.php:236
|
1535 |
msgid "Email Address"
|
1536 |
msgstr ""
|
1537 |
|
1538 |
+
#: ../settings.php:205 ../settings.php:241 ../settings.php:298
|
1539 |
msgid "Use comma to specify multiple values"
|
1540 |
msgstr ""
|
1541 |
|
1542 |
+
#: ../settings.php:210
|
1543 |
#, php-format
|
1544 |
msgid "if empty, the admin email %s will be used"
|
1545 |
msgstr ""
|
1546 |
|
1547 |
+
#: ../settings.php:213
|
1548 |
msgid "Notification limit"
|
1549 |
msgstr ""
|
1550 |
|
1551 |
+
#: ../settings.php:213
|
1552 |
msgid "notification letters allowed per hour (0 means unlimited)"
|
1553 |
msgstr ""
|
1554 |
|
1555 |
+
#: ../settings.php:219
|
1556 |
msgid "Push notifications"
|
1557 |
msgstr ""
|
1558 |
|
1559 |
+
#: ../settings.php:226
|
1560 |
msgid "All connected devices"
|
1561 |
msgstr ""
|
1562 |
|
1563 |
+
#: ../settings.php:227
|
1564 |
msgid "No devices found"
|
1565 |
msgstr ""
|
1566 |
|
1567 |
+
#: ../settings.php:229
|
1568 |
msgid "Not available"
|
1569 |
msgstr ""
|
1570 |
|
1571 |
+
#: ../settings.php:233
|
1572 |
msgid "Weekly reports"
|
1573 |
msgstr ""
|
1574 |
|
1575 |
+
#: ../settings.php:234
|
1576 |
msgid "Enable reporting"
|
1577 |
msgstr ""
|
1578 |
|
1579 |
+
#: ../settings.php:246
|
1580 |
msgid "if empty, email from notification settings will be used"
|
1581 |
msgstr ""
|
1582 |
|
1583 |
+
#: ../settings.php:254
|
1584 |
msgid "Inspection"
|
1585 |
msgstr ""
|
1586 |
|
1587 |
+
#: ../settings.php:255
|
1588 |
msgid "Enable traffic inspection"
|
1589 |
msgstr ""
|
1590 |
|
1591 |
+
#: ../settings.php:260
|
1592 |
msgid "Request whitelist"
|
1593 |
msgstr ""
|
1594 |
|
1595 |
+
#: ../settings.php:266
|
1596 |
msgid ""
|
1597 |
"Enter a request URI to exclude the request from inspection. One item per "
|
1598 |
"line."
|
1599 |
msgstr ""
|
1600 |
|
1601 |
+
#: ../settings.php:269
|
1602 |
msgid "Logging"
|
1603 |
msgstr ""
|
1604 |
|
1605 |
+
#: ../settings.php:270
|
1606 |
msgid "Logging mode"
|
1607 |
msgstr ""
|
1608 |
|
1609 |
+
#: ../settings.php:276
|
1610 |
msgid "Logging disabled"
|
1611 |
msgstr ""
|
1612 |
|
1613 |
+
#: ../settings.php:277
|
1614 |
msgid "Smart"
|
1615 |
msgstr ""
|
1616 |
|
1617 |
+
#: ../settings.php:278
|
1618 |
msgid "All traffic"
|
1619 |
msgstr ""
|
1620 |
|
1621 |
+
#: ../settings.php:282
|
1622 |
msgid "Ignore crawlers"
|
1623 |
msgstr ""
|
1624 |
|
1625 |
+
#: ../settings.php:287
|
1626 |
msgid "Save request fields"
|
1627 |
msgstr ""
|
1628 |
|
1629 |
+
#: ../settings.php:292
|
1630 |
msgid "Mask these form fields"
|
1631 |
msgstr ""
|
1632 |
|
1633 |
+
#: ../settings.php:303
|
1634 |
msgid "Save request headers"
|
1635 |
msgstr ""
|
1636 |
|
1637 |
+
#: ../settings.php:309
|
1638 |
msgid "Save $_SERVER"
|
1639 |
msgstr ""
|
1640 |
|
1641 |
+
#: ../settings.php:315
|
1642 |
msgid "Save request cookies"
|
1643 |
msgstr ""
|
1644 |
|
1645 |
+
#: ../settings.php:322
|
1646 |
msgid "Page generation time threshold"
|
1647 |
msgstr ""
|
1648 |
|
1649 |
+
#: ../settings.php:327
|
1650 |
msgid "milliseconds"
|
1651 |
msgstr ""
|
1652 |
|
1653 |
+
#: ../settings.php:344
|
1654 |
msgid "Make your protection smarter!"
|
1655 |
msgstr ""
|
1656 |
|
1657 |
+
#: ../settings.php:348
|
1658 |
msgid ""
|
1659 |
"Please enable Permalinks to use this feature. Set Permalink Settings to "
|
1660 |
"something other than Default."
|
1661 |
msgstr ""
|
1662 |
|
1663 |
+
#: ../settings.php:351
|
1664 |
msgid ""
|
1665 |
"Be careful when enabling this options. If you forget the custom login URL "
|
1666 |
"you will not be able to login."
|
1667 |
msgstr ""
|
1668 |
|
1669 |
+
#: ../settings.php:355
|
1670 |
msgid ""
|
1671 |
"In the Citadel mode nobody is able to log in except IPs from the White IP "
|
1672 |
"Access List. Active user sessions will not be affected."
|
1673 |
msgstr ""
|
1674 |
|
1675 |
+
#: ../settings.php:358
|
1676 |
msgid "These settings do not affect hosts from the "
|
1677 |
msgstr ""
|
1678 |
|
1679 |
+
#: ../settings.php:361
|
1680 |
msgid ""
|
1681 |
"Before you can start using reCAPTCHA, you have to obtain Site key and Secret "
|
1682 |
"key on the Google website"
|
1683 |
msgstr ""
|
1684 |
|
1685 |
+
#: ../settings.php:392
|
1686 |
msgid "Lockouts"
|
1687 |
msgstr ""
|
1688 |
|
1689 |
+
#: ../settings.php:401
|
1690 |
msgid "Users"
|
1691 |
msgstr ""
|
1692 |
|
1693 |
+
#: ../settings.php:406
|
1694 |
msgid "Help"
|
1695 |
msgstr ""
|
1696 |
|
1697 |
+
#: ../settings.php:513 ../settings.php:635
|
1698 |
#, php-format
|
1699 |
msgid "%s allowed retries in %s minutes"
|
1700 |
msgstr ""
|
1701 |
|
1702 |
+
#: ../settings.php:518 ../settings.php:640
|
1703 |
#, php-format
|
1704 |
msgid "%s allowed registrations in %s minutes from one IP"
|
1705 |
msgstr ""
|
1706 |
|
1707 |
+
#: ../settings.php:523 ../settings.php:645
|
1708 |
#, php-format
|
1709 |
msgid "Increase lockout duration to %s hours after %s lockouts in the last %s hours"
|
1710 |
msgstr ""
|
1711 |
|
1712 |
+
#: ../settings.php:530 ../settings.php:652
|
1713 |
msgid "Notify admin if the number of active lockouts above"
|
1714 |
msgstr ""
|
1715 |
|
1716 |
+
#: ../settings.php:535 ../settings.php:657
|
1717 |
#, php-format
|
1718 |
msgid "Enable after %s failed login attempts in last %s minutes"
|
1719 |
msgstr ""
|
1720 |
|
1721 |
+
#: ../settings.php:737
|
1722 |
msgid "Sunday"
|
1723 |
msgstr ""
|
1724 |
|
1725 |
+
#: ../settings.php:738
|
1726 |
msgid "Monday"
|
1727 |
msgstr ""
|
1728 |
|
1729 |
+
#: ../settings.php:739
|
1730 |
msgid "Tuesday"
|
1731 |
msgstr ""
|
1732 |
|
1733 |
+
#: ../settings.php:740
|
1734 |
msgid "Wednesday"
|
1735 |
msgstr ""
|
1736 |
|
1737 |
+
#: ../settings.php:741
|
1738 |
msgid "Thursday"
|
1739 |
msgstr ""
|
1740 |
|
1741 |
+
#: ../settings.php:742
|
1742 |
msgid "Friday"
|
1743 |
msgstr ""
|
1744 |
|
1745 |
+
#: ../settings.php:743
|
1746 |
msgid "Saturday"
|
1747 |
msgstr ""
|
1748 |
|
1749 |
#. translators: preposition of time
|
1750 |
+
#: ../settings.php:753
|
1751 |
msgctxt "preposition of time"
|
1752 |
msgid "at"
|
1753 |
msgstr ""
|
1754 |
|
1755 |
+
#: ../settings.php:769
|
1756 |
msgid "Click to send now"
|
1757 |
msgstr ""
|
1758 |
|
1759 |
+
#: ../settings.php:781
|
1760 |
+
msgid "Plugin initialization mode has not been changed"
|
1761 |
+
msgstr ""
|
1762 |
+
|
1763 |
+
#: ../settings.php:801 ../settings.php:802
|
1764 |
msgid "Attention! You have changed the login URL! The new login URL is"
|
1765 |
msgstr ""
|
1766 |
|
1767 |
+
#: ../settings.php:803 ../settings.php:804
|
1768 |
msgid ""
|
1769 |
"If you use a caching plugin, you have to add your new login URL to the list "
|
1770 |
"of pages not to cache."
|
1771 |
msgstr ""
|
1772 |
|
1773 |
+
#: ../settings.php:882 ../settings.php:894
|
1774 |
msgid "<strong>ERROR</strong>: please enter a valid email address."
|
1775 |
msgstr ""
|
1776 |
|
1847 |
msgid "Error while parsing file"
|
1848 |
msgstr ""
|
1849 |
|
1850 |
+
#: ../cerber-tools.php:339
|
1851 |
msgid "Antispam and bot detection settings"
|
1852 |
msgstr ""
|
1853 |
+
|
1854 |
+
#. Name of the plugin
|
1855 |
+
msgid "WP Cerber boot module"
|
1856 |
+
msgstr ""
|
1857 |
+
|
1858 |
+
#. Description of the plugin
|
1859 |
+
msgid ""
|
1860 |
+
"This is a standard boot module for WP Cerber Security & Antispam plugin. It "
|
1861 |
+
"was installed when you set the plugin initialization mode to Standard. Know "
|
1862 |
+
"more: <a href=\"https://wpcerber.com\">wpcerber.com</a>."
|
1863 |
+
msgstr ""
|
modules/aaa-wp-cerber.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Plugin Name: WP Cerber boot module
|
4 |
+
Plugin URI: https://wpcerber.com
|
5 |
+
Description: This is a standard boot module for WP Cerber Security & Antispam plugin. It was installed when you set the plugin initialization mode to Standard. Know more: <a href="https://wpcerber.com">wpcerber.com</a>.
|
6 |
+
Author: Gregory
|
7 |
+
Author URI: https://wpcerber.com
|
8 |
+
Version: 1.0
|
9 |
+
Text Domain: wp-cerber
|
10 |
+
Network: true
|
11 |
+
|
12 |
+
Copyright (C) 2015-18 CERBER TECH INC., http://cerber.tech
|
13 |
+
Copyright (C) 2015-18 Gregory Markov, https://wpcerber.com
|
14 |
+
|
15 |
+
Licenced under the GNU GPL.
|
16 |
+
|
17 |
+
This program is free software; you can redistribute it and/or modify
|
18 |
+
it under the terms of the GNU General Public License as published by
|
19 |
+
the Free Software Foundation; either version 3 of the License, or
|
20 |
+
(at your option) any later version.
|
21 |
+
|
22 |
+
This program is distributed in the hope that it will be useful,
|
23 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
24 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
25 |
+
GNU General Public License for more details.
|
26 |
+
|
27 |
+
You should have received a copy of the GNU General Public License
|
28 |
+
along with this program; if not, write to the Free Software
|
29 |
+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
30 |
+
|
31 |
+
*/
|
32 |
+
|
33 |
+
// If this file is called directly, abort executing.
|
34 |
+
if ( ! defined( 'WPINC' ) ) {
|
35 |
+
exit;
|
36 |
+
}
|
37 |
+
|
38 |
+
function cerber_mode(){
|
39 |
+
return 1;
|
40 |
+
}
|
41 |
+
|
42 |
+
if ( ( include_once WP_PLUGIN_DIR . '/wp-cerber/wp-cerber.php' ) == true ) {
|
43 |
+
define( 'CERBER_MODE', 1 );
|
44 |
+
}
|
readme.txt
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
=== Cerber Security & Antispam ===
|
2 |
Contributors: gioni
|
3 |
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SR8RJXFU35EW8
|
4 |
-
Tags: security, login,
|
5 |
Requires at least: 4.4
|
6 |
Requires PHP: 5.3
|
7 |
Tested up to: 4.9
|
8 |
-
Stable tag: 6.
|
9 |
License: GPLv2
|
10 |
|
11 |
Protection against hacker attacks and bots. Restrict access with IP access lists, track user and bot activity. reCAPTCHA. Limit login attempts.
|
@@ -13,10 +13,10 @@ Protection against hacker attacks and bots. Restrict access with IP access lists
|
|
13 |
== Description ==
|
14 |
|
15 |
Defends WordPress against brute force attacks by limiting the number of login attempts through the login form, XML-RPC / REST API requests or using auth cookies.
|
16 |
-
Restricts access with
|
17 |
Tracks user and intruder activity with powerful email, mobile and desktop notifications.
|
18 |
Stop spam: activates Cerber antispam engine and Google reCAPTCHA for protecting registration, contact and comments forms.
|
19 |
-
Hardening WordPress with a set of security
|
20 |
|
21 |
**Features you will love**
|
22 |
|
@@ -25,19 +25,19 @@ Hardening WordPress with a set of security settings.
|
|
25 |
* Permit or restrict access by [White IP Access list and Black IP Access List](https://wpcerber.com/using-ip-access-lists-to-protect-wordpress/) with a single IP, IP range or subnet.
|
26 |
* Create **Custom login URL** ([rename wp-login.php](https://wpcerber.com/how-to-rename-wp-login-php/)).
|
27 |
* Cerber antispam engine for protecting any contact form. Automatically detects and moves spam comments to trash or deny it completely.
|
28 |
-
* Log
|
29 |
-
* Cool notifications with powerful filters
|
30 |
-
* Hide wp-login.php, wp-signup.php and wp-register.php from possible attacks
|
31 |
-
* Hide wp-admin (dashboard)
|
32 |
-
* Immediately block IP or subnet when attempting to log in with non-existent or prohibited username.
|
33 |
* Restrict user registration or login with a username matching REGEX patterns.
|
34 |
-
* Disable WP REST API or restrict access with your own rules
|
35 |
* Disable XML-RPC (block access to the XML-RPC interface including Pingbacks and Trackbacks)
|
36 |
* Disable feeds (block access to the RSS, Atom and RDF feeds)
|
37 |
-
* Restrict access to XML-RPC, REST API and feeds by **White IP Access list**
|
38 |
-
* Disable automatic
|
39 |
* **Stop user enumeration** (block access to pages like /?author=n and user REST API)
|
40 |
-
* Proactively **
|
41 |
* Anti-spam: **reCAPTCHA** to protect WordPress login, register and comment forms.
|
42 |
* [reCAPTCHA for WooCommerce & WordPress forms](https://wpcerber.com/how-to-setup-recaptcha/).
|
43 |
* Invisible reCAPTCHA for WordPress comments forms
|
@@ -138,13 +138,14 @@ Installing the WP Cerber Security & Antispam plugin is the same as other WordPre
|
|
138 |
2. Activate the WP Cerber through the Plugins > Installed Plugins menu in the WordPress admin dashboard.
|
139 |
3. The plugin is now active and has started protecting your WordPress with default settings.
|
140 |
4. Make sure, that you've got a notification letter to your site admin email.
|
|
|
141 |
5. Read carefully: [Getting Started Guide](https://wpcerber.com/getting-started/)
|
142 |
|
143 |
**Important notes**
|
144 |
|
145 |
-
1. Before enabling invisible reCAPTCHA, you must
|
146 |
2. If you want to test out plugin's features, do this on another computer (or incognito browser window) and remove computer IP address or network from the White Access List. Cerber is smart enough to recognize "the boss".
|
147 |
-
3. If you've set up the Custom login URL and you use some caching plugin like **W3 Total Cache** or **WP Super Cache**, you have to add
|
148 |
4. [Read this if your website is under CloudFlare](https://wpcerber.com/cloudflare-and-wordpress-cerber/)
|
149 |
5. If you use the Jetpack plugin or another plugin that needs to connect to wordpress.com, you need to unlock XML-RPC. To do that go to the Hardening tab, uncheck Disable XML-RPC, and click the Save changes button.
|
150 |
|
@@ -286,6 +287,17 @@ To get access to your dashboard you need to copy the WP Cerber Reset folder to t
|
|
286 |
|
287 |
== Changelog ==
|
288 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
289 |
= 6.2 =
|
290 |
* New: Protection against (DoS) attacks that exploit recently discovered vulnerability (CVE-2018-6389).
|
291 |
* New: The Traffic Inspector algorithm detects malformed and double extensions like .php.jpg more precisely.
|
1 |
=== Cerber Security & Antispam ===
|
2 |
Contributors: gioni
|
3 |
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SR8RJXFU35EW8
|
4 |
+
Tags: security, login, custom login url, antispam, limit login attempts, firewall, recaptcha, captcha, activity, log, logging, whitelist, blacklist, access list
|
5 |
Requires at least: 4.4
|
6 |
Requires PHP: 5.3
|
7 |
Tested up to: 4.9
|
8 |
+
Stable tag: 6.5
|
9 |
License: GPLv2
|
10 |
|
11 |
Protection against hacker attacks and bots. Restrict access with IP access lists, track user and bot activity. reCAPTCHA. Limit login attempts.
|
13 |
== Description ==
|
14 |
|
15 |
Defends WordPress against brute force attacks by limiting the number of login attempts through the login form, XML-RPC / REST API requests or using auth cookies.
|
16 |
+
Restricts access with the Black IP Access List and the White IP Access List.
|
17 |
Tracks user and intruder activity with powerful email, mobile and desktop notifications.
|
18 |
Stop spam: activates Cerber antispam engine and Google reCAPTCHA for protecting registration, contact and comments forms.
|
19 |
+
Hardening WordPress with a set of security rules and comprehensive algorithms.
|
20 |
|
21 |
**Features you will love**
|
22 |
|
25 |
* Permit or restrict access by [White IP Access list and Black IP Access List](https://wpcerber.com/using-ip-access-lists-to-protect-wordpress/) with a single IP, IP range or subnet.
|
26 |
* Create **Custom login URL** ([rename wp-login.php](https://wpcerber.com/how-to-rename-wp-login-php/)).
|
27 |
* Cerber antispam engine for protecting any contact form. Automatically detects and moves spam comments to trash or deny it completely.
|
28 |
+
* Log users, bots, hacker and other suspicious activities.
|
29 |
+
* Cool notifications with powerful event filters.
|
30 |
+
* Hide wp-login.php, wp-signup.php and wp-register.php from possible attacks.
|
31 |
+
* Hide wp-admin (dashboard) when a user isn't logged in.
|
32 |
+
* Immediately block an IP or a subnet when attempting to log in with non-existent or prohibited username.
|
33 |
* Restrict user registration or login with a username matching REGEX patterns.
|
34 |
+
* Disable WP REST API or restrict access with your own security rules
|
35 |
* Disable XML-RPC (block access to the XML-RPC interface including Pingbacks and Trackbacks)
|
36 |
* Disable feeds (block access to the RSS, Atom and RDF feeds)
|
37 |
+
* Restrict access to XML-RPC, REST API and feeds by **White IP Access list** by an IP address or an IP range.
|
38 |
+
* Disable automatic redirection to the login page.
|
39 |
* **Stop user enumeration** (block access to pages like /?author=n and user REST API)
|
40 |
+
* Proactively **blocks IP subnet class C** for intruder's IP.
|
41 |
* Anti-spam: **reCAPTCHA** to protect WordPress login, register and comment forms.
|
42 |
* [reCAPTCHA for WooCommerce & WordPress forms](https://wpcerber.com/how-to-setup-recaptcha/).
|
43 |
* Invisible reCAPTCHA for WordPress comments forms
|
138 |
2. Activate the WP Cerber through the Plugins > Installed Plugins menu in the WordPress admin dashboard.
|
139 |
3. The plugin is now active and has started protecting your WordPress with default settings.
|
140 |
4. Make sure, that you've got a notification letter to your site admin email.
|
141 |
+
5. It's advised to enable Standard mode for the "Load security engine" setting.
|
142 |
5. Read carefully: [Getting Started Guide](https://wpcerber.com/getting-started/)
|
143 |
|
144 |
**Important notes**
|
145 |
|
146 |
+
1. Before enabling invisible reCAPTCHA, you must obtain separate keys for the invisible version. [How to enable reCAPTCHA](https://wpcerber.com/how-to-setup-recaptcha/).
|
147 |
2. If you want to test out plugin's features, do this on another computer (or incognito browser window) and remove computer IP address or network from the White Access List. Cerber is smart enough to recognize "the boss".
|
148 |
+
3. If you've set up the Custom login URL and you use some caching plugin like **W3 Total Cache** or **WP Super Cache**, you have to add the new Custom login URL to the list of pages not to cache.
|
149 |
4. [Read this if your website is under CloudFlare](https://wpcerber.com/cloudflare-and-wordpress-cerber/)
|
150 |
5. If you use the Jetpack plugin or another plugin that needs to connect to wordpress.com, you need to unlock XML-RPC. To do that go to the Hardening tab, uncheck Disable XML-RPC, and click the Save changes button.
|
151 |
|
287 |
|
288 |
== Changelog ==
|
289 |
|
290 |
+
= 6.5 =
|
291 |
+
* New: A new, advanced initialization mode which reinforces overall security performance.
|
292 |
+
* New: Traffic Inspector's algorithms detect and deny any attempt to upload executable files or an .htaccess file via any POST request.
|
293 |
+
* New: A new setting to disable email notifications about new versions of the plugin.
|
294 |
+
* New: Search in the traffic log improved. Search in the User agent string and filter out the HTTP method (GET/POST) are available.
|
295 |
+
* Update: Performance of the logging subsystem is improved.
|
296 |
+
* Update: In the Smart mode if a user is not logged in, all requests to the admin dashboard are logged.
|
297 |
+
* Bug fixed: If a user tries to log in with an email address and an incorrect password, the "Invalid username" message is shown.
|
298 |
+
* Bug fixed: On a multisite installation with websites in subdirectories a user activation link doesn't work.
|
299 |
+
* [Read more](https://wpcerber.com/wp-cerber-security-6-5/)
|
300 |
+
|
301 |
= 6.2 =
|
302 |
* New: Protection against (DoS) attacks that exploit recently discovered vulnerability (CVE-2018-6389).
|
303 |
* New: The Traffic Inspector algorithm detects malformed and double extensions like .php.jpg more precisely.
|
settings.php
CHANGED
@@ -67,6 +67,9 @@ function cerber_settings_init(){
|
|
67 |
$tab='main'; // 'cerber-main' settings
|
68 |
register_setting( 'cerberus-'.$tab, 'cerber-'.$tab );
|
69 |
|
|
|
|
|
|
|
70 |
add_settings_section('cerber', __('Limit login attempts','wp-cerber'), 'cerber_sapi_section', 'cerber-' . $tab);
|
71 |
add_settings_field('attempts',__('Attempts','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'cerber',array('group'=>$tab,'option'=>'attempts','type'=>'attempts'));
|
72 |
add_settings_field('lockout',__('Lockout duration','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'cerber',array('group'=>$tab,'option'=>'lockout','type'=>'text','label'=>__('minutes','wp-cerber'),'size'=>3));
|
@@ -208,6 +211,10 @@ function cerber_settings_init(){
|
|
208 |
) );
|
209 |
|
210 |
add_settings_field('emailrate',__('Notification limit','wp-cerber'),'cerber_field_show',CERBER_OPT_N,'notify',array('group'=>$group,'setting'=>'emailrate','type'=>'text','label'=>__('notification letters allowed per hour (0 means unlimited)','wp-cerber'),'size'=>3));
|
|
|
|
|
|
|
|
|
211 |
|
212 |
add_settings_section('pushit', __('Push notifications','wp-cerber'), 'cerber_sapi_section', CERBER_OPT_N);
|
213 |
add_settings_field('pbtoken','Pushbullet access token','cerber_field_show',CERBER_OPT_N,'pushit',array('group'=>$group,'setting'=>'pbtoken','type'=>'text','size'=>60));
|
@@ -766,7 +773,14 @@ function cerber_time_select($args, $settings){
|
|
766 |
Sanitizing users input for Main Settings
|
767 |
*/
|
768 |
add_filter( 'pre_update_option_'.CERBER_OPT, 'cerber_sanitize_m', 10, 3 );
|
769 |
-
function cerber_sanitize_m($new, $old, $option) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
770 |
|
771 |
$new['attempts'] = absint( $new['attempts'] );
|
772 |
$new['period'] = absint( $new['period'] );
|
@@ -818,7 +832,7 @@ function cerber_sanitize_m($new, $old, $option) { // $option added in WP 4.4.0
|
|
818 |
Sanitizing/checking user input for User tab settings
|
819 |
*/
|
820 |
add_filter( 'pre_update_option_'.CERBER_OPT_U, 'cerber_sanitize_u', 10, 3 );
|
821 |
-
function cerber_sanitize_u($new, $old, $option) {
|
822 |
|
823 |
$new['prohibited'] = cerber_text2array($new['prohibited'], ',', 'strtolower');
|
824 |
|
@@ -909,14 +923,15 @@ function cerber_sanitize_h($new, $old, $option) {
|
|
909 |
if ( empty( $new['adminphp'] ) ) {
|
910 |
$new['adminphp'] = 0;
|
911 |
}
|
|
|
|
|
912 |
if ( $new['adminphp'] != $old['adminphp'] ) {
|
913 |
-
|
914 |
-
if ( $result === true ) {
|
915 |
cerber_admin_message( 'The .htaccess file has been modified' );
|
916 |
}
|
917 |
else {
|
918 |
$new['adminphp'] = $old['adminphp'];
|
919 |
-
cerber_admin_notice( $
|
920 |
}
|
921 |
}
|
922 |
|
@@ -1088,6 +1103,7 @@ function cerber_ms_update() {
|
|
1088 |
function cerber_get_defaults($field = null) {
|
1089 |
$all_defaults = array(
|
1090 |
CERBER_OPT => array(
|
|
|
1091 |
'attempts' => 3,
|
1092 |
'period' => 60,
|
1093 |
'lockout' => 60,
|
@@ -1104,7 +1120,7 @@ function cerber_get_defaults($field = null) {
|
|
1104 |
'nonusers' => 0,
|
1105 |
'wplogin' => 0,
|
1106 |
'noredirect' => 0,
|
1107 |
-
'page404' =>
|
1108 |
|
1109 |
'loginpath' => '',
|
1110 |
'loginnowp' => 0,
|
@@ -1169,6 +1185,7 @@ function cerber_get_defaults($field = null) {
|
|
1169 |
CERBER_OPT_N => array(
|
1170 |
'email' => '',
|
1171 |
'emailrate' => 12,
|
|
|
1172 |
'pbtoken' => '',
|
1173 |
'pbdevice' => '',
|
1174 |
'wreports-day' => '1', // workaround, see cerber_upgrade_options()
|
@@ -1294,18 +1311,18 @@ function cerber_get_options($option = '') {
|
|
1294 |
*
|
1295 |
* @return array|bool|mixed
|
1296 |
*/
|
1297 |
-
function crb_get_settings($option = '') {
|
1298 |
-
|
1299 |
-
|
1300 |
|
1301 |
/**
|
1302 |
* For some hosting environments it might be faster, e.g. Redis enabled
|
1303 |
*/
|
1304 |
-
if ( defined( 'CERBER_WP_OPTIONS' ) ) {
|
1305 |
return cerber_get_options( $option );
|
1306 |
}
|
1307 |
|
1308 |
-
|
1309 |
|
1310 |
$options = cerber_get_setting_list();
|
1311 |
$in = 'IN ("' . implode( '","', $options ) . '")';
|
@@ -1406,7 +1423,9 @@ function cerber_load_defaults() {
|
|
1406 |
}
|
1407 |
}
|
1408 |
$old = cerber_get_options();
|
1409 |
-
if (!empty($old['loginpath']))
|
|
|
|
|
1410 |
cerber_save_options( $save );
|
1411 |
}
|
1412 |
|
67 |
$tab='main'; // 'cerber-main' settings
|
68 |
register_setting( 'cerberus-'.$tab, 'cerber-'.$tab );
|
69 |
|
70 |
+
add_settings_section( 'boot', __( 'Plugin initialization', 'wp-cerber' ), 'cerber_sapi_section', 'cerber-' . $tab );
|
71 |
+
add_settings_field('boot-mode',__('Load security engine','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'boot',array('group'=>$tab, 'option'=>'boot-mode', 'type'=>'select', 'set' => array(__('Legacy mode','wp-cerber'), __('Standard mode','wp-cerber'))));
|
72 |
+
|
73 |
add_settings_section('cerber', __('Limit login attempts','wp-cerber'), 'cerber_sapi_section', 'cerber-' . $tab);
|
74 |
add_settings_field('attempts',__('Attempts','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'cerber',array('group'=>$tab,'option'=>'attempts','type'=>'attempts'));
|
75 |
add_settings_field('lockout',__('Lockout duration','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'cerber',array('group'=>$tab,'option'=>'lockout','type'=>'text','label'=>__('minutes','wp-cerber'),'size'=>3));
|
211 |
) );
|
212 |
|
213 |
add_settings_field('emailrate',__('Notification limit','wp-cerber'),'cerber_field_show',CERBER_OPT_N,'notify',array('group'=>$group,'setting'=>'emailrate','type'=>'text','label'=>__('notification letters allowed per hour (0 means unlimited)','wp-cerber'),'size'=>3));
|
214 |
+
add_settings_field( 'notify-new-ver', __( 'New version is available', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_N, 'notify', array( 'group' => $group,
|
215 |
+
'setting' => 'notify-new-ver',
|
216 |
+
'type' => 'checkbox'
|
217 |
+
) );
|
218 |
|
219 |
add_settings_section('pushit', __('Push notifications','wp-cerber'), 'cerber_sapi_section', CERBER_OPT_N);
|
220 |
add_settings_field('pbtoken','Pushbullet access token','cerber_field_show',CERBER_OPT_N,'pushit',array('group'=>$group,'setting'=>'pbtoken','type'=>'text','size'=>60));
|
773 |
Sanitizing users input for Main Settings
|
774 |
*/
|
775 |
add_filter( 'pre_update_option_'.CERBER_OPT, 'cerber_sanitize_m', 10, 3 );
|
776 |
+
function cerber_sanitize_m($new, $old, $option) {
|
777 |
+
|
778 |
+
$ret = cerber_set_boot_mode( $new['boot-mode'], $old['boot-mode'] );
|
779 |
+
if ( is_wp_error( $ret ) ) {
|
780 |
+
cerber_admin_notice( __( 'ERROR:', 'wp-cerber' ) . ' ' . $ret->get_error_message() );
|
781 |
+
cerber_admin_notice( __( 'Plugin initialization mode has not been changed', 'wp-cerber' ) );
|
782 |
+
$new['boot-mode'] = $old['boot-mode'];
|
783 |
+
}
|
784 |
|
785 |
$new['attempts'] = absint( $new['attempts'] );
|
786 |
$new['period'] = absint( $new['period'] );
|
832 |
Sanitizing/checking user input for User tab settings
|
833 |
*/
|
834 |
add_filter( 'pre_update_option_'.CERBER_OPT_U, 'cerber_sanitize_u', 10, 3 );
|
835 |
+
function cerber_sanitize_u($new, $old, $option) {
|
836 |
|
837 |
$new['prohibited'] = cerber_text2array($new['prohibited'], ',', 'strtolower');
|
838 |
|
923 |
if ( empty( $new['adminphp'] ) ) {
|
924 |
$new['adminphp'] = 0;
|
925 |
}
|
926 |
+
|
927 |
+
$sync = cerber_htaccess_sync( $new );
|
928 |
if ( $new['adminphp'] != $old['adminphp'] ) {
|
929 |
+
if ( $sync === true ) {
|
|
|
930 |
cerber_admin_message( 'The .htaccess file has been modified' );
|
931 |
}
|
932 |
else {
|
933 |
$new['adminphp'] = $old['adminphp'];
|
934 |
+
cerber_admin_notice( $sync );
|
935 |
}
|
936 |
}
|
937 |
|
1103 |
function cerber_get_defaults($field = null) {
|
1104 |
$all_defaults = array(
|
1105 |
CERBER_OPT => array(
|
1106 |
+
'boot-mode' => 0,
|
1107 |
'attempts' => 3,
|
1108 |
'period' => 60,
|
1109 |
'lockout' => 60,
|
1120 |
'nonusers' => 0,
|
1121 |
'wplogin' => 0,
|
1122 |
'noredirect' => 0,
|
1123 |
+
'page404' => 1,
|
1124 |
|
1125 |
'loginpath' => '',
|
1126 |
'loginnowp' => 0,
|
1185 |
CERBER_OPT_N => array(
|
1186 |
'email' => '',
|
1187 |
'emailrate' => 12,
|
1188 |
+
'notify-new-ver' => '1',
|
1189 |
'pbtoken' => '',
|
1190 |
'pbdevice' => '',
|
1191 |
'wreports-day' => '1', // workaround, see cerber_upgrade_options()
|
1311 |
*
|
1312 |
* @return array|bool|mixed
|
1313 |
*/
|
1314 |
+
function crb_get_settings( $option = '' ) {
|
1315 |
+
global $wpdb;
|
1316 |
+
static $united;
|
1317 |
|
1318 |
/**
|
1319 |
* For some hosting environments it might be faster, e.g. Redis enabled
|
1320 |
*/
|
1321 |
+
if ( defined( 'CERBER_WP_OPTIONS' ) && CERBER_WP_OPTIONS ) {
|
1322 |
return cerber_get_options( $option );
|
1323 |
}
|
1324 |
|
1325 |
+
if ( ! isset( $united ) ) {
|
1326 |
|
1327 |
$options = cerber_get_setting_list();
|
1328 |
$in = 'IN ("' . implode( '","', $options ) . '")';
|
1423 |
}
|
1424 |
}
|
1425 |
$old = cerber_get_options();
|
1426 |
+
if ( ! empty( $old['loginpath'] ) ) {
|
1427 |
+
$save['loginpath'] = $old['loginpath'];
|
1428 |
+
}
|
1429 |
cerber_save_options( $save );
|
1430 |
}
|
1431 |
|
whois.php
CHANGED
@@ -201,7 +201,7 @@ function cerber_get_flag_html( $code ) {
|
|
201 |
return '';
|
202 |
}
|
203 |
if ( ! isset( $assets_url ) ) {
|
204 |
-
$assets_url =
|
205 |
}
|
206 |
|
207 |
return '<span style="padding-left: 24px; background: url(\'' . $assets_url . 'flags/' . strtolower( $code ) . '.gif\') no-repeat left;"></span>';
|
201 |
return '';
|
202 |
}
|
203 |
if ( ! isset( $assets_url ) ) {
|
204 |
+
$assets_url = cerber_plugin_dir_url() . 'assets/';
|
205 |
}
|
206 |
|
207 |
return '<span style="padding-left: 24px; background: url(\'' . $assets_url . 'flags/' . strtolower( $code ) . '.gif\') no-repeat left;"></span>';
|
wp-cerber.php
CHANGED
@@ -1,4795 +1,51 @@
|
|
1 |
-
<?php
|
2 |
-
/*
|
3 |
-
Plugin Name: WP Cerber Security & Antispam
|
4 |
-
Plugin URI: https://wpcerber.com
|
5 |
-
Description: Protects
|
6 |
-
Author: Gregory
|
7 |
-
Author URI: https://wpcerber.com
|
8 |
-
Version: 6.
|
9 |
-
Text Domain: wp-cerber
|
10 |
-
Domain Path: /languages
|
11 |
-
Network: true
|
12 |
-
|
13 |
-
Copyright (C) 2015-18 CERBER TECH INC.,
|
14 |
-
Copyright (C) 2015-18 Gregory Markov, https://wpcerber.com
|
15 |
-
|
16 |
-
Licenced under the GNU GPL.
|
17 |
-
|
18 |
-
This program is free software; you can redistribute it and/or modify
|
19 |
-
it under the terms of the GNU General Public License as published by
|
20 |
-
the Free Software Foundation; either version 3 of the License, or
|
21 |
-
(at your option) any later version.
|
22 |
-
|
23 |
-
This program is distributed in the hope that it will be useful,
|
24 |
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
25 |
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
26 |
-
GNU General Public License for more details.
|
27 |
-
|
28 |
-
You should have received a copy of the GNU General Public License
|
29 |
-
along with this program; if not, write to the Free Software
|
30 |
-
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
31 |
-
|
32 |
-
*/
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
| |
|
53 |
-
| ATTENTION! Do not change or edit this file! |
|
54 |
-
| |
|
55 |
-
*========================================================================*
|
56 |
-
|
57 |
-
*/
|
58 |
-
|
59 |
-
// If this file is called directly, abort executing.
|
60 |
-
if ( ! defined( 'WPINC' ) ) {
|
61 |
-
exit;
|
62 |
-
}
|
63 |
-
|
64 |
-
define( 'CERBER_VER', '6.2' );
|
65 |
-
define( 'CERBER_LOG_TABLE', 'cerber_log' );
|
66 |
-
define( 'CERBER_TRAF_TABLE', 'cerber_traffic' );
|
67 |
-
define( 'CERBER_ACL_TABLE', 'cerber_acl' );
|
68 |
-
define( 'CERBER_BLOCKS_TABLE', 'cerber_blocks' );
|
69 |
-
define( 'CERBER_LAB_TABLE', 'cerber_lab' );
|
70 |
-
define( 'CERBER_LAB_IP_TABLE', 'cerber_lab_ip' );
|
71 |
-
define( 'CERBER_LAB_NET_TABLE', 'cerber_lab_net' );
|
72 |
-
define( 'CERBER_GEO_TABLE', 'cerber_countries' );
|
73 |
-
|
74 |
-
define( 'WP_LOGIN_SCRIPT', 'wp-login.php' );
|
75 |
-
define( 'WP_REG_URI', 'wp-register.php' );
|
76 |
-
define( 'WP_XMLRPC_SCRIPT', 'xmlrpc.php' );
|
77 |
-
define( 'WP_TRACKBACK_SCRIPT', 'wp-trackback.php' );
|
78 |
-
define( 'WP_PING_SCRIPT', 'wp-trackback.php' );
|
79 |
-
define( 'WP_SIGNUP_SCRIPT', 'wp-signup.php' );
|
80 |
-
|
81 |
-
define( 'GOO_RECAPTCHA_URL', 'https://www.google.com/recaptcha/api/siteverify' );
|
82 |
-
|
83 |
-
define( 'CERBER_REQ_PHP', '5.3.0' );
|
84 |
-
define( 'CERBER_REQ_WP', '4.4' );
|
85 |
-
define( 'CERBER_FILE', __FILE__ );
|
86 |
-
define( 'CERBER_TECH', 'https://cerber.tech/' );
|
87 |
-
|
88 |
-
require_once( dirname( __FILE__ ) . '/cerber-pluggable.php' );
|
89 |
-
require_once( dirname( __FILE__ ) . '/common.php' );
|
90 |
-
require_once( dirname( __FILE__ ) . '/settings.php' );
|
91 |
-
require_once( dirname( __FILE__ ) . '/cerber-lab.php' );
|
92 |
-
require_once( dirname( __FILE__ ) . '/whois.php' );
|
93 |
-
require_once( dirname( __FILE__ ) . '/jetflow.php' );
|
94 |
-
require_once( dirname( __FILE__ ) . '/cerber-news.php' );
|
95 |
-
|
96 |
-
if ( defined( 'WP_ADMIN' ) || defined( 'WP_NETWORK_ADMIN' ) ) {
|
97 |
-
// Load dashboard stuff
|
98 |
-
require_once( dirname( __FILE__ ) . '/dashboard.php' );
|
99 |
-
}
|
100 |
-
|
101 |
-
|
102 |
-
// Critical stuff that must be executed first ==================================================
|
103 |
-
|
104 |
-
cerber_request_time();
|
105 |
-
|
106 |
-
cerber_upgrade_all();
|
107 |
-
|
108 |
-
cerber_beast();
|
109 |
-
|
110 |
-
$antibot = cerber_antibot_gene();
|
111 |
-
if ( $antibot && ! empty( $antibot[1] ) ) {
|
112 |
-
foreach ( $antibot[1] as $item ) {
|
113 |
-
setcookie( $item[0], $item[1], time() + 3600, COOKIEPATH );
|
114 |
-
}
|
115 |
-
}
|
116 |
-
|
117 |
-
|
118 |
-
// =============================================================================================
|
119 |
-
|
120 |
-
class WP_Cerber {
|
121 |
-
private $remote_ip;
|
122 |
-
private $session_id;
|
123 |
-
private $status = null;
|
124 |
-
private $options;
|
125 |
-
private $locked = null; // IP has been locked out
|
126 |
-
|
127 |
-
private $recaptcha = null; // Can recaptcha be verified with a current request
|
128 |
-
private $recaptcha_verified = null; // Is recaptcha successfully verified with a current request
|
129 |
-
public $recaptcha_here = null; // Is recaptcha widget enabled on the currently displayed page
|
130 |
-
|
131 |
-
public $garbage = false; // Garbage has been deleted
|
132 |
-
|
133 |
-
final function __construct() {
|
134 |
-
|
135 |
-
$this->session_id = substr(str_shuffle('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'), 0, 24);
|
136 |
-
|
137 |
-
// Load settings with filling missing (not-set) array keys
|
138 |
-
$this->options = cerber_get_options();
|
139 |
-
$keys = array();
|
140 |
-
//$defaults = array();
|
141 |
-
foreach ( cerber_get_defaults() as $item ) {
|
142 |
-
$keys = array_merge( $keys, array_keys( $item ) );
|
143 |
-
//$defaults = array_merge( $defaults, $item );
|
144 |
-
}
|
145 |
-
foreach ( $keys as $key ) {
|
146 |
-
if ( ! isset( $this->options[ $key ] ) ) {
|
147 |
-
$this->options[ $key ] = null;
|
148 |
-
}
|
149 |
-
}
|
150 |
-
|
151 |
-
if ( defined( 'CERBER_IP_KEY' ) ) {
|
152 |
-
$this->remote_ip = filter_var( $_SERVER[ CERBER_IP_KEY ], FILTER_VALIDATE_IP );
|
153 |
-
}
|
154 |
-
elseif ( $this->options['proxy'] && isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
|
155 |
-
$list = explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] );
|
156 |
-
foreach ( $list as $maybe_ip ) {
|
157 |
-
$this->remote_ip = filter_var( trim( $maybe_ip ), FILTER_VALIDATE_IP );
|
158 |
-
if ( $this->remote_ip ) {
|
159 |
-
break;
|
160 |
-
}
|
161 |
-
}
|
162 |
-
if ( ! $this->remote_ip && isset( $_SERVER['HTTP_X_REAL_IP'] ) ) {
|
163 |
-
$this->remote_ip = filter_var( $_SERVER['HTTP_X_REAL_IP'], FILTER_VALIDATE_IP );
|
164 |
-
}
|
165 |
-
} else {
|
166 |
-
if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
|
167 |
-
$this->remote_ip = $_SERVER['REMOTE_ADDR'];
|
168 |
-
} elseif ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) {
|
169 |
-
$this->remote_ip = $_SERVER['HTTP_X_REAL_IP'];
|
170 |
-
} elseif ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) {
|
171 |
-
$this->remote_ip = $_SERVER['HTTP_CLIENT_IP'];
|
172 |
-
} elseif ( isset( $_SERVER['SERVER_ADDR'] ) ) {
|
173 |
-
$this->remote_ip = $_SERVER['SERVER_ADDR'];
|
174 |
-
}
|
175 |
-
$this->remote_ip = filter_var( $this->remote_ip, FILTER_VALIDATE_IP );
|
176 |
-
}
|
177 |
-
// No IP address was found? Roll back to localhost.
|
178 |
-
if ( ! $this->remote_ip ) {
|
179 |
-
$this->remote_ip = '127.0.0.1';
|
180 |
-
} // including WP-CLI, other way is: if defined('WP_CLI')
|
181 |
-
|
182 |
-
$this->remote_ip = cerber_short_ipv6( $this->remote_ip );
|
183 |
-
|
184 |
-
$this->reCaptchaInit();
|
185 |
-
|
186 |
-
$this->deleteGarbage();
|
187 |
-
|
188 |
-
// Condition to check reCAPTCHA
|
189 |
-
|
190 |
-
add_action( 'login_init', array( $this, 'reCaptchaNow' ) );
|
191 |
-
|
192 |
-
}
|
193 |
-
|
194 |
-
// TODO: replace it with cerber_get_remote_ip()
|
195 |
-
final public function getRemoteIp() {
|
196 |
-
return $this->remote_ip;
|
197 |
-
}
|
198 |
-
|
199 |
-
final public function getSessionID() {
|
200 |
-
return $this->session_id;
|
201 |
-
}
|
202 |
-
|
203 |
-
final public function getStatus() {
|
204 |
-
if (isset($this->status)) return $this->status;
|
205 |
-
|
206 |
-
$this->status = 0; // Default
|
207 |
-
|
208 |
-
if ( cerber_is_citadel() ) {
|
209 |
-
$this->status = 3;
|
210 |
-
}
|
211 |
-
else {
|
212 |
-
//if ( ! cerber_is_allowed( $this->remote_ip ) ) {
|
213 |
-
if ( cerber_block_check( $this->remote_ip ) ) {
|
214 |
-
$this->status = 2;
|
215 |
-
}
|
216 |
-
else {
|
217 |
-
$tag = cerber_acl_check( $this->remote_ip );
|
218 |
-
if ( $tag == 'W' ) {
|
219 |
-
//$this->status = 4;
|
220 |
-
}
|
221 |
-
elseif ( $tag == 'B' || lab_is_blocked($this->remote_ip, false)) {
|
222 |
-
$this->status = 1;
|
223 |
-
}
|
224 |
-
}
|
225 |
-
}
|
226 |
-
|
227 |
-
return $this->status;
|
228 |
-
}
|
229 |
-
|
230 |
-
/*
|
231 |
-
Return Error message in context
|
232 |
-
*/
|
233 |
-
final public function getErrorMsg() {
|
234 |
-
$status = $this->getStatus();
|
235 |
-
switch ( $status ) {
|
236 |
-
case 1:
|
237 |
-
case 3:
|
238 |
-
return apply_filters( 'cerber_msg_blocked', __( 'You are not allowed to log in. Ask your administrator for assistance.', 'wp-cerber' ) , $status);
|
239 |
-
case 2:
|
240 |
-
$block = cerber_get_block();
|
241 |
-
$min = 1 + ( $block->block_until - time() ) / 60;
|
242 |
-
|
243 |
-
return apply_filters( 'cerber_msg_reached',
|
244 |
-
sprintf( __( 'You have reached the login attempts limit. Please try again in %d minutes.', 'wp-cerber' ), $min ),
|
245 |
-
$min );
|
246 |
-
break;
|
247 |
-
default:
|
248 |
-
return '';
|
249 |
-
}
|
250 |
-
}
|
251 |
-
|
252 |
-
/*
|
253 |
-
Return Remain message in context
|
254 |
-
*/
|
255 |
-
final public function getRemainMsg() {
|
256 |
-
$acl = !$this->options['limitwhite'];
|
257 |
-
$remain = cerber_get_remain_count($this->remote_ip, $acl);
|
258 |
-
if ( $remain < $this->options['attempts'] ) {
|
259 |
-
if ( $remain == 0 ) {
|
260 |
-
$remain = 1; // with some settings or when lockout was manually removed, we need to have 1 attempt.
|
261 |
-
}
|
262 |
-
return apply_filters( 'cerber_msg_remain',
|
263 |
-
sprintf( _n( 'You have only one attempt remaining.', 'You have %d attempts remaining.', $remain, 'wp-cerber' ), $remain ),
|
264 |
-
$remain );
|
265 |
-
}
|
266 |
-
|
267 |
-
return false;
|
268 |
-
}
|
269 |
-
|
270 |
-
final public function getSettings( $name = null ) {
|
271 |
-
if ( ! empty( $name ) ) {
|
272 |
-
if ( isset( $this->options[ $name ] ) ) {
|
273 |
-
return $this->options[ $name ];
|
274 |
-
} else {
|
275 |
-
return false;
|
276 |
-
}
|
277 |
-
}
|
278 |
-
|
279 |
-
return $this->options;
|
280 |
-
}
|
281 |
-
|
282 |
-
/*
|
283 |
-
final public function isProhibited( $username ) {
|
284 |
-
if ( empty( $this->options['prohibited'] ) ) {
|
285 |
-
return false;
|
286 |
-
}
|
287 |
-
|
288 |
-
return in_array( $username, (array) $this->options['prohibited'] );
|
289 |
-
}*/
|
290 |
-
|
291 |
-
/**
|
292 |
-
* Adding reCAPTCHA widgets
|
293 |
-
*
|
294 |
-
*/
|
295 |
-
final public function reCaptchaInit(){
|
296 |
-
|
297 |
-
if ( $this->status == 4 || empty( $this->options['sitekey'] ) || empty( $this->options['secretkey'] )) return;
|
298 |
-
|
299 |
-
// Native WP forms
|
300 |
-
add_action( 'login_form', function () {
|
301 |
-
global $wp_cerber;
|
302 |
-
$wp_cerber->reCaptcha( 'widget', 'recaplogin' );
|
303 |
-
} );
|
304 |
-
add_filter( 'login_form_middle', function ( $value ) {
|
305 |
-
global $wp_cerber;
|
306 |
-
$value .= $wp_cerber->reCaptcha( 'widget', 'recaplogin', false );
|
307 |
-
return $value;
|
308 |
-
});
|
309 |
-
add_action( 'lostpassword_form', function () {
|
310 |
-
global $wp_cerber;
|
311 |
-
$wp_cerber->reCaptcha( 'widget', 'recaplost' );
|
312 |
-
} );
|
313 |
-
add_action( 'register_form', function () {
|
314 |
-
global $wp_cerber;
|
315 |
-
if ( !did_action( 'woocommerce_register_form_start' ) ) {
|
316 |
-
$wp_cerber->reCaptcha( 'widget', 'recapreg' );
|
317 |
-
}
|
318 |
-
} );
|
319 |
-
|
320 |
-
// Support for WooCommerce forms: @since 3.8
|
321 |
-
add_action( 'woocommerce_login_form', function () {
|
322 |
-
global $wp_cerber;
|
323 |
-
$wp_cerber->reCaptcha( 'widget', 'recapwoologin' );
|
324 |
-
} );
|
325 |
-
add_action( 'woocommerce_lostpassword_form', function () {
|
326 |
-
global $wp_cerber;
|
327 |
-
$wp_cerber->reCaptcha( 'widget', 'recapwoolost' );
|
328 |
-
} );
|
329 |
-
add_action( 'woocommerce_register_form', function () {
|
330 |
-
global $wp_cerber;
|
331 |
-
if ( ! did_action( 'woocommerce_register_form_start' ) ) {
|
332 |
-
return;
|
333 |
-
}
|
334 |
-
$wp_cerber->reCaptcha( 'widget', 'recapwooreg' );
|
335 |
-
} );
|
336 |
-
add_filter( 'woocommerce_process_login_errors', function ( $validation_error ) {
|
337 |
-
global $wp_cerber;
|
338 |
-
//$wp_cerber->reCaptchaNow();
|
339 |
-
if ( ! $wp_cerber->reCaptchaValidate('woologin', true) ) {
|
340 |
-
|
341 |
-
return new WP_Error( 'incorrect_recaptcha', $wp_cerber->reCaptchaMsg('woocommerce-login'));
|
342 |
-
}
|
343 |
-
return $validation_error;
|
344 |
-
});
|
345 |
-
add_filter( 'allow_password_reset', function ( $var ) { // Note: 'allow_password_reset' also is fired in WP itself
|
346 |
-
global $wp_cerber;
|
347 |
-
if ( isset( $_POST['wc_reset_password'] ) && did_action( 'woocommerce_init' )) {
|
348 |
-
//$wp_cerber->reCaptchaNow();
|
349 |
-
if ( ! $wp_cerber->reCaptchaValidate( 'woolost' , true) ) {
|
350 |
-
|
351 |
-
return new WP_Error( 'incorrect_recaptcha', $wp_cerber->reCaptchaMsg('woocommerce-lost'));
|
352 |
-
}
|
353 |
-
}
|
354 |
-
return $var;
|
355 |
-
});
|
356 |
-
add_filter( 'woocommerce_process_registration_errors', function ( $validation_error ) {
|
357 |
-
global $wp_cerber;
|
358 |
-
//$wp_cerber->reCaptchaNow();
|
359 |
-
if ( ! $wp_cerber->reCaptchaValidate('wooreg' , true) ) {
|
360 |
-
|
361 |
-
return new WP_Error( 'incorrect_recaptcha', $wp_cerber->reCaptchaMsg('woocommerce-register'));
|
362 |
-
}
|
363 |
-
return $validation_error;
|
364 |
-
});
|
365 |
-
|
366 |
-
}
|
367 |
-
|
368 |
-
/**
|
369 |
-
* Generates reCAPTCHA HTML
|
370 |
-
*
|
371 |
-
* @param string $part 'style' or 'widget'
|
372 |
-
* @param null $option what plugin setting must be set to show the reCAPTCHA
|
373 |
-
* @param bool $echo if false, return the code, otherwise show it
|
374 |
-
*
|
375 |
-
* @return null|string
|
376 |
-
*/
|
377 |
-
final public function reCaptcha( $part = '', $option = null, $echo = true ) {
|
378 |
-
if ( $this->status == 4 || empty( $this->options['sitekey'] ) || empty( $this->options['secretkey'] )
|
379 |
-
|| ( $option && empty( $this->options[ $option ] ) )
|
380 |
-
) {
|
381 |
-
return null;
|
382 |
-
}
|
383 |
-
|
384 |
-
$sitekey = $this->options['sitekey'];
|
385 |
-
$ret = '';
|
386 |
-
|
387 |
-
switch ( $part ) {
|
388 |
-
case 'style': // for default login WP form only - fit it in width nicely.
|
389 |
-
?>
|
390 |
-
<style type="text/css" media="all">
|
391 |
-
#rc-imageselect, .g-recaptcha {
|
392 |
-
transform: scale(0.9);
|
393 |
-
-webkit-transform: scale(0.9);
|
394 |
-
transform-origin: 0 0;
|
395 |
-
-webkit-transform-origin: 0 0;
|
396 |
-
}
|
397 |
-
|
398 |
-
.g-recaptcha {
|
399 |
-
margin: 16px 0 20px 0;
|
400 |
-
}
|
401 |
-
</style>
|
402 |
-
<?php
|
403 |
-
break;
|
404 |
-
case 'widget':
|
405 |
-
if ( ! empty( $this->options[ $option ] ) ) {
|
406 |
-
$this->recaptcha_here = true;
|
407 |
-
|
408 |
-
//if ($this->options['invirecap']) $ret = '<div data-size="invisible" class="g-recaptcha" data-sitekey="' . $sitekey . '" data-callback="now_submit_the_form" id="cerber-recaptcha" data-badge="bottomright"></div>';
|
409 |
-
if ($this->options['invirecap']) {
|
410 |
-
$ret = '<span class="cerber-form-marker"></span><div data-size="invisible" class="g-recaptcha" data-sitekey="' . $sitekey . '" data-callback="now_submit_the_form" id="cerber-recaptcha" data-badge="bottomright"></div>';
|
411 |
-
}
|
412 |
-
else $ret = '<span class="cerber-form-marker"></span><div class="g-recaptcha" data-sitekey="' . $sitekey . '" data-callback="form_button_enabler" id="cerber-recaptcha"></div>';
|
413 |
-
|
414 |
-
//$ret = '<span class="cerber-form-marker g-recaptcha"></span>';
|
415 |
-
|
416 |
-
}
|
417 |
-
break;
|
418 |
-
}
|
419 |
-
if ( $echo ) {
|
420 |
-
echo $ret;
|
421 |
-
$ret = null;
|
422 |
-
}
|
423 |
-
|
424 |
-
return $ret;
|
425 |
-
/*
|
426 |
-
<script type="text/javascript">
|
427 |
-
var onloadCallback = function() {
|
428 |
-
//document.getElementById("wp-submit").disabled = true;
|
429 |
-
grecaptcha.render("c-recaptcha", {"sitekey" : "<?php echo $sitekey; ?>" });
|
430 |
-
//document.getElementById("wp-submit").disabled = false;
|
431 |
-
};
|
432 |
-
</script>
|
433 |
-
<script src = "https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit&hl=<?php echo $lang; ?>" async defer></script>
|
434 |
-
*/
|
435 |
-
}
|
436 |
-
|
437 |
-
/**
|
438 |
-
* Validate reCAPTCHA by calling Google service
|
439 |
-
*
|
440 |
-
* @param string $form Form ID (slug)
|
441 |
-
* @param boolean $force Force validate without pre-checks
|
442 |
-
*
|
443 |
-
* @return bool true on success false on failure
|
444 |
-
*/
|
445 |
-
final public function reCaptchaValidate($form = null, $force = false) {
|
446 |
-
if (!$force) {
|
447 |
-
if ( ! $this->recaptcha || $this->status == 4 ) {
|
448 |
-
return true;
|
449 |
-
}
|
450 |
-
}
|
451 |
-
|
452 |
-
if ($this->recaptcha_verified != null) return $this->recaptcha_verified;
|
453 |
-
|
454 |
-
if ( $form == 'comment' && $this->options['recapcomauth'] && is_user_logged_in()) return true;
|
455 |
-
|
456 |
-
if ( ! $form ) {
|
457 |
-
$form = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : 'login';
|
458 |
-
}
|
459 |
-
|
460 |
-
$forms = array( // known pairs: form => specific plugin setting
|
461 |
-
'lostpassword' => 'recaplost',
|
462 |
-
'register' => 'recapreg',
|
463 |
-
'login' => 'recaplogin',
|
464 |
-
'comment' => 'recapcom',
|
465 |
-
'woologin' => 'recapwoologin',
|
466 |
-
'woolost' => 'recapwoolost',
|
467 |
-
'wooreg' => 'recapwooreg',
|
468 |
-
);
|
469 |
-
|
470 |
-
if ( isset( $forms[ $form ] ) ) {
|
471 |
-
if ( empty( $this->options[ $forms[ $form ] ] ) ) {
|
472 |
-
return true; // no validation is required
|
473 |
-
}
|
474 |
-
}
|
475 |
-
else {
|
476 |
-
return true; // we don't know this form
|
477 |
-
}
|
478 |
-
|
479 |
-
if ( empty( $_POST['g-recaptcha-response'] ) ) {
|
480 |
-
$this->reCaptchaFailed($form);
|
481 |
-
return false;
|
482 |
-
}
|
483 |
-
|
484 |
-
$result = $this->reCaptchaRequest($_POST['g-recaptcha-response']);
|
485 |
-
if ( ! $result ) {
|
486 |
-
cerber_log( 42 );
|
487 |
-
return false;
|
488 |
-
}
|
489 |
-
|
490 |
-
$result = json_decode( $result );
|
491 |
-
$result = obj_to_arr_deep( $result );
|
492 |
-
|
493 |
-
if ( ! empty( $result['success'] ) ) {
|
494 |
-
$this->recaptcha_verified = true;
|
495 |
-
return true;
|
496 |
-
}
|
497 |
-
$this->recaptcha_verified = false;
|
498 |
-
|
499 |
-
if ( ! empty( $result['error-codes'] ) ) {
|
500 |
-
if ( in_array( 'invalid-input-secret', (array) $result['error-codes'] ) ) {
|
501 |
-
cerber_log( 41 );
|
502 |
-
}
|
503 |
-
}
|
504 |
-
|
505 |
-
$this->reCaptchaFailed($form);
|
506 |
-
|
507 |
-
return false;
|
508 |
-
}
|
509 |
-
|
510 |
-
final function reCaptchaFailed($context = '') {
|
511 |
-
cerber_log( 40 );
|
512 |
-
if ($this->options['recaptcha-period'] && $this->options['recaptcha-number'] && $this->options['recaptcha-within']) {
|
513 |
-
$remain = cerber_get_remain_count($this->remote_ip , true, 40, $this->options['recaptcha-number'], $this->options['recaptcha-within']);
|
514 |
-
if ($remain < 1) cerber_block_add( $this->remote_ip, 5 );
|
515 |
-
}
|
516 |
-
}
|
517 |
-
|
518 |
-
/**
|
519 |
-
* A form with possible reCAPTCHA has been submitted.
|
520 |
-
* Allow to process reCAPTCHA by setting a global flag.
|
521 |
-
* Must be called before reCaptchaValidate();
|
522 |
-
*
|
523 |
-
*/
|
524 |
-
final public function reCaptchaNow() {
|
525 |
-
if ( cerber_is_http_post() && $this->options['sitekey'] && $this->options['secretkey'] ) {
|
526 |
-
$this->recaptcha = true;
|
527 |
-
}
|
528 |
-
}
|
529 |
-
|
530 |
-
/**
|
531 |
-
* Make a request to the Google reCaptcha web service
|
532 |
-
*
|
533 |
-
* @param string $response Google specific field from the submitted form (widget)
|
534 |
-
*
|
535 |
-
* @return bool|string Response of the Google service or false on failure
|
536 |
-
*/
|
537 |
-
final public function reCaptchaRequest($response = ''){
|
538 |
-
|
539 |
-
if (!$response) {
|
540 |
-
if (!empty($_POST['g-recaptcha-response'])) $response = $_POST['g-recaptcha-response'];
|
541 |
-
else return false;
|
542 |
-
}
|
543 |
-
|
544 |
-
$curl = @curl_init(); // @since 4.32
|
545 |
-
if (!$curl) {
|
546 |
-
cerber_admin_notice(__( 'ERROR:', 'wp-cerber' ) .' Unable to initialize cURL');
|
547 |
-
return false;
|
548 |
-
}
|
549 |
-
|
550 |
-
$opt = curl_setopt_array($curl, array(
|
551 |
-
CURLOPT_URL => GOO_RECAPTCHA_URL,
|
552 |
-
CURLOPT_POST => true,
|
553 |
-
CURLOPT_POSTFIELDS => array( 'secret' => $this->options['secretkey'], 'response' => $response ),
|
554 |
-
CURLOPT_RETURNTRANSFER => true,
|
555 |
-
));
|
556 |
-
|
557 |
-
if (!$opt) {
|
558 |
-
cerber_admin_notice(__( 'ERROR:', 'wp-cerber' ) .' '. curl_error($curl));
|
559 |
-
curl_close($curl);
|
560 |
-
return false;
|
561 |
-
}
|
562 |
-
|
563 |
-
$result = curl_exec($curl);
|
564 |
-
if (!$result) {
|
565 |
-
cerber_admin_notice(__( 'ERROR:', 'wp-cerber' ) .' '. curl_error($curl));
|
566 |
-
$result = false;
|
567 |
-
}
|
568 |
-
curl_close($curl);
|
569 |
-
|
570 |
-
return $result;
|
571 |
-
|
572 |
-
}
|
573 |
-
|
574 |
-
final public function reCaptchaMsg($context = null){
|
575 |
-
return apply_filters( 'cerber_msg_recaptcha', __( 'Human verification failed. Please click the square box in the reCAPTCHA block below.', 'wp-cerber' ), $context);
|
576 |
-
}
|
577 |
-
|
578 |
-
final public function setLocked() {
|
579 |
-
if ( ! isset( $this->locked ) ) {
|
580 |
-
$this->locked = 1;
|
581 |
-
}
|
582 |
-
}
|
583 |
-
|
584 |
-
final public function isLocked() {
|
585 |
-
if ( ! empty( $this->locked ) ) {
|
586 |
-
return 1;
|
587 |
-
}
|
588 |
-
return 0;
|
589 |
-
}
|
590 |
-
|
591 |
-
final public function deleteGarbage() {
|
592 |
-
global $wpdb;
|
593 |
-
if ( $this->garbage ) {
|
594 |
-
return;
|
595 |
-
}
|
596 |
-
$wpdb->query( 'DELETE FROM ' . CERBER_BLOCKS_TABLE . ' WHERE block_until < ' . time() );
|
597 |
-
$this->garbage = true;
|
598 |
-
}
|
599 |
-
}
|
600 |
-
|
601 |
-
global $wp_cerber;
|
602 |
-
//$wp_cerber = new WP_Cerber();
|
603 |
-
$wp_cerber = get_wp_cerber();
|
604 |
-
|
605 |
-
/**
|
606 |
-
* Return correct WP_Cerber object
|
607 |
-
* Set global $wp_cerber
|
608 |
-
*
|
609 |
-
* @return WP_Cerber
|
610 |
-
* @since 6.0
|
611 |
-
*/
|
612 |
-
function get_wp_cerber(){
|
613 |
-
global $wp_cerber;
|
614 |
-
|
615 |
-
if ( ! is_object( $wp_cerber ) || !($wp_cerber instanceof WP_Cerber)) {
|
616 |
-
$wp_cerber = new WP_Cerber();
|
617 |
-
}
|
618 |
-
|
619 |
-
return $wp_cerber;
|
620 |
-
}
|
621 |
-
|
622 |
-
/**
|
623 |
-
*
|
624 |
-
* Initialize Cerber Security
|
625 |
-
*
|
626 |
-
*/
|
627 |
-
add_action( 'plugins_loaded', function () {
|
628 |
-
|
629 |
-
get_wp_cerber();
|
630 |
-
|
631 |
-
load_plugin_textdomain( 'wp-cerber', false, basename( dirname( __FILE__ ) ) . '/languages' );
|
632 |
-
|
633 |
-
/* @since 5.8.8
|
634 |
-
if ( ! cerber_check_groove() && ! cerber_is_allowed() ) {
|
635 |
-
wp_clear_auth_cookie();
|
636 |
-
}*/
|
637 |
-
|
638 |
-
cerber_init_cron();
|
639 |
-
|
640 |
-
__('> > > Translator of WP Cerber? To get the PRO license for free, drop your contacts here: https://wpcerber.com/contact/','wp-cerber');
|
641 |
-
|
642 |
-
}, 1000 );
|
643 |
-
|
644 |
-
/**
|
645 |
-
* Some additional tasks...
|
646 |
-
*
|
647 |
-
*/
|
648 |
-
add_action( 'shutdown', function () {
|
649 |
-
global $wpdb, $wp_cerber, $cerber_logged, $cerber_status;
|
650 |
-
|
651 |
-
if ( empty( $cerber_logged ) ) {
|
652 |
-
return;
|
653 |
-
}
|
654 |
-
|
655 |
-
// Multiple different malicious activities
|
656 |
-
$black = crb_get_activity_set('black');
|
657 |
-
$no_good = array_intersect( $black, $cerber_logged );
|
658 |
-
if ( ! empty( $no_good ) && cerber_is_allowed() ) {
|
659 |
-
$ip = $wp_cerber->getRemoteIp();
|
660 |
-
$in = implode( ',', $black );
|
661 |
-
$range = time() - 600;
|
662 |
-
$count = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_LOG_TABLE . ' WHERE ip = "' . $ip . '" AND activity IN (' . $in . ') AND stamp > ' . $range );
|
663 |
-
if ( $count >= 3 ) {
|
664 |
-
cerber_soft_block_add( $ip, 7 );
|
665 |
-
$cerber_status = 18;
|
666 |
-
}
|
667 |
-
}
|
668 |
-
|
669 |
-
} );
|
670 |
-
|
671 |
-
/*
|
672 |
-
Display login form if Custom login URL has been requested
|
673 |
-
|
674 |
-
*/
|
675 |
-
add_action( 'init', 'cerber_wp_login_page', 20 );
|
676 |
-
//add_action( 'setup_theme', 'cerber_wp_login_page' ); // @since 5.05
|
677 |
-
function cerber_wp_login_page() {
|
678 |
-
if ( $path = crb_get_settings( 'loginpath' ) ) {
|
679 |
-
if ( cerber_is_login_request() ) {
|
680 |
-
if ( ! defined( 'DONOTCACHEPAGE' ) ) {
|
681 |
-
define( 'DONOTCACHEPAGE', true ); // @since 5.7.6
|
682 |
-
}
|
683 |
-
require( ABSPATH . WP_LOGIN_SCRIPT ); // load default wp-login.php form
|
684 |
-
exit;
|
685 |
-
}
|
686 |
-
}
|
687 |
-
}
|
688 |
-
|
689 |
-
/**
|
690 |
-
* Check if the current HTTP request is a login/register/lost password page request
|
691 |
-
*
|
692 |
-
* @return bool
|
693 |
-
*/
|
694 |
-
function cerber_is_login_request() {
|
695 |
-
if ( $path = crb_get_settings( 'loginpath' ) ) {
|
696 |
-
$request = $_SERVER['REQUEST_URI'];
|
697 |
-
if ( $pos = strpos( $request, '?' ) ) {
|
698 |
-
$request = substr( $request, 0, $pos - 1 ); // @since 4.8
|
699 |
-
}
|
700 |
-
$request = explode( '/', rtrim( $request, '/' ) );
|
701 |
-
$request = end( $request ); // @since 4.8
|
702 |
-
if ( $path == $request && ! cerber_is_rest_url() ) {
|
703 |
-
return true;
|
704 |
-
}
|
705 |
-
}
|
706 |
-
//elseif ( strtolower( cerber_parse_uri( true ) ) == WP_LOGIN_SCRIPT ) {
|
707 |
-
elseif ( cerber_get_uri_script() == WP_LOGIN_SCRIPT ) {
|
708 |
-
return true;
|
709 |
-
}
|
710 |
-
|
711 |
-
return false;
|
712 |
-
}
|
713 |
-
|
714 |
-
/*
|
715 |
-
Create message to show it above login form for any simply GET
|
716 |
-
*/
|
717 |
-
add_action( 'login_head', 'cerber_login_head' );
|
718 |
-
function cerber_login_head() {
|
719 |
-
global $error, $wp_cerber;
|
720 |
-
|
721 |
-
if ( !$allowed = cerber_is_allowed() ) :
|
722 |
-
?>
|
723 |
-
<style type="text/css" media="all">
|
724 |
-
#logidnform {
|
725 |
-
display: none;
|
726 |
-
}
|
727 |
-
</style>
|
728 |
-
<?php
|
729 |
-
endif;
|
730 |
-
|
731 |
-
$wp_cerber->reCaptcha( 'style' );
|
732 |
-
|
733 |
-
if ( !cerber_is_http_get() ) {
|
734 |
-
return;
|
735 |
-
}
|
736 |
-
if ( ! cerber_can_msg() ) {
|
737 |
-
return;
|
738 |
-
}
|
739 |
-
if ( ! $allowed ) {
|
740 |
-
$error = $wp_cerber->getErrorMsg();
|
741 |
-
}
|
742 |
-
elseif ( $msg = $wp_cerber->getRemainMsg() ) {
|
743 |
-
$error = $msg;
|
744 |
-
}
|
745 |
-
}
|
746 |
-
|
747 |
-
/**
|
748 |
-
* Control the process of authentication
|
749 |
-
*
|
750 |
-
* @since 2.9
|
751 |
-
*
|
752 |
-
*/
|
753 |
-
remove_filter( 'authenticate', 'wp_authenticate_username_password', 20 );
|
754 |
-
add_filter( 'authenticate', 'cerber_auth_control', 20, 3 );
|
755 |
-
function cerber_auth_control( $null, $username, $password ) {
|
756 |
-
global $wp_cerber;
|
757 |
-
|
758 |
-
if ( ! $wp_cerber->reCaptchaValidate() ) {
|
759 |
-
|
760 |
-
return new WP_Error( 'incorrect_recaptcha',
|
761 |
-
'<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
|
762 |
-
$wp_cerber->reCaptchaMsg('login'));
|
763 |
-
}
|
764 |
-
|
765 |
-
// Check for prohibited username
|
766 |
-
//if ( $wp_cerber->isProhibited( $username ) ) {
|
767 |
-
if ( cerber_is_prohibited( $username ) ) {
|
768 |
-
cerber_log( 52, $username );
|
769 |
-
cerber_block_add( null, 4, $username );
|
770 |
-
|
771 |
-
// Create with message that is identical default WP
|
772 |
-
return new WP_Error( 'incorrect_password', sprintf(
|
773 |
-
__( '<strong>ERROR</strong>: The password you entered for the username %s is incorrect.' ),
|
774 |
-
'<strong>' . $username . '</strong>'
|
775 |
-
) );
|
776 |
-
}
|
777 |
-
/*
|
778 |
-
if ( lab_is_blocked($wp_cerber->getRemoteIp()) ) {
|
779 |
-
|
780 |
-
// Create with message which is identical default WP
|
781 |
-
return new WP_Error( 'incorrect_password', sprintf(
|
782 |
-
__( '<strong>ERROR</strong>: The password you entered for the username %s is incorrect.' ),
|
783 |
-
'<strong>' . $username . '</strong>'
|
784 |
-
) );
|
785 |
-
}*/
|
786 |
-
|
787 |
-
$user = wp_authenticate_username_password( $null, $username, $password );
|
788 |
-
|
789 |
-
// @since 4.18 it is replacement for 'wp_login_failed' action hook
|
790 |
-
// see WP function wp_authenticate()
|
791 |
-
$ignore_codes = array( 'empty_username', 'empty_password', 'cerber_denied' );
|
792 |
-
if ( is_wp_error( $user ) && ! in_array( $user->get_error_code(), $ignore_codes ) ) {
|
793 |
-
cerber_login_failed( $username );
|
794 |
-
}
|
795 |
-
|
796 |
-
return $user;
|
797 |
-
}
|
798 |
-
|
799 |
-
/*
|
800 |
-
Block authentication for an existing user if the remote IP is not allowed.
|
801 |
-
Invoking in the 'wp_authenticate_username_password()'
|
802 |
-
*/
|
803 |
-
add_filter( 'wp_authenticate_user', 'cerber_stop_authentication', 9999, 2 ); // fires after user found, with 'authenticate' filter
|
804 |
-
function cerber_stop_authentication( $user, $password ) {
|
805 |
-
global $wp_cerber, $cerber_status;
|
806 |
-
|
807 |
-
$deny = false;
|
808 |
-
|
809 |
-
if ( ! cerber_is_allowed() ) {
|
810 |
-
$deny = true;
|
811 |
-
}
|
812 |
-
elseif ( ! cerber_geo_allowed( 'geo_login' ) ) {
|
813 |
-
$cerber_status = 16;
|
814 |
-
$deny = true;
|
815 |
-
}
|
816 |
-
elseif ( lab_is_blocked( $wp_cerber->getRemoteIp() ) ) {
|
817 |
-
$cerber_status = 15;
|
818 |
-
$deny = true;
|
819 |
-
}
|
820 |
-
|
821 |
-
if ( $deny ) {
|
822 |
-
status_header( 403 );
|
823 |
-
$error = new WP_Error();
|
824 |
-
$error->add( 'cerber_wp_error', $wp_cerber->getErrorMsg() );
|
825 |
-
|
826 |
-
return $error;
|
827 |
-
}
|
828 |
-
|
829 |
-
return $user;
|
830 |
-
}
|
831 |
-
|
832 |
-
/*
|
833 |
-
* Handler for failed login attempts
|
834 |
-
*
|
835 |
-
*/
|
836 |
-
//add_action( 'wp_login_failed', 'cerber_login_failed' ); // @since 4.18
|
837 |
-
function cerber_login_failed( $user_login ) {
|
838 |
-
global $wpdb, $wp_cerber, $cerber_status;
|
839 |
-
static $is_processed = false;
|
840 |
-
|
841 |
-
if ( $is_processed ) return;
|
842 |
-
$is_processed = true;
|
843 |
-
|
844 |
-
$ip = $wp_cerber->getRemoteIp();
|
845 |
-
$acl = cerber_acl_check( $ip );
|
846 |
-
if ( ! cerber_get_user( $user_login ) ) {
|
847 |
-
$no_user = true;
|
848 |
-
}
|
849 |
-
else {
|
850 |
-
$no_user = false;
|
851 |
-
}
|
852 |
-
|
853 |
-
//cerber_failed_work($ip, $acl, $no_user, $user_login);
|
854 |
-
|
855 |
-
//if ( ! $wp_cerber->isProcessed() ) {
|
856 |
-
//if ( ! cerber_get_user( $user_login ) ) {
|
857 |
-
// $no_user = true;
|
858 |
-
//}
|
859 |
-
|
860 |
-
$ac = 7;
|
861 |
-
|
862 |
-
if ( $no_user ) {
|
863 |
-
$ac = 51;
|
864 |
-
}
|
865 |
-
elseif ( ! cerber_is_allowed( $ip ) || $cerber_status == 15 || $cerber_status == 16 ) { // TODO should be refactored together with cerber_stop_authentication
|
866 |
-
$ac = 53;
|
867 |
-
}
|
868 |
-
/*
|
869 |
-
elseif ( $acl == 'B' ) {
|
870 |
-
$ac = 14;
|
871 |
-
}
|
872 |
-
elseif ( lab_is_blocked($ip, false) ) {
|
873 |
-
$ac = 53;
|
874 |
-
}
|
875 |
-
else {
|
876 |
-
$ac = 53;
|
877 |
-
}*/
|
878 |
-
|
879 |
-
cerber_log( $ac, $user_login );
|
880 |
-
|
881 |
-
//}
|
882 |
-
|
883 |
-
|
884 |
-
// White? Stop further actions.
|
885 |
-
if ( $acl == 'W' && !crb_get_settings( 'limitwhite' )) {
|
886 |
-
return;
|
887 |
-
}
|
888 |
-
|
889 |
-
if ( crb_get_settings( 'usefile' ) ) {
|
890 |
-
cerber_file_log( $user_login, $ip );
|
891 |
-
}
|
892 |
-
|
893 |
-
if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) { // Needs additional researching and, maybe, refactoring
|
894 |
-
status_header( 403 );
|
895 |
-
}
|
896 |
-
|
897 |
-
// Blacklisted? No more actions are needed.
|
898 |
-
if ( $acl == 'B' ) {
|
899 |
-
return;
|
900 |
-
}
|
901 |
-
|
902 |
-
// Must the Citadel mode be activated?
|
903 |
-
if ( $wp_cerber->getSettings( 'ciperiod' ) && ! cerber_is_citadel() ) {
|
904 |
-
$range = time() - $wp_cerber->getSettings( 'ciperiod' ) * 60;
|
905 |
-
$lockouts = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_LOG_TABLE . ' WHERE activity IN (7,51,52) AND stamp > ' . $range );
|
906 |
-
if ( $lockouts >= $wp_cerber->getSettings( 'cilimit' ) ) {
|
907 |
-
cerber_enable_citadel();
|
908 |
-
}
|
909 |
-
}
|
910 |
-
|
911 |
-
if ( $no_user && $wp_cerber->getSettings( 'nonusers' ) ) {
|
912 |
-
cerber_block_add( $ip, 3, $user_login); // @since 5.7
|
913 |
-
}
|
914 |
-
elseif ( cerber_get_remain_count($ip, false) < 1 ) { //Limit on the number of login attempts is reached
|
915 |
-
cerber_block_add( $ip, 1, '', null, false);
|
916 |
-
}
|
917 |
-
|
918 |
-
}
|
919 |
-
|
920 |
-
/**
|
921 |
-
* Do the work with failed/blocked attempt
|
922 |
-
*
|
923 |
-
* @param $ip
|
924 |
-
* @param $acl
|
925 |
-
* @param $user_login
|
926 |
-
*/
|
927 |
-
function cerber_failed_work($ip, $acl, $no_user, $user_login){
|
928 |
-
global $wpdb, $wp_cerber;
|
929 |
-
|
930 |
-
// White? Stop further actions.
|
931 |
-
if ( $acl == 'W' && !$wp_cerber->getSettings( 'limitwhite' )) {
|
932 |
-
return;
|
933 |
-
}
|
934 |
-
|
935 |
-
if ( $wp_cerber->getSettings( 'usefile' ) ) {
|
936 |
-
cerber_file_log( $user_login, $ip );
|
937 |
-
}
|
938 |
-
|
939 |
-
if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) { // Needs additional researching and, maybe, refactoring
|
940 |
-
status_header( 403 );
|
941 |
-
}
|
942 |
-
|
943 |
-
// Blacklisted? No more actions are needed.
|
944 |
-
if ( $acl == 'B' ) {
|
945 |
-
return;
|
946 |
-
}
|
947 |
-
|
948 |
-
// Must the Citadel mode be activated?
|
949 |
-
if ( $wp_cerber->getSettings( 'ciperiod' ) && ! cerber_is_citadel() ) {
|
950 |
-
$range = time() - $wp_cerber->getSettings( 'ciperiod' ) * 60;
|
951 |
-
$lockouts = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_LOG_TABLE . ' WHERE activity IN (7,51,52) AND stamp > ' . $range );
|
952 |
-
if ( $lockouts >= $wp_cerber->getSettings( 'cilimit' ) ) {
|
953 |
-
cerber_enable_citadel();
|
954 |
-
}
|
955 |
-
}
|
956 |
-
|
957 |
-
if ( $no_user && $wp_cerber->getSettings( 'nonusers' ) ) {
|
958 |
-
cerber_block_add( $ip, 3, $user_login );
|
959 |
-
}
|
960 |
-
elseif ( cerber_get_remain_count($ip, false) <= 1 ) { //Limit on the number of login attempts is reached
|
961 |
-
cerber_block_add( $ip, 1, '', null, false);
|
962 |
-
}
|
963 |
-
}
|
964 |
-
|
965 |
-
// Registration -----------------------------------------------------------------------
|
966 |
-
|
967 |
-
function cerber_is_registration_prohibited( $sanitized_user_login ) {
|
968 |
-
global $wp_cerber, $cerber_status;
|
969 |
-
|
970 |
-
$code = null;
|
971 |
-
$msg = null;
|
972 |
-
|
973 |
-
if (crb_is_reg_limit_reached()){
|
974 |
-
$cerber_status = 17;
|
975 |
-
cerber_log(54);
|
976 |
-
$code = 'ip_denied';
|
977 |
-
$msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
|
978 |
-
apply_filters( 'cerber_msg_denied', __( 'You are not allowed to register.', 'wp-cerber' ), 'register' );
|
979 |
-
}
|
980 |
-
elseif ( cerber_is_bot('botsreg') ) {
|
981 |
-
cerber_log(54); // TODO should be separate code to detect bot activity?
|
982 |
-
$code = 'bot_detected';
|
983 |
-
$msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
|
984 |
-
apply_filters( 'cerber_msg_denied', __( 'You are not allowed to register.', 'wp-cerber' ), 'register' );
|
985 |
-
}
|
986 |
-
elseif ( ! $wp_cerber->reCaptchaValidate() ) {
|
987 |
-
$code = 'incorrect_recaptcha';
|
988 |
-
$msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
|
989 |
-
$wp_cerber->reCaptchaMsg('register');
|
990 |
-
}
|
991 |
-
elseif ( cerber_is_prohibited( $sanitized_user_login ) ) {
|
992 |
-
$code = 'prohibited_login';
|
993 |
-
$msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
|
994 |
-
apply_filters( 'cerber_msg_prohibited', __( 'Username is not allowed. Please choose another one.', 'wp-cerber' ), 'register' );
|
995 |
-
}
|
996 |
-
elseif ( !cerber_is_allowed() || lab_is_blocked($wp_cerber->getRemoteIp()) ) {
|
997 |
-
cerber_log(54);
|
998 |
-
$code = 'ip_denied';
|
999 |
-
$msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
|
1000 |
-
apply_filters( 'cerber_msg_denied', __( 'You are not allowed to register.', 'wp-cerber' ), 'register' );
|
1001 |
-
}
|
1002 |
-
elseif ( ! cerber_geo_allowed( 'geo_register' ) ) {
|
1003 |
-
$cerber_status = 16; // TODO: refactor cerber_log, include this status as a second parameter
|
1004 |
-
cerber_log(54); // TODO should be separate code?
|
1005 |
-
$code = 'country_denied';
|
1006 |
-
$msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
|
1007 |
-
apply_filters( 'cerber_msg_denied', __( 'You are not allowed to register.', 'wp-cerber' ), 'register' );
|
1008 |
-
}
|
1009 |
-
|
1010 |
-
if ( $code ) {
|
1011 |
-
return array( $code, $msg );
|
1012 |
-
}
|
1013 |
-
|
1014 |
-
return null;
|
1015 |
-
}
|
1016 |
-
|
1017 |
-
/**
|
1018 |
-
* Limit on user registrations per IP
|
1019 |
-
*
|
1020 |
-
* @return bool
|
1021 |
-
*/
|
1022 |
-
function crb_is_reg_limit_reached() {
|
1023 |
-
global $wpdb, $wp_cerber;
|
1024 |
-
|
1025 |
-
if ( ! $wp_cerber->getSettings( 'reglimit_min' ) || ! $wp_cerber->getSettings( 'reglimit_num' ) ) {
|
1026 |
-
return false;
|
1027 |
-
}
|
1028 |
-
|
1029 |
-
if ( crb_acl_is_white() ) {
|
1030 |
-
return false;
|
1031 |
-
}
|
1032 |
-
|
1033 |
-
$ip = $wp_cerber->getRemoteIp();
|
1034 |
-
$stamp = absint( time() - 60 * $wp_cerber->getSettings( 'reglimit_min' ) );
|
1035 |
-
$count = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_LOG_TABLE . ' WHERE ip = "' . $ip . '" AND activity = 2 AND stamp > ' . $stamp );
|
1036 |
-
if ( $count > $wp_cerber->getSettings( 'reglimit_num' ) ) {
|
1037 |
-
lab_save_push( $ip, 344, '' );
|
1038 |
-
return true;
|
1039 |
-
}
|
1040 |
-
|
1041 |
-
return false;
|
1042 |
-
}
|
1043 |
-
|
1044 |
-
// Fires in register_new_user()
|
1045 |
-
add_filter( 'registration_errors', 'cerber_pre_new_user', 10, 3 );
|
1046 |
-
function cerber_pre_new_user( $errors, $sanitized_user_login, $user_email ) {
|
1047 |
-
global $wp_cerber, $cerber_status;
|
1048 |
-
|
1049 |
-
$prohibited = cerber_is_registration_prohibited( $sanitized_user_login );
|
1050 |
-
|
1051 |
-
if ($prohibited){
|
1052 |
-
return new WP_Error($prohibited[0], $prohibited[1]);
|
1053 |
-
}
|
1054 |
-
|
1055 |
-
return $errors;
|
1056 |
-
}
|
1057 |
-
|
1058 |
-
// @since 5.3
|
1059 |
-
// Fires in wp_insert_user()
|
1060 |
-
add_filter( 'pre_user_login', function ( $sanitized_user_login ) {
|
1061 |
-
|
1062 |
-
if ( cerber_is_registration_prohibited( $sanitized_user_login ) ) {
|
1063 |
-
return null;
|
1064 |
-
}
|
1065 |
-
|
1066 |
-
/*
|
1067 |
-
if ( ! cerber_is_allowed() ) {
|
1068 |
-
cerber_log( 54 );
|
1069 |
-
|
1070 |
-
return null;
|
1071 |
-
}
|
1072 |
-
if ( ! cerber_geo_allowed( 'geo_register' ) ) {
|
1073 |
-
$cerber_status = 16;
|
1074 |
-
cerber_log( 54 );
|
1075 |
-
|
1076 |
-
return null;
|
1077 |
-
}
|
1078 |
-
*/
|
1079 |
-
return $sanitized_user_login;
|
1080 |
-
}, 9999 );
|
1081 |
-
|
1082 |
-
// Filter out prohibited usernames
|
1083 |
-
add_filter( 'illegal_user_logins', function () {
|
1084 |
-
return (array) crb_get_settings( 'prohibited' );
|
1085 |
-
}, 9999 );
|
1086 |
-
|
1087 |
-
add_filter( 'option_users_can_register', function ( $value ) {
|
1088 |
-
//if ( ! cerber_is_allowed() || !cerber_geo_allowed( 'geo_register' )) {
|
1089 |
-
if ( ! cerber_is_allowed() || crb_is_reg_limit_reached() ) {
|
1090 |
-
return false;
|
1091 |
-
}
|
1092 |
-
|
1093 |
-
return $value;
|
1094 |
-
}, 9999 );
|
1095 |
-
|
1096 |
-
// Lost password form --------------------------------------------------------------------
|
1097 |
-
|
1098 |
-
/**
|
1099 |
-
* Validate reCAPTCHA for the WordPress lost password form
|
1100 |
-
*/
|
1101 |
-
add_action( 'login_form_' . 'lostpassword', 'cerber_lost_captcha' );
|
1102 |
-
function cerber_lost_captcha() {
|
1103 |
-
global $wp_cerber, $cerber_lost;
|
1104 |
-
if ( ! $wp_cerber->reCaptchaValidate() ) {
|
1105 |
-
$_POST['user_login'] = null; // workaround due to lack of any way to control lost password form
|
1106 |
-
$cerber_lost = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' . $wp_cerber->reCaptchaMsg('lostpassword');
|
1107 |
-
}
|
1108 |
-
}
|
1109 |
-
/**
|
1110 |
-
* Display message on the WordPress lost password form screen
|
1111 |
-
*/
|
1112 |
-
add_action( 'lostpassword_form', 'cerber_lost_show_msg' );
|
1113 |
-
function cerber_lost_show_msg() {
|
1114 |
-
global $cerber_lost;
|
1115 |
-
if ( ! $cerber_lost ) {
|
1116 |
-
return;
|
1117 |
-
}
|
1118 |
-
?>
|
1119 |
-
<script type="text/javascript">
|
1120 |
-
//document.getElementById('login_error').style.visibility = "hidden";
|
1121 |
-
document.getElementById('login_error').innerHTML = "<?php echo $cerber_lost; ?>";
|
1122 |
-
</script>
|
1123 |
-
<?php
|
1124 |
-
}
|
1125 |
-
|
1126 |
-
|
1127 |
-
// Comments (commenting) section ----------------------------------------------------------
|
1128 |
-
|
1129 |
-
/**
|
1130 |
-
* If a comment must be marked as spam
|
1131 |
-
*
|
1132 |
-
*/
|
1133 |
-
add_filter( 'pre_comment_approved', function ( $approved, $commentdata ) {
|
1134 |
-
if ( 1 == crb_get_settings( 'spamcomm' ) && ! cerber_is_comment_allowed() ) {
|
1135 |
-
$approved = 'spam';
|
1136 |
-
}
|
1137 |
-
|
1138 |
-
return $approved;
|
1139 |
-
}, 10, 2 );
|
1140 |
-
|
1141 |
-
/**
|
1142 |
-
* If a comment must be denied
|
1143 |
-
*
|
1144 |
-
*/
|
1145 |
-
add_action( 'pre_comment_on_post', function ( $comment_post_ID ) {
|
1146 |
-
global $cerber_status;
|
1147 |
-
|
1148 |
-
$deny = false;
|
1149 |
-
|
1150 |
-
if ( 1 != crb_get_settings( 'spamcomm' ) && ! cerber_is_comment_allowed() ) {
|
1151 |
-
$deny = true;
|
1152 |
-
}
|
1153 |
-
elseif ( ! cerber_geo_allowed( 'geo_comment' ) ) {
|
1154 |
-
$cerber_status = 16;
|
1155 |
-
cerber_log(19);
|
1156 |
-
$deny = true;
|
1157 |
-
}
|
1158 |
-
|
1159 |
-
if ( $deny ) {
|
1160 |
-
setcookie( 'cerber-post-id', $comment_post_ID, time() + 60, '/' );
|
1161 |
-
$comments = get_comments( array( 'number' => '1', 'post_id' => $comment_post_ID ) );
|
1162 |
-
if ( $comments ) {
|
1163 |
-
$loc = get_comment_link( $comments[0]->comment_ID );
|
1164 |
-
} else {
|
1165 |
-
$loc = get_permalink( $comment_post_ID ) . '#cerber-recaptcha-msg';
|
1166 |
-
}
|
1167 |
-
wp_safe_redirect( $loc );
|
1168 |
-
exit;
|
1169 |
-
}
|
1170 |
-
|
1171 |
-
} );
|
1172 |
-
|
1173 |
-
/**
|
1174 |
-
* If submit comments via REST API is not allowed
|
1175 |
-
*
|
1176 |
-
*/
|
1177 |
-
add_filter( 'rest_allow_anonymous_comments', function ( $allowed, $request ) {
|
1178 |
-
global $wp_cerber, $cerber_status;
|
1179 |
-
|
1180 |
-
if ( ! cerber_is_allowed() ) {
|
1181 |
-
$allowed = false;
|
1182 |
-
}
|
1183 |
-
if ( ! cerber_geo_allowed( 'geo_comment' ) ) {
|
1184 |
-
ceber_log(19);
|
1185 |
-
$cerber_status = 16;
|
1186 |
-
$allowed = false;
|
1187 |
-
}
|
1188 |
-
elseif ( lab_is_blocked( $wp_cerber->getRemoteIp() ) ) {
|
1189 |
-
$allowed = false;
|
1190 |
-
}
|
1191 |
-
|
1192 |
-
return $allowed;
|
1193 |
-
}, 10, 2 );
|
1194 |
-
|
1195 |
-
/**
|
1196 |
-
* Check if a submitted comment is allowed
|
1197 |
-
*
|
1198 |
-
* @return bool
|
1199 |
-
*/
|
1200 |
-
function cerber_is_comment_allowed(){
|
1201 |
-
global $wp_cerber;
|
1202 |
-
|
1203 |
-
if (is_admin()) return true;
|
1204 |
-
|
1205 |
-
$deny = null;
|
1206 |
-
|
1207 |
-
if ( ! cerber_is_allowed() ) {
|
1208 |
-
$deny = 19;
|
1209 |
-
}
|
1210 |
-
elseif ( cerber_is_bot('botscomm') ) {
|
1211 |
-
$remain = cerber_get_remain_count( null , true, 16, 3, 60);
|
1212 |
-
if ($remain < 1) cerber_block_add( null, 6, '', 60 );
|
1213 |
-
$deny = 16;
|
1214 |
-
}
|
1215 |
-
elseif ( ! $wp_cerber->reCaptchaValidate( 'comment' , true ) ) {
|
1216 |
-
$deny = 16;
|
1217 |
-
}
|
1218 |
-
elseif ( lab_is_blocked( $wp_cerber->getRemoteIp() ) ) {
|
1219 |
-
$deny = 19;
|
1220 |
-
}
|
1221 |
-
|
1222 |
-
if ( $deny ) {
|
1223 |
-
cerber_log( $deny );
|
1224 |
-
$ret = false;
|
1225 |
-
}
|
1226 |
-
else {
|
1227 |
-
$ret = true;
|
1228 |
-
}
|
1229 |
-
|
1230 |
-
return $ret;
|
1231 |
-
}
|
1232 |
-
|
1233 |
-
/**
|
1234 |
-
* Showing reCAPTCHA widget.
|
1235 |
-
* Displaying error message on the comment form for a human.
|
1236 |
-
*
|
1237 |
-
*/
|
1238 |
-
add_filter( 'comment_form_submit_field', function ( $value ) {
|
1239 |
-
global $wp_cerber, $post;
|
1240 |
-
|
1241 |
-
if ( ! empty( $_COOKIE["cerber-post-id"] ) && absint( $_COOKIE["cerber-post-id"] ) == $post->ID ) {
|
1242 |
-
//echo '<div id="cerber-recaptcha-msg">' . __( 'ERROR:', 'wp-cerber' ) . ' ' . $wp_cerber->reCaptchaMsg( 'comment' ) . '</div>';
|
1243 |
-
echo '<div id="cerber-recaptcha-msg">' . __( 'ERROR:', 'wp-cerber' ) . ' ' . __('Sorry, human verification failed.') . '</div>';
|
1244 |
-
echo '<script type="text/javascript">document.cookie = "cerber-post-id=0;path=/";</script>';
|
1245 |
-
}
|
1246 |
-
|
1247 |
-
$au = $wp_cerber->getSettings( 'recapcomauth' );
|
1248 |
-
if ( ! $au || ( $au && ! is_user_logged_in() ) ) {
|
1249 |
-
$wp_cerber->reCaptcha( 'widget', 'recapcom' );
|
1250 |
-
}
|
1251 |
-
|
1252 |
-
return $value;
|
1253 |
-
} );
|
1254 |
-
|
1255 |
-
|
1256 |
-
// Messages ----------------------------------------------------------------------
|
1257 |
-
|
1258 |
-
/**
|
1259 |
-
* Replace ANY system messages or add notify message above login form if IP is not allowed (blocked or locked out)
|
1260 |
-
*/
|
1261 |
-
add_filter( 'login_errors', 'cerber_login_form_msg' ); // hook on POST if credentials was wrong
|
1262 |
-
function cerber_login_form_msg( $errors ) {
|
1263 |
-
global $error, $wp_cerber;
|
1264 |
-
if ( cerber_can_msg() ) {
|
1265 |
-
if ( ! cerber_is_allowed() ) {
|
1266 |
-
$errors = $wp_cerber->getErrorMsg();
|
1267 |
-
}
|
1268 |
-
elseif ( ! $error && ( $msg = $wp_cerber->getRemainMsg() ) ) {
|
1269 |
-
$errors .= '<p>' . $msg;
|
1270 |
-
}
|
1271 |
-
}
|
1272 |
-
|
1273 |
-
return $errors;
|
1274 |
-
}
|
1275 |
-
|
1276 |
-
add_filter( 'shake_error_codes', 'cerber_login_failure_shake' ); // Shake it, baby!
|
1277 |
-
function cerber_login_failure_shake( $shake_error_codes ) {
|
1278 |
-
$shake_error_codes[] = 'cerber_wp_error';
|
1279 |
-
|
1280 |
-
return $shake_error_codes;
|
1281 |
-
}
|
1282 |
-
|
1283 |
-
/*
|
1284 |
-
Replace default login/logout URL with Custom login page URL
|
1285 |
-
*/
|
1286 |
-
add_filter( 'site_url', 'cerber_login_logout', 9999, 4 );
|
1287 |
-
add_filter( 'network_site_url', 'cerber_login_logout', 9999, 3 );
|
1288 |
-
function cerber_login_logout( $url, $path, $scheme, $blog_id = 0 ) { // $blog_id only for 'site_url'
|
1289 |
-
global $wp_cerber;
|
1290 |
-
if ( $login_path = $wp_cerber->getSettings( 'loginpath' ) ) {
|
1291 |
-
$url = str_replace( WP_LOGIN_SCRIPT, $login_path . '/', $url );
|
1292 |
-
}
|
1293 |
-
|
1294 |
-
return $url;
|
1295 |
-
}
|
1296 |
-
|
1297 |
-
/*
|
1298 |
-
Replace default logout redirect URL with Custom login page URL
|
1299 |
-
*/
|
1300 |
-
add_filter( 'wp_redirect', 'cerber_redirect', 9999, 2 );
|
1301 |
-
function cerber_redirect( $location, $status ) {
|
1302 |
-
global $wp_cerber;
|
1303 |
-
if ( ($path = $wp_cerber->getSettings( 'loginpath' )) && ( 0 === strpos( $location, WP_LOGIN_SCRIPT . '?' ) ) ) {
|
1304 |
-
$loc = explode( '?', $location );
|
1305 |
-
$location = get_home_url() . '/' . $path . '/?' . $loc[1];
|
1306 |
-
}
|
1307 |
-
|
1308 |
-
return $location;
|
1309 |
-
}
|
1310 |
-
|
1311 |
-
// Access control ========================================================================================
|
1312 |
-
|
1313 |
-
//add_action( 'init', 'cerber_access_control', 1 );
|
1314 |
-
add_action( 'init', function () {
|
1315 |
-
if ( crb_get_settings( 'adminphp' ) && ! is_user_logged_in() ) {
|
1316 |
-
define( 'CONCATENATE_SCRIPTS', false );
|
1317 |
-
}
|
1318 |
-
cerber_access_control();
|
1319 |
-
cerber_post_control();
|
1320 |
-
}, 1 );
|
1321 |
-
|
1322 |
-
/**
|
1323 |
-
* Restrict access to vital parts of WP
|
1324 |
-
*
|
1325 |
-
*/
|
1326 |
-
function cerber_access_control() {
|
1327 |
-
global $wp_cerber, $cerber_status;
|
1328 |
-
|
1329 |
-
if ( is_admin() ) {
|
1330 |
-
return;
|
1331 |
-
}
|
1332 |
-
|
1333 |
-
// IPs from the White List are allowed
|
1334 |
-
$acl = cerber_acl_check();
|
1335 |
-
if ( $acl == 'W' ) {
|
1336 |
-
return;
|
1337 |
-
}
|
1338 |
-
|
1339 |
-
//if ( $acl == 'B' || cerber_block_check() ) {
|
1340 |
-
if ( $acl == 'B' || !cerber_is_allowed() ) { // @since 5.8.2
|
1341 |
-
$deny = true;
|
1342 |
-
}
|
1343 |
-
else {
|
1344 |
-
$deny = false;
|
1345 |
-
}
|
1346 |
-
|
1347 |
-
$opt = $wp_cerber->getSettings();
|
1348 |
-
|
1349 |
-
$script = cerber_last_uri();
|
1350 |
-
if ( substr( $script, - 4 ) != '.php' ) {
|
1351 |
-
$script .= '.php'; // Apache MultiViews enabled?
|
1352 |
-
}
|
1353 |
-
|
1354 |
-
if ( $script ) {
|
1355 |
-
if ( $script == WP_LOGIN_SCRIPT || $script == WP_SIGNUP_SCRIPT || ( $script == WP_REG_URI && ! get_option( 'users_can_register' ) ) ) { // no direct access
|
1356 |
-
if ( !empty( $opt['wplogin'] ) ) {
|
1357 |
-
cerber_log( 50 );
|
1358 |
-
cerber_soft_block_add( $wp_cerber->getRemoteIp(), 2, $script );
|
1359 |
-
cerber_404_page();
|
1360 |
-
}
|
1361 |
-
if ( $deny || !empty( $opt['loginnowp'] ) ) {
|
1362 |
-
cerber_log( 50 );
|
1363 |
-
cerber_404_page();
|
1364 |
-
}
|
1365 |
-
}
|
1366 |
-
elseif ( $script == WP_XMLRPC_SCRIPT || $script == WP_TRACKBACK_SCRIPT ) { // no direct access
|
1367 |
-
if ( $deny || ! empty( $opt['xmlrpc'] ) ) {
|
1368 |
-
cerber_log( 50 ); // @since 5.21
|
1369 |
-
cerber_404_page();
|
1370 |
-
}
|
1371 |
-
elseif ( !cerber_geo_allowed( 'geo_xmlrpc' ) ) {
|
1372 |
-
$cerber_status = 16;
|
1373 |
-
cerber_log( 71 );
|
1374 |
-
cerber_404_page();
|
1375 |
-
}
|
1376 |
-
}
|
1377 |
-
}
|
1378 |
-
|
1379 |
-
// TODO: the code below should be located before $script or be called in the beginning of cerber_404_page()
|
1380 |
-
|
1381 |
-
// REST API
|
1382 |
-
if ( $deny ) {
|
1383 |
-
cerber_block_rest();
|
1384 |
-
}
|
1385 |
-
elseif ( cerber_is_rest_url() ) {
|
1386 |
-
$rest_allowed = true;
|
1387 |
-
if ( ! empty( $opt['norest'] ) ) {
|
1388 |
-
$rest_allowed = false;
|
1389 |
-
if ( $wp_cerber->getSettings( 'restauth' ) && is_user_logged_in() ) {
|
1390 |
-
$rest_allowed = true;
|
1391 |
-
}
|
1392 |
-
elseif ( cerber_is_route_allowed() ) {
|
1393 |
-
$rest_allowed = true;
|
1394 |
-
}
|
1395 |
-
}
|
1396 |
-
/*
|
1397 |
-
$rest_allowed = true;
|
1398 |
-
if ( ! empty( $opt['norest'] ) && ! cerber_is_route_allowed() ) {
|
1399 |
-
$rest_allowed = false;
|
1400 |
-
}*/
|
1401 |
-
if ( $rest_allowed && cerber_is_route_blocked() ) {
|
1402 |
-
$rest_allowed = false;
|
1403 |
-
}
|
1404 |
-
if ( $rest_allowed && ! cerber_geo_allowed( 'geo_restapi' ) ) {
|
1405 |
-
$rest_allowed = false;
|
1406 |
-
$cerber_status = 16;
|
1407 |
-
}
|
1408 |
-
if ( ! $rest_allowed ) {
|
1409 |
-
cerber_block_rest();
|
1410 |
-
}
|
1411 |
-
}
|
1412 |
-
|
1413 |
-
// Some XML-RPC stuff
|
1414 |
-
if ( $deny || ! empty( $opt['xmlrpc'] ) ) {
|
1415 |
-
add_filter( 'xmlrpc_enabled', '__return_false' );
|
1416 |
-
add_filter( 'pings_open', '__return_false' );
|
1417 |
-
add_filter( 'bloginfo_url', 'cerber_pingback_url', 10, 2 );
|
1418 |
-
remove_action( 'wp_head', 'rsd_link', 10 );
|
1419 |
-
remove_action( 'wp_head', 'wlwmanifest_link', 10 );
|
1420 |
-
}
|
1421 |
-
|
1422 |
-
// Feeds
|
1423 |
-
if ( $deny || ! empty( $opt['nofeeds'] ) ) {
|
1424 |
-
remove_action( 'wp_head', 'feed_links', 2 );
|
1425 |
-
remove_action( 'wp_head', 'feed_links_extra', 3 );
|
1426 |
-
|
1427 |
-
remove_action( 'do_feed_rdf', 'do_feed_rdf', 10 );
|
1428 |
-
remove_action( 'do_feed_rss', 'do_feed_rss', 10 );
|
1429 |
-
remove_action( 'do_feed_rss2', 'do_feed_rss2', 10 );
|
1430 |
-
remove_action( 'do_feed_atom', 'do_feed_atom', 10 );
|
1431 |
-
remove_action( 'do_pings', 'do_all_pings', 10 );
|
1432 |
-
|
1433 |
-
add_action( 'do_feed_rdf', 'cerber_404_page', 1 );
|
1434 |
-
add_action( 'do_feed_rss', 'cerber_404_page', 1 );
|
1435 |
-
add_action( 'do_feed_rss2', 'cerber_404_page', 1 );
|
1436 |
-
add_action( 'do_feed_atom', 'cerber_404_page', 1 );
|
1437 |
-
add_action( 'do_feed_rss2_comments', 'cerber_404_page', 1 );
|
1438 |
-
add_action( 'do_feed_atom_comments', 'cerber_404_page', 1 );
|
1439 |
-
}
|
1440 |
-
}
|
1441 |
-
|
1442 |
-
/**
|
1443 |
-
* Antispam & Antibot for forms
|
1444 |
-
*
|
1445 |
-
*/
|
1446 |
-
//add_action( 'init', 'cerber_post_control', 2 );
|
1447 |
-
function cerber_post_control(){
|
1448 |
-
global $cerber_status;
|
1449 |
-
|
1450 |
-
if ( !cerber_is_http_post() || cerber_acl_check( null, 'W' ) ) {
|
1451 |
-
return;
|
1452 |
-
}
|
1453 |
-
|
1454 |
-
if ( !cerber_antibot_enabled('botsany') || !cerber_geo_rules('geo_submit')) {
|
1455 |
-
return;
|
1456 |
-
}
|
1457 |
-
|
1458 |
-
// Exceptions -----------------------------------------------------------------------
|
1459 |
-
|
1460 |
-
if ( cerber_is_post_exception() ) {
|
1461 |
-
return;
|
1462 |
-
}
|
1463 |
-
|
1464 |
-
// Let's make the checks
|
1465 |
-
|
1466 |
-
$deny = false;
|
1467 |
-
|
1468 |
-
if ( ! cerber_is_allowed() ) {
|
1469 |
-
$deny = true;
|
1470 |
-
cerber_log(18);
|
1471 |
-
}
|
1472 |
-
elseif ( cerber_is_bot( 'botsany' ) ) {
|
1473 |
-
$deny = true;
|
1474 |
-
cerber_log( 17 );
|
1475 |
-
}
|
1476 |
-
elseif ( !cerber_geo_allowed( 'geo_submit' ) ) {
|
1477 |
-
$deny = true;
|
1478 |
-
$cerber_status = 16; // TODO: refactor cerber_log, include this status as a second parameter
|
1479 |
-
cerber_log( 18 );
|
1480 |
-
}
|
1481 |
-
elseif ( lab_is_blocked( null, true ) ) {
|
1482 |
-
$deny = true;
|
1483 |
-
$cerber_status = 18;
|
1484 |
-
cerber_log( 18 );
|
1485 |
-
}
|
1486 |
-
|
1487 |
-
if ($deny){
|
1488 |
-
cerber_forbidden_page();
|
1489 |
-
}
|
1490 |
-
|
1491 |
-
}
|
1492 |
-
|
1493 |
-
/**
|
1494 |
-
* Exception for POST query control
|
1495 |
-
*
|
1496 |
-
* @return bool
|
1497 |
-
*/
|
1498 |
-
function cerber_is_post_exception(){
|
1499 |
-
|
1500 |
-
if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
|
1501 |
-
return true;
|
1502 |
-
}
|
1503 |
-
|
1504 |
-
// Admin || AJAX requests by unauthorized users
|
1505 |
-
if ( is_admin() ) {
|
1506 |
-
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
1507 |
-
if (is_user_logged_in()) {
|
1508 |
-
return true;
|
1509 |
-
}
|
1510 |
-
}
|
1511 |
-
else {
|
1512 |
-
return true;
|
1513 |
-
}
|
1514 |
-
}
|
1515 |
-
|
1516 |
-
// Comments
|
1517 |
-
if ( 0 === strpos( trim( $_SERVER['REQUEST_URI'], '/' ), 'wp-comments-post.php' ) ) {
|
1518 |
-
return true;
|
1519 |
-
}
|
1520 |
-
|
1521 |
-
// XML-RPC
|
1522 |
-
if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
|
1523 |
-
return true;
|
1524 |
-
}
|
1525 |
-
|
1526 |
-
// Trackback
|
1527 |
-
if ( is_trackback() ) {
|
1528 |
-
return true;
|
1529 |
-
}
|
1530 |
-
|
1531 |
-
// Login page
|
1532 |
-
if ( cerber_is_login_request() ) {
|
1533 |
-
return true;
|
1534 |
-
}
|
1535 |
-
|
1536 |
-
// REST API but not Contact Form 7 submission
|
1537 |
-
if ( cerber_is_rest_url() ) {
|
1538 |
-
if ( false === strpos( $_SERVER['REQUEST_URI'], 'contact-form-7' ) ) {
|
1539 |
-
return true;
|
1540 |
-
}
|
1541 |
-
}
|
1542 |
-
|
1543 |
-
return false;
|
1544 |
-
}
|
1545 |
-
|
1546 |
-
/*
|
1547 |
-
* Disable pingback URL (hide from HEAD)
|
1548 |
-
*/
|
1549 |
-
function cerber_pingback_url( $output, $show ) {
|
1550 |
-
if ( $show == 'pingback_url' ) {
|
1551 |
-
$output = '';
|
1552 |
-
}
|
1553 |
-
|
1554 |
-
return $output;
|
1555 |
-
}
|
1556 |
-
|
1557 |
-
/**
|
1558 |
-
* Disable REST API
|
1559 |
-
*
|
1560 |
-
*/
|
1561 |
-
function cerber_block_rest() {
|
1562 |
-
global $wp_version;
|
1563 |
-
// OLD WP
|
1564 |
-
add_filter( 'json_enabled', '__return_false' );
|
1565 |
-
add_filter( 'json_jsonp_enabled', '__return_false' );
|
1566 |
-
// WP 4.4, deprecated since 4.7
|
1567 |
-
if ( version_compare( $wp_version, '4.7', '<' ) ) {
|
1568 |
-
add_filter( 'rest_enabled', '__return_false', 9999 );
|
1569 |
-
}
|
1570 |
-
// WP 4.7
|
1571 |
-
add_filter( 'rest_jsonp_enabled', '__return_false' );
|
1572 |
-
// Links
|
1573 |
-
remove_action( 'wp_head', 'rest_output_link_wp_head', 10 );
|
1574 |
-
remove_action( 'template_redirect', 'rest_output_link_header', 11 );
|
1575 |
-
// Default REST API hooks from default-filters.php
|
1576 |
-
remove_action( 'init', 'rest_api_init' );
|
1577 |
-
remove_action( 'rest_api_init', 'rest_api_default_filters', 10 );
|
1578 |
-
remove_action( 'rest_api_init', 'register_initial_settings', 10 );
|
1579 |
-
remove_action( 'rest_api_init', 'create_initial_rest_routes', 99 );
|
1580 |
-
remove_action( 'parse_request', 'rest_api_loaded' );
|
1581 |
-
|
1582 |
-
if ( cerber_is_rest_url() ) {
|
1583 |
-
cerber_log( 70 );
|
1584 |
-
//cerber_404_page();
|
1585 |
-
cerber_forbidden_page(); // @since 6.0
|
1586 |
-
}
|
1587 |
-
}
|
1588 |
-
|
1589 |
-
/*
|
1590 |
-
* Redirection control: standard admin/login redirections
|
1591 |
-
*
|
1592 |
-
*/
|
1593 |
-
add_filter( 'wp_redirect', 'cerber_no_redirect', 10, 2 );
|
1594 |
-
function cerber_no_redirect( $location, $status ) {
|
1595 |
-
global $current_user, $wp_cerber;
|
1596 |
-
if ( (!$current_user || $current_user->ID == 0) && $wp_cerber->getSettings( 'noredirect' ) ) {
|
1597 |
-
$str = urlencode( '/wp-admin/' );
|
1598 |
-
$rdr = explode('redirect_to=',$location);
|
1599 |
-
if ( isset($rdr[1]) && strpos( $rdr[1], $str ) ) {
|
1600 |
-
cerber_404_page();
|
1601 |
-
}
|
1602 |
-
}
|
1603 |
-
|
1604 |
-
return $location;
|
1605 |
-
}
|
1606 |
-
/*
|
1607 |
-
* Redirection control: no default aliases for redirections
|
1608 |
-
*
|
1609 |
-
*/
|
1610 |
-
if ( $wp_cerber->getSettings( 'noredirect' ) ) {
|
1611 |
-
remove_action( 'template_redirect', 'wp_redirect_admin_locations', 1000 );
|
1612 |
-
}
|
1613 |
-
/*
|
1614 |
-
* Stop user enumeration
|
1615 |
-
*
|
1616 |
-
*/
|
1617 |
-
add_action( 'template_redirect', 'cerber_canonical', 1 );
|
1618 |
-
function cerber_canonical() {
|
1619 |
-
if ( crb_get_settings( 'stopenum' ) ) {
|
1620 |
-
if ( ! is_admin() && ! empty( $_GET['author'] ) ) {
|
1621 |
-
cerber_404_page();
|
1622 |
-
}
|
1623 |
-
}
|
1624 |
-
}
|
1625 |
-
/*
|
1626 |
-
if ( $wp_cerber->getSettings( 'hashauthor' ) ) {
|
1627 |
-
add_filter( 'request',
|
1628 |
-
function ( $vars ) {
|
1629 |
-
if (isset($vars['author_name']) && !is_admin()) {
|
1630 |
-
$vars['author_name'] = '><';
|
1631 |
-
}
|
1632 |
-
|
1633 |
-
return $vars;
|
1634 |
-
} );
|
1635 |
-
}
|
1636 |
-
*/
|
1637 |
-
|
1638 |
-
/*
|
1639 |
-
Can login form message be shown?
|
1640 |
-
*/
|
1641 |
-
function cerber_can_msg() {
|
1642 |
-
if ( ! isset( $_REQUEST['action'] ) ) {
|
1643 |
-
return true;
|
1644 |
-
}
|
1645 |
-
if ( $_REQUEST['action'] == 'login' ) {
|
1646 |
-
return true;
|
1647 |
-
}
|
1648 |
-
|
1649 |
-
return false;
|
1650 |
-
//if ( !in_array( $action, array( 'postpass', 'logout', 'lostpassword', 'retrievepassword', 'resetpass', 'rp', 'register', 'login' );
|
1651 |
-
}
|
1652 |
-
|
1653 |
-
|
1654 |
-
// Cookies ---------------------------------------------------------------------------------
|
1655 |
-
/*
|
1656 |
-
Mark user with Cerber Groove
|
1657 |
-
@since 1.3
|
1658 |
-
*/
|
1659 |
-
add_action( 'auth_cookie_valid', 'cerber_cookie1', 10, 2 );
|
1660 |
-
function cerber_cookie1( $cookie_elements = null, $user = null ) {
|
1661 |
-
global $current_user;
|
1662 |
-
if ( ! $user ) {
|
1663 |
-
$user = wp_get_current_user();
|
1664 |
-
}
|
1665 |
-
$expire = time() + apply_filters( 'auth_cookie_expiration', 14 * 24 * 3600, $user->ID, true ) + ( 24 * 3600 );
|
1666 |
-
cerber_set_groove( $expire );
|
1667 |
-
}
|
1668 |
-
|
1669 |
-
/*
|
1670 |
-
Mark switched user with Cerber Groove
|
1671 |
-
@since 1.6
|
1672 |
-
*/
|
1673 |
-
add_action( 'set_logged_in_cookie', 'cerber_cookie2', 10, 5 );
|
1674 |
-
function cerber_cookie2( $logged_in_cookie, $expire, $expiration, $user_id, $logged_in ) {
|
1675 |
-
cerber_set_groove( $expire );
|
1676 |
-
}
|
1677 |
-
|
1678 |
-
/*
|
1679 |
-
Track BAD cookies with non-existence user or bad password (hash)
|
1680 |
-
*/
|
1681 |
-
add_action( 'auth_cookie_bad_username', 'cerber_cookie_bad' );
|
1682 |
-
add_action( 'auth_cookie_bad_hash', 'cerber_cookie_bad' );
|
1683 |
-
function cerber_cookie_bad( $cookie_elements ) {
|
1684 |
-
cerber_login_failed( $cookie_elements['username'] );
|
1685 |
-
}
|
1686 |
-
|
1687 |
-
/**
|
1688 |
-
* Is bot detection engine enabled in a given rule_id
|
1689 |
-
*
|
1690 |
-
* @param $location string|array ID of the location
|
1691 |
-
*
|
1692 |
-
* @return bool true if enabled
|
1693 |
-
*/
|
1694 |
-
function cerber_antibot_enabled($location) {
|
1695 |
-
global $wp_cerber;
|
1696 |
-
|
1697 |
-
if ($wp_cerber->getSettings( 'botsnoauth' ) && is_user_logged_in()){
|
1698 |
-
return false;
|
1699 |
-
}
|
1700 |
-
|
1701 |
-
if ( is_array( $location ) ) {
|
1702 |
-
foreach ( $location as $loc ) {
|
1703 |
-
if ( $wp_cerber->getSettings( $loc ) ) {
|
1704 |
-
return true;
|
1705 |
-
}
|
1706 |
-
}
|
1707 |
-
}
|
1708 |
-
else {
|
1709 |
-
if ( $wp_cerber->getSettings( $location ) ) {
|
1710 |
-
return true;
|
1711 |
-
}
|
1712 |
-
}
|
1713 |
-
|
1714 |
-
return false;
|
1715 |
-
}
|
1716 |
-
|
1717 |
-
/**
|
1718 |
-
* Print out the antibot/antispam jQuery code
|
1719 |
-
*
|
1720 |
-
* @param $location string|array Location (setting)
|
1721 |
-
*/
|
1722 |
-
function cerber_antibot_code($location) {
|
1723 |
-
if ( ! cerber_antibot_enabled( $location ) ) {
|
1724 |
-
return;
|
1725 |
-
}
|
1726 |
-
|
1727 |
-
$values = cerber_antibot_gene();
|
1728 |
-
|
1729 |
-
if ( empty( $values ) || !is_array( $values ) ) {
|
1730 |
-
return;
|
1731 |
-
}
|
1732 |
-
|
1733 |
-
?>
|
1734 |
-
<script type="text/javascript">
|
1735 |
-
jQuery(document).ready(function ($) {
|
1736 |
-
//$( document ).ajaxStart(function() {
|
1737 |
-
//});
|
1738 |
-
|
1739 |
-
<?php // Append form fields directly to the all forms ?>
|
1740 |
-
|
1741 |
-
for (var i = 0; i < document.forms.length; ++i) {
|
1742 |
-
var form = document.forms[i];
|
1743 |
-
<?php
|
1744 |
-
foreach ( $values[0] as $value ) {
|
1745 |
-
echo 'if ($(form).attr("method") != "get") { $(form).append(\'<input type="hidden" name="' . $value[0] . '" value="' . $value[1] . '" />\'); }'."\n";
|
1746 |
-
}
|
1747 |
-
?>
|
1748 |
-
}
|
1749 |
-
|
1750 |
-
<?php // Ordinary submit ?>
|
1751 |
-
|
1752 |
-
$(document).on('submit', 'form', function () {
|
1753 |
-
<?php
|
1754 |
-
foreach ( $values[0] as $value ) {
|
1755 |
-
echo 'if ($(this).attr("method") != "get") { $(this).append(\'<input type="hidden" name="' . $value[0] . '" value="' . $value[1] . '" />\'); }'."\n";
|
1756 |
-
}
|
1757 |
-
?>
|
1758 |
-
return true;
|
1759 |
-
});
|
1760 |
-
|
1761 |
-
<?php // Pure AJAX submit with two different types of form data (object and string) ?>
|
1762 |
-
|
1763 |
-
jQuery.ajaxSetup({
|
1764 |
-
beforeSend: function (e, data) {
|
1765 |
-
|
1766 |
-
//console.log(Object.getOwnPropertyNames(data).sort());
|
1767 |
-
//console.log(data.type);
|
1768 |
-
|
1769 |
-
if (data.type !== 'POST') return;
|
1770 |
-
|
1771 |
-
if (typeof data.data === 'object' && data.data !== null) {
|
1772 |
-
<?php
|
1773 |
-
foreach ( $values[0] as $value ) {
|
1774 |
-
echo 'data.data.append("' . $value[0] . '", "' . $value[1] . '");'."\n";
|
1775 |
-
}
|
1776 |
-
?>
|
1777 |
-
}
|
1778 |
-
else {
|
1779 |
-
data.data = data.data + '<?php
|
1780 |
-
foreach ( $values[0] as $value ) {
|
1781 |
-
echo '&' . $value[0] . '=' . $value[1];
|
1782 |
-
}
|
1783 |
-
?>';
|
1784 |
-
}
|
1785 |
-
}
|
1786 |
-
});
|
1787 |
-
|
1788 |
-
});
|
1789 |
-
</script>
|
1790 |
-
<?php
|
1791 |
-
|
1792 |
-
}
|
1793 |
-
|
1794 |
-
/**
|
1795 |
-
* Generates and saves antibot markers
|
1796 |
-
*
|
1797 |
-
* @return array|bool
|
1798 |
-
*/
|
1799 |
-
function cerber_antibot_gene($recreate = false) {
|
1800 |
-
|
1801 |
-
if ( !crb_get_settings('botsany') && !crb_get_settings('botscomm') && !crb_get_settings('botsreg') ) {
|
1802 |
-
return false;
|
1803 |
-
}
|
1804 |
-
|
1805 |
-
$ret = array();
|
1806 |
-
|
1807 |
-
if (!$recreate) {
|
1808 |
-
$ret = cerber_get_site_option( 'cerber-antibot' );
|
1809 |
-
}
|
1810 |
-
|
1811 |
-
if ( $recreate || !$ret ) {
|
1812 |
-
|
1813 |
-
$ret = array();
|
1814 |
-
|
1815 |
-
$max = rand( 2, 4 );
|
1816 |
-
for ( $i = 1; $i <= $max; $i ++ ) {
|
1817 |
-
$length = rand( 6, 16 );
|
1818 |
-
$string1 = str_shuffle( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-' );
|
1819 |
-
$string2 = str_shuffle( '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.@*_[]' );
|
1820 |
-
$ret[0][] = array( substr( $string1, 0, $length ), substr( $string2, 0, $length ) );
|
1821 |
-
}
|
1822 |
-
|
1823 |
-
$max = rand( 2, 4 );
|
1824 |
-
for ( $i = 1; $i <= $max; $i ++ ) {
|
1825 |
-
$length = rand( 6, 16 );
|
1826 |
-
$string1 = str_shuffle( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-' );
|
1827 |
-
$string2 = str_shuffle( '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.@*_[]' );
|
1828 |
-
$ret[1][] = array( substr( $string1, 0, $length ), substr( $string2, 0, $length ) );
|
1829 |
-
}
|
1830 |
-
|
1831 |
-
update_site_option( 'cerber-antibot', $ret );
|
1832 |
-
}
|
1833 |
-
|
1834 |
-
return $ret;
|
1835 |
-
}
|
1836 |
-
|
1837 |
-
/**
|
1838 |
-
* Is a POST request (a form) submitted by a bot?
|
1839 |
-
*
|
1840 |
-
* @param $location string identificator of a place where we are check for a bot
|
1841 |
-
*
|
1842 |
-
* @return bool
|
1843 |
-
*/
|
1844 |
-
function cerber_is_bot($location = '') {
|
1845 |
-
global $wp_cerber, $cerber_status;
|
1846 |
-
static $ret = null;
|
1847 |
-
|
1848 |
-
if ( isset( $ret ) ) {
|
1849 |
-
return $ret;
|
1850 |
-
}
|
1851 |
-
|
1852 |
-
if ( ! $location || ! cerber_is_http_post() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
|
1853 |
-
$ret = false;
|
1854 |
-
|
1855 |
-
return $ret;
|
1856 |
-
}
|
1857 |
-
|
1858 |
-
// Admin || AJAX requests by unauthorized users
|
1859 |
-
if ( is_admin() ) {
|
1860 |
-
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
1861 |
-
if ( is_user_logged_in() ) {
|
1862 |
-
$ret = false;
|
1863 |
-
}
|
1864 |
-
elseif ( ! empty( $_POST['action'] ) ) {
|
1865 |
-
if ($_POST['action'] == 'heartbeat'){ // WP heartbeat
|
1866 |
-
$ret = false;
|
1867 |
-
}
|
1868 |
-
}
|
1869 |
-
elseif ( crb_get_settings( 'botssafe' ) ) {
|
1870 |
-
$ret = false;
|
1871 |
-
}
|
1872 |
-
}
|
1873 |
-
else {
|
1874 |
-
$ret = false;
|
1875 |
-
}
|
1876 |
-
}
|
1877 |
-
|
1878 |
-
if ($ret !== null) {
|
1879 |
-
return $ret;
|
1880 |
-
}
|
1881 |
-
|
1882 |
-
if ( ! cerber_antibot_enabled( $location ) ) {
|
1883 |
-
$ret = false;
|
1884 |
-
|
1885 |
-
return $ret;
|
1886 |
-
}
|
1887 |
-
|
1888 |
-
// Antibot whitelist
|
1889 |
-
if ( ( $list = crb_get_settings( 'botswhite' ) ) && is_array( $list ) ) {
|
1890 |
-
foreach ( $list as $exception ) {
|
1891 |
-
if ( false !== strpos( trim( $_SERVER['REQUEST_URI'], '/' ), $exception ) ) {
|
1892 |
-
$ret = false;
|
1893 |
-
return $ret;
|
1894 |
-
}
|
1895 |
-
}
|
1896 |
-
}
|
1897 |
-
|
1898 |
-
$antibot = cerber_antibot_gene();
|
1899 |
-
|
1900 |
-
$ret = false;
|
1901 |
-
|
1902 |
-
if ( ! empty( $antibot ) ) {
|
1903 |
-
|
1904 |
-
foreach ( $antibot[0] as $fields ) {
|
1905 |
-
if ( empty( $_POST[ $fields[0] ] ) || $_POST[ $fields[0] ] != $fields[1] ) {
|
1906 |
-
$ret = true;
|
1907 |
-
break;
|
1908 |
-
}
|
1909 |
-
}
|
1910 |
-
|
1911 |
-
if (!$ret){
|
1912 |
-
foreach ( $antibot[1] as $fields ) {
|
1913 |
-
if ( empty( $_COOKIE[ $fields[0] ] ) || $_COOKIE[ $fields[0] ] != $fields[1] ) {
|
1914 |
-
$ret = true;
|
1915 |
-
break;
|
1916 |
-
}
|
1917 |
-
}
|
1918 |
-
}
|
1919 |
-
|
1920 |
-
if ( $ret ) {
|
1921 |
-
$cerber_status = 11;
|
1922 |
-
lab_save_push( $wp_cerber->getRemoteIp(), 333, '' );
|
1923 |
-
}
|
1924 |
-
}
|
1925 |
-
|
1926 |
-
return $ret;
|
1927 |
-
}
|
1928 |
-
|
1929 |
-
function cerber_geo_allowed( $rule_id = '' ) {
|
1930 |
-
global $wp_cerber;
|
1931 |
-
|
1932 |
-
if ( !$rule_id || ( defined( 'DOING_CRON' ) && DOING_CRON ) || !lab_lab() ) {
|
1933 |
-
return true;
|
1934 |
-
}
|
1935 |
-
|
1936 |
-
$tag = cerber_acl_check();
|
1937 |
-
if ( $tag == 'W' ) {
|
1938 |
-
return true;
|
1939 |
-
}
|
1940 |
-
|
1941 |
-
$rule = cerber_geo_rules( $rule_id );
|
1942 |
-
if ( $rule && $country = lab_get_country( $wp_cerber->getRemoteIp(), false ) ) {
|
1943 |
-
if ( in_array( $country, $rule['list'] ) ) {
|
1944 |
-
if ( $rule['type'] == 'W' ) {
|
1945 |
-
return true;
|
1946 |
-
}
|
1947 |
-
|
1948 |
-
return false;
|
1949 |
-
}
|
1950 |
-
if ( $rule['type'] == 'W' ) {
|
1951 |
-
return false;
|
1952 |
-
}
|
1953 |
-
|
1954 |
-
return true;
|
1955 |
-
}
|
1956 |
-
|
1957 |
-
return true;
|
1958 |
-
}
|
1959 |
-
|
1960 |
-
/**
|
1961 |
-
* Retrieve and return GEO rule(s) from the DB
|
1962 |
-
*
|
1963 |
-
* @param string $rule_id Slug of a rule
|
1964 |
-
*
|
1965 |
-
* @return bool|array If a rule exists return array of countries
|
1966 |
-
*/
|
1967 |
-
function cerber_geo_rules( $rule_id = '' ) {
|
1968 |
-
global $wpdb;
|
1969 |
-
|
1970 |
-
if (is_multisite()) {
|
1971 |
-
$geo = $wpdb->get_var( 'SELECT meta_value FROM ' . $wpdb->sitemeta . ' WHERE meta_key = "geo_rule_set"' );
|
1972 |
-
}
|
1973 |
-
else {
|
1974 |
-
$geo = $wpdb->get_var( 'SELECT option_value FROM ' . $wpdb->options . ' WHERE option_name = "geo_rule_set"' );
|
1975 |
-
}
|
1976 |
-
|
1977 |
-
if ( $geo ) {
|
1978 |
-
$rules = unserialize( $geo );
|
1979 |
-
if ( $rule_id ) {
|
1980 |
-
if ( ! empty( $rules[ $rule_id ] ) ) {
|
1981 |
-
$ret = $rules[ $rule_id ];
|
1982 |
-
}
|
1983 |
-
else {
|
1984 |
-
$ret = false;
|
1985 |
-
}
|
1986 |
-
}
|
1987 |
-
else {
|
1988 |
-
$ret = $rules;
|
1989 |
-
}
|
1990 |
-
}
|
1991 |
-
else {
|
1992 |
-
$ret = false;
|
1993 |
-
}
|
1994 |
-
|
1995 |
-
return $ret;
|
1996 |
-
}
|
1997 |
-
|
1998 |
-
/**
|
1999 |
-
* Set user session expiration
|
2000 |
-
*
|
2001 |
-
*/
|
2002 |
-
add_filter( 'auth_cookie_expiration', function ( $expire ) {
|
2003 |
-
$time = crb_get_settings( 'auth_expire' );
|
2004 |
-
if ( $time ) {
|
2005 |
-
$expire = 60 * $time;
|
2006 |
-
}
|
2007 |
-
|
2008 |
-
return $expire;
|
2009 |
-
} );
|
2010 |
-
|
2011 |
-
// Track various activity -------------------------------------------------------------------------
|
2012 |
-
|
2013 |
-
add_action( 'wp_login', function ( $login, $user ) {
|
2014 |
-
global $wp_cerber_user_id;
|
2015 |
-
if ( ! empty( $_POST['log'] ) ) { // default WP form
|
2016 |
-
$user_login = htmlspecialchars( $_POST['log'] );
|
2017 |
-
}
|
2018 |
-
else {
|
2019 |
-
$user_login = $login;
|
2020 |
-
}
|
2021 |
-
$wp_cerber_user_id = $user->ID;
|
2022 |
-
cerber_log( 5, $user_login, $user->ID );
|
2023 |
-
}, 10, 2 );
|
2024 |
-
|
2025 |
-
/**
|
2026 |
-
* Catching some cases of authentication without using login form or not a default user login process
|
2027 |
-
*/
|
2028 |
-
add_action( 'set_auth_cookie', function () {
|
2029 |
-
add_action( 'shutdown', function () { // deferred to allow the possible 'wp_login' action be logged first
|
2030 |
-
if ($user_id = get_current_user_id()) {
|
2031 |
-
cerber_log( 5, '', $user_id );
|
2032 |
-
}
|
2033 |
-
} );
|
2034 |
-
} );
|
2035 |
-
|
2036 |
-
/*add_action( 'wp_logout', function() {
|
2037 |
-
global $user_ID;
|
2038 |
-
if ( ! $user_ID ) {
|
2039 |
-
$user = wp_get_current_user();
|
2040 |
-
$user_ID = $user->ID;
|
2041 |
-
}
|
2042 |
-
cerber_log( 6, '', $user_ID );
|
2043 |
-
});*/
|
2044 |
-
|
2045 |
-
add_action( 'clear_auth_cookie', function () {
|
2046 |
-
$uid = get_current_user_id();
|
2047 |
-
if ( $uid ) {
|
2048 |
-
cerber_log( 6, '', $uid );
|
2049 |
-
}
|
2050 |
-
} );
|
2051 |
-
|
2052 |
-
//add_action( 'lostpassword_post', 'cerber_password_post' );
|
2053 |
-
add_action( 'retrieve_password', function ( $user_login ) {
|
2054 |
-
cerber_log( 21, $user_login );
|
2055 |
-
} );
|
2056 |
-
|
2057 |
-
add_action( 'password_reset', 'crb_pass_reset' );
|
2058 |
-
add_action( 'crb_after_reset', 'crb_pass_reset', 10, 2);
|
2059 |
-
|
2060 |
-
function crb_pass_reset( $user, $user_id = null) {
|
2061 |
-
if ( ! $user && $user_id ) {
|
2062 |
-
$user = get_user_by( 'id', $user_id );
|
2063 |
-
}
|
2064 |
-
if ( ! $user ) {
|
2065 |
-
return;
|
2066 |
-
}
|
2067 |
-
cerber_log( 20, $user->user_login, $user->ID );
|
2068 |
-
}
|
2069 |
-
|
2070 |
-
//add_action( 'register_new_user', function ( $user_id ) { // OLD
|
2071 |
-
// Fires in wp_insert_user()
|
2072 |
-
add_action( 'user_register', function ( $user_id ) { // @since 5.6
|
2073 |
-
$cid = get_current_user_id();
|
2074 |
-
if ($user = get_user_by( 'ID', $user_id )) {
|
2075 |
-
if ( $cid && $cid != $user_id ) {
|
2076 |
-
$ac = 1;
|
2077 |
-
}
|
2078 |
-
else {
|
2079 |
-
$ac = 2;
|
2080 |
-
}
|
2081 |
-
cerber_log( $ac, $user->user_login, $user_id );
|
2082 |
-
crb_log_user_ip( $user_id, $cid );
|
2083 |
-
}
|
2084 |
-
});
|
2085 |
-
|
2086 |
-
// Fires after a new user has been created in WP dashboard.
|
2087 |
-
add_action( 'edit_user_created_user', function ( $user_id, $notify = null ) {
|
2088 |
-
if ( $user_id && $user = get_user_by( 'ID', $user_id ) ) {
|
2089 |
-
cerber_log( 1, $user->user_login, $user_id );
|
2090 |
-
crb_log_user_ip( $user_id );
|
2091 |
-
}
|
2092 |
-
}, 10, 2 );
|
2093 |
-
|
2094 |
-
// Log IP address of user registration independently
|
2095 |
-
function crb_log_user_ip( $user_id, $by_user = null ) {
|
2096 |
-
global $wp_cerber;
|
2097 |
-
if ( ! $user_id ) {
|
2098 |
-
return;
|
2099 |
-
}
|
2100 |
-
if ( ! $by_user ) {
|
2101 |
-
$by_user = get_current_user_id();
|
2102 |
-
}
|
2103 |
-
add_user_meta( $user_id, '_crb_reg_', array( 'IP' => $wp_cerber->getRemoteIp(), 'user' => $by_user ) );
|
2104 |
-
}
|
2105 |
-
|
2106 |
-
// Lockouts routines ---------------------------------------------------------------------
|
2107 |
-
|
2108 |
-
/**
|
2109 |
-
* Lock out IP address if it is an alien IP only (browser does not have valid Cerber groove)
|
2110 |
-
*
|
2111 |
-
* @param $ip string IP address to block
|
2112 |
-
* @param integer $reason_id ID of reason of blocking
|
2113 |
-
* @param string $details Reason of blocking
|
2114 |
-
* @param null $duration Duration of blocking
|
2115 |
-
*
|
2116 |
-
* @return bool|false|int
|
2117 |
-
*/
|
2118 |
-
function cerber_soft_block_add( $ip, $reason_id, $details = '', $duration = null ) {
|
2119 |
-
if ( cerber_check_groove() ) {
|
2120 |
-
return false;
|
2121 |
-
}
|
2122 |
-
|
2123 |
-
return cerber_block_add( $ip, $reason_id, $details, $duration );
|
2124 |
-
}
|
2125 |
-
|
2126 |
-
/**
|
2127 |
-
* Lock out IP address
|
2128 |
-
*
|
2129 |
-
* @param $ip string IP address to block
|
2130 |
-
* @param integer $reason_id ID of reason of blocking
|
2131 |
-
* @param string $details Reason of blocking
|
2132 |
-
* @param int $duration Duration of blocking
|
2133 |
-
* @param bool $check_acl deprecated @since 5.7 Check for ACL
|
2134 |
-
*
|
2135 |
-
* @return bool|false|int
|
2136 |
-
*/
|
2137 |
-
function cerber_block_add( $ip = '', $reason_id = 1, $details = '', $duration = null, $check_acl = true ) {
|
2138 |
-
global $wpdb, $wp_cerber;
|
2139 |
-
|
2140 |
-
//$wp_cerber->setProcessed();
|
2141 |
-
|
2142 |
-
if ( empty($ip) ) {
|
2143 |
-
$ip = $wp_cerber->getRemoteIp();
|
2144 |
-
}
|
2145 |
-
|
2146 |
-
if ( cerber_get_block( $ip ) ) {
|
2147 |
-
return false;
|
2148 |
-
}
|
2149 |
-
|
2150 |
-
if ( cerber_acl_check( $ip ) ) {
|
2151 |
-
return false;
|
2152 |
-
}
|
2153 |
-
|
2154 |
-
$ip_address = $ip;
|
2155 |
-
|
2156 |
-
lab_save_push( $ip, $reason_id, $details );
|
2157 |
-
|
2158 |
-
if ( $wp_cerber->getSettings( 'subnet' ) ) {
|
2159 |
-
$ip = cerber_get_subnet( $ip );
|
2160 |
-
$activity = 11;
|
2161 |
-
} else {
|
2162 |
-
$activity = 10;
|
2163 |
-
}
|
2164 |
-
|
2165 |
-
if ( $wpdb->get_var( $wpdb->prepare( 'SELECT count(ip) FROM ' . CERBER_BLOCKS_TABLE . ' WHERE ip = %s', $ip ) ) ) {
|
2166 |
-
return false;
|
2167 |
-
}
|
2168 |
-
|
2169 |
-
$reason = cerber_get_reason( $reason_id );
|
2170 |
-
if ($details) $reason .= ': <b>' . $details . '</b>';
|
2171 |
-
|
2172 |
-
if ( ! $duration ) {
|
2173 |
-
$duration = cerber_calc_duration( $ip );
|
2174 |
-
}
|
2175 |
-
$until = time() + $duration;
|
2176 |
-
|
2177 |
-
//$result = $wpdb->query($wpdb->prepare('INSERT INTO '. CERBER_BLOCKS_TABLE . ' (ip,block_until,reason) VALUES (%s,%d,%s)',$ip,$until,$reason));
|
2178 |
-
$result = $wpdb->insert( CERBER_BLOCKS_TABLE, array(
|
2179 |
-
'ip' => $ip,
|
2180 |
-
'block_until' => $until,
|
2181 |
-
'reason' => $reason
|
2182 |
-
), array( '%s', '%d', '%s' ) );
|
2183 |
-
|
2184 |
-
if ( $result ) {
|
2185 |
-
cerber_log( $activity, null, null, $ip_address );
|
2186 |
-
$wp_cerber->setLocked();
|
2187 |
-
do_action( 'cerber_ip_locked', array( 'IP' => $ip_address, 'reason' => $reason ) );
|
2188 |
-
$result = true;
|
2189 |
-
}
|
2190 |
-
else {
|
2191 |
-
cerber_db_error_log();
|
2192 |
-
$result = false;
|
2193 |
-
}
|
2194 |
-
|
2195 |
-
if ( $wp_cerber->getSettings( 'notify' ) ) {
|
2196 |
-
//$count = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_BLOCKS_TABLE );
|
2197 |
-
$count = cerber_blocked_num();
|
2198 |
-
if ( $count > $wp_cerber->getSettings( 'above' ) ) {
|
2199 |
-
cerber_send_notify( 'lockout', '', $ip_address );
|
2200 |
-
}
|
2201 |
-
}
|
2202 |
-
|
2203 |
-
return $result;
|
2204 |
-
}
|
2205 |
-
|
2206 |
-
function cerber_block_delete( $ip ) {
|
2207 |
-
global $wpdb;
|
2208 |
-
|
2209 |
-
return $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . CERBER_BLOCKS_TABLE . ' WHERE ip = %s', $ip ) );
|
2210 |
-
}
|
2211 |
-
|
2212 |
-
|
2213 |
-
/**
|
2214 |
-
*
|
2215 |
-
* Check if an IP address is currently blocked. With C subnet also.
|
2216 |
-
*
|
2217 |
-
* @param string $ip an IP address
|
2218 |
-
*
|
2219 |
-
* @return bool true if IP is locked out
|
2220 |
-
*/
|
2221 |
-
function cerber_block_check( $ip = '' ) {
|
2222 |
-
|
2223 |
-
// @since 4.8
|
2224 |
-
if (cerber_get_block($ip)) return true;
|
2225 |
-
|
2226 |
-
return false;
|
2227 |
-
}
|
2228 |
-
|
2229 |
-
/**
|
2230 |
-
*
|
2231 |
-
* Return the lockout row for an IP if it is blocked. With C subnet also.
|
2232 |
-
*
|
2233 |
-
* @param string $ip an IP address
|
2234 |
-
*
|
2235 |
-
* @return object|bool object if IP is locked out, false otherwise
|
2236 |
-
*/
|
2237 |
-
function cerber_get_block( $ip = '' ) {
|
2238 |
-
global $wpdb, $wp_cerber;
|
2239 |
-
|
2240 |
-
if ( ! $ip ) {
|
2241 |
-
$wp_cerber = get_wp_cerber();
|
2242 |
-
$ip = $wp_cerber->getRemoteIp();
|
2243 |
-
}
|
2244 |
-
|
2245 |
-
if ( ! filter_var( $ip, FILTER_VALIDATE_IP ) ) {
|
2246 |
-
return false;
|
2247 |
-
}
|
2248 |
-
|
2249 |
-
$where = ' WHERE ip = "' . $ip . '"';
|
2250 |
-
if ( cerber_is_ipv4( $ip ) ) {
|
2251 |
-
$subnet = cerber_get_subnet( $ip );
|
2252 |
-
$where .= ' OR ip = "' . $subnet . '"';
|
2253 |
-
}
|
2254 |
-
if ( $ret = $wpdb->get_row( 'SELECT * FROM ' . CERBER_BLOCKS_TABLE . $where ) ) {
|
2255 |
-
return $ret;
|
2256 |
-
}
|
2257 |
-
|
2258 |
-
return false;
|
2259 |
-
}
|
2260 |
-
|
2261 |
-
// TODO: replace all entrance of $count = $wpdb->get_var('SELECT count(ip) FROM '. CERBER_BLOCKS_TABLE ); with this function
|
2262 |
-
/**
|
2263 |
-
* Return the number of currently locked out IPs
|
2264 |
-
*
|
2265 |
-
* @return int the number of currently locked out IPs
|
2266 |
-
* @since 3.0
|
2267 |
-
*/
|
2268 |
-
function cerber_blocked_num(){
|
2269 |
-
global $wpdb;
|
2270 |
-
$count = $wpdb->get_var('SELECT count(ip) FROM '. CERBER_BLOCKS_TABLE );
|
2271 |
-
return absint($count);
|
2272 |
-
}
|
2273 |
-
|
2274 |
-
/*
|
2275 |
-
Calculation duration of blocking (lockout) IP address based on settings & rules.
|
2276 |
-
*/
|
2277 |
-
function cerber_calc_duration( $ip ) {
|
2278 |
-
global $wpdb, $wp_cerber;
|
2279 |
-
$range = time() - crb_get_settings( 'aglast' ) * 3600;
|
2280 |
-
$lockouts = $wpdb->get_var( $wpdb->prepare( 'SELECT count(ip) FROM ' . CERBER_LOG_TABLE . ' WHERE ip = %s AND activity IN (10,11) AND stamp > %d', $ip, $range ) );
|
2281 |
-
if ( $lockouts >= crb_get_settings( 'aglocks' ) ) {
|
2282 |
-
return crb_get_settings( 'agperiod' ) * 3600;
|
2283 |
-
}
|
2284 |
-
|
2285 |
-
return crb_get_settings( 'lockout' ) * 60;
|
2286 |
-
}
|
2287 |
-
|
2288 |
-
/**
|
2289 |
-
* Calculation of remaining attempts
|
2290 |
-
*
|
2291 |
-
* @param $ip string an IP address
|
2292 |
-
* @param $check_acl bool if true will check the White IP ACL first
|
2293 |
-
* @param $activity string comma-separated list of activity IDs to calculate for
|
2294 |
-
* @param $allowed int Allowed attempts within $period
|
2295 |
-
* @param $period int Period for count attempts
|
2296 |
-
*
|
2297 |
-
* @return int Allowed attempts for now
|
2298 |
-
*/
|
2299 |
-
function cerber_get_remain_count( $ip = '', $check_acl = true, $activity = '7,51,52', $allowed = null, $period = null ) {
|
2300 |
-
global $wpdb, $wp_cerber;
|
2301 |
-
if ( ! $ip ) {
|
2302 |
-
$ip = $wp_cerber->getRemoteIp();
|
2303 |
-
}
|
2304 |
-
|
2305 |
-
if ( ! $allowed ) {
|
2306 |
-
$allowed = absint( crb_get_settings( 'attempts' ) );
|
2307 |
-
}
|
2308 |
-
|
2309 |
-
if ( $check_acl && cerber_acl_check( $ip, 'W' ) ) {
|
2310 |
-
return $allowed; // whitelist = infinity attempts
|
2311 |
-
}
|
2312 |
-
|
2313 |
-
if ( ! $period ) {
|
2314 |
-
$period = absint( crb_get_settings( 'period' ) );
|
2315 |
-
}
|
2316 |
-
|
2317 |
-
$range = time() - $period * 60;
|
2318 |
-
// TODO: remove prepare, replace $activity with an array of integer
|
2319 |
-
$attempts = $wpdb->get_var( $wpdb->prepare( 'SELECT count(ip) FROM ' . CERBER_LOG_TABLE . ' WHERE ip = %s AND activity IN (%s) AND stamp > %d', $ip, $activity, $range ) );
|
2320 |
-
|
2321 |
-
if ( ! $attempts ) {
|
2322 |
-
return $allowed;
|
2323 |
-
}
|
2324 |
-
else {
|
2325 |
-
$ret = $allowed - $attempts;
|
2326 |
-
}
|
2327 |
-
$ret = $ret < 0 ? 0 : $ret;
|
2328 |
-
|
2329 |
-
return $ret;
|
2330 |
-
}
|
2331 |
-
|
2332 |
-
/**
|
2333 |
-
* Is a given IP is allowed to do restricted things?
|
2334 |
-
* Here Cerber makes its decision.
|
2335 |
-
*
|
2336 |
-
* @param $ip string IP address
|
2337 |
-
*
|
2338 |
-
* @return bool
|
2339 |
-
*/
|
2340 |
-
function cerber_is_allowed( $ip = '' ) {
|
2341 |
-
|
2342 |
-
if ( ! $ip ) {
|
2343 |
-
$wp_cerber = get_wp_cerber();
|
2344 |
-
$ip = $wp_cerber->getRemoteIp();
|
2345 |
-
}
|
2346 |
-
|
2347 |
-
if ( ! filter_var( $ip, FILTER_VALIDATE_IP ) ) {
|
2348 |
-
return false;
|
2349 |
-
}
|
2350 |
-
|
2351 |
-
// @since 4.7.9
|
2352 |
-
if ( cerber_block_check( $ip ) ) {
|
2353 |
-
return false;
|
2354 |
-
}
|
2355 |
-
|
2356 |
-
$tag = cerber_acl_check( $ip );
|
2357 |
-
if ( $tag == 'W' ) {
|
2358 |
-
return true;
|
2359 |
-
}
|
2360 |
-
if ( $tag == 'B' ) {
|
2361 |
-
return false;
|
2362 |
-
}
|
2363 |
-
|
2364 |
-
/* @since 4.7.9
|
2365 |
-
if ( cerber_block_check( $ip ) ) {
|
2366 |
-
return false;
|
2367 |
-
}*/
|
2368 |
-
|
2369 |
-
if ( cerber_is_citadel() ) {
|
2370 |
-
return false;
|
2371 |
-
}
|
2372 |
-
|
2373 |
-
if ( lab_is_blocked( $ip, false ) ) {
|
2374 |
-
return false;
|
2375 |
-
}
|
2376 |
-
|
2377 |
-
return true;
|
2378 |
-
}
|
2379 |
-
|
2380 |
-
/**
|
2381 |
-
* Check if a given username is not permitted to login or register
|
2382 |
-
*
|
2383 |
-
* @param $username string
|
2384 |
-
*
|
2385 |
-
* @return bool true if username is prohibited
|
2386 |
-
*/
|
2387 |
-
function cerber_is_prohibited( $username ) {
|
2388 |
-
if ( $list = (array) crb_get_settings( 'prohibited' ) ) {
|
2389 |
-
foreach ( $list as $item ) {
|
2390 |
-
if ( mb_substr( $item, 0, 1 ) == '/' && mb_substr( $item, - 1 ) == '/' ) {
|
2391 |
-
$pattern = trim( $item, '/' );
|
2392 |
-
if ( mb_ereg_match( $pattern, $username, 'i' ) ) {
|
2393 |
-
return true;
|
2394 |
-
}
|
2395 |
-
}
|
2396 |
-
elseif ($username === $item){
|
2397 |
-
return true;
|
2398 |
-
}
|
2399 |
-
}
|
2400 |
-
}
|
2401 |
-
|
2402 |
-
return false;
|
2403 |
-
}
|
2404 |
-
|
2405 |
-
// TODO: Merge with $wp_cerber->getStatus();
|
2406 |
-
function cerber_get_status( $ip ) {
|
2407 |
-
global $cerber_status;
|
2408 |
-
|
2409 |
-
if ( ! empty( $cerber_status ) ) {
|
2410 |
-
return absint($cerber_status);
|
2411 |
-
}
|
2412 |
-
|
2413 |
-
if ( cerber_block_check( $ip ) ) {
|
2414 |
-
return 13;
|
2415 |
-
}
|
2416 |
-
|
2417 |
-
$tag = cerber_acl_check( $ip );
|
2418 |
-
if ( $tag == 'W' ) {
|
2419 |
-
return 0;
|
2420 |
-
}
|
2421 |
-
if ( $tag == 'B' ) {
|
2422 |
-
return 14;
|
2423 |
-
}
|
2424 |
-
|
2425 |
-
if ( cerber_is_citadel() ) {
|
2426 |
-
return 12;
|
2427 |
-
}
|
2428 |
-
|
2429 |
-
if ( lab_is_blocked( $ip, false ) ) {
|
2430 |
-
return 15;
|
2431 |
-
}
|
2432 |
-
|
2433 |
-
|
2434 |
-
return 0;
|
2435 |
-
}
|
2436 |
-
|
2437 |
-
// Access lists (ACL) routines --------------------------------------------------------------------------------
|
2438 |
-
|
2439 |
-
// TODO: move to dashboard.php
|
2440 |
-
/**
|
2441 |
-
* Add IP to specified access list
|
2442 |
-
*
|
2443 |
-
* @param $ip string|array single IP address, string with IP network, range or associative range array
|
2444 |
-
* @param $tag string 'B'|'W'
|
2445 |
-
*
|
2446 |
-
* @return bool|int|object Result of operation
|
2447 |
-
*/
|
2448 |
-
function cerber_acl_add( $ip, $tag, $comment = '') {
|
2449 |
-
global $wpdb;
|
2450 |
-
if ( is_string( $ip ) ) {
|
2451 |
-
if ( ! cerber_is_ipv4( $ip ) ) {
|
2452 |
-
$ip = cerber_short_ipv6( $ip );
|
2453 |
-
}
|
2454 |
-
if ( $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(ip) FROM ' . CERBER_ACL_TABLE . ' WHERE ip = %s', $ip ) ) ) {
|
2455 |
-
return false; //__( 'Element is already in list', 'wp-cerber' );
|
2456 |
-
}
|
2457 |
-
$range = cerber_any2range( $ip );
|
2458 |
-
if ( is_array( $range ) ) {
|
2459 |
-
$begin = $range['begin'];
|
2460 |
-
$end = $range['end'];
|
2461 |
-
}
|
2462 |
-
else {
|
2463 |
-
if (cerber_is_ipv4($ip)) {
|
2464 |
-
$begin = ip2long( $ip );
|
2465 |
-
$end = ip2long( $ip );
|
2466 |
-
}
|
2467 |
-
else{
|
2468 |
-
$begin = 0;
|
2469 |
-
$end = 0;
|
2470 |
-
}
|
2471 |
-
}
|
2472 |
-
|
2473 |
-
$result = $wpdb->insert( CERBER_ACL_TABLE, array( 'ip' => $ip,
|
2474 |
-
'ip_long_begin' => $begin,
|
2475 |
-
'ip_long_end' => $end,
|
2476 |
-
'tag' => $tag,
|
2477 |
-
'comments' => $comment
|
2478 |
-
), array( '%s', '%d', '%d', '%s', '%s' ) );
|
2479 |
-
return $result;
|
2480 |
-
}
|
2481 |
-
elseif ( is_array( $ip ) ) {
|
2482 |
-
$range = $ip['range'];
|
2483 |
-
$begin = $ip['begin'];
|
2484 |
-
$end = $ip['end'];
|
2485 |
-
if ( $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(ip) FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin = %d AND ip_long_end = %d', $begin, $end ) ) ) {
|
2486 |
-
return false;
|
2487 |
-
}
|
2488 |
-
|
2489 |
-
$result = $wpdb->insert( CERBER_ACL_TABLE, array( 'ip' => $range,
|
2490 |
-
'ip_long_begin' => $begin,
|
2491 |
-
'ip_long_end' => $end,
|
2492 |
-
'tag' => $tag,
|
2493 |
-
'comments' => $comment
|
2494 |
-
), array( '%s', '%d', '%d', '%s', '%s' ) );
|
2495 |
-
|
2496 |
-
return $result;
|
2497 |
-
|
2498 |
-
//return $wpdb->query( $wpdb->prepare( 'INSERT INTO ' . CERBER_ACL_TABLE . ' (ip, ip_long_begin, ip_long_end, tag) VALUES (%s,%d,%d,%s)', $range, $begin, $end, $tag ) );
|
2499 |
-
}
|
2500 |
-
|
2501 |
-
return false;
|
2502 |
-
}
|
2503 |
-
// TODO: move to dashboard.php
|
2504 |
-
function cerber_add_white( $ip, $comment = '' ) {
|
2505 |
-
return cerber_acl_add( $ip, 'W', $comment );
|
2506 |
-
}
|
2507 |
-
// TODO: move to dashboard.php
|
2508 |
-
function cerber_add_black( $ip, $comment = '') {
|
2509 |
-
return cerber_acl_add( $ip, 'B', $comment );
|
2510 |
-
}
|
2511 |
-
// TODO: move to dashboard.php
|
2512 |
-
function cerber_acl_remove( $ip ) {
|
2513 |
-
global $wpdb;
|
2514 |
-
if ( is_string( $ip ) ) {
|
2515 |
-
return $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . CERBER_ACL_TABLE . ' WHERE ip = %s ', $ip ) );
|
2516 |
-
} elseif ( is_array( $ip ) ) {
|
2517 |
-
return $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin = %d AND ip_long_end = %d', $ip['begin'], $ip['end'] ) );
|
2518 |
-
}
|
2519 |
-
|
2520 |
-
return false;
|
2521 |
-
}
|
2522 |
-
|
2523 |
-
// TODO: move to dashboard.php
|
2524 |
-
/**
|
2525 |
-
* Can a given IP (user input) be added to the blacklist
|
2526 |
-
*
|
2527 |
-
* @param $ip
|
2528 |
-
* @param string $list
|
2529 |
-
*
|
2530 |
-
* @return bool
|
2531 |
-
*/
|
2532 |
-
function cerber_can_be_listed( $ip, $list = 'B' ) {
|
2533 |
-
global $wp_cerber;
|
2534 |
-
if ( $list == 'B' ) {
|
2535 |
-
if ( crb_acl_is_white( $wp_cerber->getRemoteIp() ) ) {
|
2536 |
-
return true;
|
2537 |
-
}
|
2538 |
-
if ( filter_var( $ip, FILTER_VALIDATE_IP ) ) {
|
2539 |
-
if ( cerber_is_myip( $ip ) ) {
|
2540 |
-
return false;
|
2541 |
-
}
|
2542 |
-
}
|
2543 |
-
$range = cerber_any2range( $ip );
|
2544 |
-
if ( cerber_is_ip_in_range( $range ) ) {
|
2545 |
-
return false;
|
2546 |
-
}
|
2547 |
-
|
2548 |
-
return true;
|
2549 |
-
}
|
2550 |
-
|
2551 |
-
return true;
|
2552 |
-
}
|
2553 |
-
|
2554 |
-
/**
|
2555 |
-
* Check ACLs for given IP. Some extra lines for performance reason.
|
2556 |
-
*
|
2557 |
-
* @param string $ip
|
2558 |
-
* @param string $tag
|
2559 |
-
*
|
2560 |
-
* @return bool|string
|
2561 |
-
*/
|
2562 |
-
function cerber_acl_check( $ip = null, $tag = '' ) {
|
2563 |
-
global $wpdb, $wp_cerber;
|
2564 |
-
static $cache; // @since 5.26
|
2565 |
-
|
2566 |
-
if ( ! $ip ) {
|
2567 |
-
$wp_cerber = get_wp_cerber();
|
2568 |
-
$ip = $wp_cerber->getRemoteIp();
|
2569 |
-
//$ip = cerber_get_remote_ip();
|
2570 |
-
}
|
2571 |
-
|
2572 |
-
$key = cerber_get_id_ip( $ip ) . $tag;
|
2573 |
-
|
2574 |
-
if ( isset( $cache[ $key ] ) ) {
|
2575 |
-
return $cache[ $key ];
|
2576 |
-
}
|
2577 |
-
|
2578 |
-
if ( ! cerber_is_ipv4( $ip ) ) {
|
2579 |
-
$ret = cerber_acl_checkV6( $ip, $tag );
|
2580 |
-
$cache[ $key ] = $ret;
|
2581 |
-
return $ret;
|
2582 |
-
}
|
2583 |
-
|
2584 |
-
$long = ip2long( $ip );
|
2585 |
-
|
2586 |
-
if ( $tag ) {
|
2587 |
-
if ( $tag != 'W' && $tag != 'B' ) {
|
2588 |
-
$ret = false;
|
2589 |
-
}
|
2590 |
-
elseif ( $wpdb->get_var( 'SELECT ip FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin <= '.$long.' AND '.$long.' <= ip_long_end AND tag = "'.$tag.'" LIMIT 1' ) ) {
|
2591 |
-
$ret = true;
|
2592 |
-
}
|
2593 |
-
else {
|
2594 |
-
$ret = false;
|
2595 |
-
}
|
2596 |
-
|
2597 |
-
$cache[ $key ] = $ret;
|
2598 |
-
return $ret;
|
2599 |
-
}
|
2600 |
-
else {
|
2601 |
-
// We use two queries because of possible overlapping an IP and its network
|
2602 |
-
if ( $ret = $wpdb->get_var( 'SELECT tag FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin <= ' . $long . ' AND ' . $long . ' <= ip_long_end AND tag = "W" LIMIT 1' ) ) {
|
2603 |
-
$cache[ $key ] = $ret;
|
2604 |
-
return $ret;
|
2605 |
-
}
|
2606 |
-
if ( $ret = $wpdb->get_var( 'SELECT tag FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin <= ' . $long . ' AND ' . $long . ' <= ip_long_end AND tag = "B" LIMIT 1' ) ) {
|
2607 |
-
$cache[ $key ] = $ret;
|
2608 |
-
return $ret;
|
2609 |
-
}
|
2610 |
-
|
2611 |
-
$cache[ $key ] = false;
|
2612 |
-
return false;
|
2613 |
-
}
|
2614 |
-
}
|
2615 |
-
|
2616 |
-
/**
|
2617 |
-
* IPv6 version of cerber_acl_check() without subnets and ranges
|
2618 |
-
*
|
2619 |
-
* @param null $ip
|
2620 |
-
* @param string $tag
|
2621 |
-
*
|
2622 |
-
* @return bool|null|string
|
2623 |
-
*/
|
2624 |
-
function cerber_acl_checkV6( $ip = null, $tag = '' ) {
|
2625 |
-
global $wpdb, $wp_cerber;
|
2626 |
-
if ( ! $ip ) {
|
2627 |
-
$ip = $wp_cerber->getRemoteIp();
|
2628 |
-
}
|
2629 |
-
if ( $tag ) {
|
2630 |
-
if ( $wpdb->get_var( $wpdb->prepare( 'SELECT count(ip) FROM ' . CERBER_ACL_TABLE . ' WHERE ip = %s AND tag = %s', $ip, $tag ) ) ) {
|
2631 |
-
return true;
|
2632 |
-
}
|
2633 |
-
|
2634 |
-
return false;
|
2635 |
-
} else {
|
2636 |
-
if ( $ret = $wpdb->get_var( $wpdb->prepare( 'SELECT tag FROM ' . CERBER_ACL_TABLE . ' WHERE ip = %s', $ip ) ) ) {
|
2637 |
-
return $ret;
|
2638 |
-
}
|
2639 |
-
|
2640 |
-
return false;
|
2641 |
-
}
|
2642 |
-
}
|
2643 |
-
|
2644 |
-
|
2645 |
-
function crb_acl_is_white( $ip = null ){
|
2646 |
-
|
2647 |
-
$acl = cerber_acl_check( $ip );
|
2648 |
-
if ( $acl == 'W' ) {
|
2649 |
-
return true;
|
2650 |
-
}
|
2651 |
-
|
2652 |
-
return false;
|
2653 |
-
}
|
2654 |
-
|
2655 |
-
/*
|
2656 |
-
* Logging directly to the file
|
2657 |
-
*
|
2658 |
-
* CERBER_FAIL_LOG optional, full path including filename to the log file
|
2659 |
-
* CERBER_LOG_FACILITY optional, use to specify what type of program is logging the messages
|
2660 |
-
*
|
2661 |
-
* */
|
2662 |
-
function cerber_file_log( $user_login, $ip ) {
|
2663 |
-
if ( defined( 'CERBER_FAIL_LOG' ) ) {
|
2664 |
-
if ( $log = @fopen( CERBER_FAIL_LOG, 'a' ) ) {
|
2665 |
-
$pid = absint( @posix_getpid() );
|
2666 |
-
@fwrite( $log, date( 'M j H:i:s ' ) . $_SERVER['SERVER_NAME'] . ' Cerber(' . $_SERVER['HTTP_HOST'] . ')[' . $pid . ']: Authentication failure for ' . $user_login . ' from ' . $ip . "\n" );
|
2667 |
-
@fclose( $log );
|
2668 |
-
}
|
2669 |
-
} else {
|
2670 |
-
@openlog( 'Cerber(' . $_SERVER['HTTP_HOST'] . ')', LOG_NDELAY | LOG_PID, defined( 'CERBER_LOG_FACILITY' ) ? CERBER_LOG_FACILITY : LOG_AUTH );
|
2671 |
-
@syslog( LOG_NOTICE, 'Authentication failure for ' . $user_login . ' from ' . $ip );
|
2672 |
-
@closelog();
|
2673 |
-
}
|
2674 |
-
}
|
2675 |
-
|
2676 |
-
/*
|
2677 |
-
Return wildcard - string like subnet Class C
|
2678 |
-
*/
|
2679 |
-
function cerber_get_subnet( $ip ) {
|
2680 |
-
return preg_replace( '/\.\d{1,3}$/', '.*', $ip );
|
2681 |
-
}
|
2682 |
-
|
2683 |
-
/*
|
2684 |
-
Check if given IP address or wildcard or CIDR is valid
|
2685 |
-
*/
|
2686 |
-
function cerber_is_ip_or_net( $ip ) {
|
2687 |
-
if ( filter_var( $ip, FILTER_VALIDATE_IP ) ) {
|
2688 |
-
return true;
|
2689 |
-
}
|
2690 |
-
// WILDCARD: 192.168.1.*
|
2691 |
-
$ip = str_replace( '*', '0', $ip );
|
2692 |
-
//if ( @inet_pton( $ip ) ) {
|
2693 |
-
if ( filter_var( $ip, FILTER_VALIDATE_IP ) ) {
|
2694 |
-
return true;
|
2695 |
-
}
|
2696 |
-
// CIDR: 192.168.1/24
|
2697 |
-
if ( strpos( $ip, '/' ) ) {
|
2698 |
-
$cidr = explode( '/', $ip );
|
2699 |
-
$net = $cidr[0];
|
2700 |
-
$mask = absint( $cidr[1] );
|
2701 |
-
$dots = substr_count( $net, '.' );
|
2702 |
-
if ( $dots < 3 ) {
|
2703 |
-
if ( $dots == 1 ) {
|
2704 |
-
$net .= '.0.0';
|
2705 |
-
} elseif ( $dots == 2 ) {
|
2706 |
-
$net .= '.0';
|
2707 |
-
}
|
2708 |
-
}
|
2709 |
-
if ( ! cerber_is_ipv4( $net ) ) {
|
2710 |
-
return false;
|
2711 |
-
}
|
2712 |
-
if ( ! is_numeric( $mask ) ) {
|
2713 |
-
return false;
|
2714 |
-
}
|
2715 |
-
|
2716 |
-
return true;
|
2717 |
-
}
|
2718 |
-
|
2719 |
-
return false;
|
2720 |
-
}
|
2721 |
-
|
2722 |
-
/**
|
2723 |
-
* Tries to recognize single IP address or IP v4 range (with dash) in a given string.
|
2724 |
-
*
|
2725 |
-
* @param string $string String to recognize IP address in
|
2726 |
-
*
|
2727 |
-
* @return array|bool|string Return single IP address or wildcard or CIDR as a string, and IP range as an array.
|
2728 |
-
*/
|
2729 |
-
function cerber_parse_ip( $string = '' ) {
|
2730 |
-
$string = trim( $string );
|
2731 |
-
if ( cerber_is_ip_or_net( $string ) ) {
|
2732 |
-
return $string;
|
2733 |
-
}
|
2734 |
-
$explode = explode( '-', $string );
|
2735 |
-
if ( ! is_array( $explode ) || ! $explode ) {
|
2736 |
-
return false;
|
2737 |
-
}
|
2738 |
-
$range = array();
|
2739 |
-
$count = 0;
|
2740 |
-
foreach ( $explode as $ip ) {
|
2741 |
-
$ip = trim( $ip );
|
2742 |
-
if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
|
2743 |
-
$range[] = $ip;
|
2744 |
-
$count ++;
|
2745 |
-
if ( $count >= 2 ) {
|
2746 |
-
break;
|
2747 |
-
}
|
2748 |
-
}
|
2749 |
-
}
|
2750 |
-
if ( count( $range ) < 2 ) {
|
2751 |
-
return false;
|
2752 |
-
}
|
2753 |
-
if ( ip2long( $range[1] ) <= ip2long( $range[0] ) ) {
|
2754 |
-
return false;
|
2755 |
-
}
|
2756 |
-
|
2757 |
-
return array(
|
2758 |
-
'range' => $range[0] . ' - ' . $range[1],
|
2759 |
-
'begin_ip' => $range[0],
|
2760 |
-
'end_ip' => $range[1],
|
2761 |
-
'begin' => ip2long( $range[0] ),
|
2762 |
-
'end' => ip2long( $range[1] ),
|
2763 |
-
);
|
2764 |
-
}
|
2765 |
-
|
2766 |
-
/**
|
2767 |
-
* Convert a network wildcard string like x.x.x.* to an IP v4 range
|
2768 |
-
*
|
2769 |
-
* @param $wildcard string
|
2770 |
-
*
|
2771 |
-
* @return array|bool|string False if no wildcard found, otherwise result of cerber_parse_ip()
|
2772 |
-
*/
|
2773 |
-
function cerber_wildcard2range( $wildcard = '' ) {
|
2774 |
-
$begin = str_replace( '*', '0', $wildcard );
|
2775 |
-
$end = str_replace( '*', '255', $wildcard );
|
2776 |
-
if ( ! cerber_is_ipv4( $begin ) ) {
|
2777 |
-
return false;
|
2778 |
-
}
|
2779 |
-
if ( ! cerber_is_ipv4( $end ) ) {
|
2780 |
-
return false;
|
2781 |
-
}
|
2782 |
-
|
2783 |
-
return cerber_parse_ip( $begin . ' - ' . $end );
|
2784 |
-
}
|
2785 |
-
|
2786 |
-
/**
|
2787 |
-
* Convert a CIDR to an IP v4 range
|
2788 |
-
*
|
2789 |
-
* @param $cidr string
|
2790 |
-
*
|
2791 |
-
* @return array|bool|string
|
2792 |
-
*/
|
2793 |
-
function cerber_cidr2range( $cidr = '' ) {
|
2794 |
-
if ( ! strpos( $cidr, '/' ) ) {
|
2795 |
-
return false;
|
2796 |
-
}
|
2797 |
-
$cidr = explode( '/', $cidr );
|
2798 |
-
$net = $cidr[0];
|
2799 |
-
$mask = absint( $cidr[1] );
|
2800 |
-
$dots = substr_count( $net, '.' );
|
2801 |
-
if ( $dots < 3 ) { // not completed CIDR
|
2802 |
-
if ( $dots == 1 ) {
|
2803 |
-
$net .= '.0.0';
|
2804 |
-
} elseif ( $dots == 2 ) {
|
2805 |
-
$net .= '.0';
|
2806 |
-
}
|
2807 |
-
}
|
2808 |
-
if ( ! cerber_is_ipv4( $net ) ) {
|
2809 |
-
return false;
|
2810 |
-
}
|
2811 |
-
if ( ! is_numeric( $mask ) ) {
|
2812 |
-
return false;
|
2813 |
-
}
|
2814 |
-
$begin = long2ip( ( ip2long( $net ) ) & ( ( - 1 << ( 32 - (int) $mask ) ) ) );
|
2815 |
-
$end = long2ip( ( ip2long( $net ) ) + pow( 2, ( 32 - (int) $mask ) ) - 1 );
|
2816 |
-
|
2817 |
-
return cerber_parse_ip( $begin . ' - ' . $end );
|
2818 |
-
}
|
2819 |
-
|
2820 |
-
/**
|
2821 |
-
* Try to recognize an IP range or a single IP in a string.
|
2822 |
-
*
|
2823 |
-
* @param $string string Network wildcard, CIDR or IP range.
|
2824 |
-
*
|
2825 |
-
* @return array|bool|string
|
2826 |
-
*/
|
2827 |
-
function cerber_any2range( $string = '' ) {
|
2828 |
-
// Do not change the order!
|
2829 |
-
$ret = cerber_wildcard2range( $string );
|
2830 |
-
if ( ! $ret ) {
|
2831 |
-
$ret = cerber_cidr2range( $string );
|
2832 |
-
}
|
2833 |
-
if ( ! $ret ) {
|
2834 |
-
$ret = cerber_parse_ip( $string ); // must be last due to checking for cidr and wildcard
|
2835 |
-
}
|
2836 |
-
|
2837 |
-
return $ret;
|
2838 |
-
}
|
2839 |
-
|
2840 |
-
/*
|
2841 |
-
Check for given IP address or subnet belong to this session.
|
2842 |
-
*/
|
2843 |
-
function cerber_is_myip( $ip ) {
|
2844 |
-
global $wp_cerber;
|
2845 |
-
if ( ! is_string( $ip ) ) {
|
2846 |
-
return false;
|
2847 |
-
}
|
2848 |
-
$remote_ip = $wp_cerber->getRemoteIp();
|
2849 |
-
if ( $ip == $remote_ip ) {
|
2850 |
-
return true;
|
2851 |
-
}
|
2852 |
-
if ( $ip == cerber_get_subnet( $remote_ip ) ) {
|
2853 |
-
return true;
|
2854 |
-
}
|
2855 |
-
|
2856 |
-
return false;
|
2857 |
-
}
|
2858 |
-
|
2859 |
-
function cerber_is_ip_in_range( $range, $ip = null ) {
|
2860 |
-
global $wp_cerber;
|
2861 |
-
if ( ! is_array( $range ) ) {
|
2862 |
-
return false;
|
2863 |
-
}
|
2864 |
-
if ( ! $ip ) {
|
2865 |
-
$ip = $wp_cerber->getRemoteIp();
|
2866 |
-
}
|
2867 |
-
$long = ip2long( $ip );
|
2868 |
-
if ( $range['begin'] <= $long && $long <= $range['end'] ) {
|
2869 |
-
return true;
|
2870 |
-
}
|
2871 |
-
|
2872 |
-
return false;
|
2873 |
-
}
|
2874 |
-
|
2875 |
-
/**
|
2876 |
-
* Display 404 page to bump bots and bad guys
|
2877 |
-
*
|
2878 |
-
* @param bool $simple If true force displaying basic 404 page
|
2879 |
-
*/
|
2880 |
-
function cerber_404_page($simple = false) {
|
2881 |
-
global $wp_query;
|
2882 |
-
|
2883 |
-
if ( !$simple ) {
|
2884 |
-
if ( function_exists( 'status_header' ) ) {
|
2885 |
-
status_header( '404' );
|
2886 |
-
}
|
2887 |
-
if ( $wp_query && is_object( $wp_query ) ) {
|
2888 |
-
$wp_query->set_404();
|
2889 |
-
}
|
2890 |
-
if ( 0 == crb_get_settings( 'page404' ) ) {
|
2891 |
-
$template = null;
|
2892 |
-
if ( function_exists( 'get_404_template' ) ) {
|
2893 |
-
$template = get_404_template();
|
2894 |
-
}
|
2895 |
-
if ( function_exists( 'apply_filters' ) ) {
|
2896 |
-
$template = apply_filters( 'cerber_404_template', $template );
|
2897 |
-
}
|
2898 |
-
if ( $template && @file_exists( $template ) ) {
|
2899 |
-
include( $template );
|
2900 |
-
exit;
|
2901 |
-
}
|
2902 |
-
}
|
2903 |
-
}
|
2904 |
-
|
2905 |
-
header( 'HTTP/1.0 404 Not Found', true, 404 );
|
2906 |
-
echo '<html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL ' . esc_url( $_SERVER['REQUEST_URI'] ) . ' was not found on this server.</p></body></html>';
|
2907 |
-
cerber_traffic_log(); // do not remove!
|
2908 |
-
exit;
|
2909 |
-
}
|
2910 |
-
/*
|
2911 |
-
Display Forbidden page
|
2912 |
-
*/
|
2913 |
-
function cerber_forbidden_page() {
|
2914 |
-
status_header( '403' );
|
2915 |
-
header( 'HTTP/1.0 403 Access Forbidden', true, 403 );
|
2916 |
-
?>
|
2917 |
-
<!DOCTYPE html>
|
2918 |
-
<html style="height: 100%;">
|
2919 |
-
<meta charset="UTF-8">
|
2920 |
-
<head><title>403 Access Forbidden</title></head>
|
2921 |
-
<body style="height: 100%;">
|
2922 |
-
<div style="display: flex; align-items: center; justify-content: center; height: 70%;">
|
2923 |
-
<div style="background-color: #eee; width: 70%; border: solid 3px #ddd; padding: 1.5em 3em 3em 3em; font-family: Arial, Helvetica, sans-serif;">
|
2924 |
-
<div style="display: table-row;">
|
2925 |
-
<div style="display: table-cell; font-size: 150px; color: red; vertical-align: middle; padding-right: 50px;">
|
2926 |
-
✋
|
2927 |
-
</div>
|
2928 |
-
<div style="display: table-cell; vertical-align: middle;">
|
2929 |
-
<h1><?php _e("We're sorry, you are not allowed to proceed", 'wp-cerber'); ?></h1>
|
2930 |
-
<p>Our server stopped processing your request. Your request looks suspicious or similar to automated
|
2931 |
-
requests from spam posting software.</p>
|
2932 |
-
<p>If you believe you should be able to perform this request, please let us know.</p>
|
2933 |
-
</div>
|
2934 |
-
</div>
|
2935 |
-
</div>
|
2936 |
-
</div>
|
2937 |
-
</body>
|
2938 |
-
</html>
|
2939 |
-
<?php
|
2940 |
-
cerber_traffic_log(); // do not remove!
|
2941 |
-
exit;
|
2942 |
-
}
|
2943 |
-
|
2944 |
-
// Citadel mode -------------------------------------------------------------------------------------
|
2945 |
-
|
2946 |
-
function cerber_enable_citadel() {
|
2947 |
-
global $wp_cerber;
|
2948 |
-
if ( get_transient( 'cerber_citadel' ) ) {
|
2949 |
-
return;
|
2950 |
-
}
|
2951 |
-
set_transient( 'cerber_citadel', true, crb_get_settings( 'ciduration' ) * 60 );
|
2952 |
-
cerber_log( 12 );
|
2953 |
-
|
2954 |
-
// Notify admin
|
2955 |
-
if ( $wp_cerber->getSettings( 'cinotify' ) ) {
|
2956 |
-
cerber_send_notify( 'citadel' );
|
2957 |
-
}
|
2958 |
-
}
|
2959 |
-
|
2960 |
-
function cerber_disable_citadel() {
|
2961 |
-
delete_transient( 'cerber_citadel' );
|
2962 |
-
}
|
2963 |
-
|
2964 |
-
function cerber_is_citadel() {
|
2965 |
-
if ( get_transient( 'cerber_citadel' ) ) {
|
2966 |
-
return true;
|
2967 |
-
}
|
2968 |
-
|
2969 |
-
return false;
|
2970 |
-
}
|
2971 |
-
|
2972 |
-
// Hardening -------------------------------------------------------------------------------------
|
2973 |
-
|
2974 |
-
//if (!cerber_acl_check(cerber_get_ip(),'W') && false) {
|
2975 |
-
|
2976 |
-
/*
|
2977 |
-
if ($hardening['ping']) {
|
2978 |
-
add_filter( 'xmlrpc_methods', 'remove_xmlrpc_pingback' );
|
2979 |
-
function remove_xmlrpc_pingback( $methods ) {
|
2980 |
-
unset($methods['pingback.ping']);
|
2981 |
-
unset($methods['pingback.extensions.getPingbacks']);
|
2982 |
-
return $methods;
|
2983 |
-
}
|
2984 |
-
add_filter( 'wp_headers', 'remove_pingback_header' );
|
2985 |
-
function remove_pingback_header( $headers ) {
|
2986 |
-
unset( $headers['X-Pingback'] );
|
2987 |
-
return $headers;
|
2988 |
-
}
|
2989 |
-
}
|
2990 |
-
*/
|
2991 |
-
//pingback_ping();
|
2992 |
-
|
2993 |
-
|
2994 |
-
/*
|
2995 |
-
// Remove shortlink from HEAD <link rel='shortlink' href='http://адрес-сайта/?p=45' />
|
2996 |
-
remove_action('wp_head', 'wp_shortlink_wp_head', 10, 0 );
|
2997 |
-
*/
|
2998 |
-
|
2999 |
-
/**
|
3000 |
-
*
|
3001 |
-
* Send notification letter
|
3002 |
-
*
|
3003 |
-
* @param string $type Notification type
|
3004 |
-
* @param string|array $msg Additional message
|
3005 |
-
* @param string $ip Remote IP address, if applicable
|
3006 |
-
*
|
3007 |
-
* @return bool
|
3008 |
-
*/
|
3009 |
-
function cerber_send_notify( $type = '', $msg = '', $ip = '' ) {
|
3010 |
-
global $wpdb, $wp_cerber;
|
3011 |
-
if ( ! $type ) {
|
3012 |
-
return false;
|
3013 |
-
}
|
3014 |
-
|
3015 |
-
/*
|
3016 |
-
$super = false;
|
3017 |
-
if ( function_exists( 'is_super_admin' ) ) {
|
3018 |
-
$super = is_super_admin();
|
3019 |
-
}
|
3020 |
-
if ( $type == 'lockout' && !$usper()) {
|
3021 |
-
*/
|
3022 |
-
|
3023 |
-
if ( $type == 'lockout' && !is_admin()) {
|
3024 |
-
$rate = absint( $wp_cerber->getSettings( 'emailrate' ) );
|
3025 |
-
if ( $rate ) {
|
3026 |
-
$last = get_transient( 'cerber_last' );
|
3027 |
-
$period = 60 * 60; // per hour
|
3028 |
-
if ( $last ) {
|
3029 |
-
if ( $last > ( time() - $period / $rate ) ) {
|
3030 |
-
return false;
|
3031 |
-
}
|
3032 |
-
}
|
3033 |
-
set_transient( 'cerber_last', time(), $period );
|
3034 |
-
}
|
3035 |
-
}
|
3036 |
-
|
3037 |
-
$html_mode = false;
|
3038 |
-
|
3039 |
-
$subj = '[' . get_option( 'blogname' ) . '] ' . __( 'WP Cerber notify', 'wp-cerber' ) . ': ';
|
3040 |
-
$body = '';
|
3041 |
-
|
3042 |
-
if ( is_array( $msg ) ) {
|
3043 |
-
$msg = implode( "\n\n", $msg );
|
3044 |
-
}
|
3045 |
-
|
3046 |
-
switch ( $type ) {
|
3047 |
-
case 'citadel':
|
3048 |
-
$max = $wpdb->get_var( 'SELECT MAX(stamp) FROM ' . CERBER_LOG_TABLE . ' WHERE activity = 7' );
|
3049 |
-
if ($max) {
|
3050 |
-
$last_date = cerber_date( $max );
|
3051 |
-
$last = $wpdb->get_row( 'SELECT * FROM ' . CERBER_LOG_TABLE . ' WHERE stamp = ' . $max . ' AND activity = 7' );
|
3052 |
-
}
|
3053 |
-
else $last = null;
|
3054 |
-
|
3055 |
-
if ( ! $last ) { // workaround for the empty log table
|
3056 |
-
$last = new stdClass();
|
3057 |
-
$last->ip = '127.0.0.1';
|
3058 |
-
$last->user_login = 'test';
|
3059 |
-
}
|
3060 |
-
|
3061 |
-
$subj .= __( 'Citadel mode is activated', 'wp-cerber' );
|
3062 |
-
|
3063 |
-
$body = sprintf( __( 'Citadel mode is activated after %d failed login attempts in %d minutes.', 'wp-cerber' ), $wp_cerber->getSettings( 'cilimit' ), $wp_cerber->getSettings( 'ciperiod' ) ) . "\n\n";
|
3064 |
-
$body .= sprintf( __( 'Last failed attempt was at %s from IP %s with user login: %s.', 'wp-cerber' ), $last_date, $last->ip, $last->user_login ) . "\n\n";
|
3065 |
-
$body .= __( 'View activity in dashboard', 'wp-cerber' ) . ': ' . cerber_admin_link( 'activity' ) . "\n\n";
|
3066 |
-
//$body .= __('Change notification settings','wp-cerber').': '.cerber_admin_link();
|
3067 |
-
break;
|
3068 |
-
case 'lockout':
|
3069 |
-
$max = $wpdb->get_var( 'SELECT MAX(stamp) FROM ' . CERBER_LOG_TABLE . ' WHERE activity IN (10,11)' );
|
3070 |
-
if ($max){
|
3071 |
-
$last_date = cerber_date( $max );
|
3072 |
-
$last = $wpdb->get_row( 'SELECT * FROM ' . CERBER_LOG_TABLE . ' WHERE stamp = ' . $max . ' AND activity IN (10,11)' );
|
3073 |
-
}
|
3074 |
-
else $last = null;
|
3075 |
-
if ( ! $last ) { // workaround for the empty log table
|
3076 |
-
$last = new stdClass();
|
3077 |
-
$last->ip = '127.0.0.1';
|
3078 |
-
$last->user_login = 'test';
|
3079 |
-
}
|
3080 |
-
|
3081 |
-
//if ( ! $active = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_BLOCKS_TABLE ) ) {
|
3082 |
-
if ( ! $active = cerber_blocked_num() ) {
|
3083 |
-
$active = 0;
|
3084 |
-
}
|
3085 |
-
//if ( $ip && ( $block = cerber_get_block( $ip ) ) ) {
|
3086 |
-
if ( $last->ip && ( $block = cerber_get_block( $last->ip ) ) ) {
|
3087 |
-
$reason = $block->reason;
|
3088 |
-
}
|
3089 |
-
else {
|
3090 |
-
$reason = __( 'unspecified', 'wp-cerber' );
|
3091 |
-
}
|
3092 |
-
|
3093 |
-
$subj .= __( 'Number of lockouts is increasing', 'wp-cerber' ) . ' (' . $active . ')';
|
3094 |
-
|
3095 |
-
$body = __( 'Number of active lockouts', 'wp-cerber' ) . ': ' . $active . "\n\n";
|
3096 |
-
$body .= sprintf( __( 'Last lockout was added: %s for IP %s', 'wp-cerber' ), $last_date, $last->ip . ' (' . @gethostbyaddr( $last->ip ) . ')' ) . "\n\n";
|
3097 |
-
$body .= __( 'Reason', 'wp-cerber' ) . ': ' . strip_tags($reason) . "\n\n";
|
3098 |
-
$body .= __( 'View activity for this IP', 'wp-cerber' ) . ': ' . cerber_admin_link( 'activity' ) . '&filter_ip=' . $last->ip . "\n\n";
|
3099 |
-
$body .= __( 'View lockouts in dashboard', 'wp-cerber' ) . ': ' . cerber_admin_link( 'lockouts' ) . "\n\n";
|
3100 |
-
break;
|
3101 |
-
case 'new_version':
|
3102 |
-
$subj = __( 'A new version of WP Cerber is available to install', 'wp-cerber' );
|
3103 |
-
$body = __( 'Hi!', 'wp-cerber' ) . "\n\n";
|
3104 |
-
$body .= __( 'A new version of WP Cerber is available to install', 'wp-cerber' ) . "\n\n";
|
3105 |
-
$body .= $msg . "\n\n";
|
3106 |
-
$body .= __( 'Website', 'wp-cerber' ) . ': ' . get_bloginfo( 'name' );
|
3107 |
-
break;
|
3108 |
-
case 'shutdown':
|
3109 |
-
$subj = '[' . get_option( 'blogname' ) . '] ' . __( 'The WP Cerber security plugin has been deactivated', 'wp-cerber' );
|
3110 |
-
$body .= __( 'The WP Cerber security plugin has been deactivated', 'wp-cerber' ) . "\n\n";
|
3111 |
-
if ( ! is_user_logged_in() ) {
|
3112 |
-
$u = __( 'Not logged in', 'wp-cerber' );
|
3113 |
-
} else {
|
3114 |
-
$user = wp_get_current_user();
|
3115 |
-
$u = $user->display_name;
|
3116 |
-
}
|
3117 |
-
$body .= __( 'Website', 'wp-cerber' ) . ': ' . get_bloginfo( 'name' ) . "\n";
|
3118 |
-
$body .= __( 'By user', 'wp-cerber' ) . ': ' . $u . "\n";
|
3119 |
-
$body .= __( 'From IP address', 'wp-cerber' ) . ': ' . $wp_cerber->getRemoteIp() . "\n";
|
3120 |
-
$whois = cerber_ip_whois_info( $wp_cerber->getRemoteIp() );
|
3121 |
-
if ( ! empty( $whois['data']['country'] ) ) {
|
3122 |
-
$body .= __( 'From country', 'wp-cerber' ) . ': ' . cerber_country_name( $whois['data']['country'] );
|
3123 |
-
}
|
3124 |
-
break;
|
3125 |
-
case 'activated':
|
3126 |
-
$subj = '[' . get_option( 'blogname' ) . '] ' . __( 'The WP Cerber security plugin is now active', 'wp-cerber' );
|
3127 |
-
$body .= __( 'WP Cerber is now active and has started protecting your site', 'wp-cerber' ) . "\n\n";
|
3128 |
-
//$body .= __( 'Change notification settings', 'wp-cerber' ) . ': ' . cerber_admin_link('notifications') . "\n\n";
|
3129 |
-
$body .= __( 'Getting Started Guide', 'wp-cerber' ) . "\n\n";
|
3130 |
-
$body .= 'https://wpcerber.com/getting-started/' . "\n\n";
|
3131 |
-
$body .= 'Be in touch with the developer. Subscribe to Cerber\'s newsletter: http://wpcerber.com/subscribe-newsletter/';
|
3132 |
-
//$body .= get_bloginfo( 'name' );
|
3133 |
-
break;
|
3134 |
-
case 'newlurl':
|
3135 |
-
$subj .= __( 'New Custom login URL', 'wp-cerber' );
|
3136 |
-
$body .= $msg;
|
3137 |
-
break;
|
3138 |
-
case 'subs':
|
3139 |
-
$subj .= __( 'A new activity has been recorded', 'wp-cerber' );
|
3140 |
-
$body = __( 'A new activity has been recorded', 'wp-cerber' ) . "\n\n";
|
3141 |
-
$body .= $msg;
|
3142 |
-
break;
|
3143 |
-
case 'report':
|
3144 |
-
$html_mode = true;
|
3145 |
-
$subj = '[' . get_option( 'blogname' ) . '] WP Cerber Security: ' . __( 'Weekly report', 'wp-cerber' );
|
3146 |
-
$body = cerber_generate_report();
|
3147 |
-
$link = cerber_admin_link( 'notifications' );
|
3148 |
-
$body .= '<br/>' . __( 'To change reporting settings visit', 'wp-cerber' ) . ' <a href="' . $link . '">' . $link . '</a>';
|
3149 |
-
if ($msg) {
|
3150 |
-
$body .= nl2br($msg);
|
3151 |
-
}
|
3152 |
-
break;
|
3153 |
-
}
|
3154 |
-
|
3155 |
-
$to_list = cerber_get_email( $type, true );
|
3156 |
-
$to = implode( ', ', $to_list );
|
3157 |
-
|
3158 |
-
$body_filtered = apply_filters( 'cerber_notify_body', $body, array( 'type' => $type,
|
3159 |
-
'IP' => $ip,
|
3160 |
-
'to' => $to,
|
3161 |
-
'subject' => $subj
|
3162 |
-
) );
|
3163 |
-
if ( $body_filtered && is_string( $body_filtered ) ) {
|
3164 |
-
$body = $body_filtered;
|
3165 |
-
}
|
3166 |
-
|
3167 |
-
$footer = '';
|
3168 |
-
|
3169 |
-
if ( $lolink = cerber_get_login_url() ) {
|
3170 |
-
$lourl = urldecode( $lolink );
|
3171 |
-
if ( $html_mode ) {
|
3172 |
-
$lourl = '<a href="' . $lolink . '">' . $lourl . '</a>';
|
3173 |
-
}
|
3174 |
-
$footer .= "\n\n" . __( 'Your login page:', 'wp-cerber' ) . ' ' . $lourl;
|
3175 |
-
}
|
3176 |
-
|
3177 |
-
if ( $type == 'report' && $date = lab_lab(true) ) {
|
3178 |
-
$footer .= "\n\n" . __( 'Your license is valid until', 'wp-cerber' ) . ' ' . $date;
|
3179 |
-
}
|
3180 |
-
|
3181 |
-
$footer .= "\n\n\n" . __( 'This message was sent by', 'wp-cerber' ) . ' WP Cerber Security ' . CERBER_VER . "\n";
|
3182 |
-
$footer .= 'https://wpcerber.com';
|
3183 |
-
|
3184 |
-
if ( $html_mode ) {
|
3185 |
-
add_filter( 'wp_mail_content_type', 'cerber_enable_html' );
|
3186 |
-
$footer = str_replace( "\n", '<br/>', $footer );
|
3187 |
-
}
|
3188 |
-
|
3189 |
-
// Everything is prepared, let's send it out
|
3190 |
-
|
3191 |
-
$result = null;
|
3192 |
-
if ( $to && $subj && $body ) {
|
3193 |
-
if ( ! $html_mode ) {
|
3194 |
-
cerber_pb_send( $subj, $body.$footer );
|
3195 |
-
}
|
3196 |
-
|
3197 |
-
if ( $type == 'report') {
|
3198 |
-
$result = true;
|
3199 |
-
foreach ( $to_list as $email ) {
|
3200 |
-
$lastus = '';
|
3201 |
-
if ( $rec = cerber_get_last_login( null, $email ) ) {
|
3202 |
-
$lastus = sprintf( __( 'Your last sign-in was %s from %s', 'wp-cerber' ), cerber_date( $rec->stamp ), $rec->ip . ' (' . cerber_country_name( $rec->country ) . ')' );
|
3203 |
-
if ( $html_mode ) {
|
3204 |
-
$lastus = '<br/><br/>' . $lastus;
|
3205 |
-
}
|
3206 |
-
else {
|
3207 |
-
$lastus = "\n\n" . $lastus;
|
3208 |
-
}
|
3209 |
-
}
|
3210 |
-
|
3211 |
-
if ( ! wp_mail( $email, $subj, '<html>' . $body . $lastus . $footer . '</html>' ) ) {
|
3212 |
-
$result = false;
|
3213 |
-
}
|
3214 |
-
}
|
3215 |
-
}
|
3216 |
-
else {
|
3217 |
-
if ( function_exists( 'wp_mail' ) ) {
|
3218 |
-
$body = $body . $footer;
|
3219 |
-
if ( $html_mode ) {
|
3220 |
-
$body = '<html>' . $body . '</html>';
|
3221 |
-
}
|
3222 |
-
$result = wp_mail( $to, $subj, $body );
|
3223 |
-
}
|
3224 |
-
}
|
3225 |
-
}
|
3226 |
-
|
3227 |
-
remove_filter('wp_mail_content_type', 'cerber_enable_html');
|
3228 |
-
|
3229 |
-
$params = array( 'type' => $type, 'IP' => $ip, 'to' => $to, 'subject' => $subj );
|
3230 |
-
if ( $result ) {
|
3231 |
-
do_action( 'cerber_notify_sent', $body, $params );
|
3232 |
-
}
|
3233 |
-
else {
|
3234 |
-
do_action( 'cerber_notify_fail', $body, $params );
|
3235 |
-
}
|
3236 |
-
|
3237 |
-
return $result;
|
3238 |
-
}
|
3239 |
-
|
3240 |
-
function cerber_enable_html() {
|
3241 |
-
return 'text/html';
|
3242 |
-
}
|
3243 |
-
|
3244 |
-
/**
|
3245 |
-
* Generates a performance report
|
3246 |
-
*
|
3247 |
-
* @param int $period Days to look back
|
3248 |
-
*
|
3249 |
-
* @return string
|
3250 |
-
*/
|
3251 |
-
function cerber_generate_report($period = 7){
|
3252 |
-
global $wpdb;
|
3253 |
-
|
3254 |
-
$period = absint( $period );
|
3255 |
-
|
3256 |
-
if ( ! $period ) {
|
3257 |
-
$period = 7;
|
3258 |
-
}
|
3259 |
-
|
3260 |
-
$ret = '';
|
3261 |
-
$rows = array();
|
3262 |
-
$stamp = time() - $period * 24 * 3600;
|
3263 |
-
//$in = implode( ',', crb_get_activity_set( 'malicious' ) );
|
3264 |
-
//$link_base = '<a href="' . cerber_activity_link( array( 2 ) ) . '">';
|
3265 |
-
$base_url = cerber_admin_link( 'activity' );
|
3266 |
-
$css_table = 'width: 95%; max-width: 1000px; margin:0 auto; margin-bottom: 10px; background-color: #f5f5f5; text-align: center;';
|
3267 |
-
$css_td = 'padding: 0.5em 0.5em 0.5em 1em; text-align: left;';
|
3268 |
-
$css_boder = 'border-bottom: solid 2px #f9f9f9;';
|
3269 |
-
|
3270 |
-
if (is_multisite()) {
|
3271 |
-
$site_name = get_site_option( 'site_name' );
|
3272 |
-
}
|
3273 |
-
else {
|
3274 |
-
$site_name = get_option( 'blogname' );
|
3275 |
-
}
|
3276 |
-
|
3277 |
-
$ret .= '<div style="' . $css_table . '"><div style="margin:0 auto; text-align: center;"><p style="font-size: 130%; padding-top: 0.5em;">' . $site_name .'</p><p style="padding-bottom: 1em;">'. __('Weekly Report','wp-cerber'). '</p></div></div>';
|
3278 |
-
|
3279 |
-
$kpi_list = cerber_calculate_kpi( $period );
|
3280 |
-
|
3281 |
-
foreach ($kpi_list as $kpi){
|
3282 |
-
$rows[] = '<td style="'.$css_td.' text-align: right;">'.$kpi[1].'</td><td style="padding: 0.5em; text-align: left;">'.$kpi[0].'</td>';
|
3283 |
-
}
|
3284 |
-
|
3285 |
-
$ret .= '<div style="text-align: center; '.$css_table.'"><table style="font-size: 130%; margin:0 auto;"><tr>' . implode( '</tr><tr>', $rows ) . '</tr></table></div>';
|
3286 |
-
|
3287 |
-
// Activities counters
|
3288 |
-
$rows = array();
|
3289 |
-
$rows[] = '<td style="'.$css_td.$css_boder.'" colspan="2"><p style="line-height: 1.5em; font-weight: bold;">'.__('Activity details','wp-cerber').'</p></td>';
|
3290 |
-
$activites = $wpdb->get_results( 'SELECT activity, COUNT(activity) cnt FROM ' . CERBER_LOG_TABLE . ' WHERE stamp > ' . $stamp . ' GROUP by activity ORDER BY cnt DESC' );
|
3291 |
-
if ( $activites ) {
|
3292 |
-
$lables = cerber_get_labels();
|
3293 |
-
foreach ( $activites as $a ) {
|
3294 |
-
$rows[] = '<td style="'.$css_boder.$css_td.'">' . $lables[ $a->activity ] . '</td><td style="padding: 0.5em; text-align: center; width:10%;'.$css_boder.'"><a href="'.$base_url.'&filter_activity='.$a->activity.'">' . $a->cnt . '</a></td>';
|
3295 |
-
}
|
3296 |
-
}
|
3297 |
-
$ret .= '<table style="border-collapse: collapse; '.$css_table.'"><tr>' . implode( '</tr><tr>', $rows ) . '</tr></table>';
|
3298 |
-
|
3299 |
-
// Activities counters
|
3300 |
-
$activites = $wpdb->get_results( 'SELECT user_login, COUNT(user_login) cnt FROM ' . CERBER_LOG_TABLE . ' WHERE activity = 51 AND stamp > ' . $stamp . ' GROUP by user_login ORDER BY cnt DESC LIMIT 10' );
|
3301 |
-
if ( $activites ) {
|
3302 |
-
$rows = array();
|
3303 |
-
$rows[] = '<td style="'.$css_td.$css_boder.'" colspan="2"><p style="line-height: 1.5em; font-weight: bold;">'.__('Attempts to log in with non-existent username','wp-cerber').'</p></td>';
|
3304 |
-
foreach ( $activites as $a ) {
|
3305 |
-
$rows[] = '<td style="'.$css_boder.$css_td.'">' . htmlspecialchars($a->user_login) . '</td><td style="padding: 0.5em; text-align: center; width:10%;'.$css_boder.'"><a href="'.$base_url.'&filter_login='.$a->user_login.'">' . $a->cnt . '</a></td>';
|
3306 |
-
}
|
3307 |
-
$ret .= '<table style="border-collapse: collapse; '.$css_table.'"><tr>' . implode( '</tr><tr>', $rows ) . '</tr></table>';
|
3308 |
-
}
|
3309 |
-
|
3310 |
-
$ret = '<div style="width:100%; padding: 1em; text-align: center; background-color: #f9f9f9;">' . $ret . '</div>';
|
3311 |
-
|
3312 |
-
return $ret;
|
3313 |
-
}
|
3314 |
-
|
3315 |
-
|
3316 |
-
// Maintenance routines ----------------------------------------------------------------
|
3317 |
-
|
3318 |
-
function cerber_init_cron(){
|
3319 |
-
$next_hour = floor( ( time() + 3600 ) / 3600 ) * 3600;
|
3320 |
-
|
3321 |
-
if ( ! wp_next_scheduled( 'cerber_hourly_1' ) ) {
|
3322 |
-
wp_schedule_event( $next_hour + 600, 'hourly', 'cerber_hourly_1' );
|
3323 |
-
}
|
3324 |
-
|
3325 |
-
if ( ! wp_next_scheduled( 'cerber_hourly_2' ) ) {
|
3326 |
-
wp_schedule_event( $next_hour , 'hourly', 'cerber_hourly_2' );
|
3327 |
-
}
|
3328 |
-
|
3329 |
-
if ( ! wp_next_scheduled( 'cerber_daily' ) ) {
|
3330 |
-
wp_schedule_event( $next_hour + 3600, 'daily', 'cerber_daily' );
|
3331 |
-
}
|
3332 |
-
}
|
3333 |
-
|
3334 |
-
add_action( 'cerber_hourly_1', 'cerber_do_hourly' );
|
3335 |
-
function cerber_do_hourly($force = false) {
|
3336 |
-
global $wpdb, $wp_cerber;
|
3337 |
-
|
3338 |
-
if (is_multisite()) {
|
3339 |
-
if ( ! $force && get_site_transient( 'cerber_multisite' ) ) {
|
3340 |
-
return;
|
3341 |
-
}
|
3342 |
-
set_site_transient( 'cerber_multisite', 'executed', 3600 );
|
3343 |
-
}
|
3344 |
-
|
3345 |
-
if ( crb_get_settings( 'cerberlab' ) ) {
|
3346 |
-
lab_check_nodes();
|
3347 |
-
}
|
3348 |
-
|
3349 |
-
$time = time();
|
3350 |
-
$days = absint( crb_get_settings( 'keeplog' ) );
|
3351 |
-
if ( $days > 0 ) {
|
3352 |
-
$wpdb->query( 'DELETE FROM ' . CERBER_LOG_TABLE . ' WHERE stamp < ' . ( $time - $days * 24 * 3600 ) );
|
3353 |
-
}
|
3354 |
-
$days = absint( crb_get_settings( 'tikeeprec' ) );
|
3355 |
-
if ( $days > 0 ) {
|
3356 |
-
$wpdb->query( 'DELETE FROM ' . CERBER_TRAF_TABLE . ' WHERE stamp < ' . ( $time - $days * 24 * 3600 ) );
|
3357 |
-
}
|
3358 |
-
|
3359 |
-
if ( crb_get_settings( 'cerberlab' ) ) {
|
3360 |
-
cerber_push_lab();
|
3361 |
-
}
|
3362 |
-
|
3363 |
-
$wpdb->query( 'DELETE FROM ' . CERBER_LAB_IP_TABLE . ' WHERE expires < ' . $time );
|
3364 |
-
|
3365 |
-
if ( $wp_cerber->getSettings( 'trashafter-enabled') && absint($wp_cerber->getSettings('trashafter'))) {
|
3366 |
-
$list = get_comments( array( 'status' => 'spam' ) );
|
3367 |
-
if ( $list ) {
|
3368 |
-
$time = time() - DAY_IN_SECONDS * absint($wp_cerber->getSettings( 'trashafter' ));
|
3369 |
-
foreach ( $list as $item ) {
|
3370 |
-
if ( $time > strtotime( $item->comment_date_gmt ) ) {
|
3371 |
-
wp_trash_comment( $item->comment_ID );
|
3372 |
-
}
|
3373 |
-
}
|
3374 |
-
}
|
3375 |
-
}
|
3376 |
-
|
3377 |
-
cerber_up_data();
|
3378 |
-
|
3379 |
-
set_site_transient( 'crb_hourly_1', date( 'G' ) , 3600 );
|
3380 |
-
}
|
3381 |
-
|
3382 |
-
add_action( 'cerber_hourly_2', function () {
|
3383 |
-
|
3384 |
-
// Avoid multiple executions on a weird hosting
|
3385 |
-
if ( ( $hour = get_site_transient( 'crb_hourly_2' ) ) && $hour == date( 'G' ) ) {
|
3386 |
-
return;
|
3387 |
-
}
|
3388 |
-
|
3389 |
-
$gmt_offset = get_option( 'gmt_offset' ) * 3600;
|
3390 |
-
|
3391 |
-
if ( crb_get_settings( 'enable-report' )
|
3392 |
-
&& date( 'w', time() + $gmt_offset ) == crb_get_settings( 'wreports-day' )
|
3393 |
-
&& date( 'G', time() + $gmt_offset ) == crb_get_settings( 'wreports-time' )
|
3394 |
-
//&& ! get_site_transient( 'cerber_wreport' )
|
3395 |
-
) {
|
3396 |
-
$result = cerber_send_notify( 'report' );
|
3397 |
-
//set_site_transient( 'cerber_wreport', 'sent', 7200 );
|
3398 |
-
update_site_option( '_cerber_report', array( time(), $result ) );
|
3399 |
-
}
|
3400 |
-
|
3401 |
-
cerber_watchdog( true );
|
3402 |
-
|
3403 |
-
set_site_transient( 'crb_hourly_2', date( 'G' ) , 3600 );
|
3404 |
-
});
|
3405 |
-
|
3406 |
-
add_action( 'cerber_daily', 'cerber_do_daily' );
|
3407 |
-
function cerber_do_daily() {
|
3408 |
-
global $wpdb, $wp_cerber;
|
3409 |
-
|
3410 |
-
cerber_do_hourly( true );
|
3411 |
-
|
3412 |
-
$time = time();
|
3413 |
-
|
3414 |
-
lab_trunc_push();
|
3415 |
-
|
3416 |
-
lab_validate_lic();
|
3417 |
-
|
3418 |
-
$wpdb->query( 'DELETE FROM ' . CERBER_LAB_NET_TABLE . ' WHERE expires < ' . $time );
|
3419 |
-
|
3420 |
-
$wpdb->query( 'OPTIMIZE TABLE ' . CERBER_LOG_TABLE );
|
3421 |
-
$wpdb->query( 'OPTIMIZE TABLE ' . CERBER_TRAF_TABLE );
|
3422 |
-
$wpdb->query( 'OPTIMIZE TABLE ' . CERBER_ACL_TABLE );
|
3423 |
-
$wpdb->query( 'OPTIMIZE TABLE ' . CERBER_BLOCKS_TABLE );
|
3424 |
-
$wpdb->query( 'OPTIMIZE TABLE ' . CERBER_LAB_TABLE );
|
3425 |
-
$wpdb->query( 'OPTIMIZE TABLE ' . CERBER_LAB_IP_TABLE );
|
3426 |
-
$wpdb->query( 'OPTIMIZE TABLE ' . CERBER_LAB_NET_TABLE );
|
3427 |
-
|
3428 |
-
if ( $new = cerber_check_version() ) {
|
3429 |
-
$history = get_site_option( '_cerber_notify_new' );
|
3430 |
-
if ( ! $history || ! is_array( $history ) ) {
|
3431 |
-
$history = array();
|
3432 |
-
}
|
3433 |
-
if ( !in_array( $new['ver'], $history ) ) {
|
3434 |
-
cerber_send_notify( 'new_version', 'Read more: https://wpcerber.com/?plugin_version=' . $new['ver'] );
|
3435 |
-
$history[] = $new['ver'];
|
3436 |
-
update_site_option( '_cerber_notify_new', $history );
|
3437 |
-
}
|
3438 |
-
}
|
3439 |
-
|
3440 |
-
// TODO: implement holding previous values for a while
|
3441 |
-
// cerber_antibot_gene();
|
3442 |
-
}
|
3443 |
-
|
3444 |
-
/*
|
3445 |
-
Return system ID of the WP Cerber plugin
|
3446 |
-
*/
|
3447 |
-
function cerber_plug_in() {
|
3448 |
-
return plugin_basename( __FILE__ );
|
3449 |
-
}
|
3450 |
-
|
3451 |
-
/*
|
3452 |
-
Return plugin info
|
3453 |
-
*/
|
3454 |
-
function cerber_plugin_data() {
|
3455 |
-
return get_plugin_data( __FILE__ );
|
3456 |
-
}
|
3457 |
-
|
3458 |
-
/*
|
3459 |
-
Return main plugin file
|
3460 |
-
*/
|
3461 |
-
function cerber_plugin_file() {
|
3462 |
-
return __FILE__;
|
3463 |
-
}
|
3464 |
-
|
3465 |
-
/**
|
3466 |
-
* Log activity
|
3467 |
-
*
|
3468 |
-
* @param int $activity Activity ID
|
3469 |
-
* @param string $login Login used or any additional information
|
3470 |
-
* @param int $user_id User ID
|
3471 |
-
* @param null $ip IP Address
|
3472 |
-
*
|
3473 |
-
* @return false|int
|
3474 |
-
* @since 3.0
|
3475 |
-
*/
|
3476 |
-
function cerber_log( $activity, $login = '', $user_id = 0, $ip = null ) {
|
3477 |
-
global $wpdb, $user_ID, $cerber_logged;
|
3478 |
-
static $logged = array();
|
3479 |
-
$wp_cerber = get_wp_cerber();
|
3480 |
-
|
3481 |
-
if ( isset( $logged[ $activity ] ) ) {
|
3482 |
-
return false;
|
3483 |
-
}
|
3484 |
-
else {
|
3485 |
-
$logged[ $activity ] = true;
|
3486 |
-
}
|
3487 |
-
|
3488 |
-
$cerber_logged[$activity] = $activity;
|
3489 |
-
|
3490 |
-
//$wp_cerber->setProcessed();
|
3491 |
-
|
3492 |
-
if ( empty( $ip ) ) {
|
3493 |
-
$ip = $wp_cerber->getRemoteIp();
|
3494 |
-
}
|
3495 |
-
if ( cerber_is_ipv4( $ip ) ) {
|
3496 |
-
$ip_long = ip2long( $ip );
|
3497 |
-
}
|
3498 |
-
else {
|
3499 |
-
$ip_long = 1;
|
3500 |
-
}
|
3501 |
-
|
3502 |
-
if ( empty( $user_id ) ) {
|
3503 |
-
if ($user_ID) {
|
3504 |
-
$user_id = absint($user_ID);
|
3505 |
-
}
|
3506 |
-
else $user_ID = 0;
|
3507 |
-
}
|
3508 |
-
|
3509 |
-
//$stamp = microtime( true );
|
3510 |
-
$stamp = cerber_request_time();
|
3511 |
-
|
3512 |
-
$pos = strpos($_SERVER['REQUEST_URI'],'?');
|
3513 |
-
if ($pos) {
|
3514 |
-
$path = substr( $_SERVER['REQUEST_URI'], 0, $pos );
|
3515 |
-
}
|
3516 |
-
else {
|
3517 |
-
$path = $_SERVER['REQUEST_URI'];
|
3518 |
-
}
|
3519 |
-
$url = strip_tags($_SERVER['HTTP_HOST'] . $path);
|
3520 |
-
|
3521 |
-
$why = 0;
|
3522 |
-
if ($activity != 10 && $activity != 11) {
|
3523 |
-
$why = cerber_get_status($ip);
|
3524 |
-
}
|
3525 |
-
|
3526 |
-
$details = $why .'|0|0|0|'. $url;
|
3527 |
-
|
3528 |
-
$country = lab_get_country( $ip );
|
3529 |
-
|
3530 |
-
$ret = $wpdb->query( $wpdb->prepare( 'INSERT INTO ' . CERBER_LOG_TABLE . ' (ip, ip_long, user_login, user_id, stamp, activity, session_id, country, details) VALUES (%s,%d,%s,%d,%f,%d,%s,%s,%s)', $ip, $ip_long, $login, $user_id, $stamp, $activity, $wp_cerber->getSessionID(), $country, $details ) );
|
3531 |
-
if ( ! $ret ) {
|
3532 |
-
// workaround for a WP bugs like this: WP silently doesn't not insert a row into a table
|
3533 |
-
// https://core.trac.wordpress.org/ticket/32315
|
3534 |
-
$ret = $wpdb->insert( CERBER_LOG_TABLE, array(
|
3535 |
-
'ip' => $ip,
|
3536 |
-
'ip_long' => $ip_long,
|
3537 |
-
'user_login' => $login,
|
3538 |
-
'user_id' => $user_id,
|
3539 |
-
'stamp' => $stamp,
|
3540 |
-
'activity' => $activity,
|
3541 |
-
'session_id' => $wp_cerber->getSessionID(),
|
3542 |
-
'country' => $country,
|
3543 |
-
'details' => $details,
|
3544 |
-
), array( '%s', '%d', '%s', '%d', '%f', '%d' ) );
|
3545 |
-
}
|
3546 |
-
|
3547 |
-
if ( ! $ret ) {
|
3548 |
-
cerber_watchdog();
|
3549 |
-
}
|
3550 |
-
|
3551 |
-
// Subscriptions - notifications for admin ---------------------------------------------------
|
3552 |
-
|
3553 |
-
$subs = cerber_get_site_option( '_cerber_subs' );
|
3554 |
-
|
3555 |
-
if (!empty($subs)) {
|
3556 |
-
foreach ( $subs as $hash => $sub ) {
|
3557 |
-
|
3558 |
-
// Loop through subscription parameters
|
3559 |
-
if ( ! empty( $sub[0] )) {
|
3560 |
-
if ( ! in_array( $activity, $sub[0] ) ) {
|
3561 |
-
continue;
|
3562 |
-
}
|
3563 |
-
}
|
3564 |
-
if ( ! empty( $sub[1] ) && $sub[1] != $user_id ) {
|
3565 |
-
continue;
|
3566 |
-
}
|
3567 |
-
if ( ! empty( $sub[3] ) && ( $ip_long < $sub[2] || $sub[3] < $ip_long ) ) {
|
3568 |
-
continue;
|
3569 |
-
}
|
3570 |
-
if ( ! empty( $sub[4] ) && $sub[4] != $ip ) {
|
3571 |
-
continue;
|
3572 |
-
}
|
3573 |
-
if ( ! empty( $sub[5] ) && $sub[5] != $login ) {
|
3574 |
-
continue;
|
3575 |
-
}
|
3576 |
-
if ( ! empty( $sub[6] ) && (false === strpos( $ip, $sub[6] )) && (false === mb_strpos( $login, $sub[6] )) ) {
|
3577 |
-
continue;
|
3578 |
-
}
|
3579 |
-
|
3580 |
-
// Some parameter(s) matched, prepare and send notification
|
3581 |
-
|
3582 |
-
$labels = cerber_get_labels( 'activity' );
|
3583 |
-
|
3584 |
-
$msg = __( 'Activity', 'wp-cerber' ) . ': ' . $labels[$activity] . "\n\n";
|
3585 |
-
|
3586 |
-
if ( $country ) {
|
3587 |
-
$coname = ' ('.cerber_country_name( $country ).')';
|
3588 |
-
}
|
3589 |
-
else {
|
3590 |
-
$coname = '';
|
3591 |
-
}
|
3592 |
-
|
3593 |
-
$msg .= __( 'IP', 'wp-cerber' ) . ': ' . $ip . $coname. "\n\n";
|
3594 |
-
|
3595 |
-
if ( $user_id && function_exists('get_userdata')) {
|
3596 |
-
$u = get_userdata( $user_id );
|
3597 |
-
$msg .= __( 'User', 'wp-cerber' ) . ': ' . $u->display_name . "\n\n";
|
3598 |
-
}
|
3599 |
-
|
3600 |
-
if ( $login ) {
|
3601 |
-
$msg .= __( 'Username used', 'wp-cerber' ) . ': ' . $login . "\n\n";
|
3602 |
-
}
|
3603 |
-
|
3604 |
-
if ( ! empty( $sub['6'] ) ) {
|
3605 |
-
$msg .= __( 'Search string', 'wp-cerber' ) . ': ' . $sub['6'] . "\n\n";
|
3606 |
-
}
|
3607 |
-
|
3608 |
-
// Link to the Activity admin page
|
3609 |
-
$args = cerber_subscribe_params();
|
3610 |
-
$i = 0;
|
3611 |
-
$link_params = '';
|
3612 |
-
foreach ($args as $arg => $val){
|
3613 |
-
if (is_array($sub[$i])){
|
3614 |
-
foreach ( $sub[ $i ] as $item ) {
|
3615 |
-
$link_params .= '&' . $arg . '[]=' . $item;
|
3616 |
-
}
|
3617 |
-
}
|
3618 |
-
else {
|
3619 |
-
$link_params .= '&' . $arg . '=' . $sub[ $i ];
|
3620 |
-
}
|
3621 |
-
$i++;
|
3622 |
-
}
|
3623 |
-
$link = cerber_admin_link( 'activity' ) . $link_params;
|
3624 |
-
|
3625 |
-
$msg .= __( 'View activity in dashboard', 'wp-cerber' ) . ': ' . $link;
|
3626 |
-
$msg .= "\n\n" . __( 'To unsubscribe click here', 'wp-cerber' ) . ': ' . cerber_admin_link( 'activity' ) . '&unsubscribeme=' . $hash;
|
3627 |
-
|
3628 |
-
cerber_send_notify( 'subs', $msg, $ip );
|
3629 |
-
|
3630 |
-
break; // Just one notification letter per event
|
3631 |
-
}
|
3632 |
-
}
|
3633 |
-
|
3634 |
-
if ( in_array( $activity, array( 16, 17, 40 ) ) ) {
|
3635 |
-
lab_save_push( $ip, $activity, '' );
|
3636 |
-
}
|
3637 |
-
|
3638 |
-
return $ret;
|
3639 |
-
}
|
3640 |
-
|
3641 |
-
/**
|
3642 |
-
* Get records from the log
|
3643 |
-
*
|
3644 |
-
* @param array $activity
|
3645 |
-
* @param array $user
|
3646 |
-
* @param array $order
|
3647 |
-
* @param string $limit
|
3648 |
-
*
|
3649 |
-
* @return array|null
|
3650 |
-
*/
|
3651 |
-
function cerber_get_log($activity = array(), $user = array(), $order = array(), $limit = ''){
|
3652 |
-
global $wpdb;
|
3653 |
-
|
3654 |
-
$where = array();
|
3655 |
-
if ($activity){
|
3656 |
-
$activity = array_map( 'absint', $activity );
|
3657 |
-
$where[] = 'activity IN ('.implode(', ',$activity).')';
|
3658 |
-
}
|
3659 |
-
|
3660 |
-
if ($user['email']){
|
3661 |
-
$user = get_user_by( 'email', $user['email'] );
|
3662 |
-
$where[] = 'user_id = ' . absint( $user->ID );
|
3663 |
-
}
|
3664 |
-
elseif ($user['id']){
|
3665 |
-
$where[] = 'user_id = '.absint($user['id']);
|
3666 |
-
}
|
3667 |
-
|
3668 |
-
$where_sql = '';
|
3669 |
-
if ( $where ) {
|
3670 |
-
$where_sql = ' WHERE ' . implode( ' AND ', $where );
|
3671 |
-
}
|
3672 |
-
|
3673 |
-
$order_sql = '';
|
3674 |
-
if ( $order ) {
|
3675 |
-
if ( ! empty( $order['DESC'] ) ) {
|
3676 |
-
$order_sql = ' ORDER BY ' . preg_replace( '/[^\w]/', '', $order['DESC'] ) . ' DESC ';
|
3677 |
-
}
|
3678 |
-
elseif ( ! empty( $order['ASC'] ) ) {
|
3679 |
-
$order_sql = ' ORDER BY ' . preg_replace( '/[^\w]/', '', $order['ASC'] ) . ' ASC ';
|
3680 |
-
}
|
3681 |
-
}
|
3682 |
-
|
3683 |
-
$limit_sql = '';
|
3684 |
-
if ( $limit ) {
|
3685 |
-
$limit_sql = ' LIMIT ' . preg_replace( '/[^0-9\.]/', '', $limit );
|
3686 |
-
}
|
3687 |
-
|
3688 |
-
// $row = $wpdb->get_row('SELECT * FROM '.CERBER_LOG_TABLE.' WHERE activity = 5 AND user_id = '.absint($user_id) . ' ORDER BY stamp DESC LIMIT 1');
|
3689 |
-
return $wpdb->get_results( 'SELECT * FROM ' . CERBER_LOG_TABLE . ' ' . $where_sql . $order_sql . $limit_sql );
|
3690 |
-
|
3691 |
-
}
|
3692 |
-
|
3693 |
-
/**
|
3694 |
-
* Return the last login record for a given user
|
3695 |
-
*
|
3696 |
-
* @param $user_id int|null
|
3697 |
-
* @param $user_email string
|
3698 |
-
*
|
3699 |
-
* @return array|null|object|string
|
3700 |
-
*/
|
3701 |
-
function cerber_get_last_login( $user_id, $user_email = '' ) {
|
3702 |
-
if ( $user_id ) {
|
3703 |
-
$u = array( 'id' => $user_id );
|
3704 |
-
}
|
3705 |
-
elseif ( $user_email ) {
|
3706 |
-
$u = array( 'email' => $user_email );
|
3707 |
-
}
|
3708 |
-
|
3709 |
-
if ($u) {
|
3710 |
-
$recs = cerber_get_log( array( 5 ), $u, array( 'DESC' => 'stamp' ), 1 );
|
3711 |
-
return $recs[0];
|
3712 |
-
}
|
3713 |
-
|
3714 |
-
return '';
|
3715 |
-
}
|
3716 |
-
|
3717 |
-
function cerber_count_log($activity = array(), $period = 1) {
|
3718 |
-
global $wpdb;
|
3719 |
-
|
3720 |
-
$period = absint( $period );
|
3721 |
-
if ( ! $period ) {
|
3722 |
-
$period = 1;
|
3723 |
-
}
|
3724 |
-
|
3725 |
-
$stamp = time() - $period * 24 * 3600;
|
3726 |
-
|
3727 |
-
// TODO: replace with SELECT COUNT(DISTINCT session_id)
|
3728 |
-
$ret = $wpdb->get_var('SELECT COUNT(ip) FROM '. CERBER_LOG_TABLE .' WHERE activity IN ('.implode(',',$activity).') AND stamp > '. $stamp);
|
3729 |
-
if (!$ret) $ret = 0;
|
3730 |
-
|
3731 |
-
return $ret;
|
3732 |
-
}
|
3733 |
-
|
3734 |
-
/**
|
3735 |
-
* Create a set of parameters for using it in Subscriptions
|
3736 |
-
* The keys are used to built an URL. Values to calculate a hash.
|
3737 |
-
*
|
3738 |
-
* @return array The set of parameters
|
3739 |
-
*/
|
3740 |
-
function cerber_subscribe_params() {
|
3741 |
-
$begin = 0;
|
3742 |
-
$end = 0;
|
3743 |
-
$ip = 0;
|
3744 |
-
if ( ! empty( $_GET['filter_ip'] ) ) {
|
3745 |
-
$ip = cerber_any2range( $_GET['filter_ip'] );
|
3746 |
-
if ( is_array( $ip ) ) {
|
3747 |
-
$begin = $ip['begin'];
|
3748 |
-
$end = $ip['end'];
|
3749 |
-
$ip = 0;
|
3750 |
-
} elseif ( ! $ip ) {
|
3751 |
-
$ip = 0;
|
3752 |
-
}
|
3753 |
-
}
|
3754 |
-
|
3755 |
-
$filter_activity = ( empty( $_GET['filter_activity'] ) ) ? 0 : $_GET['filter_activity'];
|
3756 |
-
$filter_user = ( empty( $_GET['filter_user'] ) ) ? 0 : $_GET['filter_user'];
|
3757 |
-
$filter_login = ( empty( $_GET['filter_login'] ) ) ? 0 : $_GET['filter_login'];
|
3758 |
-
$search_activity = ( empty( $_GET['search_activity'] ) ) ? 0 : $_GET['search_activity'];
|
3759 |
-
$filter_role = ( empty( $_GET['filter_role'] ) ) ? 0 : $_GET['filter_role'];
|
3760 |
-
|
3761 |
-
if ( ! is_array( $filter_activity ) ) {
|
3762 |
-
$filter_activity = array( $filter_activity );
|
3763 |
-
}
|
3764 |
-
$filter_activity = array_filter( $filter_activity );
|
3765 |
-
|
3766 |
-
// 'begin' and 'end' array keys are not used, added for compatibility
|
3767 |
-
return array( 'filter_activity' => $filter_activity, 'filter_user' => $filter_user, 'being' => $begin, 'end' => $end, 'filter_ip' => $ip, 'filter_login' => $filter_login, 'search_activity' => $search_activity, 'filter_role' => $filter_role );
|
3768 |
-
}
|
3769 |
-
|
3770 |
-
/*
|
3771 |
-
Plugin activation
|
3772 |
-
*/
|
3773 |
-
register_activation_hook( __FILE__, 'cerber_activate' );
|
3774 |
-
function cerber_activate() {
|
3775 |
-
global $wp_version, $wp_cerber;
|
3776 |
-
$assets_url = plugin_dir_url( CERBER_FILE ) . 'assets';
|
3777 |
-
|
3778 |
-
//cerber_load_lang();
|
3779 |
-
load_plugin_textdomain( 'wp-cerber', false, basename( dirname( __FILE__ ) ) . '/languages' );
|
3780 |
-
|
3781 |
-
if ( version_compare( CERBER_REQ_PHP, phpversion(), '>' ) ) {
|
3782 |
-
cerber_stop_activating( '<h3>' . sprintf( __( 'The WP Cerber requires PHP %s or higher. You are running', 'wp-cerber' ), CERBER_REQ_PHP ) . ' ' . phpversion() . '</h3>' );
|
3783 |
-
}
|
3784 |
-
|
3785 |
-
if ( version_compare( CERBER_REQ_WP, $wp_version, '>' ) ) {
|
3786 |
-
cerber_stop_activating( '<h3>' . sprintf( __( 'The WP Cerber requires WordPress %s or higher. You are running', 'wp-cerber' ), CERBER_REQ_WP ) . ' ' . $wp_version . '</h3>' );
|
3787 |
-
}
|
3788 |
-
|
3789 |
-
$db_errors = cerber_create_db();
|
3790 |
-
if ( $db_errors ) {
|
3791 |
-
$e = '';
|
3792 |
-
foreach ( $db_errors as $db_error ) {
|
3793 |
-
$e .= '<p>' . implode( '</p><p>', $db_error ) . '</p>';
|
3794 |
-
}
|
3795 |
-
cerber_stop_activating( '<h3>' . __( "Can't activate WP Cerber due to a database error.", 'wp-cerber' ) . '</h3>'.$e);
|
3796 |
-
}
|
3797 |
-
|
3798 |
-
cerber_upgrade_all();
|
3799 |
-
|
3800 |
-
cerber_cookie1();
|
3801 |
-
cerber_disable_citadel();
|
3802 |
-
//cerber_get_groove();
|
3803 |
-
|
3804 |
-
if ( ! is_object( $wp_cerber ) ) {
|
3805 |
-
$wp_cerber = new WP_Cerber();
|
3806 |
-
}
|
3807 |
-
cerber_add_white( cerber_get_subnet( $wp_cerber->getRemoteIp() ) ); // Protection for non-experienced user
|
3808 |
-
|
3809 |
-
cerber_admin_message(
|
3810 |
-
'<img style="float:left; margin-left:-10px;" src="' . $assets_url . '/icon-128x128.png">' .
|
3811 |
-
'<p style="font-size:120%;">' . __( 'WP Cerber is now active and has started protecting your site', 'wp-cerber' ) . '</p>' .
|
3812 |
-
' <p>' . __( 'Your IP address is added to the', 'wp-cerber' ) . ' ' . __( 'White IP Access List', 'wp-cerber' ) .
|
3813 |
-
|
3814 |
-
' <p style="font-size:120%;"><a href="http://wpcerber.com/getting-started/" target="_blank">' . __( 'Getting Started Guide', 'wp-cerber' ) . '</a></p>' .
|
3815 |
-
|
3816 |
-
//' <p><b>' . __( "It's important to check security settings.", 'wp-cerber' ) . '</b> <a href="http://wpcerber.com/" target="_blank">Read Cerber\'s blog</a> ' .
|
3817 |
-
//' <a href="http://wpcerber.com/subscribe-newsletter/" target="_blank">Subscribe to Cerber\'s newsletter</a></p>' .
|
3818 |
-
|
3819 |
-
' <p> </p><p><span class="dashicons dashicons-admin-settings"></span> <a href="' . cerber_admin_link( 'main' ) . '">' . __( 'Main Settings', 'wp-cerber' ) . '</a>' .
|
3820 |
-
' <span style="margin-left:20px;" class="dashicons dashicons-admin-network"></span> <a href="' . cerber_admin_link( 'acl' ) . '">' . __( 'Access Lists', 'wp-cerber' ) . '</a>' .
|
3821 |
-
' <span style="margin-left:20px;" class="dashicons dashicons-forms"></span> <a href="' . cerber_admin_link( 'antispam' ) . '">' . __( 'Antispam', 'wp-cerber' ) . '</a>' .
|
3822 |
-
' <span style="margin-left:20px;" class="dashicons dashicons-shield-alt"></span> <a href="' . cerber_admin_link( 'hardening' ) . '">' . __( 'Hardening', 'wp-cerber' ) . '</a>' .
|
3823 |
-
' <span style="margin-left:20px;" class="dashicons dashicons-controls-volumeon"></span> <a href="' . cerber_admin_link( 'notifications' ) . '">' . __( 'Notifications', 'wp-cerber' ) . '</a>' .
|
3824 |
-
' <span style="margin-left:20px;" class="dashicons dashicons-admin-tools"></span> <a href="' . cerber_admin_link( 'imex' ) . '">' . __( 'Import settings', 'wp-cerber' ) . '</a>' .
|
3825 |
-
'</p>' );
|
3826 |
-
|
3827 |
-
|
3828 |
-
// Check for existing options
|
3829 |
-
$opt = cerber_get_options();
|
3830 |
-
$opt = array_filter( $opt );
|
3831 |
-
if ( ! empty( $opt ) ) {
|
3832 |
-
return;
|
3833 |
-
}
|
3834 |
-
|
3835 |
-
cerber_load_defaults();
|
3836 |
-
|
3837 |
-
cerber_send_notify( 'activated' );
|
3838 |
-
|
3839 |
-
$pi = get_file_data( cerber_plugin_file(), array( 'Version' => 'Version' ), 'plugin' );
|
3840 |
-
$pi ['time'] = time();
|
3841 |
-
$pi ['user'] = get_current_user_id();
|
3842 |
-
update_site_option( '_cerber_activated', $pi );
|
3843 |
-
}
|
3844 |
-
|
3845 |
-
/*
|
3846 |
-
Abort activating plugin!
|
3847 |
-
*/
|
3848 |
-
function cerber_stop_activating( $msg ) {
|
3849 |
-
deactivate_plugins( plugin_basename( __FILE__ ) );
|
3850 |
-
wp_die( $msg );
|
3851 |
-
}
|
3852 |
-
|
3853 |
-
/**
|
3854 |
-
* Upgrade database tables, data and plugin settings
|
3855 |
-
*
|
3856 |
-
* @since 3.0
|
3857 |
-
*
|
3858 |
-
*/
|
3859 |
-
function cerber_upgrade_all() {
|
3860 |
-
$ver = cerber_get_site_option( '_cerber_up' );
|
3861 |
-
if ( ! $ver || $ver['v'] != CERBER_VER ) {
|
3862 |
-
cerber_create_db();
|
3863 |
-
cerber_upgrade_db();
|
3864 |
-
cerber_acl_fixer( true );
|
3865 |
-
cerber_push_the_news( CERBER_VER );
|
3866 |
-
cerber_antibot_gene(true);
|
3867 |
-
cerber_upgrade_options();
|
3868 |
-
wp_clear_scheduled_hook( 'cerber_hourly' ); // @since 5.8
|
3869 |
-
update_site_option( '_cerber_up', array( 'v' => CERBER_VER, 't' => time() ) );
|
3870 |
-
}
|
3871 |
-
}
|
3872 |
-
|
3873 |
-
/**
|
3874 |
-
* Creates DB tables if they don't exist
|
3875 |
-
*
|
3876 |
-
* @param bool $recreate If true, recreate some tables completely (with data lost)
|
3877 |
-
*
|
3878 |
-
* @return array Errors
|
3879 |
-
*/
|
3880 |
-
function cerber_create_db($recreate = true) {
|
3881 |
-
global $wpdb;
|
3882 |
-
|
3883 |
-
$wpdb->hide_errors();
|
3884 |
-
$db_errors = array();
|
3885 |
-
$sql = array();
|
3886 |
-
|
3887 |
-
if (!cerber_is_table(CERBER_LOG_TABLE)){
|
3888 |
-
$sql[] = "
|
3889 |
-
CREATE TABLE IF NOT EXISTS " . CERBER_LOG_TABLE . " (
|
3890 |
-
ip varchar(39) CHARACTER SET ascii NOT NULL COMMENT 'Remote IP',
|
3891 |
-
user_login varchar(60) NOT NULL COMMENT 'Username from HTTP request',
|
3892 |
-
user_id bigint(20) unsigned NOT NULL DEFAULT '0',
|
3893 |
-
stamp bigint(20) unsigned NOT NULL COMMENT 'Unix timestamp',
|
3894 |
-
activity int(10) unsigned NOT NULL DEFAULT '0',
|
3895 |
-
KEY ip (ip)
|
3896 |
-
) DEFAULT CHARSET=utf8 COMMENT='Cerber activity log';
|
3897 |
-
";
|
3898 |
-
}
|
3899 |
-
|
3900 |
-
if (!cerber_is_table(CERBER_ACL_TABLE)){
|
3901 |
-
$sql[] = "
|
3902 |
-
CREATE TABLE IF NOT EXISTS " . CERBER_ACL_TABLE . " (
|
3903 |
-
ip varchar(39) CHARACTER SET ascii NOT NULL COMMENT 'IP',
|
3904 |
-
tag char(1) NOT NULL COMMENT 'Type: B or W',
|
3905 |
-
comments varchar(250) NOT NULL,
|
3906 |
-
UNIQUE KEY ip (ip)
|
3907 |
-
) DEFAULT CHARSET=utf8 COMMENT='Cerber IP Access Lists';
|
3908 |
-
";
|
3909 |
-
}
|
3910 |
-
|
3911 |
-
if (!cerber_is_table(CERBER_BLOCKS_TABLE)){
|
3912 |
-
$sql[] = "
|
3913 |
-
CREATE TABLE IF NOT EXISTS " . CERBER_BLOCKS_TABLE . " (
|
3914 |
-
ip varchar(39) CHARACTER SET ascii NOT NULL COMMENT 'Remote IP',
|
3915 |
-
block_until bigint(20) unsigned NOT NULL COMMENT 'Unix timestamp',
|
3916 |
-
reason varchar(250) NOT NULL COMMENT 'Why IP was blocked',
|
3917 |
-
UNIQUE KEY ip (ip)
|
3918 |
-
) DEFAULT CHARSET=utf8 COMMENT='Cerber list of currently blocked IPs';
|
3919 |
-
";
|
3920 |
-
}
|
3921 |
-
|
3922 |
-
if (!cerber_is_table(CERBER_LAB_TABLE)){
|
3923 |
-
$sql[] = "
|
3924 |
-
CREATE TABLE IF NOT EXISTS " . CERBER_LAB_TABLE . " (
|
3925 |
-
ip varchar(39) CHARACTER SET ascii NOT NULL COMMENT 'Remote IP',
|
3926 |
-
reason_id int(11) unsigned NOT NULL DEFAULT '0',
|
3927 |
-
stamp bigint(20) unsigned NOT NULL COMMENT 'Unix timestamp',
|
3928 |
-
details text NOT NULL
|
3929 |
-
) DEFAULT CHARSET=utf8 COMMENT='Cerber lab cache';
|
3930 |
-
";
|
3931 |
-
}
|
3932 |
-
|
3933 |
-
|
3934 |
-
if ($recreate || !cerber_is_table(CERBER_LAB_IP_TABLE)){
|
3935 |
-
if ( $recreate && cerber_is_table( CERBER_LAB_IP_TABLE ) ) {
|
3936 |
-
$sql[] = 'DROP TABLE IF EXISTS ' . CERBER_LAB_IP_TABLE;
|
3937 |
-
}
|
3938 |
-
$sql[] = "
|
3939 |
-
CREATE TABLE IF NOT EXISTS " . CERBER_LAB_IP_TABLE . " (
|
3940 |
-
ip varchar(39) CHARACTER SET ascii NOT NULL COMMENT 'IP',
|
3941 |
-
reputation INT(11) UNSIGNED NOT NULL COMMENT 'Reputation of IP',
|
3942 |
-
expires INT(11) UNSIGNED NOT NULL COMMENT 'Unix timestamp',
|
3943 |
-
PRIMARY KEY (ip)
|
3944 |
-
) DEFAULT CHARSET=utf8 COMMENT='Cerber lab IP cache';
|
3945 |
-
";
|
3946 |
-
}
|
3947 |
-
|
3948 |
-
if ( $recreate || ! cerber_is_table( CERBER_LAB_NET_TABLE ) ) {
|
3949 |
-
if ( $recreate && cerber_is_table( CERBER_LAB_NET_TABLE ) ) {
|
3950 |
-
$sql[] = 'DROP TABLE IF EXISTS ' . CERBER_LAB_NET_TABLE;
|
3951 |
-
}
|
3952 |
-
$sql[] = '
|
3953 |
-
CREATE TABLE IF NOT EXISTS ' . CERBER_LAB_NET_TABLE . ' (
|
3954 |
-
ip varchar(39) CHARACTER SET ascii NOT NULL DEFAULT "" COMMENT "IP address",
|
3955 |
-
ip_long_begin BIGINT UNSIGNED NOT NULL DEFAULT "0",
|
3956 |
-
ip_long_end BIGINT UNSIGNED NOT NULL DEFAULT "0",
|
3957 |
-
country CHAR(3) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "" COMMENT "Country code",
|
3958 |
-
expires INT(11) UNSIGNED NOT NULL DEFAULT "0",
|
3959 |
-
PRIMARY KEY (ip),
|
3960 |
-
UNIQUE KEY begin_end (ip_long_begin, ip_long_end)
|
3961 |
-
) DEFAULT CHARSET=utf8 COMMENT="Cerber lab network cache";
|
3962 |
-
';
|
3963 |
-
}
|
3964 |
-
|
3965 |
-
if (!cerber_is_table(CERBER_GEO_TABLE)){
|
3966 |
-
$sql[] = '
|
3967 |
-
CREATE TABLE IF NOT EXISTS ' . CERBER_GEO_TABLE . ' (
|
3968 |
-
country CHAR(3) NOT NULL DEFAULT "" COMMENT "Country code",
|
3969 |
-
locale CHAR(10) NOT NULL DEFAULT "" COMMENT "Locale i18n",
|
3970 |
-
country_name VARCHAR(250) NOT NULL DEFAULT "" COMMENT "Country name",
|
3971 |
-
PRIMARY KEY (country, locale)
|
3972 |
-
) DEFAULT CHARSET=utf8;
|
3973 |
-
';
|
3974 |
-
}
|
3975 |
-
|
3976 |
-
if (!cerber_is_table(CERBER_TRAF_TABLE)){
|
3977 |
-
$sql[] = '
|
3978 |
-
CREATE TABLE IF NOT EXISTS ' . CERBER_TRAF_TABLE . ' (
|
3979 |
-
ip varchar(39) CHARACTER SET ascii NOT NULL,
|
3980 |
-
ip_long BIGINT UNSIGNED NOT NULL DEFAULT "0",
|
3981 |
-
hostname varchar(250) NOT NULL DEFAULT "",
|
3982 |
-
uri text NOT NULL,
|
3983 |
-
request_fields MEDIUMTEXT NOT NULL,
|
3984 |
-
request_details MEDIUMTEXT NOT NULL,
|
3985 |
-
session_id char(32) CHARACTER SET ascii NOT NULL,
|
3986 |
-
user_id bigint(20) UNSIGNED NOT NULL DEFAULT 0,
|
3987 |
-
stamp decimal(14,4) NOT NULL,
|
3988 |
-
processing int(10) NOT NULL DEFAULT 0,
|
3989 |
-
country char(3) CHARACTER SET ascii NOT NULL DEFAULT "",
|
3990 |
-
request_method char(8) CHARACTER SET ascii NOT NULL,
|
3991 |
-
http_code int(10) UNSIGNED NOT NULL,
|
3992 |
-
wp_id bigint(20) UNSIGNED NOT NULL DEFAULT 0,
|
3993 |
-
wp_type int(10) UNSIGNED NOT NULL DEFAULT 0,
|
3994 |
-
is_bot int(10) UNSIGNED NOT NULL DEFAULT 0,
|
3995 |
-
blog_id int(10) UNSIGNED NOT NULL DEFAULT 0,
|
3996 |
-
KEY stamp (stamp)
|
3997 |
-
) DEFAULT CHARSET=utf8;
|
3998 |
-
';
|
3999 |
-
}
|
4000 |
-
|
4001 |
-
foreach ( $sql as $query ) {
|
4002 |
-
if ( ! $wpdb->query( $query ) && $wpdb->last_error ) {
|
4003 |
-
$db_errors[] = array( $wpdb->last_error, $wpdb->last_query );
|
4004 |
-
}
|
4005 |
-
}
|
4006 |
-
|
4007 |
-
return $db_errors;
|
4008 |
-
}
|
4009 |
-
|
4010 |
-
/**
|
4011 |
-
* Upgrade structure of existing DB tables
|
4012 |
-
*
|
4013 |
-
* @return array Errors during upgrading
|
4014 |
-
* @since 3.0
|
4015 |
-
*/
|
4016 |
-
function cerber_upgrade_db( $force = false ) {
|
4017 |
-
global $wpdb;
|
4018 |
-
$wpdb->hide_errors();
|
4019 |
-
if ($force) $wpdb->suppress_errors();
|
4020 |
-
$db_errors = array();
|
4021 |
-
$sql = array();
|
4022 |
-
|
4023 |
-
// @since 3.0
|
4024 |
-
$sql[] = 'ALTER TABLE ' . CERBER_LOG_TABLE . ' CHANGE stamp stamp DECIMAL(14,4) NOT NULL';
|
4025 |
-
|
4026 |
-
// @since 3.1
|
4027 |
-
if ( $force || ! cerber_is_column( CERBER_LOG_TABLE, 'ip_long' ) ) {
|
4028 |
-
$sql[] = 'ALTER TABLE ' . CERBER_LOG_TABLE . ' ADD ip_long BIGINT UNSIGNED NOT NULL DEFAULT "0" COMMENT "IPv4 long" AFTER ip, ADD INDEX (ip_long)';
|
4029 |
-
}
|
4030 |
-
if ( $force || ! cerber_is_column( CERBER_ACL_TABLE, 'ip_long_begin' ) ) {
|
4031 |
-
$sql[] = 'ALTER TABLE ' . CERBER_ACL_TABLE . " ADD ip_long_begin BIGINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'IPv4 range begin' AFTER ip, ADD ip_long_end BIGINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'IPv4 range end' AFTER ip_long_begin";
|
4032 |
-
}
|
4033 |
-
if ( $force || !cerber_is_index( CERBER_ACL_TABLE, 'ip_begin_end' ) ) {
|
4034 |
-
$sql[] = 'ALTER TABLE ' . CERBER_ACL_TABLE . ' ADD UNIQUE ip_begin_end (ip, ip_long_begin, ip_long_end)';
|
4035 |
-
}
|
4036 |
-
if ( $force || cerber_is_index( CERBER_ACL_TABLE, 'ip' ) ) {
|
4037 |
-
$sql[] = 'ALTER TABLE ' . CERBER_ACL_TABLE . ' DROP INDEX ip';
|
4038 |
-
}
|
4039 |
-
|
4040 |
-
// @since 4.8.2
|
4041 |
-
if ( $force || cerber_is_index( CERBER_ACL_TABLE, 'begin_end' ) ) {
|
4042 |
-
$sql[] = 'ALTER TABLE ' . CERBER_ACL_TABLE . ' DROP INDEX begin_end';
|
4043 |
-
}
|
4044 |
-
if ( $force || !cerber_is_index( CERBER_ACL_TABLE, 'begin_end_tag' ) ) {
|
4045 |
-
$sql[] = 'ALTER TABLE ' . CERBER_ACL_TABLE . ' ADD INDEX begin_end_tag (ip_long_begin, ip_long_end, tag)';
|
4046 |
-
}
|
4047 |
-
|
4048 |
-
// @since 4.9
|
4049 |
-
if ( $force || ! cerber_is_column( CERBER_LOG_TABLE, 'session_id' ) ) {
|
4050 |
-
$sql[] = 'ALTER TABLE ' . CERBER_LOG_TABLE . '
|
4051 |
-
ADD session_id CHAR(32) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "",
|
4052 |
-
ADD country CHAR(3) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "" COMMENT "Country code",
|
4053 |
-
ADD details VARCHAR(250) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "" COMMENT "Details about HTTP request";
|
4054 |
-
';
|
4055 |
-
}
|
4056 |
-
|
4057 |
-
// @since 6.1
|
4058 |
-
if ( $force || !cerber_is_index( CERBER_LOG_TABLE, 'session_index' ) ) {
|
4059 |
-
$sql[] = 'ALTER TABLE ' . CERBER_LOG_TABLE . ' ADD INDEX session_index (session_id)';
|
4060 |
-
}
|
4061 |
-
|
4062 |
-
if (!empty($sql)) {
|
4063 |
-
foreach ( $sql as $query ) {
|
4064 |
-
if ( !$wpdb->query( $query ) && $wpdb->last_error ) {
|
4065 |
-
$db_errors[] = array( $wpdb->last_error, $wpdb->last_query );
|
4066 |
-
}
|
4067 |
-
}
|
4068 |
-
}
|
4069 |
-
|
4070 |
-
// Convert existing data into the new format
|
4071 |
-
|
4072 |
-
cerber_acl_fixer();
|
4073 |
-
|
4074 |
-
if ( $db_errors ) {
|
4075 |
-
update_site_option( '_cerber_db_errors', $db_errors );
|
4076 |
-
}
|
4077 |
-
else {
|
4078 |
-
update_site_option( '_cerber_db_errors', '' );
|
4079 |
-
}
|
4080 |
-
|
4081 |
-
return $db_errors;
|
4082 |
-
}
|
4083 |
-
|
4084 |
-
/**
|
4085 |
-
* Updating old activity log records to the new row format (has been introduced in v 3.1)
|
4086 |
-
*
|
4087 |
-
* @since 4.0
|
4088 |
-
*
|
4089 |
-
*/
|
4090 |
-
function cerber_up_data() {
|
4091 |
-
global $wpdb;
|
4092 |
-
$ips = $wpdb->get_col( 'SELECT DISTINCT ip FROM ' . CERBER_LOG_TABLE . ' WHERE ip_long = 0 LIMIT 50' );
|
4093 |
-
if ( ! $ips ) {
|
4094 |
-
return;
|
4095 |
-
}
|
4096 |
-
foreach ( $ips as $ip ) {
|
4097 |
-
if ( cerber_is_ipv4( $ip ) ) {
|
4098 |
-
$ip_long = ip2long( $ip );
|
4099 |
-
} else {
|
4100 |
-
$ip_long = 1;
|
4101 |
-
}
|
4102 |
-
$wpdb->query( 'UPDATE ' . CERBER_LOG_TABLE . ' SET ip_long = ' . $ip_long . ' WHERE ip = "' . $ip .'" AND ip_long = 0');
|
4103 |
-
}
|
4104 |
-
}
|
4105 |
-
|
4106 |
-
/**
|
4107 |
-
* Upgrade corrupted / from older versions of the plugin rows in ACL
|
4108 |
-
*
|
4109 |
-
* @param bool $ipv6 if true Process IPv6 addresses
|
4110 |
-
*
|
4111 |
-
*/
|
4112 |
-
function cerber_acl_fixer($ipv6 = false){
|
4113 |
-
global $wpdb;
|
4114 |
-
|
4115 |
-
// Repair/update IPs without long values
|
4116 |
-
$rows = $wpdb->get_col( 'SELECT ip FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin = 0 OR ip_long_end = 0' );
|
4117 |
-
if ( ! $rows ) {
|
4118 |
-
return;
|
4119 |
-
}
|
4120 |
-
foreach ( $rows as $ip ) {
|
4121 |
-
if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
|
4122 |
-
continue;
|
4123 |
-
}
|
4124 |
-
$range = cerber_any2range( $ip );
|
4125 |
-
if ( is_array( $range ) ) {
|
4126 |
-
$begin = $range['begin'];
|
4127 |
-
$end = $range['end'];
|
4128 |
-
}
|
4129 |
-
else {
|
4130 |
-
$begin = ip2long( $ip );
|
4131 |
-
$end = ip2long( $ip );
|
4132 |
-
}
|
4133 |
-
|
4134 |
-
$wpdb->query( 'UPDATE ' . CERBER_ACL_TABLE . ' SET ip_long_begin = ' . $begin . ', ip_long_end = ' . $end . ' WHERE ip = "' . $ip .'"');
|
4135 |
-
}
|
4136 |
-
|
4137 |
-
// Convert old IPv6 to all shortened
|
4138 |
-
if ( $ipv6 ) {
|
4139 |
-
$ips = $wpdb->get_col( 'SELECT ip FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin = 0' );
|
4140 |
-
if ( $ips ) {
|
4141 |
-
foreach ( $ips as $ip ) {
|
4142 |
-
if ( ! filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
|
4143 |
-
continue;
|
4144 |
-
}
|
4145 |
-
$short_ip = cerber_short_ipv6( $ip );
|
4146 |
-
if ($short_ip != $ip) {
|
4147 |
-
$wpdb->query( 'UPDATE ' . CERBER_ACL_TABLE . ' SET ip = "' . $short_ip . '" WHERE ip = "' . $ip . '"' );
|
4148 |
-
}
|
4149 |
-
}
|
4150 |
-
}
|
4151 |
-
}
|
4152 |
-
}
|
4153 |
-
|
4154 |
-
$file = plugin_basename( cerber_plugin_file() );
|
4155 |
-
add_action( 'deac' . 'tivate_' . $file, 'cerber_clean' );
|
4156 |
-
function cerber_clean( $ip ) {
|
4157 |
-
wp_clear_scheduled_hook( 'cerber' . '_hourly' );
|
4158 |
-
$pi = get_file_data( cerber_plugin_file(), array( 'Version' => 'Version' ), 'plugin' );
|
4159 |
-
$pi ['v'] = time();
|
4160 |
-
$pi ['u'] = get_current_user_id();
|
4161 |
-
update_site_option( '_cerber_o' . 'ff', $pi );
|
4162 |
-
$f = 'cerb' . 'er_se' . 'nd_not' . 'ify';
|
4163 |
-
$f( 'sh' . 'utd' . 'own' );
|
4164 |
-
}
|
4165 |
-
|
4166 |
-
/*
|
4167 |
-
Fix an issue with the empty user_id field in the comments table.
|
4168 |
-
*/
|
4169 |
-
add_filter( 'preprocess_comment', 'cerber_add_uid' );
|
4170 |
-
function cerber_add_uid( $commentdata ) {
|
4171 |
-
$current_user = wp_get_current_user();
|
4172 |
-
$commentdata['user_ID'] = $current_user->ID;
|
4173 |
-
|
4174 |
-
return $commentdata;
|
4175 |
-
}
|
4176 |
-
|
4177 |
-
/**
|
4178 |
-
* Load jQuery on the page
|
4179 |
-
*
|
4180 |
-
*/
|
4181 |
-
add_action( 'login_enqueue_scripts', 'cerber_login_scripts' );
|
4182 |
-
function cerber_login_scripts() {
|
4183 |
-
if ( cerber_antibot_enabled( array('botsreg', 'botsany') ) ) {
|
4184 |
-
wp_enqueue_script( 'jquery' );
|
4185 |
-
}
|
4186 |
-
}
|
4187 |
-
add_action( 'wp_enqueue_scripts', 'cerber_scripts' );
|
4188 |
-
function cerber_scripts() {
|
4189 |
-
global $wp_cerber;
|
4190 |
-
if ( ( is_singular() && cerber_antibot_enabled( array( 'botscomm', 'botsany' ) ) )
|
4191 |
-
|| ( $wp_cerber->getSettings( 'sitekey' ) && $wp_cerber->getSettings( 'secretkey' ) )
|
4192 |
-
) {
|
4193 |
-
wp_enqueue_script( 'jquery' );
|
4194 |
-
}
|
4195 |
-
}
|
4196 |
-
|
4197 |
-
/**
|
4198 |
-
* Footer stuff
|
4199 |
-
* Explicit rendering reCAPTCHA
|
4200 |
-
*
|
4201 |
-
*/
|
4202 |
-
add_action( 'login_footer', 'cerber_login_foo', 1000 );
|
4203 |
-
function cerber_login_foo( $ip ) {
|
4204 |
-
global $wp_cerber;
|
4205 |
-
|
4206 |
-
cerber_antibot_code(array( 'botsreg', 'botsany' ));
|
4207 |
-
|
4208 |
-
// Universal JS
|
4209 |
-
if (!$wp_cerber->recaptcha_here) return;
|
4210 |
-
|
4211 |
-
$sitekey = $wp_cerber->getSettings('sitekey');
|
4212 |
-
|
4213 |
-
if (!$wp_cerber->getSettings('invirecap')){
|
4214 |
-
// Classic version (visible reCAPTCHA)
|
4215 |
-
echo '<script src = https://www.google.com/recaptcha/api.js?hl='.cerber_recaptcha_lang().' async defer></script>';
|
4216 |
-
}
|
4217 |
-
else {
|
4218 |
-
// Pure JS version with explicit rendering
|
4219 |
-
?>
|
4220 |
-
<script src="https://www.google.com/recaptcha/api.js?onload=init_recaptcha_widgets&render=explicit&hl=<?php echo cerber_recaptcha_lang(); ?>" async defer></script>
|
4221 |
-
<script type='text/javascript'>
|
4222 |
-
|
4223 |
-
document.getElementById("cerber-recaptcha").remove();
|
4224 |
-
|
4225 |
-
var init_recaptcha_widgets = function () {
|
4226 |
-
for (var i = 0; i < document.forms.length; ++i) {
|
4227 |
-
var form = document.forms[i];
|
4228 |
-
var place = form.querySelector('.cerber-form-marker');
|
4229 |
-
if (null !== place) render_recaptcha_widget(form, place);
|
4230 |
-
}
|
4231 |
-
};
|
4232 |
-
|
4233 |
-
function render_recaptcha_widget(form, place) {
|
4234 |
-
var place_id = grecaptcha.render(place, {
|
4235 |
-
'callback': function (g_recaptcha_response) {
|
4236 |
-
HTMLFormElement.prototype.submit.call(form);
|
4237 |
-
},
|
4238 |
-
'sitekey': '<?php echo $sitekey; ?>',
|
4239 |
-
'size': 'invisible',
|
4240 |
-
'badge': 'bottomright'
|
4241 |
-
});
|
4242 |
-
|
4243 |
-
form.onsubmit = function (event) {
|
4244 |
-
event.preventDefault();
|
4245 |
-
grecaptcha.execute(place_id);
|
4246 |
-
};
|
4247 |
-
|
4248 |
-
}
|
4249 |
-
</script>
|
4250 |
-
<?php
|
4251 |
-
}
|
4252 |
-
}
|
4253 |
-
|
4254 |
-
/**
|
4255 |
-
* Inline reCAPTCHA widget
|
4256 |
-
*
|
4257 |
-
*/
|
4258 |
-
add_action( 'wp_footer', 'cerber_foo', 1000 );
|
4259 |
-
function cerber_foo() {
|
4260 |
-
global $wp_cerber;
|
4261 |
-
|
4262 |
-
if (is_singular()) cerber_antibot_code( array( 'botscomm', 'botsany' ) );
|
4263 |
-
|
4264 |
-
if (!$wp_cerber->recaptcha_here) return;
|
4265 |
-
|
4266 |
-
// jQuery version with support visible and invisible reCAPTCHA
|
4267 |
-
// TODO: convert it into pure JS
|
4268 |
-
?>
|
4269 |
-
<script type="text/javascript">
|
4270 |
-
|
4271 |
-
jQuery(document).ready(function ($) {
|
4272 |
-
|
4273 |
-
var recaptcha_ok = false;
|
4274 |
-
var the_recaptcha_widget = $("#cerber-recaptcha");
|
4275 |
-
var is_recaptcha_visible = ($(the_recaptcha_widget).data('size') !== 'invisible');
|
4276 |
-
|
4277 |
-
var the_form = $(the_recaptcha_widget).closest("form");
|
4278 |
-
var the_button = $(the_form).find('input[type="submit"]');
|
4279 |
-
if (!the_button.length) {
|
4280 |
-
the_button = $(the_form).find(':button');
|
4281 |
-
}
|
4282 |
-
|
4283 |
-
// visible
|
4284 |
-
if (the_button.length && is_recaptcha_visible) {
|
4285 |
-
the_button.prop("disabled", true);
|
4286 |
-
the_button.css("opacity", 0.5);
|
4287 |
-
}
|
4288 |
-
|
4289 |
-
window.form_button_enabler = function () {
|
4290 |
-
if (!the_button.length) return;
|
4291 |
-
the_button.prop("disabled", false);
|
4292 |
-
the_button.css( "opacity", 1 );
|
4293 |
-
};
|
4294 |
-
|
4295 |
-
// invisible
|
4296 |
-
if (!is_recaptcha_visible) {
|
4297 |
-
$(the_button).click(function (event) {
|
4298 |
-
if (recaptcha_ok) return;
|
4299 |
-
event.preventDefault();
|
4300 |
-
grecaptcha.execute();
|
4301 |
-
});
|
4302 |
-
}
|
4303 |
-
|
4304 |
-
window.now_submit_the_form = function () {
|
4305 |
-
recaptcha_ok = true;
|
4306 |
-
$(the_button).click(); // this is only way to submit a form that contains "submit" inputs
|
4307 |
-
};
|
4308 |
-
});
|
4309 |
-
</script>
|
4310 |
-
<script src = "https://www.google.com/recaptcha/api.js?hl=<?php echo cerber_recaptcha_lang(); ?>" async defer></script>
|
4311 |
-
<?php
|
4312 |
-
}
|
4313 |
-
|
4314 |
-
|
4315 |
-
// Traffic Logging ======================================================================
|
4316 |
-
|
4317 |
-
//add_action( 'wp', 'cerber_traffic_log' );
|
4318 |
-
add_action( 'shutdown', function () {
|
4319 |
-
cerber_traffic_log();
|
4320 |
-
} );
|
4321 |
-
register_shutdown_function( 'cerber_traffic_log' );
|
4322 |
-
/**
|
4323 |
-
* Traffic Logging
|
4324 |
-
*
|
4325 |
-
* @since 6.0
|
4326 |
-
*/
|
4327 |
-
function cerber_traffic_log(){
|
4328 |
-
global $wpdb, $wp_query, $wp_cerber_user_id, $wp_cerber_start_stamp, $blog_id;
|
4329 |
-
static $logged = false;
|
4330 |
-
|
4331 |
-
if ( $logged ) {
|
4332 |
-
return;
|
4333 |
-
}
|
4334 |
-
|
4335 |
-
$wp_cerber = get_wp_cerber();
|
4336 |
-
|
4337 |
-
$wp_type = 700;
|
4338 |
-
|
4339 |
-
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
4340 |
-
/*
|
4341 |
-
if ( isset( $_POST['action'] ) && $_POST['action'] == 'heartbeat' ) {
|
4342 |
-
return;
|
4343 |
-
}*/
|
4344 |
-
$wp_type = 500;
|
4345 |
-
}
|
4346 |
-
elseif ( is_admin() ) {
|
4347 |
-
$wp_type = 501;
|
4348 |
-
}
|
4349 |
-
elseif ( defined( 'DOING_CRON' ) && DOING_CRON ) {
|
4350 |
-
$wp_type = 502;
|
4351 |
-
}
|
4352 |
-
elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
|
4353 |
-
$wp_type = 515;
|
4354 |
-
}
|
4355 |
-
elseif ( cerber_is_rest_url() ) {
|
4356 |
-
$wp_type = 520;
|
4357 |
-
}
|
4358 |
-
// Public part starts with 600
|
4359 |
-
elseif ( $wp_query && is_object( $wp_query ) ) {
|
4360 |
-
$wp_type = 600;
|
4361 |
-
if ( $wp_query->is_singular ) {
|
4362 |
-
$wp_type = 601;
|
4363 |
-
}
|
4364 |
-
elseif ( $wp_query->is_tag ) {
|
4365 |
-
$wp_type = 603;
|
4366 |
-
}
|
4367 |
-
elseif ( $wp_query->is_category ) {
|
4368 |
-
$wp_type = 604;
|
4369 |
-
}
|
4370 |
-
elseif ( $wp_query->is_search ) {
|
4371 |
-
$wp_type = 605;
|
4372 |
-
}
|
4373 |
-
}
|
4374 |
-
|
4375 |
-
if ( function_exists( 'http_response_code' ) ) { // PHP >= 5.4.0, PHP 7
|
4376 |
-
$http_code = http_response_code();
|
4377 |
-
}
|
4378 |
-
else {
|
4379 |
-
//get_status_header_desc()
|
4380 |
-
// TODO: Add detection for other HTTP codes for PHP 5.3
|
4381 |
-
$http_code = 200;
|
4382 |
-
if ( $wp_type > 600 ) {
|
4383 |
-
if ( $wp_query->is_404 ) {
|
4384 |
-
$http_code = 404;
|
4385 |
-
}
|
4386 |
-
}
|
4387 |
-
}
|
4388 |
-
|
4389 |
-
$user_id = 0;
|
4390 |
-
if ( function_exists( 'get_current_user_id' ) ) {
|
4391 |
-
$user_id = get_current_user_id();
|
4392 |
-
}
|
4393 |
-
if ( ! $user_id && $wp_cerber_user_id ) {
|
4394 |
-
$user_id = absint( $wp_cerber_user_id );
|
4395 |
-
}
|
4396 |
-
|
4397 |
-
if ( ! cerber_to_log( $wp_type, $http_code, $user_id ) ) {
|
4398 |
-
return;
|
4399 |
-
}
|
4400 |
-
|
4401 |
-
$logged = true;
|
4402 |
-
|
4403 |
-
$ua = '';
|
4404 |
-
if ( ! empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
|
4405 |
-
$ua = substr ($_SERVER['HTTP_USER_AGENT'], 0, 1000);
|
4406 |
-
}
|
4407 |
-
|
4408 |
-
$bot = cerber_is_crawler( $ua );
|
4409 |
-
if ( $bot && crb_get_settings( 'tinocrabs' ) ) {
|
4410 |
-
return;
|
4411 |
-
}
|
4412 |
-
|
4413 |
-
$ip = $wp_cerber->getRemoteIp();
|
4414 |
-
$ip_long = 0;
|
4415 |
-
if ( cerber_is_ipv4( $ip ) ) {
|
4416 |
-
$ip_long = ip2long( $ip );
|
4417 |
-
}
|
4418 |
-
|
4419 |
-
$wp_id = 0;
|
4420 |
-
if ( $wp_query && is_object( $wp_query ) ) {
|
4421 |
-
$wp_id = absint( $wp_query->get_queried_object_id() );
|
4422 |
-
}
|
4423 |
-
|
4424 |
-
$session_id = $wp_cerber->getSessionID();
|
4425 |
-
if ( is_ssl() ) {
|
4426 |
-
$scheme = 'https';
|
4427 |
-
}
|
4428 |
-
else {
|
4429 |
-
$scheme = 'http';
|
4430 |
-
}
|
4431 |
-
$uri = $scheme . '://'. $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
4432 |
-
$method = preg_replace( '/[^\w]/', '', $_SERVER['REQUEST_METHOD'] );
|
4433 |
-
|
4434 |
-
// Request fields
|
4435 |
-
|
4436 |
-
$fields = '';
|
4437 |
-
if ( crb_get_settings( 'tifields' ) ) {
|
4438 |
-
$fields = array();
|
4439 |
-
if ( ! empty( $_POST ) ) {
|
4440 |
-
$fields[1] = cerber_prepare_fields( cerber_mask_fields( (array) $_POST ) );
|
4441 |
-
}
|
4442 |
-
if ( ! empty( $_GET ) ) {
|
4443 |
-
$fields[2] = cerber_prepare_fields( (array) $_GET );
|
4444 |
-
}
|
4445 |
-
if ( ! empty( $_FILES ) ) {
|
4446 |
-
$fields[3] = $_FILES;
|
4447 |
-
}
|
4448 |
-
if ( ! empty( $fields ) ) {
|
4449 |
-
$fields = serialize( $fields );
|
4450 |
-
}
|
4451 |
-
else {
|
4452 |
-
$fields = '';
|
4453 |
-
}
|
4454 |
-
}
|
4455 |
-
|
4456 |
-
// Extra request details
|
4457 |
-
|
4458 |
-
$details = array();
|
4459 |
-
if ( $ua ) {
|
4460 |
-
$details[1] = $ua;
|
4461 |
-
}
|
4462 |
-
if ( ! empty( $_SERVER['HTTP_REFERER'] ) ) {
|
4463 |
-
//$ref = mb_substr( $_SERVER['HTTP_REFERER'], 0, 1048576 ); // 1 Mb for ASCII
|
4464 |
-
$details[2] = filter_var( $_SERVER['HTTP_REFERER'], FILTER_SANITIZE_URL );
|
4465 |
-
}
|
4466 |
-
/*
|
4467 |
-
if ( ! empty( $_FILES ) ) {
|
4468 |
-
$details[3] = $_FILES;
|
4469 |
-
}*/
|
4470 |
-
if ( $wp_type == 605 && ! empty( $_GET['s'] ) ) {
|
4471 |
-
$details[4] = $_GET['s'];
|
4472 |
-
}
|
4473 |
-
if ( $wp_type == 515 ) {
|
4474 |
-
// TODO: add a setting to enable it because there is a user/password in the php://input
|
4475 |
-
//$details[5] = file_get_contents('php://input');
|
4476 |
-
}
|
4477 |
-
if ( crb_get_settings( 'tihdrs' ) ) {
|
4478 |
-
$hds = getallheaders();
|
4479 |
-
unset( $hds['Cookie'] );
|
4480 |
-
$details[6] = $hds;
|
4481 |
-
}
|
4482 |
-
if ( crb_get_settings( 'tisenv' ) ) {
|
4483 |
-
$srv = $_SERVER;
|
4484 |
-
unset( $srv['HTTP_COOKIE'] );
|
4485 |
-
$details[7] = $srv;
|
4486 |
-
}
|
4487 |
-
if ( crb_get_settings( 'ticandy' ) && ! empty( $_COOKIE ) ) {
|
4488 |
-
$details[8] = $_COOKIE;
|
4489 |
-
}
|
4490 |
-
if ( !empty( $details ) ) {
|
4491 |
-
/*
|
4492 |
-
foreach ( $details as &$detail ) {
|
4493 |
-
$detail = mb_substr($detail, 0, 1048576); // 1 Mb for ASCII
|
4494 |
-
}*/
|
4495 |
-
$details = cerber_prepare_fields( $details );
|
4496 |
-
$details = serialize($details);
|
4497 |
-
}
|
4498 |
-
else {
|
4499 |
-
$details = '';
|
4500 |
-
}
|
4501 |
-
|
4502 |
-
// Timestamps
|
4503 |
-
if ( ! empty( $wp_cerber_start_stamp ) && is_numeric( $wp_cerber_start_stamp ) ) {
|
4504 |
-
$stamp = (float)$wp_cerber_start_stamp; // define this variable: $wp_cerber_start_stamp = microtime( true ); in wp-config.php
|
4505 |
-
}
|
4506 |
-
else {
|
4507 |
-
$stamp = cerber_request_time();
|
4508 |
-
}
|
4509 |
-
|
4510 |
-
$processing = (int) ( 1000 * ( microtime( true ) - $stamp ) );
|
4511 |
-
|
4512 |
-
$uri = cerber_real_escape($uri);
|
4513 |
-
$fields = cerber_real_escape($fields);
|
4514 |
-
$details = cerber_real_escape($details);
|
4515 |
-
|
4516 |
-
//$uri = $wpdb->remove_placeholder_escape( esc_sql( $uri ) );
|
4517 |
-
//$fields = $wpdb->remove_placeholder_escape( esc_sql( $fields ) );
|
4518 |
-
//$details = $wpdb->remove_placeholder_escape( esc_sql( $details ) );
|
4519 |
-
|
4520 |
-
//$query = $wpdb->prepare( 'INSERT INTO ' . CERBER_TRAF_TABLE . ' (ip, ip_long, uri, request_fields , request_details, session_id, user_id, stamp, processing, request_method, http_code, wp_id, wp_type, is_bot, blog_id ) VALUES ("' .$ip .'", '. $ip_long . ', %s, %s, %s, "' . $session_id . '", ' . $user_id . ', ' . $stamp . ',' . $processing . ', "' . $method . '", ' . $http_code . ',' . $wp_id . ', ' . $wp_type . ', ' . $bot . ', ' . absint($blog_id) . ')', $uri, $fields, $details);
|
4521 |
-
|
4522 |
-
$query = 'INSERT INTO ' . CERBER_TRAF_TABLE . ' (ip, ip_long, uri, request_fields , request_details, session_id, user_id, stamp, processing, request_method, http_code, wp_id, wp_type, is_bot, blog_id ) VALUES ("' . $ip . '", ' . $ip_long . ',"' . $uri . '","' . $fields . '","' . $details . '", "' . $session_id . '", ' . $user_id . ', ' . $stamp . ',' . $processing . ', "' . $method . '", ' . $http_code . ',' . $wp_id . ', ' . $wp_type . ', ' . $bot . ', ' . absint( $blog_id ) . ')';
|
4523 |
-
|
4524 |
-
//$ret = $wpdb->query( $query );
|
4525 |
-
|
4526 |
-
$ret = cerber_direct_db_query( $query );
|
4527 |
-
|
4528 |
-
if (!$ret){
|
4529 |
-
|
4530 |
-
// mysqli_error($wpdb->dbh);
|
4531 |
-
|
4532 |
-
// TODO: Daily software error report
|
4533 |
-
/*
|
4534 |
-
echo mysqli_sqlstate($wpdb->dbh);
|
4535 |
-
echo $wpdb->last_error;
|
4536 |
-
echo "<p>\n";
|
4537 |
-
echo $uri;
|
4538 |
-
echo "<p>\n";
|
4539 |
-
echo '<p>ERR '.$query.$wpdb->last_error;
|
4540 |
-
echo '<p>'.$wpdb->_real_escape( $uri );
|
4541 |
-
*/
|
4542 |
-
}
|
4543 |
-
|
4544 |
-
}
|
4545 |
-
|
4546 |
-
/**
|
4547 |
-
* To log or not to log current request?
|
4548 |
-
*
|
4549 |
-
* @param $wp_type integer
|
4550 |
-
* @param $http_code integer
|
4551 |
-
* @param $user_id integer
|
4552 |
-
*
|
4553 |
-
* @return bool
|
4554 |
-
* @since 6.0
|
4555 |
-
*/
|
4556 |
-
function cerber_to_log($wp_type = 0, $http_code, $user_id){
|
4557 |
-
global $cerber_logged;
|
4558 |
-
|
4559 |
-
$mode = crb_get_settings( 'timode' );
|
4560 |
-
|
4561 |
-
if ($mode == 0) {
|
4562 |
-
return false;
|
4563 |
-
}
|
4564 |
-
if ($mode == 2) {
|
4565 |
-
if ($wp_type < 515) { // Pure admin requests
|
4566 |
-
return false;
|
4567 |
-
}
|
4568 |
-
return true;
|
4569 |
-
}
|
4570 |
-
|
4571 |
-
// Smart mode ---------------------------------------------------------
|
4572 |
-
|
4573 |
-
if ( ! empty( $cerber_logged ) ) {
|
4574 |
-
$tmp = $cerber_logged;
|
4575 |
-
unset( $tmp[7] );
|
4576 |
-
unset( $tmp[51] );
|
4577 |
-
if ( ! empty( $tmp ) ) {
|
4578 |
-
return true;
|
4579 |
-
}
|
4580 |
-
}
|
4581 |
-
|
4582 |
-
if ($wp_type < 515) {
|
4583 |
-
return false;
|
4584 |
-
}
|
4585 |
-
|
4586 |
-
if ( $http_code >= 400 ||
|
4587 |
-
$wp_type < 600 ||
|
4588 |
-
$user_id ||
|
4589 |
-
cerber_is_http_post() ||
|
4590 |
-
isset($_GET['s']) ||
|
4591 |
-
cerber_get_non_wp_fields()){
|
4592 |
-
return true;
|
4593 |
-
}
|
4594 |
-
|
4595 |
-
if ( cerber_get_uri_script() ) {
|
4596 |
-
return true;
|
4597 |
-
}
|
4598 |
-
|
4599 |
-
return false;
|
4600 |
-
}
|
4601 |
-
|
4602 |
-
/**
|
4603 |
-
* Mask sensitive request fields before saving in DB (avoid information leaks)
|
4604 |
-
*
|
4605 |
-
* @param $fields array
|
4606 |
-
*
|
4607 |
-
* @return array
|
4608 |
-
* @since 6.0
|
4609 |
-
*/
|
4610 |
-
function cerber_mask_fields( $fields ) {
|
4611 |
-
$to_mask = array( 'pwd', 'pass', 'password' );
|
4612 |
-
if ($list = (array)crb_get_settings( 'timask' )){
|
4613 |
-
$to_mask = array_merge($to_mask, $list);
|
4614 |
-
}
|
4615 |
-
foreach ( $to_mask as $mask_field ) {
|
4616 |
-
if ( ! empty( $fields[ $mask_field ] ) ) {
|
4617 |
-
$fields[ $mask_field ] = str_pad( '', mb_strlen( $fields[ $mask_field ] ), '*' );
|
4618 |
-
}
|
4619 |
-
}
|
4620 |
-
|
4621 |
-
return $fields;
|
4622 |
-
}
|
4623 |
-
|
4624 |
-
/**
|
4625 |
-
* Recursive prepare values in array for inserting into DB
|
4626 |
-
*
|
4627 |
-
* @param $list
|
4628 |
-
*
|
4629 |
-
* @return mixed
|
4630 |
-
* @since 6.0
|
4631 |
-
*/
|
4632 |
-
function cerber_prepare_fields( $list ) {
|
4633 |
-
foreach ( $list as &$field ) {
|
4634 |
-
if ( is_array( $field ) ) {
|
4635 |
-
cerber_prepare_fields( @$field );
|
4636 |
-
/*
|
4637 |
-
foreach ( $field as &$field_2 ) {
|
4638 |
-
$field_2 = mb_substr( $field_2, 0, 1048576 ); // 1 Mb for ASCII
|
4639 |
-
}*/
|
4640 |
-
}
|
4641 |
-
else {
|
4642 |
-
if ( ! $field ) {
|
4643 |
-
$field = '';
|
4644 |
-
}
|
4645 |
-
$field = mb_substr( $field, 0, 1048576 ); // 1 Mb for ASCII
|
4646 |
-
}
|
4647 |
-
}
|
4648 |
-
|
4649 |
-
$list = stripslashes_deep( $list );
|
4650 |
-
|
4651 |
-
return $list;
|
4652 |
-
}
|
4653 |
-
|
4654 |
-
/**
|
4655 |
-
* Request time
|
4656 |
-
*
|
4657 |
-
* @return mixed
|
4658 |
-
* @since 6.0
|
4659 |
-
*/
|
4660 |
-
function cerber_request_time() {
|
4661 |
-
static $stamp;
|
4662 |
-
|
4663 |
-
if ( ! isset( $stamp ) ) {
|
4664 |
-
if ( ! empty( $_SERVER['REQUEST_TIME_FLOAT'] ) ) { // PHP >= 5.4
|
4665 |
-
$stamp = $_SERVER['REQUEST_TIME_FLOAT'];
|
4666 |
-
}
|
4667 |
-
else {
|
4668 |
-
$stamp = microtime( true );
|
4669 |
-
}
|
4670 |
-
}
|
4671 |
-
|
4672 |
-
return $stamp;
|
4673 |
-
}
|
4674 |
-
|
4675 |
-
/**
|
4676 |
-
* Return non WP public query fields
|
4677 |
-
*
|
4678 |
-
* @param array $fields An associative array field => value to check
|
4679 |
-
*
|
4680 |
-
* @return array
|
4681 |
-
* @since 6.0
|
4682 |
-
*/
|
4683 |
-
function cerber_get_non_wp_fields($fields = array()) {
|
4684 |
-
global $wp_query;
|
4685 |
-
|
4686 |
-
if ( empty( $fields ) ) {
|
4687 |
-
$get_keys = array_keys( $_GET );
|
4688 |
-
}
|
4689 |
-
else {
|
4690 |
-
$get_keys = array_keys( $fields );
|
4691 |
-
}
|
4692 |
-
|
4693 |
-
if ( empty( $get_keys ) ) {
|
4694 |
-
return array();
|
4695 |
-
}
|
4696 |
-
|
4697 |
-
if ( is_object($wp_query) ) {
|
4698 |
-
$keys = $wp_query->fill_query_vars( array() );
|
4699 |
-
}
|
4700 |
-
else {
|
4701 |
-
$tmp = new WP_Query();
|
4702 |
-
$keys = $tmp->fill_query_vars( array() );
|
4703 |
-
}
|
4704 |
-
|
4705 |
-
$wp_keys = array_keys( $keys ); // WordPress GET fields for frontend
|
4706 |
-
|
4707 |
-
$wp_keys[] = 'redirect_to';
|
4708 |
-
$wp_keys[] = 'reauth';
|
4709 |
-
$wp_keys[] = 'action';
|
4710 |
-
$wp_keys[] = '_wpnonce';
|
4711 |
-
$wp_keys[] = 'loggedout';
|
4712 |
-
|
4713 |
-
// WP Customizer fields
|
4714 |
-
$wp_keys = array_merge($wp_keys, array( 'nonce', '_method', 'wp_customize', 'changeset_uuid', 'customize_changeset_uuid', 'customize_theme', 'theme', 'customize_messenger_channel', 'customize_autosaved' ));
|
4715 |
-
|
4716 |
-
$ret = array_diff( $get_keys, $wp_keys );
|
4717 |
-
|
4718 |
-
if ( ! $ret ) {
|
4719 |
-
$ret = array();
|
4720 |
-
}
|
4721 |
-
|
4722 |
-
return $ret;
|
4723 |
-
|
4724 |
-
}
|
4725 |
-
|
4726 |
-
|
4727 |
-
/**
|
4728 |
-
*
|
4729 |
-
* @since 6.0
|
4730 |
-
*/
|
4731 |
-
function cerber_beast(){
|
4732 |
-
global $cerber_status;
|
4733 |
-
|
4734 |
-
if ( is_admin()
|
4735 |
-
|| ( defined( 'DOING_CRON' ) && DOING_CRON )
|
4736 |
-
|| ( defined( 'WP_CLI' ) && WP_CLI )
|
4737 |
-
) {
|
4738 |
-
return;
|
4739 |
-
}
|
4740 |
-
|
4741 |
-
if ( !crb_get_settings( 'tienabled' ) ) {
|
4742 |
-
return;
|
4743 |
-
}
|
4744 |
-
|
4745 |
-
$acl = cerber_acl_check();
|
4746 |
-
if ( $acl == 'W' ) {
|
4747 |
-
return;
|
4748 |
-
}
|
4749 |
-
|
4750 |
-
$uri = cerber_purify_uri();
|
4751 |
-
|
4752 |
-
if ( $tiwhite = crb_get_settings( 'tiwhite' ) ) {
|
4753 |
-
foreach ( (array)$tiwhite as $item ) {
|
4754 |
-
if ($item == $uri){
|
4755 |
-
return;
|
4756 |
-
}
|
4757 |
-
}
|
4758 |
-
}
|
4759 |
-
|
4760 |
-
$uri_script = cerber_get_uri_script();
|
4761 |
-
|
4762 |
-
if ( $uri_script && $script_filename = cerber_script_filename() ) {
|
4763 |
-
// Scaning for executable scripts?
|
4764 |
-
if ( false === strrpos( $script_filename, $uri ) ) {
|
4765 |
-
$wp_cerber = get_wp_cerber();
|
4766 |
-
$cerber_status = 13;
|
4767 |
-
cerber_log( 55 );
|
4768 |
-
cerber_soft_block_add( $wp_cerber->getRemoteIp(), 8);
|
4769 |
-
//cerber_404_page( true );
|
4770 |
-
cerber_forbidden_page();
|
4771 |
-
}
|
4772 |
-
// Direct access to PHP script
|
4773 |
-
// TODO: add white list setting for permitted URI like query white list
|
4774 |
-
if ( ! in_array( $uri_script, cerber_get_wp_scripts() ) ) {
|
4775 |
-
$deny = false;
|
4776 |
-
if ( $acl == 'B' ) {
|
4777 |
-
$deny = true;
|
4778 |
-
$cerber_status = 14;
|
4779 |
-
}
|
4780 |
-
elseif (!cerber_is_allowed() ) {
|
4781 |
-
$deny = true;
|
4782 |
-
$cerber_status = 13;
|
4783 |
-
}
|
4784 |
-
elseif ( lab_is_blocked( null, true ) ) {
|
4785 |
-
$deny = true;
|
4786 |
-
$cerber_status = 15;
|
4787 |
-
}
|
4788 |
-
if ($deny){
|
4789 |
-
cerber_log( 50 );
|
4790 |
-
//cerber_404_page( true );
|
4791 |
-
cerber_forbidden_page();
|
4792 |
-
}
|
4793 |
-
}
|
4794 |
-
}
|
4795 |
-
}
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Plugin Name: WP Cerber Security & Antispam
|
4 |
+
Plugin URI: https://wpcerber.com
|
5 |
+
Description: Protects WordPress against brute force attacks, bots and hackers. Antispam protection with the Cerber antispam engine and reCAPTCHA. Comprehensive control of user and bot activity. Restrict login by IP access lists. Limit login attempts. Know more: <a href="https://wpcerber.com">wpcerber.com</a>.
|
6 |
+
Author: Gregory
|
7 |
+
Author URI: https://wpcerber.com
|
8 |
+
Version: 6.5
|
9 |
+
Text Domain: wp-cerber
|
10 |
+
Domain Path: /languages
|
11 |
+
Network: true
|
12 |
+
|
13 |
+
Copyright (C) 2015-18 CERBER TECH INC., http://cerber.tech
|
14 |
+
Copyright (C) 2015-18 Gregory Markov, https://wpcerber.com
|
15 |
+
|
16 |
+
Licenced under the GNU GPL.
|
17 |
+
|
18 |
+
This program is free software; you can redistribute it and/or modify
|
19 |
+
it under the terms of the GNU General Public License as published by
|
20 |
+
the Free Software Foundation; either version 3 of the License, or
|
21 |
+
(at your option) any later version.
|
22 |
+
|
23 |
+
This program is distributed in the hope that it will be useful,
|
24 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
25 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
26 |
+
GNU General Public License for more details.
|
27 |
+
|
28 |
+
You should have received a copy of the GNU General Public License
|
29 |
+
along with this program; if not, write to the Free Software
|
30 |
+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
31 |
+
|
32 |
+
*/
|
33 |
+
|
34 |
+
define( 'CERBER_VER', '6.5' );
|
35 |
+
|
36 |
+
function cerber_plugin_file() {
|
37 |
+
return __FILE__;
|
38 |
+
}
|
39 |
+
function cerber_plug_in() {
|
40 |
+
return plugin_basename( __FILE__ );
|
41 |
+
}
|
42 |
+
function cerber_plugin_data() {
|
43 |
+
return get_plugin_data( __FILE__ );
|
44 |
+
}
|
45 |
+
function cerber_plugin_dir_url() {
|
46 |
+
return plugin_dir_url( __FILE__ );
|
47 |
+
}
|
48 |
+
|
49 |
+
require_once( dirname( __FILE__ ) . '/cerber-load.php' );
|
50 |
+
cerber_init();
|
51 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|