Cerber Security & Antispam - Version 5.5

Version Description

  • White list for the WordPress anti-spam engine.
  • White list for REST API requests.
  • Disable access to user data via REST API and stop REST API user enumeration.
  • Read more
Download this release

Release Info

Developer Gioni
Plugin Icon 128x128 Cerber Security & Antispam
Version 5.5
Comparing to
See all releases

Code changes from version 5.2 to 5.5

assets/admin.css CHANGED
@@ -1,3 +1,11 @@
 
 
 
 
 
 
 
 
1
  /* Common */
2
  .crb-main {
3
  width: auto;
@@ -243,7 +251,8 @@
243
  text-decoration: none;
244
  }
245
 
246
- #crb-activity td:nth-child(2){
 
247
  word-break: break-all;
248
  }
249
 
@@ -300,7 +309,7 @@ p.act-url{
300
  border-right: 4px solid rgba(0, 0, 0, 0);
301
  }
302
 
303
- .red_label, .actv10, .actv11, .actv12, .actv16, .actv17, .actv41, .actv42, .actv53, .actv54 {
304
  display: inline-block;
305
  padding: 3px 5px 3px 5px;
306
  /*margin: 1px;*/
@@ -322,7 +331,7 @@ p.act-url{
322
  border-right: 4px solid rgba(0, 0, 0, 0);
323
  }
324
 
325
- .actv10, .actv11, .actv12 {
326
  border-left: 4px solid rgba(0, 0, 0, .25);
327
  }
328
 
@@ -717,3 +726,1106 @@ table.crb-avatar a{
717
  line-height: normal;
718
  color: #0073aa;
719
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Reset some WP styles */
2
+
3
+ .crb-main a:focus,
4
+ #crb-aside a:focus {
5
+ -webkit-box-shadow: none !important;
6
+ box-shadow: none !important;
7
+ }
8
+
9
  /* Common */
10
  .crb-main {
11
  width: auto;
251
  text-decoration: none;
252
  }
253
 
254
+ #crb-activity td:nth-child(2),
255
+ #crb-activity td:nth-child(5){
256
  word-break: break-all;
257
  }
258
 
309
  border-right: 4px solid rgba(0, 0, 0, 0);
310
  }
311
 
312
+ .red_label, .actv10, .actv11, .actv12, .actv16, .actv17, .actv18, .actv19, .actv41, .actv42, .actv53, .actv54, .actv70, .actv71 {
313
  display: inline-block;
314
  padding: 3px 5px 3px 5px;
315
  /*margin: 1px;*/
331
  border-right: 4px solid rgba(0, 0, 0, 0);
332
  }
333
 
334
+ .actv10, .actv11, .actv12, .actv16, .actv17, .actv18 {
335
  border-left: 4px solid rgba(0, 0, 0, .25);
336
  }
337
 
726
  line-height: normal;
727
  color: #0073aa;
728
  }
