Version Description
Download this release
Release Info
Developer | bmarshall511 |
Plugin | WordPress Zero Spam |
Version | 5.0.0 |
Comparing to | |
See all releases |
Code changes from version 4.10.2 to 5.0.0
- assets/css/Chart.min.css +0 -1
- assets/css/admin-blocked-ips.css +0 -56
- assets/css/admin-dashboard.css +0 -144
- assets/css/admin-tables.css +0 -62
- assets/css/admin.css +133 -62
- assets/css/debug.css +0 -25
- assets/css/jquery-jvectormap-2.0.5.css +0 -135
- assets/img/icon-yellow.svg +0 -25
- assets/img/icon.svg +0 -23
- assets/js/Chart.bundle.min.js +0 -7
- assets/js/admin-blocked-ips.js +0 -15
- assets/js/admin-tables.js +0 -22
- assets/js/admin.js +59 -0
- assets/js/jquery-jvectormap-2.0.5.min.js +0 -1
- assets/js/jquery-jvectormap-world-mill.js +0 -1
- assets/js/wpzerospam.js +0 -58
- classes/class-wpzerospam-blacklisted-table.php +0 -305
- classes/class-wpzerospam-blocked-ip-table.php +0 -260
- classes/class-wpzerospam-comments.php +0 -16
- classes/class-wpzerospam-log-table.php +0 -371
- classes/class-wpzerospam-security.php +0 -36
- classes/class-wpzerospam.php +0 -977
- composer.json +0 -36
- core/admin/class-admin.php +148 -0
- core/admin/class-dashboard.php +233 -0
- core/admin/class-settings.php +264 -0
- core/admin/tables/class-blockedtable.php +307 -0
- core/admin/tables/class-logtable.php +327 -0
- core/class-access.php +181 -0
- core/class-settings.php +191 -0
- core/class-user.php +61 -0
- core/class-utilities.php +111 -0
- inc/admin.php +0 -849
- inc/helpers.php +0 -600
- inc/install.php +0 -86
- inc/locations.php +0 -2152
- inc/scripts.php +0 -160
- inc/uninstall.php +0 -50
- inc/updates.php +0 -48
- inc/utilities.php +0 -309
- includes/class-autoloader.php +121 -0
- includes/class-db.php +280 -0
- includes/class-plugin.php +181 -0
- includes/templates/admin-block-ip.php +55 -0
- includes/templates/admin-callout.php +73 -0
- includes/templates/admin-modal-details.php +111 -0
- integrations/buddypress/buddypress.php +0 -48
- integrations/buddypress/js/buddypress.js +0 -4
- integrations/comments/comments.php +0 -379
- integrations/comments/js/comments.js +0 -4
- integrations/contact-form-7/contact-form-7.php +0 -198
- integrations/contact-form-7/js/cf7.js +0 -4
- integrations/fluentform/fluentform.php +0 -58
- integrations/fluentform/js/fluentform.js +0 -4
- integrations/formidable/formidable.php +0 -74
- integrations/registrations/js/registrations.js +0 -4
- integrations/registrations/registrations.php +0 -200
- integrations/wpforms/js/wpforms.js +0 -4
- integrations/wpforms/wpforms.php +0 -54
- languages/zero-spam-fr_FR.pot +0 -685
- languages/zero-spam-it_IT.pot +0 -875
- modules/class-botscout.php +139 -0
- modules/class-google.php +115 -0
- modules/class-ipstack.php +194 -0
- modules/class-stopforumspam.php +344 -0
- modules/class-zerospam.php +40 -0
- modules/comments/class-comments.php +163 -0
- modules/contactform7/class-contactform7.php +152 -0
- modules/registration/class-registration.php +159 -0
- readme.txt +20 -310
- templates/callout.php +0 -51
- templates/countries-pie-chart.php +0 -70
- templates/ip-list.php +0 -74
- templates/map.php +0 -114
- templates/regions-pie-chart.php +0 -85
- templates/spam-line-chart.php +0 -61
- uninstall.php +44 -0
- wordpress-zero-spam.php +50 -109
assets/css/Chart.min.css
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
@keyframes chartjs-render-animation{from{opacity:.99}to{opacity:1}}.chartjs-render-monitor{animation:chartjs-render-animation 1ms}.chartjs-size-monitor,.chartjs-size-monitor-expand,.chartjs-size-monitor-shrink{position:absolute;direction:ltr;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1}.chartjs-size-monitor-expand>div{position:absolute;width:1000000px;height:1000000px;left:0;top:0}.chartjs-size-monitor-shrink>div{position:absolute;width:200%;height:200%;left:0;top:0}
|
|
assets/css/admin-blocked-ips.css
DELETED
@@ -1,56 +0,0 @@
|
|
1 |
-
.wpzerospam-add-ip-container {
|
2 |
-
align-items: center;
|
3 |
-
display: flex;
|
4 |
-
flex-wrap: wrap;
|
5 |
-
}
|
6 |
-
|
7 |
-
.wpzerospam-add-ip-container-highlight {
|
8 |
-
animation: wpzerospam-highlight 2s;
|
9 |
-
animation-fill-mode: forwards;
|
10 |
-
}
|
11 |
-
|
12 |
-
@keyframes wpzerospam-highlight {
|
13 |
-
0% {
|
14 |
-
background: #fff;
|
15 |
-
}
|
16 |
-
|
17 |
-
100% {
|
18 |
-
background: #FFF4DC;
|
19 |
-
}
|
20 |
-
}
|
21 |
-
|
22 |
-
|
23 |
-
.wpzerospam-add-ip-container h2,
|
24 |
-
.wpzerospam-add-ip-field,
|
25 |
-
.wpzerospam-add-ip-submit {
|
26 |
-
margin-left: 10px;
|
27 |
-
margin-right: 10px;
|
28 |
-
}
|
29 |
-
|
30 |
-
.wpzerospam-add-ip-container h2 {
|
31 |
-
margin-top: 0;
|
32 |
-
width: calc(100% - 20px);
|
33 |
-
}
|
34 |
-
|
35 |
-
.wpzerospam-add-ip-container label {
|
36 |
-
display: block;
|
37 |
-
font-weight: bold;
|
38 |
-
}
|
39 |
-
|
40 |
-
.wpzerospam-add-ip-field {
|
41 |
-
width: calc(100% / 5 - 20px);
|
42 |
-
}
|
43 |
-
|
44 |
-
.wpzerospam-add-ip-field input,
|
45 |
-
.wpzerospam-add-ip-field select {
|
46 |
-
width: 100%;
|
47 |
-
}
|
48 |
-
|
49 |
-
#wpzerospam-add-ip-field-reason {
|
50 |
-
flex-grow: 1;
|
51 |
-
}
|
52 |
-
|
53 |
-
#wpzerospam-add-ip-field-submit {
|
54 |
-
margin-top: 10px;
|
55 |
-
width: auto;
|
56 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/css/admin-dashboard.css
DELETED
@@ -1,144 +0,0 @@
|
|
1 |
-
.wpzerospam-blocked-ip-option {
|
2 |
-
margin-bottom: 0.3rem;
|
3 |
-
}
|
4 |
-
|
5 |
-
.wpzerospam-setting-header,
|
6 |
-
.wpzerospam-blocked-ip-option {
|
7 |
-
display: flex;
|
8 |
-
}
|
9 |
-
|
10 |
-
.wpzerospam-setting-header div,
|
11 |
-
.wpzerospam-input {
|
12 |
-
width: calc(100% / 3);
|
13 |
-
}
|
14 |
-
|
15 |
-
.wpzerospam-setting-header div {
|
16 |
-
margin-bottom: 0.3rem;
|
17 |
-
}
|
18 |
-
|
19 |
-
.wpzerospam-setting-header label {
|
20 |
-
font-weight: bold;
|
21 |
-
}
|
22 |
-
|
23 |
-
.wpzerospam-setting-header small {
|
24 |
-
color: #666;
|
25 |
-
font-style: italic;
|
26 |
-
display: block;
|
27 |
-
}
|
28 |
-
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Info boxes
|
32 |
-
*/
|
33 |
-
.wpzerospam-boxes {
|
34 |
-
display: flex;
|
35 |
-
flex-wrap: wrap;
|
36 |
-
margin-left: -8px;
|
37 |
-
margin-right: -8px;
|
38 |
-
}
|
39 |
-
|
40 |
-
.wpzerospam-box {
|
41 |
-
background: #fff;
|
42 |
-
border: 1px solid #ccd0d4;
|
43 |
-
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
44 |
-
margin-bottom: 16px;
|
45 |
-
margin-left: 8px;
|
46 |
-
margin-right: 8px;
|
47 |
-
overflow: hidden;
|
48 |
-
width: calc(100% - 18px);
|
49 |
-
}
|
50 |
-
|
51 |
-
.wpzerospam-box h3 {
|
52 |
-
border-bottom: 1px solid #ccd0d4;
|
53 |
-
font-size: 14px;
|
54 |
-
line-height: 1.4;
|
55 |
-
margin: 0;
|
56 |
-
}
|
57 |
-
|
58 |
-
.wpzerospam-box .inside,
|
59 |
-
.wpzerospam-box h3 {
|
60 |
-
padding: 12px;
|
61 |
-
}
|
62 |
-
|
63 |
-
@media (min-width: 1024px) {
|
64 |
-
.wpzerospam-box {
|
65 |
-
width: calc(100% / 2 - 18px);
|
66 |
-
}
|
67 |
-
|
68 |
-
.wpzerospam-box-map {
|
69 |
-
width: calc(100% - 18px);
|
70 |
-
}
|
71 |
-
}
|
72 |
-
|
73 |
-
@media (min-width: 1200px) {
|
74 |
-
.wpzerospam-box {
|
75 |
-
width: calc(100% / 3 - 18px);
|
76 |
-
}
|
77 |
-
|
78 |
-
.wpzerospam-box-line-chart {
|
79 |
-
width: calc(100% - 18px);
|
80 |
-
}
|
81 |
-
|
82 |
-
.wpzerospam-box-map {
|
83 |
-
width: calc((100% / 3) * 2 - 18px);
|
84 |
-
}
|
85 |
-
|
86 |
-
.wpzerospam-box-countries-pie {
|
87 |
-
width: calc(100% / 2 - 18px);
|
88 |
-
}
|
89 |
-
}
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
/**
|
94 |
-
* List of IPs
|
95 |
-
*/
|
96 |
-
.wpzerospam-list {
|
97 |
-
margin: 0;
|
98 |
-
padding: 0;
|
99 |
-
list-style: none;
|
100 |
-
}
|
101 |
-
|
102 |
-
.wpzerospam-list-item {
|
103 |
-
display: flex;
|
104 |
-
}
|
105 |
-
|
106 |
-
.wpzerospam-list-cell-icon,
|
107 |
-
.wpzerospam-list-cell-ip,
|
108 |
-
.wpzerospam-list-cell-count,
|
109 |
-
.wpzerospam-list-cell-action {
|
110 |
-
flex-grow: 0;
|
111 |
-
flex-shrink: 0;
|
112 |
-
}
|
113 |
-
|
114 |
-
.wpzerospam-list-cell-icon {
|
115 |
-
margin-right: 5px;
|
116 |
-
width: 16px;
|
117 |
-
}
|
118 |
-
|
119 |
-
.wpzerospam-list-cell-ip {
|
120 |
-
width: 120px;
|
121 |
-
}
|
122 |
-
|
123 |
-
.wpzerospam-list-cell-country {
|
124 |
-
flex-grow: 1;
|
125 |
-
font-size: 0.8rem;
|
126 |
-
}
|
127 |
-
|
128 |
-
.wpzerospam-list-cell-count,
|
129 |
-
.wpzerospam-list-cell-action {
|
130 |
-
text-align: right;
|
131 |
-
}
|
132 |
-
|
133 |
-
.wpzerospam-list-cell-count {
|
134 |
-
width: 50px;
|
135 |
-
}
|
136 |
-
|
137 |
-
.wpzerospam-list-cell-action {
|
138 |
-
margin-left: 5px;
|
139 |
-
width: 80px;
|
140 |
-
}
|
141 |
-
|
142 |
-
.wpzerospam-list-cell-na {
|
143 |
-
color: #ccd0d4;
|
144 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/css/admin-tables.css
DELETED
@@ -1,62 +0,0 @@
|
|
1 |
-
.wpzerospam-details-modal {
|
2 |
-
background: rgba(0, 0, 0, 0.8);
|
3 |
-
cursor: pointer;
|
4 |
-
display: none;
|
5 |
-
height: 100%;
|
6 |
-
left: 0;
|
7 |
-
position: fixed;
|
8 |
-
top: 0;
|
9 |
-
width: 100%;
|
10 |
-
z-index: 9;
|
11 |
-
}
|
12 |
-
|
13 |
-
.wpzerospam-details-modal.is-active {
|
14 |
-
display: block;
|
15 |
-
}
|
16 |
-
|
17 |
-
.wpzerospam-details-modal-inner {
|
18 |
-
background-color: #fff;
|
19 |
-
border: 1px solid #ccd0d4;
|
20 |
-
border-radius: 5px;
|
21 |
-
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
22 |
-
cursor: default;
|
23 |
-
display: flex;
|
24 |
-
flex-wrap: wrap;
|
25 |
-
left: 50%;
|
26 |
-
overflow: auto;
|
27 |
-
max-height: 500px;
|
28 |
-
max-width: 800px;
|
29 |
-
padding: 30px;
|
30 |
-
position: fixed;
|
31 |
-
top: 50%;
|
32 |
-
transform: translate(-50%, -50%);
|
33 |
-
z-index: 99;
|
34 |
-
width: 95%
|
35 |
-
}
|
36 |
-
|
37 |
-
.wpzerospam-details-item {
|
38 |
-
display: flex;
|
39 |
-
padding: 5px;
|
40 |
-
width: 100%;
|
41 |
-
}
|
42 |
-
|
43 |
-
.wpzerospam-details-item-unknown {
|
44 |
-
order: 9999999;
|
45 |
-
}
|
46 |
-
|
47 |
-
.wpzerospam-details-label {
|
48 |
-
flex-shrink: 0;
|
49 |
-
font-weight: bold;
|
50 |
-
width: 150px;
|
51 |
-
}
|
52 |
-
|
53 |
-
.wpzerospam-details-data {
|
54 |
-
flex-grow: 1;
|
55 |
-
}
|
56 |
-
|
57 |
-
.wpzerospam-small {
|
58 |
-
color: #666;
|
59 |
-
display: inline-block;
|
60 |
-
font-size: 11px;
|
61 |
-
line-height: 1;
|
62 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/css/admin.css
CHANGED
@@ -1,89 +1,160 @@
|
|
1 |
-
.
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
display: flex;
|
7 |
-
flex-wrap: wrap;
|
8 |
-
margin-bottom: 10px;
|
9 |
-
padding: 20px;
|
10 |
}
|
11 |
|
12 |
-
.
|
13 |
-
|
14 |
-
|
15 |
}
|
16 |
|
17 |
-
.
|
18 |
-
|
19 |
-
|
20 |
}
|
21 |
|
22 |
-
.
|
23 |
-
|
24 |
-
|
25 |
-
width: 100%;
|
26 |
}
|
27 |
|
28 |
-
.
|
29 |
-
|
30 |
-
margin-bottom: 4px;
|
31 |
-
margin-left: 2px;
|
32 |
-
margin-right: 2px;
|
33 |
-
text-align: center;
|
34 |
-
width: calc(100% - 4px);
|
35 |
}
|
36 |
|
37 |
-
.
|
38 |
-
|
39 |
}
|
40 |
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
-
|
54 |
-
|
55 |
-
}
|
56 |
}
|
57 |
|
58 |
-
.
|
59 |
-
|
|
|
60 |
}
|
61 |
|
62 |
-
.
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
content: '';
|
68 |
-
display: inline-block;
|
69 |
-
height: 16px;
|
70 |
-
margin-right: 3px;
|
71 |
-
vertical-align: top;
|
72 |
-
width: 16px;
|
73 |
}
|
74 |
|
75 |
-
.
|
76 |
-
|
|
|
|
|
|
|
77 |
}
|
78 |
|
79 |
-
.
|
80 |
-
|
|
|
|
|
81 |
}
|
82 |
|
83 |
-
.
|
84 |
-
|
85 |
}
|
86 |
|
87 |
-
|
88 |
-
|
|
|
|
|
89 |
}
|
1 |
+
.zerospam-callout,
|
2 |
+
.zerospam-modal {
|
3 |
+
background: #fff;
|
4 |
+
border: 1px solid #ccd0d4;
|
5 |
+
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
|
|
|
|
|
|
|
|
6 |
}
|
7 |
|
8 |
+
.zerospam-callout-col,
|
9 |
+
.zerospam-modal {
|
10 |
+
padding: 30px;
|
11 |
}
|
12 |
|
13 |
+
.zerospam-callout {
|
14 |
+
display: flex;
|
15 |
+
margin: 20px 0;
|
16 |
}
|
17 |
|
18 |
+
.zerospam-callout h2,
|
19 |
+
.zerospam-callout h3 {
|
20 |
+
margin-top: 0;
|
|
|
21 |
}
|
22 |
|
23 |
+
.zerospam-callout p:last-child {
|
24 |
+
margin-bottom: 0;
|
|
|
|
|
|
|
|
|
|
|
25 |
}
|
26 |
|
27 |
+
.zerospam-callout-col {
|
28 |
+
width: 100%;
|
29 |
}
|
30 |
|
31 |
+
.zerospam-modal {
|
32 |
+
left: 50%;
|
33 |
+
max-width: 600px;
|
34 |
+
opacity: 0;
|
35 |
+
position: fixed;
|
36 |
+
max-height: calc(90vh - 60px);
|
37 |
+
overflow: auto;
|
38 |
+
top: 50%;
|
39 |
+
transform: translate(-50%, -50%);
|
40 |
+
transition: all 0.5s;
|
41 |
+
visibility: hidden;
|
42 |
+
width: 100%;
|
43 |
+
z-index: 1;
|
44 |
+
}
|
45 |
+
|
46 |
+
.zerospam-modal.is-active {
|
47 |
+
opacity: 1;
|
48 |
+
visibility: visible;
|
49 |
+
}
|
50 |
+
|
51 |
+
.zerospam-close-modal {
|
52 |
+
background: transparent;
|
53 |
+
border: 0;
|
54 |
+
cursor: pointer;
|
55 |
+
display: block;
|
56 |
+
height: 16px;
|
57 |
+
padding: 0;
|
58 |
+
position: absolute;
|
59 |
+
right: 15px;
|
60 |
+
top: 15px;
|
61 |
+
width: 15px;
|
62 |
+
}
|
63 |
+
|
64 |
+
.zerospam-close-modal::before,
|
65 |
+
.zerospam-close-modal::after {
|
66 |
+
background: #23282d;
|
67 |
+
content: '';
|
68 |
+
display: block;
|
69 |
+
height: 16px;
|
70 |
+
left: 6px;
|
71 |
+
position: absolute;
|
72 |
+
top: 0;
|
73 |
+
width: 3px;
|
74 |
+
}
|
75 |
+
|
76 |
+
.zerospam-close-modal::before {
|
77 |
+
transform: rotate(45deg);
|
78 |
+
}
|
79 |
+
|
80 |
+
.zerospam-close-modal::after {
|
81 |
+
transform: rotate(-45deg);
|
82 |
+
}
|
83 |
+
|
84 |
+
.zerospam-modal-details {
|
85 |
+
align-items: center;
|
86 |
+
display: flex;;
|
87 |
+
flex-wrap: wrap;
|
88 |
+
}
|
89 |
|
90 |
+
.zerospam-modal-title,
|
91 |
+
.zerospam-modal-subtitle {
|
92 |
+
width: 50%;
|
93 |
+
}
|
94 |
+
|
95 |
+
.zerospam-modal-headline,
|
96 |
+
.zerospam-modal-list {
|
97 |
+
width: 100%;
|
98 |
+
}
|
99 |
+
|
100 |
+
.zerospam-modal-list li {
|
101 |
+
display: flex;
|
102 |
+
justify-content: space-between;
|
103 |
+
padding: 5px;
|
104 |
+
}
|
105 |
+
|
106 |
+
.zerospam-modal-list li strong,
|
107 |
+
.zerospam-modal-list li span {
|
108 |
+
width: 50%;
|
109 |
+
}
|
110 |
+
|
111 |
+
.zerospam-modal-list li:nth-child(odd) {
|
112 |
+
background: #f9f9f9;
|
113 |
+
}
|
114 |
+
|
115 |
+
.zerospam-modal-subtitle {
|
116 |
+
text-align: right;
|
117 |
+
}
|
118 |
+
|
119 |
+
.zerospam-tab {
|
120 |
+
display: none;
|
121 |
+
}
|
122 |
|
123 |
+
.zerospam-tab.is-active {
|
124 |
+
display: block;
|
|
|
125 |
}
|
126 |
|
127 |
+
.zerospam-modal form {
|
128 |
+
display: flex;
|
129 |
+
flex-wrap: wrap;
|
130 |
}
|
131 |
|
132 |
+
.zerospam-modal form label {
|
133 |
+
display: flex;
|
134 |
+
flex-wrap: wrap;
|
135 |
+
margin-bottom: 10px;
|
136 |
+
width: 100%;
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
}
|
138 |
|
139 |
+
.zerospam-modal form label[for="blocked-ip"],
|
140 |
+
.zerospam-modal form label[for="blocked-type"],
|
141 |
+
.zerospam-modal form label[for="blocked-start-date"],
|
142 |
+
.zerospam-modal form label[for="blocked-end-date"] {
|
143 |
+
width: 50%;
|
144 |
}
|
145 |
|
146 |
+
.zerospam-modal input[type="text"],
|
147 |
+
.zerospam-modal input[type="datetime-local"],
|
148 |
+
.zerospam-modal select {
|
149 |
+
width: 100%;
|
150 |
}
|
151 |
|
152 |
+
.zerospam-modal input[type="submit"] {
|
153 |
+
margin-top: 16px;
|
154 |
}
|
155 |
|
156 |
+
@media (min-width: 768px) {
|
157 |
+
.zerospam-callout-col {
|
158 |
+
width: 50%;
|
159 |
+
}
|
160 |
}
|
assets/css/debug.css
DELETED
@@ -1,25 +0,0 @@
|
|
1 |
-
.wpzerospam-debug-overlay {
|
2 |
-
background: rgba(255, 255, 255, 0.9);
|
3 |
-
bottom: 0;
|
4 |
-
font-size: 13px;
|
5 |
-
left: 0;
|
6 |
-
max-height: 95%;
|
7 |
-
max-width: 800px;
|
8 |
-
overflow: auto;
|
9 |
-
padding: 2em;
|
10 |
-
position: fixed;
|
11 |
-
width: 100%;
|
12 |
-
}
|
13 |
-
|
14 |
-
.wpzerospam-debug-item {
|
15 |
-
display: flex;
|
16 |
-
}
|
17 |
-
|
18 |
-
.wpzerospam-debug-item-label {
|
19 |
-
flex-shrink: 0;
|
20 |
-
width: 16em;
|
21 |
-
}
|
22 |
-
|
23 |
-
.wpzerospam-debug-item-value {
|
24 |
-
flex-grow: 1;
|
25 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/css/jquery-jvectormap-2.0.5.css
DELETED
@@ -1,135 +0,0 @@
|
|
1 |
-
svg {
|
2 |
-
touch-action: none;
|
3 |
-
}
|
4 |
-
|
5 |
-
.jvectormap-container {
|
6 |
-
width: 100%;
|
7 |
-
height: 100%;
|
8 |
-
position: relative;
|
9 |
-
overflow: hidden;
|
10 |
-
touch-action: none;
|
11 |
-
}
|
12 |
-
|
13 |
-
.jvectormap-tip {
|
14 |
-
position: absolute;
|
15 |
-
display: none;
|
16 |
-
border: solid 1px #CDCDCD;
|
17 |
-
border-radius: 3px;
|
18 |
-
background: #292929;
|
19 |
-
color: white;
|
20 |
-
font-family: sans-serif, Verdana;
|
21 |
-
font-size: smaller;
|
22 |
-
padding: 3px;
|
23 |
-
}
|
24 |
-
|
25 |
-
.jvectormap-zoomin, .jvectormap-zoomout, .jvectormap-goback {
|
26 |
-
position: absolute;
|
27 |
-
left: 10px;
|
28 |
-
border-radius: 3px;
|
29 |
-
background: #292929;
|
30 |
-
padding: 3px;
|
31 |
-
color: white;
|
32 |
-
cursor: pointer;
|
33 |
-
line-height: 10px;
|
34 |
-
text-align: center;
|
35 |
-
box-sizing: content-box;
|
36 |
-
}
|
37 |
-
|
38 |
-
.jvectormap-zoomin, .jvectormap-zoomout {
|
39 |
-
width: 10px;
|
40 |
-
height: 10px;
|
41 |
-
}
|
42 |
-
|
43 |
-
.jvectormap-zoomin {
|
44 |
-
top: 10px;
|
45 |
-
}
|
46 |
-
|
47 |
-
.jvectormap-zoomout {
|
48 |
-
top: 30px;
|
49 |
-
}
|
50 |
-
|
51 |
-
.jvectormap-goback {
|
52 |
-
bottom: 10px;
|
53 |
-
z-index: 1000;
|
54 |
-
padding: 6px;
|
55 |
-
}
|
56 |
-
|
57 |
-
.jvectormap-spinner {
|
58 |
-
position: absolute;
|
59 |
-
left: 0;
|
60 |
-
top: 0;
|
61 |
-
right: 0;
|
62 |
-
bottom: 0;
|
63 |
-
background: center no-repeat url(data:image/gif;base64,R0lGODlhIAAgAPMAAP///wAAAMbGxoSEhLa2tpqamjY2NlZWVtjY2OTk5Ly8vB4eHgQEBAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ/V/nmOM82XiHRLYKhKP1oZmADdEAAAh+QQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY/CZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB+A4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6+Ho7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq+B6QDtuetcaBPnW6+O7wDHpIiK9SaVK5GgV543tzjgGcghAgAh+QQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK++G+w48edZPK+M6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE+G+cD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm+FNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk+aV+oJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0/VNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc+XiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq+E71SRQeyqUToLA7VxF0JDyIQh/MVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30/iI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE/jiuL04RGEBgwWhShRgQExHBAAh+QQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR+ipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq+E71SRQeyqUToLA7VxF0JDyIQh/MVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq+E71SRQeyqUToLA7VxF0JDyIQh/MVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY+Yip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd+MFCN6HAAIKgNggY0KtEBAAh+QQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1+vsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d+jYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg+ygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0+bm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h+Kr0SJ8MFihpNbx+4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX+BP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA==);
|
64 |
-
}
|
65 |
-
|
66 |
-
.jvectormap-legend-title {
|
67 |
-
font-weight: bold;
|
68 |
-
font-size: 14px;
|
69 |
-
text-align: center;
|
70 |
-
}
|
71 |
-
|
72 |
-
.jvectormap-legend-cnt {
|
73 |
-
position: absolute;
|
74 |
-
}
|
75 |
-
|
76 |
-
.jvectormap-legend-cnt-h {
|
77 |
-
bottom: 0;
|
78 |
-
right: 0;
|
79 |
-
}
|
80 |
-
|
81 |
-
.jvectormap-legend-cnt-v {
|
82 |
-
top: 0;
|
83 |
-
right: 0;
|
84 |
-
}
|
85 |
-
|
86 |
-
.jvectormap-legend {
|
87 |
-
background: black;
|
88 |
-
color: white;
|
89 |
-
border-radius: 3px;
|
90 |
-
}
|
91 |
-
|
92 |
-
.jvectormap-legend-cnt-h .jvectormap-legend {
|
93 |
-
float: left;
|
94 |
-
margin: 0 10px 10px 0;
|
95 |
-
padding: 3px 3px 1px 3px;
|
96 |
-
}
|
97 |
-
|
98 |
-
.jvectormap-legend-cnt-h .jvectormap-legend .jvectormap-legend-tick {
|
99 |
-
float: left;
|
100 |
-
}
|
101 |
-
|
102 |
-
.jvectormap-legend-cnt-v .jvectormap-legend {
|
103 |
-
margin: 10px 10px 0 0;
|
104 |
-
padding: 3px;
|
105 |
-
}
|
106 |
-
|
107 |
-
.jvectormap-legend-cnt-h .jvectormap-legend-tick {
|
108 |
-
width: 40px;
|
109 |
-
}
|
110 |
-
|
111 |
-
.jvectormap-legend-cnt-h .jvectormap-legend-tick-sample {
|
112 |
-
height: 15px;
|
113 |
-
}
|
114 |
-
|
115 |
-
.jvectormap-legend-cnt-v .jvectormap-legend-tick-sample {
|
116 |
-
height: 20px;
|
117 |
-
width: 20px;
|
118 |
-
display: inline-block;
|
119 |
-
vertical-align: middle;
|
120 |
-
}
|
121 |
-
|
122 |
-
.jvectormap-legend-tick-text {
|
123 |
-
font-size: 12px;
|
124 |
-
}
|
125 |
-
|
126 |
-
.jvectormap-legend-cnt-h .jvectormap-legend-tick-text {
|
127 |
-
text-align: center;
|
128 |
-
}
|
129 |
-
|
130 |
-
.jvectormap-legend-cnt-v .jvectormap-legend-tick-text {
|
131 |
-
display: inline-block;
|
132 |
-
vertical-align: middle;
|
133 |
-
line-height: 20px;
|
134 |
-
padding-left: 3px;
|
135 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/img/icon-yellow.svg
DELETED
@@ -1,25 +0,0 @@
|
|
1 |
-
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
-
<svg width="512px" height="478px" viewBox="0 0 512 478" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
3 |
-
<!-- Generator: Sketch 58 (84663) - https://sketch.com -->
|
4 |
-
<title>icon</title>
|
5 |
-
<desc>Created with Sketch.</desc>
|
6 |
-
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
7 |
-
<g id="icon" fill-rule="nonzero">
|
8 |
-
<g id="under-construction" transform="translate(256.000000, 239.000000) scale(-1, 1) translate(-256.000000, -239.000000) ">
|
9 |
-
<path d="M241,0 L96,0 C87.716,0 81,6.716 81,15 L81,127 C81,135.284 87.716,142 96,142 L241,142 C249.284,142 256,135.284 256,127 L256,15 C256,6.716 249.284,0 241,0 Z" id="Path" fill="#FCB214"></path>
|
10 |
-
<path d="M176,112 L15,112 C6.716,112 0,118.716 0,127 L0,239 C0,247.284 6.716,254 15,254 L176,254 C184.284,254 191,247.284 191,239 L191,127 C191,118.716 184.284,112 176,112 Z" id="Path" fill="#FFD06C"></path>
|
11 |
-
<path d="M351,127 L351,239 C351,247.28 344.28,254 336,254 L176,254 L176,112 L336,112 C344.28,112 351,118.72 351,127 Z" id="Path" fill="#D5A02C"></path>
|
12 |
-
<path d="M351,127 L351,239 C351,247.28 344.28,254 336,254 L256,254 L256,112 L336,112 C344.28,112 351,118.72 351,127 Z" id="Path" fill="#FFC64B"></path>
|
13 |
-
<path d="M512,127 L512,239 C512,247.28 505.28,254 497,254 L336,254 L336,112 L497,112 C505.28,112 512,118.72 512,127 Z" id="Path" fill="#895D00"></path>
|
14 |
-
<path d="M111,239 L111,351 C111,359.28 104.28,366 96,366 L15,366 C6.72,366 0,359.28 0,351 L0,239 L111,239 Z" id="Path" fill="#FFC64B"></path>
|
15 |
-
<path d="M271,239 L271,351 C271,359.28 264.28,366 256,366 L96,366 L96,239 L271,239 Z" id="Path" fill="#FCB214"></path>
|
16 |
-
<path d="M431,239 L431,351 C431,359.28 424.28,366 416,366 L256,366 L256,239 L431,239 Z" id="Path" fill="#C08200"></path>
|
17 |
-
<path d="M512,239 L512,351 C512,359.28 505.28,366 497,366 L416,366 L416,239 L512,239 Z" id="Path" fill="#FFC64B"></path>
|
18 |
-
<path d="M191,351 L191,463 C191,471.28 184.28,478 176,478 L15,478 C6.72,478 0,471.28 0,463 L0,351 L191,351 Z" id="Path" fill="#FFDA8C"></path>
|
19 |
-
<path d="M351,351 L351,463 C351,471.28 344.28,478 336,478 L176,478 L176,351 L351,351 Z" id="Path" fill="#D5A02C"></path>
|
20 |
-
<path d="M351,351 L351,463 C351,471.28 344.28,478 336,478 L256,478 L256,351 L351,351 Z" id="Path" fill="#FFC64B"></path>
|
21 |
-
<path d="M512,351 L512,463 C512,471.28 505.28,478 497,478 L336,478 L336,351 L512,351 Z" id="Path" fill="#895D00"></path>
|
22 |
-
</g>
|
23 |
-
</g>
|
24 |
-
</g>
|
25 |
-
</svg>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/img/icon.svg
DELETED
@@ -1,23 +0,0 @@
|
|
1 |
-
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
-
<svg width="512px" height="478px" viewBox="0 0 512 478" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
3 |
-
<!-- Generator: Sketch 58 (84663) - https://sketch.com -->
|
4 |
-
<title>under-construction</title>
|
5 |
-
<desc>Created with Sketch.</desc>
|
6 |
-
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
7 |
-
<g id="under-construction" transform="translate(256.000000, 239.000000) scale(-1, 1) translate(-256.000000, -239.000000) " fill-rule="nonzero">
|
8 |
-
<path d="M241,0 L96,0 C87.716,0 81,6.716 81,15 L81,127 C81,135.284 87.716,142 96,142 L241,142 C249.284,142 256,135.284 256,127 L256,15 C256,6.716 249.284,0 241,0 Z" id="Path" fill="#BE0000"></path>
|
9 |
-
<path d="M176,112 L15,112 C6.716,112 0,118.716 0,127 L0,239 C0,247.284 6.716,254 15,254 L176,254 C184.284,254 191,247.284 191,239 L191,127 C191,118.716 184.284,112 176,112 Z" id="Path" fill="#FF7038"></path>
|
10 |
-
<path d="M351,127 L351,239 C351,247.28 344.28,254 336,254 L176,254 L176,112 L336,112 C344.28,112 351,118.72 351,127 Z" id="Path" fill="#FF2929"></path>
|
11 |
-
<path d="M351,127 L351,239 C351,247.28 344.28,254 336,254 L256,254 L256,112 L336,112 C344.28,112 351,118.72 351,127 Z" id="Path" fill="#BE0000"></path>
|
12 |
-
<path d="M512,127 L512,239 C512,247.28 505.28,254 497,254 L336,254 L336,112 L497,112 C505.28,112 512,118.72 512,127 Z" id="Path" fill="#63000D"></path>
|
13 |
-
<path d="M111,239 L111,351 C111,359.28 104.28,366 96,366 L15,366 C6.72,366 0,359.28 0,351 L0,239 L111,239 Z" id="Path" fill="#FF2929"></path>
|
14 |
-
<path d="M271,239 L271,351 C271,359.28 264.28,366 256,366 L96,366 L96,239 L271,239 Z" id="Path" fill="#BE0000"></path>
|
15 |
-
<path d="M431,239 L431,351 C431,359.28 424.28,366 416,366 L256,366 L256,239 L431,239 Z" id="Path" fill="#840012"></path>
|
16 |
-
<path d="M512,239 L512,351 C512,359.28 505.28,366 497,366 L416,366 L416,239 L512,239 Z" id="Path" fill="#BE0000"></path>
|
17 |
-
<path d="M191,351 L191,463 C191,471.28 184.28,478 176,478 L15,478 C6.72,478 0,471.28 0,463 L0,351 L191,351 Z" id="Path" fill="#FFA17C"></path>
|
18 |
-
<path d="M351,351 L351,463 C351,471.28 344.28,478 336,478 L176,478 L176,351 L351,351 Z" id="Path" fill="#FF2929"></path>
|
19 |
-
<path d="M351,351 L351,463 C351,471.28 344.28,478 336,478 L256,478 L256,351 L351,351 Z" id="Path" fill="#BE0000"></path>
|
20 |
-
<path d="M512,351 L512,463 C512,471.28 505.28,478 497,478 L336,478 L336,351 L512,351 Z" id="Path" fill="#63000D"></path>
|
21 |
-
</g>
|
22 |
-
</g>
|
23 |
-
</svg>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/js/Chart.bundle.min.js
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
/*!
|
2 |
-
* Chart.js v2.9.3
|
3 |
-
* https://www.chartjs.org
|
4 |
-
* (c) 2019 Chart.js Contributors
|
5 |
-
* Released under the MIT License
|
6 |
-
*/
|
7 |
-
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Chart=e()}(this,(function(){"use strict";"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;function t(){throw new Error("Dynamic requires are not currently supported by rollup-plugin-commonjs")}function e(t,e){return t(e={exports:{}},e.exports),e.exports}var n={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},i=e((function(t){var e={};for(var i in n)n.hasOwnProperty(i)&&(e[n[i]]=i);var a=t.exports={rgb:{channels:3,labels:"rgb"},hsl:{channels:3,labels:"hsl"},hsv:{channels:3,labels:"hsv"},hwb:{channels:3,labels:"hwb"},cmyk:{channels:4,labels:"cmyk"},xyz:{channels:3,labels:"xyz"},lab:{channels:3,labels:"lab"},lch:{channels:3,labels:"lch"},hex:{channels:1,labels:["hex"]},keyword:{channels:1,labels:["keyword"]},ansi16:{channels:1,labels:["ansi16"]},ansi256:{channels:1,labels:["ansi256"]},hcg:{channels:3,labels:["h","c","g"]},apple:{channels:3,labels:["r16","g16","b16"]},gray:{channels:1,labels:["gray"]}};for(var r in a)if(a.hasOwnProperty(r)){if(!("channels"in a[r]))throw new Error("missing channels property: "+r);if(!("labels"in a[r]))throw new Error("missing channel labels property: "+r);if(a[r].labels.length!==a[r].channels)throw new Error("channel and label counts mismatch: "+r);var o=a[r].channels,s=a[r].labels;delete a[r].channels,delete a[r].labels,Object.defineProperty(a[r],"channels",{value:o}),Object.defineProperty(a[r],"labels",{value:s})}a.rgb.hsl=function(t){var e,n,i=t[0]/255,a=t[1]/255,r=t[2]/255,o=Math.min(i,a,r),s=Math.max(i,a,r),l=s-o;return s===o?e=0:i===s?e=(a-r)/l:a===s?e=2+(r-i)/l:r===s&&(e=4+(i-a)/l),(e=Math.min(60*e,360))<0&&(e+=360),n=(o+s)/2,[e,100*(s===o?0:n<=.5?l/(s+o):l/(2-s-o)),100*n]},a.rgb.hsv=function(t){var e,n,i,a,r,o=t[0]/255,s=t[1]/255,l=t[2]/255,u=Math.max(o,s,l),d=u-Math.min(o,s,l),h=function(t){return(u-t)/6/d+.5};return 0===d?a=r=0:(r=d/u,e=h(o),n=h(s),i=h(l),o===u?a=i-n:s===u?a=1/3+e-i:l===u&&(a=2/3+n-e),a<0?a+=1:a>1&&(a-=1)),[360*a,100*r,100*u]},a.rgb.hwb=function(t){var e=t[0],n=t[1],i=t[2];return[a.rgb.hsl(t)[0],100*(1/255*Math.min(e,Math.min(n,i))),100*(i=1-1/255*Math.max(e,Math.max(n,i)))]},a.rgb.cmyk=function(t){var e,n=t[0]/255,i=t[1]/255,a=t[2]/255;return[100*((1-n-(e=Math.min(1-n,1-i,1-a)))/(1-e)||0),100*((1-i-e)/(1-e)||0),100*((1-a-e)/(1-e)||0),100*e]},a.rgb.keyword=function(t){var i=e[t];if(i)return i;var a,r,o,s=1/0;for(var l in n)if(n.hasOwnProperty(l)){var u=n[l],d=(r=t,o=u,Math.pow(r[0]-o[0],2)+Math.pow(r[1]-o[1],2)+Math.pow(r[2]-o[2],2));d<s&&(s=d,a=l)}return a},a.keyword.rgb=function(t){return n[t]},a.rgb.xyz=function(t){var e=t[0]/255,n=t[1]/255,i=t[2]/255;return[100*(.4124*(e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)),100*(.2126*e+.7152*n+.0722*i),100*(.0193*e+.1192*n+.9505*i)]},a.rgb.lab=function(t){var e=a.rgb.xyz(t),n=e[0],i=e[1],r=e[2];return i/=100,r/=108.883,n=(n/=95.047)>.008856?Math.pow(n,1/3):7.787*n+16/116,[116*(i=i>.008856?Math.pow(i,1/3):7.787*i+16/116)-16,500*(n-i),200*(i-(r=r>.008856?Math.pow(r,1/3):7.787*r+16/116))]},a.hsl.rgb=function(t){var e,n,i,a,r,o=t[0]/360,s=t[1]/100,l=t[2]/100;if(0===s)return[r=255*l,r,r];e=2*l-(n=l<.5?l*(1+s):l+s-l*s),a=[0,0,0];for(var u=0;u<3;u++)(i=o+1/3*-(u-1))<0&&i++,i>1&&i--,r=6*i<1?e+6*(n-e)*i:2*i<1?n:3*i<2?e+(n-e)*(2/3-i)*6:e,a[u]=255*r;return a},a.hsl.hsv=function(t){var e=t[0],n=t[1]/100,i=t[2]/100,a=n,r=Math.max(i,.01);return n*=(i*=2)<=1?i:2-i,a*=r<=1?r:2-r,[e,100*(0===i?2*a/(r+a):2*n/(i+n)),100*((i+n)/2)]},a.hsv.rgb=function(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,r=e-Math.floor(e),o=255*i*(1-n),s=255*i*(1-n*r),l=255*i*(1-n*(1-r));switch(i*=255,a){case 0:return[i,l,o];case 1:return[s,i,o];case 2:return[o,i,l];case 3:return[o,s,i];case 4:return[l,o,i];case 5:return[i,o,s]}},a.hsv.hsl=function(t){var e,n,i,a=t[0],r=t[1]/100,o=t[2]/100,s=Math.max(o,.01);return i=(2-r)*o,n=r*s,[a,100*(n=(n/=(e=(2-r)*s)<=1?e:2-e)||0),100*(i/=2)]},a.hwb.rgb=function(t){var e,n,i,a,r,o,s,l=t[0]/360,u=t[1]/100,d=t[2]/100,h=u+d;switch(h>1&&(u/=h,d/=h),i=6*l-(e=Math.floor(6*l)),0!=(1&e)&&(i=1-i),a=u+i*((n=1-d)-u),e){default:case 6:case 0:r=n,o=a,s=u;break;case 1:r=a,o=n,s=u;break;case 2:r=u,o=n,s=a;break;case 3:r=u,o=a,s=n;break;case 4:r=a,o=u,s=n;break;case 5:r=n,o=u,s=a}return[255*r,255*o,255*s]},a.cmyk.rgb=function(t){var e=t[0]/100,n=t[1]/100,i=t[2]/100,a=t[3]/100;return[255*(1-Math.min(1,e*(1-a)+a)),255*(1-Math.min(1,n*(1-a)+a)),255*(1-Math.min(1,i*(1-a)+a))]},a.xyz.rgb=function(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100;return n=-.9689*a+1.8758*r+.0415*o,i=.0557*a+-.204*r+1.057*o,e=(e=3.2406*a+-1.5372*r+-.4986*o)>.0031308?1.055*Math.pow(e,1/2.4)-.055:12.92*e,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:12.92*n,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:12.92*i,[255*(e=Math.min(Math.max(0,e),1)),255*(n=Math.min(Math.max(0,n),1)),255*(i=Math.min(Math.max(0,i),1))]},a.xyz.lab=function(t){var e=t[0],n=t[1],i=t[2];return n/=100,i/=108.883,e=(e/=95.047)>.008856?Math.pow(e,1/3):7.787*e+16/116,[116*(n=n>.008856?Math.pow(n,1/3):7.787*n+16/116)-16,500*(e-n),200*(n-(i=i>.008856?Math.pow(i,1/3):7.787*i+16/116))]},a.lab.xyz=function(t){var e,n,i,a=t[0];e=t[1]/500+(n=(a+16)/116),i=n-t[2]/200;var r=Math.pow(n,3),o=Math.pow(e,3),s=Math.pow(i,3);return n=r>.008856?r:(n-16/116)/7.787,e=o>.008856?o:(e-16/116)/7.787,i=s>.008856?s:(i-16/116)/7.787,[e*=95.047,n*=100,i*=108.883]},a.lab.lch=function(t){var e,n=t[0],i=t[1],a=t[2];return(e=360*Math.atan2(a,i)/2/Math.PI)<0&&(e+=360),[n,Math.sqrt(i*i+a*a),e]},a.lch.lab=function(t){var e,n=t[0],i=t[1];return e=t[2]/360*2*Math.PI,[n,i*Math.cos(e),i*Math.sin(e)]},a.rgb.ansi16=function(t){var e=t[0],n=t[1],i=t[2],r=1 in arguments?arguments[1]:a.rgb.hsv(t)[2];if(0===(r=Math.round(r/50)))return 30;var o=30+(Math.round(i/255)<<2|Math.round(n/255)<<1|Math.round(e/255));return 2===r&&(o+=60),o},a.hsv.ansi16=function(t){return a.rgb.ansi16(a.hsv.rgb(t),t[2])},a.rgb.ansi256=function(t){var e=t[0],n=t[1],i=t[2];return e===n&&n===i?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(n/255*5)+Math.round(i/255*5)},a.ansi16.rgb=function(t){var e=t%10;if(0===e||7===e)return t>50&&(e+=3.5),[e=e/10.5*255,e,e];var n=.5*(1+~~(t>50));return[(1&e)*n*255,(e>>1&1)*n*255,(e>>2&1)*n*255]},a.ansi256.rgb=function(t){if(t>=232){var e=10*(t-232)+8;return[e,e,e]}var n;return t-=16,[Math.floor(t/36)/5*255,Math.floor((n=t%36)/6)/5*255,n%6/5*255]},a.rgb.hex=function(t){var e=(((255&Math.round(t[0]))<<16)+((255&Math.round(t[1]))<<8)+(255&Math.round(t[2]))).toString(16).toUpperCase();return"000000".substring(e.length)+e},a.hex.rgb=function(t){var e=t.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!e)return[0,0,0];var n=e[0];3===e[0].length&&(n=n.split("").map((function(t){return t+t})).join(""));var i=parseInt(n,16);return[i>>16&255,i>>8&255,255&i]},a.rgb.hcg=function(t){var e,n=t[0]/255,i=t[1]/255,a=t[2]/255,r=Math.max(Math.max(n,i),a),o=Math.min(Math.min(n,i),a),s=r-o;return e=s<=0?0:r===n?(i-a)/s%6:r===i?2+(a-n)/s:4+(n-i)/s+4,e/=6,[360*(e%=1),100*s,100*(s<1?o/(1-s):0)]},a.hsl.hcg=function(t){var e=t[1]/100,n=t[2]/100,i=1,a=0;return(i=n<.5?2*e*n:2*e*(1-n))<1&&(a=(n-.5*i)/(1-i)),[t[0],100*i,100*a]},a.hsv.hcg=function(t){var e=t[1]/100,n=t[2]/100,i=e*n,a=0;return i<1&&(a=(n-i)/(1-i)),[t[0],100*i,100*a]},a.hcg.rgb=function(t){var e=t[0]/360,n=t[1]/100,i=t[2]/100;if(0===n)return[255*i,255*i,255*i];var a,r=[0,0,0],o=e%1*6,s=o%1,l=1-s;switch(Math.floor(o)){case 0:r[0]=1,r[1]=s,r[2]=0;break;case 1:r[0]=l,r[1]=1,r[2]=0;break;case 2:r[0]=0,r[1]=1,r[2]=s;break;case 3:r[0]=0,r[1]=l,r[2]=1;break;case 4:r[0]=s,r[1]=0,r[2]=1;break;default:r[0]=1,r[1]=0,r[2]=l}return a=(1-n)*i,[255*(n*r[0]+a),255*(n*r[1]+a),255*(n*r[2]+a)]},a.hcg.hsv=function(t){var e=t[1]/100,n=e+t[2]/100*(1-e),i=0;return n>0&&(i=e/n),[t[0],100*i,100*n]},a.hcg.hsl=function(t){var e=t[1]/100,n=t[2]/100*(1-e)+.5*e,i=0;return n>0&&n<.5?i=e/(2*n):n>=.5&&n<1&&(i=e/(2*(1-n))),[t[0],100*i,100*n]},a.hcg.hwb=function(t){var e=t[1]/100,n=e+t[2]/100*(1-e);return[t[0],100*(n-e),100*(1-n)]},a.hwb.hcg=function(t){var e=t[1]/100,n=1-t[2]/100,i=n-e,a=0;return i<1&&(a=(n-i)/(1-i)),[t[0],100*i,100*a]},a.apple.rgb=function(t){return[t[0]/65535*255,t[1]/65535*255,t[2]/65535*255]},a.rgb.apple=function(t){return[t[0]/255*65535,t[1]/255*65535,t[2]/255*65535]},a.gray.rgb=function(t){return[t[0]/100*255,t[0]/100*255,t[0]/100*255]},a.gray.hsl=a.gray.hsv=function(t){return[0,0,t[0]]},a.gray.hwb=function(t){return[0,100,t[0]]},a.gray.cmyk=function(t){return[0,0,0,t[0]]},a.gray.lab=function(t){return[t[0],0,0]},a.gray.hex=function(t){var e=255&Math.round(t[0]/100*255),n=((e<<16)+(e<<8)+e).toString(16).toUpperCase();return"000000".substring(n.length)+n},a.rgb.gray=function(t){return[(t[0]+t[1]+t[2])/3/255*100]}}));i.rgb,i.hsl,i.hsv,i.hwb,i.cmyk,i.xyz,i.lab,i.lch,i.hex,i.keyword,i.ansi16,i.ansi256,i.hcg,i.apple,i.gray;function a(t){var e=function(){for(var t={},e=Object.keys(i),n=e.length,a=0;a<n;a++)t[e[a]]={distance:-1,parent:null};return t}(),n=[t];for(e[t].distance=0;n.length;)for(var a=n.pop(),r=Object.keys(i[a]),o=r.length,s=0;s<o;s++){var l=r[s],u=e[l];-1===u.distance&&(u.distance=e[a].distance+1,u.parent=a,n.unshift(l))}return e}function r(t,e){return function(n){return e(t(n))}}function o(t,e){for(var n=[e[t].parent,t],a=i[e[t].parent][t],o=e[t].parent;e[o].parent;)n.unshift(e[o].parent),a=r(i[e[o].parent][o],a),o=e[o].parent;return a.conversion=n,a}var s={};Object.keys(i).forEach((function(t){s[t]={},Object.defineProperty(s[t],"channels",{value:i[t].channels}),Object.defineProperty(s[t],"labels",{value:i[t].labels});var e=function(t){for(var e=a(t),n={},i=Object.keys(e),r=i.length,s=0;s<r;s++){var l=i[s];null!==e[l].parent&&(n[l]=o(l,e))}return n}(t);Object.keys(e).forEach((function(n){var i=e[n];s[t][n]=function(t){var e=function(e){if(null==e)return e;arguments.length>1&&(e=Array.prototype.slice.call(arguments));var n=t(e);if("object"==typeof n)for(var i=n.length,a=0;a<i;a++)n[a]=Math.round(n[a]);return n};return"conversion"in t&&(e.conversion=t.conversion),e}(i),s[t][n].raw=function(t){var e=function(e){return null==e?e:(arguments.length>1&&(e=Array.prototype.slice.call(arguments)),t(e))};return"conversion"in t&&(e.conversion=t.conversion),e}(i)}))}));var l=s,u={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},d={getRgba:h,getHsla:c,getRgb:function(t){var e=h(t);return e&&e.slice(0,3)},getHsl:function(t){var e=c(t);return e&&e.slice(0,3)},getHwb:f,getAlpha:function(t){var e=h(t);if(e)return e[3];if(e=c(t))return e[3];if(e=f(t))return e[3]},hexString:function(t,e){e=void 0!==e&&3===t.length?e:t[3];return"#"+b(t[0])+b(t[1])+b(t[2])+(e>=0&&e<1?b(Math.round(255*e)):"")},rgbString:function(t,e){if(e<1||t[3]&&t[3]<1)return g(t,e);return"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:g,percentString:function(t,e){if(e<1||t[3]&&t[3]<1)return m(t,e);var n=Math.round(t[0]/255*100),i=Math.round(t[1]/255*100),a=Math.round(t[2]/255*100);return"rgb("+n+"%, "+i+"%, "+a+"%)"},percentaString:m,hslString:function(t,e){if(e<1||t[3]&&t[3]<1)return p(t,e);return"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:p,hwbString:function(t,e){void 0===e&&(e=void 0!==t[3]?t[3]:1);return"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return y[t.slice(0,3)]}};function h(t){if(t){var e=[0,0,0],n=1,i=t.match(/^#([a-fA-F0-9]{3,4})$/i),a="";if(i){a=(i=i[1])[3];for(var r=0;r<e.length;r++)e[r]=parseInt(i[r]+i[r],16);a&&(n=Math.round(parseInt(a+a,16)/255*100)/100)}else if(i=t.match(/^#([a-fA-F0-9]{6}([a-fA-F0-9]{2})?)$/i)){a=i[2],i=i[1];for(r=0;r<e.length;r++)e[r]=parseInt(i.slice(2*r,2*r+2),16);a&&(n=Math.round(parseInt(a,16)/255*100)/100)}else if(i=t.match(/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i)){for(r=0;r<e.length;r++)e[r]=parseInt(i[r+1]);n=parseFloat(i[4])}else if(i=t.match(/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i)){for(r=0;r<e.length;r++)e[r]=Math.round(2.55*parseFloat(i[r+1]));n=parseFloat(i[4])}else if(i=t.match(/(\w+)/)){if("transparent"==i[1])return[0,0,0,0];if(!(e=u[i[1]]))return}for(r=0;r<e.length;r++)e[r]=v(e[r],0,255);return n=n||0==n?v(n,0,1):1,e[3]=n,e}}function c(t){if(t){var e=t.match(/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var n=parseFloat(e[4]);return[v(parseInt(e[1]),0,360),v(parseFloat(e[2]),0,100),v(parseFloat(e[3]),0,100),v(isNaN(n)?1:n,0,1)]}}}function f(t){if(t){var e=t.match(/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var n=parseFloat(e[4]);return[v(parseInt(e[1]),0,360),v(parseFloat(e[2]),0,100),v(parseFloat(e[3]),0,100),v(isNaN(n)?1:n,0,1)]}}}function g(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function m(t,e){return"rgba("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%, "+(e||t[3]||1)+")"}function p(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function v(t,e,n){return Math.min(Math.max(e,t),n)}function b(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var y={};for(var x in u)y[u[x]]=x;var _=function(t){return t instanceof _?t:this instanceof _?(this.valid=!1,this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1},void("string"==typeof t?(e=d.getRgba(t))?this.setValues("rgb",e):(e=d.getHsla(t))?this.setValues("hsl",e):(e=d.getHwb(t))&&this.setValues("hwb",e):"object"==typeof t&&(void 0!==(e=t).r||void 0!==e.red?this.setValues("rgb",e):void 0!==e.l||void 0!==e.lightness?this.setValues("hsl",e):void 0!==e.v||void 0!==e.value?this.setValues("hsv",e):void 0!==e.w||void 0!==e.whiteness?this.setValues("hwb",e):void 0===e.c&&void 0===e.cyan||this.setValues("cmyk",e)))):new _(t);var e};_.prototype={isValid:function(){return this.valid},rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t=(t%=360)<0?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return d.hexString(this.values.rgb)},rgbString:function(){return d.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return d.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return d.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return d.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return d.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return d.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return d.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],n=0;n<t.length;n++){var i=t[n]/255;e[n]=i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),n=t.luminosity();return e>n?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=t,i=void 0===e?.5:e,a=2*i-1,r=this.alpha()-n.alpha(),o=((a*r==-1?a:(a+r)/(1+a*r))+1)/2,s=1-o;return this.rgb(o*this.red()+s*n.red(),o*this.green()+s*n.green(),o*this.blue()+s*n.blue()).alpha(this.alpha()*i+n.alpha()*(1-i))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new _,i=this.values,a=n.values;for(var r in i)i.hasOwnProperty(r)&&(t=i[r],"[object Array]"===(e={}.toString.call(t))?a[r]=t.slice(0):"[object Number]"===e?a[r]=t:console.error("unexpected color value:",t));return n}},_.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},_.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},_.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i<t.length;i++)n[t.charAt(i)]=e[t][i];return 1!==e.alpha&&(n.a=e.alpha),n},_.prototype.setValues=function(t,e){var n,i,a=this.values,r=this.spaces,o=this.maxes,s=1;if(this.valid=!0,"alpha"===t)s=e;else if(e.length)a[t]=e.slice(0,t.length),s=e[t.length];else if(void 0!==e[t.charAt(0)]){for(n=0;n<t.length;n++)a[t][n]=e[t.charAt(n)];s=e.a}else if(void 0!==e[r[t][0]]){var u=r[t];for(n=0;n<t.length;n++)a[t][n]=e[u[n]];s=e.alpha}if(a.alpha=Math.max(0,Math.min(1,void 0===s?a.alpha:s)),"alpha"===t)return!1;for(n=0;n<t.length;n++)i=Math.max(0,Math.min(o[t][n],a[t][n])),a[t][n]=Math.round(i);for(var d in r)d!==t&&(a[d]=l[t][d](a[t]));return!0},_.prototype.setSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n),this)},_.prototype.setChannel=function(t,e,n){var i=this.values[t];return void 0===n?i[e]:n===i[e]?this:(i[e]=n,this.setValues(t,i),this)},"undefined"!=typeof window&&(window.Color=_);var w,k=_,M={noop:function(){},uid:(w=0,function(){return w++}),isNullOrUndef:function(t){return null==t},isArray:function(t){if(Array.isArray&&Array.isArray(t))return!0;var e=Object.prototype.toString.call(t);return"[object"===e.substr(0,7)&&"Array]"===e.substr(-6)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},isFinite:function(t){return("number"==typeof t||t instanceof Number)&&isFinite(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return M.valueOrDefault(M.isArray(t)?t[e]:t,n)},callback:function(t,e,n){if(t&&"function"==typeof t.call)return t.apply(n,e)},each:function(t,e,n,i){var a,r,o;if(M.isArray(t))if(r=t.length,i)for(a=r-1;a>=0;a--)e.call(n,t[a],a);else for(a=0;a<r;a++)e.call(n,t[a],a);else if(M.isObject(t))for(r=(o=Object.keys(t)).length,a=0;a<r;a++)e.call(n,t[o[a]],o[a])},arrayEquals:function(t,e){var n,i,a,r;if(!t||!e||t.length!==e.length)return!1;for(n=0,i=t.length;n<i;++n)if(a=t[n],r=e[n],a instanceof Array&&r instanceof Array){if(!M.arrayEquals(a,r))return!1}else if(a!==r)return!1;return!0},clone:function(t){if(M.isArray(t))return t.map(M.clone);if(M.isObject(t)){for(var e={},n=Object.keys(t),i=n.length,a=0;a<i;++a)e[n[a]]=M.clone(t[n[a]]);return e}return t},_merger:function(t,e,n,i){var a=e[t],r=n[t];M.isObject(a)&&M.isObject(r)?M.merge(a,r,i):e[t]=M.clone(r)},_mergerIf:function(t,e,n){var i=e[t],a=n[t];M.isObject(i)&&M.isObject(a)?M.mergeIf(i,a):e.hasOwnProperty(t)||(e[t]=M.clone(a))},merge:function(t,e,n){var i,a,r,o,s,l=M.isArray(e)?e:[e],u=l.length;if(!M.isObject(t))return t;for(i=(n=n||{}).merger||M._merger,a=0;a<u;++a)if(e=l[a],M.isObject(e))for(s=0,o=(r=Object.keys(e)).length;s<o;++s)i(r[s],t,e,n);return t},mergeIf:function(t,e){return M.merge(t,e,{merger:M._mergerIf})},extend:Object.assign||function(t){return M.merge(t,[].slice.call(arguments,1),{merger:function(t,e,n){e[t]=n[t]}})},inherits:function(t){var e=this,n=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},i=function(){this.constructor=n};return i.prototype=e.prototype,n.prototype=new i,n.extend=M.inherits,t&&M.extend(n.prototype,t),n.__super__=e.prototype,n},_deprecated:function(t,e,n,i){void 0!==e&&console.warn(t+': "'+n+'" is deprecated. Please use "'+i+'" instead')}},S=M;M.callCallback=M.callback,M.indexOf=function(t,e,n){return Array.prototype.indexOf.call(t,e,n)},M.getValueOrDefault=M.valueOrDefault,M.getValueAtIndexOrDefault=M.valueAtIndexOrDefault;var D={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return(t-=1)*t*t+1},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-((t-=1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return(t-=1)*t*t*t*t+1},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return 1-Math.cos(t*(Math.PI/2))},easeOutSine:function(t){return Math.sin(t*(Math.PI/2))},easeInOutSine:function(t){return-.5*(Math.cos(Math.PI*t)-1)},easeInExpo:function(t){return 0===t?0:Math.pow(2,10*(t-1))},easeOutExpo:function(t){return 1===t?1:1-Math.pow(2,-10*t)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return t>=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.45),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-D.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*D.easeInBounce(2*t):.5*D.easeOutBounce(2*t-1)+.5}},C={effects:D};S.easingEffects=D;var P=Math.PI,T=P/180,O=2*P,A=P/2,F=P/4,I=2*P/3,L={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,i,a,r){if(r){var o=Math.min(r,a/2,i/2),s=e+o,l=n+o,u=e+i-o,d=n+a-o;t.moveTo(e,l),s<u&&l<d?(t.arc(s,l,o,-P,-A),t.arc(u,l,o,-A,0),t.arc(u,d,o,0,A),t.arc(s,d,o,A,P)):s<u?(t.moveTo(s,n),t.arc(u,l,o,-A,A),t.arc(s,l,o,A,P+A)):l<d?(t.arc(s,l,o,-P,0),t.arc(s,d,o,0,P)):t.arc(s,l,o,-P,P),t.closePath(),t.moveTo(e,n)}else t.rect(e,n,i,a)},drawPoint:function(t,e,n,i,a,r){var o,s,l,u,d,h=(r||0)*T;if(e&&"object"==typeof e&&("[object HTMLImageElement]"===(o=e.toString())||"[object HTMLCanvasElement]"===o))return t.save(),t.translate(i,a),t.rotate(h),t.drawImage(e,-e.width/2,-e.height/2,e.width,e.height),void t.restore();if(!(isNaN(n)||n<=0)){switch(t.beginPath(),e){default:t.arc(i,a,n,0,O),t.closePath();break;case"triangle":t.moveTo(i+Math.sin(h)*n,a-Math.cos(h)*n),h+=I,t.lineTo(i+Math.sin(h)*n,a-Math.cos(h)*n),h+=I,t.lineTo(i+Math.sin(h)*n,a-Math.cos(h)*n),t.closePath();break;case"rectRounded":u=n-(d=.516*n),s=Math.cos(h+F)*u,l=Math.sin(h+F)*u,t.arc(i-s,a-l,d,h-P,h-A),t.arc(i+l,a-s,d,h-A,h),t.arc(i+s,a+l,d,h,h+A),t.arc(i-l,a+s,d,h+A,h+P),t.closePath();break;case"rect":if(!r){u=Math.SQRT1_2*n,t.rect(i-u,a-u,2*u,2*u);break}h+=F;case"rectRot":s=Math.cos(h)*n,l=Math.sin(h)*n,t.moveTo(i-s,a-l),t.lineTo(i+l,a-s),t.lineTo(i+s,a+l),t.lineTo(i-l,a+s),t.closePath();break;case"crossRot":h+=F;case"cross":s=Math.cos(h)*n,l=Math.sin(h)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i+l,a-s),t.lineTo(i-l,a+s);break;case"star":s=Math.cos(h)*n,l=Math.sin(h)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i+l,a-s),t.lineTo(i-l,a+s),h+=F,s=Math.cos(h)*n,l=Math.sin(h)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i+l,a-s),t.lineTo(i-l,a+s);break;case"line":s=Math.cos(h)*n,l=Math.sin(h)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l);break;case"dash":t.moveTo(i,a),t.lineTo(i+Math.cos(h)*n,a+Math.sin(h)*n)}t.fill(),t.stroke()}},_isPointInArea:function(t,e){return t.x>e.left-1e-6&&t.x<e.right+1e-6&&t.y>e.top-1e-6&&t.y<e.bottom+1e-6},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,n,i){var a=n.steppedLine;if(a){if("middle"===a){var r=(e.x+n.x)/2;t.lineTo(r,i?n.y:e.y),t.lineTo(r,i?e.y:n.y)}else"after"===a&&!i||"after"!==a&&i?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y);t.lineTo(n.x,n.y)}else n.tension?t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):t.lineTo(n.x,n.y)}},R=L;S.clear=L.clear,S.drawRoundedRectangle=function(t){t.beginPath(),L.roundedRect.apply(L,arguments)};var N={_set:function(t,e){return S.merge(this[t]||(this[t]={}),e)}};N._set("global",{defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",defaultLineHeight:1.2,showLines:!0});var W=N,Y=S.valueOrDefault;var z={toLineHeight:function(t,e){var n=(""+t).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);if(!n||"normal"===n[1])return 1.2*e;switch(t=+n[2],n[3]){case"px":return t;case"%":t/=100}return e*t},toPadding:function(t){var e,n,i,a;return S.isObject(t)?(e=+t.top||0,n=+t.right||0,i=+t.bottom||0,a=+t.left||0):e=n=i=a=+t||0,{top:e,right:n,bottom:i,left:a,height:e+i,width:a+n}},_parseFont:function(t){var e=W.global,n=Y(t.fontSize,e.defaultFontSize),i={family:Y(t.fontFamily,e.defaultFontFamily),lineHeight:S.options.toLineHeight(Y(t.lineHeight,e.defaultLineHeight),n),size:n,style:Y(t.fontStyle,e.defaultFontStyle),weight:null,string:""};return i.string=function(t){return!t||S.isNullOrUndef(t.size)||S.isNullOrUndef(t.family)?null:(t.style?t.style+" ":"")+(t.weight?t.weight+" ":"")+t.size+"px "+t.family}(i),i},resolve:function(t,e,n,i){var a,r,o,s=!0;for(a=0,r=t.length;a<r;++a)if(void 0!==(o=t[a])&&(void 0!==e&&"function"==typeof o&&(o=o(e),s=!1),void 0!==n&&S.isArray(o)&&(o=o[n],s=!1),void 0!==o))return i&&!s&&(i.cacheable=!1),o}},E={_factorize:function(t){var e,n=[],i=Math.sqrt(t);for(e=1;e<i;e++)t%e==0&&(n.push(e),n.push(t/e));return i===(0|i)&&n.push(i),n.sort((function(t,e){return t-e})).pop(),n},log10:Math.log10||function(t){var e=Math.log(t)*Math.LOG10E,n=Math.round(e);return t===Math.pow(10,n)?n:e}},V=E;S.log10=E.log10;var H=S,B=C,j=R,U=z,G=V,q={getRtlAdapter:function(t,e,n){return t?function(t,e){return{x:function(n){return t+t+e-n},setWidth:function(t){e=t},textAlign:function(t){return"center"===t?t:"right"===t?"left":"right"},xPlus:function(t,e){return t-e},leftForLtr:function(t,e){return t-e}}}(e,n):{x:function(t){return t},setWidth:function(t){},textAlign:function(t){return t},xPlus:function(t,e){return t+e},leftForLtr:function(t,e){return t}}},overrideTextDirection:function(t,e){var n,i;"ltr"!==e&&"rtl"!==e||(i=[(n=t.canvas.style).getPropertyValue("direction"),n.getPropertyPriority("direction")],n.setProperty("direction",e,"important"),t.prevTextDirection=i)},restoreTextDirection:function(t){var e=t.prevTextDirection;void 0!==e&&(delete t.prevTextDirection,t.canvas.style.setProperty("direction",e[0],e[1]))}};H.easing=B,H.canvas=j,H.options=U,H.math=G,H.rtl=q;var Z=function(t){H.extend(this,t),this.initialize.apply(this,arguments)};H.extend(Z.prototype,{_type:void 0,initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=H.extend({},t._model)),t._start={},t},transition:function(t){var e=this,n=e._model,i=e._start,a=e._view;return n&&1!==t?(a||(a=e._view={}),i||(i=e._start={}),function(t,e,n,i){var a,r,o,s,l,u,d,h,c,f=Object.keys(n);for(a=0,r=f.length;a<r;++a)if(u=n[o=f[a]],e.hasOwnProperty(o)||(e[o]=u),(s=e[o])!==u&&"_"!==o[0]){if(t.hasOwnProperty(o)||(t[o]=s),(d=typeof u)===typeof(l=t[o]))if("string"===d){if((h=k(l)).valid&&(c=k(u)).valid){e[o]=c.mix(h,i).rgbString();continue}}else if(H.isFinite(l)&&H.isFinite(u)){e[o]=l+(u-l)*i;continue}e[o]=u}}(i,a,n,t),e):(e._view=H.extend({},n),e._start=null,e)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return H.isNumber(this._model.x)&&H.isNumber(this._model.y)}}),Z.extend=H.inherits;var $=Z,X=$.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),K=X;Object.defineProperty(X.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(X.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}}),W._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:H.noop,onComplete:H.noop}});var J={animations:[],request:null,addAnimation:function(t,e,n,i){var a,r,o=this.animations;for(e.chart=t,e.startTime=Date.now(),e.duration=n,i||(t.animating=!0),a=0,r=o.length;a<r;++a)if(o[a].chart===t)return void(o[a]=e);o.push(e),1===o.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var e=H.findIndex(this.animations,(function(e){return e.chart===t}));-1!==e&&(this.animations.splice(e,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=H.requestAnimFrame.call(window,(function(){t.request=null,t.startDigest()})))},startDigest:function(){this.advance(),this.animations.length>0&&this.requestAnimationFrame()},advance:function(){for(var t,e,n,i,a=this.animations,r=0;r<a.length;)e=(t=a[r]).chart,n=t.numSteps,i=Math.floor((Date.now()-t.startTime)/t.duration*n)+1,t.currentStep=Math.min(i,n),H.callback(t.render,[e,t],e),H.callback(t.onAnimationProgress,[t],e),t.currentStep>=n?(H.callback(t.onAnimationComplete,[t],e),e.animating=!1,a.splice(r,1)):++r}},Q=H.options.resolve,tt=["push","pop","shift","splice","unshift"];function et(t,e){var n=t._chartjs;if(n){var i=n.listeners,a=i.indexOf(e);-1!==a&&i.splice(a,1),i.length>0||(tt.forEach((function(e){delete t[e]})),delete t._chartjs)}}var nt=function(t,e){this.initialize(t,e)};H.extend(nt.prototype,{datasetElementType:null,dataElementType:null,_datasetElementOptions:["backgroundColor","borderCapStyle","borderColor","borderDash","borderDashOffset","borderJoinStyle","borderWidth"],_dataElementOptions:["backgroundColor","borderColor","borderWidth","pointStyle"],initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements(),n._type=n.getMeta().type},updateIndex:function(t){this.index=t},linkScales:function(){var t=this.getMeta(),e=this.chart,n=e.scales,i=this.getDataset(),a=e.options.scales;null!==t.xAxisID&&t.xAxisID in n&&!i.xAxisID||(t.xAxisID=i.xAxisID||a.xAxes[0].id),null!==t.yAxisID&&t.yAxisID in n&&!i.yAxisID||(t.yAxisID=i.yAxisID||a.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},_getValueScaleId:function(){return this.getMeta().yAxisID},_getIndexScaleId:function(){return this.getMeta().xAxisID},_getValueScale:function(){return this.getScaleForId(this._getValueScaleId())},_getIndexScale:function(){return this.getScaleForId(this._getIndexScaleId())},reset:function(){this._update(!0)},destroy:function(){this._data&&et(this._data,this)},createMetaDataset:function(){var t=this.datasetElementType;return t&&new t({_chart:this.chart,_datasetIndex:this.index})},createMetaData:function(t){var e=this.dataElementType;return e&&new e({_chart:this.chart,_datasetIndex:this.index,_index:t})},addElements:function(){var t,e,n=this.getMeta(),i=this.getDataset().data||[],a=n.data;for(t=0,e=i.length;t<e;++t)a[t]=a[t]||this.createMetaData(t);n.dataset=n.dataset||this.createMetaDataset()},addElementAndReset:function(t){var e=this.createMetaData(t);this.getMeta().data.splice(t,0,e),this.updateElement(e,t,!0)},buildOrUpdateElements:function(){var t,e,n=this,i=n.getDataset(),a=i.data||(i.data=[]);n._data!==a&&(n._data&&et(n._data,n),a&&Object.isExtensible(a)&&(e=n,(t=a)._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),tt.forEach((function(e){var n="onData"+e.charAt(0).toUpperCase()+e.slice(1),i=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),a=i.apply(this,e);return H.each(t._chartjs.listeners,(function(t){"function"==typeof t[n]&&t[n].apply(t,e)})),a}})})))),n._data=a),n.resyncElements()},_configure:function(){this._config=H.merge({},[this.chart.options.datasets[this._type],this.getDataset()],{merger:function(t,e,n){"_meta"!==t&&"data"!==t&&H._merger(t,e,n)}})},_update:function(t){this._configure(),this._cachedDataOpts=null,this.update(t)},update:H.noop,transition:function(t){for(var e=this.getMeta(),n=e.data||[],i=n.length,a=0;a<i;++a)n[a].transition(t);e.dataset&&e.dataset.transition(t)},draw:function(){var t=this.getMeta(),e=t.data||[],n=e.length,i=0;for(t.dataset&&t.dataset.draw();i<n;++i)e[i].draw()},getStyle:function(t){var e,n=this.getMeta(),i=n.dataset;return this._configure(),i&&void 0===t?e=this._resolveDatasetElementOptions(i||{}):(t=t||0,e=this._resolveDataElementOptions(n.data[t]||{},t)),!1!==e.fill&&null!==e.fill||(e.backgroundColor=e.borderColor),e},_resolveDatasetElementOptions:function(t,e){var n,i,a,r,o=this,s=o.chart,l=o._config,u=t.custom||{},d=s.options.elements[o.datasetElementType.prototype._type]||{},h=o._datasetElementOptions,c={},f={chart:s,dataset:o.getDataset(),datasetIndex:o.index,hover:e};for(n=0,i=h.length;n<i;++n)a=h[n],r=e?"hover"+a.charAt(0).toUpperCase()+a.slice(1):a,c[a]=Q([u[r],l[r],d[r]],f);return c},_resolveDataElementOptions:function(t,e){var n=this,i=t&&t.custom,a=n._cachedDataOpts;if(a&&!i)return a;var r,o,s,l,u=n.chart,d=n._config,h=u.options.elements[n.dataElementType.prototype._type]||{},c=n._dataElementOptions,f={},g={chart:u,dataIndex:e,dataset:n.getDataset(),datasetIndex:n.index},m={cacheable:!i};if(i=i||{},H.isArray(c))for(o=0,s=c.length;o<s;++o)f[l=c[o]]=Q([i[l],d[l],h[l]],g,e,m);else for(o=0,s=(r=Object.keys(c)).length;o<s;++o)f[l=r[o]]=Q([i[l],d[c[l]],d[l],h[l]],g,e,m);return m.cacheable&&(n._cachedDataOpts=Object.freeze(f)),f},removeHoverStyle:function(t){H.merge(t._model,t.$previousStyle||{}),delete t.$previousStyle},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model,r=H.getHoverColor;t.$previousStyle={backgroundColor:a.backgroundColor,borderColor:a.borderColor,borderWidth:a.borderWidth},a.backgroundColor=Q([i.hoverBackgroundColor,e.hoverBackgroundColor,r(a.backgroundColor)],void 0,n),a.borderColor=Q([i.hoverBorderColor,e.hoverBorderColor,r(a.borderColor)],void 0,n),a.borderWidth=Q([i.hoverBorderWidth,e.hoverBorderWidth,a.borderWidth],void 0,n)},_removeDatasetHoverStyle:function(){var t=this.getMeta().dataset;t&&this.removeHoverStyle(t)},_setDatasetHoverStyle:function(){var t,e,n,i,a,r,o=this.getMeta().dataset,s={};if(o){for(r=o._model,a=this._resolveDatasetElementOptions(o,!0),t=0,e=(i=Object.keys(a)).length;t<e;++t)s[n=i[t]]=r[n],r[n]=a[n];o.$previousStyle=s}},resyncElements:function(){var t=this.getMeta(),e=this.getDataset().data,n=t.data.length,i=e.length;i<n?t.data.splice(i,n-i):i>n&&this.insertElements(n,i-n)},insertElements:function(t,e){for(var n=0;n<e;++n)this.addElementAndReset(t+n)},onDataPush:function(){var t=arguments.length;this.insertElements(this.getDataset().data.length-t,t)},onDataPop:function(){this.getMeta().data.pop()},onDataShift:function(){this.getMeta().data.shift()},onDataSplice:function(t,e){this.getMeta().data.splice(t,e),this.insertElements(t,arguments.length-2)},onDataUnshift:function(){this.insertElements(0,arguments.length)}}),nt.extend=H.inherits;var it=nt,at=2*Math.PI;function rt(t,e){var n=e.startAngle,i=e.endAngle,a=e.pixelMargin,r=a/e.outerRadius,o=e.x,s=e.y;t.beginPath(),t.arc(o,s,e.outerRadius,n-r,i+r),e.innerRadius>a?(r=a/e.innerRadius,t.arc(o,s,e.innerRadius-a,i+r,n-r,!0)):t.arc(o,s,a,i+Math.PI/2,n-Math.PI/2),t.closePath(),t.clip()}function ot(t,e,n){var i="inner"===e.borderAlign;i?(t.lineWidth=2*e.borderWidth,t.lineJoin="round"):(t.lineWidth=e.borderWidth,t.lineJoin="bevel"),n.fullCircles&&function(t,e,n,i){var a,r=n.endAngle;for(i&&(n.endAngle=n.startAngle+at,rt(t,n),n.endAngle=r,n.endAngle===n.startAngle&&n.fullCircles&&(n.endAngle+=at,n.fullCircles--)),t.beginPath(),t.arc(n.x,n.y,n.innerRadius,n.startAngle+at,n.startAngle,!0),a=0;a<n.fullCircles;++a)t.stroke();for(t.beginPath(),t.arc(n.x,n.y,e.outerRadius,n.startAngle,n.startAngle+at),a=0;a<n.fullCircles;++a)t.stroke()}(t,e,n,i),i&&rt(t,n),t.beginPath(),t.arc(n.x,n.y,e.outerRadius,n.startAngle,n.endAngle),t.arc(n.x,n.y,n.innerRadius,n.endAngle,n.startAngle,!0),t.closePath(),t.stroke()}W._set("global",{elements:{arc:{backgroundColor:W.global.defaultColor,borderColor:"#fff",borderWidth:2,borderAlign:"center"}}});var st=$.extend({_type:"arc",inLabelRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2)},inRange:function(t,e){var n=this._view;if(n){for(var i=H.getAngleFromPoint(n,{x:t,y:e}),a=i.angle,r=i.distance,o=n.startAngle,s=n.endAngle;s<o;)s+=at;for(;a>s;)a-=at;for(;a<o;)a+=at;var l=a>=o&&a<=s,u=r>=n.innerRadius&&r<=n.outerRadius;return l&&u}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t,e=this._chart.ctx,n=this._view,i="inner"===n.borderAlign?.33:0,a={x:n.x,y:n.y,innerRadius:n.innerRadius,outerRadius:Math.max(n.outerRadius-i,0),pixelMargin:i,startAngle:n.startAngle,endAngle:n.endAngle,fullCircles:Math.floor(n.circumference/at)};if(e.save(),e.fillStyle=n.backgroundColor,e.strokeStyle=n.borderColor,a.fullCircles){for(a.endAngle=a.startAngle+at,e.beginPath(),e.arc(a.x,a.y,a.outerRadius,a.startAngle,a.endAngle),e.arc(a.x,a.y,a.innerRadius,a.endAngle,a.startAngle,!0),e.closePath(),t=0;t<a.fullCircles;++t)e.fill();a.endAngle=a.startAngle+n.circumference%at}e.beginPath(),e.arc(a.x,a.y,a.outerRadius,a.startAngle,a.endAngle),e.arc(a.x,a.y,a.innerRadius,a.endAngle,a.startAngle,!0),e.closePath(),e.fill(),n.borderWidth&&ot(e,n,a),e.restore()}}),lt=H.valueOrDefault,ut=W.global.defaultColor;W._set("global",{elements:{line:{tension:.4,backgroundColor:ut,borderWidth:3,borderColor:ut,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}});var dt=$.extend({_type:"line",draw:function(){var t,e,n,i=this,a=i._view,r=i._chart.ctx,o=a.spanGaps,s=i._children.slice(),l=W.global,u=l.elements.line,d=-1,h=i._loop;if(s.length){if(i._loop){for(t=0;t<s.length;++t)if(e=H.previousItem(s,t),!s[t]._view.skip&&e._view.skip){s=s.slice(t).concat(s.slice(0,t)),h=o;break}h&&s.push(s[0])}for(r.save(),r.lineCap=a.borderCapStyle||u.borderCapStyle,r.setLineDash&&r.setLineDash(a.borderDash||u.borderDash),r.lineDashOffset=lt(a.borderDashOffset,u.borderDashOffset),r.lineJoin=a.borderJoinStyle||u.borderJoinStyle,r.lineWidth=lt(a.borderWidth,u.borderWidth),r.strokeStyle=a.borderColor||l.defaultColor,r.beginPath(),(n=s[0]._view).skip||(r.moveTo(n.x,n.y),d=0),t=1;t<s.length;++t)n=s[t]._view,e=-1===d?H.previousItem(s,t):s[d],n.skip||(d!==t-1&&!o||-1===d?r.moveTo(n.x,n.y):H.canvas.lineTo(r,e._view,n),d=t);h&&r.closePath(),r.stroke(),r.restore()}}}),ht=H.valueOrDefault,ct=W.global.defaultColor;function ft(t){var e=this._view;return!!e&&Math.abs(t-e.x)<e.radius+e.hitRadius}W._set("global",{elements:{point:{radius:3,pointStyle:"circle",backgroundColor:ct,borderColor:ct,borderWidth:1,hitRadius:1,hoverRadius:4,hoverBorderWidth:1}}});var gt=$.extend({_type:"point",inRange:function(t,e){var n=this._view;return!!n&&Math.pow(t-n.x,2)+Math.pow(e-n.y,2)<Math.pow(n.hitRadius+n.radius,2)},inLabelRange:ft,inXRange:ft,inYRange:function(t){var e=this._view;return!!e&&Math.abs(t-e.y)<e.radius+e.hitRadius},getCenterPoint:function(){var t=this._view;return{x:t.x,y:t.y}},getArea:function(){return Math.PI*Math.pow(this._view.radius,2)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(t){var e=this._view,n=this._chart.ctx,i=e.pointStyle,a=e.rotation,r=e.radius,o=e.x,s=e.y,l=W.global,u=l.defaultColor;e.skip||(void 0===t||H.canvas._isPointInArea(e,t))&&(n.strokeStyle=e.borderColor||u,n.lineWidth=ht(e.borderWidth,l.elements.point.borderWidth),n.fillStyle=e.backgroundColor||u,H.canvas.drawPoint(n,i,r,o,s,a))}}),mt=W.global.defaultColor;function pt(t){return t&&void 0!==t.width}function vt(t){var e,n,i,a,r;return pt(t)?(r=t.width/2,e=t.x-r,n=t.x+r,i=Math.min(t.y,t.base),a=Math.max(t.y,t.base)):(r=t.height/2,e=Math.min(t.x,t.base),n=Math.max(t.x,t.base),i=t.y-r,a=t.y+r),{left:e,top:i,right:n,bottom:a}}function bt(t,e,n){return t===e?n:t===n?e:t}function yt(t,e,n){var i,a,r,o,s=t.borderWidth,l=function(t){var e=t.borderSkipped,n={};return e?(t.horizontal?t.base>t.x&&(e=bt(e,"left","right")):t.base<t.y&&(e=bt(e,"bottom","top")),n[e]=!0,n):n}(t);return H.isObject(s)?(i=+s.top||0,a=+s.right||0,r=+s.bottom||0,o=+s.left||0):i=a=r=o=+s||0,{t:l.top||i<0?0:i>n?n:i,r:l.right||a<0?0:a>e?e:a,b:l.bottom||r<0?0:r>n?n:r,l:l.left||o<0?0:o>e?e:o}}function xt(t,e,n){var i=null===e,a=null===n,r=!(!t||i&&a)&&vt(t);return r&&(i||e>=r.left&&e<=r.right)&&(a||n>=r.top&&n<=r.bottom)}W._set("global",{elements:{rectangle:{backgroundColor:mt,borderColor:mt,borderSkipped:"bottom",borderWidth:0}}});var _t=$.extend({_type:"rectangle",draw:function(){var t=this._chart.ctx,e=this._view,n=function(t){var e=vt(t),n=e.right-e.left,i=e.bottom-e.top,a=yt(t,n/2,i/2);return{outer:{x:e.left,y:e.top,w:n,h:i},inner:{x:e.left+a.l,y:e.top+a.t,w:n-a.l-a.r,h:i-a.t-a.b}}}(e),i=n.outer,a=n.inner;t.fillStyle=e.backgroundColor,t.fillRect(i.x,i.y,i.w,i.h),i.w===a.w&&i.h===a.h||(t.save(),t.beginPath(),t.rect(i.x,i.y,i.w,i.h),t.clip(),t.fillStyle=e.borderColor,t.rect(a.x,a.y,a.w,a.h),t.fill("evenodd"),t.restore())},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){return xt(this._view,t,e)},inLabelRange:function(t,e){var n=this._view;return pt(n)?xt(n,t,null):xt(n,null,e)},inXRange:function(t){return xt(this._view,t,null)},inYRange:function(t){return xt(this._view,null,t)},getCenterPoint:function(){var t,e,n=this._view;return pt(n)?(t=n.x,e=(n.y+n.base)/2):(t=(n.x+n.base)/2,e=n.y),{x:t,y:e}},getArea:function(){var t=this._view;return pt(t)?t.width*Math.abs(t.y-t.base):t.height*Math.abs(t.x-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}}),wt={},kt=st,Mt=dt,St=gt,Dt=_t;wt.Arc=kt,wt.Line=Mt,wt.Point=St,wt.Rectangle=Dt;var Ct=H._deprecated,Pt=H.valueOrDefault;function Tt(t,e,n){var i,a,r=n.barThickness,o=e.stackCount,s=e.pixels[t],l=H.isNullOrUndef(r)?function(t,e){var n,i,a,r,o=t._length;for(a=1,r=e.length;a<r;++a)o=Math.min(o,Math.abs(e[a]-e[a-1]));for(a=0,r=t.getTicks().length;a<r;++a)i=t.getPixelForTick(a),o=a>0?Math.min(o,Math.abs(i-n)):o,n=i;return o}(e.scale,e.pixels):-1;return H.isNullOrUndef(r)?(i=l*n.categoryPercentage,a=n.barPercentage):(i=r*o,a=1),{chunk:i/o,ratio:a,start:s-i/2}}W._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),W._set("global",{datasets:{bar:{categoryPercentage:.8,barPercentage:.9}}});var Ot=it.extend({dataElementType:wt.Rectangle,_dataElementOptions:["backgroundColor","borderColor","borderSkipped","borderWidth","barPercentage","barThickness","categoryPercentage","maxBarThickness","minBarLength"],initialize:function(){var t,e,n=this;it.prototype.initialize.apply(n,arguments),(t=n.getMeta()).stack=n.getDataset().stack,t.bar=!0,e=n._getIndexScale().options,Ct("bar chart",e.barPercentage,"scales.[x/y]Axes.barPercentage","dataset.barPercentage"),Ct("bar chart",e.barThickness,"scales.[x/y]Axes.barThickness","dataset.barThickness"),Ct("bar chart",e.categoryPercentage,"scales.[x/y]Axes.categoryPercentage","dataset.categoryPercentage"),Ct("bar chart",n._getValueScale().options.minBarLength,"scales.[x/y]Axes.minBarLength","dataset.minBarLength"),Ct("bar chart",e.maxBarThickness,"scales.[x/y]Axes.maxBarThickness","dataset.maxBarThickness")},update:function(t){var e,n,i=this.getMeta().data;for(this._ruler=this.getRuler(),e=0,n=i.length;e<n;++e)this.updateElement(i[e],e,t)},updateElement:function(t,e,n){var i=this,a=i.getMeta(),r=i.getDataset(),o=i._resolveDataElementOptions(t,e);t._xScale=i.getScaleForId(a.xAxisID),t._yScale=i.getScaleForId(a.yAxisID),t._datasetIndex=i.index,t._index=e,t._model={backgroundColor:o.backgroundColor,borderColor:o.borderColor,borderSkipped:o.borderSkipped,borderWidth:o.borderWidth,datasetLabel:r.label,label:i.chart.data.labels[e]},H.isArray(r.data[e])&&(t._model.borderSkipped=null),i._updateElementGeometry(t,e,n,o),t.pivot()},_updateElementGeometry:function(t,e,n,i){var a=this,r=t._model,o=a._getValueScale(),s=o.getBasePixel(),l=o.isHorizontal(),u=a._ruler||a.getRuler(),d=a.calculateBarValuePixels(a.index,e,i),h=a.calculateBarIndexPixels(a.index,e,u,i);r.horizontal=l,r.base=n?s:d.base,r.x=l?n?s:d.head:h.center,r.y=l?h.center:n?s:d.head,r.height=l?h.size:void 0,r.width=l?void 0:h.size},_getStacks:function(t){var e,n,i=this._getIndexScale(),a=i._getMatchingVisibleMetas(this._type),r=i.options.stacked,o=a.length,s=[];for(e=0;e<o&&(n=a[e],(!1===r||-1===s.indexOf(n.stack)||void 0===r&&void 0===n.stack)&&s.push(n.stack),n.index!==t);++e);return s},getStackCount:function(){return this._getStacks().length},getStackIndex:function(t,e){var n=this._getStacks(t),i=void 0!==e?n.indexOf(e):-1;return-1===i?n.length-1:i},getRuler:function(){var t,e,n=this._getIndexScale(),i=[];for(t=0,e=this.getMeta().data.length;t<e;++t)i.push(n.getPixelForValue(null,t,this.index));return{pixels:i,start:n._startPixel,end:n._endPixel,stackCount:this.getStackCount(),scale:n}},calculateBarValuePixels:function(t,e,n){var i,a,r,o,s,l,u,d=this.chart,h=this._getValueScale(),c=h.isHorizontal(),f=d.data.datasets,g=h._getMatchingVisibleMetas(this._type),m=h._parseValue(f[t].data[e]),p=n.minBarLength,v=h.options.stacked,b=this.getMeta().stack,y=void 0===m.start?0:m.max>=0&&m.min>=0?m.min:m.max,x=void 0===m.start?m.end:m.max>=0&&m.min>=0?m.max-m.min:m.min-m.max,_=g.length;if(v||void 0===v&&void 0!==b)for(i=0;i<_&&(a=g[i]).index!==t;++i)a.stack===b&&(r=void 0===(u=h._parseValue(f[a.index].data[e])).start?u.end:u.min>=0&&u.max>=0?u.max:u.min,(m.min<0&&r<0||m.max>=0&&r>0)&&(y+=r));return o=h.getPixelForValue(y),l=(s=h.getPixelForValue(y+x))-o,void 0!==p&&Math.abs(l)<p&&(l=p,s=x>=0&&!c||x<0&&c?o-p:o+p),{size:l,base:o,head:s,center:s+l/2}},calculateBarIndexPixels:function(t,e,n,i){var a="flex"===i.barThickness?function(t,e,n){var i,a=e.pixels,r=a[t],o=t>0?a[t-1]:null,s=t<a.length-1?a[t+1]:null,l=n.categoryPercentage;return null===o&&(o=r-(null===s?e.end-e.start:s-r)),null===s&&(s=r+r-o),i=r-(r-Math.min(o,s))/2*l,{chunk:Math.abs(s-o)/2*l/e.stackCount,ratio:n.barPercentage,start:i}}(e,n,i):Tt(e,n,i),r=this.getStackIndex(t,this.getMeta().stack),o=a.start+a.chunk*r+a.chunk/2,s=Math.min(Pt(i.maxBarThickness,1/0),a.chunk*a.ratio);return{base:o-s/2,head:o+s/2,center:o,size:s}},draw:function(){var t=this.chart,e=this._getValueScale(),n=this.getMeta().data,i=this.getDataset(),a=n.length,r=0;for(H.canvas.clipArea(t.ctx,t.chartArea);r<a;++r){var o=e._parseValue(i.data[r]);isNaN(o.min)||isNaN(o.max)||n[r].draw()}H.canvas.unclipArea(t.ctx)},_resolveDataElementOptions:function(){var t=this,e=H.extend({},it.prototype._resolveDataElementOptions.apply(t,arguments)),n=t._getIndexScale().options,i=t._getValueScale().options;return e.barPercentage=Pt(n.barPercentage,e.barPercentage),e.barThickness=Pt(n.barThickness,e.barThickness),e.categoryPercentage=Pt(n.categoryPercentage,e.categoryPercentage),e.maxBarThickness=Pt(n.maxBarThickness,e.maxBarThickness),e.minBarLength=Pt(i.minBarLength,e.minBarLength),e}}),At=H.valueOrDefault,Ft=H.options.resolve;W._set("bubble",{hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.datasets[t.datasetIndex].label||"",i=e.datasets[t.datasetIndex].data[t.index];return n+": ("+t.xLabel+", "+t.yLabel+", "+i.r+")"}}}});var It=it.extend({dataElementType:wt.Point,_dataElementOptions:["backgroundColor","borderColor","borderWidth","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth","hoverRadius","hitRadius","pointStyle","rotation"],update:function(t){var e=this,n=e.getMeta().data;H.each(n,(function(n,i){e.updateElement(n,i,t)}))},updateElement:function(t,e,n){var i=this,a=i.getMeta(),r=t.custom||{},o=i.getScaleForId(a.xAxisID),s=i.getScaleForId(a.yAxisID),l=i._resolveDataElementOptions(t,e),u=i.getDataset().data[e],d=i.index,h=n?o.getPixelForDecimal(.5):o.getPixelForValue("object"==typeof u?u:NaN,e,d),c=n?s.getBasePixel():s.getPixelForValue(u,e,d);t._xScale=o,t._yScale=s,t._options=l,t._datasetIndex=d,t._index=e,t._model={backgroundColor:l.backgroundColor,borderColor:l.borderColor,borderWidth:l.borderWidth,hitRadius:l.hitRadius,pointStyle:l.pointStyle,rotation:l.rotation,radius:n?0:l.radius,skip:r.skip||isNaN(h)||isNaN(c),x:h,y:c},t.pivot()},setHoverStyle:function(t){var e=t._model,n=t._options,i=H.getHoverColor;t.$previousStyle={backgroundColor:e.backgroundColor,borderColor:e.borderColor,borderWidth:e.borderWidth,radius:e.radius},e.backgroundColor=At(n.hoverBackgroundColor,i(n.backgroundColor)),e.borderColor=At(n.hoverBorderColor,i(n.borderColor)),e.borderWidth=At(n.hoverBorderWidth,n.borderWidth),e.radius=n.radius+n.hoverRadius},_resolveDataElementOptions:function(t,e){var n=this,i=n.chart,a=n.getDataset(),r=t.custom||{},o=a.data[e]||{},s=it.prototype._resolveDataElementOptions.apply(n,arguments),l={chart:i,dataIndex:e,dataset:a,datasetIndex:n.index};return n._cachedDataOpts===s&&(s=H.extend({},s)),s.radius=Ft([r.radius,o.r,n._config.radius,i.options.elements.point.radius],l,e),s}}),Lt=H.valueOrDefault,Rt=Math.PI,Nt=2*Rt,Wt=Rt/2;W._set("doughnut",{animation:{animateRotate:!0,animateScale:!1},hover:{mode:"single"},legendCallback:function(t){var e,n,i,a=document.createElement("ul"),r=t.data,o=r.datasets,s=r.labels;if(a.setAttribute("class",t.id+"-legend"),o.length)for(e=0,n=o[0].data.length;e<n;++e)(i=a.appendChild(document.createElement("li"))).appendChild(document.createElement("span")).style.backgroundColor=o[0].backgroundColor[e],s[e]&&i.appendChild(document.createTextNode(s[e]));return a.outerHTML},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map((function(n,i){var a=t.getDatasetMeta(0),r=a.controller.getStyle(i);return{text:n,fillStyle:r.backgroundColor,strokeStyle:r.borderColor,lineWidth:r.borderWidth,hidden:isNaN(e.datasets[0].data[i])||a.data[i].hidden,index:i}})):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n<i;++n)(a=o.getDatasetMeta(n)).data[r]&&(a.data[r].hidden=!a.data[r].hidden);o.update()}},cutoutPercentage:50,rotation:-Wt,circumference:Nt,tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.labels[t.index],i=": "+e.datasets[t.datasetIndex].data[t.index];return H.isArray(n)?(n=n.slice())[0]+=i:n+=i,n}}}});var Yt=it.extend({dataElementType:wt.Arc,linkScales:H.noop,_dataElementOptions:["backgroundColor","borderColor","borderWidth","borderAlign","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth"],getRingIndex:function(t){for(var e=0,n=0;n<t;++n)this.chart.isDatasetVisible(n)&&++e;return e},update:function(t){var e,n,i,a,r=this,o=r.chart,s=o.chartArea,l=o.options,u=1,d=1,h=0,c=0,f=r.getMeta(),g=f.data,m=l.cutoutPercentage/100||0,p=l.circumference,v=r._getRingWeight(r.index);if(p<Nt){var b=l.rotation%Nt,y=(b+=b>=Rt?-Nt:b<-Rt?Nt:0)+p,x=Math.cos(b),_=Math.sin(b),w=Math.cos(y),k=Math.sin(y),M=b<=0&&y>=0||y>=Nt,S=b<=Wt&&y>=Wt||y>=Nt+Wt,D=b<=-Wt&&y>=-Wt||y>=Rt+Wt,C=b===-Rt||y>=Rt?-1:Math.min(x,x*m,w,w*m),P=D?-1:Math.min(_,_*m,k,k*m),T=M?1:Math.max(x,x*m,w,w*m),O=S?1:Math.max(_,_*m,k,k*m);u=(T-C)/2,d=(O-P)/2,h=-(T+C)/2,c=-(O+P)/2}for(i=0,a=g.length;i<a;++i)g[i]._options=r._resolveDataElementOptions(g[i],i);for(o.borderWidth=r.getMaxBorderWidth(),e=(s.right-s.left-o.borderWidth)/u,n=(s.bottom-s.top-o.borderWidth)/d,o.outerRadius=Math.max(Math.min(e,n)/2,0),o.innerRadius=Math.max(o.outerRadius*m,0),o.radiusLength=(o.outerRadius-o.innerRadius)/(r._getVisibleDatasetWeightTotal()||1),o.offsetX=h*o.outerRadius,o.offsetY=c*o.outerRadius,f.total=r.calculateTotal(),r.outerRadius=o.outerRadius-o.radiusLength*r._getRingWeightOffset(r.index),r.innerRadius=Math.max(r.outerRadius-o.radiusLength*v,0),i=0,a=g.length;i<a;++i)r.updateElement(g[i],i,t)},updateElement:function(t,e,n){var i=this,a=i.chart,r=a.chartArea,o=a.options,s=o.animation,l=(r.left+r.right)/2,u=(r.top+r.bottom)/2,d=o.rotation,h=o.rotation,c=i.getDataset(),f=n&&s.animateRotate?0:t.hidden?0:i.calculateCircumference(c.data[e])*(o.circumference/Nt),g=n&&s.animateScale?0:i.innerRadius,m=n&&s.animateScale?0:i.outerRadius,p=t._options||{};H.extend(t,{_datasetIndex:i.index,_index:e,_model:{backgroundColor:p.backgroundColor,borderColor:p.borderColor,borderWidth:p.borderWidth,borderAlign:p.borderAlign,x:l+a.offsetX,y:u+a.offsetY,startAngle:d,endAngle:h,circumference:f,outerRadius:m,innerRadius:g,label:H.valueAtIndexOrDefault(c.label,e,a.data.labels[e])}});var v=t._model;n&&s.animateRotate||(v.startAngle=0===e?o.rotation:i.getMeta().data[e-1]._model.endAngle,v.endAngle=v.startAngle+v.circumference),t.pivot()},calculateTotal:function(){var t,e=this.getDataset(),n=this.getMeta(),i=0;return H.each(n.data,(function(n,a){t=e.data[a],isNaN(t)||n.hidden||(i+=Math.abs(t))})),i},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?Nt*(Math.abs(t)/e):0},getMaxBorderWidth:function(t){var e,n,i,a,r,o,s,l,u=0,d=this.chart;if(!t)for(e=0,n=d.data.datasets.length;e<n;++e)if(d.isDatasetVisible(e)){t=(i=d.getDatasetMeta(e)).data,e!==this.index&&(r=i.controller);break}if(!t)return 0;for(e=0,n=t.length;e<n;++e)a=t[e],r?(r._configure(),o=r._resolveDataElementOptions(a,e)):o=a._options,"inner"!==o.borderAlign&&(s=o.borderWidth,u=(l=o.hoverBorderWidth)>(u=s>u?s:u)?l:u);return u},setHoverStyle:function(t){var e=t._model,n=t._options,i=H.getHoverColor;t.$previousStyle={backgroundColor:e.backgroundColor,borderColor:e.borderColor,borderWidth:e.borderWidth},e.backgroundColor=Lt(n.hoverBackgroundColor,i(n.backgroundColor)),e.borderColor=Lt(n.hoverBorderColor,i(n.borderColor)),e.borderWidth=Lt(n.hoverBorderWidth,n.borderWidth)},_getRingWeightOffset:function(t){for(var e=0,n=0;n<t;++n)this.chart.isDatasetVisible(n)&&(e+=this._getRingWeight(n));return e},_getRingWeight:function(t){return Math.max(Lt(this.chart.data.datasets[t].weight,1),0)},_getVisibleDatasetWeightTotal:function(){return this._getRingWeightOffset(this.chart.data.datasets.length)}});W._set("horizontalBar",{hover:{mode:"index",axis:"y"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{type:"category",position:"left",offset:!0,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{mode:"index",axis:"y"}}),W._set("global",{datasets:{horizontalBar:{categoryPercentage:.8,barPercentage:.9}}});var zt=Ot.extend({_getValueScaleId:function(){return this.getMeta().xAxisID},_getIndexScaleId:function(){return this.getMeta().yAxisID}}),Et=H.valueOrDefault,Vt=H.options.resolve,Ht=H.canvas._isPointInArea;function Bt(t,e){var n=t&&t.options.ticks||{},i=n.reverse,a=void 0===n.min?e:0,r=void 0===n.max?e:0;return{start:i?r:a,end:i?a:r}}function jt(t,e,n){var i=n/2,a=Bt(t,i),r=Bt(e,i);return{top:r.end,right:a.end,bottom:r.start,left:a.start}}function Ut(t){var e,n,i,a;return H.isObject(t)?(e=t.top,n=t.right,i=t.bottom,a=t.left):e=n=i=a=t,{top:e,right:n,bottom:i,left:a}}W._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}});var Gt=it.extend({datasetElementType:wt.Line,dataElementType:wt.Point,_datasetElementOptions:["backgroundColor","borderCapStyle","borderColor","borderDash","borderDashOffset","borderJoinStyle","borderWidth","cubicInterpolationMode","fill"],_dataElementOptions:{backgroundColor:"pointBackgroundColor",borderColor:"pointBorderColor",borderWidth:"pointBorderWidth",hitRadius:"pointHitRadius",hoverBackgroundColor:"pointHoverBackgroundColor",hoverBorderColor:"pointHoverBorderColor",hoverBorderWidth:"pointHoverBorderWidth",hoverRadius:"pointHoverRadius",pointStyle:"pointStyle",radius:"pointRadius",rotation:"pointRotation"},update:function(t){var e,n,i=this,a=i.getMeta(),r=a.dataset,o=a.data||[],s=i.chart.options,l=i._config,u=i._showLine=Et(l.showLine,s.showLines);for(i._xScale=i.getScaleForId(a.xAxisID),i._yScale=i.getScaleForId(a.yAxisID),u&&(void 0!==l.tension&&void 0===l.lineTension&&(l.lineTension=l.tension),r._scale=i._yScale,r._datasetIndex=i.index,r._children=o,r._model=i._resolveDatasetElementOptions(r),r.pivot()),e=0,n=o.length;e<n;++e)i.updateElement(o[e],e,t);for(u&&0!==r._model.tension&&i.updateBezierControlPoints(),e=0,n=o.length;e<n;++e)o[e].pivot()},updateElement:function(t,e,n){var i,a,r=this,o=r.getMeta(),s=t.custom||{},l=r.getDataset(),u=r.index,d=l.data[e],h=r._xScale,c=r._yScale,f=o.dataset._model,g=r._resolveDataElementOptions(t,e);i=h.getPixelForValue("object"==typeof d?d:NaN,e,u),a=n?c.getBasePixel():r.calculatePointY(d,e,u),t._xScale=h,t._yScale=c,t._options=g,t._datasetIndex=u,t._index=e,t._model={x:i,y:a,skip:s.skip||isNaN(i)||isNaN(a),radius:g.radius,pointStyle:g.pointStyle,rotation:g.rotation,backgroundColor:g.backgroundColor,borderColor:g.borderColor,borderWidth:g.borderWidth,tension:Et(s.tension,f?f.tension:0),steppedLine:!!f&&f.steppedLine,hitRadius:g.hitRadius}},_resolveDatasetElementOptions:function(t){var e=this,n=e._config,i=t.custom||{},a=e.chart.options,r=a.elements.line,o=it.prototype._resolveDatasetElementOptions.apply(e,arguments);return o.spanGaps=Et(n.spanGaps,a.spanGaps),o.tension=Et(n.lineTension,r.tension),o.steppedLine=Vt([i.steppedLine,n.steppedLine,r.stepped]),o.clip=Ut(Et(n.clip,jt(e._xScale,e._yScale,o.borderWidth))),o},calculatePointY:function(t,e,n){var i,a,r,o,s,l,u,d=this.chart,h=this._yScale,c=0,f=0;if(h.options.stacked){for(s=+h.getRightValue(t),u=(l=d._getSortedVisibleDatasetMetas()).length,i=0;i<u&&(r=l[i]).index!==n;++i)a=d.data.datasets[r.index],"line"===r.type&&r.yAxisID===h.id&&((o=+h.getRightValue(a.data[e]))<0?f+=o||0:c+=o||0);return s<0?h.getPixelForValue(f+s):h.getPixelForValue(c+s)}return h.getPixelForValue(t)},updateBezierControlPoints:function(){var t,e,n,i,a=this.chart,r=this.getMeta(),o=r.dataset._model,s=a.chartArea,l=r.data||[];function u(t,e,n){return Math.max(Math.min(t,n),e)}if(o.spanGaps&&(l=l.filter((function(t){return!t._model.skip}))),"monotone"===o.cubicInterpolationMode)H.splineCurveMonotone(l);else for(t=0,e=l.length;t<e;++t)n=l[t]._model,i=H.splineCurve(H.previousItem(l,t)._model,n,H.nextItem(l,t)._model,o.tension),n.controlPointPreviousX=i.previous.x,n.controlPointPreviousY=i.previous.y,n.controlPointNextX=i.next.x,n.controlPointNextY=i.next.y;if(a.options.elements.line.capBezierPoints)for(t=0,e=l.length;t<e;++t)n=l[t]._model,Ht(n,s)&&(t>0&&Ht(l[t-1]._model,s)&&(n.controlPointPreviousX=u(n.controlPointPreviousX,s.left,s.right),n.controlPointPreviousY=u(n.controlPointPreviousY,s.top,s.bottom)),t<l.length-1&&Ht(l[t+1]._model,s)&&(n.controlPointNextX=u(n.controlPointNextX,s.left,s.right),n.controlPointNextY=u(n.controlPointNextY,s.top,s.bottom)))},draw:function(){var t,e=this.chart,n=this.getMeta(),i=n.data||[],a=e.chartArea,r=e.canvas,o=0,s=i.length;for(this._showLine&&(t=n.dataset._model.clip,H.canvas.clipArea(e.ctx,{left:!1===t.left?0:a.left-t.left,right:!1===t.right?r.width:a.right+t.right,top:!1===t.top?0:a.top-t.top,bottom:!1===t.bottom?r.height:a.bottom+t.bottom}),n.dataset.draw(),H.canvas.unclipArea(e.ctx));o<s;++o)i[o].draw(a)},setHoverStyle:function(t){var e=t._model,n=t._options,i=H.getHoverColor;t.$previousStyle={backgroundColor:e.backgroundColor,borderColor:e.borderColor,borderWidth:e.borderWidth,radius:e.radius},e.backgroundColor=Et(n.hoverBackgroundColor,i(n.backgroundColor)),e.borderColor=Et(n.hoverBorderColor,i(n.borderColor)),e.borderWidth=Et(n.hoverBorderWidth,n.borderWidth),e.radius=Et(n.hoverRadius,n.radius)}}),qt=H.options.resolve;W._set("polarArea",{scale:{type:"radialLinear",angleLines:{display:!1},gridLines:{circular:!0},pointLabels:{display:!1},ticks:{beginAtZero:!0}},animation:{animateRotate:!0,animateScale:!0},startAngle:-.5*Math.PI,legendCallback:function(t){var e,n,i,a=document.createElement("ul"),r=t.data,o=r.datasets,s=r.labels;if(a.setAttribute("class",t.id+"-legend"),o.length)for(e=0,n=o[0].data.length;e<n;++e)(i=a.appendChild(document.createElement("li"))).appendChild(document.createElement("span")).style.backgroundColor=o[0].backgroundColor[e],s[e]&&i.appendChild(document.createTextNode(s[e]));return a.outerHTML},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map((function(n,i){var a=t.getDatasetMeta(0),r=a.controller.getStyle(i);return{text:n,fillStyle:r.backgroundColor,strokeStyle:r.borderColor,lineWidth:r.borderWidth,hidden:isNaN(e.datasets[0].data[i])||a.data[i].hidden,index:i}})):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n<i;++n)(a=o.getDatasetMeta(n)).data[r].hidden=!a.data[r].hidden;o.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}});var Zt=it.extend({dataElementType:wt.Arc,linkScales:H.noop,_dataElementOptions:["backgroundColor","borderColor","borderWidth","borderAlign","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth"],_getIndexScaleId:function(){return this.chart.scale.id},_getValueScaleId:function(){return this.chart.scale.id},update:function(t){var e,n,i,a=this,r=a.getDataset(),o=a.getMeta(),s=a.chart.options.startAngle||0,l=a._starts=[],u=a._angles=[],d=o.data;for(a._updateRadius(),o.count=a.countVisibleElements(),e=0,n=r.data.length;e<n;e++)l[e]=s,i=a._computeAngle(e),u[e]=i,s+=i;for(e=0,n=d.length;e<n;++e)d[e]._options=a._resolveDataElementOptions(d[e],e),a.updateElement(d[e],e,t)},_updateRadius:function(){var t=this,e=t.chart,n=e.chartArea,i=e.options,a=Math.min(n.right-n.left,n.bottom-n.top);e.outerRadius=Math.max(a/2,0),e.innerRadius=Math.max(i.cutoutPercentage?e.outerRadius/100*i.cutoutPercentage:1,0),e.radiusLength=(e.outerRadius-e.innerRadius)/e.getVisibleDatasetCount(),t.outerRadius=e.outerRadius-e.radiusLength*t.index,t.innerRadius=t.outerRadius-e.radiusLength},updateElement:function(t,e,n){var i=this,a=i.chart,r=i.getDataset(),o=a.options,s=o.animation,l=a.scale,u=a.data.labels,d=l.xCenter,h=l.yCenter,c=o.startAngle,f=t.hidden?0:l.getDistanceFromCenterForValue(r.data[e]),g=i._starts[e],m=g+(t.hidden?0:i._angles[e]),p=s.animateScale?0:l.getDistanceFromCenterForValue(r.data[e]),v=t._options||{};H.extend(t,{_datasetIndex:i.index,_index:e,_scale:l,_model:{backgroundColor:v.backgroundColor,borderColor:v.borderColor,borderWidth:v.borderWidth,borderAlign:v.borderAlign,x:d,y:h,innerRadius:0,outerRadius:n?p:f,startAngle:n&&s.animateRotate?c:g,endAngle:n&&s.animateRotate?c:m,label:H.valueAtIndexOrDefault(u,e,u[e])}}),t.pivot()},countVisibleElements:function(){var t=this.getDataset(),e=this.getMeta(),n=0;return H.each(e.data,(function(e,i){isNaN(t.data[i])||e.hidden||n++})),n},setHoverStyle:function(t){var e=t._model,n=t._options,i=H.getHoverColor,a=H.valueOrDefault;t.$previousStyle={backgroundColor:e.backgroundColor,borderColor:e.borderColor,borderWidth:e.borderWidth},e.backgroundColor=a(n.hoverBackgroundColor,i(n.backgroundColor)),e.borderColor=a(n.hoverBorderColor,i(n.borderColor)),e.borderWidth=a(n.hoverBorderWidth,n.borderWidth)},_computeAngle:function(t){var e=this,n=this.getMeta().count,i=e.getDataset(),a=e.getMeta();if(isNaN(i.data[t])||a.data[t].hidden)return 0;var r={chart:e.chart,dataIndex:t,dataset:i,datasetIndex:e.index};return qt([e.chart.options.elements.arc.angle,2*Math.PI/n],r,t)}});W._set("pie",H.clone(W.doughnut)),W._set("pie",{cutoutPercentage:0});var $t=Yt,Xt=H.valueOrDefault;W._set("radar",{spanGaps:!1,scale:{type:"radialLinear"},elements:{line:{fill:"start",tension:0}}});var Kt=it.extend({datasetElementType:wt.Line,dataElementType:wt.Point,linkScales:H.noop,_datasetElementOptions:["backgroundColor","borderWidth","borderColor","borderCapStyle","borderDash","borderDashOffset","borderJoinStyle","fill"],_dataElementOptions:{backgroundColor:"pointBackgroundColor",borderColor:"pointBorderColor",borderWidth:"pointBorderWidth",hitRadius:"pointHitRadius",hoverBackgroundColor:"pointHoverBackgroundColor",hoverBorderColor:"pointHoverBorderColor",hoverBorderWidth:"pointHoverBorderWidth",hoverRadius:"pointHoverRadius",pointStyle:"pointStyle",radius:"pointRadius",rotation:"pointRotation"},_getIndexScaleId:function(){return this.chart.scale.id},_getValueScaleId:function(){return this.chart.scale.id},update:function(t){var e,n,i=this,a=i.getMeta(),r=a.dataset,o=a.data||[],s=i.chart.scale,l=i._config;for(void 0!==l.tension&&void 0===l.lineTension&&(l.lineTension=l.tension),r._scale=s,r._datasetIndex=i.index,r._children=o,r._loop=!0,r._model=i._resolveDatasetElementOptions(r),r.pivot(),e=0,n=o.length;e<n;++e)i.updateElement(o[e],e,t);for(i.updateBezierControlPoints(),e=0,n=o.length;e<n;++e)o[e].pivot()},updateElement:function(t,e,n){var i=this,a=t.custom||{},r=i.getDataset(),o=i.chart.scale,s=o.getPointPositionForValue(e,r.data[e]),l=i._resolveDataElementOptions(t,e),u=i.getMeta().dataset._model,d=n?o.xCenter:s.x,h=n?o.yCenter:s.y;t._scale=o,t._options=l,t._datasetIndex=i.index,t._index=e,t._model={x:d,y:h,skip:a.skip||isNaN(d)||isNaN(h),radius:l.radius,pointStyle:l.pointStyle,rotation:l.rotation,backgroundColor:l.backgroundColor,borderColor:l.borderColor,borderWidth:l.borderWidth,tension:Xt(a.tension,u?u.tension:0),hitRadius:l.hitRadius}},_resolveDatasetElementOptions:function(){var t=this,e=t._config,n=t.chart.options,i=it.prototype._resolveDatasetElementOptions.apply(t,arguments);return i.spanGaps=Xt(e.spanGaps,n.spanGaps),i.tension=Xt(e.lineTension,n.elements.line.tension),i},updateBezierControlPoints:function(){var t,e,n,i,a=this.getMeta(),r=this.chart.chartArea,o=a.data||[];function s(t,e,n){return Math.max(Math.min(t,n),e)}for(a.dataset._model.spanGaps&&(o=o.filter((function(t){return!t._model.skip}))),t=0,e=o.length;t<e;++t)n=o[t]._model,i=H.splineCurve(H.previousItem(o,t,!0)._model,n,H.nextItem(o,t,!0)._model,n.tension),n.controlPointPreviousX=s(i.previous.x,r.left,r.right),n.controlPointPreviousY=s(i.previous.y,r.top,r.bottom),n.controlPointNextX=s(i.next.x,r.left,r.right),n.controlPointNextY=s(i.next.y,r.top,r.bottom)},setHoverStyle:function(t){var e=t._model,n=t._options,i=H.getHoverColor;t.$previousStyle={backgroundColor:e.backgroundColor,borderColor:e.borderColor,borderWidth:e.borderWidth,radius:e.radius},e.backgroundColor=Xt(n.hoverBackgroundColor,i(n.backgroundColor)),e.borderColor=Xt(n.hoverBorderColor,i(n.borderColor)),e.borderWidth=Xt(n.hoverBorderWidth,n.borderWidth),e.radius=Xt(n.hoverRadius,n.radius)}});W._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),W._set("global",{datasets:{scatter:{showLine:!1}}});var Jt={bar:Ot,bubble:It,doughnut:Yt,horizontalBar:zt,line:Gt,polarArea:Zt,pie:$t,radar:Kt,scatter:Gt};function Qt(t,e){return t.native?{x:t.x,y:t.y}:H.getRelativePosition(t,e)}function te(t,e){var n,i,a,r,o,s,l=t._getSortedVisibleDatasetMetas();for(i=0,r=l.length;i<r;++i)for(a=0,o=(n=l[i].data).length;a<o;++a)(s=n[a])._view.skip||e(s)}function ee(t,e){var n=[];return te(t,(function(t){t.inRange(e.x,e.y)&&n.push(t)})),n}function ne(t,e,n,i){var a=Number.POSITIVE_INFINITY,r=[];return te(t,(function(t){if(!n||t.inRange(e.x,e.y)){var o=t.getCenterPoint(),s=i(e,o);s<a?(r=[t],a=s):s===a&&r.push(t)}})),r}function ie(t){var e=-1!==t.indexOf("x"),n=-1!==t.indexOf("y");return function(t,i){var a=e?Math.abs(t.x-i.x):0,r=n?Math.abs(t.y-i.y):0;return Math.sqrt(Math.pow(a,2)+Math.pow(r,2))}}function ae(t,e,n){var i=Qt(e,t);n.axis=n.axis||"x";var a=ie(n.axis),r=n.intersect?ee(t,i):ne(t,i,!1,a),o=[];return r.length?(t._getSortedVisibleDatasetMetas().forEach((function(t){var e=t.data[r[0]._index];e&&!e._view.skip&&o.push(e)})),o):[]}var re={modes:{single:function(t,e){var n=Qt(e,t),i=[];return te(t,(function(t){if(t.inRange(n.x,n.y))return i.push(t),i})),i.slice(0,1)},label:ae,index:ae,dataset:function(t,e,n){var i=Qt(e,t);n.axis=n.axis||"xy";var a=ie(n.axis),r=n.intersect?ee(t,i):ne(t,i,!1,a);return r.length>0&&(r=t.getDatasetMeta(r[0]._datasetIndex).data),r},"x-axis":function(t,e){return ae(t,e,{intersect:!1})},point:function(t,e){return ee(t,Qt(e,t))},nearest:function(t,e,n){var i=Qt(e,t);n.axis=n.axis||"xy";var a=ie(n.axis);return ne(t,i,n.intersect,a)},x:function(t,e,n){var i=Qt(e,t),a=[],r=!1;return te(t,(function(t){t.inXRange(i.x)&&a.push(t),t.inRange(i.x,i.y)&&(r=!0)})),n.intersect&&!r&&(a=[]),a},y:function(t,e,n){var i=Qt(e,t),a=[],r=!1;return te(t,(function(t){t.inYRange(i.y)&&a.push(t),t.inRange(i.x,i.y)&&(r=!0)})),n.intersect&&!r&&(a=[]),a}}},oe=H.extend;function se(t,e){return H.where(t,(function(t){return t.pos===e}))}function le(t,e){return t.sort((function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i.index-a.index:i.weight-a.weight}))}function ue(t,e,n,i){return Math.max(t[n],e[n])+Math.max(t[i],e[i])}function de(t,e,n){var i,a,r=n.box,o=t.maxPadding;if(n.size&&(t[n.pos]-=n.size),n.size=n.horizontal?r.height:r.width,t[n.pos]+=n.size,r.getPadding){var s=r.getPadding();o.top=Math.max(o.top,s.top),o.left=Math.max(o.left,s.left),o.bottom=Math.max(o.bottom,s.bottom),o.right=Math.max(o.right,s.right)}if(i=e.outerWidth-ue(o,t,"left","right"),a=e.outerHeight-ue(o,t,"top","bottom"),i!==t.w||a!==t.h)return t.w=i,t.h=a,n.horizontal?i!==t.w:a!==t.h}function he(t,e){var n=e.maxPadding;function i(t){var i={left:0,top:0,right:0,bottom:0};return t.forEach((function(t){i[t]=Math.max(e[t],n[t])})),i}return i(t?["left","right"]:["top","bottom"])}function ce(t,e,n){var i,a,r,o,s,l,u=[];for(i=0,a=t.length;i<a;++i)(o=(r=t[i]).box).update(r.width||e.w,r.height||e.h,he(r.horizontal,e)),de(e,n,r)&&(l=!0,u.length&&(s=!0)),o.fullWidth||u.push(r);return s&&ce(u,e,n)||l}function fe(t,e,n){var i,a,r,o,s=n.padding,l=e.x,u=e.y;for(i=0,a=t.length;i<a;++i)o=(r=t[i]).box,r.horizontal?(o.left=o.fullWidth?s.left:e.left,o.right=o.fullWidth?n.outerWidth-s.right:e.left+e.w,o.top=u,o.bottom=u+o.height,o.width=o.right-o.left,u=o.bottom):(o.left=l,o.right=l+o.width,o.top=e.top,o.bottom=e.top+e.h,o.height=o.bottom-o.top,l=o.right);e.x=l,e.y=u}W._set("global",{layout:{padding:{top:0,right:0,bottom:0,left:0}}});var ge,me={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,e._layers=e._layers||function(){return[{z:0,draw:function(){e.draw.apply(e,arguments)}}]},t.boxes.push(e)},removeBox:function(t,e){var n=t.boxes?t.boxes.indexOf(e):-1;-1!==n&&t.boxes.splice(n,1)},configure:function(t,e,n){for(var i,a=["fullWidth","position","weight"],r=a.length,o=0;o<r;++o)i=a[o],n.hasOwnProperty(i)&&(e[i]=n[i])},update:function(t,e,n){if(t){var i=t.options.layout||{},a=H.options.toPadding(i.padding),r=e-a.width,o=n-a.height,s=function(t){var e=function(t){var e,n,i,a=[];for(e=0,n=(t||[]).length;e<n;++e)i=t[e],a.push({index:e,box:i,pos:i.position,horizontal:i.isHorizontal(),weight:i.weight});return a}(t),n=le(se(e,"left"),!0),i=le(se(e,"right")),a=le(se(e,"top"),!0),r=le(se(e,"bottom"));return{leftAndTop:n.concat(a),rightAndBottom:i.concat(r),chartArea:se(e,"chartArea"),vertical:n.concat(i),horizontal:a.concat(r)}}(t.boxes),l=s.vertical,u=s.horizontal,d=Object.freeze({outerWidth:e,outerHeight:n,padding:a,availableWidth:r,vBoxMaxWidth:r/2/l.length,hBoxMaxHeight:o/2}),h=oe({maxPadding:oe({},a),w:r,h:o,x:a.left,y:a.top},a);!function(t,e){var n,i,a;for(n=0,i=t.length;n<i;++n)(a=t[n]).width=a.horizontal?a.box.fullWidth&&e.availableWidth:e.vBoxMaxWidth,a.height=a.horizontal&&e.hBoxMaxHeight}(l.concat(u),d),ce(l,h,d),ce(u,h,d)&&ce(l,h,d),function(t){var e=t.maxPadding;function n(n){var i=Math.max(e[n]-t[n],0);return t[n]+=i,i}t.y+=n("top"),t.x+=n("left"),n("right"),n("bottom")}(h),fe(s.leftAndTop,h,d),h.x+=h.w,h.y+=h.h,fe(s.rightAndBottom,h,d),t.chartArea={left:h.left,top:h.top,right:h.left+h.w,bottom:h.top+h.h},H.each(s.chartArea,(function(e){var n=e.box;oe(n,t.chartArea),n.update(h.w,h.h)}))}}},pe=(ge=Object.freeze({__proto__:null,default:"@keyframes chartjs-render-animation{from{opacity:.99}to{opacity:1}}.chartjs-render-monitor{animation:chartjs-render-animation 1ms}.chartjs-size-monitor,.chartjs-size-monitor-expand,.chartjs-size-monitor-shrink{position:absolute;direction:ltr;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1}.chartjs-size-monitor-expand>div{position:absolute;width:1000000px;height:1000000px;left:0;top:0}.chartjs-size-monitor-shrink>div{position:absolute;width:200%;height:200%;left:0;top:0}"}))&&ge.default||ge,ve="$chartjs",be="chartjs-size-monitor",ye="chartjs-render-monitor",xe="chartjs-render-animation",_e=["animationstart","webkitAnimationStart"],we={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"};function ke(t,e){var n=H.getStyle(t,e),i=n&&n.match(/^(\d+)(\.\d+)?px$/);return i?Number(i[1]):void 0}var Me=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(t){}return t}()&&{passive:!0};function Se(t,e,n){t.addEventListener(e,n,Me)}function De(t,e,n){t.removeEventListener(e,n,Me)}function Ce(t,e,n,i,a){return{type:t,chart:e,native:a||null,x:void 0!==n?n:null,y:void 0!==i?i:null}}function Pe(t){var e=document.createElement("div");return e.className=t||"",e}function Te(t,e,n){var i,a,r,o,s=t[ve]||(t[ve]={}),l=s.resizer=function(t){var e=Pe(be),n=Pe(be+"-expand"),i=Pe(be+"-shrink");n.appendChild(Pe()),i.appendChild(Pe()),e.appendChild(n),e.appendChild(i),e._reset=function(){n.scrollLeft=1e6,n.scrollTop=1e6,i.scrollLeft=1e6,i.scrollTop=1e6};var a=function(){e._reset(),t()};return Se(n,"scroll",a.bind(n,"expand")),Se(i,"scroll",a.bind(i,"shrink")),e}((i=function(){if(s.resizer){var i=n.options.maintainAspectRatio&&t.parentNode,a=i?i.clientWidth:0;e(Ce("resize",n)),i&&i.clientWidth<a&&n.canvas&&e(Ce("resize",n))}},r=!1,o=[],function(){o=Array.prototype.slice.call(arguments),a=a||this,r||(r=!0,H.requestAnimFrame.call(window,(function(){r=!1,i.apply(a,o)})))}));!function(t,e){var n=t[ve]||(t[ve]={}),i=n.renderProxy=function(t){t.animationName===xe&&e()};H.each(_e,(function(e){Se(t,e,i)})),n.reflow=!!t.offsetParent,t.classList.add(ye)}(t,(function(){if(s.resizer){var e=t.parentNode;e&&e!==l.parentNode&&e.insertBefore(l,e.firstChild),l._reset()}}))}function Oe(t){var e=t[ve]||{},n=e.resizer;delete e.resizer,function(t){var e=t[ve]||{},n=e.renderProxy;n&&(H.each(_e,(function(e){De(t,e,n)})),delete e.renderProxy),t.classList.remove(ye)}(t),n&&n.parentNode&&n.parentNode.removeChild(n)}var Ae={disableCSSInjection:!1,_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,_ensureLoaded:function(t){if(!this.disableCSSInjection){var e=t.getRootNode?t.getRootNode():document;!function(t,e){var n=t[ve]||(t[ve]={});if(!n.containsStyles){n.containsStyles=!0,e="/* Chart.js */\n"+e;var i=document.createElement("style");i.setAttribute("type","text/css"),i.appendChild(document.createTextNode(e)),t.appendChild(i)}}(e.host?e:document.head,pe)}},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var n=t&&t.getContext&&t.getContext("2d");return n&&n.canvas===t?(this._ensureLoaded(t),function(t,e){var n=t.style,i=t.getAttribute("height"),a=t.getAttribute("width");if(t[ve]={initial:{height:i,width:a,style:{display:n.display,height:n.height,width:n.width}}},n.display=n.display||"block",null===a||""===a){var r=ke(t,"width");void 0!==r&&(t.width=r)}if(null===i||""===i)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var o=ke(t,"height");void 0!==r&&(t.height=o)}}(t,e),n):null},releaseContext:function(t){var e=t.canvas;if(e[ve]){var n=e[ve].initial;["height","width"].forEach((function(t){var i=n[t];H.isNullOrUndef(i)?e.removeAttribute(t):e.setAttribute(t,i)})),H.each(n.style||{},(function(t,n){e.style[n]=t})),e.width=e.width,delete e[ve]}},addEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=n[ve]||(n[ve]={});Se(i,e,(a.proxies||(a.proxies={}))[t.id+"_"+e]=function(e){n(function(t,e){var n=we[t.type]||t.type,i=H.getRelativePosition(t,e);return Ce(n,e,i.x,i.y,t)}(e,t))})}else Te(i,n,t)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n[ve]||{}).proxies||{})[t.id+"_"+e];a&&De(i,e,a)}else Oe(i)}};H.addEvent=Se,H.removeEvent=De;var Fe=Ae._enabled?Ae:{acquireContext:function(t){return t&&t.canvas&&(t=t.canvas),t&&t.getContext("2d")||null}},Ie=H.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},Fe);W._set("global",{plugins:{}});var Le={_plugins:[],_cacheId:0,register:function(t){var e=this._plugins;[].concat(t).forEach((function(t){-1===e.indexOf(t)&&e.push(t)})),this._cacheId++},unregister:function(t){var e=this._plugins;[].concat(t).forEach((function(t){var n=e.indexOf(t);-1!==n&&e.splice(n,1)})),this._cacheId++},clear:function(){this._plugins=[],this._cacheId++},count:function(){return this._plugins.length},getAll:function(){return this._plugins},notify:function(t,e,n){var i,a,r,o,s,l=this.descriptors(t),u=l.length;for(i=0;i<u;++i)if("function"==typeof(s=(r=(a=l[i]).plugin)[e])&&((o=[t].concat(n||[])).push(a.options),!1===s.apply(r,o)))return!1;return!0},descriptors:function(t){var e=t.$plugins||(t.$plugins={});if(e.id===this._cacheId)return e.descriptors;var n=[],i=[],a=t&&t.config||{},r=a.options&&a.options.plugins||{};return this._plugins.concat(a.plugins||[]).forEach((function(t){if(-1===n.indexOf(t)){var e=t.id,a=r[e];!1!==a&&(!0===a&&(a=H.clone(W.global.plugins[e])),n.push(t),i.push({plugin:t,options:a||{}}))}})),e.descriptors=i,e.id=this._cacheId,i},_invalidate:function(t){delete t.$plugins}},Re={constructors:{},defaults:{},registerScaleType:function(t,e,n){this.constructors[t]=e,this.defaults[t]=H.clone(n)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(t){return this.defaults.hasOwnProperty(t)?H.merge({},[W.scale,this.defaults[t]]):{}},updateScaleDefaults:function(t,e){this.defaults.hasOwnProperty(t)&&(this.defaults[t]=H.extend(this.defaults[t],e))},addScalesToLayout:function(t){H.each(t.scales,(function(e){e.fullWidth=e.options.fullWidth,e.position=e.options.position,e.weight=e.options.weight,me.addBox(t,e)}))}},Ne=H.valueOrDefault,We=H.rtl.getRtlAdapter;W._set("global",{tooltips:{enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleFontColor:"#fff",titleAlign:"left",bodySpacing:2,bodyFontColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerFontColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:H.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var r=t[0];r.label?n=r.label:r.xLabel?n=r.xLabel:a>0&&r.index<a&&(n=i[r.index])}return n},afterTitle:H.noop,beforeBody:H.noop,beforeLabel:H.noop,label:function(t,e){var n=e.datasets[t.datasetIndex].label||"";return n&&(n+=": "),H.isNullOrUndef(t.value)?n+=t.yLabel:n+=t.value,n},labelColor:function(t,e){var n=e.getDatasetMeta(t.datasetIndex).data[t.index]._view;return{borderColor:n.borderColor,backgroundColor:n.backgroundColor}},labelTextColor:function(){return this._options.bodyFontColor},afterLabel:H.noop,afterBody:H.noop,beforeFooter:H.noop,footer:H.noop,afterFooter:H.noop}}});var Ye={average:function(t){if(!t.length)return!1;var e,n,i=0,a=0,r=0;for(e=0,n=t.length;e<n;++e){var o=t[e];if(o&&o.hasValue()){var s=o.tooltipPosition();i+=s.x,a+=s.y,++r}}return{x:i/r,y:a/r}},nearest:function(t,e){var n,i,a,r=e.x,o=e.y,s=Number.POSITIVE_INFINITY;for(n=0,i=t.length;n<i;++n){var l=t[n];if(l&&l.hasValue()){var u=l.getCenterPoint(),d=H.distanceBetweenPoints(e,u);d<s&&(s=d,a=l)}}if(a){var h=a.tooltipPosition();r=h.x,o=h.y}return{x:r,y:o}}};function ze(t,e){return e&&(H.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function Ee(t){return("string"==typeof t||t instanceof String)&&t.indexOf("\n")>-1?t.split("\n"):t}function Ve(t){var e=W.global;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,rtl:t.rtl,textDirection:t.textDirection,bodyFontColor:t.bodyFontColor,_bodyFontFamily:Ne(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:Ne(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:Ne(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:Ne(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:Ne(t.titleFontStyle,e.defaultFontStyle),titleFontSize:Ne(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:Ne(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:Ne(t.footerFontStyle,e.defaultFontStyle),footerFontSize:Ne(t.footerFontSize,e.defaultFontSize),_footerAlign:t.footerAlign,footerSpacing:t.footerSpacing,footerMarginTop:t.footerMarginTop,caretSize:t.caretSize,cornerRadius:t.cornerRadius,backgroundColor:t.backgroundColor,opacity:0,legendColorBackground:t.multiKeyBackground,displayColors:t.displayColors,borderColor:t.borderColor,borderWidth:t.borderWidth}}function He(t,e){return"center"===e?t.x+t.width/2:"right"===e?t.x+t.width-t.xPadding:t.x+t.xPadding}function Be(t){return ze([],Ee(t))}var je=$.extend({initialize:function(){this._model=Ve(this._options),this._lastActive=[]},getTitle:function(){var t=this,e=t._options,n=e.callbacks,i=n.beforeTitle.apply(t,arguments),a=n.title.apply(t,arguments),r=n.afterTitle.apply(t,arguments),o=[];return o=ze(o,Ee(i)),o=ze(o,Ee(a)),o=ze(o,Ee(r))},getBeforeBody:function(){return Be(this._options.callbacks.beforeBody.apply(this,arguments))},getBody:function(t,e){var n=this,i=n._options.callbacks,a=[];return H.each(t,(function(t){var r={before:[],lines:[],after:[]};ze(r.before,Ee(i.beforeLabel.call(n,t,e))),ze(r.lines,i.label.call(n,t,e)),ze(r.after,Ee(i.afterLabel.call(n,t,e))),a.push(r)})),a},getAfterBody:function(){return Be(this._options.callbacks.afterBody.apply(this,arguments))},getFooter:function(){var t=this,e=t._options.callbacks,n=e.beforeFooter.apply(t,arguments),i=e.footer.apply(t,arguments),a=e.afterFooter.apply(t,arguments),r=[];return r=ze(r,Ee(n)),r=ze(r,Ee(i)),r=ze(r,Ee(a))},update:function(t){var e,n,i,a,r,o,s,l,u,d,h=this,c=h._options,f=h._model,g=h._model=Ve(c),m=h._active,p=h._data,v={xAlign:f.xAlign,yAlign:f.yAlign},b={x:f.x,y:f.y},y={width:f.width,height:f.height},x={x:f.caretX,y:f.caretY};if(m.length){g.opacity=1;var _=[],w=[];x=Ye[c.position].call(h,m,h._eventPosition);var k=[];for(e=0,n=m.length;e<n;++e)k.push((i=m[e],a=void 0,r=void 0,o=void 0,s=void 0,l=void 0,u=void 0,d=void 0,a=i._xScale,r=i._yScale||i._scale,o=i._index,s=i._datasetIndex,l=i._chart.getDatasetMeta(s).controller,u=l._getIndexScale(),d=l._getValueScale(),{xLabel:a?a.getLabelForIndex(o,s):"",yLabel:r?r.getLabelForIndex(o,s):"",label:u?""+u.getLabelForIndex(o,s):"",value:d?""+d.getLabelForIndex(o,s):"",index:o,datasetIndex:s,x:i._model.x,y:i._model.y}));c.filter&&(k=k.filter((function(t){return c.filter(t,p)}))),c.itemSort&&(k=k.sort((function(t,e){return c.itemSort(t,e,p)}))),H.each(k,(function(t){_.push(c.callbacks.labelColor.call(h,t,h._chart)),w.push(c.callbacks.labelTextColor.call(h,t,h._chart))})),g.title=h.getTitle(k,p),g.beforeBody=h.getBeforeBody(k,p),g.body=h.getBody(k,p),g.afterBody=h.getAfterBody(k,p),g.footer=h.getFooter(k,p),g.x=x.x,g.y=x.y,g.caretPadding=c.caretPadding,g.labelColors=_,g.labelTextColors=w,g.dataPoints=k,y=function(t,e){var n=t._chart.ctx,i=2*e.yPadding,a=0,r=e.body,o=r.reduce((function(t,e){return t+e.before.length+e.lines.length+e.after.length}),0);o+=e.beforeBody.length+e.afterBody.length;var s=e.title.length,l=e.footer.length,u=e.titleFontSize,d=e.bodyFontSize,h=e.footerFontSize;i+=s*u,i+=s?(s-1)*e.titleSpacing:0,i+=s?e.titleMarginBottom:0,i+=o*d,i+=o?(o-1)*e.bodySpacing:0,i+=l?e.footerMarginTop:0,i+=l*h,i+=l?(l-1)*e.footerSpacing:0;var c=0,f=function(t){a=Math.max(a,n.measureText(t).width+c)};return n.font=H.fontString(u,e._titleFontStyle,e._titleFontFamily),H.each(e.title,f),n.font=H.fontString(d,e._bodyFontStyle,e._bodyFontFamily),H.each(e.beforeBody.concat(e.afterBody),f),c=e.displayColors?d+2:0,H.each(r,(function(t){H.each(t.before,f),H.each(t.lines,f),H.each(t.after,f)})),c=0,n.font=H.fontString(h,e._footerFontStyle,e._footerFontFamily),H.each(e.footer,f),{width:a+=2*e.xPadding,height:i}}(this,g),b=function(t,e,n,i){var a=t.x,r=t.y,o=t.caretSize,s=t.caretPadding,l=t.cornerRadius,u=n.xAlign,d=n.yAlign,h=o+s,c=l+s;return"right"===u?a-=e.width:"center"===u&&((a-=e.width/2)+e.width>i.width&&(a=i.width-e.width),a<0&&(a=0)),"top"===d?r+=h:r-="bottom"===d?e.height+h:e.height/2,"center"===d?"left"===u?a+=h:"right"===u&&(a-=h):"left"===u?a-=c:"right"===u&&(a+=c),{x:a,y:r}}(g,y,v=function(t,e){var n,i,a,r,o,s=t._model,l=t._chart,u=t._chart.chartArea,d="center",h="center";s.y<e.height?h="top":s.y>l.height-e.height&&(h="bottom");var c=(u.left+u.right)/2,f=(u.top+u.bottom)/2;"center"===h?(n=function(t){return t<=c},i=function(t){return t>c}):(n=function(t){return t<=e.width/2},i=function(t){return t>=l.width-e.width/2}),a=function(t){return t+e.width+s.caretSize+s.caretPadding>l.width},r=function(t){return t-e.width-s.caretSize-s.caretPadding<0},o=function(t){return t<=f?"top":"bottom"},n(s.x)?(d="left",a(s.x)&&(d="center",h=o(s.y))):i(s.x)&&(d="right",r(s.x)&&(d="center",h=o(s.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:d,yAlign:g.yAlign?g.yAlign:h}}(this,y),h._chart)}else g.opacity=0;return g.xAlign=v.xAlign,g.yAlign=v.yAlign,g.x=b.x,g.y=b.y,g.width=y.width,g.height=y.height,g.caretX=x.x,g.caretY=x.y,h._model=g,t&&c.custom&&c.custom.call(h,g),h},drawCaret:function(t,e){var n=this._chart.ctx,i=this._view,a=this.getCaretPosition(t,e,i);n.lineTo(a.x1,a.y1),n.lineTo(a.x2,a.y2),n.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,n){var i,a,r,o,s,l,u=n.caretSize,d=n.cornerRadius,h=n.xAlign,c=n.yAlign,f=t.x,g=t.y,m=e.width,p=e.height;if("center"===c)s=g+p/2,"left"===h?(a=(i=f)-u,r=i,o=s+u,l=s-u):(a=(i=f+m)+u,r=i,o=s-u,l=s+u);else if("left"===h?(i=(a=f+d+u)-u,r=a+u):"right"===h?(i=(a=f+m-d-u)-u,r=a+u):(i=(a=n.caretX)-u,r=a+u),"top"===c)s=(o=g)-u,l=o;else{s=(o=g+p)+u,l=o;var v=r;r=i,i=v}return{x1:i,x2:a,x3:r,y1:o,y2:s,y3:l}},drawTitle:function(t,e,n){var i,a,r,o=e.title,s=o.length;if(s){var l=We(e.rtl,e.x,e.width);for(t.x=He(e,e._titleAlign),n.textAlign=l.textAlign(e._titleAlign),n.textBaseline="middle",i=e.titleFontSize,a=e.titleSpacing,n.fillStyle=e.titleFontColor,n.font=H.fontString(i,e._titleFontStyle,e._titleFontFamily),r=0;r<s;++r)n.fillText(o[r],l.x(t.x),t.y+i/2),t.y+=i+a,r+1===s&&(t.y+=e.titleMarginBottom-a)}},drawBody:function(t,e,n){var i,a,r,o,s,l,u,d,h=e.bodyFontSize,c=e.bodySpacing,f=e._bodyAlign,g=e.body,m=e.displayColors,p=0,v=m?He(e,"left"):0,b=We(e.rtl,e.x,e.width),y=function(e){n.fillText(e,b.x(t.x+p),t.y+h/2),t.y+=h+c},x=b.textAlign(f);for(n.textAlign=f,n.textBaseline="middle",n.font=H.fontString(h,e._bodyFontStyle,e._bodyFontFamily),t.x=He(e,x),n.fillStyle=e.bodyFontColor,H.each(e.beforeBody,y),p=m&&"right"!==x?"center"===f?h/2+1:h+2:0,s=0,u=g.length;s<u;++s){for(i=g[s],a=e.labelTextColors[s],r=e.labelColors[s],n.fillStyle=a,H.each(i.before,y),l=0,d=(o=i.lines).length;l<d;++l){if(m){var _=b.x(v);n.fillStyle=e.legendColorBackground,n.fillRect(b.leftForLtr(_,h),t.y,h,h),n.lineWidth=1,n.strokeStyle=r.borderColor,n.strokeRect(b.leftForLtr(_,h),t.y,h,h),n.fillStyle=r.backgroundColor,n.fillRect(b.leftForLtr(b.xPlus(_,1),h-2),t.y+1,h-2,h-2),n.fillStyle=a}y(o[l])}H.each(i.after,y)}p=0,H.each(e.afterBody,y),t.y-=c},drawFooter:function(t,e,n){var i,a,r=e.footer,o=r.length;if(o){var s=We(e.rtl,e.x,e.width);for(t.x=He(e,e._footerAlign),t.y+=e.footerMarginTop,n.textAlign=s.textAlign(e._footerAlign),n.textBaseline="middle",i=e.footerFontSize,n.fillStyle=e.footerFontColor,n.font=H.fontString(i,e._footerFontStyle,e._footerFontFamily),a=0;a<o;++a)n.fillText(r[a],s.x(t.x),t.y+i/2),t.y+=i+e.footerSpacing}},drawBackground:function(t,e,n,i){n.fillStyle=e.backgroundColor,n.strokeStyle=e.borderColor,n.lineWidth=e.borderWidth;var a=e.xAlign,r=e.yAlign,o=t.x,s=t.y,l=i.width,u=i.height,d=e.cornerRadius;n.beginPath(),n.moveTo(o+d,s),"top"===r&&this.drawCaret(t,i),n.lineTo(o+l-d,s),n.quadraticCurveTo(o+l,s,o+l,s+d),"center"===r&&"right"===a&&this.drawCaret(t,i),n.lineTo(o+l,s+u-d),n.quadraticCurveTo(o+l,s+u,o+l-d,s+u),"bottom"===r&&this.drawCaret(t,i),n.lineTo(o+d,s+u),n.quadraticCurveTo(o,s+u,o,s+u-d),"center"===r&&"left"===a&&this.drawCaret(t,i),n.lineTo(o,s+d),n.quadraticCurveTo(o,s,o+d,s),n.closePath(),n.fill(),e.borderWidth>0&&n.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},i={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,r=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&r&&(t.save(),t.globalAlpha=a,this.drawBackground(i,e,t,n),i.y+=e.yPadding,H.rtl.overrideTextDirection(t,e.textDirection),this.drawTitle(i,e,t),this.drawBody(i,e,t),this.drawFooter(i,e,t),H.rtl.restoreTextDirection(t,e.textDirection),t.restore())}},handleEvent:function(t){var e,n=this,i=n._options;return n._lastActive=n._lastActive||[],"mouseout"===t.type?n._active=[]:(n._active=n._chart.getElementsAtEventForMode(t,i.mode,i),i.reverse&&n._active.reverse()),(e=!H.arrayEquals(n._active,n._lastActive))&&(n._lastActive=n._active,(i.enabled||i.custom)&&(n._eventPosition={x:t.x,y:t.y},n.update(!0),n.pivot())),e}}),Ue=Ye,Ge=je;Ge.positioners=Ue;var qe=H.valueOrDefault;function Ze(){return H.merge({},[].slice.call(arguments),{merger:function(t,e,n,i){if("xAxes"===t||"yAxes"===t){var a,r,o,s=n[t].length;for(e[t]||(e[t]=[]),a=0;a<s;++a)o=n[t][a],r=qe(o.type,"xAxes"===t?"category":"linear"),a>=e[t].length&&e[t].push({}),!e[t][a].type||o.type&&o.type!==e[t][a].type?H.merge(e[t][a],[Re.getScaleDefaults(r),o]):H.merge(e[t][a],o)}else H._merger(t,e,n,i)}})}function $e(){return H.merge({},[].slice.call(arguments),{merger:function(t,e,n,i){var a=e[t]||{},r=n[t];"scales"===t?e[t]=Ze(a,r):"scale"===t?e[t]=H.merge(a,[Re.getScaleDefaults(r.type),r]):H._merger(t,e,n,i)}})}function Xe(t){var e=t.options;H.each(t.scales,(function(e){me.removeBox(t,e)})),e=$e(W.global,W[t.config.type],e),t.options=t.config.options=e,t.ensureScalesHaveIDs(),t.buildOrUpdateScales(),t.tooltip._options=e.tooltips,t.tooltip.initialize()}function Ke(t,e,n){var i,a=function(t){return t.id===i};do{i=e+n++}while(H.findIndex(t,a)>=0);return i}function Je(t){return"top"===t||"bottom"===t}function Qe(t,e){return function(n,i){return n[t]===i[t]?n[e]-i[e]:n[t]-i[t]}}W._set("global",{elements:{},events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,maintainAspectRatio:!0,responsive:!0,responsiveAnimationDuration:0});var tn=function(t,e){return this.construct(t,e),this};H.extend(tn.prototype,{construct:function(t,e){var n=this;e=function(t){var e=(t=t||{}).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=$e(W.global,W[t.type],t.options||{}),t}(e);var i=Ie.acquireContext(t,e),a=i&&i.canvas,r=a&&a.height,o=a&&a.width;n.id=H.uid(),n.ctx=i,n.canvas=a,n.config=e,n.width=o,n.height=r,n.aspectRatio=r?o/r:null,n.options=e.options,n._bufferedRender=!1,n._layers=[],n.chart=n,n.controller=n,tn.instances[n.id]=n,Object.defineProperty(n,"data",{get:function(){return n.config.data},set:function(t){n.config.data=t}}),i&&a?(n.initialize(),n.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return Le.notify(t,"beforeInit"),H.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.initToolTip(),Le.notify(t,"afterInit"),t},clear:function(){return H.canvas.clear(this),this},stop:function(){return J.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,a=n.maintainAspectRatio&&e.aspectRatio||null,r=Math.max(0,Math.floor(H.getMaximumWidth(i))),o=Math.max(0,Math.floor(a?r/a:H.getMaximumHeight(i)));if((e.width!==r||e.height!==o)&&(i.width=e.width=r,i.height=e.height=o,i.style.width=r+"px",i.style.height=o+"px",H.retinaScale(e,n.devicePixelRatio),!t)){var s={width:r,height:o};Le.notify(e,"resize",[s]),n.onResize&&n.onResize(e,s),e.stop(),e.update({duration:n.responsiveAnimationDuration})}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;H.each(e.xAxes,(function(t,n){t.id||(t.id=Ke(e.xAxes,"x-axis-",n))})),H.each(e.yAxes,(function(t,n){t.id||(t.id=Ke(e.yAxes,"y-axis-",n))})),n&&(n.id=n.id||"scale")},buildOrUpdateScales:function(){var t=this,e=t.options,n=t.scales||{},i=[],a=Object.keys(n).reduce((function(t,e){return t[e]=!1,t}),{});e.scales&&(i=i.concat((e.scales.xAxes||[]).map((function(t){return{options:t,dtype:"category",dposition:"bottom"}})),(e.scales.yAxes||[]).map((function(t){return{options:t,dtype:"linear",dposition:"left"}})))),e.scale&&i.push({options:e.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),H.each(i,(function(e){var i=e.options,r=i.id,o=qe(i.type,e.dtype);Je(i.position)!==Je(e.dposition)&&(i.position=e.dposition),a[r]=!0;var s=null;if(r in n&&n[r].type===o)(s=n[r]).options=i,s.ctx=t.ctx,s.chart=t;else{var l=Re.getScaleConstructor(o);if(!l)return;s=new l({id:r,type:o,options:i,ctx:t.ctx,chart:t}),n[s.id]=s}s.mergeTicksOptions(),e.isDefault&&(t.scale=s)})),H.each(a,(function(t,e){t||delete n[e]})),t.scales=n,Re.addScalesToLayout(this)},buildOrUpdateControllers:function(){var t,e,n=this,i=[],a=n.data.datasets;for(t=0,e=a.length;t<e;t++){var r=a[t],o=n.getDatasetMeta(t),s=r.type||n.config.type;if(o.type&&o.type!==s&&(n.destroyDatasetMeta(t),o=n.getDatasetMeta(t)),o.type=s,o.order=r.order||0,o.index=t,o.controller)o.controller.updateIndex(t),o.controller.linkScales();else{var l=Jt[o.type];if(void 0===l)throw new Error('"'+o.type+'" is not a chart type.');o.controller=new l(n,t),i.push(o.controller)}}return i},resetElements:function(){var t=this;H.each(t.data.datasets,(function(e,n){t.getDatasetMeta(n).controller.reset()}),t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(t){var e,n,i=this;if(t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]}),Xe(i),Le._invalidate(i),!1!==Le.notify(i,"beforeUpdate")){i.tooltip._data=i.data;var a=i.buildOrUpdateControllers();for(e=0,n=i.data.datasets.length;e<n;e++)i.getDatasetMeta(e).controller.buildOrUpdateElements();i.updateLayout(),i.options.animation&&i.options.animation.duration&&H.each(a,(function(t){t.reset()})),i.updateDatasets(),i.tooltip.initialize(),i.lastActive=[],Le.notify(i,"afterUpdate"),i._layers.sort(Qe("z","_idx")),i._bufferedRender?i._bufferedRequest={duration:t.duration,easing:t.easing,lazy:t.lazy}:i.render(t)}},updateLayout:function(){var t=this;!1!==Le.notify(t,"beforeLayout")&&(me.update(this,this.width,this.height),t._layers=[],H.each(t.boxes,(function(e){e._configure&&e._configure(),t._layers.push.apply(t._layers,e._layers())}),t),t._layers.forEach((function(t,e){t._idx=e})),Le.notify(t,"afterScaleUpdate"),Le.notify(t,"afterLayout"))},updateDatasets:function(){if(!1!==Le.notify(this,"beforeDatasetsUpdate")){for(var t=0,e=this.data.datasets.length;t<e;++t)this.updateDataset(t);Le.notify(this,"afterDatasetsUpdate")}},updateDataset:function(t){var e=this.getDatasetMeta(t),n={meta:e,index:t};!1!==Le.notify(this,"beforeDatasetUpdate",[n])&&(e.controller._update(),Le.notify(this,"afterDatasetUpdate",[n]))},render:function(t){var e=this;t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]});var n=e.options.animation,i=qe(t.duration,n&&n.duration),a=t.lazy;if(!1!==Le.notify(e,"beforeRender")){var r=function(t){Le.notify(e,"afterRender"),H.callback(n&&n.onComplete,[t],e)};if(n&&i){var o=new K({numSteps:i/16.66,easing:t.easing||n.easing,render:function(t,e){var n=H.easing.effects[e.easing],i=e.currentStep,a=i/e.numSteps;t.draw(n(a),a,i)},onAnimationProgress:n.onProgress,onAnimationComplete:r});J.addAnimation(e,o,i,a)}else e.draw(),r(new K({numSteps:0,chart:e}));return e}},draw:function(t){var e,n,i=this;if(i.clear(),H.isNullOrUndef(t)&&(t=1),i.transition(t),!(i.width<=0||i.height<=0)&&!1!==Le.notify(i,"beforeDraw",[t])){for(n=i._layers,e=0;e<n.length&&n[e].z<=0;++e)n[e].draw(i.chartArea);for(i.drawDatasets(t);e<n.length;++e)n[e].draw(i.chartArea);i._drawTooltip(t),Le.notify(i,"afterDraw",[t])}},transition:function(t){for(var e=0,n=(this.data.datasets||[]).length;e<n;++e)this.isDatasetVisible(e)&&this.getDatasetMeta(e).controller.transition(t);this.tooltip.transition(t)},_getSortedDatasetMetas:function(t){var e,n,i=[];for(e=0,n=(this.data.datasets||[]).length;e<n;++e)t&&!this.isDatasetVisible(e)||i.push(this.getDatasetMeta(e));return i.sort(Qe("order","index")),i},_getSortedVisibleDatasetMetas:function(){return this._getSortedDatasetMetas(!0)},drawDatasets:function(t){var e,n;if(!1!==Le.notify(this,"beforeDatasetsDraw",[t])){for(n=(e=this._getSortedVisibleDatasetMetas()).length-1;n>=0;--n)this.drawDataset(e[n],t);Le.notify(this,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n={meta:t,index:t.index,easingValue:e};!1!==Le.notify(this,"beforeDatasetDraw",[n])&&(t.controller.draw(e),Le.notify(this,"afterDatasetDraw",[n]))},_drawTooltip:function(t){var e=this.tooltip,n={tooltip:e,easingValue:t};!1!==Le.notify(this,"beforeTooltipDraw",[n])&&(e.draw(),Le.notify(this,"afterTooltipDraw",[n]))},getElementAtEvent:function(t){return re.modes.single(this,t)},getElementsAtEvent:function(t){return re.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return re.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,n){var i=re.modes[e];return"function"==typeof i?i(this,t,n):[]},getDatasetAtEvent:function(t){return re.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this.data.datasets[t];e._meta||(e._meta={});var n=e._meta[this.id];return n||(n=e._meta[this.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null,order:e.order||0,index:t}),n},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e<n;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroyDatasetMeta:function(t){var e=this.id,n=this.data.datasets[t],i=n._meta&&n._meta[e];i&&(i.controller.destroy(),delete n._meta[e])},destroy:function(){var t,e,n=this,i=n.canvas;for(n.stop(),t=0,e=n.data.datasets.length;t<e;++t)n.destroyDatasetMeta(t);i&&(n.unbindEvents(),H.canvas.clear(n),Ie.releaseContext(n.ctx),n.canvas=null,n.ctx=null),Le.notify(n,"destroy"),delete tn.instances[n.id]},toBase64Image:function(){return this.canvas.toDataURL.apply(this.canvas,arguments)},initToolTip:function(){var t=this;t.tooltip=new Ge({_chart:t,_chartInstance:t,_data:t.data,_options:t.options.tooltips},t)},bindEvents:function(){var t=this,e=t._listeners={},n=function(){t.eventHandler.apply(t,arguments)};H.each(t.options.events,(function(i){Ie.addEventListener(t,i,n),e[i]=n})),t.options.responsive&&(n=function(){t.resize()},Ie.addEventListener(t,"resize",n),e.resize=n)},unbindEvents:function(){var t=this,e=t._listeners;e&&(delete t._listeners,H.each(e,(function(e,n){Ie.removeEventListener(t,n,e)})))},updateHoverStyle:function(t,e,n){var i,a,r,o=n?"set":"remove";for(a=0,r=t.length;a<r;++a)(i=t[a])&&this.getDatasetMeta(i._datasetIndex).controller[o+"HoverStyle"](i);"dataset"===e&&this.getDatasetMeta(t[0]._datasetIndex).controller["_"+o+"DatasetHoverStyle"]()},eventHandler:function(t){var e=this,n=e.tooltip;if(!1!==Le.notify(e,"beforeEvent",[t])){e._bufferedRender=!0,e._bufferedRequest=null;var i=e.handleEvent(t);n&&(i=n._start?n.handleEvent(t):i|n.handleEvent(t)),Le.notify(e,"afterEvent",[t]);var a=e._bufferedRequest;return a?e.render(a):i&&!e.animating&&(e.stop(),e.render({duration:e.options.hover.animationDuration,lazy:!0})),e._bufferedRender=!1,e._bufferedRequest=null,e}},handleEvent:function(t){var e,n=this,i=n.options||{},a=i.hover;return n.lastActive=n.lastActive||[],"mouseout"===t.type?n.active=[]:n.active=n.getElementsAtEventForMode(t,a.mode,a),H.callback(i.onHover||i.hover.onHover,[t.native,n.active],n),"mouseup"!==t.type&&"click"!==t.type||i.onClick&&i.onClick.call(n,t.native,n.active),n.lastActive.length&&n.updateHoverStyle(n.lastActive,a.mode,!1),n.active.length&&a.mode&&n.updateHoverStyle(n.active,a.mode,!0),e=!H.arrayEquals(n.active,n.lastActive),n.lastActive=n.active,e}}),tn.instances={};var en=tn;tn.Controller=tn,tn.types={},H.configMerge=$e,H.scaleMerge=Ze;function nn(){throw new Error("This method is not implemented: either no adapter can be found or an incomplete integration was provided.")}function an(t){this.options=t||{}}H.extend(an.prototype,{formats:nn,parse:nn,format:nn,add:nn,diff:nn,startOf:nn,endOf:nn,_create:function(t){return t}}),an.override=function(t){H.extend(an.prototype,t)};var rn={_date:an},on={formatters:{values:function(t){return H.isArray(t)?t:""+t},linear:function(t,e,n){var i=n.length>3?n[2]-n[1]:n[1]-n[0];Math.abs(i)>1&&t!==Math.floor(t)&&(i=t-Math.floor(t));var a=H.log10(Math.abs(i)),r="";if(0!==t)if(Math.max(Math.abs(n[0]),Math.abs(n[n.length-1]))<1e-4){var o=H.log10(Math.abs(t)),s=Math.floor(o)-Math.floor(a);s=Math.max(Math.min(s,20),0),r=t.toExponential(s)}else{var l=-1*Math.floor(a);l=Math.max(Math.min(l,20),0),r=t.toFixed(l)}else r="0";return r},logarithmic:function(t,e,n){var i=t/Math.pow(10,Math.floor(H.log10(t)));return 0===t?"0":1===i||2===i||5===i||0===e||e===n.length-1?t.toExponential():""}}},sn=H.isArray,ln=H.isNullOrUndef,un=H.valueOrDefault,dn=H.valueAtIndexOrDefault;function hn(t,e,n){var i,a=t.getTicks().length,r=Math.min(e,a-1),o=t.getPixelForTick(r),s=t._startPixel,l=t._endPixel;if(!(n&&(i=1===a?Math.max(o-s,l-o):0===e?(t.getPixelForTick(1)-o)/2:(o-t.getPixelForTick(r-1))/2,(o+=r<e?i:-i)<s-1e-6||o>l+1e-6)))return o}function cn(t,e,n,i){var a,r,o,s,l,u,d,h,c,f,g,m,p,v=n.length,b=[],y=[],x=[];for(a=0;a<v;++a){if(s=n[a].label,l=n[a].major?e.major:e.minor,t.font=u=l.string,d=i[u]=i[u]||{data:{},gc:[]},h=l.lineHeight,c=f=0,ln(s)||sn(s)){if(sn(s))for(r=0,o=s.length;r<o;++r)g=s[r],ln(g)||sn(g)||(c=H.measureText(t,d.data,d.gc,c,g),f+=h)}else c=H.measureText(t,d.data,d.gc,c,s),f=h;b.push(c),y.push(f),x.push(h/2)}function _(t){return{width:b[t]||0,height:y[t]||0,offset:x[t]||0}}return function(t,e){H.each(t,(function(t){var n,i=t.gc,a=i.length/2;if(a>e){for(n=0;n<a;++n)delete t.data[i[n]];i.splice(0,a)}}))}(i,v),m=b.indexOf(Math.max.apply(null,b)),p=y.indexOf(Math.max.apply(null,y)),{first:_(0),last:_(v-1),widest:_(m),highest:_(p)}}function fn(t){return t.drawTicks?t.tickMarkLength:0}function gn(t){var e,n;return t.display?(e=H.options._parseFont(t),n=H.options.toPadding(t.padding),e.lineHeight+n.height):0}function mn(t,e){return H.extend(H.options._parseFont({fontFamily:un(e.fontFamily,t.fontFamily),fontSize:un(e.fontSize,t.fontSize),fontStyle:un(e.fontStyle,t.fontStyle),lineHeight:un(e.lineHeight,t.lineHeight)}),{color:H.options.resolve([e.fontColor,t.fontColor,W.global.defaultFontColor])})}function pn(t){var e=mn(t,t.minor);return{minor:e,major:t.major.enabled?mn(t,t.major):e}}function vn(t){var e,n,i,a=[];for(n=0,i=t.length;n<i;++n)void 0!==(e=t[n])._index&&a.push(e);return a}function bn(t,e,n,i){var a,r,o,s,l=un(n,0),u=Math.min(un(i,t.length),t.length),d=0;for(e=Math.ceil(e),i&&(e=(a=i-n)/Math.floor(a/e)),s=l;s<0;)d++,s=Math.round(l+d*e);for(r=Math.max(l,0);r<u;r++)o=t[r],r===s?(o._index=r,d++,s=Math.round(l+d*e)):delete o.label}W._set("scale",{display:!0,position:"left",offset:!1,gridLines:{display:!0,color:"rgba(0,0,0,0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",zeroLineBorderDash:[],zeroLineBorderDashOffset:0,offsetGridLines:!1,borderDash:[],borderDashOffset:0},scaleLabel:{display:!1,labelString:"",padding:{top:4,bottom:4}},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:0,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:on.formatters.values,minor:{},major:{}}});var yn=$.extend({zeroLineIndex:0,getPadding:function(){return{left:this.paddingLeft||0,top:this.paddingTop||0,right:this.paddingRight||0,bottom:this.paddingBottom||0}},getTicks:function(){return this._ticks},_getLabels:function(){var t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels||[]},mergeTicksOptions:function(){},beforeUpdate:function(){H.callback(this.options.beforeUpdate,[this])},update:function(t,e,n){var i,a,r,o,s,l=this,u=l.options.ticks,d=u.sampleSize;if(l.beforeUpdate(),l.maxWidth=t,l.maxHeight=e,l.margins=H.extend({left:0,right:0,top:0,bottom:0},n),l._ticks=null,l.ticks=null,l._labelSizes=null,l._maxLabelLines=0,l.longestLabelWidth=0,l.longestTextCache=l.longestTextCache||{},l._gridLineItems=null,l._labelItems=null,l.beforeSetDimensions(),l.setDimensions(),l.afterSetDimensions(),l.beforeDataLimits(),l.determineDataLimits(),l.afterDataLimits(),l.beforeBuildTicks(),o=l.buildTicks()||[],(!(o=l.afterBuildTicks(o)||o)||!o.length)&&l.ticks)for(o=[],i=0,a=l.ticks.length;i<a;++i)o.push({value:l.ticks[i],major:!1});return l._ticks=o,s=d<o.length,r=l._convertTicksToLabels(s?function(t,e){for(var n=[],i=t.length/e,a=0,r=t.length;a<r;a+=i)n.push(t[Math.floor(a)]);return n}(o,d):o),l._configure(),l.beforeCalculateTickRotation(),l.calculateTickRotation(),l.afterCalculateTickRotation(),l.beforeFit(),l.fit(),l.afterFit(),l._ticksToDraw=u.display&&(u.autoSkip||"auto"===u.source)?l._autoSkip(o):o,s&&(r=l._convertTicksToLabels(l._ticksToDraw)),l.ticks=r,l.afterUpdate(),l.minSize},_configure:function(){var t,e,n=this,i=n.options.ticks.reverse;n.isHorizontal()?(t=n.left,e=n.right):(t=n.top,e=n.bottom,i=!i),n._startPixel=t,n._endPixel=e,n._reversePixels=i,n._length=e-t},afterUpdate:function(){H.callback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){H.callback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){H.callback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){H.callback(this.options.beforeDataLimits,[this])},determineDataLimits:H.noop,afterDataLimits:function(){H.callback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){H.callback(this.options.beforeBuildTicks,[this])},buildTicks:H.noop,afterBuildTicks:function(t){var e=this;return sn(t)&&t.length?H.callback(e.options.afterBuildTicks,[e,t]):(e.ticks=H.callback(e.options.afterBuildTicks,[e,e.ticks])||e.ticks,t)},beforeTickToLabelConversion:function(){H.callback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this.options.ticks;this.ticks=this.ticks.map(t.userCallback||t.callback,this)},afterTickToLabelConversion:function(){H.callback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){H.callback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var t,e,n,i,a,r,o,s=this,l=s.options,u=l.ticks,d=s.getTicks().length,h=u.minRotation||0,c=u.maxRotation,f=h;!s._isVisible()||!u.display||h>=c||d<=1||!s.isHorizontal()?s.labelRotation=h:(e=(t=s._getLabelSizes()).widest.width,n=t.highest.height-t.highest.offset,i=Math.min(s.maxWidth,s.chart.width-e),e+6>(a=l.offset?s.maxWidth/d:i/(d-1))&&(a=i/(d-(l.offset?.5:1)),r=s.maxHeight-fn(l.gridLines)-u.padding-gn(l.scaleLabel),o=Math.sqrt(e*e+n*n),f=H.toDegrees(Math.min(Math.asin(Math.min((t.highest.height+6)/a,1)),Math.asin(Math.min(r/o,1))-Math.asin(n/o))),f=Math.max(h,Math.min(c,f))),s.labelRotation=f)},afterCalculateTickRotation:function(){H.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){H.callback(this.options.beforeFit,[this])},fit:function(){var t=this,e=t.minSize={width:0,height:0},n=t.chart,i=t.options,a=i.ticks,r=i.scaleLabel,o=i.gridLines,s=t._isVisible(),l="bottom"===i.position,u=t.isHorizontal();if(u?e.width=t.maxWidth:s&&(e.width=fn(o)+gn(r)),u?s&&(e.height=fn(o)+gn(r)):e.height=t.maxHeight,a.display&&s){var d=pn(a),h=t._getLabelSizes(),c=h.first,f=h.last,g=h.widest,m=h.highest,p=.4*d.minor.lineHeight,v=a.padding;if(u){var b=0!==t.labelRotation,y=H.toRadians(t.labelRotation),x=Math.cos(y),_=Math.sin(y),w=_*g.width+x*(m.height-(b?m.offset:0))+(b?0:p);e.height=Math.min(t.maxHeight,e.height+w+v);var k,M,S=t.getPixelForTick(0)-t.left,D=t.right-t.getPixelForTick(t.getTicks().length-1);b?(k=l?x*c.width+_*c.offset:_*(c.height-c.offset),M=l?_*(f.height-f.offset):x*f.width+_*f.offset):(k=c.width/2,M=f.width/2),t.paddingLeft=Math.max((k-S)*t.width/(t.width-S),0)+3,t.paddingRight=Math.max((M-D)*t.width/(t.width-D),0)+3}else{var C=a.mirror?0:g.width+v+p;e.width=Math.min(t.maxWidth,e.width+C),t.paddingTop=c.height/2,t.paddingBottom=f.height/2}}t.handleMargins(),u?(t.width=t._length=n.width-t.margins.left-t.margins.right,t.height=e.height):(t.width=e.width,t.height=t._length=n.height-t.margins.top-t.margins.bottom)},handleMargins:function(){var t=this;t.margins&&(t.margins.left=Math.max(t.paddingLeft,t.margins.left),t.margins.top=Math.max(t.paddingTop,t.margins.top),t.margins.right=Math.max(t.paddingRight,t.margins.right),t.margins.bottom=Math.max(t.paddingBottom,t.margins.bottom))},afterFit:function(){H.callback(this.options.afterFit,[this])},isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(ln(t))return NaN;if(("number"==typeof t||t instanceof Number)&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},_convertTicksToLabels:function(t){var e,n,i,a=this;for(a.ticks=t.map((function(t){return t.value})),a.beforeTickToLabelConversion(),e=a.convertTicksToLabels(t)||a.ticks,a.afterTickToLabelConversion(),n=0,i=t.length;n<i;++n)t[n].label=e[n];return e},_getLabelSizes:function(){var t=this,e=t._labelSizes;return e||(t._labelSizes=e=cn(t.ctx,pn(t.options.ticks),t.getTicks(),t.longestTextCache),t.longestLabelWidth=e.widest.width),e},_parseValue:function(t){var e,n,i,a;return sn(t)?(e=+this.getRightValue(t[0]),n=+this.getRightValue(t[1]),i=Math.min(e,n),a=Math.max(e,n)):(e=void 0,n=t=+this.getRightValue(t),i=t,a=t),{min:i,max:a,start:e,end:n}},_getScaleLabel:function(t){var e=this._parseValue(t);return void 0!==e.start?"["+e.start+", "+e.end+"]":+this.getRightValue(t)},getLabelForIndex:H.noop,getPixelForValue:H.noop,getValueForPixel:H.noop,getPixelForTick:function(t){var e=this.options.offset,n=this._ticks.length,i=1/Math.max(n-(e?0:1),1);return t<0||t>n-1?null:this.getPixelForDecimal(t*i+(e?i/2:0))},getPixelForDecimal:function(t){return this._reversePixels&&(t=1-t),this._startPixel+t*this._length},getDecimalForPixel:function(t){var e=(t-this._startPixel)/this._length;return this._reversePixels?1-e:e},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this.min,e=this.max;return this.beginAtZero?0:t<0&&e<0?e:t>0&&e>0?t:0},_autoSkip:function(t){var e,n,i,a,r=this.options.ticks,o=this._length,s=r.maxTicksLimit||o/this._tickSize()+1,l=r.major.enabled?function(t){var e,n,i=[];for(e=0,n=t.length;e<n;e++)t[e].major&&i.push(e);return i}(t):[],u=l.length,d=l[0],h=l[u-1];if(u>s)return function(t,e,n){var i,a,r=0,o=e[0];for(n=Math.ceil(n),i=0;i<t.length;i++)a=t[i],i===o?(a._index=i,o=e[++r*n]):delete a.label}(t,l,u/s),vn(t);if(i=function(t,e,n,i){var a,r,o,s,l=function(t){var e,n,i=t.length;if(i<2)return!1;for(n=t[0],e=1;e<i;++e)if(t[e]-t[e-1]!==n)return!1;return n}(t),u=(e.length-1)/i;if(!l)return Math.max(u,1);for(o=0,s=(a=H.math._factorize(l)).length-1;o<s;o++)if((r=a[o])>u)return r;return Math.max(u,1)}(l,t,0,s),u>0){for(e=0,n=u-1;e<n;e++)bn(t,i,l[e],l[e+1]);return a=u>1?(h-d)/(u-1):null,bn(t,i,H.isNullOrUndef(a)?0:d-a,d),bn(t,i,h,H.isNullOrUndef(a)?t.length:h+a),vn(t)}return bn(t,i),vn(t)},_tickSize:function(){var t=this.options.ticks,e=H.toRadians(this.labelRotation),n=Math.abs(Math.cos(e)),i=Math.abs(Math.sin(e)),a=this._getLabelSizes(),r=t.autoSkipPadding||0,o=a?a.widest.width+r:0,s=a?a.highest.height+r:0;return this.isHorizontal()?s*n>o*i?o/n:s/i:s*i<o*n?s/n:o/i},_isVisible:function(){var t,e,n,i=this.chart,a=this.options.display;if("auto"!==a)return!!a;for(t=0,e=i.data.datasets.length;t<e;++t)if(i.isDatasetVisible(t)&&((n=i.getDatasetMeta(t)).xAxisID===this.id||n.yAxisID===this.id))return!0;return!1},_computeGridLineItems:function(t){var e,n,i,a,r,o,s,l,u,d,h,c,f,g,m,p,v,b=this,y=b.chart,x=b.options,_=x.gridLines,w=x.position,k=_.offsetGridLines,M=b.isHorizontal(),S=b._ticksToDraw,D=S.length+(k?1:0),C=fn(_),P=[],T=_.drawBorder?dn(_.lineWidth,0,0):0,O=T/2,A=H._alignPixel,F=function(t){return A(y,t,T)};for("top"===w?(e=F(b.bottom),s=b.bottom-C,u=e-O,h=F(t.top)+O,f=t.bottom):"bottom"===w?(e=F(b.top),h=t.top,f=F(t.bottom)-O,s=e+O,u=b.top+C):"left"===w?(e=F(b.right),o=b.right-C,l=e-O,d=F(t.left)+O,c=t.right):(e=F(b.left),d=t.left,c=F(t.right)-O,o=e+O,l=b.left+C),n=0;n<D;++n)i=S[n]||{},ln(i.label)&&n<S.length||(n===b.zeroLineIndex&&x.offset===k?(g=_.zeroLineWidth,m=_.zeroLineColor,p=_.zeroLineBorderDash||[],v=_.zeroLineBorderDashOffset||0):(g=dn(_.lineWidth,n,1),m=dn(_.color,n,"rgba(0,0,0,0.1)"),p=_.borderDash||[],v=_.borderDashOffset||0),void 0!==(a=hn(b,i._index||n,k))&&(r=A(y,a,g),M?o=l=d=c=r:s=u=h=f=r,P.push({tx1:o,ty1:s,tx2:l,ty2:u,x1:d,y1:h,x2:c,y2:f,width:g,color:m,borderDash:p,borderDashOffset:v})));return P.ticksLength=D,P.borderValue=e,P},_computeLabelItems:function(){var t,e,n,i,a,r,o,s,l,u,d,h,c=this,f=c.options,g=f.ticks,m=f.position,p=g.mirror,v=c.isHorizontal(),b=c._ticksToDraw,y=pn(g),x=g.padding,_=fn(f.gridLines),w=-H.toRadians(c.labelRotation),k=[];for("top"===m?(r=c.bottom-_-x,o=w?"left":"center"):"bottom"===m?(r=c.top+_+x,o=w?"right":"center"):"left"===m?(a=c.right-(p?0:_)-x,o=p?"left":"right"):(a=c.left+(p?0:_)+x,o=p?"right":"left"),t=0,e=b.length;t<e;++t)i=(n=b[t]).label,ln(i)||(s=c.getPixelForTick(n._index||t)+g.labelOffset,u=(l=n.major?y.major:y.minor).lineHeight,d=sn(i)?i.length:1,v?(a=s,h="top"===m?((w?1:.5)-d)*u:(w?0:.5)*u):(r=s,h=(1-d)*u/2),k.push({x:a,y:r,rotation:w,label:i,font:l,textOffset:h,textAlign:o}));return k},_drawGrid:function(t){var e=this,n=e.options.gridLines;if(n.display){var i,a,r,o,s,l=e.ctx,u=e.chart,d=H._alignPixel,h=n.drawBorder?dn(n.lineWidth,0,0):0,c=e._gridLineItems||(e._gridLineItems=e._computeGridLineItems(t));for(r=0,o=c.length;r<o;++r)i=(s=c[r]).width,a=s.color,i&&a&&(l.save(),l.lineWidth=i,l.strokeStyle=a,l.setLineDash&&(l.setLineDash(s.borderDash),l.lineDashOffset=s.borderDashOffset),l.beginPath(),n.drawTicks&&(l.moveTo(s.tx1,s.ty1),l.lineTo(s.tx2,s.ty2)),n.drawOnChartArea&&(l.moveTo(s.x1,s.y1),l.lineTo(s.x2,s.y2)),l.stroke(),l.restore());if(h){var f,g,m,p,v=h,b=dn(n.lineWidth,c.ticksLength-1,1),y=c.borderValue;e.isHorizontal()?(f=d(u,e.left,v)-v/2,g=d(u,e.right,b)+b/2,m=p=y):(m=d(u,e.top,v)-v/2,p=d(u,e.bottom,b)+b/2,f=g=y),l.lineWidth=h,l.strokeStyle=dn(n.color,0),l.beginPath(),l.moveTo(f,m),l.lineTo(g,p),l.stroke()}}},_drawLabels:function(){var t=this;if(t.options.ticks.display){var e,n,i,a,r,o,s,l,u=t.ctx,d=t._labelItems||(t._labelItems=t._computeLabelItems());for(e=0,i=d.length;e<i;++e){if(o=(r=d[e]).font,u.save(),u.translate(r.x,r.y),u.rotate(r.rotation),u.font=o.string,u.fillStyle=o.color,u.textBaseline="middle",u.textAlign=r.textAlign,s=r.label,l=r.textOffset,sn(s))for(n=0,a=s.length;n<a;++n)u.fillText(""+s[n],0,l),l+=o.lineHeight;else u.fillText(s,0,l);u.restore()}}},_drawTitle:function(){var t=this,e=t.ctx,n=t.options,i=n.scaleLabel;if(i.display){var a,r,o=un(i.fontColor,W.global.defaultFontColor),s=H.options._parseFont(i),l=H.options.toPadding(i.padding),u=s.lineHeight/2,d=n.position,h=0;if(t.isHorizontal())a=t.left+t.width/2,r="bottom"===d?t.bottom-u-l.bottom:t.top+u+l.top;else{var c="left"===d;a=c?t.left+u+l.top:t.right-u-l.top,r=t.top+t.height/2,h=c?-.5*Math.PI:.5*Math.PI}e.save(),e.translate(a,r),e.rotate(h),e.textAlign="center",e.textBaseline="middle",e.fillStyle=o,e.font=s.string,e.fillText(i.labelString,0,0),e.restore()}},draw:function(t){this._isVisible()&&(this._drawGrid(t),this._drawTitle(),this._drawLabels())},_layers:function(){var t=this,e=t.options,n=e.ticks&&e.ticks.z||0,i=e.gridLines&&e.gridLines.z||0;return t._isVisible()&&n!==i&&t.draw===t._draw?[{z:i,draw:function(){t._drawGrid.apply(t,arguments),t._drawTitle.apply(t,arguments)}},{z:n,draw:function(){t._drawLabels.apply(t,arguments)}}]:[{z:n,draw:function(){t.draw.apply(t,arguments)}}]},_getMatchingVisibleMetas:function(t){var e=this,n=e.isHorizontal();return e.chart._getSortedVisibleDatasetMetas().filter((function(i){return(!t||i.type===t)&&(n?i.xAxisID===e.id:i.yAxisID===e.id)}))}});yn.prototype._draw=yn.prototype.draw;var xn=yn,_n=H.isNullOrUndef,wn=xn.extend({determineDataLimits:function(){var t,e=this,n=e._getLabels(),i=e.options.ticks,a=i.min,r=i.max,o=0,s=n.length-1;void 0!==a&&(t=n.indexOf(a))>=0&&(o=t),void 0!==r&&(t=n.indexOf(r))>=0&&(s=t),e.minIndex=o,e.maxIndex=s,e.min=n[o],e.max=n[s]},buildTicks:function(){var t=this._getLabels(),e=this.minIndex,n=this.maxIndex;this.ticks=0===e&&n===t.length-1?t:t.slice(e,n+1)},getLabelForIndex:function(t,e){var n=this.chart;return n.getDatasetMeta(e).controller._getValueScaleId()===this.id?this.getRightValue(n.data.datasets[e].data[t]):this._getLabels()[t]},_configure:function(){var t=this,e=t.options.offset,n=t.ticks;xn.prototype._configure.call(t),t.isHorizontal()||(t._reversePixels=!t._reversePixels),n&&(t._startValue=t.minIndex-(e?.5:0),t._valueRange=Math.max(n.length-(e?0:1),1))},getPixelForValue:function(t,e,n){var i,a,r,o=this;return _n(e)||_n(n)||(t=o.chart.data.datasets[n].data[e]),_n(t)||(i=o.isHorizontal()?t.x:t.y),(void 0!==i||void 0!==t&&isNaN(e))&&(a=o._getLabels(),t=H.valueOrDefault(i,t),e=-1!==(r=a.indexOf(t))?r:e,isNaN(e)&&(e=t)),o.getPixelForDecimal((e-o._startValue)/o._valueRange)},getPixelForTick:function(t){var e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t],t+this.minIndex)},getValueForPixel:function(t){var e=Math.round(this._startValue+this.getDecimalForPixel(t)*this._valueRange);return Math.min(Math.max(e,0),this.ticks.length-1)},getBasePixel:function(){return this.bottom}}),kn={position:"bottom"};wn._defaults=kn;var Mn=H.noop,Sn=H.isNullOrUndef;var Dn=xn.extend({getRightValue:function(t){return"string"==typeof t?+t:xn.prototype.getRightValue.call(this,t)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=H.sign(t.min),i=H.sign(t.max);n<0&&i<0?t.max=0:n>0&&i>0&&(t.min=0)}var a=void 0!==e.min||void 0!==e.suggestedMin,r=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(null===t.min?t.min=e.suggestedMin:t.min=Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(null===t.max?t.max=e.suggestedMax:t.max=Math.max(t.max,e.suggestedMax)),a!==r&&t.min>=t.max&&(a?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:function(){var t,e=this.options.ticks,n=e.stepSize,i=e.maxTicksLimit;return n?t=Math.ceil(this.max/n)-Math.floor(this.min/n)+1:(t=this._computeTickLimit(),i=i||11),i&&(t=Math.min(i,t)),t},_computeTickLimit:function(){return Number.POSITIVE_INFINITY},handleDirectionalChanges:Mn,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),i={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,precision:e.precision,stepSize:H.valueOrDefault(e.fixedStepSize,e.stepSize)},a=t.ticks=function(t,e){var n,i,a,r,o=[],s=t.stepSize,l=s||1,u=t.maxTicks-1,d=t.min,h=t.max,c=t.precision,f=e.min,g=e.max,m=H.niceNum((g-f)/u/l)*l;if(m<1e-14&&Sn(d)&&Sn(h))return[f,g];(r=Math.ceil(g/m)-Math.floor(f/m))>u&&(m=H.niceNum(r*m/u/l)*l),s||Sn(c)?n=Math.pow(10,H._decimalPlaces(m)):(n=Math.pow(10,c),m=Math.ceil(m*n)/n),i=Math.floor(f/m)*m,a=Math.ceil(g/m)*m,s&&(!Sn(d)&&H.almostWhole(d/m,m/1e3)&&(i=d),!Sn(h)&&H.almostWhole(h/m,m/1e3)&&(a=h)),r=(a-i)/m,r=H.almostEquals(r,Math.round(r),m/1e3)?Math.round(r):Math.ceil(r),i=Math.round(i*n)/n,a=Math.round(a*n)/n,o.push(Sn(d)?i:d);for(var p=1;p<r;++p)o.push(Math.round((i+p*m)*n)/n);return o.push(Sn(h)?a:h),o}(i,t);t.handleDirectionalChanges(),t.max=H.max(a),t.min=H.min(a),e.reverse?(a.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var t=this;t.ticksAsNumbers=t.ticks.slice(),t.zeroLineIndex=t.ticks.indexOf(0),xn.prototype.convertTicksToLabels.call(t)},_configure:function(){var t,e=this,n=e.getTicks(),i=e.min,a=e.max;xn.prototype._configure.call(e),e.options.offset&&n.length&&(i-=t=(a-i)/Math.max(n.length-1,1)/2,a+=t),e._startValue=i,e._endValue=a,e._valueRange=a-i}}),Cn={position:"left",ticks:{callback:on.formatters.linear}};function Pn(t,e,n,i){var a,r,o=t.options,s=function(t,e,n){var i=[n.type,void 0===e&&void 0===n.stack?n.index:"",n.stack].join(".");return void 0===t[i]&&(t[i]={pos:[],neg:[]}),t[i]}(e,o.stacked,n),l=s.pos,u=s.neg,d=i.length;for(a=0;a<d;++a)r=t._parseValue(i[a]),isNaN(r.min)||isNaN(r.max)||n.data[a].hidden||(l[a]=l[a]||0,u[a]=u[a]||0,o.relativePoints?l[a]=100:r.min<0||r.max<0?u[a]+=r.min:l[a]+=r.max)}function Tn(t,e,n){var i,a,r=n.length;for(i=0;i<r;++i)a=t._parseValue(n[i]),isNaN(a.min)||isNaN(a.max)||e.data[i].hidden||(t.min=Math.min(t.min,a.min),t.max=Math.max(t.max,a.max))}var On=Dn.extend({determineDataLimits:function(){var t,e,n,i,a=this,r=a.options,o=a.chart.data.datasets,s=a._getMatchingVisibleMetas(),l=r.stacked,u={},d=s.length;if(a.min=Number.POSITIVE_INFINITY,a.max=Number.NEGATIVE_INFINITY,void 0===l)for(t=0;!l&&t<d;++t)l=void 0!==(e=s[t]).stack;for(t=0;t<d;++t)n=o[(e=s[t]).index].data,l?Pn(a,u,e,n):Tn(a,e,n);H.each(u,(function(t){i=t.pos.concat(t.neg),a.min=Math.min(a.min,H.min(i)),a.max=Math.max(a.max,H.max(i))})),a.min=H.isFinite(a.min)&&!isNaN(a.min)?a.min:0,a.max=H.isFinite(a.max)&&!isNaN(a.max)?a.max:1,a.handleTickRangeOptions()},_computeTickLimit:function(){var t;return this.isHorizontal()?Math.ceil(this.width/40):(t=H.options._parseFont(this.options.ticks),Math.ceil(this.height/t.lineHeight))},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return this._getScaleLabel(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){return this.getPixelForDecimal((+this.getRightValue(t)-this._startValue)/this._valueRange)},getValueForPixel:function(t){return this._startValue+this.getDecimalForPixel(t)*this._valueRange},getPixelForTick:function(t){var e=this.ticksAsNumbers;return t<0||t>e.length-1?null:this.getPixelForValue(e[t])}}),An=Cn;On._defaults=An;var Fn=H.valueOrDefault,In=H.math.log10;var Ln={position:"left",ticks:{callback:on.formatters.logarithmic}};function Rn(t,e){return H.isFinite(t)&&t>=0?t:e}var Nn=xn.extend({determineDataLimits:function(){var t,e,n,i,a,r,o=this,s=o.options,l=o.chart,u=l.data.datasets,d=o.isHorizontal();function h(t){return d?t.xAxisID===o.id:t.yAxisID===o.id}o.min=Number.POSITIVE_INFINITY,o.max=Number.NEGATIVE_INFINITY,o.minNotZero=Number.POSITIVE_INFINITY;var c=s.stacked;if(void 0===c)for(t=0;t<u.length;t++)if(e=l.getDatasetMeta(t),l.isDatasetVisible(t)&&h(e)&&void 0!==e.stack){c=!0;break}if(s.stacked||c){var f={};for(t=0;t<u.length;t++){var g=[(e=l.getDatasetMeta(t)).type,void 0===s.stacked&&void 0===e.stack?t:"",e.stack].join(".");if(l.isDatasetVisible(t)&&h(e))for(void 0===f[g]&&(f[g]=[]),a=0,r=(i=u[t].data).length;a<r;a++){var m=f[g];n=o._parseValue(i[a]),isNaN(n.min)||isNaN(n.max)||e.data[a].hidden||n.min<0||n.max<0||(m[a]=m[a]||0,m[a]+=n.max)}}H.each(f,(function(t){if(t.length>0){var e=H.min(t),n=H.max(t);o.min=Math.min(o.min,e),o.max=Math.max(o.max,n)}}))}else for(t=0;t<u.length;t++)if(e=l.getDatasetMeta(t),l.isDatasetVisible(t)&&h(e))for(a=0,r=(i=u[t].data).length;a<r;a++)n=o._parseValue(i[a]),isNaN(n.min)||isNaN(n.max)||e.data[a].hidden||n.min<0||n.max<0||(o.min=Math.min(n.min,o.min),o.max=Math.max(n.max,o.max),0!==n.min&&(o.minNotZero=Math.min(n.min,o.minNotZero)));o.min=H.isFinite(o.min)?o.min:null,o.max=H.isFinite(o.max)?o.max:null,o.minNotZero=H.isFinite(o.minNotZero)?o.minNotZero:null,this.handleTickRangeOptions()},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;t.min=Rn(e.min,t.min),t.max=Rn(e.max,t.max),t.min===t.max&&(0!==t.min&&null!==t.min?(t.min=Math.pow(10,Math.floor(In(t.min))-1),t.max=Math.pow(10,Math.floor(In(t.max))+1)):(t.min=1,t.max=10)),null===t.min&&(t.min=Math.pow(10,Math.floor(In(t.max))-1)),null===t.max&&(t.max=0!==t.min?Math.pow(10,Math.floor(In(t.min))+1):10),null===t.minNotZero&&(t.min>0?t.minNotZero=t.min:t.max<1?t.minNotZero=Math.pow(10,Math.floor(In(t.max))):t.minNotZero=1)},buildTicks:function(){var t=this,e=t.options.ticks,n=!t.isHorizontal(),i={min:Rn(e.min),max:Rn(e.max)},a=t.ticks=function(t,e){var n,i,a=[],r=Fn(t.min,Math.pow(10,Math.floor(In(e.min)))),o=Math.floor(In(e.max)),s=Math.ceil(e.max/Math.pow(10,o));0===r?(n=Math.floor(In(e.minNotZero)),i=Math.floor(e.minNotZero/Math.pow(10,n)),a.push(r),r=i*Math.pow(10,n)):(n=Math.floor(In(r)),i=Math.floor(r/Math.pow(10,n)));var l=n<0?Math.pow(10,Math.abs(n)):1;do{a.push(r),10===++i&&(i=1,l=++n>=0?1:l),r=Math.round(i*Math.pow(10,n)*l)/l}while(n<o||n===o&&i<s);var u=Fn(t.max,r);return a.push(u),a}(i,t);t.max=H.max(a),t.min=H.min(a),e.reverse?(n=!n,t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max),n&&a.reverse()},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),xn.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return this._getScaleLabel(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){var e=this.tickValues;return t<0||t>e.length-1?null:this.getPixelForValue(e[t])},_getFirstTickValue:function(t){var e=Math.floor(In(t));return Math.floor(t/Math.pow(10,e))*Math.pow(10,e)},_configure:function(){var t=this,e=t.min,n=0;xn.prototype._configure.call(t),0===e&&(e=t._getFirstTickValue(t.minNotZero),n=Fn(t.options.ticks.fontSize,W.global.defaultFontSize)/t._length),t._startValue=In(e),t._valueOffset=n,t._valueRange=(In(t.max)-In(e))/(1-n)},getPixelForValue:function(t){var e=this,n=0;return(t=+e.getRightValue(t))>e.min&&t>0&&(n=(In(t)-e._startValue)/e._valueRange+e._valueOffset),e.getPixelForDecimal(n)},getValueForPixel:function(t){var e=this,n=e.getDecimalForPixel(t);return 0===n&&0===e.min?0:Math.pow(10,e._startValue+(n-e._valueOffset)*e._valueRange)}}),Wn=Ln;Nn._defaults=Wn;var Yn=H.valueOrDefault,zn=H.valueAtIndexOrDefault,En=H.options.resolve,Vn={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0,0,0,0.1)",lineWidth:1,borderDash:[],borderDashOffset:0},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:on.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}};function Hn(t){var e=t.ticks;return e.display&&t.display?Yn(e.fontSize,W.global.defaultFontSize)+2*e.backdropPaddingY:0}function Bn(t,e,n,i,a){return t===i||t===a?{start:e-n/2,end:e+n/2}:t<i||t>a?{start:e-n,end:e}:{start:e,end:e+n}}function jn(t){return 0===t||180===t?"center":t<180?"left":"right"}function Un(t,e,n,i){var a,r,o=n.y+i/2;if(H.isArray(e))for(a=0,r=e.length;a<r;++a)t.fillText(e[a],n.x,o),o+=i;else t.fillText(e,n.x,o)}function Gn(t,e,n){90===t||270===t?n.y-=e.h/2:(t>270||t<90)&&(n.y-=e.h)}function qn(t){return H.isNumber(t)?t:0}var Zn=Dn.extend({setDimensions:function(){var t=this;t.width=t.maxWidth,t.height=t.maxHeight,t.paddingTop=Hn(t.options)/2,t.xCenter=Math.floor(t.width/2),t.yCenter=Math.floor((t.height-t.paddingTop)/2),t.drawingArea=Math.min(t.height-t.paddingTop,t.width)/2},determineDataLimits:function(){var t=this,e=t.chart,n=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;H.each(e.data.datasets,(function(a,r){if(e.isDatasetVisible(r)){var o=e.getDatasetMeta(r);H.each(a.data,(function(e,a){var r=+t.getRightValue(e);isNaN(r)||o.data[a].hidden||(n=Math.min(r,n),i=Math.max(r,i))}))}})),t.min=n===Number.POSITIVE_INFINITY?0:n,t.max=i===Number.NEGATIVE_INFINITY?0:i,t.handleTickRangeOptions()},_computeTickLimit:function(){return Math.ceil(this.drawingArea/Hn(this.options))},convertTicksToLabels:function(){var t=this;Dn.prototype.convertTicksToLabels.call(t),t.pointLabels=t.chart.data.labels.map((function(){var e=H.callback(t.options.pointLabels.callback,arguments,t);return e||0===e?e:""}))},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){var t=this.options;t.display&&t.pointLabels.display?function(t){var e,n,i,a=H.options._parseFont(t.options.pointLabels),r={l:0,r:t.width,t:0,b:t.height-t.paddingTop},o={};t.ctx.font=a.string,t._pointLabelSizes=[];var s,l,u,d=t.chart.data.labels.length;for(e=0;e<d;e++){i=t.getPointPosition(e,t.drawingArea+5),s=t.ctx,l=a.lineHeight,u=t.pointLabels[e],n=H.isArray(u)?{w:H.longestText(s,s.font,u),h:u.length*l}:{w:s.measureText(u).width,h:l},t._pointLabelSizes[e]=n;var h=t.getIndexAngle(e),c=H.toDegrees(h)%360,f=Bn(c,i.x,n.w,0,180),g=Bn(c,i.y,n.h,90,270);f.start<r.l&&(r.l=f.start,o.l=h),f.end>r.r&&(r.r=f.end,o.r=h),g.start<r.t&&(r.t=g.start,o.t=h),g.end>r.b&&(r.b=g.end,o.b=h)}t.setReductions(t.drawingArea,r,o)}(this):this.setCenterPoint(0,0,0,0)},setReductions:function(t,e,n){var i=this,a=e.l/Math.sin(n.l),r=Math.max(e.r-i.width,0)/Math.sin(n.r),o=-e.t/Math.cos(n.t),s=-Math.max(e.b-(i.height-i.paddingTop),0)/Math.cos(n.b);a=qn(a),r=qn(r),o=qn(o),s=qn(s),i.drawingArea=Math.min(Math.floor(t-(a+r)/2),Math.floor(t-(o+s)/2)),i.setCenterPoint(a,r,o,s)},setCenterPoint:function(t,e,n,i){var a=this,r=a.width-e-a.drawingArea,o=t+a.drawingArea,s=n+a.drawingArea,l=a.height-a.paddingTop-i-a.drawingArea;a.xCenter=Math.floor((o+r)/2+a.left),a.yCenter=Math.floor((s+l)/2+a.top+a.paddingTop)},getIndexAngle:function(t){var e=this.chart,n=(t*(360/e.data.labels.length)+((e.options||{}).startAngle||0))%360;return(n<0?n+360:n)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(H.isNullOrUndef(t))return NaN;var n=e.drawingArea/(e.max-e.min);return e.options.ticks.reverse?(e.max-t)*n:(t-e.min)*n},getPointPosition:function(t,e){var n=this.getIndexAngle(t)-Math.PI/2;return{x:Math.cos(n)*e+this.xCenter,y:Math.sin(n)*e+this.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(t){var e=this.min,n=this.max;return this.getPointPositionForValue(t||0,this.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0)},_drawGrid:function(){var t,e,n,i=this,a=i.ctx,r=i.options,o=r.gridLines,s=r.angleLines,l=Yn(s.lineWidth,o.lineWidth),u=Yn(s.color,o.color);if(r.pointLabels.display&&function(t){var e=t.ctx,n=t.options,i=n.pointLabels,a=Hn(n),r=t.getDistanceFromCenterForValue(n.ticks.reverse?t.min:t.max),o=H.options._parseFont(i);e.save(),e.font=o.string,e.textBaseline="middle";for(var s=t.chart.data.labels.length-1;s>=0;s--){var l=0===s?a/2:0,u=t.getPointPosition(s,r+l+5),d=zn(i.fontColor,s,W.global.defaultFontColor);e.fillStyle=d;var h=t.getIndexAngle(s),c=H.toDegrees(h);e.textAlign=jn(c),Gn(c,t._pointLabelSizes[s],u),Un(e,t.pointLabels[s],u,o.lineHeight)}e.restore()}(i),o.display&&H.each(i.ticks,(function(t,n){0!==n&&(e=i.getDistanceFromCenterForValue(i.ticksAsNumbers[n]),function(t,e,n,i){var a,r=t.ctx,o=e.circular,s=t.chart.data.labels.length,l=zn(e.color,i-1),u=zn(e.lineWidth,i-1);if((o||s)&&l&&u){if(r.save(),r.strokeStyle=l,r.lineWidth=u,r.setLineDash&&(r.setLineDash(e.borderDash||[]),r.lineDashOffset=e.borderDashOffset||0),r.beginPath(),o)r.arc(t.xCenter,t.yCenter,n,0,2*Math.PI);else{a=t.getPointPosition(0,n),r.moveTo(a.x,a.y);for(var d=1;d<s;d++)a=t.getPointPosition(d,n),r.lineTo(a.x,a.y)}r.closePath(),r.stroke(),r.restore()}}(i,o,e,n))})),s.display&&l&&u){for(a.save(),a.lineWidth=l,a.strokeStyle=u,a.setLineDash&&(a.setLineDash(En([s.borderDash,o.borderDash,[]])),a.lineDashOffset=En([s.borderDashOffset,o.borderDashOffset,0])),t=i.chart.data.labels.length-1;t>=0;t--)e=i.getDistanceFromCenterForValue(r.ticks.reverse?i.min:i.max),n=i.getPointPosition(t,e),a.beginPath(),a.moveTo(i.xCenter,i.yCenter),a.lineTo(n.x,n.y),a.stroke();a.restore()}},_drawLabels:function(){var t=this,e=t.ctx,n=t.options.ticks;if(n.display){var i,a,r=t.getIndexAngle(0),o=H.options._parseFont(n),s=Yn(n.fontColor,W.global.defaultFontColor);e.save(),e.font=o.string,e.translate(t.xCenter,t.yCenter),e.rotate(r),e.textAlign="center",e.textBaseline="middle",H.each(t.ticks,(function(r,l){(0!==l||n.reverse)&&(i=t.getDistanceFromCenterForValue(t.ticksAsNumbers[l]),n.showLabelBackdrop&&(a=e.measureText(r).width,e.fillStyle=n.backdropColor,e.fillRect(-a/2-n.backdropPaddingX,-i-o.size/2-n.backdropPaddingY,a+2*n.backdropPaddingX,o.size+2*n.backdropPaddingY)),e.fillStyle=s,e.fillText(r,0,-i))})),e.restore()}},_drawTitle:H.noop}),$n=Vn;Zn._defaults=$n;var Xn=H._deprecated,Kn=H.options.resolve,Jn=H.valueOrDefault,Qn=Number.MIN_SAFE_INTEGER||-9007199254740991,ti=Number.MAX_SAFE_INTEGER||9007199254740991,ei={millisecond:{common:!0,size:1,steps:1e3},second:{common:!0,size:1e3,steps:60},minute:{common:!0,size:6e4,steps:60},hour:{common:!0,size:36e5,steps:24},day:{common:!0,size:864e5,steps:30},week:{common:!1,size:6048e5,steps:4},month:{common:!0,size:2628e6,steps:12},quarter:{common:!1,size:7884e6,steps:4},year:{common:!0,size:3154e7}},ni=Object.keys(ei);function ii(t,e){return t-e}function ai(t){return H.valueOrDefault(t.time.min,t.ticks.min)}function ri(t){return H.valueOrDefault(t.time.max,t.ticks.max)}function oi(t,e,n,i){var a=function(t,e,n){for(var i,a,r,o=0,s=t.length-1;o>=0&&o<=s;){if(a=t[(i=o+s>>1)-1]||null,r=t[i],!a)return{lo:null,hi:r};if(r[e]<n)o=i+1;else{if(!(a[e]>n))return{lo:a,hi:r};s=i-1}}return{lo:r,hi:null}}(t,e,n),r=a.lo?a.hi?a.lo:t[t.length-2]:t[0],o=a.lo?a.hi?a.hi:t[t.length-1]:t[1],s=o[e]-r[e],l=s?(n-r[e])/s:0,u=(o[i]-r[i])*l;return r[i]+u}function si(t,e){var n=t._adapter,i=t.options.time,a=i.parser,r=a||i.format,o=e;return"function"==typeof a&&(o=a(o)),H.isFinite(o)||(o="string"==typeof r?n.parse(o,r):n.parse(o)),null!==o?+o:(a||"function"!=typeof r||(o=r(e),H.isFinite(o)||(o=n.parse(o))),o)}function li(t,e){if(H.isNullOrUndef(e))return null;var n=t.options.time,i=si(t,t.getRightValue(e));return null===i?i:(n.round&&(i=+t._adapter.startOf(i,n.round)),i)}function ui(t,e,n,i){var a,r,o,s=ni.length;for(a=ni.indexOf(t);a<s-1;++a)if(o=(r=ei[ni[a]]).steps?r.steps:ti,r.common&&Math.ceil((n-e)/(o*r.size))<=i)return ni[a];return ni[s-1]}function di(t,e,n){var i,a,r=[],o={},s=e.length;for(i=0;i<s;++i)o[a=e[i]]=i,r.push({value:a,major:!1});return 0!==s&&n?function(t,e,n,i){var a,r,o=t._adapter,s=+o.startOf(e[0].value,i),l=e[e.length-1].value;for(a=s;a<=l;a=+o.add(a,1,i))(r=n[a])>=0&&(e[r].major=!0);return e}(t,r,o,n):r}var hi=xn.extend({initialize:function(){this.mergeTicksOptions(),xn.prototype.initialize.call(this)},update:function(){var t=this,e=t.options,n=e.time||(e.time={}),i=t._adapter=new rn._date(e.adapters.date);return Xn("time scale",n.format,"time.format","time.parser"),Xn("time scale",n.min,"time.min","ticks.min"),Xn("time scale",n.max,"time.max","ticks.max"),H.mergeIf(n.displayFormats,i.formats()),xn.prototype.update.apply(t,arguments)},getRightValue:function(t){return t&&void 0!==t.t&&(t=t.t),xn.prototype.getRightValue.call(this,t)},determineDataLimits:function(){var t,e,n,i,a,r,o,s=this,l=s.chart,u=s._adapter,d=s.options,h=d.time.unit||"day",c=ti,f=Qn,g=[],m=[],p=[],v=s._getLabels();for(t=0,n=v.length;t<n;++t)p.push(li(s,v[t]));for(t=0,n=(l.data.datasets||[]).length;t<n;++t)if(l.isDatasetVisible(t))if(a=l.data.datasets[t].data,H.isObject(a[0]))for(m[t]=[],e=0,i=a.length;e<i;++e)r=li(s,a[e]),g.push(r),m[t][e]=r;else m[t]=p.slice(0),o||(g=g.concat(p),o=!0);else m[t]=[];p.length&&(c=Math.min(c,p[0]),f=Math.max(f,p[p.length-1])),g.length&&(g=n>1?function(t){var e,n,i,a={},r=[];for(e=0,n=t.length;e<n;++e)a[i=t[e]]||(a[i]=!0,r.push(i));return r}(g).sort(ii):g.sort(ii),c=Math.min(c,g[0]),f=Math.max(f,g[g.length-1])),c=li(s,ai(d))||c,f=li(s,ri(d))||f,c=c===ti?+u.startOf(Date.now(),h):c,f=f===Qn?+u.endOf(Date.now(),h)+1:f,s.min=Math.min(c,f),s.max=Math.max(c+1,f),s._table=[],s._timestamps={data:g,datasets:m,labels:p}},buildTicks:function(){var t,e,n,i=this,a=i.min,r=i.max,o=i.options,s=o.ticks,l=o.time,u=i._timestamps,d=[],h=i.getLabelCapacity(a),c=s.source,f=o.distribution;for(u="data"===c||"auto"===c&&"series"===f?u.data:"labels"===c?u.labels:function(t,e,n,i){var a,r=t._adapter,o=t.options,s=o.time,l=s.unit||ui(s.minUnit,e,n,i),u=Kn([s.stepSize,s.unitStepSize,1]),d="week"===l&&s.isoWeekday,h=e,c=[];if(d&&(h=+r.startOf(h,"isoWeek",d)),h=+r.startOf(h,d?"day":l),r.diff(n,e,l)>1e5*u)throw e+" and "+n+" are too far apart with stepSize of "+u+" "+l;for(a=h;a<n;a=+r.add(a,u,l))c.push(a);return a!==n&&"ticks"!==o.bounds||c.push(a),c}(i,a,r,h),"ticks"===o.bounds&&u.length&&(a=u[0],r=u[u.length-1]),a=li(i,ai(o))||a,r=li(i,ri(o))||r,t=0,e=u.length;t<e;++t)(n=u[t])>=a&&n<=r&&d.push(n);return i.min=a,i.max=r,i._unit=l.unit||(s.autoSkip?ui(l.minUnit,i.min,i.max,h):function(t,e,n,i,a){var r,o;for(r=ni.length-1;r>=ni.indexOf(n);r--)if(o=ni[r],ei[o].common&&t._adapter.diff(a,i,o)>=e-1)return o;return ni[n?ni.indexOf(n):0]}(i,d.length,l.minUnit,i.min,i.max)),i._majorUnit=s.major.enabled&&"year"!==i._unit?function(t){for(var e=ni.indexOf(t)+1,n=ni.length;e<n;++e)if(ei[ni[e]].common)return ni[e]}(i._unit):void 0,i._table=function(t,e,n,i){if("linear"===i||!t.length)return[{time:e,pos:0},{time:n,pos:1}];var a,r,o,s,l,u=[],d=[e];for(a=0,r=t.length;a<r;++a)(s=t[a])>e&&s<n&&d.push(s);for(d.push(n),a=0,r=d.length;a<r;++a)l=d[a+1],o=d[a-1],s=d[a],void 0!==o&&void 0!==l&&Math.round((l+o)/2)===s||u.push({time:s,pos:a/(r-1)});return u}(i._timestamps.data,a,r,f),i._offsets=function(t,e,n,i,a){var r,o,s=0,l=0;return a.offset&&e.length&&(r=oi(t,"time",e[0],"pos"),s=1===e.length?1-r:(oi(t,"time",e[1],"pos")-r)/2,o=oi(t,"time",e[e.length-1],"pos"),l=1===e.length?o:(o-oi(t,"time",e[e.length-2],"pos"))/2),{start:s,end:l,factor:1/(s+1+l)}}(i._table,d,0,0,o),s.reverse&&d.reverse(),di(i,d,i._majorUnit)},getLabelForIndex:function(t,e){var n=this,i=n._adapter,a=n.chart.data,r=n.options.time,o=a.labels&&t<a.labels.length?a.labels[t]:"",s=a.datasets[e].data[t];return H.isObject(s)&&(o=n.getRightValue(s)),r.tooltipFormat?i.format(si(n,o),r.tooltipFormat):"string"==typeof o?o:i.format(si(n,o),r.displayFormats.datetime)},tickFormatFunction:function(t,e,n,i){var a=this._adapter,r=this.options,o=r.time.displayFormats,s=o[this._unit],l=this._majorUnit,u=o[l],d=n[e],h=r.ticks,c=l&&u&&d&&d.major,f=a.format(t,i||(c?u:s)),g=c?h.major:h.minor,m=Kn([g.callback,g.userCallback,h.callback,h.userCallback]);return m?m(f,e,n):f},convertTicksToLabels:function(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(this.tickFormatFunction(t[e].value,e,t));return i},getPixelForOffset:function(t){var e=this._offsets,n=oi(this._table,"time",t,"pos");return this.getPixelForDecimal((e.start+n)*e.factor)},getPixelForValue:function(t,e,n){var i=null;if(void 0!==e&&void 0!==n&&(i=this._timestamps.datasets[n][e]),null===i&&(i=li(this,t)),null!==i)return this.getPixelForOffset(i)},getPixelForTick:function(t){var e=this.getTicks();return t>=0&&t<e.length?this.getPixelForOffset(e[t].value):null},getValueForPixel:function(t){var e=this._offsets,n=this.getDecimalForPixel(t)/e.factor-e.end,i=oi(this._table,"pos",n,"time");return this._adapter._create(i)},_getLabelSize:function(t){var e=this.options.ticks,n=this.ctx.measureText(t).width,i=H.toRadians(this.isHorizontal()?e.maxRotation:e.minRotation),a=Math.cos(i),r=Math.sin(i),o=Jn(e.fontSize,W.global.defaultFontSize);return{w:n*a+o*r,h:n*r+o*a}},getLabelWidth:function(t){return this._getLabelSize(t).w},getLabelCapacity:function(t){var e=this,n=e.options.time,i=n.displayFormats,a=i[n.unit]||i.millisecond,r=e.tickFormatFunction(t,0,di(e,[t],e._majorUnit),a),o=e._getLabelSize(r),s=Math.floor(e.isHorizontal()?e.width/o.w:e.height/o.h);return e.options.offset&&s--,s>0?s:1}}),ci={position:"bottom",distribution:"linear",bounds:"data",adapters:{},time:{parser:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{}},ticks:{autoSkip:!1,source:"auto",major:{enabled:!1}}};hi._defaults=ci;var fi={category:wn,linear:On,logarithmic:Nn,radialLinear:Zn,time:hi},gi=e((function(e,n){e.exports=function(){var n,i;function a(){return n.apply(null,arguments)}function r(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function o(t){return null!=t&&"[object Object]"===Object.prototype.toString.call(t)}function s(t){return void 0===t}function l(t){return"number"==typeof t||"[object Number]"===Object.prototype.toString.call(t)}function u(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function d(t,e){var n,i=[];for(n=0;n<t.length;++n)i.push(e(t[n],n));return i}function h(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function c(t,e){for(var n in e)h(e,n)&&(t[n]=e[n]);return h(e,"toString")&&(t.toString=e.toString),h(e,"valueOf")&&(t.valueOf=e.valueOf),t}function f(t,e,n,i){return Ie(t,e,n,i,!0).utc()}function g(t){return null==t._pf&&(t._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),t._pf}function m(t){if(null==t._isValid){var e=g(t),n=i.call(e.parsedDateParts,(function(t){return null!=t})),a=!isNaN(t._d.getTime())&&e.overflow<0&&!e.empty&&!e.invalidMonth&&!e.invalidWeekday&&!e.weekdayMismatch&&!e.nullInput&&!e.invalidFormat&&!e.userInvalidated&&(!e.meridiem||e.meridiem&&n);if(t._strict&&(a=a&&0===e.charsLeftOver&&0===e.unusedTokens.length&&void 0===e.bigHour),null!=Object.isFrozen&&Object.isFrozen(t))return a;t._isValid=a}return t._isValid}function p(t){var e=f(NaN);return null!=t?c(g(e),t):g(e).userInvalidated=!0,e}i=Array.prototype.some?Array.prototype.some:function(t){for(var e=Object(this),n=e.length>>>0,i=0;i<n;i++)if(i in e&&t.call(this,e[i],i,e))return!0;return!1};var v=a.momentProperties=[];function b(t,e){var n,i,a;if(s(e._isAMomentObject)||(t._isAMomentObject=e._isAMomentObject),s(e._i)||(t._i=e._i),s(e._f)||(t._f=e._f),s(e._l)||(t._l=e._l),s(e._strict)||(t._strict=e._strict),s(e._tzm)||(t._tzm=e._tzm),s(e._isUTC)||(t._isUTC=e._isUTC),s(e._offset)||(t._offset=e._offset),s(e._pf)||(t._pf=g(e)),s(e._locale)||(t._locale=e._locale),v.length>0)for(n=0;n<v.length;n++)s(a=e[i=v[n]])||(t[i]=a);return t}var y=!1;function x(t){b(this,t),this._d=new Date(null!=t._d?t._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===y&&(y=!0,a.updateOffset(this),y=!1)}function _(t){return t instanceof x||null!=t&&null!=t._isAMomentObject}function w(t){return t<0?Math.ceil(t)||0:Math.floor(t)}function k(t){var e=+t,n=0;return 0!==e&&isFinite(e)&&(n=w(e)),n}function M(t,e,n){var i,a=Math.min(t.length,e.length),r=Math.abs(t.length-e.length),o=0;for(i=0;i<a;i++)(n&&t[i]!==e[i]||!n&&k(t[i])!==k(e[i]))&&o++;return o+r}function S(t){!1===a.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}function D(t,e){var n=!0;return c((function(){if(null!=a.deprecationHandler&&a.deprecationHandler(null,t),n){for(var i,r=[],o=0;o<arguments.length;o++){if(i="","object"==typeof arguments[o]){for(var s in i+="\n["+o+"] ",arguments[0])i+=s+": "+arguments[0][s]+", ";i=i.slice(0,-2)}else i=arguments[o];r.push(i)}S(t+"\nArguments: "+Array.prototype.slice.call(r).join("")+"\n"+(new Error).stack),n=!1}return e.apply(this,arguments)}),e)}var C,P={};function T(t,e){null!=a.deprecationHandler&&a.deprecationHandler(t,e),P[t]||(S(e),P[t]=!0)}function O(t){return t instanceof Function||"[object Function]"===Object.prototype.toString.call(t)}function A(t,e){var n,i=c({},t);for(n in e)h(e,n)&&(o(t[n])&&o(e[n])?(i[n]={},c(i[n],t[n]),c(i[n],e[n])):null!=e[n]?i[n]=e[n]:delete i[n]);for(n in t)h(t,n)&&!h(e,n)&&o(t[n])&&(i[n]=c({},i[n]));return i}function F(t){null!=t&&this.set(t)}a.suppressDeprecationWarnings=!1,a.deprecationHandler=null,C=Object.keys?Object.keys:function(t){var e,n=[];for(e in t)h(t,e)&&n.push(e);return n};var I={};function L(t,e){var n=t.toLowerCase();I[n]=I[n+"s"]=I[e]=t}function R(t){return"string"==typeof t?I[t]||I[t.toLowerCase()]:void 0}function N(t){var e,n,i={};for(n in t)h(t,n)&&(e=R(n))&&(i[e]=t[n]);return i}var W={};function Y(t,e){W[t]=e}function z(t,e,n){var i=""+Math.abs(t),a=e-i.length;return(t>=0?n?"+":"":"-")+Math.pow(10,Math.max(0,a)).toString().substr(1)+i}var E=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,V=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,H={},B={};function j(t,e,n,i){var a=i;"string"==typeof i&&(a=function(){return this[i]()}),t&&(B[t]=a),e&&(B[e[0]]=function(){return z(a.apply(this,arguments),e[1],e[2])}),n&&(B[n]=function(){return this.localeData().ordinal(a.apply(this,arguments),t)})}function U(t,e){return t.isValid()?(e=G(e,t.localeData()),H[e]=H[e]||function(t){var e,n,i,a=t.match(E);for(e=0,n=a.length;e<n;e++)B[a[e]]?a[e]=B[a[e]]:a[e]=(i=a[e]).match(/\[[\s\S]/)?i.replace(/^\[|\]$/g,""):i.replace(/\\/g,"");return function(e){var i,r="";for(i=0;i<n;i++)r+=O(a[i])?a[i].call(e,t):a[i];return r}}(e),H[e](t)):t.localeData().invalidDate()}function G(t,e){var n=5;function i(t){return e.longDateFormat(t)||t}for(V.lastIndex=0;n>=0&&V.test(t);)t=t.replace(V,i),V.lastIndex=0,n-=1;return t}var q=/\d/,Z=/\d\d/,$=/\d{3}/,X=/\d{4}/,K=/[+-]?\d{6}/,J=/\d\d?/,Q=/\d\d\d\d?/,tt=/\d\d\d\d\d\d?/,et=/\d{1,3}/,nt=/\d{1,4}/,it=/[+-]?\d{1,6}/,at=/\d+/,rt=/[+-]?\d+/,ot=/Z|[+-]\d\d:?\d\d/gi,st=/Z|[+-]\d\d(?::?\d\d)?/gi,lt=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,ut={};function dt(t,e,n){ut[t]=O(e)?e:function(t,i){return t&&n?n:e}}function ht(t,e){return h(ut,t)?ut[t](e._strict,e._locale):new RegExp(ct(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,(function(t,e,n,i,a){return e||n||i||a}))))}function ct(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var ft={};function gt(t,e){var n,i=e;for("string"==typeof t&&(t=[t]),l(e)&&(i=function(t,n){n[e]=k(t)}),n=0;n<t.length;n++)ft[t[n]]=i}function mt(t,e){gt(t,(function(t,n,i,a){i._w=i._w||{},e(t,i._w,i,a)}))}function pt(t,e,n){null!=e&&h(ft,t)&&ft[t](e,n._a,n,t)}var vt=0,bt=1,yt=2,xt=3,_t=4,wt=5,kt=6,Mt=7,St=8;function Dt(t){return Ct(t)?366:365}function Ct(t){return t%4==0&&t%100!=0||t%400==0}j("Y",0,0,(function(){var t=this.year();return t<=9999?""+t:"+"+t})),j(0,["YY",2],0,(function(){return this.year()%100})),j(0,["YYYY",4],0,"year"),j(0,["YYYYY",5],0,"year"),j(0,["YYYYYY",6,!0],0,"year"),L("year","y"),Y("year",1),dt("Y",rt),dt("YY",J,Z),dt("YYYY",nt,X),dt("YYYYY",it,K),dt("YYYYYY",it,K),gt(["YYYYY","YYYYYY"],vt),gt("YYYY",(function(t,e){e[vt]=2===t.length?a.parseTwoDigitYear(t):k(t)})),gt("YY",(function(t,e){e[vt]=a.parseTwoDigitYear(t)})),gt("Y",(function(t,e){e[vt]=parseInt(t,10)})),a.parseTwoDigitYear=function(t){return k(t)+(k(t)>68?1900:2e3)};var Pt,Tt=Ot("FullYear",!0);function Ot(t,e){return function(n){return null!=n?(Ft(this,t,n),a.updateOffset(this,e),this):At(this,t)}}function At(t,e){return t.isValid()?t._d["get"+(t._isUTC?"UTC":"")+e]():NaN}function Ft(t,e,n){t.isValid()&&!isNaN(n)&&("FullYear"===e&&Ct(t.year())&&1===t.month()&&29===t.date()?t._d["set"+(t._isUTC?"UTC":"")+e](n,t.month(),It(n,t.month())):t._d["set"+(t._isUTC?"UTC":"")+e](n))}function It(t,e){if(isNaN(t)||isNaN(e))return NaN;var n=function(t,e){return(t%e+e)%e}(e,12);return t+=(e-n)/12,1===n?Ct(t)?29:28:31-n%7%2}Pt=Array.prototype.indexOf?Array.prototype.indexOf:function(t){var e;for(e=0;e<this.length;++e)if(this[e]===t)return e;return-1},j("M",["MM",2],"Mo",(function(){return this.month()+1})),j("MMM",0,0,(function(t){return this.localeData().monthsShort(this,t)})),j("MMMM",0,0,(function(t){return this.localeData().months(this,t)})),L("month","M"),Y("month",8),dt("M",J),dt("MM",J,Z),dt("MMM",(function(t,e){return e.monthsShortRegex(t)})),dt("MMMM",(function(t,e){return e.monthsRegex(t)})),gt(["M","MM"],(function(t,e){e[bt]=k(t)-1})),gt(["MMM","MMMM"],(function(t,e,n,i){var a=n._locale.monthsParse(t,i,n._strict);null!=a?e[bt]=a:g(n).invalidMonth=t}));var Lt=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Rt="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),Nt="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_");function Wt(t,e,n){var i,a,r,o=t.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],i=0;i<12;++i)r=f([2e3,i]),this._shortMonthsParse[i]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[i]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===e?-1!==(a=Pt.call(this._shortMonthsParse,o))?a:null:-1!==(a=Pt.call(this._longMonthsParse,o))?a:null:"MMM"===e?-1!==(a=Pt.call(this._shortMonthsParse,o))?a:-1!==(a=Pt.call(this._longMonthsParse,o))?a:null:-1!==(a=Pt.call(this._longMonthsParse,o))?a:-1!==(a=Pt.call(this._shortMonthsParse,o))?a:null}function Yt(t,e){var n;if(!t.isValid())return t;if("string"==typeof e)if(/^\d+$/.test(e))e=k(e);else if(!l(e=t.localeData().monthsParse(e)))return t;return n=Math.min(t.date(),It(t.year(),e)),t._d["set"+(t._isUTC?"UTC":"")+"Month"](e,n),t}function zt(t){return null!=t?(Yt(this,t),a.updateOffset(this,!0),this):At(this,"Month")}var Et=lt,Vt=lt;function Ht(){function t(t,e){return e.length-t.length}var e,n,i=[],a=[],r=[];for(e=0;e<12;e++)n=f([2e3,e]),i.push(this.monthsShort(n,"")),a.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(i.sort(t),a.sort(t),r.sort(t),e=0;e<12;e++)i[e]=ct(i[e]),a[e]=ct(a[e]);for(e=0;e<24;e++)r[e]=ct(r[e]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+i.join("|")+")","i")}function Bt(t,e,n,i,a,r,o){var s;return t<100&&t>=0?(s=new Date(t+400,e,n,i,a,r,o),isFinite(s.getFullYear())&&s.setFullYear(t)):s=new Date(t,e,n,i,a,r,o),s}function jt(t){var e;if(t<100&&t>=0){var n=Array.prototype.slice.call(arguments);n[0]=t+400,e=new Date(Date.UTC.apply(null,n)),isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t)}else e=new Date(Date.UTC.apply(null,arguments));return e}function Ut(t,e,n){var i=7+e-n;return-(7+jt(t,0,i).getUTCDay()-e)%7+i-1}function Gt(t,e,n,i,a){var r,o,s=1+7*(e-1)+(7+n-i)%7+Ut(t,i,a);return s<=0?o=Dt(r=t-1)+s:s>Dt(t)?(r=t+1,o=s-Dt(t)):(r=t,o=s),{year:r,dayOfYear:o}}function qt(t,e,n){var i,a,r=Ut(t.year(),e,n),o=Math.floor((t.dayOfYear()-r-1)/7)+1;return o<1?i=o+Zt(a=t.year()-1,e,n):o>Zt(t.year(),e,n)?(i=o-Zt(t.year(),e,n),a=t.year()+1):(a=t.year(),i=o),{week:i,year:a}}function Zt(t,e,n){var i=Ut(t,e,n),a=Ut(t+1,e,n);return(Dt(t)-i+a)/7}function $t(t,e){return t.slice(e,7).concat(t.slice(0,e))}j("w",["ww",2],"wo","week"),j("W",["WW",2],"Wo","isoWeek"),L("week","w"),L("isoWeek","W"),Y("week",5),Y("isoWeek",5),dt("w",J),dt("ww",J,Z),dt("W",J),dt("WW",J,Z),mt(["w","ww","W","WW"],(function(t,e,n,i){e[i.substr(0,1)]=k(t)})),j("d",0,"do","day"),j("dd",0,0,(function(t){return this.localeData().weekdaysMin(this,t)})),j("ddd",0,0,(function(t){return this.localeData().weekdaysShort(this,t)})),j("dddd",0,0,(function(t){return this.localeData().weekdays(this,t)})),j("e",0,0,"weekday"),j("E",0,0,"isoWeekday"),L("day","d"),L("weekday","e"),L("isoWeekday","E"),Y("day",11),Y("weekday",11),Y("isoWeekday",11),dt("d",J),dt("e",J),dt("E",J),dt("dd",(function(t,e){return e.weekdaysMinRegex(t)})),dt("ddd",(function(t,e){return e.weekdaysShortRegex(t)})),dt("dddd",(function(t,e){return e.weekdaysRegex(t)})),mt(["dd","ddd","dddd"],(function(t,e,n,i){var a=n._locale.weekdaysParse(t,i,n._strict);null!=a?e.d=a:g(n).invalidWeekday=t})),mt(["d","e","E"],(function(t,e,n,i){e[i]=k(t)}));var Xt="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Kt="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Jt="Su_Mo_Tu_We_Th_Fr_Sa".split("_");function Qt(t,e,n){var i,a,r,o=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],i=0;i<7;++i)r=f([2e3,1]).day(i),this._minWeekdaysParse[i]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[i]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[i]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===e?-1!==(a=Pt.call(this._weekdaysParse,o))?a:null:"ddd"===e?-1!==(a=Pt.call(this._shortWeekdaysParse,o))?a:null:-1!==(a=Pt.call(this._minWeekdaysParse,o))?a:null:"dddd"===e?-1!==(a=Pt.call(this._weekdaysParse,o))?a:-1!==(a=Pt.call(this._shortWeekdaysParse,o))?a:-1!==(a=Pt.call(this._minWeekdaysParse,o))?a:null:"ddd"===e?-1!==(a=Pt.call(this._shortWeekdaysParse,o))?a:-1!==(a=Pt.call(this._weekdaysParse,o))?a:-1!==(a=Pt.call(this._minWeekdaysParse,o))?a:null:-1!==(a=Pt.call(this._minWeekdaysParse,o))?a:-1!==(a=Pt.call(this._weekdaysParse,o))?a:-1!==(a=Pt.call(this._shortWeekdaysParse,o))?a:null}var te=lt,ee=lt,ne=lt;function ie(){function t(t,e){return e.length-t.length}var e,n,i,a,r,o=[],s=[],l=[],u=[];for(e=0;e<7;e++)n=f([2e3,1]).day(e),i=this.weekdaysMin(n,""),a=this.weekdaysShort(n,""),r=this.weekdays(n,""),o.push(i),s.push(a),l.push(r),u.push(i),u.push(a),u.push(r);for(o.sort(t),s.sort(t),l.sort(t),u.sort(t),e=0;e<7;e++)s[e]=ct(s[e]),l[e]=ct(l[e]),u[e]=ct(u[e]);this._weekdaysRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+o.join("|")+")","i")}function ae(){return this.hours()%12||12}function re(t,e){j(t,0,0,(function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)}))}function oe(t,e){return e._meridiemParse}j("H",["HH",2],0,"hour"),j("h",["hh",2],0,ae),j("k",["kk",2],0,(function(){return this.hours()||24})),j("hmm",0,0,(function(){return""+ae.apply(this)+z(this.minutes(),2)})),j("hmmss",0,0,(function(){return""+ae.apply(this)+z(this.minutes(),2)+z(this.seconds(),2)})),j("Hmm",0,0,(function(){return""+this.hours()+z(this.minutes(),2)})),j("Hmmss",0,0,(function(){return""+this.hours()+z(this.minutes(),2)+z(this.seconds(),2)})),re("a",!0),re("A",!1),L("hour","h"),Y("hour",13),dt("a",oe),dt("A",oe),dt("H",J),dt("h",J),dt("k",J),dt("HH",J,Z),dt("hh",J,Z),dt("kk",J,Z),dt("hmm",Q),dt("hmmss",tt),dt("Hmm",Q),dt("Hmmss",tt),gt(["H","HH"],xt),gt(["k","kk"],(function(t,e,n){var i=k(t);e[xt]=24===i?0:i})),gt(["a","A"],(function(t,e,n){n._isPm=n._locale.isPM(t),n._meridiem=t})),gt(["h","hh"],(function(t,e,n){e[xt]=k(t),g(n).bigHour=!0})),gt("hmm",(function(t,e,n){var i=t.length-2;e[xt]=k(t.substr(0,i)),e[_t]=k(t.substr(i)),g(n).bigHour=!0})),gt("hmmss",(function(t,e,n){var i=t.length-4,a=t.length-2;e[xt]=k(t.substr(0,i)),e[_t]=k(t.substr(i,2)),e[wt]=k(t.substr(a)),g(n).bigHour=!0})),gt("Hmm",(function(t,e,n){var i=t.length-2;e[xt]=k(t.substr(0,i)),e[_t]=k(t.substr(i))})),gt("Hmmss",(function(t,e,n){var i=t.length-4,a=t.length-2;e[xt]=k(t.substr(0,i)),e[_t]=k(t.substr(i,2)),e[wt]=k(t.substr(a))}));var se,le=Ot("Hours",!0),ue={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Rt,monthsShort:Nt,week:{dow:0,doy:6},weekdays:Xt,weekdaysMin:Jt,weekdaysShort:Kt,meridiemParse:/[ap]\.?m?\.?/i},de={},he={};function ce(t){return t?t.toLowerCase().replace("_","-"):t}function fe(n){var i=null;if(!de[n]&&e&&e.exports)try{i=se._abbr,t(),ge(i)}catch(t){}return de[n]}function ge(t,e){var n;return t&&((n=s(e)?pe(t):me(t,e))?se=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+t+" not found. Did you forget to load it?")),se._abbr}function me(t,e){if(null!==e){var n,i=ue;if(e.abbr=t,null!=de[t])T("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),i=de[t]._config;else if(null!=e.parentLocale)if(null!=de[e.parentLocale])i=de[e.parentLocale]._config;else{if(null==(n=fe(e.parentLocale)))return he[e.parentLocale]||(he[e.parentLocale]=[]),he[e.parentLocale].push({name:t,config:e}),null;i=n._config}return de[t]=new F(A(i,e)),he[t]&&he[t].forEach((function(t){me(t.name,t.config)})),ge(t),de[t]}return delete de[t],null}function pe(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return se;if(!r(t)){if(e=fe(t))return e;t=[t]}return function(t){for(var e,n,i,a,r=0;r<t.length;){for(e=(a=ce(t[r]).split("-")).length,n=(n=ce(t[r+1]))?n.split("-"):null;e>0;){if(i=fe(a.slice(0,e).join("-")))return i;if(n&&n.length>=e&&M(a,n,!0)>=e-1)break;e--}r++}return se}(t)}function ve(t){var e,n=t._a;return n&&-2===g(t).overflow&&(e=n[bt]<0||n[bt]>11?bt:n[yt]<1||n[yt]>It(n[vt],n[bt])?yt:n[xt]<0||n[xt]>24||24===n[xt]&&(0!==n[_t]||0!==n[wt]||0!==n[kt])?xt:n[_t]<0||n[_t]>59?_t:n[wt]<0||n[wt]>59?wt:n[kt]<0||n[kt]>999?kt:-1,g(t)._overflowDayOfYear&&(e<vt||e>yt)&&(e=yt),g(t)._overflowWeeks&&-1===e&&(e=Mt),g(t)._overflowWeekday&&-1===e&&(e=St),g(t).overflow=e),t}function be(t,e,n){return null!=t?t:null!=e?e:n}function ye(t){var e,n,i,r,o,s=[];if(!t._d){for(i=function(t){var e=new Date(a.now());return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}(t),t._w&&null==t._a[yt]&&null==t._a[bt]&&function(t){var e,n,i,a,r,o,s,l;if(null!=(e=t._w).GG||null!=e.W||null!=e.E)r=1,o=4,n=be(e.GG,t._a[vt],qt(Le(),1,4).year),i=be(e.W,1),((a=be(e.E,1))<1||a>7)&&(l=!0);else{r=t._locale._week.dow,o=t._locale._week.doy;var u=qt(Le(),r,o);n=be(e.gg,t._a[vt],u.year),i=be(e.w,u.week),null!=e.d?((a=e.d)<0||a>6)&&(l=!0):null!=e.e?(a=e.e+r,(e.e<0||e.e>6)&&(l=!0)):a=r}i<1||i>Zt(n,r,o)?g(t)._overflowWeeks=!0:null!=l?g(t)._overflowWeekday=!0:(s=Gt(n,i,a,r,o),t._a[vt]=s.year,t._dayOfYear=s.dayOfYear)}(t),null!=t._dayOfYear&&(o=be(t._a[vt],i[vt]),(t._dayOfYear>Dt(o)||0===t._dayOfYear)&&(g(t)._overflowDayOfYear=!0),n=jt(o,0,t._dayOfYear),t._a[bt]=n.getUTCMonth(),t._a[yt]=n.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=s[e]=i[e];for(;e<7;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[xt]&&0===t._a[_t]&&0===t._a[wt]&&0===t._a[kt]&&(t._nextDay=!0,t._a[xt]=0),t._d=(t._useUTC?jt:Bt).apply(null,s),r=t._useUTC?t._d.getUTCDay():t._d.getDay(),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[xt]=24),t._w&&void 0!==t._w.d&&t._w.d!==r&&(g(t).weekdayMismatch=!0)}}var xe=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,_e=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,we=/Z|[+-]\d\d(?::?\d\d)?/,ke=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Me=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Se=/^\/?Date\((\-?\d+)/i;function De(t){var e,n,i,a,r,o,s=t._i,l=xe.exec(s)||_e.exec(s);if(l){for(g(t).iso=!0,e=0,n=ke.length;e<n;e++)if(ke[e][1].exec(l[1])){a=ke[e][0],i=!1!==ke[e][2];break}if(null==a)return void(t._isValid=!1);if(l[3]){for(e=0,n=Me.length;e<n;e++)if(Me[e][1].exec(l[3])){r=(l[2]||" ")+Me[e][0];break}if(null==r)return void(t._isValid=!1)}if(!i&&null!=r)return void(t._isValid=!1);if(l[4]){if(!we.exec(l[4]))return void(t._isValid=!1);o="Z"}t._f=a+(r||"")+(o||""),Ae(t)}else t._isValid=!1}var Ce=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;function Pe(t){var e=parseInt(t,10);return e<=49?2e3+e:e<=999?1900+e:e}var Te={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function Oe(t){var e,n,i,a,r,o,s,l=Ce.exec(t._i.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s\s*/,"").replace(/\s\s*$/,""));if(l){var u=(e=l[4],n=l[3],i=l[2],a=l[5],r=l[6],o=l[7],s=[Pe(e),Nt.indexOf(n),parseInt(i,10),parseInt(a,10),parseInt(r,10)],o&&s.push(parseInt(o,10)),s);if(!function(t,e,n){return!t||Kt.indexOf(t)===new Date(e[0],e[1],e[2]).getDay()||(g(n).weekdayMismatch=!0,n._isValid=!1,!1)}(l[1],u,t))return;t._a=u,t._tzm=function(t,e,n){if(t)return Te[t];if(e)return 0;var i=parseInt(n,10),a=i%100;return(i-a)/100*60+a}(l[8],l[9],l[10]),t._d=jt.apply(null,t._a),t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),g(t).rfc2822=!0}else t._isValid=!1}function Ae(t){if(t._f!==a.ISO_8601)if(t._f!==a.RFC_2822){t._a=[],g(t).empty=!0;var e,n,i,r,o,s=""+t._i,l=s.length,u=0;for(i=G(t._f,t._locale).match(E)||[],e=0;e<i.length;e++)r=i[e],(n=(s.match(ht(r,t))||[])[0])&&((o=s.substr(0,s.indexOf(n))).length>0&&g(t).unusedInput.push(o),s=s.slice(s.indexOf(n)+n.length),u+=n.length),B[r]?(n?g(t).empty=!1:g(t).unusedTokens.push(r),pt(r,n,t)):t._strict&&!n&&g(t).unusedTokens.push(r);g(t).charsLeftOver=l-u,s.length>0&&g(t).unusedInput.push(s),t._a[xt]<=12&&!0===g(t).bigHour&&t._a[xt]>0&&(g(t).bigHour=void 0),g(t).parsedDateParts=t._a.slice(0),g(t).meridiem=t._meridiem,t._a[xt]=function(t,e,n){var i;return null==n?e:null!=t.meridiemHour?t.meridiemHour(e,n):null!=t.isPM?((i=t.isPM(n))&&e<12&&(e+=12),i||12!==e||(e=0),e):e}(t._locale,t._a[xt],t._meridiem),ye(t),ve(t)}else Oe(t);else De(t)}function Fe(t){var e=t._i,n=t._f;return t._locale=t._locale||pe(t._l),null===e||void 0===n&&""===e?p({nullInput:!0}):("string"==typeof e&&(t._i=e=t._locale.preparse(e)),_(e)?new x(ve(e)):(u(e)?t._d=e:r(n)?function(t){var e,n,i,a,r;if(0===t._f.length)return g(t).invalidFormat=!0,void(t._d=new Date(NaN));for(a=0;a<t._f.length;a++)r=0,e=b({},t),null!=t._useUTC&&(e._useUTC=t._useUTC),e._f=t._f[a],Ae(e),m(e)&&(r+=g(e).charsLeftOver,r+=10*g(e).unusedTokens.length,g(e).score=r,(null==i||r<i)&&(i=r,n=e));c(t,n||e)}(t):n?Ae(t):function(t){var e=t._i;s(e)?t._d=new Date(a.now()):u(e)?t._d=new Date(e.valueOf()):"string"==typeof e?function(t){var e=Se.exec(t._i);null===e?(De(t),!1===t._isValid&&(delete t._isValid,Oe(t),!1===t._isValid&&(delete t._isValid,a.createFromInputFallback(t)))):t._d=new Date(+e[1])}(t):r(e)?(t._a=d(e.slice(0),(function(t){return parseInt(t,10)})),ye(t)):o(e)?function(t){if(!t._d){var e=N(t._i);t._a=d([e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],(function(t){return t&&parseInt(t,10)})),ye(t)}}(t):l(e)?t._d=new Date(e):a.createFromInputFallback(t)}(t),m(t)||(t._d=null),t))}function Ie(t,e,n,i,a){var s,l={};return!0!==n&&!1!==n||(i=n,n=void 0),(o(t)&&function(t){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(t).length;var e;for(e in t)if(t.hasOwnProperty(e))return!1;return!0}(t)||r(t)&&0===t.length)&&(t=void 0),l._isAMomentObject=!0,l._useUTC=l._isUTC=a,l._l=n,l._i=t,l._f=e,l._strict=i,(s=new x(ve(Fe(l))))._nextDay&&(s.add(1,"d"),s._nextDay=void 0),s}function Le(t,e,n,i){return Ie(t,e,n,i,!1)}a.createFromInputFallback=D("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",(function(t){t._d=new Date(t._i+(t._useUTC?" UTC":""))})),a.ISO_8601=function(){},a.RFC_2822=function(){};var Re=D("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",(function(){var t=Le.apply(null,arguments);return this.isValid()&&t.isValid()?t<this?this:t:p()})),Ne=D("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",(function(){var t=Le.apply(null,arguments);return this.isValid()&&t.isValid()?t>this?this:t:p()}));function We(t,e){var n,i;if(1===e.length&&r(e[0])&&(e=e[0]),!e.length)return Le();for(n=e[0],i=1;i<e.length;++i)e[i].isValid()&&!e[i][t](n)||(n=e[i]);return n}var Ye=["year","quarter","month","week","day","hour","minute","second","millisecond"];function ze(t){var e=N(t),n=e.year||0,i=e.quarter||0,a=e.month||0,r=e.week||e.isoWeek||0,o=e.day||0,s=e.hour||0,l=e.minute||0,u=e.second||0,d=e.millisecond||0;this._isValid=function(t){for(var e in t)if(-1===Pt.call(Ye,e)||null!=t[e]&&isNaN(t[e]))return!1;for(var n=!1,i=0;i<Ye.length;++i)if(t[Ye[i]]){if(n)return!1;parseFloat(t[Ye[i]])!==k(t[Ye[i]])&&(n=!0)}return!0}(e),this._milliseconds=+d+1e3*u+6e4*l+1e3*s*60*60,this._days=+o+7*r,this._months=+a+3*i+12*n,this._data={},this._locale=pe(),this._bubble()}function Ee(t){return t instanceof ze}function Ve(t){return t<0?-1*Math.round(-1*t):Math.round(t)}function He(t,e){j(t,0,0,(function(){var t=this.utcOffset(),n="+";return t<0&&(t=-t,n="-"),n+z(~~(t/60),2)+e+z(~~t%60,2)}))}He("Z",":"),He("ZZ",""),dt("Z",st),dt("ZZ",st),gt(["Z","ZZ"],(function(t,e,n){n._useUTC=!0,n._tzm=je(st,t)}));var Be=/([\+\-]|\d\d)/gi;function je(t,e){var n=(e||"").match(t);if(null===n)return null;var i=((n[n.length-1]||[])+"").match(Be)||["-",0,0],a=60*i[1]+k(i[2]);return 0===a?0:"+"===i[0]?a:-a}function Ue(t,e){var n,i;return e._isUTC?(n=e.clone(),i=(_(t)||u(t)?t.valueOf():Le(t).valueOf())-n.valueOf(),n._d.setTime(n._d.valueOf()+i),a.updateOffset(n,!1),n):Le(t).local()}function Ge(t){return 15*-Math.round(t._d.getTimezoneOffset()/15)}function qe(){return!!this.isValid()&&this._isUTC&&0===this._offset}a.updateOffset=function(){};var Ze=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,$e=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function Xe(t,e){var n,i,a,r,o,s,u=t,d=null;return Ee(t)?u={ms:t._milliseconds,d:t._days,M:t._months}:l(t)?(u={},e?u[e]=t:u.milliseconds=t):(d=Ze.exec(t))?(n="-"===d[1]?-1:1,u={y:0,d:k(d[yt])*n,h:k(d[xt])*n,m:k(d[_t])*n,s:k(d[wt])*n,ms:k(Ve(1e3*d[kt]))*n}):(d=$e.exec(t))?(n="-"===d[1]?-1:1,u={y:Ke(d[2],n),M:Ke(d[3],n),w:Ke(d[4],n),d:Ke(d[5],n),h:Ke(d[6],n),m:Ke(d[7],n),s:Ke(d[8],n)}):null==u?u={}:"object"==typeof u&&("from"in u||"to"in u)&&(r=Le(u.from),o=Le(u.to),a=r.isValid()&&o.isValid()?(o=Ue(o,r),r.isBefore(o)?s=Je(r,o):((s=Je(o,r)).milliseconds=-s.milliseconds,s.months=-s.months),s):{milliseconds:0,months:0},(u={}).ms=a.milliseconds,u.M=a.months),i=new ze(u),Ee(t)&&h(t,"_locale")&&(i._locale=t._locale),i}function Ke(t,e){var n=t&&parseFloat(t.replace(",","."));return(isNaN(n)?0:n)*e}function Je(t,e){var n={};return n.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(n.months,"M").isAfter(e)&&--n.months,n.milliseconds=+e-+t.clone().add(n.months,"M"),n}function Qe(t,e){return function(n,i){var a;return null===i||isNaN(+i)||(T(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),a=n,n=i,i=a),tn(this,Xe(n="string"==typeof n?+n:n,i),t),this}}function tn(t,e,n,i){var r=e._milliseconds,o=Ve(e._days),s=Ve(e._months);t.isValid()&&(i=null==i||i,s&&Yt(t,At(t,"Month")+s*n),o&&Ft(t,"Date",At(t,"Date")+o*n),r&&t._d.setTime(t._d.valueOf()+r*n),i&&a.updateOffset(t,o||s))}Xe.fn=ze.prototype,Xe.invalid=function(){return Xe(NaN)};var en=Qe(1,"add"),nn=Qe(-1,"subtract");function an(t,e){var n=12*(e.year()-t.year())+(e.month()-t.month()),i=t.clone().add(n,"months");return-(n+(e-i<0?(e-i)/(i-t.clone().add(n-1,"months")):(e-i)/(t.clone().add(n+1,"months")-i)))||0}function rn(t){var e;return void 0===t?this._locale._abbr:(null!=(e=pe(t))&&(this._locale=e),this)}a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",a.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var on=D("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",(function(t){return void 0===t?this.localeData():this.locale(t)}));function sn(){return this._locale}var ln=1e3,un=60*ln,dn=60*un,hn=3506328*dn;function cn(t,e){return(t%e+e)%e}function fn(t,e,n){return t<100&&t>=0?new Date(t+400,e,n)-hn:new Date(t,e,n).valueOf()}function gn(t,e,n){return t<100&&t>=0?Date.UTC(t+400,e,n)-hn:Date.UTC(t,e,n)}function mn(t,e){j(0,[t,t.length],0,e)}function pn(t,e,n,i,a){var r;return null==t?qt(this,i,a).year:(e>(r=Zt(t,i,a))&&(e=r),vn.call(this,t,e,n,i,a))}function vn(t,e,n,i,a){var r=Gt(t,e,n,i,a),o=jt(r.year,0,r.dayOfYear);return this.year(o.getUTCFullYear()),this.month(o.getUTCMonth()),this.date(o.getUTCDate()),this}j(0,["gg",2],0,(function(){return this.weekYear()%100})),j(0,["GG",2],0,(function(){return this.isoWeekYear()%100})),mn("gggg","weekYear"),mn("ggggg","weekYear"),mn("GGGG","isoWeekYear"),mn("GGGGG","isoWeekYear"),L("weekYear","gg"),L("isoWeekYear","GG"),Y("weekYear",1),Y("isoWeekYear",1),dt("G",rt),dt("g",rt),dt("GG",J,Z),dt("gg",J,Z),dt("GGGG",nt,X),dt("gggg",nt,X),dt("GGGGG",it,K),dt("ggggg",it,K),mt(["gggg","ggggg","GGGG","GGGGG"],(function(t,e,n,i){e[i.substr(0,2)]=k(t)})),mt(["gg","GG"],(function(t,e,n,i){e[i]=a.parseTwoDigitYear(t)})),j("Q",0,"Qo","quarter"),L("quarter","Q"),Y("quarter",7),dt("Q",q),gt("Q",(function(t,e){e[bt]=3*(k(t)-1)})),j("D",["DD",2],"Do","date"),L("date","D"),Y("date",9),dt("D",J),dt("DD",J,Z),dt("Do",(function(t,e){return t?e._dayOfMonthOrdinalParse||e._ordinalParse:e._dayOfMonthOrdinalParseLenient})),gt(["D","DD"],yt),gt("Do",(function(t,e){e[yt]=k(t.match(J)[0])}));var bn=Ot("Date",!0);j("DDD",["DDDD",3],"DDDo","dayOfYear"),L("dayOfYear","DDD"),Y("dayOfYear",4),dt("DDD",et),dt("DDDD",$),gt(["DDD","DDDD"],(function(t,e,n){n._dayOfYear=k(t)})),j("m",["mm",2],0,"minute"),L("minute","m"),Y("minute",14),dt("m",J),dt("mm",J,Z),gt(["m","mm"],_t);var yn=Ot("Minutes",!1);j("s",["ss",2],0,"second"),L("second","s"),Y("second",15),dt("s",J),dt("ss",J,Z),gt(["s","ss"],wt);var xn,_n=Ot("Seconds",!1);for(j("S",0,0,(function(){return~~(this.millisecond()/100)})),j(0,["SS",2],0,(function(){return~~(this.millisecond()/10)})),j(0,["SSS",3],0,"millisecond"),j(0,["SSSS",4],0,(function(){return 10*this.millisecond()})),j(0,["SSSSS",5],0,(function(){return 100*this.millisecond()})),j(0,["SSSSSS",6],0,(function(){return 1e3*this.millisecond()})),j(0,["SSSSSSS",7],0,(function(){return 1e4*this.millisecond()})),j(0,["SSSSSSSS",8],0,(function(){return 1e5*this.millisecond()})),j(0,["SSSSSSSSS",9],0,(function(){return 1e6*this.millisecond()})),L("millisecond","ms"),Y("millisecond",16),dt("S",et,q),dt("SS",et,Z),dt("SSS",et,$),xn="SSSS";xn.length<=9;xn+="S")dt(xn,at);function wn(t,e){e[kt]=k(1e3*("0."+t))}for(xn="S";xn.length<=9;xn+="S")gt(xn,wn);var kn=Ot("Milliseconds",!1);j("z",0,0,"zoneAbbr"),j("zz",0,0,"zoneName");var Mn=x.prototype;function Sn(t){return t}Mn.add=en,Mn.calendar=function(t,e){var n=t||Le(),i=Ue(n,this).startOf("day"),r=a.calendarFormat(this,i)||"sameElse",o=e&&(O(e[r])?e[r].call(this,n):e[r]);return this.format(o||this.localeData().calendar(r,this,Le(n)))},Mn.clone=function(){return new x(this)},Mn.diff=function(t,e,n){var i,a,r;if(!this.isValid())return NaN;if(!(i=Ue(t,this)).isValid())return NaN;switch(a=6e4*(i.utcOffset()-this.utcOffset()),e=R(e)){case"year":r=an(this,i)/12;break;case"month":r=an(this,i);break;case"quarter":r=an(this,i)/3;break;case"second":r=(this-i)/1e3;break;case"minute":r=(this-i)/6e4;break;case"hour":r=(this-i)/36e5;break;case"day":r=(this-i-a)/864e5;break;case"week":r=(this-i-a)/6048e5;break;default:r=this-i}return n?r:w(r)},Mn.endOf=function(t){var e;if(void 0===(t=R(t))||"millisecond"===t||!this.isValid())return this;var n=this._isUTC?gn:fn;switch(t){case"year":e=n(this.year()+1,0,1)-1;break;case"quarter":e=n(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":e=n(this.year(),this.month()+1,1)-1;break;case"week":e=n(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":e=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":e=n(this.year(),this.month(),this.date()+1)-1;break;case"hour":e=this._d.valueOf(),e+=dn-cn(e+(this._isUTC?0:this.utcOffset()*un),dn)-1;break;case"minute":e=this._d.valueOf(),e+=un-cn(e,un)-1;break;case"second":e=this._d.valueOf(),e+=ln-cn(e,ln)-1}return this._d.setTime(e),a.updateOffset(this,!0),this},Mn.format=function(t){t||(t=this.isUtc()?a.defaultFormatUtc:a.defaultFormat);var e=U(this,t);return this.localeData().postformat(e)},Mn.from=function(t,e){return this.isValid()&&(_(t)&&t.isValid()||Le(t).isValid())?Xe({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},Mn.fromNow=function(t){return this.from(Le(),t)},Mn.to=function(t,e){return this.isValid()&&(_(t)&&t.isValid()||Le(t).isValid())?Xe({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},Mn.toNow=function(t){return this.to(Le(),t)},Mn.get=function(t){return O(this[t=R(t)])?this[t]():this},Mn.invalidAt=function(){return g(this).overflow},Mn.isAfter=function(t,e){var n=_(t)?t:Le(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=R(e)||"millisecond")?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(e).valueOf())},Mn.isBefore=function(t,e){var n=_(t)?t:Le(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=R(e)||"millisecond")?this.valueOf()<n.valueOf():this.clone().endOf(e).valueOf()<n.valueOf())},Mn.isBetween=function(t,e,n,i){var a=_(t)?t:Le(t),r=_(e)?e:Le(e);return!!(this.isValid()&&a.isValid()&&r.isValid())&&("("===(i=i||"()")[0]?this.isAfter(a,n):!this.isBefore(a,n))&&(")"===i[1]?this.isBefore(r,n):!this.isAfter(r,n))},Mn.isSame=function(t,e){var n,i=_(t)?t:Le(t);return!(!this.isValid()||!i.isValid())&&("millisecond"===(e=R(e)||"millisecond")?this.valueOf()===i.valueOf():(n=i.valueOf(),this.clone().startOf(e).valueOf()<=n&&n<=this.clone().endOf(e).valueOf()))},Mn.isSameOrAfter=function(t,e){return this.isSame(t,e)||this.isAfter(t,e)},Mn.isSameOrBefore=function(t,e){return this.isSame(t,e)||this.isBefore(t,e)},Mn.isValid=function(){return m(this)},Mn.lang=on,Mn.locale=rn,Mn.localeData=sn,Mn.max=Ne,Mn.min=Re,Mn.parsingFlags=function(){return c({},g(this))},Mn.set=function(t,e){if("object"==typeof t)for(var n=function(t){var e=[];for(var n in t)e.push({unit:n,priority:W[n]});return e.sort((function(t,e){return t.priority-e.priority})),e}(t=N(t)),i=0;i<n.length;i++)this[n[i].unit](t[n[i].unit]);else if(O(this[t=R(t)]))return this[t](e);return this},Mn.startOf=function(t){var e;if(void 0===(t=R(t))||"millisecond"===t||!this.isValid())return this;var n=this._isUTC?gn:fn;switch(t){case"year":e=n(this.year(),0,1);break;case"quarter":e=n(this.year(),this.month()-this.month()%3,1);break;case"month":e=n(this.year(),this.month(),1);break;case"week":e=n(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":e=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":e=n(this.year(),this.month(),this.date());break;case"hour":e=this._d.valueOf(),e-=cn(e+(this._isUTC?0:this.utcOffset()*un),dn);break;case"minute":e=this._d.valueOf(),e-=cn(e,un);break;case"second":e=this._d.valueOf(),e-=cn(e,ln)}return this._d.setTime(e),a.updateOffset(this,!0),this},Mn.subtract=nn,Mn.toArray=function(){var t=this;return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second(),t.millisecond()]},Mn.toObject=function(){var t=this;return{years:t.year(),months:t.month(),date:t.date(),hours:t.hours(),minutes:t.minutes(),seconds:t.seconds(),milliseconds:t.milliseconds()}},Mn.toDate=function(){return new Date(this.valueOf())},Mn.toISOString=function(t){if(!this.isValid())return null;var e=!0!==t,n=e?this.clone().utc():this;return n.year()<0||n.year()>9999?U(n,e?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):O(Date.prototype.toISOString)?e?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",U(n,"Z")):U(n,e?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},Mn.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t="moment",e="";this.isLocal()||(t=0===this.utcOffset()?"moment.utc":"moment.parseZone",e="Z");var n="["+t+'("]',i=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",a=e+'[")]';return this.format(n+i+"-MM-DD[T]HH:mm:ss.SSS"+a)},Mn.toJSON=function(){return this.isValid()?this.toISOString():null},Mn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},Mn.unix=function(){return Math.floor(this.valueOf()/1e3)},Mn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},Mn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},Mn.year=Tt,Mn.isLeapYear=function(){return Ct(this.year())},Mn.weekYear=function(t){return pn.call(this,t,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},Mn.isoWeekYear=function(t){return pn.call(this,t,this.isoWeek(),this.isoWeekday(),1,4)},Mn.quarter=Mn.quarters=function(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)},Mn.month=zt,Mn.daysInMonth=function(){return It(this.year(),this.month())},Mn.week=Mn.weeks=function(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")},Mn.isoWeek=Mn.isoWeeks=function(t){var e=qt(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")},Mn.weeksInYear=function(){var t=this.localeData()._week;return Zt(this.year(),t.dow,t.doy)},Mn.isoWeeksInYear=function(){return Zt(this.year(),1,4)},Mn.date=bn,Mn.day=Mn.days=function(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=function(t,e){return"string"!=typeof t?t:isNaN(t)?"number"==typeof(t=e.weekdaysParse(t))?t:null:parseInt(t,10)}(t,this.localeData()),this.add(t-e,"d")):e},Mn.weekday=function(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")},Mn.isoWeekday=function(t){if(!this.isValid())return null!=t?this:NaN;if(null!=t){var e=function(t,e){return"string"==typeof t?e.weekdaysParse(t)%7||7:isNaN(t)?null:t}(t,this.localeData());return this.day(this.day()%7?e:e-7)}return this.day()||7},Mn.dayOfYear=function(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")},Mn.hour=Mn.hours=le,Mn.minute=Mn.minutes=yn,Mn.second=Mn.seconds=_n,Mn.millisecond=Mn.milliseconds=kn,Mn.utcOffset=function(t,e,n){var i,r=this._offset||0;if(!this.isValid())return null!=t?this:NaN;if(null!=t){if("string"==typeof t){if(null===(t=je(st,t)))return this}else Math.abs(t)<16&&!n&&(t*=60);return!this._isUTC&&e&&(i=Ge(this)),this._offset=t,this._isUTC=!0,null!=i&&this.add(i,"m"),r!==t&&(!e||this._changeInProgress?tn(this,Xe(t-r,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?r:Ge(this)},Mn.utc=function(t){return this.utcOffset(0,t)},Mn.local=function(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(Ge(this),"m")),this},Mn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var t=je(ot,this._i);null!=t?this.utcOffset(t):this.utcOffset(0,!0)}return this},Mn.hasAlignedHourOffset=function(t){return!!this.isValid()&&(t=t?Le(t).utcOffset():0,(this.utcOffset()-t)%60==0)},Mn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},Mn.isLocal=function(){return!!this.isValid()&&!this._isUTC},Mn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},Mn.isUtc=qe,Mn.isUTC=qe,Mn.zoneAbbr=function(){return this._isUTC?"UTC":""},Mn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},Mn.dates=D("dates accessor is deprecated. Use date instead.",bn),Mn.months=D("months accessor is deprecated. Use month instead",zt),Mn.years=D("years accessor is deprecated. Use year instead",Tt),Mn.zone=D("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",(function(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()})),Mn.isDSTShifted=D("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",(function(){if(!s(this._isDSTShifted))return this._isDSTShifted;var t={};if(b(t,this),(t=Fe(t))._a){var e=t._isUTC?f(t._a):Le(t._a);this._isDSTShifted=this.isValid()&&M(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}));var Dn=F.prototype;function Cn(t,e,n,i){var a=pe(),r=f().set(i,e);return a[n](r,t)}function Pn(t,e,n){if(l(t)&&(e=t,t=void 0),t=t||"",null!=e)return Cn(t,e,n,"month");var i,a=[];for(i=0;i<12;i++)a[i]=Cn(t,i,n,"month");return a}function Tn(t,e,n,i){"boolean"==typeof t?(l(e)&&(n=e,e=void 0),e=e||""):(n=e=t,t=!1,l(e)&&(n=e,e=void 0),e=e||"");var a,r=pe(),o=t?r._week.dow:0;if(null!=n)return Cn(e,(n+o)%7,i,"day");var s=[];for(a=0;a<7;a++)s[a]=Cn(e,(a+o)%7,i,"day");return s}Dn.calendar=function(t,e,n){var i=this._calendar[t]||this._calendar.sameElse;return O(i)?i.call(e,n):i},Dn.longDateFormat=function(t){var e=this._longDateFormat[t],n=this._longDateFormat[t.toUpperCase()];return e||!n?e:(this._longDateFormat[t]=n.replace(/MMMM|MM|DD|dddd/g,(function(t){return t.slice(1)})),this._longDateFormat[t])},Dn.invalidDate=function(){return this._invalidDate},Dn.ordinal=function(t){return this._ordinal.replace("%d",t)},Dn.preparse=Sn,Dn.postformat=Sn,Dn.relativeTime=function(t,e,n,i){var a=this._relativeTime[n];return O(a)?a(t,e,n,i):a.replace(/%d/i,t)},Dn.pastFuture=function(t,e){var n=this._relativeTime[t>0?"future":"past"];return O(n)?n(e):n.replace(/%s/i,e)},Dn.set=function(t){var e,n;for(n in t)O(e=t[n])?this[n]=e:this["_"+n]=e;this._config=t,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},Dn.months=function(t,e){return t?r(this._months)?this._months[t.month()]:this._months[(this._months.isFormat||Lt).test(e)?"format":"standalone"][t.month()]:r(this._months)?this._months:this._months.standalone},Dn.monthsShort=function(t,e){return t?r(this._monthsShort)?this._monthsShort[t.month()]:this._monthsShort[Lt.test(e)?"format":"standalone"][t.month()]:r(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},Dn.monthsParse=function(t,e,n){var i,a,r;if(this._monthsParseExact)return Wt.call(this,t,e,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),i=0;i<12;i++){if(a=f([2e3,i]),n&&!this._longMonthsParse[i]&&(this._longMonthsParse[i]=new RegExp("^"+this.months(a,"").replace(".","")+"$","i"),this._shortMonthsParse[i]=new RegExp("^"+this.monthsShort(a,"").replace(".","")+"$","i")),n||this._monthsParse[i]||(r="^"+this.months(a,"")+"|^"+this.monthsShort(a,""),this._monthsParse[i]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===e&&this._longMonthsParse[i].test(t))return i;if(n&&"MMM"===e&&this._shortMonthsParse[i].test(t))return i;if(!n&&this._monthsParse[i].test(t))return i}},Dn.monthsRegex=function(t){return this._monthsParseExact?(h(this,"_monthsRegex")||Ht.call(this),t?this._monthsStrictRegex:this._monthsRegex):(h(this,"_monthsRegex")||(this._monthsRegex=Vt),this._monthsStrictRegex&&t?this._monthsStrictRegex:this._monthsRegex)},Dn.monthsShortRegex=function(t){return this._monthsParseExact?(h(this,"_monthsRegex")||Ht.call(this),t?this._monthsShortStrictRegex:this._monthsShortRegex):(h(this,"_monthsShortRegex")||(this._monthsShortRegex=Et),this._monthsShortStrictRegex&&t?this._monthsShortStrictRegex:this._monthsShortRegex)},Dn.week=function(t){return qt(t,this._week.dow,this._week.doy).week},Dn.firstDayOfYear=function(){return this._week.doy},Dn.firstDayOfWeek=function(){return this._week.dow},Dn.weekdays=function(t,e){var n=r(this._weekdays)?this._weekdays:this._weekdays[t&&!0!==t&&this._weekdays.isFormat.test(e)?"format":"standalone"];return!0===t?$t(n,this._week.dow):t?n[t.day()]:n},Dn.weekdaysMin=function(t){return!0===t?$t(this._weekdaysMin,this._week.dow):t?this._weekdaysMin[t.day()]:this._weekdaysMin},Dn.weekdaysShort=function(t){return!0===t?$t(this._weekdaysShort,this._week.dow):t?this._weekdaysShort[t.day()]:this._weekdaysShort},Dn.weekdaysParse=function(t,e,n){var i,a,r;if(this._weekdaysParseExact)return Qt.call(this,t,e,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),i=0;i<7;i++){if(a=f([2e3,1]).day(i),n&&!this._fullWeekdaysParse[i]&&(this._fullWeekdaysParse[i]=new RegExp("^"+this.weekdays(a,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[i]=new RegExp("^"+this.weekdaysShort(a,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[i]=new RegExp("^"+this.weekdaysMin(a,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[i]||(r="^"+this.weekdays(a,"")+"|^"+this.weekdaysShort(a,"")+"|^"+this.weekdaysMin(a,""),this._weekdaysParse[i]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===e&&this._fullWeekdaysParse[i].test(t))return i;if(n&&"ddd"===e&&this._shortWeekdaysParse[i].test(t))return i;if(n&&"dd"===e&&this._minWeekdaysParse[i].test(t))return i;if(!n&&this._weekdaysParse[i].test(t))return i}},Dn.weekdaysRegex=function(t){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||ie.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(h(this,"_weekdaysRegex")||(this._weekdaysRegex=te),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)},Dn.weekdaysShortRegex=function(t){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||ie.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(h(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=ee),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},Dn.weekdaysMinRegex=function(t){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||ie.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(h(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=ne),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},Dn.isPM=function(t){return"p"===(t+"").toLowerCase().charAt(0)},Dn.meridiem=function(t,e,n){return t>11?n?"pm":"PM":n?"am":"AM"},ge("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===k(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),a.lang=D("moment.lang is deprecated. Use moment.locale instead.",ge),a.langData=D("moment.langData is deprecated. Use moment.localeData instead.",pe);var On=Math.abs;function An(t,e,n,i){var a=Xe(e,n);return t._milliseconds+=i*a._milliseconds,t._days+=i*a._days,t._months+=i*a._months,t._bubble()}function Fn(t){return t<0?Math.floor(t):Math.ceil(t)}function In(t){return 4800*t/146097}function Ln(t){return 146097*t/4800}function Rn(t){return function(){return this.as(t)}}var Nn=Rn("ms"),Wn=Rn("s"),Yn=Rn("m"),zn=Rn("h"),En=Rn("d"),Vn=Rn("w"),Hn=Rn("M"),Bn=Rn("Q"),jn=Rn("y");function Un(t){return function(){return this.isValid()?this._data[t]:NaN}}var Gn=Un("milliseconds"),qn=Un("seconds"),Zn=Un("minutes"),$n=Un("hours"),Xn=Un("days"),Kn=Un("months"),Jn=Un("years"),Qn=Math.round,ti={ss:44,s:45,m:45,h:22,d:26,M:11};function ei(t,e,n,i,a){return a.relativeTime(e||1,!!n,t,i)}var ni=Math.abs;function ii(t){return(t>0)-(t<0)||+t}function ai(){if(!this.isValid())return this.localeData().invalidDate();var t,e,n=ni(this._milliseconds)/1e3,i=ni(this._days),a=ni(this._months);t=w(n/60),e=w(t/60),n%=60,t%=60;var r=w(a/12),o=a%=12,s=i,l=e,u=t,d=n?n.toFixed(3).replace(/\.?0+$/,""):"",h=this.asSeconds();if(!h)return"P0D";var c=h<0?"-":"",f=ii(this._months)!==ii(h)?"-":"",g=ii(this._days)!==ii(h)?"-":"",m=ii(this._milliseconds)!==ii(h)?"-":"";return c+"P"+(r?f+r+"Y":"")+(o?f+o+"M":"")+(s?g+s+"D":"")+(l||u||d?"T":"")+(l?m+l+"H":"")+(u?m+u+"M":"")+(d?m+d+"S":"")}var ri=ze.prototype;return ri.isValid=function(){return this._isValid},ri.abs=function(){var t=this._data;return this._milliseconds=On(this._milliseconds),this._days=On(this._days),this._months=On(this._months),t.milliseconds=On(t.milliseconds),t.seconds=On(t.seconds),t.minutes=On(t.minutes),t.hours=On(t.hours),t.months=On(t.months),t.years=On(t.years),this},ri.add=function(t,e){return An(this,t,e,1)},ri.subtract=function(t,e){return An(this,t,e,-1)},ri.as=function(t){if(!this.isValid())return NaN;var e,n,i=this._milliseconds;if("month"===(t=R(t))||"quarter"===t||"year"===t)switch(e=this._days+i/864e5,n=this._months+In(e),t){case"month":return n;case"quarter":return n/3;case"year":return n/12}else switch(e=this._days+Math.round(Ln(this._months)),t){case"week":return e/7+i/6048e5;case"day":return e+i/864e5;case"hour":return 24*e+i/36e5;case"minute":return 1440*e+i/6e4;case"second":return 86400*e+i/1e3;case"millisecond":return Math.floor(864e5*e)+i;default:throw new Error("Unknown unit "+t)}},ri.asMilliseconds=Nn,ri.asSeconds=Wn,ri.asMinutes=Yn,ri.asHours=zn,ri.asDays=En,ri.asWeeks=Vn,ri.asMonths=Hn,ri.asQuarters=Bn,ri.asYears=jn,ri.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*k(this._months/12):NaN},ri._bubble=function(){var t,e,n,i,a,r=this._milliseconds,o=this._days,s=this._months,l=this._data;return r>=0&&o>=0&&s>=0||r<=0&&o<=0&&s<=0||(r+=864e5*Fn(Ln(s)+o),o=0,s=0),l.milliseconds=r%1e3,t=w(r/1e3),l.seconds=t%60,e=w(t/60),l.minutes=e%60,n=w(e/60),l.hours=n%24,o+=w(n/24),a=w(In(o)),s+=a,o-=Fn(Ln(a)),i=w(s/12),s%=12,l.days=o,l.months=s,l.years=i,this},ri.clone=function(){return Xe(this)},ri.get=function(t){return t=R(t),this.isValid()?this[t+"s"]():NaN},ri.milliseconds=Gn,ri.seconds=qn,ri.minutes=Zn,ri.hours=$n,ri.days=Xn,ri.weeks=function(){return w(this.days()/7)},ri.months=Kn,ri.years=Jn,ri.humanize=function(t){if(!this.isValid())return this.localeData().invalidDate();var e=this.localeData(),n=function(t,e,n){var i=Xe(t).abs(),a=Qn(i.as("s")),r=Qn(i.as("m")),o=Qn(i.as("h")),s=Qn(i.as("d")),l=Qn(i.as("M")),u=Qn(i.as("y")),d=a<=ti.ss&&["s",a]||a<ti.s&&["ss",a]||r<=1&&["m"]||r<ti.m&&["mm",r]||o<=1&&["h"]||o<ti.h&&["hh",o]||s<=1&&["d"]||s<ti.d&&["dd",s]||l<=1&&["M"]||l<ti.M&&["MM",l]||u<=1&&["y"]||["yy",u];return d[2]=e,d[3]=+t>0,d[4]=n,ei.apply(null,d)}(this,!t,e);return t&&(n=e.pastFuture(+this,n)),e.postformat(n)},ri.toISOString=ai,ri.toString=ai,ri.toJSON=ai,ri.locale=rn,ri.localeData=sn,ri.toIsoString=D("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",ai),ri.lang=on,j("X",0,0,"unix"),j("x",0,0,"valueOf"),dt("x",rt),dt("X",/[+-]?\d+(\.\d{1,3})?/),gt("X",(function(t,e,n){n._d=new Date(1e3*parseFloat(t,10))})),gt("x",(function(t,e,n){n._d=new Date(k(t))})),a.version="2.24.0",n=Le,a.fn=Mn,a.min=function(){return We("isBefore",[].slice.call(arguments,0))},a.max=function(){return We("isAfter",[].slice.call(arguments,0))},a.now=function(){return Date.now?Date.now():+new Date},a.utc=f,a.unix=function(t){return Le(1e3*t)},a.months=function(t,e){return Pn(t,e,"months")},a.isDate=u,a.locale=ge,a.invalid=p,a.duration=Xe,a.isMoment=_,a.weekdays=function(t,e,n){return Tn(t,e,n,"weekdays")},a.parseZone=function(){return Le.apply(null,arguments).parseZone()},a.localeData=pe,a.isDuration=Ee,a.monthsShort=function(t,e){return Pn(t,e,"monthsShort")},a.weekdaysMin=function(t,e,n){return Tn(t,e,n,"weekdaysMin")},a.defineLocale=me,a.updateLocale=function(t,e){if(null!=e){var n,i,a=ue;null!=(i=fe(t))&&(a=i._config),e=A(a,e),(n=new F(e)).parentLocale=de[t],de[t]=n,ge(t)}else null!=de[t]&&(null!=de[t].parentLocale?de[t]=de[t].parentLocale:null!=de[t]&&delete de[t]);return de[t]},a.locales=function(){return C(de)},a.weekdaysShort=function(t,e,n){return Tn(t,e,n,"weekdaysShort")},a.normalizeUnits=R,a.relativeTimeRounding=function(t){return void 0===t?Qn:"function"==typeof t&&(Qn=t,!0)},a.relativeTimeThreshold=function(t,e){return void 0!==ti[t]&&(void 0===e?ti[t]:(ti[t]=e,"s"===t&&(ti.ss=e-1),!0))},a.calendarFormat=function(t,e){var n=t.diff(e,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},a.prototype=Mn,a.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},a}()})),mi={datetime:"MMM D, YYYY, h:mm:ss a",millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"};rn._date.override("function"==typeof gi?{_id:"moment",formats:function(){return mi},parse:function(t,e){return"string"==typeof t&&"string"==typeof e?t=gi(t,e):t instanceof gi||(t=gi(t)),t.isValid()?t.valueOf():null},format:function(t,e){return gi(t).format(e)},add:function(t,e,n){return gi(t).add(e,n).valueOf()},diff:function(t,e,n){return gi(t).diff(gi(e),n)},startOf:function(t,e,n){return t=gi(t),"isoWeek"===e?t.isoWeekday(n).valueOf():t.startOf(e).valueOf()},endOf:function(t,e){return gi(t).endOf(e).valueOf()},_create:function(t){return gi(t)}}:{}),W._set("global",{plugins:{filler:{propagate:!0}}});var pi={dataset:function(t){var e=t.fill,n=t.chart,i=n.getDatasetMeta(e),a=i&&n.isDatasetVisible(e)&&i.dataset._children||[],r=a.length||0;return r?function(t,e){return e<r&&a[e]._view||null}:null},boundary:function(t){var e=t.boundary,n=e?e.x:null,i=e?e.y:null;return H.isArray(e)?function(t,n){return e[n]}:function(t){return{x:null===n?t.x:n,y:null===i?t.y:i}}}};function vi(t,e,n){var i,a=t._model||{},r=a.fill;if(void 0===r&&(r=!!a.backgroundColor),!1===r||null===r)return!1;if(!0===r)return"origin";if(i=parseFloat(r,10),isFinite(i)&&Math.floor(i)===i)return"-"!==r[0]&&"+"!==r[0]||(i=e+i),!(i===e||i<0||i>=n)&&i;switch(r){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return r;default:return!1}}function bi(t){return(t.el._scale||{}).getPointPositionForValue?function(t){var e,n,i,a,r,o=t.el._scale,s=o.options,l=o.chart.data.labels.length,u=t.fill,d=[];if(!l)return null;for(e=s.ticks.reverse?o.max:o.min,n=s.ticks.reverse?o.min:o.max,i=o.getPointPositionForValue(0,e),a=0;a<l;++a)r="start"===u||"end"===u?o.getPointPositionForValue(a,"start"===u?e:n):o.getBasePosition(a),s.gridLines.circular&&(r.cx=i.x,r.cy=i.y,r.angle=o.getIndexAngle(a)-Math.PI/2),d.push(r);return d}(t):function(t){var e,n=t.el._model||{},i=t.el._scale||{},a=t.fill,r=null;if(isFinite(a))return null;if("start"===a?r=void 0===n.scaleBottom?i.bottom:n.scaleBottom:"end"===a?r=void 0===n.scaleTop?i.top:n.scaleTop:void 0!==n.scaleZero?r=n.scaleZero:i.getBasePixel&&(r=i.getBasePixel()),null!=r){if(void 0!==r.x&&void 0!==r.y)return r;if(H.isFinite(r))return{x:(e=i.isHorizontal())?r:null,y:e?null:r}}return null}(t)}function yi(t,e,n){var i,a=t[e].fill,r=[e];if(!n)return a;for(;!1!==a&&-1===r.indexOf(a);){if(!isFinite(a))return a;if(!(i=t[a]))return!1;if(i.visible)return a;r.push(a),a=i.fill}return!1}function xi(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),pi[n](t))}function _i(t){return t&&!t.skip}function wi(t,e,n,i,a){var r,o,s,l;if(i&&a){for(t.moveTo(e[0].x,e[0].y),r=1;r<i;++r)H.canvas.lineTo(t,e[r-1],e[r]);if(void 0===n[0].angle)for(t.lineTo(n[a-1].x,n[a-1].y),r=a-1;r>0;--r)H.canvas.lineTo(t,n[r],n[r-1],!0);else for(o=n[0].cx,s=n[0].cy,l=Math.sqrt(Math.pow(n[0].x-o,2)+Math.pow(n[0].y-s,2)),r=a-1;r>0;--r)t.arc(o,s,l,n[r].angle,n[r-1].angle,!0)}}function ki(t,e,n,i,a,r){var o,s,l,u,d,h,c,f,g=e.length,m=i.spanGaps,p=[],v=[],b=0,y=0;for(t.beginPath(),o=0,s=g;o<s;++o)d=n(u=e[l=o%g]._view,l,i),h=_i(u),c=_i(d),r&&void 0===f&&h&&(s=g+(f=o+1)),h&&c?(b=p.push(u),y=v.push(d)):b&&y&&(m?(h&&p.push(u),c&&v.push(d)):(wi(t,p,v,b,y),b=y=0,p=[],v=[]));wi(t,p,v,b,y),t.closePath(),t.fillStyle=a,t.fill()}var Mi={id:"filler",afterDatasetsUpdate:function(t,e){var n,i,a,r,o=(t.data.datasets||[]).length,s=e.propagate,l=[];for(i=0;i<o;++i)r=null,(a=(n=t.getDatasetMeta(i)).dataset)&&a._model&&a instanceof wt.Line&&(r={visible:t.isDatasetVisible(i),fill:vi(a,i,o),chart:t,el:a}),n.$filler=r,l.push(r);for(i=0;i<o;++i)(r=l[i])&&(r.fill=yi(l,i,s),r.boundary=bi(r),r.mapper=xi(r))},beforeDatasetsDraw:function(t){var e,n,i,a,r,o,s,l=t._getSortedVisibleDatasetMetas(),u=t.ctx;for(n=l.length-1;n>=0;--n)(e=l[n].$filler)&&e.visible&&(a=(i=e.el)._view,r=i._children||[],o=e.mapper,s=a.backgroundColor||W.global.defaultColor,o&&s&&r.length&&(H.canvas.clipArea(u,t.chartArea),ki(u,r,o,a,s,i._loop),H.canvas.unclipArea(u)))}},Si=H.rtl.getRtlAdapter,Di=H.noop,Ci=H.valueOrDefault;function Pi(t,e){return t.usePointStyle&&t.boxWidth>e?e:t.boxWidth}W._set("global",{legend:{display:!0,position:"top",align:"center",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var n=e.datasetIndex,i=this.chart,a=i.getDatasetMeta(n);a.hidden=null===a.hidden?!i.data.datasets[n].hidden:null,i.update()},onHover:null,onLeave:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data.datasets,n=t.options.legend||{},i=n.labels&&n.labels.usePointStyle;return t._getSortedDatasetMetas().map((function(n){var a=n.controller.getStyle(i?0:void 0);return{text:e[n.index].label,fillStyle:a.backgroundColor,hidden:!t.isDatasetVisible(n.index),lineCap:a.borderCapStyle,lineDash:a.borderDash,lineDashOffset:a.borderDashOffset,lineJoin:a.borderJoinStyle,lineWidth:a.borderWidth,strokeStyle:a.borderColor,pointStyle:a.pointStyle,rotation:a.rotation,datasetIndex:n.index}}),this)}}},legendCallback:function(t){var e,n,i,a=document.createElement("ul"),r=t.data.datasets;for(a.setAttribute("class",t.id+"-legend"),e=0,n=r.length;e<n;e++)(i=a.appendChild(document.createElement("li"))).appendChild(document.createElement("span")).style.backgroundColor=r[e].backgroundColor,r[e].label&&i.appendChild(document.createTextNode(r[e].label));return a.outerHTML}});var Ti=$.extend({initialize:function(t){H.extend(this,t),this.legendHitBoxes=[],this._hoveredItem=null,this.doughnutMode=!1},beforeUpdate:Di,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:Di,beforeSetDimensions:Di,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:Di,beforeBuildLabels:Di,buildLabels:function(){var t=this,e=t.options.labels||{},n=H.callback(e.generateLabels,[t.chart],t)||[];e.filter&&(n=n.filter((function(n){return e.filter(n,t.chart.data)}))),t.options.reverse&&n.reverse(),t.legendItems=n},afterBuildLabels:Di,beforeFit:Di,fit:function(){var t=this,e=t.options,n=e.labels,i=e.display,a=t.ctx,r=H.options._parseFont(n),o=r.size,s=t.legendHitBoxes=[],l=t.minSize,u=t.isHorizontal();if(u?(l.width=t.maxWidth,l.height=i?10:0):(l.width=i?10:0,l.height=t.maxHeight),i){if(a.font=r.string,u){var d=t.lineWidths=[0],h=0;a.textAlign="left",a.textBaseline="middle",H.each(t.legendItems,(function(t,e){var i=Pi(n,o)+o/2+a.measureText(t.text).width;(0===e||d[d.length-1]+i+2*n.padding>l.width)&&(h+=o+n.padding,d[d.length-(e>0?0:1)]=0),s[e]={left:0,top:0,width:i,height:o},d[d.length-1]+=i+n.padding})),l.height+=h}else{var c=n.padding,f=t.columnWidths=[],g=t.columnHeights=[],m=n.padding,p=0,v=0;H.each(t.legendItems,(function(t,e){var i=Pi(n,o)+o/2+a.measureText(t.text).width;e>0&&v+o+2*c>l.height&&(m+=p+n.padding,f.push(p),g.push(v),p=0,v=0),p=Math.max(p,i),v+=o+c,s[e]={left:0,top:0,width:i,height:o}})),m+=p,f.push(p),g.push(v),l.width+=m}t.width=l.width,t.height=l.height}else t.width=l.width=t.height=l.height=0},afterFit:Di,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,e=t.options,n=e.labels,i=W.global,a=i.defaultColor,r=i.elements.line,o=t.height,s=t.columnHeights,l=t.width,u=t.lineWidths;if(e.display){var d,h=Si(e.rtl,t.left,t.minSize.width),c=t.ctx,f=Ci(n.fontColor,i.defaultFontColor),g=H.options._parseFont(n),m=g.size;c.textAlign=h.textAlign("left"),c.textBaseline="middle",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=g.string;var p=Pi(n,m),v=t.legendHitBoxes,b=function(t,i){switch(e.align){case"start":return n.padding;case"end":return t-i;default:return(t-i+n.padding)/2}},y=t.isHorizontal();d=y?{x:t.left+b(l,u[0]),y:t.top+n.padding,line:0}:{x:t.left+n.padding,y:t.top+b(o,s[0]),line:0},H.rtl.overrideTextDirection(t.ctx,e.textDirection);var x=m+n.padding;H.each(t.legendItems,(function(e,i){var f=c.measureText(e.text).width,g=p+m/2+f,_=d.x,w=d.y;h.setWidth(t.minSize.width),y?i>0&&_+g+n.padding>t.left+t.minSize.width&&(w=d.y+=x,d.line++,_=d.x=t.left+b(l,u[d.line])):i>0&&w+x>t.top+t.minSize.height&&(_=d.x=_+t.columnWidths[d.line]+n.padding,d.line++,w=d.y=t.top+b(o,s[d.line]));var k=h.x(_);!function(t,e,i){if(!(isNaN(p)||p<=0)){c.save();var o=Ci(i.lineWidth,r.borderWidth);if(c.fillStyle=Ci(i.fillStyle,a),c.lineCap=Ci(i.lineCap,r.borderCapStyle),c.lineDashOffset=Ci(i.lineDashOffset,r.borderDashOffset),c.lineJoin=Ci(i.lineJoin,r.borderJoinStyle),c.lineWidth=o,c.strokeStyle=Ci(i.strokeStyle,a),c.setLineDash&&c.setLineDash(Ci(i.lineDash,r.borderDash)),n&&n.usePointStyle){var s=p*Math.SQRT2/2,l=h.xPlus(t,p/2),u=e+m/2;H.canvas.drawPoint(c,i.pointStyle,s,l,u,i.rotation)}else c.fillRect(h.leftForLtr(t,p),e,p,m),0!==o&&c.strokeRect(h.leftForLtr(t,p),e,p,m);c.restore()}}(k,w,e),v[i].left=h.leftForLtr(k,v[i].width),v[i].top=w,function(t,e,n,i){var a=m/2,r=h.xPlus(t,p+a),o=e+a;c.fillText(n.text,r,o),n.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(r,o),c.lineTo(h.xPlus(r,i),o),c.stroke())}(k,w,e,f),y?d.x+=g+n.padding:d.y+=x})),H.rtl.restoreTextDirection(t.ctx,e.textDirection)}},_getLegendItemAt:function(t,e){var n,i,a,r=this;if(t>=r.left&&t<=r.right&&e>=r.top&&e<=r.bottom)for(a=r.legendHitBoxes,n=0;n<a.length;++n)if(t>=(i=a[n]).left&&t<=i.left+i.width&&e>=i.top&&e<=i.top+i.height)return r.legendItems[n];return null},handleEvent:function(t){var e,n=this,i=n.options,a="mouseup"===t.type?"click":t.type;if("mousemove"===a){if(!i.onHover&&!i.onLeave)return}else{if("click"!==a)return;if(!i.onClick)return}e=n._getLegendItemAt(t.x,t.y),"click"===a?e&&i.onClick&&i.onClick.call(n,t.native,e):(i.onLeave&&e!==n._hoveredItem&&(n._hoveredItem&&i.onLeave.call(n,t.native,n._hoveredItem),n._hoveredItem=e),i.onHover&&e&&i.onHover.call(n,t.native,e))}});function Oi(t,e){var n=new Ti({ctx:t.ctx,options:e,chart:t});me.configure(t,n,e),me.addBox(t,n),t.legend=n}var Ai={id:"legend",_element:Ti,beforeInit:function(t){var e=t.options.legend;e&&Oi(t,e)},beforeUpdate:function(t){var e=t.options.legend,n=t.legend;e?(H.mergeIf(e,W.global.legend),n?(me.configure(t,n,e),n.options=e):Oi(t,e)):n&&(me.removeBox(t,n),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}},Fi=H.noop;W._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,padding:10,position:"top",text:"",weight:2e3}});var Ii=$.extend({initialize:function(t){H.extend(this,t),this.legendHitBoxes=[]},beforeUpdate:Fi,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:Fi,beforeSetDimensions:Fi,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:Fi,beforeBuildLabels:Fi,buildLabels:Fi,afterBuildLabels:Fi,beforeFit:Fi,fit:function(){var t,e=this,n=e.options,i=e.minSize={},a=e.isHorizontal();n.display?(t=(H.isArray(n.text)?n.text.length:1)*H.options._parseFont(n).lineHeight+2*n.padding,e.width=i.width=a?e.maxWidth:t,e.height=i.height=a?t:e.maxHeight):e.width=i.width=e.height=i.height=0},afterFit:Fi,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,n=t.options;if(n.display){var i,a,r,o=H.options._parseFont(n),s=o.lineHeight,l=s/2+n.padding,u=0,d=t.top,h=t.left,c=t.bottom,f=t.right;e.fillStyle=H.valueOrDefault(n.fontColor,W.global.defaultFontColor),e.font=o.string,t.isHorizontal()?(a=h+(f-h)/2,r=d+l,i=f-h):(a="left"===n.position?h+l:f-l,r=d+(c-d)/2,i=c-d,u=Math.PI*("left"===n.position?-.5:.5)),e.save(),e.translate(a,r),e.rotate(u),e.textAlign="center",e.textBaseline="middle";var g=n.text;if(H.isArray(g))for(var m=0,p=0;p<g.length;++p)e.fillText(g[p],0,m,i),m+=s;else e.fillText(g,0,0,i);e.restore()}}});function Li(t,e){var n=new Ii({ctx:t.ctx,options:e,chart:t});me.configure(t,n,e),me.addBox(t,n),t.titleBlock=n}var Ri={},Ni=Mi,Wi=Ai,Yi={id:"title",_element:Ii,beforeInit:function(t){var e=t.options.title;e&&Li(t,e)},beforeUpdate:function(t){var e=t.options.title,n=t.titleBlock;e?(H.mergeIf(e,W.global.title),n?(me.configure(t,n,e),n.options=e):Li(t,e)):n&&(me.removeBox(t,n),delete t.titleBlock)}};for(var zi in Ri.filler=Ni,Ri.legend=Wi,Ri.title=Yi,en.helpers=H,function(){function t(t,e,n){var i;return"string"==typeof t?(i=parseInt(t,10),-1!==t.indexOf("%")&&(i=i/100*e.parentNode[n])):i=t,i}function e(t){return null!=t&&"none"!==t}function n(n,i,a){var r=document.defaultView,o=H._getParentNode(n),s=r.getComputedStyle(n)[i],l=r.getComputedStyle(o)[i],u=e(s),d=e(l),h=Number.POSITIVE_INFINITY;return u||d?Math.min(u?t(s,n,a):h,d?t(l,o,a):h):"none"}H.where=function(t,e){if(H.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return H.each(t,(function(t){e(t)&&n.push(t)})),n},H.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i<a;++i)if(e.call(n,t[i],i,t))return i;return-1},H.findNextWhere=function(t,e,n){H.isNullOrUndef(n)&&(n=-1);for(var i=n+1;i<t.length;i++){var a=t[i];if(e(a))return a}},H.findPreviousWhere=function(t,e,n){H.isNullOrUndef(n)&&(n=t.length);for(var i=n-1;i>=0;i--){var a=t[i];if(e(a))return a}},H.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},H.almostEquals=function(t,e,n){return Math.abs(t-e)<n},H.almostWhole=function(t,e){var n=Math.round(t);return n-e<=t&&n+e>=t},H.max=function(t){return t.reduce((function(t,e){return isNaN(e)?t:Math.max(t,e)}),Number.NEGATIVE_INFINITY)},H.min=function(t){return t.reduce((function(t,e){return isNaN(e)?t:Math.min(t,e)}),Number.POSITIVE_INFINITY)},H.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0===(t=+t)||isNaN(t)?t:t>0?1:-1},H.toRadians=function(t){return t*(Math.PI/180)},H.toDegrees=function(t){return t*(180/Math.PI)},H._decimalPlaces=function(t){if(H.isFinite(t)){for(var e=1,n=0;Math.round(t*e)/e!==t;)e*=10,n++;return n}},H.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),r=Math.atan2(i,n);return r<-.5*Math.PI&&(r+=2*Math.PI),{angle:r,distance:a}},H.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},H.aliasPixel=function(t){return t%2==0?0:.5},H._alignPixel=function(t,e,n){var i=t.currentDevicePixelRatio,a=n/2;return Math.round((e-a)*i)/i+a},H.splineCurve=function(t,e,n,i){var a=t.skip?e:t,r=e,o=n.skip?e:n,s=Math.sqrt(Math.pow(r.x-a.x,2)+Math.pow(r.y-a.y,2)),l=Math.sqrt(Math.pow(o.x-r.x,2)+Math.pow(o.y-r.y,2)),u=s/(s+l),d=l/(s+l),h=i*(u=isNaN(u)?0:u),c=i*(d=isNaN(d)?0:d);return{previous:{x:r.x-h*(o.x-a.x),y:r.y-h*(o.y-a.y)},next:{x:r.x+c*(o.x-a.x),y:r.y+c*(o.y-a.y)}}},H.EPSILON=Number.EPSILON||1e-14,H.splineCurveMonotone=function(t){var e,n,i,a,r,o,s,l,u,d=(t||[]).map((function(t){return{model:t._model,deltaK:0,mK:0}})),h=d.length;for(e=0;e<h;++e)if(!(i=d[e]).model.skip){if(n=e>0?d[e-1]:null,(a=e<h-1?d[e+1]:null)&&!a.model.skip){var c=a.model.x-i.model.x;i.deltaK=0!==c?(a.model.y-i.model.y)/c:0}!n||n.model.skip?i.mK=i.deltaK:!a||a.model.skip?i.mK=n.deltaK:this.sign(n.deltaK)!==this.sign(i.deltaK)?i.mK=0:i.mK=(n.deltaK+i.deltaK)/2}for(e=0;e<h-1;++e)i=d[e],a=d[e+1],i.model.skip||a.model.skip||(H.almostEquals(i.deltaK,0,this.EPSILON)?i.mK=a.mK=0:(r=i.mK/i.deltaK,o=a.mK/i.deltaK,(l=Math.pow(r,2)+Math.pow(o,2))<=9||(s=3/Math.sqrt(l),i.mK=r*s*i.deltaK,a.mK=o*s*i.deltaK)));for(e=0;e<h;++e)(i=d[e]).model.skip||(n=e>0?d[e-1]:null,a=e<h-1?d[e+1]:null,n&&!n.model.skip&&(u=(i.model.x-n.model.x)/3,i.model.controlPointPreviousX=i.model.x-u,i.model.controlPointPreviousY=i.model.y-u*i.mK),a&&!a.model.skip&&(u=(a.model.x-i.model.x)/3,i.model.controlPointNextX=i.model.x+u,i.model.controlPointNextY=i.model.y+u*i.mK))},H.nextItem=function(t,e,n){return n?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},H.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},H.niceNum=function(t,e){var n=Math.floor(H.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)},H.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},H.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,r=t.target||t.srcElement,o=r.getBoundingClientRect(),s=a.touches;s&&s.length>0?(n=s[0].clientX,i=s[0].clientY):(n=a.clientX,i=a.clientY);var l=parseFloat(H.getStyle(r,"padding-left")),u=parseFloat(H.getStyle(r,"padding-top")),d=parseFloat(H.getStyle(r,"padding-right")),h=parseFloat(H.getStyle(r,"padding-bottom")),c=o.right-o.left-l-d,f=o.bottom-o.top-u-h;return{x:n=Math.round((n-o.left-l)/c*r.width/e.currentDevicePixelRatio),y:i=Math.round((i-o.top-u)/f*r.height/e.currentDevicePixelRatio)}},H.getConstraintWidth=function(t){return n(t,"max-width","clientWidth")},H.getConstraintHeight=function(t){return n(t,"max-height","clientHeight")},H._calculatePadding=function(t,e,n){return(e=H.getStyle(t,e)).indexOf("%")>-1?n*parseInt(e,10)/100:parseInt(e,10)},H._getParentNode=function(t){var e=t.parentNode;return e&&"[object ShadowRoot]"===e.toString()&&(e=e.host),e},H.getMaximumWidth=function(t){var e=H._getParentNode(t);if(!e)return t.clientWidth;var n=e.clientWidth,i=n-H._calculatePadding(e,"padding-left",n)-H._calculatePadding(e,"padding-right",n),a=H.getConstraintWidth(t);return isNaN(a)?i:Math.min(i,a)},H.getMaximumHeight=function(t){var e=H._getParentNode(t);if(!e)return t.clientHeight;var n=e.clientHeight,i=n-H._calculatePadding(e,"padding-top",n)-H._calculatePadding(e,"padding-bottom",n),a=H.getConstraintHeight(t);return isNaN(a)?i:Math.min(i,a)},H.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},H.retinaScale=function(t,e){var n=t.currentDevicePixelRatio=e||"undefined"!=typeof window&&window.devicePixelRatio||1;if(1!==n){var i=t.canvas,a=t.height,r=t.width;i.height=a*n,i.width=r*n,t.ctx.scale(n,n),i.style.height||i.style.width||(i.style.height=a+"px",i.style.width=r+"px")}},H.fontString=function(t,e,n){return e+" "+t+"px "+n},H.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},r=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},r=i.garbageCollect=[],i.font=e),t.font=e;var o,s,l,u,d,h=0,c=n.length;for(o=0;o<c;o++)if(null!=(u=n[o])&&!0!==H.isArray(u))h=H.measureText(t,a,r,h,u);else if(H.isArray(u))for(s=0,l=u.length;s<l;s++)null==(d=u[s])||H.isArray(d)||(h=H.measureText(t,a,r,h,d));var f=r.length/2;if(f>n.length){for(o=0;o<f;o++)delete a[r[o]];r.splice(0,f)}return h},H.measureText=function(t,e,n,i,a){var r=e[a];return r||(r=e[a]=t.measureText(a).width,n.push(a)),r>i&&(i=r),i},H.numberOfLabelLines=function(t){var e=1;return H.each(t,(function(t){H.isArray(t)&&t.length>e&&(e=t.length)})),e},H.color=k?function(t){return t instanceof CanvasGradient&&(t=W.global.defaultColor),k(t)}:function(t){return console.error("Color.js not found!"),t},H.getHoverColor=function(t){return t instanceof CanvasPattern||t instanceof CanvasGradient?t:H.color(t).saturate(.5).darken(.1).rgbString()}}(),en._adapters=rn,en.Animation=K,en.animationService=J,en.controllers=Jt,en.DatasetController=it,en.defaults=W,en.Element=$,en.elements=wt,en.Interaction=re,en.layouts=me,en.platform=Ie,en.plugins=Le,en.Scale=xn,en.scaleService=Re,en.Ticks=on,en.Tooltip=Ge,en.helpers.each(fi,(function(t,e){en.scaleService.registerScaleType(e,t,t._defaults)})),Ri)Ri.hasOwnProperty(zi)&&en.plugins.register(Ri[zi]);en.platform.initialize();var Ei=en;return"undefined"!=typeof window&&(window.Chart=en),en.Chart=en,en.Legend=Ri.legend._element,en.Title=Ri.title._element,en.pluginService=en.plugins,en.PluginBase=en.Element.extend({}),en.canvasHelpers=en.helpers.canvas,en.layoutService=en.layouts,en.LinearScaleBase=Dn,en.helpers.each(["Bar","Bubble","Doughnut","Line","PolarArea","Radar","Scatter"],(function(t){en[t]=function(e,n){return new en(e,en.helpers.merge(n||{},{type:t.charAt(0).toLowerCase()+t.slice(1)}))}})),Ei}));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/js/admin-blocked-ips.js
DELETED
@@ -1,15 +0,0 @@
|
|
1 |
-
(function($) {
|
2 |
-
$(function() {
|
3 |
-
var $addIPContainer = $(".wpzerospam-add-ip-container");
|
4 |
-
|
5 |
-
$("#blocked-type", $addIPContainer).change(function() {
|
6 |
-
if ( $(this).val() == 'permanent' ) {
|
7 |
-
$("#wpzerospam-add-ip-field-start-date").hide();
|
8 |
-
$("#wpzerospam-add-ip-field-end-date").hide();
|
9 |
-
} else {
|
10 |
-
$("#wpzerospam-add-ip-field-start-date").show();
|
11 |
-
$("#wpzerospam-add-ip-field-end-date").show();
|
12 |
-
}
|
13 |
-
});
|
14 |
-
});
|
15 |
-
})(jQuery);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/js/admin-tables.js
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
(function($) {
|
2 |
-
$(function() {
|
3 |
-
/**
|
4 |
-
* Handles opening the 'View Details' modal on the spam log.
|
5 |
-
*/
|
6 |
-
var $detailsTrigger = $( '.wpzerospam-details-trigger' );
|
7 |
-
$detailsTrigger.click(function( e ) {
|
8 |
-
e.preventDefault();
|
9 |
-
|
10 |
-
var id = $(this).data('id');
|
11 |
-
$('#wpzerospam-details-modal-' + id).addClass( 'is-active' );
|
12 |
-
});
|
13 |
-
|
14 |
-
$('.wpzerospam-details-modal').click(function(){
|
15 |
-
$(this).removeClass('is-active');
|
16 |
-
});
|
17 |
-
|
18 |
-
$(".wpzerospam-details-modal .wpzerospam-details-modal-inner").click(function(e) {
|
19 |
-
e.stopPropagation();
|
20 |
-
});
|
21 |
-
});
|
22 |
-
})(jQuery);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/js/admin.js
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
(function($) {
|
2 |
+
$(function() {
|
3 |
+
$( '.zerospam-details-trigger' ).click(function( e ) {
|
4 |
+
e.preventDefault();
|
5 |
+
$('.zerospam-modal').removeClass('is-active');
|
6 |
+
|
7 |
+
var id = $(this).data('id');
|
8 |
+
$('#zerospam-details-' + id).addClass('is-active');
|
9 |
+
});
|
10 |
+
|
11 |
+
$('.zerospam-close-modal').click(function(e) {
|
12 |
+
e.preventDefault();
|
13 |
+
$('.zerospam-modal').removeClass('is-active');
|
14 |
+
});
|
15 |
+
|
16 |
+
$('.zerospam-block-trigger').click(function(e) {
|
17 |
+
e.preventDefault();
|
18 |
+
|
19 |
+
var ip = $(this).data('ip');
|
20 |
+
$('input[name="blocked_ip"]', $('#zerospam-block-ip')).val('');
|
21 |
+
if ( ip ) {
|
22 |
+
$('input[name="blocked_ip"]', $('#zerospam-block-ip')).val(ip);
|
23 |
+
}
|
24 |
+
|
25 |
+
var reason = $(this).data('reason');
|
26 |
+
$('input[name="blocked_reason"]', $('#zerospam-block-ip')).val('');
|
27 |
+
if ( reason ) {
|
28 |
+
$('input[name="blocked_reason"]', $('#zerospam-block-ip')).val(reason);
|
29 |
+
}
|
30 |
+
|
31 |
+
var type = $(this).data('type');
|
32 |
+
$('select[name="blocked_type"]', $('#zerospam-block-ip')).val('temporary');
|
33 |
+
if ( type ) {
|
34 |
+
$('select[name="blocked_type"]', $('#zerospam-block-ip')).val(type);
|
35 |
+
}
|
36 |
+
|
37 |
+
var startDate = $(this).data('start');
|
38 |
+
$('input[name="blocked_start_date"]', $('#zerospam-block-ip')).val('');
|
39 |
+
if ( startDate ) {
|
40 |
+
$('input[name="blocked_start_date"]', $('#zerospam-block-ip')).val(startDate);
|
41 |
+
}
|
42 |
+
|
43 |
+
var endDate = $(this).data('end');
|
44 |
+
$('input[name="blocked_end_date"]', $('#zerospam-block-ip')).val('');
|
45 |
+
if ( endDate ) {
|
46 |
+
$('input[name="blocked_end_date"]', $('#zerospam-block-ip')).val(endDate);
|
47 |
+
}
|
48 |
+
|
49 |
+
$('.zerospam-modal').removeClass('is-active');
|
50 |
+
$('#zerospam-block-ip').addClass('is-active');
|
51 |
+
});
|
52 |
+
|
53 |
+
$(document).on('keydown', function(e) {
|
54 |
+
if(e.key == "Escape") {
|
55 |
+
$('.zerospam-modal').removeClass('is-active');
|
56 |
+
}
|
57 |
+
});
|
58 |
+
});
|
59 |
+
})(jQuery);
|
assets/js/jquery-jvectormap-2.0.5.min.js
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
!function($){var apiParams={set:{colors:1,values:1,backgroundColor:1,scaleColors:1,normalizeFunction:1,focus:1},get:{selectedRegions:1,selectedMarkers:1,mapObject:1,regionName:1}};$.fn.vectorMap=function(options){var map=this.children(".jvectormap-container").data("mapObject");if("addMap"===options)jvm.Map.maps[arguments[1]]=arguments[2];else{if(("set"===options||"get"===options)&&apiParams[options][arguments[1]])return map[options+(arguments[1].charAt(0).toUpperCase()+arguments[1].substr(1))].apply(map,Array.prototype.slice.call(arguments,2));(options=options||{}).container=this,map=new jvm.Map(options)}return this}}(jQuery),function(factory){"function"==typeof define&&define.amd?define(["jquery"],factory):"object"==typeof exports?module.exports=factory:factory(jQuery)}(function($){var nullLowestDeltaTimeout,lowestDelta,toFix=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],toBind="onwheel"in document||9<=document.documentMode?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],slice=Array.prototype.slice;if($.event.fixHooks)for(var i=toFix.length;i;)$.event.fixHooks[toFix[--i]]=$.event.mouseHooks;var special=$.event.special.mousewheel={version:"3.1.9",setup:function(){if(this.addEventListener)for(var i=toBind.length;i;)this.addEventListener(toBind[--i],handler,!1);else this.onmousewheel=handler;$.data(this,"mousewheel-line-height",special.getLineHeight(this)),$.data(this,"mousewheel-page-height",special.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var i=toBind.length;i;)this.removeEventListener(toBind[--i],handler,!1);else this.onmousewheel=null},getLineHeight:function(elem){return parseInt($(elem)["offsetParent"in $.fn?"offsetParent":"parent"]().css("fontSize"),10)},getPageHeight:function(elem){return $(elem).height()},settings:{adjustOldDeltas:!0}};function handler(event){var absDelta,orgEvent=event||window.event,args=slice.call(arguments,1),delta=0,deltaX=0,deltaY=0;if((event=$.event.fix(orgEvent)).type="mousewheel","detail"in orgEvent&&(deltaY=-1*orgEvent.detail),"wheelDelta"in orgEvent&&(deltaY=orgEvent.wheelDelta),"wheelDeltaY"in orgEvent&&(deltaY=orgEvent.wheelDeltaY),"wheelDeltaX"in orgEvent&&(deltaX=-1*orgEvent.wheelDeltaX),"axis"in orgEvent&&orgEvent.axis===orgEvent.HORIZONTAL_AXIS&&(deltaX=-1*deltaY,deltaY=0),delta=0===deltaY?deltaX:deltaY,"deltaY"in orgEvent&&(delta=deltaY=-1*orgEvent.deltaY),"deltaX"in orgEvent&&(deltaX=orgEvent.deltaX,0===deltaY&&(delta=-1*deltaX)),0!==deltaY||0!==deltaX){if(1===orgEvent.deltaMode){var lineHeight=$.data(this,"mousewheel-line-height");delta*=lineHeight,deltaY*=lineHeight,deltaX*=lineHeight}else if(2===orgEvent.deltaMode){var pageHeight=$.data(this,"mousewheel-page-height");delta*=pageHeight,deltaY*=pageHeight,deltaX*=pageHeight}return absDelta=Math.max(Math.abs(deltaY),Math.abs(deltaX)),(!lowestDelta||absDelta<lowestDelta)&&shouldAdjustOldDeltas(orgEvent,lowestDelta=absDelta)&&(lowestDelta/=40),shouldAdjustOldDeltas(orgEvent,absDelta)&&(delta/=40,deltaX/=40,deltaY/=40),delta=Math[1<=delta?"floor":"ceil"](delta/lowestDelta),deltaX=Math[1<=deltaX?"floor":"ceil"](deltaX/lowestDelta),deltaY=Math[1<=deltaY?"floor":"ceil"](deltaY/lowestDelta),event.deltaX=deltaX,event.deltaY=deltaY,event.deltaFactor=lowestDelta,event.deltaMode=0,args.unshift(event,delta,deltaX,deltaY),nullLowestDeltaTimeout&&clearTimeout(nullLowestDeltaTimeout),nullLowestDeltaTimeout=setTimeout(nullLowestDelta,200),($.event.dispatch||$.event.handle).apply(this,args)}}function nullLowestDelta(){lowestDelta=null}function shouldAdjustOldDeltas(orgEvent,absDelta){return special.settings.adjustOldDeltas&&"mousewheel"===orgEvent.type&&absDelta%120==0}$.fn.extend({mousewheel:function(fn){return fn?this.bind("mousewheel",fn):this.trigger("mousewheel")},unmousewheel:function(fn){return this.unbind("mousewheel",fn)}})});var jvm={inherits:function(child,parent){function temp(){}temp.prototype=parent.prototype,child.prototype=new temp,(child.prototype.constructor=child).parentClass=parent},mixin:function(target,source){var prop;for(prop in source.prototype)source.prototype.hasOwnProperty(prop)&&(target.prototype[prop]=source.prototype[prop])},min:function(values){var i,min=Number.MAX_VALUE;if(values instanceof Array)for(i=0;i<values.length;i++)values[i]<min&&(min=values[i]);else for(i in values)values[i]<min&&(min=values[i]);return min},max:function(values){var i,max=Number.MIN_VALUE;if(values instanceof Array)for(i=0;i<values.length;i++)values[i]>max&&(max=values[i]);else for(i in values)values[i]>max&&(max=values[i]);return max},keys:function(object){var key,keys=[];for(key in object)keys.push(key);return keys},values:function(object){var key,i,values=[];for(i=0;i<arguments.length;i++)for(key in object=arguments[i])values.push(object[key]);return values},whenImageLoaded:function(url){var deferred=new jvm.$.Deferred,img=jvm.$("<img/>");return img.on("error",function(){deferred.reject()}).on("load",function(){deferred.resolve(img)}),img.attr("src",url),deferred},isImageUrl:function(s){return/\.\w{3,4}$/.test(s)}};jvm.$=jQuery,Array.prototype.indexOf||(Array.prototype.indexOf=function(searchElement,fromIndex){var k;if(null==this)throw new TypeError('"this" is null or not defined');var O=Object(this),len=O.length>>>0;if(0==len)return-1;var n=+fromIndex||0;if(Math.abs(n)===1/0&&(n=0),len<=n)return-1;for(k=Math.max(0<=n?n:len-Math.abs(n),0);k<len;){if(k in O&&O[k]===searchElement)return k;k++}return-1}),jvm.AbstractElement=function(name,config){this.node=this.createElement(name),this.name=name,this.properties={},config&&this.set(config)},jvm.AbstractElement.prototype.set=function(property,value){var key;if("object"==typeof property)for(key in property)this.properties[key]=property[key],this.applyAttr(key,property[key]);else this.properties[property]=value,this.applyAttr(property,value)},jvm.AbstractElement.prototype.get=function(property){return this.properties[property]},jvm.AbstractElement.prototype.applyAttr=function(property,value){this.node.setAttribute(property,value)},jvm.AbstractElement.prototype.remove=function(){jvm.$(this.node).remove()},jvm.AbstractCanvasElement=function(container,width,height){this.container=container,this.setSize(width,height),this.rootElement=new jvm[this.classPrefix+"GroupElement"],this.node.appendChild(this.rootElement.node),this.container.appendChild(this.node)},jvm.AbstractCanvasElement.prototype.add=function(element,group){(group=group||this.rootElement).add(element),element.canvas=this},jvm.AbstractCanvasElement.prototype.addPath=function(config,style,group){var el=new jvm[this.classPrefix+"PathElement"](config,style);return this.add(el,group),el},jvm.AbstractCanvasElement.prototype.addCircle=function(config,style,group){var el=new jvm[this.classPrefix+"CircleElement"](config,style);return this.add(el,group),el},jvm.AbstractCanvasElement.prototype.addImage=function(config,style,group){var el=new jvm[this.classPrefix+"ImageElement"](config,style);return this.add(el,group),el},jvm.AbstractCanvasElement.prototype.addText=function(config,style,group){var el=new jvm[this.classPrefix+"TextElement"](config,style);return this.add(el,group),el},jvm.AbstractCanvasElement.prototype.addGroup=function(parentGroup){var el=new jvm[this.classPrefix+"GroupElement"];return parentGroup?parentGroup.node.appendChild(el.node):this.node.appendChild(el.node),el.canvas=this,el},jvm.AbstractShapeElement=function(name,config,style){this.style=style||{},this.style.current=this.style.current||{},this.isHovered=!1,this.isSelected=!1,this.updateStyle()},jvm.AbstractShapeElement.prototype.setStyle=function(property,value){var styles={};"object"==typeof property?styles=property:styles[property]=value,jvm.$.extend(this.style.current,styles),this.updateStyle()},jvm.AbstractShapeElement.prototype.updateStyle=function(){var attrs={};jvm.AbstractShapeElement.mergeStyles(attrs,this.style.initial),jvm.AbstractShapeElement.mergeStyles(attrs,this.style.current),this.isHovered&&jvm.AbstractShapeElement.mergeStyles(attrs,this.style.hover),this.isSelected&&(jvm.AbstractShapeElement.mergeStyles(attrs,this.style.selected),this.isHovered&&jvm.AbstractShapeElement.mergeStyles(attrs,this.style.selectedHover)),this.set(attrs)},jvm.AbstractShapeElement.mergeStyles=function(styles,newStyles){var key;for(key in newStyles=newStyles||{})null===newStyles[key]?delete styles[key]:styles[key]=newStyles[key]},jvm.SVGElement=function(name,config){jvm.SVGElement.parentClass.apply(this,arguments)},jvm.inherits(jvm.SVGElement,jvm.AbstractElement),jvm.SVGElement.svgns="http://www.w3.org/2000/svg",jvm.SVGElement.prototype.createElement=function(tagName){return document.createElementNS(jvm.SVGElement.svgns,tagName)},jvm.SVGElement.prototype.addClass=function(className){this.node.setAttribute("class",className)},jvm.SVGElement.prototype.getElementCtr=function(ctr){return jvm["SVG"+ctr]},jvm.SVGElement.prototype.getBBox=function(){return this.node.getBBox()},jvm.SVGGroupElement=function(){jvm.SVGGroupElement.parentClass.call(this,"g")},jvm.inherits(jvm.SVGGroupElement,jvm.SVGElement),jvm.SVGGroupElement.prototype.add=function(element){this.node.appendChild(element.node)},jvm.SVGCanvasElement=function(container,width,height){this.classPrefix="SVG",jvm.SVGCanvasElement.parentClass.call(this,"svg"),this.defsElement=new jvm.SVGElement("defs"),this.node.appendChild(this.defsElement.node),jvm.AbstractCanvasElement.apply(this,arguments)},jvm.inherits(jvm.SVGCanvasElement,jvm.SVGElement),jvm.mixin(jvm.SVGCanvasElement,jvm.AbstractCanvasElement),jvm.SVGCanvasElement.prototype.setSize=function(width,height){this.width=width,this.height=height,this.node.setAttribute("width",width),this.node.setAttribute("height",height)},jvm.SVGCanvasElement.prototype.applyTransformParams=function(scale,transX,transY){this.scale=scale,this.transX=transX,this.transY=transY,this.rootElement.node.setAttribute("transform","scale("+scale+") translate("+transX+", "+transY+")")},jvm.SVGShapeElement=function(name,config,style){jvm.SVGShapeElement.parentClass.call(this,name,config),jvm.AbstractShapeElement.apply(this,arguments)},jvm.inherits(jvm.SVGShapeElement,jvm.SVGElement),jvm.mixin(jvm.SVGShapeElement,jvm.AbstractShapeElement),jvm.SVGShapeElement.prototype.applyAttr=function(attr,value){var patternEl,imageEl,that=this;"fill"===attr&&jvm.isImageUrl(value)?jvm.SVGShapeElement.images[value]?this.applyAttr("fill","url(#image"+jvm.SVGShapeElement.images[value]+")"):jvm.whenImageLoaded(value).then(function(img){(imageEl=new jvm.SVGElement("image")).node.setAttributeNS("http://www.w3.org/1999/xlink","href",value),imageEl.applyAttr("x","0"),imageEl.applyAttr("y","0"),imageEl.applyAttr("width",img[0].width),imageEl.applyAttr("height",img[0].height),(patternEl=new jvm.SVGElement("pattern")).applyAttr("id","image"+jvm.SVGShapeElement.imageCounter),patternEl.applyAttr("x",0),patternEl.applyAttr("y",0),patternEl.applyAttr("width",img[0].width/2),patternEl.applyAttr("height",img[0].height/2),patternEl.applyAttr("viewBox","0 0 "+img[0].width+" "+img[0].height),patternEl.applyAttr("patternUnits","userSpaceOnUse"),patternEl.node.appendChild(imageEl.node),that.canvas.defsElement.node.appendChild(patternEl.node),jvm.SVGShapeElement.images[value]=jvm.SVGShapeElement.imageCounter++,that.applyAttr("fill","url(#image"+jvm.SVGShapeElement.images[value]+")")}):jvm.SVGShapeElement.parentClass.prototype.applyAttr.apply(this,arguments)},jvm.SVGShapeElement.imageCounter=1,jvm.SVGShapeElement.images={},jvm.SVGPathElement=function(config,style){jvm.SVGPathElement.parentClass.call(this,"path",config,style),this.node.setAttribute("fill-rule","evenodd")},jvm.inherits(jvm.SVGPathElement,jvm.SVGShapeElement),jvm.SVGCircleElement=function(config,style){jvm.SVGCircleElement.parentClass.call(this,"circle",config,style)},jvm.inherits(jvm.SVGCircleElement,jvm.SVGShapeElement),jvm.SVGImageElement=function(config,style){jvm.SVGImageElement.parentClass.call(this,"image",config,style)},jvm.inherits(jvm.SVGImageElement,jvm.SVGShapeElement),jvm.SVGImageElement.prototype.applyAttr=function(attr,value){var imageUrl,that=this;"image"==attr?("object"==typeof value?(imageUrl=value.url,this.offset=value.offset):(imageUrl=value,this.offset=[0,0]),jvm.whenImageLoaded(imageUrl).then(function(img){that.node.setAttributeNS("http://www.w3.org/1999/xlink","href",imageUrl),that.width=img[0].width,that.height=img[0].height,that.applyAttr("width",that.width),that.applyAttr("height",that.height),that.applyAttr("x",that.cx-that.width/2+that.offset[0]),that.applyAttr("y",that.cy-that.height/2+that.offset[1]),jvm.$(that.node).trigger("imageloaded",[img])})):"cx"==attr?(this.cx=value,this.width&&this.applyAttr("x",value-this.width/2+this.offset[0])):"cy"==attr?(this.cy=value,this.height&&this.applyAttr("y",value-this.height/2+this.offset[1])):jvm.SVGImageElement.parentClass.prototype.applyAttr.apply(this,arguments)},jvm.SVGTextElement=function(config,style){jvm.SVGTextElement.parentClass.call(this,"text",config,style)},jvm.inherits(jvm.SVGTextElement,jvm.SVGShapeElement),jvm.SVGTextElement.prototype.applyAttr=function(attr,value){"text"===attr?this.node.textContent=value:jvm.SVGTextElement.parentClass.prototype.applyAttr.apply(this,arguments)},jvm.VMLElement=function(name,config){jvm.VMLElement.VMLInitialized||jvm.VMLElement.initializeVML(),jvm.VMLElement.parentClass.apply(this,arguments)},jvm.inherits(jvm.VMLElement,jvm.AbstractElement),jvm.VMLElement.VMLInitialized=!1,jvm.VMLElement.initializeVML=function(){try{document.namespaces.rvml||document.namespaces.add("rvml","urn:schemas-microsoft-com:vml"),jvm.VMLElement.prototype.createElement=function(tagName){return document.createElement("<rvml:"+tagName+' class="rvml">')}}catch(e){jvm.VMLElement.prototype.createElement=function(tagName){return document.createElement("<"+tagName+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}document.createStyleSheet().addRule(".rvml","behavior:url(#default#VML)"),jvm.VMLElement.VMLInitialized=!0},jvm.VMLElement.prototype.getElementCtr=function(ctr){return jvm["VML"+ctr]},jvm.VMLElement.prototype.addClass=function(className){jvm.$(this.node).addClass(className)},jvm.VMLElement.prototype.applyAttr=function(attr,value){this.node[attr]=value},jvm.VMLElement.prototype.getBBox=function(){var node=jvm.$(this.node);return{x:node.position().left/this.canvas.scale,y:node.position().top/this.canvas.scale,width:node.width()/this.canvas.scale,height:node.height()/this.canvas.scale}},jvm.VMLGroupElement=function(){jvm.VMLGroupElement.parentClass.call(this,"group"),this.node.style.left="0px",this.node.style.top="0px",this.node.coordorigin="0 0"},jvm.inherits(jvm.VMLGroupElement,jvm.VMLElement),jvm.VMLGroupElement.prototype.add=function(element){this.node.appendChild(element.node)},jvm.VMLCanvasElement=function(container,width,height){this.classPrefix="VML",jvm.VMLCanvasElement.parentClass.call(this,"group"),jvm.AbstractCanvasElement.apply(this,arguments),this.node.style.position="absolute"},jvm.inherits(jvm.VMLCanvasElement,jvm.VMLElement),jvm.mixin(jvm.VMLCanvasElement,jvm.AbstractCanvasElement),jvm.VMLCanvasElement.prototype.setSize=function(width,height){var paths,groups,i,l;if(this.width=width,this.height=height,this.node.style.width=width+"px",this.node.style.height=height+"px",this.node.coordsize=width+" "+height,this.node.coordorigin="0 0",this.rootElement){for(i=0,l=(paths=this.rootElement.node.getElementsByTagName("shape")).length;i<l;i++)paths[i].coordsize=width+" "+height,paths[i].style.width=width+"px",paths[i].style.height=height+"px";for(i=0,l=(groups=this.node.getElementsByTagName("group")).length;i<l;i++)groups[i].coordsize=width+" "+height,groups[i].style.width=width+"px",groups[i].style.height=height+"px"}},jvm.VMLCanvasElement.prototype.applyTransformParams=function(scale,transX,transY){this.scale=scale,this.transX=transX,this.transY=transY,this.rootElement.node.coordorigin=this.width-transX-this.width/100+","+(this.height-transY-this.height/100),this.rootElement.node.coordsize=this.width/scale+","+this.height/scale},jvm.VMLShapeElement=function(name,config){jvm.VMLShapeElement.parentClass.call(this,name,config),this.fillElement=new jvm.VMLElement("fill"),this.strokeElement=new jvm.VMLElement("stroke"),this.node.appendChild(this.fillElement.node),this.node.appendChild(this.strokeElement.node),this.node.stroked=!1,jvm.AbstractShapeElement.apply(this,arguments)},jvm.inherits(jvm.VMLShapeElement,jvm.VMLElement),jvm.mixin(jvm.VMLShapeElement,jvm.AbstractShapeElement),jvm.VMLShapeElement.prototype.applyAttr=function(attr,value){switch(attr){case"fill":this.node.fillcolor=value;break;case"fill-opacity":this.fillElement.node.opacity=Math.round(100*value)+"%";break;case"stroke":this.node.stroked="none"!==value,this.node.strokecolor=value;break;case"stroke-opacity":this.strokeElement.node.opacity=Math.round(100*value)+"%";break;case"stroke-width":0===parseInt(value,10)?this.node.stroked=!1:this.node.stroked=!0,this.node.strokeweight=value;break;case"d":this.node.path=jvm.VMLPathElement.pathSvgToVml(value);break;default:jvm.VMLShapeElement.parentClass.prototype.applyAttr.apply(this,arguments)}},jvm.VMLPathElement=function(config,style){var scale=new jvm.VMLElement("skew");jvm.VMLPathElement.parentClass.call(this,"shape",config,style),this.node.coordorigin="0 0",scale.node.on=!0,scale.node.matrix="0.01,0,0,0.01,0,0",scale.node.offset="0,0",this.node.appendChild(scale.node)},jvm.inherits(jvm.VMLPathElement,jvm.VMLShapeElement),jvm.VMLPathElement.prototype.applyAttr=function(attr,value){"d"===attr?this.node.path=jvm.VMLPathElement.pathSvgToVml(value):jvm.VMLShapeElement.prototype.applyAttr.call(this,attr,value)},jvm.VMLPathElement.pathSvgToVml=function(path){var ctrlx,ctrly,cx=0,cy=0;return(path=path.replace(/(-?\d+)e(-?\d+)/g,"0")).replace(/([MmLlHhVvCcSs])\s*((?:-?\d*(?:\.\d+)?\s*,?\s*)+)/g,function(segment,letter,coords,index){(coords=coords.replace(/(\d)-/g,"$1,-").replace(/^\s+/g,"").replace(/\s+$/g,"").replace(/\s+/g,",").split(","))[0]||coords.shift();for(var i=0,l=coords.length;i<l;i++)coords[i]=Math.round(100*coords[i]);switch(letter){case"m":return cx+=coords[0],cy+=coords[1],"t"+coords.join(",");case"M":return cx=coords[0],cy=coords[1],"m"+coords.join(",");case"l":return cx+=coords[0],cy+=coords[1],"r"+coords.join(",");case"L":return cx=coords[0],cy=coords[1],"l"+coords.join(",");case"h":return cx+=coords[0],"r"+coords[0]+",0";case"H":return"l"+(cx=coords[0])+","+cy;case"v":return cy+=coords[0],"r0,"+coords[0];case"V":return cy=coords[0],"l"+cx+","+cy;case"c":return ctrlx=cx+coords[coords.length-4],ctrly=cy+coords[coords.length-3],cx+=coords[coords.length-2],cy+=coords[coords.length-1],"v"+coords.join(",");case"C":return ctrlx=coords[coords.length-4],ctrly=coords[coords.length-3],cx=coords[coords.length-2],cy=coords[coords.length-1],"c"+coords.join(",");case"s":return coords.unshift(cy-ctrly),coords.unshift(cx-ctrlx),ctrlx=cx+coords[coords.length-4],ctrly=cy+coords[coords.length-3],cx+=coords[coords.length-2],cy+=coords[coords.length-1],"v"+coords.join(",");case"S":return coords.unshift(cy+cy-ctrly),coords.unshift(cx+cx-ctrlx),ctrlx=coords[coords.length-4],ctrly=coords[coords.length-3],cx=coords[coords.length-2],cy=coords[coords.length-1],"c"+coords.join(",")}return""}).replace(/z/g,"e")},jvm.VMLCircleElement=function(config,style){jvm.VMLCircleElement.parentClass.call(this,"oval",config,style)},jvm.inherits(jvm.VMLCircleElement,jvm.VMLShapeElement),jvm.VMLCircleElement.prototype.applyAttr=function(attr,value){switch(attr){case"r":this.node.style.width=2*value+"px",this.node.style.height=2*value+"px",this.applyAttr("cx",this.get("cx")||0),this.applyAttr("cy",this.get("cy")||0);break;case"cx":if(!value)return;this.node.style.left=value-(this.get("r")||0)+"px";break;case"cy":if(!value)return;this.node.style.top=value-(this.get("r")||0)+"px";break;default:jvm.VMLCircleElement.parentClass.prototype.applyAttr.call(this,attr,value)}},jvm.VectorCanvas=function(container,width,height){return this.mode=window.SVGAngle?"svg":"vml","svg"==this.mode?this.impl=new jvm.SVGCanvasElement(container,width,height):this.impl=new jvm.VMLCanvasElement(container,width,height),this.impl.mode=this.mode,this.impl},jvm.SimpleScale=function(scale){this.scale=scale},jvm.SimpleScale.prototype.getValue=function(value){return value},jvm.OrdinalScale=function(scale){this.scale=scale},jvm.OrdinalScale.prototype.getValue=function(value){return this.scale[value]},jvm.OrdinalScale.prototype.getTicks=function(){var key,ticks=[];for(key in this.scale)ticks.push({label:key,value:this.scale[key]});return ticks},jvm.NumericScale=function(scale,normalizeFunction,minValue,maxValue){this.scale=[],normalizeFunction=normalizeFunction||"linear",scale&&this.setScale(scale),normalizeFunction&&this.setNormalizeFunction(normalizeFunction),void 0!==minValue&&this.setMin(minValue),void 0!==maxValue&&this.setMax(maxValue)},jvm.NumericScale.prototype={setMin:function(min){this.clearMinValue=min,"function"==typeof this.normalize?this.minValue=this.normalize(min):this.minValue=min},setMax:function(max){this.clearMaxValue=max,"function"==typeof this.normalize?this.maxValue=this.normalize(max):this.maxValue=max},setScale:function(scale){var i;for(this.scale=[],i=0;i<scale.length;i++)this.scale[i]=[scale[i]]},setNormalizeFunction:function(f){"polynomial"===f?this.normalize=function(value){return Math.pow(value,.2)}:"linear"===f?delete this.normalize:this.normalize=f,this.setMin(this.clearMinValue),this.setMax(this.clearMaxValue)},getValue:function(value){var l,c,lengthes=[],fullLength=0,i=0;for("function"==typeof this.normalize&&(value=this.normalize(value)),i=0;i<this.scale.length-1;i++)l=this.vectorLength(this.vectorSubtract(this.scale[i+1],this.scale[i])),lengthes.push(l),fullLength+=l;for(c=(this.maxValue-this.minValue)/fullLength,i=0;i<lengthes.length;i++)lengthes[i]*=c;for(i=0,value-=this.minValue;0<=value-lengthes[i];)value-=lengthes[i],i++;return value=i==this.scale.length-1?this.vectorToNum(this.scale[i]):this.vectorToNum(this.vectorAdd(this.scale[i],this.vectorMult(this.vectorSubtract(this.scale[i+1],this.scale[i]),value/lengthes[i])))},vectorToNum:function(vector){var i,num=0;for(i=0;i<vector.length;i++)num+=Math.round(vector[i])*Math.pow(256,vector.length-i-1);return num},vectorSubtract:function(vector1,vector2){var i,vector=[];for(i=0;i<vector1.length;i++)vector[i]=vector1[i]-vector2[i];return vector},vectorAdd:function(vector1,vector2){var i,vector=[];for(i=0;i<vector1.length;i++)vector[i]=vector1[i]+vector2[i];return vector},vectorMult:function(vector,num){var i,result=[];for(i=0;i<vector.length;i++)result[i]=vector[i]*num;return result},vectorLength:function(vector){var i,result=0;for(i=0;i<vector.length;i++)result+=vector[i]*vector[i];return Math.sqrt(result)},getTicks:function(){var tick,v,extent=[this.clearMinValue,this.clearMaxValue],span=extent[1]-extent[0],step=Math.pow(10,Math.floor(Math.log(span/5)/Math.LN10)),err=5/span*step,ticks=[];for(err<=.15?step*=10:err<=.35?step*=5:err<=.75&&(step*=2),extent[0]=Math.floor(extent[0]/step)*step,extent[1]=Math.ceil(extent[1]/step)*step,tick=extent[0];tick<=extent[1];)v=tick==extent[0]?this.clearMinValue:tick==extent[1]?this.clearMaxValue:tick,ticks.push({label:tick,value:this.getValue(v)}),tick+=step;return ticks}},jvm.ColorScale=function(colors,normalizeFunction,minValue,maxValue){jvm.ColorScale.parentClass.apply(this,arguments)},jvm.inherits(jvm.ColorScale,jvm.NumericScale),jvm.ColorScale.prototype.setScale=function(scale){var i;for(i=0;i<scale.length;i++)this.scale[i]=jvm.ColorScale.rgbToArray(scale[i])},jvm.ColorScale.prototype.getValue=function(value){return jvm.ColorScale.numToRgb(jvm.ColorScale.parentClass.prototype.getValue.call(this,value))},jvm.ColorScale.arrayToRgb=function(ar){var d,i,rgb="#";for(i=0;i<ar.length;i++)rgb+=1==(d=ar[i].toString(16)).length?"0"+d:d;return rgb},jvm.ColorScale.numToRgb=function(num){for(num=num.toString(16);num.length<6;)num="0"+num;return"#"+num},jvm.ColorScale.rgbToArray=function(rgb){return rgb=rgb.substr(1),[parseInt(rgb.substr(0,2),16),parseInt(rgb.substr(2,2),16),parseInt(rgb.substr(4,2),16)]},jvm.Legend=function(params){this.params=params||{},this.map=this.params.map,this.series=this.params.series,this.body=jvm.$("<div/>"),this.body.addClass("jvectormap-legend"),this.params.cssClass&&this.body.addClass(this.params.cssClass),params.vertical?this.map.legendCntVertical.append(this.body):this.map.legendCntHorizontal.append(this.body),this.render()},jvm.Legend.prototype.render=function(){var i,tick,sample,label,ticks=this.series.scale.getTicks(),inner=jvm.$("<div/>").addClass("jvectormap-legend-inner");for(this.body.html(""),this.params.title&&this.body.append(jvm.$("<div/>").addClass("jvectormap-legend-title").html(this.params.title)),this.body.append(inner),i=0;i<ticks.length;i++){switch(tick=jvm.$("<div/>").addClass("jvectormap-legend-tick"),sample=jvm.$("<div/>").addClass("jvectormap-legend-tick-sample"),this.series.params.attribute){case"fill":jvm.isImageUrl(ticks[i].value)?sample.css("background","url("+ticks[i].value+")"):sample.css("background",ticks[i].value);break;case"stroke":sample.css("background",ticks[i].value);break;case"image":sample.css("background","url("+("object"==typeof ticks[i].value?ticks[i].value.url:ticks[i].value)+") no-repeat center center");break;case"r":jvm.$("<div/>").css({"border-radius":ticks[i].value,border:this.map.params.markerStyle.initial["stroke-width"]+"px "+this.map.params.markerStyle.initial.stroke+" solid",width:2*ticks[i].value+"px",height:2*ticks[i].value+"px",background:this.map.params.markerStyle.initial.fill}).appendTo(sample)}tick.append(sample),label=ticks[i].label,this.params.labelRender&&(label=this.params.labelRender(label)),tick.append(jvm.$("<div>"+label+" </div>").addClass("jvectormap-legend-tick-text")),inner.append(tick)}inner.append(jvm.$("<div/>").css("clear","both"))},jvm.DataSeries=function(params,elements,map){var scaleConstructor;(params=params||{}).attribute=params.attribute||"fill",this.elements=elements,this.params=params,this.map=map,params.attributes&&this.setAttributes(params.attributes),jvm.$.isArray(params.scale)?(scaleConstructor="fill"===params.attribute||"stroke"===params.attribute?jvm.ColorScale:jvm.NumericScale,this.scale=new scaleConstructor(params.scale,params.normalizeFunction,params.min,params.max)):params.scale?this.scale=new jvm.OrdinalScale(params.scale):this.scale=new jvm.SimpleScale(params.scale),this.values=params.values||{},this.setValues(this.values),this.params.legend&&(this.legend=new jvm.Legend(jvm.$.extend({map:this.map,series:this},this.params.legend)))},jvm.DataSeries.prototype={setAttributes:function(key,attr){var code,attrs=key;if("string"==typeof key)this.elements[key]&&this.elements[key].setStyle(this.params.attribute,attr);else for(code in attrs)this.elements[code]&&this.elements[code].element.setStyle(this.params.attribute,attrs[code])},setValues:function(values){var val,cc,max=-Number.MAX_VALUE,min=Number.MAX_VALUE,attrs={};if(this.scale instanceof jvm.OrdinalScale||this.scale instanceof jvm.SimpleScale)for(cc in values)values[cc]?attrs[cc]=this.scale.getValue(values[cc]):attrs[cc]=this.elements[cc].element.style.initial[this.params.attribute];else{if(void 0===this.params.min||void 0===this.params.max)for(cc in values)max<(val=parseFloat(values[cc]))&&(max=val),val<min&&(min=val);for(cc in void 0===this.params.min?(this.scale.setMin(min),this.params.min=min):this.scale.setMin(this.params.min),void 0===this.params.max?(this.scale.setMax(max),this.params.max=max):this.scale.setMax(this.params.max),values)"indexOf"!=cc&&(val=parseFloat(values[cc]),isNaN(val)?attrs[cc]=this.elements[cc].element.style.initial[this.params.attribute]:attrs[cc]=this.scale.getValue(val))}this.setAttributes(attrs),jvm.$.extend(this.values,values)},clear:function(){var key,attrs={};for(key in this.values)this.elements[key]&&(attrs[key]=this.elements[key].element.shape.style.initial[this.params.attribute]);this.setAttributes(attrs),this.values={}},setScale:function(scale){this.scale.setScale(scale),this.values&&this.setValues(this.values)},setNormalizeFunction:function(f){this.scale.setNormalizeFunction(f),this.values&&this.setValues(this.values)}},jvm.Proj={degRad:180/Math.PI,radDeg:Math.PI/180,radius:6381372,sgn:function(n){return 0<n?1:n<0?-1:n},mill:function(lat,lng,c){return{x:this.radius*(lng-c)*this.radDeg,y:-this.radius*Math.log(Math.tan((45+.4*lat)*this.radDeg))/.8}},mill_inv:function(x,y,c){return{lat:(2.5*Math.atan(Math.exp(.8*y/this.radius))-5*Math.PI/8)*this.degRad,lng:(c*this.radDeg+x/this.radius)*this.degRad}},merc:function(lat,lng,c){return{x:this.radius*(lng-c)*this.radDeg,y:-this.radius*Math.log(Math.tan(Math.PI/4+lat*Math.PI/360))}},merc_inv:function(x,y,c){return{lat:(2*Math.atan(Math.exp(y/this.radius))-Math.PI/2)*this.degRad,lng:(c*this.radDeg+x/this.radius)*this.degRad}},aea:function(lat,lng,c){var lambda0=c*this.radDeg,fi1=29.5*this.radDeg,fi2=45.5*this.radDeg,fi=lat*this.radDeg,lambda=lng*this.radDeg,n=(Math.sin(fi1)+Math.sin(fi2))/2,C=Math.cos(fi1)*Math.cos(fi1)+2*n*Math.sin(fi1),theta=n*(lambda-lambda0),ro=Math.sqrt(C-2*n*Math.sin(fi))/n,ro0=Math.sqrt(C-2*n*Math.sin(0))/n;return{x:ro*Math.sin(theta)*this.radius,y:-(ro0-ro*Math.cos(theta))*this.radius}},aea_inv:function(xCoord,yCoord,c){var x=xCoord/this.radius,y=yCoord/this.radius,lambda0=c*this.radDeg,fi1=29.5*this.radDeg,fi2=45.5*this.radDeg,n=(Math.sin(fi1)+Math.sin(fi2))/2,C=Math.cos(fi1)*Math.cos(fi1)+2*n*Math.sin(fi1),ro0=Math.sqrt(C-2*n*Math.sin(0))/n,ro=Math.sqrt(x*x+(ro0-y)*(ro0-y)),theta=Math.atan(x/(ro0-y));return{lat:Math.asin((C-ro*ro*n*n)/(2*n))*this.degRad,lng:(lambda0+theta/n)*this.degRad}},lcc:function(lat,lng,c){var lambda0=c*this.radDeg,lambda=lng*this.radDeg,fi1=33*this.radDeg,fi2=45*this.radDeg,fi=lat*this.radDeg,n=Math.log(Math.cos(fi1)*(1/Math.cos(fi2)))/Math.log(Math.tan(Math.PI/4+fi2/2)*(1/Math.tan(Math.PI/4+fi1/2))),F=Math.cos(fi1)*Math.pow(Math.tan(Math.PI/4+fi1/2),n)/n,ro=F*Math.pow(1/Math.tan(Math.PI/4+fi/2),n),ro0=F*Math.pow(1/Math.tan(Math.PI/4+0),n);return{x:ro*Math.sin(n*(lambda-lambda0))*this.radius,y:-(ro0-ro*Math.cos(n*(lambda-lambda0)))*this.radius}},lcc_inv:function(xCoord,yCoord,c){var x=xCoord/this.radius,y=yCoord/this.radius,lambda0=c*this.radDeg,fi1=33*this.radDeg,fi2=45*this.radDeg,n=Math.log(Math.cos(fi1)*(1/Math.cos(fi2)))/Math.log(Math.tan(Math.PI/4+fi2/2)*(1/Math.tan(Math.PI/4+fi1/2))),F=Math.cos(fi1)*Math.pow(Math.tan(Math.PI/4+fi1/2),n)/n,ro0=F*Math.pow(1/Math.tan(Math.PI/4+0),n),ro=this.sgn(n)*Math.sqrt(x*x+(ro0-y)*(ro0-y)),theta=Math.atan(x/(ro0-y));return{lat:(2*Math.atan(Math.pow(F/ro,1/n))-Math.PI/2)*this.degRad,lng:(lambda0+theta/n)*this.degRad}}},jvm.MapObject=function(config){},jvm.MapObject.prototype.getLabelText=function(key){return this.config.label?"function"==typeof this.config.label.render?this.config.label.render(key):key:null},jvm.MapObject.prototype.getLabelOffsets=function(key){var offsets;return this.config.label&&("function"==typeof this.config.label.offsets?offsets=this.config.label.offsets(key):"object"==typeof this.config.label.offsets&&(offsets=this.config.label.offsets[key])),offsets||[0,0]},jvm.MapObject.prototype.setHovered=function(isHovered){this.isHovered!==isHovered&&(this.isHovered=isHovered,this.shape.isHovered=isHovered,this.shape.updateStyle(),this.label&&(this.label.isHovered=isHovered,this.label.updateStyle()))},jvm.MapObject.prototype.setSelected=function(isSelected){this.isSelected!==isSelected&&(this.isSelected=isSelected,this.shape.isSelected=isSelected,this.shape.updateStyle(),this.label&&(this.label.isSelected=isSelected,this.label.updateStyle()),jvm.$(this.shape).trigger("selected",[isSelected]))},jvm.MapObject.prototype.setStyle=function(){this.shape.setStyle.apply(this.shape,arguments)},jvm.MapObject.prototype.remove=function(){this.shape.remove(),this.label&&this.label.remove()},jvm.Region=function(config){var bbox,text,offsets;this.config=config,this.map=this.config.map,this.shape=config.canvas.addPath({d:config.path,"data-code":config.code},config.style,config.canvas.rootElement),this.shape.addClass("jvectormap-region jvectormap-element"),bbox=this.shape.getBBox(),text=this.getLabelText(config.code),this.config.label&&text&&(offsets=this.getLabelOffsets(config.code),this.labelX=bbox.x+bbox.width/2+offsets[0],this.labelY=bbox.y+bbox.height/2+offsets[1],this.label=config.canvas.addText({text:text,"text-anchor":"middle","alignment-baseline":"central",x:this.labelX,y:this.labelY,"data-code":config.code},config.labelStyle,config.labelsGroup),this.label.addClass("jvectormap-region jvectormap-element"))},jvm.inherits(jvm.Region,jvm.MapObject),jvm.Region.prototype.updateLabelPosition=function(){this.label&&this.label.set({x:this.labelX*this.map.scale+this.map.transX*this.map.scale,y:this.labelY*this.map.scale+this.map.transY*this.map.scale})},jvm.Marker=function(config){var text;this.config=config,this.map=this.config.map,this.isImage=!!this.config.style.initial.image,this.createShape(),text=this.getLabelText(config.index),this.config.label&&text&&(this.offsets=this.getLabelOffsets(config.index),this.labelX=config.cx/this.map.scale-this.map.transX,this.labelY=config.cy/this.map.scale-this.map.transY,this.label=config.canvas.addText({text:text,"data-index":config.index,dy:"0.6ex",x:this.labelX,y:this.labelY},config.labelStyle,config.labelsGroup),this.label.addClass("jvectormap-marker jvectormap-element"))},jvm.inherits(jvm.Marker,jvm.MapObject),jvm.Marker.prototype.createShape=function(){var that=this;this.shape&&this.shape.remove(),this.shape=this.config.canvas[this.isImage?"addImage":"addCircle"]({"data-index":this.config.index,cx:this.config.cx,cy:this.config.cy},this.config.style,this.config.group),this.shape.addClass("jvectormap-marker jvectormap-element"),this.isImage&&jvm.$(this.shape.node).on("imageloaded",function(){that.updateLabelPosition()})},jvm.Marker.prototype.updateLabelPosition=function(){this.label&&this.label.set({x:this.labelX*this.map.scale+this.offsets[0]+this.map.transX*this.map.scale+5+(this.isImage?(this.shape.width||0)/2:this.shape.properties.r),y:this.labelY*this.map.scale+this.map.transY*this.map.scale+this.offsets[1]})},jvm.Marker.prototype.setStyle=function(property,value){var isImage;jvm.Marker.parentClass.prototype.setStyle.apply(this,arguments),"r"===property&&this.updateLabelPosition(),(isImage=!!this.shape.get("image"))!=this.isImage&&(this.isImage=isImage,this.config.style=jvm.$.extend(!0,{},this.shape.style),this.createShape())},jvm.Map=function(params){var e,map=this;if(this.params=jvm.$.extend(!0,{},jvm.Map.defaultParams,params),!jvm.Map.maps[this.params.map])throw new Error("Attempt to use map which was not loaded: "+this.params.map);for(e in this.mapData=jvm.Map.maps[this.params.map],this.markers={},this.regions={},this.regionsColors={},this.regionsData={},this.container=jvm.$("<div>").addClass("jvectormap-container"),this.params.container&&this.params.container.append(this.container),this.container.data("mapObject",this),this.defaultWidth=this.mapData.width,this.defaultHeight=this.mapData.height,this.setBackgroundColor(this.params.backgroundColor),this.onResize=function(){map.updateSize()},jvm.$(window).resize(this.onResize),jvm.Map.apiEvents)this.params[e]&&this.container.bind(jvm.Map.apiEvents[e]+".jvectormap",this.params[e]);this.canvas=new jvm.VectorCanvas(this.container[0],this.width,this.height),this.params.bindTouchEvents&&("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch?this.bindContainerTouchEvents():window.MSGesture&&this.bindContainerPointerEvents()),this.bindContainerEvents(),this.bindElementEvents(),this.createTip(),this.params.zoomButtons&&this.bindZoomButtons(),this.createRegions(),this.createMarkers(this.params.markers||{}),this.updateSize(),this.params.focusOn&&("string"==typeof this.params.focusOn?this.params.focusOn={region:this.params.focusOn}:jvm.$.isArray(this.params.focusOn)&&(this.params.focusOn={regions:this.params.focusOn}),this.setFocus(this.params.focusOn)),this.params.selectedRegions&&this.setSelectedRegions(this.params.selectedRegions),this.params.selectedMarkers&&this.setSelectedMarkers(this.params.selectedMarkers),this.legendCntHorizontal=jvm.$("<div/>").addClass("jvectormap-legend-cnt jvectormap-legend-cnt-h"),this.legendCntVertical=jvm.$("<div/>").addClass("jvectormap-legend-cnt jvectormap-legend-cnt-v"),this.container.append(this.legendCntHorizontal),this.container.append(this.legendCntVertical),this.params.series&&this.createSeries()},jvm.Map.prototype={transX:0,transY:0,scale:1,baseTransX:0,baseTransY:0,baseScale:1,width:0,height:0,setBackgroundColor:function(backgroundColor){this.container.css("background-color",backgroundColor)},resize:function(){var curBaseScale=this.baseScale;this.width/this.height>this.defaultWidth/this.defaultHeight?(this.baseScale=this.height/this.defaultHeight,this.baseTransX=Math.abs(this.width-this.defaultWidth*this.baseScale)/(2*this.baseScale)):(this.baseScale=this.width/this.defaultWidth,this.baseTransY=Math.abs(this.height-this.defaultHeight*this.baseScale)/(2*this.baseScale)),this.scale*=this.baseScale/curBaseScale,this.transX*=this.baseScale/curBaseScale,this.transY*=this.baseScale/curBaseScale},updateSize:function(){this.width=this.container.width(),this.height=this.container.height(),this.resize(),this.canvas.setSize(this.width,this.height),this.applyTransform()},reset:function(){var key,i;for(key in this.series)for(i=0;i<this.series[key].length;i++)this.series[key][i].clear();this.scale=this.baseScale,this.transX=this.baseTransX,this.transY=this.baseTransY,this.applyTransform()},applyTransform:function(){var maxTransX,maxTransY,minTransX,minTransY;minTransX=this.defaultWidth*this.scale<=this.width?(maxTransX=(this.width-this.defaultWidth*this.scale)/(2*this.scale),(this.width-this.defaultWidth*this.scale)/(2*this.scale)):(maxTransX=0,(this.width-this.defaultWidth*this.scale)/this.scale),minTransY=this.defaultHeight*this.scale<=this.height?(maxTransY=(this.height-this.defaultHeight*this.scale)/(2*this.scale),(this.height-this.defaultHeight*this.scale)/(2*this.scale)):(maxTransY=0,(this.height-this.defaultHeight*this.scale)/this.scale),this.transY>maxTransY?this.transY=maxTransY:this.transY<minTransY&&(this.transY=minTransY),this.transX>maxTransX?this.transX=maxTransX:this.transX<minTransX&&(this.transX=minTransX),this.canvas.applyTransformParams(this.scale,this.transX,this.transY),this.markers&&this.repositionMarkers(),this.repositionLabels(),this.container.trigger("viewportChange",[this.scale/this.baseScale,this.transX,this.transY])},bindContainerEvents:function(){var oldPageX,oldPageY,mouseDown=!1,map=this;this.params.panOnDrag&&(this.container.mousemove(function(e){return mouseDown&&(map.transX-=(oldPageX-e.pageX)/map.scale,map.transY-=(oldPageY-e.pageY)/map.scale,map.applyTransform(),oldPageX=e.pageX,oldPageY=e.pageY),!1}).mousedown(function(e){return mouseDown=!0,oldPageX=e.pageX,oldPageY=e.pageY,!1}),this.onContainerMouseUp=function(){mouseDown=!1},jvm.$("body").mouseup(this.onContainerMouseUp)),this.params.zoomOnScroll&&this.container.mousewheel(function(event,delta,deltaX,deltaY){var offset=jvm.$(map.container).offset(),centerX=event.pageX-offset.left,centerY=event.pageY-offset.top,zoomStep=Math.pow(1+map.params.zoomOnScrollSpeed/1e3,event.deltaFactor*event.deltaY);map.tip.hide(),map.setScale(map.scale*zoomStep,centerX,centerY),event.preventDefault()})},bindContainerTouchEvents:function(){function handleTouchEvent(e){var offset,scale,transXOld,transYOld,touches=e.originalEvent.touches;"touchstart"==e.type&&(lastTouchesLength=0),1==touches.length?(1==lastTouchesLength&&(transXOld=map.transX,transYOld=map.transY,map.transX-=(touchX-touches[0].pageX)/map.scale,map.transY-=(touchY-touches[0].pageY)/map.scale,map.applyTransform(),map.tip.hide(),transXOld==map.transX&&transYOld==map.transY||e.preventDefault()),touchX=touches[0].pageX,touchY=touches[0].pageY):2==touches.length&&(2==lastTouchesLength?(scale=Math.sqrt(Math.pow(touches[0].pageX-touches[1].pageX,2)+Math.pow(touches[0].pageY-touches[1].pageY,2))/touchStartDistance,map.setScale(touchStartScale*scale,centerTouchX,centerTouchY),map.tip.hide(),e.preventDefault()):(offset=jvm.$(map.container).offset(),centerTouchX=touches[0].pageX>touches[1].pageX?touches[1].pageX+(touches[0].pageX-touches[1].pageX)/2:touches[0].pageX+(touches[1].pageX-touches[0].pageX)/2,centerTouchY=touches[0].pageY>touches[1].pageY?touches[1].pageY+(touches[0].pageY-touches[1].pageY)/2:touches[0].pageY+(touches[1].pageY-touches[0].pageY)/2,centerTouchX-=offset.left,centerTouchY-=offset.top,touchStartScale=map.scale,touchStartDistance=Math.sqrt(Math.pow(touches[0].pageX-touches[1].pageX,2)+Math.pow(touches[0].pageY-touches[1].pageY,2)))),lastTouchesLength=touches.length}var touchStartScale,touchStartDistance,touchX,touchY,centerTouchX,centerTouchY,lastTouchesLength,map=this;jvm.$(this.container).bind("touchstart",handleTouchEvent),jvm.$(this.container).bind("touchmove",handleTouchEvent)},bindContainerPointerEvents:function(){var map=this,gesture=new MSGesture,element=this.container[0];(gesture.target=element).addEventListener("MSGestureChange",function(e){var transXOld,transYOld;0==e.translationX&&0==e.translationY||(transXOld=map.transX,transYOld=map.transY,map.transX+=e.translationX/map.scale,map.transY+=e.translationY/map.scale,map.applyTransform(),map.tip.hide(),transXOld==map.transX&&transYOld==map.transY||e.preventDefault()),1!=e.scale&&(map.setScale(map.scale*e.scale,e.offsetX,e.offsetY),map.tip.hide(),e.preventDefault())},!1),element.addEventListener("pointerdown",function(e){gesture.addPointer(e.pointerId)},!1)},bindElementEvents:function(){var pageX,pageY,mouseMoved,map=this;this.container.mousemove(function(e){2<Math.abs(pageX-e.pageX)+Math.abs(pageY-e.pageY)&&(mouseMoved=!0)}),this.container.delegate("[class~='jvectormap-element']","mouseover mouseout",function(e){var type=-1===(jvm.$(this).attr("class").baseVal||jvm.$(this).attr("class")).indexOf("jvectormap-region")?"marker":"region",code="region"==type?jvm.$(this).attr("data-code"):jvm.$(this).attr("data-index"),element="region"==type?map.regions[code].element:map.markers[code].element,tipText="region"==type?map.mapData.paths[code].name:map.markers[code].config.name||"",tipShowEvent=jvm.$.Event(type+"TipShow.jvectormap"),overEvent=jvm.$.Event(type+"Over.jvectormap");"mouseover"==e.type?(map.container.trigger(overEvent,[code]),overEvent.isDefaultPrevented()||element.setHovered(!0),map.tip.text(tipText),map.container.trigger(tipShowEvent,[map.tip,code]),tipShowEvent.isDefaultPrevented()||(map.tip.show(),map.tipWidth=map.tip.width(),map.tipHeight=map.tip.height())):(element.setHovered(!1),map.tip.hide(),map.container.trigger(type+"Out.jvectormap",[code]))}),this.container.delegate("[class~='jvectormap-element']","mousedown",function(e){pageX=e.pageX,pageY=e.pageY,mouseMoved=!1}),this.container.delegate("[class~='jvectormap-element']","mouseup",function(){var type=-1===(jvm.$(this).attr("class").baseVal?jvm.$(this).attr("class").baseVal:jvm.$(this).attr("class")).indexOf("jvectormap-region")?"marker":"region",code="region"==type?jvm.$(this).attr("data-code"):jvm.$(this).attr("data-index"),clickEvent=jvm.$.Event(type+"Click.jvectormap"),element="region"==type?map.regions[code].element:map.markers[code].element;mouseMoved||(map.container.trigger(clickEvent,[code]),("region"==type&&map.params.regionsSelectable||"marker"==type&&map.params.markersSelectable)&&(clickEvent.isDefaultPrevented()||(map.params[type+"sSelectableOne"]&&map.clearSelected(type+"s"),element.setSelected(!element.isSelected))))})},bindZoomButtons:function(){var map=this;jvm.$("<div/>").addClass("jvectormap-zoomin").text("+").appendTo(this.container),jvm.$("<div/>").addClass("jvectormap-zoomout").html("−").appendTo(this.container),this.container.find(".jvectormap-zoomin").click(function(){map.setScale(map.scale*map.params.zoomStep,map.width/2,map.height/2,!1,map.params.zoomAnimate)}),this.container.find(".jvectormap-zoomout").click(function(){map.setScale(map.scale/map.params.zoomStep,map.width/2,map.height/2,!1,map.params.zoomAnimate)})},createTip:function(){var map=this;this.tip=jvm.$("<div/>").addClass("jvectormap-tip").appendTo(jvm.$("body")),this.container.mousemove(function(e){var left=e.pageX-15-map.tipWidth,top=e.pageY-15-map.tipHeight;left<5&&(left=e.pageX+15),top<5&&(top=e.pageY+15),map.tip.css({left:left,top:top})})},setScale:function(scale,anchorX,anchorY,isCentered,animate){var interval,scaleStart,scaleDiff,transXStart,transXDiff,transYStart,transYDiff,transX,transY,viewportChangeEvent=jvm.$.Event("zoom.jvectormap"),that=this,i=0,count=Math.abs(Math.round(60*(scale-this.scale)/Math.max(scale,this.scale))),deferred=new jvm.$.Deferred;return scale>this.params.zoomMax*this.baseScale?scale=this.params.zoomMax*this.baseScale:scale<this.params.zoomMin*this.baseScale&&(scale=this.params.zoomMin*this.baseScale),void 0!==anchorX&&void 0!==anchorY&&(zoomStep=scale/this.scale,transY=isCentered?(transX=anchorX+this.defaultWidth*(this.width/(this.defaultWidth*scale))/2,anchorY+this.defaultHeight*(this.height/(this.defaultHeight*scale))/2):(transX=this.transX-(zoomStep-1)/scale*anchorX,this.transY-(zoomStep-1)/scale*anchorY)),animate&&0<count?(scaleStart=this.scale,scaleDiff=(scale-scaleStart)/count,transXStart=this.transX*this.scale,transYStart=this.transY*this.scale,transXDiff=(transX*scale-transXStart)/count,transYDiff=(transY*scale-transYStart)/count,interval=setInterval(function(){i+=1,that.scale=scaleStart+scaleDiff*i,that.transX=(transXStart+transXDiff*i)/that.scale,that.transY=(transYStart+transYDiff*i)/that.scale,that.applyTransform(),i==count&&(clearInterval(interval),that.container.trigger(viewportChangeEvent,[scale/that.baseScale]),deferred.resolve())},10)):(this.transX=transX,this.transY=transY,this.scale=scale,this.applyTransform(),this.container.trigger(viewportChangeEvent,[scale/this.baseScale]),deferred.resolve()),deferred},setFocus:function(config){var bbox,itemBbox,codes,i,point;if((config=config||{}).region?codes=[config.region]:config.regions&&(codes=config.regions),codes){for(i=0;i<codes.length;i++)this.regions[codes[i]]&&(itemBbox=this.regions[codes[i]].element.shape.getBBox())&&(bbox=void 0===bbox?itemBbox:{x:Math.min(bbox.x,itemBbox.x),y:Math.min(bbox.y,itemBbox.y),width:Math.max(bbox.x+bbox.width,itemBbox.x+itemBbox.width)-Math.min(bbox.x,itemBbox.x),height:Math.max(bbox.y+bbox.height,itemBbox.y+itemBbox.height)-Math.min(bbox.y,itemBbox.y)});return this.setScale(Math.min(this.width/bbox.width,this.height/bbox.height),-(bbox.x+bbox.width/2),-(bbox.y+bbox.height/2),!0,config.animate)}return void 0!==config.lat&&void 0!==config.lng?(point=this.latLngToPoint(config.lat,config.lng),config.x=this.transX-point.x/this.scale,config.y=this.transY-point.y/this.scale):config.x&&config.y&&(config.x*=-this.defaultWidth,config.y*=-this.defaultHeight),this.setScale(config.scale*this.baseScale,config.x,config.y,!0,config.animate)},getSelected:function(type){var key,selected=[];for(key in this[type])this[type][key].element.isSelected&&selected.push(key);return selected},getSelectedRegions:function(){return this.getSelected("regions")},getSelectedMarkers:function(){return this.getSelected("markers")},setSelected:function(type,keys){var i;if("object"!=typeof keys&&(keys=[keys]),jvm.$.isArray(keys))for(i=0;i<keys.length;i++)this[type][keys[i]].element.setSelected(!0);else for(i in keys)this[type][i].element.setSelected(!!keys[i])},setSelectedRegions:function(keys){this.setSelected("regions",keys)},setSelectedMarkers:function(keys){this.setSelected("markers",keys)},clearSelected:function(type){var i,select={},selected=this.getSelected(type);for(i=0;i<selected.length;i++)select[selected[i]]=!1;this.setSelected(type,select)},clearSelectedRegions:function(){this.clearSelected("regions")},clearSelectedMarkers:function(){this.clearSelected("markers")},getMapObject:function(){return this},getRegionName:function(code){return this.mapData.paths[code].name},createRegions:function(){var key,region,map=this;for(key in this.regionLabelsGroup=this.regionLabelsGroup||this.canvas.addGroup(),this.mapData.paths)region=new jvm.Region({map:this,path:this.mapData.paths[key].path,code:key,style:jvm.$.extend(!0,{},this.params.regionStyle),labelStyle:jvm.$.extend(!0,{},this.params.regionLabelStyle),canvas:this.canvas,labelsGroup:this.regionLabelsGroup,label:"vml"!=this.canvas.mode?this.params.labels&&this.params.labels.regions:null}),jvm.$(region.shape).bind("selected",function(e,isSelected){map.container.trigger("regionSelected.jvectormap",[jvm.$(this.node).attr("data-code"),isSelected,map.getSelectedRegions()])}),this.regions[key]={element:region,config:this.mapData.paths[key]}},createMarkers:function(markers){var i,marker,point,markerConfig,markersArray,map=this;if(this.markersGroup=this.markersGroup||this.canvas.addGroup(),this.markerLabelsGroup=this.markerLabelsGroup||this.canvas.addGroup(),jvm.$.isArray(markers))for(markersArray=markers.slice(),markers={},i=0;i<markersArray.length;i++)markers[i]=markersArray[i];for(i in markers)markerConfig=markers[i]instanceof Array?{latLng:markers[i]}:markers[i],!1!==(point=this.getMarkerPosition(markerConfig))&&(marker=new jvm.Marker({map:this,style:jvm.$.extend(!0,{},this.params.markerStyle,{initial:markerConfig.style||{}}),labelStyle:jvm.$.extend(!0,{},this.params.markerLabelStyle),index:i,cx:point.x,cy:point.y,group:this.markersGroup,canvas:this.canvas,labelsGroup:this.markerLabelsGroup,label:"vml"!=this.canvas.mode?this.params.labels&&this.params.labels.markers:null}),jvm.$(marker.shape).bind("selected",function(e,isSelected){map.container.trigger("markerSelected.jvectormap",[jvm.$(this.node).attr("data-index"),isSelected,map.getSelectedMarkers()])}),this.markers[i]&&this.removeMarkers([i]),this.markers[i]={element:marker,config:markerConfig})},repositionMarkers:function(){var i,point;for(i in this.markers)!1!==(point=this.getMarkerPosition(this.markers[i].config))&&this.markers[i].element.setStyle({cx:point.x,cy:point.y})},repositionLabels:function(){var key;for(key in this.regions)this.regions[key].element.updateLabelPosition();for(key in this.markers)this.markers[key].element.updateLabelPosition()},getMarkerPosition:function(markerConfig){return jvm.Map.maps[this.params.map].projection?this.latLngToPoint.apply(this,markerConfig.latLng||[0,0]):{x:markerConfig.coords[0]*this.scale+this.transX*this.scale,y:markerConfig.coords[1]*this.scale+this.transY*this.scale}},addMarker:function(key,marker,seriesData){var values,i,markers={},data=[];seriesData=seriesData||[];for(markers[key]=marker,i=0;i<seriesData.length;i++)values={},void 0!==seriesData[i]&&(values[key]=seriesData[i]),data.push(values);this.addMarkers(markers,data)},addMarkers:function(markers,seriesData){var i;for(seriesData=seriesData||[],this.createMarkers(markers),i=0;i<seriesData.length;i++)this.series.markers[i].setValues(seriesData[i]||{})},removeMarkers:function(markers){var i;for(i=0;i<markers.length;i++)this.markers[markers[i]].element.remove(),delete this.markers[markers[i]]},removeAllMarkers:function(){var i,markers=[];for(i in this.markers)markers.push(i);this.removeMarkers(markers)},latLngToPoint:function(lat,lng){var point,inset,bbox,proj=jvm.Map.maps[this.params.map].projection,centralMeridian=proj.centralMeridian;return lng<-180+centralMeridian&&(lng+=360),point=jvm.Proj[proj.type](lat,lng,centralMeridian),!!(inset=this.getInsetForPoint(point.x,point.y))&&(bbox=inset.bbox,point.x=(point.x-bbox[0].x)/(bbox[1].x-bbox[0].x)*inset.width*this.scale,point.y=(point.y-bbox[0].y)/(bbox[1].y-bbox[0].y)*inset.height*this.scale,{x:point.x+this.transX*this.scale+inset.left*this.scale,y:point.y+this.transY*this.scale+inset.top*this.scale})},pointToLatLng:function(x,y){var i,inset,bbox,nx,ny,proj=jvm.Map.maps[this.params.map].projection,centralMeridian=proj.centralMeridian,insets=jvm.Map.maps[this.params.map].insets;for(i=0;i<insets.length;i++)if(bbox=(inset=insets[i]).bbox,nx=x-(this.transX*this.scale+inset.left*this.scale),ny=y-(this.transY*this.scale+inset.top*this.scale),nx=nx/(inset.width*this.scale)*(bbox[1].x-bbox[0].x)+bbox[0].x,ny=ny/(inset.height*this.scale)*(bbox[1].y-bbox[0].y)+bbox[0].y,nx>bbox[0].x&&nx<bbox[1].x&&ny>bbox[0].y&&ny<bbox[1].y)return jvm.Proj[proj.type+"_inv"](nx,-ny,centralMeridian);return!1},getInsetForPoint:function(x,y){var i,bbox,insets=jvm.Map.maps[this.params.map].insets;for(i=0;i<insets.length;i++)if(x>(bbox=insets[i].bbox)[0].x&&x<bbox[1].x&&y>bbox[0].y&&y<bbox[1].y)return insets[i]},createSeries:function(){var i,key;for(key in this.series={markers:[],regions:[]},this.params.series)for(i=0;i<this.params.series[key].length;i++)this.series[key][i]=new jvm.DataSeries(this.params.series[key][i],this[key],this)},remove:function(){this.tip.remove(),this.container.remove(),jvm.$(window).unbind("resize",this.onResize),jvm.$("body").unbind("mouseup",this.onContainerMouseUp)}},jvm.Map.maps={},jvm.Map.defaultParams={map:"world_mill_en",backgroundColor:"#505050",zoomButtons:!0,zoomOnScroll:!0,zoomOnScrollSpeed:3,panOnDrag:!0,zoomMax:8,zoomMin:1,zoomStep:1.6,zoomAnimate:!0,regionsSelectable:!1,markersSelectable:!1,bindTouchEvents:!0,regionStyle:{initial:{fill:"white","fill-opacity":1,stroke:"none","stroke-width":0,"stroke-opacity":1},hover:{"fill-opacity":.8,cursor:"pointer"},selected:{fill:"yellow"},selectedHover:{}},regionLabelStyle:{initial:{"font-family":"Verdana","font-size":"12","font-weight":"bold",cursor:"default",fill:"black"},hover:{cursor:"pointer"}},markerStyle:{initial:{fill:"grey",stroke:"#505050","fill-opacity":1,"stroke-width":1,"stroke-opacity":1,r:5},hover:{stroke:"black","stroke-width":2,cursor:"pointer"},selected:{fill:"blue"},selectedHover:{}},markerLabelStyle:{initial:{"font-family":"Verdana","font-size":"12","font-weight":"bold",cursor:"default",fill:"black"},hover:{cursor:"pointer"}}},jvm.Map.apiEvents={onRegionTipShow:"regionTipShow",onRegionOver:"regionOver",onRegionOut:"regionOut",onRegionClick:"regionClick",onRegionSelected:"regionSelected",onMarkerTipShow:"markerTipShow",onMarkerOver:"markerOver",onMarkerOut:"markerOut",onMarkerClick:"markerClick",onMarkerSelected:"markerSelected",onViewportChange:"viewportChange"},jvm.MultiMap=function(params){var that=this;this.maps={},this.params=jvm.$.extend(!0,{},jvm.MultiMap.defaultParams,params),this.params.maxLevel=this.params.maxLevel||Number.MAX_VALUE,this.params.main=this.params.main||{},this.params.main.multiMapLevel=0,this.history=[this.addMap(this.params.main.map,this.params.main)],this.defaultProjection=this.history[0].mapData.projection.type,this.mapsLoaded={},this.params.container.css({position:"relative"}),this.backButton=jvm.$("<div/>").addClass("jvectormap-goback").text("Back").appendTo(this.params.container),this.backButton.hide(),this.backButton.click(function(){that.goBack()}),this.spinner=jvm.$("<div/>").addClass("jvectormap-spinner").appendTo(this.params.container),this.spinner.hide()},jvm.MultiMap.prototype={addMap:function(name,config){var cnt=jvm.$("<div/>").css({width:"100%",height:"100%"});return this.params.container.append(cnt),this.maps[name]=new jvm.Map(jvm.$.extend(config,{container:cnt})),this.params.maxLevel>config.multiMapLevel&&this.maps[name].container.on("regionClick.jvectormap",{scope:this},function(e,code){var multimap=e.data.scope,mapName=multimap.params.mapNameByCode(code,multimap);multimap.drillDownPromise&&"pending"===multimap.drillDownPromise.state()||multimap.drillDown(mapName,code)}),this.maps[name]},downloadMap:function(code){var that=this,deferred=jvm.$.Deferred();return this.mapsLoaded[code]?deferred.resolve():jvm.$.get(this.params.mapUrlByCode(code,this)).then(function(){that.mapsLoaded[code]=!0,deferred.resolve()},function(){deferred.reject()}),deferred},drillDown:function(name,code){var currentMap=this.history[this.history.length-1],that=this,focusPromise=currentMap.setFocus({region:code,animate:!0}),downloadPromise=this.downloadMap(code);focusPromise.then(function(){"pending"===downloadPromise.state()&&that.spinner.show()}),downloadPromise.always(function(){that.spinner.hide()}),this.drillDownPromise=jvm.$.when(downloadPromise,focusPromise),this.drillDownPromise.then(function(){currentMap.params.container.hide(),that.maps[name]?that.maps[name].params.container.show():that.addMap(name,{map:name,multiMapLevel:currentMap.params.multiMapLevel+1}),that.history.push(that.maps[name]),that.backButton.show()})},goBack:function(){var currentMap=this.history.pop(),prevMap=this.history[this.history.length-1],that=this;currentMap.setFocus({scale:1,x:.5,y:.5,animate:!0}).then(function(){currentMap.params.container.hide(),prevMap.params.container.show(),prevMap.updateSize(),1===that.history.length&&that.backButton.hide(),prevMap.setFocus({scale:1,x:.5,y:.5,animate:!0})})}},jvm.MultiMap.defaultParams={mapNameByCode:function(code,multiMap){return code.toLowerCase()+"_"+multiMap.defaultProjection+"_en"},mapUrlByCode:function(code,multiMap){return"jquery-jvectormap-data-"+code.toLowerCase()+"-"+multiMap.defaultProjection+"-en.js"}};
|
|
assets/js/jquery-jvectormap-world-mill.js
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
jQuery.fn.vectorMap('addMap', 'world_mill',{"insets": [{"width": 900, "top": 0, "height": 440.7063107441331, "bbox": [{"y": -12671671.123330014, "x": -20004297.151525836}, {"y": 6930392.025135122, "x": 20026572.394749384}], "left": 0}], "paths": {"BD": {"path": "M651.84,230.21l-0.6,-2.0l-1.36,-1.71l-2.31,-0.11l-0.41,0.48l0.2,0.94l-0.53,0.99l-0.72,-0.36l-0.68,0.35l-1.2,-0.36l-0.37,-2.0l-0.81,-1.86l0.39,-1.46l-0.22,-0.47l-1.14,-0.53l0.29,-0.5l1.48,-0.94l0.03,-0.65l-1.55,-1.22l0.55,-1.14l1.61,0.94l1.04,0.15l0.18,1.54l0.34,0.35l5.64,0.63l-0.84,1.64l-1.22,0.34l-0.77,1.51l0.07,0.47l1.37,1.37l0.67,-0.19l0.42,-1.39l1.21,3.84l-0.03,1.21l-0.33,-0.15l-0.4,0.28Z", "name": "Bangladesh"}, "BE": {"path": "M429.29,144.05l1.91,0.24l2.1,-0.63l2.63,1.99l-0.21,1.66l-0.69,0.4l-0.18,1.2l-1.66,-1.13l-1.39,0.15l-2.73,-2.7l-1.17,-0.18l-0.16,-0.52l1.54,-0.5Z", "name": "Belgium"}, "BF": {"path": "M421.42,247.64l-0.11,0.95l0.34,1.16l1.4,1.71l0.07,1.1l0.32,0.37l2.55,0.51l-0.04,1.28l-0.38,0.53l-1.07,0.21l-0.72,1.18l-0.63,0.21l-3.22,-0.25l-0.94,0.39l-5.4,-0.05l-0.39,0.38l0.16,2.73l-1.23,-0.43l-1.17,0.1l-0.89,0.57l-2.27,-1.72l-0.13,-1.11l0.61,-0.96l0.02,-0.93l1.87,-1.98l0.44,-1.81l0.43,-0.39l1.28,0.26l1.05,-0.52l0.47,-0.73l1.84,-1.09l0.55,-0.83l2.2,-1.0l1.15,-0.3l0.72,0.45l1.13,-0.01Z", "name": "Burkina Faso"}, "BG": {"path": "M491.65,168.18l-0.86,0.88l-0.91,2.17l0.48,1.34l-1.6,-0.24l-2.55,0.95l-0.28,1.51l-1.8,0.22l-2.0,-1.0l-1.92,0.79l-1.42,-0.07l-0.15,-1.63l-1.05,-0.97l0.0,-0.8l1.2,-1.57l0.01,-0.56l-1.14,-1.23l-0.05,-0.94l0.88,0.97l0.88,-0.2l1.91,0.47l3.68,0.16l1.42,-0.81l2.72,-0.66l2.55,1.24Z", "name": "Bulgaria"}, "BA": {"path": "M463.49,163.65l2.1,0.5l1.72,-0.03l1.52,0.68l-0.36,0.78l0.08,0.45l1.04,1.02l-0.25,0.98l-1.81,1.15l-0.38,1.38l-1.67,-0.87l-0.89,-1.2l-2.11,-1.83l-1.63,-2.22l0.23,-0.57l0.48,0.38l0.55,-0.06l0.43,-0.51l0.94,-0.06Z", "name": "Bosnia and Herz."}, "BN": {"path": "M707.48,273.58l0.68,-0.65l1.41,-0.91l-0.15,1.63l-0.81,-0.05l-0.61,0.58l-0.53,-0.6Z", "name": "Brunei"}, "BO": {"path": "M263.83,340.69l-3.09,-0.23l-0.38,0.23l-0.7,1.52l-1.31,-1.53l-3.28,-0.64l-2.37,2.4l-1.31,0.26l-0.88,-3.26l-1.3,-2.86l0.74,-2.37l-0.13,-0.43l-1.2,-1.01l-0.37,-1.89l-1.08,-1.55l1.45,-2.56l-0.96,-2.33l0.47,-1.06l-0.34,-0.73l0.91,-1.32l0.16,-3.84l0.5,-1.18l-1.81,-3.41l2.46,0.07l0.8,-0.85l3.4,-1.91l2.66,-0.35l-0.19,1.38l0.3,1.07l-0.05,1.97l2.72,2.27l2.88,0.49l0.89,0.86l1.79,0.58l0.98,0.7l1.71,0.05l1.17,0.61l0.6,2.7l-0.7,0.54l0.96,2.99l0.37,0.28l4.3,0.1l-0.25,1.2l0.27,1.02l1.43,0.9l0.5,1.35l-0.41,1.86l-0.65,1.08l0.12,1.35l-2.69,-1.65l-2.4,-0.03l-4.36,0.76l-1.49,2.5l-0.11,1.52l-0.75,2.37Z", "name": "Bolivia"}, "JP": {"path": "M781.12,166.87l1.81,0.68l1.62,-0.97l0.39,2.42l-3.35,0.75l-2.23,2.88l-3.63,-1.9l-0.56,0.2l-1.26,3.05l-2.16,0.03l-0.29,-2.51l1.08,-2.03l2.45,-0.16l0.37,-0.33l1.25,-5.94l2.47,2.71l2.03,1.12ZM773.56,187.34l-0.91,2.22l0.37,1.52l-1.14,1.75l-3.02,1.26l-4.58,0.27l-3.34,3.01l-1.25,-0.8l-0.09,-1.9l-0.46,-0.38l-4.35,0.62l-3.0,1.32l-2.85,0.05l-0.37,0.27l0.13,0.44l2.32,1.89l-1.54,4.34l-1.26,0.9l-0.79,-0.7l0.56,-2.27l-0.21,-0.45l-1.47,-0.75l-0.74,-1.4l2.12,-0.84l1.26,-1.7l2.45,-1.42l1.83,-1.91l4.78,-0.81l2.6,0.57l0.44,-0.21l2.39,-4.66l1.29,1.06l0.5,0.01l5.1,-4.02l1.69,-3.73l-0.38,-3.4l0.9,-1.61l2.14,-0.44l1.23,3.72l-0.07,2.18l-2.23,2.84l-0.04,3.16ZM757.78,196.26l0.19,0.56l-1.01,1.21l-1.16,-0.68l-1.28,0.65l-0.69,1.45l-1.02,-0.5l0.01,-0.93l1.14,-1.38l1.57,0.14l0.85,-0.98l1.4,0.46Z", "name": "Japan"}, "BI": {"path": "M495.45,295.49l-1.08,-2.99l1.14,-0.11l0.64,-1.19l0.76,0.09l0.65,1.83l-2.1,2.36Z", "name": "Burundi"}, "BJ": {"path": "M429.57,255.75l-0.05,0.8l0.5,1.34l-0.42,0.86l0.17,0.79l-1.81,2.12l-0.57,1.76l-0.08,5.42l-1.41,0.2l-0.48,-1.36l0.11,-5.71l-0.52,-0.7l-0.2,-1.35l-1.48,-1.48l0.21,-0.9l0.89,-0.43l0.42,-0.92l1.27,-0.36l1.22,-1.34l0.61,-0.0l1.62,1.24Z", "name": "Benin"}, "BT": {"path": "M650.32,213.86l0.84,0.71l-0.12,1.1l-3.76,-0.11l-1.57,0.4l-1.93,-0.87l1.48,-1.96l1.13,-0.57l1.63,0.57l1.33,0.08l0.99,0.65Z", "name": "Bhutan"}, "JM": {"path": "M228.38,239.28l-0.8,0.4l-2.26,-1.06l0.84,-0.23l2.14,0.3l1.17,0.56l-1.08,0.03Z", "name": "Jamaica"}, "BW": {"path": "M483.92,330.07l2.27,4.01l2.83,2.86l0.96,0.31l0.78,2.43l2.13,0.61l1.02,0.76l-3.0,1.64l-2.32,2.02l-1.54,2.69l-1.52,0.45l-0.64,1.94l-1.34,0.52l-1.85,-0.12l-1.21,-0.74l-1.35,-0.3l-1.22,0.62l-0.75,1.37l-2.31,1.9l-1.4,0.21l-0.35,-0.59l0.16,-1.75l-1.48,-2.54l-0.62,-0.43l-0.0,-7.1l2.08,-0.08l0.39,-0.4l0.07,-8.9l5.19,-0.93l0.8,0.89l0.51,0.07l1.5,-0.95l2.21,-0.49Z", "name": "Botswana"}, "BR": {"path": "M259.98,275.05l3.24,0.7l0.65,-0.53l4.55,-1.32l1.08,-1.06l-0.02,-0.63l0.55,-0.05l0.28,0.28l-0.26,0.87l0.22,0.48l0.73,0.32l0.4,0.81l-0.62,0.86l-0.4,2.13l0.82,2.56l1.69,1.43l1.43,0.2l3.17,-1.68l3.18,0.3l0.65,-0.75l-0.27,-0.92l1.9,-0.09l2.39,0.99l1.06,-0.61l0.84,0.78l1.2,-0.18l1.18,-1.06l0.84,-1.94l1.36,-2.11l0.37,-0.05l1.89,5.45l1.33,0.59l0.05,1.28l-1.77,1.94l0.02,0.56l1.02,0.87l4.07,0.36l0.08,2.16l0.66,0.29l1.74,-1.5l6.97,2.32l1.02,1.22l-0.35,1.18l0.49,0.5l2.81,-0.74l4.77,1.3l3.75,-0.08l3.57,2.0l3.29,2.86l1.93,0.72l2.12,0.12l0.71,0.62l1.21,4.51l-0.95,3.98l-4.72,5.06l-1.64,2.92l-1.72,2.05l-0.8,0.3l-0.72,2.03l0.18,4.75l-0.94,5.53l-0.81,1.13l-0.43,3.36l-2.55,3.5l-0.4,2.51l-1.86,1.04l-0.67,1.53l-2.54,0.01l-3.94,1.01l-1.83,1.2l-2.87,0.82l-3.03,2.19l-2.2,2.83l-0.36,2.0l0.4,1.58l-0.44,2.6l-0.51,1.2l-1.77,1.54l-2.75,4.78l-3.83,3.42l-1.24,2.74l-1.18,1.15l-0.36,-0.83l0.95,-1.14l0.01,-0.5l-1.52,-1.97l-4.56,-3.32l-1.03,-0.0l-2.38,-2.02l-0.81,-0.0l5.34,-5.45l3.77,-2.58l0.22,-2.46l-1.35,-1.81l-0.91,0.07l0.58,-2.33l0.01,-1.54l-1.11,-0.83l-1.75,0.3l-0.44,-3.11l-0.52,-0.95l-1.88,-0.88l-1.24,0.47l-2.17,-0.41l0.15,-3.21l-0.62,-1.34l0.66,-0.73l-0.22,-1.34l0.66,-1.13l0.44,-2.04l-0.61,-1.83l-1.4,-0.86l-0.2,-0.75l0.34,-1.39l-0.38,-0.5l-4.52,-0.1l-0.72,-2.22l0.59,-0.42l-0.03,-1.1l-0.5,-0.87l-0.32,-1.7l-1.45,-0.76l-1.63,-0.02l-1.05,-0.72l-1.6,-0.48l-1.13,-0.99l-2.69,-0.4l-2.47,-2.06l0.13,-4.35l-0.45,-0.45l-3.46,0.5l-3.44,1.94l-0.6,0.74l-2.9,-0.17l-1.47,0.42l-0.72,-0.18l0.15,-3.52l-0.63,-0.34l-1.94,1.41l-1.87,-0.06l-0.83,-1.18l-1.37,-0.26l0.21,-1.01l-1.35,-1.49l-0.88,-1.91l0.56,-0.6l-0.0,-0.81l1.29,-0.62l0.22,-0.43l-0.22,-1.19l0.61,-0.91l0.15,-0.99l2.65,-1.58l1.99,-0.47l0.42,-0.36l2.06,0.11l0.42,-0.33l1.19,-8.0l-0.41,-1.56l-1.1,-1.0l0.01,-1.33l1.91,-0.42l0.08,-0.96l-0.33,-0.43l-1.14,-0.2l-0.02,-0.83l4.47,0.05l0.82,-0.67l0.82,1.81l0.8,0.07l1.15,1.1l2.26,-0.05l0.71,-0.83l2.78,-0.96l0.48,-1.13l1.6,-0.64l0.24,-0.47l-0.48,-0.82l-1.83,-0.19l-0.36,-3.22Z", "name": "Brazil"}, "BS": {"path": "M226.4,223.87l-0.48,-1.15l-0.84,-0.75l0.36,-1.11l0.95,1.95l0.01,1.06ZM225.56,216.43l-1.87,0.29l-0.04,-0.22l0.74,-0.14l1.17,0.06Z", "name": "Bahamas"}, "BY": {"path": "M493.84,128.32l0.29,0.7l0.49,0.23l1.19,-0.38l2.09,0.72l0.19,1.26l-0.45,1.24l1.57,2.26l0.89,0.59l0.17,0.81l1.58,0.56l0.4,0.5l-0.53,0.41l-1.87,-0.11l-0.73,0.38l-0.13,0.52l1.04,2.74l-1.91,0.26l-0.89,0.99l-0.11,1.18l-2.73,-0.04l-0.53,-0.62l-0.52,-0.08l-0.75,0.46l-0.91,-0.42l-1.92,-0.07l-2.75,-0.79l-2.6,-0.28l-2.0,0.07l-1.5,0.92l-0.67,0.07l-0.08,-1.22l-0.59,-1.19l1.36,-0.88l0.01,-1.35l-0.7,-1.41l-0.07,-1.0l2.16,-0.02l2.72,-1.3l0.75,-2.04l1.91,-1.04l0.2,-0.41l-0.19,-1.25l3.8,-1.78l2.3,0.77Z", "name": "Belarus"}, "BZ": {"path": "M198.03,244.38l0.1,-4.49l0.69,-0.06l0.74,-1.3l0.34,0.28l-0.4,1.3l0.17,0.58l-0.34,2.25l-1.3,1.42Z", "name": "Belize"}, "RU": {"path": "M491.55,115.25l2.55,-1.85l-0.01,-0.65l-2.2,-1.5l7.32,-6.76l1.03,-2.11l-0.13,-0.49l-3.46,-2.52l0.86,-2.7l-2.11,-2.81l1.56,-3.67l-2.77,-4.52l2.15,-2.99l-0.08,-0.55l-3.65,-2.73l0.3,-2.54l1.81,-0.37l4.26,-1.77l2.42,-1.45l4.06,2.61l6.79,1.04l9.34,4.85l1.78,1.88l0.14,2.46l-2.55,2.02l-3.9,1.06l-11.07,-3.14l-2.06,0.53l-0.13,0.7l3.94,2.94l0.31,5.86l0.26,0.36l5.14,2.24l0.58,-0.29l0.32,-1.94l-1.35,-1.78l1.13,-1.09l6.13,2.42l2.11,-0.98l0.18,-0.56l-1.51,-2.67l5.41,-3.76l2.07,0.22l2.26,1.41l0.57,-0.16l1.46,-2.87l-0.05,-0.44l-1.92,-2.32l1.12,-2.32l-1.32,-2.27l5.87,1.16l1.04,1.75l-2.59,0.43l-0.33,0.4l0.02,2.36l2.46,1.83l3.87,-0.91l0.86,-2.8l13.69,-5.65l0.99,0.11l-1.92,2.06l0.23,0.67l3.11,0.45l2.0,-1.48l4.56,-0.12l3.64,-1.73l2.65,2.44l0.56,-0.01l2.85,-2.88l-0.01,-0.57l-2.35,-2.29l0.9,-1.01l7.14,1.3l3.41,1.36l9.05,4.97l0.51,-0.11l1.67,-2.27l-0.05,-0.53l-2.43,-2.21l-0.06,-0.78l-0.34,-0.36l-2.52,-0.36l0.64,-1.93l-1.32,-3.46l-0.06,-1.21l4.48,-4.06l1.69,-4.29l1.6,-0.81l6.23,1.18l0.44,2.21l-2.29,3.64l0.06,0.5l1.47,1.39l0.76,3.0l-0.56,6.03l2.69,2.82l-0.96,2.57l-4.86,5.95l0.23,0.64l2.86,0.61l0.42,-0.17l0.93,-1.4l2.64,-1.03l0.87,-2.24l2.09,-1.96l0.07,-0.5l-1.36,-2.28l1.09,-2.69l-0.32,-0.55l-2.47,-0.33l-0.5,-2.06l1.94,-4.38l-0.06,-0.42l-2.96,-3.4l4.12,-2.88l0.16,-0.4l-0.51,-2.93l0.54,-0.05l1.13,2.25l-0.96,4.35l0.27,0.47l2.68,0.84l0.5,-0.51l-1.02,-2.99l3.79,-1.66l5.01,-0.24l4.53,2.61l0.48,-0.06l0.07,-0.48l-2.18,-3.82l-0.23,-4.67l3.98,-0.9l5.97,0.21l5.49,-0.64l0.27,-0.65l-1.83,-2.31l2.56,-2.9l2.87,-0.17l4.8,-2.47l6.54,-0.67l1.03,-1.42l6.25,-0.45l2.32,1.11l5.53,-2.7l4.5,0.08l0.39,-0.28l0.66,-2.15l2.26,-2.12l5.69,-2.11l3.21,1.29l-2.46,0.94l-0.25,0.42l0.34,0.35l5.41,0.77l0.61,2.33l0.58,0.25l2.2,-1.22l7.13,0.07l5.51,2.47l1.79,1.72l-0.53,2.24l-9.16,4.15l-1.97,1.52l0.16,0.71l6.77,1.91l2.16,-0.78l1.13,2.74l0.67,0.11l1.01,-1.15l3.81,-0.73l7.7,0.77l0.54,1.99l0.36,0.29l10.47,0.71l0.43,-0.38l0.13,-3.23l4.87,0.78l3.95,-0.02l3.83,2.4l1.03,2.71l-1.35,1.79l0.02,0.5l3.15,3.64l4.07,1.96l0.53,-0.18l2.23,-4.47l3.95,1.93l4.16,-1.21l4.73,1.39l2.05,-1.26l3.94,0.62l0.43,-0.55l-1.68,-4.02l2.89,-1.8l22.31,3.03l2.16,2.75l6.55,3.51l10.29,-0.81l4.82,0.73l1.85,1.66l-0.29,3.08l0.25,0.41l3.08,1.26l3.56,-0.88l4.35,-0.11l4.8,0.87l4.57,-0.47l4.23,3.79l0.43,0.07l3.1,-1.4l0.16,-0.6l-1.88,-2.62l0.85,-1.52l7.71,1.21l5.22,-0.26l7.09,2.09l9.59,5.22l6.35,4.11l-0.2,2.38l1.88,1.41l0.6,-0.42l-0.48,-2.53l6.15,0.57l4.4,3.51l-1.97,1.43l-4.0,0.41l-0.36,0.39l-0.06,3.79l-0.74,0.62l-2.07,-0.11l-1.91,-1.39l-3.14,-1.11l-0.78,-1.85l-2.72,-0.68l-2.63,0.49l-1.04,-1.1l0.46,-1.31l-0.5,-0.51l-3.0,0.98l-0.22,0.58l0.99,1.7l-1.21,1.48l-3.04,1.68l-3.12,-0.28l-0.4,0.23l0.09,0.46l2.2,2.09l1.46,3.2l1.15,1.1l0.24,1.33l-0.42,0.67l-4.63,-0.77l-6.96,2.9l-2.19,0.44l-7.6,5.06l-0.84,1.45l-3.61,-2.37l-6.24,2.82l-0.94,-1.15l-0.53,-0.08l-2.28,1.52l-3.2,-0.49l-0.44,0.27l-0.78,2.37l-3.05,3.78l0.09,1.47l0.29,0.36l2.54,0.72l-0.29,4.53l-1.97,0.11l-0.35,0.26l-1.07,2.94l0.8,1.45l-3.91,1.58l-1.05,3.95l-3.48,0.77l-0.3,0.3l-0.72,3.29l-3.09,2.65l-0.7,-1.74l-2.44,-12.44l1.16,-4.71l2.04,-2.06l0.22,-1.64l3.8,-0.86l4.46,-4.61l4.28,-3.81l4.48,-3.01l2.17,-5.63l-0.42,-0.54l-3.04,0.33l-1.77,3.31l-5.86,3.86l-1.86,-4.25l-0.45,-0.23l-6.46,1.3l-6.47,6.44l-0.01,0.55l1.58,1.74l-8.24,1.17l0.15,-2.2l-0.34,-0.42l-3.89,-0.56l-3.25,1.81l-7.62,-0.62l-8.45,1.19l-17.71,15.41l0.22,0.7l3.74,0.41l1.36,2.17l2.43,0.76l1.88,-1.68l2.4,0.2l3.4,3.54l0.08,2.6l-1.95,3.42l-0.21,3.9l-1.1,5.06l-3.71,4.54l-0.87,2.21l-8.29,8.89l-3.19,1.7l-1.32,0.03l-1.45,-1.36l-0.49,-0.04l-2.27,1.5l0.41,-3.65l-0.59,-2.47l1.75,-0.89l2.91,0.53l0.42,-0.2l1.68,-3.03l0.87,-3.46l0.97,-1.18l1.32,-2.88l-0.45,-0.56l-4.14,0.95l-2.19,1.25l-3.41,-0.0l-1.06,-2.93l-2.97,-2.3l-4.28,-1.06l-1.75,-5.07l-2.66,-5.01l-2.29,-1.29l-3.75,-1.01l-3.44,0.08l-3.18,0.62l-2.24,1.77l0.05,0.66l1.18,0.69l0.02,1.43l-1.33,1.05l-2.26,3.51l-0.04,1.43l-3.16,1.84l-2.82,-1.16l-3.01,0.23l-1.35,-1.07l-1.5,-0.35l-3.9,2.31l-3.22,0.52l-2.27,0.79l-3.05,-0.51l-2.21,0.03l-1.48,-1.6l-2.6,-1.63l-2.63,-0.43l-5.46,1.01l-3.23,-1.25l-0.72,-2.57l-5.2,-1.24l-2.75,-1.36l-0.5,0.12l-2.59,3.45l0.84,2.1l-2.06,1.93l-3.41,-0.77l-2.42,-0.12l-1.83,-1.54l-2.53,-0.05l-2.42,-0.98l-3.86,1.57l-4.72,2.78l-3.3,0.75l-1.55,-1.92l-3.0,0.41l-1.11,-1.33l-1.62,-0.59l-1.31,-1.94l-1.38,-0.6l-3.7,0.79l-3.31,-1.83l-0.51,0.11l-0.99,1.29l-5.29,-8.05l-2.96,-2.48l0.65,-0.77l0.01,-0.51l-0.5,-0.11l-6.2,3.21l-1.84,0.15l0.15,-1.39l-0.26,-0.42l-3.22,-1.17l-2.46,0.7l-0.69,-3.16l-0.32,-0.31l-4.5,-0.75l-2.47,1.47l-6.19,1.27l-1.29,0.86l-9.51,1.3l-1.15,1.17l-0.03,0.53l1.47,1.9l-1.89,0.69l-0.22,0.56l0.31,0.6l-2.11,1.44l0.03,0.68l3.75,2.12l-0.39,0.98l-3.23,-0.13l-0.86,0.86l-3.09,-1.59l-3.97,0.07l-2.66,1.35l-8.32,-3.56l-4.07,0.06l-5.39,3.68l-0.39,2.0l-2.03,-1.5l-0.59,0.13l-2.0,3.59l0.57,0.93l-1.28,2.16l0.06,0.48l2.13,2.17l1.95,0.04l1.37,1.82l-0.23,1.46l0.25,0.43l0.83,0.33l-0.8,1.31l-2.49,0.62l-2.49,3.2l0.0,0.49l2.17,2.78l-0.15,2.18l2.5,3.24l-1.58,1.59l-0.7,-0.13l-1.63,-1.72l-2.29,-0.84l-0.94,-1.31l-2.34,-0.63l-1.48,0.4l-0.43,-0.47l-3.51,-1.48l-5.76,-1.01l-0.45,0.19l-2.89,-2.34l-2.9,-1.2l-1.53,-1.29l1.29,-0.43l2.08,-2.61l-0.05,-0.55l-0.89,-0.79l3.05,-1.06l0.27,-0.42l-0.07,-0.69l-0.49,-0.35l-1.73,0.39l0.04,-0.68l1.04,-0.72l2.66,-0.48l0.4,-1.32l-0.5,-1.6l0.92,-1.54l0.03,-1.17l-0.29,-0.37l-3.69,-1.06l-1.41,0.02l-1.42,-1.41l-2.19,0.38l-2.77,-1.01l-0.03,-0.59l-0.89,-1.43l-2.0,-0.32l-0.11,-0.54l0.49,-0.53l0.01,-0.53l-1.6,-1.9l-3.58,0.02l-0.88,0.73l-0.46,-0.07l-1.0,-2.79l2.22,-0.02l0.97,-0.74l0.07,-0.57l-0.9,-1.04l-1.35,-0.48l-0.11,-0.7l-0.95,-0.58l-1.38,-1.99l0.46,-0.98l-0.51,-1.96l-2.45,-0.84l-1.21,0.3l-0.46,-0.76l-2.46,-0.83l-0.72,-1.87l-0.21,-1.69l-0.99,-0.85l0.85,-1.17l-0.7,-3.21l1.66,-1.97l-0.16,-0.79ZM749.2,170.72l-0.6,0.4l-0.13,0.16l-0.01,-0.51l0.74,-0.05ZM871.88,65.81l2.17,-0.13l3.19,1.16l-2.39,1.09l-5.63,0.48l-0.26,-0.84l2.92,-1.76ZM797.39,48.49l-2.0,1.36l-3.8,-0.42l-4.25,-1.8l0.35,-0.97l9.69,1.83ZM783.67,46.12l-1.63,3.09l-8.98,-0.13l-4.09,1.14l-4.54,-2.97l1.16,-3.01l3.05,-0.89l6.5,0.22l8.54,2.56ZM778.2,134.98l-0.56,-0.9l0.27,-0.12l0.29,1.01ZM778.34,135.48l0.94,3.53l-0.05,3.38l1.05,3.39l2.18,5.0l-2.89,-0.83l-0.49,0.26l-1.54,4.65l2.42,3.5l-0.04,1.13l-1.24,-1.24l-0.61,0.06l-1.09,1.61l-0.28,-1.61l0.27,-3.1l-0.28,-3.4l0.58,-2.47l0.11,-4.39l-1.46,-3.36l0.21,-4.32l2.15,-1.46l0.07,-0.34ZM771.95,56.61l1.76,-1.42l2.89,-0.42l3.28,1.71l0.14,0.6l-3.27,0.03l-4.81,-0.5ZM683.76,31.09l-13.01,1.93l4.03,-6.35l1.82,-0.56l1.73,0.34l5.99,2.98l-0.56,1.66ZM670.85,27.93l-5.08,0.64l-6.86,-1.57l-3.99,-2.05l-2.1,-4.16l-2.6,-0.87l5.72,-3.5l5.2,-1.28l4.69,2.85l5.59,5.4l-0.56,4.53ZM564.15,68.94l-0.64,0.17l-7.85,-0.57l-0.86,-2.04l-4.28,-1.17l-0.28,-1.94l2.27,-0.89l0.25,-0.39l-0.08,-2.38l4.81,-3.97l-0.15,-0.7l-1.47,-0.38l5.3,-3.81l0.15,-0.44l-0.58,-1.94l5.28,-2.51l8.21,-3.27l8.28,-0.96l4.35,-1.94l4.6,-0.64l1.36,1.61l-1.34,1.28l-16.43,4.94l-7.97,4.88l-7.74,9.63l0.66,4.14l4.16,3.27ZM548.81,18.48l-5.5,1.18l-0.58,1.02l-2.59,0.84l-2.13,-1.07l1.12,-1.42l-0.3,-0.65l-2.33,-0.07l1.68,-0.36l3.47,-0.06l0.42,1.29l0.66,0.16l1.38,-1.34l2.15,-0.88l2.94,1.01l-0.39,0.36ZM477.37,133.15l-4.08,0.05l-2.56,-0.32l0.33,-0.87l3.17,-1.03l3.24,0.96l-0.09,1.23Z", "name": "Russia"}, "RW": {"path": "M497.0,288.25l0.71,1.01l-0.11,1.09l-1.63,0.03l-1.04,1.39l-0.83,-0.11l0.51,-1.2l0.08,-1.34l0.42,-0.41l0.7,0.14l1.19,-0.61Z", "name": "Rwanda"}, "RS": {"path": "M469.4,163.99l0.42,-0.5l-0.01,-0.52l-1.15,-1.63l1.43,-0.62l1.33,0.12l1.17,1.06l0.46,1.13l1.34,0.64l0.35,1.35l1.46,0.9l0.76,-0.29l0.2,0.69l-0.48,0.78l0.22,1.12l1.05,1.22l-0.77,0.8l-0.37,1.52l-1.21,0.08l0.24,-0.64l-0.39,-0.54l-2.08,-1.64l-0.9,0.05l-0.48,0.94l-2.12,-1.37l0.53,-1.6l-1.11,-1.37l0.51,-1.1l-0.41,-0.57Z", "name": "Serbia"}, "TL": {"path": "M734.55,307.93l-0.1,-0.97l4.5,-0.86l-2.82,1.28l-1.59,0.55Z", "name": "Timor-Leste"}, "TM": {"path": "M553.03,173.76l-0.04,0.34l-0.09,-0.22l0.13,-0.12ZM555.87,172.66l0.45,-0.1l1.48,0.74l2.06,2.43l4.07,-0.18l0.38,-0.51l-0.32,-1.19l1.92,-0.94l1.91,-1.59l2.94,1.39l0.43,2.47l1.19,0.67l2.58,-0.13l0.62,0.4l1.32,3.12l4.54,3.44l2.67,1.45l3.06,1.14l-0.04,1.05l-1.33,-0.75l-0.59,0.19l-0.32,0.84l-2.2,0.81l-0.46,2.13l-1.21,0.74l-1.91,0.42l-0.73,1.33l-1.56,0.31l-2.22,-0.94l-0.2,-2.17l-0.38,-0.36l-1.73,-0.09l-2.76,-2.46l-2.14,-0.4l-2.84,-1.48l-1.78,-0.27l-1.24,0.53l-1.57,-0.08l-2.0,1.69l-1.7,0.43l-0.36,-1.58l0.36,-2.98l-0.22,-0.4l-1.65,-0.84l0.54,-1.69l-0.34,-0.52l-1.22,-0.13l0.36,-1.64l2.22,0.59l2.2,-0.95l0.12,-0.65l-1.77,-1.74l-0.66,-1.57Z", "name": "Turkmenistan"}, "TJ": {"path": "M597.75,178.82l-2.54,-0.44l-0.47,0.34l-0.24,1.7l0.43,0.45l2.64,-0.22l3.18,0.95l4.39,-0.41l0.56,2.37l0.52,0.29l0.67,-0.24l1.11,0.49l0.21,2.13l-3.76,-0.21l-1.8,1.32l-1.76,0.74l-0.61,-0.58l0.21,-2.23l-0.64,-0.49l-0.07,-0.93l-1.36,-0.66l-0.45,0.07l-1.08,1.01l-0.55,1.48l-1.31,-0.05l-0.95,1.16l-0.9,-0.35l-1.86,0.74l1.26,-2.83l-0.54,-2.17l-1.67,-0.82l0.33,-0.66l2.18,-0.04l1.19,-1.63l0.76,-1.79l2.43,-0.5l-0.26,1.0l0.73,1.05Z", "name": "Tajikistan"}, "RO": {"path": "M487.53,154.23l0.6,0.24l2.87,3.98l-0.17,2.69l0.45,1.42l1.32,0.81l1.35,-0.42l0.76,0.36l0.02,0.31l-0.83,0.45l-0.59,-0.22l-0.54,0.3l-0.62,3.3l-1.0,-0.22l-2.07,-1.13l-2.95,0.71l-1.25,0.76l-3.51,-0.15l-1.89,-0.47l-0.87,0.16l-0.82,-1.3l0.29,-0.26l-0.06,-0.64l-1.09,-0.34l-0.56,0.5l-1.05,-0.64l-0.39,-1.39l-1.36,-0.65l-0.35,-1.0l-0.83,-0.75l1.54,-0.54l2.66,-4.21l2.4,-1.24l2.96,0.34l1.48,0.73l0.79,-0.45l1.78,-0.3l0.75,-0.74l0.79,0.0Z", "name": "Romania"}, "GW": {"path": "M386.23,253.6l-0.29,0.84l0.15,0.6l-2.21,0.59l-0.86,0.96l-1.04,-0.83l-1.09,-0.23l-0.54,-1.06l-0.66,-0.49l2.41,-0.48l4.13,0.1Z", "name": "Guinea-Bissau"}, "GT": {"path": "M195.08,249.77l-2.48,-0.37l-1.03,-0.45l-1.14,-0.89l0.3,-0.99l-0.24,-0.68l0.96,-1.66l2.98,-0.01l0.4,-0.37l-0.19,-1.28l-1.67,-1.4l0.51,-0.4l0.0,-1.05l3.85,0.02l-0.21,4.53l0.4,0.43l1.46,0.38l-1.48,0.98l-0.35,0.7l0.12,0.57l-2.2,1.96Z", "name": "Guatemala"}, "GR": {"path": "M487.07,174.59l-0.59,1.43l-0.37,0.21l-2.84,-0.35l-3.03,0.77l-0.18,0.68l1.28,1.23l-0.61,0.23l-1.14,0.0l-1.2,-1.39l-0.63,0.03l-0.53,1.01l0.56,1.76l1.03,1.19l-0.56,0.38l-0.05,0.62l2.52,2.12l0.02,0.87l-1.78,-0.59l-0.48,0.56l0.5,1.0l-1.07,0.2l-0.3,0.53l0.75,2.01l-0.98,0.02l-1.84,-1.12l-1.37,-4.2l-2.21,-2.95l-0.11,-0.56l1.04,-1.28l0.2,-0.95l0.85,-0.66l0.03,-0.46l1.32,-0.21l1.01,-0.64l1.22,0.05l0.65,-0.56l2.26,-0.0l1.82,-0.75l1.85,1.0l2.28,-0.28l0.35,-0.39l0.01,-0.77l0.34,0.22ZM480.49,192.16l0.58,0.4l-0.68,-0.12l0.11,-0.28ZM482.52,192.82l2.51,0.06l0.24,0.32l-1.99,0.13l-0.77,-0.51Z", "name": "Greece"}, "GQ": {"path": "M448.79,279.62l0.02,2.22l-4.09,0.0l0.69,-2.27l3.38,0.05Z", "name": "Eq. Guinea"}, "GY": {"path": "M277.42,270.07l-0.32,1.83l-1.32,0.57l-0.23,0.46l-0.28,2.0l1.11,1.82l0.83,0.19l0.32,1.25l1.13,1.62l-1.21,-0.19l-1.08,0.71l-1.77,0.5l-0.44,0.46l-0.86,-0.09l-1.32,-1.01l-0.77,-2.27l0.36,-1.9l0.68,-1.23l-0.57,-1.17l-0.74,-0.43l0.12,-1.16l-0.9,-0.69l-1.1,0.09l-1.31,-1.48l0.53,-0.72l-0.04,-0.84l1.99,-0.86l0.05,-0.59l-0.71,-0.78l0.14,-0.57l1.66,-1.24l1.36,0.77l1.41,1.49l0.06,1.15l0.37,0.38l0.8,0.05l2.06,1.86Z", "name": "Guyana"}, "GE": {"path": "M521.71,168.93l5.29,0.89l4.07,2.01l1.41,-0.44l2.07,0.56l0.68,1.1l1.07,0.55l-0.12,0.59l0.98,1.29l-1.01,-0.13l-1.81,-0.83l-0.94,0.47l-3.23,0.43l-2.29,-1.39l-2.33,0.05l0.21,-0.97l-0.76,-2.26l-1.45,-1.12l-1.43,-0.39l-0.41,-0.42Z", "name": "Georgia"}, "GB": {"path": "M412.61,118.72l-2.19,3.22l-0.0,0.45l5.13,-0.3l-0.53,2.37l-2.2,3.12l0.29,0.63l2.37,0.21l2.33,4.3l1.76,0.69l2.2,5.12l2.94,0.77l-0.23,1.62l-1.15,0.88l-0.1,0.52l0.82,1.42l-1.86,1.43l-3.3,-0.02l-4.12,0.87l-1.04,-0.58l-0.47,0.06l-1.51,1.41l-2.12,-0.34l-1.86,1.18l-0.6,-0.29l3.19,-3.0l2.16,-0.69l0.28,-0.41l-0.34,-0.36l-3.73,-0.53l-0.4,-0.76l2.2,-0.87l0.17,-0.61l-1.26,-1.67l0.36,-1.7l3.38,0.28l0.43,-0.33l0.37,-1.99l-1.79,-2.49l-3.11,-0.72l-0.38,-0.59l0.79,-1.35l-0.04,-0.46l-0.82,-0.97l-0.61,0.01l-0.68,0.84l-0.1,-2.34l-1.23,-1.88l0.85,-3.47l1.77,-2.68l1.85,0.26l2.17,-0.22ZM406.26,132.86l-1.01,1.77l-1.57,-0.59l-1.16,0.01l0.37,-1.54l-0.39,-1.39l1.45,-0.1l2.3,1.84Z", "name": "United Kingdom"}, "GA": {"path": "M453.24,279.52l-0.08,0.98l0.7,1.29l2.36,0.24l-0.98,2.63l1.18,1.79l0.25,1.78l-0.29,1.52l-0.6,0.93l-1.84,-0.09l-1.23,-1.11l-0.66,0.23l-0.15,0.84l-1.42,0.26l-1.02,0.7l-0.11,0.52l0.77,1.35l-1.34,0.97l-3.94,-4.3l-1.44,-2.45l0.06,-0.6l0.54,-0.81l1.05,-3.46l4.17,-0.07l0.4,-0.4l-0.02,-2.66l2.39,0.21l1.25,-0.27Z", "name": "Gabon"}, "GN": {"path": "M391.8,254.11l0.47,0.8l1.11,-0.32l0.98,0.7l1.07,0.2l2.26,-1.22l0.64,0.44l1.13,1.56l-0.48,1.4l0.8,0.3l-0.08,0.48l0.46,0.68l-0.35,1.36l1.05,2.61l-1.0,0.69l0.03,1.41l-0.72,-0.06l-1.08,1.0l-0.24,-0.27l0.07,-1.11l-1.05,-1.54l-1.79,0.21l-0.35,-2.01l-1.6,-2.18l-2.0,-0.0l-1.31,0.54l-1.95,2.18l-1.86,-2.19l-1.2,-0.78l-0.3,-1.11l-0.8,-0.85l0.65,-0.72l0.81,-0.03l1.64,-0.8l0.23,-1.87l2.67,0.64l0.89,-0.3l1.21,0.15Z", "name": "Guinea"}, "GM": {"path": "M379.31,251.39l0.1,-0.35l2.43,-0.07l0.74,-0.61l0.51,-0.03l0.77,0.49l-1.03,-0.3l-1.87,0.9l-1.65,-0.04ZM384.03,250.91l0.91,0.05l0.75,-0.24l-0.59,0.31l-1.08,-0.13Z", "name": "Gambia"}, "GL": {"path": "M353.02,1.2l14.69,4.67l-3.68,1.89l-22.97,0.86l-0.36,0.27l0.12,0.43l1.55,1.18l8.79,-0.66l7.48,2.07l4.86,-1.77l1.66,1.73l-2.53,3.19l-0.01,0.48l0.46,0.15l6.35,-2.2l12.06,-2.31l7.24,1.13l1.09,1.99l-9.79,4.01l-1.44,1.32l-7.87,0.98l-0.35,0.41l0.38,0.38l5.07,0.24l-2.53,3.58l-2.07,3.81l0.08,6.05l2.57,3.11l-3.22,0.2l-4.12,1.66l-0.05,0.72l4.45,2.65l0.51,3.75l-2.3,0.4l-0.25,0.64l2.79,3.69l-4.82,0.31l-0.36,0.29l0.16,0.44l2.62,1.8l-0.59,1.22l-3.3,0.7l-3.45,0.01l-0.29,0.68l3.03,3.12l0.02,1.34l-4.4,-1.73l-1.72,1.35l0.15,0.66l3.31,1.15l3.13,2.71l0.81,3.16l-3.85,0.75l-4.89,-4.26l-0.47,-0.03l-0.17,0.44l0.79,2.86l-2.71,2.21l-0.13,0.44l0.37,0.27l8.73,0.34l-12.32,6.64l-7.24,1.48l-2.94,0.08l-2.69,1.75l-3.43,4.41l-5.24,2.84l-1.73,0.18l-7.12,2.1l-2.15,2.52l-0.13,2.99l-1.19,2.45l-4.01,3.09l-0.14,0.44l0.97,2.9l-2.28,6.48l-3.1,0.2l-3.83,-3.07l-4.86,-0.02l-2.25,-1.93l-1.7,-3.79l-4.3,-4.84l-1.21,-2.49l-0.44,-3.8l-3.32,-3.63l0.84,-2.86l-1.56,-1.7l2.28,-4.6l3.83,-1.74l1.03,-1.96l0.52,-3.47l-0.59,-0.41l-4.17,2.21l-2.07,0.58l-2.72,-1.28l-0.15,-2.71l0.85,-2.09l2.01,-0.06l5.06,1.2l0.46,-0.23l-0.14,-0.49l-6.54,-4.47l-2.67,0.55l-1.58,-0.86l2.56,-4.01l-0.03,-0.48l-1.5,-1.74l-4.98,-8.5l-3.13,-1.96l0.03,-1.88l-0.24,-0.37l-6.85,-3.02l-5.36,-0.38l-12.7,0.58l-2.78,-1.57l-3.66,-2.77l5.73,-1.45l5.0,-0.28l0.38,-0.38l-0.35,-0.41l-10.67,-1.38l-5.3,-2.06l0.25,-1.54l18.41,-5.26l1.22,-2.27l-0.25,-0.55l-6.14,-1.86l1.68,-1.77l8.55,-4.03l3.59,-0.63l0.3,-0.54l-0.88,-2.27l5.47,-1.47l7.65,-0.95l7.55,-0.05l3.04,1.85l6.48,-3.27l5.81,2.22l3.56,0.5l5.16,1.94l0.5,-0.21l-0.17,-0.52l-5.71,-3.13l0.28,-2.13l8.12,-3.6l8.7,0.28l3.35,-2.34l8.71,-0.6l19.93,0.8Z", "name": "Greenland"}, "GH": {"path": "M420.53,257.51l-0.01,0.72l0.96,1.2l0.24,3.73l0.59,0.95l-0.51,2.1l0.19,1.41l1.02,2.21l-6.97,2.84l-1.8,-0.57l0.04,-0.89l-1.02,-2.04l0.61,-2.65l1.07,-2.32l-0.96,-6.47l5.01,0.07l0.94,-0.39l0.61,0.11Z", "name": "Ghana"}, "OM": {"path": "M568.09,230.93l-0.91,1.67l-1.22,0.04l-0.6,0.76l-0.41,1.51l0.27,1.58l-1.16,0.05l-1.56,0.97l-0.76,1.74l-1.62,0.05l-0.98,0.65l-0.17,1.15l-0.89,0.52l-1.49,-0.18l-2.4,0.94l-2.47,-5.4l7.35,-2.71l1.67,-5.23l-1.12,-2.09l0.05,-0.83l0.67,-1.0l0.07,-1.05l0.9,-0.42l-0.05,-2.07l0.7,-0.01l1.0,1.62l1.51,1.08l3.3,0.84l1.73,2.29l0.81,0.37l-1.23,2.35l-0.99,0.79Z", "name": "Oman"}, "TN": {"path": "M448.1,188.24l-1.0,1.27l-0.02,1.32l0.84,0.88l-0.28,2.09l-1.53,1.32l-0.12,0.42l0.48,1.54l1.42,0.32l0.53,1.11l0.9,0.52l-0.11,1.67l-3.54,2.64l-0.1,2.38l-0.58,0.3l-0.96,-4.45l-1.54,-1.25l-0.16,-0.78l-1.92,-1.56l-0.18,-1.76l1.51,-1.62l0.59,-2.34l-0.38,-2.78l0.42,-1.21l2.45,-1.05l1.29,0.26l-0.06,1.11l0.58,0.38l1.47,-0.73Z", "name": "Tunisia"}, "JO": {"path": "M518.64,201.38l-5.14,1.56l-0.19,0.65l2.16,2.39l-0.89,1.14l-1.71,0.34l-1.71,1.8l-2.34,-0.37l1.21,-4.32l0.56,-4.07l2.8,0.94l4.46,-2.71l0.79,2.66Z", "name": "Jordan"}, "HR": {"path": "M455.59,162.84l1.09,0.07l-0.82,0.94l-0.27,-1.01ZM456.96,162.92l0.62,-0.41l1.73,0.45l0.42,-0.4l-0.01,-0.59l0.86,-0.52l0.2,-1.05l1.63,-0.68l2.57,1.68l2.07,0.6l0.87,-0.31l1.05,1.57l-0.52,0.63l-1.05,-0.56l-1.68,0.04l-2.1,-0.5l-1.29,0.06l-0.57,0.49l-0.59,-0.47l-0.62,0.16l-0.46,1.7l1.79,2.42l2.79,2.75l-1.18,-0.87l-2.21,-0.87l-1.67,-1.78l0.13,-0.63l-1.05,-1.19l-0.32,-1.27l-1.42,-0.43Z", "name": "Croatia"}, "HT": {"path": "M237.05,238.38l-1.16,0.43l-0.91,-0.55l0.05,-0.2l2.02,0.31ZM237.53,238.43l1.06,0.12l-0.05,0.01l-1.01,-0.12ZM239.25,238.45l0.79,-0.51l0.06,-0.62l-1.02,-1.0l0.02,-0.82l-0.3,-0.4l-0.93,-0.32l3.16,0.45l0.02,1.84l-0.48,0.34l-0.08,0.58l0.54,0.72l-1.78,-0.26Z", "name": "Haiti"}, "HU": {"path": "M462.08,157.89l0.65,-1.59l-0.09,-0.44l0.64,-0.0l0.39,-0.34l0.1,-0.69l1.75,0.87l2.32,-0.37l0.43,-0.66l3.49,-0.78l0.69,-0.78l0.57,-0.14l2.57,0.93l0.67,-0.23l1.03,0.65l0.08,0.37l-1.42,0.71l-2.59,4.14l-1.8,0.53l-1.68,-0.1l-2.74,1.23l-1.85,-0.54l-2.54,-1.66l-0.66,-1.1Z", "name": "Hungary"}, "HN": {"path": "M199.6,249.52l-1.7,-1.21l0.06,-0.94l3.04,-2.14l2.37,0.28l1.27,-0.09l1.1,-0.52l1.3,0.28l1.14,-0.25l1.38,0.37l2.23,1.37l-2.36,0.93l-1.23,-0.39l-0.88,1.3l-1.28,0.99l-0.98,-0.22l-0.42,0.52l-0.96,0.05l-0.36,0.41l0.04,0.88l-0.52,0.6l-0.3,0.04l-0.3,-0.55l-0.66,-0.31l0.11,-0.67l-0.48,-0.65l-0.87,-0.26l-0.73,0.2Z", "name": "Honduras"}, "PR": {"path": "M256.17,238.73l-0.26,0.27l-2.83,0.05l-0.07,-0.55l1.95,-0.1l1.22,0.33Z", "name": "Puerto Rico"}, "PS": {"path": "M509.21,203.07l0.1,-0.06l-0.02,0.03l-0.09,0.03ZM509.36,202.91l-0.02,-0.63l-0.33,-0.16l0.31,-1.09l0.24,0.1l-0.2,1.78Z", "name": "Palestine"}, "PT": {"path": "M401.84,187.38l-0.64,0.47l-1.13,-0.35l-0.91,0.17l0.28,-1.78l-0.24,-1.78l-1.25,-0.56l-0.45,-0.84l0.17,-1.66l1.01,-1.18l0.69,-2.92l-0.04,-1.39l-0.59,-1.9l1.3,-0.85l0.84,1.35l3.1,-0.3l0.46,0.99l-1.05,0.94l-0.03,2.16l-0.41,0.57l-0.08,1.1l-0.79,0.18l-0.26,0.59l0.91,1.6l-0.63,1.75l0.76,1.09l-1.1,1.52l0.07,1.05Z", "name": "Portugal"}, "PY": {"path": "M274.9,336.12l0.74,1.52l-0.16,3.45l0.32,0.41l2.64,0.5l1.11,-0.47l1.4,0.59l0.36,0.6l0.53,3.42l1.27,0.4l0.98,-0.38l0.51,0.27l-0.0,1.18l-1.21,5.32l-2.09,1.9l-1.8,0.4l-4.71,-0.98l2.2,-3.63l-0.32,-1.5l-2.78,-1.28l-3.03,-1.94l-2.07,-0.44l-4.34,-4.06l0.91,-2.9l0.08,-1.42l1.07,-2.04l4.13,-0.72l2.18,0.03l2.05,1.17l0.03,0.59Z", "name": "Paraguay"}, "PA": {"path": "M213.8,263.68l0.26,-1.52l-0.36,-0.26l-0.01,-0.49l0.44,-0.1l0.93,1.4l1.26,0.03l0.77,0.49l1.38,-0.23l2.51,-1.11l0.86,-0.72l3.45,0.85l1.4,1.18l0.41,1.74l-0.21,0.34l-0.53,-0.12l-0.47,0.29l-0.16,0.6l-0.68,-1.28l0.45,-0.49l-0.19,-0.66l-0.47,-0.13l-0.54,-0.84l-1.5,-0.75l-1.1,0.16l-0.75,0.99l-1.62,0.84l-0.18,0.96l0.85,0.97l-0.58,0.45l-0.69,0.08l-0.34,-1.18l-1.27,0.03l-0.71,-1.05l-2.59,-0.46Z", "name": "Panama"}, "PG": {"path": "M808.58,298.86l2.54,2.56l-0.13,0.26l-0.33,0.12l-0.87,-0.78l-1.22,-2.16ZM801.41,293.04l0.5,0.29l0.26,0.27l-0.49,-0.35l-0.27,-0.21ZM803.17,294.58l0.59,0.5l0.08,1.06l-0.29,-0.91l-0.38,-0.65ZM796.68,298.41l0.52,0.75l1.43,-0.19l2.27,-1.81l-0.01,-1.43l1.12,0.16l-0.04,1.1l-0.7,1.28l-1.12,0.18l-0.62,0.79l-2.46,1.11l-1.17,-0.0l-3.08,-1.25l3.41,0.0l0.45,-0.68ZM789.15,303.55l2.31,1.8l1.59,2.61l1.34,0.13l-0.06,0.66l0.31,0.43l1.06,0.24l0.06,0.65l2.25,1.05l-1.22,0.13l-0.72,-0.63l-4.56,-0.65l-3.22,-2.87l-1.49,-2.34l-3.27,-1.1l-2.38,0.72l-1.59,0.86l-0.2,0.42l0.27,1.55l-1.55,0.68l-1.36,-0.4l-2.21,-0.09l-0.08,-15.41l8.39,2.93l2.95,2.4l0.6,1.64l4.02,1.49l0.31,0.68l-1.76,0.21l-0.33,0.52l0.55,1.68Z", "name": "Papua New Guinea"}, "PE": {"path": "M244.96,295.21l-1.26,-0.07l-0.57,0.42l-1.93,0.45l-2.98,1.75l-0.36,1.36l-0.58,0.8l0.12,1.37l-1.24,0.59l-0.22,1.22l-0.62,0.84l1.04,2.27l1.28,1.44l-0.41,0.84l0.32,0.57l1.48,0.13l1.16,1.37l2.21,0.07l1.63,-1.08l-0.13,3.02l0.3,0.4l1.14,0.29l1.31,-0.34l1.9,3.59l-0.48,0.85l-0.17,3.85l-0.94,1.59l0.35,0.75l-0.47,1.07l0.98,1.97l-2.1,3.82l-0.98,0.5l-2.17,-1.28l-0.39,-1.16l-4.95,-2.58l-4.46,-2.79l-1.84,-1.51l-0.91,-1.84l0.3,-0.96l-2.11,-3.33l-4.82,-9.68l-1.04,-1.2l-0.87,-1.94l-3.4,-2.48l0.58,-1.18l-1.13,-2.23l0.66,-1.49l1.45,-1.15l-0.6,0.98l0.07,0.92l0.47,0.36l1.74,0.03l0.97,1.17l0.54,0.07l1.42,-1.03l0.6,-1.84l1.42,-2.02l3.04,-1.04l2.73,-2.62l0.86,-1.74l-0.1,-1.87l1.44,1.02l0.9,1.25l1.06,0.59l1.7,2.73l1.86,0.31l1.45,-0.61l0.96,0.39l1.36,-0.19l1.45,0.89l-1.4,2.21l0.31,0.61l0.59,0.05l0.47,0.5Z", "name": "Peru"}, "PK": {"path": "M615.09,192.34l-1.83,1.81l-2.6,0.39l-3.73,-0.68l-1.58,1.33l-0.09,0.42l1.77,4.39l1.7,1.23l-1.69,1.27l-0.12,2.14l-2.33,2.64l-1.6,2.8l-2.46,2.67l-3.03,-0.07l-2.76,2.83l0.05,0.6l1.5,1.11l0.26,1.9l1.44,1.5l0.37,1.68l-5.01,-0.01l-1.78,1.7l-1.42,-0.52l-0.76,-1.87l-2.27,-2.15l-11.61,0.86l0.71,-2.34l3.43,-1.32l0.25,-0.44l-0.21,-1.24l-1.2,-0.65l-0.28,-2.46l-2.29,-1.14l-1.28,-1.94l2.82,0.94l2.62,-0.38l1.42,0.33l0.76,-0.56l1.71,0.19l3.25,-1.14l0.27,-0.36l0.08,-2.19l1.18,-1.32l1.68,0.0l0.58,-0.82l1.6,-0.3l1.19,0.16l0.98,-0.78l0.02,-1.88l0.93,-1.47l1.48,-0.66l0.19,-0.55l-0.66,-1.25l2.04,-0.11l0.69,-1.01l-0.02,-1.16l1.11,-1.06l-0.17,-1.78l-0.49,-1.03l1.15,-0.98l5.42,-0.91l2.6,-0.82l1.6,1.16l0.97,2.34l3.45,0.97Z", "name": "Pakistan"}, "PH": {"path": "M737.01,263.84l0.39,2.97l-0.44,1.18l-0.55,-1.53l-0.67,-0.14l-1.17,1.28l0.65,2.09l-0.42,0.69l-2.48,-1.23l-0.57,-1.49l0.65,-1.03l-0.1,-0.54l-1.59,-1.19l-0.56,0.08l-0.65,0.87l-1.23,0.0l-1.58,0.97l0.83,-1.8l2.56,-1.42l0.65,0.84l0.45,0.13l1.9,-0.69l0.56,-1.11l1.5,-0.06l0.38,-0.43l-0.09,-1.19l1.21,0.71l0.36,2.02ZM733.59,256.58l0.05,0.75l0.08,0.26l-0.8,-0.42l-0.18,-0.71l0.85,0.12ZM734.08,256.1l-0.12,-1.12l-1.0,-1.27l1.36,0.03l0.53,0.73l0.51,2.04l-1.27,-0.4ZM733.76,257.68l0.38,0.98l-0.32,0.15l-0.07,-1.13ZM724.65,238.43l1.46,0.7l0.72,-0.31l-0.32,1.17l0.79,1.71l-0.57,1.84l-1.53,1.04l-0.39,2.25l0.56,2.04l1.63,0.57l1.16,-0.27l2.71,1.23l-0.19,1.08l0.76,0.84l-0.08,0.36l-1.4,-0.9l-0.88,-1.27l-0.66,0.0l-0.38,0.55l-1.6,-1.31l-2.15,0.36l-0.87,-0.39l0.07,-0.61l0.66,-0.55l-0.01,-0.62l-0.75,-0.59l-0.72,0.44l-0.74,-0.87l-0.39,-2.49l0.32,0.27l0.66,-0.28l0.26,-3.97l0.7,-2.02l1.14,0.0ZM731.03,258.87l-0.88,0.85l-1.19,1.94l-1.05,-1.19l0.93,-1.1l0.32,-1.47l0.52,-0.06l-0.27,1.15l0.22,0.45l0.49,-0.12l1.0,-1.32l-0.08,0.85ZM726.83,255.78l0.83,0.38l1.17,-0.0l-0.02,0.48l-2.0,1.4l0.03,-2.26ZM724.81,252.09l-0.38,1.27l-1.42,-1.95l1.2,0.05l0.6,0.63ZM716.55,261.82l1.1,-0.95l0.03,-0.03l-0.28,0.36l-0.85,0.61ZM719.22,259.06l0.04,-0.06l0.8,-1.53l0.16,0.75l-1.0,0.84Z", "name": "Philippines"}, "PL": {"path": "M468.44,149.42l-1.11,-1.54l-1.86,-0.33l-0.48,-1.05l-1.72,-0.37l-0.65,0.69l-0.72,-0.36l0.11,-0.61l-0.33,-0.46l-1.75,-0.27l-1.04,-0.93l-0.94,-1.94l0.16,-1.22l-0.62,-1.8l-0.78,-1.07l0.57,-1.04l-0.48,-1.43l1.41,-0.83l6.91,-2.71l2.14,0.5l0.52,0.91l5.51,0.44l4.55,-0.05l1.07,0.31l0.48,0.84l0.15,1.58l0.65,1.2l-0.01,0.99l-1.27,0.58l-0.19,0.54l0.73,1.48l0.08,1.55l1.2,2.76l-0.17,0.58l-1.23,0.44l-2.27,2.72l0.18,0.95l-1.97,-1.03l-1.98,0.4l-1.36,-0.28l-1.24,0.58l-1.07,-0.97l-1.16,0.24Z", "name": "Poland"}, "ZM": {"path": "M481.47,313.3l0.39,0.31l2.52,0.14l0.99,1.17l2.01,0.35l1.4,-0.64l0.69,1.17l1.78,0.33l1.84,2.35l2.23,0.18l0.4,-0.43l-0.21,-2.74l-0.62,-0.3l-0.48,0.32l-1.98,-1.17l0.72,-5.29l-0.51,-1.18l0.57,-1.3l3.68,-0.62l0.26,0.63l1.21,0.63l0.9,-0.22l2.16,0.67l1.33,0.71l1.07,1.02l0.56,1.87l-0.88,2.7l0.43,2.09l-0.73,0.87l-0.76,2.37l0.59,0.68l-6.6,1.83l-0.29,0.44l0.19,1.45l-1.68,0.35l-1.43,1.02l-0.38,0.87l-0.87,0.26l-3.48,3.69l-4.16,-0.53l-1.52,-1.0l-1.77,-0.13l-1.83,0.52l-3.04,-3.4l0.11,-7.59l4.82,0.03l0.39,-0.49l-0.18,-0.76l0.33,-0.83l-0.4,-1.36l0.24,-1.05Z", "name": "Zambia"}, "EH": {"path": "M384.42,230.28l0.25,-0.79l1.06,-1.29l0.8,-3.51l3.38,-2.78l0.7,-1.81l0.06,4.84l-1.98,0.2l-0.94,1.59l0.39,3.56l-3.7,-0.01ZM392.01,218.1l0.7,-1.8l1.77,-0.24l2.09,0.34l0.95,-0.62l1.28,-0.07l-0.0,2.51l-6.79,-0.12Z", "name": "W. Sahara"}, "EE": {"path": "M485.71,115.04l2.64,0.6l2.56,0.11l-1.6,1.91l0.61,3.54l-0.81,0.87l-1.78,-0.01l-3.22,-1.76l-1.8,0.45l0.21,-1.53l-0.58,-0.41l-0.69,0.34l-1.26,-1.03l-0.17,-1.63l2.83,-0.92l3.05,-0.52Z", "name": "Estonia"}, "EG": {"path": "M492.06,205.03l1.46,0.42l2.95,-1.64l2.04,-0.21l1.53,0.3l0.59,1.19l0.69,0.04l0.41,-0.64l1.81,0.58l1.95,0.16l1.04,-0.51l1.42,4.08l-2.03,4.54l-1.66,-1.77l-1.76,-3.85l-0.64,-0.12l-0.36,0.67l1.04,2.88l3.44,6.95l1.78,3.04l2.03,2.65l-0.36,0.53l0.23,2.01l2.7,2.19l-28.41,0.0l0.0,-18.96l-0.73,-2.2l0.59,-1.56l-0.32,-1.26l0.68,-0.99l3.06,-0.04l4.82,1.52Z", "name": "Egypt"}, "ZA": {"path": "M467.14,373.21l-0.13,-1.96l-0.68,-1.56l0.7,-0.68l-0.13,-2.33l-4.56,-8.19l0.77,-0.86l0.6,0.45l0.69,1.31l2.83,0.72l1.5,-0.26l2.24,-1.39l0.19,-9.55l1.35,2.3l-0.21,1.5l0.61,1.2l0.4,0.19l1.79,-0.27l2.6,-2.07l0.69,-1.32l0.96,-0.48l2.19,1.04l2.04,0.13l1.77,-0.65l0.85,-2.12l1.38,-0.33l1.59,-2.76l2.15,-1.89l3.41,-1.87l2.0,0.45l1.02,-0.28l0.99,0.2l1.75,5.29l-0.38,3.25l-0.81,-0.23l-1.0,0.46l-0.87,1.68l-0.05,1.16l1.97,1.84l1.47,-0.29l0.69,-1.18l1.09,0.01l-0.76,3.69l-0.58,1.09l-2.2,1.79l-3.17,4.76l-2.8,2.83l-3.57,2.88l-2.53,1.05l-1.22,0.14l-0.51,0.7l-1.18,-0.32l-1.39,0.5l-2.59,-0.52l-1.61,0.33l-1.18,-0.11l-2.55,1.1l-2.1,0.44l-1.6,1.07l-0.85,0.05l-0.93,-0.89l-0.93,-0.15l-0.97,-1.13l-0.25,0.05ZM491.45,364.19l0.62,-0.93l1.48,-0.59l1.18,-2.19l-0.07,-0.49l-1.99,-1.69l-1.66,0.56l-1.43,1.14l-1.34,1.73l0.02,0.51l1.88,2.11l1.31,-0.16Z", "name": "South Africa"}, "EC": {"path": "M231.86,285.53l0.29,1.59l-0.69,1.45l-2.61,2.51l-3.13,1.11l-1.53,2.18l-0.49,1.68l-1.0,0.73l-1.02,-1.11l-1.78,-0.16l0.67,-1.15l-0.24,-0.86l1.25,-2.13l-0.54,-1.09l-0.67,-0.08l-0.72,0.87l-0.87,-0.64l0.35,-0.69l-0.36,-1.96l0.81,-0.51l0.45,-1.51l0.92,-1.57l-0.07,-0.97l2.65,-1.33l2.75,1.35l0.77,1.05l2.12,0.35l0.76,-0.32l1.96,1.21Z", "name": "Ecuador"}, "IT": {"path": "M451.59,158.63l3.48,0.94l-0.21,1.17l0.3,0.83l-1.49,-0.24l-2.04,1.1l-0.21,0.39l0.13,1.45l-0.25,1.12l0.82,1.57l2.39,1.63l1.31,2.54l2.79,2.43l2.05,0.08l0.21,0.23l-0.39,0.33l0.09,0.67l4.05,1.97l2.17,1.76l-0.16,0.36l-1.17,-1.08l-2.18,-0.49l-0.44,0.2l-1.05,1.91l0.14,0.54l1.57,0.95l-0.19,0.98l-1.06,0.33l-1.25,2.34l-0.37,0.08l0.0,-0.33l1.0,-2.45l-1.73,-3.17l-1.12,-0.51l-0.88,-1.33l-1.51,-0.51l-1.27,-1.25l-1.75,-0.18l-4.12,-3.21l-1.62,-1.65l-1.03,-3.19l-3.53,-1.36l-1.3,0.51l-1.69,1.41l0.16,-0.72l-0.28,-0.47l-1.14,-0.33l-0.53,-1.96l0.72,-0.78l0.04,-0.48l-0.65,-1.17l0.8,0.39l1.4,-0.23l1.11,-0.84l0.52,0.35l1.19,-0.1l0.75,-1.2l1.53,0.33l1.36,-0.56l0.35,-1.14l1.08,0.32l0.68,-0.64l1.98,-0.44l0.42,0.82ZM459.19,184.75l-0.65,1.65l0.32,1.05l-0.31,0.89l-1.5,-0.85l-4.5,-1.67l0.19,-0.82l2.67,0.23l3.78,-0.48ZM443.93,176.05l1.18,1.66l-0.3,3.32l-1.06,-0.01l-0.77,0.73l-0.53,-0.44l-0.1,-3.37l-0.39,-1.22l1.04,0.01l0.92,-0.68Z", "name": "Italy"}, "VN": {"path": "M690.56,230.25l-2.7,1.82l-2.09,2.46l-0.63,1.95l4.31,6.45l2.32,1.65l1.43,1.94l1.11,4.59l-0.32,4.24l-1.93,1.54l-2.84,1.61l-2.11,2.15l-2.73,2.06l-0.59,-1.05l0.63,-1.53l-0.13,-0.47l-1.34,-1.04l1.51,-0.71l2.55,-0.18l0.3,-0.63l-0.82,-1.14l4.0,-2.07l0.31,-3.05l-0.57,-1.77l0.42,-2.66l-0.73,-1.97l-1.86,-1.76l-3.63,-5.29l-2.72,-1.46l0.36,-0.47l1.5,-0.64l0.21,-0.52l-0.97,-2.27l-0.37,-0.24l-2.83,-0.02l-2.24,-3.9l0.83,-0.4l4.39,-0.29l2.06,-1.31l1.15,0.89l1.88,0.4l-0.17,1.51l1.35,1.16l1.67,0.45Z", "name": "Vietnam"}, "SB": {"path": "M826.69,311.6l-0.61,0.09l-0.2,-0.33l0.37,0.15l0.44,0.09ZM824.18,307.38l-0.26,-0.3l-0.31,-0.91l0.03,0.0l0.54,1.21ZM823.04,309.33l-1.66,-0.22l-0.2,-0.52l1.16,0.28l0.69,0.46ZM819.28,304.68l1.14,0.65l0.02,0.03l-0.81,-0.44l-0.35,-0.23Z", "name": "Solomon Is."}, "ET": {"path": "M516.04,247.79l1.1,0.84l1.63,-0.45l0.68,0.47l1.63,0.03l2.01,0.94l1.73,1.66l1.64,2.07l-1.52,2.04l0.16,1.72l0.39,0.38l2.05,0.0l-0.36,1.03l2.86,3.58l8.32,3.08l1.31,0.02l-6.32,6.75l-3.1,0.11l-2.36,1.77l-1.47,0.04l-0.86,0.79l-1.38,-0.0l-1.32,-0.81l-2.29,1.05l-0.76,0.98l-3.29,-0.41l-3.07,-2.07l-1.8,-0.07l-0.62,-0.6l0.0,-1.24l-0.28,-0.38l-1.15,-0.37l-1.4,-2.59l-1.19,-0.68l-0.47,-1.0l-1.27,-1.23l-1.16,-0.22l0.43,-0.72l1.45,-0.28l0.41,-0.95l-0.03,-2.21l0.68,-2.44l1.05,-0.63l1.43,-3.06l1.57,-1.37l1.02,-2.51l0.35,-1.88l2.52,0.46l0.44,-0.24l0.58,-1.43Z", "name": "Ethiopia"}, "SO": {"path": "M525.13,288.48l-1.13,-1.57l-0.03,-8.86l2.66,-3.38l1.67,-0.13l2.13,-1.69l3.41,-0.23l7.08,-7.55l2.91,-3.69l0.08,-4.82l2.98,-0.67l1.24,-0.86l0.45,-0.0l-0.2,3.0l-1.21,3.62l-2.73,5.97l-2.13,3.65l-5.03,6.16l-8.56,6.4l-2.78,3.08l-0.8,1.56Z", "name": "Somalia"}, "ZW": {"path": "M498.91,341.09l-1.11,-0.22l-0.92,0.28l-2.09,-0.44l-1.5,-1.11l-1.89,-0.43l-0.62,-1.4l-0.01,-0.84l-0.3,-0.38l-0.97,-0.25l-2.71,-2.74l-1.92,-3.32l3.83,0.45l3.73,-3.82l1.08,-0.44l0.26,-0.77l1.25,-0.9l1.41,-0.26l0.5,0.89l1.99,-0.05l1.72,1.17l1.11,0.17l1.05,0.66l0.01,2.99l-0.59,3.76l0.38,0.86l-0.23,1.23l-0.39,0.35l-0.63,1.81l-2.43,2.75Z", "name": "Zimbabwe"}, "ES": {"path": "M416.0,169.21l1.07,1.17l4.61,1.38l1.06,-0.57l2.6,1.26l2.71,-0.3l0.09,1.12l-2.14,1.8l-3.11,0.61l-0.31,0.31l-0.2,0.89l-1.54,1.69l-0.97,2.4l0.84,1.74l-1.32,1.27l-0.48,1.68l-1.88,0.65l-1.66,2.07l-5.36,-0.01l-1.79,1.08l-0.89,0.98l-0.88,-0.17l-0.79,-0.82l-0.68,-1.59l-2.37,-0.63l-0.11,-0.5l1.21,-1.82l-0.77,-1.13l0.61,-1.68l-0.76,-1.62l0.87,-0.49l0.09,-1.25l0.42,-0.6l0.03,-2.11l0.99,-0.69l0.13,-0.5l-1.03,-1.73l-1.46,-0.11l-0.61,0.38l-1.06,0.0l-0.52,-1.23l-0.53,-0.21l-1.32,0.67l-0.01,-1.49l-0.75,-0.96l3.03,-1.88l2.99,0.53l3.32,-0.02l2.63,0.51l6.01,-0.06Z", "name": "Spain"}, "ER": {"path": "M520.38,246.23l3.42,2.43l3.5,3.77l0.84,0.54l-0.95,-0.01l-3.51,-3.89l-2.33,-1.15l-1.73,-0.07l-0.91,-0.51l-1.26,0.51l-1.34,-1.02l-0.61,0.17l-0.66,1.61l-2.35,-0.43l-0.17,-0.67l1.29,-5.29l0.61,-0.61l1.95,-0.53l0.87,-1.01l1.17,2.41l0.68,2.33l1.49,1.43Z", "name": "Eritrea"}, "ME": {"path": "M468.91,172.53l-1.22,-1.02l0.47,-1.81l0.89,-0.72l2.26,1.51l-0.5,0.57l-0.75,-0.27l-1.14,1.73Z", "name": "Montenegro"}, "MD": {"path": "M488.41,153.73l1.4,-0.27l1.72,0.93l1.07,0.15l0.85,0.65l-0.14,0.84l0.96,0.85l1.12,2.47l-1.15,-0.07l-0.66,-0.41l-0.52,0.25l-0.09,0.86l-1.08,1.89l-0.27,-0.86l0.25,-1.34l-0.16,-1.6l-3.29,-4.34Z", "name": "Moldova"}, "MG": {"path": "M545.91,319.14l0.4,3.03l0.62,1.21l-0.21,1.02l-0.57,-0.8l-0.69,-0.01l-0.47,0.76l0.41,2.12l-0.18,0.87l-0.73,0.78l-0.15,2.14l-4.71,15.2l-1.06,2.88l-3.92,1.64l-3.12,-1.49l-0.6,-1.21l-0.19,-2.4l-0.86,-2.05l-0.21,-1.77l0.38,-1.62l1.21,-0.75l0.01,-0.76l1.19,-2.04l0.23,-1.66l-1.06,-2.99l-0.19,-2.21l0.81,-1.33l0.32,-1.46l4.63,-1.22l3.44,-3.0l0.85,-1.4l-0.08,-0.7l0.78,-0.04l1.38,-1.77l0.13,-1.64l0.45,-0.61l1.16,1.69l0.59,1.6Z", "name": "Madagascar"}, "MA": {"path": "M378.78,230.02l0.06,-0.59l0.92,-0.73l0.82,-1.37l-0.09,-1.04l0.79,-1.7l1.31,-1.58l0.96,-0.59l0.66,-1.55l0.09,-1.47l0.81,-1.48l1.72,-1.07l1.55,-2.69l1.16,-0.96l2.44,-0.39l1.94,-1.82l1.31,-0.78l2.09,-2.28l-0.51,-3.65l1.24,-3.7l1.5,-1.75l4.46,-2.57l2.37,-4.47l1.44,0.01l1.68,1.21l2.32,-0.19l3.47,0.65l0.8,1.54l0.16,1.71l0.86,2.96l0.56,0.59l-0.26,0.61l-3.05,0.44l-1.26,1.05l-1.33,0.22l-0.33,0.37l-0.09,1.78l-2.68,1.0l-1.07,1.42l-4.47,1.13l-4.04,2.01l-0.54,4.64l-1.15,0.06l-0.92,0.61l-1.96,-0.35l-2.42,0.54l-0.74,1.9l-0.86,0.4l-1.14,3.26l-3.53,3.01l-0.8,3.55l-0.96,1.1l-0.29,0.82l-4.95,0.18Z", "name": "Morocco"}, "UZ": {"path": "M598.64,172.75l-1.63,1.52l0.06,0.64l1.85,1.12l1.97,-0.64l2.21,1.17l-2.52,1.68l-2.59,-0.22l-0.18,-0.41l0.46,-1.23l-0.45,-0.53l-3.35,0.69l-2.1,3.51l-1.87,-0.12l-1.03,1.51l0.22,0.55l1.64,0.62l0.46,1.83l-1.19,2.49l-2.66,-0.53l0.05,-1.36l-0.26,-0.39l-3.3,-1.23l-2.56,-1.4l-4.4,-3.34l-1.34,-3.14l-1.08,-0.6l-2.58,0.13l-0.69,-0.44l-0.47,-2.52l-3.37,-1.6l-0.43,0.05l-2.07,1.72l-2.1,1.01l-0.21,0.47l0.28,1.01l-1.91,0.03l-0.09,-10.5l5.99,-1.7l6.19,3.54l2.71,2.84l7.05,-0.67l2.71,2.01l-0.17,2.81l0.39,0.42l0.9,0.02l0.44,2.14l0.38,0.32l2.94,0.09l0.95,1.42l1.28,-0.24l1.05,-2.04l4.43,-2.5Z", "name": "Uzbekistan"}, "MM": {"path": "M673.9,230.21l-1.97,1.57l-0.57,0.96l-1.4,0.6l-1.36,1.05l-1.99,0.36l-1.08,2.66l-0.91,0.4l-0.19,0.55l1.21,2.27l2.52,3.43l-0.79,1.91l-0.74,0.41l-0.17,0.52l0.65,1.37l1.61,1.95l0.25,2.58l0.9,2.13l-1.92,3.57l0.68,-2.25l-0.81,-1.74l0.19,-2.65l-1.05,-1.53l-1.24,-6.17l-1.12,-2.26l-0.6,-0.13l-4.34,3.02l-2.39,-0.65l0.77,-2.84l-0.52,-2.61l-1.91,-2.96l0.25,-0.75l-0.29,-0.51l-1.33,-0.3l-1.61,-1.93l-0.1,-1.3l0.82,-0.24l0.04,-1.64l1.02,-0.52l0.21,-0.45l-0.23,-0.95l0.54,-0.96l0.08,-2.22l1.46,0.45l0.47,-0.2l1.12,-2.19l0.16,-1.35l1.33,-2.16l-0.0,-1.52l2.89,-1.66l1.63,0.44l0.5,-0.44l-0.17,-1.4l0.64,-0.36l0.08,-1.04l0.77,-0.11l0.71,1.35l1.06,0.69l-0.03,3.86l-2.38,2.37l-0.3,3.15l0.46,0.43l2.28,-0.38l0.51,2.08l1.47,0.67l-0.6,1.8l0.19,0.48l2.97,1.48l1.64,-0.55l0.02,0.32Z", "name": "Myanmar"}, "ML": {"path": "M392.61,254.08l-0.19,-2.37l-0.99,-0.87l-0.44,-1.3l-0.09,-1.28l0.81,-0.58l0.35,-1.24l2.37,0.65l1.31,-0.47l0.86,0.15l0.66,-0.56l9.83,-0.04l0.38,-0.28l0.56,-1.8l-0.44,-0.65l-2.35,-21.95l3.27,-0.04l16.7,11.38l0.74,1.31l2.5,1.09l0.02,1.38l0.44,0.39l2.34,-0.21l0.01,5.38l-1.28,1.61l-0.26,1.49l-5.31,0.57l-1.07,0.92l-2.9,0.1l-0.86,-0.48l-1.38,0.36l-2.4,1.08l-0.6,0.87l-1.85,1.09l-0.43,0.7l-0.79,0.39l-1.44,-0.21l-0.81,0.84l-0.34,1.64l-1.91,2.02l-0.06,1.03l-0.67,1.22l0.13,1.16l-0.97,0.39l-0.23,-0.64l-0.52,-0.24l-1.35,0.4l-0.34,0.55l-2.69,-0.28l-0.37,-0.35l-0.02,-0.9l-0.65,-0.35l0.45,-0.64l-0.03,-0.53l-2.12,-2.44l-0.76,-0.01l-2.0,1.16l-0.78,-0.15l-0.8,-0.67l-1.21,0.23Z", "name": "Mali"}, "MN": {"path": "M676.61,146.48l3.81,1.68l5.67,-1.0l2.37,0.41l2.34,1.5l1.79,1.75l2.29,-0.03l3.12,0.52l2.47,-0.81l3.41,-0.59l3.53,-2.21l1.25,0.29l1.53,1.13l2.27,-0.21l-2.66,5.01l0.64,1.68l0.47,0.21l1.32,-0.38l2.38,0.48l2.02,-1.11l1.76,0.89l2.06,2.02l-0.13,0.53l-1.72,-0.29l-3.77,0.46l-1.88,0.99l-1.76,1.99l-3.71,1.17l-2.45,1.6l-3.83,-0.87l-0.41,0.17l-1.31,1.99l1.04,2.24l-1.52,0.9l-1.74,1.57l-2.79,1.02l-3.78,0.13l-4.05,1.05l-2.77,1.52l-1.16,-0.85l-2.94,0.0l-3.62,-1.79l-2.58,-0.49l-3.4,0.41l-5.12,-0.67l-2.63,0.06l-1.31,-1.6l-1.4,-3.0l-1.48,-0.33l-3.13,-1.94l-6.16,-0.93l-0.71,-1.06l0.86,-3.82l-1.93,-2.71l-3.5,-1.18l-1.95,-1.58l-0.5,-1.72l2.34,-0.52l4.75,-2.8l3.62,-1.47l2.18,0.97l2.46,0.05l1.81,1.53l2.46,0.12l3.95,0.71l2.43,-2.28l0.08,-0.48l-0.9,-1.72l2.24,-2.98l2.62,1.27l4.94,1.17l0.43,2.24Z", "name": "Mongolia"}, "MK": {"path": "M472.8,173.98l0.49,-0.71l3.57,-0.71l1.0,0.77l0.13,1.45l-0.65,0.53l-1.15,-0.05l-1.12,0.67l-1.39,0.22l-0.79,-0.55l-0.29,-1.03l0.19,-0.6Z", "name": "Macedonia"}, "MW": {"path": "M505.5,309.31l0.85,1.95l0.15,2.86l-0.69,1.65l0.71,1.8l0.06,1.28l0.49,0.64l0.07,1.06l0.4,0.55l0.8,-0.23l0.55,0.61l0.69,-0.21l0.34,0.6l0.19,2.94l-1.04,0.62l-0.54,1.25l-1.11,-1.08l-0.16,-1.56l0.51,-1.31l-0.32,-1.3l-0.99,-0.65l-0.82,0.12l-2.36,-1.64l0.63,-1.96l0.82,-1.18l-0.46,-2.01l0.9,-2.86l-0.94,-2.51l0.96,0.18l0.29,0.4Z", "name": "Malawi"}, "MR": {"path": "M407.36,220.66l-2.58,0.03l-0.39,0.44l2.42,22.56l0.36,0.43l-0.39,1.24l-9.75,0.04l-0.56,0.53l-0.91,-0.11l-1.27,0.45l-1.61,-0.66l-0.97,0.03l-0.36,0.29l-0.38,1.35l-0.42,0.23l-2.93,-3.4l-2.96,-1.52l-1.62,-0.03l-1.27,0.54l-1.12,-0.2l-0.65,0.4l-0.08,-0.49l0.68,-1.29l0.31,-2.43l-0.57,-3.91l0.23,-1.21l-0.69,-1.5l-1.15,-1.02l0.25,-0.39l9.58,0.02l0.4,-0.45l-0.46,-3.68l0.47,-1.04l2.12,-0.21l0.36,-0.4l-0.08,-6.4l7.81,0.13l0.41,-0.4l0.01,-3.31l7.76,5.35Z", "name": "Mauritania"}, "UG": {"path": "M498.55,276.32l0.7,-0.46l1.65,0.5l1.96,-0.57l1.7,0.01l1.45,-0.98l0.91,1.33l1.33,3.95l-2.57,4.03l-1.46,-0.4l-2.54,0.91l-1.37,1.61l-0.01,0.81l-2.42,-0.01l-2.26,1.01l-0.17,-1.59l0.58,-1.04l0.14,-1.94l1.37,-2.28l1.78,-1.58l-0.17,-0.65l-0.72,-0.24l0.13,-2.43Z", "name": "Uganda"}, "MY": {"path": "M717.47,273.46l-1.39,0.65l-2.12,-0.41l-2.88,-0.0l-0.38,0.28l-0.84,2.75l-0.99,0.96l-1.21,3.29l-1.73,0.45l-2.45,-0.68l-1.39,0.31l-1.33,1.15l-1.59,-0.14l-1.41,0.44l-1.44,-1.19l-0.18,-0.73l1.34,0.53l1.93,-0.47l0.75,-2.22l4.02,-1.03l2.75,-3.21l0.82,0.94l0.64,-0.05l0.4,-0.65l0.96,0.06l0.42,-0.36l0.24,-2.68l1.81,-1.64l1.21,-1.86l0.63,-0.01l1.07,1.05l0.34,1.28l3.44,1.35l-0.06,0.35l-1.37,0.1l-0.35,0.54l0.32,0.88ZM673.68,269.59l0.17,1.09l0.47,0.33l1.65,-0.3l0.87,-0.94l1.61,1.52l0.98,1.56l-0.12,2.81l0.41,2.29l0.95,0.9l0.88,2.44l-1.27,0.12l-5.1,-3.67l-0.34,-1.29l-1.37,-1.59l-0.33,-1.97l-0.88,-1.4l0.25,-1.68l-0.46,-1.05l1.63,0.84Z", "name": "Malaysia"}, "MX": {"path": "M133.12,200.41l0.2,0.47l9.63,3.33l6.96,-0.02l0.4,-0.4l0.0,-0.74l3.77,0.0l3.55,2.93l1.39,2.83l1.52,1.04l2.08,0.82l0.47,-0.14l1.46,-2.0l1.73,-0.04l1.59,0.98l2.05,3.35l1.47,1.56l1.26,3.14l2.18,1.02l2.26,0.58l-1.18,3.72l-0.42,5.04l1.79,4.89l1.62,1.89l0.61,1.52l1.2,1.42l2.55,0.66l1.37,1.1l7.54,-1.89l1.86,-1.3l1.14,-4.3l4.1,-1.21l3.57,-0.11l0.32,0.3l-0.06,0.94l-1.26,1.45l-0.67,1.71l0.38,0.7l-0.72,2.27l-0.49,-0.3l-1.0,0.08l-1.0,1.39l-0.47,-0.11l-0.53,0.47l-4.26,-0.02l-0.4,0.4l-0.0,1.06l-1.1,0.26l0.1,0.44l1.82,1.44l0.56,0.91l-3.19,0.21l-1.21,2.09l0.24,0.72l-0.2,0.44l-2.24,-2.18l-1.45,-0.93l-2.22,-0.69l-1.52,0.22l-3.07,1.16l-10.55,-3.85l-2.86,-1.96l-3.78,-0.92l-1.08,-1.19l-2.62,-1.43l-1.18,-1.54l-0.38,-0.81l0.66,-0.63l-0.18,-0.53l0.52,-0.76l0.01,-0.91l-2.0,-3.82l-2.21,-2.63l-2.53,-2.09l-1.19,-1.62l-2.2,-1.17l-0.3,-0.43l0.34,-1.48l-0.21,-0.45l-1.23,-0.6l-1.36,-1.2l-0.59,-1.78l-1.54,-0.47l-2.44,-2.55l-0.16,-0.9l-1.33,-2.03l-0.84,-1.99l-0.16,-1.33l-1.81,-1.1l-0.97,0.05l-1.31,-0.7l-0.57,0.22l-0.4,1.12l0.72,3.77l3.51,3.89l0.28,0.78l0.53,0.26l0.41,1.43l1.33,1.73l1.58,1.41l0.8,2.39l1.43,2.41l0.13,1.32l0.37,0.36l1.04,0.08l1.67,2.28l-0.85,0.76l-0.66,-1.51l-1.68,-1.54l-2.91,-1.87l0.06,-1.82l-0.54,-1.68l-2.91,-2.03l-0.55,0.09l-1.95,-1.1l-0.88,-0.94l0.68,-0.08l0.93,-1.01l0.08,-1.78l-1.93,-1.94l-1.46,-0.77l-3.75,-7.56l4.88,-0.42Z", "name": "Mexico"}, "IL": {"path": "M507.76,203.05l0.4,-0.78l0.18,0.4l-0.33,1.03l0.52,0.44l0.68,-0.22l-0.86,3.6l-1.16,-3.32l0.59,-0.74l-0.03,-0.41ZM508.73,200.34l0.37,-1.02l0.64,0.0l0.52,-0.51l-0.49,1.53l-0.56,-0.24l-0.48,0.23Z", "name": "Israel"}, "FR": {"path": "M444.48,172.62l-0.64,1.78l-0.58,-0.31l-0.49,-1.72l0.4,-0.89l1.0,-0.72l0.3,1.85ZM429.64,147.1l1.78,1.58l1.46,-0.13l2.1,1.42l1.35,0.27l1.23,0.83l3.04,0.5l-1.03,1.85l-0.3,2.12l-0.41,0.32l-0.95,-0.24l-0.5,0.43l0.06,0.61l-1.81,1.92l-0.04,1.42l0.55,0.38l0.88,-0.36l0.61,0.97l-0.03,1.0l0.57,0.91l-0.75,1.09l0.65,2.39l1.27,0.57l-0.18,0.82l-2.01,1.53l-4.77,-0.8l-3.82,1.0l-0.53,1.85l-2.49,0.34l-2.71,-1.31l-1.16,0.57l-4.31,-1.29l-0.72,-0.86l1.19,-1.78l0.39,-6.45l-2.58,-3.3l-1.9,-1.66l-3.72,-1.23l-0.19,-1.72l2.81,-0.61l4.12,0.81l0.47,-0.48l-0.6,-2.77l1.94,0.95l5.83,-2.54l0.92,-2.74l1.6,-0.49l0.24,0.78l1.36,0.33l1.05,1.19ZM289.01,278.39l-0.81,0.8l-0.78,0.12l-0.5,-0.66l-0.56,-0.1l-0.91,0.6l-0.46,-0.22l1.09,-2.96l-0.96,-1.77l-0.17,-1.49l1.07,-1.77l2.32,0.75l2.51,2.01l0.3,0.74l-2.14,3.96Z", "name": "France"}, "XS": {"path": "M531.15,258.94l1.51,0.12l5.13,-0.95l5.3,-1.48l-0.01,4.4l-2.67,3.39l-1.85,0.01l-8.04,-2.94l-2.55,-3.17l1.12,-1.71l2.04,2.34Z", "name": "Somaliland"}, "FI": {"path": "M492.17,76.39l-0.23,3.5l3.52,2.63l-2.08,2.88l-0.02,0.44l2.8,4.56l-1.59,3.31l2.16,3.24l-0.94,2.39l0.14,0.47l3.44,2.51l-0.77,1.62l-7.52,6.95l-4.5,0.31l-4.38,1.37l-3.8,0.74l-1.44,-1.96l-2.17,-1.11l0.5,-3.66l-1.16,-3.33l1.09,-2.08l2.21,-2.42l5.67,-4.32l1.64,-0.83l0.21,-0.42l-0.46,-2.02l-3.38,-1.89l-0.75,-1.43l-0.22,-6.74l-6.79,-4.8l0.8,-0.62l2.54,2.12l3.46,-0.12l3.0,0.96l2.51,-2.11l1.17,-3.08l3.55,-1.38l2.76,1.53l-0.95,2.79Z", "name": "Finland"}, "FJ": {"path": "M869.95,326.98l-1.21,0.41l-0.08,-0.23l2.97,-1.21l-0.14,0.42l-1.54,0.61ZM867.58,329.25l0.43,0.37l-0.27,0.88l-1.24,0.28l-1.04,-0.24l-0.14,-0.66l0.63,-0.58l0.92,0.26l0.7,-0.31Z", "name": "Fiji"}, "FK": {"path": "M274.36,425.85l1.44,1.08l-0.47,0.73l-3.0,0.89l-0.96,-1.0l-0.52,-0.05l-1.83,1.29l-0.73,-0.88l2.46,-1.64l1.93,0.76l1.67,-1.19Z", "name": "Falkland Is."}, "NI": {"path": "M202.33,252.67l0.81,-0.18l1.03,-1.02l-0.04,-0.88l0.68,-0.0l0.63,-0.54l0.97,0.22l1.53,-1.26l0.58,-0.99l1.17,0.34l2.41,-0.94l0.13,1.32l-0.81,1.94l0.1,2.74l-0.36,0.37l-0.11,1.75l-0.47,0.81l0.18,1.14l-1.73,-0.85l-0.71,0.27l-1.47,-0.6l-0.52,0.16l-4.01,-3.81Z", "name": "Nicaragua"}, "NL": {"path": "M430.31,143.39l0.6,-0.5l2.13,-4.8l3.2,-1.33l1.74,0.08l0.33,0.8l-0.59,2.92l-0.5,0.99l-1.26,0.0l-0.4,0.45l0.33,2.7l-2.2,-1.78l-2.62,0.58l-0.75,-0.11Z", "name": "Netherlands"}, "NO": {"path": "M491.44,67.41l6.8,2.89l-2.29,0.86l-0.15,0.65l2.33,2.38l-4.98,1.79l0.84,-2.45l-0.18,-0.48l-3.55,-1.8l-3.89,1.52l-1.42,3.38l-2.12,1.72l-2.64,-1.0l-3.11,0.21l-2.66,-2.22l-0.5,-0.01l-1.41,1.1l-1.44,0.17l-0.35,0.35l-0.32,2.47l-4.32,-0.64l-0.44,0.29l-0.58,2.11l-2.45,0.2l-4.15,7.68l-3.88,5.76l0.78,1.62l-0.64,1.16l-2.24,-0.06l-0.38,0.24l-1.66,3.89l0.15,5.17l1.57,2.04l-0.78,4.16l-2.02,2.48l-0.85,1.63l-1.3,-1.75l-0.58,-0.07l-4.87,4.19l-3.1,0.79l-3.16,-1.7l-0.85,-3.77l-0.77,-8.55l2.14,-2.31l6.55,-3.27l5.02,-4.17l10.63,-13.84l10.98,-8.7l5.35,-1.91l4.34,0.12l3.69,-3.64l4.49,0.19l4.37,-0.89ZM484.55,20.04l4.26,1.75l-3.1,2.55l-7.1,0.65l-7.08,-0.9l-0.37,-1.31l-0.37,-0.29l-3.44,-0.1l-2.08,-2.0l6.87,-1.44l3.9,1.31l2.39,-1.64l6.13,1.4ZM481.69,33.93l-4.45,1.74l-3.54,-0.99l1.12,-0.9l0.05,-0.58l-1.06,-1.22l4.22,-0.89l1.09,1.97l2.57,0.87ZM466.44,24.04l7.43,3.77l-5.41,1.86l-1.58,4.08l-2.26,1.2l-1.12,4.11l-2.61,0.18l-4.79,-2.86l1.84,-1.54l-0.1,-0.68l-3.69,-1.53l-4.77,-4.51l-1.73,-3.89l6.11,-1.82l1.54,1.92l3.57,-0.08l1.2,-1.96l3.32,-0.18l3.05,1.92Z", "name": "Norway"}, "NA": {"path": "M474.26,330.66l-0.97,0.04l-0.38,0.4l-0.07,8.9l-2.09,0.08l-0.39,0.4l-0.0,17.42l-1.98,1.23l-1.17,0.17l-2.44,-0.66l-0.48,-1.13l-0.99,-0.74l-0.54,0.05l-0.9,1.01l-1.53,-1.68l-0.93,-1.88l-1.99,-8.56l-0.06,-3.12l-0.33,-1.52l-2.3,-3.34l-1.91,-4.83l-1.96,-2.43l-0.12,-1.57l2.33,-0.79l1.43,0.07l1.81,1.13l10.23,-0.25l1.84,1.23l5.87,0.35ZM474.66,330.64l6.51,-1.6l1.9,0.39l-1.69,0.4l-1.31,0.83l-1.12,-0.94l-4.29,0.92Z", "name": "Namibia"}, "VU": {"path": "M839.04,322.8l0.22,1.14l-0.44,0.03l-0.2,-1.45l0.42,0.27Z", "name": "Vanuatu"}, "NC": {"path": "M838.78,341.24l-0.33,0.22l-2.9,-1.75l-3.26,-3.37l1.65,0.83l4.85,4.07Z", "name": "New Caledonia"}, "NE": {"path": "M454.75,226.53l1.33,1.37l0.48,0.07l1.27,-0.7l0.53,3.52l0.94,0.83l0.17,0.92l0.81,0.69l-0.44,0.95l-0.96,5.26l-0.13,3.22l-3.04,2.31l-1.22,3.57l1.02,1.24l-0.0,1.46l0.39,0.4l1.13,0.04l-0.9,1.25l-1.47,-2.42l-0.86,-0.29l-2.09,1.37l-1.74,-0.67l-1.45,-0.17l-0.85,0.35l-1.36,-0.07l-1.64,1.09l-1.06,0.05l-2.94,-1.28l-1.44,0.59l-1.01,-0.03l-0.97,-0.94l-2.7,-0.98l-2.69,0.3l-0.87,0.64l-0.47,1.6l-0.75,1.16l-0.12,1.53l-1.57,-1.1l-1.31,0.24l0.03,-0.81l-0.32,-0.41l-2.59,-0.52l-0.15,-1.16l-1.35,-1.6l-0.29,-1.0l0.13,-0.84l1.29,-0.08l1.08,-0.92l3.31,-0.22l2.22,-0.41l0.32,-0.34l0.2,-1.47l1.39,-1.88l-0.01,-5.66l3.36,-1.12l7.24,-5.12l8.42,-4.92l3.69,1.06Z", "name": "Niger"}, "NG": {"path": "M456.32,253.89l0.64,0.65l-0.28,1.04l-2.11,2.01l-2.03,5.18l-1.37,1.16l-1.15,3.18l-1.33,0.66l-1.46,-0.97l-1.21,0.16l-1.38,1.36l-0.91,0.24l-1.79,4.06l-2.33,0.81l-1.11,-0.07l-0.86,0.5l-1.71,-0.05l-1.19,-1.39l-0.89,-1.89l-1.77,-1.66l-3.95,-0.08l0.07,-5.21l0.42,-1.43l1.95,-2.3l-0.14,-0.91l0.43,-1.18l-0.53,-1.41l0.25,-2.92l0.72,-1.07l0.32,-1.34l0.46,-0.39l2.47,-0.28l2.34,0.89l1.15,1.02l1.28,0.04l1.22,-0.58l3.03,1.27l1.49,-0.14l1.36,-1.0l1.33,0.07l0.82,-0.35l3.45,0.8l1.82,-1.32l1.84,2.67l0.66,0.16Z", "name": "Nigeria"}, "NZ": {"path": "M857.8,379.65l1.86,3.12l0.44,0.18l0.3,-0.38l0.03,-1.23l0.38,0.27l0.57,2.31l2.02,0.94l1.81,0.27l1.57,-1.06l0.7,0.18l-1.15,3.59l-1.98,0.11l-0.74,1.2l0.2,1.11l-2.42,3.98l-1.49,0.92l-1.04,-0.85l1.21,-2.05l-0.81,-2.01l-2.63,-1.25l0.04,-0.57l1.82,-1.19l0.43,-2.34l-0.16,-2.03l-0.95,-1.82l-0.06,-0.72l-3.11,-3.64l-0.79,-1.52l1.56,1.45l1.76,0.66l0.65,2.34ZM853.83,393.59l0.57,1.24l0.59,0.16l1.42,-0.97l0.46,0.79l0.0,1.03l-2.47,3.48l-1.26,1.2l-0.06,0.5l0.55,0.87l-1.41,0.07l-2.33,1.38l-2.03,5.02l-3.02,2.16l-2.06,-0.06l-1.71,-1.04l-2.47,-0.2l-0.27,-0.73l1.22,-2.1l3.05,-2.94l1.62,-0.59l4.02,-2.82l1.57,-1.67l1.07,-2.16l0.88,-0.7l0.48,-1.75l1.24,-0.97l0.35,0.79Z", "name": "New Zealand"}, "NP": {"path": "M641.14,213.62l0.01,3.19l-1.74,0.04l-4.8,-0.86l-1.58,-1.39l-3.37,-0.34l-7.65,-3.7l0.8,-2.09l2.33,-1.7l1.77,0.75l2.49,1.76l1.38,0.41l0.99,1.35l1.9,0.52l1.99,1.17l5.49,0.9Z", "name": "Nepal"}, "XK": {"path": "M472.77,172.64l-1.08,-1.29l0.96,-0.77l0.29,-0.83l1.98,1.64l-0.36,0.67l-1.79,0.58Z", "name": "Kosovo"}, "CI": {"path": "M407.4,259.27l0.86,0.42l0.56,0.9l1.13,0.53l1.19,-0.61l0.97,-0.08l1.42,0.54l0.6,3.24l-1.03,2.08l-0.65,2.84l1.06,2.33l-0.06,0.53l-2.54,-0.47l-1.66,0.03l-3.06,0.46l-4.11,1.6l0.32,-3.06l-1.18,-1.31l-1.32,-0.66l0.42,-0.85l-0.2,-1.4l0.5,-0.67l0.01,-1.59l0.84,-0.32l0.26,-0.5l-1.15,-3.01l0.12,-0.5l0.51,-0.25l0.66,0.31l1.93,0.02l0.67,-0.71l0.71,-0.14l0.25,0.69l0.57,0.22l1.4,-0.61Z", "name": "C\u00f4te d'Ivoire"}, "CH": {"path": "M444.62,156.35l-0.29,0.87l0.18,0.53l1.13,0.58l1.0,0.1l-0.1,0.65l-0.79,0.38l-1.72,-0.37l-0.45,0.23l-0.45,1.04l-0.75,0.06l-0.84,-0.4l-1.32,1.0l-0.96,0.12l-0.88,-0.55l-0.81,-1.3l-0.49,-0.16l-0.63,0.26l0.02,-0.65l1.71,-1.66l0.1,-0.56l0.93,0.08l0.58,-0.46l1.99,0.02l0.66,-0.61l2.19,0.79Z", "name": "Switzerland"}, "CO": {"path": "M242.07,254.93l-1.7,0.59l-0.59,1.18l-1.7,1.69l-0.38,1.93l-0.67,1.43l0.31,0.57l1.03,0.13l0.25,0.9l0.57,0.64l-0.04,2.34l1.64,1.42l3.16,-0.24l1.26,0.28l1.67,2.06l0.41,0.13l4.09,-0.39l0.45,0.22l-0.92,1.95l-0.2,1.8l0.52,1.83l0.75,1.05l-1.12,1.1l0.07,0.63l0.84,0.51l0.74,1.29l-0.39,-0.45l-0.59,-0.01l-0.71,0.74l-4.71,-0.05l-0.4,0.41l0.03,1.57l0.33,0.39l1.11,0.2l-1.68,0.4l-0.29,0.38l-0.01,1.82l1.16,1.14l0.34,1.25l-1.05,7.05l-1.04,-0.87l1.26,-1.99l-0.13,-0.56l-2.18,-1.23l-1.38,0.2l-1.14,-0.38l-1.27,0.61l-1.55,-0.26l-1.38,-2.46l-1.23,-0.75l-0.85,-1.2l-1.67,-1.19l-0.86,0.13l-2.11,-1.32l-1.01,0.31l-1.8,-0.29l-0.52,-0.91l-3.09,-1.68l0.77,-0.52l-0.1,-1.12l0.41,-0.64l1.34,-0.32l2.0,-2.88l-0.11,-0.57l-0.66,-0.43l0.39,-1.38l-0.52,-2.1l0.49,-0.83l-0.4,-2.13l-0.97,-1.35l0.17,-0.66l0.86,-0.08l0.47,-0.75l-0.46,-1.63l1.41,-0.07l1.8,-1.69l0.93,-0.24l0.3,-0.38l0.45,-2.76l1.22,-1.0l1.44,-0.04l0.45,-0.5l1.91,0.12l2.93,-1.84l1.15,-1.14l0.91,0.46l-0.25,0.45Z", "name": "Colombia"}, "CN": {"path": "M740.23,148.97l4.57,1.3l2.8,2.17l0.98,2.9l0.38,0.27l3.8,0.0l2.32,-1.28l3.29,-0.75l-0.96,2.09l-1.02,1.28l-0.85,3.4l-1.52,2.73l-2.76,-0.5l-2.4,1.13l-0.21,0.45l0.64,2.57l-0.32,3.2l-0.94,0.06l-0.37,0.89l-0.91,-1.01l-0.64,0.07l-0.92,1.57l-3.73,1.25l-0.26,0.48l0.26,1.06l-1.5,-0.08l-1.09,-0.86l-0.56,0.06l-1.67,2.06l-2.7,1.56l-2.03,1.88l-3.4,0.83l-1.93,1.4l-1.15,0.34l0.33,-0.7l-0.41,-0.89l1.79,-1.79l0.02,-0.54l-1.32,-1.56l-0.48,-0.1l-2.24,1.09l-2.83,2.06l-1.51,1.83l-2.28,0.13l-1.55,1.49l-0.04,0.5l1.32,1.97l2.0,0.58l0.31,1.35l1.98,0.84l3.0,-1.96l2.0,1.02l1.49,0.11l0.22,0.83l-3.37,0.86l-1.12,1.48l-2.5,1.52l-1.29,1.99l0.14,0.56l2.57,1.48l0.97,2.7l3.17,4.63l-0.03,1.66l-1.35,0.65l-0.2,0.51l0.6,1.47l1.4,0.91l-0.89,3.82l-1.43,0.38l-3.85,6.44l-2.27,3.11l-6.78,4.57l-2.73,0.29l-1.45,1.04l-0.62,-0.61l-0.55,-0.01l-1.36,1.25l-3.39,1.27l-2.61,0.4l-1.1,2.79l-0.81,0.09l-0.49,-1.42l0.5,-0.85l-0.25,-0.59l-3.36,-0.84l-1.3,0.4l-2.31,-0.62l-0.94,-0.84l0.33,-1.28l-0.3,-0.49l-2.19,-0.46l-1.13,-0.93l-0.47,-0.02l-2.06,1.36l-4.29,0.28l-2.76,1.05l-0.28,0.43l0.32,2.53l-0.59,-0.03l-0.19,-1.34l-0.55,-0.34l-1.68,0.7l-2.46,-1.23l0.62,-1.87l-0.26,-0.51l-1.37,-0.44l-0.54,-2.22l-0.45,-0.3l-2.13,0.35l0.24,-2.48l2.39,-2.4l0.03,-4.31l-1.19,-0.92l-0.78,-1.49l-0.41,-0.21l-1.41,0.19l-1.98,-0.3l0.46,-1.07l-1.17,-1.7l-0.55,-0.11l-1.63,1.05l-2.25,-0.57l-2.89,1.73l-2.25,1.98l-1.75,0.29l-1.17,-0.71l-3.31,-0.65l-1.48,0.79l-1.04,1.27l-0.12,-1.17l-0.54,-0.34l-1.44,0.54l-5.55,-0.86l-1.98,-1.16l-1.89,-0.54l-0.99,-1.35l-1.34,-0.37l-2.55,-1.79l-2.01,-0.84l-1.21,0.56l-5.57,-3.45l-0.53,-2.31l1.19,0.25l0.48,-0.37l0.08,-1.42l-0.98,-1.56l0.15,-2.44l-2.69,-3.32l-4.12,-1.23l-0.67,-2.0l-1.92,-1.48l-0.38,-0.7l-0.51,-3.01l-1.52,-0.66l-0.7,0.13l-0.48,-2.05l0.55,-0.51l-0.09,-0.82l2.03,-1.19l1.6,-0.54l2.56,0.38l0.42,-0.22l0.85,-1.7l3.0,-0.33l1.1,-1.26l4.05,-1.77l0.39,-0.91l-0.17,-1.44l1.45,-0.67l0.2,-0.52l-2.07,-4.9l4.51,-1.12l1.37,-0.73l1.89,-5.51l4.98,0.86l1.51,-1.7l0.11,-2.87l1.99,-0.38l1.83,-2.06l0.49,-0.13l0.68,2.08l2.23,1.77l3.44,1.16l1.55,2.29l-0.92,3.49l0.96,1.67l6.54,1.13l2.95,1.87l1.47,0.35l1.06,2.62l1.53,1.91l3.05,0.08l5.14,0.67l3.37,-0.41l2.36,0.43l3.65,1.8l3.06,0.04l1.45,0.88l2.87,-1.59l3.95,-1.02l3.83,-0.14l3.06,-1.14l1.77,-1.6l1.72,-1.01l0.17,-0.49l-1.1,-2.05l1.02,-1.54l4.02,0.8l2.45,-1.61l3.76,-1.19l1.96,-2.13l1.63,-0.83l3.51,-0.4l1.92,0.34l0.46,-0.3l0.17,-1.5l-2.27,-2.22l-2.11,-1.09l-2.18,1.11l-2.32,-0.47l-1.29,0.32l-0.4,-0.82l2.73,-5.16l3.02,1.06l3.53,-2.06l0.18,-1.68l2.16,-3.35l1.49,-1.35l-0.03,-1.85l-1.07,-0.85l1.54,-1.26l2.98,-0.59l3.23,-0.09l3.64,0.99l2.04,1.16l3.29,6.71l0.92,3.19ZM696.92,237.31l-1.87,1.08l-1.63,-0.64l-0.06,-1.79l1.03,-0.98l2.58,-0.69l1.16,0.05l0.3,0.54l-0.98,1.06l-0.53,1.37Z", "name": "China"}, "CM": {"path": "M457.92,257.49l1.05,1.91l-1.4,0.16l-1.05,-0.23l-0.45,0.22l-0.54,1.19l0.08,0.45l1.48,1.47l1.05,0.45l1.01,2.46l-1.52,2.99l-0.68,0.68l-0.13,3.69l2.38,3.84l1.09,0.8l0.24,2.48l-3.67,-1.14l-11.27,-0.13l0.23,-1.79l-0.98,-1.66l-1.19,-0.54l-0.44,-0.97l-0.6,-0.42l1.71,-4.27l0.75,-0.13l1.38,-1.36l0.65,-0.03l1.71,0.99l1.93,-1.12l1.14,-3.18l1.38,-1.17l2.0,-5.14l2.17,-2.13l0.3,-1.64l-0.86,-0.88l0.03,-0.33l0.94,1.28l0.07,3.22Z", "name": "Cameroon"}, "CL": {"path": "M246.5,429.18l-3.14,1.83l-0.57,3.16l-0.64,0.05l-2.68,-1.06l-2.82,-2.33l-3.04,-1.89l-0.69,-1.85l0.63,-2.14l-1.21,-2.11l-0.31,-5.37l1.01,-2.91l2.57,-2.38l-0.18,-0.68l-3.16,-0.77l2.05,-2.47l0.77,-4.65l2.32,0.9l0.54,-0.29l1.31,-6.31l-0.22,-0.44l-1.68,-0.8l-0.56,0.28l-0.7,3.36l-0.81,-0.22l1.56,-9.41l1.15,-2.24l-0.71,-2.82l-0.18,-2.84l1.01,-0.33l3.26,-9.14l1.07,-4.22l-0.56,-4.21l0.74,-2.34l-0.29,-3.27l1.46,-3.34l2.04,-16.59l-0.66,-7.76l1.03,-0.53l0.54,-0.9l0.79,1.14l0.32,1.78l1.25,1.16l-0.69,2.55l1.33,2.9l0.97,3.59l0.46,0.29l1.5,-0.3l0.11,0.23l-0.76,2.44l-2.57,1.23l-0.23,0.37l0.08,4.33l-0.46,0.77l0.56,1.21l-1.58,1.51l-1.68,2.62l-0.89,2.47l0.2,2.7l-1.48,2.73l1.12,5.09l0.64,0.61l-0.01,2.29l-1.38,2.68l0.01,2.4l-1.89,2.04l0.02,2.75l0.69,2.57l-1.43,1.13l-1.26,5.68l0.39,3.51l-0.97,0.89l0.58,3.5l1.02,1.14l-0.65,1.02l0.15,0.57l1.0,0.53l0.16,0.69l-1.03,0.85l0.26,1.75l-0.89,4.03l-1.31,2.66l0.24,1.75l-0.71,1.83l-1.99,1.7l0.3,3.67l0.88,1.19l1.58,0.01l0.01,2.21l1.04,1.95l5.98,0.63ZM248.69,430.79l0.0,7.33l0.4,0.4l3.52,0.05l-0.44,0.75l-1.94,0.98l-2.49,-0.37l-1.88,-1.06l-2.55,-0.49l-5.59,-3.71l-2.38,-2.63l4.1,2.48l3.32,1.23l0.45,-0.12l1.29,-1.57l0.83,-2.32l2.05,-1.24l1.31,0.29Z", "name": "Chile"}, "XC": {"path": "M504.91,192.87l0.34,0.01l0.27,-0.07l-0.29,0.26l-0.31,-0.2Z", "name": "N. Cyprus"}, "CA": {"path": "M280.06,145.6l-1.67,2.88l0.07,0.49l0.5,0.04l1.46,-0.98l1.0,0.42l-0.56,0.72l0.17,0.62l2.22,0.89l1.35,-0.71l1.95,0.78l-0.66,2.01l0.5,0.51l1.32,-0.42l0.98,3.17l-0.91,2.41l-0.8,0.08l-1.23,-0.45l0.47,-2.25l-0.89,-0.83l-0.48,0.06l-2.78,2.63l-0.34,-0.02l1.02,-0.85l-0.14,-0.69l-2.4,-0.77l-7.4,0.08l-0.17,-0.41l1.3,-0.94l0.02,-0.64l-0.73,-0.58l1.85,-1.74l2.57,-5.16l1.47,-1.79l1.99,-1.05l0.46,0.06l-1.53,2.45ZM68.32,74.16l4.13,0.95l4.02,2.14l2.61,0.4l2.47,-1.89l2.88,-1.31l3.85,0.48l3.71,-1.94l3.82,-1.04l1.56,1.68l0.49,0.08l1.87,-1.04l0.65,-1.98l1.24,0.35l4.16,3.94l0.54,0.01l2.75,-2.49l0.26,2.59l0.49,0.35l3.08,-0.73l1.04,-1.27l2.73,0.23l3.83,1.86l5.86,1.61l3.47,0.75l2.44,-0.26l2.73,1.78l-2.98,1.81l-0.19,0.41l0.31,0.32l4.53,0.92l6.87,-0.5l2.0,-0.69l2.49,2.39l0.53,0.02l2.72,-2.16l-0.02,-0.64l-2.16,-1.54l1.15,-1.06l4.83,-0.61l1.84,0.95l2.48,2.31l3.01,-0.23l4.55,1.92l3.85,-0.67l3.61,0.1l0.41,-0.44l-0.25,-2.36l1.79,-0.61l3.49,1.32l-0.01,3.77l0.31,0.39l0.45,-0.22l1.48,-3.16l1.74,0.1l0.41,-0.3l1.13,-4.37l-2.78,-3.11l-2.8,-1.74l0.19,-4.64l2.71,-3.07l2.98,0.67l2.41,1.95l3.19,4.8l-1.99,1.97l0.21,0.68l4.33,0.84l-0.01,4.15l0.25,0.37l0.44,-0.09l3.07,-3.15l2.54,2.39l-0.61,3.33l2.42,2.88l0.61,0.0l2.61,-3.08l1.88,-3.82l0.17,-4.58l6.72,0.94l3.13,2.04l0.13,1.82l-1.76,2.19l-0.01,0.49l1.66,2.16l-0.26,1.71l-4.68,2.8l-3.28,0.61l-2.47,-1.2l-0.55,0.23l-0.73,2.04l-2.38,3.43l-0.74,1.77l-2.74,2.57l-3.44,0.25l-2.21,1.78l-0.28,2.53l-2.82,0.55l-3.12,3.22l-2.72,4.31l-1.03,3.17l-0.14,4.31l0.33,0.41l3.44,0.57l2.24,5.95l0.45,0.23l3.4,-0.69l4.52,1.51l2.43,1.31l1.91,1.73l3.1,0.96l2.62,1.46l6.6,0.54l-0.35,2.74l0.81,3.53l1.81,3.78l3.83,3.3l0.45,0.04l2.1,-1.28l1.37,-3.69l-1.31,-5.38l-1.45,-1.58l3.57,-1.47l2.84,-2.46l1.52,-2.8l-0.25,-2.55l-1.7,-3.07l-2.85,-2.61l2.8,-3.95l-1.08,-3.37l-0.79,-5.67l1.36,-0.7l6.76,1.41l2.12,-0.96l5.12,3.36l1.05,1.61l4.08,0.26l-0.06,2.87l0.83,4.7l0.3,0.32l2.16,0.54l1.73,2.06l0.5,0.09l3.63,-2.03l2.52,-4.19l1.26,-1.32l7.6,11.72l-0.92,2.04l0.16,0.51l3.3,1.97l2.22,1.98l4.1,0.98l1.43,0.99l0.95,2.79l2.1,0.68l0.84,1.08l0.17,3.45l-3.37,2.26l-4.22,1.24l-3.06,2.63l-4.06,0.51l-5.35,-0.69l-6.39,0.2l-2.3,2.41l-3.26,1.51l-6.47,7.15l-0.06,0.48l0.44,0.19l2.13,-0.52l4.17,-4.24l5.12,-2.62l3.52,-0.3l1.69,1.21l-2.12,2.21l0.81,3.47l1.02,2.61l3.47,1.6l4.14,-0.45l2.15,-2.8l0.26,1.48l1.14,0.8l-2.56,1.69l-5.5,1.82l-2.54,1.27l-2.74,2.15l-1.4,-0.16l-0.07,-2.01l4.14,-2.44l0.18,-0.45l-0.39,-0.29l-6.63,0.45l-1.39,-1.49l-0.14,-4.43l-1.11,-0.91l-1.82,0.39l-0.66,-0.66l-0.6,0.03l-1.91,2.39l-0.82,2.52l-0.8,1.27l-1.67,0.56l-0.46,0.76l-8.31,0.07l-1.21,0.62l-2.35,1.97l-0.71,-0.14l-1.37,0.96l-1.12,-0.48l-4.74,1.26l-0.9,1.17l0.21,0.62l1.73,0.3l-1.81,0.31l-1.85,0.81l-2.11,-0.13l-2.95,1.78l-0.69,-0.09l1.39,-2.1l1.73,-1.21l0.1,-2.29l1.16,-1.99l0.49,0.53l2.03,0.42l1.2,-1.16l0.02,-0.47l-2.66,-3.51l-2.28,-0.61l-5.64,-0.71l-0.4,-0.57l-0.79,0.13l0.2,-0.41l-0.22,-0.55l-0.68,-0.26l0.19,-1.26l-0.78,-0.73l0.31,-0.64l-0.29,-0.57l-2.6,-0.44l-0.75,-1.63l-0.94,-0.66l-4.31,-0.65l-1.13,1.19l-1.48,0.59l-0.85,1.06l-2.83,-0.76l-2.09,0.39l-2.39,-0.97l-4.24,-0.7l-0.57,-0.4l-0.41,-1.63l-0.4,-0.3l-0.85,0.02l-0.39,0.4l-0.01,0.85l-69.13,-0.01l-6.51,-4.52l-4.5,-1.38l-1.26,-2.66l0.33,-1.93l-0.23,-0.43l-3.01,-1.35l-0.55,-2.77l-2.89,-2.38l-0.04,-1.45l1.39,-1.83l-0.28,-2.55l-4.16,-2.2l-4.07,-6.6l-4.02,-3.22l-1.3,-1.88l-0.5,-0.13l-2.51,1.21l-2.23,1.87l-3.85,-3.88l-2.44,-1.04l-2.22,-0.13l0.03,-37.49ZM260.37,148.65l3.04,0.76l2.26,1.2l-3.78,-0.95l-1.53,-1.01ZM249.4,3.81l6.68,0.49l5.32,0.79l4.26,1.57l-0.07,1.1l-5.85,2.53l-6.02,1.21l-2.39,1.39l-0.18,0.45l0.39,0.29l4.01,-0.02l-4.65,2.82l-4.2,1.74l-4.19,4.59l-5.03,0.92l-1.67,1.15l-7.47,0.59l-0.37,0.37l0.32,0.42l2.41,0.49l-0.81,0.47l-0.12,0.59l1.83,2.41l-2.02,1.59l-3.81,1.51l-1.32,2.16l-3.38,1.53l-0.22,0.48l0.35,1.19l0.4,0.29l3.88,-0.18l0.03,0.61l-6.33,2.95l-6.41,-1.4l-7.43,0.79l-3.72,-0.62l-4.4,-0.25l-0.23,-1.83l4.29,-1.11l0.28,-0.51l-1.1,-3.45l1.0,-0.25l6.58,2.28l0.47,-0.16l-0.05,-0.49l-3.41,-3.45l-3.58,-0.98l1.48,-1.55l4.34,-1.29l0.97,-2.19l-0.16,-0.48l-3.42,-2.13l-0.81,-2.26l6.2,0.22l2.24,0.58l3.91,-2.1l0.2,-0.43l-0.35,-0.32l-5.64,-0.67l-8.73,0.36l-4.26,-1.9l-2.12,-2.4l-2.78,-1.66l-0.41,-1.52l3.31,-1.03l2.93,-0.2l4.91,-0.99l3.7,-2.27l2.87,0.3l2.62,1.67l0.56,-0.14l1.82,-3.2l3.13,-0.94l4.44,-0.69l7.53,-0.26l1.48,0.67l7.19,-1.06l10.8,0.79ZM203.85,57.54l0.01,0.42l1.97,2.97l0.68,-0.02l2.24,-3.72l5.95,-1.86l4.01,4.64l-0.35,2.91l0.5,0.43l4.95,-1.36l2.32,-1.8l5.31,2.28l3.27,2.11l0.3,1.84l0.48,0.33l4.42,-0.99l2.64,2.87l5.97,1.77l2.06,1.72l2.11,3.71l-4.19,1.86l-0.01,0.73l5.9,2.83l3.94,0.94l3.78,3.95l3.46,0.25l-0.63,2.37l-4.11,4.47l-2.76,-1.56l-3.9,-3.94l-3.59,0.41l-0.33,0.34l-0.19,2.72l2.63,2.38l3.42,1.89l0.94,0.97l1.55,3.75l-0.7,2.29l-2.74,-0.92l-6.25,-3.15l-0.51,0.13l0.05,0.52l6.07,5.69l0.18,0.59l-6.09,-1.39l-5.31,-2.24l-2.63,-1.66l0.6,-0.77l-0.12,-0.6l-7.39,-4.01l-0.59,0.37l0.03,0.79l-6.73,0.6l-1.69,-1.1l1.36,-2.46l4.51,-0.07l5.15,-0.52l0.31,-0.6l-0.74,-1.3l0.78,-1.84l3.21,-4.05l-0.67,-2.35l-1.11,-1.6l-3.84,-2.1l-4.35,-1.28l0.91,-0.63l0.06,-0.61l-2.65,-2.75l-2.34,-0.36l-1.89,-1.46l-0.53,0.03l-1.24,1.23l-4.36,0.55l-9.04,-0.99l-9.26,-1.98l-1.6,-1.22l2.22,-1.77l0.13,-0.44l-0.38,-0.27l-3.22,-0.02l-0.72,-4.25l1.83,-4.04l2.42,-1.85l5.5,-1.1l-1.39,2.35ZM261.19,159.33l2.07,0.61l1.44,-0.04l-1.15,0.63l-2.94,-1.23l-0.4,-0.68l0.36,-0.37l0.61,1.07ZM230.83,84.39l-2.37,0.18l-0.49,-1.63l0.93,-2.09l1.94,-0.51l1.62,0.99l0.02,1.52l-1.66,1.54ZM229.43,58.25l0.11,0.65l-4.87,-0.21l-2.72,0.62l-3.1,-2.57l0.08,-1.26l0.86,-0.23l5.57,0.51l4.08,2.5ZM222.0,105.02l-0.72,1.49l-0.63,-0.19l-0.48,-0.84l0.81,-0.99l0.65,0.05l0.37,0.46ZM183.74,38.32l2.9,1.7l4.79,-0.01l1.84,1.46l-0.49,1.68l0.23,0.48l2.82,1.14l1.76,1.26l7.01,0.65l4.1,-1.1l5.03,-0.43l3.93,0.35l2.48,1.77l0.46,1.7l-1.3,1.1l-3.56,1.01l-3.23,-0.59l-7.17,0.76l-5.09,0.09l-3.99,-0.6l-6.42,-1.54l-0.79,-2.51l-0.3,-2.49l-2.64,-2.5l-5.32,-0.72l-2.52,-1.4l0.68,-1.57l4.78,0.31ZM207.38,91.35l0.4,1.56l0.56,0.26l1.06,-0.52l1.32,0.96l5.42,2.57l0.2,1.68l0.46,0.35l1.68,-0.28l1.15,0.85l-1.55,0.87l-3.61,-0.88l-1.32,-1.69l-0.57,-0.06l-2.45,2.1l-3.12,1.79l-0.7,-1.87l-0.42,-0.26l-2.16,0.24l1.39,-1.39l0.32,-3.14l0.76,-3.35l1.18,0.22ZM215.49,102.6l-2.67,1.95l-1.4,-0.07l-0.3,-0.58l1.53,-1.48l2.84,0.18ZM202.7,24.12l2.53,1.59l-2.87,1.4l-4.53,4.05l-4.25,0.38l-5.03,-0.68l-2.45,-2.04l0.03,-1.62l1.82,-1.37l0.14,-0.45l-0.38,-0.27l-4.45,0.04l-2.59,-1.76l-1.41,-2.29l1.57,-2.32l1.62,-1.66l2.44,-0.39l0.25,-0.65l-0.6,-0.74l4.86,-0.25l3.24,3.11l8.16,2.3l1.9,3.61ZM187.47,59.2l-2.76,3.49l-2.38,-0.15l-1.44,-3.84l0.04,-2.2l1.19,-1.88l2.3,-1.23l5.07,0.17l4.11,1.02l-3.24,3.72l-2.88,0.89ZM186.07,48.79l-1.08,1.53l-3.34,-0.34l-2.56,-1.1l1.03,-1.75l3.25,-1.23l1.95,1.58l0.75,1.3ZM185.71,35.32l-5.3,-0.2l-0.32,-0.71l4.31,0.07l1.3,0.84ZM180.68,32.48l-3.34,1.0l-1.79,-1.1l-0.98,-1.87l-0.15,-1.73l4.1,0.53l2.67,1.7l-0.51,1.47ZM180.9,76.31l-1.1,1.08l-3.13,-1.23l-2.12,0.43l-2.71,-1.57l1.72,-1.09l1.55,-1.72l3.81,1.9l1.98,2.2ZM169.74,54.87l2.96,0.97l4.17,-0.57l0.41,0.88l-2.14,2.11l0.09,0.64l3.55,1.92l-0.4,3.72l-3.79,1.65l-2.17,-0.35l-1.72,-1.74l-6.02,-3.5l0.03,-0.85l4.68,0.54l0.4,-0.21l-0.05,-0.45l-2.48,-2.81l2.46,-1.95ZM174.45,40.74l1.37,1.73l0.07,2.44l-1.05,3.45l-3.79,0.47l-2.32,-0.69l0.05,-2.64l-0.44,-0.41l-3.68,0.35l-0.12,-3.1l2.45,0.1l3.67,-1.73l3.41,0.29l0.37,-0.26ZM170.05,31.55l0.67,1.56l-3.33,-0.49l-4.22,-1.77l-4.35,-0.16l1.4,-0.94l-0.06,-0.7l-2.81,-1.23l-0.12,-1.39l4.39,0.68l6.62,1.98l1.81,2.47ZM134.5,58.13l-1.02,1.82l0.45,0.58l5.4,-1.39l3.33,2.29l0.49,-0.03l2.6,-2.23l1.94,1.32l2.0,4.5l0.7,0.06l1.3,-2.29l-1.63,-4.46l1.69,-0.54l2.31,0.71l2.65,1.81l2.49,7.92l8.48,4.27l-0.19,1.35l-3.79,0.33l-0.26,0.67l1.4,1.49l-0.58,1.1l-4.23,-0.64l-4.43,-1.19l-3.0,0.28l-4.66,1.47l-10.52,1.04l-1.43,-2.02l-3.42,-1.2l-2.21,0.43l-2.51,-2.86l4.84,-1.05l3.6,0.19l3.27,-0.78l0.31,-0.39l-0.31,-0.39l-4.84,-1.06l-8.79,0.27l-0.85,-1.07l5.26,-1.66l0.27,-0.45l-0.4,-0.34l-3.8,0.06l-3.81,-1.06l1.81,-3.01l1.66,-1.79l6.48,-2.81l1.97,0.71ZM158.7,56.61l-1.7,2.44l-3.2,-2.75l0.37,-0.3l3.11,-0.18l1.42,0.79ZM149.61,42.73l1.01,1.89l0.5,0.18l2.14,-0.82l2.23,0.19l0.36,2.04l-1.33,2.09l-8.28,0.76l-6.35,2.15l-3.41,0.1l-0.19,-0.96l4.9,-2.08l0.23,-0.46l-0.41,-0.31l-11.25,0.59l-2.89,-0.74l3.04,-4.44l2.14,-1.32l6.81,1.69l4.58,3.06l4.37,0.39l0.36,-0.63l-3.36,-4.6l1.85,-1.53l2.18,0.51l0.77,2.26ZM144.76,34.41l-4.36,1.44l-3.0,-1.4l1.46,-1.24l3.47,-0.52l2.96,0.71l-0.52,1.01ZM145.13,29.83l-1.9,0.66l-3.67,-0.0l2.27,-1.61l3.3,0.95ZM118.92,65.79l-6.03,2.02l-1.33,-1.9l-5.38,-2.28l2.59,-5.05l2.16,-3.14l-0.02,-0.48l-1.97,-2.41l7.64,-0.7l3.6,1.02l6.3,0.27l4.42,2.95l-2.53,0.98l-6.24,3.43l-3.1,3.28l-0.11,2.01ZM129.54,35.53l-0.28,3.37l-1.72,1.62l-2.33,0.28l-4.61,2.19l-3.86,0.76l-2.64,-0.87l3.72,-3.4l5.01,-3.34l3.72,0.07l3.0,-0.67ZM111.09,152.69l-0.67,0.24l-3.85,-1.37l-0.83,-1.17l-2.12,-1.07l-0.66,-1.02l-2.4,-0.55l-0.74,-1.71l6.02,1.45l2.0,2.55l2.52,1.39l0.73,1.27ZM87.8,134.64l0.89,0.29l1.86,-0.21l-0.65,3.34l1.69,2.33l-1.31,-1.33l-0.99,-1.62l-1.17,-0.98l-0.33,-1.82Z", "name": "Canada"}, "CG": {"path": "M466.72,276.48l-0.1,1.03l-1.25,2.97l-0.19,3.62l-0.46,1.78l-0.23,0.63l-1.61,1.19l-1.21,1.39l-1.09,2.43l0.04,2.09l-3.25,3.24l-0.5,-0.24l-0.5,-0.83l-1.36,-0.02l-0.98,0.89l-1.68,-0.99l-1.54,1.24l-1.52,-1.96l1.57,-1.14l0.11,-0.52l-0.77,-1.35l2.1,-0.66l0.39,-0.73l1.05,0.82l2.21,0.11l1.12,-1.37l0.37,-1.81l-0.27,-2.09l-1.13,-1.5l1.0,-2.69l-0.13,-0.45l-0.92,-0.58l-1.6,0.17l-0.51,-0.94l0.1,-0.61l2.75,0.09l3.97,1.24l0.51,-0.33l0.17,-1.28l1.24,-2.21l1.28,-1.14l2.76,0.49Z", "name": "Congo"}, "CF": {"path": "M461.16,278.2l-0.26,-1.19l-1.09,-0.77l-0.84,-1.17l-0.29,-1.0l-1.04,-1.15l0.08,-3.43l0.58,-0.49l1.16,-2.35l1.85,-0.17l0.61,-0.62l0.97,0.58l3.15,-0.96l2.48,-1.92l0.02,-0.96l2.81,0.02l2.36,-1.17l1.93,-2.85l1.16,-0.93l1.11,-0.3l0.27,0.86l1.34,1.47l-0.39,2.01l0.3,1.01l4.01,2.75l0.17,0.93l2.63,2.31l0.6,1.44l2.08,1.4l-3.84,-0.21l-1.94,0.88l-1.23,-0.49l-2.67,1.2l-1.29,-0.18l-0.51,0.36l-0.6,1.22l-3.35,-0.65l-1.57,-0.91l-2.42,-0.83l-1.45,0.91l-0.97,1.27l-0.26,1.56l-3.22,-0.43l-1.49,1.33l-0.94,1.62Z", "name": "Central African Rep."}, "CD": {"path": "M487.01,272.38l2.34,-0.14l1.35,1.84l1.34,0.45l0.86,-0.39l1.21,0.12l1.07,-0.41l0.54,0.89l2.04,1.54l-0.14,2.72l0.7,0.54l-1.38,1.13l-1.53,2.54l-0.17,2.05l-0.59,1.08l-0.02,1.72l-0.72,0.84l-0.66,3.01l0.63,1.32l-0.44,4.26l0.64,1.47l-0.37,1.22l0.86,1.8l1.53,1.41l0.3,1.26l0.44,0.5l-4.08,0.75l-0.92,1.81l0.51,1.34l-0.74,5.43l0.17,0.38l2.45,1.46l0.54,-0.1l0.12,1.62l-1.28,-0.01l-1.85,-2.35l-1.94,-0.45l-0.48,-1.13l-0.55,-0.2l-1.41,0.74l-1.71,-0.3l-1.01,-1.18l-2.49,-0.19l-0.44,-0.77l-1.98,-0.21l-2.88,0.36l0.11,-2.41l-0.85,-1.13l-0.16,-1.36l0.32,-1.73l-0.46,-0.89l-0.04,-1.49l-0.4,-0.39l-2.53,0.02l0.1,-0.41l-0.39,-0.49l-1.28,0.01l-0.43,0.45l-1.62,0.32l-0.83,1.79l-1.09,-0.28l-2.4,0.52l-1.37,-1.91l-1.3,-3.3l-0.38,-0.27l-7.39,-0.03l-2.46,0.42l0.5,-0.45l0.37,-1.47l0.66,-0.38l0.92,0.08l0.73,-0.82l0.87,0.02l0.31,0.68l1.4,0.36l3.59,-3.63l0.01,-2.23l1.02,-2.29l2.69,-2.39l0.43,-0.99l0.49,-1.96l0.17,-3.51l1.25,-2.95l0.36,-3.14l0.86,-1.13l1.1,-0.66l3.57,1.73l3.65,0.73l0.46,-0.21l0.8,-1.46l1.24,0.19l2.61,-1.17l0.81,0.44l1.04,-0.03l0.59,-0.66l0.7,-0.16l1.81,0.25Z", "name": "Dem. Rep. Congo"}, "CZ": {"path": "M458.46,144.88l1.22,1.01l1.47,0.23l0.13,0.93l1.36,0.68l0.54,-0.2l0.24,-0.55l1.15,0.25l0.53,1.09l1.68,0.18l0.6,0.84l-1.04,0.73l-0.96,1.28l-1.6,0.17l-0.55,0.56l-1.04,-0.46l-1.05,0.15l-2.12,-0.96l-1.05,0.34l-1.2,1.12l-1.56,-0.87l-2.57,-2.1l-0.53,-1.88l4.7,-2.52l0.71,0.26l0.9,-0.28Z", "name": "Czech Rep."}, "CY": {"path": "M504.36,193.47l0.43,0.28l-1.28,0.57l-0.92,-0.28l-0.24,-0.46l2.01,-0.13Z", "name": "Cyprus"}, "CR": {"path": "M211.34,258.05l0.48,0.99l1.6,1.6l-0.54,0.45l0.29,1.42l-0.25,1.19l-1.09,-0.59l-0.05,-1.25l-2.46,-1.42l-0.28,-0.77l-0.66,-0.45l-0.45,-0.0l-0.11,1.04l-1.32,-0.95l0.31,-1.3l-0.36,-0.6l0.31,-0.27l1.42,0.58l1.29,-0.14l0.56,0.56l0.74,0.17l0.55,-0.27Z", "name": "Costa Rica"}, "CU": {"path": "M221.21,227.25l1.27,1.02l2.19,-0.28l4.43,3.33l2.08,0.43l-0.1,0.38l0.36,0.5l1.75,0.1l1.48,0.84l-3.11,0.51l-4.15,-0.03l0.77,-0.67l-0.04,-0.64l-1.2,-0.74l-1.49,-0.16l-0.7,-0.61l-0.56,-1.4l-0.4,-0.25l-1.34,0.1l-2.2,-0.66l-0.88,-0.58l-3.18,-0.4l-0.27,-0.16l0.58,-0.74l-0.36,-0.29l-2.72,-0.05l-1.7,1.29l-0.91,0.03l-0.61,0.69l-1.01,0.22l1.11,-1.29l1.01,-0.52l3.69,-1.01l3.98,0.21l2.21,0.84Z", "name": "Cuba"}, "SZ": {"path": "M500.35,351.36l0.5,2.04l-0.38,0.89l-1.05,0.21l-1.23,-1.2l-0.02,-0.64l0.83,-1.57l1.34,0.27Z", "name": "Swaziland"}, "SY": {"path": "M511.0,199.79l0.05,-1.33l0.54,-1.36l1.28,-0.99l0.13,-0.45l-0.41,-1.11l-1.14,-0.36l-0.19,-1.74l0.52,-1.0l1.29,-1.21l0.2,-1.18l0.59,0.23l2.62,-0.76l1.36,0.52l2.06,-0.01l2.95,-1.08l3.25,-0.26l-0.67,0.94l-1.28,0.66l-0.21,0.4l0.23,2.01l-0.88,3.19l-10.15,5.73l-2.15,-0.85Z", "name": "Syria"}, "KG": {"path": "M621.35,172.32l-3.87,1.69l-0.96,1.18l-3.04,0.34l-1.13,1.86l-2.36,-0.35l-1.99,0.63l-2.39,1.4l0.06,0.95l-0.4,0.37l-4.52,0.43l-3.02,-0.93l-2.37,0.17l0.11,-0.79l2.32,0.42l1.13,-0.88l1.99,0.2l3.21,-2.14l-0.03,-0.69l-2.97,-1.57l-1.94,0.65l-1.22,-0.74l1.71,-1.58l-0.12,-0.67l-0.36,-0.15l0.32,-0.77l1.36,-0.35l4.02,1.02l0.49,-0.3l0.35,-1.59l1.09,-0.48l3.42,1.22l1.11,-0.31l7.64,0.39l1.16,1.0l1.23,0.39Z", "name": "Kyrgyzstan"}, "KE": {"path": "M506.26,284.69l1.87,-2.56l0.93,-2.15l-1.38,-4.08l-1.06,-1.6l2.82,-2.75l0.79,0.26l0.12,1.41l0.86,0.83l1.9,0.11l3.28,2.13l3.57,0.44l1.05,-1.12l1.96,-0.9l0.82,0.68l1.16,0.09l-1.78,2.45l0.03,9.12l1.3,1.94l-1.37,0.78l-0.67,1.03l-1.08,0.46l-0.34,1.67l-0.81,1.07l-0.45,1.55l-0.68,0.56l-3.2,-2.23l-0.35,-1.58l-8.86,-4.98l0.14,-1.6l-0.57,-1.04Z", "name": "Kenya"}, "SS": {"path": "M481.71,263.34l1.07,-0.72l1.2,-3.18l1.36,-0.26l1.61,1.99l0.87,0.34l1.1,-0.41l1.5,0.07l0.57,0.53l2.49,0.0l0.44,-0.63l1.07,-0.4l0.45,-0.84l0.59,-0.33l1.9,1.33l1.6,-0.2l2.83,-3.33l-0.32,-2.21l1.59,-0.52l-0.24,1.6l0.3,1.83l1.35,1.18l0.2,1.87l0.35,0.41l0.02,1.53l-0.23,0.47l-1.42,0.25l-0.85,1.44l0.3,0.6l1.4,0.16l1.11,1.08l0.59,1.13l1.03,0.53l1.28,2.36l-4.41,3.98l-1.74,0.01l-1.89,0.55l-1.47,-0.52l-1.15,0.57l-2.96,-2.62l-1.3,0.49l-1.06,-0.15l-0.79,0.39l-0.82,-0.22l-1.8,-2.7l-1.91,-1.1l-0.66,-1.5l-2.62,-2.32l-0.18,-0.94l-2.37,-1.6Z", "name": "S. Sudan"}, "SR": {"path": "M283.12,270.19l2.1,0.53l-1.08,1.95l0.2,1.72l0.93,1.49l-0.59,2.03l-0.43,0.71l-1.12,-0.42l-1.32,0.22l-0.93,-0.2l-0.46,0.26l-0.25,0.73l0.33,0.7l-0.89,-0.13l-1.39,-1.97l-0.31,-1.34l-0.97,-0.31l-0.89,-1.47l0.35,-1.61l1.45,-0.82l0.33,-1.87l2.61,0.44l0.57,-0.47l1.75,-0.16Z", "name": "Suriname"}, "KH": {"path": "M689.52,249.39l0.49,1.45l-0.28,2.74l-4.0,1.86l-0.16,0.6l0.68,0.95l-2.06,0.17l-2.05,0.97l-1.82,-0.32l-2.12,-3.7l-0.55,-2.85l1.4,-1.85l3.02,-0.45l2.23,0.35l2.01,0.98l0.51,-0.14l0.95,-1.48l1.74,0.74Z", "name": "Cambodia"}, "SV": {"path": "M195.8,250.13l1.4,-1.19l2.24,1.45l0.98,-0.27l0.44,0.2l-0.27,1.05l-1.14,-0.03l-3.64,-1.21Z", "name": "El Salvador"}, "SK": {"path": "M476.82,151.17l-1.14,1.9l-2.73,-0.92l-0.82,0.2l-0.74,0.8l-3.46,0.73l-0.47,0.69l-1.76,0.33l-1.88,-1.0l-0.18,-0.81l0.38,-0.75l1.87,-0.32l1.74,-1.89l0.83,0.16l0.79,-0.34l1.51,1.04l1.34,-0.63l1.25,0.3l1.65,-0.42l1.81,0.95Z", "name": "Slovakia"}, "KR": {"path": "M737.51,185.84l0.98,-0.1l0.87,-1.17l2.69,-0.32l0.33,-0.29l1.76,2.79l0.58,1.76l0.02,3.12l-0.8,1.32l-2.21,0.55l-1.93,1.13l-1.8,0.19l-0.2,-1.1l0.43,-2.28l-0.95,-2.56l1.43,-0.37l0.23,-0.62l-1.43,-2.06Z", "name": "Korea"}, "SI": {"path": "M456.18,162.07l-0.51,-1.32l0.18,-1.05l1.69,0.2l1.42,-0.71l2.09,-0.07l0.62,-0.51l0.21,0.47l-1.61,0.67l-0.44,1.34l-0.66,0.24l-0.26,0.82l-1.22,-0.49l-0.84,0.46l-0.69,-0.04Z", "name": "Slovenia"}, "KP": {"path": "M736.77,185.16l-0.92,-0.42l-0.88,0.62l-1.21,-0.88l0.96,-1.15l0.59,-2.59l-0.46,-0.74l-2.09,-0.77l1.64,-1.52l2.72,-1.58l1.58,-1.91l1.11,0.78l2.17,0.11l0.41,-0.5l-0.3,-1.22l3.52,-1.18l0.94,-1.4l0.98,1.08l-2.19,2.18l0.01,2.14l-1.06,0.54l-1.41,1.4l-1.7,0.52l-1.25,1.09l-0.14,1.98l0.94,0.45l1.15,1.04l-0.13,0.26l-2.6,0.29l-1.13,1.29l-1.22,0.08Z", "name": "Dem. Rep. Korea"}, "KW": {"path": "M540.81,207.91l0.37,0.86l-0.17,0.76l0.6,1.53l-0.95,0.04l-0.82,-1.28l-1.57,-0.18l1.31,-1.88l1.22,0.17Z", "name": "Kuwait"}, "SN": {"path": "M390.09,248.21l0.12,1.55l0.49,1.46l0.96,0.82l0.05,1.28l-1.26,-0.19l-0.75,0.33l-1.84,-0.61l-5.84,-0.13l-2.54,0.51l-0.22,-1.03l1.77,0.04l2.01,-0.91l1.03,0.48l1.09,0.04l1.29,-0.62l0.14,-0.58l-0.51,-0.74l-1.81,0.25l-1.13,-0.63l-0.79,0.04l-0.72,0.61l-2.31,0.06l-0.92,-1.77l-0.81,-0.64l0.64,-0.35l2.46,-3.74l1.04,0.19l1.38,-0.56l1.19,-0.02l2.72,1.37l3.03,3.48Z", "name": "Senegal"}, "SL": {"path": "M394.46,264.11l-1.73,1.98l-0.58,1.33l-2.07,-1.06l-1.22,-1.26l-0.65,-2.39l1.16,-0.96l0.67,-1.17l1.21,-0.52l1.66,0.0l1.03,1.64l0.52,2.41Z", "name": "Sierra Leone"}, "KZ": {"path": "M552.8,172.89l0.46,-1.27l-0.48,-1.05l-2.96,-1.19l-1.06,-2.58l-1.37,-0.87l-0.03,-0.3l1.95,0.23l0.45,-0.38l0.08,-1.96l1.75,-0.41l2.1,0.45l0.48,-0.33l0.45,-3.04l-0.45,-2.09l-0.41,-0.31l-2.42,0.15l-2.36,-0.73l-2.87,1.37l-2.17,0.61l-0.85,-0.34l0.13,-1.61l-1.6,-2.12l-2.02,-0.08l-1.78,-1.82l1.29,-2.18l-0.57,-0.95l1.62,-2.91l2.21,1.63l0.63,-0.27l0.29,-2.22l4.92,-3.43l3.71,-0.08l8.4,3.6l2.92,-1.36l3.77,-0.06l3.11,1.66l0.51,-0.11l0.6,-0.81l3.31,0.13l0.39,-0.25l0.63,-1.57l-0.17,-0.5l-3.5,-1.98l1.87,-1.27l-0.13,-1.03l1.98,-0.72l0.18,-0.62l-1.59,-2.06l0.81,-0.82l9.23,-1.18l1.33,-0.88l6.18,-1.26l2.26,-1.42l4.08,0.68l0.73,3.33l0.51,0.3l2.48,-0.8l2.79,1.02l-0.17,1.56l0.43,0.44l2.55,-0.24l4.89,-2.53l0.03,0.32l3.15,2.61l5.56,8.47l0.65,0.02l1.12,-1.46l3.15,1.74l3.76,-0.78l1.15,0.49l1.14,1.8l1.84,0.76l0.99,1.29l3.35,-0.25l1.02,1.52l-1.6,1.81l-1.93,0.28l-0.34,0.38l-0.11,3.05l-1.13,1.16l-4.75,-1.0l-0.46,0.27l-1.76,5.47l-1.1,0.59l-4.91,1.23l-0.27,0.54l2.1,4.97l-1.37,0.63l-0.23,0.41l0.13,1.13l-0.88,-0.25l-1.42,-1.13l-7.89,-0.4l-0.92,0.31l-3.73,-1.22l-1.42,0.63l-0.53,1.66l-3.72,-0.94l-1.85,0.43l-0.76,1.4l-4.65,2.62l-1.13,2.08l-0.44,0.01l-0.92,-1.4l-2.87,-0.09l-0.45,-2.14l-0.38,-0.32l-0.8,-0.01l0.0,-2.96l-3.0,-2.22l-7.31,0.58l-2.35,-2.68l-6.71,-3.69l-6.45,1.83l-0.29,0.39l0.1,10.85l-0.7,0.08l-1.62,-2.17l-1.83,-0.96l-3.11,0.59l-0.64,0.51Z", "name": "Kazakhstan"}, "SA": {"path": "M537.53,210.34l2.0,0.24l0.9,1.32l1.49,-0.06l0.87,2.08l1.29,0.76l0.51,0.99l1.56,1.03l-0.1,1.9l0.32,0.9l1.58,2.47l0.76,0.53l0.7,-0.04l1.68,4.23l7.53,1.33l0.51,-0.29l0.77,1.25l-1.55,4.87l-7.29,2.52l-7.3,1.03l-2.34,1.17l-1.88,2.74l-0.76,0.28l-0.82,-0.78l-0.91,0.12l-2.88,-0.51l-3.51,0.25l-0.86,-0.56l-0.57,0.15l-0.66,1.27l0.16,1.11l-0.43,0.32l-0.93,-1.4l-0.33,-1.16l-1.23,-0.88l-1.27,-2.06l-0.78,-2.22l-1.73,-1.79l-1.14,-0.48l-1.54,-2.31l-0.21,-3.41l-1.44,-2.93l-1.27,-1.16l-1.33,-0.57l-1.31,-3.37l-0.77,-0.67l-0.97,-1.97l-2.8,-4.03l-1.06,-0.17l0.37,-1.96l0.2,-0.72l2.74,0.3l1.08,-0.84l0.6,-0.94l1.74,-0.35l0.65,-1.03l0.71,-0.4l0.1,-0.62l-2.06,-2.28l4.39,-1.22l0.48,-0.37l2.77,0.69l3.66,1.9l7.03,5.5l4.87,0.3Z", "name": "Saudi Arabia"}, "SE": {"path": "M480.22,89.3l-4.03,1.17l-2.43,2.86l0.26,2.57l-8.77,6.64l-1.78,5.79l1.78,2.68l2.22,1.96l-2.07,3.77l-2.72,1.13l-0.95,6.04l-1.29,3.01l-2.74,-0.31l-0.4,0.22l-1.31,2.59l-2.34,0.13l-0.75,-3.09l-2.08,-4.03l-1.83,-4.96l1.0,-1.93l2.14,-2.7l0.83,-4.45l-1.6,-2.17l-0.15,-4.94l1.48,-3.39l2.58,-0.15l0.87,-1.59l-0.78,-1.57l3.76,-5.59l4.04,-7.48l2.17,0.01l0.39,-0.29l0.57,-2.07l4.37,0.64l0.46,-0.34l0.33,-2.56l1.1,-0.13l6.94,4.87l0.06,6.32l0.66,1.36Z", "name": "Sweden"}, "SD": {"path": "M505.98,259.4l-0.34,-0.77l-1.17,-0.9l-0.26,-1.61l0.29,-1.81l-0.34,-0.46l-1.16,-0.17l-0.54,0.59l-1.23,0.11l-0.28,0.65l0.53,0.65l0.17,1.22l-2.44,3.0l-0.96,0.19l-2.39,-1.4l-0.95,0.52l-0.38,0.78l-1.11,0.41l-0.29,0.5l-1.94,0.0l-0.54,-0.52l-1.81,-0.09l-0.95,0.4l-2.45,-2.35l-2.07,0.54l-0.73,1.26l-0.6,2.1l-1.25,0.58l-0.75,-0.62l0.27,-2.65l-1.48,-1.78l-0.22,-1.48l-0.92,-0.96l-0.02,-1.29l-0.57,-1.16l-0.68,-0.16l0.69,-1.29l-0.18,-1.14l0.65,-0.62l0.03,-0.55l-0.36,-0.41l1.55,-2.97l1.91,0.16l0.43,-0.4l-0.1,-10.94l2.49,-0.01l0.4,-0.4l-0.0,-4.82l29.02,0.0l0.64,2.04l-0.49,0.66l0.36,2.69l0.93,3.16l2.12,1.55l-0.89,1.04l-1.72,0.39l-0.98,0.9l-1.43,5.65l0.24,1.15l-0.38,2.06l-0.96,2.38l-1.53,1.31l-1.32,2.91l-1.22,0.86l-0.37,1.34Z", "name": "Sudan"}, "DO": {"path": "M241.8,239.2l0.05,-0.65l-0.46,-0.73l0.42,-0.44l0.19,-1.0l-0.09,-1.53l1.66,0.01l1.99,0.63l0.33,0.67l1.28,0.19l0.33,0.76l1.0,0.08l0.8,0.62l-0.45,0.51l-1.13,-0.47l-1.88,-0.01l-1.27,0.59l-0.75,-0.55l-1.01,0.54l-0.79,1.4l-0.23,-0.61Z", "name": "Dominican Rep."}, "DJ": {"path": "M528.43,256.18l-0.45,0.66l-0.58,-0.25l-1.51,0.13l-0.18,-1.01l1.45,-1.95l0.83,0.17l0.77,-0.44l0.2,1.0l-1.2,0.51l-0.06,0.7l0.73,0.47Z", "name": "Djibouti"}, "DK": {"path": "M452.28,129.07l-1.19,2.24l-2.13,-1.6l-0.23,-0.95l2.98,-0.95l0.57,1.26ZM447.74,126.31l-0.26,0.57l-0.88,-0.07l-1.8,2.53l0.48,1.69l-1.09,0.36l-1.61,-0.39l-0.89,-1.69l-0.07,-3.43l0.96,-1.73l2.02,-0.2l1.09,-1.07l1.33,-0.67l-0.05,1.06l-0.73,1.41l0.3,1.0l1.2,0.64Z", "name": "Denmark"}, "DE": {"path": "M453.14,155.55l-0.55,-0.36l-1.2,-0.1l-1.87,0.57l-2.13,-0.13l-0.56,0.63l-0.86,-0.6l-0.96,0.09l-2.57,-0.93l-0.85,0.67l-1.47,-0.02l0.24,-1.75l1.23,-2.14l-0.28,-0.59l-3.52,-0.58l-0.92,-0.66l0.12,-1.2l-0.48,-0.88l0.27,-2.17l-0.37,-3.03l1.41,-0.22l0.63,-1.26l0.66,-3.19l-0.41,-1.18l0.26,-0.39l1.66,-0.15l0.33,0.54l0.62,0.07l1.7,-1.69l-0.54,-3.02l1.37,0.33l1.31,-0.37l0.31,1.18l2.25,0.71l-0.02,0.92l0.5,0.4l2.55,-0.65l1.34,-0.87l2.57,1.24l1.06,0.98l0.48,1.44l-0.57,0.74l-0.0,0.48l0.87,1.15l0.57,1.64l-0.14,1.29l0.82,1.7l-1.5,-0.07l-0.56,0.57l-4.47,2.15l-0.22,0.54l0.68,2.26l2.58,2.16l-0.66,1.11l-0.79,0.36l-0.23,0.43l0.32,1.87Z", "name": "Germany"}, "YE": {"path": "M528.27,246.72l0.26,-0.42l-0.22,-1.01l0.19,-1.5l0.92,-0.69l-0.07,-1.35l0.39,-0.75l1.01,0.47l3.34,-0.27l3.76,0.41l0.95,0.81l1.36,-0.58l1.74,-2.62l2.18,-1.09l6.86,-0.94l2.48,5.41l-1.64,0.76l-0.56,1.9l-6.23,2.16l-2.29,1.8l-1.93,0.05l-1.41,1.02l-4.24,0.74l-1.72,1.49l-3.28,0.19l-0.52,-1.18l0.02,-1.51l-1.34,-3.29Z", "name": "Yemen"}, "DZ": {"path": "M441.46,188.44l-0.32,1.07l0.39,2.64l-0.54,2.16l-1.58,1.82l0.37,2.39l1.91,1.55l0.18,0.8l1.42,1.03l1.84,7.23l0.12,1.16l-0.57,5.0l0.2,1.51l-0.87,0.99l-0.02,0.51l1.41,1.86l0.14,1.2l0.89,1.48l0.5,0.16l0.98,-0.41l1.73,1.08l0.82,1.23l-8.22,4.81l-7.23,5.11l-3.43,1.13l-2.3,0.21l-0.28,-1.59l-2.56,-1.09l-0.67,-1.25l-26.12,-17.86l0.01,-3.47l3.77,-1.88l2.44,-0.41l2.12,-0.75l1.08,-1.42l2.81,-1.05l0.35,-2.08l1.33,-0.29l1.04,-0.94l3.47,-0.69l0.46,-1.08l-0.1,-0.45l-0.58,-0.52l-0.82,-2.81l-0.19,-1.83l-0.78,-1.49l2.03,-1.31l2.63,-0.48l1.7,-1.22l2.31,-0.84l8.24,-0.73l1.49,0.38l2.28,-1.1l2.46,-0.02l0.92,0.6l1.35,-0.05Z", "name": "Algeria"}, "US": {"path": "M892.72,99.2l1.31,0.53l1.41,-0.37l1.89,0.98l1.89,0.42l-1.32,0.58l-2.9,-1.53l-2.08,0.22l-0.26,-0.15l0.07,-0.67ZM183.22,150.47l0.37,1.47l1.12,0.85l4.23,0.7l2.39,0.98l2.17,-0.38l1.85,0.5l-1.55,0.65l-3.49,2.61l-0.16,0.77l0.5,0.39l2.33,-0.61l1.77,1.02l5.15,-2.4l-0.31,0.65l0.25,0.56l1.36,0.38l1.71,1.16l4.7,-0.88l0.67,0.85l1.31,0.21l0.58,0.58l-1.34,0.17l-2.18,-0.32l-3.6,0.89l-2.71,3.25l0.35,0.9l0.59,-0.0l0.55,-0.6l-1.36,4.65l0.29,3.09l0.67,1.58l0.61,0.45l1.77,-0.44l1.6,-1.96l0.14,-2.21l-0.82,-1.96l0.11,-1.13l1.19,-2.37l0.44,-0.33l0.48,0.75l0.4,-0.29l0.4,-1.37l0.6,-0.47l0.24,-0.8l1.69,0.49l1.65,1.08l-0.03,2.37l-1.27,1.13l-0.0,1.13l0.87,0.36l1.66,-1.29l0.5,0.17l0.5,2.6l-2.49,3.75l0.17,0.61l1.54,0.62l1.48,0.17l1.92,-0.44l4.72,-2.15l2.16,-1.8l-0.05,-1.24l0.75,-0.22l3.92,0.36l2.12,-1.05l0.21,-0.4l-0.28,-1.48l3.27,-2.4l8.32,-0.02l0.56,-0.82l1.9,-0.77l0.93,-1.51l0.74,-2.37l1.58,-1.98l0.92,0.62l1.47,-0.47l0.8,0.66l-0.0,4.09l1.96,2.6l-2.34,1.31l-5.37,2.09l-1.83,2.72l0.02,1.79l0.83,1.59l0.54,0.23l-6.19,0.94l-2.2,0.89l-0.23,0.48l0.45,0.29l2.99,-0.46l-2.19,0.56l-1.13,0.0l-0.15,-0.32l-0.48,0.08l-0.76,0.82l0.22,0.67l0.32,0.06l-0.41,1.62l-1.27,1.58l-1.48,-1.07l-0.49,-0.04l-0.16,0.46l0.52,1.58l0.61,0.59l0.03,0.79l-0.95,1.38l-1.21,-1.22l-0.27,-2.27l-0.35,-0.35l-0.42,0.25l-0.48,1.27l0.33,1.41l-0.97,-0.27l-0.48,0.24l0.18,0.5l1.52,0.83l0.1,2.52l0.79,0.51l0.52,3.42l-1.42,1.88l-2.47,0.8l-1.71,1.66l-1.31,0.25l-1.27,1.03l-0.43,0.99l-2.69,1.78l-2.64,3.03l-0.45,2.12l0.45,2.08l0.85,2.38l1.09,1.9l0.04,1.2l1.16,3.06l-0.18,2.69l-0.55,1.43l-0.47,0.21l-0.89,-0.23l-0.49,-1.18l-0.87,-0.56l-2.75,-5.16l0.48,-1.68l-0.72,-1.78l-2.01,-2.38l-1.12,-0.53l-2.72,1.18l-1.47,-1.35l-1.57,-0.68l-2.99,0.31l-2.17,-0.3l-2.0,0.19l-1.15,0.46l-0.19,0.58l0.39,0.63l0.14,1.34l-0.84,-0.2l-0.84,0.46l-1.58,-0.07l-2.08,-1.44l-2.09,0.33l-1.91,-0.62l-3.73,0.84l-2.39,2.07l-2.54,1.22l-1.45,1.41l-0.61,1.38l0.34,3.71l-0.29,0.02l-3.5,-1.33l-1.25,-3.11l-1.44,-1.5l-2.24,-3.56l-1.76,-1.09l-2.27,-0.01l-1.71,2.07l-1.76,-0.69l-1.16,-0.74l-1.52,-2.98l-3.93,-3.16l-4.34,-0.0l-0.4,0.4l-0.0,0.74l-6.5,0.02l-9.02,-3.14l-0.34,-0.71l-5.7,0.49l-0.43,-1.29l-1.62,-1.61l-1.14,-0.38l-0.55,-0.88l-1.28,-0.13l-1.01,-0.77l-2.22,-0.27l-0.43,-0.3l-0.36,-1.58l-2.4,-2.83l-2.01,-3.85l-0.06,-0.9l-2.92,-3.26l-0.33,-2.29l-1.3,-1.66l0.52,-2.37l-0.09,-2.57l-0.78,-2.3l0.95,-2.82l0.61,-5.68l-0.47,-4.27l-1.46,-4.08l3.19,0.79l1.26,2.83l0.69,0.08l0.69,-1.14l-1.1,-4.79l68.76,-0.0l0.4,-0.4l0.14,-0.86ZM32.44,67.52l1.73,1.97l0.55,0.05l0.99,-0.79l3.65,0.24l-0.09,0.62l0.32,0.45l3.83,0.77l2.61,-0.43l5.19,1.4l4.84,0.43l1.89,0.57l3.42,-0.7l6.14,1.87l-0.03,38.06l0.38,0.4l2.39,0.11l2.31,0.98l3.9,3.99l0.55,0.04l2.4,-2.03l2.16,-1.04l1.2,1.71l3.95,3.14l4.09,6.63l4.2,2.29l0.06,1.83l-1.02,1.23l-1.16,-1.08l-2.04,-1.03l-0.67,-2.89l-3.28,-3.03l-1.65,-3.57l-6.35,-0.32l-2.82,-1.01l-5.26,-3.85l-6.77,-2.04l-3.53,0.3l-4.81,-1.69l-3.25,-1.63l-2.78,0.8l-0.28,0.46l0.44,2.21l-3.91,0.96l-2.26,1.27l-2.3,0.65l-0.27,-1.65l1.05,-3.42l2.49,-1.09l0.16,-0.6l-0.69,-0.96l-0.55,-0.1l-3.19,2.12l-1.78,2.56l-3.55,2.61l-0.04,0.61l1.56,1.52l-2.07,2.29l-5.11,2.57l-0.77,1.66l-3.76,1.77l-0.92,1.73l-2.69,1.38l-1.81,-0.22l-6.95,3.32l-3.97,0.91l4.85,-2.5l2.59,-1.86l3.26,-0.52l1.19,-1.4l3.42,-2.1l2.59,-2.27l0.42,-2.68l1.23,-2.1l-0.04,-0.46l-0.45,-0.11l-2.68,1.03l-0.63,-0.49l-0.53,0.03l-1.05,1.04l-1.36,-1.54l-0.66,0.08l-0.32,0.62l-0.58,-1.14l-0.56,-0.16l-2.41,1.42l-1.07,-0.0l-0.17,-1.75l0.3,-1.71l-1.61,-1.33l-3.41,0.59l-1.96,-1.63l-1.57,-0.84l-0.15,-2.21l-1.7,-1.43l0.82,-1.88l1.99,-2.12l0.88,-1.92l1.71,-0.24l2.04,0.51l1.87,-1.77l1.91,0.25l1.91,-1.23l0.17,-0.43l-0.47,-1.82l-1.07,-0.7l1.39,-1.17l0.12,-0.45l-0.39,-0.26l-1.65,0.07l-2.66,0.88l-0.75,0.78l-1.92,-0.8l-3.46,0.44l-3.44,-0.91l-1.06,-1.61l-2.65,-1.99l2.91,-1.43l5.5,-2.0l1.52,0.0l-0.26,1.62l0.41,0.46l5.29,-0.16l0.3,-0.65l-2.03,-2.59l-3.14,-1.68l-1.79,-2.12l-2.4,-1.83l-3.09,-1.24l1.04,-1.69l4.23,-0.14l3.36,-2.07l0.73,-2.27l2.39,-1.99l2.42,-0.52l4.65,-1.97l2.46,0.23l3.71,-2.35l3.5,0.89ZM37.6,123.41l-2.25,1.23l-0.95,-0.69l-0.29,-1.24l3.21,-1.63l1.42,0.21l0.67,0.7l-1.8,1.42ZM31.06,234.03l0.98,0.47l0.74,0.87l-1.77,1.07l-0.44,-1.53l0.49,-0.89ZM29.34,232.07l0.18,0.05l0.08,0.05l-0.16,0.03l-0.11,-0.14ZM25.16,230.17l0.05,-0.03l0.18,0.22l-0.13,-0.01l-0.1,-0.18ZM5.89,113.26l-1.08,0.41l-2.21,-1.12l1.53,-0.4l1.62,0.28l0.14,0.83Z", "name": "United States"}, "UY": {"path": "M286.85,372.74l-0.92,1.5l-2.59,1.44l-1.69,-0.52l-1.42,0.26l-2.39,-1.19l-1.52,0.08l-1.27,-1.3l0.16,-1.5l0.56,-0.79l-0.02,-2.73l1.21,-4.74l1.19,-0.21l2.37,2.0l1.08,0.03l4.36,3.17l1.22,1.6l-0.96,1.5l0.61,1.4Z", "name": "Uruguay"}, "LB": {"path": "M510.37,198.01l-0.88,0.51l1.82,-3.54l0.62,0.08l0.22,0.61l-1.13,0.88l-0.65,1.47Z", "name": "Lebanon"}, "LA": {"path": "M689.54,248.53l-1.76,-0.74l-0.49,0.15l-0.94,1.46l-1.32,-0.64l0.62,-0.98l0.11,-2.17l-2.04,-2.42l-0.25,-2.65l-1.9,-2.1l-2.15,-0.31l-0.78,0.91l-1.12,0.06l-1.05,-0.4l-2.06,1.2l-0.04,-1.59l0.61,-2.68l-0.36,-0.49l-1.35,-0.1l-0.11,-1.23l-0.96,-0.88l1.96,-1.89l0.39,0.36l1.33,0.07l0.42,-0.45l-0.34,-2.66l0.7,-0.21l1.28,1.81l1.11,2.35l0.36,0.23l2.82,0.02l0.71,1.67l-1.39,0.65l-0.72,0.93l0.13,0.6l2.91,1.51l3.6,5.25l1.88,1.78l0.56,1.62l-0.35,1.96Z", "name": "Lao PDR"}, "TW": {"path": "M724.01,226.68l-0.74,1.48l-0.9,-1.52l-0.25,-1.74l1.38,-2.44l1.73,-1.74l0.64,0.44l-1.85,5.52Z", "name": "Taiwan"}, "TT": {"path": "M266.64,259.32l0.28,-1.16l1.13,-0.22l-0.06,1.2l-1.35,0.18Z", "name": "Trinidad and Tobago"}, "TR": {"path": "M513.21,175.47l3.64,1.17l3.05,-0.44l2.1,0.26l3.11,-1.56l2.46,-0.13l2.19,1.33l0.33,0.82l-0.22,1.33l0.25,0.44l2.28,1.13l-1.17,0.57l-0.21,0.45l0.75,3.2l-0.41,1.16l1.13,1.92l-0.55,0.22l-0.9,-0.67l-2.91,-0.37l-1.24,0.46l-4.23,0.41l-2.81,1.05l-1.91,0.01l-1.52,-0.53l-2.58,0.75l-0.66,-0.45l-0.62,0.3l-0.12,1.45l-0.89,0.84l-0.47,-0.67l0.79,-1.3l-0.41,-0.2l-1.43,0.23l-2.0,-0.63l-2.02,1.65l-3.51,0.3l-2.13,-1.53l-2.7,-0.1l-0.86,1.24l-1.38,0.27l-2.29,-1.44l-2.71,-0.01l-1.37,-2.65l-1.68,-1.52l1.07,-1.99l-0.09,-0.49l-1.27,-1.12l2.37,-2.41l3.7,-0.11l1.28,-2.24l4.49,0.37l3.21,-1.97l2.81,-0.82l3.99,-0.06l4.29,2.07ZM488.79,176.72l-1.72,1.31l-0.5,-0.88l1.37,-2.57l-0.7,-0.85l1.7,-0.63l1.8,0.34l0.46,1.17l1.76,0.78l-2.87,0.32l-1.3,1.01Z", "name": "Turkey"}, "LK": {"path": "M624.16,268.99l-1.82,0.48l-0.99,-1.67l-0.42,-3.46l0.95,-3.43l1.21,0.98l2.26,4.19l-0.34,2.33l-0.85,0.58Z", "name": "Sri Lanka"}, "LV": {"path": "M489.16,122.85l0.96,0.66l0.22,1.65l0.68,1.76l-3.65,1.7l-2.23,-1.58l-1.29,-0.26l-0.68,-0.77l-2.42,0.34l-4.16,-0.23l-2.47,0.9l0.06,-1.98l1.13,-2.06l1.95,-1.02l2.12,2.58l2.01,-0.07l0.38,-0.33l0.44,-2.52l1.76,-0.53l3.06,1.7l2.15,0.07Z", "name": "Latvia"}, "LT": {"path": "M486.93,129.3l0.17,1.12l-1.81,0.98l-0.72,2.02l-2.47,1.18l-2.1,-0.02l-0.73,-1.05l-1.06,-0.3l-0.09,-1.87l-3.56,-1.13l-0.43,-2.36l2.48,-0.94l4.12,0.22l2.25,-0.31l0.52,0.69l1.24,0.21l2.19,1.56Z", "name": "Lithuania"}, "LU": {"path": "M436.08,149.45l-0.48,-0.07l0.3,-1.28l0.27,0.4l-0.09,0.96Z", "name": "Luxembourg"}, "LR": {"path": "M399.36,265.97l0.18,1.54l-0.48,0.99l0.08,0.47l2.47,1.8l-0.33,2.8l-2.65,-1.13l-5.78,-4.61l0.58,-1.32l2.1,-2.33l0.86,-0.22l0.77,1.14l-0.14,0.85l0.59,0.87l1.0,0.14l0.76,-0.99Z", "name": "Liberia"}, "LS": {"path": "M491.06,363.48l-0.49,0.15l-1.49,-1.67l1.1,-1.43l2.19,-1.44l1.51,1.27l-0.98,1.82l-1.23,0.38l-0.62,0.93Z", "name": "Lesotho"}, "TH": {"path": "M670.27,255.86l-1.41,3.87l0.15,2.0l0.38,0.36l1.38,0.07l0.9,2.04l0.55,2.34l1.4,1.44l1.61,0.38l0.96,0.97l-0.5,0.64l-1.1,0.2l-0.34,-1.18l-2.04,-1.1l-0.63,0.23l-0.63,-0.62l-0.48,-1.3l-2.56,-2.63l-0.73,0.41l0.95,-3.89l2.16,-4.22ZM670.67,254.77l-0.92,-2.18l-0.26,-2.61l-2.14,-3.06l0.71,-0.49l0.89,-2.59l-3.61,-5.45l0.87,-0.51l1.05,-2.58l1.74,-0.18l2.6,-1.59l0.76,0.56l0.13,1.39l0.37,0.36l1.23,0.09l-0.51,2.28l0.05,2.42l0.6,0.34l2.43,-1.42l0.77,0.39l1.47,-0.07l0.71,-0.88l1.48,0.14l1.71,1.88l0.25,2.65l1.92,2.11l-0.1,1.89l-0.61,0.86l-2.22,-0.33l-3.5,0.64l-1.6,2.12l0.36,2.58l-1.51,-0.79l-1.84,-0.01l0.28,-1.52l-0.4,-0.47l-2.21,0.01l-0.4,0.37l-0.19,2.74l-0.34,0.93Z", "name": "Thailand"}, "TF": {"path": "M596.68,420.38l-3.2,0.18l-0.05,-1.26l0.39,-1.41l1.3,0.78l2.08,0.35l-0.52,1.36Z", "name": "Fr. S. Antarctic Lands"}, "TG": {"path": "M422.7,257.63l-0.09,1.23l1.53,1.52l0.08,1.09l0.5,0.65l-0.11,5.62l0.49,1.47l-1.31,0.35l-1.02,-2.13l-0.18,-1.12l0.53,-2.19l-0.63,-1.16l-0.22,-3.68l-1.01,-1.4l0.07,-0.28l1.37,0.03Z", "name": "Togo"}, "TD": {"path": "M480.25,235.49l0.12,9.57l-2.1,0.05l-1.14,1.89l-0.69,1.63l0.34,0.73l-0.66,0.91l0.24,0.89l-0.86,1.95l0.45,0.5l0.6,-0.1l0.34,0.64l0.03,1.38l0.9,1.04l-1.45,0.43l-1.27,1.03l-1.83,2.76l-2.16,1.07l-2.31,-0.15l-0.86,0.25l-0.26,0.49l0.17,0.61l-2.11,1.68l-2.85,0.87l-1.09,-0.57l-0.73,0.66l-1.12,0.1l-1.1,-3.12l-1.25,-0.64l-1.22,-1.22l0.29,-0.64l3.01,0.04l0.35,-0.6l-1.3,-2.2l-0.08,-3.31l-0.97,-1.66l0.22,-1.04l-0.38,-0.48l-1.22,-0.04l0.0,-1.25l-0.98,-1.07l0.96,-3.01l3.25,-2.65l0.13,-3.33l0.95,-5.18l0.52,-1.07l-0.1,-0.48l-0.91,-0.78l-0.2,-0.96l-0.8,-0.58l-0.55,-3.65l2.1,-1.2l19.57,9.83Z", "name": "Chad"}, "LY": {"path": "M483.48,203.15l-0.75,1.1l0.29,1.39l-0.6,1.83l0.73,2.14l0.0,24.12l-2.48,0.01l-0.41,0.85l-19.41,-9.76l-4.41,2.28l-1.37,-1.33l-3.82,-1.1l-1.14,-1.65l-1.98,-1.23l-1.22,0.32l-0.66,-1.11l-0.17,-1.26l-1.28,-1.69l0.87,-1.19l-0.07,-4.34l0.43,-2.27l-0.86,-3.45l1.13,-0.76l0.22,-1.16l-0.2,-1.03l3.48,-2.61l0.29,-1.94l2.45,0.8l1.18,-0.21l1.98,0.44l3.15,1.18l1.37,2.54l5.72,1.67l2.64,1.35l1.61,-0.72l1.29,-1.34l-0.44,-2.34l0.66,-1.13l1.67,-1.21l1.57,-0.35l3.14,0.53l1.08,1.28l3.99,0.78l0.36,0.54Z", "name": "Libya"}, "AE": {"path": "M550.76,223.97l1.88,-0.4l3.84,0.02l4.78,-4.75l0.19,0.36l0.26,1.58l-0.81,0.01l-0.39,0.35l-0.08,2.04l-0.81,0.63l-0.01,0.96l-0.66,0.99l-0.39,1.41l-7.08,-1.25l-0.7,-1.96Z", "name": "United Arab Emirates"}, "VE": {"path": "M240.68,256.69l0.53,0.75l-0.02,1.06l-1.07,1.78l0.95,2.0l0.42,0.22l1.4,-0.44l0.56,-1.83l-0.77,-1.17l-0.1,-1.47l2.82,-0.93l0.26,-0.49l-0.28,-0.96l0.3,-0.28l0.66,1.31l1.96,0.26l1.4,1.22l0.08,0.68l0.39,0.35l4.81,-0.22l1.49,1.11l1.92,0.31l1.67,-0.84l0.22,-0.6l3.44,-0.14l-0.17,0.55l0.86,1.19l2.19,0.35l1.67,1.1l0.37,1.86l0.41,0.32l1.55,0.17l-1.66,1.35l-0.22,0.92l0.65,0.97l-1.67,0.54l-0.3,0.4l0.04,0.99l-0.56,0.57l-0.01,0.55l1.85,2.27l-0.66,0.69l-4.47,1.29l-0.72,0.54l-3.69,-0.9l-0.71,0.27l-0.02,0.7l0.91,0.53l-0.08,1.54l0.35,1.58l0.35,0.31l1.66,0.17l-1.3,0.52l-0.48,1.13l-2.68,0.91l-0.6,0.77l-1.57,0.13l-1.17,-1.13l-0.8,-2.52l-1.25,-1.26l1.02,-1.23l-1.29,-2.95l0.18,-1.62l1.0,-2.21l-0.2,-0.49l-1.14,-0.46l-4.02,0.36l-1.82,-2.1l-1.57,-0.33l-2.99,0.22l-1.06,-0.97l0.25,-1.23l-0.2,-1.01l-0.59,-0.69l-0.29,-1.06l-1.08,-0.39l0.78,-2.79l1.9,-2.11Z", "name": "Venezuela"}, "AF": {"path": "M600.7,188.88l-1.57,1.3l-0.1,0.48l0.8,2.31l-1.09,1.04l-0.03,1.27l-0.48,0.71l-2.16,-0.08l-0.37,0.59l0.78,1.48l-1.38,0.69l-1.06,1.69l0.06,1.7l-0.65,0.52l-0.91,-0.21l-1.91,0.36l-0.48,0.77l-1.88,0.13l-1.4,1.56l-0.18,2.32l-2.91,1.02l-1.65,-0.23l-0.71,0.55l-1.41,-0.3l-2.41,0.39l-3.52,-1.17l1.96,-2.35l-0.21,-1.78l-0.3,-0.34l-1.63,-0.4l-0.19,-1.58l-0.75,-2.03l0.95,-1.36l-0.19,-0.6l-0.73,-0.28l1.47,-4.8l2.14,0.9l2.12,-0.36l0.74,-1.34l1.77,-0.39l1.54,-0.92l0.63,-2.31l1.87,-0.5l0.49,-0.81l0.94,0.56l2.13,0.11l2.55,0.92l1.95,-0.83l0.65,0.43l0.56,-0.13l0.69,-1.12l1.57,-0.08l0.72,-1.66l0.79,-0.74l0.8,0.39l-0.17,0.56l0.71,0.58l-0.08,2.39l1.11,0.95ZM601.37,188.71l1.73,-0.71l1.43,-1.18l4.03,0.35l-2.23,0.74l-4.95,0.8Z", "name": "Afghanistan"}, "IQ": {"path": "M530.82,187.47l0.79,0.66l1.26,-0.28l1.46,3.08l1.63,0.94l0.14,1.23l-1.22,1.05l-0.53,2.52l1.73,2.67l3.12,1.62l1.15,1.88l-0.38,1.85l0.39,0.48l0.41,-0.0l0.02,1.07l0.76,0.94l-2.47,-0.1l-1.71,2.44l-4.31,-0.2l-7.02,-5.48l-3.73,-1.94l-2.88,-0.73l-0.85,-2.87l5.45,-3.02l0.95,-3.43l-0.19,-1.96l1.27,-0.7l1.22,-1.7l0.87,-0.36l2.69,0.34Z", "name": "Iraq"}, "IS": {"path": "M384.14,88.06l-0.37,2.61l2.54,2.51l-2.9,2.75l-9.19,3.4l-9.25,-1.66l1.7,-1.22l-0.1,-0.7l-4.05,-1.47l2.96,-0.53l0.33,-0.43l-0.11,-1.2l-0.33,-0.36l-4.67,-0.85l1.28,-2.04l3.45,-0.56l3.77,2.72l0.44,0.02l3.64,-2.16l3.3,1.08l3.98,-2.16l3.58,0.26Z", "name": "Iceland"}, "IR": {"path": "M533.43,187.16l-1.27,-2.15l0.42,-0.98l-0.71,-3.04l1.03,-0.5l0.33,0.83l1.26,1.35l2.05,0.51l1.11,-0.16l2.89,-2.11l0.62,-0.14l0.39,0.46l-0.72,1.2l0.06,0.49l1.56,1.53l0.65,0.04l0.67,1.81l2.56,0.83l1.87,1.48l3.69,0.49l3.91,-0.76l0.47,-0.73l2.17,-0.6l1.66,-1.54l1.51,0.08l1.18,-0.53l1.59,0.24l2.83,1.48l1.88,0.3l2.77,2.47l1.77,0.18l0.18,1.99l-1.68,5.49l0.24,0.5l0.61,0.23l-0.82,1.48l0.8,2.18l0.19,1.71l0.3,0.34l1.63,0.4l0.15,1.32l-2.15,2.35l-0.01,0.53l2.21,3.03l2.34,1.24l0.06,2.14l1.24,0.72l0.11,0.69l-3.31,1.27l-1.08,3.03l-9.68,-1.68l-0.99,-3.05l-1.43,-0.73l-2.17,0.46l-2.47,1.26l-2.83,-0.82l-2.46,-2.02l-2.41,-0.8l-3.42,-6.06l-0.48,-0.2l-1.18,0.39l-1.44,-0.82l-0.5,0.08l-0.65,0.74l-0.97,-1.01l-0.02,-1.31l-0.71,-0.39l0.26,-1.81l-1.29,-2.11l-3.13,-1.63l-1.58,-2.43l0.5,-1.9l1.31,-1.26l-0.19,-1.66l-1.74,-1.1l-1.57,-3.3Z", "name": "Iran"}, "AM": {"path": "M536.99,182.33l-0.28,0.03l-1.23,-2.13l-0.93,0.01l-0.62,-0.66l-0.69,-0.07l-0.96,-0.81l-1.56,-0.62l0.19,-1.12l-0.26,-0.79l2.72,-0.36l1.09,1.01l-0.17,0.92l1.02,0.78l-0.47,0.62l0.08,0.56l2.04,1.23l0.04,1.4Z", "name": "Armenia"}, "AL": {"path": "M470.32,171.8l0.74,0.03l0.92,0.89l-0.17,1.95l0.36,1.28l1.01,0.82l-1.82,2.83l-0.19,-0.61l-1.25,-0.89l-0.18,-1.2l0.53,-2.82l-0.54,-1.47l0.6,-0.83Z", "name": "Albania"}, "AO": {"path": "M461.55,300.03l1.26,3.15l1.94,2.36l2.47,-0.53l1.25,0.32l0.44,-0.18l0.93,-1.92l1.31,-0.08l0.41,-0.44l0.47,-0.0l-0.1,0.41l0.39,0.49l2.65,-0.02l0.03,1.19l0.48,1.01l-0.34,1.52l0.18,1.55l0.83,1.04l-0.13,2.85l0.54,0.39l3.96,-0.41l-0.1,1.79l0.39,1.05l-0.24,1.43l-4.7,-0.03l-0.4,0.39l-0.12,8.13l2.92,3.49l-3.83,0.88l-5.89,-0.36l-1.88,-1.24l-10.47,0.22l-1.3,-1.01l-1.85,-0.16l-2.4,0.77l-0.15,-1.06l0.33,-2.16l1.0,-3.45l1.35,-3.2l2.24,-2.8l0.33,-2.06l-0.13,-1.53l-0.8,-1.08l-1.21,-2.87l0.87,-1.62l-1.27,-4.12l-1.17,-1.53l2.47,-0.63l7.03,0.03ZM451.71,298.87l-0.47,-1.25l1.25,-1.11l0.32,0.3l-0.99,1.03l-0.12,1.03Z", "name": "Angola"}, "AR": {"path": "M249.29,428.93l-2.33,-0.52l-5.83,-0.43l-0.89,-1.66l0.05,-2.37l-0.45,-0.4l-1.43,0.18l-0.67,-0.91l-0.2,-3.13l1.88,-1.47l0.79,-2.04l-0.25,-1.7l1.3,-2.68l0.91,-4.15l-0.22,-1.69l0.85,-0.45l0.2,-0.44l-0.27,-1.16l-0.98,-0.68l0.59,-0.92l-0.05,-0.5l-1.04,-1.07l-0.52,-3.1l0.97,-0.86l-0.42,-3.58l1.2,-5.43l1.38,-0.98l0.16,-0.43l-0.75,-2.79l-0.01,-2.43l1.78,-1.75l0.06,-2.57l1.43,-2.85l0.01,-2.58l-0.69,-0.74l-1.09,-4.52l1.47,-2.7l-0.18,-2.79l0.85,-2.35l1.59,-2.46l1.73,-1.64l0.05,-0.52l-0.6,-0.84l0.44,-0.85l-0.07,-4.19l2.7,-1.44l0.86,-2.75l-0.21,-0.71l1.76,-2.01l2.9,0.57l1.38,1.78l0.68,-0.08l0.87,-1.87l2.39,0.09l4.95,4.77l2.17,0.49l3.0,1.92l2.47,1.0l0.25,0.82l-2.37,3.93l0.23,0.59l5.39,1.16l2.12,-0.44l2.45,-2.16l0.5,-2.38l0.76,-0.31l0.98,1.2l-0.04,1.8l-3.67,2.51l-2.85,2.66l-3.43,3.88l-1.3,5.07l0.01,2.72l-0.54,0.73l-0.36,3.28l3.14,2.64l-0.16,2.11l1.4,1.11l-0.1,1.09l-2.29,3.52l-3.55,1.49l-4.92,0.6l-2.71,-0.29l-0.43,0.51l0.5,1.65l-0.49,2.1l0.38,1.42l-1.19,0.83l-2.36,0.38l-2.3,-1.04l-1.38,0.83l0.41,3.64l1.69,0.91l1.4,-0.71l0.36,0.76l-2.04,0.86l-2.01,1.89l-0.97,4.63l-2.34,0.1l-2.09,1.78l-0.61,2.75l2.46,2.31l2.17,0.63l-0.7,2.32l-2.83,1.73l-1.73,3.86l-2.17,1.22l-1.16,1.67l0.75,3.76l1.04,1.28ZM256.71,438.88l-2.0,0.15l-1.4,-1.22l-3.82,-0.1l-0.0,-5.83l1.6,3.05l3.26,2.07l3.08,0.78l-0.71,1.1Z", "name": "Argentina"}, "AU": {"path": "M705.8,353.26l0.26,0.04l0.17,-0.47l-0.48,-1.42l0.92,1.11l0.45,0.15l0.27,-0.39l-0.1,-1.56l-1.98,-3.63l1.09,-3.31l-0.24,-1.57l0.34,-0.62l0.38,1.06l0.43,-0.19l0.99,-1.7l1.91,-0.83l1.29,-1.15l1.81,-0.91l0.96,-0.17l0.92,0.26l1.92,-0.95l1.47,-0.28l1.03,-0.8l1.43,0.04l2.78,-0.84l1.36,-1.15l0.71,-1.45l1.41,-1.26l0.3,-2.58l1.27,-1.59l0.78,1.65l0.54,0.19l1.07,-0.51l0.15,-0.6l-0.73,-1.0l0.45,-0.71l0.78,0.39l0.58,-0.3l0.28,-1.82l1.87,-2.14l1.12,-0.39l0.28,-0.58l0.62,0.17l0.53,-0.73l1.87,-0.57l1.65,1.05l1.35,1.48l3.39,0.38l0.43,-0.54l-0.46,-1.23l1.05,-1.79l1.04,-0.61l0.14,-0.55l-0.25,-0.41l0.88,-1.17l1.31,-0.77l1.3,0.27l2.1,-0.48l0.31,-0.4l-0.05,-1.3l-0.92,-0.77l1.48,0.56l1.41,1.07l2.11,0.65l0.81,-0.2l1.4,0.7l1.69,-0.66l0.8,0.19l0.64,-0.33l0.71,0.77l-1.33,1.94l-0.71,0.07l-0.35,0.51l0.24,0.86l-1.52,2.35l0.12,1.05l2.15,1.65l1.97,0.85l3.04,2.36l1.97,0.65l0.55,0.88l2.72,0.85l1.84,-1.1l2.07,-5.97l-0.42,-3.59l0.3,-1.73l0.47,-0.87l-0.31,-0.68l1.09,-3.28l0.46,-0.47l0.4,0.71l0.16,1.51l0.65,0.52l0.16,1.04l0.85,1.21l0.12,2.38l0.9,2.0l0.57,0.18l1.3,-0.78l1.69,1.7l-0.2,1.08l0.53,2.2l0.39,1.3l0.68,0.48l0.6,1.95l-0.19,1.48l0.81,1.76l6.01,3.69l-0.11,0.76l1.38,1.58l0.95,2.77l0.58,0.22l0.72,-0.41l0.8,0.9l0.61,0.01l0.46,2.41l4.81,4.71l0.66,2.02l-0.07,3.31l1.14,2.2l-0.13,2.24l-1.1,3.68l0.03,1.64l-0.47,1.89l-1.05,2.4l-1.9,1.47l-1.72,3.51l-2.38,6.09l-0.24,2.82l-1.14,0.8l-2.85,0.15l-2.31,1.19l-2.51,2.25l-3.09,-1.57l0.3,-1.15l-0.54,-0.47l-1.5,0.63l-2.01,1.94l-7.12,-2.18l-1.48,-1.63l-1.14,-3.74l-1.45,-1.26l-1.81,-0.26l0.56,-1.18l-0.61,-2.1l-0.72,-0.1l-1.14,1.82l-0.9,0.21l0.63,-0.82l0.36,-1.55l0.92,-1.31l-0.13,-2.34l-0.7,-0.22l-2.0,2.34l-1.51,0.93l-0.94,2.01l-1.35,-0.81l-0.02,-1.52l-1.57,-2.04l-1.09,-0.88l0.24,-0.33l-0.14,-0.59l-3.21,-1.69l-1.83,-0.12l-2.54,-1.35l-4.58,0.28l-6.02,1.9l-2.53,-0.13l-2.62,1.41l-2.13,0.63l-1.49,2.6l-3.49,0.31l-2.29,-0.5l-3.48,0.43l-1.6,1.47l-0.81,-0.04l-2.37,1.63l-3.26,-0.1l-3.72,-2.21l0.04,-1.05l1.19,-0.46l0.49,-0.89l0.21,-2.97l-0.28,-1.64l-1.34,-2.86l-0.38,-1.47l0.05,-1.72l-0.95,-1.7l-0.18,-0.97l-1.01,-0.99l-0.29,-1.98l-1.13,-1.75ZM784.92,393.44l2.65,1.02l3.23,-0.96l1.09,0.14l0.15,3.06l-0.85,1.13l-0.17,1.63l-0.87,-0.24l-1.57,1.91l-1.68,-0.18l-1.4,-2.36l-0.37,-2.04l-1.39,-2.51l0.04,-0.8l1.15,0.18Z", "name": "Australia"}, "AT": {"path": "M462.89,152.8l0.04,2.25l-1.07,0.0l-0.33,0.63l0.36,0.51l-1.04,2.13l-2.02,0.07l-1.33,0.7l-5.29,-0.99l-0.47,-0.93l-0.44,-0.21l-2.47,0.55l-0.42,0.51l-3.18,-0.81l0.43,-0.91l1.12,0.78l0.6,-0.17l0.25,-0.58l1.93,0.12l1.86,-0.56l1.0,0.08l0.68,0.57l0.62,-0.15l0.26,-0.77l-0.3,-1.78l0.8,-0.44l0.68,-1.15l1.52,0.85l0.47,-0.06l1.34,-1.25l0.64,-0.17l1.81,0.92l1.28,-0.11l0.7,0.37Z", "name": "Austria"}, "IN": {"path": "M623.34,207.03l-1.24,1.04l-0.97,2.55l0.22,0.51l8.04,3.87l3.42,0.37l1.57,1.38l4.92,0.88l2.18,-0.04l0.38,-0.3l0.29,-1.24l-0.32,-1.64l0.14,-0.87l0.82,-0.31l0.45,2.48l2.28,1.02l1.77,-0.38l4.14,0.1l0.38,-0.36l0.18,-1.66l-0.5,-0.65l1.37,-0.29l2.25,-1.99l2.7,-1.62l1.93,0.62l1.8,-0.98l0.79,1.14l-0.68,0.91l0.26,0.63l2.42,0.36l0.09,0.47l-0.83,0.75l0.13,1.07l-1.52,-0.29l-3.24,1.86l-0.13,1.78l-1.32,2.14l-0.18,1.39l-0.93,1.82l-1.64,-0.5l-0.52,0.37l-0.09,2.63l-0.56,1.11l0.19,0.81l-0.53,0.27l-1.18,-3.73l-1.08,-0.27l-0.38,0.31l-0.24,1.0l-0.66,-0.66l0.54,-1.06l1.22,-0.34l1.15,-2.25l-0.24,-0.56l-1.57,-0.47l-4.34,-0.28l-0.18,-1.56l-0.35,-0.35l-1.11,-0.12l-1.91,-1.12l-0.56,0.17l-0.88,1.82l0.11,0.49l1.36,1.07l-1.09,0.69l-0.69,1.11l0.18,0.56l1.24,0.57l-0.32,1.54l0.85,1.94l0.36,2.01l-0.22,0.59l-4.58,0.52l-0.33,0.42l0.13,1.8l-1.17,1.36l-3.65,1.81l-2.79,3.03l-4.32,3.28l-0.18,1.27l-4.65,1.79l-0.77,2.16l0.64,5.3l-1.06,2.49l-0.01,3.94l-1.24,0.28l-1.14,1.93l0.39,0.84l-1.68,0.53l-1.04,1.83l-0.65,0.47l-2.06,-2.05l-2.1,-6.02l-2.2,-3.64l-1.05,-4.75l-2.29,-3.57l-1.76,-8.2l0.01,-3.11l-0.49,-2.53l-0.55,-0.29l-3.53,1.52l-1.53,-0.27l-2.86,-2.77l0.85,-0.67l0.08,-0.55l-0.74,-1.03l-2.67,-2.06l1.24,-1.32l5.34,0.01l0.39,-0.49l-0.5,-2.29l-1.42,-1.46l-0.27,-1.93l-1.43,-1.2l2.31,-2.37l3.05,0.06l2.62,-2.85l1.6,-2.81l2.4,-2.73l0.07,-2.04l1.97,-1.48l-0.02,-0.65l-1.93,-1.31l-0.82,-1.78l-0.8,-2.21l0.9,-0.89l3.59,0.65l2.92,-0.42l2.33,-2.19l2.31,2.85l-0.24,2.13l0.99,1.59l-0.05,0.82l-1.34,-0.28l-0.47,0.48l0.7,3.06l2.62,1.99l2.99,1.65Z", "name": "India"}, "TZ": {"path": "M495.56,296.42l2.8,-3.12l-0.02,-0.81l-0.64,-1.3l0.68,-0.52l0.14,-1.47l-0.76,-1.25l0.31,-0.11l2.26,0.03l-0.51,2.76l0.76,1.3l0.5,0.12l1.05,-0.53l1.19,-0.12l0.61,0.24l1.43,-0.62l0.1,-0.67l-0.71,-0.62l1.57,-1.7l8.65,4.86l0.32,1.53l3.34,2.33l-1.05,2.8l0.13,1.61l1.63,1.12l-0.6,1.76l-0.01,2.33l1.89,4.03l0.57,0.43l-1.46,1.08l-2.61,0.94l-1.43,-0.04l-1.06,0.77l-2.29,0.36l-2.87,-0.68l-0.83,0.07l-0.63,-0.75l-0.31,-2.78l-1.32,-1.35l-3.25,-0.77l-3.96,-1.58l-1.18,-2.41l-0.32,-1.75l-1.76,-1.49l0.42,-1.05l-0.44,-0.89l0.08,-0.96l-0.46,-0.58l0.06,-0.56Z", "name": "Tanzania"}, "AZ": {"path": "M539.29,175.73l1.33,0.32l1.94,-1.8l2.3,3.34l1.43,0.43l-1.26,0.15l-0.35,0.32l-0.8,3.14l-0.99,0.96l0.05,1.11l-1.26,-1.13l0.7,-1.18l-0.04,-0.47l-0.74,-0.86l-1.48,0.15l-2.34,1.71l-0.03,-1.27l-2.03,-1.35l0.47,-0.62l-0.08,-0.56l-1.03,-0.79l0.29,-0.43l-0.14,-0.58l-1.13,-0.86l1.89,0.68l1.69,0.06l0.37,-0.87l-0.81,-1.37l0.42,0.06l1.63,1.72ZM533.78,180.57l0.61,0.46l0.69,-0.0l0.59,1.15l-0.68,-0.15l-1.21,-1.45Z", "name": "Azerbaijan"}, "IE": {"path": "M405.08,135.42l0.35,2.06l-1.75,2.78l-4.22,1.88l-2.84,-0.4l1.73,-3.0l-1.18,-3.53l4.6,-3.74l0.32,1.15l-0.49,1.74l0.4,0.51l1.47,-0.04l1.6,0.6Z", "name": "Ireland"}, "ID": {"path": "M756.47,287.89l0.69,4.01l2.79,1.78l0.51,-0.1l2.04,-2.59l2.71,-1.43l2.05,-0.0l3.9,1.73l2.46,0.45l0.08,15.12l-1.75,-1.54l-2.54,-0.51l-0.88,0.71l-2.32,0.06l0.69,-1.33l1.45,-0.64l0.23,-0.46l-0.65,-2.74l-1.24,-2.21l-5.04,-2.29l-2.09,-0.23l-3.68,-2.27l-0.55,0.13l-0.65,1.07l-0.52,0.12l-0.55,-1.89l-1.21,-0.78l1.84,-0.62l1.72,0.05l0.39,-0.52l-0.21,-0.66l-0.38,-0.28l-3.45,-0.0l-1.13,-1.48l-2.1,-0.43l-0.52,-0.6l2.69,-0.48l1.28,-0.78l3.66,0.94l0.3,0.71ZM757.91,300.34l-0.62,0.82l-0.1,-0.8l0.59,-1.12l0.13,1.1ZM747.38,292.98l0.34,0.72l-1.22,-0.57l-4.68,-0.1l0.27,-0.62l2.78,-0.09l2.52,0.67ZM741.05,285.25l-0.67,-2.88l0.64,-2.01l0.41,0.86l1.21,0.18l0.16,0.7l-0.1,1.68l-0.84,-0.16l-0.46,0.3l-0.34,1.34ZM739.05,293.5l-0.5,0.44l-1.34,-0.36l-0.17,-0.37l1.73,-0.08l0.27,0.36ZM721.45,284.51l-0.19,1.97l2.24,2.23l0.54,0.02l1.27,-1.07l2.75,-0.5l-0.9,1.21l-2.11,0.93l-0.16,0.6l2.22,3.01l-0.3,1.07l1.36,1.74l-2.26,0.85l-0.28,-0.31l0.12,-1.19l-1.64,-1.34l0.17,-2.23l-0.56,-0.39l-1.67,0.76l-0.23,0.39l0.3,6.17l-1.1,0.25l-0.69,-0.47l0.64,-2.21l-0.39,-2.42l-0.39,-0.34l-0.8,-0.01l-0.58,-1.29l0.98,-1.6l0.35,-1.96l1.32,-3.87ZM728.59,296.27l0.38,0.49l-0.02,1.28l-0.88,0.49l-0.53,-0.47l1.04,-1.79ZM729.04,286.98l0.27,-0.05l-0.02,0.13l-0.24,-0.08ZM721.68,284.05l0.16,-0.32l1.89,-1.65l1.83,0.68l3.16,0.35l2.94,-0.1l2.39,-1.66l-1.73,2.13l-1.66,0.43l-2.41,-0.48l-4.17,0.13l-2.39,0.51ZM730.55,310.47l1.11,-1.93l2.03,-0.82l0.08,0.62l-1.45,1.67l-1.77,0.46ZM728.12,305.88l-0.1,0.38l-3.46,0.66l-2.91,-0.27l-0.0,-0.25l1.54,-0.41l1.66,0.73l1.67,-0.19l1.61,-0.65ZM722.9,310.24l-0.64,0.03l-2.26,-1.2l1.11,-0.24l1.78,1.41ZM716.26,305.77l0.88,0.51l1.28,-0.17l0.2,0.35l-4.65,0.73l0.39,-0.67l1.15,-0.02l0.75,-0.73ZM711.66,293.84l-0.38,-0.16l-2.54,1.01l-1.12,-1.44l-1.69,-0.13l-1.16,-0.75l-3.04,0.77l-1.1,-1.15l-3.31,-0.11l-0.35,-3.05l-1.35,-0.95l-1.11,-1.98l-0.33,-2.06l0.27,-2.14l0.9,-1.01l0.37,1.15l2.09,1.49l1.53,-0.48l1.82,0.08l1.38,-1.19l1.0,-0.18l2.28,0.67l2.26,-0.53l1.52,-3.64l1.01,-0.99l0.78,-2.57l4.1,0.3l-1.11,1.77l0.02,0.46l1.7,2.2l-0.23,1.39l2.07,1.71l-2.33,0.42l-0.88,1.9l0.1,2.05l-2.4,1.9l-0.06,2.45l-0.7,2.79ZM692.58,302.03l0.35,0.26l4.8,0.25l0.78,-0.97l4.17,1.09l1.13,1.68l3.69,0.45l2.13,1.04l-1.8,0.6l-2.77,-0.99l-4.8,-0.12l-5.24,-1.41l-1.84,-0.25l-1.11,0.3l-4.26,-0.97l-0.7,-1.14l-1.59,-0.13l1.18,-1.65l2.74,0.13l2.87,1.13l0.26,0.68ZM685.53,299.17l-2.22,0.04l-2.06,-2.03l-3.15,-2.01l-2.93,-3.51l-3.11,-5.33l-2.2,-2.12l-1.64,-4.06l-2.32,-1.69l-1.27,-2.07l-1.96,-1.5l-2.51,-2.65l-0.11,-0.66l4.81,0.53l2.15,2.38l3.31,2.74l2.35,2.66l2.7,0.17l1.95,1.59l1.54,2.17l1.59,0.95l-0.84,1.71l0.15,0.52l1.44,0.87l0.79,0.1l0.4,1.58l0.87,1.4l1.96,0.39l1.0,1.31l-0.6,3.01l-0.09,3.5Z", "name": "Indonesia"}, "UA": {"path": "M492.5,162.44l1.28,-2.49l1.82,0.19l0.66,-0.23l0.09,-0.71l-0.25,-0.75l-0.79,-0.72l-0.33,-1.21l-0.86,-0.62l-0.02,-1.19l-1.13,-0.86l-1.15,-0.19l-2.04,-1.0l-1.66,0.32l-0.66,0.47l-0.92,-0.0l-0.84,0.78l-2.48,0.7l-1.18,-0.71l-3.07,-0.36l-0.89,0.43l-0.24,-0.55l-1.11,-0.7l0.35,-0.93l1.26,-1.02l-0.54,-1.23l2.04,-2.43l1.4,-0.62l0.25,-1.19l-1.04,-2.39l0.83,-0.13l1.28,-0.84l1.8,-0.07l2.47,0.26l2.86,0.81l1.88,0.06l0.86,0.44l1.04,-0.41l0.77,0.66l2.18,-0.15l0.92,0.3l0.52,-0.34l0.15,-1.53l0.56,-0.54l2.85,-0.05l0.84,-0.72l3.04,-0.18l1.23,1.46l-0.48,0.77l0.21,1.03l0.36,0.32l1.8,0.14l0.93,2.08l3.18,1.15l1.94,-0.45l1.67,1.49l1.4,-0.03l3.35,0.96l0.02,0.54l-0.96,1.59l0.47,1.97l-0.26,0.7l-2.36,0.28l-1.29,0.89l-0.23,1.38l-1.83,0.27l-1.58,0.97l-2.41,0.21l-2.16,1.17l-0.21,0.38l0.34,2.26l1.23,0.75l2.13,-0.08l-0.14,0.31l-2.65,0.53l-3.23,1.69l-0.87,-0.39l0.42,-1.1l-0.25,-0.52l-2.21,-0.73l2.35,-1.06l0.12,-0.65l-0.93,-0.82l-3.62,-0.74l-0.13,-0.89l-0.46,-0.34l-2.61,0.59l-0.91,1.69l-1.71,2.04l-0.86,-0.4l-1.62,0.27Z", "name": "Ukraine"}, "QA": {"path": "M549.33,221.64l-0.76,-0.23l-0.14,-1.64l0.84,-1.29l0.47,0.52l0.04,1.34l-0.45,1.3Z", "name": "Qatar"}, "MZ": {"path": "M508.58,318.75l-0.34,-2.57l0.51,-2.05l3.55,0.63l2.5,-0.38l1.02,-0.76l1.49,0.01l2.74,-0.98l1.66,-1.2l0.5,9.24l0.41,1.23l-0.68,1.67l-0.93,1.71l-1.5,1.5l-5.16,2.28l-2.78,2.73l-1.02,0.53l-1.71,1.8l-0.98,0.57l-0.35,2.41l1.16,1.94l0.49,2.17l0.43,0.31l-0.06,2.06l-0.39,1.17l0.5,0.72l-0.25,0.73l-0.92,0.83l-5.12,2.39l-1.22,1.36l0.21,1.13l0.58,0.39l-0.11,0.72l-1.22,-0.01l-0.73,-2.97l0.42,-3.09l-1.78,-5.37l2.49,-2.81l0.69,-1.89l0.44,-0.43l0.28,-1.53l-0.39,-0.93l0.59,-3.65l-0.01,-3.26l-1.49,-1.16l-1.2,-0.22l-1.74,-1.17l-1.92,0.01l-0.29,-2.08l7.06,-1.96l1.28,1.09l0.89,-0.1l0.67,0.44l0.1,0.73l-0.51,1.29l0.19,1.81l1.75,1.83l0.65,-0.13l0.71,-1.65l1.17,-0.86l-0.26,-3.47l-1.05,-1.85l-1.04,-0.94Z", "name": "Mozambique"}}, "height": 440.7063107441331, "projection": {"type": "mill", "centralMeridian": 11.5}, "width": 900.0});
|
|
assets/js/wpzerospam.js
DELETED
@@ -1,58 +0,0 @@
|
|
1 |
-
/**
|
2 |
-
* WordPress Zero Spam jQuery plugin.
|
3 |
-
*
|
4 |
-
* Handles adding the required functionality for spam detections.
|
5 |
-
*
|
6 |
-
* @since 4.9.11
|
7 |
-
*/
|
8 |
-
(function ($) {
|
9 |
-
$.fn.WordPressZeroSpam = function () {
|
10 |
-
// Check if the required WPZS key is defined.
|
11 |
-
if (typeof wpzerospam.key == "undefined") {
|
12 |
-
// The key is not defined, alert the site owner via the console.
|
13 |
-
console.log(
|
14 |
-
"WordPress Zero Spam is unable to initialize, missing the required key."
|
15 |
-
);
|
16 |
-
|
17 |
-
return this;
|
18 |
-
}
|
19 |
-
|
20 |
-
// Check if the element is on the page.
|
21 |
-
if (!this.length) {
|
22 |
-
console.log(
|
23 |
-
"WordPress Zero Spam could not find a " + this.selector + " instance."
|
24 |
-
);
|
25 |
-
|
26 |
-
return this;
|
27 |
-
}
|
28 |
-
|
29 |
-
console.log(
|
30 |
-
"WordPress Zero Spam found " +
|
31 |
-
this.length +
|
32 |
-
" instance(s) of " +
|
33 |
-
this.selector +
|
34 |
-
"."
|
35 |
-
);
|
36 |
-
|
37 |
-
// Add an attribute to the element to show its been initialized by WPZS.
|
38 |
-
this.attr("data-wpzerospam", "protected");
|
39 |
-
|
40 |
-
// Check if the WPZS hidden input already exists.
|
41 |
-
if ($('[name="wpzerospam_key"]', this).length) {
|
42 |
-
// Hidden input already exists, update its value.
|
43 |
-
$('[name="wpzerospam_key"]', this).val(wpzerospam.key);
|
44 |
-
} else {
|
45 |
-
// Hidden input isn't present, add it.
|
46 |
-
$(
|
47 |
-
'<input type="hidden" name="wpzerospam_key" value="' +
|
48 |
-
wpzerospam.key +
|
49 |
-
'" />'
|
50 |
-
).appendTo(this);
|
51 |
-
}
|
52 |
-
};
|
53 |
-
})(jQuery);
|
54 |
-
|
55 |
-
// Initialize WPZS on form elements with the wpzerospam class.
|
56 |
-
jQuery(function() {
|
57 |
-
jQuery(".wpzerospam").WordPressZeroSpam();
|
58 |
-
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/class-wpzerospam-blacklisted-table.php
DELETED
@@ -1,305 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* WordPress Zero Spam blacklisted table
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.0.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
|
10 |
-
|
11 |
-
if ( ! class_exists( 'WP_List_Table' ) ) {
|
12 |
-
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
|
13 |
-
}
|
14 |
-
|
15 |
-
class WPZeroSpam_Blacklisted_Table extends WP_List_Table {
|
16 |
-
function __construct() {
|
17 |
-
global $status, $page;
|
18 |
-
|
19 |
-
$args = [
|
20 |
-
'singular' => __( 'Blacklist', 'zero-spam' ),
|
21 |
-
'plural' => __( 'Blacklist IPs', 'zero-spam' ),
|
22 |
-
'ajax' => true
|
23 |
-
];
|
24 |
-
parent::__construct( $args );
|
25 |
-
}
|
26 |
-
|
27 |
-
// Register columns
|
28 |
-
function get_columns() {
|
29 |
-
// Render a checkbox instead of text
|
30 |
-
$columns = [
|
31 |
-
'cb' => '<input type="checkbox" />',
|
32 |
-
'last_updated' => __( 'Last Updated', 'zero-spam' ),
|
33 |
-
'user_ip' => __( 'IP Address', 'zero-spam' ),
|
34 |
-
'service' => __( 'Service', 'zero-spam' ),
|
35 |
-
'attempts' => __( 'Attempts', 'zero-spam' ),
|
36 |
-
'details' => __( 'Details', 'zero-spam' )
|
37 |
-
];
|
38 |
-
|
39 |
-
return $columns;
|
40 |
-
}
|
41 |
-
|
42 |
-
// Sortable columns
|
43 |
-
function get_sortable_columns() {
|
44 |
-
$sortable_columns = [
|
45 |
-
'last_updated' => [ 'last_updated', false ],
|
46 |
-
'user_ip' => [ 'user_ip', false ],
|
47 |
-
'service' => [ 'service', false ],
|
48 |
-
'attempts' => [ 'attempts', false ],
|
49 |
-
];
|
50 |
-
|
51 |
-
return $sortable_columns;
|
52 |
-
}
|
53 |
-
|
54 |
-
function extra_tablenav( $which ) {
|
55 |
-
global $cat_id;
|
56 |
-
|
57 |
-
if ( 'top' !== $which ) {
|
58 |
-
return;
|
59 |
-
}
|
60 |
-
?>
|
61 |
-
<div class="alignleft actions">
|
62 |
-
<?php
|
63 |
-
echo '<label class="screen-reader-text" for="filter-by-service">' . __( 'Filter by service', 'zero-spam' ) . '</label>';
|
64 |
-
$current_service = ! empty( $_REQUEST['service'] ) ? sanitize_text_field( $_REQUEST['service'] ) : false;
|
65 |
-
?>
|
66 |
-
<select name="service" id="filter-by-service">
|
67 |
-
<option value=""><?php _e( 'All services', 'zero-spam' ); ?></option>
|
68 |
-
<option<?php if ( $current_service == 'botscout' ): ?> selected="selected" <?php endif; ?> value="botscout"><?php _e( 'BotScout', 'zero-spam' ); ?></option>
|
69 |
-
<option<?php if ( $current_service == 'stopforumspam' ): ?> selected="selected" <?php endif; ?> value="stopforumspam"><?php _e( 'Stop Forum Spam', 'zero-spam' ); ?></option>
|
70 |
-
<option<?php if ( $current_service == 'zerospam' ): ?> selected="selected" <?php endif; ?> value="zerospam"><?php _e( 'Zero Spam', 'zero-spam' ); ?></option>
|
71 |
-
</select>
|
72 |
-
<?php
|
73 |
-
submit_button( __( 'Filter' ), '', 'filter_action', false );
|
74 |
-
?>
|
75 |
-
</div>
|
76 |
-
<?php
|
77 |
-
}
|
78 |
-
|
79 |
-
// Checkbox column
|
80 |
-
function column_cb( $item ){
|
81 |
-
return sprintf(
|
82 |
-
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
|
83 |
-
/*$1%s*/ 'ids',
|
84 |
-
/*$2%s*/ $item->blacklist_id
|
85 |
-
);
|
86 |
-
}
|
87 |
-
|
88 |
-
// Render column
|
89 |
-
function column_default( $item, $column_name ) {
|
90 |
-
switch( $column_name ) {
|
91 |
-
case 'service':
|
92 |
-
switch( $item->blacklist_service ) {
|
93 |
-
case 'stopforumspam':
|
94 |
-
return '<a href="https://www.stopforumspam.com/" target="_blank" rel="noopener noreferrer">Stop Forum Spam</a>';
|
95 |
-
break;
|
96 |
-
case 'botscout':
|
97 |
-
return '<a href="https://botscout.com/" target="_blank" rel="noopener noreferrer">BotScout</a>';
|
98 |
-
break;
|
99 |
-
case 'zerospam':
|
100 |
-
return '<a href="https://zerospam.org/" target="_blank" rel="noopener noreferrer">Zero Spam</a>';
|
101 |
-
break;
|
102 |
-
default:
|
103 |
-
return $item->blacklist_service;
|
104 |
-
}
|
105 |
-
break;
|
106 |
-
case 'attempts':
|
107 |
-
return number_format( $item->attempts, 0 );
|
108 |
-
break;
|
109 |
-
case 'user_ip':
|
110 |
-
return '<a href="https://zerospam.org/ip-lookup/' . $item->user_ip .'/" target="_blank" rel="noopener noreferrer">' . $item->user_ip . '</a>';
|
111 |
-
break;
|
112 |
-
case 'last_updated':
|
113 |
-
return date( 'M j, Y g:ia' , strtotime( $item->last_updated ) );
|
114 |
-
break;
|
115 |
-
case 'details':
|
116 |
-
if ( empty( $item->blacklist_data ) ) { return __( 'No details available.', 'wpzerospam' ); }
|
117 |
-
ob_start();
|
118 |
-
?>
|
119 |
-
<button class="button action wpzerospam-details-trigger" data-id="<?php echo $item->blacklist_id; ?>"><?php _e( 'View', 'zero-spam' ); ?></button>
|
120 |
-
<div class="wpzerospam-details-modal" id="wpzerospam-details-modal-<?php echo $item->blacklist_id; ?>">
|
121 |
-
<div class="wpzerospam-details-modal-inner">
|
122 |
-
<?php
|
123 |
-
$item->blacklist_data = json_decode( $item->blacklist_data, true );
|
124 |
-
|
125 |
-
echo '<div class="wpzerospam-details-item">';
|
126 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Detected Spam IP', 'zero-spam' ) . '</div>';
|
127 |
-
echo '<div class="wpzerospam-details-data">' . '<a href="https://zerospam.org/ip-lookup/' . urlencode( $item->user_ip ) .'" target="_blank" rel="noopener noreferrer">' . $item->user_ip . '</a>' . '</div>';
|
128 |
-
echo '</div>';
|
129 |
-
|
130 |
-
echo '<div class="wpzerospam-details-item">';
|
131 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Last Updated', 'zero-spam' ) . '</div>';
|
132 |
-
echo '<div class="wpzerospam-details-data">' . date( 'M j, Y g:ia' , strtotime( $item->last_updated ) ) . '</div>';
|
133 |
-
echo '</div>';
|
134 |
-
|
135 |
-
echo '<div class="wpzerospam-details-item">';
|
136 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Service', 'zero-spam' ) . '</div>';
|
137 |
-
echo '<div class="wpzerospam-details-data">';
|
138 |
-
switch( $item->blacklist_service ) {
|
139 |
-
case 'stopforumspam':
|
140 |
-
echo '<a href="https://www.stopforumspam.com/" target="_blank" rel="noopener noreferrer">Stop Forum Spam</a>';
|
141 |
-
break;
|
142 |
-
case 'botscout':
|
143 |
-
echo '<a href="https://botscout.com/" target="_blank" rel="noopener noreferrer">BotScout</a>';
|
144 |
-
break;
|
145 |
-
case 'zerospam':
|
146 |
-
echo '<a href="https://zerospam.org/" target="_blank" rel="noopener noreferrer">Zero Spam</a>';
|
147 |
-
break;
|
148 |
-
default:
|
149 |
-
echo $item->blacklist_service;
|
150 |
-
}
|
151 |
-
echo '</div>';
|
152 |
-
echo '</div>';
|
153 |
-
|
154 |
-
if ( ! empty( $item->blacklist_data ) ) {
|
155 |
-
foreach( $item->blacklist_data as $key => $value ):
|
156 |
-
if ( ! $value ) { continue; }
|
157 |
-
switch( $key ):
|
158 |
-
case 'appears':
|
159 |
-
echo '<div class="wpzerospam-details-item">';
|
160 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Appears', 'zero-spam' ) . '</div>';
|
161 |
-
echo '<div class="wpzerospam-details-data">' . $value . '</div>';
|
162 |
-
echo '</div>';
|
163 |
-
break;
|
164 |
-
case 'confidence':
|
165 |
-
echo '<div class="wpzerospam-details-item">';
|
166 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Confidence', 'zero-spam' ) . '</div>';
|
167 |
-
echo '<div class="wpzerospam-details-data">' . $value . '%</div>';
|
168 |
-
echo '</div>';
|
169 |
-
break;
|
170 |
-
case 'frequency':
|
171 |
-
echo '<div class="wpzerospam-details-item">';
|
172 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Frequency', 'zero-spam' ) . '</div>';
|
173 |
-
echo '<div class="wpzerospam-details-data">' . $value . '</div>';
|
174 |
-
echo '</div>';
|
175 |
-
break;
|
176 |
-
case 'lastseen':
|
177 |
-
echo '<div class="wpzerospam-details-item">';
|
178 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Last Seen', 'zero-spam' ) . '</div>';
|
179 |
-
echo '<div class="wpzerospam-details-data">' . $value . '</div>';
|
180 |
-
echo '</div>';
|
181 |
-
break;
|
182 |
-
case 'asn':
|
183 |
-
echo '<div class="wpzerospam-details-item">';
|
184 |
-
echo '<div class="wpzerospam-details-label">' . __( 'ASN', 'zero-spam' ) . '</div>';
|
185 |
-
echo '<div class="wpzerospam-details-data">' . $value . '</div>';
|
186 |
-
echo '</div>';
|
187 |
-
break;
|
188 |
-
default:
|
189 |
-
echo '<div class="wpzerospam-details-item">';
|
190 |
-
echo '<div class="wpzerospam-details-label">' . $key . '</div>';
|
191 |
-
echo '<div class="wpzerospam-details-data">' . json_encode( $value ) . '</div>';
|
192 |
-
echo '</div>';
|
193 |
-
endswitch;
|
194 |
-
endforeach;
|
195 |
-
};
|
196 |
-
?>
|
197 |
-
</div>
|
198 |
-
</div>
|
199 |
-
<?php
|
200 |
-
return ob_get_clean();
|
201 |
-
break;
|
202 |
-
}
|
203 |
-
}
|
204 |
-
|
205 |
-
// Register bulk actions
|
206 |
-
function get_bulk_actions() {
|
207 |
-
$actions = [
|
208 |
-
'delete' => __( 'Delete', 'zero-spam' ),
|
209 |
-
'delete_all' => __( 'Delete All Entries', 'zero-spam' )
|
210 |
-
];
|
211 |
-
|
212 |
-
return $actions;
|
213 |
-
}
|
214 |
-
|
215 |
-
/**
|
216 |
-
* Define which columns are hidden
|
217 |
-
*
|
218 |
-
* @return Array
|
219 |
-
*/
|
220 |
-
public function get_hidden_columns() {
|
221 |
-
return [];
|
222 |
-
}
|
223 |
-
|
224 |
-
// Get results
|
225 |
-
function prepare_items($args = []) {
|
226 |
-
$this->process_bulk_action();
|
227 |
-
|
228 |
-
$columns = $this->get_columns();
|
229 |
-
$hidden = $this->get_hidden_columns();
|
230 |
-
$sortable = $this->get_sortable_columns();
|
231 |
-
|
232 |
-
$per_page = 50;
|
233 |
-
$current_page = $this->get_pagenum();
|
234 |
-
$offset = $per_page * ( $current_page - 1 );
|
235 |
-
$order = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( $_REQUEST['order'] ) : 'desc';
|
236 |
-
$orderby = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( $_REQUEST['orderby'] ) : 'last_updated';
|
237 |
-
|
238 |
-
$user_ip = ! empty( $_REQUEST['s'] ) ? sanitize_text_field( $_REQUEST['s'] ) : false;
|
239 |
-
$blacklist_service = ! empty( $_REQUEST['service'] ) ? sanitize_text_field( $_REQUEST['service'] ) : false;
|
240 |
-
|
241 |
-
$query_args = [
|
242 |
-
'limit' => $per_page,
|
243 |
-
'offset' => $offset,
|
244 |
-
'order' => $order,
|
245 |
-
'orderby' => $orderby
|
246 |
-
];
|
247 |
-
|
248 |
-
if ( $blacklist_service || $user_ip ) {
|
249 |
-
$query_args['where'] = [];
|
250 |
-
|
251 |
-
if ( $blacklist_service ) {
|
252 |
-
$query_args['where']['blacklist_service'] = $blacklist_service;
|
253 |
-
}
|
254 |
-
|
255 |
-
if ( $user_ip ) {
|
256 |
-
$query_args['where']['user_ip'] = $user_ip;
|
257 |
-
}
|
258 |
-
}
|
259 |
-
|
260 |
-
$data = wpzerospam_query( 'blacklist', $query_args );
|
261 |
-
if ( ! $data ) { return false; }
|
262 |
-
|
263 |
-
// Set the $_SERVER['REQUEST_URI'] for paging
|
264 |
-
wpzerospam_set_list_table_request_uri( $query_args );
|
265 |
-
|
266 |
-
$total_items = wpzerospam_query( 'blacklist', $query_args, true );
|
267 |
-
|
268 |
-
$this->set_pagination_args([
|
269 |
-
'total_items' => $total_items,
|
270 |
-
'per_page' => $per_page,
|
271 |
-
'total_pages' => ceil( $total_items / $per_page ),
|
272 |
-
'orderby' => $orderby,
|
273 |
-
'order' => $order
|
274 |
-
]);
|
275 |
-
|
276 |
-
$this->_column_headers = [ $columns, $hidden, $sortable ];
|
277 |
-
$this->items = $data;
|
278 |
-
}
|
279 |
-
|
280 |
-
// Process bulk actions
|
281 |
-
function process_bulk_action() {
|
282 |
-
global $wpdb;
|
283 |
-
|
284 |
-
$ids = ( isset( $_REQUEST['ids'] ) ) ? $_REQUEST['ids'] : '';
|
285 |
-
|
286 |
-
switch( $this->current_action() ) {
|
287 |
-
// Delete
|
288 |
-
case 'delete':
|
289 |
-
// Delete query
|
290 |
-
$nonce = ( isset( $_REQUEST['wpzerospam_nonce'] ) ) ? $_REQUEST['wpzerospam_nonce'] : '';
|
291 |
-
if ( ! wp_verify_nonce( $nonce, 'wpzerospam_nonce' ) ) return false;
|
292 |
-
|
293 |
-
if ( ! empty ( $ids ) && is_array( $ids ) ) {
|
294 |
-
// Delete query
|
295 |
-
foreach( $ids as $k => $blacklist_id ) {
|
296 |
-
$wpdb->delete( wpzerospam_tables( 'blacklist' ), [ 'blacklist_id' => $blacklist_id ] );
|
297 |
-
}
|
298 |
-
}
|
299 |
-
break;
|
300 |
-
case 'delete_all':
|
301 |
-
$wpdb->query( "TRUNCATE TABLE " . wpzerospam_tables( 'blacklist' ) );
|
302 |
-
break;
|
303 |
-
}
|
304 |
-
}
|
305 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/class-wpzerospam-blocked-ip-table.php
DELETED
@@ -1,260 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* WordPress Zero Spam blocked IP table
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.0.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
|
10 |
-
|
11 |
-
if ( ! class_exists( 'WP_List_Table' ) ) {
|
12 |
-
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
|
13 |
-
}
|
14 |
-
|
15 |
-
class WPZeroSpam_Blocked_IP_Table extends WP_List_Table {
|
16 |
-
function __construct() {
|
17 |
-
global $status, $page;
|
18 |
-
|
19 |
-
$args = [
|
20 |
-
'singular' => __( 'Blocked IP', 'zero-spam' ),
|
21 |
-
'plural' => __( 'Blocked IPs', 'zero-spam' ),
|
22 |
-
'ajax' => true
|
23 |
-
];
|
24 |
-
parent::__construct( $args );
|
25 |
-
}
|
26 |
-
|
27 |
-
// Register columns
|
28 |
-
function get_columns() {
|
29 |
-
// Render a checkbox instead of text
|
30 |
-
$columns = [
|
31 |
-
'cb' => '<input type="checkbox" />',
|
32 |
-
'user_ip' => __( 'IP Address', 'zero-spam' ),
|
33 |
-
'blocked_type' => __( 'Type', 'zero-spam' ),
|
34 |
-
'date_added' => __( 'Date Added', 'zero-spam' ),
|
35 |
-
'start_block' => __( 'Start Date', 'zero-spam' ),
|
36 |
-
'end_block' => __( 'End Date', 'zero-spam' ),
|
37 |
-
'reason' => __( 'Reason', 'zero-spam' ),
|
38 |
-
'attempts' => __( 'Attempts', 'zero-spam' ),
|
39 |
-
];
|
40 |
-
|
41 |
-
return $columns;
|
42 |
-
}
|
43 |
-
|
44 |
-
// Sortable columns
|
45 |
-
function get_sortable_columns() {
|
46 |
-
$sortable_columns = [
|
47 |
-
'user_ip' => [ 'user_ip', false ],
|
48 |
-
'blocked_type' => [ 'blocked_type', false ],
|
49 |
-
'date_added' => [ 'date_added', false ],
|
50 |
-
'start_block' => [ 'start_block', false ],
|
51 |
-
'end_block' => [ 'end_block', false ],
|
52 |
-
'attempts' => [ 'attempts', false ],
|
53 |
-
];
|
54 |
-
|
55 |
-
return $sortable_columns;
|
56 |
-
}
|
57 |
-
|
58 |
-
function extra_tablenav( $which ) {
|
59 |
-
global $cat_id;
|
60 |
-
|
61 |
-
if ( 'top' !== $which ) {
|
62 |
-
return;
|
63 |
-
}
|
64 |
-
?>
|
65 |
-
<div class="alignleft actions">
|
66 |
-
<?php
|
67 |
-
echo '<label class="screen-reader-text" for="filter-by-type">' . __( 'Filter by type', 'zero-spam' ) . '</label>';
|
68 |
-
$current_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
|
69 |
-
?>
|
70 |
-
<select name="type" id="filter-by-type">
|
71 |
-
<option value=""><?php _e( 'All types', 'zero-spam' ); ?></option>
|
72 |
-
<option<?php if ( $current_type == 'permanent' ): ?> selected="selected" <?php endif; ?> value="permanent"><?php _e( 'Permanent', 'zero-spam' ); ?></option>
|
73 |
-
<option<?php if ( $current_type == 'temporary' ): ?> selected="selected" <?php endif; ?> value="temporary"><?php _e( 'Temporary', 'zero-spam' ); ?></option>
|
74 |
-
</select>
|
75 |
-
<?php
|
76 |
-
submit_button( __( 'Filter', 'zero-spam' ), '', 'filter_action', false );
|
77 |
-
?>
|
78 |
-
</div>
|
79 |
-
<?php
|
80 |
-
}
|
81 |
-
|
82 |
-
// Checkbox column
|
83 |
-
function column_cb( $item ){
|
84 |
-
return sprintf(
|
85 |
-
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
|
86 |
-
/*$1%s*/ 'ids',
|
87 |
-
/*$2%s*/ $item->blocked_id
|
88 |
-
);
|
89 |
-
}
|
90 |
-
|
91 |
-
// Render column
|
92 |
-
function column_default( $item, $column_name ) {
|
93 |
-
switch( $column_name ) {
|
94 |
-
case 'user_ip':
|
95 |
-
return '<a href="https://zerospam.org/ip-lookup/' . urlencode( $item->user_ip ) .'" target="_blank" rel="noopener noreferrer">' . $item->user_ip . '</a>';
|
96 |
-
break;
|
97 |
-
case 'blocked_id':
|
98 |
-
return $item->blocked_id;
|
99 |
-
break;
|
100 |
-
case 'blocked_type':
|
101 |
-
switch( $item->blocked_type ) {
|
102 |
-
case 'permanent':
|
103 |
-
return '<span class="wpzerospam-blocked">' . __( 'Permanent', 'zero-spam' ) . '</span>';
|
104 |
-
break;
|
105 |
-
case 'temporary':
|
106 |
-
return '<span class="wpzerospam-warning">' . __( 'Temporary', 'zero-spam' ) . '</span>';
|
107 |
-
break;
|
108 |
-
default:
|
109 |
-
return $item->blocked_type;
|
110 |
-
}
|
111 |
-
break;
|
112 |
-
case 'date_added':
|
113 |
-
return date( 'M j, Y g:ia' , strtotime( $item->date_added ) );
|
114 |
-
break;
|
115 |
-
case 'start_block':
|
116 |
-
if ( ! $item->start_block || '0000-00-00 00:00:00' == $item->start_block || 'permanent' == $item->blocked_type ) {
|
117 |
-
return 'N/A';
|
118 |
-
}
|
119 |
-
|
120 |
-
return date( 'M j, Y g:ia' , strtotime( $item->start_block ) );
|
121 |
-
break;
|
122 |
-
case 'end_block':
|
123 |
-
if ( ! $item->end_block || '0000-00-00 00:00:00' == $item->end_block || 'permanent' == $item->blocked_type ) {
|
124 |
-
return 'N/A';
|
125 |
-
}
|
126 |
-
|
127 |
-
return date( 'M j, Y g:ia' , strtotime( $item->end_block ) );
|
128 |
-
break;
|
129 |
-
case 'reason':
|
130 |
-
if ( ! $item->reason ) {
|
131 |
-
return 'N/A';
|
132 |
-
}
|
133 |
-
|
134 |
-
switch( $item->reason ) {
|
135 |
-
case 'comment (permanently auto-blocked)':
|
136 |
-
return sprintf(
|
137 |
-
wp_kses(
|
138 |
-
__( 'Comment <span class="wpzerospam-small">(<strong>permanently</strong> auto-blocked)</span>', 'zero-spam' ),
|
139 |
-
[ 'span' => [ 'class' => [] ], 'strong' => [] ]
|
140 |
-
)
|
141 |
-
);
|
142 |
-
break;
|
143 |
-
case 'comment (auto-blocked)':
|
144 |
-
return sprintf(
|
145 |
-
wp_kses(
|
146 |
-
__( 'Comment <span class="wpzerospam-small">(auto-blocked)</span>', 'zero-spam' ),
|
147 |
-
[ 'span' => [ 'class' => [] ] ]
|
148 |
-
)
|
149 |
-
);
|
150 |
-
break;
|
151 |
-
default:
|
152 |
-
return $item->reason;
|
153 |
-
}
|
154 |
-
break;
|
155 |
-
case 'attempts':
|
156 |
-
return $item->attempts;
|
157 |
-
break;
|
158 |
-
}
|
159 |
-
}
|
160 |
-
|
161 |
-
// Register bulk actions
|
162 |
-
function get_bulk_actions() {
|
163 |
-
$actions = [
|
164 |
-
'delete' => __( 'Delete', 'zero-spam' ),
|
165 |
-
'delete_all' => __( 'Delete All Entries', 'zero-spam' )
|
166 |
-
];
|
167 |
-
|
168 |
-
return $actions;
|
169 |
-
}
|
170 |
-
|
171 |
-
/**
|
172 |
-
* Define which columns are hidden
|
173 |
-
*
|
174 |
-
* @return Array
|
175 |
-
*/
|
176 |
-
public function get_hidden_columns() {
|
177 |
-
return [];
|
178 |
-
}
|
179 |
-
|
180 |
-
// Get results
|
181 |
-
function prepare_items($args = []) {
|
182 |
-
$this->process_bulk_action();
|
183 |
-
|
184 |
-
$columns = $this->get_columns();
|
185 |
-
$hidden = $this->get_hidden_columns();
|
186 |
-
$sortable = $this->get_sortable_columns();
|
187 |
-
|
188 |
-
$per_page = 50;
|
189 |
-
$current_page = $this->get_pagenum();
|
190 |
-
$offset = $per_page * ( $current_page - 1 );
|
191 |
-
$order = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( $_REQUEST['order'] ) : 'desc';
|
192 |
-
$orderby = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( $_REQUEST['orderby'] ) : 'date_added';
|
193 |
-
|
194 |
-
$user_ip = ! empty( $_REQUEST['s'] ) ? sanitize_text_field( $_REQUEST['s'] ) : false;
|
195 |
-
$blocked_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
|
196 |
-
|
197 |
-
$query_args = [
|
198 |
-
'limit' => $per_page,
|
199 |
-
'offset' => $offset,
|
200 |
-
'order' => $order,
|
201 |
-
'orderby' => $orderby
|
202 |
-
];
|
203 |
-
|
204 |
-
if ( $blocked_type || $user_ip ) {
|
205 |
-
$query_args['where'] = [];
|
206 |
-
|
207 |
-
if ( $blocked_type ) {
|
208 |
-
$query_args['where']['blocked_type'] = $blocked_type;
|
209 |
-
}
|
210 |
-
|
211 |
-
if ( $user_ip ) {
|
212 |
-
$query_args['where']['user_ip'] = $user_ip;
|
213 |
-
}
|
214 |
-
}
|
215 |
-
|
216 |
-
$data = wpzerospam_query( 'blocked', $query_args );
|
217 |
-
if ( ! $data ) { return false; }
|
218 |
-
|
219 |
-
// Set the $_SERVER['REQUEST_URI'] for paging
|
220 |
-
wpzerospam_set_list_table_request_uri( $query_args );
|
221 |
-
|
222 |
-
$total_items = wpzerospam_query( 'blocked', $query_args, true );
|
223 |
-
|
224 |
-
$this->set_pagination_args([
|
225 |
-
'total_items' => $total_items,
|
226 |
-
'per_page' => $per_page,
|
227 |
-
'total_pages' => ceil( $total_items / $per_page ),
|
228 |
-
'orderby' => $orderby,
|
229 |
-
'order' => $order
|
230 |
-
]);
|
231 |
-
|
232 |
-
$this->_column_headers = [ $columns, $hidden, $sortable ];
|
233 |
-
$this->items = $data;
|
234 |
-
}
|
235 |
-
|
236 |
-
// Process bulk actions
|
237 |
-
function process_bulk_action() {
|
238 |
-
global $wpdb;
|
239 |
-
|
240 |
-
$ids = ( isset( $_REQUEST['ids'] ) ) ? $_REQUEST['ids'] : '';
|
241 |
-
|
242 |
-
switch( $this->current_action() ) {
|
243 |
-
// Delete
|
244 |
-
case 'delete':
|
245 |
-
$nonce = ( isset( $_REQUEST['wpzerospam_nonce'] ) ) ? $_REQUEST['wpzerospam_nonce'] : '';
|
246 |
-
if ( ! wp_verify_nonce( $nonce, 'wpzerospam_nonce' ) ) return false;
|
247 |
-
|
248 |
-
if ( ! empty ( $ids ) && is_array( $ids ) ) {
|
249 |
-
// Delete query
|
250 |
-
foreach( $ids as $k => $blocked_id ) {
|
251 |
-
$wpdb->delete( wpzerospam_tables( 'blocked' ), [ 'blocked_id' => $blocked_id ] );
|
252 |
-
}
|
253 |
-
}
|
254 |
-
break;
|
255 |
-
case 'delete_all':
|
256 |
-
$wpdb->query( "TRUNCATE TABLE " . wpzerospam_tables( 'blocked' ) );
|
257 |
-
break;
|
258 |
-
}
|
259 |
-
}
|
260 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/class-wpzerospam-comments.php
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* WordPress Zero Spam comments class.
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
*/
|
7 |
-
|
8 |
-
// Security Note: Blocks direct access to the plugin PHP files.
|
9 |
-
defined( 'ABSPATH' ) || die();
|
10 |
-
|
11 |
-
/**
|
12 |
-
* WordPress Zero Spam comments class.
|
13 |
-
*/
|
14 |
-
class WPZeroSpam_Comments {
|
15 |
-
|
16 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/class-wpzerospam-log-table.php
DELETED
@@ -1,371 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* WordPress Zero Spam log table
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.0.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
|
10 |
-
|
11 |
-
if ( ! class_exists( 'WP_List_Table' ) ) {
|
12 |
-
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
|
13 |
-
}
|
14 |
-
|
15 |
-
class WPZeroSpam_Log_Table extends WP_List_Table {
|
16 |
-
function __construct() {
|
17 |
-
global $status, $page;
|
18 |
-
|
19 |
-
$args = [
|
20 |
-
'singular' => __( 'Spam Detection', 'zero-spam' ),
|
21 |
-
'plural' => __( 'Spam Detections', 'zero-spam' ),
|
22 |
-
'ajax' => true
|
23 |
-
];
|
24 |
-
parent::__construct( $args );
|
25 |
-
}
|
26 |
-
|
27 |
-
// Register columns
|
28 |
-
function get_columns() {
|
29 |
-
// Render a checkbox instead of text
|
30 |
-
$columns = [
|
31 |
-
'cb' => '<input type="checkbox" />',
|
32 |
-
'date_recorded' => __( 'Date', 'zero-spam' ),
|
33 |
-
'log_type' => __( 'Type', 'zero-spam' ),
|
34 |
-
'user_ip' => __( 'IP Address', 'zero-spam' ),
|
35 |
-
'country' => __( 'Country', 'zero-spam' ),
|
36 |
-
'region' => __( 'Region', 'zero-spam' ),
|
37 |
-
'city' => __( 'City', 'zero-spam' ),
|
38 |
-
'details' => __( 'Details', 'zero-spam' ),
|
39 |
-
'actions' => __( 'Block IP', 'zero-spam' ),
|
40 |
-
];
|
41 |
-
|
42 |
-
return $columns;
|
43 |
-
}
|
44 |
-
|
45 |
-
// Sortable columns
|
46 |
-
function get_sortable_columns() {
|
47 |
-
$sortable_columns = [
|
48 |
-
'date_recorded' => [ 'date_recorded', false ],
|
49 |
-
'log_type' => [ 'log_type', false ],
|
50 |
-
'user_ip' => [ 'user_ip', false ],
|
51 |
-
'country' => [ 'country', false ],
|
52 |
-
'region' => [ 'region', false ],
|
53 |
-
'city' => [ 'city', false ],
|
54 |
-
];
|
55 |
-
|
56 |
-
return $sortable_columns;
|
57 |
-
}
|
58 |
-
|
59 |
-
function extra_tablenav( $which ) {
|
60 |
-
global $cat_id;
|
61 |
-
|
62 |
-
if ( 'top' !== $which ) {
|
63 |
-
return;
|
64 |
-
}
|
65 |
-
?>
|
66 |
-
<div class="alignleft actions">
|
67 |
-
<?php
|
68 |
-
echo '<label class="screen-reader-text" for="filter-by-type">' . __( 'Filter by type', 'zero-spam' ) . '</label>';
|
69 |
-
$options = wpzerospam_types();
|
70 |
-
$current_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
|
71 |
-
?>
|
72 |
-
<select name="type" id="filter-by-type">
|
73 |
-
<option value=""><?php _e( 'All types', 'zero-spam' ); ?></option>
|
74 |
-
<?php foreach( $options as $key => $value ): ?>
|
75 |
-
<option<?php if ( $current_type == $key ): ?> selected="selected" <?php endif; ?> value="<?php echo $key; ?>"><?php echo $value; ?></option>
|
76 |
-
<?php endforeach; ?>
|
77 |
-
</select>
|
78 |
-
<?php
|
79 |
-
submit_button( __( 'Filter', 'zero-spam' ), '', 'filter_action', false );
|
80 |
-
?>
|
81 |
-
</div>
|
82 |
-
<?php
|
83 |
-
}
|
84 |
-
|
85 |
-
// Checkbox column
|
86 |
-
function column_cb( $item ){
|
87 |
-
return sprintf(
|
88 |
-
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
|
89 |
-
/*$1%s*/ 'ids',
|
90 |
-
/*$2%s*/ $item->log_id
|
91 |
-
);
|
92 |
-
}
|
93 |
-
|
94 |
-
// Render column
|
95 |
-
function column_default( $item, $column_name ) {
|
96 |
-
switch( $column_name ) {
|
97 |
-
case 'actions':
|
98 |
-
if ( wpzerospam_is_blocked( $item->user_ip ) ) {
|
99 |
-
return '<span class="wpzerospam-blocked">' . __( 'Blocked', 'zero-spam' ) . '</span>';
|
100 |
-
} else {
|
101 |
-
return '<a class="button" href="' . admin_url( 'admin.php?page=wordpress-zero-spam-blocked-ips&ip=' . $item->user_ip ) . '">' . __( 'Block IP', 'zero-spam' ) . '</a>';
|
102 |
-
}
|
103 |
-
break;
|
104 |
-
case 'log_id':
|
105 |
-
return $item->log_id;
|
106 |
-
break;
|
107 |
-
case 'log_type':
|
108 |
-
return '<span class="wpzerospam-' . $item->log_type . '">' . wpzerospam_types( $item->log_type ) . '</span>';
|
109 |
-
break;
|
110 |
-
case 'user_ip':
|
111 |
-
return '<a href="https://zerospam.org/ip-lookup/' . urlencode( $item->user_ip ) .'" target="_blank" rel="noopener noreferrer">' . $item->user_ip . '</a>';
|
112 |
-
break;
|
113 |
-
case 'date_recorded':
|
114 |
-
return date( 'M j, Y g:ia' , strtotime( $item->date_recorded ) );
|
115 |
-
break;
|
116 |
-
case 'country':
|
117 |
-
if ( ! $item->country ) {
|
118 |
-
return 'N/A';
|
119 |
-
}
|
120 |
-
|
121 |
-
return '<img class="wpzerospam-country-flag" width="16" src="https://hatscripts.github.io/circle-flags/flags/' . strtolower( $item->country ) . '.svg" alt="' . wpzerospam_get_location( $item->country ) .'" /> ' . wpzerospam_get_location( $item->country );
|
122 |
-
break;
|
123 |
-
case 'region':
|
124 |
-
$region = wpzerospam_get_location( $item->country, $item->region );
|
125 |
-
if ( $region ) {
|
126 |
-
return $region;
|
127 |
-
} else if ( ! empty( $item->region) ) {
|
128 |
-
return $item->region;
|
129 |
-
}
|
130 |
-
|
131 |
-
return 'N/A';
|
132 |
-
break;
|
133 |
-
case 'city':
|
134 |
-
if ( ! $item->city ) {
|
135 |
-
return 'N/A';
|
136 |
-
}
|
137 |
-
return $item->city;
|
138 |
-
break;
|
139 |
-
case 'details':
|
140 |
-
if ( empty( $item->submission_data ) ) { return __( 'No details available.', 'zero-spam' ); }
|
141 |
-
ob_start();
|
142 |
-
?>
|
143 |
-
<button class="button action wpzerospam-details-trigger" data-id="<?php echo $item->log_id; ?>"><?php _e( 'View', 'zero-spam' ); ?></button>
|
144 |
-
<div class="wpzerospam-details-modal" id="wpzerospam-details-modal-<?php echo $item->log_id; ?>">
|
145 |
-
<div class="wpzerospam-details-modal-inner">
|
146 |
-
<?php
|
147 |
-
echo '<div class="wpzerospam-details-item">';
|
148 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Detected Spam IP', 'zero-spam' ) . '</div>';
|
149 |
-
echo '<div class="wpzerospam-details-data">' . '<a href="https://whatismyipaddress.com/ip/' . $item->user_ip .'" target="_blank" rel="noopener noreferrer">' . $item->user_ip . '</a></div>';
|
150 |
-
echo '</div>';
|
151 |
-
|
152 |
-
echo '<div class="wpzerospam-details-item">';
|
153 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Page URL', 'zero-spam' ) . '</div>';
|
154 |
-
echo '<div class="wpzerospam-details-data"><a href="' . esc_url( $item->page_url ) . '" target="_blank" rel="noreferrer noopener">' . $item->page_url . '</a></div>';
|
155 |
-
echo '</div>';
|
156 |
-
|
157 |
-
echo '<div class="wpzerospam-details-item">';
|
158 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Date', 'zero-spam' ) . '</div>';
|
159 |
-
echo '<div class="wpzerospam-details-data">' . date( 'M j, Y g:ia' , strtotime( $item->date_recorded ) ) . '</div>';
|
160 |
-
echo '</div>';
|
161 |
-
|
162 |
-
echo '<div class="wpzerospam-details-item">';
|
163 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Type', 'zero-spam' ) . '</div>';
|
164 |
-
echo '<div class="wpzerospam-details-data">' . wpzerospam_types( $item->log_type ) . '</div>';
|
165 |
-
echo '</div>';
|
166 |
-
|
167 |
-
if ( $item->country ) {
|
168 |
-
echo '<div class="wpzerospam-details-item">';
|
169 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Country', 'zero-spam' ) . '</div>';
|
170 |
-
echo '<div class="wpzerospam-details-data">' . wpzerospam_get_location( $item->country ) . '</div>';
|
171 |
-
echo '</div>';
|
172 |
-
}
|
173 |
-
|
174 |
-
if ( $item->region ) {
|
175 |
-
echo '<div class="wpzerospam-details-item">';
|
176 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Region', 'zero-spam' ) . '</div>';
|
177 |
-
echo '<div class="wpzerospam-details-data">' . wpzerospam_get_location( $item->country, $item->region ) . '</div>';
|
178 |
-
echo '</div>';
|
179 |
-
}
|
180 |
-
|
181 |
-
if ( $item->city ) {
|
182 |
-
echo '<div class="wpzerospam-details-item">';
|
183 |
-
echo '<div class="wpzerospam-details-label">' . __( 'City', 'zero-spam' ) . '</div>';
|
184 |
-
echo '<div class="wpzerospam-details-data">' . $item->city . '</div>';
|
185 |
-
echo '</div>';
|
186 |
-
}
|
187 |
-
|
188 |
-
if ( ! empty( $item->submission_data ) ) {
|
189 |
-
$submission_data = json_decode( $item->submission_data, true );
|
190 |
-
|
191 |
-
foreach( $submission_data as $key => $value ):
|
192 |
-
if ( ! $value ) { continue; }
|
193 |
-
|
194 |
-
do_action( 'wpzerospam_admin_submission_data_items', $key, $value );
|
195 |
-
|
196 |
-
switch( $key ):
|
197 |
-
case 'reason':
|
198 |
-
echo '<div class="wpzerospam-details-item">';
|
199 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Reason', 'zero-spam' ) . '</div>';
|
200 |
-
echo '<div class="wpzerospam-details-data">' . $value . '</div>';
|
201 |
-
echo '</div>';
|
202 |
-
break;
|
203 |
-
|
204 |
-
// Formidable fields
|
205 |
-
case 'frm_action':
|
206 |
-
echo '<div class="wpzerospam-details-item">';
|
207 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Form Action', 'zero-spam' ) . '</div>';
|
208 |
-
echo '<div class="wpzerospam-details-data">' . $value . '</div>';
|
209 |
-
echo '</div>';
|
210 |
-
break;
|
211 |
-
case 'form_id':
|
212 |
-
echo '<div class="wpzerospam-details-item">';
|
213 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Form ID', 'zero-spam' ) . '</div>';
|
214 |
-
echo '<div class="wpzerospam-details-data">' . $value . '</div>';
|
215 |
-
echo '</div>';
|
216 |
-
break;
|
217 |
-
case 'form_key':
|
218 |
-
echo '<div class="wpzerospam-details-item">';
|
219 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Form Key', 'zero-spam' ) . '</div>';
|
220 |
-
echo '<div class="wpzerospam-details-data">' . $value . '</div>';
|
221 |
-
echo '</div>';
|
222 |
-
break;
|
223 |
-
case 'item_key':
|
224 |
-
echo '<div class="wpzerospam-details-item">';
|
225 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Item Key', 'zero-spam' ) . '</div>';
|
226 |
-
echo '<div class="wpzerospam-details-data">' . $value . '</div>';
|
227 |
-
echo '</div>';
|
228 |
-
break;
|
229 |
-
case 'item_meta':
|
230 |
-
echo '<div class="wpzerospam-details-item">';
|
231 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Form Values', 'zero-spam' ) . '</div>';
|
232 |
-
if ( is_array( $value ) ) {
|
233 |
-
echo '<div class="wpzerospam-details-data">' . implode( ", ", array_filter( $value ) ) . '</div>';
|
234 |
-
} else {
|
235 |
-
echo '<div class="wpzerospam-details-data">' . $value . '</div>';
|
236 |
-
}
|
237 |
-
echo '</div>';
|
238 |
-
break;
|
239 |
-
case '_wp_http_referer':
|
240 |
-
echo '<div class="wpzerospam-details-item">';
|
241 |
-
echo '<div class="wpzerospam-details-label">' . __( 'Source', 'zero-spam' ) . '</div>';
|
242 |
-
if ( $value ) {
|
243 |
-
$source_url = esc_url( site_url( $value ) );
|
244 |
-
echo '<div class="wpzerospam-details-data"><a href="' . $source_url . '" target="_blank" rel="noopener noreferrer">' . $source_url . '</a></div>';
|
245 |
-
} else {
|
246 |
-
echo '<div class="wpzerospam-details-data">N/A</div>';
|
247 |
-
}
|
248 |
-
echo '</div>';
|
249 |
-
break;
|
250 |
-
|
251 |
-
default:
|
252 |
-
$defined_submission_data = apply_filters( 'wpzerospam_defined_submission_data', [] );
|
253 |
-
if ( ! in_array( $key, $defined_submission_data ) ) {
|
254 |
-
echo '<div class="wpzerospam-details-item wpzerospam-details-item-unknown">';
|
255 |
-
echo '<div class="wpzerospam-details-label">' . $key . '</div>';
|
256 |
-
echo '<div class="wpzerospam-details-data">' . json_encode( $value ) . '</div>';
|
257 |
-
echo '</div>';
|
258 |
-
}
|
259 |
-
endswitch;
|
260 |
-
endforeach;
|
261 |
-
};
|
262 |
-
?>
|
263 |
-
</div>
|
264 |
-
</div>
|
265 |
-
<?php
|
266 |
-
return ob_get_clean();
|
267 |
-
break;
|
268 |
-
}
|
269 |
-
}
|
270 |
-
|
271 |
-
// Register bulk actions
|
272 |
-
function get_bulk_actions() {
|
273 |
-
$actions = [
|
274 |
-
'delete' => __( 'Delete Selected', 'zero-spam' ) ,
|
275 |
-
'delete_all' => __( 'Delete All Entries', 'zero-spam' )
|
276 |
-
];
|
277 |
-
|
278 |
-
return $actions;
|
279 |
-
}
|
280 |
-
|
281 |
-
/**
|
282 |
-
* Define which columns are hidden
|
283 |
-
*
|
284 |
-
* @return Array
|
285 |
-
*/
|
286 |
-
public function get_hidden_columns() {
|
287 |
-
return [];
|
288 |
-
}
|
289 |
-
|
290 |
-
// Get results
|
291 |
-
function prepare_items($args = []) {
|
292 |
-
$this->process_bulk_action();
|
293 |
-
|
294 |
-
$columns = $this->get_columns();
|
295 |
-
$hidden = $this->get_hidden_columns();
|
296 |
-
$sortable = $this->get_sortable_columns();
|
297 |
-
|
298 |
-
$per_page = 50;
|
299 |
-
$current_page = $this->get_pagenum();
|
300 |
-
$offset = $per_page * ( $current_page - 1 );
|
301 |
-
$order = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( $_REQUEST['order'] ) : 'desc';
|
302 |
-
$orderby = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( $_REQUEST['orderby'] ) : 'date_recorded';
|
303 |
-
|
304 |
-
$log_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
|
305 |
-
$user_ip = ! empty( $_REQUEST['s'] ) ? sanitize_text_field( $_REQUEST['s'] ) : false;
|
306 |
-
|
307 |
-
$query_args = [
|
308 |
-
'limit' => $per_page,
|
309 |
-
'offset' => $offset,
|
310 |
-
'order' => $order,
|
311 |
-
'orderby' => $orderby
|
312 |
-
];
|
313 |
-
|
314 |
-
if ( $log_type || $user_ip ) {
|
315 |
-
$query_args['where'] = [];
|
316 |
-
|
317 |
-
if ( $log_type ) {
|
318 |
-
$query_args['where']['log_type'] = $log_type;
|
319 |
-
}
|
320 |
-
|
321 |
-
if ( $user_ip ) {
|
322 |
-
$query_args['where']['user_ip'] = $user_ip;
|
323 |
-
}
|
324 |
-
}
|
325 |
-
|
326 |
-
$data = wpzerospam_query( 'log', $query_args );
|
327 |
-
if ( ! $data ) { return false; }
|
328 |
-
|
329 |
-
// Set the $_SERVER['REQUEST_URI'] for paging
|
330 |
-
wpzerospam_set_list_table_request_uri( $query_args );
|
331 |
-
|
332 |
-
$total_items = wpzerospam_query( 'log', $query_args, true );
|
333 |
-
|
334 |
-
$this->set_pagination_args([
|
335 |
-
'total_items' => $total_items,
|
336 |
-
'per_page' => $per_page,
|
337 |
-
'total_pages' => ceil( $total_items / $per_page ),
|
338 |
-
'orderby' => $orderby,
|
339 |
-
'order' => $order
|
340 |
-
]);
|
341 |
-
|
342 |
-
$this->_column_headers = [ $columns, $hidden, $sortable ];
|
343 |
-
$this->items = $data;
|
344 |
-
}
|
345 |
-
|
346 |
-
// Process bulk actions
|
347 |
-
function process_bulk_action() {
|
348 |
-
global $wpdb;
|
349 |
-
|
350 |
-
$ids = ( isset( $_REQUEST['ids'] ) ) ? $_REQUEST['ids'] : '';
|
351 |
-
|
352 |
-
switch( $this->current_action() ) {
|
353 |
-
// Delete
|
354 |
-
case 'delete':
|
355 |
-
// Delete query
|
356 |
-
$nonce = ( isset( $_REQUEST['wpzerospam_nonce'] ) ) ? $_REQUEST['wpzerospam_nonce'] : '';
|
357 |
-
if ( ! wp_verify_nonce( $nonce, 'wpzerospam_nonce' ) ) return false;
|
358 |
-
|
359 |
-
if ( ! empty ( $ids ) && is_array( $ids ) ) {
|
360 |
-
// Delete query
|
361 |
-
foreach( $ids as $k => $log_id ) {
|
362 |
-
$wpdb->delete( wpzerospam_tables( 'log' ), [ 'log_id' => $log_id ] );
|
363 |
-
}
|
364 |
-
}
|
365 |
-
break;
|
366 |
-
case 'delete_all':
|
367 |
-
$wpdb->query( "TRUNCATE TABLE " . wpzerospam_tables( 'log' ) );
|
368 |
-
break;
|
369 |
-
}
|
370 |
-
}
|
371 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/class-wpzerospam-security.php
DELETED
@@ -1,36 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* WordPress Zero Spam security class.
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
*/
|
7 |
-
|
8 |
-
// Security Note: Blocks direct access to the plugin PHP files.
|
9 |
-
defined( 'ABSPATH' ) || die();
|
10 |
-
|
11 |
-
/**
|
12 |
-
* WordPress Zero Spam security class.
|
13 |
-
*/
|
14 |
-
class WPZeroSpam_Security {
|
15 |
-
/**
|
16 |
-
* Class constructor.
|
17 |
-
*/
|
18 |
-
public function __construct() {
|
19 |
-
// Removes the meta generator tag.
|
20 |
-
add_action( 'after_setup_theme', array( $this, 'after_setup_theme' ) );
|
21 |
-
}
|
22 |
-
|
23 |
-
/**
|
24 |
-
* Removes the meta generator tag.
|
25 |
-
*/
|
26 |
-
public function after_setup_theme() {
|
27 |
-
// Remove the meta generator tag.
|
28 |
-
remove_action( 'wp_head', 'wp_generator' );
|
29 |
-
add_filter(
|
30 |
-
'the_generator',
|
31 |
-
function() {
|
32 |
-
return '';
|
33 |
-
}
|
34 |
-
);
|
35 |
-
}
|
36 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/class-wpzerospam.php
DELETED
@@ -1,977 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* WordPress Zero Spam class.
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
*/
|
7 |
-
|
8 |
-
// Security Note: Blocks direct access to the plugin PHP files.
|
9 |
-
defined( 'ABSPATH' ) || die();
|
10 |
-
|
11 |
-
/**
|
12 |
-
* WordPress Zero Spam class.
|
13 |
-
*/
|
14 |
-
class WPZeroSpam {
|
15 |
-
/**
|
16 |
-
* Contains all plugin options.
|
17 |
-
*
|
18 |
-
* @var array Array of plugin options.
|
19 |
-
*/
|
20 |
-
public $options;
|
21 |
-
|
22 |
-
/**
|
23 |
-
* The default core plugin options.
|
24 |
-
*
|
25 |
-
* @var array Array of core plugin options.
|
26 |
-
*/
|
27 |
-
public $default_options = array(
|
28 |
-
'debug' => 'disabled',
|
29 |
-
'ip_whitelist' => '',
|
30 |
-
'cookie_expiration' => 7,
|
31 |
-
'log_spam' => false,
|
32 |
-
'log_blocked_ips' => false,
|
33 |
-
'share_detections' => true,
|
34 |
-
'stop_forum_spam' => 'enabled',
|
35 |
-
'stopforumspam_confidence_min' => 20,
|
36 |
-
'botscout_count_min' => 5,
|
37 |
-
'botscout_api' => false,
|
38 |
-
'api_timeout' => 5,
|
39 |
-
'block_handler' => 403,
|
40 |
-
'blocked_redirect_url' => 'https://google.com',
|
41 |
-
'blocked_message' => false,
|
42 |
-
'ipstack_api' => false,
|
43 |
-
);
|
44 |
-
|
45 |
-
/**
|
46 |
-
* The current user's IP address.
|
47 |
-
*
|
48 |
-
* @var string The current user's IP address.
|
49 |
-
*/
|
50 |
-
public $current_user_ip;
|
51 |
-
|
52 |
-
/**
|
53 |
-
* The current user's IP address access.
|
54 |
-
*
|
55 |
-
* @var array IP address access details.
|
56 |
-
*/
|
57 |
-
public $current_user_ip_access;
|
58 |
-
|
59 |
-
/**
|
60 |
-
* Database tables.
|
61 |
-
*
|
62 |
-
* @var array Array of plugin database tables.
|
63 |
-
*/
|
64 |
-
public $tables;
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Class constructor.
|
68 |
-
*/
|
69 |
-
public function __construct() {
|
70 |
-
global $wpdb;
|
71 |
-
|
72 |
-
// Set the database tables.
|
73 |
-
$this->tables = array(
|
74 |
-
'log' => $wpdb->prefix . 'wpzerospam_log',
|
75 |
-
'blocked' => $wpdb->prefix . 'wpzerospam_blocked',
|
76 |
-
'blacklist' => $wpdb->prefix . 'wpzerospam_blacklist',
|
77 |
-
);
|
78 |
-
}
|
79 |
-
|
80 |
-
/**
|
81 |
-
* Initializes the plugin.
|
82 |
-
*/
|
83 |
-
public function initialize() {
|
84 |
-
// Triggered on the WP init action.
|
85 |
-
add_action( 'init', array( $this, 'wp_init' ) );
|
86 |
-
|
87 |
-
// Triggered on the WP wp_footer action.
|
88 |
-
add_action( 'wp_footer', array( $this, 'wp_footer' ) );
|
89 |
-
|
90 |
-
// Triggered on he WP plugins_loaded action.
|
91 |
-
add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ) );
|
92 |
-
|
93 |
-
// Handles IPs that have been denied access.
|
94 |
-
add_action( 'template_redirect', array( $this, 'access_check' ) );
|
95 |
-
}
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Loads the plugin text domain.
|
99 |
-
*/
|
100 |
-
public function plugins_loaded() {
|
101 |
-
load_plugin_textdomain( 'zero-spam', '', basename( dirname( WORDPRESS_ZERO_SPAM ) ) . '/languages/' );
|
102 |
-
}
|
103 |
-
|
104 |
-
/**
|
105 |
-
* Checks is an IP is safe (i.e. from a known bot or crawler)
|
106 |
-
*/
|
107 |
-
public function is_known_safe_ip() {
|
108 |
-
$safe_hosts = array(
|
109 |
-
'googlebot.com',
|
110 |
-
'google.com',
|
111 |
-
'search.msn.com',
|
112 |
-
'bing.com',
|
113 |
-
'yahoo.com',
|
114 |
-
'duckduckgo.com',
|
115 |
-
'baidu.com',
|
116 |
-
'yandex.com',
|
117 |
-
'exabot.com',
|
118 |
-
'facebook.com',
|
119 |
-
'alexa.com',
|
120 |
-
);
|
121 |
-
|
122 |
-
$safe_user_agents = array(
|
123 |
-
'Googlebot',
|
124 |
-
'Bingbot',
|
125 |
-
'Slurp',
|
126 |
-
'DuckDuckBot',
|
127 |
-
'Baiduspider',
|
128 |
-
'YandexBot',
|
129 |
-
'facebot',
|
130 |
-
'ia_archiver',
|
131 |
-
);
|
132 |
-
|
133 |
-
if ( ! $this->current_user_ip ) {
|
134 |
-
return false;
|
135 |
-
}
|
136 |
-
|
137 |
-
$ip_host = gethostbyaddr( $this->current_user_ip );
|
138 |
-
$user_agent = ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? esc_html( $_SERVER['HTTP_USER_AGENT'] ) : false;
|
139 |
-
|
140 |
-
if ( ! $ip_host || ! $user_agent ) {
|
141 |
-
return false;
|
142 |
-
}
|
143 |
-
|
144 |
-
// 1. Check hostnames.
|
145 |
-
foreach ( $safe_hosts as $key => $host ) {
|
146 |
-
if ( stripos( $ip_host, $host ) !== false ) {
|
147 |
-
return true;
|
148 |
-
}
|
149 |
-
}
|
150 |
-
|
151 |
-
// 2. Check user agents.
|
152 |
-
foreach ( $safe_user_agents as $key => $agent ) {
|
153 |
-
if ( stripos( $user_agent, $agent ) !== false ) {
|
154 |
-
return true;
|
155 |
-
}
|
156 |
-
}
|
157 |
-
|
158 |
-
return false;
|
159 |
-
}
|
160 |
-
|
161 |
-
/**
|
162 |
-
* Checks an IP access.
|
163 |
-
*
|
164 |
-
* @param string $ip The IP address to check.
|
165 |
-
*/
|
166 |
-
public function get_access( $ip ) {
|
167 |
-
$access = array(
|
168 |
-
'ip_checked' => $ip,
|
169 |
-
'has_access' => true,
|
170 |
-
'access_checked' => false,
|
171 |
-
'cached' => false,
|
172 |
-
'blacklist_api' => false,
|
173 |
-
'attempts' => false,
|
174 |
-
);
|
175 |
-
|
176 |
-
if ( ! $ip ) {
|
177 |
-
return $access;
|
178 |
-
}
|
179 |
-
|
180 |
-
// Ignore logged in users.
|
181 |
-
if ( is_user_logged_in() ) {
|
182 |
-
$access['access_checked'] = 'authenticated';
|
183 |
-
return $this->set_access_cookies( $access );
|
184 |
-
}
|
185 |
-
|
186 |
-
// 1. Check if an access check has already been ran for this IP.
|
187 |
-
if ( $this->get_cookie( 'access_checked' ) && $this->get_cookie( 'ip_checked' ) === $ip ) {
|
188 |
-
// IP has already been checked, return the saved access.
|
189 |
-
foreach ( $access as $key => $value ) {
|
190 |
-
$access[ $key ] = $this->get_cookie( $key );
|
191 |
-
}
|
192 |
-
|
193 |
-
$access['cached'] = 'cookie';
|
194 |
-
|
195 |
-
return $this->set_access_cookies( $access );
|
196 |
-
}
|
197 |
-
|
198 |
-
// 2. Check known/safe hosts (i.e. Google crawlers, etc.)
|
199 |
-
if ( $this->is_known_safe_ip( $ip ) ) {
|
200 |
-
$access['access_checked'] = 'safe_ip';
|
201 |
-
|
202 |
-
return $this->set_access_cookies( $access );
|
203 |
-
}
|
204 |
-
|
205 |
-
// 3. Check the whitelisted IP addresses.
|
206 |
-
$whitelisted_ips = $this->get_whitelisted_ips();
|
207 |
-
|
208 |
-
if ( array_key_exists( $ip, $whitelisted_ips ) ) {
|
209 |
-
// IP address found in the whitelist.
|
210 |
-
$access['access_checked'] = 'whitelisted';
|
211 |
-
|
212 |
-
return $this->set_access_cookies( $access );
|
213 |
-
}
|
214 |
-
|
215 |
-
// 4. Check if IP has been blocked.
|
216 |
-
$blocked_ip = $this->get_blocked_ip( $ip );
|
217 |
-
if ( $blocked_ip ) {
|
218 |
-
$access['attempts'] = $blocked_ip['attempts'];
|
219 |
-
|
220 |
-
// IP has been blocked, check the type.
|
221 |
-
if ( 'permanent' === $blocked_ip['blocked_type'] ) {
|
222 |
-
// Permanent block.
|
223 |
-
$access['access_checked'] = 'permanent_block';
|
224 |
-
$access['has_access'] = false;
|
225 |
-
return $this->set_access_cookies( $access );
|
226 |
-
} else {
|
227 |
-
// Temporary block, check if still valid.
|
228 |
-
if ( $this->is_blocked_ip_active( $blocked_ip ) ) {
|
229 |
-
$access['access_checked'] = 'temporary_block';
|
230 |
-
$access['has_access'] = false;
|
231 |
-
return $this->set_access_cookies( $access );
|
232 |
-
}
|
233 |
-
}
|
234 |
-
}
|
235 |
-
|
236 |
-
// 5. Check if the IP appears on the blacklist.
|
237 |
-
$blacklisted_ip = $this->get_blacklisted_ip( $ip );
|
238 |
-
if ( $blacklisted_ip ) {
|
239 |
-
// IP has been blacklisted, check if it needs updated.
|
240 |
-
$current_datetime = strtotime( current_time( 'mysql' ) );
|
241 |
-
$last_updated = strtotime( $blacklisted_ip['last_updated'] );
|
242 |
-
if ( $current_datetime >= ( $last_updated + MONTH_IN_SECONDS ) ) {
|
243 |
-
// Expired, update the record.
|
244 |
-
$blacklisted_api_ip = $this->get_ip_from_api( $ip, $blacklisted_ip['blacklist_service'] );
|
245 |
-
if ( ! $blacklisted_api_ip ) {
|
246 |
-
// IP not found, delete.
|
247 |
-
$this->delete_blacklisted_ip( $ip );
|
248 |
-
} else {
|
249 |
-
// IP found, update (or delete depending on plugin settings) it.
|
250 |
-
if ( $this->update_blacklisted_ip( $blacklisted_api_ip, 'update' ) ) {
|
251 |
-
$access['has_access'] = false;
|
252 |
-
$access['access_checked'] = 'blacklist';
|
253 |
-
$access['blacklist_api'] = $blacklisted_ip['blacklist_service'];
|
254 |
-
$access['attempts'] = $blacklisted_ip['attempts'];
|
255 |
-
|
256 |
-
return $this->set_access_cookies( $access );
|
257 |
-
}
|
258 |
-
}
|
259 |
-
} else {
|
260 |
-
// Not expired.
|
261 |
-
$access['has_access'] = false;
|
262 |
-
$access['access_checked'] = 'blacklist';
|
263 |
-
$access['blacklist_api'] = $blacklisted_ip['blacklist_service'];
|
264 |
-
$access['attempts'] = $blacklisted_ip['attempts'];
|
265 |
-
|
266 |
-
return $this->set_access_cookies( $access );
|
267 |
-
}
|
268 |
-
}
|
269 |
-
|
270 |
-
// 6. Check the IP against the StopForumSpam API.
|
271 |
-
$blacklisted_api_ip = $this->get_ip_from_api( $ip, 'stopforumspam' );
|
272 |
-
if ( $blacklisted_api_ip && $this->update_blacklisted_ip( $blacklisted_api_ip, 'insert' ) ) {
|
273 |
-
$access['has_access'] = false;
|
274 |
-
$access['access_checked'] = 'blacklist';
|
275 |
-
$access['blacklist_api'] = 'stopforumspam';
|
276 |
-
$access['attempts'] = $blacklisted_api_ip['attempts'];
|
277 |
-
|
278 |
-
return $this->set_access_cookies( $access );
|
279 |
-
}
|
280 |
-
|
281 |
-
// 7. Check the IP against the BotScout API.
|
282 |
-
$blacklisted_api_ip = $this->get_ip_from_api( $ip, 'botscout' );
|
283 |
-
if ( $blacklisted_api_ip && $this->update_blacklisted_ip( $blacklisted_api_ip, 'insert' ) ) {
|
284 |
-
$access['has_access'] = false;
|
285 |
-
$access['access_checked'] = 'blacklist';
|
286 |
-
$access['blacklist_api'] = 'botscout';
|
287 |
-
$access['attempts'] = $blacklisted_api_ip['attempts'];
|
288 |
-
|
289 |
-
return $this->set_access_cookies( $access );
|
290 |
-
}
|
291 |
-
|
292 |
-
return $this->set_access_cookies( $access );
|
293 |
-
}
|
294 |
-
|
295 |
-
/**
|
296 |
-
* Handles IPs that have been denied access.
|
297 |
-
*/
|
298 |
-
public function access_check() {
|
299 |
-
global $wpdb;
|
300 |
-
|
301 |
-
if ( ! $this->current_user_ip_access['has_access'] ) {
|
302 |
-
$block_type = $this->current_user_ip_access['access_checked'];
|
303 |
-
$log_data = array();
|
304 |
-
|
305 |
-
// IP doesn't have access, update attempts.
|
306 |
-
switch ( $block_type ) {
|
307 |
-
case 'temporary_block':
|
308 |
-
case 'permanent_block':
|
309 |
-
case 'blacklist':
|
310 |
-
$log_data['reason'] = $block_type;
|
311 |
-
|
312 |
-
switch ( $block_type ) {
|
313 |
-
case 'temporary_block':
|
314 |
-
case 'permanent_block':
|
315 |
-
$table = 'blocked';
|
316 |
-
break;
|
317 |
-
case 'blacklist':
|
318 |
-
$table = 'blacklist';
|
319 |
-
break;
|
320 |
-
}
|
321 |
-
|
322 |
-
if ( ! $this->current_user_ip_access[ 'attempts' ] ) {
|
323 |
-
$this->current_user_ip_access[ 'attempts' ] = 1;
|
324 |
-
} else {
|
325 |
-
$this->current_user_ip_access[ 'attempts' ]++;
|
326 |
-
}
|
327 |
-
|
328 |
-
$wpdb->update(
|
329 |
-
$this->tables[ $table ],
|
330 |
-
array(
|
331 |
-
'attempts' => $this->current_user_ip_access[ 'attempts' ],
|
332 |
-
),
|
333 |
-
array(
|
334 |
-
'user_ip' => $this->current_user_ip,
|
335 |
-
)
|
336 |
-
);
|
337 |
-
|
338 |
-
$this->set_cookie( 'attempts', $this->current_user_ip_access[ 'attempts' ], 0 );
|
339 |
-
break;
|
340 |
-
}
|
341 |
-
|
342 |
-
// Log the detection.
|
343 |
-
$this->log_detection( 'blocked', $log_data );
|
344 |
-
|
345 |
-
if ( 'redirect' === $this->options['block_handler'] ) {
|
346 |
-
wp_redirect( esc_url( $this->options['blocked_redirect_url'] ) );
|
347 |
-
exit();
|
348 |
-
} else {
|
349 |
-
status_header( 403 );
|
350 |
-
die( $this->options['blocked_message'] );
|
351 |
-
}
|
352 |
-
}
|
353 |
-
}
|
354 |
-
|
355 |
-
/**
|
356 |
-
* Logs a IP detections.
|
357 |
-
*/
|
358 |
-
public function log_detection( $type, $data ) {
|
359 |
-
global $wpdb;
|
360 |
-
|
361 |
-
$record = array(
|
362 |
-
'user_ip' => $this->current_user_ip,
|
363 |
-
'log_type' => $type,
|
364 |
-
'date_recorded' => current_time( 'mysql' ),
|
365 |
-
);
|
366 |
-
|
367 |
-
|
368 |
-
// If sharing detections is enabled, send the detection to Zero Spam.
|
369 |
-
/*if ( 'enabled' === $this->options['share_detections'] ) {
|
370 |
-
$this->share_detection( $record['user_ip'], $record['log_type'] );
|
371 |
-
}*/
|
372 |
-
|
373 |
-
// Check if logging detections & 'blocks' are enabled.
|
374 |
-
if (
|
375 |
-
'enabled' !== $this->options['log_spam'] ||
|
376 |
-
( 'blocked' === $record['log_type'] && 'enabled' !== $this->options['log_blocked_ips'] )
|
377 |
-
) {
|
378 |
-
// Logging disabled.
|
379 |
-
return false;
|
380 |
-
}
|
381 |
-
|
382 |
-
// Logging enabled, get the current URL & IP location information.
|
383 |
-
$location = $this->get_ip_geolocation( $record['user_ip'] );
|
384 |
-
$current_url = $this->get_current_url();
|
385 |
-
|
386 |
-
// Add additional information to the detection record.
|
387 |
-
$record['page_url'] = $current_url;
|
388 |
-
$record['submission_data'] = wp_json_encode( $data );
|
389 |
-
|
390 |
-
if ( $location ) {
|
391 |
-
$record['country'] = ! empty( $location['country_code'] ) ? $location['country_code'] : false;
|
392 |
-
$record['region'] = ! empty( $location['region_code'] ) ? $location['region_code'] : false;
|
393 |
-
$record['city'] = ! empty( $location['city'] ) ? $location['city'] : false;
|
394 |
-
$record['latitude'] = ! empty( $location['latitude'] ) ? $location['latitude'] : false;
|
395 |
-
$record['longitude'] = ! empty( $location['longitude'] ) ? $location['longitude'] : false;
|
396 |
-
}
|
397 |
-
|
398 |
-
return $wpdb->insert( $this->tables['log'], $record );
|
399 |
-
}
|
400 |
-
|
401 |
-
/**
|
402 |
-
* Returns the current page URL.
|
403 |
-
*
|
404 |
-
* @return string The current page URL.
|
405 |
-
*/
|
406 |
-
public function get_current_url() {
|
407 |
-
global $wp;
|
408 |
-
|
409 |
-
return home_url( add_query_arg( array(), $wp->request ) );
|
410 |
-
}
|
411 |
-
|
412 |
-
/**
|
413 |
-
* Retrieves an IP geolocation.
|
414 |
-
*
|
415 |
-
* @param string $ip The IP to get geolocation information for.
|
416 |
-
*/
|
417 |
-
public function get_ip_geolocation( $ip ) {
|
418 |
-
if ( empty( $this->options['ipstack_api'] ) ) {
|
419 |
-
return false;
|
420 |
-
}
|
421 |
-
|
422 |
-
$base_url = 'http://api.ipstack.com/';
|
423 |
-
$remote_url = $base_url . $ip . '?access_key=' . $this->options['ipstack_api'];
|
424 |
-
$response = wp_remote_get( $remote_url, array( 'timeout' => $this->options['api_timeout'] ) );
|
425 |
-
|
426 |
-
if ( is_array( $response ) && ! is_wp_error( $response ) ) {
|
427 |
-
$info = json_decode( $response['body'], true );
|
428 |
-
|
429 |
-
return array(
|
430 |
-
'type' => ! empty( $info['type'] ) ? sanitize_text_field( $info['type'] ) : false,
|
431 |
-
'continent_code' => ! empty( $info['continent_code'] ) ? sanitize_text_field( $info['continent_code'] ) : false,
|
432 |
-
'continent_name' => ! empty( $info['continent_name'] ) ? sanitize_text_field( $info['continent_name'] ) : false,
|
433 |
-
'country_code' => ! empty( $info['country_code'] ) ? sanitize_text_field( $info['country_code'] ) : false,
|
434 |
-
'country_name' => ! empty( $info['country_name'] ) ? sanitize_text_field( $info['country_name'] ) : false,
|
435 |
-
'region_code' => ! empty( $info['region_code'] ) ? sanitize_text_field( $info['region_code'] ) : false,
|
436 |
-
'region_name' => ! empty( $info['region_name'] ) ? sanitize_text_field( $info['region_name'] ) : false,
|
437 |
-
'city' => ! empty( $info['city'] ) ? sanitize_text_field( $info['city'] ) : false,
|
438 |
-
'zip' => ! empty( $info['zip'] ) ? sanitize_text_field( $info['zip'] ) : false,
|
439 |
-
'latitude' => ! empty( $info['latitude'] ) ? sanitize_text_field( $info['latitude'] ) : false,
|
440 |
-
'longitude' => ! empty( $info['longitude'] ) ? sanitize_text_field( $info['longitude'] ) : false,
|
441 |
-
'flag' => ! empty( $info['location']['country_flag'] ) ? sanitize_text_field( $info['location']['country_flag'] ) : false,
|
442 |
-
);
|
443 |
-
}
|
444 |
-
|
445 |
-
return false;
|
446 |
-
}
|
447 |
-
|
448 |
-
/**
|
449 |
-
* Share a detection with Zero Spam.
|
450 |
-
*/
|
451 |
-
public function share_detection( $ip, $type ) {
|
452 |
-
// The Zero Spam API endpoint for sharing detections.
|
453 |
-
$api_url = 'https://zerospam.org/wp-json/wpzerospamapi/v1/detection/';
|
454 |
-
|
455 |
-
// Setup the request parameters.
|
456 |
-
$request_args = array(
|
457 |
-
'method' => 'POST',
|
458 |
-
'body' => array(
|
459 |
-
'ip' => $ip,
|
460 |
-
'type' => $type,
|
461 |
-
'site' => site_url(),
|
462 |
-
'email' => get_bloginfo( 'admin_email' ),
|
463 |
-
'wpversion' => get_bloginfo( 'version' ),
|
464 |
-
'name' => get_bloginfo( 'name' ),
|
465 |
-
'desc' => get_bloginfo( 'description' ),
|
466 |
-
'language' => get_bloginfo( 'language' ),
|
467 |
-
'version' => WORDPRESS_ZERO_SPAM_VERSION,
|
468 |
-
),
|
469 |
-
'sslverify' => true,
|
470 |
-
);
|
471 |
-
|
472 |
-
// For debugging purposes only.
|
473 |
-
if ( WP_DEBUG ) {
|
474 |
-
$request_args['sslverify'] = false;
|
475 |
-
}
|
476 |
-
|
477 |
-
// Send the request.
|
478 |
-
$request = wp_remote_post( $api_url, $request_args );
|
479 |
-
if ( is_wp_error( $request ) ) {
|
480 |
-
// Request failed.
|
481 |
-
return false;
|
482 |
-
}
|
483 |
-
|
484 |
-
// Request succeeded, return the result.
|
485 |
-
return wp_remote_retrieve_body( $request );
|
486 |
-
}
|
487 |
-
|
488 |
-
/**
|
489 |
-
* Triggered on the WP init action.
|
490 |
-
*/
|
491 |
-
public function wp_footer() {
|
492 |
-
// Display debug info if enabled.
|
493 |
-
if ( 'enabled' === $this->options['debug'] ) {
|
494 |
-
wp_enqueue_style(
|
495 |
-
'wpzerospam-debug',
|
496 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
497 |
-
'assets/css/debug.css',
|
498 |
-
false,
|
499 |
-
WORDPRESS_ZERO_SPAM_VERSION
|
500 |
-
);
|
501 |
-
?>
|
502 |
-
<div class="wpzerospam-debug-overlay">
|
503 |
-
<div class="wpzerospam-debug-item">
|
504 |
-
<div class="wpzerospam-debug-item-label"><strong><?php esc_html_e( 'Options', 'wpzerospam' ); ?>:</strong></div>
|
505 |
-
<div class="wpzerospam-debug-item-value">
|
506 |
-
<?php foreach ( $this->options as $key => $value ): ?>
|
507 |
-
<div class="wpzerospam-debug-item">
|
508 |
-
<div class="wpzerospam-debug-item-label"><?php esc_html_e( $key ); ?></div>
|
509 |
-
<div class="wpzerospam-debug-item-value"><?php esc_html_e( $value ); ?></div>
|
510 |
-
</div>
|
511 |
-
<?php endforeach; ?>
|
512 |
-
</div>
|
513 |
-
</div>
|
514 |
-
<div class="wpzerospam-debug-item">
|
515 |
-
<div class="wpzerospam-debug-item-label"><strong><?php esc_html_e( 'Current User IP', 'wpzerospam' ); ?>:</strong></div>
|
516 |
-
<div class="wpzerospam-debug-item-value"><?php echo esc_html( $this->current_user_ip ); ?></div>
|
517 |
-
</div>
|
518 |
-
<div class="wpzerospam-debug-item">
|
519 |
-
<div class="wpzerospam-debug-item-label"><strong><?php esc_html_e( 'Current User IP Access', 'wpzerospam' ); ?>:</strong></div>
|
520 |
-
<div class="wpzerospam-debug-item-value">
|
521 |
-
<?php foreach ( $this->current_user_ip_access as $key => $value ): ?>
|
522 |
-
<div class="wpzerospam-debug-item">
|
523 |
-
<div class="wpzerospam-debug-item-label"><?php esc_html_e( $key ); ?></div>
|
524 |
-
<div class="wpzerospam-debug-item-value"><?php esc_html_e( $value ); ?></div>
|
525 |
-
</div>
|
526 |
-
<?php endforeach; ?>
|
527 |
-
</div>
|
528 |
-
</div>
|
529 |
-
</div>
|
530 |
-
<?php
|
531 |
-
}
|
532 |
-
}
|
533 |
-
|
534 |
-
/**
|
535 |
-
* Triggered on the WP init action.
|
536 |
-
*/
|
537 |
-
public function wp_init() {
|
538 |
-
// Set the plugin options.
|
539 |
-
$this->options = $this->get_options();
|
540 |
-
if ( empty( $this->options['blocked_message'] ) ) {
|
541 |
-
$this->options['blocked_message'] = __( 'You have been blocked from visiting this site by WordPress Zero Spam due to detected spam activity.', 'wpzerospam' );
|
542 |
-
}
|
543 |
-
|
544 |
-
// Set the current user's IP address.
|
545 |
-
if ( 'enabled' === $this->options['debug'] && ! empty( $_REQUEST['wpzerospamip'] ) ) {
|
546 |
-
$this->current_user_ip = $_REQUEST['wpzerospamip'];
|
547 |
-
} else {
|
548 |
-
$this->current_user_ip = $this->get_user_ip();
|
549 |
-
}
|
550 |
-
|
551 |
-
// Set the current user's IP address access.
|
552 |
-
$this->current_user_ip_access = $this->get_access( $this->current_user_ip );
|
553 |
-
}
|
554 |
-
|
555 |
-
/**
|
556 |
-
* Returns the saved plugin options.
|
557 |
-
*/
|
558 |
-
public function get_options() {
|
559 |
-
$saved_options = get_option( 'wpzerospam' );
|
560 |
-
if ( ! $saved_options || ! is_array( $saved_options ) ) {
|
561 |
-
$saved_options = array();
|
562 |
-
}
|
563 |
-
|
564 |
-
$options = $this->default_options;
|
565 |
-
$options = array_merge( $options, $saved_options );
|
566 |
-
$options = apply_filters( 'wpzerospam_options', $options );
|
567 |
-
|
568 |
-
return $options;
|
569 |
-
}
|
570 |
-
|
571 |
-
/**
|
572 |
-
* Sets access cookies.
|
573 |
-
*
|
574 |
-
* @param array $access Access details.
|
575 |
-
*/
|
576 |
-
public function set_access_cookies( $access ) {
|
577 |
-
foreach ( $access as $key => $value ) {
|
578 |
-
$this->set_cookie( $key, $value, 0 );
|
579 |
-
}
|
580 |
-
|
581 |
-
return $access;
|
582 |
-
}
|
583 |
-
|
584 |
-
/**
|
585 |
-
* Updates a blacklisted IP.
|
586 |
-
*
|
587 |
-
* @param array $api_data The returned IP data from the API.
|
588 |
-
*/
|
589 |
-
public function update_blacklisted_ip( $api_data, $type ) {
|
590 |
-
global $wpdb;
|
591 |
-
|
592 |
-
if ( ! $api_data ) {
|
593 |
-
return false;
|
594 |
-
}
|
595 |
-
|
596 |
-
switch ( $api_data['api'] ) {
|
597 |
-
case 'stopforumspam':
|
598 |
-
if ( ! empty( $api_data['confidence'] ) && $api_data['confidence'] < $this->options['stopforumspam_confidence_min'] ) {
|
599 |
-
// Doesn't meet the threshold, delete the IP from the database.
|
600 |
-
$this->delete_blacklisted_ip( $api_data['ip_address'] );
|
601 |
-
return false;
|
602 |
-
}
|
603 |
-
break;
|
604 |
-
case 'botscout':
|
605 |
-
if ( ! empty( $api_data['count'] ) && $api_data['count'] < $this->options['botscout_count_min'] ) {
|
606 |
-
// Doesn't meet the threshold, delete the IP from the database.
|
607 |
-
$this->delete_blacklisted_ip( $api_data['ip_address'] );
|
608 |
-
return false;
|
609 |
-
}
|
610 |
-
break;
|
611 |
-
}
|
612 |
-
|
613 |
-
// Update the record.
|
614 |
-
if ( 'update' === $type ) {
|
615 |
-
$wpdb->update(
|
616 |
-
$this->tables['blacklist'],
|
617 |
-
array(
|
618 |
-
'last_updated' => current_time( 'mysql' ),
|
619 |
-
'blacklist_data' => wp_json_encode( $api_data ),
|
620 |
-
),
|
621 |
-
array(
|
622 |
-
'user_ip' => $api_data['ip_address'],
|
623 |
-
)
|
624 |
-
);
|
625 |
-
} else {
|
626 |
-
$wpdb->insert(
|
627 |
-
$this->tables['blacklist'],
|
628 |
-
array(
|
629 |
-
'user_ip' => $api_data['ip_address'],
|
630 |
-
'last_updated' => current_time( 'mysql' ),
|
631 |
-
'blacklist_service' => $api_data['api'],
|
632 |
-
'blacklist_data' => wp_json_encode( $api_data ),
|
633 |
-
)
|
634 |
-
);
|
635 |
-
}
|
636 |
-
|
637 |
-
return true;
|
638 |
-
}
|
639 |
-
|
640 |
-
/**
|
641 |
-
* Deletes an IP from the blacklist.
|
642 |
-
*
|
643 |
-
* @param string $ip The IP address to delete.
|
644 |
-
*/
|
645 |
-
public function delete_blacklisted_ip( $ip ) {
|
646 |
-
global $wpdb;
|
647 |
-
|
648 |
-
$wpdb->delete(
|
649 |
-
$this->tables['blacklist'],
|
650 |
-
array(
|
651 |
-
'user_ip' => $ip
|
652 |
-
)
|
653 |
-
);
|
654 |
-
}
|
655 |
-
|
656 |
-
/**
|
657 |
-
* Checks an IP using a third-party API.
|
658 |
-
*
|
659 |
-
* @param string $ip IP address to query.
|
660 |
-
* @param string $api The API to query. stopforumspam | botscout.
|
661 |
-
* @return array The API query result.
|
662 |
-
*/
|
663 |
-
public function get_ip_from_api( $ip, $api ) {
|
664 |
-
$cache_key = sanitize_title( $api . '_' . $ip );
|
665 |
-
$data = wp_cache_get( $cache_key );
|
666 |
-
|
667 |
-
if ( false === $data ) {
|
668 |
-
switch ( $api ) {
|
669 |
-
case 'stopforumspam':
|
670 |
-
if ( 'enabled' !== $this->options['stop_forum_spam'] ) {
|
671 |
-
return false;
|
672 |
-
}
|
673 |
-
|
674 |
-
$api_url = 'https://api.stopforumspam.org/api?';
|
675 |
-
$params = array(
|
676 |
-
'ip' => $ip,
|
677 |
-
'json' => '',
|
678 |
-
);
|
679 |
-
break;
|
680 |
-
case 'botscout':
|
681 |
-
if ( ! $this->options['botscout_api'] ) {
|
682 |
-
return false;
|
683 |
-
}
|
684 |
-
|
685 |
-
$api_url = 'https://botscout.com/test/?';
|
686 |
-
$params = array(
|
687 |
-
'ip' => $ip,
|
688 |
-
'key' => $this->options['botscout_api'],
|
689 |
-
);
|
690 |
-
break;
|
691 |
-
}
|
692 |
-
|
693 |
-
if ( ! empty( $api_url ) ) {
|
694 |
-
$endpoint = $api_url . http_build_query( $params );
|
695 |
-
$response = wp_remote_get( $endpoint, array( 'timeout' => $this->options['api_timeout'] ) );
|
696 |
-
if ( is_array( $response ) && ! is_wp_error( $response ) ) {
|
697 |
-
$body_data = wp_remote_retrieve_body( $response );
|
698 |
-
switch ( $api ) {
|
699 |
-
case 'stopforumspam':
|
700 |
-
$body_data = json_decode( $body_data, true );
|
701 |
-
if (
|
702 |
-
! empty( $body_data['success'] ) &&
|
703 |
-
$body_data['success'] &&
|
704 |
-
! empty( $body_data['ip'] ) &&
|
705 |
-
! empty( $body_data['ip']['appears'] )
|
706 |
-
) {
|
707 |
-
$data = $body_data['ip'];
|
708 |
-
$data['api'] = 'stopforumspam';
|
709 |
-
$data['ip_address'] = $ip;
|
710 |
-
}
|
711 |
-
break;
|
712 |
-
case 'botscout':
|
713 |
-
if ( strpos( $body_data, '!' ) === false ) {
|
714 |
-
list( $matched, $type, $count ) = explode( '|', $body_data );
|
715 |
-
if ( 'Y' === $matched ) {
|
716 |
-
$data = array(
|
717 |
-
'type' => $type,
|
718 |
-
'count' => $count,
|
719 |
-
'api' => 'botscout',
|
720 |
-
'ip_address' => $ip,
|
721 |
-
);
|
722 |
-
}
|
723 |
-
}
|
724 |
-
break;
|
725 |
-
}
|
726 |
-
|
727 |
-
if ( $data ) {
|
728 |
-
wp_cache_set( $cache_key, $data );
|
729 |
-
}
|
730 |
-
}
|
731 |
-
}
|
732 |
-
}
|
733 |
-
|
734 |
-
return $data;
|
735 |
-
}
|
736 |
-
|
737 |
-
/**
|
738 |
-
* Checks if a temporary blocked IP is active.
|
739 |
-
*
|
740 |
-
* @param string $blocked_ip The blocked IP record from the DB.
|
741 |
-
*/
|
742 |
-
public function is_blocked_ip_active( $blocked_ip ) {
|
743 |
-
$current_datetime = strtotime( current_time( 'mysql' ) );
|
744 |
-
$start_block = strtotime( $blocked_ip['start_block'] );
|
745 |
-
$end_block = strtotime( $blocked_ip['end_block'] );
|
746 |
-
if (
|
747 |
-
$current_datetime >= $start_block &&
|
748 |
-
$current_datetime < $end_block
|
749 |
-
) {
|
750 |
-
return true;
|
751 |
-
}
|
752 |
-
|
753 |
-
return false;
|
754 |
-
}
|
755 |
-
|
756 |
-
/**
|
757 |
-
* Checks if an IP has been blacklisted & returns the record if found.
|
758 |
-
*
|
759 |
-
* @param string $ip The IP address to check.
|
760 |
-
* @return array|false The blacklisted API record or false if not found.
|
761 |
-
*/
|
762 |
-
public function get_blacklisted_ip( $ip ) {
|
763 |
-
$blacklisted_ip = $this->table_query(
|
764 |
-
'blacklist',
|
765 |
-
array(
|
766 |
-
'type' => 'row',
|
767 |
-
'select' => array(
|
768 |
-
'blacklist_service',
|
769 |
-
'blacklist_id',
|
770 |
-
'last_updated',
|
771 |
-
'attempts',
|
772 |
-
),
|
773 |
-
'where' => array(
|
774 |
-
array(
|
775 |
-
array(
|
776 |
-
'key' => 'user_ip',
|
777 |
-
'value' => $ip,
|
778 |
-
'relation' => '=',
|
779 |
-
),
|
780 |
-
),
|
781 |
-
),
|
782 |
-
'limit' => 1,
|
783 |
-
)
|
784 |
-
);
|
785 |
-
|
786 |
-
return $blacklisted_ip;
|
787 |
-
}
|
788 |
-
|
789 |
-
/**
|
790 |
-
* Checks if an IP has been blocked & returns the record if found.
|
791 |
-
*
|
792 |
-
* @param string $ip The IP address to check.
|
793 |
-
* @return array|false The blocked API record or false if not found.
|
794 |
-
*/
|
795 |
-
public function get_blocked_ip( $ip ) {
|
796 |
-
$blocked_ip = $this->table_query(
|
797 |
-
'blocked',
|
798 |
-
array(
|
799 |
-
'type' => 'row',
|
800 |
-
'select' => array(
|
801 |
-
'blocked_type',
|
802 |
-
'start_block',
|
803 |
-
'end_block',
|
804 |
-
'reason',
|
805 |
-
'attempts',
|
806 |
-
),
|
807 |
-
'where' => array(
|
808 |
-
array(
|
809 |
-
array(
|
810 |
-
'key' => 'user_ip',
|
811 |
-
'value' => $ip,
|
812 |
-
'relation' => '=',
|
813 |
-
),
|
814 |
-
),
|
815 |
-
),
|
816 |
-
'limit' => 1,
|
817 |
-
)
|
818 |
-
);
|
819 |
-
|
820 |
-
return $blocked_ip;
|
821 |
-
}
|
822 |
-
|
823 |
-
/**
|
824 |
-
* Queries a database table.
|
825 |
-
*
|
826 |
-
* @param string $table Table key.
|
827 |
-
* @param array $args Array of query arguments.
|
828 |
-
*/
|
829 |
-
public function table_query( $table, $args = array() ) {
|
830 |
-
global $wpdb;
|
831 |
-
|
832 |
-
$sql = 'SELECT';
|
833 |
-
|
834 |
-
// Select.
|
835 |
-
$select = '';
|
836 |
-
if ( ! empty( $args['select'] ) ) {
|
837 |
-
foreach ( $args['select'] as $key => $value ) {
|
838 |
-
if ( $select ) {
|
839 |
-
$select .= ', ';
|
840 |
-
}
|
841 |
-
$select .= $value;
|
842 |
-
}
|
843 |
-
} else {
|
844 |
-
$select = '*';
|
845 |
-
}
|
846 |
-
|
847 |
-
$sql .= ' ' . $select;
|
848 |
-
|
849 |
-
// From.
|
850 |
-
$sql .= ' FROM ' . $this->tables[ $table ];
|
851 |
-
|
852 |
-
// Where.
|
853 |
-
$where = '';
|
854 |
-
if ( ! empty( $args['where'] ) ) {
|
855 |
-
foreach ( $args['where'] as $key => $where_stmt ) {
|
856 |
-
if ( ! $where ) {
|
857 |
-
$where .= 'WHERE ';
|
858 |
-
}
|
859 |
-
|
860 |
-
foreach ( $where_stmt as $k => $array ) {
|
861 |
-
$where .= $array['key'];
|
862 |
-
switch ( $array['relation'] ) {
|
863 |
-
case '=':
|
864 |
-
$where .= ' = ';
|
865 |
-
if ( is_numeric( $array['value'] ) ) {
|
866 |
-
$where .= ' ' . $array['value'];
|
867 |
-
} else {
|
868 |
-
$where .= ' "' . $array['value'] . '"';
|
869 |
-
}
|
870 |
-
break;
|
871 |
-
}
|
872 |
-
}
|
873 |
-
}
|
874 |
-
}
|
875 |
-
|
876 |
-
$sql .= ' ' . $where;
|
877 |
-
|
878 |
-
// Limit.
|
879 |
-
if ( ! empty( $args['limit'] ) ) {
|
880 |
-
$sql .= ' LIMIT ' . $args['limit'];
|
881 |
-
}
|
882 |
-
|
883 |
-
// Offset.
|
884 |
-
if ( ! empty( $args['offset'] ) ) {
|
885 |
-
$sql .= ' OFFSET ' . $args['offset'];
|
886 |
-
}
|
887 |
-
|
888 |
-
if ( ! empty( $args['type'] ) ) {
|
889 |
-
if ( 'row' === $args['type'] ) {
|
890 |
-
return $wpdb->get_row( $sql, ARRAY_A );
|
891 |
-
}
|
892 |
-
} else {
|
893 |
-
return $wpdb->get_results( $sql, ARRAY_A );
|
894 |
-
}
|
895 |
-
}
|
896 |
-
|
897 |
-
/**
|
898 |
-
* Returns the whitelisted IPs.
|
899 |
-
*
|
900 |
-
* @return array Array of whitelisted IP addresses defined in the plugin settings.
|
901 |
-
*/
|
902 |
-
public function get_whitelisted_ips() {
|
903 |
-
$whitelist = explode( PHP_EOL, $this->options['ip_whitelist'] );
|
904 |
-
if ( ! $whitelist ) {
|
905 |
-
return array();
|
906 |
-
}
|
907 |
-
|
908 |
-
$whitelisted = array();
|
909 |
-
foreach ( $whitelist as $k => $whitelisted_ip ) {
|
910 |
-
$whitelisted[ $whitelisted_ip ] = $whitelisted_ip;
|
911 |
-
}
|
912 |
-
|
913 |
-
$whitelisted = apply_filters( 'wpzerospam_whitelisted_ips', $whitelisted );
|
914 |
-
|
915 |
-
return $whitelisted;
|
916 |
-
}
|
917 |
-
|
918 |
-
/**
|
919 |
-
* Gets a cookie.
|
920 |
-
*
|
921 |
-
* @param string $cookie_key The cookie of the cookie to retrieve.
|
922 |
-
*/
|
923 |
-
public function get_cookie( $cookie_key ) {
|
924 |
-
$cookie_key = 'wpzerospam_' . $cookie_key;
|
925 |
-
|
926 |
-
return ! empty( $_COOKIE[ $cookie_key ] ) ? $_COOKIE[ $cookie_key ] : false;
|
927 |
-
}
|
928 |
-
|
929 |
-
/**
|
930 |
-
* Sets a cookie.
|
931 |
-
*
|
932 |
-
* @param string $cookie_key The cookie key.
|
933 |
-
* @param string $value The value of the cookie.
|
934 |
-
*/
|
935 |
-
public function set_cookie( $cookie_key, $value, $expiration ) {
|
936 |
-
$current_time = current_time( 'mysql' );
|
937 |
-
|
938 |
-
setcookie( 'wpzerospam_' . $cookie_key, $value, $expiration, COOKIEPATH, COOKIE_DOMAIN );
|
939 |
-
}
|
940 |
-
|
941 |
-
/**
|
942 |
-
* Returns the current user's IP address.
|
943 |
-
*
|
944 |
-
* @link https://www.benmarshall.me/get-ip-address/
|
945 |
-
*/
|
946 |
-
public function get_user_ip() {
|
947 |
-
foreach (
|
948 |
-
array(
|
949 |
-
'HTTP_CLIENT_IP',
|
950 |
-
'HTTP_X_FORWARDED_FOR',
|
951 |
-
'HTTP_X_FORWARDED',
|
952 |
-
'HTTP_X_CLUSTER_CLIENT_IP',
|
953 |
-
'HTTP_FORWARDED_FOR',
|
954 |
-
'HTTP_FORWARDED',
|
955 |
-
'REMOTE_ADDR',
|
956 |
-
)
|
957 |
-
as $key ) {
|
958 |
-
if ( array_key_exists( $key, $_SERVER ) === true ) {
|
959 |
-
foreach ( explode(',', $_SERVER[ $key ]) as $ip_address ) {
|
960 |
-
$ip_address = trim( $ip_address );
|
961 |
-
|
962 |
-
if (
|
963 |
-
filter_var(
|
964 |
-
$ip_address,
|
965 |
-
FILTER_VALIDATE_IP,
|
966 |
-
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
|
967 |
-
) !== false
|
968 |
-
) {
|
969 |
-
return $ip_address;
|
970 |
-
}
|
971 |
-
}
|
972 |
-
}
|
973 |
-
}
|
974 |
-
|
975 |
-
return false;
|
976 |
-
}
|
977 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
composer.json
DELETED
@@ -1,36 +0,0 @@
|
|
1 |
-
{
|
2 |
-
"name": "bmarshall511/wordpress_zero_spam",
|
3 |
-
"description": "WordPress Zero Spam makes blocking spam & malicious visitors a cinch. Just install, activate and enjoy a spam-free site.",
|
4 |
-
"keywords": ["wordpress-plugin"],
|
5 |
-
"type": "wordpress-plugin",
|
6 |
-
"homepage": "https://www.benmarshall.me/wordpress-zero-spam",
|
7 |
-
"authors": [
|
8 |
-
{
|
9 |
-
"name": "Ben Marshall (bmarshall)",
|
10 |
-
"homepage": "https://www.benmarshall.me",
|
11 |
-
"role": "Maintainer"
|
12 |
-
}
|
13 |
-
],
|
14 |
-
"support": {
|
15 |
-
"issues": "https://github.com/bmarshall511/wordpress-zero-spam/issues"
|
16 |
-
},
|
17 |
-
"license": "GPL-2.0-or-later",
|
18 |
-
"minimum-stability": "stable",
|
19 |
-
"repositories": [
|
20 |
-
{
|
21 |
-
"type": "package",
|
22 |
-
"package": {
|
23 |
-
"name": "bmarshall511/wordpress-zero-spam",
|
24 |
-
"version": "master",
|
25 |
-
"source": {
|
26 |
-
"url": "git://github.com/bmarshall511/wordpress-zero-spam.git",
|
27 |
-
"type": "git",
|
28 |
-
"reference": "master"
|
29 |
-
}
|
30 |
-
}
|
31 |
-
}
|
32 |
-
],
|
33 |
-
"require": {
|
34 |
-
"php" : ">=7.1"
|
35 |
-
}
|
36 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/admin/class-admin.php
ADDED
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Admin class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Core\Admin;
|
9 |
+
|
10 |
+
use ZeroSpam\Core\Admin\Admin;
|
11 |
+
|
12 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
13 |
+
defined( 'ABSPATH' ) || die();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Admin.
|
17 |
+
*
|
18 |
+
* Handles access checks.
|
19 |
+
*
|
20 |
+
* @since 5.0.0
|
21 |
+
*/
|
22 |
+
class Admin {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Admin constructor.
|
26 |
+
*
|
27 |
+
* @since 5.0.0
|
28 |
+
* @access public
|
29 |
+
*/
|
30 |
+
public function __construct() {
|
31 |
+
new Settings();
|
32 |
+
new Dashboard();
|
33 |
+
|
34 |
+
add_filter( 'plugin_action_links_' . ZEROSPAM_PLUGIN_BASE, array( $this, 'plugin_action_links' ) );
|
35 |
+
add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 2 );
|
36 |
+
add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ) );
|
37 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'scripts' ) );
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Scripts.
|
42 |
+
*
|
43 |
+
* @since 5.0.0
|
44 |
+
* @access public
|
45 |
+
*/
|
46 |
+
public function scripts( $hook_suffix ) {
|
47 |
+
if (
|
48 |
+
'dashboard_page_wordpress-zero-spam-dashboard' === $hook_suffix ||
|
49 |
+
'settings_page_wordpress-zero-spam-settings' === $hook_suffix
|
50 |
+
) {
|
51 |
+
wp_enqueue_style(
|
52 |
+
'zerospam-admin',
|
53 |
+
plugin_dir_url( ZEROSPAM ) . 'assets/css/admin.css',
|
54 |
+
false,
|
55 |
+
ZEROSPAM_VERSION
|
56 |
+
);
|
57 |
+
|
58 |
+
wp_enqueue_script(
|
59 |
+
'zerospam-admin',
|
60 |
+
plugin_dir_url( ZEROSPAM ) . 'assets/js/admin.js',
|
61 |
+
array(),
|
62 |
+
ZEROSPAM_VERSION,
|
63 |
+
true
|
64 |
+
);
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Plugin action links.
|
70 |
+
*
|
71 |
+
* Adds action links to the plugin list table
|
72 |
+
*
|
73 |
+
* Fired by `plugin_action_links` filter.
|
74 |
+
*
|
75 |
+
* @since 5.0.0
|
76 |
+
* @access public
|
77 |
+
*
|
78 |
+
* @param array $links An array of plugin action links.
|
79 |
+
*
|
80 |
+
* @return array An array of plugin action links.
|
81 |
+
*/
|
82 |
+
public function plugin_action_links( $links ) {
|
83 |
+
$settings_link = sprintf( '<a href="%1$s">%2$s</a>', admin_url( 'options-general.php?page=wordpress-zero-spam-settings' ), __( 'Settings', 'zerospam' ) );
|
84 |
+
|
85 |
+
array_unshift( $links, $settings_link );
|
86 |
+
|
87 |
+
return $links;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Plugin row meta.
|
92 |
+
*
|
93 |
+
* Adds row meta links to the plugin list table
|
94 |
+
*
|
95 |
+
* Fired by `plugin_row_meta` filter.
|
96 |
+
*
|
97 |
+
* @since 5.0.0
|
98 |
+
* @access public
|
99 |
+
*
|
100 |
+
* @param array $plugin_meta An array of the plugin's metadata, including
|
101 |
+
* the version, author, author URI, and plugin URI.
|
102 |
+
* @param string $plugin_file Path to the plugin file, relative to the plugins
|
103 |
+
* directory.
|
104 |
+
*
|
105 |
+
* @return array An array of plugin row meta links.
|
106 |
+
*/
|
107 |
+
public function plugin_row_meta( $plugin_meta, $plugin_file ) {
|
108 |
+
if ( ZEROSPAM_PLUGIN_BASE === $plugin_file ) {
|
109 |
+
$row_meta = [
|
110 |
+
'docs' => '<a href="https://github.com/bmarshall511/wordpress-zero-spam/wiki" aria-label="' . esc_attr( __( 'View WordPress Zero Spam Documentation', 'zerospam' ) ) . '" target="_blank">' . __( 'Docs & FAQs', 'zerospam' ) . '</a>',
|
111 |
+
];
|
112 |
+
|
113 |
+
$plugin_meta = array_merge( $plugin_meta, $row_meta );
|
114 |
+
}
|
115 |
+
|
116 |
+
return $plugin_meta;
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Admin footer text.
|
121 |
+
*
|
122 |
+
* Modifies the "Thank you" text displayed in the admin footer.
|
123 |
+
*
|
124 |
+
* Fired by `admin_footer_text` filter.
|
125 |
+
*
|
126 |
+
* @since 5.0.0
|
127 |
+
* @access public
|
128 |
+
*
|
129 |
+
* @param string $footer_text The content that will be printed.
|
130 |
+
*
|
131 |
+
* @return string The content that will be printed.
|
132 |
+
*/
|
133 |
+
public function admin_footer_text( $footer_text ) {
|
134 |
+
$current_screen = get_current_screen();
|
135 |
+
$is_zerospam_screen = ( $current_screen && false !== strpos( $current_screen->id, 'wordpress-zero-spam' ) );
|
136 |
+
|
137 |
+
if ( $is_zerospam_screen ) {
|
138 |
+
$footer_text = sprintf(
|
139 |
+
/* translators: 1: Elementor, 2: Link to plugin review */
|
140 |
+
__( 'Enjoyed %1$s? Please leave us a %2$s rating. We really appreciate your support!', 'zerospam' ),
|
141 |
+
'<strong>' . __( 'WordPress Zero Spam', 'zerospam' ) . '</strong>',
|
142 |
+
'<a href="https://wordpress.org/plugins/zero-spam/#reviews" target="_blank">★★★★★</a>'
|
143 |
+
);
|
144 |
+
}
|
145 |
+
|
146 |
+
return $footer_text;
|
147 |
+
}
|
148 |
+
}
|
core/admin/class-dashboard.php
ADDED
@@ -0,0 +1,233 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Dashboard class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Core\Admin;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
|
12 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
13 |
+
defined( 'ABSPATH' ) || die();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Dashboard.
|
17 |
+
*
|
18 |
+
* @since 5.0.0
|
19 |
+
*/
|
20 |
+
class Dashboard {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Dashboard constructor.
|
24 |
+
*
|
25 |
+
* @since 5.0.0
|
26 |
+
* @access public
|
27 |
+
*/
|
28 |
+
public function __construct() {
|
29 |
+
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
|
30 |
+
add_action( 'admin_action_add_blocked_ip', array( $this, 'block_ip' ) );
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Block IP handler.
|
35 |
+
*
|
36 |
+
* @since 5.0.0
|
37 |
+
* @access public
|
38 |
+
*/
|
39 |
+
public function block_ip() {
|
40 |
+
$url = parse_url( $_POST['redirect'] );
|
41 |
+
$url['query'] = str_replace(
|
42 |
+
array(
|
43 |
+
'zerospam-success=1',
|
44 |
+
'zerospam-error=1',
|
45 |
+
'zerospam-error=2',
|
46 |
+
'zerospam-error=3',
|
47 |
+
'zerospam-error=4',
|
48 |
+
'zerospam-error=5',
|
49 |
+
),
|
50 |
+
'',
|
51 |
+
$url['query']
|
52 |
+
);
|
53 |
+
|
54 |
+
$url = $url['scheme'] . '://' . $url['host'] . ( ! empty( $url['port'] ) ? ':' . $url['port'] : '' ) . $url['path'] . '?' . $url['query'] . ( ! empty( $url['fragment'] ) ? '#' . $url['fragment'] : '' );
|
55 |
+
|
56 |
+
if ( ! isset( $_POST['zerospam'] ) || ! wp_verify_nonce( $_POST['zerospam'], 'zerospam' ) ) {
|
57 |
+
wp_redirect( $url . '&zerospam-error=1' );
|
58 |
+
exit;
|
59 |
+
}
|
60 |
+
|
61 |
+
$record = array();
|
62 |
+
|
63 |
+
$record['user_ip'] = sanitize_text_field( $_POST['blocked_ip'] );
|
64 |
+
$record['blocked_type'] = in_array( sanitize_text_field( $_POST['blocked_type'] ), [ 'permanent', 'temporary' ] ) ? sanitize_text_field( $_POST['blocked_type'] ) : false;
|
65 |
+
$record['reason'] = sanitize_text_field( $_POST['blocked_reason'] );
|
66 |
+
$record['start_block'] = sanitize_text_field( $_POST['blocked_start_date'] );
|
67 |
+
$record['end_block'] = sanitize_text_field( $_POST['blocked_end_date'] );
|
68 |
+
|
69 |
+
if ( ! $record['user_ip'] || ! rest_is_ip_address( $record['user_ip'] ) ) {
|
70 |
+
wp_safe_redirect( $url . '&zerospam-error=1' );
|
71 |
+
exit;
|
72 |
+
}
|
73 |
+
|
74 |
+
if ( ! $record['blocked_type'] ) {
|
75 |
+
wp_safe_redirect( $url . '&zerospam-error=2' );
|
76 |
+
exit;
|
77 |
+
}
|
78 |
+
|
79 |
+
if ( 'temporary' === $record['blocked_type'] && ! $record['end_block'] ) {
|
80 |
+
wp_safe_redirect( $url . '&zerospam-error=5' );
|
81 |
+
exit;
|
82 |
+
}
|
83 |
+
|
84 |
+
if ( $record['start_block'] ) {
|
85 |
+
$record['start_block'] = gmdate( 'Y-m-d G:i:s', strtotime( $record['start_block'] ) );
|
86 |
+
} else {
|
87 |
+
$record['start_block'] = current_time( 'mysql' );
|
88 |
+
}
|
89 |
+
|
90 |
+
if ( $record['end_block'] ) {
|
91 |
+
$record['end_block'] = gmdate( 'Y-m-d G:i:s', strtotime( $record['end_block'] ) );
|
92 |
+
}
|
93 |
+
|
94 |
+
if ( 'temporary' === $record['blocked_type'] && ! $record['end_block'] ) {
|
95 |
+
wp_safe_redirect( $url . '&error=3' );
|
96 |
+
exit;
|
97 |
+
}
|
98 |
+
|
99 |
+
if ( ! ZeroSpam\Includes\DB::blocked( $record ) ) {
|
100 |
+
wp_safe_redirect( $url . '&zerospam-error=4' );
|
101 |
+
exit;
|
102 |
+
}
|
103 |
+
|
104 |
+
wp_safe_redirect( $url . '&zerospam-success=1' );
|
105 |
+
exit;
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Admin menu.
|
110 |
+
*
|
111 |
+
* @since 5.0.0
|
112 |
+
* @access public
|
113 |
+
*/
|
114 |
+
public function admin_menu() {
|
115 |
+
add_submenu_page(
|
116 |
+
'index.php',
|
117 |
+
__( 'WordPress Zero Spam Dashboard', 'zerospam' ),
|
118 |
+
__( 'Zero Spam', 'zerospam' ),
|
119 |
+
'manage_options',
|
120 |
+
'wordpress-zero-spam-dashboard',
|
121 |
+
array( $this, 'dashboard_page' )
|
122 |
+
);
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Dashboard page.
|
127 |
+
*
|
128 |
+
* @since 5.0.0
|
129 |
+
* @access public
|
130 |
+
*/
|
131 |
+
public function dashboard_page() {
|
132 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
133 |
+
return;
|
134 |
+
}
|
135 |
+
?>
|
136 |
+
<div class="wrap">
|
137 |
+
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
|
138 |
+
<?php require ZEROSPAM_PATH . 'includes/templates/admin-callout.php'; ?>
|
139 |
+
|
140 |
+
<?php if ( ! empty( $_GET['zerospam-error'] ) ): ?>
|
141 |
+
<div class="notice notice-error is-dismissible">
|
142 |
+
<p><strong>
|
143 |
+
<?php
|
144 |
+
switch( $_GET['zerospam-error'] ):
|
145 |
+
case 1:
|
146 |
+
_e( 'Please enter a valid IP address.', 'zerospam' );
|
147 |
+
break;
|
148 |
+
case 2:
|
149 |
+
_e( 'Please select a valid type.', 'zerospam' );
|
150 |
+
break;
|
151 |
+
case 3:
|
152 |
+
_e( 'Please select a date & time when the temporary block should end.', 'zerospam' );
|
153 |
+
break;
|
154 |
+
case 4:
|
155 |
+
_e( 'There was a problem add the IP to the database. Please try again.', 'zerospam' );
|
156 |
+
break;
|
157 |
+
case 5:
|
158 |
+
_e( 'Temporary blocks require an end date.', 'zerospam' );
|
159 |
+
break;
|
160 |
+
endswitch;
|
161 |
+
?>
|
162 |
+
</strong></p>
|
163 |
+
<button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php _e( 'Dismiss this notice.', 'zerospam' ); ?></span></button>
|
164 |
+
</div>
|
165 |
+
<?php elseif ( ! empty( $_GET['zerospam-success'] ) ): ?>
|
166 |
+
<div class="notice notice-success is-dismissible">
|
167 |
+
<p><strong><?php _e( 'The blocked IP has been successfully added.', 'wpzerospam' ); ?></strong></p>
|
168 |
+
<button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php _e( 'Dismiss this notice.', 'zerospam' ); ?>.</span></button>
|
169 |
+
</div>
|
170 |
+
<?php endif; ?>
|
171 |
+
|
172 |
+
<?php
|
173 |
+
$active_tab = 'log';
|
174 |
+
if ( ! empty( $_REQUEST['tab'] ) ) {
|
175 |
+
$active_tab = sanitize_text_field( $_REQUEST['tab'] );
|
176 |
+
}
|
177 |
+
?>
|
178 |
+
<div class="nav-tab-wrapper">
|
179 |
+
<a id="zerospam-settings-tab-log" class="nav-tab<?php if ( 'log' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=log' ) ); ?>"><?php echo __( 'Log', 'zerospam' ); ?></a>
|
180 |
+
<a id="zerospam-settings-tab-blocked-ips" class="nav-tab<?php if ( 'blocked' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=blocked' ) ); ?>"><?php echo __( 'Blocked IPs', 'zerospam' ); ?></a>
|
181 |
+
</div>
|
182 |
+
|
183 |
+
<div class="zerospam-tabs">
|
184 |
+
<?php if ( 'log' === $active_tab ) : ?>
|
185 |
+
<div id="tab-log" class="zerospam-tab is-active">
|
186 |
+
<h2><?php echo __( 'WordPress Zero Spam Log', 'zerospam' ); ?></h2>
|
187 |
+
<?php
|
188 |
+
$table_data = new ZeroSpam\Core\Admin\Tables\LogTable();
|
189 |
+
$table_data->prepare_items();
|
190 |
+
?>
|
191 |
+
<form id="zerospam-log-table" method="post">
|
192 |
+
<?php wp_nonce_field( 'zerospam_nonce', 'zerospam_nonce' ); ?>
|
193 |
+
<input type="hidden" name="paged" value="1" />
|
194 |
+
<?php $table_data->search_box( __( 'Search IPs', 'zerospam' ), 'search-ip' ); ?>
|
195 |
+
<?php $table_data->display(); ?>
|
196 |
+
</form>
|
197 |
+
</div>
|
198 |
+
<?php endif; ?>
|
199 |
+
|
200 |
+
<?php if ( 'blocked' === $active_tab ) : ?>
|
201 |
+
<div id="tab-blocked-ips" class="zerospam-tab is-active">
|
202 |
+
<h2><?php echo __( 'Blocked IPs', 'zerospam' ); ?></h2>
|
203 |
+
<?php
|
204 |
+
$table_data = new ZeroSpam\Core\Admin\Tables\BlockedTable();
|
205 |
+
$table_data->prepare_items();
|
206 |
+
?>
|
207 |
+
<form id="zerospam-blocked-table" method="post">
|
208 |
+
<?php wp_nonce_field( 'zerospam_nonce', 'zerospam_nonce' ); ?>
|
209 |
+
<input type="hidden" name="paged" value="1" />
|
210 |
+
<?php $table_data->search_box( __( 'Search IPs', 'zerospam' ), 'search-ip' ); ?>
|
211 |
+
<?php $table_data->display(); ?>
|
212 |
+
</form>
|
213 |
+
</div>
|
214 |
+
<?php endif; ?>
|
215 |
+
</div>
|
216 |
+
|
217 |
+
<div class="zerospam-modal" id="zerospam-block-ip">
|
218 |
+
<button class="zerospam-close-modal" aria-label="<?php echo esc_attr( __( 'Close Modal', 'zerospam' ) ); ?>"></button>
|
219 |
+
<div class="zerospam-modal-details">
|
220 |
+
<div class="zerospam-modal-title">
|
221 |
+
<h3><?php echo __( 'Add/Update Blocked IP', 'zerospam' ); ?></h3>
|
222 |
+
</div>
|
223 |
+
<div class="zerospam-modal-subtitle">
|
224 |
+
|
225 |
+
</div>
|
226 |
+
|
227 |
+
<?php require ZEROSPAM_PATH . 'includes/templates/admin-block-ip.php'; ?>
|
228 |
+
</div>
|
229 |
+
</div>
|
230 |
+
</div>
|
231 |
+
<?php
|
232 |
+
}
|
233 |
+
}
|
core/admin/class-settings.php
ADDED
@@ -0,0 +1,264 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Settings class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Core\Admin;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
|
12 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
13 |
+
defined( 'ABSPATH' ) || die();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Settings.
|
17 |
+
*
|
18 |
+
* @since 5.0.0
|
19 |
+
*/
|
20 |
+
class Settings {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Admin constructor.
|
24 |
+
*
|
25 |
+
* @since 5.0.0
|
26 |
+
* @access public
|
27 |
+
*/
|
28 |
+
public function __construct() {
|
29 |
+
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
|
30 |
+
add_action( 'admin_init', array( $this, 'register_settings' ) );
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Admin menu.
|
35 |
+
*
|
36 |
+
* @since 5.0.0
|
37 |
+
* @access public
|
38 |
+
*/
|
39 |
+
public function admin_menu() {
|
40 |
+
add_submenu_page(
|
41 |
+
'options-general.php',
|
42 |
+
__( 'WordPress Zero Spam Settings', 'zerospam' ),
|
43 |
+
__( 'Zero Spam', 'zerospam' ),
|
44 |
+
'manage_options',
|
45 |
+
'wordpress-zero-spam-settings',
|
46 |
+
array( $this, 'settings_page' )
|
47 |
+
);
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Register settings.
|
52 |
+
*
|
53 |
+
* @since 5.0.0
|
54 |
+
* @access public
|
55 |
+
*/
|
56 |
+
public function register_settings() {
|
57 |
+
register_setting( 'wpzerospam', 'wpzerospam' );
|
58 |
+
|
59 |
+
foreach ( ZeroSpam\Core\Settings::get_sections() as $key => $section ) {
|
60 |
+
add_settings_section(
|
61 |
+
'zerospam_' . $key,
|
62 |
+
$section['title'],
|
63 |
+
array( $this, 'settings_section' ),
|
64 |
+
'wpzerospam'
|
65 |
+
);
|
66 |
+
}
|
67 |
+
|
68 |
+
foreach ( ZeroSpam\Core\Settings::get_settings() as $key => $setting ) {
|
69 |
+
$options = array(
|
70 |
+
'label_for' => $key,
|
71 |
+
'type' => $setting['type'],
|
72 |
+
);
|
73 |
+
|
74 |
+
if ( ! empty( $setting['options'] ) ) {
|
75 |
+
$options['options'] = $setting['options'];
|
76 |
+
}
|
77 |
+
|
78 |
+
if ( ! empty( $setting['value'] ) ) {
|
79 |
+
$options['value'] = $setting['value'];
|
80 |
+
}
|
81 |
+
|
82 |
+
if ( ! empty( $setting['placeholder'] ) ) {
|
83 |
+
$options['placeholder'] = $setting['placeholder'];
|
84 |
+
}
|
85 |
+
|
86 |
+
if ( ! empty( $setting['class'] ) ) {
|
87 |
+
$options['class'] = $setting['class'];
|
88 |
+
}
|
89 |
+
|
90 |
+
if ( ! empty( $setting['desc'] ) ) {
|
91 |
+
$options['desc'] = $setting['desc'];
|
92 |
+
}
|
93 |
+
|
94 |
+
if ( ! empty( $setting['suffix'] ) ) {
|
95 |
+
$options['suffix'] = $setting['suffix'];
|
96 |
+
}
|
97 |
+
|
98 |
+
if ( ! empty( $setting['min'] ) ) {
|
99 |
+
$options['min'] = $setting['min'];
|
100 |
+
}
|
101 |
+
|
102 |
+
if ( ! empty( $setting['max'] ) ) {
|
103 |
+
$options['max'] = $setting['max'];
|
104 |
+
}
|
105 |
+
|
106 |
+
if ( ! empty( $setting['step'] ) ) {
|
107 |
+
$options['step'] = $setting['step'];
|
108 |
+
}
|
109 |
+
|
110 |
+
if ( ! empty( $setting['field_class'] ) ) {
|
111 |
+
$options['field_class'] = $setting['field_class'];
|
112 |
+
}
|
113 |
+
|
114 |
+
add_settings_field(
|
115 |
+
$key,
|
116 |
+
$setting['title'],
|
117 |
+
array( $this, 'settings_field' ),
|
118 |
+
'wpzerospam',
|
119 |
+
'zerospam_' . $setting['section'],
|
120 |
+
$options
|
121 |
+
);
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Settings section.
|
127 |
+
*
|
128 |
+
* @since 5.0.0
|
129 |
+
* @access public
|
130 |
+
*/
|
131 |
+
public function settings_section( $arg ) {
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Settings field.
|
136 |
+
*
|
137 |
+
* @since 5.0.0
|
138 |
+
* @access public
|
139 |
+
*/
|
140 |
+
public function settings_field( $args ) {
|
141 |
+
switch ( $args['type'] ) {
|
142 |
+
case 'textarea':
|
143 |
+
?>
|
144 |
+
<textarea
|
145 |
+
id="<?php echo esc_attr( $args['label_for'] ); ?>"
|
146 |
+
name="wpzerospam[<?php echo esc_attr( $args['label_for'] ); ?>]"
|
147 |
+
rows="5"
|
148 |
+
<?php if ( ! empty( $args['field_class'] ) ) : ?>
|
149 |
+
class="<?php echo esc_attr( $args['field_class'] ); ?>"
|
150 |
+
<?php endif; ?>
|
151 |
+
<?php if ( ! empty( $args['placeholder'] ) ) : ?>
|
152 |
+
placeholder="<?php echo esc_attr( $args['placeholder'] ); ?>"
|
153 |
+
<?php endif; ?>
|
154 |
+
><?php if( ! empty( $args['value'] ) ) : ?><?php echo esc_attr( $args['value'] ); ?><?php endif; ?></textarea>
|
155 |
+
<?php
|
156 |
+
break;
|
157 |
+
case 'url':
|
158 |
+
case 'text':
|
159 |
+
case 'password':
|
160 |
+
case 'number':
|
161 |
+
case 'email':
|
162 |
+
?>
|
163 |
+
<input
|
164 |
+
id="<?php echo esc_attr( $args['label_for'] ); ?>"
|
165 |
+
name="wpzerospam[<?php echo esc_attr( $args['label_for'] ); ?>]"
|
166 |
+
type="<?php echo esc_attr( $args['type'] ); ?>"
|
167 |
+
<?php if( ! empty( $args['value'] ) ) : ?>
|
168 |
+
value="<?php echo esc_attr( $args['value'] ); ?>"
|
169 |
+
<?php endif; ?>
|
170 |
+
<?php if ( ! empty( $args['field_class'] ) ) : ?>
|
171 |
+
class="<?php echo esc_attr( $args['field_class'] ); ?>"
|
172 |
+
<?php endif; ?>
|
173 |
+
<?php if ( ! empty( $args['placeholder'] ) ) : ?>
|
174 |
+
placeholder="<?php echo esc_attr( $args['placeholder'] ); ?>"
|
175 |
+
<?php endif; ?>
|
176 |
+
<?php if( ! empty( $args['min'] ) ) : ?>
|
177 |
+
min="<?php echo esc_attr( $args['min'] ); ?>"
|
178 |
+
<?php endif; ?>
|
179 |
+
<?php if( ! empty( $args['max'] ) ) : ?>
|
180 |
+
max="<?php echo esc_attr( $args['max'] ); ?>"
|
181 |
+
<?php endif; ?>
|
182 |
+
<?php if( ! empty( $args['step'] ) ) : ?>
|
183 |
+
step="<?php echo esc_attr( $args['step'] ); ?>"
|
184 |
+
<?php endif; ?>
|
185 |
+
/>
|
186 |
+
<?php
|
187 |
+
break;
|
188 |
+
case 'checkbox':
|
189 |
+
case 'radio':
|
190 |
+
if ( empty( $args['options'] ) ) {
|
191 |
+
return;
|
192 |
+
}
|
193 |
+
|
194 |
+
foreach ( $args['options'] as $key => $label ) {
|
195 |
+
$selected = false;
|
196 |
+
$name = 'wpzerospam[' . esc_attr( $args['label_for'] ) . ']';
|
197 |
+
if ( count( $args['options'] ) > 1 && 'checkbox' === $args['type'] ) {
|
198 |
+
$name .= '[' . esc_attr( $key ) . ']';
|
199 |
+
}
|
200 |
+
|
201 |
+
if ( ! empty( $args['value'] ) && $args['value'] == $key ) {
|
202 |
+
$selected = true;
|
203 |
+
}
|
204 |
+
|
205 |
+
?>
|
206 |
+
<label for="<?php echo esc_attr( $args['label_for'] . $key ); ?>">
|
207 |
+
<input
|
208 |
+
type="<?php echo esc_attr( $args['type'] ); ?>"
|
209 |
+
id="<?php echo esc_attr( $args['label_for'] . $key ); ?>"
|
210 |
+
name="<?php echo esc_attr( $name ); ?>"
|
211 |
+
value="<?php echo esc_attr( $key ); ?>"
|
212 |
+
<?php if ( ! empty( $args['field_class'] ) ) : ?>
|
213 |
+
class="<?php echo esc_attr( $args['field_class'] ); ?>"
|
214 |
+
<?php endif; ?>
|
215 |
+
<?php if ( $selected ) : ?>
|
216 |
+
checked="checked"
|
217 |
+
<?php endif; ?>
|
218 |
+
/> <?php echo $label; ?>
|
219 |
+
</label><br />
|
220 |
+
<?php
|
221 |
+
}
|
222 |
+
break;
|
223 |
+
}
|
224 |
+
|
225 |
+
if ( ! empty( $args['suffix'] ) ) {
|
226 |
+
echo $args['suffix'];
|
227 |
+
}
|
228 |
+
|
229 |
+
if ( ! empty( $args['desc'] ) ) {
|
230 |
+
echo '<p class="description">' . $args['desc'] . '</p>';
|
231 |
+
}
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Settings page.
|
236 |
+
*
|
237 |
+
* @since 5.0.0
|
238 |
+
* @access public
|
239 |
+
*/
|
240 |
+
public function settings_page() {
|
241 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
242 |
+
return;
|
243 |
+
}
|
244 |
+
?>
|
245 |
+
<div class="wrap">
|
246 |
+
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
|
247 |
+
<?php require ZEROSPAM_PATH . 'includes/templates/admin-callout.php'; ?>
|
248 |
+
|
249 |
+
<form action="options.php" method="post">
|
250 |
+
<?php
|
251 |
+
// Output security fields for the registered setting "wpzerospam".
|
252 |
+
settings_fields( 'wpzerospam' );
|
253 |
+
|
254 |
+
// Output setting sections and their fields.
|
255 |
+
do_settings_sections( 'wpzerospam' );
|
256 |
+
|
257 |
+
// Output save settings button.
|
258 |
+
submit_button( 'Save Settings' );
|
259 |
+
?>
|
260 |
+
</form>
|
261 |
+
</div>
|
262 |
+
<?php
|
263 |
+
}
|
264 |
+
}
|
core/admin/tables/class-blockedtable.php
ADDED
@@ -0,0 +1,307 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Blocked table class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Core\Admin\Tables;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
use WP_List_Table;
|
12 |
+
|
13 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
14 |
+
defined( 'ABSPATH' ) || die();
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Log table.
|
18 |
+
*
|
19 |
+
* @since 5.0.0
|
20 |
+
*/
|
21 |
+
class BlockedTable extends WP_List_Table {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Log table constructor.
|
25 |
+
*
|
26 |
+
* @since 5.0.0
|
27 |
+
* @access public
|
28 |
+
*/
|
29 |
+
public function __construct() {
|
30 |
+
global $status, $page;
|
31 |
+
|
32 |
+
$args = array(
|
33 |
+
'singular' => __( 'WordPress Zero Spam Blocked IP', 'zerospam' ),
|
34 |
+
'plural' => __( 'WordPress Zero Spam Blocked IPs', 'zerospam' ),
|
35 |
+
);
|
36 |
+
parent::__construct( $args );
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Column values.
|
41 |
+
*
|
42 |
+
* @since 5.0.0
|
43 |
+
* @access public
|
44 |
+
*/
|
45 |
+
public function column_default( $item, $column_name ) {
|
46 |
+
switch ( $column_name ) {
|
47 |
+
case 'user_ip':
|
48 |
+
return '<a href="https://www.zerospam.org/ip-lookup/' . urlencode( $item[ $column_name ] ) .'" target="_blank" rel="noopener noreferrer">' . $item[ $column_name ] . '</a>';
|
49 |
+
break;
|
50 |
+
case 'date_added':
|
51 |
+
case 'start_block':
|
52 |
+
case 'end_block':
|
53 |
+
if ( empty( $item[ $column_name ] ) || '0000-00-00 00:00:00' === $item[ $column_name ] ) {
|
54 |
+
return 'N/A';
|
55 |
+
} else {
|
56 |
+
return gmdate( 'M j, Y g:ia' , strtotime( $item[ $column_name ] ) );
|
57 |
+
}
|
58 |
+
break;
|
59 |
+
case 'actions':
|
60 |
+
ob_start();
|
61 |
+
?>
|
62 |
+
<button
|
63 |
+
class="button zerospam-block-trigger"
|
64 |
+
data-ip="<?php echo esc_attr( $item['user_ip'] ); ?>"
|
65 |
+
data-reason="<?php echo esc_attr( $item['reason'] ); ?>"
|
66 |
+
data-start="<?php echo esc_attr( gmdate( 'Y-m-d', strtotime( $item['start_block'] ) ) ); ?>T<?php echo esc_attr( gmdate( 'H:i', strtotime( $item['start_block'] ) ) ); ?>"
|
67 |
+
data-end="<?php echo esc_attr( gmdate( 'Y-m-d', strtotime( $item['end_block'] ) ) ); ?>T<?php echo esc_attr( gmdate( 'H:i', strtotime( $item['end_block'] ) ) ); ?>"
|
68 |
+
data-type="<?php echo esc_attr( $item['blocked_type'] ); ?>"
|
69 |
+
>
|
70 |
+
<?php _e( 'Update Block', 'zerospam' ); ?>
|
71 |
+
</button>
|
72 |
+
<?php
|
73 |
+
return ob_get_clean();
|
74 |
+
break;
|
75 |
+
default:
|
76 |
+
if ( empty( $item[ $column_name ] ) ) {
|
77 |
+
return 'N/A';
|
78 |
+
} else {
|
79 |
+
return $item[ $column_name ];
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Bulk actions.
|
86 |
+
*
|
87 |
+
* @since 5.0.0
|
88 |
+
* @access public
|
89 |
+
*/
|
90 |
+
public function get_bulk_actions() {
|
91 |
+
$actions = array(
|
92 |
+
'delete' => __( 'Delete Selected', 'zerospam' ),
|
93 |
+
'delete_all' => __( 'Delete All IPs', 'zerospam' ),
|
94 |
+
);
|
95 |
+
|
96 |
+
return $actions;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Hidable columns.
|
101 |
+
*
|
102 |
+
* @since 5.0.0
|
103 |
+
* @access public
|
104 |
+
*/
|
105 |
+
public function get_hidden_columns() {
|
106 |
+
return array();
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Prepare log items.
|
111 |
+
*
|
112 |
+
* @since 5.0.0
|
113 |
+
* @access public
|
114 |
+
*/
|
115 |
+
public function prepare_items( $args = array() ) {
|
116 |
+
$this->process_bulk_action();
|
117 |
+
|
118 |
+
$columns = $this->get_columns();
|
119 |
+
$hidden = $this->get_hidden_columns();
|
120 |
+
$sortable = $this->get_sortable_columns();
|
121 |
+
|
122 |
+
$per_page = 50;
|
123 |
+
$current_page = $this->get_pagenum();
|
124 |
+
$offset = $per_page * ( $current_page - 1 );
|
125 |
+
$order = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( $_REQUEST['order'] ) : 'desc';
|
126 |
+
$orderby = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( $_REQUEST['orderby'] ) : 'date_added';
|
127 |
+
|
128 |
+
$log_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
|
129 |
+
$user_ip = ! empty( $_REQUEST['s'] ) ? sanitize_text_field( $_REQUEST['s'] ) : false;
|
130 |
+
|
131 |
+
$query_args = array(
|
132 |
+
'limit' => $per_page,
|
133 |
+
'offset' => $offset,
|
134 |
+
'order' => $order,
|
135 |
+
'orderby' => $orderby,
|
136 |
+
'where' => array(),
|
137 |
+
);
|
138 |
+
|
139 |
+
if ( $log_type ) {
|
140 |
+
$query_args['where']['blocked_type'] = array(
|
141 |
+
'value' => $log_type,
|
142 |
+
);
|
143 |
+
}
|
144 |
+
|
145 |
+
if ( $user_ip ) {
|
146 |
+
$query_args['where']['user_ip'] = array(
|
147 |
+
'value' => $user_ip,
|
148 |
+
);
|
149 |
+
}
|
150 |
+
|
151 |
+
$data = ZeroSpam\Includes\DB::query( 'blocked', $query_args );
|
152 |
+
if ( ! $data ) {
|
153 |
+
return false;
|
154 |
+
}
|
155 |
+
|
156 |
+
$this->items = $data;
|
157 |
+
|
158 |
+
unset( $query_args['limit'] );
|
159 |
+
unset( $query_args['offset'] );
|
160 |
+
$data = ZeroSpam\Includes\DB::query( 'blocked', $query_args );
|
161 |
+
$total_items = count( $data );
|
162 |
+
|
163 |
+
$this->set_pagination_args(
|
164 |
+
array(
|
165 |
+
'total_items' => $total_items,
|
166 |
+
'per_page' => $per_page,
|
167 |
+
'total_pages' => ceil( $total_items / $per_page ),
|
168 |
+
'orderby' => $orderby,
|
169 |
+
'order' => $order,
|
170 |
+
)
|
171 |
+
);
|
172 |
+
|
173 |
+
$this->_column_headers = array( $columns, $hidden, $sortable );
|
174 |
+
|
175 |
+
$paging_options = array();
|
176 |
+
if ( ! empty( $query_args['where'] ) ) {
|
177 |
+
foreach ( $query_args['where'] as $key => $value ) {
|
178 |
+
switch( $key ) {
|
179 |
+
case 'blocked_type':
|
180 |
+
$paging_options['type'] = $value['value'];
|
181 |
+
break;
|
182 |
+
case 'user_ip':
|
183 |
+
$paging_options['s'] = $value['value'];
|
184 |
+
break;
|
185 |
+
}
|
186 |
+
}
|
187 |
+
}
|
188 |
+
|
189 |
+
$_SERVER['REQUEST_URI'] = add_query_arg( $paging_options, $_SERVER['REQUEST_URI'] );
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Add more filters.
|
194 |
+
*
|
195 |
+
* @since 5.0.0
|
196 |
+
* @access public
|
197 |
+
*/
|
198 |
+
public function extra_tablenav( $which ) {
|
199 |
+
if ( 'top' !== $which ) {
|
200 |
+
return;
|
201 |
+
}
|
202 |
+
?>
|
203 |
+
<div class="alignleft actions">
|
204 |
+
<?php
|
205 |
+
/*
|
206 |
+
echo '<label class="screen-reader-text" for="filter-by-type">' . __( 'Filter by type', 'zerospam' ) . '</label>';
|
207 |
+
$options = apply_filters( 'zerospam_types', array() );
|
208 |
+
$current_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
|
209 |
+
?>
|
210 |
+
<select name="type" id="filter-by-type">
|
211 |
+
<option value=""><?php _e( 'All types', 'zerospam' ); ?></option>
|
212 |
+
<?php foreach ( $options as $key => $value ) : ?>
|
213 |
+
<option<?php if ( $current_type === $key ) : ?> selected="selected"<?php endif; ?> value="<?php echo esc_attr( $key ); ?>"><?php echo $value; ?></option>
|
214 |
+
<?php endforeach; ?>
|
215 |
+
</select>
|
216 |
+
<?php
|
217 |
+
submit_button( __( 'Filter', 'zerospam' ), '', 'filter_action', false );
|
218 |
+
*/
|
219 |
+
?>
|
220 |
+
<button class="button zerospam-block-trigger"><?php echo __( 'Add Blocked IP Address', 'zerospam' ); ?></button>
|
221 |
+
</div>
|
222 |
+
<?php
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Define table columns.
|
227 |
+
*
|
228 |
+
* @since 5.0.0
|
229 |
+
* @access public
|
230 |
+
*/
|
231 |
+
public function get_columns() {
|
232 |
+
$columns = array(
|
233 |
+
'cb' => '<input type="checkbox" />',
|
234 |
+
'date_added' => __( 'Date', 'zerospam' ),
|
235 |
+
'blocked_type' => __( 'Type', 'zerospam' ),
|
236 |
+
'user_ip' => __( 'IP Address', 'zerospam' ),
|
237 |
+
'start_block' => __( 'Starts', 'zerospam' ),
|
238 |
+
'end_block' => __( 'Ends', 'zerospam' ),
|
239 |
+
'reason' => __( 'Reason', 'zerospam' ),
|
240 |
+
'actions' => __( 'Actions', 'zerospam' ),
|
241 |
+
);
|
242 |
+
|
243 |
+
return $columns;
|
244 |
+
}
|
245 |
+
|
246 |
+
/**
|
247 |
+
* Sortable columns.
|
248 |
+
*
|
249 |
+
* @since 5.0.0
|
250 |
+
* @access public
|
251 |
+
*/
|
252 |
+
public function get_sortable_columns() {
|
253 |
+
$sortable_columns = array(
|
254 |
+
'date_added' => array( 'date_added', false ),
|
255 |
+
'blocked_type' => array( 'blocked_type', false ),
|
256 |
+
'user_ip' => array( 'user_ip', false ),
|
257 |
+
'start_block' => array( 'start_block', false ),
|
258 |
+
'end_block' => array( 'end_block', false ),
|
259 |
+
);
|
260 |
+
|
261 |
+
return $sortable_columns;
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* Column contact.
|
266 |
+
*
|
267 |
+
* @since 5.0.0
|
268 |
+
* @access public
|
269 |
+
*/
|
270 |
+
public function column_cb( $item ) {
|
271 |
+
return sprintf(
|
272 |
+
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
|
273 |
+
/*$1%s*/ 'ids',
|
274 |
+
/*$2%s*/ $item['blocked_id']
|
275 |
+
);
|
276 |
+
}
|
277 |
+
|
278 |
+
/**
|
279 |
+
* Process bulk actions.
|
280 |
+
*
|
281 |
+
* @since 5.0.0
|
282 |
+
* @access public
|
283 |
+
*/
|
284 |
+
public function process_bulk_action() {
|
285 |
+
global $wpdb;
|
286 |
+
|
287 |
+
$ids = ( isset( $_REQUEST['ids'] ) ) ? $_REQUEST['ids'] : '';
|
288 |
+
|
289 |
+
switch( $this->current_action() ) {
|
290 |
+
case 'delete':
|
291 |
+
$nonce = ( isset( $_REQUEST['zerospam_nonce'] ) ) ? sanitize_text_field( $_REQUEST['zerospam_nonce'] ) : '';
|
292 |
+
if ( ! wp_verify_nonce( $nonce, 'zerospam_nonce' ) ) {
|
293 |
+
return false;
|
294 |
+
}
|
295 |
+
|
296 |
+
if ( ! empty ( $ids ) && is_array( $ids ) ) {
|
297 |
+
foreach ( $ids as $k => $blocked_id ) {
|
298 |
+
ZeroSpam\Includes\DB::delete( 'blocked', 'blocked_id', $blocked_id );
|
299 |
+
}
|
300 |
+
}
|
301 |
+
break;
|
302 |
+
case 'delete_all':
|
303 |
+
ZeroSpam\Includes\DB::delete_all( 'blocked' );
|
304 |
+
break;
|
305 |
+
}
|
306 |
+
}
|
307 |
+
}
|
core/admin/tables/class-logtable.php
ADDED
@@ -0,0 +1,327 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Log table class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Core\Admin\Tables;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
use WP_List_Table;
|
12 |
+
|
13 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
14 |
+
defined( 'ABSPATH' ) || die();
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Log table.
|
18 |
+
*
|
19 |
+
* @since 5.0.0
|
20 |
+
*/
|
21 |
+
class LogTable extends WP_List_Table {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Log table constructor.
|
25 |
+
*
|
26 |
+
* @since 5.0.0
|
27 |
+
* @access public
|
28 |
+
*/
|
29 |
+
public function __construct() {
|
30 |
+
global $status, $page;
|
31 |
+
|
32 |
+
$args = array(
|
33 |
+
'singular' => __( 'WordPress Zero Spam Log', 'zerospam' ),
|
34 |
+
'plural' => __( 'WordPress Zero Spam Logs', 'zerospam' ),
|
35 |
+
);
|
36 |
+
parent::__construct( $args );
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Column values.
|
41 |
+
*
|
42 |
+
* @since 5.0.0
|
43 |
+
* @access public
|
44 |
+
*/
|
45 |
+
public function column_default( $item, $column_name ) {
|
46 |
+
switch ( $column_name ) {
|
47 |
+
case 'log_type':
|
48 |
+
$types = apply_filters( 'zerospam_types', array() );
|
49 |
+
if ( ! empty( $types[ $item[ $column_name ] ] ) ) {
|
50 |
+
return $types[ $item[ $column_name ] ];
|
51 |
+
} else {
|
52 |
+
return $item[ $column_name ];
|
53 |
+
}
|
54 |
+
break;
|
55 |
+
case 'user_ip':
|
56 |
+
return '<a href="https://www.zerospam.org/ip-lookup/' . urlencode( $item[ $column_name ] ) .'" target="_blank" rel="noopener noreferrer">' . $item[ $column_name ] . '</a>';
|
57 |
+
break;
|
58 |
+
case 'date_recorded':
|
59 |
+
return date( 'M j, Y g:ia' , strtotime( $item[ $column_name ] ) );
|
60 |
+
break;
|
61 |
+
case 'details':
|
62 |
+
ob_start();
|
63 |
+
?>
|
64 |
+
<button class="button zerospam-details-trigger" data-id="<?php echo esc_attr( $item['log_id'] ); ?>"><?php _e( 'View', 'zerospam' ); ?></button>
|
65 |
+
<div class="zerospam-modal" id="zerospam-details-<?php echo esc_attr( $item['log_id'] ); ?>">
|
66 |
+
<button class="zerospam-close-modal" aria-label="<?php echo esc_attr( __( 'Close Modal', 'zerospam' ) ); ?>"></button>
|
67 |
+
<?php require ZEROSPAM_PATH . 'includes/templates/admin-modal-details.php'; ?>
|
68 |
+
</div>
|
69 |
+
<?php
|
70 |
+
return ob_get_clean();
|
71 |
+
break;
|
72 |
+
case 'actions':
|
73 |
+
ob_start();
|
74 |
+
$blocked = ZeroSpam\Includes\DB::blocked( $item['user_ip'] );
|
75 |
+
if ( $blocked ) :
|
76 |
+
?>
|
77 |
+
<button
|
78 |
+
class="button zerospam-block-trigger"
|
79 |
+
data-ip="<?php echo esc_attr( $item['user_ip'] ); ?>"
|
80 |
+
data-reason="<?php echo esc_attr( $blocked['reason'] ); ?>"
|
81 |
+
data-start="<?php echo esc_attr( gmdate( 'Y-m-d', strtotime( $blocked['start_block'] ) ) ); ?>T<?php echo esc_attr( gmdate( 'H:i', strtotime( $blocked['start_block'] ) ) ); ?>"
|
82 |
+
data-end="<?php echo esc_attr( gmdate( 'Y-m-d', strtotime( $blocked['end_block'] ) ) ); ?>T<?php echo esc_attr( gmdate( 'H:i', strtotime( $blocked['end_block'] ) ) ); ?>"
|
83 |
+
data-type="<?php echo esc_attr( $blocked['blocked_type'] ); ?>"
|
84 |
+
>
|
85 |
+
<?php _e( 'Update Block', 'zerospam' ); ?>
|
86 |
+
</button>
|
87 |
+
<?php
|
88 |
+
else :
|
89 |
+
?>
|
90 |
+
<button class="button zerospam-block-trigger" data-ip="<?php echo esc_attr( $item['user_ip'] ); ?>"><?php _e( 'Block IP', 'zerospam' ); ?></button>
|
91 |
+
<?php
|
92 |
+
endif;
|
93 |
+
|
94 |
+
return ob_get_clean();
|
95 |
+
break;
|
96 |
+
default:
|
97 |
+
if ( empty( $item[ $column_name ] ) ) {
|
98 |
+
return 'N/A';
|
99 |
+
} else {
|
100 |
+
return $item[ $column_name ];
|
101 |
+
}
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Bulk actions.
|
107 |
+
*
|
108 |
+
* @since 5.0.0
|
109 |
+
* @access public
|
110 |
+
*/
|
111 |
+
public function get_bulk_actions() {
|
112 |
+
$actions = array(
|
113 |
+
'delete' => __( 'Delete Selected', 'zerospam' ),
|
114 |
+
'delete_all' => __( 'Delete All Logs', 'zerospam' ),
|
115 |
+
);
|
116 |
+
|
117 |
+
return $actions;
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Hidable columns.
|
122 |
+
*
|
123 |
+
* @since 5.0.0
|
124 |
+
* @access public
|
125 |
+
*/
|
126 |
+
public function get_hidden_columns() {
|
127 |
+
return array();
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Prepare log items.
|
132 |
+
*
|
133 |
+
* @since 5.0.0
|
134 |
+
* @access public
|
135 |
+
*/
|
136 |
+
public function prepare_items( $args = array() ) {
|
137 |
+
$this->process_bulk_action();
|
138 |
+
|
139 |
+
$columns = $this->get_columns();
|
140 |
+
$hidden = $this->get_hidden_columns();
|
141 |
+
$sortable = $this->get_sortable_columns();
|
142 |
+
|
143 |
+
$per_page = 50;
|
144 |
+
$current_page = $this->get_pagenum();
|
145 |
+
$offset = $per_page * ( $current_page - 1 );
|
146 |
+
$order = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( $_REQUEST['order'] ) : 'desc';
|
147 |
+
$orderby = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( $_REQUEST['orderby'] ) : 'date_recorded';
|
148 |
+
|
149 |
+
$log_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
|
150 |
+
$user_ip = ! empty( $_REQUEST['s'] ) ? sanitize_text_field( $_REQUEST['s'] ) : false;
|
151 |
+
|
152 |
+
$query_args = array(
|
153 |
+
'limit' => $per_page,
|
154 |
+
'offset' => $offset,
|
155 |
+
'order' => $order,
|
156 |
+
'orderby' => $orderby,
|
157 |
+
'where' => array(),
|
158 |
+
);
|
159 |
+
|
160 |
+
if ( $log_type ) {
|
161 |
+
$query_args['where']['log_type'] = array(
|
162 |
+
'value' => $log_type,
|
163 |
+
);
|
164 |
+
}
|
165 |
+
|
166 |
+
if ( $user_ip ) {
|
167 |
+
$query_args['where']['user_ip'] = array(
|
168 |
+
'value' => $user_ip,
|
169 |
+
);
|
170 |
+
}
|
171 |
+
|
172 |
+
$data = ZeroSpam\Includes\DB::query( 'log', $query_args );
|
173 |
+
if ( ! $data ) {
|
174 |
+
return false;
|
175 |
+
}
|
176 |
+
|
177 |
+
$this->items = $data;
|
178 |
+
|
179 |
+
unset( $query_args['limit'] );
|
180 |
+
unset( $query_args['offset'] );
|
181 |
+
$data = ZeroSpam\Includes\DB::query( 'log', $query_args );
|
182 |
+
$total_items = count( $data );
|
183 |
+
|
184 |
+
$this->set_pagination_args(
|
185 |
+
array(
|
186 |
+
'total_items' => $total_items,
|
187 |
+
'per_page' => $per_page,
|
188 |
+
'total_pages' => ceil( $total_items / $per_page ),
|
189 |
+
'orderby' => $orderby,
|
190 |
+
'order' => $order,
|
191 |
+
)
|
192 |
+
);
|
193 |
+
|
194 |
+
$this->_column_headers = array( $columns, $hidden, $sortable );
|
195 |
+
|
196 |
+
$paging_options = array();
|
197 |
+
if ( ! empty( $query_args['where'] ) ) {
|
198 |
+
foreach ( $query_args['where'] as $key => $value ) {
|
199 |
+
switch( $key ) {
|
200 |
+
case 'log_type':
|
201 |
+
$paging_options['type'] = $value['value'];
|
202 |
+
break;
|
203 |
+
case 'user_ip':
|
204 |
+
$paging_options['s'] = $value['value'];
|
205 |
+
break;
|
206 |
+
}
|
207 |
+
}
|
208 |
+
}
|
209 |
+
|
210 |
+
$_SERVER['REQUEST_URI'] = add_query_arg( $paging_options, $_SERVER['REQUEST_URI'] );
|
211 |
+
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Add more filters.
|
215 |
+
*
|
216 |
+
* @since 5.0.0
|
217 |
+
* @access public
|
218 |
+
*/
|
219 |
+
public function extra_tablenav( $which ) {
|
220 |
+
if ( 'top' !== $which ) {
|
221 |
+
return;
|
222 |
+
}
|
223 |
+
?>
|
224 |
+
<div class="alignleft actions">
|
225 |
+
<?php
|
226 |
+
echo '<label class="screen-reader-text" for="filter-by-type">' . __( 'Filter by type', 'zerospam' ) . '</label>';
|
227 |
+
$options = apply_filters( 'zerospam_types', array() );
|
228 |
+
$current_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
|
229 |
+
?>
|
230 |
+
<select name="type" id="filter-by-type">
|
231 |
+
<option value=""><?php _e( 'All types', 'zerospam' ); ?></option>
|
232 |
+
<?php foreach ( $options as $key => $value ) : ?>
|
233 |
+
<option<?php if ( $current_type === $key ) : ?> selected="selected"<?php endif; ?> value="<?php echo esc_attr( $key ); ?>"><?php echo $value; ?></option>
|
234 |
+
<?php endforeach; ?>
|
235 |
+
</select>
|
236 |
+
<?php
|
237 |
+
submit_button( __( 'Filter', 'zerospam' ), '', 'filter_action', false );
|
238 |
+
?>
|
239 |
+
</div>
|
240 |
+
<?php
|
241 |
+
}
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Define table columns.
|
245 |
+
*
|
246 |
+
* @since 5.0.0
|
247 |
+
* @access public
|
248 |
+
*/
|
249 |
+
public function get_columns() {
|
250 |
+
$columns = array(
|
251 |
+
'cb' => '<input type="checkbox" />',
|
252 |
+
'date_recorded' => __( 'Date', 'zerospam' ),
|
253 |
+
'log_type' => __( 'Type', 'zerospam' ),
|
254 |
+
'user_ip' => __( 'IP Address', 'zerospam' ),
|
255 |
+
'country' => __( 'Country', 'zerospam' ),
|
256 |
+
'region' => __( 'Region', 'zerospam' ),
|
257 |
+
'city' => __( 'City', 'zerospam' ),
|
258 |
+
'details' => __( 'Details', 'zerospam' ),
|
259 |
+
'actions' => __( 'Actions', 'zerospam' ),
|
260 |
+
);
|
261 |
+
|
262 |
+
return $columns;
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Sortable columns.
|
267 |
+
*
|
268 |
+
* @since 5.0.0
|
269 |
+
* @access public
|
270 |
+
*/
|
271 |
+
public function get_sortable_columns() {
|
272 |
+
$sortable_columns = array(
|
273 |
+
'date_recorded' => array( 'date_recorded', false ),
|
274 |
+
'log_type' => array( 'log_type', false ),
|
275 |
+
'user_ip' => array( 'user_ip', false ),
|
276 |
+
'country' => array( 'country', false ),
|
277 |
+
'region' => array( 'region', false ),
|
278 |
+
'city' => array( 'city', false ),
|
279 |
+
);
|
280 |
+
|
281 |
+
return $sortable_columns;
|
282 |
+
}
|
283 |
+
|
284 |
+
/**
|
285 |
+
* Column contact.
|
286 |
+
*
|
287 |
+
* @since 5.0.0
|
288 |
+
* @access public
|
289 |
+
*/
|
290 |
+
public function column_cb( $item ) {
|
291 |
+
return sprintf(
|
292 |
+
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
|
293 |
+
/*$1%s*/ 'ids',
|
294 |
+
/*$2%s*/ $item['log_id']
|
295 |
+
);
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Process bulk actions.
|
300 |
+
*
|
301 |
+
* @since 5.0.0
|
302 |
+
* @access public
|
303 |
+
*/
|
304 |
+
public function process_bulk_action() {
|
305 |
+
global $wpdb;
|
306 |
+
|
307 |
+
$ids = ( isset( $_REQUEST['ids'] ) ) ? $_REQUEST['ids'] : '';
|
308 |
+
|
309 |
+
switch( $this->current_action() ) {
|
310 |
+
case 'delete':
|
311 |
+
$nonce = ( isset( $_REQUEST['zerospam_nonce'] ) ) ? sanitize_text_field( $_REQUEST['zerospam_nonce'] ) : '';
|
312 |
+
if ( ! wp_verify_nonce( $nonce, 'zerospam_nonce' ) ) {
|
313 |
+
return false;
|
314 |
+
}
|
315 |
+
|
316 |
+
if ( ! empty ( $ids ) && is_array( $ids ) ) {
|
317 |
+
foreach ( $ids as $k => $log_id ) {
|
318 |
+
ZeroSpam\Includes\DB::delete( 'log', 'log_id', $log_id );
|
319 |
+
}
|
320 |
+
}
|
321 |
+
break;
|
322 |
+
case 'delete_all':
|
323 |
+
ZeroSpam\Includes\DB::delete_all( 'log' );
|
324 |
+
break;
|
325 |
+
}
|
326 |
+
}
|
327 |
+
}
|
core/class-access.php
ADDED
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Access class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Core;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
|
12 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
13 |
+
defined( 'ABSPATH' ) || die();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Admin.
|
17 |
+
*
|
18 |
+
* Handles access checks.
|
19 |
+
*
|
20 |
+
* @since 5.0.0
|
21 |
+
*/
|
22 |
+
class Access {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Access constructor.
|
26 |
+
*
|
27 |
+
* @since 5.0.0
|
28 |
+
* @access private
|
29 |
+
*/
|
30 |
+
public function __construct() {
|
31 |
+
add_action( 'template_redirect', array( $this, 'access_check' ), 0 );
|
32 |
+
add_filter( 'zerospam_access_checks', array( $this, 'check_blocked' ), 0, 3 );
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Access check.
|
37 |
+
*
|
38 |
+
* Determines if the current user should be blocked.
|
39 |
+
*
|
40 |
+
* @since 5.0.0
|
41 |
+
* @access public
|
42 |
+
*/
|
43 |
+
public function access_check() {
|
44 |
+
$access = self::get_access();
|
45 |
+
|
46 |
+
if ( ! empty( $access['blocked'] ) ) {
|
47 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
48 |
+
|
49 |
+
|
50 |
+
if ( ! empty( $access['details'] ) && is_array( $access['details'] ) ) {
|
51 |
+
if ( ! empty( $settings['share_data']['value'] ) && 'enabled' === $settings['share_data']['value'] ) {
|
52 |
+
do_action( 'zerospam_share_blocked', $access['details'] );
|
53 |
+
}
|
54 |
+
|
55 |
+
foreach ( $access['details'] as $key => $detail ) {
|
56 |
+
if ( ! empty( $detail['blocked'] ) ) {
|
57 |
+
if ( empty( $detail['details']['failed'] ) ) {
|
58 |
+
$detail['details']['failed'] = $key;
|
59 |
+
}
|
60 |
+
|
61 |
+
if ( ! empty( $settings['log_blocked_ips']['value'] ) && 'enabled' === $settings['log_blocked_ips']['value'] ) {
|
62 |
+
ZeroSpam\Includes\DB::log( $detail['type'], $detail['details'] );
|
63 |
+
}
|
64 |
+
}
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
if ( ! empty( $settings['block_handler']['value'] ) ) {
|
69 |
+
switch ( $settings['block_handler']['value'] ) {
|
70 |
+
case 403:
|
71 |
+
$message = __( 'Your IP address has been blocked by WordPress Zero Spam due to detected spam/malicious activity.', 'zerospam' );
|
72 |
+
if ( ! empty( $settings['blocked_message']['value'] ) ) {
|
73 |
+
$message = $settings['blocked_message']['value'];
|
74 |
+
}
|
75 |
+
wp_die(
|
76 |
+
$message,
|
77 |
+
__( 'Blocked by WordPress Zero Spam', 'zerospam' ),
|
78 |
+
array(
|
79 |
+
'response' => 403,
|
80 |
+
)
|
81 |
+
);
|
82 |
+
break;
|
83 |
+
case 'redirect':
|
84 |
+
$url = 'https://wordpress.org/plugins/zero-spam/';
|
85 |
+
if ( ! empty( $settings['blocked_redirect_url']['value'] ) ) {
|
86 |
+
$url = esc_url( $settings['blocked_redirect_url']['value'] );
|
87 |
+
}
|
88 |
+
wp_redirect( $url );
|
89 |
+
exit;
|
90 |
+
break;
|
91 |
+
}
|
92 |
+
}
|
93 |
+
}
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Checks if an IP has been blocked.
|
98 |
+
*
|
99 |
+
* @since 5.0.0
|
100 |
+
* @access public
|
101 |
+
*/
|
102 |
+
public function check_blocked( $access_checks, $user_ip, $settings ) {
|
103 |
+
$access_checks['blocked'] = array(
|
104 |
+
'blocked' => false,
|
105 |
+
);
|
106 |
+
|
107 |
+
$blocked = ZeroSpam\Includes\DB::blocked( $user_ip );
|
108 |
+
|
109 |
+
if ( $blocked ) {
|
110 |
+
$today = new \DateTime();
|
111 |
+
|
112 |
+
// Check the start & end dates (all blocks require a start date).
|
113 |
+
$start_date = new \DateTime();
|
114 |
+
if ( ! empty( $blocked['start_block'] ) ) {
|
115 |
+
$start_date = new \DateTime( $blocked['start_block'] );
|
116 |
+
}
|
117 |
+
|
118 |
+
if ( $today >= $start_date ) {
|
119 |
+
// Check the end date if temporary block.
|
120 |
+
if (
|
121 |
+
! empty( $blocked['blocked_type'] ) &&
|
122 |
+
'temporary' === $blocked['blocked_type']
|
123 |
+
) {
|
124 |
+
// Temporary block.
|
125 |
+
if ( ! empty( $blocked['end_block'] ) ) {
|
126 |
+
$end_date = new \DateTime( $blocked['end_block'] );
|
127 |
+
|
128 |
+
if ( $today < $end_date ) {
|
129 |
+
$access_checks['blocked']['blocked'] = true;
|
130 |
+
$access_checks['blocked']['type'] = 'blocked';
|
131 |
+
$access_checks['blocked']['details'] = $blocked;
|
132 |
+
$access_checks['blocked']['details']['failed'] = 'blocked_ips';
|
133 |
+
}
|
134 |
+
}
|
135 |
+
} else {
|
136 |
+
// Permanent block.
|
137 |
+
$access_checks['blocked']['blocked'] = true;
|
138 |
+
$access_checks['blocked']['type'] = 'blocked';
|
139 |
+
$access_checks['blocked']['details'] = $blocked;
|
140 |
+
$access_checks['blocked']['details']['failed'] = 'blocked_ips';
|
141 |
+
}
|
142 |
+
}
|
143 |
+
}
|
144 |
+
|
145 |
+
return $access_checks;
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Gets the current user's access.
|
150 |
+
*
|
151 |
+
* @since 5.0.0
|
152 |
+
* @access public
|
153 |
+
*/
|
154 |
+
public function get_access() {
|
155 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
156 |
+
|
157 |
+
$access = array(
|
158 |
+
'blocked' => false,
|
159 |
+
);
|
160 |
+
|
161 |
+
$user_ip = ZeroSpam\Core\User::get_ip();
|
162 |
+
|
163 |
+
if ( $user_ip ) {
|
164 |
+
if ( ZeroSpam\Core\Utilities::is_whitelisted( $user_ip ) ) {
|
165 |
+
return $access;
|
166 |
+
}
|
167 |
+
|
168 |
+
$access_checks = apply_filters( 'zerospam_access_checks', array(), $user_ip, $settings );
|
169 |
+
foreach ( $access_checks as $key => $check ) {
|
170 |
+
if ( ! empty( $check['blocked'] ) ) {
|
171 |
+
$access['blocked'] = true;
|
172 |
+
break;
|
173 |
+
}
|
174 |
+
}
|
175 |
+
|
176 |
+
$access['details'] = $access_checks;
|
177 |
+
}
|
178 |
+
|
179 |
+
return $access;
|
180 |
+
}
|
181 |
+
}
|
core/class-settings.php
ADDED
@@ -0,0 +1,191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Settings class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Core;
|
9 |
+
|
10 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
11 |
+
defined( 'ABSPATH' ) || die();
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Settings.
|
15 |
+
*
|
16 |
+
* @since 5.0.0
|
17 |
+
*/
|
18 |
+
class Settings {
|
19 |
+
/**
|
20 |
+
* Settings.
|
21 |
+
*
|
22 |
+
* Holds the plugin settings.
|
23 |
+
*
|
24 |
+
* @since 5.0.0
|
25 |
+
* @access public
|
26 |
+
* @static
|
27 |
+
*
|
28 |
+
* @var Settings
|
29 |
+
*/
|
30 |
+
public static $settings = array();
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Sections.
|
34 |
+
*
|
35 |
+
* @since 5.0.0
|
36 |
+
* @access public
|
37 |
+
* @static
|
38 |
+
*
|
39 |
+
* @var Settings
|
40 |
+
*/
|
41 |
+
public static $sections = array();
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Returns the plugin setting sections.
|
45 |
+
*
|
46 |
+
* @since 5.0.0
|
47 |
+
* @access public
|
48 |
+
*/
|
49 |
+
public static function get_sections() {
|
50 |
+
self::$sections['improve'] = array(
|
51 |
+
'title' => __( 'Improve WordPress Zero Spam', 'zerospam' ),
|
52 |
+
);
|
53 |
+
|
54 |
+
self::$sections['general'] = array(
|
55 |
+
'title' => __( 'General Settings', 'zerospam' ),
|
56 |
+
);
|
57 |
+
|
58 |
+
self::$sections['debug'] = array(
|
59 |
+
'title' => __( 'Debug', 'zerospam' ),
|
60 |
+
);
|
61 |
+
|
62 |
+
return apply_filters( 'zerospam_setting_sections', self::$sections );
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Returns the plugin settings.
|
67 |
+
*
|
68 |
+
* @since 5.0.0
|
69 |
+
* @access public
|
70 |
+
*/
|
71 |
+
public static function get_settings( $key = false ) {
|
72 |
+
$options = get_option( 'wpzerospam' );
|
73 |
+
|
74 |
+
self::$settings['share_data'] = array(
|
75 |
+
'title' => __( 'Usage Data Sharing', 'zerospam' ),
|
76 |
+
'section' => 'improve',
|
77 |
+
'type' => 'checkbox',
|
78 |
+
'options' => array(
|
79 |
+
'enabled' => __( 'Become a super contributor by opting in to share non-sensitive plugin data.', 'zerospam' ),
|
80 |
+
),
|
81 |
+
'value' => ! empty( $options['share_data'] ) ? $options['share_data'] : false,
|
82 |
+
);
|
83 |
+
|
84 |
+
self::$settings['block_handler'] = array(
|
85 |
+
'title' => __( 'IP Block Handler', 'zerospam' ),
|
86 |
+
'desc' => __( 'Determines how blocked IPs are handled when they attempt to access the site.', 'zerospam' ),
|
87 |
+
'section' => 'general',
|
88 |
+
'type' => 'radio',
|
89 |
+
'options' => array(
|
90 |
+
'redirect' => __( 'Redirect user', 'zerospam' ),
|
91 |
+
'403' => sprintf(
|
92 |
+
wp_kses(
|
93 |
+
__( 'Display a <a href="%s" target="_blank" rel="noreferrer noopener"><code>403 Forbidden</code></a> error', 'zerospam' ),
|
94 |
+
array(
|
95 |
+
'code' => array(),
|
96 |
+
'a' => array(
|
97 |
+
'target' => array(),
|
98 |
+
'href' => array(),
|
99 |
+
'rel' => array(),
|
100 |
+
),
|
101 |
+
)
|
102 |
+
),
|
103 |
+
esc_url( 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403' )
|
104 |
+
)
|
105 |
+
),
|
106 |
+
'value' => ! empty( $options['block_handler'] ) ? $options['block_handler'] : 403,
|
107 |
+
);
|
108 |
+
|
109 |
+
switch ( self::$settings['block_handler']['value'] ) {
|
110 |
+
case 403:
|
111 |
+
$message = __( 'Your IP address has been blocked by WordPress Zero Spam due to detected spam/malicious activity.', 'zerospam' );
|
112 |
+
|
113 |
+
self::$settings['blocked_message'] = array(
|
114 |
+
'title' => __( 'Blocked Message', 'zerospam' ),
|
115 |
+
'desc' => __( 'The message that will be displayed to a blocked user.', 'zerospam' ),
|
116 |
+
'section' => 'general',
|
117 |
+
'type' => 'text',
|
118 |
+
'field_class' => 'large-text',
|
119 |
+
'placeholder' => $message,
|
120 |
+
'value' => ! empty( $options['blocked_message'] ) ? $options['blocked_message'] : $message,
|
121 |
+
);
|
122 |
+
break;
|
123 |
+
case 'redirect':
|
124 |
+
self::$settings['blocked_redirect_url'] = array(
|
125 |
+
'title' => __( 'Redirect for Blocked Users', 'zerospam' ),
|
126 |
+
'desc' => __( 'URL blocked users will be redirected to.', 'zerospam' ),
|
127 |
+
'section' => 'general',
|
128 |
+
'type' => 'url',
|
129 |
+
'field_class' => 'regular-text',
|
130 |
+
'placeholder' => 'https://wordpress.org/plugins/zero-spam/',
|
131 |
+
'value' => ! empty( $options['blocked_redirect_url'] ) ? $options['blocked_redirect_url'] : 'https://wordpress.org/plugins/zero-spam/',
|
132 |
+
);
|
133 |
+
break;
|
134 |
+
}
|
135 |
+
|
136 |
+
self::$settings['log_blocked_ips'] = array(
|
137 |
+
'title' => __( 'Log Blocked IPs', 'zerospam' ),
|
138 |
+
'section' => 'general',
|
139 |
+
'type' => 'checkbox',
|
140 |
+
'desc' => __( 'Enables logging IPs that are blocked from accessing the site. High traffic sites should leave this disabled.', 'zerospam' ),
|
141 |
+
'options' => array(
|
142 |
+
'enabled' => __( 'Enabled', 'zerospam' ),
|
143 |
+
),
|
144 |
+
'value' => ! empty( $options['log_blocked_ips'] ) ? $options['log_blocked_ips'] : false,
|
145 |
+
);
|
146 |
+
|
147 |
+
self::$settings['ip_whitelist'] = array(
|
148 |
+
'title' => __( 'IP Whitelist', 'zerospam' ),
|
149 |
+
'desc' => __( 'Enter IPs that should be whitelisted (IPs that should never be blocked), one per line.', 'zerospam' ),
|
150 |
+
'section' => 'general',
|
151 |
+
'type' => 'textarea',
|
152 |
+
'field_class' => 'regular-text code',
|
153 |
+
'placeholder' => '',
|
154 |
+
'value' => ! empty( $options['ip_whitelist'] ) ? $options['ip_whitelist'] : false,
|
155 |
+
);
|
156 |
+
|
157 |
+
self::$settings['debug'] = array(
|
158 |
+
'title' => __( 'Debug', 'zerospam' ),
|
159 |
+
'desc' => __( 'For troubleshooting site issues.', 'zerospam' ),
|
160 |
+
'section' => 'debug',
|
161 |
+
'type' => 'checkbox',
|
162 |
+
'options' => array(
|
163 |
+
'enabled' => __( 'Enabled', 'zerospam' ),
|
164 |
+
),
|
165 |
+
'value' => ! empty( $options['debug'] ) ? $options['debug'] : false,
|
166 |
+
);
|
167 |
+
|
168 |
+
if ( 'enabled' === self::$settings['debug']['value'] ) {
|
169 |
+
self::$settings['debug_ip'] = array(
|
170 |
+
'title' => __( 'Debug IP', 'zerospam' ),
|
171 |
+
'desc' => __( 'Mock a IP address for debugging.', 'zerospam' ),
|
172 |
+
'section' => 'debug',
|
173 |
+
'type' => 'text',
|
174 |
+
'placeholder' => '127.0.0.1',
|
175 |
+
'value' => ! empty( $options['debug_ip'] ) ? $options['debug_ip'] : false,
|
176 |
+
);
|
177 |
+
}
|
178 |
+
|
179 |
+
$settings = apply_filters( 'zerospam_settings', self::$settings );
|
180 |
+
|
181 |
+
if ( $key ) {
|
182 |
+
if ( ! empty( $settings[ $key ]['value'] ) ) {
|
183 |
+
return $key;
|
184 |
+
}
|
185 |
+
|
186 |
+
return false;
|
187 |
+
}
|
188 |
+
|
189 |
+
return $settings;
|
190 |
+
}
|
191 |
+
}
|
core/class-user.php
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* User class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Core;
|
9 |
+
|
10 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
11 |
+
defined( 'ABSPATH' ) || die();
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Admin.
|
15 |
+
*
|
16 |
+
* Handles access checks.
|
17 |
+
*
|
18 |
+
* @since 5.0.0
|
19 |
+
*/
|
20 |
+
class User {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Gets the current user's IP.
|
24 |
+
*
|
25 |
+
* @since 5.0.0
|
26 |
+
* @access public
|
27 |
+
*/
|
28 |
+
public static function get_ip() {
|
29 |
+
$settings = Settings::get_settings();
|
30 |
+
if (
|
31 |
+
! empty( $settings['debug']['value'] ) &&
|
32 |
+
'enabled' === $settings['debug']['value'] &&
|
33 |
+
! empty( $settings['debug_ip']['value'] )
|
34 |
+
) {
|
35 |
+
return $settings['debug_ip']['value'];
|
36 |
+
}
|
37 |
+
|
38 |
+
if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
|
39 |
+
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
40 |
+
} elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
|
41 |
+
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
42 |
+
} elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED'] ) ) {
|
43 |
+
$ip = $_SERVER['HTTP_X_FORWARDED'];
|
44 |
+
} elseif ( ! empty( $_SERVER['HTTP_FORWARDED_FOR'] ) ) {
|
45 |
+
$ip = $_SERVER['HTTP_FORWARDED_FOR'];
|
46 |
+
} elseif ( ! empty( $_SERVER['HTTP_FORWARDED'] ) ) {
|
47 |
+
$ip = $_SERVER['HTTP_FORWARDED'];
|
48 |
+
} else {
|
49 |
+
$ip = $_SERVER['REMOTE_ADDR'];
|
50 |
+
}
|
51 |
+
|
52 |
+
$ip = explode( ',', $ip );
|
53 |
+
$ip = trim( $ip[0] );
|
54 |
+
|
55 |
+
if ( ! rest_is_ip_address( $ip ) ) {
|
56 |
+
return false;
|
57 |
+
}
|
58 |
+
|
59 |
+
return $ip;
|
60 |
+
}
|
61 |
+
}
|
core/class-utilities.php
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Utilities class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Core;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
|
12 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
13 |
+
defined( 'ABSPATH' ) || die();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Utilities.
|
17 |
+
*
|
18 |
+
* @since 5.0.0
|
19 |
+
*/
|
20 |
+
class Utilities {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Outputs a honeypot field
|
24 |
+
*
|
25 |
+
* @since 5.0.0
|
26 |
+
* @access public
|
27 |
+
*
|
28 |
+
* @return string Returns a HTML honeypot field.
|
29 |
+
*/
|
30 |
+
public static function honeypot_field() {
|
31 |
+
return '<input type="text" name="' . self::get_honeypot() . '" value="" style="display: none !important;" />';
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Returns the generated key for checking submissions.
|
36 |
+
*
|
37 |
+
* @since 5.0.0
|
38 |
+
* @access public
|
39 |
+
*
|
40 |
+
* @return string A unique key used for the 'honeypot' field.
|
41 |
+
*/
|
42 |
+
public static function get_honeypot() {
|
43 |
+
$key = get_option( 'wpzerospam_honeypot' );
|
44 |
+
if ( ! $key ) {
|
45 |
+
$key = wp_generate_password( 5, false, false );
|
46 |
+
update_option( 'wpzerospam_honeypot', $key );
|
47 |
+
}
|
48 |
+
|
49 |
+
return $key;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Returns a cache key.
|
54 |
+
*
|
55 |
+
* @since 5.0.0
|
56 |
+
* @access public
|
57 |
+
*/
|
58 |
+
public static function cache_key( $args, $table = false ) {
|
59 |
+
return sanitize_title( $table . '_' . implode( '_', $args ) );
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Remote get.
|
64 |
+
*
|
65 |
+
* @since 5.0.0
|
66 |
+
* @access public
|
67 |
+
*/
|
68 |
+
public static function remote_get( $endpoint, $args = array() ) {
|
69 |
+
$response = wp_remote_get( $endpoint, $args );
|
70 |
+
if ( is_array( $response ) && ! is_wp_error( $response ) ) {
|
71 |
+
return wp_remote_retrieve_body( $response );
|
72 |
+
}
|
73 |
+
|
74 |
+
return false;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Returns the current URL.
|
79 |
+
*
|
80 |
+
* @since 5.0.0
|
81 |
+
* @access public
|
82 |
+
*/
|
83 |
+
public static function current_url() {
|
84 |
+
return ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] === 'on' ? "https" : "http" ) . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Checks if an IP is on the whitelist.
|
89 |
+
*
|
90 |
+
* @since 5.0.0
|
91 |
+
* @access public
|
92 |
+
*/
|
93 |
+
public static function is_whitelisted( $ip ) {
|
94 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
95 |
+
|
96 |
+
// Check whitelist.
|
97 |
+
if ( ! empty( $settings['ip_whitelist']['value'] ) ) {
|
98 |
+
$whitelisted = explode( PHP_EOL, $settings['ip_whitelist']['value'] );
|
99 |
+
if ( $whitelisted ) {
|
100 |
+
foreach ( $whitelisted as $key => $whitelisted_ip ) {
|
101 |
+
$whitelisted_ip = trim( $whitelisted_ip );
|
102 |
+
if ( $whitelisted_ip === $ip ) {
|
103 |
+
return true;
|
104 |
+
}
|
105 |
+
}
|
106 |
+
}
|
107 |
+
}
|
108 |
+
|
109 |
+
return false;
|
110 |
+
}
|
111 |
+
}
|
inc/admin.php
DELETED
@@ -1,849 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Admin interface & functionality
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.0.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Returns output for detail item.
|
11 |
-
*
|
12 |
-
* @since 4.9.9
|
13 |
-
*
|
14 |
-
* @param string $label The item label.
|
15 |
-
* @param string $value The item value.
|
16 |
-
* @return string HTML for the detail item output.
|
17 |
-
*/
|
18 |
-
if ( ! function_exists( 'wpzerospam_details_item') ) {
|
19 |
-
function wpzerospam_admin_details_item( $label, $value ) {
|
20 |
-
ob_start();
|
21 |
-
?>
|
22 |
-
<div class="wpzerospam-details-item">
|
23 |
-
<div class="wpzerospam-details-label"><?php echo $label; ?></div>
|
24 |
-
<div class="wpzerospam-details-data">
|
25 |
-
<?php
|
26 |
-
if ( is_array( $value ) ):
|
27 |
-
print_r( $value );
|
28 |
-
else:
|
29 |
-
echo $value;
|
30 |
-
endif;
|
31 |
-
?>
|
32 |
-
</div>
|
33 |
-
</div>
|
34 |
-
<?php
|
35 |
-
return ob_get_clean();
|
36 |
-
}
|
37 |
-
}
|
38 |
-
|
39 |
-
function wpzerospam_admin_menu() {
|
40 |
-
add_menu_page(
|
41 |
-
__( 'WordPress Zero Spam Dashboard', 'zero-spam' ),
|
42 |
-
__( 'WP Zero Spam', 'zero-spam' ),
|
43 |
-
'manage_options',
|
44 |
-
'wordpress-zero-spam',
|
45 |
-
'wpzerospam_dashboard',
|
46 |
-
'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNTEycHgiIGhlaWdodD0iNDc4cHgiIHZpZXdCb3g9IjAgMCA1MTIgNDc4IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPCEtLSBHZW5lcmF0b3I6IFNrZXRjaCA1OCAoODQ2NjMpIC0gaHR0cHM6Ly9za2V0Y2guY29tIC0tPgogICAgPHRpdGxlPmljb248L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZyBpZD0iUGFnZS0xIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0iaWNvbiIgZmlsbD0iI0ExQTVBOSIgZmlsbC1ydWxlPSJub256ZXJvIj4KICAgICAgICAgICAgPHBhdGggZD0iTTE1LDExMiBMMjU2LjIyMDA1MiwxMTIgTDI1Ni4yMjAwNTIsMTEyIEwyNTYuMjIwMDUyLDE1IEMyNTYuMjIwMDUyLDYuNzE1NzI4NzUgMjYyLjkzNTc4MSwwIDI3MS4yMjAwNTIsMCBMNDE2LDAgQzQyNC4yODQyNzEsMCA0MzEsNi43MTU3Mjg3NSA0MzEsMTUgTDQzMSwxMTIgTDQzMSwxMTIgTDQ5NywxMTIgQzUwNS4yODQyNzEsMTEyIDUxMiwxMTguNzE1NzI5IDUxMiwxMjcgTDUxMiw0NjMgQzUxMiw0NzEuMjg0MjcxIDUwNS4yODQyNzEsNDc4IDQ5Nyw0NzggTDE1LDQ3OCBDNi43MTU3Mjg3NSw0NzggMCw0NzEuMjg0MjcxIDAsNDYzIEwwLDEyNyBDMCwxMTguNzE1NzI5IDYuNzE1NzI4NzUsMTEyIDE1LDExMiBaIiBpZD0iUmVjdGFuZ2xlIj48L3BhdGg+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4='
|
47 |
-
);
|
48 |
-
|
49 |
-
add_submenu_page(
|
50 |
-
'wordpress-zero-spam',
|
51 |
-
__( 'WordPress Zero Spam Dashboard', 'zero-spam' ),
|
52 |
-
__( 'Dashboard', 'zero-spam' ),
|
53 |
-
'manage_options',
|
54 |
-
'wordpress-zero-spam',
|
55 |
-
'wpzerospam_dashboard'
|
56 |
-
);
|
57 |
-
|
58 |
-
add_submenu_page(
|
59 |
-
'wordpress-zero-spam',
|
60 |
-
__( 'Spam Detections', 'zero-spam' ),
|
61 |
-
__( 'Spam Detections', 'zero-spam' ),
|
62 |
-
'manage_options',
|
63 |
-
'wordpress-zero-spam-detections',
|
64 |
-
'wpzerospam_spam_detections_page'
|
65 |
-
);
|
66 |
-
|
67 |
-
add_submenu_page(
|
68 |
-
'wordpress-zero-spam',
|
69 |
-
__( 'Blocked IP Addresses', 'zero-spam' ),
|
70 |
-
__( 'Blocked IPs', 'zero-spam' ),
|
71 |
-
'manage_options',
|
72 |
-
'wordpress-zero-spam-blocked-ips',
|
73 |
-
'wpzerospam_blocked_ips_page'
|
74 |
-
);
|
75 |
-
|
76 |
-
add_submenu_page(
|
77 |
-
'wordpress-zero-spam',
|
78 |
-
__( 'Blacklisted IPs', 'zero-spam' ),
|
79 |
-
__( 'Blacklisted IPs', 'zero-spam' ),
|
80 |
-
'manage_options',
|
81 |
-
'wordpress-zero-spam-blacklisted',
|
82 |
-
'wpzerospam_blacklist_page'
|
83 |
-
);
|
84 |
-
|
85 |
-
add_submenu_page(
|
86 |
-
'wordpress-zero-spam',
|
87 |
-
__( 'WordPress Zero Spam Settings', 'zero-spam' ),
|
88 |
-
__( 'Settings', 'zero-spam' ),
|
89 |
-
'manage_options',
|
90 |
-
'wordpress-zero-spam-settings',
|
91 |
-
'wpzerospam_options_page'
|
92 |
-
);
|
93 |
-
}
|
94 |
-
add_action( 'admin_menu', 'wpzerospam_admin_menu' );
|
95 |
-
|
96 |
-
function wpzerospam_spam_detections_page() {
|
97 |
-
if ( ! current_user_can( 'manage_options' ) ) { return; }
|
98 |
-
?>
|
99 |
-
<div class="wrap">
|
100 |
-
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
|
101 |
-
|
102 |
-
<?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'templates/callout.php'; ?>
|
103 |
-
|
104 |
-
<?php
|
105 |
-
/**
|
106 |
-
* Log table
|
107 |
-
*/
|
108 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'classes/class-wpzerospam-log-table.php';
|
109 |
-
|
110 |
-
$table_data = new WPZeroSpam_Log_Table();
|
111 |
-
|
112 |
-
// Fetch, prepare, sort, and filter our data...
|
113 |
-
$table_data->prepare_items();
|
114 |
-
?>
|
115 |
-
<form id="log-table" method="post">
|
116 |
-
<?php wp_nonce_field( 'wpzerospam_nonce', 'wpzerospam_nonce' ); ?>
|
117 |
-
<input type="hidden" name="paged" value="1" />
|
118 |
-
<?php $table_data->search_box( __( 'Search IPs', 'zero-spam' ), 'search-ip' ); ?>
|
119 |
-
<?php $table_data->display(); ?>
|
120 |
-
</form>
|
121 |
-
</div>
|
122 |
-
<?php
|
123 |
-
}
|
124 |
-
|
125 |
-
function wpzerospam_blacklist_page() {
|
126 |
-
if ( ! current_user_can( 'manage_options' ) ) { return; }
|
127 |
-
?>
|
128 |
-
<div class="wrap">
|
129 |
-
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
|
130 |
-
|
131 |
-
<?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'templates/callout.php'; ?>
|
132 |
-
|
133 |
-
<?php
|
134 |
-
/**
|
135 |
-
* Blocked IP table
|
136 |
-
*/
|
137 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'classes/class-wpzerospam-blacklisted-table.php';
|
138 |
-
|
139 |
-
$table_data = new WPZeroSpam_Blacklisted_Table();
|
140 |
-
|
141 |
-
// Fetch, prepare, sort, and filter our data...
|
142 |
-
$table_data->prepare_items();
|
143 |
-
?>
|
144 |
-
<form id="blacklist-table" method="post">
|
145 |
-
<?php wp_nonce_field( 'wpzerospam_nonce', 'wpzerospam_nonce' ); ?>
|
146 |
-
<input type="hidden" name="paged" value="1" />
|
147 |
-
<?php $table_data->search_box( __( 'Search IPs', 'zero-spam' ), 'search-ip' ); ?>
|
148 |
-
<?php $table_data->display(); ?>
|
149 |
-
</form>
|
150 |
-
</div>
|
151 |
-
<?php
|
152 |
-
}
|
153 |
-
|
154 |
-
function wpzerospam_add_blocked_ip_action() {
|
155 |
-
if ( ! empty( $_POST ) ) {
|
156 |
-
$ip = sanitize_text_field( $_POST['blocked_ip'] );
|
157 |
-
$type = in_array( sanitize_text_field( $_POST['blocked_type'] ), [ 'permanent', 'temporary' ] ) ? sanitize_text_field( $_POST['blocked_type'] ) : false;
|
158 |
-
$reason = sanitize_text_field( $_POST['blocked_reason'] );
|
159 |
-
$blocked_start_date = sanitize_text_field( $_POST['blocked_start_date'] );
|
160 |
-
$blocked_end_date = sanitize_text_field( $_POST['blocked_end_date'] );
|
161 |
-
|
162 |
-
if ( ! $ip || false === WP_Http::is_ip_address( $ip ) ) {
|
163 |
-
wp_redirect( $_SERVER['HTTP_REFERER'] . '&error=1' );
|
164 |
-
exit;
|
165 |
-
}
|
166 |
-
|
167 |
-
if ( ! $type ) {
|
168 |
-
wp_redirect( $_SERVER['HTTP_REFERER'] . '&error=2' );
|
169 |
-
exit;
|
170 |
-
}
|
171 |
-
|
172 |
-
$data = [ 'blocked_type' => $type ];
|
173 |
-
|
174 |
-
if ( $reason ) {
|
175 |
-
$data['reason'] = $reason;
|
176 |
-
} else {
|
177 |
-
$data['reason'] = NULL;
|
178 |
-
}
|
179 |
-
|
180 |
-
if ( $blocked_start_date ) {
|
181 |
-
$data['start_block'] = date( 'Y-m-d G:i:s', strtotime( $blocked_start_date ));
|
182 |
-
} else {
|
183 |
-
$data['start_block'] = NULL;
|
184 |
-
}
|
185 |
-
|
186 |
-
if ( $blocked_end_date ) {
|
187 |
-
$data['end_block'] = date( 'Y-m-d G:i:s', strtotime( $blocked_end_date ));
|
188 |
-
} else {
|
189 |
-
$data['end_block'] = NULL;
|
190 |
-
}
|
191 |
-
|
192 |
-
if ( 'temporary' == $type && ! $data['end_block'] ) {
|
193 |
-
wp_redirect( $_SERVER['HTTP_REFERER'] . '&error=3' );
|
194 |
-
exit;
|
195 |
-
}
|
196 |
-
|
197 |
-
$data['attempts'] = 0;
|
198 |
-
|
199 |
-
wpzerospam_update_blocked_ip( $ip, $data );
|
200 |
-
}
|
201 |
-
|
202 |
-
wp_redirect( $_SERVER['HTTP_REFERER'] . '&success=1' );
|
203 |
-
exit();
|
204 |
-
}
|
205 |
-
add_action( 'admin_action_add_blocked_ip', 'wpzerospam_add_blocked_ip_action' );
|
206 |
-
|
207 |
-
function wpzerospam_blocked_ips_page() {
|
208 |
-
if ( ! current_user_can( 'manage_options' ) ) { return; }
|
209 |
-
?>
|
210 |
-
<div class="wrap">
|
211 |
-
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
|
212 |
-
|
213 |
-
<?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'templates/callout.php'; ?>
|
214 |
-
|
215 |
-
<?php if ( ! empty( $_GET['error'] ) ): ?>
|
216 |
-
<div class="notice notice-error is-dismissible">
|
217 |
-
<p><strong>
|
218 |
-
<?php
|
219 |
-
switch( $_GET['error'] ):
|
220 |
-
case 1:
|
221 |
-
_e( 'Please enter a valid IP address.', 'zero-spam' );
|
222 |
-
break;
|
223 |
-
case 2:
|
224 |
-
_e( 'Please select a valid type.', 'zero-spam' );
|
225 |
-
break;
|
226 |
-
case 3:
|
227 |
-
_e( 'Please select a date & time when the temporary block should end.', 'zero-spam' );
|
228 |
-
break;
|
229 |
-
endswitch;
|
230 |
-
?>
|
231 |
-
</strong></p>
|
232 |
-
<button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php _e( 'Dismiss this notice.', 'zero-spam' ); ?></span></button>
|
233 |
-
</div>
|
234 |
-
<?php elseif ( ! empty( $_GET['success'] ) ): ?>
|
235 |
-
<div class="notice notice-success is-dismissible">
|
236 |
-
<p><strong><?php _e( 'The blocked IP has been successfully added.', 'wpzerospam' ); ?></strong></p>
|
237 |
-
<button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php _e( 'Dismiss this notice.', 'zero-spam' ); ?>.</span></button>
|
238 |
-
</div>
|
239 |
-
<?php endif; ?>
|
240 |
-
<form method="post" action="<?php echo admin_url( 'admin.php' ); ?>">
|
241 |
-
<input type="hidden" name="action" value="add_blocked_ip" />
|
242 |
-
<div class="wpzerospam-callout wpzerospam-add-ip-container<?php if( ! empty( $_REQUEST['ip'] ) ): ?> wpzerospam-add-ip-container-highlight<?php endif; ?>">
|
243 |
-
<h2><?php _e( 'Add Blocked IP', 'wpzerospam' ); ?></h2>
|
244 |
-
<div class="wpzerospam-add-ip-field">
|
245 |
-
<label for="blocked-ip"><?php _e( 'IP Address', 'zero-spam' ); ?></label>
|
246 |
-
<input
|
247 |
-
type="text"
|
248 |
-
id="blocked-ip"
|
249 |
-
name="blocked_ip"
|
250 |
-
value="<?php if( ! empty( $_REQUEST['ip'] ) ): echo esc_attr( $_REQUEST['ip'] ); endif; ?>"
|
251 |
-
placeholder="e.g. xxx.xxx.x.x"
|
252 |
-
/>
|
253 |
-
</div>
|
254 |
-
<div class="wpzerospam-add-ip-field">
|
255 |
-
<label for="blocked-type"><?php _e( 'Type', 'zero-spam' ); ?></label>
|
256 |
-
<select id="blocked-type" name="blocked_type">
|
257 |
-
<option value="temporary"><?php _e( 'Temporary', 'zero-spam' ); ?></option>
|
258 |
-
<option value="permanent"><?php _e( 'Permanent', 'zero-spam' ); ?></option>
|
259 |
-
</select>
|
260 |
-
</div>
|
261 |
-
<div class="wpzerospam-add-ip-field" id="wpzerospam-add-ip-field-reason">
|
262 |
-
<label for="blocked-reason"><?php _e( 'Reason', 'zero-spam' ); ?></label>
|
263 |
-
<input type="text" id="blocked-reason" name="blocked_reason" value="" placeholder="<?php _e( 'e.g. Spammed form', 'zero-spam' ); ?>" />
|
264 |
-
</div>
|
265 |
-
<div class="wpzerospam-add-ip-field" id="wpzerospam-add-ip-field-start-date">
|
266 |
-
<label for="blocked-start-date"><?php _e( 'Start Date', 'zero-spam' ); ?></label>
|
267 |
-
<input type="datetime-local" id="blocked-start-date" name="blocked_start_date" value="" placeholder="<?php _e( 'Optional', 'zero-spam' ); ?>" />
|
268 |
-
</div>
|
269 |
-
<div class="wpzerospam-add-ip-field" id="wpzerospam-add-ip-field-end-date">
|
270 |
-
<label for="blocked-end-date"><?php _e( 'End Date', 'zero-spam' ); ?></label>
|
271 |
-
<input type="datetime-local" id="blocked-end-date" name="blocked_end_date" value="" placeholder="<?php _e( 'Optional', 'zero-spam' ); ?>" />
|
272 |
-
</div>
|
273 |
-
<div class="wpzerospam-add-ip-field" id="wpzerospam-add-ip-field-submit">
|
274 |
-
<input type="submit" class="button button-primary" value="<?php _e( 'Add Blocked IP', 'zero-spam' ); ?>" />
|
275 |
-
</div>
|
276 |
-
</div>
|
277 |
-
</form>
|
278 |
-
|
279 |
-
<?php
|
280 |
-
/**
|
281 |
-
* Blocked IP table
|
282 |
-
*/
|
283 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'classes/class-wpzerospam-blocked-ip-table.php';
|
284 |
-
|
285 |
-
$table_data = new WPZeroSpam_Blocked_IP_Table();
|
286 |
-
|
287 |
-
// Fetch, prepare, sort, and filter our data...
|
288 |
-
$table_data->prepare_items();
|
289 |
-
?>
|
290 |
-
<form id="blocked-table" method="post">
|
291 |
-
<?php wp_nonce_field( 'wpzerospam_nonce', 'wpzerospam_nonce' ); ?>
|
292 |
-
<input type="hidden" name="paged" value="1" />
|
293 |
-
<?php $table_data->search_box( __( 'Search IPs', 'zero-spam' ), 'search-ip' ); ?>
|
294 |
-
<?php $table_data->display(); ?>
|
295 |
-
</form>
|
296 |
-
</div>
|
297 |
-
<?php
|
298 |
-
}
|
299 |
-
|
300 |
-
function wpzerospam_dashboard() {
|
301 |
-
if ( ! current_user_can( 'manage_options' ) ) { return; }
|
302 |
-
|
303 |
-
$log = wpzerospam_query( 'log' );
|
304 |
-
|
305 |
-
$predefined_colors = [
|
306 |
-
'#1a0003', '#4d000a', '#800011', '#b30017', '#e6001e', '#ff1a38', '#ff4d64', '#ff8090', '#ffb3bd', '#ffe5e9'
|
307 |
-
];
|
308 |
-
?>
|
309 |
-
<div class="wrap">
|
310 |
-
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
|
311 |
-
|
312 |
-
<?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'templates/callout.php'; ?>
|
313 |
-
|
314 |
-
<h2><?php _e( 'Statistics', 'wpzerospam' ); ?></h2>
|
315 |
-
<div class="wpzerospam-boxes">
|
316 |
-
<?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'templates/map.php'; ?>
|
317 |
-
<?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'templates/ip-list.php'; ?>
|
318 |
-
<?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'templates/countries-pie-chart.php'; ?>
|
319 |
-
<?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'templates/regions-pie-chart.php'; ?>
|
320 |
-
<?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'templates/spam-line-chart.php'; ?>
|
321 |
-
</div>
|
322 |
-
</div>
|
323 |
-
<?php
|
324 |
-
}
|
325 |
-
|
326 |
-
function wpzerospam_options_page() {
|
327 |
-
if ( ! current_user_can( 'manage_options' ) ) { return; }
|
328 |
-
?>
|
329 |
-
<div class="wrap">
|
330 |
-
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
|
331 |
-
|
332 |
-
<?php require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'templates/callout.php'; ?>
|
333 |
-
|
334 |
-
<form action="options.php" method="post">
|
335 |
-
<?php
|
336 |
-
// Output security fields for the registered setting "wpzerospam"
|
337 |
-
settings_fields( 'wpzerospam' );
|
338 |
-
|
339 |
-
// Output setting sections and their fields
|
340 |
-
do_settings_sections( 'wpzerospam' );
|
341 |
-
|
342 |
-
// Output save settings button
|
343 |
-
submit_button( 'Save Settings' );
|
344 |
-
?>
|
345 |
-
</form>
|
346 |
-
</div>
|
347 |
-
<?php
|
348 |
-
}
|
349 |
-
|
350 |
-
function wpzerospam_validate_options( $input ) {
|
351 |
-
if ( empty( $input['log_spam'] ) ) { $input['log_spam'] = 'disabled'; }
|
352 |
-
if ( empty( $input['log_blocked_ips'] ) ) { $input['log_blocked_ips'] = 'disabled'; }
|
353 |
-
if ( empty( $input['auto_block_ips'] ) ) { $input['auto_block_ips'] = 'disabled'; }
|
354 |
-
if ( empty( $input['auto_block_period'] ) ) { $input['auto_block_period'] = 0; }
|
355 |
-
if ( empty( $input['botscout_api'] ) ) { $input['botscout'] = false; }
|
356 |
-
if ( empty( $input['auto_block_permanently'] ) ) { $input['auto_block_permanently'] = 3; }
|
357 |
-
if ( empty( $input['api_timeout'] ) ) { $input['api_timeout'] = 5; }
|
358 |
-
if ( empty( $input['stopforumspam_confidence_min'] ) ) { $input['stopforumspam_confidence_min'] = 20; }
|
359 |
-
if ( empty( $input['botscout_count_min'] ) ) { $input['botscout_count_min'] = 5; }
|
360 |
-
if ( empty( $input['cookie_expiration'] ) ) { $input['cookie_expiration'] = 7; }
|
361 |
-
|
362 |
-
if ( empty( $input['ip_whitelist'] ) ) {
|
363 |
-
$input['ip_whitelist'] = '';
|
364 |
-
} else {
|
365 |
-
$whitelist = explode( PHP_EOL, $input['ip_whitelist'] );
|
366 |
-
$cleaned_whitelist = '';
|
367 |
-
foreach( $whitelist as $k => $whitelisted_ip ) {
|
368 |
-
$whitelisted_ip = trim( $whitelisted_ip );
|
369 |
-
|
370 |
-
if ( rest_is_ip_address( $whitelisted_ip ) ) {
|
371 |
-
if ( $cleaned_whitelist ) { $cleaned_whitelist .= "\n"; }
|
372 |
-
$cleaned_whitelist .= $whitelisted_ip;
|
373 |
-
}
|
374 |
-
}
|
375 |
-
|
376 |
-
$input['ip_whitelist'] = $cleaned_whitelist;
|
377 |
-
}
|
378 |
-
|
379 |
-
if ( empty( $input['verify_bp_registrations'] ) ) {
|
380 |
-
$input['verify_bp_registrations'] = 'disabled';
|
381 |
-
}
|
382 |
-
|
383 |
-
if ( empty( $input['verify_wpforms'] ) ) {
|
384 |
-
$input['verify_wpforms'] = 'disabled';
|
385 |
-
}
|
386 |
-
|
387 |
-
if ( empty( $input['verify_fluentform'] ) ) {
|
388 |
-
$input['verify_fluentform'] = 'disabled';
|
389 |
-
}
|
390 |
-
|
391 |
-
if ( empty( $input['verify_formidable'] ) ) {
|
392 |
-
$input['verify_formidable'] = 'disabled';
|
393 |
-
}
|
394 |
-
|
395 |
-
if ( empty( $input['stop_forum_spam'] ) ) {
|
396 |
-
$input['stop_forum_spam'] = 'disabled';
|
397 |
-
}
|
398 |
-
|
399 |
-
if ( empty( $input['share_detections'] ) ) {
|
400 |
-
$input['share_detections'] = 'disabled';
|
401 |
-
}
|
402 |
-
|
403 |
-
if ( empty( $input['blocked_message'] ) ) {
|
404 |
-
$input['blocked_message'] = __( 'You have been blocked from visiting this site by WordPress Zero Spam due to detected spam activity.', 'zero-spam' );
|
405 |
-
}
|
406 |
-
|
407 |
-
$input = apply_filters( 'wpzerospam_admin_validation', $input );
|
408 |
-
|
409 |
-
return $input;
|
410 |
-
}
|
411 |
-
|
412 |
-
/**
|
413 |
-
* Add settings link to plugin description
|
414 |
-
*/
|
415 |
-
function wpzerospam_admin_action_links( $actions, $plugin_file, $plugin_data, $context ) {
|
416 |
-
$links = [
|
417 |
-
'settings' => '<a href="' . admin_url( 'admin.php?page=wordpress-zero-spam-settings' ) . '">' . __( 'Settings' ) . '</a>'
|
418 |
-
];
|
419 |
-
|
420 |
-
return array_merge( $links, $actions );
|
421 |
-
}
|
422 |
-
|
423 |
-
|
424 |
-
function wpzerospam_admin_init() {
|
425 |
-
if( ! function_exists( 'is_plugin_active' ) ) {
|
426 |
-
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
427 |
-
}
|
428 |
-
|
429 |
-
$options = wpzerospam_options();
|
430 |
-
|
431 |
-
// Add settings link to plugin description
|
432 |
-
add_filter( 'plugin_action_links_' . plugin_basename( WORDPRESS_ZERO_SPAM ), 'wpzerospam_admin_action_links', 10, 4 );
|
433 |
-
|
434 |
-
register_setting( 'wpzerospam', 'wpzerospam', 'wpzerospam_validate_options' );
|
435 |
-
|
436 |
-
add_settings_section( 'wpzerospam_general_settings', __( 'General Plugin Settings', 'zero-spam' ), 'wpzerospam_general_settings_cb', 'wpzerospam' );
|
437 |
-
add_settings_section( 'wpzerospam_autoblocks', __( 'Auto-block Settings', 'zero-spam' ), 'wpzerospam_autoblock_settings_cb', 'wpzerospam' );
|
438 |
-
add_settings_section( 'wpzerospam_onsite', __( 'On-site Spam Prevention', 'zero-spam' ), 'wpzerospam_onsite_cb', 'wpzerospam' );
|
439 |
-
add_settings_section( 'wpzerospam_spam_checks', __( 'Integrations & Third-party APIs', 'zero-spam' ), 'wpzerospam_spam_checks_cb', 'wpzerospam' );
|
440 |
-
|
441 |
-
/*add_settings_field( 'share_detections', __( 'Share Spam/Malicious IP Detections', 'wpzerospam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
|
442 |
-
'label_for' => 'share_detections',
|
443 |
-
'type' => 'checkbox',
|
444 |
-
'multi' => false,
|
445 |
-
'desc' => sprintf(
|
446 |
-
wp_kses(
|
447 |
-
__( 'Help support WordPress Zero Spam and strengthen its ability to detect spammers by sharing spam detections. For more information about what\'s being shared, see the plugin\'s <a href="%1$s" target="_blank" rel="noreferrer noopener">documentation</a>.', 'wpzerospam' ),
|
448 |
-
array(
|
449 |
-
'strong' => array(),
|
450 |
-
'a' => array(
|
451 |
-
'href' => array(),
|
452 |
-
'rel' => array(),
|
453 |
-
'target' => array(),
|
454 |
-
)
|
455 |
-
)
|
456 |
-
),
|
457 |
-
esc_url('https://www.benmarshall.me/wordpress-zero-spam/')
|
458 |
-
),
|
459 |
-
'options' => [
|
460 |
-
'enabled' => __( 'Enabled', 'wpzerospam' )
|
461 |
-
]
|
462 |
-
]);*/
|
463 |
-
|
464 |
-
// Cookie expiration
|
465 |
-
add_settings_field( 'cookie_expiration', __( 'Cookie Expiration', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
|
466 |
-
'label_for' => 'cookie_expiration',
|
467 |
-
'type' => 'number',
|
468 |
-
'desc' => wp_kses(
|
469 |
-
__( 'Number of days until a user\'s cookie is expired. Helps boost site performance so access & blacklist checks aren\'t sent each page visit. <strong>Minimum recommend is 7 days</strong>.', 'zero-spam' ),
|
470 |
-
[ 'strong' => [] ]
|
471 |
-
),
|
472 |
-
'class' => 'small-text',
|
473 |
-
'placeholder' => '7',
|
474 |
-
'suffix' => __( 'days', 'zero-spam' )
|
475 |
-
]);
|
476 |
-
|
477 |
-
// Determines is spam detected IPs should automatically be blocked
|
478 |
-
add_settings_field( 'auto_block_ips', __( 'Auto-block IPs', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_autoblocks', [
|
479 |
-
'label_for' => 'auto_block_ips',
|
480 |
-
'type' => 'checkbox',
|
481 |
-
'multi' => false,
|
482 |
-
'desc' => __( 'Auto-blocks IPs addresses that trigger a spam detection.', 'zero-spam' ),
|
483 |
-
'options' => [
|
484 |
-
'enabled' => __( 'Enabled', 'zero-spam' )
|
485 |
-
]
|
486 |
-
]);
|
487 |
-
|
488 |
-
if ( 'enabled' == $options['auto_block_ips'] ) {
|
489 |
-
// Number of minutes a IP should be blocked after a auto-block
|
490 |
-
add_settings_field( 'auto_block_period', __( 'Auto-block Period', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_autoblocks', [
|
491 |
-
'label_for' => 'auto_block_period',
|
492 |
-
'type' => 'number',
|
493 |
-
'desc' => __( 'Number of minutes a user will be blocked from viewing the site after being auto-blocked.', 'zero-spam' ),
|
494 |
-
'class' => 'small-text',
|
495 |
-
'placeholder' => '30',
|
496 |
-
'suffix' => __( 'minutes', 'zero-spam' )
|
497 |
-
]);
|
498 |
-
}
|
499 |
-
|
500 |
-
// Number of spam attempts before the IP is permanently blocked
|
501 |
-
add_settings_field( 'auto_block_permanently', __( 'Permanently Auto-block', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_autoblocks', [
|
502 |
-
'label_for' => 'auto_block_permanently',
|
503 |
-
'type' => 'number',
|
504 |
-
'desc' => __( 'Number of spam detections before an IP is permanently blocked.', 'zero-spam' ),
|
505 |
-
'class' => 'small-text',
|
506 |
-
'placeholder' => 3
|
507 |
-
]);
|
508 |
-
|
509 |
-
// API timeout
|
510 |
-
add_settings_field( 'api_timeout', __( 'API Timeout', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_spam_checks', [
|
511 |
-
'label_for' => 'api_timeout',
|
512 |
-
'type' => 'number',
|
513 |
-
'desc' => wp_kses(
|
514 |
-
__( 'Number of seconds to allow an API to return a response.<br /><strong>WARNING:</strong> Setting this too high could cause your site to load slowly. Setting too low may not allow an API enough time to respond with a result. <strong>Recommended is 5 seconds.</strong>.', 'zero-spam' ),
|
515 |
-
[ 'strong' => [], 'br' => [] ]
|
516 |
-
),
|
517 |
-
'class' => 'small-text',
|
518 |
-
'placeholder' => '30',
|
519 |
-
'suffix' => __( 'seconds', 'zero-spam' )
|
520 |
-
]);
|
521 |
-
|
522 |
-
if ( 'enabled' == $options['log_spam'] ) {
|
523 |
-
// Redirect URL for spam detections
|
524 |
-
add_settings_field( 'ipstack_api', __( 'ipstack API Key', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_spam_checks', [
|
525 |
-
'label_for' => 'ipstack_api',
|
526 |
-
'type' => 'text',
|
527 |
-
'placeholder' => __( 'Enter your ipstack API key.', 'zero-spam' ),
|
528 |
-
'class' => 'regular-text',
|
529 |
-
'desc' => sprintf(
|
530 |
-
wp_kses(
|
531 |
-
__( 'Enter your <a href="%s" target="_blank" rel="noopener noreferrer">ipstack API key</a> to enable location-based statistics. Don\'t have an API key? <a href="%s" target="_blank" rel="noopener noreferrer"><strong>Get one for free!</strong></a>', 'zero-spam' ),
|
532 |
-
[ 'strong' => [], 'a' => [ 'target' => [], 'href' => [], 'rel' => [] ] ]
|
533 |
-
),
|
534 |
-
esc_url( 'https://ipstack.com/' ),
|
535 |
-
esc_url( 'https://ipstack.com/signup/free' )
|
536 |
-
)
|
537 |
-
]);
|
538 |
-
}
|
539 |
-
|
540 |
-
// Enables the ability to check IPs against BotScout blacklists.
|
541 |
-
add_settings_field( 'botscout_api', __( 'BotScout API Key', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_spam_checks', [
|
542 |
-
'label_for' => 'botscout_api',
|
543 |
-
'type' => 'text',
|
544 |
-
'class' => 'regular-text',
|
545 |
-
'placeholder' => __( 'Enter your free BotScout API key.', 'zero-spam' ),
|
546 |
-
'desc' => sprintf(
|
547 |
-
wp_kses(
|
548 |
-
__( 'Enter your BotScout API key to check user IPs against <a href="%s" target="_blank" rel="noopener noreferrer">BotScout</a>\'s blacklist. Don\'t have an API key? <a href="%s" target="_blank" rel="noopener noreferrer"><strong>Get one for free!</strong></a>', 'zero-spam' ),
|
549 |
-
[ 'strong' => [], 'a' => [ 'target' => [], 'href' => [], 'rel' => [] ] ]
|
550 |
-
),
|
551 |
-
esc_url( 'https://botscout.com/' ),
|
552 |
-
esc_url( 'https://botscout.com/getkey.htm' )
|
553 |
-
)
|
554 |
-
]);
|
555 |
-
|
556 |
-
// BotScout count minimum
|
557 |
-
add_settings_field( 'botscout_count_min', __( 'BotScout Count Minimum', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_spam_checks', [
|
558 |
-
'label_for' => 'botscout_count_min',
|
559 |
-
'type' => 'number',
|
560 |
-
'desc' => sprintf(
|
561 |
-
wp_kses(
|
562 |
-
__( 'Minimum <a href="%s" target="_blank" rel="noopener noreferrer">count</a> an IP must meet before being marked as spam/malicious.<br /><strong>WARNING:</strong> Setting this too low could cause users to be blocked that shouldn\'t be, <strong>recommended is 5</strong>.', 'zero-spam' ),
|
563 |
-
[ 'strong' => [], 'a' => [ 'target' => [], 'href' => [], 'rel' => [] ], 'br' => [] ]
|
564 |
-
),
|
565 |
-
esc_url( 'https://botscout.com/api.htm' )
|
566 |
-
),
|
567 |
-
'class' => 'small-text',
|
568 |
-
'placeholder' => '20',
|
569 |
-
]);
|
570 |
-
|
571 |
-
// Enables the ability to check IPs against Stop Forum Spam blacklists.
|
572 |
-
add_settings_field( 'stop_forum_spam', __( 'Stop Forum Spam', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_spam_checks', [
|
573 |
-
'label_for' => 'stop_forum_spam',
|
574 |
-
'type' => 'checkbox',
|
575 |
-
'multi' => false,
|
576 |
-
'desc' => sprintf(
|
577 |
-
wp_kses(
|
578 |
-
__( 'Checks user IPs against <a href="%s" target="_blank" rel="noopener noreferrer">Stop Forum Spam</a>\'s blacklist.', 'zero-spam' ),
|
579 |
-
[ 'strong' => [], 'a' => [ 'target' => [], 'href' => [], 'rel' => [] ] ]
|
580 |
-
),
|
581 |
-
esc_url( 'https://www.stopforumspam.com/' )
|
582 |
-
),
|
583 |
-
'options' => [
|
584 |
-
'enabled' => __( 'Enabled', 'zero-spam' )
|
585 |
-
]
|
586 |
-
]);
|
587 |
-
|
588 |
-
// StopForumSpam confidence minimum
|
589 |
-
add_settings_field( 'stopforumspam_confidence_min', __( 'Stop Forum Spam Confidence Minimum', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_spam_checks', [
|
590 |
-
'label_for' => 'stopforumspam_confidence_min',
|
591 |
-
'type' => 'number',
|
592 |
-
'desc' => sprintf(
|
593 |
-
wp_kses(
|
594 |
-
__( 'Minimum <a href="%s" target="_blank" rel="noopener noreferrer">confidence score</a> an IP must meet before being marked as spam/malicious.<br /><strong>WARNING:</strong> Setting this too low could cause users to be blocked that shouldn\'t be, <strong>recommended is 20%%</strong>.', 'zero-spam' ),
|
595 |
-
[ 'strong' => [], 'a' => [ 'target' => [], 'href' => [], 'rel' => [] ], 'br' => [] ]
|
596 |
-
),
|
597 |
-
esc_url( 'https://www.stopforumspam.com/usage' )
|
598 |
-
),
|
599 |
-
'class' => 'small-text',
|
600 |
-
'placeholder' => '20',
|
601 |
-
'suffix' => '%'
|
602 |
-
]);
|
603 |
-
|
604 |
-
// How to handle blocks
|
605 |
-
add_settings_field( 'block_handler', __( 'Blocked IPs', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
|
606 |
-
'label_for' => 'block_handler',
|
607 |
-
'type' => 'radio',
|
608 |
-
'desc' => __( 'Determines how blocked IPs are handled when they attempt to visit the site.', 'zero-spam' ),
|
609 |
-
'options' => [
|
610 |
-
'redirect' => __( 'Redirect user', 'zero-spam' ),
|
611 |
-
'403' => sprintf(
|
612 |
-
wp_kses(
|
613 |
-
__( 'Display a <a href="%s" target="_blank" rel="noreferrer noopener"><code>403 Forbidden</code></a> error', 'zero-spam' ),
|
614 |
-
[ 'code' => [], 'a' => [ 'target' => [], 'href' => [], 'rel' => [] ] ]
|
615 |
-
),
|
616 |
-
esc_url( 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403' )
|
617 |
-
)
|
618 |
-
]
|
619 |
-
]);
|
620 |
-
|
621 |
-
if ( 'redirect' == $options['block_handler'] ) {
|
622 |
-
// Redirect URL for blocked users
|
623 |
-
add_settings_field( 'blocked_redirect_url', __( 'Redirect for Blocked Users', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
|
624 |
-
'label_for' => 'blocked_redirect_url',
|
625 |
-
'type' => 'url',
|
626 |
-
'class' => 'regular-text',
|
627 |
-
'desc' => __( 'URL blocked users will be taken to.', 'zero-spam' ),
|
628 |
-
'placeholder' => 'e.g. https://google.com'
|
629 |
-
]);
|
630 |
-
} else {
|
631 |
-
// Blocked message
|
632 |
-
add_settings_field( 'blocked_message', __( 'Blocked Message', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
|
633 |
-
'label_for' => 'blocked_message',
|
634 |
-
'type' => 'text',
|
635 |
-
'class' => 'large-text',
|
636 |
-
'desc' => __( 'The message that will be displayed to a blocked user.', 'zero-spam' ),
|
637 |
-
'placeholder' => __( 'You have been blocked from visiting this site by WordPress Zero Spam due to detected spam activity.', 'zero-spam' )
|
638 |
-
]);
|
639 |
-
}
|
640 |
-
|
641 |
-
// How to handle spam detections
|
642 |
-
add_settings_field( 'spam_handler', __( 'Spam Detections', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
|
643 |
-
'label_for' => 'spam_handler',
|
644 |
-
'type' => 'radio',
|
645 |
-
'desc' => __( 'Determines how users are handled when spam is detected.', 'zero-spam' ),
|
646 |
-
'options' => [
|
647 |
-
'redirect' => __( 'Redirect user', 'zero-spam' ),
|
648 |
-
'403' => sprintf(
|
649 |
-
wp_kses(
|
650 |
-
__( 'Display a <a href="%s" target="_blank" rel="noreferrer noopener"><code>403 Forbidden</code></a> error', 'zero-spam' ),
|
651 |
-
[ 'code' => [], 'a' => [ 'target' => [], 'href' => [], 'rel' => [] ] ]
|
652 |
-
),
|
653 |
-
esc_url( 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403' )
|
654 |
-
)
|
655 |
-
]
|
656 |
-
]);
|
657 |
-
|
658 |
-
if ( 'redirect' == $options['spam_handler'] ) {
|
659 |
-
// Redirect URL for spam detections
|
660 |
-
add_settings_field( 'spam_redirect_url', __( 'Redirect for Spam', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
|
661 |
-
'label_for' => 'spam_redirect_url',
|
662 |
-
'type' => 'url',
|
663 |
-
'class' => 'regular-text',
|
664 |
-
'desc' => __( 'URL users will be taken to when a spam submission is detected.', 'zero-spam' ),
|
665 |
-
'placeholder' => 'e.g. https://google.com'
|
666 |
-
]);
|
667 |
-
} else {
|
668 |
-
// Spam message
|
669 |
-
add_settings_field( 'spam_message', __( 'Spam Detection Message', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
|
670 |
-
'label_for' => 'spam_message',
|
671 |
-
'type' => 'text',
|
672 |
-
'class' => 'large-text',
|
673 |
-
'desc' => __( 'The message that will be displayed when spam is detected.', 'zero-spam' ),
|
674 |
-
'placeholder' => __( 'There was a problem with your submission. Please go back and try again.', 'zero-spam' )
|
675 |
-
]);
|
676 |
-
}
|
677 |
-
|
678 |
-
// Toggle logging of blocked IPs
|
679 |
-
add_settings_field( 'log_blocked_ips', __( 'Log Blocked IPs', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
|
680 |
-
'label_for' => 'log_blocked_ips',
|
681 |
-
'type' => 'checkbox',
|
682 |
-
'multi' => false,
|
683 |
-
'desc' => __( 'Enables logging of when IPs are blocked from accessing the site.', 'zero-spam' ),
|
684 |
-
'options' => [
|
685 |
-
'enabled' => __( 'Enabled', 'zero-spam' )
|
686 |
-
]
|
687 |
-
]);
|
688 |
-
|
689 |
-
// Log spam detections
|
690 |
-
add_settings_field( 'log_spam', __( 'Log Spam Detections', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
|
691 |
-
'label_for' => 'log_spam',
|
692 |
-
'type' => 'checkbox',
|
693 |
-
'multi' => false,
|
694 |
-
'desc' => __( 'Enables logging of spam detections and provides an admin interface to view statistics.', 'zero-spam' ),
|
695 |
-
'options' => [
|
696 |
-
'enabled' => __( 'Enabled', 'zero-spam' )
|
697 |
-
]
|
698 |
-
]);
|
699 |
-
|
700 |
-
do_action( 'wpzerospam_admin_options' );
|
701 |
-
|
702 |
-
// BuddyPress registrations spam check
|
703 |
-
if ( function_exists( 'bp_is_active' ) ) {
|
704 |
-
add_settings_field( 'verify_bp_registrations', __( 'Verify BuddyPress Registrations', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_spam_checks', [
|
705 |
-
'label_for' => 'verify_bp_registrations',
|
706 |
-
'type' => 'checkbox',
|
707 |
-
'multi' => false,
|
708 |
-
'desc' => __( 'Enables spam detection for BuddyPress registrations.', 'zero-spam' ),
|
709 |
-
'options' => [
|
710 |
-
'enabled' => __( 'Enabled', 'zero-spam' )
|
711 |
-
]
|
712 |
-
]);
|
713 |
-
}
|
714 |
-
|
715 |
-
// WPForms spam check
|
716 |
-
if ( is_plugin_active( 'wpforms/wpforms.php' ) || is_plugin_active( 'wpforms-lite/wpforms.php' ) ) {
|
717 |
-
add_settings_field( 'verify_wpforms', __( 'Verify WPForms Submissions', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_spam_checks', [
|
718 |
-
'label_for' => 'verify_wpforms',
|
719 |
-
'type' => 'checkbox',
|
720 |
-
'multi' => false,
|
721 |
-
'desc' => __( 'Enables spam detection for WPForms submissions.'. 'zero-spam' ),
|
722 |
-
'options' => [
|
723 |
-
'enabled' => __( 'Enabled', 'zero-spam' )
|
724 |
-
]
|
725 |
-
]);
|
726 |
-
}
|
727 |
-
|
728 |
-
// Fluent Form spam check
|
729 |
-
if ( is_plugin_active( 'fluentform/fluentform.php' ) ) {
|
730 |
-
add_settings_field( 'verify_fluentform', __( 'Verify Fluent Form Submissions', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_spam_checks', [
|
731 |
-
'label_for' => 'verify_fluentform',
|
732 |
-
'type' => 'checkbox',
|
733 |
-
'multi' => false,
|
734 |
-
'desc' => __( 'Enables spam detection for Fluent Form submissions.', 'zero-spam' ),
|
735 |
-
'options' => [
|
736 |
-
'enabled' => __( 'Enabled', 'zero-spam' )
|
737 |
-
]
|
738 |
-
]);
|
739 |
-
}
|
740 |
-
|
741 |
-
// Formidable forms spam check
|
742 |
-
if ( is_plugin_active( 'formidable/formidable.php' ) ) {
|
743 |
-
add_settings_field( 'verify_formidable', __( 'Verify Formidable Form Submissions', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_spam_checks', [
|
744 |
-
'label_for' => 'verify_formidable',
|
745 |
-
'type' => 'checkbox',
|
746 |
-
'multi' => false,
|
747 |
-
'desc' => __( 'Enables spam detection for Formidable form submissions.', 'zero-spam' ),
|
748 |
-
'options' => [
|
749 |
-
'enabled' => __( 'Enabled', 'zero-spam' )
|
750 |
-
]
|
751 |
-
]);
|
752 |
-
}
|
753 |
-
|
754 |
-
// IP whitelist
|
755 |
-
add_settings_field( 'ip_whitelist', __( 'IP Whitelist', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_general_settings', [
|
756 |
-
'label_for' => 'ip_whitelist',
|
757 |
-
'type' => 'textarea',
|
758 |
-
'class' => 'large-text',
|
759 |
-
'desc' => __( 'Enter IPs that should be whitelisted (IPs that should never be blocked), one per line.', 'zero-spam' ),
|
760 |
-
'placeholder' => __( 'e.g. xxx.xxx.x.x', 'zero-spam' )
|
761 |
-
]);
|
762 |
-
}
|
763 |
-
add_action( 'admin_init', 'wpzerospam_admin_init' );
|
764 |
-
|
765 |
-
function wpzerospam_general_settings_cb() {
|
766 |
-
echo wp_kses(
|
767 |
-
__( '<strong>WordPress Zero Spam just works — no need for additional configuration.</strong> However, for more control over its functionality, you can configure the general settings below.', 'wpzerospam' ),
|
768 |
-
array(
|
769 |
-
'strong' => array(),
|
770 |
-
)
|
771 |
-
);
|
772 |
-
}
|
773 |
-
|
774 |
-
function wpzerospam_autoblock_settings_cb() {
|
775 |
-
}
|
776 |
-
|
777 |
-
function wpzerospam_spam_checks_cb() {
|
778 |
-
}
|
779 |
-
|
780 |
-
function wpzerospam_onsite_cb() {
|
781 |
-
}
|
782 |
-
|
783 |
-
function wpzerospam_whitelist_cb() {
|
784 |
-
}
|
785 |
-
|
786 |
-
function wpzerospam_field_cb( $args ) {
|
787 |
-
$options = wpzerospam_options();
|
788 |
-
|
789 |
-
switch( $args['type'] ) {
|
790 |
-
case 'url':
|
791 |
-
case 'text':
|
792 |
-
case 'password':
|
793 |
-
case 'number':
|
794 |
-
case 'email':
|
795 |
-
?>
|
796 |
-
<input class="<?php echo $args['class']; ?>" type="<?php echo $args['type']; ?>" value="<?php if ( ! empty( $options[ $args['label_for'] ] ) ): echo esc_attr( $options[ $args['label_for'] ] ); endif; ?>" placeholder="<?php if ( ! empty( $args['placeholder'] ) ): echo $args['placeholder']; endif; ?>" id="<?php echo esc_attr( $args['label_for'] ); ?>" name="wpzerospam[<?php echo esc_attr( $args['label_for'] ); ?>]"><?php if ( ! empty( $args['suffix'] ) ): echo ' ' . $args['suffix']; endif; ?>
|
797 |
-
<p class="description"><?php echo $args['desc'] ?></p>
|
798 |
-
<?php
|
799 |
-
break;
|
800 |
-
case 'textarea':
|
801 |
-
?>
|
802 |
-
<textarea rows="10" class="<?php echo $args['class']; ?>" id="<?php echo esc_attr( $args['label_for'] ); ?>" name="wpzerospam[<?php echo esc_attr( $args['label_for'] ); ?>]"><?php if ( ! empty( $options[ $args['label_for'] ] ) ): echo esc_attr( $options[ $args['label_for'] ] ); endif; ?></textarea>
|
803 |
-
<p class="description"><?php echo $args['desc'] ?></p>
|
804 |
-
<?php
|
805 |
-
break;
|
806 |
-
case 'select':
|
807 |
-
?>
|
808 |
-
<select name="wpzerospam[<?php echo esc_attr( $args['label_for'] ); ?>]" id="<?php echo esc_attr( $args['label_for'] ); ?>">
|
809 |
-
<?php foreach( $args['options'] as $key => $label ): ?>
|
810 |
-
<option value="<?php echo $key; ?>"<?php if ( $key === $options[ $args['label_for'] ] ): ?> selected="selected"<?php endif; ?>><?php echo $label; ?></option>
|
811 |
-
<?php endforeach; ?>
|
812 |
-
</select>
|
813 |
-
<p class="description"><?php echo $args['desc'] ?></p>
|
814 |
-
<?php
|
815 |
-
break;
|
816 |
-
case 'checkbox':
|
817 |
-
?>
|
818 |
-
<?php foreach( $args['options'] as $key => $label ): ?>
|
819 |
-
<label for="<?php echo esc_attr( $args['label_for'] . $key ); ?>">
|
820 |
-
<input
|
821 |
-
type="checkbox"
|
822 |
-
<?php if ( ! empty( $args['class'] ) ): ?>class="<?php echo $args['class']; ?>"<?php endif; ?>
|
823 |
-
id="<?php echo esc_attr( $args['label_for'] . $key ); ?>"
|
824 |
-
name="wpzerospam[<?php echo esc_attr( $args['label_for'] ); ?>]<?php if( $args['multi'] ): ?>[<?php echo $key; ?>]<?php endif; ?>" value="<?php echo $key; ?>"
|
825 |
-
<?php if( $args['multi'] && $key === $options[ $args['label_for'] ][ $key ] || ! $args['multi'] && $key === $options[ $args['label_for'] ] ): ?> checked="checked"<?php endif; ?> /> <?php echo $label; ?>
|
826 |
-
</label>
|
827 |
-
<?php endforeach; ?>
|
828 |
-
<p class="description"><?php echo $args['desc'] ?></p>
|
829 |
-
<?php
|
830 |
-
break;
|
831 |
-
case 'radio':
|
832 |
-
?>
|
833 |
-
<?php foreach( $args['options'] as $key => $label ): ?>
|
834 |
-
<label for="<?php echo esc_attr( $args['label_for'] . $key ); ?>">
|
835 |
-
<input
|
836 |
-
type="radio"
|
837 |
-
<?php if ( ! empty( $args['class'] ) ): ?>class="<?php echo $args['class']; ?>"<?php endif; ?>
|
838 |
-
id="<?php echo esc_attr( $args['label_for'] . $key ); ?>"
|
839 |
-
name="wpzerospam[<?php echo esc_attr( $args['label_for'] ); ?>]" value="<?php echo $key; ?>"
|
840 |
-
<?php if( $key == $options[ $args['label_for'] ] ): ?> checked="checked"<?php endif; ?> /> <?php echo $label; ?>
|
841 |
-
</label><br />
|
842 |
-
<?php endforeach; ?>
|
843 |
-
<p class="description"><?php echo $args['desc'] ?></p>
|
844 |
-
<?php
|
845 |
-
break;
|
846 |
-
}
|
847 |
-
?>
|
848 |
-
<?php
|
849 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/helpers.php
DELETED
@@ -1,600 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Plugin helpers
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.0.0
|
7 |
-
* @link https://benmarshall.me/wordpress-zero-spam/
|
8 |
-
*/
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Logs a spam detection.
|
12 |
-
*
|
13 |
-
* This functions logs (if enabled) detections & handles sharing those
|
14 |
-
* detections with Zero Spam (if enabled).
|
15 |
-
*
|
16 |
-
* @since 4.9.7
|
17 |
-
*
|
18 |
-
* @param string $type Machine-readable name of the detection type. Pass an 'ip'
|
19 |
-
* key to define a specific IP address vs. inferring it
|
20 |
-
* from the current users IP address.
|
21 |
-
* @param array $data Optional. Array of additional information to log.
|
22 |
-
*/
|
23 |
-
if ( ! function_exists( 'wpzerospam_log_detection' ) ) {
|
24 |
-
function wpzerospam_log_detection( $type, $data = [] ) {
|
25 |
-
global $wpdb;
|
26 |
-
$options = wpzerospam_options();
|
27 |
-
|
28 |
-
// Setup the detection record.
|
29 |
-
$record = [
|
30 |
-
'user_ip' => wpzerospam_ip(),
|
31 |
-
'log_type' => $type,
|
32 |
-
'date_recorded' => current_time( 'mysql' )
|
33 |
-
];
|
34 |
-
|
35 |
-
// Check if an IP address is present, if not, get it from the current user.
|
36 |
-
if ( ! empty( $data['ip'] ) && rest_is_ip_address( $data['ip'] ) ) {
|
37 |
-
$record['user_ip'] = $data['ip'];
|
38 |
-
}
|
39 |
-
|
40 |
-
// Make sure an IP address was found.
|
41 |
-
if (
|
42 |
-
empty( $record['user_ip'] ) ||
|
43 |
-
! rest_is_ip_address( $record['user_ip'] )
|
44 |
-
) {
|
45 |
-
return false;
|
46 |
-
}
|
47 |
-
|
48 |
-
// If sharing detections is enabled, send the detection to Zero Spam.
|
49 |
-
if ( 'enabled' == $options['share_detections'] ) {
|
50 |
-
/*wpzerospam_share_detection([
|
51 |
-
'ip' => $record['user_ip'],
|
52 |
-
'type' => $record['log_type']
|
53 |
-
]);*/
|
54 |
-
}
|
55 |
-
|
56 |
-
// Check if logging detections & 'blocks' are enabled.
|
57 |
-
if (
|
58 |
-
'enabled' != $options['log_spam'] ||
|
59 |
-
('blocked' == $record['log_type'] && 'enabled' != $options['log_blocked_ips'])
|
60 |
-
) {
|
61 |
-
// Logging disabled.
|
62 |
-
return false;
|
63 |
-
}
|
64 |
-
|
65 |
-
// Logging enabled, get the current URL & IP location information.
|
66 |
-
$location = wpzerospam_get_ip_info( $record['user_ip'] );
|
67 |
-
$current_url = wpzerospam_current_url();
|
68 |
-
|
69 |
-
// Add additional information to the detection record.
|
70 |
-
$record['page_url'] = ! empty( $current_url['full'] ) ? $current_url['full'] : false;
|
71 |
-
$record['submission_data'] = json_encode( $data );
|
72 |
-
|
73 |
-
if ( $location ) {
|
74 |
-
$record['country'] = ! empty( $location['country_code'] ) ? $location['country_code'] : false;
|
75 |
-
$record['region'] = ! empty( $location['region_code'] ) ? $location['region_code'] : false;
|
76 |
-
$record['city'] = ! empty( $location['city'] ) ? $location['city'] : false;
|
77 |
-
$record['latitude'] = ! empty( $location['latitude'] ) ? $location['latitude'] : false;
|
78 |
-
$record['longitude'] = ! empty( $location['longitude'] ) ? $location['longitude'] : false;
|
79 |
-
}
|
80 |
-
|
81 |
-
return $wpdb->insert( wpzerospam_tables( 'log' ), $record );
|
82 |
-
}
|
83 |
-
}
|
84 |
-
|
85 |
-
/**
|
86 |
-
* Shares a detection with the Zero Spam database.
|
87 |
-
*/
|
88 |
-
function wpzerospam_share_detection( $data ) {
|
89 |
-
// The Zero Spam API endpoint for sharing detections.
|
90 |
-
$api_url = 'https://zerospam.org/wp-json/wpzerospamapi/v1/detection/';
|
91 |
-
|
92 |
-
// Make sure a type & valid IP address are provided.
|
93 |
-
if (
|
94 |
-
empty( $data['ip'] ) ||
|
95 |
-
! rest_is_ip_address( $data['ip'] ) ||
|
96 |
-
empty( $data['type'] )
|
97 |
-
) {
|
98 |
-
return false;
|
99 |
-
}
|
100 |
-
|
101 |
-
// Setup the request parameters.
|
102 |
-
$request_args = [
|
103 |
-
'method' => 'POST',
|
104 |
-
'timeout' => 100,
|
105 |
-
'body' => [
|
106 |
-
'ip' => $data['ip'],
|
107 |
-
'type' => $data['type'],
|
108 |
-
'site' => site_url(),
|
109 |
-
'email' => get_bloginfo( 'admin_email' ),
|
110 |
-
'wpversion' => get_bloginfo( 'version' ),
|
111 |
-
'name' => get_bloginfo( 'name' ),
|
112 |
-
'desc' => get_bloginfo( 'description' ),
|
113 |
-
'language' => get_bloginfo( 'language' ),
|
114 |
-
'version' => WORDPRESS_ZERO_SPAM_VERSION
|
115 |
-
],
|
116 |
-
'sslverify' => true
|
117 |
-
];
|
118 |
-
|
119 |
-
// For debugging purposes only.
|
120 |
-
if ( WP_DEBUG ) {
|
121 |
-
$request_args['sslverify'] = false;
|
122 |
-
}
|
123 |
-
|
124 |
-
// Send the request.
|
125 |
-
$request = wp_remote_post( $api_url, $request_args );
|
126 |
-
if ( is_wp_error( $request ) ) {
|
127 |
-
// Request failed.
|
128 |
-
return false;
|
129 |
-
}
|
130 |
-
|
131 |
-
// Request succeeded, return the result.
|
132 |
-
return wp_remote_retrieve_body( $request );
|
133 |
-
}
|
134 |
-
|
135 |
-
/**
|
136 |
-
* Returns the generated key for checking submissions.
|
137 |
-
*
|
138 |
-
* @since 4.0.0
|
139 |
-
*
|
140 |
-
* @return string A unique key used for detections.
|
141 |
-
*/
|
142 |
-
if ( ! function_exists( 'wpzerospam_get_key' ) ) {
|
143 |
-
function wpzerospam_get_key() {
|
144 |
-
$key = get_option( 'wpzerospam_key' );
|
145 |
-
if ( ! $key ) {
|
146 |
-
$key = wp_generate_password( 64 );
|
147 |
-
update_option( 'wpzerospam_key', $key );
|
148 |
-
}
|
149 |
-
|
150 |
-
return $key;
|
151 |
-
}
|
152 |
-
}
|
153 |
-
|
154 |
-
/**
|
155 |
-
* Returns the generated key for checking submissions.
|
156 |
-
*
|
157 |
-
* @since 4.9.9
|
158 |
-
*
|
159 |
-
* @return string A unique key used for the 'honeypot' field.
|
160 |
-
*/
|
161 |
-
if ( ! function_exists( 'wpzerospam_get_honeypot' ) ) {
|
162 |
-
function wpzerospam_get_honeypot() {
|
163 |
-
$key = get_option( 'wpzerospam_honeypot' );
|
164 |
-
if ( ! $key ) {
|
165 |
-
$key = wp_generate_password( 5, false, false );
|
166 |
-
update_option( 'wpzerospam_honeypot', $key );
|
167 |
-
}
|
168 |
-
|
169 |
-
return $key;
|
170 |
-
}
|
171 |
-
}
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
/**
|
183 |
-
* Handles what happens when spam is detected.
|
184 |
-
*
|
185 |
-
* @since 4.0.0
|
186 |
-
*
|
187 |
-
* @param string $type Machine-readable name for the type of spam.
|
188 |
-
* @param array $data Additional information submitted when the spam was detected.
|
189 |
-
* @param boolean $handle_detection Determines if this function should handle the function or is handled in the submission hook.
|
190 |
-
* @return void
|
191 |
-
*/
|
192 |
-
if ( ! function_exists( 'wpzerospam_spam_detected' ) ) {
|
193 |
-
function wpzerospam_spam_detected( $type, $data = [], $handle_detection = true ) {
|
194 |
-
$options = wpzerospam_options();
|
195 |
-
$ip = wpzerospam_ip();
|
196 |
-
|
197 |
-
// Log the spam sttempt
|
198 |
-
wpzerospam_log_detection( $type, $data );
|
199 |
-
|
200 |
-
// Check if number attempts should result in a permanent block
|
201 |
-
$blocked_ip = wpzerospam_get_blocked_ips( $ip );
|
202 |
-
if ( $blocked_ip && $blocked_ip->attempts >= $options['auto_block_permanently'] ) {
|
203 |
-
// Permanently block the IP
|
204 |
-
wpzerospam_update_blocked_ip( $ip , [
|
205 |
-
'blocked_type' => 'permanent',
|
206 |
-
'reason' => $type . ' (permanently auto-blocked)'
|
207 |
-
]);
|
208 |
-
|
209 |
-
// Check if the IP should be temporarily auto-blocked
|
210 |
-
} elseif ( 'enabled' == $options['auto_block_ips'] ) {
|
211 |
-
|
212 |
-
$start_block = current_time( 'mysql' );
|
213 |
-
$end_block = new DateTime( $start_block );
|
214 |
-
$end_block->add( new DateInterval( 'PT' . $options['auto_block_period'] . 'M' ) );
|
215 |
-
|
216 |
-
wpzerospam_update_blocked_ip( $ip , [
|
217 |
-
'blocked_type' => 'temporary',
|
218 |
-
'start_block' => $start_block,
|
219 |
-
'end_block' => $end_block->format('Y-m-d G:i:s'),
|
220 |
-
'reason' => $type . ' (auto-blocked)'
|
221 |
-
]);
|
222 |
-
}
|
223 |
-
|
224 |
-
// Check if WordPress Zero Spam should handle the error. False for forms
|
225 |
-
// that process via AJAX & expect a json response.
|
226 |
-
if ( $handle_detection ) {
|
227 |
-
if ( 'redirect' == $options['spam_handler'] ) {
|
228 |
-
wp_redirect( esc_url( $options['spam_redirect_url'] ) );
|
229 |
-
exit();
|
230 |
-
} else {
|
231 |
-
status_header( 403 );
|
232 |
-
die( $options['spam_message'] );
|
233 |
-
}
|
234 |
-
}
|
235 |
-
}
|
236 |
-
}
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
/**
|
292 |
-
* Checks if either the submission data or $_POST contain the wpzerospam_key and
|
293 |
-
* if it matches whats in the database.
|
294 |
-
*
|
295 |
-
* @param array $submission_data An array of submission data that contains the
|
296 |
-
* wpzerospam_key field
|
297 |
-
* @return boolean true if the submission key matches the one in the database,
|
298 |
-
* false if it doesn’t.
|
299 |
-
*/
|
300 |
-
if ( ! function_exists( 'wpzerospam_key_check' ) ) {
|
301 |
-
function wpzerospam_key_check( $submission_data = false ) {
|
302 |
-
if (
|
303 |
-
$submission_data &&
|
304 |
-
! empty( $submission_data['wpzerospam_key'] ) &&
|
305 |
-
$submission_data['wpzerospam_key'] == wpzerospam_get_key()
|
306 |
-
) {
|
307 |
-
return true;
|
308 |
-
}
|
309 |
-
|
310 |
-
if ( ! empty( $_POST['wpzerospam_key'] ) && $_POST['wpzerospam_key'] == wpzerospam_get_key() ) {
|
311 |
-
return true;
|
312 |
-
}
|
313 |
-
|
314 |
-
return false;
|
315 |
-
}
|
316 |
-
}
|
317 |
-
|
318 |
-
/**
|
319 |
-
* Sets the $_SERVER['REQUEST_URI'] for pages that extend WP_List_Table
|
320 |
-
*
|
321 |
-
* Fix for passing filters to WP_List_Table paging. See @link below.
|
322 |
-
*
|
323 |
-
* @since 4.8.2
|
324 |
-
* @link https://wordpress.stackexchange.com/questions/67669/how-to-stop-wpnonce-and-wp-http-referer-from-appearing-in-url/185006#185006
|
325 |
-
* @param array $query_args Array of the current query arguments for a table
|
326 |
-
* query.
|
327 |
-
* @return void
|
328 |
-
*/
|
329 |
-
if ( ! function_exists( 'wpzerospam_set_list_table_request_uri' ) ) {
|
330 |
-
function wpzerospam_set_list_table_request_uri( $query_args ) {
|
331 |
-
$paging_options = $query_args;
|
332 |
-
unset( $paging_options['offset'] );
|
333 |
-
unset( $paging_options['where'] );
|
334 |
-
|
335 |
-
if ( ! empty( $query_args['where'] ) ) {
|
336 |
-
foreach( $query_args['where'] as $key => $value ) {
|
337 |
-
switch( $key ) {
|
338 |
-
case 'blacklist_service':
|
339 |
-
$paging_options['service'] = $value;
|
340 |
-
break;
|
341 |
-
case 'user_ip':
|
342 |
-
$paging_options['s'] = $value;
|
343 |
-
break;
|
344 |
-
case 'blocked_type':
|
345 |
-
case 'log_type':
|
346 |
-
$paging_options['type'] = $value;
|
347 |
-
break;
|
348 |
-
}
|
349 |
-
}
|
350 |
-
}
|
351 |
-
|
352 |
-
$_SERVER['REQUEST_URI'] = add_query_arg( $paging_options, $_SERVER['REQUEST_URI'] );
|
353 |
-
}
|
354 |
-
}
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
/**
|
364 |
-
* Query the database
|
365 |
-
*/
|
366 |
-
if ( ! function_exists( 'wpzerospam_query' ) ) {
|
367 |
-
function wpzerospam_query( $table, $args = [], $return_total = false ) {
|
368 |
-
global $wpdb;
|
369 |
-
|
370 |
-
$sql = 'SELECT';
|
371 |
-
|
372 |
-
if ( ! $return_total ) {
|
373 |
-
if ( ! empty( $args['select'] ) ) {
|
374 |
-
$sql .= ' ' . implode( ',', $args['select'] );
|
375 |
-
} else {
|
376 |
-
$sql .= ' *';
|
377 |
-
}
|
378 |
-
} else {
|
379 |
-
$sql .= ' COUNT(*)';
|
380 |
-
}
|
381 |
-
|
382 |
-
$sql .= ' FROM ' . wpzerospam_tables( $table );
|
383 |
-
|
384 |
-
if ( ! empty( $args['where'] ) ) {
|
385 |
-
$sql .= ' WHERE';
|
386 |
-
$cnt = 0;
|
387 |
-
foreach( $args['where'] as $k => $v ) {
|
388 |
-
if ( $cnt ) {
|
389 |
-
$sql .= ' AND ';
|
390 |
-
} else {
|
391 |
-
$sql .= ' ';
|
392 |
-
}
|
393 |
-
|
394 |
-
if ( is_int( $v ) ) {
|
395 |
-
$sql .= $k . ' = ' . $v;
|
396 |
-
} else {
|
397 |
-
$sql .= $k . ' = "' . $v . '"';
|
398 |
-
}
|
399 |
-
|
400 |
-
$cnt++;
|
401 |
-
}
|
402 |
-
}
|
403 |
-
|
404 |
-
if ( ! empty( $args['orderby'] ) ) {
|
405 |
-
$sql .= ' ORDER BY ' . $args['orderby'];
|
406 |
-
}
|
407 |
-
|
408 |
-
if ( ! empty( $args['order'] ) ) {
|
409 |
-
$sql .= ' ' . $args['order'];
|
410 |
-
}
|
411 |
-
|
412 |
-
if ( ! $return_total ) {
|
413 |
-
if ( ! empty( $args['limit'] ) ) {
|
414 |
-
$sql .= ' LIMIT ' . $args['limit'];
|
415 |
-
}
|
416 |
-
|
417 |
-
if ( ! empty( $args['offset'] ) ) {
|
418 |
-
$sql .= ', ' . $args['offset'];
|
419 |
-
}
|
420 |
-
}
|
421 |
-
|
422 |
-
if ( ! $return_total ) {
|
423 |
-
return $wpdb->get_results( $sql );
|
424 |
-
} else {
|
425 |
-
return $wpdb->get_var( $sql );
|
426 |
-
}
|
427 |
-
}
|
428 |
-
}
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
/**
|
443 |
-
* Add a IP address to the blocked table
|
444 |
-
*/
|
445 |
-
if ( ! function_exists( 'wpzerospam_update_blocked_ip' ) ) {
|
446 |
-
function wpzerospam_update_blocked_ip( $ip, $args = [] ) {
|
447 |
-
global $wpdb;
|
448 |
-
|
449 |
-
$options = wpzerospam_options();
|
450 |
-
|
451 |
-
$record = wp_parse_args( $args, [
|
452 |
-
'blocked_type' => 'permanent',
|
453 |
-
'date_added' => current_time( 'mysql' ),
|
454 |
-
'start_block' => false,
|
455 |
-
'end_block' => false,
|
456 |
-
'reason' => false,
|
457 |
-
'attempts' => 1
|
458 |
-
]);
|
459 |
-
|
460 |
-
$record['user_ip'] = $ip;
|
461 |
-
|
462 |
-
// First, check if the IP is already in the DB
|
463 |
-
$check = wpzerospam_get_blocked_ips( $record['user_ip'] );
|
464 |
-
if ( $check ) {
|
465 |
-
$attempts = $check->attempts;
|
466 |
-
$attempts++;
|
467 |
-
|
468 |
-
// IP exists, update accordingly
|
469 |
-
$update = [ 'attempts' => $attempts ];
|
470 |
-
|
471 |
-
if ( $record['blocked_type'] && $record['blocked_type'] != $check->blocked_type ) {
|
472 |
-
$update['blocked_type'] = $record['blocked_type'];
|
473 |
-
}
|
474 |
-
|
475 |
-
if ( $record['start_block'] && $record['start_block'] != $check->start_block ) {
|
476 |
-
$update['start_block'] = $record['start_block'];
|
477 |
-
}
|
478 |
-
|
479 |
-
if ( $record['end_block'] && $record['end_block'] != $check->end_block ) {
|
480 |
-
$update['end_block'] = $record['end_block'];
|
481 |
-
}
|
482 |
-
|
483 |
-
if ( $record['reason'] && $record['reason'] != $check->reason ) {
|
484 |
-
$update['reason'] = $record['reason'];
|
485 |
-
}
|
486 |
-
|
487 |
-
if ( $update ) {
|
488 |
-
$wpdb->update( wpzerospam_tables( 'blocked' ), $update, [
|
489 |
-
'blocked_id' => $check->blocked_id
|
490 |
-
]);
|
491 |
-
}
|
492 |
-
} else {
|
493 |
-
// IP doesn't exist, add it
|
494 |
-
$wpdb->insert( wpzerospam_tables( 'blocked' ), $record );
|
495 |
-
}
|
496 |
-
}
|
497 |
-
}
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
/**
|
502 |
-
* Validates a post submission
|
503 |
-
*/
|
504 |
-
if ( ! function_exists( 'wpzerospam_validate_submission' ) ) {
|
505 |
-
function wpzerospam_validate_submission() {
|
506 |
-
if ( ! empty( $_POST['wpzerospam'] ) && wpzerospam_get_key() == $_POST['wpzerospam'] ) {
|
507 |
-
return true;
|
508 |
-
}
|
509 |
-
|
510 |
-
return false;
|
511 |
-
}
|
512 |
-
}
|
513 |
-
|
514 |
-
/**
|
515 |
-
* Returns an array of blocked IPs or an individual IP's details
|
516 |
-
*/
|
517 |
-
if ( ! function_exists( 'wpzerospam_get_blocked_ips' ) ) {
|
518 |
-
function wpzerospam_get_blocked_ips( $ip = false ) {
|
519 |
-
global $wpdb;
|
520 |
-
|
521 |
-
if ( ! $ip ) {
|
522 |
-
return $wpdb->get_results( 'SELECT * FROM ' . wpzerospam_tables( 'blocked' ) );
|
523 |
-
}
|
524 |
-
|
525 |
-
return $wpdb->get_row($wpdb->prepare(
|
526 |
-
'SELECT * FROM ' . wpzerospam_tables( 'blocked' ) . ' WHERE user_ip = %s',
|
527 |
-
$ip
|
528 |
-
));
|
529 |
-
}
|
530 |
-
}
|
531 |
-
|
532 |
-
/**
|
533 |
-
* Checks if a specific plugin integration is turned on & plugin active.
|
534 |
-
*/
|
535 |
-
if ( ! function_exists( 'wpzerospam_plugin_integration_enabled' ) ) {
|
536 |
-
function wpzerospam_plugin_integration_enabled( $plugin ) {
|
537 |
-
if( ! function_exists( 'is_plugin_active' ) ) {
|
538 |
-
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
539 |
-
}
|
540 |
-
|
541 |
-
$options = wpzerospam_options();
|
542 |
-
|
543 |
-
$integrations = [
|
544 |
-
'fluentform' => 'fluentform/fluentform.php',
|
545 |
-
'wpforms' => [ 'wpforms/wpforms.php', 'wpforms-lite/wpforms.php' ],
|
546 |
-
'formidable' => 'formidable/formidable.php',
|
547 |
-
];
|
548 |
-
|
549 |
-
// Handle BuddyPress check a little differently for presence of a function
|
550 |
-
if ( 'bp_registrations' == $plugin ) {
|
551 |
-
if (
|
552 |
-
! empty( $options['verify_bp_registrations'] ) &&
|
553 |
-
'enabled' == $options['verify_bp_registrations']
|
554 |
-
) {
|
555 |
-
return true;
|
556 |
-
} else {
|
557 |
-
return false;
|
558 |
-
}
|
559 |
-
}
|
560 |
-
|
561 |
-
// Handling all other plugin checks
|
562 |
-
if (
|
563 |
-
! empty( $options['verify_' . $plugin] ) &&
|
564 |
-
'enabled' == $options['verify_' . $plugin ] &&
|
565 |
-
! empty( $integrations[ $plugin ] )
|
566 |
-
) {
|
567 |
-
if ( is_array( $integrations[ $plugin ] ) ) {
|
568 |
-
// Check at least one of the defined plugins are active
|
569 |
-
foreach( $integrations[ $plugin ] as $key => $value ) {
|
570 |
-
if ( is_plugin_active( $value ) ) {
|
571 |
-
return true;
|
572 |
-
}
|
573 |
-
}
|
574 |
-
} else {
|
575 |
-
// Check if one plugin is active
|
576 |
-
if ( is_plugin_active( $integrations[ $plugin ] ) ) {
|
577 |
-
return true;
|
578 |
-
}
|
579 |
-
}
|
580 |
-
}
|
581 |
-
|
582 |
-
return false;
|
583 |
-
}
|
584 |
-
}
|
585 |
-
|
586 |
-
/**
|
587 |
-
* Determines if the current page is the login page
|
588 |
-
*/
|
589 |
-
if ( ! function_exists( 'wpzerospam_is_login' ) ) {
|
590 |
-
function wpzerospam_is_login() {
|
591 |
-
$login_url = wp_login_url();
|
592 |
-
$current_url = wpzerospam_current_url();
|
593 |
-
|
594 |
-
if ( $login_url == $current_url['full'] ) {
|
595 |
-
return true;
|
596 |
-
}
|
597 |
-
|
598 |
-
return false;
|
599 |
-
}
|
600 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/install.php
DELETED
@@ -1,86 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Install plugin tables.
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
*/
|
7 |
-
|
8 |
-
// Security Note: Blocks direct access to the plugin PHP files.
|
9 |
-
defined( 'ABSPATH' ) || die();
|
10 |
-
|
11 |
-
/**
|
12 |
-
* Installs the plugin tables.
|
13 |
-
*/
|
14 |
-
function wpzerospam_install() {
|
15 |
-
global $wpdb;
|
16 |
-
|
17 |
-
$wordpress_zero_spam = new WPZeroSpam();
|
18 |
-
$charset_collate = $wpdb->get_charset_collate();
|
19 |
-
$installed_db_version = get_option( 'wpzerospam_db_version' );
|
20 |
-
|
21 |
-
if ( WORDPRESS_ZERO_SPAM_DB_VERSION !== $installed_db_version ) {
|
22 |
-
$log_table = wpzerospam_tables( 'log' );
|
23 |
-
$blocked_table = wpzerospam_tables( 'blocked' );
|
24 |
-
$blacklist_table = wpzerospam_tables( 'blacklist' );
|
25 |
-
|
26 |
-
$sql = 'CREATE TABLE ' . $wordpress_zero_spam->tables['log'] . " (
|
27 |
-
log_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
28 |
-
log_type VARCHAR(255) NOT NULL,
|
29 |
-
user_ip VARCHAR(39) NOT NULL,
|
30 |
-
date_recorded DATETIME NOT NULL,
|
31 |
-
page_url VARCHAR(255) NULL DEFAULT NULL,
|
32 |
-
submission_data LONGTEXT NULL DEFAULT NULL,
|
33 |
-
country VARCHAR(2) NULL DEFAULT NULL,
|
34 |
-
country_name VARCHAR(255) NULL DEFAULT NULL,
|
35 |
-
region VARCHAR(255) NULL DEFAULT NULL,
|
36 |
-
region_name VARCHAR(255) NULL DEFAULT NULL,
|
37 |
-
city VARCHAR(255) NULL DEFAULT NULL,
|
38 |
-
latitude VARCHAR(255) NULL DEFAULT NULL,
|
39 |
-
longitude VARCHAR(255) NULL DEFAULT NULL,
|
40 |
-
PRIMARY KEY (`log_id`)) $charset_collate;";
|
41 |
-
|
42 |
-
$sql .= 'CREATE TABLE ' . $wordpress_zero_spam->tables['blocked'] . " (
|
43 |
-
blocked_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
44 |
-
blocked_type ENUM('permanent','temporary') NOT NULL DEFAULT 'temporary',
|
45 |
-
user_ip VARCHAR(39) NOT NULL,
|
46 |
-
date_added DATETIME NOT NULL,
|
47 |
-
start_block DATETIME NULL DEFAULT NULL,
|
48 |
-
end_block DATETIME NULL DEFAULT NULL,
|
49 |
-
reason VARCHAR(255) NULL DEFAULT NULL,
|
50 |
-
attempts BIGINT UNSIGNED NOT NULL,
|
51 |
-
PRIMARY KEY (`blocked_id`)) $charset_collate;";
|
52 |
-
|
53 |
-
$sql .= 'CREATE TABLE ' . $wordpress_zero_spam->tables['blacklist'] . " (
|
54 |
-
blacklist_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
55 |
-
user_ip VARCHAR(39) NOT NULL,
|
56 |
-
last_updated DATETIME NOT NULL,
|
57 |
-
blacklist_service VARCHAR(255) NULL DEFAULT NULL,
|
58 |
-
attempts BIGINT UNSIGNED NOT NULL,
|
59 |
-
blacklist_data LONGTEXT NULL DEFAULT NULL,
|
60 |
-
PRIMARY KEY (`blacklist_id`)) $charset_collate;";
|
61 |
-
|
62 |
-
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
63 |
-
dbDelta( $sql );
|
64 |
-
|
65 |
-
if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $blocked_table ) ) === $blocked_table ) {
|
66 |
-
$wpdb->query( "DELETE t1 FROM $blocked_table AS t1 JOIN $blocked_table AS t2 ON t2.blocked_id = t1.blocked_id WHERE t1.blocked_id < t2.blocked_id AND t1.user_ip = t2.user_ip" );
|
67 |
-
}
|
68 |
-
|
69 |
-
if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $blacklist_table ) ) === $blacklist_table ) {
|
70 |
-
$wpdb->query( "DELETE t1 FROM $blacklist_table AS t1 JOIN $blacklist_table AS t2 ON t2.blacklist_id = t1.blacklist_id WHERE t1.blacklist_id < t2.blacklist_id AND t1.user_ip = t2.user_ip" );
|
71 |
-
}
|
72 |
-
|
73 |
-
update_option( 'wpzerospam_db_version', WORDPRESS_ZERO_SPAM_DB_VERSION );
|
74 |
-
}
|
75 |
-
}
|
76 |
-
register_activation_hook( WORDPRESS_ZERO_SPAM, 'wpzerospam_install' );
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Check to ensure the database tables have been installed
|
80 |
-
*/
|
81 |
-
function wpzerospam_db_check() {
|
82 |
-
if ( WORDPRESS_ZERO_SPAM_DB_VERSION !== get_site_option( 'wpzerospam_db_version' ) ) {
|
83 |
-
wpzerospam_install();
|
84 |
-
}
|
85 |
-
}
|
86 |
-
add_action( 'plugins_loaded', 'wpzerospam_db_check' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/locations.php
DELETED
@@ -1,2152 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Location helper
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.0.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Returns the human-readable country or region name.
|
11 |
-
*
|
12 |
-
* * If no region is provided, it returns the country name.
|
13 |
-
* * If the country’s name isn’t available, it returns the country abbreviation.
|
14 |
-
* * If a region is provided, it returns the region name.
|
15 |
-
* * If the region name isn’t available, it returns the region abbreviation.
|
16 |
-
*
|
17 |
-
* @link https://en.wikipedia.org/wiki/ISO_3166-2:COUNTRY_CODE
|
18 |
-
* @param string $country_code The two letter country code.
|
19 |
-
* @param string $region_code The two letter region code.
|
20 |
-
*/
|
21 |
-
if ( ! function_exists( 'wpzerospam_get_location' ) ) {
|
22 |
-
function wpzerospam_get_location( $country_code, $region_code = false ) {
|
23 |
-
$locations = [
|
24 |
-
'US' => [
|
25 |
-
'name' => 'United States',
|
26 |
-
'regions' => [
|
27 |
-
'AK' => [
|
28 |
-
'name' => 'Alaska',
|
29 |
-
],
|
30 |
-
'AZ' => [
|
31 |
-
'name' => 'Arizona',
|
32 |
-
],
|
33 |
-
'AR' => [
|
34 |
-
'name' => 'Arkansas',
|
35 |
-
],
|
36 |
-
'CA' => [
|
37 |
-
'name' => 'California',
|
38 |
-
],
|
39 |
-
'CO' => [
|
40 |
-
'name' => 'Colorado',
|
41 |
-
],
|
42 |
-
'CT' => [
|
43 |
-
'name' => 'Connecticut',
|
44 |
-
],
|
45 |
-
'DE' => [
|
46 |
-
'name' => 'Delaware',
|
47 |
-
],
|
48 |
-
'DC' => [
|
49 |
-
'name' => 'District Of Columbia',
|
50 |
-
],
|
51 |
-
'FL' => [
|
52 |
-
'name' => 'Florida',
|
53 |
-
],
|
54 |
-
'GA' => [
|
55 |
-
'name' => 'Georgia',
|
56 |
-
],
|
57 |
-
'HI' => [
|
58 |
-
'name' => 'Hawaii',
|
59 |
-
],
|
60 |
-
'ID' => [
|
61 |
-
'name' => 'Idaho',
|
62 |
-
],
|
63 |
-
'IL' => [
|
64 |
-
'name' => 'Illinois',
|
65 |
-
],
|
66 |
-
'IN' => [
|
67 |
-
'name' => 'Indiana',
|
68 |
-
],
|
69 |
-
'IA' => [
|
70 |
-
'name' => 'Iowa',
|
71 |
-
],
|
72 |
-
'KS' => [
|
73 |
-
'name' => 'Kansas',
|
74 |
-
],
|
75 |
-
'KY' => [
|
76 |
-
'name' => 'Kentucky',
|
77 |
-
],
|
78 |
-
'LA' => [
|
79 |
-
'name' => 'Louisiana',
|
80 |
-
],
|
81 |
-
'ME' => [
|
82 |
-
'name' => 'Maine',
|
83 |
-
],
|
84 |
-
'MD' => [
|
85 |
-
'name' => 'Maryland',
|
86 |
-
],
|
87 |
-
'MA' => [
|
88 |
-
'name' => 'Massachusetts',
|
89 |
-
],
|
90 |
-
'MI' => [
|
91 |
-
'name' => 'Michigan',
|
92 |
-
],
|
93 |
-
'MN' => [
|
94 |
-
'name' => 'Minnesota',
|
95 |
-
],
|
96 |
-
'MS' => [
|
97 |
-
'name' => 'Mississippi',
|
98 |
-
],
|
99 |
-
'MO' => [
|
100 |
-
'name' => 'Missouri',
|
101 |
-
],
|
102 |
-
'MT' => [
|
103 |
-
'name' => 'Montana',
|
104 |
-
],
|
105 |
-
'NE' => [
|
106 |
-
'name' => 'Nebraska',
|
107 |
-
],
|
108 |
-
'NV' => [
|
109 |
-
'name' => 'Nevada',
|
110 |
-
],
|
111 |
-
'NH' => [
|
112 |
-
'name' => 'New Hampshire',
|
113 |
-
],
|
114 |
-
'NJ' => [
|
115 |
-
'name' => 'New Jersey',
|
116 |
-
],
|
117 |
-
'NM' => [
|
118 |
-
'name' => 'New Mexico',
|
119 |
-
],
|
120 |
-
'NY' => [
|
121 |
-
'name' => 'New York',
|
122 |
-
],
|
123 |
-
'NC' => [
|
124 |
-
'name' => 'North Carolina',
|
125 |
-
],
|
126 |
-
'ND' => [
|
127 |
-
'name' => 'North Dakota',
|
128 |
-
],
|
129 |
-
'OH' => [
|
130 |
-
'name' => 'Ohio',
|
131 |
-
],
|
132 |
-
'OK' => [
|
133 |
-
'name' => 'Oklahoma',
|
134 |
-
],
|
135 |
-
'OR' => [
|
136 |
-
'name' => 'Oregon',
|
137 |
-
],
|
138 |
-
'PA' => [
|
139 |
-
'name' => 'Pennsylvania',
|
140 |
-
],
|
141 |
-
'RI' => [
|
142 |
-
'name' => 'Rhode Island',
|
143 |
-
],
|
144 |
-
'SC' => [
|
145 |
-
'name' => 'South Carolina',
|
146 |
-
],
|
147 |
-
'SD' => [
|
148 |
-
'name' => 'South Dakota',
|
149 |
-
],
|
150 |
-
'TN' => [
|
151 |
-
'name' => 'Tennessee',
|
152 |
-
],
|
153 |
-
'TX' => [
|
154 |
-
'name' => 'Texas',
|
155 |
-
],
|
156 |
-
'UT' => [
|
157 |
-
'name' => 'Utah',
|
158 |
-
],
|
159 |
-
'VT' => [
|
160 |
-
'name' => 'Vermont',
|
161 |
-
],
|
162 |
-
'VA' => [
|
163 |
-
'name' => 'Virginia',
|
164 |
-
],
|
165 |
-
'WA' => [
|
166 |
-
'name' => 'Washington',
|
167 |
-
],
|
168 |
-
'WV' => [
|
169 |
-
'name' => 'West Virginia',
|
170 |
-
],
|
171 |
-
'WI' => [
|
172 |
-
'name' => 'Wisconsin',
|
173 |
-
],
|
174 |
-
'WY' => [
|
175 |
-
'name' => 'Wyoming'
|
176 |
-
]
|
177 |
-
]
|
178 |
-
],
|
179 |
-
'AF' => [
|
180 |
-
'name' => 'Afghanistan',
|
181 |
-
'regions' => []
|
182 |
-
],
|
183 |
-
'AX' => [
|
184 |
-
'name' => 'Aland Islands',
|
185 |
-
'regions' => []
|
186 |
-
],
|
187 |
-
'AL' => [
|
188 |
-
'name' => 'Albania',
|
189 |
-
'regions' => []
|
190 |
-
],
|
191 |
-
'DZ' => [
|
192 |
-
'name' => 'Algeria',
|
193 |
-
'regions' => []
|
194 |
-
],
|
195 |
-
'AS' => [
|
196 |
-
'name' => 'American Samoa',
|
197 |
-
'regions' => []
|
198 |
-
],
|
199 |
-
'AD' => [
|
200 |
-
'name' => 'Andorra',
|
201 |
-
'regions' => []
|
202 |
-
],
|
203 |
-
'AO' => [
|
204 |
-
'name' => 'Angola',
|
205 |
-
'regions' => []
|
206 |
-
],
|
207 |
-
'AI' => [
|
208 |
-
'name' => 'Anguilla',
|
209 |
-
'regions' => []
|
210 |
-
],
|
211 |
-
'AQ' => [
|
212 |
-
'name' => 'Antarctica',
|
213 |
-
'regions' => []
|
214 |
-
],
|
215 |
-
'AG' => [
|
216 |
-
'name' => 'Antigua And Barbuda',
|
217 |
-
'regions' => []
|
218 |
-
],
|
219 |
-
'AR' => [
|
220 |
-
'name' => 'Argentina',
|
221 |
-
'regions' => []
|
222 |
-
],
|
223 |
-
'AM' => [
|
224 |
-
'name' => 'Armenia',
|
225 |
-
'regions' => []
|
226 |
-
],
|
227 |
-
'AW' => [
|
228 |
-
'name' => 'Aruba',
|
229 |
-
'regions' => []
|
230 |
-
],
|
231 |
-
'AU' => [
|
232 |
-
'name' => 'Australia',
|
233 |
-
'regions' => []
|
234 |
-
],
|
235 |
-
'AT' => [
|
236 |
-
'name' => 'Austria',
|
237 |
-
'regions' => []
|
238 |
-
],
|
239 |
-
'AZ' => [
|
240 |
-
'name' => 'Azerbaijan',
|
241 |
-
'regions' => []
|
242 |
-
],
|
243 |
-
'BS' => [
|
244 |
-
'name' => 'Bahamas',
|
245 |
-
'regions' => []
|
246 |
-
],
|
247 |
-
'BH' => [
|
248 |
-
'name' => 'Bahrain',
|
249 |
-
'regions' => []
|
250 |
-
],
|
251 |
-
'BD' => [
|
252 |
-
'name' => 'Bangladesh',
|
253 |
-
'regions' => []
|
254 |
-
],
|
255 |
-
'BB' => [
|
256 |
-
'name' => 'Barbados',
|
257 |
-
'regions' => []
|
258 |
-
],
|
259 |
-
'BY' => [
|
260 |
-
'name' => 'Belarus',
|
261 |
-
'regions' => []
|
262 |
-
],
|
263 |
-
'BE' => [
|
264 |
-
'name' => 'Belgium',
|
265 |
-
'regions' => []
|
266 |
-
],
|
267 |
-
'BZ' => [
|
268 |
-
'name' => 'Belize',
|
269 |
-
'regions' => []
|
270 |
-
],
|
271 |
-
'BJ' => [
|
272 |
-
'name' => 'Benin',
|
273 |
-
'regions' => []
|
274 |
-
],
|
275 |
-
'BM' => [
|
276 |
-
'name' => 'Bermuda',
|
277 |
-
'regions' => []
|
278 |
-
],
|
279 |
-
'BT' => [
|
280 |
-
'name' => 'Bhutan',
|
281 |
-
'regions' => []
|
282 |
-
],
|
283 |
-
'BO' => [
|
284 |
-
'name' => 'Bolivia',
|
285 |
-
'regions' => []
|
286 |
-
],
|
287 |
-
'BA' => [
|
288 |
-
'name' => 'Bosnia And Herzegovina',
|
289 |
-
'regions' => []
|
290 |
-
],
|
291 |
-
'BW' => [
|
292 |
-
'name' => 'Botswana',
|
293 |
-
'regions' => []
|
294 |
-
],
|
295 |
-
'BV' => [
|
296 |
-
'name' => 'Bouvet Island',
|
297 |
-
'regions' => []
|
298 |
-
],
|
299 |
-
'BR' => [
|
300 |
-
'name' => 'Brazil',
|
301 |
-
'regions' => []
|
302 |
-
],
|
303 |
-
'IO' => [
|
304 |
-
'name' => 'British Indian Ocean Territory',
|
305 |
-
'regions' => []
|
306 |
-
],
|
307 |
-
'BN' => [
|
308 |
-
'name' => 'Brunei Darussalam',
|
309 |
-
'regions' => []
|
310 |
-
],
|
311 |
-
'BG' => [
|
312 |
-
'name' => 'Bulgaria',
|
313 |
-
'regions' => []
|
314 |
-
],
|
315 |
-
'BF' => [
|
316 |
-
'name' => 'Burkina Faso',
|
317 |
-
'regions' => []
|
318 |
-
],
|
319 |
-
'BI' => [
|
320 |
-
'name' => 'Burundi',
|
321 |
-
'regions' => []
|
322 |
-
],
|
323 |
-
'KH' => [
|
324 |
-
'name' => 'Cambodia',
|
325 |
-
'regions' => []
|
326 |
-
],
|
327 |
-
'CM' => [
|
328 |
-
'name' => 'Cameroon',
|
329 |
-
'regions' => []
|
330 |
-
],
|
331 |
-
'CA' => [
|
332 |
-
'name' => 'Canada',
|
333 |
-
'regions' => [
|
334 |
-
'AB' => [
|
335 |
-
'name' => 'Alberta'
|
336 |
-
],
|
337 |
-
'BC' => [
|
338 |
-
'name' => 'British Columbia'
|
339 |
-
],
|
340 |
-
'MB' => [
|
341 |
-
'name' => 'Manitoba'
|
342 |
-
],
|
343 |
-
'NB' => [
|
344 |
-
'name' => 'New Brunswick'
|
345 |
-
],
|
346 |
-
'NL' => [
|
347 |
-
'name' => 'Newfoundland and Labrador'
|
348 |
-
],
|
349 |
-
'NS' => [
|
350 |
-
'name' => 'Nova Scotia'
|
351 |
-
],
|
352 |
-
'ON' => [
|
353 |
-
'name' => 'Ontario'
|
354 |
-
],
|
355 |
-
'PE' => [
|
356 |
-
'name' => 'Prince Edward Island'
|
357 |
-
],
|
358 |
-
'QC' => [
|
359 |
-
'name' => 'Quebec'
|
360 |
-
],
|
361 |
-
'SK' => [
|
362 |
-
'name' => 'Saskatchewan'
|
363 |
-
],
|
364 |
-
'NT' => [
|
365 |
-
'name' => 'Northwest Territories'
|
366 |
-
],
|
367 |
-
'NU' => [
|
368 |
-
'name' => 'Nunavut'
|
369 |
-
],
|
370 |
-
'YT' => [
|
371 |
-
'name' => 'Yukon'
|
372 |
-
]
|
373 |
-
]
|
374 |
-
],
|
375 |
-
'CV' => [
|
376 |
-
'name' => 'Cape Verde',
|
377 |
-
'regions' => []
|
378 |
-
],
|
379 |
-
'KY' => [
|
380 |
-
'name' => 'Cayman Islands',
|
381 |
-
'regions' => []
|
382 |
-
],
|
383 |
-
'CF' => [
|
384 |
-
'name' => 'Central African Republic',
|
385 |
-
'regions' => []
|
386 |
-
],
|
387 |
-
'TD' => [
|
388 |
-
'name' => 'Chad',
|
389 |
-
'regions' => []
|
390 |
-
],
|
391 |
-
'CL' => [
|
392 |
-
'name' => 'Chile',
|
393 |
-
'regions' => []
|
394 |
-
],
|
395 |
-
'CN' => [
|
396 |
-
'name' => 'China',
|
397 |
-
'regions' => []
|
398 |
-
],
|
399 |
-
'CX' => [
|
400 |
-
'name' => 'Christmas Island',
|
401 |
-
'regions' => []
|
402 |
-
],
|
403 |
-
'CC' => [
|
404 |
-
'name' => 'Cocos (Keeling) Islands',
|
405 |
-
'regions' => []
|
406 |
-
],
|
407 |
-
'CO' => [
|
408 |
-
'name' => 'Colombia',
|
409 |
-
'regions' => []
|
410 |
-
],
|
411 |
-
'KM' => [
|
412 |
-
'name' => 'Comoros',
|
413 |
-
'regions' => []
|
414 |
-
],
|
415 |
-
'CG' => [
|
416 |
-
'name' => 'Congo',
|
417 |
-
'regions' => []
|
418 |
-
],
|
419 |
-
'CD' => [
|
420 |
-
'name' => 'Congo, Democratic Republic',
|
421 |
-
'regions' => []
|
422 |
-
],
|
423 |
-
'CK' => [
|
424 |
-
'name' => 'Cook Islands',
|
425 |
-
'regions' => []
|
426 |
-
],
|
427 |
-
'CR' => [
|
428 |
-
'name' => 'Costa Rica',
|
429 |
-
'regions' => []
|
430 |
-
],
|
431 |
-
'CI' => [
|
432 |
-
'name' => 'Cote D\'Ivoire',
|
433 |
-
'regions' => []
|
434 |
-
],
|
435 |
-
'HR' => [
|
436 |
-
'name' => 'Croatia',
|
437 |
-
'regions' => []
|
438 |
-
],
|
439 |
-
'CU' => [
|
440 |
-
'name' => 'Cuba',
|
441 |
-
'regions' => []
|
442 |
-
],
|
443 |
-
'CY' => [
|
444 |
-
'name' => 'Cyprus',
|
445 |
-
'regions' => []
|
446 |
-
],
|
447 |
-
'CZ' => [
|
448 |
-
'name' => 'Czech Republic',
|
449 |
-
'regions' => []
|
450 |
-
],
|
451 |
-
'DK' => [
|
452 |
-
'name' => 'Denmark',
|
453 |
-
'regions' => []
|
454 |
-
],
|
455 |
-
'DJ' => [
|
456 |
-
'name' => 'Djibouti',
|
457 |
-
'regions' => []
|
458 |
-
],
|
459 |
-
'DM' => [
|
460 |
-
'name' => 'Dominica',
|
461 |
-
'regions' => []
|
462 |
-
],
|
463 |
-
'DO' => [
|
464 |
-
'name' => 'Dominican Republic',
|
465 |
-
'regions' => []
|
466 |
-
],
|
467 |
-
'EC' => [
|
468 |
-
'name' => 'Ecuador',
|
469 |
-
'regions' => []
|
470 |
-
],
|
471 |
-
'EG' => [
|
472 |
-
'name' => 'Egypt',
|
473 |
-
'regions' => []
|
474 |
-
],
|
475 |
-
'SV' => [
|
476 |
-
'name' => 'El Salvador',
|
477 |
-
'regions' => []
|
478 |
-
],
|
479 |
-
'GQ' => [
|
480 |
-
'name' => 'Equatorial Guinea',
|
481 |
-
'regions' => []
|
482 |
-
],
|
483 |
-
'ER' => [
|
484 |
-
'name' => 'Eritrea',
|
485 |
-
'regions' => []
|
486 |
-
],
|
487 |
-
'EE' => [
|
488 |
-
'name' => 'Estonia',
|
489 |
-
'regions' => []
|
490 |
-
],
|
491 |
-
'ET' => [
|
492 |
-
'name' => 'Ethiopia',
|
493 |
-
'regions' => []
|
494 |
-
],
|
495 |
-
'FK' => [
|
496 |
-
'name' => 'Falkland Islands (Malvinas)',
|
497 |
-
'regions' => []
|
498 |
-
],
|
499 |
-
'FO' => [
|
500 |
-
'name' => 'Faroe Islands',
|
501 |
-
'regions' => []
|
502 |
-
],
|
503 |
-
'FJ' => [
|
504 |
-
'name' => 'Fiji',
|
505 |
-
'regions' => []
|
506 |
-
],
|
507 |
-
'FI' => [
|
508 |
-
'name' => 'Finland',
|
509 |
-
'regions' => []
|
510 |
-
],
|
511 |
-
'FR' => [
|
512 |
-
'name' => 'France',
|
513 |
-
'regions' => [
|
514 |
-
'ARA' => [
|
515 |
-
'name' => 'Auvergne-Rhône-Alpes'
|
516 |
-
],
|
517 |
-
'BFC' => [
|
518 |
-
'name' => 'Bourgogne-Franche-Comté'
|
519 |
-
],
|
520 |
-
'BRE' => [
|
521 |
-
'name' => 'Bretagne'
|
522 |
-
],
|
523 |
-
'CVL' => [
|
524 |
-
'name' => 'Centre-Val de Loire'
|
525 |
-
],
|
526 |
-
'COR' => [
|
527 |
-
'name' => 'Corse'
|
528 |
-
],
|
529 |
-
'GES' => [
|
530 |
-
'name' => 'Grand-Est'
|
531 |
-
],
|
532 |
-
'GUA' => [
|
533 |
-
'name' => 'Guadeloupe'
|
534 |
-
],
|
535 |
-
'HDF' => [
|
536 |
-
'name' => 'Hauts-de-France'
|
537 |
-
],
|
538 |
-
'IDF' => [
|
539 |
-
'name' => 'Île-de-France'
|
540 |
-
],
|
541 |
-
'MAY' => [
|
542 |
-
'name' => 'Mayotte'
|
543 |
-
],
|
544 |
-
'NOR' => [
|
545 |
-
'name' => 'Normandie'
|
546 |
-
],
|
547 |
-
'NAQ' => [
|
548 |
-
'name' => 'Nouvelle-Aquitaine'
|
549 |
-
],
|
550 |
-
'OCC' => [
|
551 |
-
'name' => 'Occitanie'
|
552 |
-
],
|
553 |
-
'PDL' => [
|
554 |
-
'name' => 'Pays-de-la-Loire'
|
555 |
-
],
|
556 |
-
'PDL' => [
|
557 |
-
'name' => 'Provence-Alpes-Côte-d’Azur'
|
558 |
-
],
|
559 |
-
'LRE' => [
|
560 |
-
'name' => 'La Réunion'
|
561 |
-
],
|
562 |
-
]
|
563 |
-
],
|
564 |
-
'GF' => [
|
565 |
-
'name' => 'French Guiana',
|
566 |
-
'regions' => []
|
567 |
-
],
|
568 |
-
'PF' => [
|
569 |
-
'name' => 'French Polynesia',
|
570 |
-
'regions' => []
|
571 |
-
],
|
572 |
-
'TF' => [
|
573 |
-
'name' => 'French Southern Territories',
|
574 |
-
'regions' => []
|
575 |
-
],
|
576 |
-
'GA' => [
|
577 |
-
'name' => 'Gabon',
|
578 |
-
'regions' => []
|
579 |
-
],
|
580 |
-
'GM' => [
|
581 |
-
'name' => 'Gambia',
|
582 |
-
'regions' => []
|
583 |
-
],
|
584 |
-
'GE' => [
|
585 |
-
'name' => 'Georgia',
|
586 |
-
'regions' => []
|
587 |
-
],
|
588 |
-
'DE' => [
|
589 |
-
'name' => 'Germany',
|
590 |
-
'regions' => []
|
591 |
-
],
|
592 |
-
'GH' => [
|
593 |
-
'name' => 'Ghana',
|
594 |
-
'regions' => []
|
595 |
-
],
|
596 |
-
'GI' => [
|
597 |
-
'name' => 'Gibraltar',
|
598 |
-
'regions' => []
|
599 |
-
],
|
600 |
-
'GR' => [
|
601 |
-
'name' => 'Greece',
|
602 |
-
'regions' => []
|
603 |
-
],
|
604 |
-
'GL' => [
|
605 |
-
'name' => 'Greenland',
|
606 |
-
'regions' => []
|
607 |
-
],
|
608 |
-
'GD' => [
|
609 |
-
'name' => 'Grenada',
|
610 |
-
'regions' => []
|
611 |
-
],
|
612 |
-
'GP' => [
|
613 |
-
'name' => 'Guadeloupe',
|
614 |
-
'regions' => []
|
615 |
-
],
|
616 |
-
'GU' => [
|
617 |
-
'name' => 'Guam',
|
618 |
-
'regions' => []
|
619 |
-
],
|
620 |
-
'GT' => [
|
621 |
-
'name' => 'Guatemala',
|
622 |
-
'regions' => []
|
623 |
-
],
|
624 |
-
'GG' => [
|
625 |
-
'name' => 'Guernsey',
|
626 |
-
'regions' => []
|
627 |
-
],
|
628 |
-
'GN' => [
|
629 |
-
'name' => 'Guinea',
|
630 |
-
'regions' => []
|
631 |
-
],
|
632 |
-
'GW' => [
|
633 |
-
'name' => 'Guinea-Bissau',
|
634 |
-
'regions' => []
|
635 |
-
],
|
636 |
-
'GY' => [
|
637 |
-
'name' => 'Guyana',
|
638 |
-
'regions' => []
|
639 |
-
],
|
640 |
-
'HT' => [
|
641 |
-
'name' => 'Haiti',
|
642 |
-
'regions' => []
|
643 |
-
],
|
644 |
-
'HM' => [
|
645 |
-
'name' => 'Heard Island & Mcdonald Islands',
|
646 |
-
'regions' => []
|
647 |
-
],
|
648 |
-
'VA' => [
|
649 |
-
'name' => 'Holy See (Vatican City State)',
|
650 |
-
'regions' => []
|
651 |
-
],
|
652 |
-
'HN' => [
|
653 |
-
'name' => 'Honduras',
|
654 |
-
'regions' => []
|
655 |
-
],
|
656 |
-
'HK' => [
|
657 |
-
'name' => 'Hong Kong',
|
658 |
-
'regions' => []
|
659 |
-
],
|
660 |
-
'HU' => [
|
661 |
-
'name' => 'Hungary',
|
662 |
-
'regions' => []
|
663 |
-
],
|
664 |
-
'IS' => [
|
665 |
-
'name' => 'Iceland',
|
666 |
-
'regions' => []
|
667 |
-
],
|
668 |
-
'IN' => [
|
669 |
-
'name' => 'India',
|
670 |
-
'regions' => [
|
671 |
-
'AP' => [
|
672 |
-
'name' => 'Andhra Pradesh'
|
673 |
-
],
|
674 |
-
'AR' => [
|
675 |
-
'name' => 'Arunachal Pradesh'
|
676 |
-
],
|
677 |
-
'AS' => [
|
678 |
-
'name' => 'Assam'
|
679 |
-
],
|
680 |
-
'BR' => [
|
681 |
-
'name' => 'Bihar'
|
682 |
-
],
|
683 |
-
'CT' => [
|
684 |
-
'name' => 'Chhattisgarh'
|
685 |
-
],
|
686 |
-
'GA' => [
|
687 |
-
'name' => 'Goa'
|
688 |
-
],
|
689 |
-
'GJ' => [
|
690 |
-
'name' => 'Gujarat'
|
691 |
-
],
|
692 |
-
'HR' => [
|
693 |
-
'name' => 'Haryana'
|
694 |
-
],
|
695 |
-
'HP' => [
|
696 |
-
'name' => 'Himachal Pradesh'
|
697 |
-
],
|
698 |
-
'JH' => [
|
699 |
-
'name' => 'Jharkhand'
|
700 |
-
],
|
701 |
-
'KA' => [
|
702 |
-
'name' => 'Karnataka'
|
703 |
-
],
|
704 |
-
'KL' => [
|
705 |
-
'name' => 'Kerala'
|
706 |
-
],
|
707 |
-
'MP' => [
|
708 |
-
'name' => 'Madhya Pradesh'
|
709 |
-
],
|
710 |
-
'MH' => [
|
711 |
-
'name' => 'Maharashtra'
|
712 |
-
],
|
713 |
-
'MN' => [
|
714 |
-
'name' => 'Manipur'
|
715 |
-
],
|
716 |
-
'ML' => [
|
717 |
-
'name' => 'Meghalaya'
|
718 |
-
],
|
719 |
-
'MZ' => [
|
720 |
-
'name' => 'Mizoram'
|
721 |
-
],
|
722 |
-
'NL' => [
|
723 |
-
'name' => 'Nagaland'
|
724 |
-
],
|
725 |
-
'OR' => [
|
726 |
-
'name' => 'Odisha'
|
727 |
-
],
|
728 |
-
'PB' => [
|
729 |
-
'name' => 'Punjab'
|
730 |
-
],
|
731 |
-
'RJ' => [
|
732 |
-
'name' => 'Rajasthan'
|
733 |
-
],
|
734 |
-
'SK' => [
|
735 |
-
'name' => 'Sikkim'
|
736 |
-
],
|
737 |
-
'TN' => [
|
738 |
-
'name' => 'Tamil Nadu'
|
739 |
-
],
|
740 |
-
'TG' => [
|
741 |
-
'name' => 'Telangana'
|
742 |
-
],
|
743 |
-
'TR' => [
|
744 |
-
'name' => 'Tripura'
|
745 |
-
],
|
746 |
-
'UT' => [
|
747 |
-
'name' => 'Uttarakhand'
|
748 |
-
],
|
749 |
-
'UP' => [
|
750 |
-
'name' => 'Uttar Pradesh'
|
751 |
-
],
|
752 |
-
'WP' => [
|
753 |
-
'name' => 'West Bengal'
|
754 |
-
],
|
755 |
-
'AN' => [
|
756 |
-
'name' => 'Andaman and Nicobar Islands'
|
757 |
-
],
|
758 |
-
'CH' => [
|
759 |
-
'name' => 'Chandigarh'
|
760 |
-
],
|
761 |
-
'DN' => [
|
762 |
-
'name' => 'Dadra and Nagar Haveli'
|
763 |
-
],
|
764 |
-
'DD' => [
|
765 |
-
'name' => 'Daman and Diu'
|
766 |
-
],
|
767 |
-
'DL' => [
|
768 |
-
'name' => 'Delhi'
|
769 |
-
],
|
770 |
-
'JK' => [
|
771 |
-
'name' => 'Jammu and Kashmir'
|
772 |
-
],
|
773 |
-
'LA' => [
|
774 |
-
'name' => 'Ladakh'
|
775 |
-
],
|
776 |
-
'LD' => [
|
777 |
-
'name' => 'Lakshadweep'
|
778 |
-
],
|
779 |
-
'PY' => [
|
780 |
-
'name' => 'Puducherry'
|
781 |
-
]
|
782 |
-
]
|
783 |
-
],
|
784 |
-
'ID' => [
|
785 |
-
'name' => 'Indonesia',
|
786 |
-
'regions' => []
|
787 |
-
],
|
788 |
-
'IR' => [
|
789 |
-
'name' => 'Iran, Islamic Republic Of',
|
790 |
-
'regions' => []
|
791 |
-
],
|
792 |
-
'IQ' => [
|
793 |
-
'name' => 'Iraq',
|
794 |
-
'regions' => []
|
795 |
-
],
|
796 |
-
'IE' => [
|
797 |
-
'name' => 'Ireland',
|
798 |
-
'regions' => []
|
799 |
-
],
|
800 |
-
'IM' => [
|
801 |
-
'name' => 'Isle Of Man',
|
802 |
-
'regions' => []
|
803 |
-
],
|
804 |
-
'IL' => [
|
805 |
-
'name' => 'Israel',
|
806 |
-
'regions' => []
|
807 |
-
],
|
808 |
-
'IT' => [
|
809 |
-
'name' => 'Italy',
|
810 |
-
'regions' => [
|
811 |
-
'65' => [
|
812 |
-
'name' => 'Abruzzo'
|
813 |
-
],
|
814 |
-
'77' => [
|
815 |
-
'name' => 'Basilicata'
|
816 |
-
],
|
817 |
-
'78' => [
|
818 |
-
'name' => 'Calabria'
|
819 |
-
],
|
820 |
-
'72' => [
|
821 |
-
'name' => 'Campania'
|
822 |
-
],
|
823 |
-
'45' => [
|
824 |
-
'name' => 'Emilia-Romagna'
|
825 |
-
],
|
826 |
-
'62' => [
|
827 |
-
'name' => 'Lazio'
|
828 |
-
],
|
829 |
-
'42' => [
|
830 |
-
'name' => 'Liguria'
|
831 |
-
],
|
832 |
-
'25' => [
|
833 |
-
'name' => 'Lombardy'
|
834 |
-
],
|
835 |
-
'57' => [
|
836 |
-
'name' => 'Marche'
|
837 |
-
],
|
838 |
-
'67' => [
|
839 |
-
'name' => 'Molise'
|
840 |
-
],
|
841 |
-
'21' => [
|
842 |
-
'name' => 'Piedmont'
|
843 |
-
],
|
844 |
-
'75' => [
|
845 |
-
'name' => 'Apulia'
|
846 |
-
],
|
847 |
-
'52' => [
|
848 |
-
'name' => 'Tuscany'
|
849 |
-
],
|
850 |
-
'55' => [
|
851 |
-
'name' => 'Umbria'
|
852 |
-
],
|
853 |
-
'34' => [
|
854 |
-
'name' => 'Veneto'
|
855 |
-
]
|
856 |
-
]
|
857 |
-
],
|
858 |
-
'JM' => [
|
859 |
-
'name' => 'Jamaica',
|
860 |
-
'regions' => []
|
861 |
-
],
|
862 |
-
'JP' => [
|
863 |
-
'name' => 'Japan',
|
864 |
-
'regions' => []
|
865 |
-
],
|
866 |
-
'JE' => [
|
867 |
-
'name' => 'Jersey',
|
868 |
-
'regions' => []
|
869 |
-
],
|
870 |
-
'JO' => [
|
871 |
-
'name' => 'Jordan',
|
872 |
-
'regions' => []
|
873 |
-
],
|
874 |
-
'KZ' => [
|
875 |
-
'name' => 'Kazakhstan',
|
876 |
-
'regions' => []
|
877 |
-
],
|
878 |
-
'KE' => [
|
879 |
-
'name' => 'Kenya',
|
880 |
-
'regions' => []
|
881 |
-
],
|
882 |
-
'KI' => [
|
883 |
-
'name' => 'Kiribati',
|
884 |
-
'regions' => []
|
885 |
-
],
|
886 |
-
'KR' => [
|
887 |
-
'name' => 'Korea',
|
888 |
-
'regions' => []
|
889 |
-
],
|
890 |
-
'KW' => [
|
891 |
-
'name' => 'Kuwait',
|
892 |
-
'regions' => []
|
893 |
-
],
|
894 |
-
'KG' => [
|
895 |
-
'name' => 'Kyrgyzstan',
|
896 |
-
'regions' => []
|
897 |
-
],
|
898 |
-
'LA' => [
|
899 |
-
'name' => 'Lao People\'s Democratic Republic',
|
900 |
-
'regions' => []
|
901 |
-
],
|
902 |
-
'LV' => [
|
903 |
-
'name' => 'Latvia',
|
904 |
-
'regions' => []
|
905 |
-
],
|
906 |
-
'LB' => [
|
907 |
-
'name' => 'Lebanon',
|
908 |
-
'regions' => []
|
909 |
-
],
|
910 |
-
'LS' => [
|
911 |
-
'name' => 'Lesotho',
|
912 |
-
'regions' => []
|
913 |
-
],
|
914 |
-
'LR' => [
|
915 |
-
'name' => 'Liberia',
|
916 |
-
'regions' => []
|
917 |
-
],
|
918 |
-
'LY' => [
|
919 |
-
'name' => 'Libyan Arab Jamahiriya',
|
920 |
-
'regions' => []
|
921 |
-
],
|
922 |
-
'LI' => [
|
923 |
-
'name' => 'Liechtenstein',
|
924 |
-
'regions' => []
|
925 |
-
],
|
926 |
-
'LT' => [
|
927 |
-
'name' => 'Lithuania',
|
928 |
-
'regions' => []
|
929 |
-
],
|
930 |
-
'LU' => [
|
931 |
-
'name' => 'Luxembourg',
|
932 |
-
'regions' => []
|
933 |
-
],
|
934 |
-
'MO' => [
|
935 |
-
'name' => 'Macao',
|
936 |
-
'regions' => []
|
937 |
-
],
|
938 |
-
'MK' => [
|
939 |
-
'name' => 'Macedonia',
|
940 |
-
'regions' => []
|
941 |
-
],
|
942 |
-
'MG' => [
|
943 |
-
'name' => 'Madagascar',
|
944 |
-
'regions' => []
|
945 |
-
],
|
946 |
-
'MW' => [
|
947 |
-
'name' => 'Malawi',
|
948 |
-
'regions' => []
|
949 |
-
],
|
950 |
-
'MY' => [
|
951 |
-
'name' => 'Malaysia',
|
952 |
-
'regions' => [
|
953 |
-
'14' => [
|
954 |
-
'name' => 'Wilayah Persekutuan Kuala Lumpur'
|
955 |
-
],
|
956 |
-
'15' => [
|
957 |
-
'name' => 'Wilayah Persekutuan Labuan'
|
958 |
-
],
|
959 |
-
'16' => [
|
960 |
-
'name' => 'Wilayah Persekutuan Putrajaya'
|
961 |
-
],
|
962 |
-
'01' => [
|
963 |
-
'name' => 'Johor'
|
964 |
-
],
|
965 |
-
'02' => [
|
966 |
-
'name' => 'Kedah'
|
967 |
-
],
|
968 |
-
'03' => [
|
969 |
-
'name' => 'Kelantan'
|
970 |
-
],
|
971 |
-
'04' => [
|
972 |
-
'name' => 'Melaka'
|
973 |
-
],
|
974 |
-
'05' => [
|
975 |
-
'name' => 'Negeri Sembilan'
|
976 |
-
],
|
977 |
-
'06' => [
|
978 |
-
'name' => 'Pahang'
|
979 |
-
],
|
980 |
-
'08' => [
|
981 |
-
'name' => 'Perak'
|
982 |
-
],
|
983 |
-
'09' => [
|
984 |
-
'name' => 'Perlis'
|
985 |
-
],
|
986 |
-
'07' => [
|
987 |
-
'name' => 'Pulau Pinang'
|
988 |
-
],
|
989 |
-
'12' => [
|
990 |
-
'name' => 'Sabah'
|
991 |
-
],
|
992 |
-
'13' => [
|
993 |
-
'name' => 'Sarawak'
|
994 |
-
],
|
995 |
-
'10' => [
|
996 |
-
'name' => 'Selangor'
|
997 |
-
],
|
998 |
-
'11' => [
|
999 |
-
'name' => 'Terengganu'
|
1000 |
-
]
|
1001 |
-
]
|
1002 |
-
],
|
1003 |
-
'MV' => [
|
1004 |
-
'name' => 'Maldives',
|
1005 |
-
'regions' => []
|
1006 |
-
],
|
1007 |
-
'ML' => [
|
1008 |
-
'name' => 'Mali',
|
1009 |
-
'regions' => []
|
1010 |
-
],
|
1011 |
-
'MT' => [
|
1012 |
-
'name' => 'Malta',
|
1013 |
-
'regions' => []
|
1014 |
-
],
|
1015 |
-
'MH' => [
|
1016 |
-
'name' => 'Marshall Islands',
|
1017 |
-
'regions' => []
|
1018 |
-
],
|
1019 |
-
'MQ' => [
|
1020 |
-
'name' => 'Martinique',
|
1021 |
-
'regions' => []
|
1022 |
-
],
|
1023 |
-
'MR' => [
|
1024 |
-
'name' => 'Mauritania',
|
1025 |
-
'regions' => []
|
1026 |
-
],
|
1027 |
-
'MU' => [
|
1028 |
-
'name' => 'Mauritius',
|
1029 |
-
'regions' => []
|
1030 |
-
],
|
1031 |
-
'YT' => [
|
1032 |
-
'name' => 'Mayotte',
|
1033 |
-
'regions' => []
|
1034 |
-
],
|
1035 |
-
'MX' => [
|
1036 |
-
'name' => 'Mexico',
|
1037 |
-
'regions' => []
|
1038 |
-
],
|
1039 |
-
'FM' => [
|
1040 |
-
'name' => 'Micronesia, Federated States Of',
|
1041 |
-
'regions' => []
|
1042 |
-
],
|
1043 |
-
'MD' => [
|
1044 |
-
'name' => 'Moldova',
|
1045 |
-
'regions' => []
|
1046 |
-
],
|
1047 |
-
'MC' => [
|
1048 |
-
'name' => 'Monaco',
|
1049 |
-
'regions' => []
|
1050 |
-
],
|
1051 |
-
'MN' => [
|
1052 |
-
'name' => 'Mongolia',
|
1053 |
-
'regions' => []
|
1054 |
-
],
|
1055 |
-
'ME' => [
|
1056 |
-
'name' => 'Montenegro',
|
1057 |
-
'regions' => []
|
1058 |
-
],
|
1059 |
-
'MS' => [
|
1060 |
-
'name' => 'Montserrat',
|
1061 |
-
'regions' => []
|
1062 |
-
],
|
1063 |
-
'MA' => [
|
1064 |
-
'name' => 'Morocco',
|
1065 |
-
'regions' => []
|
1066 |
-
],
|
1067 |
-
'MZ' => [
|
1068 |
-
'name' => 'Mozambique',
|
1069 |
-
'regions' => []
|
1070 |
-
],
|
1071 |
-
'MM' => [
|
1072 |
-
'name' => 'Myanmar',
|
1073 |
-
'regions' => []
|
1074 |
-
],
|
1075 |
-
'NA' => [
|
1076 |
-
'name' => 'Namibia',
|
1077 |
-
'regions' => []
|
1078 |
-
],
|
1079 |
-
'NR' => [
|
1080 |
-
'name' => 'Nauru',
|
1081 |
-
'regions' => []
|
1082 |
-
],
|
1083 |
-
'NP' => [
|
1084 |
-
'name' => 'Nepal',
|
1085 |
-
'regions' => []
|
1086 |
-
],
|
1087 |
-
'NL' => [
|
1088 |
-
'name' => 'Netherlands',
|
1089 |
-
'regions' => [
|
1090 |
-
'NH' => [
|
1091 |
-
'name' => 'North Holland'
|
1092 |
-
],
|
1093 |
-
'ZH' => [
|
1094 |
-
'name' => 'South Holland'
|
1095 |
-
],
|
1096 |
-
'ZE' => [
|
1097 |
-
'name' => 'Zeeland'
|
1098 |
-
],
|
1099 |
-
'UT' => [
|
1100 |
-
'name' => 'Utrecht'
|
1101 |
-
],
|
1102 |
-
'OV' => [
|
1103 |
-
'name' => 'Overijssel'
|
1104 |
-
],
|
1105 |
-
'NB' => [
|
1106 |
-
'name' => 'North Brabant'
|
1107 |
-
],
|
1108 |
-
'LI' => [
|
1109 |
-
'name' => 'Limburg'
|
1110 |
-
],
|
1111 |
-
'GR' => [
|
1112 |
-
'name' => 'Groningen'
|
1113 |
-
],
|
1114 |
-
'GE' => [
|
1115 |
-
'name' => 'Gelderland'
|
1116 |
-
],
|
1117 |
-
'FR' => [
|
1118 |
-
'name' => 'Friesland'
|
1119 |
-
],
|
1120 |
-
'FL' => [
|
1121 |
-
'name' => 'Flevoland'
|
1122 |
-
],
|
1123 |
-
'DR' => [
|
1124 |
-
'name' => 'Drenthe'
|
1125 |
-
]
|
1126 |
-
]
|
1127 |
-
],
|
1128 |
-
'AN' => [
|
1129 |
-
'name' => 'Netherlands Antilles',
|
1130 |
-
'regions' => []
|
1131 |
-
],
|
1132 |
-
'NC' => [
|
1133 |
-
'name' => 'New Caledonia',
|
1134 |
-
'regions' => []
|
1135 |
-
],
|
1136 |
-
'NZ' => [
|
1137 |
-
'name' => 'New Zealand',
|
1138 |
-
'regions' => []
|
1139 |
-
],
|
1140 |
-
'NI' => [
|
1141 |
-
'name' => 'Nicaragua',
|
1142 |
-
'regions' => []
|
1143 |
-
],
|
1144 |
-
'NE' => [
|
1145 |
-
'name' => 'Niger',
|
1146 |
-
'regions' => []
|
1147 |
-
],
|
1148 |
-
'NG' => [
|
1149 |
-
'name' => 'Nigeria',
|
1150 |
-
'regions' => []
|
1151 |
-
],
|
1152 |
-
'NU' => [
|
1153 |
-
'name' => 'Niue',
|
1154 |
-
'regions' => []
|
1155 |
-
],
|
1156 |
-
'NF' => [
|
1157 |
-
'name' => 'Norfolk Island',
|
1158 |
-
'regions' => []
|
1159 |
-
],
|
1160 |
-
'MP' => [
|
1161 |
-
'name' => 'Northern Mariana Islands',
|
1162 |
-
'regions' => []
|
1163 |
-
],
|
1164 |
-
'NO' => [
|
1165 |
-
'name' => 'Norway',
|
1166 |
-
'regions' => []
|
1167 |
-
],
|
1168 |
-
'OM' => [
|
1169 |
-
'name' => 'Oman',
|
1170 |
-
'regions' => []
|
1171 |
-
],
|
1172 |
-
'PK' => [
|
1173 |
-
'name' => 'Pakistan',
|
1174 |
-
'regions' => []
|
1175 |
-
],
|
1176 |
-
'PW' => [
|
1177 |
-
'name' => 'Palau',
|
1178 |
-
'regions' => []
|
1179 |
-
],
|
1180 |
-
'PS' => [
|
1181 |
-
'name' => 'Palestinian Territory, Occupied',
|
1182 |
-
'regions' => []
|
1183 |
-
],
|
1184 |
-
'PA' => [
|
1185 |
-
'name' => 'Panama',
|
1186 |
-
'regions' => []
|
1187 |
-
],
|
1188 |
-
'PG' => [
|
1189 |
-
'name' => 'Papua New Guinea',
|
1190 |
-
'regions' => []
|
1191 |
-
],
|
1192 |
-
'PY' => [
|
1193 |
-
'name' => 'Paraguay',
|
1194 |
-
'regions' => []
|
1195 |
-
],
|
1196 |
-
'PE' => [
|
1197 |
-
'name' => 'Peru',
|
1198 |
-
'regions' => []
|
1199 |
-
],
|
1200 |
-
'PH' => [
|
1201 |
-
'name' => 'Philippines',
|
1202 |
-
'regions' => []
|
1203 |
-
],
|
1204 |
-
'PN' => [
|
1205 |
-
'name' => 'Pitcairn',
|
1206 |
-
'regions' => []
|
1207 |
-
],
|
1208 |
-
'PL' => [
|
1209 |
-
'name' => 'Poland',
|
1210 |
-
'regions' => [
|
1211 |
-
'02' => [
|
1212 |
-
'name' => 'Lower Silesia'
|
1213 |
-
],
|
1214 |
-
'04' => [
|
1215 |
-
'name' => 'Kuyavia-Pomerania'
|
1216 |
-
],
|
1217 |
-
'06' => [
|
1218 |
-
'name' => 'Lublin'
|
1219 |
-
],
|
1220 |
-
'08' => [
|
1221 |
-
'name' => 'Lubusz'
|
1222 |
-
],
|
1223 |
-
'10' => [
|
1224 |
-
'name' => 'Łódź'
|
1225 |
-
],
|
1226 |
-
'12' => [
|
1227 |
-
'name' => 'Lesser Poland'
|
1228 |
-
],
|
1229 |
-
'14' => [
|
1230 |
-
'name' => 'Mazovia'
|
1231 |
-
],
|
1232 |
-
'MZ' => [
|
1233 |
-
'name' => 'Mazovia'
|
1234 |
-
],
|
1235 |
-
'16' => [
|
1236 |
-
'name' => 'Opole (Upper Silesia)'
|
1237 |
-
],
|
1238 |
-
'18' => [
|
1239 |
-
'name' => 'Subcarpathia'
|
1240 |
-
],
|
1241 |
-
'20' => [
|
1242 |
-
'name' => 'Podlaskie'
|
1243 |
-
],
|
1244 |
-
'22' => [
|
1245 |
-
'name' => 'Pomerania'
|
1246 |
-
],
|
1247 |
-
'24' => [
|
1248 |
-
'name' => 'Silesia'
|
1249 |
-
],
|
1250 |
-
'26' => [
|
1251 |
-
'name' => 'Holy Cross'
|
1252 |
-
],
|
1253 |
-
'28' => [
|
1254 |
-
'name' => 'Warmia-Masuria'
|
1255 |
-
],
|
1256 |
-
'30' => [
|
1257 |
-
'name' => 'Greater Poland'
|
1258 |
-
],
|
1259 |
-
'32' => [
|
1260 |
-
'name' => 'West Pomerania'
|
1261 |
-
],
|
1262 |
-
]
|
1263 |
-
],
|
1264 |
-
'PT' => [
|
1265 |
-
'name' => 'Portugal',
|
1266 |
-
'regions' => []
|
1267 |
-
],
|
1268 |
-
'PR' => [
|
1269 |
-
'name' => 'Puerto Rico',
|
1270 |
-
'regions' => []
|
1271 |
-
],
|
1272 |
-
'QA' => [
|
1273 |
-
'name' => 'Qatar',
|
1274 |
-
'regions' => []
|
1275 |
-
],
|
1276 |
-
'RE' => [
|
1277 |
-
'name' => 'Reunion',
|
1278 |
-
'regions' => []
|
1279 |
-
],
|
1280 |
-
'RO' => [
|
1281 |
-
'name' => 'Romania',
|
1282 |
-
'regions' => []
|
1283 |
-
],
|
1284 |
-
'RU' => [
|
1285 |
-
'name' => 'Russian Federation',
|
1286 |
-
'regions' => [
|
1287 |
-
'AD' => [
|
1288 |
-
'name' => 'Adygeya, Respublika'
|
1289 |
-
],
|
1290 |
-
'AL' => [
|
1291 |
-
'name' => 'Altay, Respublika'
|
1292 |
-
],
|
1293 |
-
'BA' => [
|
1294 |
-
'name' => 'Bashkortostan, Respublika'
|
1295 |
-
],
|
1296 |
-
'BU' => [
|
1297 |
-
'name' => 'Buryatiya, Respublika'
|
1298 |
-
],
|
1299 |
-
'CE' => [
|
1300 |
-
'name' => 'Chechenskaya Respublika'
|
1301 |
-
],
|
1302 |
-
'CU' => [
|
1303 |
-
'name' => 'Chuvashskaya Respublika'
|
1304 |
-
],
|
1305 |
-
'DA' => [
|
1306 |
-
'name' => 'Dagestan, Respublika'
|
1307 |
-
],
|
1308 |
-
'IN' => [
|
1309 |
-
'name' => 'Ingushetiya, Respublika'
|
1310 |
-
],
|
1311 |
-
'KB' => [
|
1312 |
-
'name' => 'Kabardino-Balkarskaya Respublika'
|
1313 |
-
],
|
1314 |
-
'KL' => [
|
1315 |
-
'name' => 'Kalmykiya, Respublika'
|
1316 |
-
],
|
1317 |
-
'KC' => [
|
1318 |
-
'name' => 'Karachayevo-Cherkesskaya Respublika'
|
1319 |
-
],
|
1320 |
-
'KR' => [
|
1321 |
-
'name' => 'Kareliya, Respublika'
|
1322 |
-
],
|
1323 |
-
'KK' => [
|
1324 |
-
'name' => 'Khakasiya, Respublika'
|
1325 |
-
],
|
1326 |
-
'KO' => [
|
1327 |
-
'name' => 'Komi, Respublika'
|
1328 |
-
],
|
1329 |
-
'ME' => [
|
1330 |
-
'name' => 'Mariy El, Respublika'
|
1331 |
-
],
|
1332 |
-
'MO' => [
|
1333 |
-
'name' => 'Mordoviya, Respublika'
|
1334 |
-
],
|
1335 |
-
'SA' => [
|
1336 |
-
'name' => 'Saha, Respublika'
|
1337 |
-
],
|
1338 |
-
'SE' => [
|
1339 |
-
'name' => 'Severnaya Osetiya, Respublika'
|
1340 |
-
],
|
1341 |
-
'TA' => [
|
1342 |
-
'name' => 'Tatarstan, Respublika'
|
1343 |
-
],
|
1344 |
-
'TY' => [
|
1345 |
-
'name' => 'Tyva, Respublika'
|
1346 |
-
],
|
1347 |
-
'UD' => [
|
1348 |
-
'name' => 'Udmurtskaya Respublika'
|
1349 |
-
],
|
1350 |
-
'ALT' => [
|
1351 |
-
'name' => 'Altayskiy kray'
|
1352 |
-
],
|
1353 |
-
'KAM' => [
|
1354 |
-
'name' => 'Kamchatskiy kray'
|
1355 |
-
],
|
1356 |
-
'KHA' => [
|
1357 |
-
'name' => 'Khabarovskiy kray'
|
1358 |
-
],
|
1359 |
-
'KDA' => [
|
1360 |
-
'name' => 'Krasnodarskiy kray'
|
1361 |
-
],
|
1362 |
-
'KYA' => [
|
1363 |
-
'name' => 'Krasnoyarskiy kray'
|
1364 |
-
],
|
1365 |
-
'PER' => [
|
1366 |
-
'name' => 'Permskiy kray'
|
1367 |
-
],
|
1368 |
-
'PRI' => [
|
1369 |
-
'name' => 'Primorskiy kray'
|
1370 |
-
],
|
1371 |
-
'STA' => [
|
1372 |
-
'name' => 'Stavropol\'skiy kray'
|
1373 |
-
],
|
1374 |
-
'ZAB' => [
|
1375 |
-
'name' => 'Zabaykal\'skiy kray'
|
1376 |
-
],
|
1377 |
-
'AMU' => [
|
1378 |
-
'name' => 'Amurskaya oblast\''
|
1379 |
-
],
|
1380 |
-
'ARK' => [
|
1381 |
-
'name' => 'Arkhangel\'skaya oblast\''
|
1382 |
-
],
|
1383 |
-
'AST' => [
|
1384 |
-
'name' => 'Astrakhanskaya oblast\''
|
1385 |
-
],
|
1386 |
-
'BEL' => [
|
1387 |
-
'name' => 'Belgorodskaya oblast\''
|
1388 |
-
],
|
1389 |
-
'BRY' => [
|
1390 |
-
'name' => 'Bryanskaya oblast\''
|
1391 |
-
],
|
1392 |
-
'CHE' => [
|
1393 |
-
'name' => 'Chelyabinskaya oblast\''
|
1394 |
-
],
|
1395 |
-
'IRK' => [
|
1396 |
-
'name' => 'Irkutskaya oblast\''
|
1397 |
-
],
|
1398 |
-
'IVA' => [
|
1399 |
-
'name' => 'Ivanovskaya oblast\''
|
1400 |
-
],
|
1401 |
-
'KGD' => [
|
1402 |
-
'name' => 'Kaliningradskaya oblast\''
|
1403 |
-
],
|
1404 |
-
'KLU' => [
|
1405 |
-
'name' => 'Kaluzhskaya oblast\''
|
1406 |
-
],
|
1407 |
-
'KEM' => [
|
1408 |
-
'name' => 'Kemerovskaya oblast\''
|
1409 |
-
],
|
1410 |
-
'KIR' => [
|
1411 |
-
'name' => 'Kirovskaya oblast\''
|
1412 |
-
],
|
1413 |
-
'KOS' => [
|
1414 |
-
'name' => 'Kostromskaya oblast\''
|
1415 |
-
],
|
1416 |
-
'KGN' => [
|
1417 |
-
'name' => 'Kurganskaya oblast\''
|
1418 |
-
],
|
1419 |
-
'KRS' => [
|
1420 |
-
'name' => 'Kurskaya oblast\''
|
1421 |
-
],
|
1422 |
-
'LEN' => [
|
1423 |
-
'name' => 'Leningradskaya oblast\''
|
1424 |
-
],
|
1425 |
-
'LIP' => [
|
1426 |
-
'name' => 'Lipetskaya oblast\''
|
1427 |
-
],
|
1428 |
-
'MAG' => [
|
1429 |
-
'name' => 'Magadanskaya oblast\''
|
1430 |
-
],
|
1431 |
-
'MOS' => [
|
1432 |
-
'name' => 'Moskovskaya oblast\''
|
1433 |
-
],
|
1434 |
-
'MUR' => [
|
1435 |
-
'name' => 'Murmanskaya oblast\''
|
1436 |
-
],
|
1437 |
-
'NIZ' => [
|
1438 |
-
'name' => 'Nizhegorodskaya oblast\''
|
1439 |
-
],
|
1440 |
-
'NGR' => [
|
1441 |
-
'name' => 'Novgorodskaya oblast\''
|
1442 |
-
],
|
1443 |
-
'NVS' => [
|
1444 |
-
'name' => 'Novosibirskaya oblast\''
|
1445 |
-
],
|
1446 |
-
'OMS' => [
|
1447 |
-
'name' => 'Omskaya oblast\''
|
1448 |
-
],
|
1449 |
-
'ORE' => [
|
1450 |
-
'name' => 'Orenburgskaya oblast\''
|
1451 |
-
],
|
1452 |
-
'ORL' => [
|
1453 |
-
'name' => 'Orlovskaya oblast\''
|
1454 |
-
],
|
1455 |
-
'PNZ' => [
|
1456 |
-
'name' => 'Penzenskaya oblast\''
|
1457 |
-
],
|
1458 |
-
'PSK' => [
|
1459 |
-
'name' => 'Pskovskaya oblast\''
|
1460 |
-
],
|
1461 |
-
'ROS' => [
|
1462 |
-
'name' => 'Rostovskaya oblast\''
|
1463 |
-
],
|
1464 |
-
'RYA' => [
|
1465 |
-
'name' => 'Ryazanskaya oblast\''
|
1466 |
-
],
|
1467 |
-
'SAK' => [
|
1468 |
-
'name' => 'Sakhalinskaya oblast\''
|
1469 |
-
],
|
1470 |
-
'SAM' => [
|
1471 |
-
'name' => 'Samarskaya oblast\''
|
1472 |
-
],
|
1473 |
-
'SAR' => [
|
1474 |
-
'name' => 'Saratovskaya oblast\''
|
1475 |
-
],
|
1476 |
-
'SMO' => [
|
1477 |
-
'name' => 'Smolenskaya oblast\''
|
1478 |
-
],
|
1479 |
-
'SVE' => [
|
1480 |
-
'name' => 'Sverdlovskaya oblast\''
|
1481 |
-
],
|
1482 |
-
'TAM' => [
|
1483 |
-
'name' => 'Tambovskaya oblast\''
|
1484 |
-
],
|
1485 |
-
'TOM' => [
|
1486 |
-
'name' => 'Tomskaya oblast\''
|
1487 |
-
],
|
1488 |
-
'TUL' => [
|
1489 |
-
'name' => 'Tul\'skaya oblast\''
|
1490 |
-
],
|
1491 |
-
'TVE' => [
|
1492 |
-
'name' => 'Tverskaya oblast\''
|
1493 |
-
],
|
1494 |
-
'TYU' => [
|
1495 |
-
'name' => 'Tyumenskaya oblast\''
|
1496 |
-
],
|
1497 |
-
'ULY' => [
|
1498 |
-
'name' => 'Ul\'yanovskaya oblast\''
|
1499 |
-
],
|
1500 |
-
'VLA' => [
|
1501 |
-
'name' => 'Vladimirskaya oblast\''
|
1502 |
-
],
|
1503 |
-
'VGG' => [
|
1504 |
-
'name' => 'Volgogradskaya oblast\''
|
1505 |
-
],
|
1506 |
-
'VLG' => [
|
1507 |
-
'name' => 'Vologodskaya oblast\''
|
1508 |
-
],
|
1509 |
-
'VOR' => [
|
1510 |
-
'name' => 'Voronezhskaya oblast\''
|
1511 |
-
],
|
1512 |
-
'YAR' => [
|
1513 |
-
'name' => 'Yaroslavskaya oblast\''
|
1514 |
-
],
|
1515 |
-
'MOW' => [
|
1516 |
-
'name' => 'Moskva'
|
1517 |
-
],
|
1518 |
-
'SPE' => [
|
1519 |
-
'name' => 'Sankt-Peterburg'
|
1520 |
-
],
|
1521 |
-
'YEV' => [
|
1522 |
-
'name' => 'Yevreyskaya avtonomnaya oblast\''
|
1523 |
-
],
|
1524 |
-
'CHU' => [
|
1525 |
-
'name' => 'Chukotskiy avtonomnyy okrug'
|
1526 |
-
],
|
1527 |
-
'KHM' => [
|
1528 |
-
'name' => 'Khanty-Mansiyskiy avtonomnyy okrug'
|
1529 |
-
],
|
1530 |
-
'NEN' => [
|
1531 |
-
'name' => 'Nenetskiy avtonomnyy okrug'
|
1532 |
-
],
|
1533 |
-
'YAN' => [
|
1534 |
-
'name' => 'Yamalo-Nenetskiy avtonomnyy okrug'
|
1535 |
-
],
|
1536 |
-
]
|
1537 |
-
],
|
1538 |
-
'RW' => [
|
1539 |
-
'name' => 'Rwanda',
|
1540 |
-
'regions' => []
|
1541 |
-
],
|
1542 |
-
'BL' => [
|
1543 |
-
'name' => 'Saint Barthelemy',
|
1544 |
-
'regions' => []
|
1545 |
-
],
|
1546 |
-
'SH' => [
|
1547 |
-
'name' => 'Saint Helena',
|
1548 |
-
'regions' => []
|
1549 |
-
],
|
1550 |
-
'KN' => [
|
1551 |
-
'name' => 'Saint Kitts And Nevis',
|
1552 |
-
'regions' => []
|
1553 |
-
],
|
1554 |
-
'LC' => [
|
1555 |
-
'name' => 'Saint Lucia',
|
1556 |
-
'regions' => []
|
1557 |
-
],
|
1558 |
-
'MF' => [
|
1559 |
-
'name' => 'Saint Martin',
|
1560 |
-
'regions' => []
|
1561 |
-
],
|
1562 |
-
'PM' => [
|
1563 |
-
'name' => 'Saint Pierre And Miquelon',
|
1564 |
-
'regions' => []
|
1565 |
-
],
|
1566 |
-
'VC' => [
|
1567 |
-
'name' => 'Saint Vincent And Grenadines',
|
1568 |
-
'regions' => []
|
1569 |
-
],
|
1570 |
-
'WS' => [
|
1571 |
-
'name' => 'Samoa',
|
1572 |
-
'regions' => []
|
1573 |
-
],
|
1574 |
-
'SM' => [
|
1575 |
-
'name' => 'San Marino',
|
1576 |
-
'regions' => []
|
1577 |
-
],
|
1578 |
-
'ST' => [
|
1579 |
-
'name' => 'Sao Tome And Principe',
|
1580 |
-
'regions' => []
|
1581 |
-
],
|
1582 |
-
'SA' => [
|
1583 |
-
'name' => 'Saudi Arabia',
|
1584 |
-
'regions' => []
|
1585 |
-
],
|
1586 |
-
'SN' => [
|
1587 |
-
'name' => 'Senegal',
|
1588 |
-
'regions' => []
|
1589 |
-
],
|
1590 |
-
'RS' => [
|
1591 |
-
'name' => 'Serbia',
|
1592 |
-
'regions' => []
|
1593 |
-
],
|
1594 |
-
'SC' => [
|
1595 |
-
'name' => 'Seychelles',
|
1596 |
-
'regions' => []
|
1597 |
-
],
|
1598 |
-
'SL' => [
|
1599 |
-
'name' => 'Sierra Leone',
|
1600 |
-
'regions' => []
|
1601 |
-
],
|
1602 |
-
'SG' => [
|
1603 |
-
'name' => 'Singapore',
|
1604 |
-
'regions' => [
|
1605 |
-
'01' => [
|
1606 |
-
'name' => 'Central Singapore'
|
1607 |
-
],
|
1608 |
-
'02' => [
|
1609 |
-
'name' => 'North East'
|
1610 |
-
],
|
1611 |
-
'03' => [
|
1612 |
-
'name' => 'North West'
|
1613 |
-
],
|
1614 |
-
'04' => [
|
1615 |
-
'name' => 'South East'
|
1616 |
-
],
|
1617 |
-
'05' => [
|
1618 |
-
'name' => 'South West'
|
1619 |
-
]
|
1620 |
-
]
|
1621 |
-
],
|
1622 |
-
'SK' => [
|
1623 |
-
'name' => 'Slovakia',
|
1624 |
-
'regions' => []
|
1625 |
-
],
|
1626 |
-
'SI' => [
|
1627 |
-
'name' => 'Slovenia',
|
1628 |
-
'regions' => []
|
1629 |
-
],
|
1630 |
-
'SB' => [
|
1631 |
-
'name' => 'Solomon Islands',
|
1632 |
-
'regions' => []
|
1633 |
-
],
|
1634 |
-
'SO' => [
|
1635 |
-
'name' => 'Somalia',
|
1636 |
-
'regions' => []
|
1637 |
-
],
|
1638 |
-
'ZA' => [
|
1639 |
-
'name' => 'South Africa',
|
1640 |
-
'regions' => []
|
1641 |
-
],
|
1642 |
-
'GS' => [
|
1643 |
-
'name' => 'South Georgia And Sandwich Isl.',
|
1644 |
-
'regions' => []
|
1645 |
-
],
|
1646 |
-
'ES' => [
|
1647 |
-
'name' => 'Spain',
|
1648 |
-
'regions' => []
|
1649 |
-
],
|
1650 |
-
'LK' => [
|
1651 |
-
'name' => 'Sri Lanka',
|
1652 |
-
'regions' => []
|
1653 |
-
],
|
1654 |
-
'SD' => [
|
1655 |
-
'name' => 'Sudan',
|
1656 |
-
'regions' => []
|
1657 |
-
],
|
1658 |
-
'SR' => [
|
1659 |
-
'name' => 'Suriname',
|
1660 |
-
'regions' => []
|
1661 |
-
],
|
1662 |
-
'SJ' => [
|
1663 |
-
'name' => 'Svalbard And Jan Mayen',
|
1664 |
-
'regions' => []
|
1665 |
-
],
|
1666 |
-
'SZ' => [
|
1667 |
-
'name' => 'Swaziland',
|
1668 |
-
'regions' => []
|
1669 |
-
],
|
1670 |
-
'SE' => [
|
1671 |
-
'name' => 'Sweden',
|
1672 |
-
'regions' => []
|
1673 |
-
],
|
1674 |
-
'CH' => [
|
1675 |
-
'name' => 'Switzerland',
|
1676 |
-
'regions' => []
|
1677 |
-
],
|
1678 |
-
'SY' => [
|
1679 |
-
'name' => 'Syrian Arab Republic',
|
1680 |
-
'regions' => []
|
1681 |
-
],
|
1682 |
-
'TW' => [
|
1683 |
-
'name' => 'Taiwan',
|
1684 |
-
'regions' => []
|
1685 |
-
],
|
1686 |
-
'TJ' => [
|
1687 |
-
'name' => 'Tajikistan',
|
1688 |
-
'regions' => []
|
1689 |
-
],
|
1690 |
-
'TZ' => [
|
1691 |
-
'name' => 'Tanzania',
|
1692 |
-
'regions' => []
|
1693 |
-
],
|
1694 |
-
'TH' => [
|
1695 |
-
'name' => 'Thailand',
|
1696 |
-
'regions' => []
|
1697 |
-
],
|
1698 |
-
'TL' => [
|
1699 |
-
'name' => 'Timor-Leste',
|
1700 |
-
'regions' => []
|
1701 |
-
],
|
1702 |
-
'TG' => [
|
1703 |
-
'name' => 'Togo',
|
1704 |
-
'regions' => []
|
1705 |
-
],
|
1706 |
-
'TK' => [
|
1707 |
-
'name' => 'Tokelau',
|
1708 |
-
'regions' => []
|
1709 |
-
],
|
1710 |
-
'TO' => [
|
1711 |
-
'name' => 'Tonga',
|
1712 |
-
'regions' => []
|
1713 |
-
],
|
1714 |
-
'TT' => [
|
1715 |
-
'name' => 'Trinidad And Tobago',
|
1716 |
-
'regions' => []
|
1717 |
-
],
|
1718 |
-
'TN' => [
|
1719 |
-
'name' => 'Tunisia',
|
1720 |
-
'regions' => []
|
1721 |
-
],
|
1722 |
-
'TR' => [
|
1723 |
-
'name' => 'Turkey',
|
1724 |
-
'regions' => [
|
1725 |
-
'01' => [
|
1726 |
-
'name' => 'Adana'
|
1727 |
-
],
|
1728 |
-
'02' => [
|
1729 |
-
'name' => 'Adıyaman'
|
1730 |
-
],
|
1731 |
-
'03' => [
|
1732 |
-
'name' => 'Afyonkarahisar'
|
1733 |
-
],
|
1734 |
-
'04' => [
|
1735 |
-
'name' => 'Ağrı'
|
1736 |
-
],
|
1737 |
-
'68' => [
|
1738 |
-
'name' => 'Aksaray'
|
1739 |
-
],
|
1740 |
-
'05' => [
|
1741 |
-
'name' => 'Amasya'
|
1742 |
-
],
|
1743 |
-
'06' => [
|
1744 |
-
'name' => 'Ankara'
|
1745 |
-
],
|
1746 |
-
'07' => [
|
1747 |
-
'name' => 'Antalya'
|
1748 |
-
],
|
1749 |
-
'75' => [
|
1750 |
-
'name' => 'Ardahan'
|
1751 |
-
],
|
1752 |
-
'08' => [
|
1753 |
-
'name' => 'Artvin'
|
1754 |
-
],
|
1755 |
-
'09' => [
|
1756 |
-
'name' => 'Aydın'
|
1757 |
-
],
|
1758 |
-
'10' => [
|
1759 |
-
'name' => 'Balıkesir'
|
1760 |
-
],
|
1761 |
-
'74' => [
|
1762 |
-
'name' => 'Bartın'
|
1763 |
-
],
|
1764 |
-
'72' => [
|
1765 |
-
'name' => 'Batman'
|
1766 |
-
],
|
1767 |
-
'69' => [
|
1768 |
-
'name' => 'Bayburt'
|
1769 |
-
],
|
1770 |
-
'11' => [
|
1771 |
-
'name' => 'Bilecik'
|
1772 |
-
],
|
1773 |
-
'12' => [
|
1774 |
-
'name' => 'Bingöl'
|
1775 |
-
],
|
1776 |
-
'13' => [
|
1777 |
-
'name' => 'Bitlis'
|
1778 |
-
],
|
1779 |
-
'14' => [
|
1780 |
-
'name' => 'Bolu'
|
1781 |
-
],
|
1782 |
-
'15' => [
|
1783 |
-
'name' => 'Burdur'
|
1784 |
-
],
|
1785 |
-
'16' => [
|
1786 |
-
'name' => 'Bursa'
|
1787 |
-
],
|
1788 |
-
'17' => [
|
1789 |
-
'name' => 'Çanakkale'
|
1790 |
-
],
|
1791 |
-
'18' => [
|
1792 |
-
'name' => 'Çankırı'
|
1793 |
-
],
|
1794 |
-
'19' => [
|
1795 |
-
'name' => 'Çorum'
|
1796 |
-
],
|
1797 |
-
'20' => [
|
1798 |
-
'name' => 'Denizli'
|
1799 |
-
],
|
1800 |
-
'21' => [
|
1801 |
-
'name' => 'Diyarbakır'
|
1802 |
-
],
|
1803 |
-
'81' => [
|
1804 |
-
'name' => 'Düzce'
|
1805 |
-
],
|
1806 |
-
'22' => [
|
1807 |
-
'name' => 'Edirne'
|
1808 |
-
],
|
1809 |
-
'23' => [
|
1810 |
-
'name' => 'Elazığ'
|
1811 |
-
],
|
1812 |
-
'24' => [
|
1813 |
-
'name' => 'Erzincan'
|
1814 |
-
],
|
1815 |
-
'25' => [
|
1816 |
-
'name' => 'Erzurum'
|
1817 |
-
],
|
1818 |
-
'26' => [
|
1819 |
-
'name' => 'Eskişehir'
|
1820 |
-
],
|
1821 |
-
'27' => [
|
1822 |
-
'name' => 'Gaziantep'
|
1823 |
-
],
|
1824 |
-
'28' => [
|
1825 |
-
'name' => 'Giresun'
|
1826 |
-
],
|
1827 |
-
'29' => [
|
1828 |
-
'name' => 'Gümüşhane'
|
1829 |
-
],
|
1830 |
-
'30' => [
|
1831 |
-
'name' => 'Hakkâri'
|
1832 |
-
],
|
1833 |
-
'31' => [
|
1834 |
-
'name' => 'Hatay'
|
1835 |
-
],
|
1836 |
-
'76' => [
|
1837 |
-
'name' => 'Iğdır'
|
1838 |
-
],
|
1839 |
-
'32' => [
|
1840 |
-
'name' => 'Isparta'
|
1841 |
-
],
|
1842 |
-
'34' => [
|
1843 |
-
'name' => 'İstanbul'
|
1844 |
-
],
|
1845 |
-
'35' => [
|
1846 |
-
'name' => 'İzmir'
|
1847 |
-
],
|
1848 |
-
'46' => [
|
1849 |
-
'name' => 'Kahramanmaraş'
|
1850 |
-
],
|
1851 |
-
'78' => [
|
1852 |
-
'name' => 'Karabük'
|
1853 |
-
],
|
1854 |
-
'70' => [
|
1855 |
-
'name' => 'Karaman'
|
1856 |
-
],
|
1857 |
-
'36' => [
|
1858 |
-
'name' => 'Kars'
|
1859 |
-
],
|
1860 |
-
'37' => [
|
1861 |
-
'name' => 'Kastamonu'
|
1862 |
-
],
|
1863 |
-
'38' => [
|
1864 |
-
'name' => 'Kayseri'
|
1865 |
-
],
|
1866 |
-
'71' => [
|
1867 |
-
'name' => 'Kırıkkale'
|
1868 |
-
],
|
1869 |
-
'39' => [
|
1870 |
-
'name' => 'Kırklareli'
|
1871 |
-
],
|
1872 |
-
'40' => [
|
1873 |
-
'name' => 'Kırşehir'
|
1874 |
-
],
|
1875 |
-
'79' => [
|
1876 |
-
'name' => 'Kilis'
|
1877 |
-
],
|
1878 |
-
'41' => [
|
1879 |
-
'name' => 'Kocaeli'
|
1880 |
-
],
|
1881 |
-
'42' => [
|
1882 |
-
'name' => 'Konya'
|
1883 |
-
],
|
1884 |
-
'43' => [
|
1885 |
-
'name' => 'Kütahya'
|
1886 |
-
],
|
1887 |
-
'44' => [
|
1888 |
-
'name' => 'Malatya'
|
1889 |
-
],
|
1890 |
-
'45' => [
|
1891 |
-
'name' => 'Manisa'
|
1892 |
-
],
|
1893 |
-
'47' => [
|
1894 |
-
'name' => 'Mardin'
|
1895 |
-
],
|
1896 |
-
'33' => [
|
1897 |
-
'name' => 'Mersin'
|
1898 |
-
],
|
1899 |
-
'48' => [
|
1900 |
-
'name' => 'Muğla'
|
1901 |
-
],
|
1902 |
-
'49' => [
|
1903 |
-
'name' => 'Muş'
|
1904 |
-
],
|
1905 |
-
'50' => [
|
1906 |
-
'name' => 'Nevşehir'
|
1907 |
-
],
|
1908 |
-
'51' => [
|
1909 |
-
'name' => 'Niğde'
|
1910 |
-
],
|
1911 |
-
'52' => [
|
1912 |
-
'name' => 'Ordu'
|
1913 |
-
],
|
1914 |
-
'80' => [
|
1915 |
-
'name' => 'Osmaniye'
|
1916 |
-
],
|
1917 |
-
'53' => [
|
1918 |
-
'name' => 'Rize'
|
1919 |
-
],
|
1920 |
-
'54' => [
|
1921 |
-
'name' => 'Sakarya'
|
1922 |
-
],
|
1923 |
-
'55' => [
|
1924 |
-
'name' => 'Samsun'
|
1925 |
-
],
|
1926 |
-
'56' => [
|
1927 |
-
'name' => 'Siirt'
|
1928 |
-
],
|
1929 |
-
'57' => [
|
1930 |
-
'name' => 'Sinop'
|
1931 |
-
],
|
1932 |
-
'58' => [
|
1933 |
-
'name' => 'Sivas'
|
1934 |
-
],
|
1935 |
-
'63' => [
|
1936 |
-
'name' => 'Şanlıurfa'
|
1937 |
-
],
|
1938 |
-
'73' => [
|
1939 |
-
'name' => 'Şırnak'
|
1940 |
-
],
|
1941 |
-
'59' => [
|
1942 |
-
'name' => 'Tekirdağ'
|
1943 |
-
],
|
1944 |
-
'60' => [
|
1945 |
-
'name' => 'Tokat'
|
1946 |
-
],
|
1947 |
-
'61' => [
|
1948 |
-
'name' => 'Trabzon'
|
1949 |
-
],
|
1950 |
-
'62' => [
|
1951 |
-
'name' => 'Tunceli'
|
1952 |
-
],
|
1953 |
-
'64' => [
|
1954 |
-
'name' => 'Uşak'
|
1955 |
-
],
|
1956 |
-
'65' => [
|
1957 |
-
'name' => 'Van'
|
1958 |
-
],
|
1959 |
-
'77' => [
|
1960 |
-
'name' => 'Yalova'
|
1961 |
-
],
|
1962 |
-
'66' => [
|
1963 |
-
'name' => 'Yozgat'
|
1964 |
-
],
|
1965 |
-
'67' => [
|
1966 |
-
'name' => 'Zonguldak'
|
1967 |
-
]
|
1968 |
-
]
|
1969 |
-
],
|
1970 |
-
'TM' => [
|
1971 |
-
'name' => 'Turkmenistan',
|
1972 |
-
'regions' => []
|
1973 |
-
],
|
1974 |
-
'TC' => [
|
1975 |
-
'name' => 'Turks And Caicos Islands',
|
1976 |
-
'regions' => []
|
1977 |
-
],
|
1978 |
-
'TV' => [
|
1979 |
-
'name' => 'Tuvalu',
|
1980 |
-
'regions' => []
|
1981 |
-
],
|
1982 |
-
'UG' => [
|
1983 |
-
'name' => 'Uganda',
|
1984 |
-
'regions' => []
|
1985 |
-
],
|
1986 |
-
'UA' => [
|
1987 |
-
'name' => 'Ukraine',
|
1988 |
-
'regions' => [
|
1989 |
-
'40' => [
|
1990 |
-
'name' => 'Sevastopol'
|
1991 |
-
],
|
1992 |
-
'30' => [
|
1993 |
-
'name' => 'Kyiv'
|
1994 |
-
],
|
1995 |
-
'43' => [
|
1996 |
-
'name' => 'Avtonomna Respublika Krym'
|
1997 |
-
],
|
1998 |
-
'18' => [
|
1999 |
-
'name' => 'Zhytomyrska oblast'
|
2000 |
-
],
|
2001 |
-
'23' => [
|
2002 |
-
'name' => 'Zaporizka oblast'
|
2003 |
-
],
|
2004 |
-
'21' => [
|
2005 |
-
'name' => 'Zakarpatska oblast'
|
2006 |
-
],
|
2007 |
-
'07' => [
|
2008 |
-
'name' => 'Volynska oblast'
|
2009 |
-
],
|
2010 |
-
'05' => [
|
2011 |
-
'name' => 'Vinnytska oblast'
|
2012 |
-
],
|
2013 |
-
'61' => [
|
2014 |
-
'name' => 'Ternopilska oblast'
|
2015 |
-
],
|
2016 |
-
'59' => [
|
2017 |
-
'name' => 'Sumska oblast'
|
2018 |
-
],
|
2019 |
-
'56' => [
|
2020 |
-
'name' => 'Rivnenska oblast'
|
2021 |
-
],
|
2022 |
-
'53' => [
|
2023 |
-
'name' => 'Poltavska oblast'
|
2024 |
-
],
|
2025 |
-
'51' => [
|
2026 |
-
'name' => 'Odeska oblast'
|
2027 |
-
],
|
2028 |
-
'48' => [
|
2029 |
-
'name' => 'Mykolaivska oblast'
|
2030 |
-
],
|
2031 |
-
'46' => [
|
2032 |
-
'name' => 'Lvivska oblast'
|
2033 |
-
],
|
2034 |
-
'09' => [
|
2035 |
-
'name' => 'Luhanska oblast'
|
2036 |
-
],
|
2037 |
-
'32' => [
|
2038 |
-
'name' => 'Kyivska oblast'
|
2039 |
-
],
|
2040 |
-
'35' => [
|
2041 |
-
'name' => 'Kirovohradska oblast'
|
2042 |
-
],
|
2043 |
-
'68' => [
|
2044 |
-
'name' => 'Khmelnytska oblast'
|
2045 |
-
],
|
2046 |
-
'65' => [
|
2047 |
-
'name' => 'Khersonska oblast'
|
2048 |
-
],
|
2049 |
-
'63' => [
|
2050 |
-
'name' => 'Kharkivska oblast'
|
2051 |
-
],
|
2052 |
-
'26' => [
|
2053 |
-
'name' => 'Ivano-Frankivska oblast'
|
2054 |
-
],
|
2055 |
-
'14' => [
|
2056 |
-
'name' => 'Donetska oblast'
|
2057 |
-
],
|
2058 |
-
'12' => [
|
2059 |
-
'name' => 'Dnipropetrovska oblast'
|
2060 |
-
],
|
2061 |
-
'77' => [
|
2062 |
-
'name' => 'Chernivetska oblast'
|
2063 |
-
],
|
2064 |
-
'74' => [
|
2065 |
-
'name' => 'Chernihivska oblast'
|
2066 |
-
],
|
2067 |
-
'71' => [
|
2068 |
-
'name' => 'Cherkaska oblast'
|
2069 |
-
]
|
2070 |
-
]
|
2071 |
-
],
|
2072 |
-
'AE' => [
|
2073 |
-
'name' => 'United Arab Emirates',
|
2074 |
-
'regions' => []
|
2075 |
-
],
|
2076 |
-
'GB' => [
|
2077 |
-
'name' => 'United Kingdom',
|
2078 |
-
'regions' => []
|
2079 |
-
],
|
2080 |
-
'UM' => [
|
2081 |
-
'name' => 'United States Outlying Islands',
|
2082 |
-
'regions' => []
|
2083 |
-
],
|
2084 |
-
'UY' => [
|
2085 |
-
'name' => 'Uruguay',
|
2086 |
-
'regions' => []
|
2087 |
-
],
|
2088 |
-
'UZ' => [
|
2089 |
-
'name' => 'Uzbekistan',
|
2090 |
-
'regions' => []
|
2091 |
-
],
|
2092 |
-
'VU' => [
|
2093 |
-
'name' => 'Vanuatu',
|
2094 |
-
'regions' => []
|
2095 |
-
],
|
2096 |
-
'VE' => [
|
2097 |
-
'name' => 'Venezuela',
|
2098 |
-
'regions' => []
|
2099 |
-
],
|
2100 |
-
'VN' => [
|
2101 |
-
'name' => 'Viet Nam',
|
2102 |
-
'regions' => []
|
2103 |
-
],
|
2104 |
-
'VG' => [
|
2105 |
-
'name' => 'Virgin Islands, British',
|
2106 |
-
'regions' => []
|
2107 |
-
],
|
2108 |
-
'VI' => [
|
2109 |
-
'name' => 'Virgin Islands, U.S.',
|
2110 |
-
'regions' => []
|
2111 |
-
],
|
2112 |
-
'WF' => [
|
2113 |
-
'name' => 'Wallis And Futuna',
|
2114 |
-
'regions' => []
|
2115 |
-
],
|
2116 |
-
'EH' => [
|
2117 |
-
'name' => 'Western Sahara',
|
2118 |
-
'regions' => []
|
2119 |
-
],
|
2120 |
-
'YE' => [
|
2121 |
-
'name' => 'Yemen',
|
2122 |
-
'regions' => []
|
2123 |
-
],
|
2124 |
-
'ZM' => [
|
2125 |
-
'name' => 'Zambia',
|
2126 |
-
'regions' => []
|
2127 |
-
],
|
2128 |
-
'ZW' => [
|
2129 |
-
'name' => 'Zimbabwe',
|
2130 |
-
'regions' => []
|
2131 |
-
]
|
2132 |
-
];
|
2133 |
-
|
2134 |
-
if ( ! $region_code ) {
|
2135 |
-
if ( ! empty( $locations[ $country_code ]['name'] ) ) {
|
2136 |
-
return $locations[ $country_code ]['name'];
|
2137 |
-
} elseif( ! $country_code ) {
|
2138 |
-
return false;
|
2139 |
-
} else {
|
2140 |
-
return $country_code;
|
2141 |
-
}
|
2142 |
-
} else {
|
2143 |
-
if ( ! empty( $locations[ $country_code ]['regions'][ $region_code ]['name'] ) ) {
|
2144 |
-
return $locations[ $country_code ]['regions'][ $region_code ]['name'];
|
2145 |
-
} elseif( ! $region_code ) {
|
2146 |
-
return false;
|
2147 |
-
} else {
|
2148 |
-
return $region_code;
|
2149 |
-
}
|
2150 |
-
}
|
2151 |
-
}
|
2152 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/scripts.php
DELETED
@@ -1,160 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Contains all JS & CSS scripts for the WordPress Zero Spam plugin.
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.0.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Register & enqueue the WordPress Zero Spam JS & CSS for the admin dashboard
|
11 |
-
*/
|
12 |
-
if ( ! function_exists( 'wpzerospam_admin_scripts' ) ) {
|
13 |
-
function wpzerospam_admin_scripts( $hook_suffix ) {
|
14 |
-
wp_enqueue_style(
|
15 |
-
'wpzerospam-admin',
|
16 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
17 |
-
'assets/css/admin.css',
|
18 |
-
false,
|
19 |
-
WORDPRESS_ZERO_SPAM_VERSION
|
20 |
-
);
|
21 |
-
|
22 |
-
// Register Chart.js for graphs
|
23 |
-
wp_register_script(
|
24 |
-
'wpzerospam-charts',
|
25 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
26 |
-
'assets/js/Chart.bundle.min.js',
|
27 |
-
[],
|
28 |
-
'2.9.3'
|
29 |
-
);
|
30 |
-
|
31 |
-
// Register Chart.css for graphs
|
32 |
-
wp_register_style(
|
33 |
-
'wpzerospam-charts',
|
34 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
35 |
-
'assets/css/Chart.min.css',
|
36 |
-
false,
|
37 |
-
'2.9.3'
|
38 |
-
);
|
39 |
-
|
40 |
-
// Register jvectormap for world map
|
41 |
-
wp_register_script(
|
42 |
-
'wpzerospam-map',
|
43 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
44 |
-
'assets/js/jquery-jvectormap-2.0.5.min.js',
|
45 |
-
[ 'jquery' ],
|
46 |
-
'2.0.5'
|
47 |
-
);
|
48 |
-
|
49 |
-
wp_register_script(
|
50 |
-
'wpzerospam-world-map',
|
51 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
52 |
-
'assets/js/jquery-jvectormap-world-mill.js',
|
53 |
-
[ 'wpzerospam-map' ],
|
54 |
-
'2.0.5'
|
55 |
-
);
|
56 |
-
|
57 |
-
// Register jvectormap for world map
|
58 |
-
wp_register_style(
|
59 |
-
'wpzerospam-map',
|
60 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
61 |
-
'assets/css/jquery-jvectormap-2.0.5.css',
|
62 |
-
false,
|
63 |
-
'2.9.3'
|
64 |
-
);
|
65 |
-
|
66 |
-
wp_register_script(
|
67 |
-
'wpzerospam-admin-tables',
|
68 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
69 |
-
'assets/js/admin-tables.js',
|
70 |
-
[ 'jquery' ],
|
71 |
-
WORDPRESS_ZERO_SPAM_VERSION,
|
72 |
-
true
|
73 |
-
);
|
74 |
-
|
75 |
-
wp_register_style(
|
76 |
-
'wpzerospam-admin-tables',
|
77 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
78 |
-
'assets/css/admin-tables.css',
|
79 |
-
false,
|
80 |
-
WORDPRESS_ZERO_SPAM_VERSION
|
81 |
-
);
|
82 |
-
|
83 |
-
// Handle registering & enqueuing scripts based on the current admin page
|
84 |
-
switch( $hook_suffix ) {
|
85 |
-
case 'wp-zero-spam_page_wordpress-zero-spam-detections':
|
86 |
-
case 'wp-zero-spam_page_wordpress-zero-spam-blacklisted':
|
87 |
-
wp_enqueue_script( 'wpzerospam-admin-tables' );
|
88 |
-
wp_enqueue_style( 'wpzerospam-admin-tables' );
|
89 |
-
break;
|
90 |
-
case 'toplevel_page_wordpress-zero-spam':
|
91 |
-
// Enqueue Chart.js
|
92 |
-
wp_enqueue_script( 'wpzerospam-charts' );
|
93 |
-
wp_enqueue_style( 'wpzerospam-charts' );
|
94 |
-
|
95 |
-
// Enqueue jvectormap.js
|
96 |
-
wp_enqueue_script( 'wpzerospam-world-map' );
|
97 |
-
wp_enqueue_style( 'wpzerospam-map' );
|
98 |
-
|
99 |
-
wp_enqueue_style(
|
100 |
-
'wpzerospam-admin-dashboard',
|
101 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
102 |
-
'assets/css/admin-dashboard.css',
|
103 |
-
false,
|
104 |
-
WORDPRESS_ZERO_SPAM_VERSION
|
105 |
-
);
|
106 |
-
break;
|
107 |
-
case 'wp-zero-spam_page_wordpress-zero-spam-blocked-ips':
|
108 |
-
wp_enqueue_script( 'wpzerospam-admin-tables' );
|
109 |
-
wp_enqueue_style( 'wpzerospam-admin-tables' );
|
110 |
-
|
111 |
-
// Enqueue the JS for the WordPress Zero Spam blocked IPs page
|
112 |
-
wp_enqueue_script(
|
113 |
-
'wpzerospam-admin-blocked-ips',
|
114 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
115 |
-
'assets/js/admin-blocked-ips.js',
|
116 |
-
[ 'jquery' ],
|
117 |
-
WORDPRESS_ZERO_SPAM_VERSION,
|
118 |
-
true
|
119 |
-
);
|
120 |
-
|
121 |
-
// Enqueue the CSS for the WordPress Zero Spam blocked IPs page
|
122 |
-
wp_enqueue_style(
|
123 |
-
'wpzerospam-admin-block_ips',
|
124 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
125 |
-
'assets/css/admin-blocked-ips.css',
|
126 |
-
false,
|
127 |
-
WORDPRESS_ZERO_SPAM_VERSION
|
128 |
-
);
|
129 |
-
break;
|
130 |
-
}
|
131 |
-
}
|
132 |
-
}
|
133 |
-
add_action( 'admin_enqueue_scripts', 'wpzerospam_admin_scripts' );
|
134 |
-
|
135 |
-
/**
|
136 |
-
* Register & enqueue the WordPress Zero Spam JS & CSS for the frontend
|
137 |
-
*/
|
138 |
-
if ( ! function_exists( 'wpzerospam_enqueue_scripts' ) ) {
|
139 |
-
function wpzerospam_enqueue_scripts() {
|
140 |
-
// Load the JS that contains the WordPressZeroSpam oject, needed on all
|
141 |
-
// pages
|
142 |
-
wp_enqueue_script(
|
143 |
-
'wpzerospam',
|
144 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
145 |
-
'assets/js/wpzerospam.js',
|
146 |
-
[ 'jquery' ],
|
147 |
-
WORDPRESS_ZERO_SPAM_VERSION,
|
148 |
-
true
|
149 |
-
);
|
150 |
-
|
151 |
-
// Pass the latest generate key to the frontend script
|
152 |
-
wp_localize_script(
|
153 |
-
'wpzerospam',
|
154 |
-
'wpzerospam',
|
155 |
-
[ 'key' => wpzerospam_get_key() ]
|
156 |
-
);
|
157 |
-
}
|
158 |
-
}
|
159 |
-
add_action( 'wp_enqueue_scripts', 'wpzerospam_enqueue_scripts' );
|
160 |
-
add_action( 'login_footer', 'wpzerospam_enqueue_scripts' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/uninstall.php
DELETED
@@ -1,50 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Handles uninstalling the plugin
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
*/
|
7 |
-
|
8 |
-
// Security Note: Blocks direct access to the plugin PHP files.
|
9 |
-
defined( 'ABSPATH' ) || die();
|
10 |
-
|
11 |
-
/**
|
12 |
-
* Fired when the plugin is deleted.
|
13 |
-
*/
|
14 |
-
function wpzerospam_uninstall() {
|
15 |
-
global $wpdb;
|
16 |
-
|
17 |
-
$wordpress_zero_spam = new WPZeroSpam();
|
18 |
-
|
19 |
-
if ( is_multisite() ) {
|
20 |
-
$blogs = $wpdb->get_results( "SELECT blog_id FROM {$wpdb->blogs}", ARRAY_A );
|
21 |
-
|
22 |
-
if ( $blogs ) {
|
23 |
-
foreach ( $blogs as $blog ) {
|
24 |
-
switch_to_blog( $blog['blog_id'] );
|
25 |
-
|
26 |
-
delete_option( 'wpzerospam' );
|
27 |
-
delete_option( 'wpzerospam_key' );
|
28 |
-
delete_option( 'wpzerospam_honeypot' );
|
29 |
-
delete_option( 'wpzerospam_db_version' );
|
30 |
-
delete_option( 'wpzerospam_update_version' );
|
31 |
-
|
32 |
-
foreach ( $wordpress_zero_spam->tables as $key => $table ) {
|
33 |
-
$wpdb->query( "DROP TABLE IF EXISTS $table" );
|
34 |
-
}
|
35 |
-
}
|
36 |
-
restore_current_blog();
|
37 |
-
}
|
38 |
-
} else {
|
39 |
-
delete_option( 'wpzerospam' );
|
40 |
-
delete_option( 'wpzerospam_key' );
|
41 |
-
delete_option( 'wpzerospam_honeypot' );
|
42 |
-
delete_option( 'wpzerospam_db_version' );
|
43 |
-
delete_option( 'wpzerospam_update_version' );
|
44 |
-
|
45 |
-
foreach ( $wordpress_zero_spam->tables as $key => $table ) {
|
46 |
-
$wpdb->query( "DROP TABLE IF EXISTS $table" );
|
47 |
-
}
|
48 |
-
}
|
49 |
-
}
|
50 |
-
register_uninstall_hook( WORDPRESS_ZERO_SPAM, 'wpzerospam_uninstall' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/updates.php
DELETED
@@ -1,48 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Contains plugin updates
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.0.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Check if any updates should be preformed
|
11 |
-
*/
|
12 |
-
add_action( 'init', function() {
|
13 |
-
global $wpdb;
|
14 |
-
$update_version = get_option( 'wpzerospam_update_version' );
|
15 |
-
|
16 |
-
if ( ! $update_version ) {
|
17 |
-
// Clear the blacklist.
|
18 |
-
$wpdb->query( "TRUNCATE TABLE " . wpzerospam_tables( 'blacklist' ) );
|
19 |
-
update_option( 'wpzerospam_update_version', '1' );
|
20 |
-
}
|
21 |
-
});
|
22 |
-
|
23 |
-
|
24 |
-
/**
|
25 |
-
* Fixes issue with upgrade from 3 to 4
|
26 |
-
*
|
27 |
-
* @since 4.2.0
|
28 |
-
*/
|
29 |
-
add_action( 'admin_init', function() {
|
30 |
-
if( ! function_exists( 'is_plugin_active' ) ) {
|
31 |
-
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
32 |
-
}
|
33 |
-
|
34 |
-
// Deactive deprecated versions of the plugin & activate the new one
|
35 |
-
if (
|
36 |
-
is_plugin_active( 'zero-spam/zero-spam.php' ) &&
|
37 |
-
function_exists( 'deactivate_plugins' )
|
38 |
-
) {
|
39 |
-
deactivate_plugins( 'zero-spam/zero-spam.php', false, true );
|
40 |
-
}
|
41 |
-
|
42 |
-
if (
|
43 |
-
! is_plugin_active( 'zero-spam/wordpress-zero-spam.php' ) &&
|
44 |
-
function_exists( 'activate_plugin' )
|
45 |
-
) {
|
46 |
-
activate_plugin( 'zero-spam/wordpress-zero-spam.php', '', true );
|
47 |
-
}
|
48 |
-
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/utilities.php
DELETED
@@ -1,309 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Utility helpers
|
4 |
-
*
|
5 |
-
* Helpers functions to return data vs. altering it or doing anything with it.
|
6 |
-
*
|
7 |
-
* @package WordPressZeroSpam
|
8 |
-
* @since 4.9.3
|
9 |
-
* @link https://benmarshall.me/wordpress-zero-spam/
|
10 |
-
*/
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Locations helper
|
14 |
-
*/
|
15 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'inc/locations.php';
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Outputs a honeypot field
|
19 |
-
*
|
20 |
-
* @since 4.9.9
|
21 |
-
*
|
22 |
-
* @return string Returns a HTML honeypot field.
|
23 |
-
*/
|
24 |
-
if ( ! function_exists( 'wpzerospam_honeypot_field' ) ) {
|
25 |
-
function wpzerospam_honeypot_field() {
|
26 |
-
return '<input type="text" name="' . wpzerospam_get_honeypot() . '" value="" style="display: none !important;" />';
|
27 |
-
}
|
28 |
-
}
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Get the user's current URL
|
32 |
-
*/
|
33 |
-
if ( ! function_exists( 'wpzerospam_current_url' ) ) {
|
34 |
-
function wpzerospam_current_url() {
|
35 |
-
$url = [];
|
36 |
-
|
37 |
-
$url['full'] = ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
|
38 |
-
$url = array_merge( $url, parse_url( $url['full'] ) );
|
39 |
-
|
40 |
-
// Parse the URL query string
|
41 |
-
if ( ! empty( $url['query'] ) ) {
|
42 |
-
parse_str( $url['query'], $url['query'] );
|
43 |
-
}
|
44 |
-
|
45 |
-
return $url;
|
46 |
-
}
|
47 |
-
}
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Returns the current user's IP address
|
51 |
-
*/
|
52 |
-
if ( ! function_exists( 'wpzerospam_ip' ) ) {
|
53 |
-
function wpzerospam_ip() {
|
54 |
-
if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
|
55 |
-
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
56 |
-
} elseif ( ! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
57 |
-
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
58 |
-
} elseif ( ! empty($_SERVER['HTTP_X_FORWARDED'])) {
|
59 |
-
$ip = $_SERVER['HTTP_X_FORWARDED'];
|
60 |
-
} elseif ( ! empty($_SERVER['HTTP_FORWARDED_FOR'])) {
|
61 |
-
$ip = $_SERVER['HTTP_FORWARDED_FOR'];
|
62 |
-
} elseif ( ! empty($_SERVER['HTTP_FORWARDED'])) {
|
63 |
-
$ip = $_SERVER['HTTP_FORWARDED'];
|
64 |
-
} else {
|
65 |
-
$ip = $_SERVER['REMOTE_ADDR'];
|
66 |
-
}
|
67 |
-
|
68 |
-
$ip = explode( ',', $ip );
|
69 |
-
$ip = trim( $ip[0] );
|
70 |
-
|
71 |
-
if ( ! rest_is_ip_address( $ip ) ) { return false; }
|
72 |
-
|
73 |
-
return $ip;
|
74 |
-
}
|
75 |
-
}
|
76 |
-
|
77 |
-
/**
|
78 |
-
* Returns an array of tables the plugin uses
|
79 |
-
*/
|
80 |
-
if ( ! function_exists( 'wpzerospam_tables' ) ) {
|
81 |
-
function wpzerospam_tables( $key = false ) {
|
82 |
-
global $wpdb;
|
83 |
-
|
84 |
-
$tables = [
|
85 |
-
'log' => $wpdb->prefix . 'wpzerospam_log',
|
86 |
-
'blocked' => $wpdb->prefix . 'wpzerospam_blocked',
|
87 |
-
'blacklist' => $wpdb->prefix . 'wpzerospam_blacklist'
|
88 |
-
];
|
89 |
-
|
90 |
-
if ( ! $key ) {
|
91 |
-
return $tables;
|
92 |
-
} elseif( ! empty( $tables[ $key ] ) ) {
|
93 |
-
return $tables[ $key ];
|
94 |
-
}
|
95 |
-
|
96 |
-
return false;
|
97 |
-
}
|
98 |
-
}
|
99 |
-
|
100 |
-
/**
|
101 |
-
* Returns the plugin settings.
|
102 |
-
*/
|
103 |
-
if ( ! function_exists( 'wpzerospam_options' ) ) {
|
104 |
-
function wpzerospam_options() {
|
105 |
-
$options = get_option( 'wpzerospam' );
|
106 |
-
|
107 |
-
if ( empty( $options['share_data'] ) ) { $options['share_data'] = 'enabled'; }
|
108 |
-
if ( empty( $options['auto_block_ips'] ) ) { $options['auto_block_ips'] = 'disabled'; }
|
109 |
-
if ( empty( $options['auto_block_period'] ) ) { $options['auto_block_period'] = 30; }
|
110 |
-
if ( empty( $options['blocked_redirect_url'] ) ) { $options['blocked_redirect_url'] = 'https://www.google.com'; }
|
111 |
-
if ( empty( $options['spam_handler'] ) ) { $options['spam_handler'] = '403'; }
|
112 |
-
if ( empty( $options['block_handler'] ) ) { $options['block_handler'] = '403'; }
|
113 |
-
if ( empty( $options['spam_redirect_url'] ) ) { $options['spam_redirect_url'] = 'https://www.google.com'; }
|
114 |
-
if ( empty( $options['spam_message'] ) ) { $options['spam_message'] = __( 'There was a problem with your submission. Please go back and try again.', 'zero-spam' ); }
|
115 |
-
if ( empty( $options['blocked_message'] ) ) { $options['blocked_message'] = __( 'You have been blocked from visiting this site by WordPress Zero Spam due to detected spam activity.', 'zero-spam' ); }
|
116 |
-
if ( empty( $options['log_spam'] ) ) { $options['log_spam'] = 'disabled'; }
|
117 |
-
if ( empty( $options['log_blocked_ips'] ) ) { $options['log_blocked_ips'] = 'disabled'; }
|
118 |
-
if ( empty( $options['auto_block_permanently'] ) ) { $options['auto_block_permanently'] = 3; }
|
119 |
-
if ( empty( $options['botscout_api'] ) ) { $options['botscout_api'] = false; }
|
120 |
-
if ( empty( $options['ip_whitelist'] ) ) { $options['ip_whitelist'] = false; }
|
121 |
-
if ( empty( $options['api_timeout'] ) ) { $options['api_timeout'] = 5; }
|
122 |
-
if ( empty( $options['stopforumspam_confidence_min'] ) ) { $options['stopforumspam_confidence_min'] = 20; }
|
123 |
-
if ( empty( $options['botscout_count_min'] ) ) { $options['botscout_count_min'] = 5; }
|
124 |
-
if ( empty( $options['cookie_expiration'] ) ) { $options['cookie_expiration'] = 7; }
|
125 |
-
|
126 |
-
if ( empty( $options['share_detections'] ) ) {
|
127 |
-
$options['share_detections'] = 'disabled';
|
128 |
-
}
|
129 |
-
|
130 |
-
if ( empty( $options['verify_bp_registrations'] ) ) {
|
131 |
-
$options['verify_bp_registrations'] = 'enabled';
|
132 |
-
}
|
133 |
-
|
134 |
-
if ( empty( $options['verify_wpforms'] ) ) {
|
135 |
-
$options['verify_wpforms'] = 'enabled';
|
136 |
-
}
|
137 |
-
|
138 |
-
if ( empty( $options['verify_fluentform'] ) ) {
|
139 |
-
$options['verify_fluentform'] = 'enabled';
|
140 |
-
}
|
141 |
-
|
142 |
-
if ( empty( $options['verify_formidable'] ) ) {
|
143 |
-
$options['verify_formidable'] = 'enabled';
|
144 |
-
}
|
145 |
-
|
146 |
-
if ( empty( $options['stop_forum_spam'] ) ) {
|
147 |
-
$options['stop_forum_spam'] = 'enabled';
|
148 |
-
}
|
149 |
-
|
150 |
-
$options = apply_filters( 'wpzerospam_admin_options_defaults', $options );
|
151 |
-
return $options;
|
152 |
-
}
|
153 |
-
}
|
154 |
-
|
155 |
-
/**
|
156 |
-
* Query the database tables
|
157 |
-
*
|
158 |
-
* @return false/array False if not found, otherwise the blocked IP info.
|
159 |
-
*/
|
160 |
-
if ( ! function_exists( 'wpzerospam_query_table' ) ) {
|
161 |
-
function wpzerospam_query_table( $table, $args = [] ) {
|
162 |
-
global $wpdb;
|
163 |
-
|
164 |
-
// Select
|
165 |
-
$sql = 'SELECT ';
|
166 |
-
if ( ! empty( $args['select'] ) ) {
|
167 |
-
$sql .= implode( ',', $args['select'] );
|
168 |
-
} else {
|
169 |
-
$sql .= '*';
|
170 |
-
}
|
171 |
-
|
172 |
-
// From
|
173 |
-
$sql .= " from " . wpzerospam_tables( $table );
|
174 |
-
|
175 |
-
// Where
|
176 |
-
if ( ! empty( $args['where'] ) ) {
|
177 |
-
$sql .= ' WHERE ';
|
178 |
-
foreach( $args['where'] as $key => $value ) {
|
179 |
-
if ( is_int( $value ) ) {
|
180 |
-
$sql .= $key . ' = ' . $value . ' ';
|
181 |
-
} else {
|
182 |
-
$sql .= $key . ' = "' . $value . '" ';
|
183 |
-
}
|
184 |
-
}
|
185 |
-
}
|
186 |
-
|
187 |
-
// Limit
|
188 |
-
if ( ! empty( $args['limit'] ) ) {
|
189 |
-
$sql .= 'LIMIT ' . $args['limit'];
|
190 |
-
|
191 |
-
// Offset
|
192 |
-
if ( ! empty( $args['offset'] ) ) {
|
193 |
-
$sql .= ', ' . $args['offset'];
|
194 |
-
}
|
195 |
-
}
|
196 |
-
|
197 |
-
if ( ! empty( $args['limit'] ) && 1 == $args['limit'] ) {
|
198 |
-
return $wpdb->get_row( $sql, ARRAY_A );
|
199 |
-
} else {
|
200 |
-
return $wpdb->get_results( $sql, ARRAY_A );
|
201 |
-
}
|
202 |
-
}
|
203 |
-
}
|
204 |
-
|
205 |
-
/**
|
206 |
-
* Returns the geolocation information for a specified IP address.
|
207 |
-
*
|
208 |
-
* @param string $ip IP address.
|
209 |
-
* @return array/false An array with the IP address location information or
|
210 |
-
* false if not found.
|
211 |
-
*/
|
212 |
-
if ( ! function_exists( 'wpzerospam_get_ip_info' ) ) {
|
213 |
-
function wpzerospam_get_ip_info( $ip ) {
|
214 |
-
$options = wpzerospam_options();
|
215 |
-
|
216 |
-
if ( empty( $options['ipstack_api'] ) ) { return false; }
|
217 |
-
|
218 |
-
$base_url = 'http://api.ipstack.com/';
|
219 |
-
$remote_url = $base_url . $ip . '?access_key=' . $options['ipstack_api'];
|
220 |
-
$response = wp_remote_get( $remote_url, [ 'timeout' => $options['api_timeout'] ] );
|
221 |
-
|
222 |
-
if ( is_array( $response ) && ! is_wp_error( $response ) ) {
|
223 |
-
$info = json_decode( $response['body'], true );
|
224 |
-
|
225 |
-
return [
|
226 |
-
'type' => ! empty( $info['type'] ) ? sanitize_text_field( $info['type'] ) : false,
|
227 |
-
'continent_code' => ! empty( $info['continent_code'] ) ? sanitize_text_field( $info['continent_code'] ) : false,
|
228 |
-
'continent_name' => ! empty( $info['continent_name'] ) ? sanitize_text_field( $info['continent_name'] ) : false,
|
229 |
-
'country_code' => ! empty( $info['country_code'] ) ? sanitize_text_field( $info['country_code'] ) : false,
|
230 |
-
'country_name' => ! empty( $info['country_name'] ) ? sanitize_text_field( $info['country_name'] ) : false,
|
231 |
-
'region_code' => ! empty( $info['region_code'] ) ? sanitize_text_field( $info['region_code'] ) : false,
|
232 |
-
'region_name' => ! empty( $info['region_name'] ) ? sanitize_text_field( $info['region_name'] ) : false,
|
233 |
-
'city' => ! empty( $info['city'] ) ? sanitize_text_field( $info['city'] ) : false,
|
234 |
-
'zip' => ! empty( $info['zip'] ) ? sanitize_text_field( $info['zip'] ) : false,
|
235 |
-
'latitude' => ! empty( $info['latitude'] ) ? sanitize_text_field( $info['latitude'] ) : false,
|
236 |
-
'longitude' => ! empty( $info['longitude'] ) ? sanitize_text_field( $info['longitude'] ) : false,
|
237 |
-
'flag' => ! empty( $info['location']['country_flag'] ) ? sanitize_text_field( $info['location']['country_flag'] ) : false,
|
238 |
-
];
|
239 |
-
}
|
240 |
-
|
241 |
-
return false;
|
242 |
-
}
|
243 |
-
}
|
244 |
-
|
245 |
-
/**
|
246 |
-
* Returns the human-readable spam type or an array of available spam types.
|
247 |
-
*
|
248 |
-
* @param string $type_key The key of the type that should be returned.
|
249 |
-
* @return string/array The human-readable type name or an array of all the
|
250 |
-
* available types.
|
251 |
-
*/
|
252 |
-
if ( ! function_exists( 'wpzerospam_types' ) ) {
|
253 |
-
function wpzerospam_types( $type_key = false ) {
|
254 |
-
$types = apply_filters( 'wpzerospam_types', [ 'blocked' => __( 'Access Blocked', 'wpzerospam' ) ] );
|
255 |
-
|
256 |
-
if ( $type_key ) {
|
257 |
-
if ( ! empty( $types[ $type_key ] ) ) {
|
258 |
-
return $types[ $type_key ];
|
259 |
-
}
|
260 |
-
|
261 |
-
return $type_key;
|
262 |
-
}
|
263 |
-
|
264 |
-
return $types;
|
265 |
-
}
|
266 |
-
}
|
267 |
-
|
268 |
-
/**
|
269 |
-
* Checks if an IP is blocked
|
270 |
-
*
|
271 |
-
* @param string IP address to check.
|
272 |
-
* @return boolean/array False is not blocked, otherwise an array with the
|
273 |
-
* blocked IP information.
|
274 |
-
*/
|
275 |
-
if ( ! function_exists( 'wpzerospam_is_blocked' ) ) {
|
276 |
-
function wpzerospam_is_blocked( $ip ) {
|
277 |
-
$blocked_ip = wpzerospam_query_table( 'blocked', [
|
278 |
-
'select' => [
|
279 |
-
'blocked_type',
|
280 |
-
'start_block',
|
281 |
-
'end_block',
|
282 |
-
'reason',
|
283 |
-
'attempts'
|
284 |
-
],
|
285 |
-
'where' => [ 'user_ip' => $ip ],
|
286 |
-
'limit' => 1
|
287 |
-
]);
|
288 |
-
|
289 |
-
if ( $blocked_ip ) {
|
290 |
-
if ( 'permanent' == $blocked_ip['blocked_type'] ) {
|
291 |
-
// Permanently blocked
|
292 |
-
return $blocked_ip;
|
293 |
-
} else {
|
294 |
-
// Temporarily blocked
|
295 |
-
$current_datetime = current_time( 'timestamp' );
|
296 |
-
$start_block = strtotime( $blocked_ip['start_block'] );
|
297 |
-
$end_block = strtotime( $blocked_ip['end_block'] );
|
298 |
-
if (
|
299 |
-
$current_datetime >= $start_block &&
|
300 |
-
$current_datetime < $end_block
|
301 |
-
) {
|
302 |
-
return $blocked_ip;
|
303 |
-
}
|
304 |
-
}
|
305 |
-
}
|
306 |
-
|
307 |
-
return false;
|
308 |
-
}
|
309 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/class-autoloader.php
ADDED
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Autoloader class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam;
|
9 |
+
|
10 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
11 |
+
defined( 'ABSPATH' ) || die();
|
12 |
+
|
13 |
+
/**
|
14 |
+
* WordPress Zero Spam autoloader.
|
15 |
+
*
|
16 |
+
* WordPress Zero Spam autoloader handler class is responsible for loading the
|
17 |
+
* different classes needed to run the plugin.
|
18 |
+
*
|
19 |
+
* @since 5.0.0
|
20 |
+
*/
|
21 |
+
class Autoloader {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Default path for autoloader.
|
25 |
+
*
|
26 |
+
* @var string
|
27 |
+
*/
|
28 |
+
private static $default_path;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Default namespace for autoloader.
|
32 |
+
*
|
33 |
+
* @var string
|
34 |
+
*/
|
35 |
+
private static $default_namespace;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Run autoloader.
|
39 |
+
*
|
40 |
+
* Register a function as `__autoload()` implementation.
|
41 |
+
*
|
42 |
+
* @param string $default_path
|
43 |
+
* @param string $default_namespace
|
44 |
+
*
|
45 |
+
* @since 5.0.0
|
46 |
+
* @access public
|
47 |
+
* @static
|
48 |
+
*/
|
49 |
+
public static function run( $default_path = '', $default_namespace = '' ) {
|
50 |
+
if ( '' === $default_path ) {
|
51 |
+
$default_path = ZEROSPAM_PATH;
|
52 |
+
}
|
53 |
+
|
54 |
+
if ( '' === $default_namespace ) {
|
55 |
+
$default_namespace = __NAMESPACE__;
|
56 |
+
}
|
57 |
+
|
58 |
+
self::$default_path = $default_path;
|
59 |
+
self::$default_namespace = $default_namespace;
|
60 |
+
|
61 |
+
spl_autoload_register( array( __CLASS__, 'autoload' ) );
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Load class.
|
66 |
+
*
|
67 |
+
* For a given class name, require the class file.
|
68 |
+
*
|
69 |
+
* @since 5.0.0
|
70 |
+
* @access private
|
71 |
+
* @static
|
72 |
+
*
|
73 |
+
* @param string $relative_class_name Class name.
|
74 |
+
*/
|
75 |
+
private static function load_class( $relative_class_name ) {
|
76 |
+
$filename = strtolower(
|
77 |
+
preg_replace(
|
78 |
+
array( '/_/', '/\\\/' ),
|
79 |
+
array( '', DIRECTORY_SEPARATOR ),
|
80 |
+
$relative_class_name
|
81 |
+
)
|
82 |
+
);
|
83 |
+
|
84 |
+
$filename_parts = explode( '/', $filename );
|
85 |
+
$last_part = array_key_last( $filename_parts );
|
86 |
+
|
87 |
+
$filename_parts[ $last_part ] = 'class-' . $filename_parts[ $last_part ];
|
88 |
+
|
89 |
+
$filename = implode( '/', $filename_parts );
|
90 |
+
$filename = self::$default_path . $filename . '.php';
|
91 |
+
|
92 |
+
if ( is_readable( $filename ) ) {
|
93 |
+
require $filename;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Autoload.
|
99 |
+
*
|
100 |
+
* For a given class, check if it exist and load it.
|
101 |
+
*
|
102 |
+
* @since 5.0.0
|
103 |
+
* @access private
|
104 |
+
* @static
|
105 |
+
*
|
106 |
+
* @param string $class Class name.
|
107 |
+
*/
|
108 |
+
private static function autoload( $class ) {
|
109 |
+
if ( 0 !== strpos( $class, self::$default_namespace . '\\' ) ) {
|
110 |
+
return;
|
111 |
+
}
|
112 |
+
|
113 |
+
$relative_class_name = preg_replace( '/^' . self::$default_namespace . '\\\/', '', $class );
|
114 |
+
|
115 |
+
$final_class_name = self::$default_namespace . '\\' . $relative_class_name;
|
116 |
+
|
117 |
+
if ( ! class_exists( $final_class_name ) ) {
|
118 |
+
self::load_class( $relative_class_name );
|
119 |
+
}
|
120 |
+
}
|
121 |
+
}
|
includes/class-db.php
ADDED
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* DB class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Includes;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
|
12 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
13 |
+
defined( 'ABSPATH' ) || die();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* WordPress Zero Spam DB class.
|
17 |
+
*
|
18 |
+
* @since 5.0.0
|
19 |
+
*/
|
20 |
+
class DB {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Current DB version.
|
24 |
+
*/
|
25 |
+
const DB_VERSION = '0.4';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* DB tables.
|
29 |
+
*
|
30 |
+
* @since 5.0.0
|
31 |
+
* @access public
|
32 |
+
*
|
33 |
+
* @var Assets_Manager
|
34 |
+
*/
|
35 |
+
public static $tables = array(
|
36 |
+
'log' => 'wpzerospam_log',
|
37 |
+
'blocked' => 'wpzerospam_blocked',
|
38 |
+
'blacklist' => 'wpzerospam_blacklist',
|
39 |
+
);
|
40 |
+
|
41 |
+
/**
|
42 |
+
* DB constructor.
|
43 |
+
*
|
44 |
+
* @since 5.0.0
|
45 |
+
* @access public
|
46 |
+
*/
|
47 |
+
public function __construct() {
|
48 |
+
add_action( 'init', array( $this, 'update' ) );
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Installs & updates the DB tables.
|
53 |
+
*
|
54 |
+
* @since 5.0.0
|
55 |
+
* @access public
|
56 |
+
*/
|
57 |
+
public function update() {
|
58 |
+
if ( self::DB_VERSION !== get_site_option( 'zerospam_db_version' ) ) {
|
59 |
+
global $wpdb;
|
60 |
+
|
61 |
+
$charset_collate = $wpdb->get_charset_collate();
|
62 |
+
$installed_db_version = get_option( 'zerospam_db_version' );
|
63 |
+
|
64 |
+
$sql = 'CREATE TABLE ' . $wpdb->prefix . self::$tables['log'] . " (
|
65 |
+
log_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
66 |
+
log_type VARCHAR(255) NOT NULL,
|
67 |
+
user_ip VARCHAR(39) NOT NULL,
|
68 |
+
date_recorded DATETIME NOT NULL,
|
69 |
+
page_url VARCHAR(255) NULL DEFAULT NULL,
|
70 |
+
submission_data LONGTEXT NULL DEFAULT NULL,
|
71 |
+
country VARCHAR(2) NULL DEFAULT NULL,
|
72 |
+
country_name VARCHAR(255) NULL DEFAULT NULL,
|
73 |
+
region VARCHAR(255) NULL DEFAULT NULL,
|
74 |
+
region_name VARCHAR(255) NULL DEFAULT NULL,
|
75 |
+
city VARCHAR(255) NULL DEFAULT NULL,
|
76 |
+
zip VARCHAR(10) NULL DEFAULT NULL,
|
77 |
+
latitude VARCHAR(255) NULL DEFAULT NULL,
|
78 |
+
longitude VARCHAR(255) NULL DEFAULT NULL,
|
79 |
+
PRIMARY KEY (`log_id`)) $charset_collate;";
|
80 |
+
|
81 |
+
$sql .= 'CREATE TABLE ' . $wpdb->prefix . self::$tables['blocked'] . " (
|
82 |
+
blocked_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
83 |
+
blocked_type ENUM('permanent','temporary') NOT NULL DEFAULT 'temporary',
|
84 |
+
user_ip VARCHAR(39) NOT NULL,
|
85 |
+
blocked_key VARCHAR(255) NULL,
|
86 |
+
key_type ENUM('ip','email') NOT NULL DEFAULT 'ip',
|
87 |
+
date_added DATETIME NOT NULL,
|
88 |
+
start_block DATETIME NULL DEFAULT NULL,
|
89 |
+
end_block DATETIME NULL DEFAULT NULL,
|
90 |
+
reason VARCHAR(255) NULL DEFAULT NULL,
|
91 |
+
PRIMARY KEY (`blocked_id`)) $charset_collate;";
|
92 |
+
|
93 |
+
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
94 |
+
dbDelta( $sql );
|
95 |
+
|
96 |
+
update_option( 'zerospam_db_version', self::DB_VERSION );
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Adds/returns a blocked IP.
|
102 |
+
*
|
103 |
+
* @since 5.0.0
|
104 |
+
* @access public
|
105 |
+
*/
|
106 |
+
public static function blocked( $record, $key_type = false ) {
|
107 |
+
global $wpdb;
|
108 |
+
|
109 |
+
if ( is_array( $record ) ) {
|
110 |
+
$blocked = false;
|
111 |
+
|
112 |
+
// Add or update a record.
|
113 |
+
if ( ! empty( $record['blocked_id'] ) ) {
|
114 |
+
// Update a record.
|
115 |
+
$blocked['blocked_id'] = $record['blocked_id'];
|
116 |
+
} elseif ( ! empty( $record['user_ip'] ) ) {
|
117 |
+
// Add a record, but first check if IP is unique.
|
118 |
+
$blocked = self::blocked( $record['user_ip'] );
|
119 |
+
} elseif ( ! empty( $record['key_type'] ) && ! empty( $record['blocked_key'] ) ) {
|
120 |
+
// Add a record, but first check if key is unique.
|
121 |
+
$blocked = self::blocked( $record['blocked_key'], $record['key_type'] );
|
122 |
+
}
|
123 |
+
|
124 |
+
if ( $blocked ) {
|
125 |
+
// Update the record.
|
126 |
+
$record['last_updated'] = current_time( 'mysql' );
|
127 |
+
return $wpdb->update(
|
128 |
+
$wpdb->prefix . self::$tables['blocked'],
|
129 |
+
$record,
|
130 |
+
array(
|
131 |
+
'blocked_id' => $blocked['blocked_id'],
|
132 |
+
)
|
133 |
+
);
|
134 |
+
} else {
|
135 |
+
// Insert the record.
|
136 |
+
$record['date_added'] = current_time( 'mysql' );
|
137 |
+
return $wpdb->insert( $wpdb->prefix . self::$tables['blocked'], $record );
|
138 |
+
}
|
139 |
+
} elseif ( $key_type ) {
|
140 |
+
// Get record by key.
|
141 |
+
return $wpdb->get_row( 'SELECT * FROM ' . $wpdb->prefix . self::$tables['blocked'] . ' WHERE key_type = "' . $key_type . '" AND blocked_key = "' . $record . '"', ARRAY_A );
|
142 |
+
} elseif ( is_int( $record ) ) {
|
143 |
+
// Get record by ID.
|
144 |
+
return $wpdb->get_row( 'SELECT * FROM ' . $wpdb->prefix . self::$tables['blocked'] . ' WHERE blocked_id = "' . $record . '"', ARRAY_A );
|
145 |
+
} elseif ( rest_is_ip_address( $record ) ) {
|
146 |
+
// Get record by IP.
|
147 |
+
return $wpdb->get_row( 'SELECT * FROM ' . $wpdb->prefix . self::$tables['blocked'] . ' WHERE user_ip = "' . $record . '"', ARRAY_A );
|
148 |
+
}
|
149 |
+
|
150 |
+
return false;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Log.
|
155 |
+
*
|
156 |
+
* @since 5.0.0
|
157 |
+
* @access public
|
158 |
+
*/
|
159 |
+
public static function log( $type, $details ) {
|
160 |
+
global $wpdb;
|
161 |
+
|
162 |
+
$page_url = ZeroSpam\Core\Utilities::current_url();
|
163 |
+
$extension = substr( $page_url, strrpos( $page_url, '.' ) + 1 );
|
164 |
+
$ignore = array( 'map', 'js', 'css' );
|
165 |
+
if ( in_array( $extension, $ignore, true ) ) {
|
166 |
+
// Ignore assets.
|
167 |
+
return false;
|
168 |
+
}
|
169 |
+
|
170 |
+
$record = array(
|
171 |
+
'user_ip' => ZeroSpam\Core\User::get_ip(),
|
172 |
+
'log_type' => $type,
|
173 |
+
'date_recorded' => current_time( 'mysql' ),
|
174 |
+
'page_url' => $page_url,
|
175 |
+
'submission_data' => wp_json_encode( $details ),
|
176 |
+
);
|
177 |
+
|
178 |
+
$record = apply_filters( 'zerospam_log_record', $record );
|
179 |
+
|
180 |
+
return $wpdb->insert( $wpdb->prefix . self::$tables['log'], $record );
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Delete a record.
|
185 |
+
*
|
186 |
+
* @since 5.0.0
|
187 |
+
* @access public
|
188 |
+
*/
|
189 |
+
public static function delete( $table, $key, $value ) {
|
190 |
+
global $wpdb;
|
191 |
+
|
192 |
+
$wpdb->delete(
|
193 |
+
$wpdb->prefix . self::$tables[ $table ],
|
194 |
+
array(
|
195 |
+
$key => $value,
|
196 |
+
)
|
197 |
+
);
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Delete everything in a table.
|
202 |
+
*
|
203 |
+
* @since 5.0.0
|
204 |
+
* @access public
|
205 |
+
*/
|
206 |
+
public static function delete_all( $table ) {
|
207 |
+
global $wpdb;
|
208 |
+
|
209 |
+
$wpdb->query( "TRUNCATE TABLE " . $wpdb->prefix . self::$tables[ $table ] );
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Query the DB.
|
214 |
+
*
|
215 |
+
* @since 5.0.0
|
216 |
+
* @access public
|
217 |
+
*/
|
218 |
+
public static function query( $table, $args = array() ) {
|
219 |
+
global $wpdb;
|
220 |
+
|
221 |
+
if ( ! array_key_exists( $table, self::$tables ) ) {
|
222 |
+
return false;
|
223 |
+
}
|
224 |
+
|
225 |
+
$sql = 'SELECT';
|
226 |
+
|
227 |
+
if ( ! empty( $args['select'] ) ) {
|
228 |
+
$sql .= implode( ', ', $args['select'] );
|
229 |
+
} else {
|
230 |
+
$sql .= ' * ';
|
231 |
+
}
|
232 |
+
|
233 |
+
$sql .= 'FROM ' . $wpdb->prefix . self::$tables[ $table ];
|
234 |
+
|
235 |
+
if ( ! empty( $args['where'] ) ) {
|
236 |
+
$sql .= ' WHERE ';
|
237 |
+
|
238 |
+
$where_stmt = '';
|
239 |
+
foreach ( $args['where'] as $key => $where ) {
|
240 |
+
if ( $where_stmt ) {
|
241 |
+
$where_stmt .= ' AND ';
|
242 |
+
}
|
243 |
+
|
244 |
+
$where_stmt .= $key;
|
245 |
+
|
246 |
+
if ( ! empty( $where['relation'] ) ) {
|
247 |
+
$where_stmt .= ' ' . $where['relation'] . ' ';
|
248 |
+
} else {
|
249 |
+
$where_stmt .= ' = ';
|
250 |
+
}
|
251 |
+
|
252 |
+
if ( is_numeric( $where['value'] ) ) {
|
253 |
+
$where_stmt .= $where['value'];
|
254 |
+
} else {
|
255 |
+
$where_stmt .= '"' . $where['value'] . '"';
|
256 |
+
}
|
257 |
+
}
|
258 |
+
|
259 |
+
$sql .= $where_stmt;
|
260 |
+
}
|
261 |
+
|
262 |
+
if ( ! empty( $args['orderby'] ) ) {
|
263 |
+
$sql .= ' ORDER BY ' . $args['orderby'];
|
264 |
+
}
|
265 |
+
|
266 |
+
if ( ! empty( $args['order'] ) ) {
|
267 |
+
$sql .= ' ' . $args['order'];
|
268 |
+
}
|
269 |
+
|
270 |
+
if ( ! empty( $args['limit'] ) ) {
|
271 |
+
$sql .= ' LIMIT ' . $args['limit'];
|
272 |
+
}
|
273 |
+
|
274 |
+
if ( ! empty( $args['offset'] ) ) {
|
275 |
+
$sql .= ' OFFSET ' . $args['offset'];
|
276 |
+
}
|
277 |
+
|
278 |
+
return $wpdb->get_results( $sql, ARRAY_A );
|
279 |
+
}
|
280 |
+
}
|
includes/class-plugin.php
ADDED
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Main plugin class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam;
|
9 |
+
|
10 |
+
use ZeroSpam\Includes\DB;
|
11 |
+
use ZeroSpam\Core\Access;
|
12 |
+
use ZeroSpam\Core\User;
|
13 |
+
use ZeroSpam\Core\Admin\Admin;
|
14 |
+
use ZeroSpam\Modules\BotScout;
|
15 |
+
use ZeroSpam\Modules\StopForumSpam;
|
16 |
+
use ZeroSpam\Modules\ipstack;
|
17 |
+
use ZeroSpam\Modules\Google;
|
18 |
+
use ZeroSpam\Modules\Zero_Spam;
|
19 |
+
use ZeroSpam\Modules\Registration\Registration;
|
20 |
+
use ZeroSpam\Modules\Comments\Comments;
|
21 |
+
use ZeroSpam\Modules\ContactForm7\ContactForm7;
|
22 |
+
|
23 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
24 |
+
defined( 'ABSPATH' ) || die();
|
25 |
+
|
26 |
+
/**
|
27 |
+
* WordPress Zero Spam plugin.
|
28 |
+
*
|
29 |
+
* The main plugin handler class is responsible for initializing WordPress Zero
|
30 |
+
* Spam. The class registers and all the components required to run the plugin.
|
31 |
+
*
|
32 |
+
* @since 5.0.0
|
33 |
+
*/
|
34 |
+
class Plugin {
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Instance.
|
38 |
+
*
|
39 |
+
* Holds the plugin instance.
|
40 |
+
*
|
41 |
+
* @since 5.0.0
|
42 |
+
* @access public
|
43 |
+
* @static
|
44 |
+
*
|
45 |
+
* @var Plugin
|
46 |
+
*/
|
47 |
+
public static $instance = null;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Plugin constructor.
|
51 |
+
*
|
52 |
+
* Initializing WordPress Zero Spam plugin.
|
53 |
+
*
|
54 |
+
* @since 5.0.0
|
55 |
+
* @access private
|
56 |
+
*/
|
57 |
+
private function __construct() {
|
58 |
+
$this->register_autoloader();
|
59 |
+
|
60 |
+
add_action( 'init', array( $this, 'init' ), 0 );
|
61 |
+
add_filter( 'zerospam_types', array( $this, 'types' ), 10, 1 );
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Register autoloader.
|
66 |
+
*
|
67 |
+
* WordPress Zero Spam autoloader loads all the classes needed to run the
|
68 |
+
* plugin.
|
69 |
+
*
|
70 |
+
* @since 5.0.0
|
71 |
+
* @access private
|
72 |
+
*/
|
73 |
+
private function register_autoloader() {
|
74 |
+
require_once ZEROSPAM_PATH . 'includes/class-autoloader.php';
|
75 |
+
|
76 |
+
Autoloader::run();
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Instance.
|
81 |
+
*
|
82 |
+
* Ensures only one instance of the plugin class is loaded or can be loaded.
|
83 |
+
*
|
84 |
+
* @since 1.0.0
|
85 |
+
* @access public
|
86 |
+
* @static
|
87 |
+
*
|
88 |
+
* @return Plugin An instance of the class.
|
89 |
+
*/
|
90 |
+
public static function instance() {
|
91 |
+
if ( is_null( self::$instance ) ) {
|
92 |
+
self::$instance = new self();
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Elementor loaded.
|
96 |
+
*
|
97 |
+
* Fires when Elementor was fully loaded and instantiated.
|
98 |
+
*
|
99 |
+
* @since 1.0.0
|
100 |
+
*/
|
101 |
+
do_action( 'zerospam_loaded' );
|
102 |
+
}
|
103 |
+
|
104 |
+
return self::$instance;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Init.
|
109 |
+
*
|
110 |
+
* Initialize WordPress Zero Spam Plugin. Checks if the current user should be
|
111 |
+
* blocked.
|
112 |
+
*
|
113 |
+
* @since 5.0.0
|
114 |
+
* @access public
|
115 |
+
*/
|
116 |
+
public function init() {
|
117 |
+
$this->init_components();
|
118 |
+
|
119 |
+
/**
|
120 |
+
* WordPress Zero Spam init.
|
121 |
+
*
|
122 |
+
* Fires on WordPress Zero Spam init, after WordPress Zero Spam has finished
|
123 |
+
* loading but before any headers are sent.
|
124 |
+
*
|
125 |
+
* @since 5.0.0
|
126 |
+
*/
|
127 |
+
do_action( 'zerospam_init' );
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Init components.
|
132 |
+
*
|
133 |
+
* Initialize WordPress Zero Spam components. Register actions, initialize all
|
134 |
+
* the components that run WordPress Zero Spam, and if in admin page
|
135 |
+
* initialize admin components.
|
136 |
+
*
|
137 |
+
* @since 5.0.0
|
138 |
+
* @access private
|
139 |
+
*/
|
140 |
+
private function init_components() {
|
141 |
+
new DB();
|
142 |
+
new Registration();
|
143 |
+
new Comments();
|
144 |
+
|
145 |
+
include_once ABSPATH . 'wp-admin/includes/plugin.php';
|
146 |
+
if ( is_plugin_active( 'contact-form-7/wp-contact-form-7.php' ) ) {
|
147 |
+
new ContactForm7();
|
148 |
+
}
|
149 |
+
|
150 |
+
//= new BotScout();
|
151 |
+
new StopForumSpam();
|
152 |
+
new ipstack();
|
153 |
+
new Zero_Spam();
|
154 |
+
|
155 |
+
if (
|
156 |
+
! is_admin() &&
|
157 |
+
is_main_query()
|
158 |
+
) {
|
159 |
+
new Access();
|
160 |
+
}
|
161 |
+
|
162 |
+
if ( is_admin() ) {
|
163 |
+
new Google();
|
164 |
+
new Admin();
|
165 |
+
}
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Add to the types array.
|
170 |
+
*
|
171 |
+
* @since 5.0.0
|
172 |
+
* @access public
|
173 |
+
*/
|
174 |
+
public function types( $types ) {
|
175 |
+
$types['blocked'] = __( 'Blocked', 'zerospam' );
|
176 |
+
|
177 |
+
return $types;
|
178 |
+
}
|
179 |
+
}
|
180 |
+
|
181 |
+
Plugin::instance();
|
includes/templates/admin-block-ip.php
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Block IP.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
* @since 5.0.0
|
7 |
+
*/
|
8 |
+
?>
|
9 |
+
|
10 |
+
<form method="post" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>">
|
11 |
+
<?php wp_nonce_field( 'zerospam', 'zerospam' ); ?>
|
12 |
+
<input type="hidden" name="action" value="add_blocked_ip" />
|
13 |
+
<input type="hidden" name="redirect" value="<?php echo esc_url( ZeroSpam\Core\Utilities::current_url() ); ?>" />
|
14 |
+
|
15 |
+
<label for="blocked-ip">
|
16 |
+
<?php _e( 'IP Address', 'zerospam' ); ?>
|
17 |
+
<input
|
18 |
+
type="text"
|
19 |
+
name="blocked_ip"
|
20 |
+
value="<?php if( ! empty( $_REQUEST['ip'] ) ) : echo esc_attr( $_REQUEST['ip'] ); endif; ?>"
|
21 |
+
placeholder="e.g. xxx.xxx.x.x"
|
22 |
+
/>
|
23 |
+
</label>
|
24 |
+
|
25 |
+
<label for="blocked-type"><?php _e( 'Type', 'zerospam' ); ?>
|
26 |
+
<select id="blocked-type" name="blocked_type">
|
27 |
+
<option value="temporary"><?php _e( 'Temporary', 'zerospam' ); ?></option>
|
28 |
+
<option value="permanent"><?php _e( 'Permanent', 'zerospam' ); ?></option>
|
29 |
+
</select>
|
30 |
+
</label>
|
31 |
+
|
32 |
+
<label for="blocked-reason">
|
33 |
+
<?php _e( 'Reason', 'zerospam' ); ?>
|
34 |
+
<input type="text" id="blocked-reason" name="blocked_reason" value="" placeholder="<?php _e( 'e.g. Spammed form', 'zerospam' ); ?>" />
|
35 |
+
</label>
|
36 |
+
|
37 |
+
<label for="blocked-start-date">
|
38 |
+
<?php esc_html_e( 'Start Date', 'zerospam' ); ?>
|
39 |
+
<input
|
40 |
+
type="datetime-local"
|
41 |
+
id="blocked-start-date"
|
42 |
+
name="blocked_start_date"
|
43 |
+
value=""
|
44 |
+
placeholder="<?php echo esc_attr( __( 'Optional', 'zerospam' ) ); ?>"
|
45 |
+
/>
|
46 |
+
</label>
|
47 |
+
|
48 |
+
<label for="blocked-end-date">
|
49 |
+
<?php _e( 'End Date', 'zerospam' ); ?>
|
50 |
+
<input type="datetime-local" id="blocked-end-date" name="blocked_end_date" value="" placeholder="<?php _e( 'Optional', 'zerospam' ); ?>" />
|
51 |
+
</label>
|
52 |
+
|
53 |
+
<input type="submit" class="button button-primary" value="<?php _e( 'Add/Update Blocked IP', 'zerospam' ); ?>" />
|
54 |
+
|
55 |
+
</form>
|
includes/templates/admin-callout.php
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Callout.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
* @since 5.0.0
|
7 |
+
*/
|
8 |
+
?>
|
9 |
+
|
10 |
+
<div class="zerospam-callout">
|
11 |
+
<div class="zerospam-callout-col">
|
12 |
+
<h2>
|
13 |
+
<?php
|
14 |
+
echo sprintf(
|
15 |
+
wp_kses(
|
16 |
+
__( 'Help support the <a href="%s" target="_blank" rel="noopener noreferrer">WordPress Zero Spam</a> plugin.', 'zerospam' ),
|
17 |
+
array(
|
18 |
+
'a' => array(
|
19 |
+
'target' => array(),
|
20 |
+
'href' => array(),
|
21 |
+
'rel' => array(),
|
22 |
+
),
|
23 |
+
)
|
24 |
+
),
|
25 |
+
esc_url( 'https://benmarshall.me/wordpress-zero-spam/?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=donation' )
|
26 |
+
);
|
27 |
+
?>
|
28 |
+
</h2>
|
29 |
+
<p>
|
30 |
+
<?php
|
31 |
+
echo sprintf(
|
32 |
+
wp_kses(
|
33 |
+
__( 'Support the continued development of the WPZS by <a href="%s" target="_blank" rel="noopener noreferrer">donating today</a>. Donation goes towards the time it takes to develop new features & updates, but also helps provide pro bono work for nonprofits.', 'zerospam' ),
|
34 |
+
array(
|
35 |
+
'a' => array(
|
36 |
+
'target' => array(),
|
37 |
+
'href' => array(),
|
38 |
+
'rel' => array(),
|
39 |
+
),
|
40 |
+
)
|
41 |
+
),
|
42 |
+
esc_url( 'https://benmarshall.me/donate/?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=donation' )
|
43 |
+
);
|
44 |
+
?>
|
45 |
+
</p>
|
46 |
+
<p>
|
47 |
+
<?php
|
48 |
+
echo sprintf(
|
49 |
+
wp_kses(
|
50 |
+
__( '<strong>Integrate Zero Spam in any application</strong> with the <a href="%s" target="_blank" rel="noopener noreferrer">Zero Spam Blacklist API</a>.', 'zerospam' ),
|
51 |
+
array(
|
52 |
+
'strong' => array(),
|
53 |
+
'a' => array(
|
54 |
+
'target' => array(),
|
55 |
+
'href' => array(),
|
56 |
+
'rel' => array(),
|
57 |
+
),
|
58 |
+
)
|
59 |
+
),
|
60 |
+
esc_url( 'https://zerospam.org/spam-blacklist-api/' )
|
61 |
+
);
|
62 |
+
?>
|
63 |
+
</p>
|
64 |
+
</div>
|
65 |
+
<div class="zerospam-callout-col zerospam-callout-actions">
|
66 |
+
<ul>
|
67 |
+
<li><a href="https://github.com/bmarshall511/wordpress-zero-spam/issues" target="_blank"><?php _e( 'Submit Bug/Feature Request', 'zerospam' ); ?></a></li>
|
68 |
+
<li><a href="https://twitter.com/ZeroSpamOrg" target="_blank"><?php _e( 'Follow us on Twitter', 'zerospam' ); ?></a></li>
|
69 |
+
<li><a href="https://www.facebook.com/zerospamorg/" target="_blank"><?php _e( 'Like us on Facebook', 'zerospam' ); ?></a></li>
|
70 |
+
<li><a href="https://benmarshall.me/donate?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=admin" target="_blank"><?php _e( 'Show your Support — Donate', 'zerospam' ); ?></a></li>
|
71 |
+
</ul>
|
72 |
+
</div>
|
73 |
+
</div>
|
includes/templates/admin-modal-details.php
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Modal details.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
* @since 5.0.0
|
7 |
+
*/
|
8 |
+
?>
|
9 |
+
|
10 |
+
<div class="zerospam-modal-details">
|
11 |
+
<div class="zerospam-modal-title">
|
12 |
+
<h3>ID #<?php echo $item['log_id']; ?></h3>
|
13 |
+
</div>
|
14 |
+
<div class="zerospam-modal-subtitle">
|
15 |
+
<?php echo gmdate( 'M j, Y g:ia' , strtotime( $item[ 'date_recorded' ] ) ); ?>
|
16 |
+
</div>
|
17 |
+
|
18 |
+
<ul class="zerospam-modal-list">
|
19 |
+
<li>
|
20 |
+
<strong><?php echo __( 'IP Address', 'zerospam' ); ?></strong>
|
21 |
+
<span><?php echo '<a href="https://www.zerospam.org/ip-lookup/' . urlencode( $item['user_ip'] ) .'" target="_blank" rel="noopener noreferrer">' . $item['user_ip'] . '</a>'; ?></span>
|
22 |
+
</li>
|
23 |
+
<li>
|
24 |
+
<strong><?php echo __( 'Type', 'zerospam' ); ?></strong>
|
25 |
+
<span><?php echo $item['log_type']; ?></span>
|
26 |
+
</li>
|
27 |
+
</ul>
|
28 |
+
|
29 |
+
<button class="button action zerospam-block-trigger" data-id="<?php echo esc_attr( $item['log_id'] ); ?>"><?php _e( 'Block IP', 'zerospam' ); ?></button>
|
30 |
+
|
31 |
+
<?php
|
32 |
+
if ( ! empty( $item['latitude'] ) && ! empty( $item['longitude'] ) ) {
|
33 |
+
?>
|
34 |
+
<h4 class="zerospam-modal-headline"><?php echo __( 'Location', 'zerospam' ); ?></h4>
|
35 |
+
<?php
|
36 |
+
$coordinates = $item['latitude'] . ',' . $item['longitude'];
|
37 |
+
do_action( 'zerospam_google_map', $coordinates );
|
38 |
+
?>
|
39 |
+
<ul class="zerospam-modal-list">
|
40 |
+
<?php if ( ! empty( $item['country_name'] ) || ! empty( $item['country'] ) ) : ?>
|
41 |
+
<li>
|
42 |
+
<strong><?php echo __( 'Country', 'zerospam' ); ?></strong>
|
43 |
+
<span>
|
44 |
+
<?php if ( ! empty( $item['country_name'] ) ) : ?>
|
45 |
+
<?php echo $item['country_name']; ?>
|
46 |
+
<?php endif; ?>
|
47 |
+
<?php if ( ! empty( $item['country'] ) ) : ?>
|
48 |
+
(<?php echo $item['country']; ?>)
|
49 |
+
<?php endif; ?>
|
50 |
+
</span>
|
51 |
+
</li>
|
52 |
+
<?php endif; ?>
|
53 |
+
<?php if ( ! empty( $item['region'] ) || ! empty( $item['region_name'] ) ) : ?>
|
54 |
+
<li>
|
55 |
+
<strong><?php echo __( 'Region', 'zerospam' ); ?></strong>
|
56 |
+
<span>
|
57 |
+
<?php if ( ! empty( $item['region_name'] ) ) : ?>
|
58 |
+
<?php echo $item['region_name']; ?>
|
59 |
+
<?php endif; ?>
|
60 |
+
<?php if ( ! empty( $item['region'] ) ) : ?>
|
61 |
+
(<?php echo $item['region']; ?>)
|
62 |
+
<?php endif; ?>
|
63 |
+
</span>
|
64 |
+
</li>
|
65 |
+
<?php endif; ?>
|
66 |
+
<?php if ( ! empty( $item['city'] ) ) : ?>
|
67 |
+
<li>
|
68 |
+
<strong><?php echo __( 'City', 'zerospam' ); ?></strong>
|
69 |
+
<span><?php echo $item['city']; ?>
|
70 |
+
</span>
|
71 |
+
</li>
|
72 |
+
<?php endif; ?>
|
73 |
+
<?php if ( ! empty( $item['zip'] ) ) : ?>
|
74 |
+
<li>
|
75 |
+
<strong><?php echo __( 'Zip/Postal Code', 'zerospam' ); ?></strong>
|
76 |
+
<span><?php echo $item['zip']; ?>
|
77 |
+
</span>
|
78 |
+
</li>
|
79 |
+
<?php endif; ?>
|
80 |
+
<?php if ( ! empty( $item['latitude'] ) || ! empty( $item['region_name'] ) ) : ?>
|
81 |
+
<li>
|
82 |
+
<strong><?php echo __( 'Coordinates', 'zerospam' ); ?></strong>
|
83 |
+
<span>
|
84 |
+
<?php if ( ! empty( $item['latitude'] ) ) : ?>
|
85 |
+
<?php echo $item['latitude']; ?>°,
|
86 |
+
<?php endif; ?>
|
87 |
+
<?php if ( ! empty( $item['longitude'] ) ) : ?>
|
88 |
+
<?php echo $item['longitude']; ?>°
|
89 |
+
<?php endif; ?>
|
90 |
+
</span>
|
91 |
+
</li>
|
92 |
+
<?php endif; ?>
|
93 |
+
</ul>
|
94 |
+
<?php
|
95 |
+
}
|
96 |
+
?>
|
97 |
+
|
98 |
+
<h4 class="zerospam-modal-headline"><?php echo __( 'Additional Details', 'zerospam' ); ?></h4>
|
99 |
+
<?php
|
100 |
+
if ( ! empty( $item['submission_data'] ) ) :
|
101 |
+
$submission_data = json_decode( $item['submission_data'], true );
|
102 |
+
echo '<ul class="zerospam-modal-list">';
|
103 |
+
foreach ( $submission_data as $key => $value ) :
|
104 |
+
?>
|
105 |
+
<li><strong><?php echo $key; ?></strong> <span><?php echo $value; ?></span></li>
|
106 |
+
<?php
|
107 |
+
endforeach;
|
108 |
+
echo '</ul>';
|
109 |
+
endif;
|
110 |
+
?>
|
111 |
+
</div>
|
integrations/buddypress/buddypress.php
DELETED
@@ -1,48 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Handles checking submitted BuddyPress registrations
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.1.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Add the 'bp_registration' spam type
|
11 |
-
*/
|
12 |
-
add_filter( 'wpzerospam_types', function( $types ) {
|
13 |
-
$types = array_merge( $types, [ 'bp_registration' => __( 'BuddyPress Registration', 'zero-spam' ) ] );
|
14 |
-
return $types;
|
15 |
-
});
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Validation for BuddyPress registrations
|
19 |
-
*/
|
20 |
-
if ( ! function_exists( 'wpzerospam_bp_signup_validate' ) ) {
|
21 |
-
function wpzerospam_bp_signup_validate() {
|
22 |
-
if ( is_user_logged_in() || wpzerospam_key_check() ) {
|
23 |
-
return;
|
24 |
-
}
|
25 |
-
|
26 |
-
do_action( 'wpzerospam_bp_registration_spam' );
|
27 |
-
|
28 |
-
wpzerospam_spam_detected( 'bp_registration' );
|
29 |
-
}
|
30 |
-
}
|
31 |
-
add_action( 'bp_signup_validate', 'wpzerospam_bp_signup_validate' );
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Enqueue the BuddyPress form JS
|
35 |
-
*/
|
36 |
-
if ( ! function_exists( 'wpzerospam_buddy_press' ) ) {
|
37 |
-
function wpzerospam_buddy_press() {
|
38 |
-
wp_enqueue_script(
|
39 |
-
'wpzerospam-integration-buddy-press',
|
40 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
41 |
-
'integrations/buddypress/js/buddypress.js',
|
42 |
-
[ 'wpzerospam' ],
|
43 |
-
WORDPRESS_ZERO_SPAM_VERSION,
|
44 |
-
true
|
45 |
-
);
|
46 |
-
}
|
47 |
-
}
|
48 |
-
add_action( 'bp_before_register_page', 'wpzerospam_buddy_press' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
integrations/buddypress/js/buddypress.js
DELETED
@@ -1,4 +0,0 @@
|
|
1 |
-
// Initialize WPZS on BuddyPress registration forms.
|
2 |
-
jQuery(function() {
|
3 |
-
jQuery("#buddypress #signup_form").WordPressZeroSpam();
|
4 |
-
});
|
|
|
|
|
|
|
|
integrations/comments/comments.php
DELETED
@@ -1,379 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Comment form spam detection
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.3.7
|
7 |
-
*/
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Adds admin settings for comment submission protection.
|
11 |
-
*
|
12 |
-
* @since 4.9.9
|
13 |
-
*
|
14 |
-
* @return void
|
15 |
-
*/
|
16 |
-
if ( ! function_exists( 'wpzerospam_comments_admin_fields' ) ) {
|
17 |
-
function wpzerospam_comments_admin_fields() {
|
18 |
-
// Option to strips links in comments
|
19 |
-
add_settings_field( 'strip_comment_links', __( 'Strip Comment Links', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_onsite', [
|
20 |
-
'label_for' => 'strip_comment_links',
|
21 |
-
'type' => 'checkbox',
|
22 |
-
'multi' => false,
|
23 |
-
'desc' => __( 'Spambots commonly post spam links in comments. Enable this option to strip links from comments.', 'zero-spam' ),
|
24 |
-
'options' => [
|
25 |
-
'enabled' => __( 'Enabled', 'zero-spam' )
|
26 |
-
]
|
27 |
-
]);
|
28 |
-
|
29 |
-
// Option to remove author links
|
30 |
-
add_settings_field( 'strip_comment_author_links', __( 'Strip Comment Author Links', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_onsite', [
|
31 |
-
'label_for' => 'strip_comment_author_links',
|
32 |
-
'type' => 'checkbox',
|
33 |
-
'multi' => false,
|
34 |
-
'desc' => __( 'Spammers are well-known at injecting malicious links in the comment author website field, this option disables it.', 'zero-spam' ),
|
35 |
-
'options' => [
|
36 |
-
'enabled' => __( 'Enabled', 'zero-spam' )
|
37 |
-
]
|
38 |
-
]);
|
39 |
-
|
40 |
-
// Add option to enable/disable comment form submission protection.
|
41 |
-
add_settings_field( 'verify_comments', __( 'Detect Spam/Malicious Comments', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_spam_checks', [
|
42 |
-
'label_for' => 'verify_comments',
|
43 |
-
'type' => 'checkbox',
|
44 |
-
'multi' => false,
|
45 |
-
'desc' => __( 'Monitors comments for malicious links and automated spambot submissions.', 'zero-spam' ),
|
46 |
-
'options' => [
|
47 |
-
'enabled' => __( 'Enabled', 'zero-spam' )
|
48 |
-
]
|
49 |
-
]);
|
50 |
-
}
|
51 |
-
}
|
52 |
-
add_action( 'wpzerospam_admin_options', 'wpzerospam_comments_admin_fields' );
|
53 |
-
|
54 |
-
/**
|
55 |
-
* Add validation to the comment form submission protection admin fields.
|
56 |
-
*
|
57 |
-
* @since 4.9.9
|
58 |
-
*
|
59 |
-
* @param array $fields Array on available admin fields.
|
60 |
-
*/
|
61 |
-
if ( ! function_exists( 'wpzerospam_comments_admin_validation' ) ) {
|
62 |
-
function wpzerospam_comments_admin_validation( $fields ) {
|
63 |
-
if ( empty( $fields['verify_comments'] ) ) { $fields['verify_comments'] = 'disabled'; }
|
64 |
-
if ( empty( $fields['strip_comment_links'] ) ) { $fields['strip_comment_links'] = 'disabled'; }
|
65 |
-
if ( empty( $fields['strip_comment_author_links'] ) ) { $fields['strip_comment_author_links'] = 'disabled'; }
|
66 |
-
|
67 |
-
return $fields;
|
68 |
-
}
|
69 |
-
}
|
70 |
-
add_filter( 'wpzerospam_admin_validation', 'wpzerospam_comments_admin_validation' );
|
71 |
-
|
72 |
-
if ( ! function_exists( 'wpzerospam_comments_admin_fields_default' ) ) {
|
73 |
-
function wpzerospam_comments_admin_fields_default( $defaults ) {
|
74 |
-
if ( empty( $defaults['verify_comments'] ) ) { $defaults['verify_comments'] = 'enabled'; }
|
75 |
-
if ( empty( $defaults['strip_comment_links'] ) ) { $defaults['strip_comment_links'] = 'disabled'; }
|
76 |
-
if ( empty( $defaults['strip_comment_author_links'] ) ) { $defaults['strip_comment_author_links'] = 'disabled'; }
|
77 |
-
|
78 |
-
return $defaults;
|
79 |
-
}
|
80 |
-
}
|
81 |
-
add_filter( 'wpzerospam_admin_options_defaults', 'wpzerospam_comments_admin_fields_default' );
|
82 |
-
|
83 |
-
if ( ! function_exists( 'wpzerospam_comments_admin_submission_data_item' ) ) {
|
84 |
-
function wpzerospam_comments_admin_submission_data_item( $key, $value ) {
|
85 |
-
switch( $key ) {
|
86 |
-
case 'comment_post_ID':
|
87 |
-
$post = get_post( $value );
|
88 |
-
if ( $post ) {
|
89 |
-
$item_value = '<a href="' . get_the_permalink( $value ) . '">' . get_the_title( $value ) . '</a>';
|
90 |
-
} else {
|
91 |
-
$item_value = 'N/A';
|
92 |
-
}
|
93 |
-
echo wpzerospam_admin_details_item( __( 'Comment Post', 'zero-spam' ), $item_value );
|
94 |
-
break;
|
95 |
-
case 'comment_author':
|
96 |
-
echo wpzerospam_admin_details_item( __( 'Author', 'zero-spam' ), $value );
|
97 |
-
break;
|
98 |
-
case 'comment_author_email':
|
99 |
-
echo wpzerospam_admin_details_item( __( 'Email', 'zero-spam' ), $value );
|
100 |
-
break;
|
101 |
-
case 'comment_author_url':
|
102 |
-
echo wpzerospam_admin_details_item( __( 'Website', 'zero-spam' ), $value );
|
103 |
-
break;
|
104 |
-
case 'comment_content':
|
105 |
-
echo wpzerospam_admin_details_item( __( 'Comment', 'zero-spam' ), sanitize_text_field( $value ) );
|
106 |
-
break;
|
107 |
-
case 'comment_type':
|
108 |
-
echo wpzerospam_admin_details_item( __( 'Comment Type', 'zero-spam' ), $value );
|
109 |
-
break;
|
110 |
-
case 'comment_parent':
|
111 |
-
echo wpzerospam_admin_details_item( __( 'Comment Parent ID', 'zero-spam' ), '<a href="' . get_comment_link( $value ) . '">' . $value . '</a>' );
|
112 |
-
break;
|
113 |
-
case 'comment_as_submitted':
|
114 |
-
foreach( $value as $k => $v ):
|
115 |
-
if ( ! $v ) { continue; }
|
116 |
-
switch( $k ):
|
117 |
-
case 'comment_author':
|
118 |
-
if ( empty( $author_shown ) ) {
|
119 |
-
echo wpzerospam_admin_details_item( __( 'Author', 'zero-spam' ), $v );
|
120 |
-
}
|
121 |
-
break;
|
122 |
-
case 'comment_author_email':
|
123 |
-
if ( empty( $author_email ) ) {
|
124 |
-
echo wpzerospam_admin_details_item( __( 'Email', 'zero-spam' ), $v );
|
125 |
-
}
|
126 |
-
break;
|
127 |
-
case 'comment_author_url':
|
128 |
-
if ( empty( $author_url ) ) {
|
129 |
-
echo wpzerospam_admin_details_item( __( 'Website', 'zero-spam' ), $v );
|
130 |
-
}
|
131 |
-
break;
|
132 |
-
case 'comment_content':
|
133 |
-
echo wpzerospam_admin_details_item( __( 'Comment', 'zero-spam' ), sanitize_text_field( $v ) );
|
134 |
-
break;
|
135 |
-
case 'user_ip':
|
136 |
-
echo wpzerospam_admin_details_item( __( 'User IP', 'zero-spam' ), '<a href="https://zerospam.org/ip-lookup/' . urlencode( $v ) .'" target="_blank" rel="noopener noreferrer">' . $v . '</a>' );
|
137 |
-
break;
|
138 |
-
case 'user_agent':
|
139 |
-
echo wpzerospam_admin_details_item( __( 'User Agent', 'zero-spam' ), $v );
|
140 |
-
break;
|
141 |
-
case 'blog':
|
142 |
-
echo wpzerospam_admin_details_item( __( 'Site', 'zero-spam' ), $v );
|
143 |
-
break;
|
144 |
-
case 'blog_lang':
|
145 |
-
echo wpzerospam_admin_details_item( __( 'Site Language', 'zero-spam' ), $v );
|
146 |
-
break;
|
147 |
-
case 'blog_charset':
|
148 |
-
echo wpzerospam_admin_details_item( __( 'Site Charset', 'zero-spam' ), $v );
|
149 |
-
break;
|
150 |
-
case 'permalink':
|
151 |
-
echo wpzerospam_admin_details_item( __( 'Permalink', 'zero-spam' ), '<a href="' . $v . '" target="_blank">' . $v . '</a>' );
|
152 |
-
break;
|
153 |
-
default:
|
154 |
-
echo wpzerospam_admin_details_item( $k, $v );
|
155 |
-
endswitch;
|
156 |
-
endforeach;
|
157 |
-
break;
|
158 |
-
case 'akismet_result':
|
159 |
-
echo wpzerospam_admin_details_item( __( 'Akismet Result', 'zero-spam' ), $value );
|
160 |
-
break;
|
161 |
-
case 'akismet_pro_tip':
|
162 |
-
echo wpzerospam_admin_details_item( __( 'Akismet Pro Tip', 'zero-spam' ), $value );
|
163 |
-
break;
|
164 |
-
}
|
165 |
-
}
|
166 |
-
}
|
167 |
-
add_action( 'wpzerospam_admin_submission_data_items', 'wpzerospam_comments_admin_submission_data_item', 10, 2 );
|
168 |
-
|
169 |
-
if ( ! function_exists( 'wpzerospam_comments_defined_submission_data' ) ) {
|
170 |
-
function wpzerospam_comments_defined_submission_data( $submission_data_keys ) {
|
171 |
-
$submission_data_keys[] = 'comment_post_ID';
|
172 |
-
$submission_data_keys[] = 'comment_author';
|
173 |
-
$submission_data_keys[] = 'comment_author_email';
|
174 |
-
$submission_data_keys[] = 'comment_author_url';
|
175 |
-
$submission_data_keys[] = 'comment_content';
|
176 |
-
$submission_data_keys[] = 'comment_type';
|
177 |
-
$submission_data_keys[] = 'comment_parent';
|
178 |
-
$submission_data_keys[] = 'comment_as_submitted';
|
179 |
-
$submission_data_keys[] = 'akismet_result';
|
180 |
-
$submission_data_keys[] = 'akismet_pro_tip';
|
181 |
-
|
182 |
-
return $submission_data_keys;
|
183 |
-
}
|
184 |
-
}
|
185 |
-
add_filter( 'wpzerospam_defined_submission_data', 'wpzerospam_comments_defined_submission_data', 10, 1 );
|
186 |
-
|
187 |
-
/**
|
188 |
-
* Runs the comment form spam detections.
|
189 |
-
*
|
190 |
-
* Runs all action & filter hooks needed for monitoring comment submissions for
|
191 |
-
* spam (when enabled via the 'Detect Comment Spam' option).
|
192 |
-
*
|
193 |
-
* @since 4.9.9
|
194 |
-
*
|
195 |
-
* @return void
|
196 |
-
*/
|
197 |
-
if ( ! function_exists( 'wpzerospam_comments_after_setup_theme' ) ) {
|
198 |
-
function wpzerospam_comments_after_setup_theme() {
|
199 |
-
$options = wpzerospam_options();
|
200 |
-
|
201 |
-
// Add the 'comment' spam type.
|
202 |
-
add_filter( 'wpzerospam_types', 'wpzerospam_comments_types' );
|
203 |
-
|
204 |
-
// Determines is author links should be stripped.
|
205 |
-
if ( 'enabled' == $options['strip_comment_author_links'] ) {
|
206 |
-
add_filter( 'get_comment_author_link', 'wpzerospam_remove_comment_author_link', 10, 3 );
|
207 |
-
add_filter( 'get_comment_author_url', 'wpzerospam_remove_author_url' );
|
208 |
-
add_filter( 'comment_form_default_fields', 'wpzerospam_remove_author_url_field' );
|
209 |
-
}
|
210 |
-
|
211 |
-
// Determines if comment links should be stripped.
|
212 |
-
if ( 'enabled' == $options['strip_comment_links'] ) {
|
213 |
-
remove_filter( 'comment_text', 'make_clickable', 9 );
|
214 |
-
add_filter( 'comment_text', 'wpzerospam_strip_comment_links_display', 10, 1);
|
215 |
-
add_filter( 'comment_text_rss', 'wpzerospam_strip_comment_links_display', 10, 1);
|
216 |
-
add_filter( 'comment_excerpt', 'wpzerospam_strip_comment_links_display', 10, 1);
|
217 |
-
add_filter( 'preprocess_comment', 'wpzerospam_strip_comment_links', 10, 1 );
|
218 |
-
}
|
219 |
-
|
220 |
-
// Check if detecting comments is enabled & user is unauthenticated.
|
221 |
-
if ( 'enabled' != $options['verify_comments'] || is_user_logged_in() ) { return false; }
|
222 |
-
|
223 |
-
// Add the 'honeypot' field to the comment form.
|
224 |
-
add_filter( 'comment_form_defaults', 'wpzerospam_comments_form_defaults' );
|
225 |
-
|
226 |
-
// Preprocess comment submissions.
|
227 |
-
add_action( 'preprocess_comment', 'wpzerospam_comments_preprocess' );
|
228 |
-
|
229 |
-
// Register & enqueue needed CSS & JS files, only when the comment form is on the page.
|
230 |
-
add_action( 'comment_form', 'wpzerospam_comments_enqueue_scripts' );
|
231 |
-
}
|
232 |
-
}
|
233 |
-
add_action( 'after_setup_theme', 'wpzerospam_comments_after_setup_theme' );
|
234 |
-
|
235 |
-
/**
|
236 |
-
* Strips links from comment submissions.
|
237 |
-
*/
|
238 |
-
if ( ! function_exists( 'wpzerospam_strip_comment_links' ) ) {
|
239 |
-
function wpzerospam_strip_comment_links( $comment ) {
|
240 |
-
global $allowedtags;
|
241 |
-
|
242 |
-
$tags = $allowedtags;
|
243 |
-
unset( $tags['a'] );
|
244 |
-
$content = addslashes( wp_kses( stripslashes( $comment ), $tags) );
|
245 |
-
|
246 |
-
return $comment;
|
247 |
-
}
|
248 |
-
}
|
249 |
-
|
250 |
-
/**
|
251 |
-
* Strips links from comments when displayed.
|
252 |
-
*/
|
253 |
-
if ( ! function_exists( 'wpzerospam_strip_comment_links_display' ) ) {
|
254 |
-
function wpzerospam_strip_comment_links_display( $comment ) {
|
255 |
-
global $allowedtags;
|
256 |
-
|
257 |
-
$tags = $allowedtags;
|
258 |
-
unset( $tags['a'] );
|
259 |
-
$content = addslashes( wp_kses( stripslashes( $comment ), $tags) );
|
260 |
-
|
261 |
-
return $comment;
|
262 |
-
}
|
263 |
-
}
|
264 |
-
|
265 |
-
/**
|
266 |
-
* Removes the comment author link.
|
267 |
-
*/
|
268 |
-
if ( ! function_exists( 'wpzerospam_remove_comment_author_link' ) ) {
|
269 |
-
function wpzerospam_remove_comment_author_link( $return, $author, $comment_ID ) {
|
270 |
-
return $author;
|
271 |
-
}
|
272 |
-
}
|
273 |
-
|
274 |
-
/**
|
275 |
-
* Removes the comment author url from display.
|
276 |
-
*/
|
277 |
-
if ( ! function_exists( 'wpzerospam_remove_author_url' ) ) {
|
278 |
-
function wpzerospam_remove_author_url() {
|
279 |
-
return false;
|
280 |
-
}
|
281 |
-
}
|
282 |
-
|
283 |
-
/**
|
284 |
-
* Removed the comment author url field.
|
285 |
-
*/
|
286 |
-
if ( ! function_exists( 'wpzerospam_remove_author_url_field' ) ) {
|
287 |
-
function wpzerospam_remove_author_url_field( $fields ) {
|
288 |
-
if ( isset( $fields['url'] ) ) {
|
289 |
-
unset( $fields['url'] );
|
290 |
-
}
|
291 |
-
|
292 |
-
return $fields;
|
293 |
-
}
|
294 |
-
}
|
295 |
-
|
296 |
-
/**
|
297 |
-
* Adds the 'comment' spam type.
|
298 |
-
*
|
299 |
-
* @param array An array of the current spam types.
|
300 |
-
* @return array The resulting current spam types.
|
301 |
-
*/
|
302 |
-
if ( ! function_exists( 'wpzerospam_comments_types' ) ) {
|
303 |
-
function wpzerospam_comments_types( $types ) {
|
304 |
-
$types = array_merge( $types, [ 'comment' => __( 'Comment', 'zero-spam' ) ] );
|
305 |
-
|
306 |
-
return $types;
|
307 |
-
}
|
308 |
-
}
|
309 |
-
|
310 |
-
/**
|
311 |
-
* Add a 'honeypot' field to the comment form.
|
312 |
-
*
|
313 |
-
* @since 4.9.9
|
314 |
-
*
|
315 |
-
* @link https://developer.wordpress.org/reference/hooks/comment_form_defaults/
|
316 |
-
*
|
317 |
-
* @return array The default comment form arguments.
|
318 |
-
*/
|
319 |
-
if ( ! function_exists( 'wpzerospam_comments_form_defaults' ) ) {
|
320 |
-
function wpzerospam_comments_form_defaults( $defaults ) {
|
321 |
-
$defaults['fields']['wpzerospam_hp'] = wpzerospam_honeypot_field();
|
322 |
-
|
323 |
-
return $defaults;
|
324 |
-
}
|
325 |
-
}
|
326 |
-
|
327 |
-
/**
|
328 |
-
* Preprocess comment fields.
|
329 |
-
*
|
330 |
-
* @since 4.3.7
|
331 |
-
*
|
332 |
-
* @link https://codex.wordpress.org/Plugin_API/Filter_Reference/preprocess_comment
|
333 |
-
*
|
334 |
-
* @return array The $commentdata array which may have been manipulated during the execution of the handler.
|
335 |
-
*/
|
336 |
-
if ( ! function_exists( 'wpzerospam_comments_preprocess' ) ) {
|
337 |
-
function wpzerospam_comments_preprocess( $commentdata ) {
|
338 |
-
$options = wpzerospam_options();
|
339 |
-
$honeypot = wpzerospam_get_honeypot();
|
340 |
-
|
341 |
-
if (
|
342 |
-
// First, check the 'honeypot' field.
|
343 |
-
( ! isset( $_REQUEST[ $honeypot ] ) || $_REQUEST[ $honeypot ] ) ||
|
344 |
-
// Next, check the 'wpzerospam_key' field.
|
345 |
-
( empty( $_REQUEST['wpzerospam_key'] ) || wpzerospam_get_key() != $_REQUEST['wpzerospam_key'] )
|
346 |
-
) {
|
347 |
-
// Spam comment selected.
|
348 |
-
do_action( 'wpzerospam_comment_spam', $commentdata );
|
349 |
-
wpzerospam_spam_detected( 'comment', $commentdata );
|
350 |
-
|
351 |
-
return false;
|
352 |
-
}
|
353 |
-
|
354 |
-
return $commentdata;
|
355 |
-
}
|
356 |
-
}
|
357 |
-
|
358 |
-
/**
|
359 |
-
* Register & enqueue CSS & JS files for comment spam detection.
|
360 |
-
*
|
361 |
-
* @since 4.9.9
|
362 |
-
*
|
363 |
-
* @link https://developer.wordpress.org/reference/hooks/wp_enqueue_scripts/
|
364 |
-
*
|
365 |
-
* @return void
|
366 |
-
*/
|
367 |
-
if ( ! function_exists( 'wpzerospam_comments_enqueue_scripts' ) ) {
|
368 |
-
function wpzerospam_comments_enqueue_scripts() {
|
369 |
-
// Load the 'wpzerospam_key' form field JS
|
370 |
-
wp_enqueue_script(
|
371 |
-
'wpzerospam-integration-comments',
|
372 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
373 |
-
'integrations/comments/js/comments.js',
|
374 |
-
[ 'wpzerospam' ],
|
375 |
-
WORDPRESS_ZERO_SPAM_VERSION,
|
376 |
-
true
|
377 |
-
);
|
378 |
-
}
|
379 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
integrations/comments/js/comments.js
DELETED
@@ -1,4 +0,0 @@
|
|
1 |
-
// Initialize WPZS on comment forms.
|
2 |
-
jQuery(function() {
|
3 |
-
jQuery("#commentform, #ast-commentform").WordPressZeroSpam();
|
4 |
-
});
|
|
|
|
|
|
|
|
integrations/contact-form-7/contact-form-7.php
DELETED
@@ -1,198 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Handles checking submitted Contact Form 7 forms for spam
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.3.7
|
7 |
-
*/
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Adds admin settings for CF7 protection.
|
11 |
-
*
|
12 |
-
* @since 4.9.12
|
13 |
-
*
|
14 |
-
* @return void
|
15 |
-
*/
|
16 |
-
if ( ! function_exists( 'wpzerospam_cf7_admin_fields' ) ) {
|
17 |
-
function wpzerospam_cf7_admin_fields() {
|
18 |
-
if ( is_plugin_active( 'contact-form-7/wp-contact-form-7.php' ) ) {
|
19 |
-
add_settings_field( 'verify_cf7', __( 'Detect Spam/Malicious CF7 Submissions', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_spam_checks', [
|
20 |
-
'label_for' => 'verify_cf7',
|
21 |
-
'type' => 'checkbox',
|
22 |
-
'multi' => false,
|
23 |
-
'desc' => __( 'Monitors CF7 for malicious or automated spambot submissions.', 'zero-spam' ),
|
24 |
-
'options' => [
|
25 |
-
'enabled' => __( 'Enabled', 'zero-spam' )
|
26 |
-
]
|
27 |
-
]);
|
28 |
-
}
|
29 |
-
}
|
30 |
-
}
|
31 |
-
add_action( 'wpzerospam_admin_options', 'wpzerospam_cf7_admin_fields' );
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Add validation to the CF7 form protection admin fields.
|
35 |
-
*
|
36 |
-
* @since 4.9.12
|
37 |
-
*
|
38 |
-
* @param array $fields Array on available admin fields.
|
39 |
-
*/
|
40 |
-
if ( ! function_exists( 'wpzerospam_cf7_admin_validation' ) ) {
|
41 |
-
function wpzerospam_cf7_admin_validation( $fields ) {
|
42 |
-
if ( empty( $fields['verify_cf7'] ) ) { $fields['verify_cf7'] = 'disabled'; }
|
43 |
-
|
44 |
-
return $fields;
|
45 |
-
}
|
46 |
-
}
|
47 |
-
add_filter( 'wpzerospam_admin_validation', 'wpzerospam_cf7_admin_validation' );
|
48 |
-
|
49 |
-
if ( ! function_exists( 'wpzerospam_cf7_admin_fields_default' ) ) {
|
50 |
-
function wpzerospam_cf7_admin_fields_default( $defaults ) {
|
51 |
-
if ( empty( $defaults['verify_cf7'] ) ) { $defaults['verify_cf7'] = 'enabled'; }
|
52 |
-
|
53 |
-
return $defaults;
|
54 |
-
}
|
55 |
-
}
|
56 |
-
add_filter( 'wpzerospam_admin_option_defaults', 'wpzerospam_cf7_admin_fields_default' );
|
57 |
-
|
58 |
-
if ( ! function_exists( 'zero_spam_wpcf7_admin_submission_data_item' ) ) {
|
59 |
-
function zero_spam_wpcf7_admin_submission_data_item( $key, $value ) {
|
60 |
-
switch( $key ) {
|
61 |
-
case '_wpcf7':
|
62 |
-
echo wpzerospam_admin_details_item( __( 'CF7 ID', 'zero-spam' ), $value );
|
63 |
-
break;
|
64 |
-
case '_wpcf7_version':
|
65 |
-
echo wpzerospam_admin_details_item( __( 'CF7 Version', 'zero-spam' ), $value );
|
66 |
-
break;
|
67 |
-
case '_wpcf7_locale':
|
68 |
-
echo wpzerospam_admin_details_item( __( 'CF7 Language', 'zero-spam' ), json_encode( $value ) );
|
69 |
-
break;
|
70 |
-
case '_wpcf7_container_post':
|
71 |
-
echo wpzerospam_admin_details_item( __( 'CF7 Referrer Post ID', 'zero-spam' ), json_encode( $value ) );
|
72 |
-
break;
|
73 |
-
case '_wpcf7_unit_tag':
|
74 |
-
echo wpzerospam_admin_details_item( __( 'CF7 Unit Tag', 'zero-spam' ), json_encode( $value ) );
|
75 |
-
break;
|
76 |
-
}
|
77 |
-
}
|
78 |
-
}
|
79 |
-
add_action( 'wpzerospam_admin_submission_data_items', 'zero_spam_wpcf7_admin_submission_data_item', 10, 2 );
|
80 |
-
|
81 |
-
if ( ! function_exists( 'wpzerospam_wpcf7_defined_submission_data' ) ) {
|
82 |
-
function wpzerospam_wpcf7_defined_submission_data( $submission_data_keys ) {
|
83 |
-
$submission_data_keys[] = '_wpcf7';
|
84 |
-
$submission_data_keys[] = '_wpcf7_version';
|
85 |
-
$submission_data_keys[] = '_wpcf7_locale';
|
86 |
-
$submission_data_keys[] = '_wpcf7_container_post';
|
87 |
-
$submission_data_keys[] = '_wpcf7_unit_tag';
|
88 |
-
|
89 |
-
return $submission_data_keys;
|
90 |
-
}
|
91 |
-
}
|
92 |
-
add_filter( 'wpzerospam_defined_submission_data', 'wpzerospam_wpcf7_defined_submission_data', 10, 1 );
|
93 |
-
|
94 |
-
/*
|
95 |
-
* Runs the CF7 form spam detections.
|
96 |
-
*
|
97 |
-
* Runs all action & filter hooks needed for monitoring CF7 for
|
98 |
-
* spam (when enabled via the 'Detect Spam/Malicious CF7 Submissions' option).
|
99 |
-
*
|
100 |
-
* @since 4.9.12
|
101 |
-
*
|
102 |
-
* @return void
|
103 |
-
*/
|
104 |
-
if ( ! function_exists( 'wpzerospam_cf7_after_setup_theme' ) ) {
|
105 |
-
function wpzerospam_cf7_after_setup_theme() {
|
106 |
-
// Check if site registrations are enabled
|
107 |
-
$options = wpzerospam_options();
|
108 |
-
|
109 |
-
// Add the 'cf7' spam type.
|
110 |
-
add_filter( 'wpzerospam_types', 'wpzerospam_wpcf7_type' );
|
111 |
-
|
112 |
-
// Check if detecting registration spam is enabled & user is unauthenticated.
|
113 |
-
if ( 'enabled' != $options['verify_cf7'] || is_user_logged_in() ) { return false; }
|
114 |
-
|
115 |
-
// Add the 'honeypot' field to the CF7 form.
|
116 |
-
add_filter( 'wpcf7_form_elements', 'zero_spam_wpcf7_form_elements', 10, 1 );
|
117 |
-
|
118 |
-
// Preprocess CF7 form submissions.
|
119 |
-
add_filter( 'wpcf7_validate', 'wpzerospam_wpcf7_preprocess_submission', 10, 2 );
|
120 |
-
}
|
121 |
-
}
|
122 |
-
add_action( 'after_setup_theme', 'wpzerospam_cf7_after_setup_theme' );
|
123 |
-
|
124 |
-
/**
|
125 |
-
* Adds the 'cf7' spam type.
|
126 |
-
*
|
127 |
-
* @param array An array of the current spam types.
|
128 |
-
* @return array The resulting current spam types.
|
129 |
-
*/
|
130 |
-
if ( ! function_exists( 'wpzerospam_wpcf7_type' ) ) {
|
131 |
-
function wpzerospam_wpcf7_type( $types ) {
|
132 |
-
$types = array_merge( $types, [ 'cf7' => __( 'Contact Form 7', 'zero-spam' ) ] );
|
133 |
-
|
134 |
-
return $types;
|
135 |
-
}
|
136 |
-
}
|
137 |
-
|
138 |
-
/**
|
139 |
-
* Adds the honeypot field to CF7 forms.
|
140 |
-
*
|
141 |
-
* @since 4.9.12
|
142 |
-
*
|
143 |
-
* @param sting HTML for the form.
|
144 |
-
* @return string The modified form HTML.
|
145 |
-
*/
|
146 |
-
function zero_spam_wpcf7_form_elements( $this_form_do_shortcode ) {
|
147 |
-
$this_form_do_shortcode .= wpzerospam_honeypot_field();
|
148 |
-
|
149 |
-
return $this_form_do_shortcode;
|
150 |
-
};
|
151 |
-
|
152 |
-
/**
|
153 |
-
* Preprocess CF7 submissions.
|
154 |
-
*
|
155 |
-
* @since 4.9.12
|
156 |
-
*
|
157 |
-
* @param object $result CF7 result object.
|
158 |
-
* @param object $tags CF7 tags object.
|
159 |
-
* @return object A CF7 object.
|
160 |
-
*/
|
161 |
-
if ( ! function_exists( 'wpzerospam_wpcf7_preprocess_submission' ) ) {
|
162 |
-
function wpzerospam_wpcf7_preprocess_submission( $result, $tags ) {
|
163 |
-
$options = wpzerospam_options();
|
164 |
-
$honeypot = wpzerospam_get_honeypot();
|
165 |
-
|
166 |
-
if (
|
167 |
-
// First, check the 'honeypot' field.
|
168 |
-
( ! isset( $_REQUEST[ $honeypot ] ) || $_REQUEST[ $honeypot ] ) ||
|
169 |
-
// Next, check the 'wpzerospam_key' field.
|
170 |
-
( empty( $_REQUEST['wpzerospam_key'] ) || wpzerospam_get_key() != $_REQUEST['wpzerospam_key'] )
|
171 |
-
) {
|
172 |
-
// Spam registration selected.
|
173 |
-
do_action( 'wpzerospam_cf7_spam', $_REQUEST );
|
174 |
-
wpzerospam_spam_detected( 'cf7', $_REQUEST, false );
|
175 |
-
|
176 |
-
$result->invalidate( $tags[0], $options['spam_message'] );
|
177 |
-
}
|
178 |
-
|
179 |
-
return $result;
|
180 |
-
}
|
181 |
-
}
|
182 |
-
|
183 |
-
/**
|
184 |
-
* Enqueue the CF7 form JS
|
185 |
-
*/
|
186 |
-
if ( ! function_exists( 'wpzerospam_cf7' ) ) {
|
187 |
-
function wpzerospam_cf7() {
|
188 |
-
wp_enqueue_script(
|
189 |
-
'wpzerospam-integration-cf7',
|
190 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
191 |
-
'integrations/contact-form-7/js/cf7.js',
|
192 |
-
[ 'wpzerospam' ],
|
193 |
-
WORDPRESS_ZERO_SPAM_VERSION,
|
194 |
-
true
|
195 |
-
);
|
196 |
-
}
|
197 |
-
}
|
198 |
-
add_action( 'wpcf7_enqueue_scripts', 'wpzerospam_cf7' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
integrations/contact-form-7/js/cf7.js
DELETED
@@ -1,4 +0,0 @@
|
|
1 |
-
// Initialize WPZS on CF7 forms.
|
2 |
-
jQuery(function() {
|
3 |
-
jQuery(".wpcf7-form").WordPressZeroSpam();
|
4 |
-
});
|
|
|
|
|
|
|
|
integrations/fluentform/fluentform.php
DELETED
@@ -1,58 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Handles checking submitted Fluent Forms for spam
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.4.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Add the 'fluentform' spam type
|
11 |
-
*/
|
12 |
-
add_filter( 'wpzerospam_types', function( $types ) {
|
13 |
-
$types = array_merge( $types, [ 'fluentform' => __( 'Fluent Forms', 'zero-spam' ) ] );
|
14 |
-
return $types;
|
15 |
-
});
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Validation for Fluent Form submissions
|
19 |
-
*/
|
20 |
-
if ( ! function_exists( 'wpzerospam_fluentform_validate' ) ) {
|
21 |
-
function wpzerospam_fluentform_validate( $insertData, $data, $form ) {
|
22 |
-
if ( is_user_logged_in() || wpzerospam_key_check( $data ) ) {
|
23 |
-
return;
|
24 |
-
}
|
25 |
-
|
26 |
-
do_action( 'wpzerospam_fluentform_spam' );
|
27 |
-
|
28 |
-
$data = [
|
29 |
-
'insertData' => $insertData,
|
30 |
-
'data' => $data,
|
31 |
-
'form' => $form
|
32 |
-
];
|
33 |
-
|
34 |
-
wpzerospam_spam_detected( 'fluentform', $result, false );
|
35 |
-
|
36 |
-
$options = wpzerospam_options();
|
37 |
-
echo $options['spam_message'];
|
38 |
-
die();
|
39 |
-
}
|
40 |
-
}
|
41 |
-
add_action( 'fluentform_before_insert_submission', 'wpzerospam_fluentform_validate', 10, 3 );
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Enqueue the Fluent Form JS
|
45 |
-
*/
|
46 |
-
if ( ! function_exists( 'wpzerospam_fluentform' ) ) {
|
47 |
-
function wpzerospam_fluentform() {
|
48 |
-
wp_enqueue_script(
|
49 |
-
'wpzerospam-integration-fluentform',
|
50 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
51 |
-
'integrations/fluentform/js/fluentform.js',
|
52 |
-
[ 'wpzerospam' ],
|
53 |
-
WORDPRESS_ZERO_SPAM_VERSION,
|
54 |
-
true
|
55 |
-
);
|
56 |
-
}
|
57 |
-
}
|
58 |
-
add_action( 'fluentform_before_form_render', 'wpzerospam_fluentform' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
integrations/fluentform/js/fluentform.js
DELETED
@@ -1,4 +0,0 @@
|
|
1 |
-
// Initialize WPZS on Fluent Forms.
|
2 |
-
jQuery(function() {
|
3 |
-
jQuery(".frm-fluent-form").WordPressZeroSpam();
|
4 |
-
});
|
|
|
|
|
|
|
|
integrations/formidable/formidable.php
DELETED
@@ -1,74 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Handles checking submitted Formidable forms for spam
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.9.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Add the 'formidable' spam type
|
11 |
-
*
|
12 |
-
* @since 4.9.0
|
13 |
-
*/
|
14 |
-
add_filter( 'wpzerospam_types', function( $types ) {
|
15 |
-
$types = array_merge( $types, [ 'formidable' => __( 'Formidable Forms', 'zero-spam' ) ] );
|
16 |
-
return $types;
|
17 |
-
});
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Validates the wpzerospam_key
|
21 |
-
*
|
22 |
-
* @since 4.9.0
|
23 |
-
* @link https://formidableforms.com/knowledgebase/frm_validate_entry/
|
24 |
-
*/
|
25 |
-
if ( ! function_exists( 'wpzerospam_formidable_frm_validate_entry' ) ) {
|
26 |
-
function wpzerospam_formidable_frm_validate_entry( $errors, $values ) {
|
27 |
-
// Don't validate for logged in users
|
28 |
-
if ( is_user_logged_in() ) {
|
29 |
-
return $errors;
|
30 |
-
}
|
31 |
-
|
32 |
-
// Validate the wpzerospam_key
|
33 |
-
if ( ! wpzerospam_key_check( $values ) ) {
|
34 |
-
$options = wpzerospam_options();
|
35 |
-
|
36 |
-
do_action( 'wpzerospam_formidable_spam' );
|
37 |
-
|
38 |
-
wpzerospam_spam_detected( 'formidable', $values, false );
|
39 |
-
|
40 |
-
$errors['wpzerospam'] = $options['spam_message'];
|
41 |
-
}
|
42 |
-
|
43 |
-
return $errors;
|
44 |
-
}
|
45 |
-
}
|
46 |
-
add_filter( 'frm_validate_entry', 'wpzerospam_formidable_frm_validate_entry', 20, 2 );
|
47 |
-
|
48 |
-
/**
|
49 |
-
* Adds the hidden wpzerospam_key field
|
50 |
-
*
|
51 |
-
* @since 4.9.0
|
52 |
-
* @link https://formidableforms.com/knowledgebase/frm_entry_form/
|
53 |
-
*/
|
54 |
-
if ( ! function_exists( 'wpzerospam_formidable_frm_entry_form' ) ) {
|
55 |
-
function wpzerospam_formidable_frm_entry_form( $form ) {
|
56 |
-
echo '<input type="hidden" name="wpzerospam_key" value="" />';
|
57 |
-
}
|
58 |
-
}
|
59 |
-
add_action( 'frm_entry_form', 'wpzerospam_formidable_frm_entry_form' );
|
60 |
-
|
61 |
-
/**
|
62 |
-
* Adds the wpzerospam_key value to the hidden field via JS
|
63 |
-
*
|
64 |
-
* @since 4.9.0
|
65 |
-
* @link https://formidableforms.com/knowledgebase/frm_entries_footer_scripts/
|
66 |
-
*/
|
67 |
-
if ( ! function_exists( 'wpzerospam_formidable_frm_entries_footer_scripts' ) ) {
|
68 |
-
function wpzerospam_formidable_frm_entries_footer_scripts( $fields, $form ) {
|
69 |
-
?>
|
70 |
-
jQuery( '[name="wpzerospam_key"]' ).val( "<?php echo wpzerospam_get_key(); ?>" );
|
71 |
-
<?php
|
72 |
-
}
|
73 |
-
}
|
74 |
-
add_action( 'frm_entries_footer_scripts', 'wpzerospam_formidable_frm_entries_footer_scripts', 20, 2 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
integrations/registrations/js/registrations.js
DELETED
@@ -1,4 +0,0 @@
|
|
1 |
-
// Initialize WPZS on registration forms.
|
2 |
-
jQuery(function() {
|
3 |
-
jQuery("#registerform").WordPressZeroSpam();
|
4 |
-
});
|
|
|
|
|
|
|
|
integrations/registrations/registrations.php
DELETED
@@ -1,200 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Handles checking registration submissions for spam
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.3.7
|
7 |
-
*/
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Adds admin settings for registration protection.
|
11 |
-
*
|
12 |
-
* @since 4.9.12
|
13 |
-
*
|
14 |
-
* @return void
|
15 |
-
*/
|
16 |
-
if ( ! function_exists( 'wpzerospam_registrations_admin_fields' ) ) {
|
17 |
-
function wpzerospam_registrations_admin_fields() {
|
18 |
-
if ( get_option( 'users_can_register' ) ) {
|
19 |
-
// Registration spam check
|
20 |
-
add_settings_field( 'verify_registrations', __( 'Detect Spam/Malicious Registrations', 'zero-spam' ), 'wpzerospam_field_cb', 'wpzerospam', 'wpzerospam_spam_checks', [
|
21 |
-
'label_for' => 'verify_registrations',
|
22 |
-
'type' => 'checkbox',
|
23 |
-
'multi' => false,
|
24 |
-
'desc' => __( 'Monitors registrations for malicious or automated spambot submissions.', 'zero-spam' ),
|
25 |
-
'options' => [
|
26 |
-
'enabled' => __( 'Enabled', 'zero-spam' )
|
27 |
-
]
|
28 |
-
]);
|
29 |
-
}
|
30 |
-
}
|
31 |
-
}
|
32 |
-
add_action( 'wpzerospam_admin_options', 'wpzerospam_registrations_admin_fields' );
|
33 |
-
|
34 |
-
/**
|
35 |
-
* Add validation to the registration form protection admin fields.
|
36 |
-
*
|
37 |
-
* @since 4.9.12
|
38 |
-
*
|
39 |
-
* @param array $fields Array on available admin fields.
|
40 |
-
*/
|
41 |
-
if ( ! function_exists( 'wpzerospam_registrations_admin_validation' ) ) {
|
42 |
-
function wpzerospam_registrations_admin_validation( $fields ) {
|
43 |
-
if ( empty( $fields['verify_registrations'] ) ) { $fields['verify_registrations'] = 'disabled'; }
|
44 |
-
|
45 |
-
return $fields;
|
46 |
-
}
|
47 |
-
}
|
48 |
-
add_filter( 'wpzerospam_admin_validation', 'wpzerospam_registrations_admin_validation' );
|
49 |
-
|
50 |
-
/**
|
51 |
-
* Sets the default admin option fields for registrations.
|
52 |
-
*
|
53 |
-
* @since 4.9.12
|
54 |
-
*
|
55 |
-
* @param array $defaults Array of WPZS admin option fields.
|
56 |
-
* @return array The modified array of the WPZS admin option fields.
|
57 |
-
*/
|
58 |
-
if ( ! function_exists( 'wpzerospam_registrations_admin_fields_default' ) ) {
|
59 |
-
function wpzerospam_registrations_admin_fields_default( $defaults ) {
|
60 |
-
if ( empty( $defaults['verify_registrations'] ) ) { $defaults['verify_registrations'] = 'enabled'; }
|
61 |
-
|
62 |
-
return $defaults;
|
63 |
-
}
|
64 |
-
}
|
65 |
-
add_filter( 'wpzerospam_admin_options_defaults', 'wpzerospam_registrations_admin_fields_default' );
|
66 |
-
|
67 |
-
if ( ! function_exists( 'wpzerospam_registrations_admin_submission_data_item' ) ) {
|
68 |
-
function wpzerospam_registrations_admin_submission_data_item( $key, $value ) {
|
69 |
-
switch( $key ) {
|
70 |
-
case 'sanitized_user_login':
|
71 |
-
echo wpzerospam_admin_details_item( __( 'Sanitized User Login', 'zero-spam' ), $value );
|
72 |
-
break;
|
73 |
-
case 'user_email':
|
74 |
-
echo wpzerospam_admin_details_item( __( 'User Email', 'zero-spam' ), $value );
|
75 |
-
break;
|
76 |
-
case 'errors':
|
77 |
-
echo wpzerospam_admin_details_item( __( 'Errors', 'zero-spam' ), json_encode( $value ) );
|
78 |
-
break;
|
79 |
-
}
|
80 |
-
}
|
81 |
-
}
|
82 |
-
add_action( 'wpzerospam_admin_submission_data_items', 'wpzerospam_registrations_admin_submission_data_item', 10, 2 );
|
83 |
-
|
84 |
-
if ( ! function_exists( 'wpzerospamregistrations_defined_submission_data' ) ) {
|
85 |
-
function wpzerospamregistrations_defined_submission_data( $submission_data_keys ) {
|
86 |
-
$submission_data_keys[] = 'sanitized_user_login';
|
87 |
-
$submission_data_keys[] = 'user_email';
|
88 |
-
$submission_data_keys[] = 'errors';
|
89 |
-
|
90 |
-
return $submission_data_keys;
|
91 |
-
}
|
92 |
-
}
|
93 |
-
add_filter( 'wpzerospam_defined_submission_data', 'wpzerospamregistrations_defined_submission_data', 10, 1 );
|
94 |
-
|
95 |
-
/*
|
96 |
-
* Runs the registration form spam detections.
|
97 |
-
*
|
98 |
-
* Runs all action & filter hooks needed for monitoring registrations for
|
99 |
-
* spam (when enabled via the 'Detect Registration Spam' option).
|
100 |
-
*
|
101 |
-
* @since 4.9.12
|
102 |
-
*
|
103 |
-
* @return void
|
104 |
-
*/
|
105 |
-
if ( ! function_exists( 'wpzerospam_registrations_after_setup_theme' ) ) {
|
106 |
-
function wpzerospam_registrations_after_setup_theme() {
|
107 |
-
// Add the 'registration' spam type.
|
108 |
-
add_filter( 'wpzerospam_types', 'wpzerospam_registrations_types' );
|
109 |
-
|
110 |
-
// Check if site registrations are enabled
|
111 |
-
if ( ! get_option( 'users_can_register' ) ) { return false; }
|
112 |
-
|
113 |
-
$options = wpzerospam_options();
|
114 |
-
|
115 |
-
// Check if detecting registration spam is enabled & user is unauthenticated.
|
116 |
-
if ( 'enabled' != $options['verify_registrations'] || is_user_logged_in() ) { return false; }
|
117 |
-
|
118 |
-
// Add the 'honeypot' field to the registration form.
|
119 |
-
add_action( 'register_form', 'wpzerospam_registrations_form' );
|
120 |
-
|
121 |
-
// Preprocess registration submissions.
|
122 |
-
add_action( 'register_post', 'wpzerospam_registrations_preprocess', 10, 3 );
|
123 |
-
}
|
124 |
-
}
|
125 |
-
add_action( 'after_setup_theme', 'wpzerospam_registrations_after_setup_theme' );
|
126 |
-
|
127 |
-
/**
|
128 |
-
* Adds the 'registration' spam type.
|
129 |
-
*
|
130 |
-
* @param array An array of the current spam types.
|
131 |
-
* @return array The resulting current spam types.
|
132 |
-
*/
|
133 |
-
if ( ! function_exists( 'wpzerospam_registrations_types' ) ) {
|
134 |
-
function wpzerospam_registrations_types( $types ) {
|
135 |
-
$types = array_merge( $types, [ 'registration' => __( 'Registration', 'zero-spam' ) ] );
|
136 |
-
|
137 |
-
return $types;
|
138 |
-
}
|
139 |
-
}
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Add a 'honeypot' field to the registration form.
|
143 |
-
*
|
144 |
-
* @since 4.9.12
|
145 |
-
*
|
146 |
-
* @link https://codex.wordpress.org/Plugin_API/Action_Reference/register_form
|
147 |
-
*
|
148 |
-
* @return string HTML to append to the registration form.
|
149 |
-
*/
|
150 |
-
if ( ! function_exists( 'wpzerospam_registrations_form' ) ) {
|
151 |
-
function wpzerospam_registrations_form( $defaults ) {
|
152 |
-
echo wpzerospam_honeypot_field();
|
153 |
-
}
|
154 |
-
}
|
155 |
-
|
156 |
-
/**
|
157 |
-
* Preprocess registration form submissions.
|
158 |
-
*/
|
159 |
-
if ( ! function_exists( 'wpzerospam_registrations_preprocess' ) ) {
|
160 |
-
function wpzerospam_registrations_preprocess( $sanitized_user_login, $user_email, $errors ) {
|
161 |
-
$options = wpzerospam_options();
|
162 |
-
$honeypot = wpzerospam_get_honeypot();
|
163 |
-
|
164 |
-
if (
|
165 |
-
// First, check the 'honeypot' field.
|
166 |
-
( ! isset( $_REQUEST[ $honeypot ] ) || $_REQUEST[ $honeypot ] ) ||
|
167 |
-
// Next, check the 'wpzerospam_key' field.
|
168 |
-
( empty( $_REQUEST['wpzerospam_key'] ) || wpzerospam_get_key() != $_REQUEST['wpzerospam_key'] )
|
169 |
-
) {
|
170 |
-
// Spam registration selected.
|
171 |
-
do_action( 'wpzerospam_registration_spam', $errors, $sanitized_user_login, $user_email );
|
172 |
-
wpzerospam_spam_detected( 'registration', [
|
173 |
-
'sanitized_user_login' => $sanitized_user_login,
|
174 |
-
'user_email' => $user_email,
|
175 |
-
'errors' => $errors
|
176 |
-
]);
|
177 |
-
}
|
178 |
-
}
|
179 |
-
}
|
180 |
-
|
181 |
-
/**
|
182 |
-
* Enqueue the registration form JS
|
183 |
-
*/
|
184 |
-
if ( ! function_exists( 'wpzerospam_registration_form' ) ) {
|
185 |
-
function wpzerospam_registration_form() {
|
186 |
-
$options = wpzerospam_options();
|
187 |
-
if ( 'enabled' != $options['verify_registrations'] ) { return; }
|
188 |
-
|
189 |
-
// WordPress Zero Spam registration integration
|
190 |
-
wp_enqueue_script(
|
191 |
-
'wpzerospam-integration-registrations',
|
192 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
193 |
-
'integrations/registrations/js/registrations.js',
|
194 |
-
[ 'wpzerospam' ],
|
195 |
-
WORDPRESS_ZERO_SPAM_VERSION,
|
196 |
-
true
|
197 |
-
);
|
198 |
-
}
|
199 |
-
}
|
200 |
-
add_action( 'login_enqueue_scripts', 'wpzerospam_registration_form' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
integrations/wpforms/js/wpforms.js
DELETED
@@ -1,4 +0,0 @@
|
|
1 |
-
// Initialize WPZS on WPForms.
|
2 |
-
jQuery(function() {
|
3 |
-
jQuery(".wpforms-form").WordPressZeroSpam();
|
4 |
-
});
|
|
|
|
|
|
|
|
integrations/wpforms/wpforms.php
DELETED
@@ -1,54 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Handles checking submitted WPForms submissions
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.1.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Add the 'wpform' spam type
|
11 |
-
*/
|
12 |
-
add_filter( 'wpzerospam_types', function( $types ) {
|
13 |
-
$types = array_merge( $types, [ 'wpform' => __( 'WPForms', 'zero-spam' ) ] );
|
14 |
-
return $types;
|
15 |
-
});
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Validation for WPForms submissions
|
19 |
-
*
|
20 |
-
* @link https://wpforms.com/developers/wpforms_process_before/
|
21 |
-
*/
|
22 |
-
if ( ! function_exists( 'wpzerospam_wpforms_process_before' ) ) {
|
23 |
-
function wpzerospam_wpforms_process_before( $entry, $form_data ) {
|
24 |
-
if ( is_user_logged_in() || wpzerospam_key_check() ) {
|
25 |
-
return;
|
26 |
-
}
|
27 |
-
|
28 |
-
do_action( 'wpzerospam_wpform_spam' );
|
29 |
-
|
30 |
-
$data = [
|
31 |
-
'entry' => $entry,
|
32 |
-
'form_data' => $form_data
|
33 |
-
];
|
34 |
-
wpzerospam_spam_detected( 'wpform', $data );
|
35 |
-
}
|
36 |
-
}
|
37 |
-
add_action( 'wpforms_process_before', 'wpzerospam_wpforms_process_before', 10, 2 );
|
38 |
-
|
39 |
-
/**
|
40 |
-
* Enqueue the WPForms form JS
|
41 |
-
*/
|
42 |
-
if ( ! function_exists( 'wpzerospam_wpforms' ) ) {
|
43 |
-
function wpzerospam_wpforms() {
|
44 |
-
wp_enqueue_script(
|
45 |
-
'wpzerospam-integration-wpforms',
|
46 |
-
plugin_dir_url( WORDPRESS_ZERO_SPAM ) .
|
47 |
-
'integrations/wpforms/js/wpforms.js',
|
48 |
-
[ 'wpzerospam' ],
|
49 |
-
WORDPRESS_ZERO_SPAM_VERSION,
|
50 |
-
true
|
51 |
-
);
|
52 |
-
}
|
53 |
-
}
|
54 |
-
add_action( 'wpforms_frontend_output_before', 'wpzerospam_wpforms' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
languages/zero-spam-fr_FR.pot
DELETED
@@ -1,685 +0,0 @@
|
|
1 |
-
#, fuzzy
|
2 |
-
msgid ""
|
3 |
-
msgstr ""
|
4 |
-
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
|
5 |
-
"Project-Id-Version: WordPress Zero Spam\n"
|
6 |
-
"POT-Creation-Date: 2020-08-07 10:12-0500\n"
|
7 |
-
"PO-Revision-Date: 2020-08-07 10:10-0500\n"
|
8 |
-
"Last-Translator: \n"
|
9 |
-
"Language-Team: \n"
|
10 |
-
"MIME-Version: 1.0\n"
|
11 |
-
"Content-Type: text/plain; charset=UTF-8\n"
|
12 |
-
"Content-Transfer-Encoding: 8bit\n"
|
13 |
-
"X-Generator: Poedit 2.4\n"
|
14 |
-
"X-Poedit-Basepath: ..\n"
|
15 |
-
"X-Poedit-Flags-xgettext: --add-comments=translators:\n"
|
16 |
-
"X-Poedit-WPHeader: wordpress-zero-spam.php\n"
|
17 |
-
"X-Poedit-SourceCharset: UTF-8\n"
|
18 |
-
"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
|
19 |
-
"esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;"
|
20 |
-
"_nx_noop:3c,1,2;__ngettext_noop:1,2\n"
|
21 |
-
"X-Poedit-SearchPath-0: .\n"
|
22 |
-
"X-Poedit-SearchPathExcluded-0: *.min.js\n"
|
23 |
-
|
24 |
-
#: classes/class-wpzerospam-blacklisted-table.php:20
|
25 |
-
msgid "Blacklist"
|
26 |
-
msgstr ""
|
27 |
-
|
28 |
-
#: classes/class-wpzerospam-blacklisted-table.php:21
|
29 |
-
msgid "Blacklist IPs"
|
30 |
-
msgstr ""
|
31 |
-
|
32 |
-
#: classes/class-wpzerospam-blacklisted-table.php:32
|
33 |
-
#: classes/class-wpzerospam-blacklisted-table.php:131
|
34 |
-
msgid "Last Updated"
|
35 |
-
msgstr ""
|
36 |
-
|
37 |
-
#: classes/class-wpzerospam-blacklisted-table.php:33
|
38 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:32
|
39 |
-
#: classes/class-wpzerospam-log-table.php:34 inc/admin.php:245
|
40 |
-
msgid "IP Address"
|
41 |
-
msgstr ""
|
42 |
-
|
43 |
-
#: classes/class-wpzerospam-blacklisted-table.php:34
|
44 |
-
#: classes/class-wpzerospam-blacklisted-table.php:136
|
45 |
-
msgid "Service"
|
46 |
-
msgstr ""
|
47 |
-
|
48 |
-
#: classes/class-wpzerospam-blacklisted-table.php:35
|
49 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:38
|
50 |
-
msgid "Attempts"
|
51 |
-
msgstr ""
|
52 |
-
|
53 |
-
#: classes/class-wpzerospam-blacklisted-table.php:36
|
54 |
-
#: classes/class-wpzerospam-log-table.php:38
|
55 |
-
msgid "Details"
|
56 |
-
msgstr ""
|
57 |
-
|
58 |
-
#: classes/class-wpzerospam-blacklisted-table.php:63
|
59 |
-
msgid "Filter by service"
|
60 |
-
msgstr ""
|
61 |
-
|
62 |
-
#: classes/class-wpzerospam-blacklisted-table.php:67
|
63 |
-
msgid "All services"
|
64 |
-
msgstr ""
|
65 |
-
|
66 |
-
#: classes/class-wpzerospam-blacklisted-table.php:68
|
67 |
-
msgid "BotScout"
|
68 |
-
msgstr ""
|
69 |
-
|
70 |
-
#: classes/class-wpzerospam-blacklisted-table.php:69 inc/admin.php:539
|
71 |
-
msgid "Stop Forum Spam"
|
72 |
-
msgstr ""
|
73 |
-
|
74 |
-
#: classes/class-wpzerospam-blacklisted-table.php:70
|
75 |
-
msgid "Zero Spam"
|
76 |
-
msgstr ""
|
77 |
-
|
78 |
-
#: classes/class-wpzerospam-blacklisted-table.php:73
|
79 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:76
|
80 |
-
#: classes/class-wpzerospam-log-table.php:79
|
81 |
-
msgid "Filter"
|
82 |
-
msgstr ""
|
83 |
-
|
84 |
-
#: classes/class-wpzerospam-blacklisted-table.php:116
|
85 |
-
#: classes/class-wpzerospam-log-table.php:140
|
86 |
-
msgid "No details available."
|
87 |
-
msgstr ""
|
88 |
-
|
89 |
-
#: classes/class-wpzerospam-blacklisted-table.php:119
|
90 |
-
#: classes/class-wpzerospam-log-table.php:143
|
91 |
-
msgid "View"
|
92 |
-
msgstr ""
|
93 |
-
|
94 |
-
#: classes/class-wpzerospam-blacklisted-table.php:126
|
95 |
-
#: classes/class-wpzerospam-log-table.php:148
|
96 |
-
msgid "Detected Spam IP"
|
97 |
-
msgstr ""
|
98 |
-
|
99 |
-
#: classes/class-wpzerospam-blacklisted-table.php:160
|
100 |
-
msgid "Appears"
|
101 |
-
msgstr ""
|
102 |
-
|
103 |
-
#: classes/class-wpzerospam-blacklisted-table.php:166
|
104 |
-
msgid "Confidence"
|
105 |
-
msgstr ""
|
106 |
-
|
107 |
-
#: classes/class-wpzerospam-blacklisted-table.php:172
|
108 |
-
msgid "Frequency"
|
109 |
-
msgstr ""
|
110 |
-
|
111 |
-
#: classes/class-wpzerospam-blacklisted-table.php:178
|
112 |
-
msgid "Last Seen"
|
113 |
-
msgstr ""
|
114 |
-
|
115 |
-
#: classes/class-wpzerospam-blacklisted-table.php:184
|
116 |
-
msgid "ASN"
|
117 |
-
msgstr ""
|
118 |
-
|
119 |
-
#: classes/class-wpzerospam-blacklisted-table.php:208
|
120 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:154
|
121 |
-
msgid "Delete"
|
122 |
-
msgstr ""
|
123 |
-
|
124 |
-
#: classes/class-wpzerospam-blacklisted-table.php:209
|
125 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:155
|
126 |
-
#: classes/class-wpzerospam-log-table.php:289
|
127 |
-
msgid "Delete All Entries"
|
128 |
-
msgstr ""
|
129 |
-
|
130 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:20
|
131 |
-
msgid "Blocked IP"
|
132 |
-
msgstr ""
|
133 |
-
|
134 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:21 inc/admin.php:70
|
135 |
-
#: inc/admin.php:560
|
136 |
-
msgid "Blocked IPs"
|
137 |
-
msgstr ""
|
138 |
-
|
139 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:33
|
140 |
-
#: classes/class-wpzerospam-log-table.php:33
|
141 |
-
#: classes/class-wpzerospam-log-table.php:163 inc/admin.php:255
|
142 |
-
msgid "Type"
|
143 |
-
msgstr ""
|
144 |
-
|
145 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:34
|
146 |
-
msgid "Date Added"
|
147 |
-
msgstr ""
|
148 |
-
|
149 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:35 inc/admin.php:266
|
150 |
-
msgid "Start Date"
|
151 |
-
msgstr ""
|
152 |
-
|
153 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:36 inc/admin.php:270
|
154 |
-
msgid "End Date"
|
155 |
-
msgstr ""
|
156 |
-
|
157 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:37
|
158 |
-
#: classes/class-wpzerospam-log-table.php:216 inc/admin.php:262
|
159 |
-
msgid "Reason"
|
160 |
-
msgstr ""
|
161 |
-
|
162 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:67
|
163 |
-
#: classes/class-wpzerospam-log-table.php:68
|
164 |
-
msgid "Filter by type"
|
165 |
-
msgstr ""
|
166 |
-
|
167 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:71
|
168 |
-
#: classes/class-wpzerospam-log-table.php:73
|
169 |
-
msgid "All types"
|
170 |
-
msgstr ""
|
171 |
-
|
172 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:72 inc/admin.php:258
|
173 |
-
msgid "Permanent"
|
174 |
-
msgstr ""
|
175 |
-
|
176 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:73 inc/admin.php:257
|
177 |
-
msgid "Temporary"
|
178 |
-
msgstr ""
|
179 |
-
|
180 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:136
|
181 |
-
msgid ""
|
182 |
-
"Comment <span class=\"wpzerospam-small\">(<strong>permanently</strong> auto-"
|
183 |
-
"blocked)</span>"
|
184 |
-
msgstr ""
|
185 |
-
|
186 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:139
|
187 |
-
msgid "Comment <span class=\"wpzerospam-small\">(auto-blocked)</span>"
|
188 |
-
msgstr ""
|
189 |
-
|
190 |
-
#: classes/class-wpzerospam-log-table.php:20
|
191 |
-
msgid "Spam Detection"
|
192 |
-
msgstr ""
|
193 |
-
|
194 |
-
#: classes/class-wpzerospam-log-table.php:21 inc/admin.php:60 inc/admin.php:61
|
195 |
-
#: inc/admin.php:591 templates/map.php:97
|
196 |
-
msgid "Spam Detections"
|
197 |
-
msgstr ""
|
198 |
-
|
199 |
-
#: classes/class-wpzerospam-log-table.php:32
|
200 |
-
#: classes/class-wpzerospam-log-table.php:158
|
201 |
-
msgid "Date"
|
202 |
-
msgstr ""
|
203 |
-
|
204 |
-
#: classes/class-wpzerospam-log-table.php:35
|
205 |
-
#: classes/class-wpzerospam-log-table.php:169
|
206 |
-
msgid "Country"
|
207 |
-
msgstr ""
|
208 |
-
|
209 |
-
#: classes/class-wpzerospam-log-table.php:36
|
210 |
-
#: classes/class-wpzerospam-log-table.php:176
|
211 |
-
msgid "Region"
|
212 |
-
msgstr ""
|
213 |
-
|
214 |
-
#: classes/class-wpzerospam-log-table.php:37
|
215 |
-
#: classes/class-wpzerospam-log-table.php:183
|
216 |
-
msgid "City"
|
217 |
-
msgstr ""
|
218 |
-
|
219 |
-
#: classes/class-wpzerospam-log-table.php:39
|
220 |
-
#: classes/class-wpzerospam-log-table.php:101 templates/ip-list.php:63
|
221 |
-
msgid "Block IP"
|
222 |
-
msgstr ""
|
223 |
-
|
224 |
-
#: classes/class-wpzerospam-log-table.php:99 templates/ip-list.php:60
|
225 |
-
msgid "Blocked"
|
226 |
-
msgstr ""
|
227 |
-
|
228 |
-
#: classes/class-wpzerospam-log-table.php:153
|
229 |
-
msgid "Page URL"
|
230 |
-
msgstr ""
|
231 |
-
|
232 |
-
#: classes/class-wpzerospam-log-table.php:198
|
233 |
-
msgid "Sanitized User Login"
|
234 |
-
msgstr ""
|
235 |
-
|
236 |
-
#: classes/class-wpzerospam-log-table.php:204
|
237 |
-
msgid "User Email"
|
238 |
-
msgstr ""
|
239 |
-
|
240 |
-
#: classes/class-wpzerospam-log-table.php:210
|
241 |
-
msgid "Errors"
|
242 |
-
msgstr ""
|
243 |
-
|
244 |
-
#: classes/class-wpzerospam-log-table.php:224
|
245 |
-
msgid "Form Action"
|
246 |
-
msgstr ""
|
247 |
-
|
248 |
-
#: classes/class-wpzerospam-log-table.php:230
|
249 |
-
msgid "Form ID"
|
250 |
-
msgstr ""
|
251 |
-
|
252 |
-
#: classes/class-wpzerospam-log-table.php:236
|
253 |
-
msgid "Form Key"
|
254 |
-
msgstr ""
|
255 |
-
|
256 |
-
#: classes/class-wpzerospam-log-table.php:242
|
257 |
-
msgid "Item Key"
|
258 |
-
msgstr ""
|
259 |
-
|
260 |
-
#: classes/class-wpzerospam-log-table.php:248
|
261 |
-
msgid "Form Values"
|
262 |
-
msgstr ""
|
263 |
-
|
264 |
-
#: classes/class-wpzerospam-log-table.php:258
|
265 |
-
msgid "Source"
|
266 |
-
msgstr ""
|
267 |
-
|
268 |
-
#: classes/class-wpzerospam-log-table.php:288
|
269 |
-
msgid "Delete Selected"
|
270 |
-
msgstr ""
|
271 |
-
|
272 |
-
#: inc/admin.php:41 inc/admin.php:51
|
273 |
-
msgid "WordPress Zero Spam Dashboard"
|
274 |
-
msgstr ""
|
275 |
-
|
276 |
-
#: inc/admin.php:42
|
277 |
-
msgid "WP Zero Spam"
|
278 |
-
msgstr ""
|
279 |
-
|
280 |
-
#: inc/admin.php:52
|
281 |
-
msgid "Dashboard"
|
282 |
-
msgstr ""
|
283 |
-
|
284 |
-
#: inc/admin.php:69
|
285 |
-
msgid "Blocked IP Addresses"
|
286 |
-
msgstr ""
|
287 |
-
|
288 |
-
#: inc/admin.php:78 inc/admin.php:79
|
289 |
-
msgid "Blacklisted IPs"
|
290 |
-
msgstr ""
|
291 |
-
|
292 |
-
#: inc/admin.php:87
|
293 |
-
msgid "WordPress Zero Spam Settings"
|
294 |
-
msgstr ""
|
295 |
-
|
296 |
-
#: inc/admin.php:88 inc/admin.php:422
|
297 |
-
msgid "Settings"
|
298 |
-
msgstr ""
|
299 |
-
|
300 |
-
#: inc/admin.php:118 inc/admin.php:147 inc/admin.php:293
|
301 |
-
msgid "Search IPs"
|
302 |
-
msgstr ""
|
303 |
-
|
304 |
-
#: inc/admin.php:221
|
305 |
-
msgid "Please enter a valid IP address."
|
306 |
-
msgstr ""
|
307 |
-
|
308 |
-
#: inc/admin.php:224
|
309 |
-
msgid "Please select a valid type."
|
310 |
-
msgstr ""
|
311 |
-
|
312 |
-
#: inc/admin.php:227
|
313 |
-
msgid "Please select a date & time when the temporary block should end."
|
314 |
-
msgstr ""
|
315 |
-
|
316 |
-
#: inc/admin.php:236
|
317 |
-
msgid "The blocked IP has been successfully added."
|
318 |
-
msgstr ""
|
319 |
-
|
320 |
-
#: inc/admin.php:243 inc/admin.php:274
|
321 |
-
msgid "Add Blocked IP"
|
322 |
-
msgstr ""
|
323 |
-
|
324 |
-
#: inc/admin.php:263
|
325 |
-
msgid "e.g. Spammed form"
|
326 |
-
msgstr ""
|
327 |
-
|
328 |
-
#: inc/admin.php:267 inc/admin.php:271
|
329 |
-
msgid "Optional"
|
330 |
-
msgstr ""
|
331 |
-
|
332 |
-
#: inc/admin.php:314
|
333 |
-
msgid "Statistics"
|
334 |
-
msgstr ""
|
335 |
-
|
336 |
-
#: inc/admin.php:441
|
337 |
-
msgid "General Settings"
|
338 |
-
msgstr ""
|
339 |
-
|
340 |
-
#: inc/admin.php:442
|
341 |
-
msgid "Auto-block Settings"
|
342 |
-
msgstr ""
|
343 |
-
|
344 |
-
#: inc/admin.php:443
|
345 |
-
msgid "On-site Spam Prevention"
|
346 |
-
msgstr ""
|
347 |
-
|
348 |
-
#: inc/admin.php:444
|
349 |
-
msgid "Integrations & Third-party APIs"
|
350 |
-
msgstr ""
|
351 |
-
|
352 |
-
#: inc/admin.php:447
|
353 |
-
msgid "Cookie Expiration"
|
354 |
-
msgstr ""
|
355 |
-
|
356 |
-
#: inc/admin.php:453
|
357 |
-
msgid "days"
|
358 |
-
msgstr ""
|
359 |
-
|
360 |
-
#: inc/admin.php:457
|
361 |
-
msgid "Share Spam Detections"
|
362 |
-
msgstr ""
|
363 |
-
|
364 |
-
#: inc/admin.php:463 inc/admin.php:474 inc/admin.php:545 inc/admin.php:628
|
365 |
-
#: inc/admin.php:639 inc/admin.php:652 inc/admin.php:664 inc/admin.php:677
|
366 |
-
#: inc/admin.php:690 inc/admin.php:703 inc/admin.php:716
|
367 |
-
#: integrations/comments/comments.php:25 integrations/comments/comments.php:36
|
368 |
-
#: integrations/comments/comments.php:47
|
369 |
-
msgid "Enabled"
|
370 |
-
msgstr ""
|
371 |
-
|
372 |
-
#: inc/admin.php:468
|
373 |
-
msgid "Auto-block IPs"
|
374 |
-
msgstr ""
|
375 |
-
|
376 |
-
#: inc/admin.php:480
|
377 |
-
msgid "Auto-block Period"
|
378 |
-
msgstr ""
|
379 |
-
|
380 |
-
#: inc/admin.php:486
|
381 |
-
msgid "minutes"
|
382 |
-
msgstr ""
|
383 |
-
|
384 |
-
#: inc/admin.php:491
|
385 |
-
msgid "Permanently Auto-block"
|
386 |
-
msgstr ""
|
387 |
-
|
388 |
-
#: inc/admin.php:500
|
389 |
-
msgid "API Timeout"
|
390 |
-
msgstr ""
|
391 |
-
|
392 |
-
#: inc/admin.php:506
|
393 |
-
msgid "seconds"
|
394 |
-
msgstr ""
|
395 |
-
|
396 |
-
#: inc/admin.php:511
|
397 |
-
msgid "ipstack API Key"
|
398 |
-
msgstr ""
|
399 |
-
|
400 |
-
#: inc/admin.php:514
|
401 |
-
msgid "Enter your ipstack API key."
|
402 |
-
msgstr ""
|
403 |
-
|
404 |
-
#: inc/admin.php:521
|
405 |
-
msgid "BotScout API Key"
|
406 |
-
msgstr ""
|
407 |
-
|
408 |
-
#: inc/admin.php:525
|
409 |
-
msgid "Enter your free BotScout API key."
|
410 |
-
msgstr ""
|
411 |
-
|
412 |
-
#: inc/admin.php:530
|
413 |
-
msgid "BotScout Count Minimum"
|
414 |
-
msgstr ""
|
415 |
-
|
416 |
-
#: inc/admin.php:550
|
417 |
-
msgid "Stop Forum Spam Confidence Minimum"
|
418 |
-
msgstr ""
|
419 |
-
|
420 |
-
#: inc/admin.php:556
|
421 |
-
msgid "%"
|
422 |
-
msgstr ""
|
423 |
-
|
424 |
-
#: inc/admin.php:565 inc/admin.php:596
|
425 |
-
msgid "Redirect user"
|
426 |
-
msgstr ""
|
427 |
-
|
428 |
-
#: inc/admin.php:566 inc/admin.php:597
|
429 |
-
msgid ""
|
430 |
-
"Display a <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/"
|
431 |
-
"Status/403\" target=\"_blank\"><code>403 Forbidden</code></a> error"
|
432 |
-
msgstr ""
|
433 |
-
|
434 |
-
#: inc/admin.php:572
|
435 |
-
msgid "Redirect for Blocked Users"
|
436 |
-
msgstr ""
|
437 |
-
|
438 |
-
#: inc/admin.php:581
|
439 |
-
msgid "Blocked Message"
|
440 |
-
msgstr ""
|
441 |
-
|
442 |
-
#: inc/admin.php:586 inc/utilities.php:115
|
443 |
-
msgid ""
|
444 |
-
"You have been blocked from visiting this site by WordPress Zero Spam due to "
|
445 |
-
"detected spam activity."
|
446 |
-
msgstr ""
|
447 |
-
|
448 |
-
#: inc/admin.php:603
|
449 |
-
msgid "Redirect for Spam"
|
450 |
-
msgstr ""
|
451 |
-
|
452 |
-
#: inc/admin.php:612
|
453 |
-
msgid "Spam Detection Message"
|
454 |
-
msgstr ""
|
455 |
-
|
456 |
-
#: inc/admin.php:617 inc/utilities.php:114
|
457 |
-
msgid "There was a problem with your submission. Please go back and try again."
|
458 |
-
msgstr ""
|
459 |
-
|
460 |
-
#: inc/admin.php:622
|
461 |
-
msgid "Log Blocked IPs"
|
462 |
-
msgstr ""
|
463 |
-
|
464 |
-
#: inc/admin.php:633
|
465 |
-
msgid "Log Spam Detections"
|
466 |
-
msgstr ""
|
467 |
-
|
468 |
-
#: inc/admin.php:646
|
469 |
-
msgid "Verify Registrations"
|
470 |
-
msgstr ""
|
471 |
-
|
472 |
-
#: inc/admin.php:658
|
473 |
-
msgid "Verify CF7 Submissions"
|
474 |
-
msgstr ""
|
475 |
-
|
476 |
-
#: inc/admin.php:671
|
477 |
-
msgid "Verify BuddyPress Registrations"
|
478 |
-
msgstr ""
|
479 |
-
|
480 |
-
#: inc/admin.php:684
|
481 |
-
msgid "Verify WPForms Submissions"
|
482 |
-
msgstr ""
|
483 |
-
|
484 |
-
#: inc/admin.php:697
|
485 |
-
msgid "Verify Fluent Form Submissions"
|
486 |
-
msgstr ""
|
487 |
-
|
488 |
-
#: inc/admin.php:710
|
489 |
-
msgid "Verify Formidable Form Submissions"
|
490 |
-
msgstr ""
|
491 |
-
|
492 |
-
#: inc/admin.php:722
|
493 |
-
msgid "IP Whitelist"
|
494 |
-
msgstr ""
|
495 |
-
|
496 |
-
#: inc/admin.php:727
|
497 |
-
msgid "e.g. xxx.xxx.x.x"
|
498 |
-
msgstr ""
|
499 |
-
|
500 |
-
#: inc/utilities.php:324
|
501 |
-
msgid "Access Blocked"
|
502 |
-
msgstr ""
|
503 |
-
|
504 |
-
#: integrations/comments/comments.php:19
|
505 |
-
msgid "Strip Comment Links"
|
506 |
-
msgstr ""
|
507 |
-
|
508 |
-
#: integrations/comments/comments.php:30
|
509 |
-
msgid "Strip Comment Author Links"
|
510 |
-
msgstr ""
|
511 |
-
|
512 |
-
#: integrations/comments/comments.php:41
|
513 |
-
msgid "Detect Comment Spam"
|
514 |
-
msgstr ""
|
515 |
-
|
516 |
-
#: integrations/comments/comments.php:93
|
517 |
-
msgid "Comment Post"
|
518 |
-
msgstr ""
|
519 |
-
|
520 |
-
#: integrations/comments/comments.php:96 integrations/comments/comments.php:119
|
521 |
-
msgid "Author"
|
522 |
-
msgstr ""
|
523 |
-
|
524 |
-
#: integrations/comments/comments.php:99 integrations/comments/comments.php:124
|
525 |
-
msgid "Email"
|
526 |
-
msgstr ""
|
527 |
-
|
528 |
-
#: integrations/comments/comments.php:102
|
529 |
-
#: integrations/comments/comments.php:129
|
530 |
-
msgid "Website"
|
531 |
-
msgstr ""
|
532 |
-
|
533 |
-
#: integrations/comments/comments.php:105
|
534 |
-
#: integrations/comments/comments.php:133
|
535 |
-
#: integrations/comments/comments.php:286
|
536 |
-
msgid "Comment"
|
537 |
-
msgstr ""
|
538 |
-
|
539 |
-
#: integrations/comments/comments.php:108
|
540 |
-
msgid "Comment Type"
|
541 |
-
msgstr ""
|
542 |
-
|
543 |
-
#: integrations/comments/comments.php:111
|
544 |
-
msgid "Comment Parent ID"
|
545 |
-
msgstr ""
|
546 |
-
|
547 |
-
#: integrations/comments/comments.php:136
|
548 |
-
msgid "User IP"
|
549 |
-
msgstr ""
|
550 |
-
|
551 |
-
#: integrations/comments/comments.php:139
|
552 |
-
msgid "User Agent"
|
553 |
-
msgstr ""
|
554 |
-
|
555 |
-
#: integrations/comments/comments.php:142
|
556 |
-
msgid "Site"
|
557 |
-
msgstr ""
|
558 |
-
|
559 |
-
#: integrations/comments/comments.php:145
|
560 |
-
msgid "Site Language"
|
561 |
-
msgstr ""
|
562 |
-
|
563 |
-
#: integrations/comments/comments.php:148
|
564 |
-
msgid "Site Charset"
|
565 |
-
msgstr ""
|
566 |
-
|
567 |
-
#: integrations/comments/comments.php:151
|
568 |
-
msgid "Permalink"
|
569 |
-
msgstr ""
|
570 |
-
|
571 |
-
#: integrations/comments/comments.php:159
|
572 |
-
msgid "Akismet Result"
|
573 |
-
msgstr ""
|
574 |
-
|
575 |
-
#: integrations/comments/comments.php:162
|
576 |
-
msgid "Akismet Pro Tip"
|
577 |
-
msgstr ""
|
578 |
-
|
579 |
-
#: templates/callout.php:12
|
580 |
-
msgid ""
|
581 |
-
"Are you a fan of the <a href=\"https://benmarshall.me/wordpress-zero-spam/?"
|
582 |
-
"utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=admin\" "
|
583 |
-
"target=\"_blank\">WordPress Zero Spam</a> plugin? Show your support."
|
584 |
-
msgstr ""
|
585 |
-
|
586 |
-
#: templates/callout.php:13
|
587 |
-
msgid ""
|
588 |
-
"Help support the continued development of the WordPress Zero Spam plugin by "
|
589 |
-
"<a href=\"https://benmarshall.me/donate?"
|
590 |
-
"utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=admin\" "
|
591 |
-
"target=\"_blank\">donating today</a>. Your donation goes towards the time it "
|
592 |
-
"takes to develop new features & updates, but also helps provide pro bono "
|
593 |
-
"work for nonprofits. <a href=\"https://benmarshall.me/donate?"
|
594 |
-
"utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=admin\" "
|
595 |
-
"target=\"_blank\">Learn more</a>."
|
596 |
-
msgstr ""
|
597 |
-
|
598 |
-
#: templates/callout.php:14
|
599 |
-
msgid "For the latest updates,"
|
600 |
-
msgstr ""
|
601 |
-
|
602 |
-
#: templates/callout.php:14
|
603 |
-
msgid "follow us on Twitter"
|
604 |
-
msgstr ""
|
605 |
-
|
606 |
-
#: templates/callout.php:14
|
607 |
-
msgid "Facebook"
|
608 |
-
msgstr ""
|
609 |
-
|
610 |
-
#: templates/callout.php:14
|
611 |
-
msgid "or"
|
612 |
-
msgstr ""
|
613 |
-
|
614 |
-
#: templates/callout.php:14
|
615 |
-
msgid "visit our website"
|
616 |
-
msgstr ""
|
617 |
-
|
618 |
-
#: templates/callout.php:17
|
619 |
-
msgid "Submit Bug/Feature Request"
|
620 |
-
msgstr ""
|
621 |
-
|
622 |
-
#: templates/callout.php:18
|
623 |
-
msgid "Fork on Github"
|
624 |
-
msgstr ""
|
625 |
-
|
626 |
-
#: templates/callout.php:19
|
627 |
-
msgid "Show your Support — Donate"
|
628 |
-
msgstr ""
|
629 |
-
|
630 |
-
#: templates/callout.php:23
|
631 |
-
msgid "Your IP Address:"
|
632 |
-
msgstr ""
|
633 |
-
|
634 |
-
#: templates/countries-pie-chart.php:12
|
635 |
-
msgid "Most Spam by Country"
|
636 |
-
msgstr ""
|
637 |
-
|
638 |
-
#: templates/countries-pie-chart.php:67 templates/ip-list.php:71
|
639 |
-
#: templates/regions-pie-chart.php:82 templates/spam-line-chart.php:58
|
640 |
-
msgid "No data to report yet."
|
641 |
-
msgstr ""
|
642 |
-
|
643 |
-
#: templates/ip-list.php:12
|
644 |
-
msgid "Most Spam by IP Address"
|
645 |
-
msgstr ""
|
646 |
-
|
647 |
-
#: templates/map.php:11
|
648 |
-
msgid "Spam Detections World Map"
|
649 |
-
msgstr ""
|
650 |
-
|
651 |
-
#: templates/map.php:103
|
652 |
-
msgid "<strong>Enter your <a href=\""
|
653 |
-
msgstr ""
|
654 |
-
|
655 |
-
#: templates/regions-pie-chart.php:12
|
656 |
-
msgid "Most Spam by Region"
|
657 |
-
msgstr ""
|
658 |
-
|
659 |
-
#: templates/spam-line-chart.php:10
|
660 |
-
msgid "Spam by Date"
|
661 |
-
msgstr ""
|
662 |
-
|
663 |
-
#. Plugin Name of the plugin/theme
|
664 |
-
msgid "WordPress Zero Spam"
|
665 |
-
msgstr ""
|
666 |
-
|
667 |
-
#. Plugin URI of the plugin/theme
|
668 |
-
msgid "https://benmarshall.me/wordpress-zero-spam"
|
669 |
-
msgstr ""
|
670 |
-
|
671 |
-
#. Description of the plugin/theme
|
672 |
-
msgid ""
|
673 |
-
"Tired of all the useless and bloated WordPress spam plugins? The WordPress "
|
674 |
-
"Zero Spam plugin makes blocking spam a cinch. <strong>Just install, activate "
|
675 |
-
"and say goodbye to spam.</strong> Based on work by <a href=\"http://"
|
676 |
-
"davidwalsh.name/wordpress-comment-spam\" target=\"_blank\">David Walsh</a>."
|
677 |
-
msgstr ""
|
678 |
-
|
679 |
-
#. Author of the plugin/theme
|
680 |
-
msgid "Ben Marshall"
|
681 |
-
msgstr ""
|
682 |
-
|
683 |
-
#. Author URI of the plugin/theme
|
684 |
-
msgid "https://benmarshall.me"
|
685 |
-
msgstr ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
languages/zero-spam-it_IT.pot
DELETED
@@ -1,875 +0,0 @@
|
|
1 |
-
#, fuzzy
|
2 |
-
msgid ""
|
3 |
-
msgstr ""
|
4 |
-
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
|
5 |
-
"Project-Id-Version: WordPress Zero Spam\n"
|
6 |
-
"POT-Creation-Date: 2020-08-07 13:08-0500\n"
|
7 |
-
"PO-Revision-Date: 2020-08-07 13:06-0500\n"
|
8 |
-
"Last-Translator: \n"
|
9 |
-
"Language-Team: \n"
|
10 |
-
"MIME-Version: 1.0\n"
|
11 |
-
"Content-Type: text/plain; charset=UTF-8\n"
|
12 |
-
"Content-Transfer-Encoding: 8bit\n"
|
13 |
-
"X-Generator: Poedit 2.4\n"
|
14 |
-
"X-Poedit-Basepath: ..\n"
|
15 |
-
"X-Poedit-Flags-xgettext: --add-comments=translators:\n"
|
16 |
-
"X-Poedit-WPHeader: wordpress-zero-spam.php\n"
|
17 |
-
"X-Poedit-SourceCharset: UTF-8\n"
|
18 |
-
"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
|
19 |
-
"esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;"
|
20 |
-
"_nx_noop:3c,1,2;__ngettext_noop:1,2\n"
|
21 |
-
"X-Poedit-SearchPath-0: .\n"
|
22 |
-
"X-Poedit-SearchPathExcluded-0: *.min.js\n"
|
23 |
-
|
24 |
-
#: classes/class-wpzerospam-blacklisted-table.php:20
|
25 |
-
msgid "Blacklist"
|
26 |
-
msgstr ""
|
27 |
-
|
28 |
-
#: classes/class-wpzerospam-blacklisted-table.php:21
|
29 |
-
msgid "Blacklist IPs"
|
30 |
-
msgstr ""
|
31 |
-
|
32 |
-
#: classes/class-wpzerospam-blacklisted-table.php:32
|
33 |
-
#: classes/class-wpzerospam-blacklisted-table.php:131
|
34 |
-
msgid "Last Updated"
|
35 |
-
msgstr ""
|
36 |
-
|
37 |
-
#: classes/class-wpzerospam-blacklisted-table.php:33
|
38 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:32
|
39 |
-
#: classes/class-wpzerospam-log-table.php:34 inc/admin.php:245
|
40 |
-
msgid "IP Address"
|
41 |
-
msgstr ""
|
42 |
-
|
43 |
-
#: classes/class-wpzerospam-blacklisted-table.php:34
|
44 |
-
#: classes/class-wpzerospam-blacklisted-table.php:136
|
45 |
-
msgid "Service"
|
46 |
-
msgstr ""
|
47 |
-
|
48 |
-
#: classes/class-wpzerospam-blacklisted-table.php:35
|
49 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:38
|
50 |
-
msgid "Attempts"
|
51 |
-
msgstr ""
|
52 |
-
|
53 |
-
#: classes/class-wpzerospam-blacklisted-table.php:36
|
54 |
-
#: classes/class-wpzerospam-log-table.php:38
|
55 |
-
msgid "Details"
|
56 |
-
msgstr ""
|
57 |
-
|
58 |
-
#: classes/class-wpzerospam-blacklisted-table.php:63
|
59 |
-
msgid "Filter by service"
|
60 |
-
msgstr ""
|
61 |
-
|
62 |
-
#: classes/class-wpzerospam-blacklisted-table.php:67
|
63 |
-
msgid "All services"
|
64 |
-
msgstr ""
|
65 |
-
|
66 |
-
#: classes/class-wpzerospam-blacklisted-table.php:68
|
67 |
-
msgid "BotScout"
|
68 |
-
msgstr ""
|
69 |
-
|
70 |
-
#: classes/class-wpzerospam-blacklisted-table.php:69 inc/admin.php:568
|
71 |
-
msgid "Stop Forum Spam"
|
72 |
-
msgstr ""
|
73 |
-
|
74 |
-
#: classes/class-wpzerospam-blacklisted-table.php:70
|
75 |
-
msgid "Zero Spam"
|
76 |
-
msgstr ""
|
77 |
-
|
78 |
-
#: classes/class-wpzerospam-blacklisted-table.php:73
|
79 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:76
|
80 |
-
#: classes/class-wpzerospam-log-table.php:79
|
81 |
-
msgid "Filter"
|
82 |
-
msgstr ""
|
83 |
-
|
84 |
-
#: classes/class-wpzerospam-blacklisted-table.php:116
|
85 |
-
#: classes/class-wpzerospam-log-table.php:140
|
86 |
-
msgid "No details available."
|
87 |
-
msgstr ""
|
88 |
-
|
89 |
-
#: classes/class-wpzerospam-blacklisted-table.php:119
|
90 |
-
#: classes/class-wpzerospam-log-table.php:143
|
91 |
-
msgid "View"
|
92 |
-
msgstr ""
|
93 |
-
|
94 |
-
#: classes/class-wpzerospam-blacklisted-table.php:126
|
95 |
-
#: classes/class-wpzerospam-log-table.php:148
|
96 |
-
msgid "Detected Spam IP"
|
97 |
-
msgstr ""
|
98 |
-
|
99 |
-
#: classes/class-wpzerospam-blacklisted-table.php:160
|
100 |
-
msgid "Appears"
|
101 |
-
msgstr ""
|
102 |
-
|
103 |
-
#: classes/class-wpzerospam-blacklisted-table.php:166
|
104 |
-
msgid "Confidence"
|
105 |
-
msgstr ""
|
106 |
-
|
107 |
-
#: classes/class-wpzerospam-blacklisted-table.php:172
|
108 |
-
msgid "Frequency"
|
109 |
-
msgstr ""
|
110 |
-
|
111 |
-
#: classes/class-wpzerospam-blacklisted-table.php:178
|
112 |
-
msgid "Last Seen"
|
113 |
-
msgstr ""
|
114 |
-
|
115 |
-
#: classes/class-wpzerospam-blacklisted-table.php:184
|
116 |
-
msgid "ASN"
|
117 |
-
msgstr ""
|
118 |
-
|
119 |
-
#: classes/class-wpzerospam-blacklisted-table.php:208
|
120 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:164
|
121 |
-
msgid "Delete"
|
122 |
-
msgstr ""
|
123 |
-
|
124 |
-
#: classes/class-wpzerospam-blacklisted-table.php:209
|
125 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:165
|
126 |
-
#: classes/class-wpzerospam-log-table.php:289
|
127 |
-
msgid "Delete All Entries"
|
128 |
-
msgstr ""
|
129 |
-
|
130 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:20
|
131 |
-
msgid "Blocked IP"
|
132 |
-
msgstr ""
|
133 |
-
|
134 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:21 inc/admin.php:70
|
135 |
-
#: inc/admin.php:601
|
136 |
-
msgid "Blocked IPs"
|
137 |
-
msgstr ""
|
138 |
-
|
139 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:33
|
140 |
-
#: classes/class-wpzerospam-log-table.php:33
|
141 |
-
#: classes/class-wpzerospam-log-table.php:163 inc/admin.php:255
|
142 |
-
msgid "Type"
|
143 |
-
msgstr ""
|
144 |
-
|
145 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:34
|
146 |
-
msgid "Date Added"
|
147 |
-
msgstr ""
|
148 |
-
|
149 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:35 inc/admin.php:266
|
150 |
-
msgid "Start Date"
|
151 |
-
msgstr ""
|
152 |
-
|
153 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:36 inc/admin.php:270
|
154 |
-
msgid "End Date"
|
155 |
-
msgstr ""
|
156 |
-
|
157 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:37
|
158 |
-
#: classes/class-wpzerospam-log-table.php:216 inc/admin.php:262
|
159 |
-
msgid "Reason"
|
160 |
-
msgstr ""
|
161 |
-
|
162 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:67
|
163 |
-
#: classes/class-wpzerospam-log-table.php:68
|
164 |
-
msgid "Filter by type"
|
165 |
-
msgstr ""
|
166 |
-
|
167 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:71
|
168 |
-
#: classes/class-wpzerospam-log-table.php:73
|
169 |
-
msgid "All types"
|
170 |
-
msgstr ""
|
171 |
-
|
172 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:72
|
173 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:103 inc/admin.php:258
|
174 |
-
msgid "Permanent"
|
175 |
-
msgstr ""
|
176 |
-
|
177 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:73
|
178 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:106 inc/admin.php:257
|
179 |
-
msgid "Temporary"
|
180 |
-
msgstr ""
|
181 |
-
|
182 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:138
|
183 |
-
msgid ""
|
184 |
-
"Comment <span class=\"wpzerospam-small\">(<strong>permanently</strong> auto-"
|
185 |
-
"blocked)</span>"
|
186 |
-
msgstr ""
|
187 |
-
|
188 |
-
#: classes/class-wpzerospam-blocked-ip-table.php:146
|
189 |
-
msgid "Comment <span class=\"wpzerospam-small\">(auto-blocked)</span>"
|
190 |
-
msgstr ""
|
191 |
-
|
192 |
-
#: classes/class-wpzerospam-log-table.php:20
|
193 |
-
msgid "Spam Detection"
|
194 |
-
msgstr ""
|
195 |
-
|
196 |
-
#: classes/class-wpzerospam-log-table.php:21 inc/admin.php:60 inc/admin.php:61
|
197 |
-
#: inc/admin.php:638 templates/map.php:97
|
198 |
-
msgid "Spam Detections"
|
199 |
-
msgstr ""
|
200 |
-
|
201 |
-
#: classes/class-wpzerospam-log-table.php:32
|
202 |
-
#: classes/class-wpzerospam-log-table.php:158
|
203 |
-
msgid "Date"
|
204 |
-
msgstr ""
|
205 |
-
|
206 |
-
#: classes/class-wpzerospam-log-table.php:35
|
207 |
-
#: classes/class-wpzerospam-log-table.php:169
|
208 |
-
msgid "Country"
|
209 |
-
msgstr ""
|
210 |
-
|
211 |
-
#: classes/class-wpzerospam-log-table.php:36
|
212 |
-
#: classes/class-wpzerospam-log-table.php:176
|
213 |
-
msgid "Region"
|
214 |
-
msgstr ""
|
215 |
-
|
216 |
-
#: classes/class-wpzerospam-log-table.php:37
|
217 |
-
#: classes/class-wpzerospam-log-table.php:183
|
218 |
-
msgid "City"
|
219 |
-
msgstr ""
|
220 |
-
|
221 |
-
#: classes/class-wpzerospam-log-table.php:39
|
222 |
-
#: classes/class-wpzerospam-log-table.php:101 templates/ip-list.php:63
|
223 |
-
msgid "Block IP"
|
224 |
-
msgstr ""
|
225 |
-
|
226 |
-
#: classes/class-wpzerospam-log-table.php:99 templates/ip-list.php:60
|
227 |
-
msgid "Blocked"
|
228 |
-
msgstr ""
|
229 |
-
|
230 |
-
#: classes/class-wpzerospam-log-table.php:153
|
231 |
-
msgid "Page URL"
|
232 |
-
msgstr ""
|
233 |
-
|
234 |
-
#: classes/class-wpzerospam-log-table.php:198
|
235 |
-
msgid "Sanitized User Login"
|
236 |
-
msgstr ""
|
237 |
-
|
238 |
-
#: classes/class-wpzerospam-log-table.php:204
|
239 |
-
msgid "User Email"
|
240 |
-
msgstr ""
|
241 |
-
|
242 |
-
#: classes/class-wpzerospam-log-table.php:210
|
243 |
-
msgid "Errors"
|
244 |
-
msgstr ""
|
245 |
-
|
246 |
-
#: classes/class-wpzerospam-log-table.php:224
|
247 |
-
msgid "Form Action"
|
248 |
-
msgstr ""
|
249 |
-
|
250 |
-
#: classes/class-wpzerospam-log-table.php:230
|
251 |
-
msgid "Form ID"
|
252 |
-
msgstr ""
|
253 |
-
|
254 |
-
#: classes/class-wpzerospam-log-table.php:236
|
255 |
-
msgid "Form Key"
|
256 |
-
msgstr ""
|
257 |
-
|
258 |
-
#: classes/class-wpzerospam-log-table.php:242
|
259 |
-
msgid "Item Key"
|
260 |
-
msgstr ""
|
261 |
-
|
262 |
-
#: classes/class-wpzerospam-log-table.php:248
|
263 |
-
msgid "Form Values"
|
264 |
-
msgstr ""
|
265 |
-
|
266 |
-
#: classes/class-wpzerospam-log-table.php:258
|
267 |
-
msgid "Source"
|
268 |
-
msgstr ""
|
269 |
-
|
270 |
-
#: classes/class-wpzerospam-log-table.php:288
|
271 |
-
msgid "Delete Selected"
|
272 |
-
msgstr ""
|
273 |
-
|
274 |
-
#: inc/admin.php:41 inc/admin.php:51
|
275 |
-
msgid "WordPress Zero Spam Dashboard"
|
276 |
-
msgstr ""
|
277 |
-
|
278 |
-
#: inc/admin.php:42
|
279 |
-
msgid "WP Zero Spam"
|
280 |
-
msgstr ""
|
281 |
-
|
282 |
-
#: inc/admin.php:52
|
283 |
-
msgid "Dashboard"
|
284 |
-
msgstr ""
|
285 |
-
|
286 |
-
#: inc/admin.php:69
|
287 |
-
msgid "Blocked IP Addresses"
|
288 |
-
msgstr ""
|
289 |
-
|
290 |
-
#: inc/admin.php:78 inc/admin.php:79
|
291 |
-
msgid "Blacklisted IPs"
|
292 |
-
msgstr ""
|
293 |
-
|
294 |
-
#: inc/admin.php:87
|
295 |
-
msgid "WordPress Zero Spam Settings"
|
296 |
-
msgstr ""
|
297 |
-
|
298 |
-
#: inc/admin.php:88 inc/admin.php:422
|
299 |
-
msgid "Settings"
|
300 |
-
msgstr ""
|
301 |
-
|
302 |
-
#: inc/admin.php:118 inc/admin.php:147 inc/admin.php:293
|
303 |
-
msgid "Search IPs"
|
304 |
-
msgstr ""
|
305 |
-
|
306 |
-
#: inc/admin.php:221
|
307 |
-
msgid "Please enter a valid IP address."
|
308 |
-
msgstr ""
|
309 |
-
|
310 |
-
#: inc/admin.php:224
|
311 |
-
msgid "Please select a valid type."
|
312 |
-
msgstr ""
|
313 |
-
|
314 |
-
#: inc/admin.php:227
|
315 |
-
msgid "Please select a date & time when the temporary block should end."
|
316 |
-
msgstr ""
|
317 |
-
|
318 |
-
#: inc/admin.php:232 inc/admin.php:237
|
319 |
-
msgid "Dismiss this notice."
|
320 |
-
msgstr ""
|
321 |
-
|
322 |
-
#: inc/admin.php:236
|
323 |
-
msgid "The blocked IP has been successfully added."
|
324 |
-
msgstr ""
|
325 |
-
|
326 |
-
#: inc/admin.php:243 inc/admin.php:274
|
327 |
-
msgid "Add Blocked IP"
|
328 |
-
msgstr ""
|
329 |
-
|
330 |
-
#: inc/admin.php:263
|
331 |
-
msgid "e.g. Spammed form"
|
332 |
-
msgstr ""
|
333 |
-
|
334 |
-
#: inc/admin.php:267 inc/admin.php:271
|
335 |
-
msgid "Optional"
|
336 |
-
msgstr ""
|
337 |
-
|
338 |
-
#: inc/admin.php:314
|
339 |
-
msgid "Statistics"
|
340 |
-
msgstr ""
|
341 |
-
|
342 |
-
#: inc/admin.php:409 inc/admin.php:633 inc/utilities.php:115
|
343 |
-
msgid ""
|
344 |
-
"You have been blocked from visiting this site by WordPress Zero Spam due to "
|
345 |
-
"detected spam activity."
|
346 |
-
msgstr ""
|
347 |
-
|
348 |
-
#: inc/admin.php:441
|
349 |
-
msgid "General Settings"
|
350 |
-
msgstr ""
|
351 |
-
|
352 |
-
#: inc/admin.php:442
|
353 |
-
msgid "Auto-block Settings"
|
354 |
-
msgstr ""
|
355 |
-
|
356 |
-
#: inc/admin.php:443
|
357 |
-
msgid "On-site Spam Prevention"
|
358 |
-
msgstr ""
|
359 |
-
|
360 |
-
#: inc/admin.php:444
|
361 |
-
msgid "Integrations & Third-party APIs"
|
362 |
-
msgstr ""
|
363 |
-
|
364 |
-
#: inc/admin.php:447
|
365 |
-
msgid "Cookie Expiration"
|
366 |
-
msgstr ""
|
367 |
-
|
368 |
-
#: inc/admin.php:451
|
369 |
-
msgid ""
|
370 |
-
"Number of days until a user's cookie is expired. Helps boost site "
|
371 |
-
"performance so access & blacklist checks aren't sent each page visit. "
|
372 |
-
"<strong>Minimum recommend is 7 days</strong>."
|
373 |
-
msgstr ""
|
374 |
-
|
375 |
-
#: inc/admin.php:456
|
376 |
-
msgid "days"
|
377 |
-
msgstr ""
|
378 |
-
|
379 |
-
#: inc/admin.php:460
|
380 |
-
msgid "Share Spam Detections"
|
381 |
-
msgstr ""
|
382 |
-
|
383 |
-
#: inc/admin.php:465
|
384 |
-
msgid ""
|
385 |
-
"Help support WordPress Zero Spam and strenghten its ability to detect "
|
386 |
-
"spammers by sharing spam detections. The only data that's shared is the IP "
|
387 |
-
"address, type & site where the spam was detected. <strong>Absolutely no "
|
388 |
-
"personal data is shared.</strong>."
|
389 |
-
msgstr ""
|
390 |
-
|
391 |
-
#: inc/admin.php:469 inc/admin.php:480 inc/admin.php:580 inc/admin.php:681
|
392 |
-
#: inc/admin.php:692 inc/admin.php:705 inc/admin.php:717 inc/admin.php:730
|
393 |
-
#: inc/admin.php:743 inc/admin.php:756 inc/admin.php:769
|
394 |
-
#: integrations/comments/comments.php:25 integrations/comments/comments.php:36
|
395 |
-
#: integrations/comments/comments.php:47
|
396 |
-
msgid "Enabled"
|
397 |
-
msgstr ""
|
398 |
-
|
399 |
-
#: inc/admin.php:474
|
400 |
-
msgid "Auto-block IPs"
|
401 |
-
msgstr ""
|
402 |
-
|
403 |
-
#: inc/admin.php:478
|
404 |
-
msgid "Auto-blocks IPs addresses that trigger a spam detection."
|
405 |
-
msgstr ""
|
406 |
-
|
407 |
-
#: inc/admin.php:486
|
408 |
-
msgid "Auto-block Period"
|
409 |
-
msgstr ""
|
410 |
-
|
411 |
-
#: inc/admin.php:489
|
412 |
-
msgid ""
|
413 |
-
"Number of minutes a user will be blocked from viewing the site after being "
|
414 |
-
"auto-blocked."
|
415 |
-
msgstr ""
|
416 |
-
|
417 |
-
#: inc/admin.php:492
|
418 |
-
msgid "minutes"
|
419 |
-
msgstr ""
|
420 |
-
|
421 |
-
#: inc/admin.php:497
|
422 |
-
msgid "Permanently Auto-block"
|
423 |
-
msgstr ""
|
424 |
-
|
425 |
-
#: inc/admin.php:500
|
426 |
-
msgid "Number of spam detections before an IP is permanently blocked."
|
427 |
-
msgstr ""
|
428 |
-
|
429 |
-
#: inc/admin.php:506
|
430 |
-
msgid "API Timeout"
|
431 |
-
msgstr ""
|
432 |
-
|
433 |
-
#: inc/admin.php:510
|
434 |
-
msgid ""
|
435 |
-
"Number of seconds to allow an API to return a response.<br /><strong>WARNING:"
|
436 |
-
"</strong> Setting this too high could cause your site to load slowly. "
|
437 |
-
"Setting too low may not allow an API enough time to respond with a result. "
|
438 |
-
"<strong>Recommended is 5 seconds.</strong>."
|
439 |
-
msgstr ""
|
440 |
-
|
441 |
-
#: inc/admin.php:515
|
442 |
-
msgid "seconds"
|
443 |
-
msgstr ""
|
444 |
-
|
445 |
-
#: inc/admin.php:520
|
446 |
-
msgid "ipstack API Key"
|
447 |
-
msgstr ""
|
448 |
-
|
449 |
-
#: inc/admin.php:523
|
450 |
-
msgid "Enter your ipstack API key."
|
451 |
-
msgstr ""
|
452 |
-
|
453 |
-
#: inc/admin.php:527
|
454 |
-
#, php-format
|
455 |
-
msgid ""
|
456 |
-
"Enter your <a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer"
|
457 |
-
"\">ipstack API key</a> to enable location-based statistics. Don't have an "
|
458 |
-
"API key? <a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer"
|
459 |
-
"\"><strong>Get one for free!</strong></a>"
|
460 |
-
msgstr ""
|
461 |
-
|
462 |
-
#: inc/admin.php:537
|
463 |
-
msgid "BotScout API Key"
|
464 |
-
msgstr ""
|
465 |
-
|
466 |
-
#: inc/admin.php:541
|
467 |
-
msgid "Enter your free BotScout API key."
|
468 |
-
msgstr ""
|
469 |
-
|
470 |
-
#: inc/admin.php:544
|
471 |
-
#, php-format
|
472 |
-
msgid ""
|
473 |
-
"Enter your BotScout API key to check user IPs against <a href=\"%s\" target="
|
474 |
-
"\"_blank\" rel=\"noopener noreferrer\">BotScout</a>'s blacklist. Don't have "
|
475 |
-
"an API key? <a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer"
|
476 |
-
"\"><strong>Get one for free!</strong></a>"
|
477 |
-
msgstr ""
|
478 |
-
|
479 |
-
#: inc/admin.php:553
|
480 |
-
msgid "BotScout Count Minimum"
|
481 |
-
msgstr ""
|
482 |
-
|
483 |
-
#: inc/admin.php:558
|
484 |
-
#, php-format
|
485 |
-
msgid ""
|
486 |
-
"Minimum <a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer\">count</"
|
487 |
-
"a> an IP must meet before being marked as spam/malicious.<br /"
|
488 |
-
"><strong>WARNING:</strong> Setting this too low could cause users to be "
|
489 |
-
"blocked that shouldn't be, <strong>recommended is 5</strong>."
|
490 |
-
msgstr ""
|
491 |
-
|
492 |
-
#: inc/admin.php:574
|
493 |
-
#, php-format
|
494 |
-
msgid ""
|
495 |
-
"Checks user IPs against <a href=\"%s\" target=\"_blank\" rel=\"noopener "
|
496 |
-
"noreferrer\">Stop Forum Spam</a>'s blacklist."
|
497 |
-
msgstr ""
|
498 |
-
|
499 |
-
#: inc/admin.php:585
|
500 |
-
msgid "Stop Forum Spam Confidence Minimum"
|
501 |
-
msgstr ""
|
502 |
-
|
503 |
-
#: inc/admin.php:590
|
504 |
-
#, php-format
|
505 |
-
msgid ""
|
506 |
-
"Minimum <a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer"
|
507 |
-
"\">confidence score</a> an IP must meet before being marked as spam/"
|
508 |
-
"malicious.<br /><strong>WARNING:</strong> Setting this too low could cause "
|
509 |
-
"users to be blocked that shouldn't be, <strong>recommended is 20%%</strong>."
|
510 |
-
msgstr ""
|
511 |
-
|
512 |
-
#: inc/admin.php:604
|
513 |
-
msgid ""
|
514 |
-
"Determines how blocked IPs are handled when they attempt to visit the site."
|
515 |
-
msgstr ""
|
516 |
-
|
517 |
-
#: inc/admin.php:606 inc/admin.php:643
|
518 |
-
msgid "Redirect user"
|
519 |
-
msgstr ""
|
520 |
-
|
521 |
-
#: inc/admin.php:609 inc/admin.php:646
|
522 |
-
#, php-format
|
523 |
-
msgid ""
|
524 |
-
"Display a <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener"
|
525 |
-
"\"><code>403 Forbidden</code></a> error"
|
526 |
-
msgstr ""
|
527 |
-
|
528 |
-
#: inc/admin.php:619
|
529 |
-
msgid "Redirect for Blocked Users"
|
530 |
-
msgstr ""
|
531 |
-
|
532 |
-
#: inc/admin.php:623
|
533 |
-
msgid "URL blocked users will be taken to."
|
534 |
-
msgstr ""
|
535 |
-
|
536 |
-
#: inc/admin.php:628
|
537 |
-
msgid "Blocked Message"
|
538 |
-
msgstr ""
|
539 |
-
|
540 |
-
#: inc/admin.php:632
|
541 |
-
msgid "The message that will be displayed to a blocked user."
|
542 |
-
msgstr ""
|
543 |
-
|
544 |
-
#: inc/admin.php:641
|
545 |
-
msgid "Determines how users are handled when spam is detected."
|
546 |
-
msgstr ""
|
547 |
-
|
548 |
-
#: inc/admin.php:656
|
549 |
-
msgid "Redirect for Spam"
|
550 |
-
msgstr ""
|
551 |
-
|
552 |
-
#: inc/admin.php:660
|
553 |
-
msgid "URL users will be taken to when a spam submission is detected."
|
554 |
-
msgstr ""
|
555 |
-
|
556 |
-
#: inc/admin.php:665
|
557 |
-
msgid "Spam Detection Message"
|
558 |
-
msgstr ""
|
559 |
-
|
560 |
-
#: inc/admin.php:669
|
561 |
-
msgid "The message that will be displayed when spam is detected."
|
562 |
-
msgstr ""
|
563 |
-
|
564 |
-
#: inc/admin.php:670 inc/utilities.php:114
|
565 |
-
msgid "There was a problem with your submission. Please go back and try again."
|
566 |
-
msgstr ""
|
567 |
-
|
568 |
-
#: inc/admin.php:675
|
569 |
-
msgid "Log Blocked IPs"
|
570 |
-
msgstr ""
|
571 |
-
|
572 |
-
#: inc/admin.php:679
|
573 |
-
msgid "Enables logging of when IPs are blocked from accessing the site."
|
574 |
-
msgstr ""
|
575 |
-
|
576 |
-
#: inc/admin.php:686
|
577 |
-
msgid "Log Spam Detections"
|
578 |
-
msgstr ""
|
579 |
-
|
580 |
-
#: inc/admin.php:690
|
581 |
-
msgid ""
|
582 |
-
"Enables logging of spam detections and provides an admin interface to view "
|
583 |
-
"statistics."
|
584 |
-
msgstr ""
|
585 |
-
|
586 |
-
#: inc/admin.php:699
|
587 |
-
msgid "Verify Registrations"
|
588 |
-
msgstr ""
|
589 |
-
|
590 |
-
#: inc/admin.php:703
|
591 |
-
msgid "Enables spam detection for site registrations."
|
592 |
-
msgstr ""
|
593 |
-
|
594 |
-
#: inc/admin.php:711
|
595 |
-
msgid "Verify CF7 Submissions"
|
596 |
-
msgstr ""
|
597 |
-
|
598 |
-
#: inc/admin.php:715
|
599 |
-
msgid "Enables spam detection for Contact Form 7 submissions."
|
600 |
-
msgstr ""
|
601 |
-
|
602 |
-
#: inc/admin.php:724
|
603 |
-
msgid "Verify BuddyPress Registrations"
|
604 |
-
msgstr ""
|
605 |
-
|
606 |
-
#: inc/admin.php:728
|
607 |
-
msgid "Enables spam detection for BuddyPress registrations."
|
608 |
-
msgstr ""
|
609 |
-
|
610 |
-
#: inc/admin.php:737
|
611 |
-
msgid "Verify WPForms Submissions"
|
612 |
-
msgstr ""
|
613 |
-
|
614 |
-
#: inc/admin.php:741
|
615 |
-
msgid "Enables spam detection for WPForms submissions.zero-spam"
|
616 |
-
msgstr ""
|
617 |
-
|
618 |
-
#: inc/admin.php:750
|
619 |
-
msgid "Verify Fluent Form Submissions"
|
620 |
-
msgstr ""
|
621 |
-
|
622 |
-
#: inc/admin.php:754
|
623 |
-
msgid "Enables spam detection for Fluent Form submissions."
|
624 |
-
msgstr ""
|
625 |
-
|
626 |
-
#: inc/admin.php:763
|
627 |
-
msgid "Verify Formidable Form Submissions"
|
628 |
-
msgstr ""
|
629 |
-
|
630 |
-
#: inc/admin.php:767
|
631 |
-
msgid "Enables spam detection for Formidable form submissions."
|
632 |
-
msgstr ""
|
633 |
-
|
634 |
-
#: inc/admin.php:775
|
635 |
-
msgid "IP Whitelist"
|
636 |
-
msgstr ""
|
637 |
-
|
638 |
-
#: inc/admin.php:779
|
639 |
-
msgid ""
|
640 |
-
"Enter IPs that should be whitelisted (IPs that should never be blocked), one "
|
641 |
-
"per line."
|
642 |
-
msgstr ""
|
643 |
-
|
644 |
-
#: inc/admin.php:780
|
645 |
-
msgid "e.g. xxx.xxx.x.x"
|
646 |
-
msgstr ""
|
647 |
-
|
648 |
-
#: inc/utilities.php:324
|
649 |
-
msgid "Access Blocked"
|
650 |
-
msgstr ""
|
651 |
-
|
652 |
-
#: integrations/buddypress/buddypress.php:13
|
653 |
-
msgid "BuddyPress Registration"
|
654 |
-
msgstr ""
|
655 |
-
|
656 |
-
#: integrations/comments/comments.php:19
|
657 |
-
msgid "Strip Comment Links"
|
658 |
-
msgstr ""
|
659 |
-
|
660 |
-
#: integrations/comments/comments.php:23
|
661 |
-
msgid ""
|
662 |
-
"Spambots commonly post spam links in comments. Enable this option to strip "
|
663 |
-
"links from comments."
|
664 |
-
msgstr ""
|
665 |
-
|
666 |
-
#: integrations/comments/comments.php:30
|
667 |
-
msgid "Strip Comment Author Links"
|
668 |
-
msgstr ""
|
669 |
-
|
670 |
-
#: integrations/comments/comments.php:34
|
671 |
-
msgid ""
|
672 |
-
"Spammers are well-known at injecting malicious links in the comment author "
|
673 |
-
"website field, this option disables it."
|
674 |
-
msgstr ""
|
675 |
-
|
676 |
-
#: integrations/comments/comments.php:41
|
677 |
-
msgid "Detect Comment Spam"
|
678 |
-
msgstr ""
|
679 |
-
|
680 |
-
#: integrations/comments/comments.php:45
|
681 |
-
msgid "Enables comment form submission protection."
|
682 |
-
msgstr ""
|
683 |
-
|
684 |
-
#: integrations/comments/comments.php:93
|
685 |
-
msgid "Comment Post"
|
686 |
-
msgstr ""
|
687 |
-
|
688 |
-
#: integrations/comments/comments.php:96 integrations/comments/comments.php:119
|
689 |
-
msgid "Author"
|
690 |
-
msgstr ""
|
691 |
-
|
692 |
-
#: integrations/comments/comments.php:99 integrations/comments/comments.php:124
|
693 |
-
msgid "Email"
|
694 |
-
msgstr ""
|
695 |
-
|
696 |
-
#: integrations/comments/comments.php:102
|
697 |
-
#: integrations/comments/comments.php:129
|
698 |
-
msgid "Website"
|
699 |
-
msgstr ""
|
700 |
-
|
701 |
-
#: integrations/comments/comments.php:105
|
702 |
-
#: integrations/comments/comments.php:133
|
703 |
-
#: integrations/comments/comments.php:286
|
704 |
-
msgid "Comment"
|
705 |
-
msgstr ""
|
706 |
-
|
707 |
-
#: integrations/comments/comments.php:108
|
708 |
-
msgid "Comment Type"
|
709 |
-
msgstr ""
|
710 |
-
|
711 |
-
#: integrations/comments/comments.php:111
|
712 |
-
msgid "Comment Parent ID"
|
713 |
-
msgstr ""
|
714 |
-
|
715 |
-
#: integrations/comments/comments.php:136
|
716 |
-
msgid "User IP"
|
717 |
-
msgstr ""
|
718 |
-
|
719 |
-
#: integrations/comments/comments.php:139
|
720 |
-
msgid "User Agent"
|
721 |
-
msgstr ""
|
722 |
-
|
723 |
-
#: integrations/comments/comments.php:142
|
724 |
-
msgid "Site"
|
725 |
-
msgstr ""
|
726 |
-
|
727 |
-
#: integrations/comments/comments.php:145
|
728 |
-
msgid "Site Language"
|
729 |
-
msgstr ""
|
730 |
-
|
731 |
-
#: integrations/comments/comments.php:148
|
732 |
-
msgid "Site Charset"
|
733 |
-
msgstr ""
|
734 |
-
|
735 |
-
#: integrations/comments/comments.php:151
|
736 |
-
msgid "Permalink"
|
737 |
-
msgstr ""
|
738 |
-
|
739 |
-
#: integrations/comments/comments.php:159
|
740 |
-
msgid "Akismet Result"
|
741 |
-
msgstr ""
|
742 |
-
|
743 |
-
#: integrations/comments/comments.php:162
|
744 |
-
msgid "Akismet Pro Tip"
|
745 |
-
msgstr ""
|
746 |
-
|
747 |
-
#: integrations/contact-form-7/contact-form-7.php:13
|
748 |
-
msgid "Contact Form 7"
|
749 |
-
msgstr ""
|
750 |
-
|
751 |
-
#: integrations/fluentform/fluentform.php:13
|
752 |
-
msgid "Fluent Forms"
|
753 |
-
msgstr ""
|
754 |
-
|
755 |
-
#: integrations/formidable/formidable.php:15
|
756 |
-
msgid "Formidable Forms"
|
757 |
-
msgstr ""
|
758 |
-
|
759 |
-
#: integrations/registrations/registrations.php:13
|
760 |
-
msgid "Registration"
|
761 |
-
msgstr ""
|
762 |
-
|
763 |
-
#: integrations/wpforms/wpforms.php:13
|
764 |
-
msgid "WPForms"
|
765 |
-
msgstr ""
|
766 |
-
|
767 |
-
#: templates/callout.php:15
|
768 |
-
#, php-format
|
769 |
-
msgid ""
|
770 |
-
"Help support the <a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer"
|
771 |
-
"\">WordPress Zero Spam</a> plugin."
|
772 |
-
msgstr ""
|
773 |
-
|
774 |
-
#: templates/callout.php:24
|
775 |
-
#, php-format
|
776 |
-
msgid ""
|
777 |
-
"Support the continued development of the WPZS by <a href=\"%s\" target="
|
778 |
-
"\"_blank\" rel=\"noopener noreferrer\">donating today</a>. Donation goes "
|
779 |
-
"towards the time it takes to develop new features & updates, but also "
|
780 |
-
"helps provide pro bono work for nonprofits. <a href=\"%s\" target=\"_blank\" "
|
781 |
-
"rel=\"noopener noreferrer\">Learn more</a>."
|
782 |
-
msgstr ""
|
783 |
-
|
784 |
-
#: templates/callout.php:34
|
785 |
-
#, php-format
|
786 |
-
msgid ""
|
787 |
-
"<strong>Integrate Zero Spam in any application. </strong> Use the <a href="
|
788 |
-
"\"%s\" target=\"_blank\" rel=\"noopener noreferrer\">Zero Spam Blacklist "
|
789 |
-
"API</a> to easily put a stop to spam on any site or application."
|
790 |
-
msgstr ""
|
791 |
-
|
792 |
-
#: templates/callout.php:42
|
793 |
-
msgid "Submit Bug/Feature Request"
|
794 |
-
msgstr ""
|
795 |
-
|
796 |
-
#: templates/callout.php:43
|
797 |
-
msgid "Follow us on Twitter"
|
798 |
-
msgstr ""
|
799 |
-
|
800 |
-
#: templates/callout.php:44
|
801 |
-
msgid "Like us on Facebook"
|
802 |
-
msgstr ""
|
803 |
-
|
804 |
-
#: templates/callout.php:45
|
805 |
-
msgid "Learn more about Zero Spam"
|
806 |
-
msgstr ""
|
807 |
-
|
808 |
-
#: templates/callout.php:46
|
809 |
-
msgid "Fork on Github"
|
810 |
-
msgstr ""
|
811 |
-
|
812 |
-
#: templates/callout.php:47
|
813 |
-
msgid "Show your Support — Donate"
|
814 |
-
msgstr ""
|
815 |
-
|
816 |
-
#: templates/callout.php:51
|
817 |
-
msgid "Your IP Address:"
|
818 |
-
msgstr ""
|
819 |
-
|
820 |
-
#: templates/countries-pie-chart.php:12
|
821 |
-
msgid "Most Spam by Country"
|
822 |
-
msgstr ""
|
823 |
-
|
824 |
-
#: templates/countries-pie-chart.php:67 templates/ip-list.php:71
|
825 |
-
#: templates/regions-pie-chart.php:82 templates/spam-line-chart.php:58
|
826 |
-
msgid "No data to report yet."
|
827 |
-
msgstr ""
|
828 |
-
|
829 |
-
#: templates/ip-list.php:12
|
830 |
-
msgid "Most Spam by IP Address"
|
831 |
-
msgstr ""
|
832 |
-
|
833 |
-
#: templates/map.php:11
|
834 |
-
msgid "Spam Detections World Map"
|
835 |
-
msgstr ""
|
836 |
-
|
837 |
-
#: templates/map.php:106
|
838 |
-
#, php-format
|
839 |
-
msgid ""
|
840 |
-
"<strong>Enter your <a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer"
|
841 |
-
"\">ipstack API Key</a></strong> to enable the world mp view of spam "
|
842 |
-
"detections."
|
843 |
-
msgstr ""
|
844 |
-
|
845 |
-
#: templates/regions-pie-chart.php:12
|
846 |
-
msgid "Most Spam by Region"
|
847 |
-
msgstr ""
|
848 |
-
|
849 |
-
#: templates/spam-line-chart.php:10
|
850 |
-
msgid "Spam by Date"
|
851 |
-
msgstr ""
|
852 |
-
|
853 |
-
#. Plugin Name of the plugin/theme
|
854 |
-
msgid "WordPress Zero Spam"
|
855 |
-
msgstr ""
|
856 |
-
|
857 |
-
#. Plugin URI of the plugin/theme
|
858 |
-
msgid "https://benmarshall.me/wordpress-zero-spam"
|
859 |
-
msgstr ""
|
860 |
-
|
861 |
-
#. Description of the plugin/theme
|
862 |
-
msgid ""
|
863 |
-
"Tired of all the useless and bloated WordPress spam plugins? The WordPress "
|
864 |
-
"Zero Spam plugin makes blocking spam a cinch. <strong>Just install, activate "
|
865 |
-
"and say goodbye to spam.</strong> Based on work by <a href=\"http://"
|
866 |
-
"davidwalsh.name/wordpress-comment-spam\" target=\"_blank\">David Walsh</a>."
|
867 |
-
msgstr ""
|
868 |
-
|
869 |
-
#. Author of the plugin/theme
|
870 |
-
msgid "Ben Marshall"
|
871 |
-
msgstr ""
|
872 |
-
|
873 |
-
#. Author URI of the plugin/theme
|
874 |
-
msgid "https://benmarshall.me"
|
875 |
-
msgstr ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
modules/class-botscout.php
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Botscout class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Modules;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
|
12 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
13 |
+
defined( 'ABSPATH' ) || die();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* BotScout.
|
17 |
+
*
|
18 |
+
* @since 5.0.0
|
19 |
+
*/
|
20 |
+
class BotScout {
|
21 |
+
/**
|
22 |
+
* Botscout constructor.
|
23 |
+
*
|
24 |
+
* @since 5.0.0
|
25 |
+
* @access public
|
26 |
+
*/
|
27 |
+
public function __construct() {
|
28 |
+
add_filter( 'zerospam_setting_sections', array( $this, 'sections' ) );
|
29 |
+
add_filter( 'zerospam_settings', array( $this, 'settings' ) );
|
30 |
+
|
31 |
+
add_filter( 'zerospam_access_checks', array( $this, 'access_check' ), 10, 3 );
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Botscout access_check.
|
36 |
+
*
|
37 |
+
* @since 5.0.0
|
38 |
+
* @access public
|
39 |
+
*/
|
40 |
+
public function access_check( $access_checks, $user_ip, $settings ) {
|
41 |
+
$access_checks['botscout'] = array(
|
42 |
+
'blocked' => false,
|
43 |
+
);
|
44 |
+
|
45 |
+
if ( empty( $settings['botscout_api']['value'] ) ) {
|
46 |
+
return $access_checks;
|
47 |
+
}
|
48 |
+
|
49 |
+
$cache_key = ZeroSpam\Core\Utilities::cache_key(
|
50 |
+
array(
|
51 |
+
'botscout',
|
52 |
+
$user_ip,
|
53 |
+
)
|
54 |
+
);
|
55 |
+
|
56 |
+
$result = wp_cache_get( $cache_key );
|
57 |
+
if ( false === $result ) {
|
58 |
+
$endpoint = 'https://botscout.com/test/?';
|
59 |
+
$params = array(
|
60 |
+
'ip' => $user_ip,
|
61 |
+
'key' => $settings['botscout_api']['value'],
|
62 |
+
);
|
63 |
+
$endpoint = $endpoint . http_build_query( $params );
|
64 |
+
|
65 |
+
$timeout = 5;
|
66 |
+
if ( ! empty( $settings['botscout_timeout'] ) ) {
|
67 |
+
$timeout = intval( $settings['botscout_timeout']['value'] );
|
68 |
+
}
|
69 |
+
|
70 |
+
$response = ZeroSpam\Core\Utilities::remote_get( $endpoint, array( 'timeout' => $timeout ) );
|
71 |
+
|
72 |
+
|
73 |
+
print_r($response);
|
74 |
+
}
|
75 |
+
|
76 |
+
return $access_checks;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Botscout sections.
|
81 |
+
*
|
82 |
+
* @since 5.0.0
|
83 |
+
* @access public
|
84 |
+
*/
|
85 |
+
public function sections( $sections ) {
|
86 |
+
$sections['botscout'] = array(
|
87 |
+
'title' => __( 'BotScout Integration', 'zerospam' ),
|
88 |
+
);
|
89 |
+
|
90 |
+
return $sections;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Botscout settings.
|
95 |
+
*
|
96 |
+
* @since 5.0.0
|
97 |
+
* @access public
|
98 |
+
*/
|
99 |
+
public function settings( $settings ) {
|
100 |
+
$options = get_option( 'wpzerospam' );
|
101 |
+
|
102 |
+
$settings['botscout_api'] = array(
|
103 |
+
'title' => __( 'BotScout API Key', 'zerospam' ),
|
104 |
+
'section' => 'botscout',
|
105 |
+
'type' => 'text',
|
106 |
+
'field_class' => 'regular-text',
|
107 |
+
'placeholder' => __( 'Enter your free BotScout API key.', 'zerospam' ),
|
108 |
+
'desc' => sprintf(
|
109 |
+
wp_kses(
|
110 |
+
__( 'Enter your BotScout API key to check user IPs against <a href="%1$s" target="_blank" rel="noopener noreferrer">BotScout</a>\'s blacklist. Don\'t have an API key? <a href="%2$s" target="_blank" rel="noopener noreferrer"><strong>Get one for free!</strong></a>', 'zerospam' ),
|
111 |
+
array(
|
112 |
+
'strong' => array(),
|
113 |
+
'a' => array(
|
114 |
+
'target' => array(),
|
115 |
+
'href' => array(),
|
116 |
+
'rel' => array(),
|
117 |
+
),
|
118 |
+
)
|
119 |
+
),
|
120 |
+
esc_url( 'https://botscout.com/#utm_source=wordpresszerospam&utm_medium=admin_link&utm_campaign=wordpresszerospam' ),
|
121 |
+
esc_url( 'https://botscout.com/getkey.htm#utm_source=wordpresszerospam&utm_medium=admin_link&utm_campaign=wordpresszerospam' )
|
122 |
+
),
|
123 |
+
'value' => ! empty( $options['botscout_api'] ) ? $options['botscout_api'] : false,
|
124 |
+
);
|
125 |
+
|
126 |
+
$settings['botscout_timeout'] = array(
|
127 |
+
'title' => __( 'BotScout API Timeout', 'zerospam' ),
|
128 |
+
'section' => 'botscout',
|
129 |
+
'type' => 'number',
|
130 |
+
'field_class' => 'small-text',
|
131 |
+
'suffix' => __( 'seconds', 'zerospam' ),
|
132 |
+
'placeholder' => __( '5', 'zerospam' ),
|
133 |
+
'desc' => __( 'Recommended setting is 5 seconds. Setting to high could result in degraded site performance, too low won\'t allow to API enough time to respond.', 'zerospam' ),
|
134 |
+
'value' => ! empty( $options['botscout_timeout'] ) ? $options['botscout_timeout'] : 5,
|
135 |
+
);
|
136 |
+
|
137 |
+
return $settings;
|
138 |
+
}
|
139 |
+
}
|
modules/class-google.php
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Google maps class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Modules;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
|
12 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
13 |
+
defined( 'ABSPATH' ) || die();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Google maps.
|
17 |
+
*
|
18 |
+
* @since 5.0.0
|
19 |
+
*/
|
20 |
+
class Google {
|
21 |
+
/**
|
22 |
+
* Google maps constructor.
|
23 |
+
*
|
24 |
+
* @since 5.0.0
|
25 |
+
* @access public
|
26 |
+
*/
|
27 |
+
public function __construct() {
|
28 |
+
add_filter( 'zerospam_setting_sections', array( $this, 'sections' ) );
|
29 |
+
add_filter( 'zerospam_settings', array( $this, 'settings' ) );
|
30 |
+
|
31 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
32 |
+
if ( ! empty( $settings['google_api']['value'] ) ) {
|
33 |
+
add_action( 'zerospam_google_map', array( $this, 'map' ), 10, 2 );
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Embeds a map;
|
39 |
+
*
|
40 |
+
* @since 5.0.0
|
41 |
+
* @access public
|
42 |
+
*/
|
43 |
+
public function map( $coordinates ) {
|
44 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
45 |
+
|
46 |
+
if ( ! empty( $settings['google_api']['value'] ) ) {
|
47 |
+
$url = 'https://www.google.com/maps/embed/v1/place?';
|
48 |
+
$url_params = array(
|
49 |
+
'key' => $settings['google_api']['value'],
|
50 |
+
'q' => $coordinates,
|
51 |
+
);
|
52 |
+
$url .= http_build_query( $url_params );
|
53 |
+
|
54 |
+
$api_key
|
55 |
+
?>
|
56 |
+
<iframe
|
57 |
+
width="100%"
|
58 |
+
height="200"
|
59 |
+
style="border:0"
|
60 |
+
loading="lazy"
|
61 |
+
allowfullscreen
|
62 |
+
src="<?php echo esc_url( $url ); ?>">
|
63 |
+
</iframe>
|
64 |
+
<?php
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Google maps sections.
|
70 |
+
*
|
71 |
+
* @since 5.0.0
|
72 |
+
* @access public
|
73 |
+
*/
|
74 |
+
public function sections( $sections ) {
|
75 |
+
$sections['google'] = array(
|
76 |
+
'title' => __( 'Google Integration', 'zerospam' ),
|
77 |
+
);
|
78 |
+
|
79 |
+
return $sections;
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Botscout settings.
|
84 |
+
*
|
85 |
+
* @since 5.0.0
|
86 |
+
* @access public
|
87 |
+
*/
|
88 |
+
public function settings( $settings ) {
|
89 |
+
$options = get_option( 'wpzerospam' );
|
90 |
+
|
91 |
+
$settings['google_api'] = array(
|
92 |
+
'title' => __( 'Google API Key', 'zerospam' ),
|
93 |
+
'section' => 'google',
|
94 |
+
'type' => 'text',
|
95 |
+
'field_class' => 'regular-text',
|
96 |
+
'placeholder' => __( 'Enter your Google API key.', 'zerospam' ),
|
97 |
+
'desc' => sprintf(
|
98 |
+
wp_kses(
|
99 |
+
__( 'Enter your <a href="%1$s" target="_blank" rel="noopener noreferrer">Google API key</a> for Google Maps integration.', 'zerospam' ),
|
100 |
+
array(
|
101 |
+
'a' => array(
|
102 |
+
'target' => array(),
|
103 |
+
'href' => array(),
|
104 |
+
'rel' => array(),
|
105 |
+
),
|
106 |
+
)
|
107 |
+
),
|
108 |
+
esc_url( 'https://developers.google.com/maps/documentation/embed/get-api-key' ),
|
109 |
+
),
|
110 |
+
'value' => ! empty( $options['google_api'] ) ? $options['google_api'] : false,
|
111 |
+
);
|
112 |
+
|
113 |
+
return $settings;
|
114 |
+
}
|
115 |
+
}
|
modules/class-ipstack.php
ADDED
@@ -0,0 +1,194 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* ipstack class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Modules;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
|
12 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
13 |
+
defined( 'ABSPATH' ) || die();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* ipstack.
|
17 |
+
*
|
18 |
+
* @since 5.0.0
|
19 |
+
*/
|
20 |
+
class ipstack {
|
21 |
+
/**
|
22 |
+
* ipstack constructor.
|
23 |
+
*
|
24 |
+
* @since 5.0.0
|
25 |
+
* @access public
|
26 |
+
*/
|
27 |
+
public function __construct() {
|
28 |
+
add_filter( 'zerospam_setting_sections', array( $this, 'sections' ) );
|
29 |
+
add_filter( 'zerospam_settings', array( $this, 'settings' ) );
|
30 |
+
add_filter( 'zerospam_log_record', array( $this, 'log_record' ) );
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* ipstack sections.
|
35 |
+
*
|
36 |
+
* @since 5.0.0
|
37 |
+
* @access public
|
38 |
+
*/
|
39 |
+
public function sections( $sections ) {
|
40 |
+
$sections['ipstack'] = array(
|
41 |
+
'title' => __( 'ipstack Integration', 'zerospam' ),
|
42 |
+
);
|
43 |
+
|
44 |
+
return $sections;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Botscout settings.
|
49 |
+
*
|
50 |
+
* @since 5.0.0
|
51 |
+
* @access public
|
52 |
+
*/
|
53 |
+
public function settings( $settings ) {
|
54 |
+
$options = get_option( 'wpzerospam' );
|
55 |
+
|
56 |
+
$settings['ipstack_api'] = array(
|
57 |
+
'title' => __( 'ipstack API Key', 'zerospam' ),
|
58 |
+
'desc' => sprintf(
|
59 |
+
wp_kses(
|
60 |
+
__( 'Enter your <a href="%1$s" target="_blank" rel="noopener noreferrer">ipstack API key</a> to enable location-based statistics. Don\'t have an API key? <a href="%2$s" target="_blank" rel="noopener noreferrer"><strong>Get one for free!</strong></a>', 'zerospam' ),
|
61 |
+
array(
|
62 |
+
'strong' => array(),
|
63 |
+
'a' => array(
|
64 |
+
'target' => array(),
|
65 |
+
'href' => array(),
|
66 |
+
'rel' => array(),
|
67 |
+
),
|
68 |
+
)
|
69 |
+
),
|
70 |
+
esc_url( 'https://ipstack.com/#utm_source=wordpresszerospam&utm_medium=admin_link&utm_campaign=wordpresszerospam' ),
|
71 |
+
esc_url( 'https://ipstack.com/signup/free#utm_source=wordpresszerospam&utm_medium=admin_link&utm_campaign=wordpresszerospam' )
|
72 |
+
),
|
73 |
+
'section' => 'ipstack',
|
74 |
+
'type' => 'text',
|
75 |
+
'field_class' => 'regular-text',
|
76 |
+
'placeholder' => __( 'Enter your ipstack API key.', 'zerospam' ),
|
77 |
+
'value' => ! empty( $options['ipstack_api'] ) ? $options['ipstack_api'] : false,
|
78 |
+
);
|
79 |
+
|
80 |
+
$settings['ipstack_timeout'] = array(
|
81 |
+
'title' => __( 'ipstack API Timeout', 'zerospam' ),
|
82 |
+
'section' => 'ipstack',
|
83 |
+
'type' => 'number',
|
84 |
+
'field_class' => 'small-text',
|
85 |
+
'suffix' => __( 'seconds', 'zerospam' ),
|
86 |
+
'placeholder' => __( '5', 'zerospam' ),
|
87 |
+
'desc' => __( 'Recommended setting is 5 seconds. Setting to high could result in degraded site performance, too low won\'t allow to API enough time to respond.', 'zerospam' ),
|
88 |
+
'value' => ! empty( $options['ipstack_timeout'] ) ? $options['ipstack_timeout'] : 5,
|
89 |
+
);
|
90 |
+
|
91 |
+
$settings['ipstack_cache'] = array(
|
92 |
+
'title' => __( 'ipstack Cache Expiration', 'zerospam' ),
|
93 |
+
'section' => 'ipstack',
|
94 |
+
'type' => 'number',
|
95 |
+
'field_class' => 'small-text',
|
96 |
+
'suffix' => __( 'day(s)', 'zerospam' ),
|
97 |
+
'placeholder' => __( '14', 'zerospam' ),
|
98 |
+
'desc' => __( 'Recommended setting is 14 days. Setting to high could result in outdated information, too low could cause a decrease in performance.', 'zerospam' ),
|
99 |
+
'value' => ! empty( $options['ipstack_cache'] ) ? $options['ipstack_cache'] : 14,
|
100 |
+
);
|
101 |
+
|
102 |
+
return $settings;
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Log record filter.
|
107 |
+
*
|
108 |
+
* @since 5.0.0
|
109 |
+
* @access public
|
110 |
+
*/
|
111 |
+
public static function log_record( $record ) {
|
112 |
+
$location = self::get_geolocation( ZeroSpam\Core\User::get_ip() );
|
113 |
+
if ( $location ) {
|
114 |
+
if ( ! empty( $location['country_code'] ) ) {
|
115 |
+
$record['country'] = $location['country_code'];
|
116 |
+
}
|
117 |
+
|
118 |
+
if ( ! empty( $location['country_name'] ) ) {
|
119 |
+
$record['country_name'] = $location['country_name'];
|
120 |
+
}
|
121 |
+
|
122 |
+
if ( ! empty( $location['region_code'] ) ) {
|
123 |
+
$record['region'] = $location['region_code'];
|
124 |
+
}
|
125 |
+
|
126 |
+
if ( ! empty( $location['region_name'] ) ) {
|
127 |
+
$record['region_name'] = $location['region_name'];
|
128 |
+
}
|
129 |
+
|
130 |
+
if ( ! empty( $location['city'] ) ) {
|
131 |
+
$record['city'] = $location['city'];
|
132 |
+
}
|
133 |
+
|
134 |
+
if ( ! empty( $location['latitude'] ) ) {
|
135 |
+
$record['latitude'] = $location['latitude'];
|
136 |
+
}
|
137 |
+
|
138 |
+
if ( ! empty( $location['longitude'] ) ) {
|
139 |
+
$record['longitude'] = $location['longitude'];
|
140 |
+
}
|
141 |
+
|
142 |
+
if ( ! empty( $location['zip'] ) ) {
|
143 |
+
$record['zip'] = $location['zip'];
|
144 |
+
}
|
145 |
+
}
|
146 |
+
|
147 |
+
return $record;
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Get geolocation.
|
152 |
+
*
|
153 |
+
* @since 5.0.0
|
154 |
+
* @access public
|
155 |
+
*/
|
156 |
+
public static function get_geolocation( $ip ) {
|
157 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
158 |
+
|
159 |
+
if ( empty( $settings['ipstack_api']['value'] ) ) {
|
160 |
+
return false;
|
161 |
+
}
|
162 |
+
|
163 |
+
$cache_key = ZeroSpam\Core\Utilities::cache_key(
|
164 |
+
array(
|
165 |
+
'ipstack',
|
166 |
+
$ip,
|
167 |
+
)
|
168 |
+
);
|
169 |
+
|
170 |
+
$result = wp_cache_get( $cache_key );
|
171 |
+
if ( false === $result ) {
|
172 |
+
$endpoint = 'http://api.ipstack.com/';
|
173 |
+
$endpoint .= $ip . '?access_key=' . $settings['ipstack_api']['value'];
|
174 |
+
|
175 |
+
$timeout = 5;
|
176 |
+
if ( ! empty( $settings['ipstack_timeout'] ) ) {
|
177 |
+
$timeout = intval( $settings['ipstack_timeout']['value'] );
|
178 |
+
}
|
179 |
+
|
180 |
+
$response = ZeroSpam\Core\Utilities::remote_get( $endpoint, array( 'timeout' => $timeout ) );
|
181 |
+
if ( $response ) {
|
182 |
+
$result = json_decode( $response, true );
|
183 |
+
|
184 |
+
$expiration = 14 * DAY_IN_SECONDS;
|
185 |
+
if ( ! empty( $settings['ipstack_cache']['value'] ) ) {
|
186 |
+
$expiration = $settings['ipstack_cache']['value'] * DAY_IN_SECONDS;
|
187 |
+
}
|
188 |
+
wp_cache_set( $cache_key, $result, 'zerospam', $expiration );
|
189 |
+
}
|
190 |
+
}
|
191 |
+
|
192 |
+
return $result;
|
193 |
+
}
|
194 |
+
}
|
modules/class-stopforumspam.php
ADDED
@@ -0,0 +1,344 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Stop Forum Spam class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Modules;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
|
12 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
13 |
+
defined( 'ABSPATH' ) || die();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Stop Forum Spam.
|
17 |
+
*
|
18 |
+
* @since 5.0.0
|
19 |
+
*/
|
20 |
+
class StopForumSpam {
|
21 |
+
/**
|
22 |
+
* Stop Forum Spam constructor.
|
23 |
+
*
|
24 |
+
* @since 5.0.0
|
25 |
+
* @access public
|
26 |
+
*/
|
27 |
+
public function __construct() {
|
28 |
+
add_filter( 'zerospam_setting_sections', array( $this, 'sections' ) );
|
29 |
+
add_filter( 'zerospam_settings', array( $this, 'settings' ) );
|
30 |
+
add_filter( 'zerospam_access_checks', array( $this, 'access_check' ), 10, 3 );
|
31 |
+
add_filter( 'zerospam_registration_errors', array( $this, 'preprocess_registrations' ), 10, 3 );
|
32 |
+
add_filter( 'zerospam_preprocess_comment', array( $this, 'preprocess_comments' ), 10, 1 );
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Stop Forum Spam sections.
|
37 |
+
*
|
38 |
+
* @since 5.0.0
|
39 |
+
* @access public
|
40 |
+
*/
|
41 |
+
public function sections( $sections ) {
|
42 |
+
$sections['stop_forum_spam'] = array(
|
43 |
+
'title' => __( 'Stop Forum Spam Integration', 'zerospam' ),
|
44 |
+
);
|
45 |
+
|
46 |
+
return $sections;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Stop Forum Spam settings.
|
51 |
+
*
|
52 |
+
* @since 5.0.0
|
53 |
+
* @access public
|
54 |
+
*/
|
55 |
+
public function settings( $settings ) {
|
56 |
+
$options = get_option( 'wpzerospam' );
|
57 |
+
|
58 |
+
$settings['stop_forum_spam'] = array(
|
59 |
+
'title' => __( 'Stop Forum Spam', 'zerospam' ),
|
60 |
+
'section' => 'stop_forum_spam',
|
61 |
+
'type' => 'checkbox',
|
62 |
+
'options' => array(
|
63 |
+
'enabled' => __( 'Enabled', 'zerospam' ),
|
64 |
+
),
|
65 |
+
'desc' => sprintf(
|
66 |
+
wp_kses(
|
67 |
+
__( 'Checks user IPs against <a href="%s" target="_blank" rel="noopener noreferrer">Stop Forum Spam</a>\'s blacklist.', 'zerospam' ),
|
68 |
+
array(
|
69 |
+
'strong' => array(),
|
70 |
+
'a' => array(
|
71 |
+
'target' => array(),
|
72 |
+
'href' => array(),
|
73 |
+
'rel' => array(),
|
74 |
+
),
|
75 |
+
)
|
76 |
+
),
|
77 |
+
esc_url( 'https://www.stopforumspam.com/#utm_source=wordpresszerospam&utm_medium=admin_link&utm_campaign=wordpresszerospam' )
|
78 |
+
),
|
79 |
+
'value' => ! empty( $options['stop_forum_spam'] ) ? $options['stop_forum_spam'] : false,
|
80 |
+
);
|
81 |
+
|
82 |
+
$settings['stop_forum_spam_timeout'] = array(
|
83 |
+
'title' => __( 'Stop Forum Spam API Timeout', 'zerospam' ),
|
84 |
+
'section' => 'stop_forum_spam',
|
85 |
+
'type' => 'number',
|
86 |
+
'field_class' => 'small-text',
|
87 |
+
'suffix' => __( 'seconds', 'zerospam' ),
|
88 |
+
'placeholder' => __( '5', 'zerospam' ),
|
89 |
+
'min' => 0,
|
90 |
+
'desc' => __( 'Recommended setting is 5 seconds. Setting to high could result in degraded site performance, too low won\'t allow to API enough time to respond.', 'zerospam' ),
|
91 |
+
'value' => ! empty( $options['stop_forum_spam_timeout'] ) ? $options['stop_forum_spam_timeout'] : 5,
|
92 |
+
);
|
93 |
+
|
94 |
+
$settings['stop_forum_spam_cache'] = array(
|
95 |
+
'title' => __( 'Stop Forum Spam Cache Expiration', 'zerospam' ),
|
96 |
+
'section' => 'stop_forum_spam',
|
97 |
+
'type' => 'number',
|
98 |
+
'field_class' => 'small-text',
|
99 |
+
'suffix' => __( 'day(s)', 'zerospam' ),
|
100 |
+
'placeholder' => __( WEEK_IN_SECONDS, 'zerospam' ),
|
101 |
+
'min' => 0,
|
102 |
+
'desc' => __( 'Recommended setting is 14 days. Setting to high could result in outdated information, too low could cause a decrease in performance.', 'zerospam' ),
|
103 |
+
'value' => ! empty( $options['stop_forum_spam_cache'] ) ? $options['stop_forum_spam_cache'] : 14,
|
104 |
+
);
|
105 |
+
|
106 |
+
$settings['stop_forum_spam_confidence_min'] = array(
|
107 |
+
'title' => __( 'Stop Forum Spam Confidence Minimum', 'zerospam' ),
|
108 |
+
'section' => 'stop_forum_spam',
|
109 |
+
'type' => 'number',
|
110 |
+
'field_class' => 'small-text',
|
111 |
+
'suffix' => __( '%', 'zerospam' ),
|
112 |
+
'placeholder' => __( '30', 'zerospam' ),
|
113 |
+
'min' => 0,
|
114 |
+
'max' => 100,
|
115 |
+
'step' => 0.1,
|
116 |
+
'desc' => sprintf(
|
117 |
+
wp_kses(
|
118 |
+
__( 'Recommended setting is 20%%. Minimum <a href="%s" target="_blank" rel="noopener noreferrer">confidence score</a> an IP must meet before being blocked. Setting this too low could cause users to be blocked that shouldn\'t be.', 'zerospam' ),
|
119 |
+
array(
|
120 |
+
'a' => array(
|
121 |
+
'target' => array(),
|
122 |
+
'href' => array(),
|
123 |
+
'rel' => array(),
|
124 |
+
),
|
125 |
+
)
|
126 |
+
),
|
127 |
+
esc_url( 'https://www.stopforumspam.com/usage#utm_source=wordpresszerospam&utm_medium=admin_link&utm_campaign=wordpresszerospam' )
|
128 |
+
),
|
129 |
+
'value' => ! empty( $options['stop_forum_spam_confidence_min'] ) ? $options['stop_forum_spam_confidence_min'] : 30,
|
130 |
+
);
|
131 |
+
|
132 |
+
return $settings;
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Processes comments.
|
137 |
+
*
|
138 |
+
* @since 5.0.0
|
139 |
+
* @access public
|
140 |
+
*/
|
141 |
+
public function preprocess_comments( $commentdata ) {
|
142 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
143 |
+
|
144 |
+
if ( empty( $settings['stop_forum_spam']['value'] ) || 'enabled' !== $settings['stop_forum_spam']['value'] ) {
|
145 |
+
return $errors;
|
146 |
+
}
|
147 |
+
|
148 |
+
$response = self::query(
|
149 |
+
array(
|
150 |
+
'email' => $commentdata['comment_author_email'],
|
151 |
+
)
|
152 |
+
);
|
153 |
+
if ( $response ) {
|
154 |
+
$response = json_decode( $response, true );
|
155 |
+
if ( ! empty( $response['success'] ) && $response['success'] ) {
|
156 |
+
|
157 |
+
// Check email.
|
158 |
+
if (
|
159 |
+
! empty( $response['email'] ) &&
|
160 |
+
! empty( $response['email']['confidence'] ) &&
|
161 |
+
! empty( $settings['stop_forum_spam_confidence_min']['value'] ) &&
|
162 |
+
floatval( $response['email']['confidence'] ) >= floatval( $settings['stop_forum_spam_confidence_min']['value'] )
|
163 |
+
) {
|
164 |
+
$message = __( 'You have been flagged as spam/malicious by WordPress Zero Spam.', 'zerospam' );
|
165 |
+
if ( ! empty( $settings['registration_spam_message']['value'] ) ) {
|
166 |
+
$message = $settings['registration_spam_message']['value'];
|
167 |
+
}
|
168 |
+
|
169 |
+
if ( count( $errors->errors ) == 0 ) {
|
170 |
+
$errors->add( 'zerospam_error_stopformspam_email', __( $message, 'zerospam' ) );
|
171 |
+
}
|
172 |
+
|
173 |
+
$details = array(
|
174 |
+
'user_login' => $sanitized_user_login,
|
175 |
+
'user_email' => $user_email,
|
176 |
+
'failed' => 'stop_forum_spam_email',
|
177 |
+
);
|
178 |
+
ZeroSpam\Includes\DB::log( 'registration', $details );
|
179 |
+
}
|
180 |
+
}
|
181 |
+
}
|
182 |
+
|
183 |
+
|
184 |
+
return $errors;
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Processes registrations.
|
189 |
+
*
|
190 |
+
* @since 5.0.0
|
191 |
+
* @access public
|
192 |
+
*/
|
193 |
+
public function preprocess_registrations( $errors, $sanitized_user_login, $user_email ) {
|
194 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
195 |
+
|
196 |
+
if ( empty( $settings['stop_forum_spam']['value'] ) || 'enabled' !== $settings['stop_forum_spam']['value'] ) {
|
197 |
+
return $errors;
|
198 |
+
}
|
199 |
+
|
200 |
+
$response = self::query(
|
201 |
+
array(
|
202 |
+
'username' => $sanitized_user_login,
|
203 |
+
'email' => $user_email,
|
204 |
+
)
|
205 |
+
);
|
206 |
+
if ( $response ) {
|
207 |
+
$response = json_decode( $response, true );
|
208 |
+
if ( ! empty( $response['success'] ) && $response['success'] ) {
|
209 |
+
// Check username.
|
210 |
+
if (
|
211 |
+
! empty( $response['username'] ) &&
|
212 |
+
! empty( $response['username']['confidence'] ) &&
|
213 |
+
! empty( $settings['stop_forum_spam_confidence_min']['value'] ) &&
|
214 |
+
floatval( $response['username']['confidence'] ) >= floatval( $settings['stop_forum_spam_confidence_min']['value'] )
|
215 |
+
) {
|
216 |
+
$message = __( 'Your been flagged as spam/malicious by WordPress Zero Spam.', 'zerospam' );
|
217 |
+
if ( ! empty( $settings['registration_spam_message']['value'] ) ) {
|
218 |
+
$message = $settings['registration_spam_message']['value'];
|
219 |
+
}
|
220 |
+
$errors->add( 'zerospam_error_stopformspam_username', __( $message, 'zerospam' ) );
|
221 |
+
|
222 |
+
$details = array(
|
223 |
+
'user_login' => $sanitized_user_login,
|
224 |
+
'user_email' => $user_email,
|
225 |
+
'failed' => 'stop_forum_spam_username',
|
226 |
+
);
|
227 |
+
ZeroSpam\Includes\DB::log( 'registration', $details );
|
228 |
+
}
|
229 |
+
|
230 |
+
// Check email.
|
231 |
+
if (
|
232 |
+
! empty( $response['email'] ) &&
|
233 |
+
! empty( $response['email']['confidence'] ) &&
|
234 |
+
! empty( $settings['stop_forum_spam_confidence_min']['value'] ) &&
|
235 |
+
floatval( $response['email']['confidence'] ) >= floatval( $settings['stop_forum_spam_confidence_min']['value'] )
|
236 |
+
) {
|
237 |
+
$message = __( 'You have been flagged as spam/malicious by WordPress Zero Spam.', 'zerospam' );
|
238 |
+
if ( ! empty( $settings['registration_spam_message']['value'] ) ) {
|
239 |
+
$message = $settings['registration_spam_message']['value'];
|
240 |
+
}
|
241 |
+
|
242 |
+
if ( count( $errors->errors ) == 0 ) {
|
243 |
+
$errors->add( 'zerospam_error_stopformspam_email', __( $message, 'zerospam' ) );
|
244 |
+
}
|
245 |
+
|
246 |
+
$details = array(
|
247 |
+
'user_login' => $sanitized_user_login,
|
248 |
+
'user_email' => $user_email,
|
249 |
+
'failed' => 'stop_forum_spam_email',
|
250 |
+
);
|
251 |
+
ZeroSpam\Includes\DB::log( 'registration', $details );
|
252 |
+
}
|
253 |
+
}
|
254 |
+
}
|
255 |
+
|
256 |
+
|
257 |
+
return $errors;
|
258 |
+
}
|
259 |
+
|
260 |
+
/**
|
261 |
+
* Query the Stop Forum Spam API.
|
262 |
+
*
|
263 |
+
* @since 5.0.0
|
264 |
+
* @access public
|
265 |
+
*/
|
266 |
+
public function query( $params ) {
|
267 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
268 |
+
|
269 |
+
$cache_array = array( 'stop_forum_spam' );
|
270 |
+
$cache_array = array_merge( $cache_array, $params );
|
271 |
+
$cache_key = ZeroSpam\Core\Utilities::cache_key( $cache_array );
|
272 |
+
|
273 |
+
$response = wp_cache_get( $cache_key );
|
274 |
+
if ( false === $response ) {
|
275 |
+
$endpoint = 'https://api.stopforumspam.org/api?';
|
276 |
+
$params = array( 'json' => '' );
|
277 |
+
$params = array_merge( $cache_array, $params );
|
278 |
+
$endpoint = $endpoint . http_build_query( $params );
|
279 |
+
|
280 |
+
$timeout = 5;
|
281 |
+
if ( ! empty( $settings['stop_forum_spam_timeout'] ) ) {
|
282 |
+
$timeout = intval( $settings['stop_forum_spam_timeout']['value'] );
|
283 |
+
}
|
284 |
+
|
285 |
+
$response = ZeroSpam\Core\Utilities::remote_get( $endpoint, array( 'timeout' => $timeout ) );
|
286 |
+
if ( $response ) {
|
287 |
+
$expiration = 14 * DAY_IN_SECONDS;
|
288 |
+
if ( ! empty( $settings['stop_forum_spam_cache']['value'] ) ) {
|
289 |
+
$expiration = $settings['stop_forum_spam_cache']['value'] * DAY_IN_SECONDS;
|
290 |
+
}
|
291 |
+
wp_cache_set( $cache_key, $response, 'zerospam', $expiration );
|
292 |
+
}
|
293 |
+
}
|
294 |
+
|
295 |
+
return $response;
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Stop Forum Spam access_check.
|
300 |
+
*
|
301 |
+
* @since 5.0.0
|
302 |
+
* @access public
|
303 |
+
*/
|
304 |
+
public function access_check( $access_checks, $user_ip, $settings ) {
|
305 |
+
$access_checks['stop_forum_spam'] = array(
|
306 |
+
'blocked' => false,
|
307 |
+
);
|
308 |
+
|
309 |
+
if ( empty( $settings['stop_forum_spam']['value'] ) || 'enabled' !== $settings['stop_forum_spam']['value'] ) {
|
310 |
+
return $access_checks;
|
311 |
+
}
|
312 |
+
|
313 |
+
$response = self::query( array( 'ip' => $user_ip ) );
|
314 |
+
if ( $response ) {
|
315 |
+
$response = json_decode( $response, true );
|
316 |
+
if (
|
317 |
+
! empty( $response['success'] ) &&
|
318 |
+
$response['success'] &&
|
319 |
+
! empty( $response['ip'] ) &&
|
320 |
+
! empty( $response['ip']['appears'] )
|
321 |
+
) {
|
322 |
+
|
323 |
+
$blacklisted = array(
|
324 |
+
'user_ip' => $user_ip,
|
325 |
+
'blacklist_service' => 'stop_forum_spam',
|
326 |
+
'blacklist_data' => wp_json_encode( $response['ip'] ),
|
327 |
+
);
|
328 |
+
ZeroSpam\Includes\DB::blacklisted( $blacklisted );
|
329 |
+
|
330 |
+
if (
|
331 |
+
! empty( $response['ip']['confidence'] ) &&
|
332 |
+
! empty( $settings['stop_forum_spam_confidence_min']['value'] ) &&
|
333 |
+
floatval( $response['ip']['confidence'] ) >= floatval( $settings['stop_forum_spam_confidence_min']['value'] )
|
334 |
+
) {
|
335 |
+
$access_checks['stop_forum_spam']['blocked'] = true;
|
336 |
+
$access_checks['stop_forum_spam']['type'] = 'blocked';
|
337 |
+
$access_checks['stop_forum_spam']['details'] = $response['ip'];
|
338 |
+
}
|
339 |
+
}
|
340 |
+
}
|
341 |
+
|
342 |
+
return $access_checks;
|
343 |
+
}
|
344 |
+
}
|
modules/class-zerospam.php
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Zero Spam class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Modules;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
|
12 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
13 |
+
defined( 'ABSPATH' ) || die();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Zero Spam.
|
17 |
+
*
|
18 |
+
* @since 5.0.0
|
19 |
+
*/
|
20 |
+
class Zero_Spam {
|
21 |
+
/**
|
22 |
+
* Zero Spam constructor.
|
23 |
+
*
|
24 |
+
* @since 5.0.0
|
25 |
+
* @access public
|
26 |
+
*/
|
27 |
+
public function __construct() {
|
28 |
+
add_action( 'zerospam_share_blocked', array( $this, 'share_blocked' ), 10, 1 );
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Share blocked.
|
33 |
+
*
|
34 |
+
* @since 5.0.0
|
35 |
+
* @access public
|
36 |
+
*/
|
37 |
+
public function share_blocked( $details ) {
|
38 |
+
|
39 |
+
}
|
40 |
+
}
|
modules/comments/class-comments.php
ADDED
@@ -0,0 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Comments class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Modules\Comments;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
use WP_Error;
|
12 |
+
|
13 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
14 |
+
defined( 'ABSPATH' ) || die();
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Comments.
|
18 |
+
*
|
19 |
+
* @since 5.0.0
|
20 |
+
*/
|
21 |
+
class Comments {
|
22 |
+
/**
|
23 |
+
* Comments constructor.
|
24 |
+
*
|
25 |
+
* @since 5.0.0
|
26 |
+
* @access public
|
27 |
+
*/
|
28 |
+
public function __construct() {
|
29 |
+
add_filter( 'zerospam_setting_sections', array( $this, 'sections' ) );
|
30 |
+
add_filter( 'zerospam_settings', array( $this, 'settings' ) );
|
31 |
+
add_filter( 'zerospam_types', array( $this, 'types' ), 10, 1 );
|
32 |
+
|
33 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
34 |
+
if ( ! empty( $settings['verify_comments']['value'] ) && 'enabled' === $settings['verify_comments']['value'] ) {
|
35 |
+
add_filter( 'comment_form_defaults', array( $this, 'honeypot' ) );
|
36 |
+
add_action( 'preprocess_comment', array( $this, 'preprocess_comments' ) );
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Add to the types array.
|
42 |
+
*
|
43 |
+
* @since 5.0.0
|
44 |
+
* @access public
|
45 |
+
*/
|
46 |
+
public function types( $types ) {
|
47 |
+
$types['comment'] = __( 'Comment', 'zerospam' );
|
48 |
+
|
49 |
+
return $types;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Preprocess comments.
|
54 |
+
*
|
55 |
+
* @since 5.0.0
|
56 |
+
* @access public
|
57 |
+
*/
|
58 |
+
public function preprocess_comments( $commentdata ) {
|
59 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
60 |
+
$honeypot = ZeroSpam\Core\Utilities::get_honeypot();
|
61 |
+
|
62 |
+
// Check honeypot.
|
63 |
+
if (
|
64 |
+
! empty( $_REQUEST[ $honeypot ] )
|
65 |
+
) {
|
66 |
+
if ( ! empty( $settings['log_blocked_comments']['value'] ) && 'enabled' === $settings['log_blocked_comments']['value'] ) {
|
67 |
+
$details = array(
|
68 |
+
'failed' => 'honeypot',
|
69 |
+
);
|
70 |
+
$details = array_merge( $details, $commentdata );
|
71 |
+
ZeroSpam\Includes\DB::log( 'comment', $details );
|
72 |
+
}
|
73 |
+
|
74 |
+
$message = __( 'You have been flagged as spam/malicious by WordPress Zero Spam.', 'zerospam' );
|
75 |
+
if ( ! empty( $settings['comment_spam_message']['value'] ) ) {
|
76 |
+
$message = $settings['comment_spam_message']['value'];
|
77 |
+
}
|
78 |
+
|
79 |
+
wp_die(
|
80 |
+
$message,
|
81 |
+
__( 'Blocked by WordPress Zero Spam', 'zerospam' ),
|
82 |
+
array(
|
83 |
+
'response' => 403,
|
84 |
+
)
|
85 |
+
);
|
86 |
+
}
|
87 |
+
|
88 |
+
return apply_filters( 'zerospam_preprocess_comment', $commentdata );
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Add a 'honeypot' field to the comment form.
|
93 |
+
*
|
94 |
+
* @since 5.0.0
|
95 |
+
*
|
96 |
+
* @return array The default comment form arguments.
|
97 |
+
*/
|
98 |
+
function honeypot( $defaults ) {
|
99 |
+
$defaults['fields']['wpzerospam_hp'] = ZeroSpam\Core\Utilities::honeypot_field();
|
100 |
+
|
101 |
+
return $defaults;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Comment sections.
|
106 |
+
*
|
107 |
+
* @since 5.0.0
|
108 |
+
* @access public
|
109 |
+
*/
|
110 |
+
public function sections( $sections ) {
|
111 |
+
$sections['comments'] = array(
|
112 |
+
'title' => __( 'Comment Settings', 'zerospam' ),
|
113 |
+
);
|
114 |
+
|
115 |
+
return $sections;
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Botscout settings.
|
120 |
+
*
|
121 |
+
* @since 5.0.0
|
122 |
+
* @access public
|
123 |
+
*/
|
124 |
+
public function settings( $settings ) {
|
125 |
+
$options = get_option( 'wpzerospam' );
|
126 |
+
|
127 |
+
$settings['verify_comments'] = array(
|
128 |
+
'title' => __( 'Detect Spam/Malicious Comments', 'zerospam' ),
|
129 |
+
'section' => 'comments',
|
130 |
+
'type' => 'checkbox',
|
131 |
+
'options' => array(
|
132 |
+
'enabled' => __( 'Monitor comments for malicious or automated spambots.', 'zerospam' ),
|
133 |
+
),
|
134 |
+
'value' => ! empty( $options['verify_comments'] ) ? $options['verify_comments'] : false,
|
135 |
+
);
|
136 |
+
|
137 |
+
if ( ! empty( $options['verify_comments'] ) && 'enabled' === $options['verify_comments'] ) {
|
138 |
+
$message = __( 'You have been flagged as spam/malicious by WordPress Zero Spam.', 'zerospam' );
|
139 |
+
$settings['comment_spam_message'] = array(
|
140 |
+
'title' => __( 'Comment Spam/Malicious Message', 'zerospam' ),
|
141 |
+
'desc' => __( 'Displayed to the user when a comment is detected as spam/malicious.', 'zerospam' ),
|
142 |
+
'section' => 'comments',
|
143 |
+
'type' => 'text',
|
144 |
+
'field_class' => 'large-text',
|
145 |
+
'placeholder' => $message,
|
146 |
+
'value' => ! empty( $options['comment_spam_message'] ) ? $options['comment_spam_message'] : $message,
|
147 |
+
);
|
148 |
+
}
|
149 |
+
|
150 |
+
$settings['log_blocked_comments'] = array(
|
151 |
+
'title' => __( 'Log Blocked Comments', 'zerospam' ),
|
152 |
+
'section' => 'comments',
|
153 |
+
'type' => 'checkbox',
|
154 |
+
'desc' => __( 'Enables logging blocked comments. High traffic sites should leave this disabled.', 'zerospam' ),
|
155 |
+
'options' => array(
|
156 |
+
'enabled' => __( 'Enabled', 'zerospam' ),
|
157 |
+
),
|
158 |
+
'value' => ! empty( $options['log_blocked_comments'] ) ? $options['log_blocked_comments'] : false,
|
159 |
+
);
|
160 |
+
|
161 |
+
return $settings;
|
162 |
+
}
|
163 |
+
}
|
modules/contactform7/class-contactform7.php
ADDED
@@ -0,0 +1,152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Contact Form 7 class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Modules\ContactForm7;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
|
12 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
13 |
+
defined( 'ABSPATH' ) || die();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Contact Form 7.
|
17 |
+
*
|
18 |
+
* @since 5.0.0
|
19 |
+
*/
|
20 |
+
class ContactForm7 {
|
21 |
+
/**
|
22 |
+
* Registration constructor.
|
23 |
+
*
|
24 |
+
* @since 5.0.0
|
25 |
+
* @access public
|
26 |
+
*/
|
27 |
+
public function __construct() {
|
28 |
+
add_filter( 'zerospam_setting_sections', array( $this, 'sections' ) );
|
29 |
+
add_filter( 'zerospam_settings', array( $this, 'settings' ) );
|
30 |
+
add_filter( 'zerospam_types', array( $this, 'types' ), 10, 1 );
|
31 |
+
|
32 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
33 |
+
if ( ! empty( $settings['verify_contactform7']['value'] ) && 'enabled' === $settings['verify_contactform7']['value'] ) {
|
34 |
+
add_filter( 'wpcf7_form_elements', array( $this, 'honeypot' ), 10, 1 );
|
35 |
+
add_filter( 'wpcf7_validate', array( $this, 'preprocess_submission' ), 10, 2 );
|
36 |
+
}
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Add a 'honeypot' field to the form.
|
41 |
+
*
|
42 |
+
* @since 5.0.0
|
43 |
+
*
|
44 |
+
* @return string HTML to append to the form.
|
45 |
+
*/
|
46 |
+
public function honeypot( $this_form_do_shortcode ) {
|
47 |
+
$this_form_do_shortcode .= ZeroSpam\Core\Utilities::honeypot_field();
|
48 |
+
|
49 |
+
return $this_form_do_shortcode;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Preprocess submission.
|
54 |
+
*
|
55 |
+
* @since 5.0.0
|
56 |
+
* @access public
|
57 |
+
*/
|
58 |
+
public function preprocess_submission( $result, $tags ) {
|
59 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
60 |
+
$honeypot = ZeroSpam\Core\Utilities::get_honeypot();
|
61 |
+
|
62 |
+
// Check honeypot.
|
63 |
+
if (
|
64 |
+
! empty( $_REQUEST[ $honeypot ] )
|
65 |
+
) {
|
66 |
+
$message = __( 'You have been flagged as spam/malicious by WordPress Zero Spam.', 'zerospam' );
|
67 |
+
if ( ! empty( $settings['contactform7_spam_message']['value'] ) ) {
|
68 |
+
$message = $settings['contactform7_spam_message']['value'];
|
69 |
+
}
|
70 |
+
$result->invalidate( $tags[0], $message );
|
71 |
+
|
72 |
+
if ( ! empty( $settings['log_blocked_contactform7']['value'] ) && 'enabled' === $settings['log_blocked_contactform7']['value'] ) {
|
73 |
+
$_REQUEST['failed'] = 'honeypot';
|
74 |
+
ZeroSpam\Includes\DB::log( 'contactform7', $_REQUEST );
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
return $result;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Add to the types array.
|
83 |
+
*
|
84 |
+
* @since 5.0.0
|
85 |
+
* @access public
|
86 |
+
*/
|
87 |
+
public function types( $types ) {
|
88 |
+
$types['contactform7'] = __( 'Contact Form 7', 'zerospam' );
|
89 |
+
|
90 |
+
return $types;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Registration sections.
|
95 |
+
*
|
96 |
+
* @since 5.0.0
|
97 |
+
* @access public
|
98 |
+
*/
|
99 |
+
public function sections( $sections ) {
|
100 |
+
$sections['contactform7'] = array(
|
101 |
+
'title' => __( 'Contact Form 7', 'zerospam' ),
|
102 |
+
);
|
103 |
+
|
104 |
+
return $sections;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Botscout settings.
|
109 |
+
*
|
110 |
+
* @since 5.0.0
|
111 |
+
* @access public
|
112 |
+
*/
|
113 |
+
public function settings( $settings ) {
|
114 |
+
$options = get_option( 'wpzerospam' );
|
115 |
+
|
116 |
+
$settings['verify_contactform7'] = array(
|
117 |
+
'title' => __( 'Detect Contact Form 7 Submissions', 'zerospam' ),
|
118 |
+
'section' => 'contactform7',
|
119 |
+
'type' => 'checkbox',
|
120 |
+
'options' => array(
|
121 |
+
'enabled' => __( 'Monitor Contact Form 7 form submissions for malicious or automated spambots.', 'zerospam' ),
|
122 |
+
),
|
123 |
+
'value' => ! empty( $options['verify_contactform7'] ) ? $options['verify_contactform7'] : false,
|
124 |
+
);
|
125 |
+
|
126 |
+
if ( ! empty( $options['verify_contactform7'] ) && 'enabled' === $options['verify_contactform7'] ) {
|
127 |
+
$message = __( 'You have been flagged as spam/malicious by WordPress Zero Spam.', 'zerospam' );
|
128 |
+
$settings['contactform7_spam_message'] = array(
|
129 |
+
'title' => __( 'Contact Form 7 Spam/Malicious Message', 'zerospam' ),
|
130 |
+
'desc' => __( 'Displayed to the user when a submission is detected as spam/malicious.', 'zerospam' ),
|
131 |
+
'section' => 'contactform7',
|
132 |
+
'type' => 'text',
|
133 |
+
'field_class' => 'large-text',
|
134 |
+
'placeholder' => $message,
|
135 |
+
'value' => ! empty( $options['contactform7_spam_message'] ) ? $options['contactform7_spam_message'] : $message,
|
136 |
+
);
|
137 |
+
}
|
138 |
+
|
139 |
+
$settings['log_blocked_contactform7'] = array(
|
140 |
+
'title' => __( 'Log Blocked Contact Form 7 Submissions', 'zerospam' ),
|
141 |
+
'section' => 'contactform7',
|
142 |
+
'type' => 'checkbox',
|
143 |
+
'desc' => __( 'Enables logging blocked Contact Form 7 submissions. High traffic sites should leave this disabled.', 'zerospam' ),
|
144 |
+
'options' => array(
|
145 |
+
'enabled' => __( 'Enabled', 'zerospam' ),
|
146 |
+
),
|
147 |
+
'value' => ! empty( $options['log_blocked_contactform7'] ) ? $options['log_blocked_contactform7'] : false,
|
148 |
+
);
|
149 |
+
|
150 |
+
return $settings;
|
151 |
+
}
|
152 |
+
}
|
modules/registration/class-registration.php
ADDED
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Registration class.
|
4 |
+
*
|
5 |
+
* @package ZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace ZeroSpam\Modules\Registration;
|
9 |
+
|
10 |
+
use ZeroSpam;
|
11 |
+
|
12 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
13 |
+
defined( 'ABSPATH' ) || die();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Registration.
|
17 |
+
*
|
18 |
+
* @since 5.0.0
|
19 |
+
*/
|
20 |
+
class Registration {
|
21 |
+
/**
|
22 |
+
* Registration constructor.
|
23 |
+
*
|
24 |
+
* @since 5.0.0
|
25 |
+
* @access public
|
26 |
+
*/
|
27 |
+
public function __construct() {
|
28 |
+
|
29 |
+
if ( get_option( 'users_can_register' ) ) {
|
30 |
+
add_filter( 'zerospam_setting_sections', array( $this, 'sections' ) );
|
31 |
+
add_filter( 'zerospam_settings', array( $this, 'settings' ) );
|
32 |
+
add_filter( 'zerospam_types', array( $this, 'types' ), 10, 1 );
|
33 |
+
|
34 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
35 |
+
if ( ! empty( $settings['verify_registrations']['value'] ) && 'enabled' === $settings['verify_registrations']['value'] ) {
|
36 |
+
add_action( 'register_form', array( $this, 'honeypot' ) );
|
37 |
+
add_filter( 'registration_errors', array( $this, 'preprocess_registrations' ), 10, 3 );
|
38 |
+
}
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Add to the types array.
|
44 |
+
*
|
45 |
+
* @since 5.0.0
|
46 |
+
* @access public
|
47 |
+
*/
|
48 |
+
public function types( $types ) {
|
49 |
+
$types['registration'] = __( 'Registration', 'zerospam' );
|
50 |
+
|
51 |
+
return $types;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Preprocess registrations.
|
56 |
+
*
|
57 |
+
* @since 5.0.0
|
58 |
+
* @access public
|
59 |
+
*/
|
60 |
+
public function preprocess_registrations( $errors, $sanitized_user_login, $user_email ) {
|
61 |
+
$settings = ZeroSpam\Core\Settings::get_settings();
|
62 |
+
$honeypot = ZeroSpam\Core\Utilities::get_honeypot();
|
63 |
+
|
64 |
+
// Check honeypot.
|
65 |
+
if (
|
66 |
+
! empty( $_REQUEST[ $honeypot ] )
|
67 |
+
) {
|
68 |
+
$message = __( 'You have been flagged as spam/malicious by WordPress Zero Spam.', 'zerospam' );
|
69 |
+
if ( ! empty( $settings['registration_spam_message']['value'] ) ) {
|
70 |
+
$message = $settings['registration_spam_message']['value'];
|
71 |
+
}
|
72 |
+
$errors->add( 'zerospam_error', __( $message, 'zerospam' ) );
|
73 |
+
|
74 |
+
if ( ! empty( $settings['log_blocked_registrations']['value'] ) && 'enabled' === $settings['log_blocked_registrations']['value'] ) {
|
75 |
+
$details = array(
|
76 |
+
'user_login' => $sanitized_user_login,
|
77 |
+
'user_email' => $user_email,
|
78 |
+
'failed' => 'honeypot',
|
79 |
+
);
|
80 |
+
ZeroSpam\Includes\DB::log( 'registration', $details );
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
$errors = apply_filters( 'zerospam_registration_errors', $errors, $sanitized_user_login, $user_email );
|
85 |
+
|
86 |
+
return $errors;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Add a 'honeypot' field to the registration form.
|
91 |
+
*
|
92 |
+
* @since 5.0.0
|
93 |
+
*
|
94 |
+
* @return string HTML to append to the registration form.
|
95 |
+
*/
|
96 |
+
public function honeypot() {
|
97 |
+
echo ZeroSpam\Core\Utilities::honeypot_field();
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Registration sections.
|
102 |
+
*
|
103 |
+
* @since 5.0.0
|
104 |
+
* @access public
|
105 |
+
*/
|
106 |
+
public function sections( $sections ) {
|
107 |
+
$sections['registration'] = array(
|
108 |
+
'title' => __( 'Registration Settings', 'zerospam' ),
|
109 |
+
);
|
110 |
+
|
111 |
+
return $sections;
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Botscout settings.
|
116 |
+
*
|
117 |
+
* @since 5.0.0
|
118 |
+
* @access public
|
119 |
+
*/
|
120 |
+
public function settings( $settings ) {
|
121 |
+
$options = get_option( 'wpzerospam' );
|
122 |
+
|
123 |
+
$settings['verify_registrations'] = array(
|
124 |
+
'title' => __( 'Detect Spam/Malicious Registrations', 'zerospam' ),
|
125 |
+
'section' => 'registration',
|
126 |
+
'type' => 'checkbox',
|
127 |
+
'options' => array(
|
128 |
+
'enabled' => __( 'Monitor registrations for malicious or automated spambots.', 'zerospam' ),
|
129 |
+
),
|
130 |
+
'value' => ! empty( $options['verify_registrations'] ) ? $options['verify_registrations'] : false,
|
131 |
+
);
|
132 |
+
|
133 |
+
if ( ! empty( $options['verify_registrations'] ) && 'enabled' === $options['verify_registrations'] ) {
|
134 |
+
$message = __( 'You have been flagged as spam/malicious by WordPress Zero Spam.', 'zerospam' );
|
135 |
+
$settings['registration_spam_message'] = array(
|
136 |
+
'title' => __( 'Registration Spam/Malicious Message', 'zerospam' ),
|
137 |
+
'desc' => __( 'Displayed to the user when a registration is detected as spam/malicious.', 'zerospam' ),
|
138 |
+
'section' => 'registration',
|
139 |
+
'type' => 'text',
|
140 |
+
'field_class' => 'large-text',
|
141 |
+
'placeholder' => $message,
|
142 |
+
'value' => ! empty( $options['registration_spam_message'] ) ? $options['registration_spam_message'] : $message,
|
143 |
+
);
|
144 |
+
}
|
145 |
+
|
146 |
+
$settings['log_blocked_registrations'] = array(
|
147 |
+
'title' => __( 'Log Blocked Registrations', 'zerospam' ),
|
148 |
+
'section' => 'registration',
|
149 |
+
'type' => 'checkbox',
|
150 |
+
'desc' => __( 'Enables logging blocked registrations. High traffic sites should leave this disabled.', 'zerospam' ),
|
151 |
+
'options' => array(
|
152 |
+
'enabled' => __( 'Enabled', 'zerospam' ),
|
153 |
+
),
|
154 |
+
'value' => ! empty( $options['log_blocked_registrations'] ) ? $options['log_blocked_registrations'] : false,
|
155 |
+
);
|
156 |
+
|
157 |
+
return $settings;
|
158 |
+
}
|
159 |
+
}
|
readme.txt
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
=== WordPress Zero Spam ===
|
2 |
-
Contributors: bmarshall511
|
3 |
Tags: comments, spam, antispam, anti-spam, comment spam, spambot, spammer, spam free, spam blocker, registration spam
|
4 |
Donate link: https://www.benmarshall.me/donate/?utm_source=wordpress_zero_spam&utm_medium=wordpress_repo&utm_campaign=donate
|
5 |
Requires at least: 5.2
|
6 |
Tested up to: 5.5
|
7 |
-
Requires PHP: 7.
|
8 |
-
Stable tag:
|
9 |
License: GNU GPLv3
|
10 |
License URI: https://choosealicense.com/licenses/gpl-3.0/
|
11 |
|
@@ -13,38 +13,27 @@ WordPress Zero Spam makes blocking spam & malicious visitors a cinch. Just insta
|
|
13 |
|
14 |
== Description ==
|
15 |
|
16 |
-
Quit forcing
|
17 |
|
18 |
-
[WordPress Zero Spam](https://www.benmarshall.me/wordpress-zero-spam/?utm_source=wordpress.org&utm_medium=plugin&utm_campaign=wordpress_zero_spam) uses AI in combination with proven spam detection techniques and
|
19 |
|
20 |
-
|
21 |
|
22 |
= WordPress Zero Spam features =
|
23 |
|
24 |
-
*
|
25 |
-
*
|
26 |
-
*
|
27 |
-
*
|
28 |
-
*
|
29 |
-
*
|
30 |
-
*
|
31 |
-
*
|
32 |
-
* **Manually block IPs** either temporarily or permanently
|
33 |
-
* **Whitelist IPs** to avoid getting blocked
|
34 |
-
* **Geolocate IP addresses** to see where spammers are coming from
|
35 |
-
* **Detailed logging** to catch & block recurring spammers
|
36 |
-
* **Charts & statistics** for easy to understand spam analytics
|
37 |
-
* **Advanced settings** for complete control over spammers
|
38 |
-
* **Developer-friendly**, integrate with any theme, plugin or form
|
39 |
|
40 |
= WordPress Zero Spam also protects =
|
41 |
|
42 |
* WordPress core comments & user registrations
|
43 |
* [Contact Form 7](https://wordpress.org/plugins/contact-form-7/) submissions
|
44 |
-
* [BuddyPress](https://wordpress.org/plugins/buddypress/) registrations
|
45 |
-
* [WPForms](https://wordpress.org/plugins/wpforms-lite/) submissions
|
46 |
-
* [WP Fluent Form](https://wordpress.org/plugins/fluentform/) submissions
|
47 |
-
* [Formidable Form Builder](https://wordpress.org/plugins/formidable/) submissions
|
48 |
* and can be easily integrated into any existing theme or plugin
|
49 |
|
50 |
WordPress Zero Spam is great at blocking spam — as a site owner there's more you can do to [stop WordPress spam](https://www.benmarshall.me/stop-wordpress-spam/) in its tracks.
|
@@ -53,16 +42,6 @@ WordPress Zero Spam is great at blocking spam — as a site owner there's mo
|
|
53 |
|
54 |
We’ve integrated multi language support within the framework of our plugin, so you get a translated dashboard out of the box, and developer options to add even more languages. Contribute new languages via [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/zero-spam/).
|
55 |
|
56 |
-
* [French](https://translate.wordpress.org/locale/fr/default/wp-plugins/zero-spam/) – (fr_FR)
|
57 |
-
* [Italian](https://translate.wordpress.org/locale/it/default/wp-plugins/zero-spam/) – (it_IT)
|
58 |
-
|
59 |
-
= Developer API =
|
60 |
-
|
61 |
-
WordPress Zero Spam is free and open source. It’s the perfect solution to stopping spam and can be extended and integrated further. It was created and developed with the developer in mind, and we have already seen some truly remarkable addons already developed.
|
62 |
-
|
63 |
-
To help you get started and learn just how to integrate with WordPress Zero Spam, visit the [plugin's documentation](https://www.benmarshall.me/wordpress-zero-spam/?utm_source=wordpress.org&utm_medium=plugin&utm_campaign=wordpress_zero_spam).
|
64 |
-
|
65 |
-
|
66 |
= Help test & contribute to WordPress Zero Spam =
|
67 |
|
68 |
WordPress Zero Spam can only stay up-to-date and bug-free with the help of contributors and testers. You can help test upcoming releases and contribute by forking the project on [GitHub](https://github.com/bmarshall511/wordpress-zero-spam).
|
@@ -85,54 +64,16 @@ WordPress Zero Spam can only stay up-to-date and bug-free with the help of contr
|
|
85 |
|
86 |
1. Upload the entire wordpress-zero-spam folder to the */wp-content/plugins/* directory.
|
87 |
2. Activate the plugin through the Plugins screen (*Plugins > Installed Plugins*).
|
88 |
-
3. Visit the plugin setting to configure as needed (*Settings >
|
89 |
|
90 |
For more information & developer documentation, see the [plugin’s website](https://www.benmarshall.me/wordpress-zero-spam).
|
91 |
|
92 |
== Frequently Asked Questions ==
|
93 |
|
94 |
-
= Does WordPress Zero Spam check Ninja Forms submissions? =
|
95 |
-
|
96 |
-
**No.** As of v4.10.0, WordPress Zero Spam no longer checks Ninja Form submissions. Support was dropped due to its [requirement of JavaScript](https://developer.ninjaforms.com/codex/loading-the-form-via-ajax/) and how it submits forms. JavaScript is one of the techniques WordPress Zero Spam uses to determine if a submission is spam. Ninja Forms employs a similar method and has its own [spam detection](https://ninjaforms.com/blog/spam-wordpress-form/) feature.
|
97 |
-
|
98 |
-
**Does this mean WPZP won't do you any good? Absolutely not.** WPZS employs other techniques and IP blacklist checks that will help prevent malicious IP and spambots from ever seeing your site. You will still get all of the benefits of this plugin, it just won't provide the extra check on Ninja Form submissions.
|
99 |
-
|
100 |
-
= Does WordPress Zero Spam check Gravity Form submissions? =
|
101 |
-
|
102 |
-
**No.** As of v4.9.9, WordPress Zero Spam no longer checks Gravity Form submissions. Support was dropped due the numerous addon plugins that can be installed & alter GF submissions. These addons will often conflict with how WPZS validates submissions. In addition, Gravity Forms already has a spam detection option that works similar to how this plugin detects forms. You can enable it by going to the form settings and checking the *Enable anti-spam honeypot* option. For more information, see [Gravity Forms documentation](https://docs.gravityforms.com/form-settings/).
|
103 |
-
|
104 |
-
**Does this mean WPZP won't do you any good? Absolutely not.** WPZS employs other techniques and IP blacklist checks that will help prevent malicious IP and spambots from ever seeing your site. You will still get all of the benefits of this plugin, it just won't provide the extra check on Gravity Form submissions.
|
105 |
-
|
106 |
= Does WordPress Zero Spam check Jetpack comments? =
|
107 |
|
108 |
**No.** WordPress Zero Spam is unable to integrate Jetpack. For more information, see [https://wordpress.org/support/topic/incompatible-with-jetpack-comments](https://wordpress.org/support/topic/incompatible-with-jetpack-comments).
|
109 |
|
110 |
-
= Spam coments are still getting through, help! =
|
111 |
-
|
112 |
-
WordPress Zero Spam relies on the default core form id (`#commentform`) in order to check comment submissions. Verify your comment forms have this ID or add the class `wpzerospam` to enable it on your site.
|
113 |
-
|
114 |
-
= All registrations are marked as spam, help! =
|
115 |
-
|
116 |
-
This is most likely due to a plugin or theme overriding the default markup of the registration form. Verify the form has an id of `registerform` or add the `wpzerospam` class to it.
|
117 |
-
|
118 |
-
Example with `registerform` id:
|
119 |
-
|
120 |
-
`<form name="registerform" id="registerform" action="https://yourdomain.local/login/?action=register" method="post" novalidate="novalidate">`
|
121 |
-
|
122 |
-
Example with `wpzerospam` class:
|
123 |
-
|
124 |
-
`<form name="registerform" class="wpzerospam" action="https://yourdomain.local/login/?action=register" method="post" novalidate="novalidate">`
|
125 |
-
|
126 |
-
If you need help, please don't hesitate to [reach out](https://www.benmarshall.me/contact/?utm_source=wordpress.org&utm_medium=plugin&utm_campaign=wordpress_zero_spam).
|
127 |
-
|
128 |
-
= How do I integrate this into another plugin or theme? =
|
129 |
-
|
130 |
-
It's easy as adding the class `wpzerospam` to the `form` element, then adding a check in the form processor that the `wpzerospam_key` post value matches the option value in the database using the `wpzerospam_key_check()` helper function. See the [plugin's documentation](https://www.benmarshall.me/wordpress-zero-spam/?utm_source=wordpress.org&utm_medium=plugin&utm_campaign=wordpress_zero_spam) for more information on available hooks & functions.
|
131 |
-
|
132 |
-
= Is JavaScript required to check form submissions? =
|
133 |
-
|
134 |
-
Yes. One of the many techniques WordPress Zero Spam employs requires JavaScript be enabled to work properly.
|
135 |
-
|
136 |
== Screenshots ==
|
137 |
|
138 |
1. WordPress Zero Spam dashboard
|
@@ -143,240 +84,9 @@ Yes. One of the many techniques WordPress Zero Spam employs requires JavaScript
|
|
143 |
|
144 |
== Changelog ==
|
145 |
|
146 |
-
=
|
147 |
-
|
148 |
-
* Added composer. See [#150](https://github.com/bmarshall511/wordpress-zero-spam/pull/150/).
|
149 |
-
* Temporarily disabled sharing spam detection information.
|
150 |
-
|
151 |
-
= 4.10.2 =
|
152 |
-
|
153 |
-
* Update to comply with the GDPR/CCPA. See [#216](https://github.com/bmarshall511/wordpress-zero-spam/issues/216).
|
154 |
-
|
155 |
-
= 4.10.1 =
|
156 |
-
|
157 |
-
* Fix - PHP notice `Warning: array_merge(): Expected parameter 2 to be an array, bool given in /wp-content/plugins/zero-spam/classes/class-wordpress-zero-spam.php on line 532`. See https://wordpress.org/support/topic/warning-array_merge-14/#post-13319702.
|
158 |
-
* Fix - StopForumSpam & BotScout being queried even if the options are disabled. See https://wordpress.org/support/topic/api-timeout/#post-13323551.
|
159 |
-
* Enhancement - Moved the security functions into the new `WordPress_Zero_Spam_Security` class.
|
160 |
-
* Enhancement - General code clean-up & documentation.
|
161 |
-
|
162 |
-
= 4.10.0 =
|
163 |
-
|
164 |
-
* Enhancement - Various performance improvements & caching added.
|
165 |
-
* Enhancement - Easier to use class methods for integrating Zero Spam into any plugin or theme.
|
166 |
-
* Enhancement - New `WordPress_Zero_Spam` class added.
|
167 |
-
* Enhancement - IPs are now checked against known, safe hosts and user agents (i.e. search engine crawlers).
|
168 |
-
* Enhancement - Added advanced debugging functionality.
|
169 |
-
|
170 |
-
= 4.9.13 =
|
171 |
-
|
172 |
-
* Fix - PHP notices for comment options [#209](https://github.com/bmarshall511/wordpress-zero-spam/issues/209)
|
173 |
-
|
174 |
-
= 4.9.12 =
|
175 |
-
|
176 |
-
* Enhancement - Added support for the French & Italian languages. See [#207](https://github.com/bmarshall511/wordpress-zero-spam/issues/207).
|
177 |
-
* Enhancement - Strengthened spam detection for registrations using a 'honeypot' field.
|
178 |
-
* Enhancement - Strengthened spam detection for Contact Form 7 using a 'honeypot' field.
|
179 |
-
* Fix - Fix for Contact Form 7 protection not firing.
|
180 |
-
|
181 |
-
= 4.9.11 =
|
182 |
-
|
183 |
-
* Optimization - Converted the WPZS JS to be a jQuery plugin to initialize and manage easier.
|
184 |
-
* Fix - Fix for WPZS failing when the Autoptimize plugin is set to aggregate JS files. See [#205](https://github.com/bmarshall511/wordpress-zero-spam/issues/205).
|
185 |
-
|
186 |
-
= 4.9.10 =
|
187 |
-
|
188 |
-
* Fix - Fix for PHP notice relating to an undefined variable, `strip_comment_links`. See [https://wordpress.org/support/topic/im-getting-this-after-latest-update/](https://wordpress.org/support/topic/im-getting-this-after-latest-update/).
|
189 |
-
|
190 |
-
= 4.9.9 =
|
191 |
-
|
192 |
-
* Enhancement - Strengthened spam detection for comment submission using a 'honeypot' field.
|
193 |
-
* Enhancement - Added a 'honeypot' helper functions (`wpzerospam_honeypot_field()`, `wpzerospam_get_honeypot()`) to allow other forms, plugins, and themes to easily integrate a 'honeypot' check into submissions.
|
194 |
-
* Enhancement - IP lookup links integrated in the admin dashboard and tables.
|
195 |
-
* Deprecation - Gravity Forms is no longer supported — for the time being. See the plugin FAQs for more information.
|
196 |
-
|
197 |
-
= 4.9.8 =
|
198 |
-
|
199 |
-
* Fix - Fix for a reporting issue during detections.
|
200 |
-
|
201 |
-
= 4.9.7 =
|
202 |
-
|
203 |
-
* Enhancement - Added enhanced site security features (no configuration required)
|
204 |
-
* Enhancement - Added plugin version to the information shared to Zero Spam (optional).
|
205 |
-
* Optimization - Misc. code clean-up
|
206 |
-
|
207 |
-
= 4.9.6 =
|
208 |
-
|
209 |
-
* Fix - Gravity Forms not catching spam.
|
210 |
-
|
211 |
-
= 4.9.5 =
|
212 |
-
|
213 |
-
* Enhancement - Added the *BotScout Count Minimum* field in settings to allow sites to control when a BotScout result should be marked spam/malicious. See [BotScout's documentation](https://botscout.com/api.htm) for more information.
|
214 |
-
* Enhancement - Improved performance by only querying the blacklist API once every X number of days (set in the admin settings).
|
215 |
-
* Fix - Removed double slashes in some required PHP & JS paths.
|
216 |
-
|
217 |
-
= 4.9.4 =
|
218 |
-
|
219 |
-
* Fixed issued with BuddyPress checks not running.
|
220 |
-
|
221 |
-
= 4.9.3 =
|
222 |
-
|
223 |
-
* Added a confidence threshold for Stop Form Spam checks. See [#202](https://github.com/bmarshall511/wordpress-zero-spam/issues/202);
|
224 |
-
* Added an API timeout field to adjust how long a response is allowed to take.
|
225 |
-
* Restructred several functions which fixed some interment bugs users were experiencing.
|
226 |
-
* Added ability to delete all entries from a table.
|
227 |
-
* This update **will delete all exisiting blacklisted IPs** to ensure visitors aren't getting blocked when that shouldn't be.
|
228 |
-
|
229 |
-
= 4.9.2 =
|
230 |
-
|
231 |
-
* Removed Ninja Form submission support. See FAQs for more details.
|
232 |
-
* Fix for PHP notice on the log page in the view details modal.
|
233 |
-
* Fix for double slashes in the JS URLs.
|
234 |
-
* Fix for BotScout not checking IPs
|
235 |
-
* Fix for table not found notice on activation
|
236 |
-
|
237 |
-
= 4.9.1 =
|
238 |
-
|
239 |
-
Fix for PHP notice on the modals for spam detections
|
240 |
-
|
241 |
-
= 4.9.0 =
|
242 |
-
|
243 |
-
* Added support for [Formidable Forms](https://wordpress.org/plugins/formidable/). See [#112](https://github.com/bmarshall511/wordpress-zero-spam/issues/112).
|
244 |
-
* Added additional country regions
|
245 |
-
* UI enhancments to the admin tables
|
246 |
-
* Added a spam detection world map to the dashboard
|
247 |
-
|
248 |
-
= 4.8.2 =
|
249 |
-
|
250 |
-
* Fix for admin table paging keeping set filters
|
251 |
-
|
252 |
-
= 4.8.1 =
|
253 |
-
|
254 |
-
* Fix for charts not showing up in the dashboard
|
255 |
-
|
256 |
-
= 4.8.0 =
|
257 |
-
|
258 |
-
* Added filter & seach options to admin tables
|
259 |
-
* Various performance enhancements
|
260 |
-
* Added ability to whitelist IP addresses
|
261 |
-
|
262 |
-
= 4.7.1 =
|
263 |
-
|
264 |
-
* Update to the WP Zero Spam API
|
265 |
-
|
266 |
-
= 4.7.0 =
|
267 |
-
|
268 |
-
* Various performance enhancements
|
269 |
-
* Updates to the admin tables
|
270 |
-
* Improved UI
|
271 |
-
* Added functionality & option to permanently auto-block after X spam detections
|
272 |
-
* Added ability to share spam detections with WordPress Zero Spam to strengthen it's ability to detect spammers
|
273 |
-
|
274 |
-
= 4.6.0 =
|
275 |
-
|
276 |
-
* Added option to strip links from comments
|
277 |
-
* Added option to strip & disable the comment author website field
|
278 |
-
* Added integration with the BotScout blacklist API
|
279 |
-
|
280 |
-
= 4.5.0 =
|
281 |
-
|
282 |
-
* Added integration with the Stop Forum Spam known spammy IPs
|
283 |
-
* Fixed issue with Gravity Forms not being enabled by default
|
284 |
-
|
285 |
-
= 4.4.1 =
|
286 |
-
|
287 |
-
* Fix for Gravity Forms not submitting
|
288 |
-
|
289 |
-
= 4.4.0 =
|
290 |
-
|
291 |
-
* Misc. code clean-up
|
292 |
-
* Added support for the Fluent Forms plugin
|
293 |
-
|
294 |
-
= 4.3.10 =
|
295 |
-
|
296 |
-
* Updated get_plugin_data calls to use a constant. See [#196](https://github.com/bmarshall511/wordpress-zero-spam/issues/196)
|
297 |
-
* Added additional country regions for geolocation lookup
|
298 |
-
* Renamed 'addons' to 'integrations'
|
299 |
-
* Fixed issue with WPForm spam detections
|
300 |
-
* Fix for plugin deactivation from v3 to v4 upgrade
|
301 |
-
|
302 |
-
= 4.3.9 =
|
303 |
-
|
304 |
-
* Fix for `Notice: Undefined index: verify_ninja_form`. See [#195](https://github.com/bmarshall511/wordpress-zero-spam/issues/195)
|
305 |
-
|
306 |
-
= 4.3.8 =
|
307 |
-
|
308 |
-
* Fix for `Call to undefined function wpzerospam_tables()` error
|
309 |
-
|
310 |
-
= 4.3.7 =
|
311 |
-
|
312 |
-
* Optimized scripts & when they get loaded (only when needed)
|
313 |
-
* Fixed bug with incrementing spam detections in the blocked IPs log
|
314 |
-
|
315 |
-
= 4.3.6 =
|
316 |
-
|
317 |
-
* Added a check for the `is_plugin_active` functions to ensure they're available before calling it
|
318 |
-
|
319 |
-
= 4.3.5 =
|
320 |
-
|
321 |
-
* Fix for `Uncaught Error: Call to undefined function get_plugin_data()`. See [#193](https://github.com/bmarshall511/wordpress-zero-spam/issues/193).
|
322 |
-
|
323 |
-
= 4.3.4 =
|
324 |
-
|
325 |
-
* Fixed issue with adding/updating IP addresses manually
|
326 |
-
* Fixed PHP notice for missing submission data on the log chart
|
327 |
-
* Fixed PHP notice for "Undefined index: log_blocked_ips". See [#191](https://github.com/bmarshall511/wordpress-zero-spam/issues/191)
|
328 |
-
* Updated the admin scripts to only login on the plugin admin pages
|
329 |
-
* Fixed an issue with default add-on plugin options being disabled on first save. See [#192](https://github.com/bmarshall511/wordpress-zero-spam/issues/192)
|
330 |
-
|
331 |
-
= 4.3.3 =
|
332 |
-
|
333 |
-
* Fix for `REFERRER_ANALYTICS` unknown constant
|
334 |
-
|
335 |
-
= 4.3.2 =
|
336 |
-
|
337 |
-
* Fix for Gravity Forms PHP notice. See [#188](https://github.com/bmarshall511/wordpress-zero-spam/issues/188)
|
338 |
-
* Add more stats & charts. See [#184](https://github.com/bmarshall511/wordpress-zero-spam/issues/184)
|
339 |
-
|
340 |
-
= 4.3.1 =
|
341 |
-
|
342 |
-
* Fixing plugin version
|
343 |
-
|
344 |
-
= 4.3.0 =
|
345 |
-
|
346 |
-
* Added the ability to manually add blocked IPs. See [#185](https://github.com/bmarshall511/wordpress-zero-spam/issues/185)
|
347 |
-
* Fixed the ignored start & end date of blocked IPs
|
348 |
-
* Added the ability to auto-block an IP when spam is detected. See [#185](https://github.com/bmarshall511/wordpress-zero-spam/issues/185)
|
349 |
-
* Added raw data to spammer log table
|
350 |
-
* Added the ability to uninstall options on Multisite. See [#187](https://github.com/bmarshall511/wordpress-zero-spam/pull/187)
|
351 |
-
|
352 |
-
= 4.2.0 =
|
353 |
-
|
354 |
-
* Re-implemented logging & added admin pages to prepare for charts & statistics. See [#181](https://github.com/bmarshall511/wordpress-zero-spam/issues/181)
|
355 |
-
|
356 |
-
= 4.1.3 =
|
357 |
-
|
358 |
-
* Fixed JS errors for some 3rd-party plugins. See [#178](https://github.com/bmarshall511/wordpress-zero-spam/issues/178)
|
359 |
-
* Fixed caching conflicts issue relating to using cookies to set & get keys. See [#177](https://github.com/bmarshall511/wordpress-zero-spam/issues/177)
|
360 |
-
* When plugin is uninstalled, plugin-related data is now deleted. See [#179](https://github.com/bmarshall511/wordpress-zero-spam/issues/179)
|
361 |
-
* Added an option in the plugin settings to determine how spam detections are handled. See [#180](https://github.com/bmarshall511/wordpress-zero-spam/issues/180)
|
362 |
-
|
363 |
-
= 4.1.2 =
|
364 |
-
|
365 |
-
* Fixed issue with plugin settings not saving. See [#176](https://github.com/bmarshall511/wordpress-zero-spam/issues/176).
|
366 |
-
* Fixed some PHP notices. See [#175](https://github.com/bmarshall511/wordpress-zero-spam/issues/175).
|
367 |
-
|
368 |
-
= v4.1.1 =
|
369 |
-
|
370 |
-
* Fixed missing JS for new 3rd-party plugin support
|
371 |
-
|
372 |
-
= v4.1.0 =
|
373 |
-
|
374 |
-
* Added support for [Contact Form 7](https://wordpress.org/plugins/contact-form-7/)
|
375 |
-
* Added support for [Gravity Forms](https://www.gravityforms.com/)
|
376 |
-
* Added support for [Ninja Forms](https://wordpress.org/plugins/ninja-forms/)
|
377 |
-
* Added support for [BuddyPress](https://wordpress.org/plugins/buddypress/)
|
378 |
-
* Added support for [Contact Form by WPForms](https://wordpress.org/plugins/wpforms-lite/)
|
379 |
-
|
380 |
-
= v4.0.0 =
|
381 |
|
382 |
-
*
|
|
|
|
|
|
1 |
=== WordPress Zero Spam ===
|
2 |
+
Contributors: bmarshall511
|
3 |
Tags: comments, spam, antispam, anti-spam, comment spam, spambot, spammer, spam free, spam blocker, registration spam
|
4 |
Donate link: https://www.benmarshall.me/donate/?utm_source=wordpress_zero_spam&utm_medium=wordpress_repo&utm_campaign=donate
|
5 |
Requires at least: 5.2
|
6 |
Tested up to: 5.5
|
7 |
+
Requires PHP: 7.2
|
8 |
+
Stable tag: 5.0.0
|
9 |
License: GNU GPLv3
|
10 |
License URI: https://choosealicense.com/licenses/gpl-3.0/
|
11 |
|
13 |
|
14 |
== Description ==
|
15 |
|
16 |
+
Quit forcing people to answer questions or confusing captchas to prove they're not spam. Stop malicious users before they ever have a chance to infiltrate your site — **introducing WordPress Zero Spam**.
|
17 |
|
18 |
+
[WordPress Zero Spam](https://www.benmarshall.me/wordpress-zero-spam/?utm_source=wordpress.org&utm_medium=plugin&utm_campaign=wordpress_zero_spam) uses AI in combination with proven spam detection techniques and databases of known malicious IPs from around the world to detect and block unwanted visitors.
|
19 |
|
20 |
+
**Just install, activate, and enjoy a spam-free site!**
|
21 |
|
22 |
= WordPress Zero Spam features =
|
23 |
|
24 |
+
* Blocks 99.9% of spam & malicious visitors
|
25 |
+
* No captcha, spam isn't a users' problem
|
26 |
+
* No moderation queues, spam isn't a administrators' problem
|
27 |
+
* IP blacklist spam checks ([Zero Spam](https://www.zerospam.org), [Stop Forum Spam](https://www.stopforumspam.com/))
|
28 |
+
* Automatically & manually block IPs temporarily or permanently
|
29 |
+
* Geolocate IP addresses to see where offenders are coming from
|
30 |
+
* Detailed logging to catch, investigate & block recurring offenders
|
31 |
+
* Developer-friendly, integrate with any theme, plugin or form
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
|
33 |
= WordPress Zero Spam also protects =
|
34 |
|
35 |
* WordPress core comments & user registrations
|
36 |
* [Contact Form 7](https://wordpress.org/plugins/contact-form-7/) submissions
|
|
|
|
|
|
|
|
|
37 |
* and can be easily integrated into any existing theme or plugin
|
38 |
|
39 |
WordPress Zero Spam is great at blocking spam — as a site owner there's more you can do to [stop WordPress spam](https://www.benmarshall.me/stop-wordpress-spam/) in its tracks.
|
42 |
|
43 |
We’ve integrated multi language support within the framework of our plugin, so you get a translated dashboard out of the box, and developer options to add even more languages. Contribute new languages via [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/zero-spam/).
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
= Help test & contribute to WordPress Zero Spam =
|
46 |
|
47 |
WordPress Zero Spam can only stay up-to-date and bug-free with the help of contributors and testers. You can help test upcoming releases and contribute by forking the project on [GitHub](https://github.com/bmarshall511/wordpress-zero-spam).
|
64 |
|
65 |
1. Upload the entire wordpress-zero-spam folder to the */wp-content/plugins/* directory.
|
66 |
2. Activate the plugin through the Plugins screen (*Plugins > Installed Plugins*).
|
67 |
+
3. Visit the plugin setting to configure as needed (*Settings > Zero Spam*).
|
68 |
|
69 |
For more information & developer documentation, see the [plugin’s website](https://www.benmarshall.me/wordpress-zero-spam).
|
70 |
|
71 |
== Frequently Asked Questions ==
|
72 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
= Does WordPress Zero Spam check Jetpack comments? =
|
74 |
|
75 |
**No.** WordPress Zero Spam is unable to integrate Jetpack. For more information, see [https://wordpress.org/support/topic/incompatible-with-jetpack-comments](https://wordpress.org/support/topic/incompatible-with-jetpack-comments).
|
76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
== Screenshots ==
|
78 |
|
79 |
1. WordPress Zero Spam dashboard
|
84 |
|
85 |
== Changelog ==
|
86 |
|
87 |
+
= v5.0.0 =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
|
89 |
+
* Initial v5.0.0 release
|
90 |
+
* Huge performance enhancements
|
91 |
+
* More control over settings to fine-tune functionality
|
92 |
+
* Lots of bug fixes & improvements
|
templates/callout.php
DELETED
@@ -1,51 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Plugin callout
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 4.6.0
|
7 |
-
*/
|
8 |
-
?>
|
9 |
-
|
10 |
-
<div class="wpzerospam-callout">
|
11 |
-
<div class="wpzerospam-callout-content">
|
12 |
-
<h2><?php
|
13 |
-
echo sprintf(
|
14 |
-
wp_kses(
|
15 |
-
__( 'Help support the <a href="%s" target="_blank" rel="noopener noreferrer">WordPress Zero Spam</a> plugin.', 'zero-spam' ),
|
16 |
-
[ 'a' => [ 'target' => [], 'href' => [], 'rel' => [] ] ]
|
17 |
-
),
|
18 |
-
esc_url( 'https://benmarshall.me/wordpress-zero-spam/?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=donation' )
|
19 |
-
);
|
20 |
-
?></h2>
|
21 |
-
<p><?php
|
22 |
-
echo sprintf(
|
23 |
-
wp_kses(
|
24 |
-
__( 'Support the continued development of the WPZS by <a href="%s" target="_blank" rel="noopener noreferrer">donating today</a>. Donation goes towards the time it takes to develop new features & updates, but also helps provide pro bono work for nonprofits. <a href="%s" target="_blank" rel="noopener noreferrer">Learn more</a>.', 'zero-spam' ),
|
25 |
-
[ 'a' => [ 'target' => [], 'href' => [], 'rel' => [] ] ]
|
26 |
-
),
|
27 |
-
esc_url( 'https://benmarshall.me/donate/?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=donation' ),
|
28 |
-
esc_url( 'https://benmarshall.me/donate/?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=donation' )
|
29 |
-
);
|
30 |
-
?></p>
|
31 |
-
<p><?php
|
32 |
-
echo sprintf(
|
33 |
-
wp_kses(
|
34 |
-
__( '<strong>Integrate Zero Spam in any application</strong> with the <a href="%s" target="_blank" rel="noopener noreferrer">Zero Spam Blacklist API</a>.', 'zero-spam' ),
|
35 |
-
[ 'strong' => [], 'a' => [ 'target' => [], 'href' => [], 'rel' => [] ] ]
|
36 |
-
),
|
37 |
-
esc_url( 'https://zerospam.org/spam-blacklist-api/' )
|
38 |
-
);
|
39 |
-
?></p>
|
40 |
-
</div>
|
41 |
-
<div class="wpzerospam-callout-actions">
|
42 |
-
<a href="https://github.com/bmarshall511/wordpress-zero-spam/issues" class="button" target="_blank"><?php _e( 'Submit Bug/Feature Request', 'zero-spam' ); ?></a>
|
43 |
-
<a href="https://twitter.com/ZeroSpamOrg" class="button" target="_blank"><?php _e( 'Follow us on Twitter', 'zero-spam' ); ?></a>
|
44 |
-
<a href="https://www.facebook.com/zerospamorg/" class="button" target="_blank"><?php _e( 'Like us on Facebook', 'zero-spam' ); ?></a>
|
45 |
-
<a href="https://zerospam.org/" class="button" target="_blank"><?php _e( 'Learn more about Zero Spam', 'zero-spam' ); ?></a>
|
46 |
-
<a href="https://github.com/bmarshall511/wordpress-zero-spam" class="button" target="_blank"><?php _e( 'Fork on Github', 'zero-spam' ); ?></a>
|
47 |
-
<a href="https://benmarshall.me/donate?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=admin" class="button button-primary" target="_blank"><?php _e( 'Show your Support — Donate', 'zero-spam' ); ?></a>
|
48 |
-
</div>
|
49 |
-
</div>
|
50 |
-
|
51 |
-
<p><strong><?php _e( 'Your IP Address:', 'zero-spam' ); ?>:</strong> <code><?php echo wpzerospam_ip(); ?></code></p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
templates/countries-pie-chart.php
DELETED
@@ -1,70 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Countries pie chart
|
4 |
-
*
|
5 |
-
* @package ReferrerAnalytics
|
6 |
-
* @since 1.0.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
$chart_limit = 10;
|
10 |
-
?>
|
11 |
-
<div class="wpzerospam-box wpzerospam-box-countries-pie">
|
12 |
-
<h3><?php _e( 'Most Spam by Country', 'zero-spam' ); ?></h3>
|
13 |
-
<div class="inside">
|
14 |
-
<?php
|
15 |
-
if ( $log ):
|
16 |
-
$countries = [];
|
17 |
-
foreach( $log as $key => $entry ):
|
18 |
-
|
19 |
-
$k = wpzerospam_get_location( $entry->country );
|
20 |
-
if ( empty( $countries[ $k ] ) ):
|
21 |
-
$countries[ $k ] = 1;
|
22 |
-
else:
|
23 |
-
$countries[ $k ]++;
|
24 |
-
endif;
|
25 |
-
endforeach;
|
26 |
-
|
27 |
-
if ( $countries ):
|
28 |
-
arsort( $countries );
|
29 |
-
endif;
|
30 |
-
?>
|
31 |
-
<canvas id="wpzerospam-pie-countries"></canvas>
|
32 |
-
<script>
|
33 |
-
<?php
|
34 |
-
$labels = [];
|
35 |
-
$data = [];
|
36 |
-
$count = 0;
|
37 |
-
foreach( $countries as $key => $value ):
|
38 |
-
if ( $count >= $chart_limit ): break; endif;
|
39 |
-
|
40 |
-
$labels[] = $key;
|
41 |
-
$data[] = $value;
|
42 |
-
$colors[] = $predefined_colors[ $count ];
|
43 |
-
$count++;
|
44 |
-
endforeach;
|
45 |
-
?>
|
46 |
-
var countries = document.getElementById('wpzerospam-pie-countries');
|
47 |
-
var countriesAnalyticsPie = new Chart(countries, {
|
48 |
-
type: 'pie',
|
49 |
-
data: {
|
50 |
-
labels: <?php echo json_encode( $labels ); ?>,
|
51 |
-
datasets: [{
|
52 |
-
data: <?php echo json_encode( $data ); ?>,
|
53 |
-
backgroundColor: <?php echo json_encode( $colors ); ?>,
|
54 |
-
borderWidth: 0,
|
55 |
-
borderColor: '#f1f1f1'
|
56 |
-
}],
|
57 |
-
},
|
58 |
-
options: {
|
59 |
-
legend: {
|
60 |
-
position: 'right',
|
61 |
-
fullWidth: false
|
62 |
-
}
|
63 |
-
}
|
64 |
-
});
|
65 |
-
</script>
|
66 |
-
<?php else: ?>
|
67 |
-
<?php _e( 'No data to report yet.', 'zero-spam' ); ?>
|
68 |
-
<?php endif; ?>
|
69 |
-
</div>
|
70 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
templates/ip-list.php
DELETED
@@ -1,74 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* IP list
|
4 |
-
*
|
5 |
-
* @package ReferrerAnalytics
|
6 |
-
* @since 1.0.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
$chart_limit = 20;
|
10 |
-
?>
|
11 |
-
<div class="wpzerospam-box wpzerospam-box-ip-list">
|
12 |
-
<h3><?php _e( 'Most Spam by IP Address', 'zero-spam' ); ?></h3>
|
13 |
-
<div class="inside">
|
14 |
-
<?php
|
15 |
-
if ( $log ):
|
16 |
-
$ips = [];
|
17 |
-
foreach( $log as $key => $entry ):
|
18 |
-
if ( empty( $ips[ $entry->user_ip ] ) ):
|
19 |
-
$ips[ $entry->user_ip ] = [
|
20 |
-
'count' => 1,
|
21 |
-
'country' => $entry->country
|
22 |
-
];
|
23 |
-
else:
|
24 |
-
$ips[ $entry->user_ip ]['count']++;
|
25 |
-
endif;
|
26 |
-
endforeach;
|
27 |
-
|
28 |
-
if ( $ips ):
|
29 |
-
arsort( $ips );
|
30 |
-
endif;
|
31 |
-
?>
|
32 |
-
<ol class="wpzerospam-list">
|
33 |
-
<?php
|
34 |
-
$cnt = 0;
|
35 |
-
foreach( $ips as $ip => $ary ):
|
36 |
-
$cnt++;
|
37 |
-
if ( $cnt > $chart_limit ) { break; }
|
38 |
-
?>
|
39 |
-
<li class="wpzerospam-list-item">
|
40 |
-
<span class="wpzerospam-list-cell wpzerospam-list-cell-icon">
|
41 |
-
<?php if ( ! empty( $ary['country'] ) ): ?>
|
42 |
-
<img class="wpzerospam-country-flag" width="16" src="https://hatscripts.github.io/circle-flags/flags/<?php echo strtolower( $ary['country'] ); ?>.svg" alt="<?php echo wpzerospam_get_location( $ary['country'] ); ?>" />
|
43 |
-
<?php endif; ?>
|
44 |
-
</span>
|
45 |
-
<span class="wpzerospam-list-cell wpzerospam-list-cell-ip">
|
46 |
-
<a href="https://zerospam.org/ip-lookup/<?php echo urlencode( $ip ); ?>" target="_blank" rel="noopener noreferrer"><strong><?php echo $ip; ?></strong></a>
|
47 |
-
</span>
|
48 |
-
<span class="wpzerospam-list-cell wpzerospam-list-cell-country<?php if ( empty( $ary['country'] ) ): ?> wpzerospam-list-cell-na<?php endif; ?>">
|
49 |
-
<?php if ( ! empty( $ary['country'] ) ): ?>
|
50 |
-
<?php echo wpzerospam_get_location( $ary['country'] ); ?>
|
51 |
-
<?php else: ?>
|
52 |
-
N/A
|
53 |
-
<?php endif; ?>
|
54 |
-
</span>
|
55 |
-
<span class="wpzerospam-list-cell wpzerospam-list-cell-count">
|
56 |
-
<?php echo number_format( $ary['count'], 0 ); ?>
|
57 |
-
</span>
|
58 |
-
<span class="wpzerospam-list-cell wpzerospam-list-cell-action">
|
59 |
-
<?php if ( wpzerospam_is_blocked( $ip ) ): ?>
|
60 |
-
<span class="wpzerospam-blocked"><?php _e( 'Blocked', 'zero-spam' ); ?></span>
|
61 |
-
<?php else: ?>
|
62 |
-
<a href="<?php echo admin_url( 'admin.php?page=wordpress-zero-spam-blocked-ips&ip=' . $ip ); ?>">
|
63 |
-
<?php _e( 'Block IP', 'zero-spam' ); ?>
|
64 |
-
</a>
|
65 |
-
<?php endif; ?>
|
66 |
-
</span>
|
67 |
-
</li>
|
68 |
-
<?php endforeach; ?>
|
69 |
-
</ol>
|
70 |
-
<?php else: ?>
|
71 |
-
<?php _e( 'No data to report yet.', 'zero-spam' ); ?>
|
72 |
-
<?php endif; ?>
|
73 |
-
</div>
|
74 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
templates/map.php
DELETED
@@ -1,114 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* World map
|
4 |
-
*
|
5 |
-
* @package WordPressZeroSpam
|
6 |
-
* @since 1.0.0
|
7 |
-
*/
|
8 |
-
$options = wpzerospam_options();
|
9 |
-
?>
|
10 |
-
<div class="wpzerospam-box wpzerospam-box-map">
|
11 |
-
<h3><?php _e( 'Spam Detections World Map', 'zero-spam' ); ?></h3>
|
12 |
-
<div class="inside">
|
13 |
-
<?php if ( ! empty( $options['ipstack_api'] ) ): ?>
|
14 |
-
<?php
|
15 |
-
$regions_data = [];
|
16 |
-
$coords = [];
|
17 |
-
$names = [];
|
18 |
-
foreach( $log as $key => $entry ):
|
19 |
-
if ( ! empty( $entry->latitude ) && ! empty( $entry->longitude ) ) {
|
20 |
-
$coords[] = [ $entry->latitude, $entry->longitude ];
|
21 |
-
|
22 |
-
$name = '';
|
23 |
-
|
24 |
-
if ( ! empty( $entry->city ) ) {
|
25 |
-
$name .= $entry->city;
|
26 |
-
}
|
27 |
-
|
28 |
-
if ( ! empty( $entry->region ) ) {
|
29 |
-
if ( $name ) { $name .= ', '; }
|
30 |
-
$name .= $entry->region;
|
31 |
-
}
|
32 |
-
|
33 |
-
if ( ! empty( $entry->country ) ) {
|
34 |
-
if ( $name ) { $name .= ', '; }
|
35 |
-
$name .= $entry->country;
|
36 |
-
}
|
37 |
-
|
38 |
-
$names[] = $name;
|
39 |
-
}
|
40 |
-
|
41 |
-
if ( ! empty( $entry->country ) ) {
|
42 |
-
|
43 |
-
if ( array_key_exists( $entry->country, $regions_data ) ) {
|
44 |
-
$regions_data[ $entry->country ]++;
|
45 |
-
} else {
|
46 |
-
$regions_data[ $entry->country ] = 1;
|
47 |
-
}
|
48 |
-
|
49 |
-
}
|
50 |
-
endforeach;
|
51 |
-
|
52 |
-
$regions_data = json_encode( $regions_data );
|
53 |
-
$coords = json_encode( $coords );
|
54 |
-
$names = json_encode( $names );
|
55 |
-
?>
|
56 |
-
<div id="world-map" style="width: 100%; height: 490px"></div>
|
57 |
-
<script>
|
58 |
-
jQuery( function() {
|
59 |
-
var regionsData = <?php echo $regions_data; ?>;
|
60 |
-
var coords = <?php echo $coords; ?>;
|
61 |
-
var names = <?php echo $names; ?>;
|
62 |
-
|
63 |
-
jQuery( '#world-map' ).vectorMap({
|
64 |
-
map: 'world_mill',
|
65 |
-
backgroundColor: 'transparent',
|
66 |
-
markers: coords,
|
67 |
-
markerStyle: {
|
68 |
-
initial: {
|
69 |
-
fill: '#BE0000',
|
70 |
-
stroke: '#000000',
|
71 |
-
"fill-opacity": 1,
|
72 |
-
"stroke-width": 1,
|
73 |
-
"stroke-opacity": 0.5,
|
74 |
-
r: 3
|
75 |
-
},
|
76 |
-
},
|
77 |
-
regionStyle: {
|
78 |
-
initial: {
|
79 |
-
fill: 'transparent',
|
80 |
-
"fill-opacity": 1,
|
81 |
-
stroke: '#63000D',
|
82 |
-
"stroke-width": 1,
|
83 |
-
"stroke-opacity": 0.5
|
84 |
-
},
|
85 |
-
},
|
86 |
-
series: {
|
87 |
-
regions: [{
|
88 |
-
values: regionsData,
|
89 |
-
scale: ['#FFA17C','#63000D'],
|
90 |
-
normalizeFunction: 'polynomial'
|
91 |
-
}]
|
92 |
-
},
|
93 |
-
onMarkerTipShow: function(event, label, index){
|
94 |
-
label.html( names[index] );
|
95 |
-
},
|
96 |
-
onRegionTipShow: function(e, el, code){
|
97 |
-
el.html( el.html() + ' (<?php _e( 'Spam Detections', 'zero-spam' ); ?>: ' + regionsData[code] + ')' );
|
98 |
-
}
|
99 |
-
});
|
100 |
-
});
|
101 |
-
</script>
|
102 |
-
<?php else: ?>
|
103 |
-
<p><?php
|
104 |
-
echo sprintf(
|
105 |
-
wp_kses(
|
106 |
-
__( '<strong>Enter your <a href="%s" target="_blank" rel="noopener noreferrer">ipstack API Key</a></strong> to enable the world mp view of spam detections.', 'zero-spam' ),
|
107 |
-
[ 'strong' => [], 'a' => [ 'target' => [], 'href' => [], 'rel' => [] ] ]
|
108 |
-
),
|
109 |
-
admin_url( 'admin.php?page=wordpress-zero-spam-settings' )
|
110 |
-
);
|
111 |
-
?></p>
|
112 |
-
<?php endif; ?>
|
113 |
-
</div>
|
114 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
templates/regions-pie-chart.php
DELETED
@@ -1,85 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Regions pie chart
|
4 |
-
*
|
5 |
-
* @package ReferrerAnalytics
|
6 |
-
* @since 1.0.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
$chart_limit = 10;
|
10 |
-
?>
|
11 |
-
<div class="wpzerospam-box wpzerospam-box-countries-pie">
|
12 |
-
<h3><?php _e( 'Most Spam by Region', 'zero-spam' ); ?></h3>
|
13 |
-
<div class="inside">
|
14 |
-
<?php
|
15 |
-
if ( $log ):
|
16 |
-
$regions = [];
|
17 |
-
foreach( $log as $key => $entry ):
|
18 |
-
$region = wpzerospam_get_location( $entry->country, $entry->region );
|
19 |
-
if ( $region ) {
|
20 |
-
if ( empty( $regions[ $region ] ) ) {
|
21 |
-
$regions[ $region ] = 1;
|
22 |
-
} else {
|
23 |
-
$regions[ $region ]++;
|
24 |
-
}
|
25 |
-
} else {
|
26 |
-
if ( empty( $entry->region ) ) {
|
27 |
-
if ( empty( $regions['N/A'] ) ) {
|
28 |
-
$regions['N/A'] = 1;
|
29 |
-
} else {
|
30 |
-
$regions['N/A']++;
|
31 |
-
}
|
32 |
-
} else {
|
33 |
-
if ( empty( $regions[ $entry->region ] ) ) {
|
34 |
-
$regions[ $entry->region ] = 1;
|
35 |
-
} else {
|
36 |
-
$regions[ $entry->region ]++;
|
37 |
-
}
|
38 |
-
}
|
39 |
-
}
|
40 |
-
endforeach;
|
41 |
-
|
42 |
-
if ( $regions ):
|
43 |
-
arsort( $regions );
|
44 |
-
endif;
|
45 |
-
?>
|
46 |
-
<canvas id="wpzerospam-pie-regions"></canvas>
|
47 |
-
<script>
|
48 |
-
<?php
|
49 |
-
$labels = [];
|
50 |
-
$data = [];
|
51 |
-
$count = 0;
|
52 |
-
foreach( $regions as $key => $value ):
|
53 |
-
if ( $count >= $chart_limit ): break; endif;
|
54 |
-
|
55 |
-
$labels[] = $key;
|
56 |
-
$data[] = $value;
|
57 |
-
$colors[] = $predefined_colors[ $count ];
|
58 |
-
$count++;
|
59 |
-
endforeach;
|
60 |
-
?>
|
61 |
-
var regions = document.getElementById('wpzerospam-pie-regions');
|
62 |
-
var regionsAnalyticsPie = new Chart(regions, {
|
63 |
-
type: 'pie',
|
64 |
-
data: {
|
65 |
-
labels: <?php echo json_encode( $labels ); ?>,
|
66 |
-
datasets: [{
|
67 |
-
data: <?php echo json_encode( $data ); ?>,
|
68 |
-
backgroundColor: <?php echo json_encode( $colors ); ?>,
|
69 |
-
borderWidth: 0,
|
70 |
-
borderColor: '#f1f1f1'
|
71 |
-
}],
|
72 |
-
},
|
73 |
-
options: {
|
74 |
-
legend: {
|
75 |
-
position: 'right',
|
76 |
-
fullWidth: false
|
77 |
-
}
|
78 |
-
}
|
79 |
-
});
|
80 |
-
</script>
|
81 |
-
<?php else: ?>
|
82 |
-
<?php _e( 'No data to report yet.', 'zero-spam' ); ?>
|
83 |
-
<?php endif; ?>
|
84 |
-
</div>
|
85 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
templates/spam-line-chart.php
DELETED
@@ -1,61 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Spam line chart
|
4 |
-
*
|
5 |
-
* @package ReferrerAnalytics
|
6 |
-
* @since 1.0.0
|
7 |
-
*/
|
8 |
-
?>
|
9 |
-
<div class="wpzerospam-box wpzerospam-box-line-chart">
|
10 |
-
<h3><?php _e( 'Spam by Date', 'zero-spam' ); ?></h3>
|
11 |
-
<div class="inside">
|
12 |
-
<?php
|
13 |
-
if ( $log ):
|
14 |
-
?>
|
15 |
-
<canvas id="wpzerospam-line-chart"></canvas>
|
16 |
-
<script>
|
17 |
-
<?php
|
18 |
-
$parsed = [];
|
19 |
-
foreach( $log as $key => $entry ):
|
20 |
-
$date_key = date( 'Y-m-d', strtotime( $entry->date_recorded ) );
|
21 |
-
if ( empty( $parsed[ $date_key ] ) ) {
|
22 |
-
$parsed[ $date_key ] = 1;
|
23 |
-
} else {
|
24 |
-
$parsed[ $date_key ]++;
|
25 |
-
}
|
26 |
-
endforeach;
|
27 |
-
|
28 |
-
ksort( $parsed );
|
29 |
-
$labels = [];
|
30 |
-
$data = [];
|
31 |
-
foreach( $parsed as $date => $count ) {
|
32 |
-
$labels[] = date( 'M j, Y', strtotime( $date ) );
|
33 |
-
$data[] = $count;
|
34 |
-
}
|
35 |
-
?>
|
36 |
-
var lineChart = document.getElementById('wpzerospam-line-chart');
|
37 |
-
var lineChartAnalytics= new Chart(lineChart, {
|
38 |
-
type: 'line',
|
39 |
-
data: {
|
40 |
-
labels: <?php echo json_encode( $labels ); ?>,
|
41 |
-
datasets: [{
|
42 |
-
data: <?php echo json_encode( $data ); ?>,
|
43 |
-
backgroundColor: 'rgba(88, 0, 15, 0.5)',
|
44 |
-
borderColor: '#63000D',
|
45 |
-
borderWidth: 2,
|
46 |
-
pointBorderWidth: 2,
|
47 |
-
pointBackgroundColor: '#58000f',
|
48 |
-
pointRadius: 2,
|
49 |
-
fill: false,
|
50 |
-
}],
|
51 |
-
},
|
52 |
-
options: {
|
53 |
-
legend: false
|
54 |
-
}
|
55 |
-
});
|
56 |
-
</script>
|
57 |
-
<?php else: ?>
|
58 |
-
<?php _e( 'No data to report yet.', 'zero-spam' ); ?>
|
59 |
-
<?php endif; ?>
|
60 |
-
</div>
|
61 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uninstall.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Handles uninstalling the plugin
|
4 |
+
*
|
5 |
+
* @package WordPressZeroSpam
|
6 |
+
*/
|
7 |
+
|
8 |
+
// Security Note: Blocks direct access to the plugin PHP files.
|
9 |
+
defined( 'ABSPATH' ) || die();
|
10 |
+
|
11 |
+
global $wpdb;
|
12 |
+
|
13 |
+
$tables = array(
|
14 |
+
'log' => 'wpzerospam_log',
|
15 |
+
'blocked' => 'wpzerospam_blocked',
|
16 |
+
'blacklist' => 'wpzerospam_blacklist',
|
17 |
+
);
|
18 |
+
|
19 |
+
if ( is_multisite() ) {
|
20 |
+
$blogs = $wpdb->get_results( "SELECT blog_id FROM {$wpdb->blogs}", ARRAY_A );
|
21 |
+
|
22 |
+
if ( $blogs ) {
|
23 |
+
foreach ( $blogs as $blog ) {
|
24 |
+
switch_to_blog( $blog['blog_id'] );
|
25 |
+
|
26 |
+
delete_option( 'wpzerospam' );
|
27 |
+
delete_option( 'wpzerospam_honeypot' );
|
28 |
+
delete_option( 'zerospam_db_version' );
|
29 |
+
|
30 |
+
foreach ( $tables as $key => $table ) {
|
31 |
+
$wpdb->query( "DROP TABLE IF EXISTS " . $wpdb->prefix . $table );
|
32 |
+
}
|
33 |
+
}
|
34 |
+
restore_current_blog();
|
35 |
+
}
|
36 |
+
} else {
|
37 |
+
delete_option( 'wpzerospam' );
|
38 |
+
delete_option( 'wpzerospam_honeypot' );
|
39 |
+
delete_option( 'zerospam_db_version' );
|
40 |
+
|
41 |
+
foreach ( $tables as $key => $table ) {
|
42 |
+
$wpdb->query( "DROP TABLE IF EXISTS " . $wpdb->prefix . $table );
|
43 |
+
}
|
44 |
+
}
|
wordpress-zero-spam.php
CHANGED
@@ -4,21 +4,21 @@
|
|
4 |
*
|
5 |
* @package WordPressZeroSpam
|
6 |
* @subpackage WordPress
|
7 |
-
* @since
|
8 |
* @author Ben Marshall
|
9 |
-
* @copyright
|
10 |
* @license GPL-2.0-or-later
|
11 |
*
|
12 |
* @wordpress-plugin
|
13 |
* Plugin Name: WordPress Zero Spam
|
14 |
* Plugin URI: https://benmarshall.me/wordpress-zero-spam
|
15 |
* Description: Tired of all the useless and bloated WordPress spam plugins? The WordPress Zero Spam plugin makes blocking spam a cinch. <strong>Just install, activate and say goodbye to spam.</strong> Based on work by <a href="http://davidwalsh.name/wordpress-comment-spam" target="_blank">David Walsh</a>.
|
16 |
-
* Version:
|
17 |
* Requires at least: 5.2
|
18 |
* Requires PHP: 7.2
|
19 |
* Author: Ben Marshall
|
20 |
* Author URI: https://benmarshall.me
|
21 |
-
* Text Domain:
|
22 |
* Domain Path: /languages
|
23 |
* License: GPL v2 or later
|
24 |
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
|
@@ -28,121 +28,62 @@
|
|
28 |
defined( 'ABSPATH' ) || die();
|
29 |
|
30 |
// Define plugin constants.
|
31 |
-
define( '
|
32 |
-
define( '
|
33 |
-
define( '
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
require
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Include the WordPress Zero Spam comments class.
|
47 |
-
*/
|
48 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'classes/class-wpzerospam-comments.php';
|
49 |
-
|
50 |
-
// Initialize the plugin.
|
51 |
-
$wpzerospam = new WPZeroSpam();
|
52 |
-
$wpzerospam_security = new WPZeroSpam_Security();
|
53 |
-
|
54 |
-
// Fires the plugin WordPress hooks.
|
55 |
-
$wpzerospam->initialize();
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Install & upgrade functionality.
|
59 |
-
*/
|
60 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'inc/install.php';
|
61 |
-
|
62 |
-
/**
|
63 |
-
* Uninstall functionality.
|
64 |
-
*/
|
65 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'inc/uninstall.php';
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
/**
|
77 |
-
* Utility helper functions.
|
78 |
-
*/
|
79 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'inc/utilities.php';
|
80 |
-
|
81 |
-
/**
|
82 |
-
* Helpers.
|
83 |
-
*/
|
84 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'inc/helpers.php';
|
85 |
-
|
86 |
-
/**
|
87 |
-
* Plugin updates.
|
88 |
-
*/
|
89 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'inc/updates.php';
|
90 |
|
91 |
/**
|
92 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
*/
|
94 |
-
|
|
|
|
|
95 |
|
96 |
/**
|
97 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
*/
|
99 |
-
|
|
|
|
|
|
|
|
|
|
|
100 |
|
101 |
/**
|
102 |
-
*
|
103 |
*
|
104 |
-
*
|
|
|
|
|
105 |
*
|
106 |
* @return void
|
107 |
*/
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'integrations/comments/comments.php';
|
114 |
-
|
115 |
-
/**
|
116 |
-
* Include the WPZS core registration integration.
|
117 |
-
*/
|
118 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'integrations/registrations/registrations.php';
|
119 |
-
|
120 |
-
/**
|
121 |
-
* Include the WPZS Contact Form 7 integration if it's active.
|
122 |
-
*/
|
123 |
-
if ( class_exists( 'WPCF7' ) ) {
|
124 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'integrations/contact-form-7/contact-form-7.php';
|
125 |
-
}
|
126 |
-
}
|
127 |
-
}
|
128 |
-
add_action( 'plugins_loaded', 'zero_spam_setup' );
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
if ( wpzerospam_plugin_integration_enabled( 'bp_registrations' ) ) {
|
135 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'integrations/buddypress/buddypress.php';
|
136 |
-
}
|
137 |
-
|
138 |
-
if ( wpzerospam_plugin_integration_enabled( 'wpforms' ) ) {
|
139 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'integrations/wpforms/wpforms.php';
|
140 |
-
}
|
141 |
-
|
142 |
-
if ( wpzerospam_plugin_integration_enabled( 'fluentform' ) ) {
|
143 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'integrations/fluentform/fluentform.php';
|
144 |
-
}
|
145 |
-
|
146 |
-
if ( wpzerospam_plugin_integration_enabled( 'formidable' ) ) {
|
147 |
-
require plugin_dir_path( WORDPRESS_ZERO_SPAM ) . 'integrations/formidable/formidable.php';
|
148 |
}
|
4 |
*
|
5 |
* @package WordPressZeroSpam
|
6 |
* @subpackage WordPress
|
7 |
+
* @since 5.0.0
|
8 |
* @author Ben Marshall
|
9 |
+
* @copyright 2021 Ben Marshall
|
10 |
* @license GPL-2.0-or-later
|
11 |
*
|
12 |
* @wordpress-plugin
|
13 |
* Plugin Name: WordPress Zero Spam
|
14 |
* Plugin URI: https://benmarshall.me/wordpress-zero-spam
|
15 |
* Description: Tired of all the useless and bloated WordPress spam plugins? The WordPress Zero Spam plugin makes blocking spam a cinch. <strong>Just install, activate and say goodbye to spam.</strong> Based on work by <a href="http://davidwalsh.name/wordpress-comment-spam" target="_blank">David Walsh</a>.
|
16 |
+
* Version: 5.0.0
|
17 |
* Requires at least: 5.2
|
18 |
* Requires PHP: 7.2
|
19 |
* Author: Ben Marshall
|
20 |
* Author URI: https://benmarshall.me
|
21 |
+
* Text Domain: zerospam
|
22 |
* Domain Path: /languages
|
23 |
* License: GPL v2 or later
|
24 |
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
|
28 |
defined( 'ABSPATH' ) || die();
|
29 |
|
30 |
// Define plugin constants.
|
31 |
+
define( 'ZEROSPAM', __FILE__ );
|
32 |
+
define( 'ZEROSPAM_PATH', plugin_dir_path( ZEROSPAM ) );
|
33 |
+
define( 'ZEROSPAM_PLUGIN_BASE', plugin_basename( ZEROSPAM ) );
|
34 |
+
define( 'ZEROSPAM_VERSION', '5.0.0' );
|
35 |
+
|
36 |
+
add_action( 'plugins_loaded', 'zerospam_load_plugin_textdomain' );
|
37 |
+
|
38 |
+
if ( ! version_compare( PHP_VERSION, '7.2', '>=' ) ) {
|
39 |
+
add_action( 'admin_notices', 'zerospam_fail_php_version' );
|
40 |
+
} elseif ( ! version_compare( get_bloginfo( 'version' ), '5.2', '>=' ) ) {
|
41 |
+
add_action( 'admin_notices', 'zerospam_fail_wp_version' );
|
42 |
+
} else {
|
43 |
+
require ZEROSPAM_PATH . 'includes/class-plugin.php';
|
44 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
|
46 |
/**
|
47 |
+
* Load Elementor textdomain.
|
48 |
+
*
|
49 |
+
* Load gettext translate for Elementor text domain.
|
50 |
+
*
|
51 |
+
* @since 1.0.0
|
52 |
+
*
|
53 |
+
* @return void
|
54 |
*/
|
55 |
+
function zerospam_load_plugin_textdomain() {
|
56 |
+
load_plugin_textdomain( 'zerospam' );
|
57 |
+
}
|
58 |
|
59 |
/**
|
60 |
+
* WordPress Zero Spam admin notice for minimum PHP version.
|
61 |
+
*
|
62 |
+
* Warning when the site doesn't have the minimum required PHP version.
|
63 |
+
*
|
64 |
+
* @since 5.0.0
|
65 |
+
*
|
66 |
+
* @return void
|
67 |
*/
|
68 |
+
function zerospam_fail_php_version() {
|
69 |
+
/* translators: %s: PHP version */
|
70 |
+
$message = sprintf( esc_html__( 'WordPress Zero Spam requires PHP version %s+, plugin is currently NOT RUNNING.', 'zerospam' ), '7.2' );
|
71 |
+
$html_message = sprintf( '<div class="error">%s</div>', wpautop( $message ) );
|
72 |
+
echo wp_kses_post( $html_message );
|
73 |
+
}
|
74 |
|
75 |
/**
|
76 |
+
* WordPress Zero Spam admin notice for minimum WordPress version.
|
77 |
*
|
78 |
+
* Warning when the site doesn't have the minimum required WordPress version.
|
79 |
+
*
|
80 |
+
* @since 5.0.0
|
81 |
*
|
82 |
* @return void
|
83 |
*/
|
84 |
+
function zerospam_fail_wp_version() {
|
85 |
+
/* translators: %s: WordPress version */
|
86 |
+
$message = sprintf( esc_html__( 'WordPress Zero Spam requires WordPress version %s+. Because you are using an earlier version, the plugin is currently NOT RUNNING.', 'zerospam' ), '5.2' );
|
87 |
+
$html_message = sprintf( '<div class="error">%s</div>', wpautop( $message ) );
|
88 |
+
echo wp_kses_post( $html_message );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
}
|