729
+
730
+ /* GEO */
731
+
732
+ .crb-geo-rule {
733
+ width: 100%;
734
+ /*table-layout: fixed;*/
735
+ }
736
+ table.crb-geo-rule td{
737
+ vertical-align: top;
738
+ }
739
+ table.crb-geo-rule td:first-child{
740
+ width: 10%;
741
+ vertical-align: middle;
742
+ }
743
+ table.crb-geo-rule td:first-child{
744
+ vertical-align: middle;
745
+ }
746
+
747
+
748
+ /* Multi */
749
+
750
+ .multi-wrapper .item {
751
+ padding-left: 24px !important;
752
+ }
753
+ .multi-wrapper .item:hover {
754
+ border-radius: 0 !important;
755
+ }
756
+ .multi-wrapper .non-selected-wrapper .item.selected {
757
+ display: none;
758
+ }
759
+
760
+ .multi-wrapper .non-selected-wrapper, .multi-wrapper .selected-wrapper{
761
+ height: 350px !important;
762
+ }
763
+
764
+ /* Vertical Tabs */
765
+
766
+ table.vtable td {
767
+ vertical-align: top;
768
+ padding: 0;
769
+ }
770
+
771
+ table.vtable td:nth-child(2) {
772
+ padding-left: 1em;
773
+ padding-right: 1em;
774
+ }
775
+
776
+ .vtabs {
777
+ /*float: left;*/
778
+ border: 1px solid #CCC;
779
+ /*background-color: #f1f1f1;*/
780
+ /*width: 30%;*/
781
+ /*min-width: 20%;*/
782
+ min-height: 600px;
783
+ }
784
+
785
+ .vtabs .tablinks {
786
+ font-size: 110%;
787
+ font-weight: bold;
788
+ display: block;
789
+ color: black;
790
+ padding: 22px 16px;
791
+ /*width: 100%;*/
792
+ border: none;
793
+ /* outline: none;*/
794
+ text-align: left;
795
+ cursor: pointer;
796
+ transition: 0.3s;
797
+ }
798
+ .vtabs .tablinks:hover {
799
+ background-color: #ddd;
800
+ }
801
+
802
+ .vtabs .tablinks.active {
803
+ background-color: #fff;
804
+ }
805
+
806
+ .vtabs .tablinks span{
807
+ font-size: 85%;
808
+ color: #555;
809
+ font-weight: normal;
810
+ }
811
+
812
+ .vtabs-content {
813
+ float: left;
814
+ }
815
+ .vtabcontent {
816
+ /*float: left;*/
817
+ padding: 40px 40px 0 40px;
818
+ border: 1px solid #ccc;
819
+ background-color: #fff;
820
+ /*min-width: 50%;*/
821
+ /*border-left: none;*/
822
+ min-height: 560px;
823
+ /*height: 300px;*/
824
+ }
825
+
826
+
827
+ /* Flags */
828
+
829
+ a[data-value="AF"]{
830
+ background: url("flags/af.gif") no-repeat left;
831
+ }
832
+
833
+ a[data-value="AL"]{
834
+ background: url("flags/al.gif") no-repeat left;
835
+ }
836
+
837
+ a[data-value="AX"]{
838
+ background: url("flags/ax.gif") no-repeat left;
839
+ }
840
+
841
+ a[data-value="DZ"]{
842
+ background: url("flags/dz.gif") no-repeat left;
843
+ }
844
+
845
+ a[data-value="AS"]{
846
+ background: url("flags/as.gif") no-repeat left;
847
+ }
848
+
849
+ a[data-value="AD"]{
850
+ background: url("flags/ad.gif") no-repeat left;
851
+ }
852
+
853
+ a[data-value="AO"]{
854
+ background: url("flags/ao.gif") no-repeat left;
855
+ }
856
+
857
+ a[data-value="AI"]{
858
+ background: url("flags/ai.gif") no-repeat left;
859
+ }
860
+
861
+ a[data-value="AQ"]{
862
+ background: url("flags/aq.gif") no-repeat left;
863
+ }
864
+
865
+ a[data-value="AG"]{
866
+ background: url("flags/ag.gif") no-repeat left;
867
+ }
868
+
869
+ a[data-value="AR"]{
870
+ background: url("flags/ar.gif") no-repeat left;
871
+ }
872
+
873
+ a[data-value="AM"]{
874
+ background: url("flags/am.gif") no-repeat left;
875
+ }
876
+
877
+ a[data-value="AW"]{
878
+ background: url("flags/aw.gif") no-repeat left;
879
+ }
880
+
881
+ a[data-value="AU"]{
882
+ background: url("flags/au.gif") no-repeat left;
883
+ }
884
+
885
+ a[data-value="AT"]{
886
+ background: url("flags/at.gif") no-repeat left;
887
+ }
888
+
889
+ a[data-value="AZ"]{
890
+ background: url("flags/az.gif") no-repeat left;
891
+ }
892
+
893
+ a[data-value="BS"]{
894
+ background: url("flags/bs.gif") no-repeat left;
895
+ }
896
+
897
+ a[data-value="BH"]{
898
+ background: url("flags/bh.gif") no-repeat left;
899
+ }
900
+
901
+ a[data-value="BD"]{
902
+ background: url("flags/bd.gif") no-repeat left;
903
+ }
904
+
905
+ a[data-value="BB"]{
906
+ background: url("flags/bb.gif") no-repeat left;
907
+ }
908
+
909
+ a[data-value="BY"]{
910
+ background: url("flags/by.gif") no-repeat left;
911
+ }
912
+
913
+ a[data-value="BE"]{
914
+ background: url("flags/be.gif") no-repeat left;
915
+ }
916
+
917
+ a[data-value="BZ"]{
918
+ background: url("flags/bz.gif") no-repeat left;
919
+ }
920
+
921
+ a[data-value="BJ"]{
922
+ background: url("flags/bj.gif") no-repeat left;
923
+ }
924
+
925
+ a[data-value="BM"]{
926
+ background: url("flags/bm.gif") no-repeat left;
927
+ }
928
+
929
+ a[data-value="BT"]{
930
+ background: url("flags/bt.gif") no-repeat left;
931
+ }
932
+
933
+ a[data-value="BO"]{
934
+ background: url("flags/bo.gif") no-repeat left;
935
+ }
936
+
937
+ a[data-value="BQ"]{
938
+ background: url("flags/bq.gif") no-repeat left;
939
+ }
940
+
941
+ a[data-value="BA"]{
942
+ background: url("flags/ba.gif") no-repeat left;
943
+ }
944
+
945
+ a[data-value="BW"]{
946
+ background: url("flags/bw.gif") no-repeat left;
947
+ }
948
+
949
+ a[data-value="BV"]{
950
+ background: url("flags/bv.gif") no-repeat left;
951
+ }
952
+
953
+ a[data-value="BR"]{
954
+ background: url("flags/br.gif") no-repeat left;
955
+ }
956
+
957
+ a[data-value="IO"]{
958
+ background: url("flags/io.gif") no-repeat left;
959
+ }
960
+
961
+ a[data-value="BN"]{
962
+ background: url("flags/bn.gif") no-repeat left;
963
+ }
964
+
965
+ a[data-value="BG"]{
966
+ background: url("flags/bg.gif") no-repeat left;
967
+ }
968
+
969
+ a[data-value="BF"]{
970
+ background: url("flags/bf.gif") no-repeat left;
971
+ }
972
+
973
+ a[data-value="BI"]{
974
+ background: url("flags/bi.gif") no-repeat left;
975
+ }
976
+
977
+ a[data-value="KH"]{
978
+ background: url("flags/kh.gif") no-repeat left;
979
+ }
980
+
981
+ a[data-value="CM"]{
982
+ background: url("flags/cm.gif") no-repeat left;
983
+ }
984
+
985
+ a[data-value="CA"]{
986
+ background: url("flags/ca.gif") no-repeat left;
987
+ }
988
+
989
+ a[data-value="CV"]{
990
+ background: url("flags/cv.gif") no-repeat left;
991
+ }
992
+
993
+ a[data-value="KY"]{
994
+ background: url("flags/ky.gif") no-repeat left;
995
+ }
996
+
997
+ a[data-value="CF"]{
998
+ background: url("flags/cf.gif") no-repeat left;
999
+ }
1000
+
1001
+ a[data-value="TD"]{
1002
+ background: url("flags/td.gif") no-repeat left;
1003
+ }
1004
+
1005
+ a[data-value="CL"]{
1006
+ background: url("flags/cl.gif") no-repeat left;
1007
+ }
1008
+
1009
+ a[data-value="CN"]{
1010
+ background: url("flags/cn.gif") no-repeat left;
1011
+ }
1012
+
1013
+ a[data-value="CX"]{
1014
+ background: url("flags/cx.gif") no-repeat left;
1015
+ }
1016
+
1017
+ a[data-value="CC"]{
1018
+ background: url("flags/cc.gif") no-repeat left;
1019
+ }
1020
+
1021
+ a[data-value="CO"]{
1022
+ background: url("flags/co.gif") no-repeat left;
1023
+ }
1024
+
1025
+ a[data-value="KM"]{
1026
+ background: url("flags/km.gif") no-repeat left;
1027
+ }
1028
+
1029
+ a[data-value="CG"]{
1030
+ background: url("flags/cg.gif") no-repeat left;
1031
+ }
1032
+
1033
+ a[data-value="CD"]{
1034
+ background: url("flags/cd.gif") no-repeat left;
1035
+ }
1036
+
1037
+ a[data-value="CK"]{
1038
+ background: url("flags/ck.gif") no-repeat left;
1039
+ }
1040
+
1041
+ a[data-value="CR"]{
1042
+ background: url("flags/cr.gif") no-repeat left;
1043
+ }
1044
+
1045
+ a[data-value="CI"]{
1046
+ background: url("flags/ci.gif") no-repeat left;
1047
+ }
1048
+
1049
+ a[data-value="HR"]{
1050
+ background: url("flags/hr.gif") no-repeat left;
1051
+ }
1052
+
1053
+ a[data-value="CU"]{
1054
+ background: url("flags/cu.gif") no-repeat left;
1055
+ }
1056
+
1057
+ a[data-value="CW"]{
1058
+ background: url("flags/cw.gif") no-repeat left;
1059
+ }
1060
+
1061
+ a[data-value="CY"]{
1062
+ background: url("flags/cy.gif") no-repeat left;
1063
+ }
1064
+
1065
+ a[data-value="CZ"]{
1066
+ background: url("flags/cz.gif") no-repeat left;
1067
+ }
1068
+
1069
+ a[data-value="DK"]{
1070
+ background: url("flags/dk.gif") no-repeat left;
1071
+ }
1072
+
1073
+ a[data-value="DJ"]{
1074
+ background: url("flags/dj.gif") no-repeat left;
1075
+ }
1076
+
1077
+ a[data-value="DM"]{
1078
+ background: url("flags/dm.gif") no-repeat left;
1079
+ }
1080
+
1081
+ a[data-value="DO"]{
1082
+ background: url("flags/do.gif") no-repeat left;
1083
+ }
1084
+
1085
+ a[data-value="EC"]{
1086
+ background: url("flags/ec.gif") no-repeat left;
1087
+ }
1088
+
1089
+ a[data-value="EG"]{
1090
+ background: url("flags/eg.gif") no-repeat left;
1091
+ }
1092
+
1093
+ a[data-value="SV"]{
1094
+ background: url("flags/sv.gif") no-repeat left;
1095
+ }
1096
+
1097
+ a[data-value="GQ"]{
1098
+ background: url("flags/gq.gif") no-repeat left;
1099
+ }
1100
+
1101
+ a[data-value="ER"]{
1102
+ background: url("flags/er.gif") no-repeat left;
1103
+ }
1104
+
1105
+ a[data-value="EE"]{
1106
+ background: url("flags/ee.gif") no-repeat left;
1107
+ }
1108
+
1109
+ a[data-value="ET"]{
1110
+ background: url("flags/et.gif") no-repeat left;
1111
+ }
1112
+
1113
+ a[data-value="EU"]{
1114
+ background: url("flags/eu.gif") no-repeat left;
1115
+ }
1116
+
1117
+ a[data-value="EZ"]{
1118
+ background: url("flags/ez.gif") no-repeat left;
1119
+ }
1120
+
1121
+ a[data-value="FK"]{
1122
+ background: url("flags/fk.gif") no-repeat left;
1123
+ }
1124
+
1125
+ a[data-value="FO"]{
1126
+ background: url("flags/fo.gif") no-repeat left;
1127
+ }
1128
+
1129
+ a[data-value="FJ"]{
1130
+ background: url("flags/fj.gif") no-repeat left;
1131
+ }
1132
+
1133
+ a[data-value="FI"]{
1134
+ background: url("flags/fi.gif") no-repeat left;
1135
+ }
1136
+
1137
+ a[data-value="FR"]{
1138
+ background: url("flags/fr.gif") no-repeat left;
1139
+ }
1140
+
1141
+ a[data-value="GF"]{
1142
+ background: url("flags/gf.gif") no-repeat left;
1143
+ }
1144
+
1145
+ a[data-value="PF"]{
1146
+ background: url("flags/pf.gif") no-repeat left;
1147
+ }
1148
+
1149
+ a[data-value="TF"]{
1150
+ background: url("flags/tf.gif") no-repeat left;
1151
+ }
1152
+
1153
+ a[data-value="GA"]{
1154
+ background: url("flags/ga.gif") no-repeat left;
1155
+ }
1156
+
1157
+ a[data-value="GM"]{
1158
+ background: url("flags/gm.gif") no-repeat left;
1159
+ }
1160
+
1161
+ a[data-value="GE"]{
1162
+ background: url("flags/ge.gif") no-repeat left;
1163
+ }
1164
+
1165
+ a[data-value="DE"]{
1166
+ background: url("flags/de.gif") no-repeat left;
1167
+ }
1168
+
1169
+ a[data-value="GH"]{
1170
+ background: url("flags/gh.gif") no-repeat left;
1171
+ }
1172
+
1173
+ a[data-value="GI"]{
1174
+ background: url("flags/gi.gif") no-repeat left;
1175
+ }
1176
+
1177
+ a[data-value="GR"]{
1178
+ background: url("flags/gr.gif") no-repeat left;
1179
+ }
1180
+
1181
+ a[data-value="GL"]{
1182
+ background: url("flags/gl.gif") no-repeat left;
1183
+ }
1184
+
1185
+ a[data-value="GD"]{
1186
+ background: url("flags/gd.gif") no-repeat left;
1187
+ }
1188
+
1189
+ a[data-value="GP"]{
1190
+ background: url("flags/gp.gif") no-repeat left;
1191
+ }
1192
+
1193
+ a[data-value="GU"]{
1194
+ background: url("flags/gu.gif") no-repeat left;
1195
+ }
1196
+
1197
+ a[data-value="GT"]{
1198
+ background: url("flags/gt.gif") no-repeat left;
1199
+ }
1200
+
1201
+ a[data-value="GG"]{
1202
+ background: url("flags/gg.gif") no-repeat left;
1203
+ }
1204
+
1205
+ a[data-value="GN"]{
1206
+ background: url("flags/gn.gif") no-repeat left;
1207
+ }
1208
+
1209
+ a[data-value="GW"]{
1210
+ background: url("flags/gw.gif") no-repeat left;
1211
+ }
1212
+
1213
+ a[data-value="GY"]{
1214
+ background: url("flags/gy.gif") no-repeat left;
1215
+ }
1216
+
1217
+ a[data-value="HT"]{
1218
+ background: url("flags/ht.gif") no-repeat left;
1219
+ }
1220
+
1221
+ a[data-value="HM"]{
1222
+ background: url("flags/hm.gif") no-repeat left;
1223
+ }
1224
+
1225
+ a[data-value="VA"]{
1226
+ background: url("flags/va.gif") no-repeat left;
1227
+ }
1228
+
1229
+ a[data-value="HN"]{
1230
+ background: url("flags/hn.gif") no-repeat left;
1231
+ }
1232
+
1233
+ a[data-value="HK"]{
1234
+ background: url("flags/hk.gif") no-repeat left;
1235
+ }
1236
+
1237
+ a[data-value="HU"]{
1238
+ background: url("flags/hu.gif") no-repeat left;
1239
+ }
1240
+
1241
+ a[data-value="IS"]{
1242
+ background: url("flags/is.gif") no-repeat left;
1243
+ }
1244
+
1245
+ a[data-value="IN"]{
1246
+ background: url("flags/in.gif") no-repeat left;
1247
+ }
1248
+
1249
+ a[data-value="ID"]{
1250
+ background: url("flags/id.gif") no-repeat left;
1251
+ }
1252
+
1253
+ a[data-value="IR"]{
1254
+ background: url("flags/ir.gif") no-repeat left;
1255
+ }
1256
+
1257
+ a[data-value="IQ"]{
1258
+ background: url("flags/iq.gif") no-repeat left;
1259
+ }
1260
+
1261
+ a[data-value="IE"]{
1262
+ background: url("flags/ie.gif") no-repeat left;
1263
+ }
1264
+
1265
+ a[data-value="IM"]{
1266
+ background: url("flags/im.gif") no-repeat left;
1267
+ }
1268
+
1269
+ a[data-value="IL"]{
1270
+ background: url("flags/il.gif") no-repeat left;
1271
+ }
1272
+
1273
+ a[data-value="IT"]{
1274
+ background: url("flags/it.gif") no-repeat left;
1275
+ }
1276
+
1277
+ a[data-value="JM"]{
1278
+ background: url("flags/jm.gif") no-repeat left;
1279
+ }
1280
+
1281
+ a[data-value="JP"]{
1282
+ background: url("flags/jp.gif") no-repeat left;
1283
+ }
1284
+
1285
+ a[data-value="JE"]{
1286
+ background: url("flags/je.gif") no-repeat left;
1287
+ }
1288
+
1289
+ a[data-value="JO"]{
1290
+ background: url("flags/jo.gif") no-repeat left;
1291
+ }
1292
+
1293
+ a[data-value="KZ"]{
1294
+ background: url("flags/kz.gif") no-repeat left;
1295
+ }
1296
+
1297
+ a[data-value="KE"]{
1298
+ background: url("flags/ke.gif") no-repeat left;
1299
+ }
1300
+
1301
+ a[data-value="KI"]{
1302
+ background: url("flags/ki.gif") no-repeat left;
1303
+ }
1304
+
1305
+ a[data-value="KP"]{
1306
+ background: url("flags/kp.gif") no-repeat left;
1307
+ }
1308
+
1309
+ a[data-value="KR"]{
1310
+ background: url("flags/kr.gif") no-repeat left;
1311
+ }
1312
+
1313
+ a[data-value="KW"]{
1314
+ background: url("flags/kw.gif") no-repeat left;
1315
+ }
1316
+
1317
+ a[data-value="KG"]{
1318
+ background: url("flags/kg.gif") no-repeat left;
1319
+ }
1320
+
1321
+ a[data-value="LA"]{
1322
+ background: url("flags/la.gif") no-repeat left;
1323
+ }
1324
+
1325
+ a[data-value="LV"]{
1326
+ background: url("flags/lv.gif") no-repeat left;
1327
+ }
1328
+
1329
+ a[data-value="LB"]{
1330
+ background: url("flags/lb.gif") no-repeat left;
1331
+ }
1332
+
1333
+ a[data-value="LS"]{
1334
+ background: url("flags/ls.gif") no-repeat left;
1335
+ }
1336
+
1337
+ a[data-value="LR"]{
1338
+ background: url("flags/lr.gif") no-repeat left;
1339
+ }
1340
+
1341
+ a[data-value="LY"]{
1342
+ background: url("flags/ly.gif") no-repeat left;
1343
+ }
1344
+
1345
+ a[data-value="LI"]{
1346
+ background: url("flags/li.gif") no-repeat left;
1347
+ }
1348
+
1349
+ a[data-value="LT"]{
1350
+ background: url("flags/lt.gif") no-repeat left;
1351
+ }
1352
+
1353
+ a[data-value="LU"]{
1354
+ background: url("flags/lu.gif") no-repeat left;
1355
+ }
1356
+
1357
+ a[data-value="MO"]{
1358
+ background: url("flags/mo.gif") no-repeat left;
1359
+ }
1360
+
1361
+ a[data-value="MK"]{
1362
+ background: url("flags/mk.gif") no-repeat left;
1363
+ }
1364
+
1365
+ a[data-value="MG"]{
1366
+ background: url("flags/mg.gif") no-repeat left;
1367
+ }
1368
+
1369
+ a[data-value="MW"]{
1370
+ background: url("flags/mw.gif") no-repeat left;
1371
+ }
1372
+
1373
+ a[data-value="MY"]{
1374
+ background: url("flags/my.gif") no-repeat left;
1375
+ }
1376
+
1377
+ a[data-value="MV"]{
1378
+ background: url("flags/mv.gif") no-repeat left;
1379
+ }
1380
+
1381
+ a[data-value="ML"]{
1382
+ background: url("flags/ml.gif") no-repeat left;
1383
+ }
1384
+
1385
+ a[data-value="MT"]{
1386
+ background: url("flags/mt.gif") no-repeat left;
1387
+ }
1388
+
1389
+ a[data-value="MH"]{
1390
+ background: url("flags/mh.gif") no-repeat left;
1391
+ }
1392
+
1393
+ a[data-value="MQ"]{
1394
+ background: url("flags/mq.gif") no-repeat left;
1395
+ }
1396
+
1397
+ a[data-value="MR"]{
1398
+ background: url("flags/mr.gif") no-repeat left;
1399
+ }
1400
+
1401
+ a[data-value="MU"]{
1402
+ background: url("flags/mu.gif") no-repeat left;
1403
+ }
1404
+
1405
+ a[data-value="YT"]{
1406
+ background: url("flags/yt.gif") no-repeat left;
1407
+ }
1408
+
1409
+ a[data-value="MX"]{
1410
+ background: url("flags/mx.gif") no-repeat left;
1411
+ }
1412
+
1413
+ a[data-value="FM"]{
1414
+ background: url("flags/fm.gif") no-repeat left;
1415
+ }
1416
+
1417
+ a[data-value="MD"]{
1418
+ background: url("flags/md.gif") no-repeat left;
1419
+ }
1420
+
1421
+ a[data-value="MC"]{
1422
+ background: url("flags/mc.gif") no-repeat left;
1423
+ }
1424
+
1425
+ a[data-value="MN"]{
1426
+ background: url("flags/mn.gif") no-repeat left;
1427
+ }
1428
+
1429
+ a[data-value="ME"]{
1430
+ background: url("flags/me.gif") no-repeat left;
1431
+ }
1432
+
1433
+ a[data-value="MS"]{
1434
+ background: url("flags/ms.gif") no-repeat left;
1435
+ }
1436
+
1437
+ a[data-value="MA"]{
1438
+ background: url("flags/ma.gif") no-repeat left;
1439
+ }
1440
+
1441
+ a[data-value="MZ"]{
1442
+ background: url("flags/mz.gif") no-repeat left;
1443
+ }
1444
+
1445
+ a[data-value="MM"]{
1446
+ background: url("flags/mm.gif") no-repeat left;
1447
+ }
1448
+
1449
+ a[data-value="NA"]{
1450
+ background: url("flags/na.gif") no-repeat left;
1451
+ }
1452
+
1453
+ a[data-value="NR"]{
1454
+ background: url("flags/nr.gif") no-repeat left;
1455
+ }
1456
+
1457
+ a[data-value="NP"]{
1458
+ background: url("flags/np.gif") no-repeat left;
1459
+ }
1460
+
1461
+ a[data-value="NL"]{
1462
+ background: url("flags/nl.gif") no-repeat left;
1463
+ }
1464
+
1465
+ a[data-value="NC"]{
1466
+ background: url("flags/nc.gif") no-repeat left;
1467
+ }
1468
+
1469
+ a[data-value="NZ"]{
1470
+ background: url("flags/nz.gif") no-repeat left;
1471
+ }
1472
+
1473
+ a[data-value="NI"]{
1474
+ background: url("flags/ni.gif") no-repeat left;
1475
+ }
1476
+
1477
+ a[data-value="NE"]{
1478
+ background: url("flags/ne.gif") no-repeat left;
1479
+ }
1480
+
1481
+ a[data-value="NG"]{
1482
+ background: url("flags/ng.gif") no-repeat left;
1483
+ }
1484
+
1485
+ a[data-value="NU"]{
1486
+ background: url("flags/nu.gif") no-repeat left;
1487
+ }
1488
+
1489
+ a[data-value="NF"]{
1490
+ background: url("flags/nf.gif") no-repeat left;
1491
+ }
1492
+
1493
+ a[data-value="MP"]{
1494
+ background: url("flags/mp.gif") no-repeat left;
1495
+ }
1496
+
1497
+ a[data-value="NO"]{
1498
+ background: url("flags/no.gif") no-repeat left;
1499
+ }
1500
+
1501
+ a[data-value="OM"]{
1502
+ background: url("flags/om.gif") no-repeat left;
1503
+ }
1504
+
1505
+ a[data-value="PK"]{
1506
+ background: url("flags/pk.gif") no-repeat left;
1507
+ }
1508
+
1509
+ a[data-value="PW"]{
1510
+ background: url("flags/pw.gif") no-repeat left;
1511
+ }
1512
+
1513
+ a[data-value="PS"]{
1514
+ background: url("flags/ps.gif") no-repeat left;
1515
+ }
1516
+
1517
+ a[data-value="PA"]{
1518
+ background: url("flags/pa.gif") no-repeat left;
1519
+ }
1520
+
1521
+ a[data-value="PG"]{
1522
+ background: url("flags/pg.gif") no-repeat left;
1523
+ }
1524
+
1525
+ a[data-value="PY"]{
1526
+ background: url("flags/py.gif") no-repeat left;
1527
+ }
1528
+
1529
+ a[data-value="PE"]{
1530
+ background: url("flags/pe.gif") no-repeat left;
1531
+ }
1532
+
1533
+ a[data-value="PH"]{
1534
+ background: url("flags/ph.gif") no-repeat left;
1535
+ }
1536
+
1537
+ a[data-value="PN"]{
1538
+ background: url("flags/pn.gif") no-repeat left;
1539
+ }
1540
+
1541
+ a[data-value="PL"]{
1542
+ background: url("flags/pl.gif") no-repeat left;
1543
+ }
1544
+
1545
+ a[data-value="PT"]{
1546
+ background: url("flags/pt.gif") no-repeat left;
1547
+ }
1548
+
1549
+ a[data-value="PR"]{
1550
+ background: url("flags/pr.gif") no-repeat left;
1551
+ }
1552
+
1553
+ a[data-value="QA"]{
1554
+ background: url("flags/qa.gif") no-repeat left;
1555
+ }
1556
+
1557
+ a[data-value="RE"]{
1558
+ background: url("flags/re.gif") no-repeat left;
1559
+ }
1560
+
1561
+ a[data-value="RO"]{
1562
+ background: url("flags/ro.gif") no-repeat left;
1563
+ }
1564
+
1565
+ a[data-value="RU"]{
1566
+ background: url("flags/ru.gif") no-repeat left;
1567
+ }
1568
+
1569
+ a[data-value="RW"]{
1570
+ background: url("flags/rw.gif") no-repeat left;
1571
+ }
1572
+
1573
+ a[data-value="BL"]{
1574
+ background: url("flags/bl.gif") no-repeat left;
1575
+ }
1576
+
1577
+ a[data-value="SH"]{
1578
+ background: url("flags/sh.gif") no-repeat left;
1579
+ }
1580
+
1581
+ a[data-value="KN"]{
1582
+ background: url("flags/kn.gif") no-repeat left;
1583
+ }
1584
+
1585
+ a[data-value="LC"]{
1586
+ background: url("flags/lc.gif") no-repeat left;
1587
+ }
1588
+
1589
+ a[data-value="MF"]{
1590
+ background: url("flags/mf.gif") no-repeat left;
1591
+ }
1592
+
1593
+ a[data-value="PM"]{
1594
+ background: url("flags/pm.gif") no-repeat left;
1595
+ }
1596
+
1597
+ a[data-value="VC"]{
1598
+ background: url("flags/vc.gif") no-repeat left;
1599
+ }
1600
+
1601
+ a[data-value="WS"]{
1602
+ background: url("flags/ws.gif") no-repeat left;
1603
+ }
1604
+
1605
+ a[data-value="SM"]{
1606
+ background: url("flags/sm.gif") no-repeat left;
1607
+ }
1608
+
1609
+ a[data-value="ST"]{
1610
+ background: url("flags/st.gif") no-repeat left;
1611
+ }
1612
+
1613
+ a[data-value="SA"]{
1614
+ background: url("flags/sa.gif") no-repeat left;
1615
+ }
1616
+
1617
+ a[data-value="SN"]{
1618
+ background: url("flags/sn.gif") no-repeat left;
1619
+ }
1620
+
1621
+ a[data-value="RS"]{
1622
+ background: url("flags/rs.gif") no-repeat left;
1623
+ }
1624
+
1625
+ a[data-value="SC"]{
1626
+ background: url("flags/sc.gif") no-repeat left;
1627
+ }
1628
+
1629
+ a[data-value="SL"]{
1630
+ background: url("flags/sl.gif") no-repeat left;
1631
+ }
1632
+
1633
+ a[data-value="SG"]{
1634
+ background: url("flags/sg.gif") no-repeat left;
1635
+ }
1636
+
1637
+ a[data-value="SX"]{
1638
+ background: url("flags/sx.gif") no-repeat left;
1639
+ }
1640
+
1641
+ a[data-value="SK"]{
1642
+ background: url("flags/sk.gif") no-repeat left;
1643
+ }
1644
+
1645
+ a[data-value="SI"]{
1646
+ background: url("flags/si.gif") no-repeat left;
1647
+ }
1648
+
1649
+ a[data-value="SB"]{
1650
+ background: url("flags/sb.gif") no-repeat left;
1651
+ }
1652
+
1653
+ a[data-value="SO"]{
1654
+ background: url("flags/so.gif") no-repeat left;
1655
+ }
1656
+
1657
+ a[data-value="ZA"]{
1658
+ background: url("flags/za.gif") no-repeat left;
1659
+ }
1660
+
1661
+ a[data-value="GS"]{
1662
+ background: url("flags/gs.gif") no-repeat left;
1663
+ }
1664
+
1665
+ a[data-value="SS"]{
1666
+ background: url("flags/ss.gif") no-repeat left;
1667
+ }
1668
+
1669
+ a[data-value="ES"]{
1670
+ background: url("flags/es.gif") no-repeat left;
1671
+ }
1672
+
1673
+ a[data-value="LK"]{
1674
+ background: url("flags/lk.gif") no-repeat left;
1675
+ }
1676
+
1677
+ a[data-value="SD"]{
1678
+ background: url("flags/sd.gif") no-repeat left;
1679
+ }
1680
+
1681
+ a[data-value="SR"]{
1682
+ background: url("flags/sr.gif") no-repeat left;
1683
+ }
1684
+
1685
+ a[data-value="SJ"]{
1686
+ background: url("flags/sj.gif") no-repeat left;
1687
+ }
1688
+
1689
+ a[data-value="SZ"]{
1690
+ background: url("flags/sz.gif") no-repeat left;
1691
+ }
1692
+
1693
+ a[data-value="SE"]{
1694
+ background: url("flags/se.gif") no-repeat left;
1695
+ }
1696
+
1697
+ a[data-value="CH"]{
1698
+ background: url("flags/ch.gif") no-repeat left;
1699
+ }
1700
+
1701
+ a[data-value="SY"]{
1702
+ background: url("flags/sy.gif") no-repeat left;
1703
+ }
1704
+
1705
+ a[data-value="TW"]{
1706
+ background: url("flags/tw.gif") no-repeat left;
1707
+ }
1708
+
1709
+ a[data-value="TJ"]{
1710
+ background: url("flags/tj.gif") no-repeat left;
1711
+ }
1712
+
1713
+ a[data-value="TZ"]{
1714
+ background: url("flags/tz.gif") no-repeat left;
1715
+ }
1716
+
1717
+ a[data-value="TH"]{
1718
+ background: url("flags/th.gif") no-repeat left;
1719
+ }
1720
+
1721
+ a[data-value="TL"]{
1722
+ background: url("flags/tl.gif") no-repeat left;
1723
+ }
1724
+
1725
+ a[data-value="TG"]{
1726
+ background: url("flags/tg.gif") no-repeat left;
1727
+ }
1728
+
1729
+ a[data-value="TK"]{
1730
+ background: url("flags/tk.gif") no-repeat left;
1731
+ }
1732
+
1733
+ a[data-value="TO"]{
1734
+ background: url("flags/to.gif") no-repeat left;
1735
+ }
1736
+
1737
+ a[data-value="TT"]{
1738
+ background: url("flags/tt.gif") no-repeat left;
1739
+ }
1740
+
1741
+ a[data-value="TN"]{
1742
+ background: url("flags/tn.gif") no-repeat left;
1743
+ }
1744
+
1745
+ a[data-value="TR"]{
1746
+ background: url("flags/tr.gif") no-repeat left;
1747
+ }
1748
+
1749
+ a[data-value="TM"]{
1750
+ background: url("flags/tm.gif") no-repeat left;
1751
+ }
1752
+
1753
+ a[data-value="TC"]{
1754
+ background: url("flags/tc.gif") no-repeat left;
1755
+ }
1756
+
1757
+ a[data-value="TV"]{
1758
+ background: url("flags/tv.gif") no-repeat left;
1759
+ }
1760
+
1761
+ a[data-value="UG"]{
1762
+ background: url("flags/ug.gif") no-repeat left;
1763
+ }
1764
+
1765
+ a[data-value="UA"]{
1766
+ background: url("flags/ua.gif") no-repeat left;
1767
+ }
1768
+
1769
+ a[data-value="AE"]{
1770
+ background: url("flags/ae.gif") no-repeat left;
1771
+ }
1772
+
1773
+ a[data-value="GB"]{
1774
+ background: url("flags/gb.gif") no-repeat left;
1775
+ }
1776
+
1777
+ a[data-value="US"]{
1778
+ background: url("flags/us.gif") no-repeat left;
1779
+ }
1780
+
1781
+ a[data-value="UM"]{
1782
+ background: url("flags/um.gif") no-repeat left;
1783
+ }
1784
+
1785
+ a[data-value="UY"]{
1786
+ background: url("flags/uy.gif") no-repeat left;
1787
+ }
1788
+
1789
+ a[data-value="UZ"]{
1790
+ background: url("flags/uz.gif") no-repeat left;
1791
+ }
1792
+
1793
+ a[data-value="VU"]{
1794
+ background: url("flags/vu.gif") no-repeat left;
1795
+ }
1796
+
1797
+ a[data-value="VE"]{
1798
+ background: url("flags/ve.gif") no-repeat left;
1799
+ }
1800
+
1801
+ a[data-value="VN"]{
1802
+ background: url("flags/vn.gif") no-repeat left;
1803
+ }
1804
+
1805
+ a[data-value="VG"]{
1806
+ background: url("flags/vg.gif") no-repeat left;
1807
+ }
1808
+
1809
+ a[data-value="VI"]{
1810
+ background: url("flags/vi.gif") no-repeat left;
1811
+ }
1812
+
1813
+ a[data-value="WF"]{
1814
+ background: url("flags/wf.gif") no-repeat left;
1815
+ }
1816
+
1817
+ a[data-value="EH"]{
1818
+ background: url("flags/eh.gif") no-repeat left;
1819
+ }
1820
+
1821
+ a[data-value="YE"]{
1822
+ background: url("flags/ye.gif") no-repeat left;
1823
+ }
1824
+
1825
+ a[data-value="ZM"]{
1826
+ background: url("flags/zm.gif") no-repeat left;
1827
+ }
1828
+
1829
+ a[data-value="ZW"]{
1830
+ background: url("flags/zw.gif") no-repeat left;
1831
+ }
assets/admin.js CHANGED
@@ -1,6 +1,51 @@
1
  jQuery(document).ready(function ($) {
2
 
3
- $(".delete_entry").click(function () {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  /* if (!confirm('<?php _e('Are you sure?','wp-cerber') ?>')) return; */
5
  $.post(ajaxurl, {
6
  action: 'cerber_ajax',
@@ -17,27 +62,7 @@ jQuery(document).ready(function ($) {
17
  $('.delete_entry[data-ip="' + cerber_response['deleted_ip'] + '"]').parent().parent().fadeOut(300);
18
  }
19
 
20
-
21
- if ($(".crb-table").length) {
22
- function setHostNames(server_data) {
23
- var hostnames = $.parseJSON(server_data);
24
- $(".crb-table .crb-no-hn").each(function (index) {
25
- $(this).replaceWith(hostnames[$(this).data('ip-id')]);
26
- });
27
- }
28
-
29
- var ip_list = $(".crb-table .crb-no-hn").map(
30
- function () {
31
- return $(this).data('ip-id');
32
- }
33
- );
34
- if (ip_list.length != 0) {
35
- $.post(ajaxurl, {
36
- action: 'cerber_ajax',
37
- get_hostnames: ip_list.toArray()
38
- }, setHostNames);
39
- }
40
- }
41
 
42
  /*
43
  $('#add-acl-black').submit(function( event ) {
1
  jQuery(document).ready(function ($) {
2
 
3
+ /* Load data with AJAX */
4
+
5
+ if ($(".crb-table").length) {
6
+ cerberLoadData('hostname');
7
+ cerberLoadData('country');
8
+ }
9
+
10
+ if ($("table.users").length) {
11
+ //cerberLoadData('hostname');
12
+ cerberLoadData('country');
13
+ }
14
+
15
+ function cerberLoadData(slug) {
16
+ var ip_list = $(".crb-no-" + slug).map(
17
+ function () {
18
+ return $(this).data('ip-id');
19
+ }
20
+ );
21
+ if (ip_list.length !== 0) {
22
+ $.post(ajaxurl, {
23
+ action: 'cerber_ajax',
24
+ crb_ajax_slug: slug,
25
+ crb_ajax_list: ip_list.toArray(),
26
+ ajax_nonce: crb_ajax_nonce
27
+ }, cerberSetData);
28
+ }
29
+ }
30
+
31
+ function cerberSetData(server_response) {
32
+ var server_data = $.parseJSON(server_response);
33
+ if (!server_data['data']) {
34
+ console.log('No data loaded from server!');
35
+ return;
36
+ }
37
+ var data = server_data['data'];
38
+ var slug = server_data['slug'];
39
+ $(".crb-no-" + slug).each(function (index) {
40
+ if (data[$(this).data('ip-id')]) {
41
+ $(this).replaceWith(data[$(this).data('ip-id')]);
42
+ }
43
+ });
44
+ }
45
+
46
+ // ACL management
47
+
48
+ $(".acl-table .delete_entry").click(function () {
49
  /* if (!confirm('<?php _e('Are you sure?','wp-cerber') ?>')) return; */
50
  $.post(ajaxurl, {
51
  action: 'cerber_ajax',
62
  $('.delete_entry[data-ip="' + cerber_response['deleted_ip'] + '"]').parent().parent().fadeOut(300);
63
  }
64
 
65
+ //
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  /*
68
  $('#add-acl-black').submit(function( event ) {
assets/ajax-loader-ip.gif DELETED
Binary file
assets/ajax-loader.gif ADDED
Binary file
assets/flags/aq.gif ADDED
Binary file
assets/flags/bl.gif ADDED
Binary file
assets/flags/bq.gif ADDED
Binary file
assets/flags/cw.gif ADDED
Binary file
assets/flags/ez.gif ADDED
Binary file
assets/flags/gg.gif ADDED
Binary file
assets/flags/im.gif ADDED
Binary file
assets/flags/je.gif ADDED
Binary file
assets/flags/mf.gif ADDED
Binary file
assets/flags/ss.gif ADDED
Binary file
assets/flags/sx.gif ADDED
Binary file
assets/multi/license.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ Copyright 2017 Fabian Lindfors
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
assets/multi/multi.css ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .multi-wrapper {
2
+ border: 1px solid #ccc;
3
+ border-radius: 3px;
4
+ width: 100%;
5
+ }
6
+
7
+ .multi-wrapper .non-selected-wrapper,
8
+ .multi-wrapper .selected-wrapper {
9
+ box-sizing: border-box;
10
+ display: inline-block;
11
+ height: 200px;
12
+ overflow-y: scroll;
13
+ padding: 10px;
14
+ vertical-align: top;
15
+ width: 50%;
16
+ }
17
+
18
+ .multi-wrapper .non-selected-wrapper {
19
+ background: #fafafa;
20
+ border-right: 1px solid #ccc;
21
+ }
22
+
23
+ .multi-wrapper .selected-wrapper {
24
+ background: #fff;
25
+ }
26
+
27
+ .multi-wrapper .item {
28
+ cursor: pointer;
29
+ display: block;
30
+ padding: 5px 10px;
31
+ }
32
+
33
+ .multi-wrapper .item:hover {
34
+ /* background: #ececec; */ /* by Gioni */
35
+ background-color: #ececec; /* by Gioni */
36
+ border-radius: 2px;
37
+ }
38
+
39
+ .multi-wrapper .search-input {
40
+ border: 0;
41
+ border-bottom: 1px solid #ccc;
42
+ border-radius: 0;
43
+ display: block;
44
+ font-size: 1em;
45
+ margin: 0;
46
+ outline: 0;
47
+ padding: 10px 20px;
48
+ width: 100%;
49
+ box-sizing: border-box;
50
+ }
51
+
52
+ .multi-wrapper .non-selected-wrapper .item.selected {
53
+ opacity: 0.5;
54
+ }
55
+
56
+ .multi-wrapper .non-selected-wrapper .item.disabled,
57
+ .multi-wrapper .selected-wrapper .item.disabled {
58
+ opacity: 0.5;
59
+ text-decoration: line-through;
60
+ }
61
+
62
+ .multi-wrapper .non-selected-wrapper .item.disabled:hover,
63
+ .multi-wrapper .selected-wrapper .item.disabled:hover {
64
+ background: inherit;
65
+ cursor: inherit;
66
+ }
assets/multi/multi.js ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * multi.js
3
+ * A user-friendly replacement for select boxes with multiple attribute enabled.
4
+ *
5
+ * Author: Fabian Lindfors
6
+ * License: MIT
7
+ */
8
+ var multi = (function() {
9
+
10
+ // Helper function to trigger an event on an element
11
+ var trigger_event = function( type, el ) {
12
+ var e = document.createEvent( 'HTMLEvents' );
13
+ e.initEvent( type, false, true );
14
+ el.dispatchEvent( e );
15
+ };
16
+
17
+ // Toggles the target option on the select
18
+ var toggle_option = function ( select, event ) {
19
+ var option = select.options[ event.target.getAttribute( 'multi-index' ) ];
20
+
21
+ if ( option.disabled ) {
22
+ return;
23
+ }
24
+
25
+ option.selected = !option.selected;
26
+ trigger_event( 'change', select );
27
+ };
28
+
29
+ // Refreshes an already constructed multi.js instance
30
+ var refresh_select = function( select, settings ) {
31
+
32
+ // Clear columns
33
+ select.wrapper.selected.innerHTML = '';
34
+ select.wrapper.non_selected.innerHTML = '';
35
+
36
+ // Get search value
37
+ if ( select.wrapper.search ) {
38
+ var query = select.wrapper.search.value;
39
+ }
40
+
41
+ // Loop over select options and add to the non-selected and selected columns
42
+ for ( var i = 0; i < select.options.length; i++ ) {
43
+
44
+ var option = select.options[i];
45
+
46
+ var value = option.value;
47
+ var label = option.textContent || option.innerText;
48
+
49
+ var row = document.createElement( 'a' );
50
+ row.tabIndex = 0;
51
+ row.className = 'item';
52
+ row.innerHTML = label;
53
+ row.setAttribute( 'role', 'button' );
54
+ row.setAttribute( 'data-value', value );
55
+ row.setAttribute( 'multi-index', i );
56
+
57
+ if ( option.disabled ) {
58
+ row.className += ' disabled';
59
+ }
60
+
61
+ // Add row to selected column if option selected
62
+ if ( option.selected ) {
63
+
64
+ row.className += ' selected';
65
+ var clone = row.cloneNode( true );
66
+ select.wrapper.selected.appendChild( clone );
67
+
68
+ }
69
+
70
+ // Apply search filtering
71
+ if ( !query || query && label.toLowerCase().indexOf( query.toLowerCase() ) > -1 ) {
72
+ select.wrapper.non_selected.appendChild( row );
73
+ }
74
+
75
+ }
76
+
77
+ };
78
+
79
+
80
+ // Intializes and constructs an multi.js instance
81
+ var init = function( select, settings ) {
82
+
83
+ /**
84
+ * Set up settings (optional parameter) and its default values
85
+ *
86
+ * Default values:
87
+ * enable_search : true
88
+ * search_placeholder : 'Search...'
89
+ */
90
+ settings = typeof settings !== 'undefined' ? settings : {};
91
+
92
+ settings['enable_search'] = typeof settings['enable_search'] !== 'undefined' ? settings['enable_search'] : true;
93
+ settings['search_placeholder'] = typeof settings['search_placeholder'] !== 'undefined' ? settings['search_placeholder'] : 'Search...';
94
+
95
+
96
+ // Check if already initalized
97
+ if ( select.dataset.multijs != null ) {
98
+ return;
99
+ }
100
+
101
+ // Make sure element is select and multiple is enabled
102
+ if ( select.nodeName != 'SELECT' || ! select.multiple ) {
103
+ return;
104
+ }
105
+
106
+ // Hide select
107
+ select.style.display = 'none';
108
+ select.setAttribute( 'data-multijs', true );
109
+
110
+ // Start constructing selector
111
+ var wrapper = document.createElement( 'div' );
112
+ wrapper.className = 'multi-wrapper';
113
+
114
+
115
+ // Add search bar
116
+ if ( settings.enable_search ) {
117
+ var search = document.createElement( 'input' );
118
+ search.className = 'search-input';
119
+ search.type = 'text';
120
+ search.setAttribute( 'placeholder', settings.search_placeholder );
121
+
122
+ search.addEventListener( 'input', function() {
123
+ refresh_select( select, settings );
124
+ });
125
+
126
+ wrapper.appendChild( search );
127
+ wrapper.search = search;
128
+ }
129
+
130
+
131
+ // Add columns for selected and non-selected
132
+ var non_selected = document.createElement( 'div' );
133
+ non_selected.className = 'non-selected-wrapper';
134
+
135
+ var selected = document.createElement( 'div' );
136
+ selected.className = 'selected-wrapper';
137
+
138
+
139
+ // Add click handler to toggle the selected status
140
+ wrapper.addEventListener( 'click', function ( event ) {
141
+
142
+ if ( event.target.getAttribute( 'multi-index' ) ) {
143
+ toggle_option( select, event );
144
+ }
145
+
146
+ });
147
+
148
+
149
+ // Add keyboard handler to toggle the selected status
150
+ wrapper.addEventListener( 'keypress', function ( event ) {
151
+
152
+ var is_action_key = event.keyCode === 32 || event.keyCode === 13;
153
+ var is_option = event.target.getAttribute( 'multi-index' );
154
+
155
+ if ( is_option && is_action_key ) {
156
+
157
+ // Prevent the default action to stop scrolling when space is pressed
158
+ event.preventDefault();
159
+ toggle_option( select, event );
160
+
161
+ }
162
+
163
+ });
164
+
165
+
166
+ wrapper.appendChild( non_selected );
167
+ wrapper.appendChild( selected );
168
+
169
+ wrapper.non_selected = non_selected;
170
+ wrapper.selected = selected;
171
+
172
+ select.wrapper = wrapper;
173
+
174
+ // Add multi.js wrapper after select element
175
+ select.parentNode.insertBefore( wrapper, select.nextSibling );
176
+
177
+
178
+ // Initialize selector with values from select element
179
+ refresh_select( select, settings );
180
+
181
+ // Refresh selector when select values change
182
+ select.addEventListener( 'change', function() {
183
+ refresh_select( select, settings );
184
+ });
185
+
186
+ };
187
+
188
+
189
+ return init;
190
+
191
+ }());
192
+
193
+
194
+ // Add jQuery wrapper if jQuery is present
195
+ if ( typeof jQuery !== 'undefined' ) {
196
+ (function($) {
197
+
198
+ $.fn.multi = function( settings ) {
199
+
200
+ settings = typeof settings !== 'undefined' ? settings : {};
201
+
202
+ return this.each( function() {
203
+
204
+ var $select = $(this);
205
+
206
+ multi( $select.get(0), settings );
207
+
208
+ });
209
+
210
+ }
211
+
212
+ })(jQuery);
213
+ }
assets/multi/multi.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ /*! multi.js 14-04-2017 */
2
+ var multi=function(){var a=function(a,b){var c=document.createEvent("HTMLEvents");c.initEvent(a,!1,!0),b.dispatchEvent(c)},b=function(b,c){var d=b.options[c.target.getAttribute("multi-index")];d.disabled||(d.selected=!d.selected,a("change",b))},c=function(a,b){if(a.wrapper.selected.innerHTML="",a.wrapper.non_selected.innerHTML="",a.wrapper.search)var c=a.wrapper.search.value;for(var d=0;d<a.options.length;d++){var e=a.options[d],f=e.value,g=e.textContent||e.innerText,h=document.createElement("a");if(h.tabIndex=0,h.className="item",h.innerHTML=g,h.setAttribute("role","button"),h.setAttribute("data-value",f),h.setAttribute("multi-index",d),e.disabled&&(h.className+=" disabled"),e.selected){h.className+=" selected";var i=h.cloneNode(!0);a.wrapper.selected.appendChild(i)}(!c||c&&g.toLowerCase().indexOf(c.toLowerCase())>-1)&&a.wrapper.non_selected.appendChild(h)}},d=function(a,d){if(d="undefined"!=typeof d?d:{},d.enable_search="undefined"==typeof d.enable_search||d.enable_search,d.search_placeholder="undefined"!=typeof d.search_placeholder?d.search_placeholder:"Search...",null==a.dataset.multijs&&"SELECT"==a.nodeName&&a.multiple){a.style.display="none",a.setAttribute("data-multijs",!0);var e=document.createElement("div");if(e.className="multi-wrapper",d.enable_search){var f=document.createElement("input");f.className="search-input",f.type="text",f.setAttribute("placeholder",d.search_placeholder),f.addEventListener("input",function(){c(a,d)}),e.appendChild(f),e.search=f}var g=document.createElement("div");g.className="non-selected-wrapper";var h=document.createElement("div");h.className="selected-wrapper",e.addEventListener("click",function(c){c.target.getAttribute("multi-index")&&b(a,c)}),e.addEventListener("keypress",function(c){var d=32===c.keyCode||13===c.keyCode,e=c.target.getAttribute("multi-index");e&&d&&(c.preventDefault(),b(a,c))}),e.appendChild(g),e.appendChild(h),e.non_selected=g,e.selected=h,a.wrapper=e,a.parentNode.insertBefore(e,a.nextSibling),c(a,d),a.addEventListener("change",function(){c(a,d)})}};return d}();"undefined"!=typeof jQuery&&!function(a){a.fn.multi=function(b){return b="undefined"!=typeof b?b:{},this.each(function(){var c=a(this);multi(c.get(0),b)})}}(jQuery);
cerber-lab.php CHANGED
@@ -102,21 +102,56 @@ function lab_get_reputation( $ip, $ask = true ) {
102
  $ip_id = cerber_get_id_ip( $ip );
103
  $lab_data = lab_api_send_request( array( 'ask_cerberlab' => array( $ip_id => $ip ) ) );
104
 
105
- if ( ! $lab_data || empty( $lab_data['response'][ $ip_id ]['reputation'] ) ) {
106
  $reputation = LAB_IP_OK;
107
- $expires = time() + 3600;
 
 
108
  }
109
  else {
110
- $rep = $lab_data['response'][ $ip_id ]['reputation'];
 
 
 
 
 
 
 
 
 
 
 
 
111
  $reputation = absint( $rep['value'] );
112
  $expires = time() + absint( $rep['ttl'] );
113
  }
114
 
115
  $wpdb->query( 'INSERT INTO ' . CERBER_LAB_IP_TABLE . ' (ip, reputation, expires) VALUES ("' . $ip . '",' . $reputation . ',' . $expires . ')' );
 
 
 
 
 
116
 
117
  return $reputation;
118
  }
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
  /**
122
  * Send request to a Cerber Lab node.
@@ -143,6 +178,7 @@ function lab_api_send_request($workload = array()) {
143
  'workload' => $workload,
144
  'push' => $push,
145
  'lang' => get_bloginfo( 'language' ),
 
146
  'version' => CERBER_VER,
147
  );
148
 
@@ -483,57 +519,70 @@ function cerber_push_lab() {
483
  set_transient( '_cerberpush_', 1, LAB_INTERVAL );
484
  }
485
 
486
- function lab_get_key($regenerate = false){
487
- $key = get_site_option( '_cerberkey_' );
488
- if ($regenerate || !$key || !is_array($key)){
489
- if (is_multisite()){
 
 
 
 
 
 
490
  $home = network_home_url();
491
- }
492
- else {
493
  $home = home_url();
494
  }
495
  if ( $host = parse_url( $home, PHP_URL_HOST ) ) {
496
  $site_id = md5( $host );
497
- }
498
- else {
499
  $site_id = md5( $home );
500
  }
501
  $new = array( $site_id, time() );
502
- if (isset($key[2])) $new[2] = $key[2];
 
 
 
 
503
  update_site_option( '_cerberkey_', $new );
504
  }
 
505
  return $key;
506
  }
507
 
508
  function lab_update_key( $lic, $expires = 0 ) {
509
  $key = lab_get_key();
510
- $key[2] = strtoupper($lic);
511
- $key[3] = absint($expires);
512
  update_site_option( '_cerberkey_', $key );
 
513
  }
514
 
515
- function lab_validate_key( $lic = '' ) {
 
516
  $key = lab_get_key();
517
- if (!$lic){
518
- if (empty($key[2])) return false;
 
 
519
  $lic = $key[2];
520
  }
 
521
  $request = array( 'key' => $key, 'validate' => $lic );
522
- $i = LAB_NODE_MAX;
523
- while ( !( $ret = lab_send_request( $request ) ) && $i > 0 ) {
524
- $i--;
525
  }
526
 
527
- if (!$ret) return false;
528
-
529
- $expires = 0;
530
- if ( ! empty( $ret['response']['expires_gmt'] ) ) {
531
- $expires = absint($ret['response']['expires_gmt']);
532
  }
533
 
 
 
534
  lab_update_key($lic, $expires);
535
 
536
- if ( !$expires ) {
537
  return false;
538
  }
539
 
@@ -543,6 +592,18 @@ function lab_validate_key( $lic = '' ) {
543
  return date_i18n( $df, $gmt_offset + $expires );
544
  }
545
 
 
 
 
 
 
 
 
 
 
 
 
 
546
  /**
547
  * Opt in for the connection to Cerber Lab
548
  *
@@ -615,4 +676,136 @@ function lab_user_opt_in( $button = '' ) {
615
  if ( $a ) {
616
  update_site_option( '_lab_o' . 'pt_in_', $a );
617
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
618
  }
102
  $ip_id = cerber_get_id_ip( $ip );
103
  $lab_data = lab_api_send_request( array( 'ask_cerberlab' => array( $ip_id => $ip ) ) );
104
 
105
+ if ( ! $lab_data || empty( $lab_data['response']['payload'][ $ip_id ]['reputation'] ) ) {
106
  $reputation = LAB_IP_OK;
107
+ $ip_data = array();
108
+ $ip_data['reputation']['value'] = $reputation;
109
+ $ip_data['reputation']['ttl'] = 600;
110
  }
111
  else {
112
+ $reputation = absint( $lab_data['response']['payload'][ $ip_id ]['reputation']['value'] );
113
+ $ip_data = $lab_data['response']['payload'][ $ip_id ];
114
+ }
115
+
116
+ lab_reputation_update($ip , $ip_data);
117
+
118
+ /*
119
+ if ( ! $lab_data || empty( $lab_data['response']['payload'][ $ip_id ]['reputation'] ) ) {
120
+ $reputation = LAB_IP_OK;
121
+ $expires = time() + 600;
122
+ }
123
+ else {
124
+ $rep = $lab_data['response']['payload'][ $ip_id ]['reputation'];
125
  $reputation = absint( $rep['value'] );
126
  $expires = time() + absint( $rep['ttl'] );
127
  }
128
 
129
  $wpdb->query( 'INSERT INTO ' . CERBER_LAB_IP_TABLE . ' (ip, reputation, expires) VALUES ("' . $ip . '",' . $reputation . ',' . $expires . ')' );
130
+ */
131
+
132
+ if ( ! empty( $lab_data['response']['payload'][ $ip_id ]['network']['geo'] ) ) {
133
+ lab_geo_update($ip, $lab_data['response']['payload'][ $ip_id ]);
134
+ }
135
 
136
  return $reputation;
137
  }
138
 
139
+ function lab_reputation_update( $ip, $ip_data ) {
140
+ global $wpdb;
141
+
142
+ if ( empty( $ip_data['reputation'] ) ) {
143
+ return;
144
+ }
145
+
146
+ if ( ! $ip = filter_var( $ip, FILTER_VALIDATE_IP ) ) {
147
+ return;
148
+ }
149
+
150
+ $reputation = absint( $ip_data['reputation']['value'] );
151
+ $expires = time() + absint( $ip_data['reputation']['ttl'] );
152
+
153
+ $wpdb->query( 'INSERT INTO ' . CERBER_LAB_IP_TABLE . ' (ip, reputation, expires) VALUES ("' . $ip . '",' . $reputation . ',' . $expires . ')' );
154
+ }
155
 
156
  /**
157
  * Send request to a Cerber Lab node.
178
  'workload' => $workload,
179
  'push' => $push,
180
  'lang' => get_bloginfo( 'language' ),
181
+ 'multi' => is_multisite(),
182
  'version' => CERBER_VER,
183
  );
184
 
519
  set_transient( '_cerberpush_', 1, LAB_INTERVAL );
520
  }
521
 
522
+ function lab_get_key( $regenerate = false, $nocache = false) {
523
+ static $key = null;
524
+
525
+ if ( ! isset( $key ) || $nocache ) {
526
+ $key = get_site_option( '_cerberkey_' );
527
+ }
528
+
529
+ if ( $regenerate || ! $key || ! is_array( $key ) ) {
530
+
531
+ if ( is_multisite() ) {
532
  $home = network_home_url();
533
+ } else {
 
534
  $home = home_url();
535
  }
536
  if ( $host = parse_url( $home, PHP_URL_HOST ) ) {
537
  $site_id = md5( $host );
538
+ } else {
 
539
  $site_id = md5( $home );
540
  }
541
  $new = array( $site_id, time() );
542
+ if ( isset( $key[2] ) ) {
543
+ $new[2] = $key[2];
544
+ }
545
+ $key = $new;
546
+
547
  update_site_option( '_cerberkey_', $new );
548
  }
549
+
550
  return $key;
551
  }
552
 
553
  function lab_update_key( $lic, $expires = 0 ) {
554
  $key = lab_get_key();
555
+ $key[2] = strtoupper( $lic );
556
+ $key[3] = absint( $expires );
557
  update_site_option( '_cerberkey_', $key );
558
+ lab_get_key( false, true ); // refresh the static cache
559
  }
560
 
561
+ function lab_validate_lic( $lic = '' ) {
562
+
563
  $key = lab_get_key();
564
+ if ( ! $lic ) {
565
+ if ( empty( $key[2] ) ) {
566
+ return false;
567
+ }
568
  $lic = $key[2];
569
  }
570
+
571
  $request = array( 'key' => $key, 'validate' => $lic );
572
+ $i = LAB_NODE_MAX;
573
+ while ( ! ( $ret = lab_send_request( $request ) ) && $i > 0 ) {
574
+ $i --;
575
  }
576
 
577
+ if ( !$ret || empty( $ret['response']['expires_gmt'] ) ) {
578
+ return false;
 
 
 
579
  }
580
 
581
+ $expires = absint( $ret['response']['expires_gmt'] );
582
+
583
  lab_update_key($lic, $expires);
584
 
585
+ if ( !$expires || time() > $expires ) {
586
  return false;
587
  }
588
 
592
  return date_i18n( $df, $gmt_offset + $expires );
593
  }
594
 
595
+ function lab_lab() {
596
+ $key = lab_get_key();
597
+ if ( empty( $key[2] ) || empty( $key[3] ) ) {
598
+ return false;
599
+ }
600
+ if ( time() > $key[3] ) {
601
+ return false;
602
+ }
603
+
604
+ return $key[3];
605
+ }
606
+
607
  /**
608
  * Opt in for the connection to Cerber Lab
609
  *
676
  if ( $a ) {
677
  update_site_option( '_lab_o' . 'pt_in_', $a );
678
  }
679
+ }
680
+
681
+
682
+ /**
683
+ * Return country ISO code
684
+ *
685
+ * @param $ip array|string IP address(es)
686
+ * @param bool $cache_only Use local cache. If false and an IP is not in the cache, sends a request to the Cerber Lab GEO service.
687
+ *
688
+ * @return array|string|bool A list of country codes if a list of IPs provided, otherwise a string with the country code.
689
+ */
690
+ function lab_get_country( $ip, $cache_only = true ) {
691
+ global $wpdb, $remote_country;
692
+
693
+ if (!lab_lab()){
694
+ return false;
695
+ }
696
+
697
+ if ( filter_var( $ip, FILTER_VALIDATE_IP ) ) {
698
+ $ip_id = cerber_get_id_ip( $ip );
699
+ if ( isset( $remote_country[ $ip_id ] ) ) {
700
+ return $remote_country[ $ip_id ];
701
+ }
702
+ }
703
+
704
+ if ( ! is_array( $ip ) ) {
705
+ $ip_list = array( $ip );
706
+ }
707
+ else {
708
+ $ip_list = $ip;
709
+ }
710
+
711
+ $ret = array();
712
+ $ask = array();
713
+
714
+ foreach ( $ip_list as $item ) {
715
+ if ( ! filter_var( $item, FILTER_VALIDATE_IP ) ) {
716
+ continue;
717
+ }
718
+ if ( cerber_is_ipv4( $item ) ) {
719
+ $ip_long = ip2long($item);
720
+ $where = ' WHERE ip_long_begin <= ' . $ip_long . ' AND ' . $ip_long . ' <= ip_long_end';
721
+ }
722
+ else {
723
+ $where = ' WHERE ip = "' . $item . '"';
724
+ }
725
+ $country = $wpdb->get_var( 'SELECT country FROM ' . CERBER_LAB_NET_TABLE . $where );
726
+
727
+ $ip_id = cerber_get_id_ip( $item );
728
+ if ( $country ) {
729
+ $ret[ $ip_id ] = $country;
730
+ }
731
+ elseif (!$cache_only) {
732
+ $ask[ $ip_id ] = $item;
733
+ }
734
+ }
735
+
736
+ if ( !$cache_only && $ask ) {
737
+ $lab_data = lab_api_send_request( array( 'ask_cerberlab' => $ask ) );
738
+
739
+ if ( ! empty( $lab_data['response']['payload'] ) ) {
740
+ foreach ( $lab_data['response']['payload'] as $ip_id => $ip_data ) {
741
+ //foreach ( $ask as $ip_id => $ip_ask ) {
742
+ //if ( ! empty( $lab_data['response']['payload'][ $ip_id ] ) ) {
743
+ //$ip_data = $lab_data['response']['payload'][ $ip_id ];
744
+ lab_geo_update( $ip_data['ip'], $ip_data );
745
+ lab_reputation_update($ip_data['ip'] , $ip_data);
746
+ $ret[ $ip_id ] = $ip_data['network']['geo']['country_iso'];
747
+ //}
748
+ }
749
+ }
750
+
751
+ }
752
+
753
+ if ( ! is_array( $ip ) && ! empty( $ret ) ) {
754
+ return current($ret);
755
+ }
756
+
757
+ return $ret;
758
+
759
+ }
760
+
761
+ /**
762
+ * Update local GEO cache with a given network data
763
+ *
764
+ * @param string $ip IP address which country we asked for
765
+ * @param array $data IP and its network data
766
+ */
767
+ function lab_geo_update( $ip = '', $data = array() ) {
768
+ global $wpdb, $remote_country;
769
+ if ( empty( $data['network']['geo'] ) ) {
770
+ return;
771
+ }
772
+
773
+ $code = substr( $data['network']['geo']['country_iso'], 0, 3 );
774
+ $remote_country[ cerber_get_id_ip( $ip ) ] = $code;
775
+ $expires = time() + absint($data['network']['geo']['country_expires']);
776
+ $begin = intval($data['network']['begin']);
777
+ $end = intval($data['network']['end']);
778
+
779
+ if ( cerber_is_ipv4( $ip ) ) {
780
+ $where = ' WHERE ip_long_begin = ' . $begin . ' AND ip_long_end = ' . $end;
781
+ //$ip = '';
782
+ }
783
+ else {
784
+ $where = ' WHERE ip = "' . $ip . '"';
785
+ }
786
+
787
+ $exists = $wpdb->get_var( 'SELECT country FROM ' . CERBER_LAB_NET_TABLE . $where );
788
+
789
+ if ($exists){
790
+ $wpdb->query( 'UPDATE ' . CERBER_LAB_NET_TABLE . " SET expires = $expires, country = '$code' $where");
791
+ }
792
+ else {
793
+ $wpdb->query( 'INSERT INTO ' . CERBER_LAB_NET_TABLE . " (ip, ip_long_begin, ip_long_end, country, expires) VALUES ('{$ip}',{$begin},{$end},'{$code}',{$expires})" );
794
+ }
795
+
796
+ // The list of names of the countries
797
+
798
+ if ( ! empty( $data['network']['geo']['country'] ) ) {
799
+ foreach ( $data['network']['geo']['country'] as $locale => $name ) {
800
+ $where = ' WHERE country = "' . $code . '" AND locale = "' . $locale . '"';
801
+ $exists = $wpdb->get_var( 'SELECT country FROM ' . CERBER_GEO_TABLE . $where );
802
+
803
+ if ( ! $exists ) {
804
+ $wpdb->query( 'INSERT INTO ' . CERBER_GEO_TABLE . ' (country, locale, country_name) VALUES ("' . $code . '","' . $locale . '","' . $name . '")' );
805
+ }
806
+ else {
807
+ //$wpdb->query( 'UPDATE ' . CERBER_GEO_TABLE . ' SET country_name = "' . $name . '"' . $where );
808
+ }
809
+ }
810
+ }
811
  }
cerber-news.php CHANGED
@@ -91,6 +91,10 @@ function cerber_push_the_news( $version ) {
91
  $news['5.1'][] = 'Antispam and anti-bot engine for contact and other forms. Cerber antispam and bot detection engine now protects all forms on a website. It’s compatible with virtually any form. Tested with Caldera Forms, Gravity Forms, Contact Form 7, Ninja Forms, Formidable Forms, Fast Secure Contact Form, Contact Form by WPForms.';
92
  $news['5.1'][] = 'Portuguese of Portugal translation has been added, thanks to Helderk.';
93
 
 
 
 
 
94
  if ( ! empty( $news[ $version ] ) ) {
95
  //$text = '<h3>What\'s new in WP Cerber '.$version.'</h3>';
96
 
91
  $news['5.1'][] = 'Antispam and anti-bot engine for contact and other forms. Cerber antispam and bot detection engine now protects all forms on a website. It’s compatible with virtually any form. Tested with Caldera Forms, Gravity Forms, Contact Form 7, Ninja Forms, Formidable Forms, Fast Secure Contact Form, Contact Form by WPForms.';
92
  $news['5.1'][] = 'Portuguese of Portugal translation has been added, thanks to Helderk.';
93
 
94
+ $news['5.5'][] = 'White list for the <a href="http://wpcerber.com/antispam-for-wordpress-contact-forms/">WordPress anti-spam engine</a>. It allows creating a list of exceptions by specifying a string to search it in a request URI.';
95
+ $news['5.5'][] = 'White list for REST API requests. It allows creating a list of namespace exceptions if REST API is disabled.';
96
+ $news['5.5'][] = 'Disable access to user data via REST API and stop REST API user enumeration.';
97
+
98
  if ( ! empty( $news[ $version ] ) ) {
99
  //$text = '<h3>What\'s new in WP Cerber '.$version.'</h3>';
100
 
cerber-tools.php CHANGED
@@ -107,8 +107,13 @@ function cerber_export(){
107
  if (!current_user_can('manage_options')) wp_die('Error!');
108
  $p = cerber_plugin_data();
109
  $data = array('cerber_version' => $p['Version'],'home'=> get_home_url(),'date'=>date('d M Y H:i:s'));
110
- if (!empty($_GET['exportset'])) $data ['options'] = cerber_get_options(); // @since 2.0
111
- if (!empty($_GET['exportacl'])) $data ['acl'] = cerber_acl_all('ip,tag,comments');
 
 
 
 
 
112
  $file = json_encode($data);
113
  $file .= '==/'.strlen($file).'/'.crc32($file).'/EOF';
114
  header($_SERVER["SERVER_PROTOCOL"].' 200 OK');
@@ -139,12 +144,15 @@ function cerber_import(){
139
  if ($sys[3] == 'EOF' && crc32($data) == $sys[2] && ($data = json_decode($data, true))) {
140
 
141
  if ($_POST['importset'] && $data['options'] && !empty($data['options']) && is_array($data['options'])) {
142
- $data['options']['loginpath'] = urldecode($data['options']['loginpath']); // needed to work filter cerber_sanitize_options()
143
  if ($data['home'] != get_home_url()) {
144
  $data['options']['sitekey'] = $wp_cerber->getSettings('sitekey');
145
  $data['options']['secretkey'] = $wp_cerber->getSettings('secretkey');
146
  }
147
  cerber_save_options($data['options']); // @since 2.0
 
 
 
148
  }
149
 
150
  if ($_POST['importacl'] && $data['acl'] && is_array($data['acl']) && !empty($data['acl'])) {
@@ -175,7 +183,7 @@ function cerber_import(){
175
  function cerber_show_diag(){
176
  ?>
177
  <!-- <h3 style="margin-top: 3em;">Diagnostic and maintenance</h3>
178
- <a href="#" onclick="toggle_visibility('diagnostic'); return false;">Show diagnostic information</a>
179
  -->
180
  <form id="diagnostic" style="margin-top: 2em;">
181
  <div class="diag-section">
@@ -206,6 +214,20 @@ function cerber_show_diag(){
206
  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>';
207
  ?>
208
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  </form>
210
  <script type="text/javascript">
211
  function toggle_visibility(id) {
@@ -224,11 +246,11 @@ function cerber_show_lic() {
224
  $valid = '';
225
  if ( ! empty( $key[2] ) ) {
226
  $lic = $key[2];
227
- if ( $expires = lab_validate_key( $lic ) ) {
228
  $valid = '<span style="color: green;">This key is valid until '.$expires.'</span>';
229
  }
230
  else {
231
- $valid = '<span style="color: red;">This key is invalid</span>';
232
  }
233
  }
234
  else {
@@ -241,10 +263,16 @@ function cerber_show_lic() {
241
  <tr>
242
  <th scope="row">License key for PRO version</th>
243
  <td>
244
- <input name="cerber_license" value="<?php echo $lic; ?>" size="<?php echo LAB_KEY_LENGTH; ?>" maxlength="<?php echo LAB_KEY_LENGTH; ?>" type="text">
245
  <?php echo '<p>'.$valid.'</p>'; ?>
246
  </td>
247
  </tr>
 
 
 
 
 
 
248
  <tbody>
249
  </table>
250
  <div style="padding-left: 220px">
107
  if (!current_user_can('manage_options')) wp_die('Error!');
108
  $p = cerber_plugin_data();
109
  $data = array('cerber_version' => $p['Version'],'home'=> get_home_url(),'date'=>date('d M Y H:i:s'));
110
+ if (!empty($_GET['exportset'])) {
111
+ $data ['options'] = cerber_get_options();
112
+ $data ['geo-rules'] = cerber_geo_rules();
113
+ }
114
+ if ( ! empty( $_GET['exportacl'] ) ) {
115
+ $data ['acl'] = cerber_acl_all( 'ip,tag,comments' );
116
+ }
117
  $file = json_encode($data);
118
  $file .= '==/'.strlen($file).'/'.crc32($file).'/EOF';
119
  header($_SERVER["SERVER_PROTOCOL"].' 200 OK');
144
  if ($sys[3] == 'EOF' && crc32($data) == $sys[2] && ($data = json_decode($data, true))) {
145
 
146
  if ($_POST['importset'] && $data['options'] && !empty($data['options']) && is_array($data['options'])) {
147
+ $data['options']['loginpath'] = urldecode($data['options']['loginpath']); // needed for filter cerber_sanitize_options()
148
  if ($data['home'] != get_home_url()) {
149
  $data['options']['sitekey'] = $wp_cerber->getSettings('sitekey');
150
  $data['options']['secretkey'] = $wp_cerber->getSettings('secretkey');
151
  }
152
  cerber_save_options($data['options']); // @since 2.0
153
+ if ( isset( $data['geo-rules'] ) ) {
154
+ update_site_option( 'geo_rule_set', $data['geo-rules'] );
155
+ }
156
  }
157
 
158
  if ($_POST['importacl'] && $data['acl'] && is_array($data['acl']) && !empty($data['acl'])) {
183
  function cerber_show_diag(){
184
  ?>
185
  <!-- <h3 style="margin-top: 3em;">Diagnostic and maintenance</h3>
186
+ <a href="javascript:void(0)" onclick="toggle_visibility('diagnostic'); return false;">Show diagnostic information</a>
187
  -->
188
  <form id="diagnostic" style="margin-top: 2em;">
189
  <div class="diag-section">
214
  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>';
215
  ?>
216
  </div>
217
+ <?php
218
+ $subs = get_site_option( '_cerber_subs' );
219
+ if ( $subs ) {
220
+ echo '
221
+ <div class="diag-section">
222
+ <h3>Subscriptions for notifications</h3>';
223
+ echo '<ol>';
224
+ foreach ( $subs as $hash => $sub ) {
225
+ echo '<li> '.$hash.' | <a href = "' .cerber_admin_link( 'activity' ).'&unsubscribeme='.$hash.'">'.__( 'Unsubscribe', 'wp-cerber' ).'</a></li>';
226
+ }
227
+ echo '</ol>';
228
+ echo '</div>';
229
+ }
230
+ ?>
231
  </form>
232
  <script type="text/javascript">
233
  function toggle_visibility(id) {
246
  $valid = '';
247
  if ( ! empty( $key[2] ) ) {
248
  $lic = $key[2];
249
+ if ( $expires = lab_validate_lic( $lic ) ) {
250
  $valid = '<span style="color: green;">This key is valid until '.$expires.'</span>';
251
  }
252
  else {
253
+ $valid = '<span style="color: red;">This license key is invalid or expired</span>';
254
  }
255
  }
256
  else {
263
  <tr>
264
  <th scope="row">License key for PRO version</th>
265
  <td>
266
+ <input name="cerber_license" style="font-family: Consolas, Monaco, monospace;" value="<?php echo $lic; ?>" size="<?php echo LAB_KEY_LENGTH; ?>" maxlength="<?php echo LAB_KEY_LENGTH; ?>" type="text">
267
  <?php echo '<p>'.$valid.'</p>'; ?>
268
  </td>
269
  </tr>
270
+ <tr>
271
+ <th scope="row">Site ID</th>
272
+ <td>
273
+ <?php echo '<p style="font-family: Consolas, Monaco, monospace;">'.$key[0].'</p>'; ?>
274
+ </td>
275
+ </tr>
276
  <tbody>
277
  </table>
278
  <div style="padding-left: 220px">
common.php CHANGED
@@ -52,6 +52,9 @@ function cerber_admin_link($tab = '', $args = array()){
52
  elseif ( in_array( $tab, array( 'imex', 'diagnostic', 'license' ) ) ) {
53
  $page = 'cerber-tools';
54
  }
 
 
 
55
  else $page = 'cerber-security';
56
 
57
  if (!is_multisite()) {
@@ -174,7 +177,7 @@ function cerber_pb_send($title, $body){
174
  return $curl_error;
175
  }
176
  /**
177
- * Just test is cURL available
178
  */
179
  function cerber_check_environment(){
180
  if (!in_array('curl', get_loaded_extensions())) {
@@ -309,17 +312,81 @@ function recursive_search_key($array, $needle){
309
  * @since 3.0
310
  */
311
  function cerber_is_rest_url(){
 
 
312
  if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
313
  return true;
314
  }
 
 
 
 
 
315
  if (false !== strpos($_SERVER['REQUEST_URI'], rest_get_url_prefix()) || false !== strpos($_SERVER['REQUEST_URI'], '?rest_route=')){
316
  if (0 === strpos(get_home_url().urldecode($_SERVER['REQUEST_URI']),get_rest_url())) {
 
317
  return true;
318
  }
319
  }
 
 
320
  return false;
321
  }
322
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
  /**
324
  * Return the last portion of the requested URI.
325
  *
@@ -328,11 +395,14 @@ function cerber_is_rest_url(){
328
  * @return bool|string
329
  */
330
  function cerber_get_last_in_uri( $check_php = false ) {
331
- $ret = substr( strrchr( $_SERVER['REQUEST_URI'], '/' ), 1 );
 
332
  if ( $pos = strpos( $ret, '?' ) ) {
333
  $ret = substr( $ret, 0, $pos );
334
  }
 
335
  $ret = rtrim( $ret, '/' );
 
336
 
337
  if ( $check_php ) {
338
  if ( strtolower( substr( $ret, - 4 ) ) != '.php' ) {
@@ -366,12 +436,15 @@ function cerber_get_labels($type = 'activity'){
366
  $labels[12]=__('Citadel activated!','wp-cerber');
367
  $labels[16]=__('Spam comment denied','wp-cerber');
368
  $labels[17]=__('Spam form submission denied','wp-cerber');
 
 
369
 
370
  // Cerber status // TODO: should be separated as another list ---------
371
- $labels[13]=__('Locked out','wp-cerber');
372
- $labels[14]=__('IP blacklisted','wp-cerber');
373
  // @since 4.9
374
- $labels[15]=__('by Cerber Lab','wp-cerber');
 
375
  // --------------------------------------------------------------
376
 
377
  // Other actions
@@ -389,7 +462,23 @@ function cerber_get_labels($type = 'activity'){
389
  $labels[53]=__('Attempt to log in denied','wp-cerber');
390
  $labels[54]=__('Attempt to register denied','wp-cerber');
391
 
 
 
 
392
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
393
  return $labels;
394
  }
395
 
52
  elseif ( in_array( $tab, array( 'imex', 'diagnostic', 'license' ) ) ) {
53
  $page = 'cerber-tools';
54
  }
55
+ elseif ( in_array( $tab, array( 'geo' ) ) ) {
56
+ $page = 'cerber-rules';
57
+ }
58
  else $page = 'cerber-security';
59
 
60
  if (!is_multisite()) {
177
  return $curl_error;
178
  }
179
  /**
180
+ * Just test if cURL available
181
  */
182
  function cerber_check_environment(){
183
  if (!in_array('curl', get_loaded_extensions())) {
312
  * @since 3.0
313
  */
314
  function cerber_is_rest_url(){
315
+ static $cache = null;
316
+
317
  if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
318
  return true;
319
  }
320
+
321
+ if (isset($cache)) {
322
+ return $cache;
323
+ }
324
+
325
  if (false !== strpos($_SERVER['REQUEST_URI'], rest_get_url_prefix()) || false !== strpos($_SERVER['REQUEST_URI'], '?rest_route=')){
326
  if (0 === strpos(get_home_url().urldecode($_SERVER['REQUEST_URI']),get_rest_url())) {
327
+ $cache = true;
328
  return true;
329
  }
330
  }
331
+
332
+ $cache = false;
333
  return false;
334
  }
335
 
336
+ /**
337
+ * Is requested REST API namespace is whitelisted
338
+ *
339
+ * @return bool
340
+ */
341
+ function cerber_is_route_allowed() {
342
+ global $wp_cerber;
343
+
344
+ $list = $wp_cerber->getSettings( 'restwhite' );
345
+
346
+ if ( ! is_array( $list ) || empty( $list ) ) {
347
+ return false;
348
+ }
349
+
350
+ $rest_path = crb_get_rest_path();
351
+
352
+ $namespace = substr( $rest_path, 0, strpos( $rest_path, '/' ) );
353
+
354
+ foreach ( $list as $exception ) {
355
+ if ($exception == $namespace) {
356
+ return true;
357
+ }
358
+ }
359
+
360
+ return false;
361
+ }
362
+
363
+ function cerber_is_route_blocked() {
364
+ global $wp_cerber;
365
+ if ( $wp_cerber->getSettings( 'stopenum' ) ) {
366
+ $path = explode( '/', crb_get_rest_path() );
367
+ if ( $path && count( $path ) > 2 && $path[0] == 'wp' && $path[2] == 'users' ) {
368
+ return true;
369
+ }
370
+ }
371
+ return false;
372
+ }
373
+
374
+ function crb_get_rest_path() {
375
+ static $ret;
376
+ if ( isset( $ret ) ) {
377
+ return $ret;
378
+ }
379
+ if ( get_option( 'permalink_structure' ) ) {
380
+ $pos = strlen( rest_get_url_prefix() ) + 2;
381
+ $ret = substr( $_SERVER['REQUEST_URI'], $pos );
382
+ }
383
+ else {
384
+ $ret = ltrim( $_REQUEST['rest_route'], '/' );
385
+ }
386
+
387
+ return $ret;
388
+ }
389
+
390
  /**
391
  * Return the last portion of the requested URI.
392
  *
395
  * @return bool|string
396
  */
397
  function cerber_get_last_in_uri( $check_php = false ) {
398
+ $ret = $_SERVER['REQUEST_URI'];
399
+
400
  if ( $pos = strpos( $ret, '?' ) ) {
401
  $ret = substr( $ret, 0, $pos );
402
  }
403
+
404
  $ret = rtrim( $ret, '/' );
405
+ $ret = substr( strrchr( $ret, '/' ), 1 );
406
 
407
  if ( $check_php ) {
408
  if ( strtolower( substr( $ret, - 4 ) ) != '.php' ) {
436
  $labels[12]=__('Citadel activated!','wp-cerber');
437
  $labels[16]=__('Spam comment denied','wp-cerber');
438
  $labels[17]=__('Spam form submission denied','wp-cerber');
439
+ $labels[18]=__('Form submission denied','wp-cerber');
440
+ $labels[19]=__('Comment denied','wp-cerber');
441
 
442
  // Cerber status // TODO: should be separated as another list ---------
443
+ //$labels[13]=__('Locked out','wp-cerber');
444
+ //$labels[14]=__('IP blacklisted','wp-cerber');
445
  // @since 4.9
446
+ //$labels[15]=__('by Cerber Lab','wp-cerber');
447
+ //$labels[15]=__('Malicious activity detected','wp-cerber');
448
  // --------------------------------------------------------------
449
 
450
  // Other actions
462
  $labels[53]=__('Attempt to log in denied','wp-cerber');
463
  $labels[54]=__('Attempt to register denied','wp-cerber');
464
 
465
+ $labels[70]=__('Request to REST API denied','wp-cerber');
466
+ $labels[71]=__('XML-RPC request denied','wp-cerber');
467
+
468
  }
469
+ elseif ( $type == 'status' ) {
470
+ $labels[11] = __( 'Bot detected', 'wp-cerber' );
471
+ $labels[12] = __( 'Citadel mode is active', 'wp-cerber' );
472
+ $labels[13] = __( 'Locked out', 'wp-cerber' );
473
+ $labels[14] = __( 'IP blacklisted', 'wp-cerber' );
474
+ // @since 4.9
475
+ //$labels[15]=__('by Cerber Lab','wp-cerber');
476
+ $labels[15] = __( 'Malicious activity detected', 'wp-cerber' );
477
+ if ( lab_lab() ) {
478
+ $labels[16] = __( 'Blocked by country rule', 'wp-cerber' );
479
+ }
480
+ }
481
+
482
  return $labels;
483
  }
484
 
dashboard.php CHANGED
@@ -68,7 +68,7 @@ function cerber_show_lockouts($args = array(), $echo = true){
68
  if (isset($ip_info['hostname'])) $hostname = $ip_info['hostname'];
69
  else {
70
  $ip_id = cerber_get_id_ip($row->ip);
71
- $hostname = '<img data-ip-id="'.$ip_id .'" class="crb-no-hn" src="'.$assets_url.'ajax-loader-ip.gif" />'."\n";
72
  }
73
 
74
  $list[]='<td>'.$ip.'</td><td>'.$hostname.'</td><td>'.cerber_date($row->block_until).'</td><td>'.$row->reason.'</td><td><a href="'.wp_nonce_url(add_query_arg(array('lockdelete'=>$row->ip)),'control','cerber_nonce').'">'.__('Remove','wp-cerber').'</a></td>';
@@ -103,7 +103,12 @@ function cerber_acl_form(){
103
  cerber_acl_get_table('W');
104
  echo '<h2>'.__('Black IP Access List','wp-cerber').'</h2><p><span style="color:red;" class="dashicons-before dashicons-thumbs-down"></span> '.__('Nobody can log in or register from these IPs','wp-cerber').' - <a target="_blank" href="http://wpcerber.com/using-ip-access-lists-to-protect-wordpress/">Know more</a></p>'.
105
  cerber_acl_get_table('B');
106
- echo '<p><b><span class="dashicons-before dashicons-star-filled"></span> '.__('Your IP','wp-cerber').': '.$wp_cerber->getRemoteIp().'</b></p>';
 
 
 
 
 
107
  echo '<h4 style="margin-top: 2em;"><span class="dashicons-before dashicons-info"></span> Possible values for entries in the access lists with examples</h4>
108
  <p>Single IPv6 address: <b>2001:0db8:85a3:0000:0000:8a2e:0370:7334</b>
109
  <p>Single IPv4 address: <b>192.168.5.22</b>
@@ -186,7 +191,8 @@ function cerber_admin_ajax() {
186
  if (!current_user_can('manage_options')) return;
187
  $response = array();
188
  if (isset($_REQUEST['acl_delete'])){
189
- check_ajax_referer('delete-ip','ajax_nonce');
 
190
  $ip = $_REQUEST['acl_delete'];
191
  if (!$ip = cerber_parse_ip($ip)) wp_die();
192
  if (cerber_acl_remove($ip)) {
@@ -195,17 +201,61 @@ function cerber_admin_ajax() {
195
  $response['deleted_ip'] = $deleted;
196
  }
197
  else $response['error'] = 'Unable to delete';
 
198
  }
199
- elseif (isset($_REQUEST['get_hostnames'])){
200
- $list = array_unique($_REQUEST['get_hostnames']);
201
- foreach ($list as $ip_id) {
202
- $ip = cerber_get_ip_id($ip_id);
203
- $ip_info = cerber_get_ip_info($ip);
204
- $response[$ip_id] = $ip_info['hostname'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  }
 
206
  }
207
  elseif (isset($_REQUEST['dismiss_info'])){
208
- if (isset($_REQUEST['button_id']) && ($_REQUEST['button_id'] == 'lab_ok' || $_REQUEST['button_id'] == 'lab_no')){
 
209
  lab_user_opt_in($_REQUEST['button_id']);
210
  }
211
  else update_site_option('cerber_admin_info','');
@@ -243,7 +293,7 @@ function cerber_get_ip_info($ip, $cache_only = false){
243
 
244
 
245
  /*
246
- Admin's actions with GET requests are handled here
247
  */
248
  add_action('admin_init','cerber_admin_request');
249
  function cerber_admin_request(){
@@ -304,7 +354,10 @@ function cerber_admin_request(){
304
  }
305
 
306
  if ( $_SERVER['REQUEST_METHOD'] == 'POST') {
307
- if ( isset( $_POST['cerber_license'] ) ) {
 
 
 
308
  $lic = preg_replace( "/[^A-Z0-9]/i", '', $_POST['cerber_license'] );
309
  if ( !empty($lic) && strlen( $lic ) != LAB_KEY_LENGTH ) {
310
  return;
@@ -395,9 +448,11 @@ function cerber_export_activity() {
395
  *
396
  */
397
  function cerber_show_activity($args = array(), $echo = true){
398
- global $wpdb, $wp_cerber, $wp_roles;
399
 
400
  $labels = cerber_get_labels('activity');
 
 
401
  $base_url = cerber_admin_link('activity');
402
  $right_links = '';
403
  $export_link = '';
@@ -415,27 +470,30 @@ function cerber_show_activity($args = array(), $echo = true){
415
  $assets_url = plugin_dir_url( CERBER_FILE ) . 'assets/';
416
  $list = array();
417
  $roles = $wp_roles->roles;
 
 
418
 
419
  foreach ($rows as $row) {
420
 
 
 
421
  $activity = '<span class="crb-activity actv' . $row->activity . '">'.$labels[ $row->activity ].'</span>';
422
  /*
423
  if ($row->activity == 50 ) {
424
  $activity .= ' <b>'.htmlspecialchars($row->user_login).'</b>';
425
  }*/
426
 
427
- if ($row->details) {
428
- $details = explode('|',$row->details);
429
- if (!empty($details[0])) {
430
- $activity .= ' <span class = "act-details">'.$labels[$details[0]].'</span>';
431
  }
432
  //elseif ($row->activity == 50 && $details[4]) $activity .= ' '.$details[4];
433
 
434
- if (empty($args['no_details'])) {
435
- if ( isset( $details[4] ) && ( $row->activity < 10 || $row->activity > 12 ) ) {
436
- $activity .= '<p class="act-url">URL: ' . $details[4] . '</p>';
437
- }
438
  }
 
439
  }
440
 
441
 
@@ -473,8 +531,7 @@ function cerber_show_activity($args = array(), $echo = true){
473
  $ip_info = cerber_get_ip_info($row->ip,true);
474
  if (isset($ip_info['hostname'])) $hostname = $ip_info['hostname'];
475
  else {
476
- $ip_id = cerber_get_id_ip($row->ip);
477
- $hostname = '<img data-ip-id="'.$ip_id .'" class="crb-no-hn" src="'.$assets_url.'ajax-loader-ip.gif" />'."\n";
478
  }
479
 
480
  $tip='';
@@ -496,10 +553,47 @@ function cerber_show_activity($args = array(), $echo = true){
496
  $date = '<span title="'.$row->stamp.' / '.$row->session_id.' / '.$row->activity .'">'.cerber_date( $row->stamp ).'<span/>';
497
  }
498
 
499
- $list[] = '<td><div class="act-icon ip-acl' . $acl . ' ' . $block . '" title="' . $tip . '"></div>' . $ip . '</td><td>' . $hostname . '</td><td>' . $date . '</td><td>' . $activity . '</td><td>' . $name . '</td><td>' . $username . '</td>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
500
  }
501
 
502
- $titles = '<tr><th><div class="act-icon"></div>' . __( 'IP', 'wp-cerber' ) . '</th><th>' . __( 'Hostname', 'wp-cerber' ) . '</th><th>' . __( 'Date', 'wp-cerber' ) . '</th><th>' . __( 'Event', 'wp-cerber' ) . '</th><th>' . __( 'Local User', 'wp-cerber' ) . '</th><th>' . __( 'Username used', 'wp-cerber' ) . '</th></tr>';
 
503
  $table = '<table id="crb-activity" class="widefat crb-table cerber-margin"><thead>' . $titles . '</thead><tfoot>' . $titles . '</tfoot><tbody><tr>' . implode( '</tr><tr>', $list ) . '</tr></tbody></table>';
504
 
505
  if (empty($args['no_navi'])) $table .= cerber_page_navi($total, $per_page);
@@ -518,7 +612,7 @@ function cerber_show_activity($args = array(), $echo = true){
518
  if (empty($args['no_navi'])) {
519
 
520
  unset( $labels[13], $labels[14], $labels[15] );
521
- $labels = array( 0 => __( 'All activities', 'wp-cerber' ) ) + $labels;
522
 
523
  if (!empty($_GET['filter_activity']) && !is_array($_GET['filter_activity'])) {
524
  $selected = absint($_GET['filter_activity']);
@@ -613,6 +707,11 @@ function cerber_activity_query($args = array()){
613
  $search = '%'.$search.'%';
614
  $where[] = $wpdb->prepare('(log.ip LIKE %s OR log.user_login LIKE %s)', $search, $search);
615
  }
 
 
 
 
 
616
 
617
  if (!empty($where)) $where = 'WHERE '.implode(' AND ',$where);
618
  else $where = '';
@@ -745,6 +844,10 @@ function cerber_admin_menu() {
745
  add_action( 'load-' . $hook, "cerber_screen_options" );
746
  add_submenu_page( 'cerber-security', __( 'Cerber Dashboard', 'wp-cerber' ), __( 'Dashboard' ), 'manage_options', 'cerber-security', 'cerber_settings_page' );
747
 
 
 
 
 
748
  add_submenu_page( 'cerber-security', __( 'Cerber antispam settings', 'wp-cerber' ), __( 'Antispam', 'wp-cerber' ), 'manage_options', 'cerber-recaptcha', 'cerber_recaptcha_page' );
749
  add_submenu_page( 'cerber-security', __( 'Cerber tools', 'wp-cerber' ), __( 'Tools', 'wp-cerber' ), 'manage_options', 'cerber-tools', 'cerber_tools_page' );
750
 
@@ -765,27 +868,35 @@ function cerber_admin_bar( $wp_admin_bar ) {
765
  /*
766
  Check if currently displayed page is a Cerber admin dashboard page with optional checking a set of GET params
767
  */
768
- function cerber_is_admin_page($force = true, $params = array()){
769
 
770
- if (!is_admin()) return false;
 
 
771
 
772
  $ret = false;
773
 
774
- if (isset($_GET['page']) && false !== strpos($_GET['page'],'cerber-')) {
775
  $ret = true;
776
- if ($params) {
777
- foreach ( $params as $param => $value) {
778
- if (!isset($_GET[$param]) || $_GET[$param] != $value){
779
  $ret = false;
780
  break;
781
  }
782
  }
783
  }
784
  }
785
- if (!$force || $ret) return $ret;
 
 
786
 
787
- if (!$screen = get_current_screen()) return false;
788
- if ($screen->base == 'plugins') return true;
 
 
 
 
789
  /*
790
  if ($screen->parent_base == 'options-general') return true;
791
  if ($screen->parent_base == 'settings') return true;
@@ -794,7 +905,7 @@ function cerber_is_admin_page($force = true, $params = array()){
794
  }
795
 
796
  /*
797
- Add custom columns to the Users screen
798
  */
799
  add_filter('manage_users_columns' , 'cerber_u_columns');
800
  function cerber_u_columns($columns) {
@@ -822,17 +933,23 @@ function cerber_show_u_columns($value, $column, $user_id) {
822
  else $ret = 0;
823
  break;
824
  case 'cbla' :
825
- $ret = $wpdb->get_var('SELECT MAX(stamp) FROM '.CERBER_LOG_TABLE.' WHERE user_id = '.$user_id);
826
- if ($ret) {
 
827
  $act_link = cerber_admin_link('activity');
828
- $ret = '<a href="'.$act_link.'&filter_user='.$user_id.'">'.cerber_date($ret).'</a>';
 
 
 
 
 
829
  }
830
  else $ret=__('Never','wp-cerber');
831
  break;
832
  case 'cbfl' :
833
  $act_link = cerber_admin_link('activity');
834
  $u=get_userdata($user_id);
835
- $failed = $wpdb->get_var('SELECT count(user_id) FROM '.CERBER_LOG_TABLE.' WHERE user_login = \''.$u->user_login.'\' AND activity = 7 AND stamp > ' . (time() - 24 * 3600));
836
  $ret = '<a href="'.$act_link.'&filter_login='.$u->user_login.'&filter_activity=7">'.$failed.'</a>';
837
  break;
838
  case 'cbdr' :
@@ -1051,9 +1168,10 @@ function cerber_show_dashboard() {
1051
  //array( __('Incidents detected','wp-cerber').'</a>', cerber_count_log( array( 16, 40, 50, 51, 52, 53, 54 ) ) ),
1052
  array( __('Malicious activities mitigated','wp-cerber').'</a>', cerber_count_log( array( 10, 11, 16, 17, 40, 50, 51, 52, 53, 54 ) ) ),
1053
  array( __('Spam comments denied','wp-cerber'), cerber_count_log( array( 16 ) ) ),
 
1054
  array( __('Malicious IP addresses detected','wp-cerber'), $unique_ip ),
1055
  array( __('Lockouts occurred','wp-cerber'), cerber_count_log( array( 10, 11 ) ) ),
1056
- array( __('Locked out IP now','wp-cerber'), $kpi_locknum ),
1057
  );
1058
 
1059
  $kpi_show = '';
@@ -1071,7 +1189,7 @@ function cerber_show_dashboard() {
1071
  $links = array();
1072
  $links[] = '<a href="' . cerber_admin_link( 'activity' ) . '">' . __( 'View all', 'wp-cerber' ) . '</a>';
1073
 
1074
- $labels = cerber_get_labels();
1075
  $set = array( 5 );
1076
  foreach ( $set as $item ) {
1077
  $links[] = '<a href="' . cerber_admin_link( 'activity' ) . '&filter_activity=' . $item . '">' . $labels[ $item ] . '</a>';
@@ -1086,7 +1204,7 @@ function cerber_show_dashboard() {
1086
  echo '<table class="cerber-margin"><tr><td><h2 style="margin-bottom:0.5em;">' . __( 'Activity', 'wp-cerber' ) . '</h2></td><td>' . $nav_links . '</td></tr></table>';
1087
 
1088
  cerber_show_activity( array(
1089
- 'filter_activity' => array( 1, 2, 5, 10, 11, 12, 16, 17, 40, 41, 42, 50, 51, 52, 53, 54 ),
1090
  'per_page' => 10,
1091
  'no_navi' => true,
1092
  'no_export' => true,
@@ -1149,9 +1267,10 @@ function cerber_show_aside($page){
1149
  </div>
1150
  ';
1151
 
1152
- $aside[] = '<div class="crb-box" id = "crb-donate">
 
1153
  <div class="crb-box-inner">
1154
- <h3>'.__('Donate','wp-cerber').'</h3>
1155
  <p>Hi! It\'s Gregory. I am an author of this plugin. Please consider making a donation to support the continued development and free support of this plugin because I spend my free time for that. Any help is greatly appreciated. Thanks!</p>
1156
 
1157
  <div style="text-align:center;">
@@ -1165,6 +1284,7 @@ function cerber_show_aside($page){
1165
 
1166
  </div>
1167
  </div>';
 
1168
 
1169
  /*$aside[] = '<div class="crb-box" id = "crb-jetflow">
1170
  <div class="crb-box-inner">
@@ -1343,7 +1463,7 @@ function cerber_subscribe( $mode = 'on', $hash = null ) {
1343
  $mode = 'off';
1344
  }
1345
  else {
1346
- $args = array_values(cerber_subscribe_params());
1347
  $hash = sha1( json_encode( $args ) );
1348
  }
1349
 
@@ -1539,20 +1659,24 @@ function cerber_admin_enqueue($hook) {
1539
 
1540
  add_action( 'admin_enqueue_scripts', 'cerber_admin_assets', 9999 );
1541
  function cerber_admin_assets() {
1542
- /*
1543
- if ( ! cerber_is_admin_page() ) {
1544
- return;
1545
- }*/
1546
 
1547
  $assets_url = plugin_dir_url( __FILE__ ) . 'assets';
1548
 
1549
- if ( ! defined( 'CERBER_BETA' ) ) {
1550
- wp_register_style( 'cerber_css', plugin_dir_url( __FILE__ ) . 'assets/admin.css', null, CERBER_VER );
1551
- wp_enqueue_style( 'cerber_css' );
 
 
 
 
1552
 
 
1553
  wp_enqueue_script( 'cerber_js', $assets_url . '/admin.js', array( 'jquery' ), CERBER_VER, true );
1554
  }
1555
 
 
 
 
1556
  // Select2
1557
  //wp_register_style( 'select2css', $assets_url . '/select2/dist/css/select2.min.css' );
1558
  //wp_enqueue_style( 'select2css' );
@@ -1564,9 +1688,12 @@ function cerber_admin_assets() {
1564
  * JS & CSS for admin head
1565
  *
1566
  */
1567
- add_action('admin_head','cerber_admin_head');
1568
- function cerber_admin_head(){
1569
- //$assets_url = plugin_dir_url(CERBER_FILE).'assets';
 
 
 
1570
 
1571
  if (defined('CERBER_BETA')) :
1572
  ?>
@@ -1576,9 +1703,6 @@ function cerber_admin_head(){
1576
  <?php
1577
  endif;
1578
 
1579
- if ( ! cerber_is_admin_page() ) {
1580
- return;
1581
- }
1582
  ?>
1583
  <style type="text/css" media="all">
1584
  /* Aliens messages */
@@ -1600,21 +1724,21 @@ function cerber_admin_head(){
1600
  * JS & CSS for admin footer
1601
  *
1602
  */
1603
- add_action('admin_footer','cerber_basement');
1604
- function cerber_basement(){
1605
  //add_some_pointers();
1606
  //$assets_url = plugin_dir_url(CERBER_FILE).'assets';
1607
- $ajax_nonce = wp_create_nonce('delete-ip');
1608
  ?>
1609
- <script type="text/javascript">
1610
  crb_ajax_nonce = '<?php echo $ajax_nonce; ?>';
1611
- </script>
1612
  <?php
1613
 
1614
- if (defined('CERBER_BETA')) :
1615
  ?>
1616
  <script type="text/javascript">
1617
- <?php readfile(dirname(__FILE__).'/assets/admin.js'); ?>
1618
  </script>
1619
  <?php
1620
  endif;
@@ -1624,12 +1748,18 @@ function cerber_basement(){
1624
  add_filter( 'admin_footer_text','cerber_footer_text1');
1625
  function cerber_footer_text1($text){
1626
  if (!cerber_is_admin_page(false)) return $text;
1627
- return 'If you like how <strong>WP Cerber</strong> protects your website, please <a target="_blank" href="https://wordpress.org/support/plugin/wp-cerber/reviews/#new-post">leave it a &#9733; &#9733; &#9733; &#9733; &#9733; rating</a>. Thanks in advance!';
1628
  }
1629
  add_filter( 'update_footer','cerber_footer_text2', 1000);
1630
  function cerber_footer_text2($text){
1631
  if (!cerber_is_admin_page(false)) return $text;
1632
- return '<a target="_blank" href="https://wordpress.org/support/plugin/wp-cerber">Support forum</a>';
 
 
 
 
 
 
1633
  }
1634
 
1635
  /*
@@ -1680,3 +1810,312 @@ function cerber_get_per_page(){
1680
  return $per_page;
1681
  }
1682
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  if (isset($ip_info['hostname'])) $hostname = $ip_info['hostname'];
69
  else {
70
  $ip_id = cerber_get_id_ip($row->ip);
71
+ $hostname = '<img data-ip-id="'.$ip_id .'" class="crb-no-hostname" src="'.$assets_url.'ajax-loader.gif" />'."\n";
72
  }
73
 
74
  $list[]='<td>'.$ip.'</td><td>'.$hostname.'</td><td>'.cerber_date($row->block_until).'</td><td>'.$row->reason.'</td><td><a href="'.wp_nonce_url(add_query_arg(array('lockdelete'=>$row->ip)),'control','cerber_nonce').'">'.__('Remove','wp-cerber').'</a></td>';
103
  cerber_acl_get_table('W');
104
  echo '<h2>'.__('Black IP Access List','wp-cerber').'</h2><p><span style="color:red;" class="dashicons-before dashicons-thumbs-down"></span> '.__('Nobody can log in or register from these IPs','wp-cerber').' - <a target="_blank" href="http://wpcerber.com/using-ip-access-lists-to-protect-wordpress/">Know more</a></p>'.
105
  cerber_acl_get_table('B');
106
+
107
+ $user_ip = $wp_cerber->getRemoteIp();
108
+ $link = cerber_admin_link( 'activity' ) . '&filter_ip=' . $user_ip;
109
+ $name = cerber_country_html(null, $user_ip);
110
+
111
+ echo '<p><b><span class="dashicons-before dashicons-star-filled"></span> '.__('Your IP','wp-cerber').': </b><a href="'.$link.'">'.$user_ip.'</a> '.$name.'</p>';
112
  echo '<h4 style="margin-top: 2em;"><span class="dashicons-before dashicons-info"></span> Possible values for entries in the access lists with examples</h4>
113
  <p>Single IPv6 address: <b>2001:0db8:85a3:0000:0000:8a2e:0370:7334</b>
114
  <p>Single IPv4 address: <b>192.168.5.22</b>
191
  if (!current_user_can('manage_options')) return;
192
  $response = array();
193
  if (isset($_REQUEST['acl_delete'])){
194
+
195
+ check_ajax_referer('crb-ajax-admin','ajax_nonce');
196
  $ip = $_REQUEST['acl_delete'];
197
  if (!$ip = cerber_parse_ip($ip)) wp_die();
198
  if (cerber_acl_remove($ip)) {
201
  $response['deleted_ip'] = $deleted;
202
  }
203
  else $response['error'] = 'Unable to delete';
204
+
205
  }
206
+ elseif ( isset( $_REQUEST['crb_ajax_slug'] ) && isset( $_REQUEST['crb_ajax_list'] ) ) {
207
+
208
+ check_ajax_referer('crb-ajax-admin','ajax_nonce');
209
+ $slug = $_REQUEST['crb_ajax_slug'];
210
+ $response['slug'] = $slug;
211
+ $list = array_unique( $_REQUEST['crb_ajax_list'] );
212
+
213
+ /*
214
+ $list = array_map(function ($ip_id){
215
+ return cerber_get_ip_id( $ip_id );
216
+ }, $list);
217
+ $list = array_filter( $list, function ( $ip ) {
218
+ if (filter_var( $ip, FILTER_VALIDATE_IP )){
219
+ return true;
220
+ }
221
+ });*/
222
+
223
+ $ip_list = array();
224
+ foreach ( $list as $ip_id ) {
225
+ if ($ip = filter_var( cerber_get_ip_id( $ip_id ), FILTER_VALIDATE_IP )){
226
+ $ip_list[ $ip_id ] = $ip;
227
+ }
228
+ else {
229
+ $response['data'][ $ip_id ] = '-';
230
+ }
231
+ }
232
+
233
+ switch($slug){
234
+ case 'hostname':
235
+ foreach ( $ip_list as $ip_id => $ip ) {
236
+ $ip_info = cerber_get_ip_info( $ip );
237
+ $response['data'][ $ip_id ] = $ip_info['hostname'];
238
+ }
239
+ break;
240
+ case 'country':
241
+ /*
242
+ $ip_list = array();
243
+ foreach ( $list as $ip_id ) {
244
+ $ip_list[] = cerber_get_ip_id( $ip_id );
245
+ //$response['data'][ $ip_id ] = 'Italy';
246
+ }*/
247
+ $list = lab_get_country($ip_list, false);
248
+ foreach ( $list as $ip_id => $country ) {
249
+ $response['data'][ $ip_id ] = cerber_get_flag_html( $country ) . cerber_country_name( $country );
250
+ }
251
+ break;
252
+
253
  }
254
+
255
  }
256
  elseif (isset($_REQUEST['dismiss_info'])){
257
+
258
+ if (isset($_REQUEST['button_id']) && ($_REQUEST['button_id'] == 'lab_ok' || $_REQUEST['button_id'] == 'lab_no')){
259
  lab_user_opt_in($_REQUEST['button_id']);
260
  }
261
  else update_site_option('cerber_admin_info','');
293
 
294
 
295
  /*
296
+ Admin's actions
297
  */
298
  add_action('admin_init','cerber_admin_request');
299
  function cerber_admin_request(){
354
  }
355
 
356
  if ( $_SERVER['REQUEST_METHOD'] == 'POST') {
357
+ if ( isset( $_POST['crb_geo_rules'] ) ) {
358
+ cerber_save_geo_rules();
359
+ }
360
+ elseif ( isset( $_POST['cerber_license'] ) ) {
361
  $lic = preg_replace( "/[^A-Z0-9]/i", '', $_POST['cerber_license'] );
362
  if ( !empty($lic) && strlen( $lic ) != LAB_KEY_LENGTH ) {
363
  return;
448
  *
449
  */
450
  function cerber_show_activity($args = array(), $echo = true){
451
+ global $wpdb, $assets_url, $wp_cerber, $wp_roles;
452
 
453
  $labels = cerber_get_labels('activity');
454
+ $status_labels = cerber_get_labels('status');
455
+
456
  $base_url = cerber_admin_link('activity');
457
  $right_links = '';
458
  $export_link = '';
470
  $assets_url = plugin_dir_url( CERBER_FILE ) . 'assets/';
471
  $list = array();
472
  $roles = $wp_roles->roles;
473
+ $country = '';
474
+ $geo = lab_lab();
475
 
476
  foreach ($rows as $row) {
477
 
478
+ $ip_id = cerber_get_id_ip($row->ip);
479
+
480
  $activity = '<span class="crb-activity actv' . $row->activity . '">'.$labels[ $row->activity ].'</span>';
481
  /*
482
  if ($row->activity == 50 ) {
483
  $activity .= ' <b>'.htmlspecialchars($row->user_login).'</b>';
484
  }*/
485
 
486
+ if ( empty( $args['no_details'] ) && $row->details ) {
487
+ $details = explode( '|', $row->details );
488
+ if ( ! empty( $details[0] ) ) {
489
+ $activity .= ' <span class = "act-details">' . $status_labels[ $details[0] ] . '</span>';
490
  }
491
  //elseif ($row->activity == 50 && $details[4]) $activity .= ' '.$details[4];
492
 
493
+ if ( isset( $details[4] ) && ( $row->activity < 10 || $row->activity > 12 ) ) {
494
+ $activity .= '<p class="act-url">URL: ' . $details[4] . '</p>';
 
 
495
  }
496
+
497
  }
498
 
499
 
531
  $ip_info = cerber_get_ip_info($row->ip,true);
532
  if (isset($ip_info['hostname'])) $hostname = $ip_info['hostname'];
533
  else {
534
+ $hostname = '<img data-ip-id="'.$ip_id .'" class="crb-no-hostname" src="'.$assets_url.'ajax-loader.gif" />'."\n";
 
535
  }
536
 
537
  $tip='';
553
  $date = '<span title="'.$row->stamp.' / '.$row->session_id.' / '.$row->activity .'">'.cerber_date( $row->stamp ).'<span/>';
554
  }
555
 
556
+ if ( $geo ) {
557
+ /*
558
+ if ( $row->country ) {
559
+ $code = $row->country;
560
+ } else {
561
+ $code = lab_get_country( $row->ip );
562
+ }
563
+
564
+ if ( $code ) {
565
+ //$country = cerber_get_flag_html( $code ) . '<a href="'.$base_url.'&filter_country='.$code.'">'.cerber_country_name( $code ).'</a>';
566
+ $country = cerber_get_flag_html( $code ) . cerber_country_name( $code );
567
+ } else {
568
+ $country = '<img data-ip-id="' . $ip_id . '" class="crb-no-country" src="' . $assets_url . 'ajax-loader.gif" />' . "\n";
569
+ }
570
+
571
+ $country = '</td><td>' . $country;
572
+ */
573
+ $country = '</td><td>' . cerber_country_html($row->country, $row->ip);
574
+ }
575
+
576
+ $list[] = '<td><div class="act-icon ip-acl' . $acl . ' ' . $block . '" title="' . $tip . '"></div>' . $ip . '</td><td>' . $hostname . $country . '</td><td>' . $date . '</td><td class="crb'.$row->activity .'">' . $activity . '</td><td>' . $name . '</td><td>' . $username . '</td>';
577
+ }
578
+
579
+ //$titles = '<tr><th><div class="act-icon"></div>' . __( 'IP', 'wp-cerber' ) . '</th><th>' . __( 'Hostname', 'wp-cerber' ) . '</th><th>' . __( 'Date', 'wp-cerber' ) . '</th><th>' . __( 'Event', 'wp-cerber' ) . '</th><th>' . __( 'Local User', 'wp-cerber' ) . '</th><th>' . __( 'Username used', 'wp-cerber' ) . '</th></tr>';
580
+
581
+ $heading = array(
582
+ '<div class="act-icon"></div>' . __( 'IP', 'wp-cerber' ),
583
+ __( 'Hostname', 'wp-cerber' ),
584
+ __( 'Country', 'wp-cerber' ),
585
+ __( 'Date', 'wp-cerber' ),
586
+ __( 'Event', 'wp-cerber' ),
587
+ __( 'Local User', 'wp-cerber' ),
588
+ __( 'Username used', 'wp-cerber' )
589
+ );
590
+
591
+ if ( !lab_lab() ) {
592
+ unset( $heading[2] );
593
  }
594
 
595
+ $titles = '<tr><th>' . implode( '</th><th>', $heading ) . '</th></tr>';
596
+
597
  $table = '<table id="crb-activity" class="widefat crb-table cerber-margin"><thead>' . $titles . '</thead><tfoot>' . $titles . '</tfoot><tbody><tr>' . implode( '</tr><tr>', $list ) . '</tr></tbody></table>';
598
 
599
  if (empty($args['no_navi'])) $table .= cerber_page_navi($total, $per_page);
612
  if (empty($args['no_navi'])) {
613
 
614
  unset( $labels[13], $labels[14], $labels[15] );
615
+ $labels = array( 0 => __( 'All events', 'wp-cerber' ) ) + $labels;
616
 
617
  if (!empty($_GET['filter_activity']) && !is_array($_GET['filter_activity'])) {
618
  $selected = absint($_GET['filter_activity']);
707
  $search = '%'.$search.'%';
708
  $where[] = $wpdb->prepare('(log.ip LIKE %s OR log.user_login LIKE %s)', $search, $search);
709
  }
710
+ if (!empty($_GET['filter_country'])) {
711
+ $country = substr($_GET['filter_country'], 0, 3);
712
+ $ret[7] = htmlspecialchars($country);
713
+ $where[] = 'log.country = "'.$country.'"';
714
+ }
715
 
716
  if (!empty($where)) $where = 'WHERE '.implode(' AND ',$where);
717
  else $where = '';
844
  add_action( 'load-' . $hook, "cerber_screen_options" );
845
  add_submenu_page( 'cerber-security', __( 'Cerber Dashboard', 'wp-cerber' ), __( 'Dashboard' ), 'manage_options', 'cerber-security', 'cerber_settings_page' );
846
 
847
+ if (lab_lab()) {
848
+ add_submenu_page( 'cerber-security', __( 'Cerber Security Rules', 'wp-cerber' ), __( 'Security Rules', 'wp-cerber' ), 'manage_options', 'cerber-rules', 'cerber_rules_page' );
849
+ }
850
+
851
  add_submenu_page( 'cerber-security', __( 'Cerber antispam settings', 'wp-cerber' ), __( 'Antispam', 'wp-cerber' ), 'manage_options', 'cerber-recaptcha', 'cerber_recaptcha_page' );
852
  add_submenu_page( 'cerber-security', __( 'Cerber tools', 'wp-cerber' ), __( 'Tools', 'wp-cerber' ), 'manage_options', 'cerber-tools', 'cerber_tools_page' );
853
 
868
  /*
869
  Check if currently displayed page is a Cerber admin dashboard page with optional checking a set of GET params
870
  */
871
+ function cerber_is_admin_page( $force = true, $params = array() ) {
872
 
873
+ if ( ! is_admin() ) {
874
+ return false;
875
+ }
876
 
877
  $ret = false;
878
 
879
+ if ( isset( $_GET['page'] ) && false !== strpos( $_GET['page'], 'cerber-' ) ) {
880
  $ret = true;
881
+ if ( $params ) {
882
+ foreach ( $params as $param => $value ) {
883
+ if ( ! isset( $_GET[ $param ] ) || $_GET[ $param ] != $value ) {
884
  $ret = false;
885
  break;
886
  }
887
  }
888
  }
889
  }
890
+ if ( $ret || !$force) {
891
+ return $ret;
892
+ }
893
 
894
+ if ( ! $screen = get_current_screen() ) {
895
+ return false;
896
+ }
897
+ if ( $screen->base == 'plugins' ) {
898
+ return true;
899
+ }
900
  /*
901
  if ($screen->parent_base == 'options-general') return true;
902
  if ($screen->parent_base == 'settings') return true;
905
  }
906
 
907
  /*
908
+ Add custom columns to the Users admin screen
909
  */
910
  add_filter('manage_users_columns' , 'cerber_u_columns');
911
  function cerber_u_columns($columns) {
933
  else $ret = 0;
934
  break;
935
  case 'cbla' :
936
+ //$row = $wpdb->get_row('SELECT MAX(stamp) FROM '.CERBER_LOG_TABLE.' WHERE user_id = '.absint($user_id));
937
+ $row = $wpdb->get_row('SELECT * FROM '.CERBER_LOG_TABLE.' WHERE activity = 5 AND user_id = '.absint($user_id) . ' ORDER BY stamp DESC LIMIT 1');
938
+ if ($row) {
939
  $act_link = cerber_admin_link('activity');
940
+ if ( $country = cerber_country_html( $row->country, $row->ip ) ) {
941
+ $country = '<br>' . $country;
942
+ } else {
943
+ $country = '';
944
+ }
945
+ $ret = '<a href="'.$act_link.'&filter_user='.$user_id.'">'.cerber_date($row->stamp).'</a>'.$country;
946
  }
947
  else $ret=__('Never','wp-cerber');
948
  break;
949
  case 'cbfl' :
950
  $act_link = cerber_admin_link('activity');
951
  $u=get_userdata($user_id);
952
+ $failed = $wpdb->get_var('SELECT COUNT(user_id) FROM '.CERBER_LOG_TABLE.' WHERE user_login = \''.$u->user_login.'\' AND activity = 7 AND stamp > ' . (time() - 24 * 3600));
953
  $ret = '<a href="'.$act_link.'&filter_login='.$u->user_login.'&filter_activity=7">'.$failed.'</a>';
954
  break;
955
  case 'cbdr' :
1168
  //array( __('Incidents detected','wp-cerber').'</a>', cerber_count_log( array( 16, 40, 50, 51, 52, 53, 54 ) ) ),
1169
  array( __('Malicious activities mitigated','wp-cerber').'</a>', cerber_count_log( array( 10, 11, 16, 17, 40, 50, 51, 52, 53, 54 ) ) ),
1170
  array( __('Spam comments denied','wp-cerber'), cerber_count_log( array( 16 ) ) ),
1171
+ array( __('Spam form submissions denied','wp-cerber'), cerber_count_log( array( 17 ) ) ),
1172
  array( __('Malicious IP addresses detected','wp-cerber'), $unique_ip ),
1173
  array( __('Lockouts occurred','wp-cerber'), cerber_count_log( array( 10, 11 ) ) ),
1174
+ //array( __('Locked out IP now','wp-cerber'), $kpi_locknum ),
1175
  );
1176
 
1177
  $kpi_show = '';
1189
  $links = array();
1190
  $links[] = '<a href="' . cerber_admin_link( 'activity' ) . '">' . __( 'View all', 'wp-cerber' ) . '</a>';
1191
 
1192
+ $labels = cerber_get_labels('activity');
1193
  $set = array( 5 );
1194
  foreach ( $set as $item ) {
1195
  $links[] = '<a href="' . cerber_admin_link( 'activity' ) . '&filter_activity=' . $item . '">' . $labels[ $item ] . '</a>';
1204
  echo '<table class="cerber-margin"><tr><td><h2 style="margin-bottom:0.5em;">' . __( 'Activity', 'wp-cerber' ) . '</h2></td><td>' . $nav_links . '</td></tr></table>';
1205
 
1206
  cerber_show_activity( array(
1207
+ 'filter_activity' => array( 1, 2, 5, 10, 11, 12, 16, 17, 18, 19, 40, 41, 42, 50, 51, 52, 53, 54, 70, 71 ),
1208
  'per_page' => 10,
1209
  'no_navi' => true,
1210
  'no_export' => true,
1267
  </div>
1268
  ';
1269
 
1270
+ if (!in_array($page,array('geo'))) {
1271
+ $aside[] = '<div class="crb-box" id = "crb-donate">
1272
  <div class="crb-box-inner">
1273
+ <h3>' . __( 'Donate', 'wp-cerber' ) . '</h3>
1274
  <p>Hi! It\'s Gregory. I am an author of this plugin. Please consider making a donation to support the continued development and free support of this plugin because I spend my free time for that. Any help is greatly appreciated. Thanks!</p>
1275
 
1276
  <div style="text-align:center;">
1284
 
1285
  </div>
1286
  </div>';
1287
+ }
1288
 
1289
  /*$aside[] = '<div class="crb-box" id = "crb-jetflow">
1290
  <div class="crb-box-inner">
1463
  $mode = 'off';
1464
  }
1465
  else {
1466
+ $args = array_values( cerber_subscribe_params() );
1467
  $hash = sha1( json_encode( $args ) );
1468
  }
1469
 
1659
 
1660
  add_action( 'admin_enqueue_scripts', 'cerber_admin_assets', 9999 );
1661
  function cerber_admin_assets() {
 
 
 
 
1662
 
1663
  $assets_url = plugin_dir_url( __FILE__ ) . 'assets';
1664
 
1665
+ if ( cerber_is_admin_page() ) {
1666
+
1667
+ wp_register_style( 'crb_multi_css', $assets_url . '/multi/multi.css', null, CERBER_VER );
1668
+ wp_enqueue_style( 'crb_multi_css' );
1669
+ wp_enqueue_script( 'crb_multi_js', $assets_url . '/multi/multi.min.js', array(), CERBER_VER );
1670
+
1671
+ }
1672
 
1673
+ if ( ! defined( 'CERBER_BETA' ) ) {
1674
  wp_enqueue_script( 'cerber_js', $assets_url . '/admin.js', array( 'jquery' ), CERBER_VER, true );
1675
  }
1676
 
1677
+ wp_register_style( 'cerber_css', $assets_url . '/admin.css', null, CERBER_VER );
1678
+ wp_enqueue_style( 'cerber_css' );
1679
+
1680
  // Select2
1681
  //wp_register_style( 'select2css', $assets_url . '/select2/dist/css/select2.min.css' );
1682
  //wp_enqueue_style( 'select2css' );
1688
  * JS & CSS for admin head
1689
  *
1690
  */
1691
+ add_action('admin_head','cerber_admin_css');
1692
+ function cerber_admin_css(){
1693
+ global $assets_url;
1694
+
1695
+ $assets_url = plugin_dir_url( CERBER_FILE ) . 'assets/';
1696
+
1697
 
1698
  if (defined('CERBER_BETA')) :
1699
  ?>
1703
  <?php
1704
  endif;
1705
 
 
 
 
1706
  ?>
1707
  <style type="text/css" media="all">
1708
  /* Aliens messages */
1724
  * JS & CSS for admin footer
1725
  *
1726
  */
1727
+ add_action( 'admin_footer', 'cerber_admin_footer' );
1728
+ function cerber_admin_footer() {
1729
  //add_some_pointers();
1730
  //$assets_url = plugin_dir_url(CERBER_FILE).'assets';
1731
+ $ajax_nonce = wp_create_nonce( 'crb-ajax-admin' );
1732
  ?>
1733
+ <script type="text/javascript">
1734
  crb_ajax_nonce = '<?php echo $ajax_nonce; ?>';
1735
+ </script>
1736
  <?php
1737
 
1738
+ if ( defined( 'CERBER_BETA' ) && cerber_is_admin_page( false ) ) :
1739
  ?>
1740
  <script type="text/javascript">
1741
+ <?php readfile( dirname( __FILE__ ) . '/assets/admin.js' ); ?>
1742
  </script>
1743
  <?php
1744
  endif;
1748
  add_filter( 'admin_footer_text','cerber_footer_text1');
1749
  function cerber_footer_text1($text){
1750
  if (!cerber_is_admin_page(false)) return $text;
1751
+ return 'If you like how <strong>WP Cerber</strong> protects your website, please <a target="_blank" href="https://wordpress.org/support/plugin/wp-cerber/reviews/#new-post">leave it a &#9733; &#9733; &#9733; &#9733; &#9733; rating</a>. Thanks!';
1752
  }
1753
  add_filter( 'update_footer','cerber_footer_text2', 1000);
1754
  function cerber_footer_text2($text){
1755
  if (!cerber_is_admin_page(false)) return $text;
1756
+ if ( lab_lab() ) {
1757
+ $pr = 'PRO';
1758
+ }
1759
+ else {
1760
+ $pr = '';
1761
+ }
1762
+ return 'WP Cerber Security '.$pr.' v '.CERBER_VER.'. | <a target="_blank" href="https://wordpress.org/support/plugin/wp-cerber">Support forum</a>';
1763
  }
1764
 
1765
  /*
1810
  return $per_page;
1811
  }
1812
 
1813
+ function cerber_rules_page(){
1814
+
1815
+ $tab = cerber_get_tab( 'geo', array( 'geo' ) );
1816
+
1817
+ ?>
1818
+ <div class="wrap">
1819
+
1820
+ <h2><?php _e( 'Security Rules', 'wp-cerber' ) ?></h2>
1821
+
1822
+ <h2 class="nav-tab-wrapper cerber-tabs">
1823
+ <?php
1824
+
1825
+ echo '<a href="' . cerber_admin_link('geo') . '" class="nav-tab ' . ( $tab == 'geo' ? 'nav-tab-active' : '') . '"><span class="dashicons dashicons-admin-site"></span> ' . __('Countries') . '</a>';
1826
+ //echo '<a href="' . cerber_admin_link('diagnostic') . '" class="nav-tab ' . ( $tab == 'diagnostic' ? 'nav-tab-active' : '') . '"><span class="dashicons dashicons-admin-tools"></span> ' . __('Diagnostic') . '</a>';
1827
+ //echo '<a href="' . cerber_admin_link('license') . '" class="nav-tab ' . ( $tab == 'license' ? 'nav-tab-active' : '') . '"><span class="dashicons dashicons-id-alt"></span> ' . __('License') . '</a>';
1828
+
1829
+ ?>
1830
+ </h2>
1831
+
1832
+ <?php
1833
+
1834
+ cerber_show_aside( 'geo' );
1835
+
1836
+ echo '<div class="crb-main">';
1837
+
1838
+ switch ($tab){
1839
+ case 'geo':
1840
+ cerber_show_geo_rules();
1841
+ break;
1842
+ default: cerber_show_geo_rules();
1843
+ }
1844
+
1845
+ echo '</div>';
1846
+
1847
+ ?>
1848
+ </div>
1849
+ <?php
1850
+ }
1851
+
1852
+ function cerber_show_geo_rules(){
1853
+ global $wp_cerber;
1854
+
1855
+ /*
1856
+ echo "\n";
1857
+ foreach ( cerber_get_country_list() as $code => $i ) {
1858
+ echo '
1859
+ a[data-value="'.$code.'"]{
1860
+ background: url("flags/'.strtolower($code).'.gif") no-repeat left;
1861
+ }'."\n";
1862
+ }*/
1863
+
1864
+ $rules = cerber_geo_rule_set();
1865
+
1866
+ $tablinks = '';
1867
+ $tabs = '';
1868
+ $first = true;
1869
+ $opt = $wp_cerber->getSettings();
1870
+
1871
+ foreach ( $rules as $rule_id => $rule ) {
1872
+
1873
+ $config = cerber_geo_rules($rule_id);
1874
+
1875
+ $selector = cerber_country_form($config, $rule_id, $rule);
1876
+
1877
+ if ($first) {
1878
+ $b_class = 'active';
1879
+ $t_style = '';
1880
+ }
1881
+ else {
1882
+ $b_class = '';
1883
+ $t_style = 'style= "display: none;"';
1884
+ }
1885
+
1886
+ if ( ! empty( $config['list'] ) ) {
1887
+ $num = count( $config['list'] );
1888
+ if ( $config['type'] == 'W' ) {
1889
+ $info = sprintf( _n( 'Permitted for one country', 'Permitted for %d countries', $num, 'wp-cerber' ), $num );
1890
+ }
1891
+ else {
1892
+ $info = sprintf( _n( 'Blocked for one country', 'Blocked for %d countries', $num, 'wp-cerber' ), $num );
1893
+ }
1894
+ }
1895
+ else {
1896
+ $info = __( 'No rule', 'wp-cerber' );
1897
+ }
1898
+
1899
+ $note = '';
1900
+ switch ( $rule_id ) {
1901
+ case 'geo_register':
1902
+ if ( !get_option( 'users_can_register' ) ) {
1903
+ $note = 'Registration is disabled in the General Settings';
1904
+ }
1905
+ break;
1906
+ case 'geo_restapi':
1907
+ if ( $opt['norest'] ) {
1908
+ $note = 'REST API is disabled in the Hardening settings of the plugin';
1909
+ }
1910
+ break;
1911
+ case 'geo_xmlrpc':
1912
+ if ( $opt['xmlrpc'] ) {
1913
+ $note = 'XML-RPC is disabled in the Hardening settings of the plugin';
1914
+ }
1915
+ break;
1916
+ }
1917
+ if ($note) $note = '<p><span class="dashicons-before dashicons-warning"></span> Warning: '.$note.'</p>';
1918
+
1919
+ //$tablinks .= '<button class="tablinks '.$b_class.'" data-rule-id="'.$rule_id.'">'.$rule['name'].'</button>';
1920
+ $tablinks .= '<div class="tablinks '.$b_class.'" data-rule-id="'.$rule_id.'">'.$rule['name'].'<br><span>'.$info.'</span></div>';
1921
+
1922
+ $tabs .= '<div id="tab-' . $rule_id . '" class="vtabcontent" '.$t_style.'>'.$note.$selector.'</div>';
1923
+
1924
+ $first = false;
1925
+ }
1926
+
1927
+ echo '<form method="post" action="">';
1928
+
1929
+ echo '<table class="vtable" style="width: 100%; border-collapse: collapse;"><tr><td style="width: 20%"><div class="vtabs">'.$tablinks.'</div></td><td>'.$tabs.'
1930
+ <p style="margin-left: 3em;"><input type="submit" class="button button-primary" value="Save all rules"></p>
1931
+ </td></tr></table>';
1932
+
1933
+ //echo '<div class="vtabs">'.$buttons.'</div>';
1934
+ //echo '<div class="vtabs-content">'.$tabs.'</div>';
1935
+
1936
+ echo wp_nonce_field('control','cerber_nonce');
1937
+ echo '<input type="hidden" name="crb_geo_rules" value="1"></form>';
1938
+
1939
+
1940
+ // Script for tabbed layout
1941
+
1942
+ reset($rules);
1943
+ $first_id = 'countries-'.key($rules);
1944
+
1945
+ ?>
1946
+
1947
+ <script type="text/javascript">
1948
+ //var select_element = document.getElementById( '<?php echo $first_id; ?>' );
1949
+ //multi( select_element );
1950
+
1951
+ jQuery(document).ready(function ($) {
1952
+ $("#<?php echo $first_id; ?>").multi({'search_placeholder': 'Start typing here to find a country'});
1953
+
1954
+ $('.tablinks').click(function () {
1955
+
1956
+ // Tabs...
1957
+
1958
+ var rule_id = $(this).data('rule-id');
1959
+ $('.vtabcontent').hide();
1960
+ $('#tab-' + rule_id).show();
1961
+
1962
+ $( ".tablinks" ).removeClass( "active" );
1963
+ $( this ).addClass( "active" );
1964
+
1965
+ // Multiselect...
1966
+
1967
+ $('.multi-wrapper').remove();
1968
+ document.querySelector('.crb-select-multi').removeAttribute('data-multijs');
1969
+ $('.crb-select-multi').removeAttr('data-multijs');
1970
+
1971
+ $( '#countries-' + rule_id ).multi({'search_placeholder': 'Start typing here to find a country'});
1972
+ });
1973
+ });
1974
+
1975
+ </script>
1976
+
1977
+ <?php
1978
+
1979
+ }
1980
+
1981
+ /**
1982
+ * Generates GEO rule form
1983
+ *
1984
+ * @param array $config saved rule configuration
1985
+ * @param string $rule_id
1986
+ * @param array $rule
1987
+ *
1988
+ * @return string HTML code of form
1989
+ */
1990
+ function cerber_country_form( $config = array(), $rule_id = '', $rule = array() ) {
1991
+
1992
+ //$ret = '<form action="" method="post" id="form-' . $rule_id . '">';
1993
+
1994
+ $ret = '';
1995
+
1996
+ $ret .= '<select id="countries-' . $rule_id . '" name="crb-' . $rule_id . '-list[]" class="crb-select-multi" style="display: none;" multiple="multiple">';
1997
+
1998
+ if (!empty($config['list'])){
1999
+ $selected = $config['list'];
2000
+ }
2001
+ else {
2002
+ $selected = null;
2003
+ }
2004
+
2005
+ foreach ( cerber_get_country_list() as $code => $country ) {
2006
+ if ( $selected && in_array( $code, $selected ) ) {
2007
+ $sel = 'selected';
2008
+ } else {
2009
+ $sel = '';
2010
+ }
2011
+ $ret .= '<option ' . $sel . ' value="' . $code . '">' . $country . '</option>';
2012
+ }
2013
+
2014
+ if (!empty($config['type']) && $config['type'] == 'B'){
2015
+ $w = '';
2016
+ $b = 'checked="checked"';
2017
+ }
2018
+ else {
2019
+ $w = 'checked="checked"';
2020
+ $b = '';
2021
+ }
2022
+
2023
+ if (!empty($rule['desc'])) {
2024
+ $desc = $rule['desc'];
2025
+ }
2026
+ else{
2027
+ $desc = '<span style="text-transform: lowercase;">'.$rule['name'].'</span>';
2028
+ }
2029
+
2030
+
2031
+ $ret .= '
2032
+ </select>
2033
+ <p><i>Click on a country name to add it to the list of selected countries</i></p>
2034
+
2035
+ <p style="margin-top: 2em;"><input type="radio" value="W" name="crb-'.$rule_id.'-type" id="geo-type-'.$rule_id.'-W" '.$w.'><label for="geo-type-'.$rule_id.'-W">Selected countries are <b>allowed</b> to '.$desc.', other countries are <b>not allowed</b></label></p>
2036
+ <p><input type="radio" value="B" name="crb-'.$rule_id.'-type" id="geo-type-'.$rule_id.'-B" '.$b.'><label for="geo-type-'.$rule_id.'-B">Selected countries are <b>not allowed</b> to '.$desc.', other countries are <b>allowed</b></label></p>';
2037
+
2038
+ //$ret .= '<p style="text-align: right;"><input type="submit" class="button button-primary" value="Save the rule"></p>'.wp_nonce_field('cerber_dashboard','cerber_nonce');
2039
+ //$ret .= '</form>';
2040
+
2041
+ return $ret;
2042
+
2043
+ }
2044
+
2045
+ function cerber_geo_rule_set(){
2046
+ $rules = array(
2047
+ 'geo_submit' => array( 'name' => 'Submit forms', 'desc' => 'submit forms' ),
2048
+ 'geo_comment' => array( 'name' => 'Post comments' ),
2049
+ 'geo_login' => array( 'name' => 'Log in to the website' ),
2050
+ 'geo_register' => array( 'name' => 'Register on the website' ),
2051
+ 'geo_xmlrpc' => array( 'name' => 'Using XML-RPC' , 'desc' => 'use XML-RPC' ), // Should it be in the Hardening section?
2052
+ 'geo_restapi' => array( 'name' => 'Using REST API' , 'desc' => 'use REST API' ) // Should it be in the Hardening section?
2053
+ );
2054
+
2055
+ return $rules;
2056
+ }
2057
+
2058
+ function cerber_save_geo_rules(){
2059
+ global $cerber_country_names, $wp_cerber;
2060
+
2061
+ if (!lab_lab()) return;
2062
+
2063
+ $geo = array();
2064
+ $check = array_keys($cerber_country_names);
2065
+
2066
+ // Preserve admin country to be blocked
2067
+ $admin_country = lab_get_country($wp_cerber->getRemoteIp(), false);
2068
+
2069
+ foreach ( cerber_geo_rule_set() as $rule_id => $rule ) {
2070
+ if ( ! empty( $_POST[ 'crb-' . $rule_id . '-list' ] ) && ! empty( $_POST[ 'crb-' . $rule_id . '-type' ] ) ) {
2071
+ $list = array_intersect( $_POST[ 'crb-' . $rule_id . '-list' ], $check );
2072
+
2073
+ if ( $_POST[ 'crb-' . $rule_id . '-type' ] == 'B' ) {
2074
+ $type = 'B';
2075
+ if ( ( $key = array_search( $admin_country, $list ) ) !== false ) {
2076
+ unset( $list[ $key ] );
2077
+ }
2078
+ }
2079
+ else{
2080
+ $type = 'W';
2081
+ if ( ( $key = array_search( $admin_country, $list ) ) === false ) {
2082
+ array_push( $list, $admin_country );
2083
+ }
2084
+ }
2085
+
2086
+ $geo[$rule_id]['list'] = $list;
2087
+ $geo[$rule_id]['type'] = $type;
2088
+ }
2089
+ }
2090
+
2091
+ if ( update_site_option( 'geo_rule_set', $geo ) ) {
2092
+ cerber_admin_message( __( 'Security rules have been updated', 'wp-cerber' ) );
2093
+ }
2094
+ }
2095
+
2096
+ function cerber_country_html($code = null, $ip = null){
2097
+ global $assets_url;
2098
+
2099
+ if (!lab_lab()){
2100
+ return '';
2101
+ }
2102
+
2103
+ if ( ! $code ) {
2104
+ if ( $ip ) {
2105
+ $code = lab_get_country( $ip );
2106
+ } else {
2107
+ return '';
2108
+ }
2109
+ }
2110
+
2111
+ if ( $code ) {
2112
+ //$country = cerber_get_flag_html( $code ) . '<a href="'.$base_url.'&filter_country='.$code.'">'.cerber_country_name( $code ).'</a>';
2113
+ $ret = cerber_get_flag_html( $code ) . cerber_country_name( $code );
2114
+ }
2115
+ else {
2116
+ $ip_id = cerber_get_id_ip($ip);
2117
+ $ret = '<img data-ip-id="' . $ip_id . '" class="crb-no-country" src="' . $assets_url . 'ajax-loader.gif" />' . "\n";
2118
+ }
2119
+
2120
+ return $ret;
2121
+ }
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: Mon Sep 11 2017 18:39:47 GMT+0300\n"
9
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
10
  "Last-Translator: \n"
11
  "Language-Team: \n"
@@ -24,15 +24,15 @@ msgstr ""
24
  "esc_html_x:1,2c;comments_number_link:2,3;t:1;st:1;trans:1;transChoice:1,2\n"
25
  "X-Generator: Loco - https://localise.biz/"
26
 
27
- #: ../dashboard.php:74 ../dashboard.php:123
28
  msgid "Remove"
29
  msgstr ""
30
 
31
- #: ../dashboard.php:77 ../dashboard.php:502 ../wp-cerber.php:2898
32
  msgid "IP"
33
  msgstr ""
34
 
35
- #: ../dashboard.php:77 ../dashboard.php:502
36
  msgid "Hostname"
37
  msgstr ""
38
 
@@ -40,7 +40,7 @@ msgstr ""
40
  msgid "Expires"
41
  msgstr ""
42
 
43
- #: ../dashboard.php:77 ../wp-cerber.php:2604
44
  msgid "Reason"
45
  msgstr ""
46
 
@@ -65,8 +65,8 @@ msgstr ""
65
  msgid "No lockouts at the moment. The sky is clear."
66
  msgstr ""
67
 
68
- #: ../dashboard.php:102 ../dashboard.php:483 ../dashboard.php:663 ../dashboard.
69
- #: php:902 ../wp-cerber.php:3024 ../settings.php:61 ../settings.php:196
70
  msgid "White IP Access List"
71
  msgstr ""
72
 
@@ -74,8 +74,8 @@ msgstr ""
74
  msgid "These IPs will never be locked out"
75
  msgstr ""
76
 
77
- #: ../dashboard.php:104 ../dashboard.php:484 ../dashboard.php:665 ../dashboard.
78
- #: php:903
79
  msgid "Black IP Access List"
80
  msgstr ""
81
 
@@ -83,352 +83,398 @@ msgstr ""
83
  msgid "Nobody can log in or register from these IPs"
84
  msgstr ""
85
 
86
- #: ../dashboard.php:106
87
  msgid "Your IP"
88
  msgstr ""
89
 
90
- #: ../dashboard.php:123 ../dashboard.php:695
91
  msgid "Check for activity"
92
  msgstr ""
93
 
94
- #: ../dashboard.php:126
95
  msgid "List is empty"
96
  msgstr ""
97
 
98
- #: ../dashboard.php:130
99
  msgid "Add IP to the list"
100
  msgstr ""
101
 
102
- #: ../dashboard.php:150 ../dashboard.php:158
103
  msgid "Incorrect IP address or IP range"
104
  msgstr ""
105
 
106
- #: ../dashboard.php:153
107
  #, php-format
108
  msgid "Address %s was added to White IP Access List"
109
  msgstr ""
110
 
111
- #: ../dashboard.php:162
112
  msgid "You can't add your IP address"
113
  msgstr ""
114
 
115
- #: ../dashboard.php:166
116
  #, php-format
117
  msgid "Address %s was added to Black IP Access List"
118
  msgstr ""
119
 
120
- #: ../dashboard.php:237
121
  msgid "unknown"
122
  msgstr ""
123
 
124
- #: ../dashboard.php:259
125
  msgid "Message has been sent to "
126
  msgstr ""
127
 
128
- #: ../dashboard.php:262
129
  msgid "Unable to send notification email"
130
  msgstr ""
131
 
132
- #: ../dashboard.php:270
133
  #, php-format
134
  msgid "Lockout for %s was removed"
135
  msgstr ""
136
 
137
- #: ../dashboard.php:287 ../dashboard.php:1220
138
  msgid "Settings saved"
139
  msgstr ""
140
 
141
- #: ../dashboard.php:355
142
  msgid "IP address"
143
  msgstr ""
144
 
145
- #: ../dashboard.php:355 ../dashboard.php:502
146
  msgid "Date"
147
  msgstr ""
148
 
149
- #: ../dashboard.php:355 ../dashboard.php:502
150
  msgid "Event"
151
  msgstr ""
152
 
153
- #: ../dashboard.php:355 ../dashboard.php:502
154
  msgid "Local User"
155
  msgstr ""
156
 
157
- #: ../dashboard.php:355
158
  msgid "User login"
159
  msgstr ""
160
 
161
- #: ../dashboard.php:355
162
  msgid "User ID"
163
  msgstr ""
164
 
165
- #: ../dashboard.php:355 ../dashboard.php:502 ../wp-cerber.php:2906
166
  msgid "Username used"
167
  msgstr ""
168
 
169
- #: ../dashboard.php:488 ../dashboard.php:668 ../common.php:348
170
  msgid "Locked out"
171
  msgstr ""
172
 
173
- #: ../dashboard.php:511
 
 
 
 
174
  msgid "Export"
175
  msgstr ""
176
 
177
- #: ../dashboard.php:515
178
  msgid "No activity has been logged."
179
  msgstr ""
180
 
181
- #: ../dashboard.php:521
182
- msgid "All activities"
183
  msgstr ""
184
 
185
- #: ../dashboard.php:530
186
  msgid "Search for IP or username"
187
  msgstr ""
188
 
189
- #: ../dashboard.php:530
190
  msgid "Filter"
191
  msgstr ""
192
 
193
- #: ../dashboard.php:691
194
  msgid "Abuse email:"
195
  msgstr ""
196
 
197
- #: ../dashboard.php:695
198
  msgid "Network:"
199
  msgstr ""
200
 
201
- #: ../dashboard.php:709
202
  msgid "Add network to the Black List"
203
  msgstr ""
204
 
205
- #: ../dashboard.php:713
206
  msgid "Add IP to the Black List"
207
  msgstr ""
208
 
209
- #: ../dashboard.php:744 ../settings.php:219
210
  msgid "WP Cerber Security"
211
  msgstr ""
212
 
213
  #. Name of the plugin
214
- #: ../dashboard.php:744 ../dashboard.php:759
215
  msgid "WP Cerber"
216
  msgstr ""
217
 
218
- #: ../dashboard.php:746
219
  msgid "Cerber Dashboard"
220
  msgstr ""
221
 
222
- #: ../dashboard.php:746 ../dashboard.php:910 ../dashboard.php:1412 ../settings.
223
- #: php:224
224
  msgid "Dashboard"
225
  msgstr ""
226
 
227
- #: ../dashboard.php:748
 
 
 
 
 
 
 
 
228
  msgid "Cerber antispam settings"
229
  msgstr ""
230
 
231
- #: ../dashboard.php:748 ../wp-cerber.php:3031 ../settings.php:147
232
  msgid "Antispam"
233
  msgstr ""
234
 
235
- #: ../dashboard.php:749
236
  msgid "Cerber tools"
237
  msgstr ""
238
 
239
- #: ../dashboard.php:749 ../cerber-tools.php:43
240
  msgid "Tools"
241
  msgstr ""
242
 
243
- #: ../dashboard.php:802
244
  msgid "Comments"
245
  msgstr ""
246
 
247
- #: ../dashboard.php:803
248
  msgid "Last login"
249
  msgstr ""
250
 
251
- #: ../dashboard.php:804
252
  msgid "Failed attempts in last 24 hours"
253
  msgstr ""
254
 
255
- #: ../dashboard.php:805
256
  msgid "Date of registration"
257
  msgstr ""
258
 
259
- #: ../dashboard.php:830 ../dashboard.php:885
260
  msgid "Never"
261
  msgstr ""
262
 
263
- #: ../dashboard.php:854
264
  msgid "Cerber Quick View"
265
  msgstr ""
266
 
267
- #: ../dashboard.php:889
268
  msgid "active"
269
  msgstr ""
270
 
271
- #: ../dashboard.php:889
272
  msgid "deactivate"
273
  msgstr ""
274
 
275
- #: ../dashboard.php:891
276
  msgid "not active"
277
  msgstr ""
278
 
279
- #: ../dashboard.php:892
280
  msgid "disabled"
281
  msgstr ""
282
 
283
- #: ../dashboard.php:897
284
  msgid "failed attempts"
285
  msgstr ""
286
 
287
- #: ../dashboard.php:897 ../dashboard.php:898
288
  msgid "in 24 hours"
289
  msgstr ""
290
 
291
- #: ../dashboard.php:897 ../dashboard.php:898
292
  msgid "view all"
293
  msgstr ""
294
 
295
- #: ../dashboard.php:898
296
  msgid "lockouts"
297
  msgstr ""
298
 
299
- #: ../dashboard.php:900
300
  msgid "Lockouts at the moment"
301
  msgstr ""
302
 
303
- #: ../dashboard.php:901
304
  msgid "Last lockout"
305
  msgstr ""
306
 
307
- #: ../dashboard.php:902 ../dashboard.php:903 ../dashboard.php:1392
308
  msgid "entry"
309
  msgid_plural "entries"
310
  msgstr[0] ""
311
  msgstr[1] ""
312
 
313
- #: ../dashboard.php:904 ../settings.php:76
314
  msgid "Citadel mode"
315
  msgstr ""
316
 
317
- #: ../dashboard.php:906 ../settings.php:161
318
  msgid "Push notifications"
319
  msgstr ""
320
 
321
- #: ../dashboard.php:911 ../dashboard.php:1082 ../wp-cerber.php:2897 ../settings.
322
- #: php:82 ../settings.php:226
323
  msgid "Activity"
324
  msgstr ""
325
 
326
- #: ../dashboard.php:912 ../settings.php:230
327
  msgid "Lockouts"
328
  msgstr ""
329
 
330
- #: ../dashboard.php:913 ../dashboard.php:1413 ../wp-cerber.php:3030 ../settings.
331
- #: php:235 ../cerber-tools.php:87 ../cerber-tools.php:96 ../cerber-tools.php:162
332
  msgid "Access Lists"
333
  msgstr ""
334
 
335
- #: ../dashboard.php:1048
 
 
 
 
336
  msgid "Malicious activities mitigated"
337
  msgstr ""
338
 
339
- #: ../dashboard.php:1049
340
  msgid "Spam comments denied"
341
  msgstr ""
342
 
343
- #: ../dashboard.php:1050
344
- msgid "Malicious IP addresses detected"
345
  msgstr ""
346
 
347
- #: ../dashboard.php:1051
348
- msgid "Lockouts occurred"
349
  msgstr ""
350
 
351
- #: ../dashboard.php:1052
352
- msgid "Locked out IP now"
353
  msgstr ""
354
 
355
- #: ../dashboard.php:1068 ../dashboard.php:1097
356
  msgid "View all"
357
  msgstr ""
358
 
359
- #: ../dashboard.php:1076 ../common.php:334
360
  msgid "User registered"
361
  msgstr ""
362
 
363
- #: ../dashboard.php:1077
364
  msgid "All suspicious activity"
365
  msgstr ""
366
 
367
- #: ../dashboard.php:1098
368
  msgid "Recently locked out IP addresses"
369
  msgstr ""
370
 
371
- #: ../dashboard.php:1120
372
  msgid "Confused about some settings?"
373
  msgstr ""
374
 
375
- #: ../dashboard.php:1121
376
  msgid "You can easily load default recommended settings using button below"
377
  msgstr ""
378
 
379
- #: ../dashboard.php:1123
380
  msgid "Load default settings"
381
  msgstr ""
382
 
383
- #: ../dashboard.php:1125
384
  msgid "Are you sure?"
385
  msgstr ""
386
 
387
- #: ../dashboard.php:1131
388
  msgid "doesn't affect Custom login URL and Access Lists"
389
  msgstr ""
390
 
391
- #: ../dashboard.php:1150
392
  msgid "Donate"
393
  msgstr ""
394
 
395
- #: ../dashboard.php:1203
396
  msgid "Attention! Citadel mode is now active. Nobody is able to log in."
397
  msgstr ""
398
 
399
- #: ../dashboard.php:1204
400
  msgid "Deactivate"
401
  msgstr ""
402
 
403
- #: ../dashboard.php:1205
404
  msgid "View Activity"
405
  msgstr ""
406
 
407
- #: ../dashboard.php:1280
408
  msgid "New version is available"
409
  msgstr ""
410
 
411
- #: ../dashboard.php:1286
412
  #, php-format
413
  msgid "Update to version %s of WP Cerber"
414
  msgstr ""
415
 
416
- #: ../dashboard.php:1325
417
  msgid "Subscribe"
418
  msgstr ""
419
 
420
- #: ../dashboard.php:1326
421
  msgid "Unsubscribe"
422
  msgstr ""
423
 
424
- #: ../dashboard.php:1354
425
  msgid "You've subscribed"
426
  msgstr ""
427
 
428
- #: ../dashboard.php:1357
429
  msgid "You've unsubscribed"
430
  msgstr ""
431
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
432
  #. URI of the plugin
433
  msgid "http://wpcerber.com"
434
  msgstr ""
@@ -436,330 +482,354 @@ msgstr ""
436
  #. Description of the plugin
437
  msgid ""
438
  "Protects site from brute force attacks, bots and hackers. Antispam "
439
- "protection with reCAPTCHA. Comprehensive control of user activity. Restrict "
440
- "login by IP access lists. Limit login attempts. Know more: <a href=\"http:"
441
- "//wpcerber.com\">wpcerber.com</a>."
442
  msgstr ""
443
 
444
  #. Author of the plugin
445
  msgid "Gregory"
446
  msgstr ""
447
 
448
- #: ../wp-cerber.php:215
449
  msgid "You are not allowed to log in. Ask your administrator for assistance."
450
  msgstr ""
451
 
452
- #: ../wp-cerber.php:221
453
  #, php-format
454
  msgid "You have reached the login attempts limit. Please try again in %d minutes."
455
  msgstr ""
456
 
457
- #: ../wp-cerber.php:240
458
  #, php-format
459
  msgid "You have only one attempt remaining."
460
  msgid_plural "You have %d attempts remaining."
461
  msgstr[0] ""
462
  msgstr[1] ""
463
 
464
- #: ../wp-cerber.php:560 ../wp-cerber.php:572 ../wp-cerber.php:579 ../wp-cerber.
465
- #: php:746 ../wp-cerber.php:951 ../wp-cerber.php:956 ../wp-cerber.php:961 ../wp-
466
- #: cerber.php:967 ../wp-cerber.php:997 ../wp-cerber.php:1093 ../common.php:128 ..
467
- #: /common.php:181 ../common.php:185 ../settings.php:517
468
  msgid "ERROR:"
469
  msgstr ""
470
 
471
- #: ../wp-cerber.php:589
472
  msgid ""
473
  "Human verification failed. Please click the square box in the reCAPTCHA "
474
  "block below."
475
  msgstr ""
476
 
477
- #: ../wp-cerber.php:757
478
  #, php-format
479
  msgid ""
480
  "<strong>ERROR</strong>: The password you entered for the username %s is "
481
  "incorrect."
482
  msgstr ""
483
 
484
- #: ../wp-cerber.php:952 ../wp-cerber.php:968
485
  msgid "You are not allowed to register."
486
  msgstr ""
487
 
488
- #: ../wp-cerber.php:962
489
  msgid "Username is not allowed. Please choose another one."
490
  msgstr ""
491
 
492
- #: ../wp-cerber.php:1093
493
  msgid "Sorry, human verification failed."
494
  msgstr ""
495
 
496
- #: ../wp-cerber.php:2550
497
  msgid "WP Cerber notify"
498
  msgstr ""
499
 
500
- #: ../wp-cerber.php:2568
501
  msgid "Citadel mode is activated"
502
  msgstr ""
503
 
504
- #: ../wp-cerber.php:2570
505
  #, php-format
506
  msgid "Citadel mode is activated after %d failed login attempts in %d minutes."
507
  msgstr ""
508
 
509
- #: ../wp-cerber.php:2571
510
  #, php-format
511
  msgid "Last failed attempt was at %s from IP %s with user login: %s."
512
  msgstr ""
513
 
514
- #: ../wp-cerber.php:2572 ../wp-cerber.php:2922
515
  msgid "View activity in dashboard"
516
  msgstr ""
517
 
518
- #: ../wp-cerber.php:2597
519
  msgid "unspecified"
520
  msgstr ""
521
 
522
- #: ../wp-cerber.php:2600
523
  msgid "Number of lockouts is increasing"
524
  msgstr ""
525
 
526
- #: ../wp-cerber.php:2602
527
  msgid "Number of active lockouts"
528
  msgstr ""
529
 
530
- #: ../wp-cerber.php:2603
531
  #, php-format
532
  msgid "Last lockout was added: %s for IP %s"
533
  msgstr ""
534
 
535
- #: ../wp-cerber.php:2605
536
  msgid "View activity for this IP"
537
  msgstr ""
538
 
539
- #: ../wp-cerber.php:2606
540
  msgid "View lockouts in dashboard"
541
  msgstr ""
542
 
543
- #: ../wp-cerber.php:2609 ../wp-cerber.php:2611
544
  msgid "A new version of WP Cerber is available to install"
545
  msgstr ""
546
 
547
- #: ../wp-cerber.php:2610
548
  msgid "Hi!"
549
  msgstr ""
550
 
551
- #: ../wp-cerber.php:2612 ../wp-cerber.php:2623
552
  msgid "Website"
553
  msgstr ""
554
 
555
- #: ../wp-cerber.php:2615 ../wp-cerber.php:2616
556
  msgid "The WP Cerber security plugin has been deactivated"
557
  msgstr ""
558
 
559
- #: ../wp-cerber.php:2618
560
  msgid "Not logged in"
561
  msgstr ""
562
 
563
- #: ../wp-cerber.php:2624
564
  msgid "By user"
565
  msgstr ""
566
 
567
- #: ../wp-cerber.php:2625
568
  msgid "From IP address"
569
  msgstr ""
570
 
571
- #: ../wp-cerber.php:2628
572
  msgid "From country"
573
  msgstr ""
574
 
575
- #: ../wp-cerber.php:2632
576
  msgid "The WP Cerber security plugin is now active"
577
  msgstr ""
578
 
579
- #: ../wp-cerber.php:2633 ../wp-cerber.php:3023
580
  msgid "WP Cerber is now active and has started protecting your site"
581
  msgstr ""
582
 
583
- #: ../wp-cerber.php:2634
584
  msgid "Change notification settings"
585
  msgstr ""
586
 
587
- #: ../wp-cerber.php:2639
588
  msgid "New Custom login URL"
589
  msgstr ""
590
 
591
- #: ../wp-cerber.php:2643 ../wp-cerber.php:2644
592
  msgid "A new activity has been recorded"
593
  msgstr ""
594
 
595
- #: ../wp-cerber.php:2659
596
  msgid "This message was sent by"
597
  msgstr ""
598
 
599
- #: ../wp-cerber.php:2902
600
  msgid "User"
601
  msgstr ""
602
 
603
- #: ../wp-cerber.php:2910
604
  msgid "Search string"
605
  msgstr ""
606
 
607
- #: ../wp-cerber.php:2923
608
  msgid "To unsubscribe click here"
609
  msgstr ""
610
 
611
- #: ../wp-cerber.php:2998
612
  #, php-format
613
  msgid "The WP Cerber requires PHP %s or higher. You are running"
614
  msgstr ""
615
 
616
- #: ../wp-cerber.php:3002
617
  #, php-format
618
  msgid "The WP Cerber requires WordPress %s or higher. You are running"
619
  msgstr ""
620
 
621
- #: ../wp-cerber.php:3007
622
  msgid "Can't activate WP Cerber due to a database error."
623
  msgstr ""
624
 
625
- #: ../wp-cerber.php:3024
626
  msgid "Your IP address is added to the"
627
  msgstr ""
628
 
629
- #: ../wp-cerber.php:3026
630
- msgid "It's important to check security settings."
631
- msgstr ""
632
-
633
- #: ../wp-cerber.php:3029 ../settings.php:232
634
  msgid "Main Settings"
635
  msgstr ""
636
 
637
- #: ../wp-cerber.php:3032 ../settings.php:237
638
  msgid "Hardening"
639
  msgstr ""
640
 
641
- #: ../wp-cerber.php:3033 ../settings.php:62 ../settings.php:80 ../settings.php:242
642
  msgid "Notifications"
643
  msgstr ""
644
 
645
- #: ../wp-cerber.php:3034
646
  msgid "Import settings"
647
  msgstr ""
648
 
649
- #: ../whois.php:210 ../common.php:375
650
  msgid "Unknown"
651
  msgstr ""
652
 
653
- #: ../common.php:333
654
  msgid "User created"
655
  msgstr ""
656
 
657
- #: ../common.php:335
658
  msgid "Logged in"
659
  msgstr ""
660
 
661
- #: ../common.php:336
662
  msgid "Logged out"
663
  msgstr ""
664
 
665
- #: ../common.php:337
666
  msgid "Login failed"
667
  msgstr ""
668
 
669
- #: ../common.php:340
670
  msgid "IP blocked"
671
  msgstr ""
672
 
673
- #: ../common.php:341
674
  msgid "Subnet blocked"
675
  msgstr ""
676
 
677
- #: ../common.php:343
678
  msgid "Citadel activated!"
679
  msgstr ""
680
 
681
- #: ../common.php:344
682
  msgid "Spam comment denied"
683
  msgstr ""
684
 
685
- #: ../common.php:345
686
  msgid "Spam form submission denied"
687
  msgstr ""
688
 
689
- #: ../common.php:349
690
- msgid "IP blacklisted"
691
  msgstr ""
692
 
693
- #: ../common.php:351
694
- msgid "by Cerber Lab"
695
  msgstr ""
696
 
697
- #: ../common.php:355
698
  msgid "Password changed"
699
  msgstr ""
700
 
701
- #: ../common.php:356
702
  msgid "Password reset requested"
703
  msgstr ""
704
 
705
- #: ../common.php:358
706
  msgid "reCAPTCHA verification failed"
707
  msgstr ""
708
 
709
- #: ../common.php:359
710
  msgid "reCAPTCHA settings are incorrect"
711
  msgstr ""
712
 
713
- #: ../common.php:360
714
  msgid "Request to the Google reCAPTCHA service failed"
715
  msgstr ""
716
 
717
- #: ../common.php:362
718
  msgid "Attempt to access prohibited URL"
719
  msgstr ""
720
 
721
- #: ../common.php:363 ../common.php:378
722
  msgid "Attempt to log in with non-existent username"
723
  msgstr ""
724
 
725
- #: ../common.php:364 ../common.php:379
726
  msgid "Attempt to log in with prohibited username"
727
  msgstr ""
728
 
729
- #: ../common.php:366
730
  msgid "Attempt to log in denied"
731
  msgstr ""
732
 
733
- #: ../common.php:367
734
  msgid "Attempt to register denied"
735
  msgstr ""
736
 
737
- #: ../common.php:376
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
738
  msgid "Limit on login attempts is reached"
739
  msgstr ""
740
 
741
- #: ../common.php:377
742
  msgid "Attempt to access"
743
  msgstr ""
744
 
745
- #: ../common.php:380
746
  msgid "Limit on failed reCAPTCHA verifications is reached"
747
  msgstr ""
748
 
749
- #: ../common.php:381
750
  msgid "Bot activity is detected"
751
  msgstr ""
752
 
753
- #: ../common.php:433
754
  #, php-format
755
  msgid "%s ago"
756
  msgstr ""
757
 
758
- #: ../cerber-lab.php:576
759
  msgid "Want to make WP Cerber even more powerful?"
760
  msgstr ""
761
 
762
- #: ../cerber-lab.php:577
763
  msgid ""
764
  "Allow WP Cerber to send locked out malicious IP addresses to Cerber Lab. "
765
  "This helps the plugin team to develop new algorithms for WP Cerber that will "
@@ -767,15 +837,15 @@ msgid ""
767
  "everyday. You can disable the sending in the plugin settings at any time."
768
  msgstr ""
769
 
770
- #: ../cerber-lab.php:578
771
  msgid "OK, nail them all"
772
  msgstr ""
773
 
774
- #: ../cerber-lab.php:579
775
  msgid "NO, maybe later"
776
  msgstr ""
777
 
778
- #: ../cerber-lab.php:580 ../settings.php:200
779
  msgid "Know more"
780
  msgstr ""
781
 
@@ -807,10 +877,6 @@ msgstr ""
807
  msgid "Site connection"
808
  msgstr ""
809
 
810
- #: ../settings.php:63
811
- msgid "My site is behind a reverse proxy"
812
- msgstr ""
813
-
814
  #: ../settings.php:65
815
  msgid "Proactive security rules"
816
  msgstr ""
@@ -885,7 +951,7 @@ msgstr ""
885
  msgid "Send notification to admin email"
886
  msgstr ""
887
 
888
- #: ../settings.php:80 ../settings.php:371
889
  msgid "Click to send test"
890
  msgstr ""
891
 
@@ -893,7 +959,7 @@ msgstr ""
893
  msgid "Keep records for"
894
  msgstr ""
895
 
896
- #: ../settings.php:83 ../settings.php:130
897
  msgid "days"
898
  msgstr ""
899
 
@@ -947,7 +1013,7 @@ msgid "Stop user enumeration"
947
  msgstr ""
948
 
949
  #: ../settings.php:98
950
- msgid "Block access to the pages like /?author=n"
951
  msgstr ""
952
 
953
  #: ../settings.php:99
@@ -971,272 +1037,292 @@ msgid "Disable REST API"
971
  msgstr ""
972
 
973
  #: ../settings.php:101
974
- msgid "Block access to the WordPress REST API"
975
  msgstr ""
976
 
977
- #: ../settings.php:110
978
- msgid "User related settings"
 
 
 
 
 
 
979
  msgstr ""
980
 
981
  #: ../settings.php:111
 
 
 
 
982
  msgid "Prohibited usernames"
983
  msgstr ""
984
 
985
- #: ../settings.php:111
986
  msgid ""
987
  "Usernames from this list are not allowed to log in or register. Any IP "
988
  "address, have tried to use any of these usernames, will be immediately "
989
  "blocked. Use comma to separate logins."
990
  msgstr ""
991
 
992
- #: ../settings.php:112
993
  msgid "User session expire"
994
  msgstr ""
995
 
996
- #: ../settings.php:112
997
  msgid "in minutes (leave empty to use default WP value)"
998
  msgstr ""
999
 
1000
- #: ../settings.php:119
1001
  msgid "Cerber antispam engine"
1002
  msgstr ""
1003
 
1004
- #: ../settings.php:120
1005
  msgid "Comment form"
1006
  msgstr ""
1007
 
1008
- #: ../settings.php:120
1009
  msgid "Protect comment form with bot detection engine"
1010
  msgstr ""
1011
 
1012
- #: ../settings.php:121 ../settings.php:138
1013
  msgid "Registration form"
1014
  msgstr ""
1015
 
1016
- #: ../settings.php:121
1017
  msgid "Protect registration form with bot detection engine"
1018
  msgstr ""
1019
 
1020
- #: ../settings.php:122
1021
  msgid "Other forms"
1022
  msgstr ""
1023
 
1024
- #: ../settings.php:122
1025
  msgid "Protect all forms on the website with bot detection engine"
1026
  msgstr ""
1027
 
1028
- #: ../settings.php:124
1029
  msgid "Adjust antispam engine"
1030
  msgstr ""
1031
 
1032
- #: ../settings.php:125
1033
  msgid "Safe mode"
1034
  msgstr ""
1035
 
1036
- #: ../settings.php:125
1037
  msgid "Use less restrictive policies (allow AJAX)"
1038
  msgstr ""
1039
 
1040
- #: ../settings.php:126
1041
  msgid "Logged in users"
1042
  msgstr ""
1043
 
1044
- #: ../settings.php:126
1045
  msgid "Disable bot detection engine for logged in users"
1046
  msgstr ""
1047
 
1048
  #: ../settings.php:128
 
 
 
 
 
 
 
 
 
 
1049
  msgid "Comment processing"
1050
  msgstr ""
1051
 
1052
- #: ../settings.php:129
1053
  msgid "If a spam comment detected"
1054
  msgstr ""
1055
 
1056
- #: ../settings.php:130
1057
  msgid "Trash spam comments"
1058
  msgstr ""
1059
 
1060
- #: ../settings.php:130
1061
  msgid "Move spam comments to trash after"
1062
  msgstr ""
1063
 
1064
- #: ../settings.php:133
1065
  msgid "reCAPTCHA settings"
1066
  msgstr ""
1067
 
1068
- #: ../settings.php:134
1069
  msgid "Site key"
1070
  msgstr ""
1071
 
1072
- #: ../settings.php:135
1073
  msgid "Secret key"
1074
  msgstr ""
1075
 
1076
- #: ../settings.php:136
1077
  msgid "Invisible reCAPTCHA"
1078
  msgstr ""
1079
 
1080
- #: ../settings.php:136
1081
  msgid "Enable invisible reCAPTCHA"
1082
  msgstr ""
1083
 
1084
- #: ../settings.php:136
1085
  msgid ""
1086
  "(do not enable it unless you get and enter the Site and Secret keys for the "
1087
  "invisible version)"
1088
  msgstr ""
1089
 
1090
- #: ../settings.php:138
1091
  msgid "Enable reCAPTCHA for WordPress registration form"
1092
  msgstr ""
1093
 
1094
- #: ../settings.php:139
1095
  msgid "Enable reCAPTCHA for WooCommerce registration form"
1096
  msgstr ""
1097
 
1098
- #: ../settings.php:141
1099
  msgid "Lost password form"
1100
  msgstr ""
1101
 
1102
- #: ../settings.php:141
1103
  msgid "Enable reCAPTCHA for WordPress lost password form"
1104
  msgstr ""
1105
 
1106
- #: ../settings.php:142
1107
  msgid "Enable reCAPTCHA for WooCommerce lost password form"
1108
  msgstr ""
1109
 
1110
- #: ../settings.php:144
1111
  msgid "Login form"
1112
  msgstr ""
1113
 
1114
- #: ../settings.php:144
1115
  msgid "Enable reCAPTCHA for WordPress login form"
1116
  msgstr ""
1117
 
1118
- #: ../settings.php:145
1119
  msgid "Enable reCAPTCHA for WooCommerce login form"
1120
  msgstr ""
1121
 
1122
- #: ../settings.php:147
1123
  msgid "Enable reCAPTCHA for WordPress comment form"
1124
  msgstr ""
1125
 
1126
- #: ../settings.php:148
1127
  msgid "Disable reCAPTCHA for logged in users"
1128
  msgstr ""
1129
 
1130
- #: ../settings.php:150
1131
  msgid "Limit attempts"
1132
  msgstr ""
1133
 
1134
- #: ../settings.php:150
1135
  #, php-format
1136
  msgid "Lock out IP address for %s minutes after %s failed attempts within %s minutes"
1137
  msgstr ""
1138
 
1139
- #: ../settings.php:156
1140
  msgid "Email notifications"
1141
  msgstr ""
1142
 
1143
- #: ../settings.php:158
1144
  msgid "Email Address"
1145
  msgstr ""
1146
 
1147
- #: ../settings.php:158
1148
  msgid "Use comma to specify multiple values"
1149
  msgstr ""
1150
 
1151
- #: ../settings.php:158
1152
  #, php-format
1153
  msgid "if empty, the admin email %s will be used"
1154
  msgstr ""
1155
 
1156
- #: ../settings.php:159
1157
  msgid "Notification limit"
1158
  msgstr ""
1159
 
1160
- #: ../settings.php:159
1161
  msgid "notification letters allowed per hour (0 means unlimited)"
1162
  msgstr ""
1163
 
1164
- #: ../settings.php:168
1165
  msgid "All connected devices"
1166
  msgstr ""
1167
 
1168
- #: ../settings.php:169
1169
  msgid "No devices found"
1170
  msgstr ""
1171
 
1172
- #: ../settings.php:171
1173
  msgid "Not available"
1174
  msgstr ""
1175
 
1176
- #: ../settings.php:182
1177
  msgid "Make your protection smarter!"
1178
  msgstr ""
1179
 
1180
- #: ../settings.php:186
1181
  msgid ""
1182
  "Please enable Permalinks to use this feature. Set Permalink Settings to "
1183
  "something other than Default."
1184
  msgstr ""
1185
 
1186
- #: ../settings.php:189
1187
  msgid ""
1188
  "Be careful when enabling this options. If you forget the custom login URL "
1189
  "you will not be able to login."
1190
  msgstr ""
1191
 
1192
- #: ../settings.php:193
1193
  msgid ""
1194
  "In the Citadel mode nobody is able to log in except IPs from the White IP "
1195
  "Access List. Active user sessions will not be affected."
1196
  msgstr ""
1197
 
1198
- #: ../settings.php:196
1199
  msgid "These settings do not affect hosts from the "
1200
  msgstr ""
1201
 
1202
- #: ../settings.php:199
1203
  msgid ""
1204
  "Before you can start using reCAPTCHA, you have to obtain Site key and Secret "
1205
  "key on the Google website"
1206
  msgstr ""
1207
 
1208
- #: ../settings.php:239
1209
  msgid "Users"
1210
  msgstr ""
1211
 
1212
- #: ../settings.php:244
1213
  msgid "Help"
1214
  msgstr ""
1215
 
1216
- #: ../settings.php:357
1217
  #, php-format
1218
  msgid "%s allowed retries in %s minutes"
1219
  msgstr ""
1220
 
1221
- #: ../settings.php:362
1222
  #, php-format
1223
  msgid "Increase lockout duration to %s hours after %s lockouts in the last %s hours"
1224
  msgstr ""
1225
 
1226
- #: ../settings.php:369
1227
  msgid "Notify admin if the number of active lockouts above"
1228
  msgstr ""
1229
 
1230
- #: ../settings.php:374
1231
  #, php-format
1232
  msgid "Enable after %s failed login attempts in last %s minutes"
1233
  msgstr ""
1234
 
1235
- #: ../settings.php:464
1236
  msgid "Attention! You have changed the login URL! The new login URL is"
1237
  msgstr ""
1238
 
1239
- #: ../settings.php:544
1240
  msgid "<strong>ERROR</strong>: please enter a valid email address."
1241
  msgstr ""
1242
 
@@ -1248,6 +1334,10 @@ msgstr ""
1248
  msgid "Diagnostic"
1249
  msgstr ""
1250
 
 
 
 
 
1251
  #: ../cerber-tools.php:83
1252
  msgid "Export settings to the file"
1253
  msgstr ""
@@ -1297,22 +1387,22 @@ msgstr ""
1297
  msgid "Upload file"
1298
  msgstr ""
1299
 
1300
- #: ../cerber-tools.php:132
1301
  msgid "No file was uploaded or file is corrupted"
1302
  msgstr ""
1303
 
1304
- #: ../cerber-tools.php:162
1305
  msgid "Error while updating"
1306
  msgstr ""
1307
 
1308
- #: ../cerber-tools.php:165
1309
  msgid "Settings has imported successfully from"
1310
  msgstr ""
1311
 
1312
- #: ../cerber-tools.php:169
1313
  msgid "Error while parsing file"
1314
  msgstr ""
1315
 
1316
- #: ../cerber-tools.php:267
1317
  msgid "Antispam and bot detection settings"
1318
  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: Sun Oct 29 2017 17:10:49 GMT+0300\n"
9
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
10
  "Last-Translator: \n"
11
  "Language-Team: \n"
24
  "esc_html_x:1,2c;comments_number_link:2,3;t:1;st:1;trans:1;transChoice:1,2\n"
25
  "X-Generator: Loco - https://localise.biz/"
26
 
27
+ #: ../dashboard.php:74 ../dashboard.php:128
28
  msgid "Remove"
29
  msgstr ""
30
 
31
+ #: ../dashboard.php:77 ../dashboard.php:582 ../wp-cerber.php:3149
32
  msgid "IP"
33
  msgstr ""
34
 
35
+ #: ../dashboard.php:77 ../dashboard.php:583
36
  msgid "Hostname"
37
  msgstr ""
38
 
40
  msgid "Expires"
41
  msgstr ""
42
 
43
+ #: ../dashboard.php:77 ../wp-cerber.php:2838
44
  msgid "Reason"
45
  msgstr ""
46
 
65
  msgid "No lockouts at the moment. The sky is clear."
66
  msgstr ""
67
 
68
+ #: ../dashboard.php:102 ../dashboard.php:540 ../dashboard.php:762 ../dashboard.
69
+ #: php:1019 ../wp-cerber.php:3288 ../settings.php:61 ../settings.php:198
70
  msgid "White IP Access List"
71
  msgstr ""
72
 
74
  msgid "These IPs will never be locked out"
75
  msgstr ""
76
 
77
+ #: ../dashboard.php:104 ../dashboard.php:541 ../dashboard.php:764 ../dashboard.
78
+ #: php:1020
79
  msgid "Black IP Access List"
80
  msgstr ""
81
 
83
  msgid "Nobody can log in or register from these IPs"
84
  msgstr ""
85
 
86
+ #: ../dashboard.php:111
87
  msgid "Your IP"
88
  msgstr ""
89
 
90
+ #: ../dashboard.php:128 ../dashboard.php:794
91
  msgid "Check for activity"
92
  msgstr ""
93
 
94
+ #: ../dashboard.php:131
95
  msgid "List is empty"
96
  msgstr ""
97
 
98
+ #: ../dashboard.php:135
99
  msgid "Add IP to the list"
100
  msgstr ""
101
 
102
+ #: ../dashboard.php:155 ../dashboard.php:163
103
  msgid "Incorrect IP address or IP range"
104
  msgstr ""
105
 
106
+ #: ../dashboard.php:158
107
  #, php-format
108
  msgid "Address %s was added to White IP Access List"
109
  msgstr ""
110
 
111
+ #: ../dashboard.php:167
112
  msgid "You can't add your IP address"
113
  msgstr ""
114
 
115
+ #: ../dashboard.php:171
116
  #, php-format
117
  msgid "Address %s was added to Black IP Access List"
118
  msgstr ""
119
 
120
+ #: ../dashboard.php:287
121
  msgid "unknown"
122
  msgstr ""
123
 
124
+ #: ../dashboard.php:309
125
  msgid "Message has been sent to "
126
  msgstr ""
127
 
128
+ #: ../dashboard.php:312
129
  msgid "Unable to send notification email"
130
  msgstr ""
131
 
132
+ #: ../dashboard.php:320
133
  #, php-format
134
  msgid "Lockout for %s was removed"
135
  msgstr ""
136
 
137
+ #: ../dashboard.php:337 ../dashboard.php:1344
138
  msgid "Settings saved"
139
  msgstr ""
140
 
141
+ #: ../dashboard.php:408
142
  msgid "IP address"
143
  msgstr ""
144
 
145
+ #: ../dashboard.php:408 ../dashboard.php:585
146
  msgid "Date"
147
  msgstr ""
148
 
149
+ #: ../dashboard.php:408 ../dashboard.php:586
150
  msgid "Event"
151
  msgstr ""
152
 
153
+ #: ../dashboard.php:408 ../dashboard.php:587
154
  msgid "Local User"
155
  msgstr ""
156
 
157
+ #: ../dashboard.php:408
158
  msgid "User login"
159
  msgstr ""
160
 
161
+ #: ../dashboard.php:408
162
  msgid "User ID"
163
  msgstr ""
164
 
165
+ #: ../dashboard.php:408 ../dashboard.php:588 ../wp-cerber.php:3157
166
  msgid "Username used"
167
  msgstr ""
168
 
169
+ #: ../dashboard.php:545 ../dashboard.php:767 ../common.php:472
170
  msgid "Locked out"
171
  msgstr ""
172
 
173
+ #: ../dashboard.php:584
174
+ msgid "Country"
175
+ msgstr ""
176
+
177
+ #: ../dashboard.php:605
178
  msgid "Export"
179
  msgstr ""
180
 
181
+ #: ../dashboard.php:609
182
  msgid "No activity has been logged."
183
  msgstr ""
184
 
185
+ #: ../dashboard.php:615
186
+ msgid "All events"
187
  msgstr ""
188
 
189
+ #: ../dashboard.php:624
190
  msgid "Search for IP or username"
191
  msgstr ""
192
 
193
+ #: ../dashboard.php:624
194
  msgid "Filter"
195
  msgstr ""
196
 
197
+ #: ../dashboard.php:790
198
  msgid "Abuse email:"
199
  msgstr ""
200
 
201
+ #: ../dashboard.php:794
202
  msgid "Network:"
203
  msgstr ""
204
 
205
+ #: ../dashboard.php:808
206
  msgid "Add network to the Black List"
207
  msgstr ""
208
 
209
+ #: ../dashboard.php:812
210
  msgid "Add IP to the Black List"
211
  msgstr ""
212
 
213
+ #: ../dashboard.php:843 ../settings.php:221
214
  msgid "WP Cerber Security"
215
  msgstr ""
216
 
217
  #. Name of the plugin
218
+ #: ../dashboard.php:843 ../dashboard.php:862
219
  msgid "WP Cerber"
220
  msgstr ""
221
 
222
+ #: ../dashboard.php:845
223
  msgid "Cerber Dashboard"
224
  msgstr ""
225
 
226
+ #: ../dashboard.php:845 ../dashboard.php:1027 ../dashboard.php:1536 ../settings.
227
+ #: php:226
228
  msgid "Dashboard"
229
  msgstr ""
230
 
231
+ #: ../dashboard.php:848
232
+ msgid "Cerber Security Rules"
233
+ msgstr ""
234
+
235
+ #: ../dashboard.php:848 ../dashboard.php:1820
236
+ msgid "Security Rules"
237
+ msgstr ""
238
+
239
+ #: ../dashboard.php:851
240
  msgid "Cerber antispam settings"
241
  msgstr ""
242
 
243
+ #: ../dashboard.php:851 ../wp-cerber.php:3297 ../settings.php:149
244
  msgid "Antispam"
245
  msgstr ""
246
 
247
+ #: ../dashboard.php:852
248
  msgid "Cerber tools"
249
  msgstr ""
250
 
251
+ #: ../dashboard.php:852 ../cerber-tools.php:43
252
  msgid "Tools"
253
  msgstr ""
254
 
255
+ #: ../dashboard.php:913
256
  msgid "Comments"
257
  msgstr ""
258
 
259
+ #: ../dashboard.php:914
260
  msgid "Last login"
261
  msgstr ""
262
 
263
+ #: ../dashboard.php:915
264
  msgid "Failed attempts in last 24 hours"
265
  msgstr ""
266
 
267
+ #: ../dashboard.php:916
268
  msgid "Date of registration"
269
  msgstr ""
270
 
271
+ #: ../dashboard.php:947 ../dashboard.php:1002
272
  msgid "Never"
273
  msgstr ""
274
 
275
+ #: ../dashboard.php:971
276
  msgid "Cerber Quick View"
277
  msgstr ""
278
 
279
+ #: ../dashboard.php:1006
280
  msgid "active"
281
  msgstr ""
282
 
283
+ #: ../dashboard.php:1006
284
  msgid "deactivate"
285
  msgstr ""
286
 
287
+ #: ../dashboard.php:1008
288
  msgid "not active"
289
  msgstr ""
290
 
291
+ #: ../dashboard.php:1009
292
  msgid "disabled"
293
  msgstr ""
294
 
295
+ #: ../dashboard.php:1014
296
  msgid "failed attempts"
297
  msgstr ""
298
 
299
+ #: ../dashboard.php:1014 ../dashboard.php:1015
300
  msgid "in 24 hours"
301
  msgstr ""
302
 
303
+ #: ../dashboard.php:1014 ../dashboard.php:1015
304
  msgid "view all"
305
  msgstr ""
306
 
307
+ #: ../dashboard.php:1015
308
  msgid "lockouts"
309
  msgstr ""
310
 
311
+ #: ../dashboard.php:1017
312
  msgid "Lockouts at the moment"
313
  msgstr ""
314
 
315
+ #: ../dashboard.php:1018
316
  msgid "Last lockout"
317
  msgstr ""
318
 
319
+ #: ../dashboard.php:1019 ../dashboard.php:1020 ../dashboard.php:1516
320
  msgid "entry"
321
  msgid_plural "entries"
322
  msgstr[0] ""
323
  msgstr[1] ""
324
 
325
+ #: ../dashboard.php:1021 ../settings.php:76
326
  msgid "Citadel mode"
327
  msgstr ""
328
 
329
+ #: ../dashboard.php:1023 ../settings.php:163
330
  msgid "Push notifications"
331
  msgstr ""
332
 
333
+ #: ../dashboard.php:1028 ../dashboard.php:1204 ../wp-cerber.php:3140 ../settings.
334
+ #: php:82 ../settings.php:228
335
  msgid "Activity"
336
  msgstr ""
337
 
338
+ #: ../dashboard.php:1029 ../settings.php:232
339
  msgid "Lockouts"
340
  msgstr ""
341
 
342
+ #: ../dashboard.php:1030 ../dashboard.php:1537 ../wp-cerber.php:3296 ../settings.
343
+ #: php:237 ../cerber-tools.php:87 ../cerber-tools.php:96 ../cerber-tools.php:170
344
  msgid "Access Lists"
345
  msgstr ""
346
 
347
+ #: ../dashboard.php:1056 ../settings.php:63
348
+ msgid "My site is behind a reverse proxy"
349
+ msgstr ""
350
+
351
+ #: ../dashboard.php:1169
352
  msgid "Malicious activities mitigated"
353
  msgstr ""
354
 
355
+ #: ../dashboard.php:1170
356
  msgid "Spam comments denied"
357
  msgstr ""
358
 
359
+ #: ../dashboard.php:1171
360
+ msgid "Spam form submissions denied"
361
  msgstr ""
362
 
363
+ #: ../dashboard.php:1172
364
+ msgid "Malicious IP addresses detected"
365
  msgstr ""
366
 
367
+ #: ../dashboard.php:1173
368
+ msgid "Lockouts occurred"
369
  msgstr ""
370
 
371
+ #: ../dashboard.php:1190 ../dashboard.php:1219
372
  msgid "View all"
373
  msgstr ""
374
 
375
+ #: ../dashboard.php:1198 ../common.php:427
376
  msgid "User registered"
377
  msgstr ""
378
 
379
+ #: ../dashboard.php:1199
380
  msgid "All suspicious activity"
381
  msgstr ""
382
 
383
+ #: ../dashboard.php:1220
384
  msgid "Recently locked out IP addresses"
385
  msgstr ""
386
 
387
+ #: ../dashboard.php:1242
388
  msgid "Confused about some settings?"
389
  msgstr ""
390
 
391
+ #: ../dashboard.php:1243
392
  msgid "You can easily load default recommended settings using button below"
393
  msgstr ""
394
 
395
+ #: ../dashboard.php:1245
396
  msgid "Load default settings"
397
  msgstr ""
398
 
399
+ #: ../dashboard.php:1247
400
  msgid "Are you sure?"
401
  msgstr ""
402
 
403
+ #: ../dashboard.php:1253
404
  msgid "doesn't affect Custom login URL and Access Lists"
405
  msgstr ""
406
 
407
+ #: ../dashboard.php:1273
408
  msgid "Donate"
409
  msgstr ""
410
 
411
+ #: ../dashboard.php:1327
412
  msgid "Attention! Citadel mode is now active. Nobody is able to log in."
413
  msgstr ""
414
 
415
+ #: ../dashboard.php:1328
416
  msgid "Deactivate"
417
  msgstr ""
418
 
419
+ #: ../dashboard.php:1329
420
  msgid "View Activity"
421
  msgstr ""
422
 
423
+ #: ../dashboard.php:1404
424
  msgid "New version is available"
425
  msgstr ""
426
 
427
+ #: ../dashboard.php:1410
428
  #, php-format
429
  msgid "Update to version %s of WP Cerber"
430
  msgstr ""
431
 
432
+ #: ../dashboard.php:1449
433
  msgid "Subscribe"
434
  msgstr ""
435
 
436
+ #: ../dashboard.php:1450 ../cerber-tools.php:225
437
  msgid "Unsubscribe"
438
  msgstr ""
439
 
440
+ #: ../dashboard.php:1478
441
  msgid "You've subscribed"
442
  msgstr ""
443
 
444
+ #: ../dashboard.php:1481
445
  msgid "You've unsubscribed"
446
  msgstr ""
447
 
448
+ #: ../dashboard.php:1825
449
+ msgid "Countries"
450
+ msgstr ""
451
+
452
+ #: ../dashboard.php:1889
453
+ #, php-format
454
+ msgid "Permitted for one country"
455
+ msgid_plural "Permitted for %d countries"
456
+ msgstr[0] ""
457
+ msgstr[1] ""
458
+
459
+ #: ../dashboard.php:1892
460
+ #, php-format
461
+ msgid "Blocked for one country"
462
+ msgid_plural "Blocked for %d countries"
463
+ msgstr[0] ""
464
+ msgstr[1] ""
465
+
466
+ #: ../dashboard.php:1896
467
+ msgid "No rule"
468
+ msgstr ""
469
+
470
+ #: ../dashboard.php:2092
471
+ msgid "Security rules have been updated"
472
+ msgstr ""
473
+
474
+ #. Name of the plugin
475
+ msgid "WP Cerber Security & Antispam"
476
+ msgstr ""
477
+
478
  #. URI of the plugin
479
  msgid "http://wpcerber.com"
480
  msgstr ""
482
  #. Description of the plugin
483
  msgid ""
484
  "Protects site from brute force attacks, bots and hackers. Antispam "
485
+ "protection with the Cerber antispam engine and reCAPTCHA. Comprehensive "
486
+ "control of user activity. Restrict login by IP access lists. Limit login "
487
+ "attempts. Know more: <a href=\"http://wpcerber.com\">wpcerber.com</a>."
488
  msgstr ""
489
 
490
  #. Author of the plugin
491
  msgid "Gregory"
492
  msgstr ""
493
 
494
+ #: ../wp-cerber.php:217
495
  msgid "You are not allowed to log in. Ask your administrator for assistance."
496
  msgstr ""
497
 
498
+ #: ../wp-cerber.php:223
499
  #, php-format
500
  msgid "You have reached the login attempts limit. Please try again in %d minutes."
501
  msgstr ""
502
 
503
+ #: ../wp-cerber.php:242
504
  #, php-format
505
  msgid "You have only one attempt remaining."
506
  msgid_plural "You have %d attempts remaining."
507
  msgstr[0] ""
508
  msgstr[1] ""
509
 
510
+ #: ../wp-cerber.php:562 ../wp-cerber.php:574 ../wp-cerber.php:581 ../wp-cerber.
511
+ #: php:758 ../wp-cerber.php:973 ../wp-cerber.php:978 ../wp-cerber.php:983 ../wp-
512
+ #: cerber.php:989 ../wp-cerber.php:996 ../wp-cerber.php:1053 ../wp-cerber.php:
513
+ #: 1190 ../common.php:131 ../common.php:184 ../common.php:188 ../settings.php:516
514
  msgid "ERROR:"
515
  msgstr ""
516
 
517
+ #: ../wp-cerber.php:591
518
  msgid ""
519
  "Human verification failed. Please click the square box in the reCAPTCHA "
520
  "block below."
521
  msgstr ""
522
 
523
+ #: ../wp-cerber.php:769
524
  #, php-format
525
  msgid ""
526
  "<strong>ERROR</strong>: The password you entered for the username %s is "
527
  "incorrect."
528
  msgstr ""
529
 
530
+ #: ../wp-cerber.php:974 ../wp-cerber.php:990 ../wp-cerber.php:997
531
  msgid "You are not allowed to register."
532
  msgstr ""
533
 
534
+ #: ../wp-cerber.php:984
535
  msgid "Username is not allowed. Please choose another one."
536
  msgstr ""
537
 
538
+ #: ../wp-cerber.php:1190
539
  msgid "Sorry, human verification failed."
540
  msgstr ""
541
 
542
+ #: ../wp-cerber.php:2784
543
  msgid "WP Cerber notify"
544
  msgstr ""
545
 
546
+ #: ../wp-cerber.php:2802
547
  msgid "Citadel mode is activated"
548
  msgstr ""
549
 
550
+ #: ../wp-cerber.php:2804
551
  #, php-format
552
  msgid "Citadel mode is activated after %d failed login attempts in %d minutes."
553
  msgstr ""
554
 
555
+ #: ../wp-cerber.php:2805
556
  #, php-format
557
  msgid "Last failed attempt was at %s from IP %s with user login: %s."
558
  msgstr ""
559
 
560
+ #: ../wp-cerber.php:2806 ../wp-cerber.php:3181
561
  msgid "View activity in dashboard"
562
  msgstr ""
563
 
564
+ #: ../wp-cerber.php:2831
565
  msgid "unspecified"
566
  msgstr ""
567
 
568
+ #: ../wp-cerber.php:2834
569
  msgid "Number of lockouts is increasing"
570
  msgstr ""
571
 
572
+ #: ../wp-cerber.php:2836
573
  msgid "Number of active lockouts"
574
  msgstr ""
575
 
576
+ #: ../wp-cerber.php:2837
577
  #, php-format
578
  msgid "Last lockout was added: %s for IP %s"
579
  msgstr ""
580
 
581
+ #: ../wp-cerber.php:2839
582
  msgid "View activity for this IP"
583
  msgstr ""
584
 
585
+ #: ../wp-cerber.php:2840
586
  msgid "View lockouts in dashboard"
587
  msgstr ""
588
 
589
+ #: ../wp-cerber.php:2843 ../wp-cerber.php:2845
590
  msgid "A new version of WP Cerber is available to install"
591
  msgstr ""
592
 
593
+ #: ../wp-cerber.php:2844
594
  msgid "Hi!"
595
  msgstr ""
596
 
597
+ #: ../wp-cerber.php:2846 ../wp-cerber.php:2857
598
  msgid "Website"
599
  msgstr ""
600
 
601
+ #: ../wp-cerber.php:2849 ../wp-cerber.php:2850
602
  msgid "The WP Cerber security plugin has been deactivated"
603
  msgstr ""
604
 
605
+ #: ../wp-cerber.php:2852
606
  msgid "Not logged in"
607
  msgstr ""
608
 
609
+ #: ../wp-cerber.php:2858
610
  msgid "By user"
611
  msgstr ""
612
 
613
+ #: ../wp-cerber.php:2859
614
  msgid "From IP address"
615
  msgstr ""
616
 
617
+ #: ../wp-cerber.php:2862
618
  msgid "From country"
619
  msgstr ""
620
 
621
+ #: ../wp-cerber.php:2866
622
  msgid "The WP Cerber security plugin is now active"
623
  msgstr ""
624
 
625
+ #: ../wp-cerber.php:2867 ../wp-cerber.php:3287
626
  msgid "WP Cerber is now active and has started protecting your site"
627
  msgstr ""
628
 
629
+ #: ../wp-cerber.php:2868
630
  msgid "Change notification settings"
631
  msgstr ""
632
 
633
+ #: ../wp-cerber.php:2873
634
  msgid "New Custom login URL"
635
  msgstr ""
636
 
637
+ #: ../wp-cerber.php:2877 ../wp-cerber.php:2878
638
  msgid "A new activity has been recorded"
639
  msgstr ""
640
 
641
+ #: ../wp-cerber.php:2893
642
  msgid "This message was sent by"
643
  msgstr ""
644
 
645
+ #: ../wp-cerber.php:3153
646
  msgid "User"
647
  msgstr ""
648
 
649
+ #: ../wp-cerber.php:3161
650
  msgid "Search string"
651
  msgstr ""
652
 
653
+ #: ../wp-cerber.php:3182
654
  msgid "To unsubscribe click here"
655
  msgstr ""
656
 
657
+ #: ../wp-cerber.php:3262
658
  #, php-format
659
  msgid "The WP Cerber requires PHP %s or higher. You are running"
660
  msgstr ""
661
 
662
+ #: ../wp-cerber.php:3266
663
  #, php-format
664
  msgid "The WP Cerber requires WordPress %s or higher. You are running"
665
  msgstr ""
666
 
667
+ #: ../wp-cerber.php:3271
668
  msgid "Can't activate WP Cerber due to a database error."
669
  msgstr ""
670
 
671
+ #: ../wp-cerber.php:3288
672
  msgid "Your IP address is added to the"
673
  msgstr ""
674
 
675
+ #: ../wp-cerber.php:3295 ../settings.php:234
 
 
 
 
676
  msgid "Main Settings"
677
  msgstr ""
678
 
679
+ #: ../wp-cerber.php:3298 ../settings.php:239
680
  msgid "Hardening"
681
  msgstr ""
682
 
683
+ #: ../wp-cerber.php:3299 ../settings.php:62 ../settings.php:80 ../settings.php:244
684
  msgid "Notifications"
685
  msgstr ""
686
 
687
+ #: ../wp-cerber.php:3300
688
  msgid "Import settings"
689
  msgstr ""
690
 
691
+ #: ../whois.php:215 ../whois.php:246 ../common.php:487
692
  msgid "Unknown"
693
  msgstr ""
694
 
695
+ #: ../common.php:426
696
  msgid "User created"
697
  msgstr ""
698
 
699
+ #: ../common.php:428
700
  msgid "Logged in"
701
  msgstr ""
702
 
703
+ #: ../common.php:429
704
  msgid "Logged out"
705
  msgstr ""
706
 
707
+ #: ../common.php:430
708
  msgid "Login failed"
709
  msgstr ""
710
 
711
+ #: ../common.php:433
712
  msgid "IP blocked"
713
  msgstr ""
714
 
715
+ #: ../common.php:434
716
  msgid "Subnet blocked"
717
  msgstr ""
718
 
719
+ #: ../common.php:436
720
  msgid "Citadel activated!"
721
  msgstr ""
722
 
723
+ #: ../common.php:437
724
  msgid "Spam comment denied"
725
  msgstr ""
726
 
727
+ #: ../common.php:438
728
  msgid "Spam form submission denied"
729
  msgstr ""
730
 
731
+ #: ../common.php:439
732
+ msgid "Form submission denied"
733
  msgstr ""
734
 
735
+ #: ../common.php:440
736
+ msgid "Comment denied"
737
  msgstr ""
738
 
739
+ #: ../common.php:451
740
  msgid "Password changed"
741
  msgstr ""
742
 
743
+ #: ../common.php:452
744
  msgid "Password reset requested"
745
  msgstr ""
746
 
747
+ #: ../common.php:454
748
  msgid "reCAPTCHA verification failed"
749
  msgstr ""
750
 
751
+ #: ../common.php:455
752
  msgid "reCAPTCHA settings are incorrect"
753
  msgstr ""
754
 
755
+ #: ../common.php:456
756
  msgid "Request to the Google reCAPTCHA service failed"
757
  msgstr ""
758
 
759
+ #: ../common.php:458
760
  msgid "Attempt to access prohibited URL"
761
  msgstr ""
762
 
763
+ #: ../common.php:459 ../common.php:490
764
  msgid "Attempt to log in with non-existent username"
765
  msgstr ""
766
 
767
+ #: ../common.php:460 ../common.php:491
768
  msgid "Attempt to log in with prohibited username"
769
  msgstr ""
770
 
771
+ #: ../common.php:462
772
  msgid "Attempt to log in denied"
773
  msgstr ""
774
 
775
+ #: ../common.php:463
776
  msgid "Attempt to register denied"
777
  msgstr ""
778
 
779
+ #: ../common.php:465
780
+ msgid "Request to REST API denied"
781
+ msgstr ""
782
+
783
+ #: ../common.php:466
784
+ msgid "XML-RPC request denied"
785
+ msgstr ""
786
+
787
+ #: ../common.php:470
788
+ msgid "Bot detected"
789
+ msgstr ""
790
+
791
+ #: ../common.php:471
792
+ msgid "Citadel mode is active"
793
+ msgstr ""
794
+
795
+ #: ../common.php:473
796
+ msgid "IP blacklisted"
797
+ msgstr ""
798
+
799
+ #: ../common.php:476
800
+ msgid "Malicious activity detected"
801
+ msgstr ""
802
+
803
+ #: ../common.php:478
804
+ msgid "Blocked by country rule"
805
+ msgstr ""
806
+
807
+ #: ../common.php:488
808
  msgid "Limit on login attempts is reached"
809
  msgstr ""
810
 
811
+ #: ../common.php:489
812
  msgid "Attempt to access"
813
  msgstr ""
814
 
815
+ #: ../common.php:492
816
  msgid "Limit on failed reCAPTCHA verifications is reached"
817
  msgstr ""
818
 
819
+ #: ../common.php:493
820
  msgid "Bot activity is detected"
821
  msgstr ""
822
 
823
+ #: ../common.php:545
824
  #, php-format
825
  msgid "%s ago"
826
  msgstr ""
827
 
828
+ #: ../cerber-lab.php:638
829
  msgid "Want to make WP Cerber even more powerful?"
830
  msgstr ""
831
 
832
+ #: ../cerber-lab.php:639
833
  msgid ""
834
  "Allow WP Cerber to send locked out malicious IP addresses to Cerber Lab. "
835
  "This helps the plugin team to develop new algorithms for WP Cerber that will "
837
  "everyday. You can disable the sending in the plugin settings at any time."
838
  msgstr ""
839
 
840
+ #: ../cerber-lab.php:640
841
  msgid "OK, nail them all"
842
  msgstr ""
843
 
844
+ #: ../cerber-lab.php:641
845
  msgid "NO, maybe later"
846
  msgstr ""
847
 
848
+ #: ../cerber-lab.php:642 ../settings.php:202
849
  msgid "Know more"
850
  msgstr ""
851
 
877
  msgid "Site connection"
878
  msgstr ""
879
 
 
 
 
 
880
  #: ../settings.php:65
881
  msgid "Proactive security rules"
882
  msgstr ""
951
  msgid "Send notification to admin email"
952
  msgstr ""
953
 
954
+ #: ../settings.php:80 ../settings.php:376
955
  msgid "Click to send test"
956
  msgstr ""
957
 
959
  msgid "Keep records for"
960
  msgstr ""
961
 
962
+ #: ../settings.php:83 ../settings.php:132
963
  msgid "days"
964
  msgstr ""
965
 
1013
  msgstr ""
1014
 
1015
  #: ../settings.php:98
1016
+ msgid "Block access to user pages like /?author=n and user data via REST API"
1017
  msgstr ""
1018
 
1019
  #: ../settings.php:99
1037
  msgstr ""
1038
 
1039
  #: ../settings.php:101
1040
+ msgid "Block access to the WordPress REST API except the following namespaces"
1041
  msgstr ""
1042
 
1043
+ #: ../settings.php:102
1044
+ msgid "REST API whitelist"
1045
+ msgstr ""
1046
+
1047
+ #: ../settings.php:102
1048
+ msgid ""
1049
+ "Specify REST API namespaces to be allowed if REST API is disabled. One "
1050
+ "string per line."
1051
  msgstr ""
1052
 
1053
  #: ../settings.php:111
1054
+ msgid "User related settings"
1055
+ msgstr ""
1056
+
1057
+ #: ../settings.php:112
1058
  msgid "Prohibited usernames"
1059
  msgstr ""
1060
 
1061
+ #: ../settings.php:112
1062
  msgid ""
1063
  "Usernames from this list are not allowed to log in or register. Any IP "
1064
  "address, have tried to use any of these usernames, will be immediately "
1065
  "blocked. Use comma to separate logins."
1066
  msgstr ""
1067
 
1068
+ #: ../settings.php:113
1069
  msgid "User session expire"
1070
  msgstr ""
1071
 
1072
+ #: ../settings.php:113
1073
  msgid "in minutes (leave empty to use default WP value)"
1074
  msgstr ""
1075
 
1076
+ #: ../settings.php:120
1077
  msgid "Cerber antispam engine"
1078
  msgstr ""
1079
 
1080
+ #: ../settings.php:121
1081
  msgid "Comment form"
1082
  msgstr ""
1083
 
1084
+ #: ../settings.php:121
1085
  msgid "Protect comment form with bot detection engine"
1086
  msgstr ""
1087
 
1088
+ #: ../settings.php:122 ../settings.php:140
1089
  msgid "Registration form"
1090
  msgstr ""
1091
 
1092
+ #: ../settings.php:122
1093
  msgid "Protect registration form with bot detection engine"
1094
  msgstr ""
1095
 
1096
+ #: ../settings.php:123
1097
  msgid "Other forms"
1098
  msgstr ""
1099
 
1100
+ #: ../settings.php:123
1101
  msgid "Protect all forms on the website with bot detection engine"
1102
  msgstr ""
1103
 
1104
+ #: ../settings.php:125
1105
  msgid "Adjust antispam engine"
1106
  msgstr ""
1107
 
1108
+ #: ../settings.php:126
1109
  msgid "Safe mode"
1110
  msgstr ""
1111
 
1112
+ #: ../settings.php:126
1113
  msgid "Use less restrictive policies (allow AJAX)"
1114
  msgstr ""
1115
 
1116
+ #: ../settings.php:127
1117
  msgid "Logged in users"
1118
  msgstr ""
1119
 
1120
+ #: ../settings.php:127
1121
  msgid "Disable bot detection engine for logged in users"
1122
  msgstr ""
1123
 
1124
  #: ../settings.php:128
1125
+ msgid "Query whitelist"
1126
+ msgstr ""
1127
+
1128
+ #: ../settings.php:128
1129
+ msgid ""
1130
+ "Specify search strings to search in a request URI to exclude the request "
1131
+ "from inspection by the engine. One string per line."
1132
+ msgstr ""
1133
+
1134
+ #: ../settings.php:130
1135
  msgid "Comment processing"
1136
  msgstr ""
1137
 
1138
+ #: ../settings.php:131
1139
  msgid "If a spam comment detected"
1140
  msgstr ""
1141
 
1142
+ #: ../settings.php:132
1143
  msgid "Trash spam comments"
1144
  msgstr ""
1145
 
1146
+ #: ../settings.php:132
1147
  msgid "Move spam comments to trash after"
1148
  msgstr ""
1149
 
1150
+ #: ../settings.php:135
1151
  msgid "reCAPTCHA settings"
1152
  msgstr ""
1153
 
1154
+ #: ../settings.php:136
1155
  msgid "Site key"
1156
  msgstr ""
1157
 
1158
+ #: ../settings.php:137
1159
  msgid "Secret key"
1160
  msgstr ""
1161
 
1162
+ #: ../settings.php:138
1163
  msgid "Invisible reCAPTCHA"
1164
  msgstr ""
1165
 
1166
+ #: ../settings.php:138
1167
  msgid "Enable invisible reCAPTCHA"
1168
  msgstr ""
1169
 
1170
+ #: ../settings.php:138
1171
  msgid ""
1172
  "(do not enable it unless you get and enter the Site and Secret keys for the "
1173
  "invisible version)"
1174
  msgstr ""
1175
 
1176
+ #: ../settings.php:140
1177
  msgid "Enable reCAPTCHA for WordPress registration form"
1178
  msgstr ""
1179
 
1180
+ #: ../settings.php:141
1181
  msgid "Enable reCAPTCHA for WooCommerce registration form"
1182
  msgstr ""
1183
 
1184
+ #: ../settings.php:143
1185
  msgid "Lost password form"
1186
  msgstr ""
1187
 
1188
+ #: ../settings.php:143
1189
  msgid "Enable reCAPTCHA for WordPress lost password form"
1190
  msgstr ""
1191
 
1192
+ #: ../settings.php:144
1193
  msgid "Enable reCAPTCHA for WooCommerce lost password form"
1194
  msgstr ""
1195
 
1196
+ #: ../settings.php:146
1197
  msgid "Login form"
1198
  msgstr ""
1199
 
1200
+ #: ../settings.php:146
1201
  msgid "Enable reCAPTCHA for WordPress login form"
1202
  msgstr ""
1203
 
1204
+ #: ../settings.php:147
1205
  msgid "Enable reCAPTCHA for WooCommerce login form"
1206
  msgstr ""
1207
 
1208
+ #: ../settings.php:149
1209
  msgid "Enable reCAPTCHA for WordPress comment form"
1210
  msgstr ""
1211
 
1212
+ #: ../settings.php:150
1213
  msgid "Disable reCAPTCHA for logged in users"
1214
  msgstr ""
1215
 
1216
+ #: ../settings.php:152
1217
  msgid "Limit attempts"
1218
  msgstr ""
1219
 
1220
+ #: ../settings.php:152
1221
  #, php-format
1222
  msgid "Lock out IP address for %s minutes after %s failed attempts within %s minutes"
1223
  msgstr ""
1224
 
1225
+ #: ../settings.php:158
1226
  msgid "Email notifications"
1227
  msgstr ""
1228
 
1229
+ #: ../settings.php:160
1230
  msgid "Email Address"
1231
  msgstr ""
1232
 
1233
+ #: ../settings.php:160
1234
  msgid "Use comma to specify multiple values"
1235
  msgstr ""
1236
 
1237
+ #: ../settings.php:160
1238
  #, php-format
1239
  msgid "if empty, the admin email %s will be used"
1240
  msgstr ""
1241
 
1242
+ #: ../settings.php:161
1243
  msgid "Notification limit"
1244
  msgstr ""
1245
 
1246
+ #: ../settings.php:161
1247
  msgid "notification letters allowed per hour (0 means unlimited)"
1248
  msgstr ""
1249
 
1250
+ #: ../settings.php:170
1251
  msgid "All connected devices"
1252
  msgstr ""
1253
 
1254
+ #: ../settings.php:171
1255
  msgid "No devices found"
1256
  msgstr ""
1257
 
1258
+ #: ../settings.php:173
1259
  msgid "Not available"
1260
  msgstr ""
1261
 
1262
+ #: ../settings.php:184
1263
  msgid "Make your protection smarter!"
1264
  msgstr ""
1265
 
1266
+ #: ../settings.php:188
1267
  msgid ""
1268
  "Please enable Permalinks to use this feature. Set Permalink Settings to "
1269
  "something other than Default."
1270
  msgstr ""
1271
 
1272
+ #: ../settings.php:191
1273
  msgid ""
1274
  "Be careful when enabling this options. If you forget the custom login URL "
1275
  "you will not be able to login."
1276
  msgstr ""
1277
 
1278
+ #: ../settings.php:195
1279
  msgid ""
1280
  "In the Citadel mode nobody is able to log in except IPs from the White IP "
1281
  "Access List. Active user sessions will not be affected."
1282
  msgstr ""
1283
 
1284
+ #: ../settings.php:198
1285
  msgid "These settings do not affect hosts from the "
1286
  msgstr ""
1287
 
1288
+ #: ../settings.php:201
1289
  msgid ""
1290
  "Before you can start using reCAPTCHA, you have to obtain Site key and Secret "
1291
  "key on the Google website"
1292
  msgstr ""
1293
 
1294
+ #: ../settings.php:241
1295
  msgid "Users"
1296
  msgstr ""
1297
 
1298
+ #: ../settings.php:246
1299
  msgid "Help"
1300
  msgstr ""
1301
 
1302
+ #: ../settings.php:362
1303
  #, php-format
1304
  msgid "%s allowed retries in %s minutes"
1305
  msgstr ""
1306
 
1307
+ #: ../settings.php:367
1308
  #, php-format
1309
  msgid "Increase lockout duration to %s hours after %s lockouts in the last %s hours"
1310
  msgstr ""
1311
 
1312
+ #: ../settings.php:374
1313
  msgid "Notify admin if the number of active lockouts above"
1314
  msgstr ""
1315
 
1316
+ #: ../settings.php:379
1317
  #, php-format
1318
  msgid "Enable after %s failed login attempts in last %s minutes"
1319
  msgstr ""
1320
 
1321
+ #: ../settings.php:469
1322
  msgid "Attention! You have changed the login URL! The new login URL is"
1323
  msgstr ""
1324
 
1325
+ #: ../settings.php:543
1326
  msgid "<strong>ERROR</strong>: please enter a valid email address."
1327
  msgstr ""
1328
 
1334
  msgid "Diagnostic"
1335
  msgstr ""
1336
 
1337
+ #: ../cerber-tools.php:50
1338
+ msgid "License"
1339
+ msgstr ""
1340
+
1341
  #: ../cerber-tools.php:83
1342
  msgid "Export settings to the file"
1343
  msgstr ""
1387
  msgid "Upload file"
1388
  msgstr ""
1389
 
1390
+ #: ../cerber-tools.php:137
1391
  msgid "No file was uploaded or file is corrupted"
1392
  msgstr ""
1393
 
1394
+ #: ../cerber-tools.php:170
1395
  msgid "Error while updating"
1396
  msgstr ""
1397
 
1398
+ #: ../cerber-tools.php:173
1399
  msgid "Settings has imported successfully from"
1400
  msgstr ""
1401
 
1402
+ #: ../cerber-tools.php:177
1403
  msgid "Error while parsing file"
1404
  msgstr ""
1405
 
1406
+ #: ../cerber-tools.php:295
1407
  msgid "Antispam and bot detection settings"
1408
  msgstr ""
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: security, login, custom login, protect, antispam, woocommerce, recaptcha,
5
  Requires at least: 4.4
6
  Requires PHP: 5.3
7
  Tested up to: 4.8.1
8
- Stable tag: 5.2
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.
@@ -30,12 +30,12 @@ Hardening WordPress with a set of security settings.
30
  * Hide wp-login.php, wp-signup.php and wp-register.php from possible attacks and return 404 HTTP Error.
31
  * Hide wp-admin (dashboard) and return 404 HTTP Error when a user isn't logged in.
32
  * Immediately block IP or subnet when attempting to log in with non-existent or prohibited username.
33
- * Disable WP REST API
34
  * Disable XML-RPC (block access to the XML-RPC interface including Pingbacks and Trackbacks)
35
  * Disable feeds (block access to the RSS, Atom and RDF feeds)
36
  * Restrict access to XML-RPC, REST API and feeds by **White IP Access list** with IP or IP range.
37
- * Disable automatic redirecting to login page.
38
- * **Stop user enumeration** (block access to the pages like /?author=n)
39
  * Proactively **block IP subnet class C** for intruder's IP.
40
  * Antispam: **reCAPTCHA** to protect WordPress login, register and comment forms.
41
  * [reCAPTCHA for WooCommerce & WordPress forms](http://wpcerber.com/how-to-setup-recaptcha/).
@@ -45,7 +45,7 @@ Hardening WordPress with a set of security settings.
45
  * Filter out and inspect activities by IP address, user, username or a particular activity.
46
  * Filter out activities and export them to a CSV file.
47
  * Limit login attempts works on a site/server behind a reverse proxy.
48
- * [Notifications by email or mobile push notifications](http://wpcerber.com/wordpress-notifications-made-easy/).
49
  * Trigger and action for the [jetFlow.io automation plugin](http://jetflow.io).
50
 
51
  = Limit login attempts done right =
@@ -129,17 +129,18 @@ Make your website instantly available in 90+ languages with Google Translate Wid
129
 
130
  == Installation ==
131
 
132
- Installing the WP Cerber security plugin is the same as other WordPress plugins.
133
 
134
  1. Install the plugin through Plugins > Add New > Upload or unzip plugin package into wp-content/plugins/.
135
  2. Activate the WP Cerber through the Plugins > Installed Plugins menu in the WordPress admin dashboard.
136
  3. The plugin is now active and has started protecting your WordPress with default settings.
137
- 4. Make sure, that you received a notification letter with your site admin email.
 
138
 
139
  **Important notes**
140
 
141
- 1. Before enabling invisible reCAPTCHA, you must get separate keys for invisible version. [How to enable reCAPTCHA](http://wpcerber.com/how-to-setup-recaptcha/).
142
- 2. If you want to test out plugin's features, do this from another computer and remove that computer's network from the White Access List. Cerber is smart enough to recognize "the boss".
143
  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 a new Custom login URL to the list of pages not to cache.
144
  4. [Read this if your website is under CloudFlare](http://wpcerber.com/cloudflare-and-wordpress-cerber/)
145
  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.
@@ -258,9 +259,15 @@ To get access to your dashboard you need to copy the WP Cerber Reset folder to t
258
 
259
  == Changelog ==
260
 
 
 
 
 
 
 
261
  = 5.2 =
262
  * Bug fixed: Hidden custom login URL may be discovered by using specially formatted URL.
263
- * Bug fixed: Customization CSS styles don’t work on the Custom login page.
264
 
265
  = 5.1 =
266
  * New: Anti-spam and anti-bot for contact and other forms. Cerber antispam and bot detection engine now protects all forms on a website. It’s compatible with virtually any form. Tested with Caldera Forms, Gravity Forms, Contact Form 7, Ninja Forms, Formidable Forms, Fast Secure Contact Form, Contact Form by WPForms.
5
  Requires at least: 4.4
6
  Requires PHP: 5.3
7
  Tested up to: 4.8.1
8
+ Stable tag: 5.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.
30
  * Hide wp-login.php, wp-signup.php and wp-register.php from possible attacks and return 404 HTTP Error.
31
  * Hide wp-admin (dashboard) and return 404 HTTP Error when a user isn't logged in.
32
  * Immediately block IP or subnet when attempting to log in with non-existent or prohibited username.
33
+ * Disable WP REST API or restrict access with your own rules
34
  * Disable XML-RPC (block access to the XML-RPC interface including Pingbacks and Trackbacks)
35
  * Disable feeds (block access to the RSS, Atom and RDF feeds)
36
  * Restrict access to XML-RPC, REST API and feeds by **White IP Access list** with IP or IP range.
37
+ * Disable automatic redirecting to the login page.
38
+ * **Stop user enumeration** (block access to pages like /?author=n and user REST API)
39
  * Proactively **block IP subnet class C** for intruder's IP.
40
  * Antispam: **reCAPTCHA** to protect WordPress login, register and comment forms.
41
  * [reCAPTCHA for WooCommerce & WordPress forms](http://wpcerber.com/how-to-setup-recaptcha/).
45
  * Filter out and inspect activities by IP address, user, username or a particular activity.
46
  * Filter out activities and export them to a CSV file.
47
  * Limit login attempts works on a site/server behind a reverse proxy.
48
+ * [Get notifications by email or via mobile push notifications](http://wpcerber.com/wordpress-notifications-made-easy/).
49
  * Trigger and action for the [jetFlow.io automation plugin](http://jetflow.io).
50
 
51
  = Limit login attempts done right =
129
 
130
  == Installation ==
131
 
132
+ Installing the WP Cerber Security & Antispam plugin is the same as other WordPress plugins.
133
 
134
  1. Install the plugin through Plugins > Add New > Upload or unzip plugin package into wp-content/plugins/.
135
  2. Activate the WP Cerber through the Plugins > Installed Plugins menu in the WordPress admin dashboard.
136
  3. The plugin is now active and has started protecting your WordPress with default settings.
137
+ 4. Make sure, that you've got a notification letter to your site admin email.
138
+ 5. Read carefully: [Getting Started Guide](http://wpcerber.com/getting-started/)
139
 
140
  **Important notes**
141
 
142
+ 1. Before enabling invisible reCAPTCHA, you must get separate keys for the invisible version. [How to enable reCAPTCHA](http://wpcerber.com/how-to-setup-recaptcha/).
143
+ 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".
144
  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 a new Custom login URL to the list of pages not to cache.
145
  4. [Read this if your website is under CloudFlare](http://wpcerber.com/cloudflare-and-wordpress-cerber/)
146
  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.
259
 
260
  == Changelog ==
261
 
262
+ = 5.5 =
263
+ * White list for the WordPress anti-spam engine.
264
+ * White list for REST API requests.
265
+ * Disable access to user data via REST API and stop REST API user enumeration.
266
+ * [Read more](http://wpcerber.com/wp-cerber-security-5-5/)
267
+
268
  = 5.2 =
269
  * Bug fixed: Hidden custom login URL may be discovered by using specially formatted URL.
270
+ * Bug fixed: Customized CSS styles don’t work on the Custom login page.
271
 
272
  = 5.1 =
273
  * New: Anti-spam and anti-bot for contact and other forms. Cerber antispam and bot detection engine now protects all forms on a website. It’s compatible with virtually any form. Tested with Caldera Forms, Gravity Forms, Contact Form 7, Ninja Forms, Formidable Forms, Fast Secure Contact Form, Contact Form by WPForms.
ripe.php CHANGED
@@ -143,7 +143,7 @@ function ripe_readable_info($ip){
143
  $ret['data'][$att->name] = $att->value;
144
  if (is_email($att->value)) $value = '<a href="mailto:'.$att->value.'">'.$att->value.'</a>';
145
  elseif (strtolower($att->name) == 'country') {
146
- $value = '<b><span '.cerber_get_flag_css($att->value).'>'.cerber_country_name($att->value).'</span> ('.$att->value.')</b>';
147
  $ret['country'] = $value;
148
  }
149
  else $value = $att->value;
143
  $ret['data'][$att->name] = $att->value;
144
  if (is_email($att->value)) $value = '<a href="mailto:'.$att->value.'">'.$att->value.'</a>';
145
  elseif (strtolower($att->name) == 'country') {
146
+ $value = cerber_get_flag_html($att->value) . '<b>' . cerber_country_name($att->value) . ' (' . $att->value . ')</b>';
147
  $ret['country'] = $value;
148
  }
149
  else $value = $att->value;
settings.php CHANGED
@@ -57,7 +57,7 @@ function cerber_settings_init(){
57
  add_settings_section('cerber', __('Limit login attempts','wp-cerber'), 'cerber_sapi_section', 'cerber-' . $tab);
58
  add_settings_field('attempts',__('Attempts','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'cerber',array('group'=>$tab,'option'=>'attempts','type'=>'attempts'));
59
  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));
60
- add_settings_field('aggressive',__('Aggressive lockout','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'cerber',array('group'=>$tab,'type'=>'aggressive'));
61
  add_settings_field('limitwhite',__('White IP Access List','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'cerber',array('group'=>$tab,'option'=>'limitwhite','type'=>'checkbox','label'=>__('Apply limit login rules to IP addresses in the White IP Access List','wp-cerber')));
62
  add_settings_field('notify',__('Notifications','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'cerber',array('group'=>$tab,'type'=>'notify','option'=>'notify'));
63
  add_settings_field('proxy',__('Site connection','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'cerber',array('group'=>$tab,'option'=>'proxy','type'=>'checkbox','label'=>__('My site is behind a reverse proxy','wp-cerber')));
@@ -74,7 +74,7 @@ function cerber_settings_init(){
74
  add_settings_field('loginnowp',__('Disable wp-login.php','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'custom',array('group'=>$tab,'option'=>'loginnowp','type'=>'checkbox','label'=>__('Block direct access to wp-login.php and return HTTP 404 Not Found Error','wp-cerber')));
75
 
76
  add_settings_section('citadel', __('Citadel mode','wp-cerber'), 'cerber_sapi_section', 'cerber-' . $tab);
77
- add_settings_field('citadel',__('Threshold','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'citadel',array('group'=>$tab,'type'=>'citadel'));
78
  add_settings_field('ciduration',__('Duration','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'citadel',array('group'=>$tab,'option'=>'ciduration','type'=>'text','label'=>__('minutes','wp-cerber'),'size'=>3));
79
  //add_settings_field('ciwhite',__('White IP Access List','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'citadel',array('group'=>$tab,'option'=>'ciwhite','type'=>'checkbox','label'=>__('Permit IPs from the White IP Access List to log in','wp-cerber')));
80
  add_settings_field('cinotify',__('Notifications','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'citadel',array('group'=>$tab,'option'=>'cinotify','type'=>'checkbox','label'=>__('Send notification to admin email','wp-cerber').' (<a href="'.wp_nonce_url(add_query_arg(array('testnotify'=>'citadel', 'settings-updated' => 0)),'control','cerber_nonce').'">'.__('Click to send test','wp-cerber').'</a>)'));
@@ -95,10 +95,11 @@ function cerber_settings_init(){
95
  $tab='hardening'; // 'cerber-hardening' settings
96
  register_setting( 'cerberus-'.$tab, CERBER_OPT_H);
97
  add_settings_section('hwp', __('Hardening WordPress','wp-cerber'), 'cerber_sapi_section', CERBER_OPT_H);
98
- add_settings_field('stopenum',__('Stop user enumeration','wp-cerber'),'cerberus_field_show',CERBER_OPT_H,'hwp',array('group'=>$tab,'option'=>'stopenum','type'=>'checkbox','label'=>__('Block access to the pages like /?author=n','wp-cerber')));
99
  add_settings_field('xmlrpc',__('Disable XML-RPC','wp-cerber'),'cerberus_field_show',CERBER_OPT_H,'hwp',array('group'=>$tab,'option'=>'xmlrpc','type'=>'checkbox','label'=>__('Block access to the XML-RPC server (including Pingbacks and Trackbacks)','wp-cerber')));
100
  add_settings_field('nofeeds',__('Disable feeds','wp-cerber'),'cerberus_field_show',CERBER_OPT_H,'hwp',array('group'=>$tab,'option'=>'nofeeds','type'=>'checkbox','label'=>__('Block access to the RSS, Atom and RDF feeds','wp-cerber')));
101
- add_settings_field('norest',__('Disable REST API','wp-cerber'),'cerberus_field_show',CERBER_OPT_H,'hwp',array('group'=>$tab,'option'=>'norest','type'=>'checkbox','label'=>__('Block access to the WordPress REST API','wp-cerber')));
 
102
  //add_settings_field('hashauthor',__('Hide author usernames','wp-cerber'),'cerberus_field_show',CERBER_OPT_H,'hwp',array('group'=>$tab,'option'=>'hashauthor','type'=>'checkbox','label'=>__('Replace author username with hash for author pages and URLs','wp-cerber')));
103
  //add_settings_field('cleanhead',__('Clean up HEAD','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'hwp',array('group'=>$tab,'option'=>'cleanhead','type'=>'checkbox','label'=>__('Remove generator and version tags from HEAD section','wp-cerber')));
104
  //add_settings_field('ping',__('Disable Pingback','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'hwp',array('group'=>$tab,'option'=>'ping','type'=>'checkbox','label'=>__('Block access to ping functional','wp-cerber')));
@@ -111,7 +112,7 @@ function cerber_settings_init(){
111
  add_settings_field('prohibited',__('Prohibited usernames','wp-cerber'),'cerberus_field_show',CERBER_OPT_U,'us',array('group'=>$tab,'option'=>'prohibited','type'=>'textarea','label'=>__('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.','wp-cerber')));
112
  add_settings_field('auth_expire',__('User session expire','wp-cerber'),'cerberus_field_show',CERBER_OPT_U,'us',array('group'=>$tab,'option'=>'auth_expire','type'=>'text','label'=>__('in minutes (leave empty to use default WP value)','wp-cerber'),'size' => 6));
113
 
114
- // reCAPTCHA -----------------------------------------------------------------------------
115
 
116
  $tab='recaptcha'; // 'cerber-recaptcha' settings
117
  register_setting( 'cerberus-'.$tab, CERBER_OPT_C);
@@ -124,6 +125,7 @@ function cerber_settings_init(){
124
  add_settings_section('antibot_more', __('Adjust antispam engine','wp-cerber'), 'cerber_sapi_section', CERBER_OPT_C);
125
  add_settings_field('botssafe',__('Safe mode','wp-cerber'),'cerberus_field_show',CERBER_OPT_C,'antibot_more',array('group'=>$tab,'option'=>'botssafe','type'=>'checkbox','label'=>__('Use less restrictive policies (allow AJAX)','wp-cerber') ));
126
  add_settings_field('botsnoauth',__('Logged in users','wp-cerber'),'cerberus_field_show',CERBER_OPT_C,'antibot_more',array('group'=>$tab,'option'=>'botsnoauth','type'=>'checkbox','label'=>__('Disable bot detection engine for logged in users','wp-cerber') ));
 
127
 
128
  add_settings_section('commproc', __('Comment processing','wp-cerber'), 'cerber_sapi_section', CERBER_OPT_C);
129
  add_settings_field('spamcomm',__('If a spam comment detected','wp-cerber'),'cerberus_field_show',CERBER_OPT_C,'commproc',array('group'=>$tab, 'option'=>'spamcomm', 'type'=>'select', 'set' => array('Deny it completely', 'Mark it as spam')));
@@ -327,15 +329,18 @@ function cerberus_field_show($args){
327
  else {
328
  $disabled = '';
329
  }
 
330
  if ( $args['option'] == 'loginpath' ) {
331
  $pre = rtrim( get_home_url(), '/' ) . '/';
332
  $value = urldecode( $value );
333
  }
334
  elseif ( $args['option'] == 'prohibited' || $args['option'] == 'email' ) {
335
- if ( is_array( $value ) ) {
336
- $value = implode( ', ', $value );
337
- }
 
338
  }
 
339
  }
340
 
341
  $name = 'cerber-'.$args['group'].'['.$args['option'].']';
@@ -489,19 +494,13 @@ function cerber_sanitize_options($new, $old, $option) { // $option added in WP 4
489
  return $new;
490
  }
491
  /*
492
- Sanitizing/checking user input for User tab settings
493
  */
494
  add_filter( 'pre_update_option_'.CERBER_OPT_U, 'cerber_sanitize_u', 10, 3 );
495
  function cerber_sanitize_u($new, $old, $option) { // $option added in WP 4.4.0
496
- if ( ! is_array( $new['prohibited'] ) ) {
497
- $list = explode( ',', $new['prohibited'] );
498
- } else {
499
- $list = $new['prohibited'];
500
- }
501
- $list = array_map('trim', $list);
502
- $list = array_filter($list);
503
- $list = array_unique($list);
504
- $new['prohibited'] = $list;
505
  return $new;
506
  }
507
  /*
@@ -523,6 +522,8 @@ function cerber_sanitize_c($new, $old, $option) {
523
  $new['recaptcha-number'] = absint( $new['recaptcha-number'] );
524
  $new['recaptcha-within'] = absint( $new['recaptcha-within'] );
525
 
 
 
526
  return $new;
527
  }
528
  /*
@@ -531,23 +532,22 @@ function cerber_sanitize_c($new, $old, $option) {
531
  add_filter( 'pre_update_option_'.CERBER_OPT_N, 'cerber_sanitize_n', 10, 3 );
532
  function cerber_sanitize_n($new, $old, $option) {
533
 
534
- if ( ! empty( $new['email'] ) ) {
535
- if ( ! is_array( $new['email'] ) ) {
536
- $list = explode( ',', $new['email'] );
537
- } else {
538
- $list = $new['email'];
 
539
  }
540
- $list = array_map('trim', $list);
541
- $list = array_filter($list);
542
- $list = array_unique($list);
543
- foreach ( $list as $item ) {
544
- if (!is_email( $item )) cerber_admin_notice( __( '<strong>ERROR</strong>: please enter a valid email address.' ) );
545
  }
546
- $new['email'] = $list;
547
  }
 
 
548
  $new['emailrate'] = absint( $new['emailrate'] );
549
 
550
- // set 'default' value for device setting if a new token has been entered
551
  if ( $new['pbtoken'] != $old['pbtoken'] ) {
552
  $list = cerber_pb_get_devices($new['pbtoken']);
553
  if (is_array($list) && !empty($list)) $new['pbdevice'] = 'all';
@@ -556,6 +556,18 @@ function cerber_sanitize_n($new, $old, $option) {
556
 
557
  return $new;
558
  }
 
 
 
 
 
 
 
 
 
 
 
 
559
  /**
560
  * Let's sanitize them all
561
  * @since 4.1
@@ -576,6 +588,45 @@ function cerber_o_o_sanitizer($value, $option, $old_value) {
576
  return $value;
577
  }
578
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
579
  /*
580
  * Save settings on the multisite WP.
581
  * Process POST Form for settings screens.
@@ -654,6 +705,7 @@ function cerber_get_defaults($field = null) {
654
  'xmlrpc' => 0,
655
  'nofeeds' => 0,
656
  'norest' => 1,
 
657
  'hashauthor' => 0,
658
  'cleanhead' => 1,
659
  ),
@@ -667,6 +719,7 @@ function cerber_get_defaults($field = null) {
667
  'botsany' => 0,
668
  'botssafe' => 0,
669
  'botsnoauth' => 1,
 
670
 
671
  'spamcomm' => 0,
672
  'trashafter' => 7,
@@ -748,6 +801,56 @@ function cerber_get_options($option = '') {
748
  }
749
  return $options;
750
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
751
  /*
752
  Load default settings, except Custom Login URL
753
  */
57
  add_settings_section('cerber', __('Limit login attempts','wp-cerber'), 'cerber_sapi_section', 'cerber-' . $tab);
58
  add_settings_field('attempts',__('Attempts','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'cerber',array('group'=>$tab,'option'=>'attempts','type'=>'attempts'));
59
  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));
60
+ add_settings_field('aggressive',__('Aggressive lockout','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'cerber',array('group'=>$tab,'option'=>'aggressive','type'=>'aggressive'));
61
  add_settings_field('limitwhite',__('White IP Access List','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'cerber',array('group'=>$tab,'option'=>'limitwhite','type'=>'checkbox','label'=>__('Apply limit login rules to IP addresses in the White IP Access List','wp-cerber')));
62
  add_settings_field('notify',__('Notifications','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'cerber',array('group'=>$tab,'type'=>'notify','option'=>'notify'));
63
  add_settings_field('proxy',__('Site connection','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'cerber',array('group'=>$tab,'option'=>'proxy','type'=>'checkbox','label'=>__('My site is behind a reverse proxy','wp-cerber')));
74
  add_settings_field('loginnowp',__('Disable wp-login.php','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'custom',array('group'=>$tab,'option'=>'loginnowp','type'=>'checkbox','label'=>__('Block direct access to wp-login.php and return HTTP 404 Not Found Error','wp-cerber')));
75
 
76
  add_settings_section('citadel', __('Citadel mode','wp-cerber'), 'cerber_sapi_section', 'cerber-' . $tab);
77
+ add_settings_field('citadel',__('Threshold','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'citadel',array('group'=>$tab,'option'=>'citadel','type'=>'citadel'));
78
  add_settings_field('ciduration',__('Duration','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'citadel',array('group'=>$tab,'option'=>'ciduration','type'=>'text','label'=>__('minutes','wp-cerber'),'size'=>3));
79
  //add_settings_field('ciwhite',__('White IP Access List','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'citadel',array('group'=>$tab,'option'=>'ciwhite','type'=>'checkbox','label'=>__('Permit IPs from the White IP Access List to log in','wp-cerber')));
80
  add_settings_field('cinotify',__('Notifications','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'citadel',array('group'=>$tab,'option'=>'cinotify','type'=>'checkbox','label'=>__('Send notification to admin email','wp-cerber').' (<a href="'.wp_nonce_url(add_query_arg(array('testnotify'=>'citadel', 'settings-updated' => 0)),'control','cerber_nonce').'">'.__('Click to send test','wp-cerber').'</a>)'));
95
  $tab='hardening'; // 'cerber-hardening' settings
96
  register_setting( 'cerberus-'.$tab, CERBER_OPT_H);
97
  add_settings_section('hwp', __('Hardening WordPress','wp-cerber'), 'cerber_sapi_section', CERBER_OPT_H);
98
+ add_settings_field('stopenum',__('Stop user enumeration','wp-cerber'),'cerberus_field_show',CERBER_OPT_H,'hwp',array('group'=>$tab,'option'=>'stopenum','type'=>'checkbox','label'=>__('Block access to user pages like /?author=n and user data via REST API','wp-cerber')));
99
  add_settings_field('xmlrpc',__('Disable XML-RPC','wp-cerber'),'cerberus_field_show',CERBER_OPT_H,'hwp',array('group'=>$tab,'option'=>'xmlrpc','type'=>'checkbox','label'=>__('Block access to the XML-RPC server (including Pingbacks and Trackbacks)','wp-cerber')));
100
  add_settings_field('nofeeds',__('Disable feeds','wp-cerber'),'cerberus_field_show',CERBER_OPT_H,'hwp',array('group'=>$tab,'option'=>'nofeeds','type'=>'checkbox','label'=>__('Block access to the RSS, Atom and RDF feeds','wp-cerber')));
101
+ add_settings_field('norest',__('Disable REST API','wp-cerber'),'cerberus_field_show',CERBER_OPT_H,'hwp',array('group'=>$tab,'option'=>'norest','type'=>'checkbox','label'=>__('Block access to the WordPress REST API except the following namespaces','wp-cerber')));
102
+ add_settings_field('restwhite',__('REST API whitelist','wp-cerber'),'cerberus_field_show',CERBER_OPT_H,'hwp',array('group'=>$tab,'option'=>'restwhite','type'=>'textarea','label'=>__('Specify REST API namespaces to be allowed if REST API is disabled. One string per line.','wp-cerber')));
103
  //add_settings_field('hashauthor',__('Hide author usernames','wp-cerber'),'cerberus_field_show',CERBER_OPT_H,'hwp',array('group'=>$tab,'option'=>'hashauthor','type'=>'checkbox','label'=>__('Replace author username with hash for author pages and URLs','wp-cerber')));
104
  //add_settings_field('cleanhead',__('Clean up HEAD','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'hwp',array('group'=>$tab,'option'=>'cleanhead','type'=>'checkbox','label'=>__('Remove generator and version tags from HEAD section','wp-cerber')));
105
  //add_settings_field('ping',__('Disable Pingback','wp-cerber'),'cerberus_field_show','cerber-'.$tab,'hwp',array('group'=>$tab,'option'=>'ping','type'=>'checkbox','label'=>__('Block access to ping functional','wp-cerber')));
112
  add_settings_field('prohibited',__('Prohibited usernames','wp-cerber'),'cerberus_field_show',CERBER_OPT_U,'us',array('group'=>$tab,'option'=>'prohibited','type'=>'textarea','label'=>__('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.','wp-cerber')));
113
  add_settings_field('auth_expire',__('User session expire','wp-cerber'),'cerberus_field_show',CERBER_OPT_U,'us',array('group'=>$tab,'option'=>'auth_expire','type'=>'text','label'=>__('in minutes (leave empty to use default WP value)','wp-cerber'),'size' => 6));
114
 
115
+ // Antibot & reCAPTCHA -----------------------------------------------------------------------------
116
 
117
  $tab='recaptcha'; // 'cerber-recaptcha' settings
118
  register_setting( 'cerberus-'.$tab, CERBER_OPT_C);
125
  add_settings_section('antibot_more', __('Adjust antispam engine','wp-cerber'), 'cerber_sapi_section', CERBER_OPT_C);
126
  add_settings_field('botssafe',__('Safe mode','wp-cerber'),'cerberus_field_show',CERBER_OPT_C,'antibot_more',array('group'=>$tab,'option'=>'botssafe','type'=>'checkbox','label'=>__('Use less restrictive policies (allow AJAX)','wp-cerber') ));
127
  add_settings_field('botsnoauth',__('Logged in users','wp-cerber'),'cerberus_field_show',CERBER_OPT_C,'antibot_more',array('group'=>$tab,'option'=>'botsnoauth','type'=>'checkbox','label'=>__('Disable bot detection engine for logged in users','wp-cerber') ));
128
+ add_settings_field('botswhite',__('Query whitelist','wp-cerber'),'cerberus_field_show',CERBER_OPT_C,'antibot_more',array('group'=>$tab,'option'=>'botswhite','type'=>'textarea','label'=>__('Specify search strings to search in a request URI to exclude the request from inspection by the engine. One string per line.','wp-cerber')));
129
 
130
  add_settings_section('commproc', __('Comment processing','wp-cerber'), 'cerber_sapi_section', CERBER_OPT_C);
131
  add_settings_field('spamcomm',__('If a spam comment detected','wp-cerber'),'cerberus_field_show',CERBER_OPT_C,'commproc',array('group'=>$tab, 'option'=>'spamcomm', 'type'=>'select', 'set' => array('Deny it completely', 'Mark it as spam')));
329
  else {
330
  $disabled = '';
331
  }
332
+
333
  if ( $args['option'] == 'loginpath' ) {
334
  $pre = rtrim( get_home_url(), '/' ) . '/';
335
  $value = urldecode( $value );
336
  }
337
  elseif ( $args['option'] == 'prohibited' || $args['option'] == 'email' ) {
338
+ $value = cerber_array2text($value, ', ');
339
+ }
340
+ elseif ( $args['option'] == 'botswhite' || $args['option'] == 'restwhite') {
341
+ $value = cerber_array2text($value, "\n");
342
  }
343
+
344
  }
345
 
346
  $name = 'cerber-'.$args['group'].'['.$args['option'].']';
494
  return $new;
495
  }
496
  /*
497
+ Sanitizing/checking user input for User tab settings
498
  */
499
  add_filter( 'pre_update_option_'.CERBER_OPT_U, 'cerber_sanitize_u', 10, 3 );
500
  function cerber_sanitize_u($new, $old, $option) { // $option added in WP 4.4.0
501
+
502
+ $new['prohibited'] = cerber_text2array($new['prohibited'], ',', 'strtolower');
503
+
 
 
 
 
 
 
504
  return $new;
505
  }
506
  /*
522
  $new['recaptcha-number'] = absint( $new['recaptcha-number'] );
523
  $new['recaptcha-within'] = absint( $new['recaptcha-within'] );
524
 
525
+ $new['botswhite'] = cerber_text2array($new['botswhite'], "\n");
526
+
527
  return $new;
528
  }
529
  /*
532
  add_filter( 'pre_update_option_'.CERBER_OPT_N, 'cerber_sanitize_n', 10, 3 );
533
  function cerber_sanitize_n($new, $old, $option) {
534
 
535
+ $emails = cerber_text2array( $new['email'], ',' );
536
+
537
+ $new['email'] = array();
538
+ foreach ( $emails as $item ) {
539
+ if ( is_email( $item ) ) {
540
+ $new['email'][] = $item;
541
  }
542
+ else {
543
+ cerber_admin_notice( __( '<strong>ERROR</strong>: please enter a valid email address.' ) );
 
 
 
544
  }
 
545
  }
546
+
547
+
548
  $new['emailrate'] = absint( $new['emailrate'] );
549
 
550
+ // set 'default' value for the device setting if a new token has been entered
551
  if ( $new['pbtoken'] != $old['pbtoken'] ) {
552
  $list = cerber_pb_get_devices($new['pbtoken']);
553
  if (is_array($list) && !empty($list)) $new['pbdevice'] = 'all';
556
 
557
  return $new;
558
  }
559
+
560
+ /*
561
+ Sanitizing/checking user input for Hardening tab settings
562
+ */
563
+ add_filter( 'pre_update_option_'.CERBER_OPT_H, 'cerber_sanitize_h', 10, 3 );
564
+ function cerber_sanitize_h($new, $old, $option) {
565
+
566
+ $new['restwhite'] = cerber_text2array($new['restwhite'], "\n");
567
+
568
+ return $new;
569
+ }
570
+
571
  /**
572
  * Let's sanitize them all
573
  * @since 4.1
588
  return $value;
589
  }
590
 
591
+ function cerber_array2text( $array = array(), $delimiter = '') {
592
+ if ( empty( $array ) ) {
593
+ return '';
594
+ }
595
+
596
+ if ( is_array( $array ) ) {
597
+ $ret = implode( $delimiter , $array );
598
+ }
599
+ else {
600
+ $ret = $array;
601
+ }
602
+
603
+ return $ret;
604
+ }
605
+
606
+ function cerber_text2array( $text = '', $delimiter = '', $callback = '') {
607
+
608
+ if ( empty( $text ) ) {
609
+ return array();
610
+ }
611
+
612
+ if ( ! is_array( $text ) ) {
613
+ $list = explode( $delimiter, $text );
614
+ }
615
+ else {
616
+ $list = $text;
617
+ }
618
+ $list = array_map( 'trim', $list );
619
+
620
+ if ( $callback ) {
621
+ $list = array_map( $callback, $list );
622
+ }
623
+
624
+ $list = array_filter( $list );
625
+ $list = array_unique( $list );
626
+
627
+ return $list;
628
+ }
629
+
630
  /*
631
  * Save settings on the multisite WP.
632
  * Process POST Form for settings screens.
705
  'xmlrpc' => 0,
706
  'nofeeds' => 0,
707
  'norest' => 1,
708
+ 'restwhite' => '',
709
  'hashauthor' => 0,
710
  'cleanhead' => 1,
711
  ),
719
  'botsany' => 0,
720
  'botssafe' => 0,
721
  'botsnoauth' => 1,
722
+ 'botswhite' => '',
723
 
724
  'spamcomm' => 0,
725
  'trashafter' => 7,
801
  }
802
  return $options;
803
  }
804
+
805
+ /**
806
+ * The replacement for cerber_get_options()
807
+ *
808
+ * @param string $option
809
+ *
810
+ * @return array|bool|mixed
811
+ */
812
+ function cerber_get_settings($option = '') {
813
+ global $wpdb;
814
+ static $united;
815
+
816
+ if (!isset($united)) {
817
+
818
+ $options = array( CERBER_OPT, CERBER_OPT_H, CERBER_OPT_U, CERBER_OPT_C, CERBER_OPT_N );
819
+ $united = array();
820
+
821
+ foreach ( $options as $opt ) {
822
+
823
+ if ( is_multisite() ) {
824
+ $value = $wpdb->get_var( 'SELECT meta_value FROM ' . $wpdb->sitemeta . ' WHERE meta_key = "' . $opt . '"' );
825
+ }
826
+ else {
827
+ $value = $wpdb->get_var( 'SELECT option_value FROM ' . $wpdb->options . ' WHERE option_name = "' . $opt . '"' );
828
+ }
829
+
830
+ if ( $value ) {
831
+ $value = unserialize( $value );
832
+ }
833
+
834
+ if ( ! $value || ! is_array( $value ) ) {
835
+ continue;
836
+ }
837
+
838
+ $united = array_merge( $united, $value );
839
+ }
840
+ }
841
+
842
+ $options = $united;
843
+ if ( ! empty( $option ) ) {
844
+ if ( isset( $options[ $option ] ) ) {
845
+ return $options[ $option ];
846
+ } else {
847
+ return false;
848
+ }
849
+ }
850
+
851
+ return $options;
852
+ }
853
+
854
  /*
855
  Load default settings, except Custom Login URL
856
  */
whois.php CHANGED
@@ -70,7 +70,7 @@ function cerber_ip_whois_info($ip) {
70
  foreach ( $data as $key => $value ) {
71
  if (is_email($value)) $value = '<a href="mailto:'.$value.'">'.$value.'</a>';
72
  elseif (strtolower($key) == 'country') {
73
- $value = '<b><span '.cerber_get_flag_css($value).'>'.cerber_country_name($value).'</span> ('.$value.')</b>';
74
  $ret['country'] = $value;
75
  }
76
 
@@ -192,9 +192,13 @@ function make_whois_request($server, $ip) {
192
  * @since 2.7
193
  *
194
  */
195
- function cerber_get_flag_css($code){
196
- $assets_url = plugin_dir_url(CERBER_FILE).'assets';
197
- return 'style="padding-left: 24px; background: url(\''.$assets_url.'/flags/'.strtolower($code).'.gif\') no-repeat left;"';
 
 
 
 
198
  }
199
  /*
200
  *
@@ -203,11 +207,57 @@ function cerber_get_flag_css($code){
203
  * @since 2.7
204
  *
205
  */
206
- function cerber_country_name($code) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
  global $cerber_country_names;
208
- $code = strtoupper($code);
209
- if (isset($cerber_country_names[$code])) return $cerber_country_names[$code];
210
- return __('Unknown','wp-cerber');
 
 
 
211
  }
212
 
213
  $cerber_country_names = array(
70
  foreach ( $data as $key => $value ) {
71
  if (is_email($value)) $value = '<a href="mailto:'.$value.'">'.$value.'</a>';
72
  elseif (strtolower($key) == 'country') {
73
+ $value = cerber_get_flag_html($value) . '<b>' . cerber_country_name($value) . ' (' . $value . ')</b>';
74
  $ret['country'] = $value;
75
  }
76
 
192
  * @since 2.7
193
  *
194
  */
195
+ function cerber_get_flag_html( $code ) {
196
+ static $assets_url;
197
+ if ( ! isset( $assets_url ) ) {
198
+ $assets_url = plugin_dir_url( CERBER_FILE ) . 'assets';
199
+ }
200
+
201
+ return '<span style="padding-left: 24px; background: url(\'' . $assets_url . '/flags/' . strtolower( $code ) . '.gif\') no-repeat left;"></span>';
202
  }
203
  /*
204
  *
207
  * @since 2.7
208
  *
209
  */
210
+ function cerber_country_name( $code ) {
211
+ global $wpdb, $cerber_country_names;
212
+ static $cache, $locale;
213
+
214
+ if ( ! $code ) {
215
+ return __( 'Unknown', 'wp-cerber' );
216
+ }
217
+
218
+ if ( isset( $cache[ $code ] ) ) {
219
+ return $cache[ $code ];
220
+ }
221
+
222
+ $code = strtoupper( $code );
223
+ $ret = '';
224
+
225
+ if (!isset($locale)) {
226
+ $locale = get_bloginfo( 'language' );
227
+ if ( $locale != 'pt-BR' && $locale != 'zh-CN' ) {
228
+ $locale = substr( $locale, 0, 2 );
229
+ if ( ! in_array( $locale, array( 'de', 'en', 'es', 'fr', 'ja', 'ru' ) ) ) {
230
+ $locale = 'en';
231
+ }
232
+ }
233
+ }
234
+
235
+ $ret = $wpdb->get_var( 'SELECT country_name FROM ' . CERBER_GEO_TABLE . ' WHERE country = "'.$code.'" AND locale = "'.$locale.'"' );
236
+
237
+ if ($ret) {
238
+ $cache[ $code ] = $ret;
239
+ return $ret;
240
+ }
241
+
242
+ if ( isset( $cerber_country_names[ $code ] ) ) {
243
+ $ret = $cerber_country_names[ $code ];
244
+ }
245
+ else {
246
+ $ret = __( 'Unknown', 'wp-cerber' );
247
+ }
248
+
249
+ $cache[ $code ] = $ret;
250
+ return $ret;
251
+ }
252
+
253
+ function cerber_get_country_list() {
254
  global $cerber_country_names;
255
+ $ret = array();
256
+ foreach ( $cerber_country_names as $code => $name ) {
257
+ $ret[ $code ] = cerber_country_name( $code );
258
+ }
259
+
260
+ return $ret;
261
  }
262
 
263
  $cerber_country_names = array(
wp-cerber.php CHANGED
@@ -5,7 +5,7 @@
5
  Description: 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="http://wpcerber.com">wpcerber.com</a>.
6
  Author: Gregory
7
  Author URI: http://wpcerber.com
8
- Version: 5.2
9
  Text Domain: wp-cerber
10
  Domain Path: /languages
11
  Network: true
@@ -59,13 +59,15 @@
59
  // If this file is called directly, abort executing.
60
  if ( ! defined( 'WPINC' ) ) { exit; }
61
 
62
- define( 'CERBER_VER', '5.2' );
63
  define( 'CERBER_LOG_TABLE', 'cerber_log' );
64
  define( 'CERBER_ACL_TABLE', 'cerber_acl' );
65
  define( 'CERBER_BLOCKS_TABLE', 'cerber_blocks' );
66
  define( 'CERBER_LAB_TABLE', 'cerber_lab' );
67
  define( 'CERBER_LAB_IP_TABLE', 'cerber_lab_ip' );
68
  define( 'CERBER_LAB_NET_TABLE', 'cerber_lab_net' );
 
 
69
 
70
  define( 'WP_LOGIN_SCRIPT', 'wp-login.php' );
71
  define( 'WP_REG_URI', 'wp-register.php' );
@@ -641,6 +643,15 @@ function cerber_init() {
641
  if ( ! wp_next_scheduled( 'cerber_daily' ) ) {
642
  wp_schedule_event( time(), 'daily', 'cerber_daily' );
643
  }
 
 
 
 
 
 
 
 
 
644
  }
645
 
646
  /*
@@ -753,7 +764,7 @@ function cerber_auth_control( $null, $username, $password ) {
753
  cerber_log( 52, $username );
754
  cerber_block_add( null, 4, $username );
755
 
756
- // Create with message which is identical default WP
757
  return new WP_Error( 'incorrect_password', sprintf(
758
  __( '<strong>ERROR</strong>: The password you entered for the username %s is incorrect.' ),
759
  '<strong>' . $username . '</strong>'
@@ -773,7 +784,7 @@ function cerber_auth_control( $null, $username, $password ) {
773
 
774
  // @since 4.18 it is replacement for 'wp_login_failed' action hook
775
  // see WP function wp_authenticate()
776
- $ignore_codes = array( 'empty_username', 'empty_password' );
777
  if ( is_wp_error( $user ) && ! in_array( $user->get_error_code(), $ignore_codes ) ) {
778
  cerber_login_failed( $username );
779
  }
@@ -782,14 +793,28 @@ function cerber_auth_control( $null, $username, $password ) {
782
  }
783
 
784
  /*
785
- Block authentication for an existing user if IP is not allowed.
786
- Invoked in the 'wp_authenticate_username_password()'
787
  */
788
  add_filter( 'wp_authenticate_user', 'cerber_stop_authentication', 9999, 2 ); // fires after user found, with 'authenticate' filter
789
  function cerber_stop_authentication( $user, $password ) {
790
- global $wp_cerber;
791
 
792
- if ( !cerber_is_allowed() || lab_is_blocked($wp_cerber->getRemoteIp())) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
793
  status_header( 403 );
794
  $error = new WP_Error();
795
  $error->add( 'cerber_wp_error', $wp_cerber->getErrorMsg() );
@@ -800,17 +825,13 @@ function cerber_stop_authentication( $user, $password ) {
800
  return $user;
801
  }
802
 
803
- // Block prohibited usernames
804
- // add_filter('illegal_user_logins',function(){ return cerber_get_options('prohibited'); });
805
-
806
-
807
  /*
808
  * Handler for failed login attempts
809
  *
810
  */
811
  //add_action( 'wp_login_failed', 'cerber_login_failed' ); // @since 4.18
812
  function cerber_login_failed( $user_login ) {
813
- global $wpdb, $wp_cerber;
814
  static $is_processed = false;
815
 
816
  if ( $is_processed ) return;
@@ -837,7 +858,7 @@ function cerber_login_failed( $user_login ) {
837
  if ( $no_user ) {
838
  $ac = 51;
839
  }
840
- elseif ( ! cerber_is_allowed( $ip ) ) {
841
  $ac = 53;
842
  }
843
  /*
@@ -941,13 +962,13 @@ function cerber_failed_work($ip, $acl, $no_user, $user_login){
941
 
942
  add_filter( 'registration_errors', 'cerber_registration_request', 10, 3 );
943
  function cerber_registration_request( $errors, $sanitized_user_login, $user_email ) {
944
- global $wp_cerber;
945
 
946
  $code = null;
947
  $msg = null;
948
 
949
  if ( cerber_is_bot('botsreg') ) {
950
- cerber_log(54);
951
  $code = 'bot_detected';
952
  $msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
953
  apply_filters( 'cerber_msg_denied', __( 'You are not allowed to register.', 'wp-cerber' ), 'register' );
@@ -968,6 +989,13 @@ function cerber_registration_request( $errors, $sanitized_user_login, $user_emai
968
  $msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
969
  apply_filters( 'cerber_msg_denied', __( 'You are not allowed to register.', 'wp-cerber' ), 'register' );
970
  }
 
 
 
 
 
 
 
971
 
972
  if ($code){
973
  return new WP_Error($code, $msg);
@@ -977,6 +1005,7 @@ function cerber_registration_request( $errors, $sanitized_user_login, $user_emai
977
  }
978
 
979
  add_filter( 'option_users_can_register', function ( $value ) {
 
980
  if ( ! cerber_is_allowed() ) {
981
  return false;
982
  }
@@ -984,6 +1013,32 @@ add_filter( 'option_users_can_register', function ( $value ) {
984
  return $value;
985
  }, 9999 );
986
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
987
 
988
  // Lost password form --------------------------------------------------------------------
989
 
@@ -1016,37 +1071,74 @@ function cerber_lost_show_msg() {
1016
  }
1017
 
1018
 
1019
- // Comments section ----------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
1020
 
 
 
1021
 
1022
- if (1 == cerber_get_options('spamcomm')) {
1023
- // $approved = apply_filters( 'pre_comment_approved', $approved, $commentdata );
1024
- add_filter( 'pre_comment_approved', function ( $approved, $commentdata ) {
1025
- if ( ! cerber_is_comment_allowed() ) {
1026
- $approved = 'spam';
1027
- }
1028
- return $approved;
1029
- }, 10, 2 );
1030
- }
1031
- else {
1032
- add_action( 'pre_comment_on_post', function ( $comment_post_ID ) {
1033
- global $wp_cerber;
1034
-
1035
- if ( ! cerber_is_comment_allowed() ) {
1036
- setcookie( 'cerber-post-id', $comment_post_ID, time() + 60, '/' );
1037
- $comments = get_comments( array( 'number' => '1', 'post_id' => $comment_post_ID ) );
1038
- if ( $comments ) {
1039
- $loc = get_comment_link( $comments[0]->comment_ID );
1040
- } else {
1041
- $loc = get_permalink( $comment_post_ID ) . '#cerber-recaptcha-msg';
1042
- }
1043
- wp_safe_redirect( $loc );
1044
- exit;
 
 
1045
  }
 
 
 
1046
 
1047
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1048
 
1049
- }
1050
  /**
1051
  * Check if a submitted comment is allowed
1052
  *
@@ -1057,28 +1149,32 @@ function cerber_is_comment_allowed(){
1057
 
1058
  if (is_admin()) return true;
1059
 
1060
- $deny = false;
1061
 
1062
  if ( ! cerber_is_allowed() ) {
1063
- $deny = true;
1064
  }
1065
  elseif ( cerber_is_bot('botscomm') ) {
1066
  $remain = cerber_get_remain_count( null , true, 16, 3, 60);
1067
  if ($remain < 1) cerber_block_add( null, 6, '', 60 );
1068
- $deny = true;
1069
  }
1070
  elseif ( ! $wp_cerber->reCaptchaValidate( 'comment' , true ) ) {
1071
- $deny = true;
1072
  }
1073
  elseif ( lab_is_blocked( $wp_cerber->getRemoteIp() ) ) {
1074
- $deny = true;
1075
  }
1076
 
1077
- if ($deny) {
1078
- cerber_log( 16 );
 
 
 
 
1079
  }
1080
 
1081
- return !$deny;
1082
  }
1083
 
1084
  /**
@@ -1116,7 +1212,7 @@ function cerber_login_form_msg( $errors ) {
1116
  if ( ! cerber_is_allowed() ) {
1117
  $errors = $wp_cerber->getErrorMsg();
1118
  }
1119
- elseif ( ! $error && ( $msg = $wp_cerber->getRemainMsg() ) ) {
1120
  $errors .= '<p>' . $msg;
1121
  }
1122
  }
@@ -1167,7 +1263,7 @@ function cerber_redirect( $location, $status ) {
1167
  */
1168
  add_action( 'init', 'cerber_access_control', 1 );
1169
  function cerber_access_control() {
1170
- global $wp_cerber;
1171
 
1172
  if ( is_admin() ) {
1173
  return;
@@ -1187,6 +1283,8 @@ function cerber_access_control() {
1187
 
1188
  $opt = $wp_cerber->getSettings();
1189
 
 
 
1190
  $script = strtolower( cerber_get_last_in_uri( true ) );
1191
 
1192
  if ( $script ) {
@@ -1203,16 +1301,41 @@ function cerber_access_control() {
1203
  }
1204
  elseif ( $script == WP_XMLRPC_SCRIPT || $script == WP_TRACKBACK_SCRIPT ) { // no direct access
1205
  if ( $deny || ! empty( $opt['xmlrpc'] ) ) {
1206
- //cerber_log( 50 );
 
 
 
 
 
1207
  cerber_404_page();
1208
  }
1209
  }
1210
  }
1211
 
1212
- if ( $deny || ! empty( $opt['norest'] ) ) {
 
 
 
1213
  cerber_block_rest();
1214
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1215
 
 
1216
  if ( $deny || ! empty( $opt['xmlrpc'] ) ) {
1217
  add_filter( 'xmlrpc_enabled', '__return_false' );
1218
  add_filter( 'pings_open', '__return_false' );
@@ -1221,6 +1344,7 @@ function cerber_access_control() {
1221
  remove_action( 'wp_head', 'wlwmanifest_link', 10 );
1222
  }
1223
 
 
1224
  if ( $deny || ! empty( $opt['nofeeds'] ) ) {
1225
  remove_action( 'wp_head', 'feed_links', 2 );
1226
  remove_action( 'wp_head', 'feed_links_extra', 3 );
@@ -1240,92 +1364,92 @@ function cerber_access_control() {
1240
  }
1241
  }
1242
 
1243
- /* Antispam */
 
 
 
1244
  add_action( 'init', 'cerber_post_control', 2 );
1245
  function cerber_post_control(){
1246
- global $wp_cerber;
1247
 
1248
- //if ( $_SERVER['REQUEST_METHOD'] == 'GET' && cerber_antibot_enabled( array( 'botscomm', 'botsany' ) ) ){
1249
- if ( $_SERVER['REQUEST_METHOD'] == 'GET' ){
1250
- $antibot = get_site_option( 'cerber-antibot', null );
1251
- if (!empty($antibot[1])) {
1252
- foreach ( $antibot[1] as $item ) {
1253
- setcookie( $item[0], $item[1], time() + 3600, COOKIEPATH );
1254
- }
1255
- }
1256
  }
1257
 
1258
- if ( $_SERVER['REQUEST_METHOD'] != 'POST' || !cerber_antibot_enabled('botsany') ) {
 
 
 
 
1259
  return;
1260
  }
1261
 
1262
  // Exceptions -----------------------------------------------------------------------
1263
 
1264
- if ( cerber_acl_check( null, 'W' ) ) {
1265
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1266
  }
1267
 
1268
- // Comments
 
 
 
 
 
 
 
 
 
1269
  if ( 0 === strpos( trim( $_SERVER['REQUEST_URI'], '/' ), 'wp-comments-post.php' ) ) {
1270
- return;
1271
  }
1272
 
1273
  // XML-RPC
1274
  if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
1275
- return;
1276
  }
1277
 
1278
  // Trackback
1279
  if ( is_trackback() ) {
1280
- return;
1281
  }
1282
 
1283
  // Login page
1284
  if ( cerber_is_login_request() ) {
1285
- return;
1286
- }
1287
-
1288
- // Admin and AJAX requests by unauthorized users
1289
- if ( is_admin() ) {
1290
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
1291
- if (is_user_logged_in()) {
1292
- return;
1293
- }
1294
- if ($wp_cerber->getSettings('botssafe')){
1295
- return;
1296
- }
1297
- }
1298
- else {
1299
- return;
1300
- }
1301
- // if ( ! ( defined( 'DOING_AJAX' ) && DOING_AJAX && !is_user_logged_in() ) ) {
1302
- // return;
1303
- //}
1304
  }
1305
 
1306
-
1307
- // REST API but not a Contact Form 7 submission
1308
  if ( cerber_is_rest_url() ) {
1309
  if ( false === strpos( $_SERVER['REQUEST_URI'], 'contact-form-7' ) ) {
1310
- return;
1311
  }
1312
  }
1313
 
1314
- $deny = false;
1315
-
1316
- if ( ! cerber_is_allowed() ) {
1317
- $deny = true;
1318
- cerber_log(17); // TODO: should be another event, not 17 'spam bot'
1319
- }
1320
- elseif (cerber_is_bot('botsany')){
1321
- $deny = true;
1322
- cerber_log(17);
1323
- }
1324
-
1325
- if ($deny){
1326
- cerber_forbidden_page();
1327
- }
1328
-
1329
  }
1330
 
1331
  /*
@@ -1362,6 +1486,7 @@ function cerber_block_rest() {
1362
  remove_action( 'parse_request', 'rest_api_loaded' );
1363
 
1364
  if ( cerber_is_rest_url() ) {
 
1365
  cerber_404_page();
1366
  }
1367
  }
@@ -1515,9 +1640,9 @@ function cerber_check_groove( $hash = '' ) {
1515
  }
1516
 
1517
  /**
1518
- * Is bot detection engine enabled in a given location
1519
  *
1520
- * @param $location string|array Location
1521
  *
1522
  * @return bool true if enabled
1523
  */
@@ -1655,7 +1780,7 @@ function cerber_antibot_gene() {
1655
  * @return bool
1656
  */
1657
  function cerber_is_bot($location = '') {
1658
- global $wp_cerber;
1659
  static $ret = null;
1660
 
1661
  if ( isset( $ret ) ) {
@@ -1667,11 +1792,39 @@ function cerber_is_bot($location = '') {
1667
  return $ret;
1668
  }
1669
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1670
  if ( ! cerber_antibot_enabled($location) ) {
1671
  $ret = false;
1672
  return $ret;
1673
  }
1674
 
 
 
 
 
 
 
 
 
 
 
1675
  $antibot = get_site_option( 'cerber-antibot', null );
1676
 
1677
  $ret = false;
@@ -1695,6 +1848,7 @@ function cerber_is_bot($location = '') {
1695
  }
1696
 
1697
  if ( $ret ) {
 
1698
  if ( $wp_cerber->getSettings( 'cerberlab' ) ) {
1699
  lab_save_push( $wp_cerber->getRemoteIp(), 333, '' );
1700
  }
@@ -1704,6 +1858,75 @@ function cerber_is_bot($location = '') {
1704
  return $ret;
1705
  }
1706
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1707
  /**
1708
  * Set user session expiration
1709
  *
@@ -1741,27 +1964,23 @@ function cerber_log_logout() {
1741
  }
1742
 
1743
  //add_action( 'lostpassword_post', 'cerber_password_post' );
1744
- add_action( 'retrieve_password', 'cerber_password_post' );
1745
- function cerber_password_post( $user_login ) {
1746
  cerber_log( 21, $user_login );
1747
- }
1748
 
1749
- add_action( 'password_reset', 'cerber_password_reset' );
1750
- function cerber_password_reset( $user ) {
1751
  cerber_log( 20, $user->user_login, $user->ID );
1752
- }
1753
 
1754
- add_action( 'register_new_user', 'cerber_log_reg' );
1755
- function cerber_log_reg( $user_id ) {
1756
  $user = get_user_by( 'ID', $user_id );
1757
  cerber_log( 2, $user->user_login, $user_id );
1758
- }
1759
 
1760
- add_action( 'edit_user_created_user', 'cerber_log_create', 10, 2 );
1761
- function cerber_log_create( $user_id, $notify = null ) {
1762
  $user = get_user_by( 'ID', $user_id );
1763
  cerber_log( 1, $user->user_login, $user_id );
1764
- }
1765
 
1766
  // Lockouts routines ---------------------------------------------------------------------
1767
 
@@ -1995,7 +2214,6 @@ function cerber_get_remain_count( $ip = '', $check_acl = true, $activity = '7,51
1995
  */
1996
  function cerber_is_allowed( $ip = '' ) {
1997
  global $wp_cerber;
1998
- static $cache = array();
1999
 
2000
  if ( ! $ip ) {
2001
  $ip = $wp_cerber->getRemoteIp();
@@ -2005,25 +2223,16 @@ function cerber_is_allowed( $ip = '' ) {
2005
  return false;
2006
  }
2007
 
2008
- /*
2009
- if ( isset( $cache[ $ip ] ) ) {
2010
- return $cache[ $ip ];
2011
- }
2012
- */
2013
-
2014
  // @since 4.7.9
2015
  if ( cerber_block_check( $ip ) ) {
2016
- $cache[ $ip ] = false;
2017
  return false;
2018
  }
2019
 
2020
  $tag = cerber_acl_check( $ip );
2021
  if ( $tag == 'W' ) {
2022
- $cache[ $ip ] = true;
2023
  return true;
2024
  }
2025
  if ( $tag == 'B' ) {
2026
- $cache[ $ip ] = false;
2027
  return false;
2028
  }
2029
 
@@ -2033,20 +2242,22 @@ function cerber_is_allowed( $ip = '' ) {
2033
  }*/
2034
 
2035
  if ( cerber_is_citadel() ) {
2036
- $cache[ $ip ] = false;
2037
  return false;
2038
  }
2039
 
2040
  if ( lab_is_blocked( $ip, false ) ) {
2041
- $cache[ $ip ] = false;
2042
  return false;
2043
  }
2044
 
2045
- $cache[ $ip ] = true;
2046
  return true;
2047
  }
2048
  // TODO: Merge with $wp_cerber->getStatus();
2049
  function cerber_get_status( $ip ) {
 
 
 
 
 
2050
 
2051
  if ( cerber_block_check( $ip ) ) {
2052
  return 13;
@@ -2068,6 +2279,7 @@ function cerber_get_status( $ip ) {
2068
  return 15;
2069
  }
2070
 
 
2071
  return 0;
2072
  }
2073
 
@@ -2142,33 +2354,52 @@ function cerber_acl_remove( $ip ) {
2142
  */
2143
  function cerber_acl_check( $ip = null, $tag = '' ) {
2144
  global $wpdb, $wp_cerber;
 
 
2145
  if ( ! $ip ) {
2146
  $ip = $wp_cerber->getRemoteIp();
2147
  }
2148
 
 
 
 
 
 
 
2149
  if ( ! cerber_is_ipv4( $ip ) ) {
2150
- return cerber_acl_checkV6( $ip, $tag );
 
 
2151
  }
2152
 
2153
  $long = ip2long( $ip );
2154
 
2155
  if ( $tag ) {
2156
  if ( $tag != 'W' && $tag != 'B' ) {
2157
- return false;
2158
  }
2159
- if ( $wpdb->get_var( 'SELECT ip FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin <= '.$long.' AND '.$long.' <= ip_long_end AND tag = "'.$tag.'" LIMIT 1' ) ) {
2160
- return true;
2161
  }
2162
- return false;
 
 
 
 
 
2163
  }
2164
  else {
 
2165
  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' ) ) {
 
2166
  return $ret;
2167
  }
2168
  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' ) ) {
 
2169
  return $ret;
2170
  }
2171
 
 
2172
  return false;
2173
  }
2174
  }
@@ -2454,7 +2685,7 @@ function cerber_forbidden_page() {
2454
  <div style="background-color: #eee; width: 70%; border: solid 3px #ddd; padding: 1.5em 3em 3em 3em; font-family: Arial, Helvetica, sans-serif;">
2455
  <h1>We're sorry, you are not allowed to proceed</h1>
2456
  <p>Server stopped processing your request. Your attempt to submit the form looks similar to automated requests from spam posting software.</p>
2457
- <p>If you believe you should be able to submit, please let us know.</p>
2458
  </div>
2459
  </div>
2460
  </body>
@@ -2752,6 +2983,8 @@ function cerber_do_daily() {
2752
 
2753
  lab_trunc_push();
2754
 
 
 
2755
  $wpdb->query( 'DELETE FROM ' . CERBER_LAB_NET_TABLE . ' WHERE expires < ' . $time );
2756
 
2757
  $wpdb->query( 'OPTIMIZE TABLE ' . CERBER_LOG_TABLE );
@@ -2761,7 +2994,6 @@ function cerber_do_daily() {
2761
  $wpdb->query( 'OPTIMIZE TABLE ' . CERBER_LAB_IP_TABLE );
2762
  $wpdb->query( 'OPTIMIZE TABLE ' . CERBER_LAB_NET_TABLE );
2763
 
2764
- lab_validate_key();
2765
  }
2766
 
2767
  /*
@@ -2849,7 +3081,9 @@ function cerber_log( $activity, $login = '', $user_id = 0, $ip = null ) {
2849
 
2850
  $details = $why .'|0|0|0|'. $url;
2851
 
2852
- $ret = $wpdb->query( $wpdb->prepare( 'INSERT INTO ' . CERBER_LOG_TABLE . ' (ip, ip_long, user_login, user_id, stamp, activity, session_id, details) VALUES (%s,%d,%s,%d,%f,%d,%s,%s)', $ip, $ip_long, $login, $user_id, $stamp, $activity, $wp_cerber->getSessionID(), $details ) );
 
 
2853
  if ( ! $ret ) {
2854
  // workaround for a WP bugs like this: WP silently doesn't not insert a row into a table
2855
  // https://core.trac.wordpress.org/ticket/32315
@@ -2861,6 +3095,7 @@ function cerber_log( $activity, $login = '', $user_id = 0, $ip = null ) {
2861
  'stamp' => $stamp,
2862
  'activity' => $activity,
2863
  'session_id' => $wp_cerber->getSessionID(),
 
2864
  'details' => $details,
2865
  ), array( '%s', '%d', '%s', '%d', '%f', '%d' ) );
2866
  }
@@ -2876,7 +3111,12 @@ function cerber_log( $activity, $login = '', $user_id = 0, $ip = null ) {
2876
  if (!empty($subs)) {
2877
  foreach ( $subs as $hash => $sub ) {
2878
 
2879
- // Loop through parameters
 
 
 
 
 
2880
  if ( ! empty( $sub[1] ) && $sub[1] != $user_id ) {
2881
  continue;
2882
  }
@@ -2893,12 +3133,20 @@ function cerber_log( $activity, $login = '', $user_id = 0, $ip = null ) {
2893
  continue;
2894
  }
2895
 
2896
- // Some parameter(s) matched, send notification
2897
 
2898
  $labels = cerber_get_labels( 'activity' );
2899
 
2900
  $msg = __( 'Activity', 'wp-cerber' ) . ': ' . $labels[$activity] . "\n\n";
2901
- $msg .= __( 'IP', 'wp-cerber' ) . ': ' . $ip . "\n\n";
 
 
 
 
 
 
 
 
2902
 
2903
  if ( $user_id ) {
2904
  $u = get_userdata( $user_id );
@@ -2913,17 +3161,25 @@ function cerber_log( $activity, $login = '', $user_id = 0, $ip = null ) {
2913
  $msg .= __( 'Search string', 'wp-cerber' ) . ': ' . $sub['6'] . "\n\n";
2914
  }
2915
 
 
2916
  $args = cerber_subscribe_params();
2917
- $i = 0; $str = '';
 
2918
  foreach ($args as $arg => $val){
2919
- $str .= '&'.$arg.'='.$sub[$i];
 
 
 
 
 
 
 
2920
  $i++;
2921
  }
2922
-
2923
- $link = cerber_admin_link( 'activity' ).$str;
2924
 
2925
  $msg .= __( 'View activity in dashboard', 'wp-cerber' ) . ': ' . $link;
2926
- $msg .= "\n\n" . __( 'To unsubscribe click here', 'wp-cerber' ) .': '. cerber_admin_link( 'activity' ).'&unsubscribeme='.$hash;
2927
 
2928
  cerber_send_notify( 'subs', $msg, $ip );
2929
 
@@ -2931,7 +3187,7 @@ function cerber_log( $activity, $login = '', $user_id = 0, $ip = null ) {
2931
  }
2932
  }
2933
 
2934
- if ( $activity == 40 && $wp_cerber->getSettings( 'cerberlab' ) ) {
2935
  lab_save_push( $ip, $activity, '' );
2936
  }
2937
 
@@ -2982,6 +3238,11 @@ function cerber_subscribe_params() {
2982
  $search_activity = ( empty( $_GET['search_activity'] ) ) ? 0 : $_GET['search_activity'];
2983
  $filter_role = ( empty( $_GET['filter_role'] ) ) ? 0 : $_GET['filter_role'];
2984
 
 
 
 
 
 
2985
  // 'begin' and 'end' array keys are not used, added for compatibility
2986
  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 );
2987
  }
@@ -3026,8 +3287,10 @@ function cerber_activate() {
3026
  '<p style="font-size:120%;">' . __( 'WP Cerber is now active and has started protecting your site', 'wp-cerber' ) . '</p>' .
3027
  ' <p>' . __( 'Your IP address is added to the', 'wp-cerber' ) . ' ' . __( 'White IP Access List', 'wp-cerber' ) .
3028
 
3029
- ' <p><b>' . __( "It's important to check security settings.", 'wp-cerber' ) . '</b> &nbsp;<a href="http://wpcerber.com/" target="_blank">Read Cerber\'s blog</a> ' .
3030
- '&nbsp; <a href="http://wpcerber.com/subscribe-newsletter/" target="_blank">Subscribe to Cerber\'s newsletter</a></p>' .
 
 
3031
 
3032
  ' <p> </p><p><span class="dashicons dashicons-admin-settings"></span> <a href="' . cerber_admin_link( 'main' ) . '">' . __( 'Main Settings', 'wp-cerber' ) . '</a>' .
3033
  ' <span style="margin-left:20px;" class="dashicons dashicons-admin-network"></span> <a href="' . cerber_admin_link( 'acl' ) . '">' . __( 'Access Lists', 'wp-cerber' ) . '</a>' .
@@ -3187,13 +3450,28 @@ function cerber_create_db($recreate = true) {
3187
  }
3188
  $sql[] = '
3189
  CREATE TABLE IF NOT EXISTS ' . CERBER_LAB_NET_TABLE . ' (
3190
- ip varchar(39) CHARACTER SET ascii NOT NULL COMMENT "Malicious IP",
3191
- expires INT(11) UNSIGNED NOT NULL,
3192
- PRIMARY KEY (ip)
 
 
 
 
3193
  ) DEFAULT CHARSET=utf8 COMMENT="Cerber lab network cache";
3194
  ';
3195
  }
3196
 
 
 
 
 
 
 
 
 
 
 
 
3197
  foreach ( $sql as $query ) {
3198
  if ( ! $wpdb->query( $query ) && $wpdb->last_error ) {
3199
  $db_errors[] = array( $wpdb->last_error, $wpdb->last_query );
@@ -3242,8 +3520,8 @@ function cerber_upgrade_db( $force = false ) {
3242
  }
3243
 
3244
  // @since 4.9
3245
- if ( $force || ! cerber_is_column( CERBER_ACL_TABLE, 'session_id' ) ) {
3246
- $sql[] = 'ALTER TABLE cerber_log
3247
  ADD session_id CHAR(32) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "",
3248
  ADD country CHAR(3) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "" COMMENT "Country code",
3249
  ADD details VARCHAR(250) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "" COMMENT "Details about HTTP request";
5
  Description: 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="http://wpcerber.com">wpcerber.com</a>.
6
  Author: Gregory
7
  Author URI: http://wpcerber.com
8
+ Version: 5.5
9
  Text Domain: wp-cerber
10
  Domain Path: /languages
11
  Network: true
59
  // If this file is called directly, abort executing.
60
  if ( ! defined( 'WPINC' ) ) { exit; }
61
 
62
+ define( 'CERBER_VER', '5.5' );
63
  define( 'CERBER_LOG_TABLE', 'cerber_log' );
64
  define( 'CERBER_ACL_TABLE', 'cerber_acl' );
65
  define( 'CERBER_BLOCKS_TABLE', 'cerber_blocks' );
66
  define( 'CERBER_LAB_TABLE', 'cerber_lab' );
67
  define( 'CERBER_LAB_IP_TABLE', 'cerber_lab_ip' );
68
  define( 'CERBER_LAB_NET_TABLE', 'cerber_lab_net' );
69
+ define( 'CERBER_GEO_TABLE', 'cerber_countries' );
70
+
71
 
72
  define( 'WP_LOGIN_SCRIPT', 'wp-login.php' );
73
  define( 'WP_REG_URI', 'wp-register.php' );
643
  if ( ! wp_next_scheduled( 'cerber_daily' ) ) {
644
  wp_schedule_event( time(), 'daily', 'cerber_daily' );
645
  }
646
+
647
+ if ( isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'GET' ){
648
+ $antibot = get_site_option( 'cerber-antibot', null );
649
+ if (!empty($antibot[1])) {
650
+ foreach ( $antibot[1] as $item ) {
651
+ setcookie( $item[0], $item[1], time() + 3600, COOKIEPATH );
652
+ }
653
+ }
654
+ }
655
  }
656
 
657
  /*
764
  cerber_log( 52, $username );
765
  cerber_block_add( null, 4, $username );
766
 
767
+ // Create with message that is identical default WP
768
  return new WP_Error( 'incorrect_password', sprintf(
769
  __( '<strong>ERROR</strong>: The password you entered for the username %s is incorrect.' ),
770
  '<strong>' . $username . '</strong>'
784
 
785
  // @since 4.18 it is replacement for 'wp_login_failed' action hook
786
  // see WP function wp_authenticate()
787
+ $ignore_codes = array( 'empty_username', 'empty_password', 'cerber_denied' );
788
  if ( is_wp_error( $user ) && ! in_array( $user->get_error_code(), $ignore_codes ) ) {
789
  cerber_login_failed( $username );
790
  }
793
  }
794
 
795
  /*
796
+ Block authentication for an existing user if the remote IP is not allowed.
797
+ Invoking in the 'wp_authenticate_username_password()'
798
  */
799
  add_filter( 'wp_authenticate_user', 'cerber_stop_authentication', 9999, 2 ); // fires after user found, with 'authenticate' filter
800
  function cerber_stop_authentication( $user, $password ) {
801
+ global $wp_cerber, $cerber_status;
802
 
803
+ $deny = false;
804
+
805
+ if ( ! cerber_is_allowed() ) {
806
+ $deny = true;
807
+ }
808
+ elseif ( ! cerber_geo_allowed( 'geo_login' ) ) {
809
+ $cerber_status = 16;
810
+ $deny = true;
811
+ }
812
+ elseif ( lab_is_blocked( $wp_cerber->getRemoteIp() ) ) {
813
+ $cerber_status = 15;
814
+ $deny = true;
815
+ }
816
+
817
+ if ( $deny ) {
818
  status_header( 403 );
819
  $error = new WP_Error();
820
  $error->add( 'cerber_wp_error', $wp_cerber->getErrorMsg() );
825
  return $user;
826
  }
827
 
 
 
 
 
828
  /*
829
  * Handler for failed login attempts
830
  *
831
  */
832
  //add_action( 'wp_login_failed', 'cerber_login_failed' ); // @since 4.18
833
  function cerber_login_failed( $user_login ) {
834
+ global $wpdb, $wp_cerber, $cerber_status;
835
  static $is_processed = false;
836
 
837
  if ( $is_processed ) return;
858
  if ( $no_user ) {
859
  $ac = 51;
860
  }
861
+ elseif ( ! cerber_is_allowed( $ip ) || $cerber_status == 15 || $cerber_status == 16 ) { // TODO should be refactored together with cerber_stop_authentication
862
  $ac = 53;
863
  }
864
  /*
962
 
963
  add_filter( 'registration_errors', 'cerber_registration_request', 10, 3 );
964
  function cerber_registration_request( $errors, $sanitized_user_login, $user_email ) {
965
+ global $wp_cerber, $cerber_status;
966
 
967
  $code = null;
968
  $msg = null;
969
 
970
  if ( cerber_is_bot('botsreg') ) {
971
+ cerber_log(54); // TODO should be separate code to detect bot activity?
972
  $code = 'bot_detected';
973
  $msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
974
  apply_filters( 'cerber_msg_denied', __( 'You are not allowed to register.', 'wp-cerber' ), 'register' );
989
  $msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
990
  apply_filters( 'cerber_msg_denied', __( 'You are not allowed to register.', 'wp-cerber' ), 'register' );
991
  }
992
+ elseif ( ! cerber_geo_allowed( 'geo_register' ) ) {
993
+ $cerber_status = 16; // TODO: refactor cerber_log, include this status as a second parameter
994
+ cerber_log(54); // TODO should be separate code?
995
+ $code = 'country_denied';
996
+ $msg = '<strong>' . __( 'ERROR:', 'wp-cerber' ) . ' </strong>' .
997
+ apply_filters( 'cerber_msg_denied', __( 'You are not allowed to register.', 'wp-cerber' ), 'register' );
998
+ }
999
 
1000
  if ($code){
1001
  return new WP_Error($code, $msg);
1005
  }
1006
 
1007
  add_filter( 'option_users_can_register', function ( $value ) {
1008
+ //if ( ! cerber_is_allowed() || !cerber_geo_allowed( 'geo_register' )) {
1009
  if ( ! cerber_is_allowed() ) {
1010
  return false;
1011
  }
1013
  return $value;
1014
  }, 9999 );
1015
 
1016
+ // @since 5.3
1017
+ // TODO: Use the result of cerber_registration_request()
1018
+ add_filter( 'pre_user_login', function ( $login ) {
1019
+ global $cerber_status;
1020
+ if ( ! cerber_is_allowed() ) {
1021
+ cerber_log( 54 );
1022
+
1023
+ return null;
1024
+ }
1025
+ if ( ! cerber_geo_allowed( 'geo_register' ) ) {
1026
+ $cerber_status = 16;
1027
+ cerber_log( 54 );
1028
+
1029
+ return null;
1030
+ }
1031
+
1032
+ return $login;
1033
+ }, 9999 );
1034
+
1035
+ // Filter out prohibited usernames
1036
+ add_filter( 'illegal_user_logins', function () {
1037
+ global $wp_cerber;
1038
+ return $wp_cerber->getSettings( 'prohibited' );
1039
+ }, 9999 );
1040
+
1041
+
1042
 
1043
  // Lost password form --------------------------------------------------------------------
1044
 
1071
  }
1072
 
1073
 
1074
+ // Comments (commenting) section ----------------------------------------------------------
1075
+
1076
+ /**
1077
+ * If a comment must be marked as spam
1078
+ *
1079
+ */
1080
+ add_filter( 'pre_comment_approved', function ( $approved, $commentdata ) {
1081
+ if ( 1 == cerber_get_options( 'spamcomm' ) && ! cerber_is_comment_allowed() ) {
1082
+ $approved = 'spam';
1083
+ }
1084
 
1085
+ return $approved;
1086
+ }, 10, 2 );
1087
 
1088
+ /**
1089
+ * If a comment must be denied
1090
+ *
1091
+ */
1092
+ add_action( 'pre_comment_on_post', function ( $comment_post_ID ) {
1093
+ global $cerber_status;
1094
+
1095
+ $deny = false;
1096
+
1097
+ if ( 1 != cerber_get_options( 'spamcomm' ) && ! cerber_is_comment_allowed() ) {
1098
+ $deny = true;
1099
+ }
1100
+ elseif ( ! cerber_geo_allowed( 'geo_comment' ) ) {
1101
+ $cerber_status = 16;
1102
+ cerber_log(19);
1103
+ $deny = true;
1104
+ }
1105
+
1106
+ if ( $deny ) {
1107
+ setcookie( 'cerber-post-id', $comment_post_ID, time() + 60, '/' );
1108
+ $comments = get_comments( array( 'number' => '1', 'post_id' => $comment_post_ID ) );
1109
+ if ( $comments ) {
1110
+ $loc = get_comment_link( $comments[0]->comment_ID );
1111
+ } else {
1112
+ $loc = get_permalink( $comment_post_ID ) . '#cerber-recaptcha-msg';
1113
  }
1114
+ wp_safe_redirect( $loc );
1115
+ exit;
1116
+ }
1117
 
1118
+ } );
1119
+
1120
+ /**
1121
+ * If submit comments via REST API is not allowed
1122
+ *
1123
+ */
1124
+ add_filter( 'rest_allow_anonymous_comments', function ( $allowed, $request ) {
1125
+ global $wp_cerber, $cerber_status;
1126
+
1127
+ if ( ! cerber_is_allowed() ) {
1128
+ $allowed = false;
1129
+ }
1130
+ if ( ! cerber_geo_allowed( 'geo_comment' ) ) {
1131
+ ceber_log(19);
1132
+ $cerber_status = 16;
1133
+ $allowed = false;
1134
+ }
1135
+ elseif ( lab_is_blocked( $wp_cerber->getRemoteIp() ) ) {
1136
+ $allowed = false;
1137
+ }
1138
+
1139
+ return $allowed;
1140
+ }, 10, 2 );
1141
 
 
1142
  /**
1143
  * Check if a submitted comment is allowed
1144
  *
1149
 
1150
  if (is_admin()) return true;
1151
 
1152
+ $deny = null;
1153
 
1154
  if ( ! cerber_is_allowed() ) {
1155
+ $deny = 19;
1156
  }
1157
  elseif ( cerber_is_bot('botscomm') ) {
1158
  $remain = cerber_get_remain_count( null , true, 16, 3, 60);
1159
  if ($remain < 1) cerber_block_add( null, 6, '', 60 );
1160
+ $deny = 16;
1161
  }
1162
  elseif ( ! $wp_cerber->reCaptchaValidate( 'comment' , true ) ) {
1163
+ $deny = 16;
1164
  }
1165
  elseif ( lab_is_blocked( $wp_cerber->getRemoteIp() ) ) {
1166
+ $deny = 19;
1167
  }
1168
 
1169
+ if ( $deny ) {
1170
+ cerber_log( $deny );
1171
+ $ret = false;
1172
+ }
1173
+ else {
1174
+ $ret = true;
1175
  }
1176
 
1177
+ return $ret;
1178
  }
1179
 
1180
  /**
1212
  if ( ! cerber_is_allowed() ) {
1213
  $errors = $wp_cerber->getErrorMsg();
1214
  }
1215
+ elseif ( ! $error && ( $msg = $wp_cerber->getRemainMsg() ) ) {
1216
  $errors .= '<p>' . $msg;
1217
  }
1218
  }
1263
  */
1264
  add_action( 'init', 'cerber_access_control', 1 );
1265
  function cerber_access_control() {
1266
+ global $wp_cerber, $cerber_status;
1267
 
1268
  if ( is_admin() ) {
1269
  return;
1283
 
1284
  $opt = $wp_cerber->getSettings();
1285
 
1286
+
1287
+
1288
  $script = strtolower( cerber_get_last_in_uri( true ) );
1289
 
1290
  if ( $script ) {
1301
  }
1302
  elseif ( $script == WP_XMLRPC_SCRIPT || $script == WP_TRACKBACK_SCRIPT ) { // no direct access
1303
  if ( $deny || ! empty( $opt['xmlrpc'] ) ) {
1304
+ cerber_log( 50 ); // @since 5.21
1305
+ cerber_404_page();
1306
+ }
1307
+ elseif ( !cerber_geo_allowed( 'geo_xmlrpc' ) ) {
1308
+ $cerber_status = 16;
1309
+ cerber_log( 71 );
1310
  cerber_404_page();
1311
  }
1312
  }
1313
  }
1314
 
1315
+ // TODO: the code below should be located before $script or be called in the beginning of cerber_404_page()
1316
+
1317
+ // REST API
1318
+ if ( $deny ) {
1319
  cerber_block_rest();
1320
  }
1321
+ elseif ( cerber_is_rest_url() ) {
1322
+ $rest_allowed = true;
1323
+ if ( ! empty( $opt['norest']) && ! cerber_is_route_allowed() ) {
1324
+ $rest_allowed = false;
1325
+ }
1326
+ if ( $rest_allowed && cerber_is_route_blocked() ) {
1327
+ $rest_allowed = false;
1328
+ }
1329
+ if ( $rest_allowed && ! cerber_geo_allowed( 'geo_restapi' ) ) {
1330
+ $rest_allowed = false;
1331
+ $cerber_status = 16;
1332
+ }
1333
+ if ( ! $rest_allowed ) {
1334
+ cerber_block_rest();
1335
+ }
1336
+ }
1337
 
1338
+ // Some XML-RPC stuff
1339
  if ( $deny || ! empty( $opt['xmlrpc'] ) ) {
1340
  add_filter( 'xmlrpc_enabled', '__return_false' );
1341
  add_filter( 'pings_open', '__return_false' );
1344
  remove_action( 'wp_head', 'wlwmanifest_link', 10 );
1345
  }
1346
 
1347
+ // Feeds
1348
  if ( $deny || ! empty( $opt['nofeeds'] ) ) {
1349
  remove_action( 'wp_head', 'feed_links', 2 );
1350
  remove_action( 'wp_head', 'feed_links_extra', 3 );
1364
  }
1365
  }
1366
 
1367
+ /**
1368
+ * Antispam & Antibot for forms
1369
+ *
1370
+ */
1371
  add_action( 'init', 'cerber_post_control', 2 );
1372
  function cerber_post_control(){
1373
+ global $wp_cerber, $cerber_status;
1374
 
1375
+ if ( isset( $_SERVER['REQUEST_METHOD'] ) ) {
1376
+ $method = $_SERVER['REQUEST_METHOD'];
1377
+ }
1378
+ else {
1379
+ $method = '';
 
 
 
1380
  }
1381
 
1382
+ if ( $method != 'POST' || cerber_acl_check( null, 'W' ) ) {
1383
+ return;
1384
+ }
1385
+
1386
+ if ( !cerber_antibot_enabled('botsany') || !cerber_geo_rules('geo_submit')) {
1387
  return;
1388
  }
1389
 
1390
  // Exceptions -----------------------------------------------------------------------
1391
 
1392
+ if (cerber_post_exception()) {
1393
+ return;
1394
+ }
1395
+
1396
+ $deny = false;
1397
+
1398
+ if ( ! cerber_is_allowed() ) {
1399
+ $deny = true;
1400
+ cerber_log(18);
1401
+ }
1402
+ elseif ( cerber_is_bot( 'botsany' ) ) {
1403
+ $deny = true;
1404
+ cerber_log( 17 );
1405
+ }
1406
+ elseif ( !cerber_geo_allowed( 'geo_submit' ) ) {
1407
+ $deny = true;
1408
+ $cerber_status = 16; // TODO: refactor cerber_log, include this status as a second parameter
1409
+ cerber_log( 18 );
1410
+ }
1411
+
1412
+ if ($deny){
1413
+ cerber_forbidden_page();
1414
  }
1415
 
1416
+ }
1417
+
1418
+ /**
1419
+ * Exception for POST query control
1420
+ *
1421
+ * @return bool
1422
+ */
1423
+ function cerber_post_exception(){
1424
+
1425
+ // Comments
1426
  if ( 0 === strpos( trim( $_SERVER['REQUEST_URI'], '/' ), 'wp-comments-post.php' ) ) {
1427
+ return true;
1428
  }
1429
 
1430
  // XML-RPC
1431
  if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
1432
+ return true;
1433
  }
1434
 
1435
  // Trackback
1436
  if ( is_trackback() ) {
1437
+ return true;
1438
  }
1439
 
1440
  // Login page
1441
  if ( cerber_is_login_request() ) {
1442
+ return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1443
  }
1444
 
1445
+ // REST API but not Contact Form 7 submission
 
1446
  if ( cerber_is_rest_url() ) {
1447
  if ( false === strpos( $_SERVER['REQUEST_URI'], 'contact-form-7' ) ) {
1448
+ return true;
1449
  }
1450
  }
1451
 
1452
+ return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1453
  }
1454
 
1455
  /*
1486
  remove_action( 'parse_request', 'rest_api_loaded' );
1487
 
1488
  if ( cerber_is_rest_url() ) {
1489
+ cerber_log(70);
1490
  cerber_404_page();
1491
  }
1492
  }
1640
  }
1641
 
1642
  /**
1643
+ * Is bot detection engine enabled in a given rule_id
1644
  *
1645
+ * @param $rule_id string|array Location
1646
  *
1647
  * @return bool true if enabled
1648
  */
1780
  * @return bool
1781
  */
1782
  function cerber_is_bot($location = '') {
1783
+ global $wp_cerber, $cerber_status;
1784
  static $ret = null;
1785
 
1786
  if ( isset( $ret ) ) {
1792
  return $ret;
1793
  }
1794
 
1795
+ // Admin || AJAX requests by unauthorized users
1796
+ if ( is_admin() ) {
1797
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
1798
+ if (is_user_logged_in()) {
1799
+ $ret = false;
1800
+ return $ret;
1801
+ }
1802
+ if ($wp_cerber->getSettings('botssafe')){
1803
+ $ret = false;
1804
+ return $ret;
1805
+ }
1806
+ }
1807
+ else {
1808
+ $ret = false;
1809
+ return $ret;
1810
+ }
1811
+ }
1812
+
1813
  if ( ! cerber_antibot_enabled($location) ) {
1814
  $ret = false;
1815
  return $ret;
1816
  }
1817
 
1818
+ // Antibot whitelist
1819
+ if ( ( $list = $wp_cerber->getSettings( 'botswhite' ) ) && is_array( $list ) ) {
1820
+ foreach ( $list as $exception ) {
1821
+ if ( false !== strpos( trim( $_SERVER['REQUEST_URI'], '/' ), $exception ) ) {
1822
+ $ret = false;
1823
+ return $ret;
1824
+ }
1825
+ }
1826
+ }
1827
+
1828
  $antibot = get_site_option( 'cerber-antibot', null );
1829
 
1830
  $ret = false;
1848
  }
1849
 
1850
  if ( $ret ) {
1851
+ $cerber_status = 11;
1852
  if ( $wp_cerber->getSettings( 'cerberlab' ) ) {
1853
  lab_save_push( $wp_cerber->getRemoteIp(), 333, '' );
1854
  }
1858
  return $ret;
1859
  }
1860
 
1861
+ function cerber_geo_allowed( $rule_id = '' ) {
1862
+ global $wp_cerber;
1863
+
1864
+ if ( !$rule_id || ( defined( 'DOING_CRON' ) && DOING_CRON ) || !lab_lab() ) {
1865
+ return true;
1866
+ }
1867
+
1868
+ $tag = cerber_acl_check();
1869
+ if ( $tag == 'W' ) {
1870
+ return true;
1871
+ }
1872
+
1873
+ $rule = cerber_geo_rules( $rule_id );
1874
+ if ( $rule && $country = lab_get_country( $wp_cerber->getRemoteIp(), false ) ) {
1875
+ if ( in_array( $country, $rule['list'] ) ) {
1876
+ if ( $rule['type'] == 'W' ) {
1877
+ return true;
1878
+ }
1879
+
1880
+ return false;
1881
+ }
1882
+ if ( $rule['type'] == 'W' ) {
1883
+ return false;
1884
+ }
1885
+
1886
+ return true;
1887
+ }
1888
+
1889
+ return true;
1890
+ }
1891
+
1892
+ /**
1893
+ * Retrieve and return GEO rule(s) from the DB
1894
+ *
1895
+ * @param string $rule_id Slug of a rule
1896
+ *
1897
+ * @return bool|array If a rule exists return array of countries
1898
+ */
1899
+ function cerber_geo_rules( $rule_id = '' ) {
1900
+ global $wpdb;
1901
+
1902
+ if (is_multisite()) {
1903
+ $geo = $wpdb->get_var( 'SELECT meta_value FROM ' . $wpdb->sitemeta . ' WHERE meta_key = "geo_rule_set"' );
1904
+ }
1905
+ else {
1906
+ $geo = $wpdb->get_var( 'SELECT option_value FROM ' . $wpdb->options . ' WHERE option_name = "geo_rule_set"' );
1907
+ }
1908
+
1909
+ if ( $geo ) {
1910
+ $rules = unserialize( $geo );
1911
+ if ( $rule_id ) {
1912
+ if ( ! empty( $rules[ $rule_id ] ) ) {
1913
+ $ret = $rules[ $rule_id ];
1914
+ }
1915
+ else {
1916
+ $ret = false;
1917
+ }
1918
+ }
1919
+ else {
1920
+ $ret = $rules;
1921
+ }
1922
+ }
1923
+ else {
1924
+ $ret = false;
1925
+ }
1926
+
1927
+ return $ret;
1928
+ }
1929
+
1930
  /**
1931
  * Set user session expiration
1932
  *
1964
  }
1965
 
1966
  //add_action( 'lostpassword_post', 'cerber_password_post' );
1967
+ add_action( 'retrieve_password', function ( $user_login ) {
 
1968
  cerber_log( 21, $user_login );
1969
+ } );
1970
 
1971
+ add_action( 'password_reset', function ( $user ) {
 
1972
  cerber_log( 20, $user->user_login, $user->ID );
1973
+ } );
1974
 
1975
+ add_action( 'register_new_user', function ( $user_id ) {
 
1976
  $user = get_user_by( 'ID', $user_id );
1977
  cerber_log( 2, $user->user_login, $user_id );
1978
+ });
1979
 
1980
+ add_action( 'edit_user_created_user', function ( $user_id, $notify = null ) {
 
1981
  $user = get_user_by( 'ID', $user_id );
1982
  cerber_log( 1, $user->user_login, $user_id );
1983
+ }, 10, 2 );
1984
 
1985
  // Lockouts routines ---------------------------------------------------------------------
1986
 
2214
  */
2215
  function cerber_is_allowed( $ip = '' ) {
2216
  global $wp_cerber;
 
2217
 
2218
  if ( ! $ip ) {
2219
  $ip = $wp_cerber->getRemoteIp();
2223
  return false;
2224
  }
2225
 
 
 
 
 
 
 
2226
  // @since 4.7.9
2227
  if ( cerber_block_check( $ip ) ) {
 
2228
  return false;
2229
  }
2230
 
2231
  $tag = cerber_acl_check( $ip );
2232
  if ( $tag == 'W' ) {
 
2233
  return true;
2234
  }
2235
  if ( $tag == 'B' ) {
 
2236
  return false;
2237
  }
2238
 
2242
  }*/
2243
 
2244
  if ( cerber_is_citadel() ) {
 
2245
  return false;
2246
  }
2247
 
2248
  if ( lab_is_blocked( $ip, false ) ) {
 
2249
  return false;
2250
  }
2251
 
 
2252
  return true;
2253
  }
2254
  // TODO: Merge with $wp_cerber->getStatus();
2255
  function cerber_get_status( $ip ) {
2256
+ global $cerber_status;
2257
+
2258
+ if ( ! empty( $cerber_status ) ) {
2259
+ return $cerber_status;
2260
+ }
2261
 
2262
  if ( cerber_block_check( $ip ) ) {
2263
  return 13;
2279
  return 15;
2280
  }
2281
 
2282
+
2283
  return 0;
2284
  }
2285
 
2354
  */
2355
  function cerber_acl_check( $ip = null, $tag = '' ) {
2356
  global $wpdb, $wp_cerber;
2357
+ static $cache; // @since 5.26
2358
+
2359
  if ( ! $ip ) {
2360
  $ip = $wp_cerber->getRemoteIp();
2361
  }
2362
 
2363
+ $key = cerber_get_id_ip( $ip ) . $tag;
2364
+
2365
+ if ( isset( $cache[ $key ] ) ) {
2366
+ return $cache[ $key ];
2367
+ }
2368
+
2369
  if ( ! cerber_is_ipv4( $ip ) ) {
2370
+ $ret = cerber_acl_checkV6( $ip, $tag );
2371
+ $cache[ $key ] = $ret;
2372
+ return $ret;
2373
  }
2374
 
2375
  $long = ip2long( $ip );
2376
 
2377
  if ( $tag ) {
2378
  if ( $tag != 'W' && $tag != 'B' ) {
2379
+ $ret = false;
2380
  }
2381
+ 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' ) ) {
2382
+ $ret = true;
2383
  }
2384
+ else {
2385
+ $ret = false;
2386
+ }
2387
+
2388
+ $cache[ $key ] = $ret;
2389
+ return $ret;
2390
  }
2391
  else {
2392
+ // We use two queries because of possible overlapping an IP and its network
2393
  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' ) ) {
2394
+ $cache[ $key ] = $ret;
2395
  return $ret;
2396
  }
2397
  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' ) ) {
2398
+ $cache[ $key ] = $ret;
2399
  return $ret;
2400
  }
2401
 
2402
+ $cache[ $key ] = false;
2403
  return false;
2404
  }
2405
  }
2685
  <div style="background-color: #eee; width: 70%; border: solid 3px #ddd; padding: 1.5em 3em 3em 3em; font-family: Arial, Helvetica, sans-serif;">
2686
  <h1>We're sorry, you are not allowed to proceed</h1>
2687
  <p>Server stopped processing your request. Your attempt to submit the form looks similar to automated requests from spam posting software.</p>
2688
+ <p>If you believe you should be able to perform this request, please let us know.</p>
2689
  </div>
2690
  </div>
2691
  </body>
2983
 
2984
  lab_trunc_push();
2985
 
2986
+ lab_validate_lic();
2987
+
2988
  $wpdb->query( 'DELETE FROM ' . CERBER_LAB_NET_TABLE . ' WHERE expires < ' . $time );
2989
 
2990
  $wpdb->query( 'OPTIMIZE TABLE ' . CERBER_LOG_TABLE );
2994
  $wpdb->query( 'OPTIMIZE TABLE ' . CERBER_LAB_IP_TABLE );
2995
  $wpdb->query( 'OPTIMIZE TABLE ' . CERBER_LAB_NET_TABLE );
2996
 
 
2997
  }
2998
 
2999
  /*
3081
 
3082
  $details = $why .'|0|0|0|'. $url;
3083
 
3084
+ $country = lab_get_country( $ip );
3085
+
3086
+ $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 ) );
3087
  if ( ! $ret ) {
3088
  // workaround for a WP bugs like this: WP silently doesn't not insert a row into a table
3089
  // https://core.trac.wordpress.org/ticket/32315
3095
  'stamp' => $stamp,
3096
  'activity' => $activity,
3097
  'session_id' => $wp_cerber->getSessionID(),
3098
+ 'country' => $country,
3099
  'details' => $details,
3100
  ), array( '%s', '%d', '%s', '%d', '%f', '%d' ) );
3101
  }
3111
  if (!empty($subs)) {
3112
  foreach ( $subs as $hash => $sub ) {
3113
 
3114
+ // Loop through subscription parameters
3115
+ if ( ! empty( $sub[0] )) {
3116
+ if ( ! in_array( $activity, $sub[0] ) ) {
3117
+ continue;
3118
+ }
3119
+ }
3120
  if ( ! empty( $sub[1] ) && $sub[1] != $user_id ) {
3121
  continue;
3122
  }
3133
  continue;
3134
  }
3135
 
3136
+ // Some parameter(s) matched, prepare and send notification
3137
 
3138
  $labels = cerber_get_labels( 'activity' );
3139
 
3140
  $msg = __( 'Activity', 'wp-cerber' ) . ': ' . $labels[$activity] . "\n\n";
3141
+
3142
+ if ( $country ) {
3143
+ $coname = ' ('.cerber_country_name( $country ).')';
3144
+ }
3145
+ else {
3146
+ $coname = '';
3147
+ }
3148
+
3149
+ $msg .= __( 'IP', 'wp-cerber' ) . ': ' . $ip . $coname. "\n\n";
3150
 
3151
  if ( $user_id ) {
3152
  $u = get_userdata( $user_id );
3161
  $msg .= __( 'Search string', 'wp-cerber' ) . ': ' . $sub['6'] . "\n\n";
3162
  }
3163
 
3164
+ // Link to the Activity admin page
3165
  $args = cerber_subscribe_params();
3166
+ $i = 0;
3167
+ $link_params = '';
3168
  foreach ($args as $arg => $val){
3169
+ if (is_array($sub[$i])){
3170
+ foreach ( $sub[ $i ] as $item ) {
3171
+ $link_params .= '&' . $arg . '[]=' . $item;
3172
+ }
3173
+ }
3174
+ else {
3175
+ $link_params .= '&' . $arg . '=' . $sub[ $i ];
3176
+ }
3177
  $i++;
3178
  }
3179
+ $link = cerber_admin_link( 'activity' ) . $link_params;
 
3180
 
3181
  $msg .= __( 'View activity in dashboard', 'wp-cerber' ) . ': ' . $link;
3182
+ $msg .= "\n\n" . __( 'To unsubscribe click here', 'wp-cerber' ) . ': ' . cerber_admin_link( 'activity' ) . '&unsubscribeme=' . $hash;
3183
 
3184
  cerber_send_notify( 'subs', $msg, $ip );
3185
 
3187
  }
3188
  }
3189
 
3190
+ if ( in_array( $activity, array( 16, 17, 40 ) ) && $wp_cerber->getSettings( 'cerberlab' ) ) {
3191
  lab_save_push( $ip, $activity, '' );
3192
  }
3193
 
3238
  $search_activity = ( empty( $_GET['search_activity'] ) ) ? 0 : $_GET['search_activity'];
3239
  $filter_role = ( empty( $_GET['filter_role'] ) ) ? 0 : $_GET['filter_role'];
3240
 
3241
+ if ( ! is_array( $filter_activity ) ) {
3242
+ $filter_activity = array( $filter_activity );
3243
+ }
3244
+ $filter_activity = array_filter( $filter_activity );
3245
+
3246
  // 'begin' and 'end' array keys are not used, added for compatibility
3247
  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 );
3248
  }
3287
  '<p style="font-size:120%;">' . __( 'WP Cerber is now active and has started protecting your site', 'wp-cerber' ) . '</p>' .
3288
  ' <p>' . __( 'Your IP address is added to the', 'wp-cerber' ) . ' ' . __( 'White IP Access List', 'wp-cerber' ) .
3289
 
3290
+ ' <p style="font-size:120%;"><a href="http://wpcerber.com/getting-started/" target="_blank">Getting Started Guide</a></p>'.
3291
+
3292
+ //' <p><b>' . __( "It's important to check security settings.", 'wp-cerber' ) . '</b> &nbsp;<a href="http://wpcerber.com/" target="_blank">Read Cerber\'s blog</a> ' .
3293
+ //'&nbsp; <a href="http://wpcerber.com/subscribe-newsletter/" target="_blank">Subscribe to Cerber\'s newsletter</a></p>' .
3294
 
3295
  ' <p> </p><p><span class="dashicons dashicons-admin-settings"></span> <a href="' . cerber_admin_link( 'main' ) . '">' . __( 'Main Settings', 'wp-cerber' ) . '</a>' .
3296
  ' <span style="margin-left:20px;" class="dashicons dashicons-admin-network"></span> <a href="' . cerber_admin_link( 'acl' ) . '">' . __( 'Access Lists', 'wp-cerber' ) . '</a>' .
3450
  }
3451
  $sql[] = '
3452
  CREATE TABLE IF NOT EXISTS ' . CERBER_LAB_NET_TABLE . ' (
3453
+ ip varchar(39) CHARACTER SET ascii NOT NULL DEFAULT "" COMMENT "IP address",
3454
+ ip_long_begin BIGINT UNSIGNED NOT NULL DEFAULT "0",
3455
+ ip_long_end BIGINT UNSIGNED NOT NULL DEFAULT "0",
3456
+ country CHAR(3) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "" COMMENT "Country code",
3457
+ expires INT(11) UNSIGNED NOT NULL DEFAULT "0",
3458
+ PRIMARY KEY (ip),
3459
+ UNIQUE KEY begin_end (ip_long_begin, ip_long_end)
3460
  ) DEFAULT CHARSET=utf8 COMMENT="Cerber lab network cache";
3461
  ';
3462
  }
3463
 
3464
+ if (!cerber_is_table(CERBER_GEO_TABLE)){
3465
+ $sql[] = '
3466
+ CREATE TABLE IF NOT EXISTS ' . CERBER_GEO_TABLE . ' (
3467
+ country CHAR(3) NOT NULL DEFAULT "" COMMENT "Country code",
3468
+ locale CHAR(10) NOT NULL DEFAULT "" COMMENT "Locale i18n",
3469
+ country_name VARCHAR(250) NOT NULL DEFAULT "" COMMENT "Country name",
3470
+ PRIMARY KEY (country, locale)
3471
+ ) DEFAULT CHARSET=utf8;
3472
+ ';
3473
+ }
3474
+
3475
  foreach ( $sql as $query ) {
3476
  if ( ! $wpdb->query( $query ) && $wpdb->last_error ) {
3477
  $db_errors[] = array( $wpdb->last_error, $wpdb->last_query );
3520
  }
3521
 
3522
  // @since 4.9
3523
+ if ( $force || ! cerber_is_column( CERBER_LOG_TABLE, 'session_id' ) ) {
3524
+ $sql[] = 'ALTER TABLE ' . CERBER_LOG_TABLE . '
3525
  ADD session_id CHAR(32) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "",
3526
  ADD country CHAR(3) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "" COMMENT "Country code",
3527
  ADD details VARCHAR(250) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT "" COMMENT "Details about HTTP request";