Cerber Security & Antispam - Version 7.2

Version Description

  • New: Monitoring new and changed files.
  • New: Detecting malicious redirections and directives in .htaccess files.
  • New: Automated hourly and daily scheduled scans with flexible email reports.
  • Update: Added a protection from logging wrong time stamps on some not correctly configured servers.
  • Bug fixed: Unexpected warning messages in the WordPress dashboard.
  • Bug fixed: Some file status links on the scanner results page may not work.
Download this release

Release Info

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

Code changes from version 7.0 to 7.2

assets/admin.css CHANGED
@@ -680,8 +680,9 @@ body.wp-cerber_page_cerber-integrity {
680
  /*width: 97%;*/
681
  overflow: auto;
682
  padding: 20px 10px 10px 10px;
683
- background-color: #f9f9f9;
684
- border: solid #E5E5E5 2px;
 
685
  border-bottom: none;
686
  /*margin-bottom: 10px;*/
687
  }
@@ -715,7 +716,6 @@ div.scan-tile div {
715
  width: 23%;
716
  text-align: left !important;
717
  }
718
-
719
  #crb-scan-info table {
720
  width: 100%;
721
  }
@@ -738,12 +738,30 @@ div.scan-tile div {
738
  border: 1px solid #E5E5E5;
739
  }
740
 
 
 
 
 
741
  #crb-browse-files td {
742
  color: #333;
743
  text-align: left;
744
  padding: 10px;
745
  }
746
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
747
  #crb-browse-files .crb-scan-container {
748
  display: none;
749
  }
@@ -764,6 +782,7 @@ div.scan-tile div {
764
 
765
  #crb-browse-files tr.crb-item-file td:nth-child(2) {
766
  font-family: Menlo, Consolas, Monaco, monospace;
 
767
  /*cursor: pointer;*/
768
  }
769
 
@@ -825,6 +844,7 @@ div.scan-tile div {
825
  width: 100%;
826
  margin-top: 10px;
827
  background-color: #f1f1f1;
 
828
  }
829
  #crb-scan-controls td{
830
  text-align: center;
@@ -917,7 +937,7 @@ div.scan-tile div {
917
  border-bottom-style: solid;
918
  border-bottom-color: #eeeeee;
919
  padding: 4px 12px 12px;
920
-
921
  }
922
 
923
  .cerber-widget .bigdig {
@@ -926,7 +946,7 @@ div.scan-tile div {
926
 
927
  #quick-info td {
928
  padding: 0 8px 6px 0;
929
- font-size: 110%;
930
  }
931
 
932
  .cerber-widget td.per {
@@ -1336,7 +1356,8 @@ table.vtable td:nth-child(2) {
1336
  position: relative;
1337
  display: inline-block;
1338
  width: 50px;
1339
- height: 22px;
 
1340
  margin-right: 0.8em;
1341
  }
1342
 
@@ -1361,9 +1382,13 @@ table.vtable td:nth-child(2) {
1361
  .crb-slider:before {
1362
  position: absolute;
1363
  content: "";
1364
- height: 16px;
1365
  width: 16px;
1366
  left: 4px;
 
 
 
 
1367
  bottom: 3px;
1368
  background-color: white;
1369
  -webkit-transition: .2s;
@@ -1392,6 +1417,12 @@ input:checked + .crb-slider:before {
1392
  border-radius: 50%;
1393
  }
1394
 
 
 
 
 
 
 
1395
 
1396
  /* Flags */
1397
 
680
  /*width: 97%;*/
681
  overflow: auto;
682
  padding: 20px 10px 10px 10px;
683
+ /*background-color: #f9f9f9;*/
684
+ background-color: #fff;
685
+ border: solid #E5E5E5 1px;
686
  border-bottom: none;
687
  /*margin-bottom: 10px;*/
688
  }
716
  width: 23%;
717
  text-align: left !important;
718
  }
 
719
  #crb-scan-info table {
720
  width: 100%;
721
  }
738
  border: 1px solid #E5E5E5;
739
  }
740
 
741
+ #crb-browse-files td p {
742
+ margin-bottom: 0;
743
+ }
744
+
745
  #crb-browse-files td {
746
  color: #333;
747
  text-align: left;
748
  padding: 10px;
749
  }
750
 
751
+ #crb-browse-files tr td:nth-child(3) {
752
+ color: #000;
753
+ }
754
+
755
+ #crb-browse-files tr td:nth-child(n+5) {
756
+ color: #444;
757
+ }
758
+
759
+ #crb-browse-files tr:hover td {
760
+ /*background-color: #fff;*/
761
+ color: #000;
762
+ /*font-weight: bold;*/
763
+ }
764
+
765
  #crb-browse-files .crb-scan-container {
766
  display: none;
767
  }
782
 
783
  #crb-browse-files tr.crb-item-file td:nth-child(2) {
784
  font-family: Menlo, Consolas, Monaco, monospace;
785
+ color: #000;
786
  /*cursor: pointer;*/
787
  }
788
 
844
  width: 100%;
845
  margin-top: 10px;
846
  background-color: #f1f1f1;
847
+ border-collapse: collapse;
848
  }
849
  #crb-scan-controls td{
850
  text-align: center;
937
  border-bottom-style: solid;
938
  border-bottom-color: #eeeeee;
939
  padding: 4px 12px 12px;
940
+ font-family: 'Roboto', sans-serif;
941
  }
942
 
943
  .cerber-widget .bigdig {
946
 
947
  #quick-info td {
948
  padding: 0 8px 6px 0;
949
+ font-size: 105%;
950
  }
951
 
952
  .cerber-widget td.per {
1356
  position: relative;
1357
  display: inline-block;
1358
  width: 50px;
1359
+ /*height: 22px;*/
1360
+ height: 20px;
1361
  margin-right: 0.8em;
1362
  }
1363
 
1382
  .crb-slider:before {
1383
  position: absolute;
1384
  content: "";
1385
+ /*height: 16px;
1386
  width: 16px;
1387
  left: 4px;
1388
+ bottom: 3px;*/
1389
+ height: 14px;
1390
+ width: 14px;
1391
+ left: 5px;
1392
  bottom: 3px;
1393
  background-color: white;
1394
  -webkit-transition: .2s;
1417
  border-radius: 50%;
1418
  }
1419
 
1420
+ .crb-pro-req {
1421
+ padding: 2em;
1422
+ background-color: #fff;
1423
+ color: #dc2f34;
1424
+ border-left: solid 2px #dc2f34;
1425
+ }
1426
 
1427
  /* Flags */
1428
 
assets/scanner.js CHANGED
@@ -15,6 +15,7 @@ jQuery(document).ready(function ($) {
15
 
16
  var crb_response;
17
  var scanner_data;
 
18
 
19
  var crb_scan_requests = 0;
20
  var crb_server_errors = 0;
@@ -30,11 +31,9 @@ jQuery(document).ready(function ($) {
30
  var crb_scan_message = $("#crb-scan-message");
31
  var crb_scan_browser = $("#crb-browse-files");
32
 
33
- var crb_scan_strings = null;
34
 
35
- cerber_scan_load_last();
36
-
37
- cerber_load_strings();
38
 
39
  crb_scan_controls.find(':button,a').click(function (event) {
40
  var operation = $(event.target).data('control');
@@ -73,6 +72,8 @@ jQuery(document).ready(function ($) {
73
 
74
  function cerber_scan_start(object) {
75
 
 
 
76
  crb_scan_mode = object.data('mode');
77
  crb_scan_requests = 0;
78
  crb_user_stop = false;
@@ -99,6 +100,8 @@ jQuery(document).ready(function ($) {
99
  }
100
 
101
  function cerber_scan_step(operation) {
 
 
102
  if (!operation) {
103
  operation = 'continue_scan';
104
  }
@@ -176,10 +179,20 @@ jQuery(document).ready(function ($) {
176
  return;
177
  }
178
 
 
 
 
 
 
 
 
 
 
179
  $("#crb-started").html(scanner_data.started);
180
  $("#crb-finished").html(scanner_data.finished);
181
  $("#crb-duration").html(scanner_data.duration);
182
  $("#crb-performance").html(scanner_data.performance);
 
183
 
184
  $("#crb-total-files").html(scanner_data.total.files);
185
  $("#crb-scanned-files").html(scanner_data.scanned.files);
@@ -192,16 +205,15 @@ jQuery(document).ready(function ($) {
192
 
193
  // Displaying issues
194
 
195
- var issues = [];
196
  if (!scanner_data.issues && scanner_data.step_issues) {
197
- scanner_data.issues = scanner_data.step_issues;
 
 
 
198
  }
199
- /*else if (scanner_data.issues) {
200
- issues = scanner_data.issues;
201
- }*/
202
-
203
- $.each(scanner_data.issues, function (section_id) {
204
 
 
205
  var the_items = [];
206
 
207
  if (!this.issues.length) {
@@ -258,7 +270,7 @@ jQuery(document).ready(function ($) {
258
  }
259
  extra += '<span class="crb-it-' + issue_type_id + ' scan-ilabel">' + crb_scan_msg_issues[issue_type_id] + '</span>';
260
  if (issue_type_id === 5) {
261
- extra += ' &mdash; <a href="#" class="crb-issue-link" data-itype="' + issue_type_id + '" data-section-name="' + section_name + ' v. ' + version + '">Resolve issue</a>';
262
  }
263
 
264
  section_header = '<tr id="' + section_id + '" class="' + section_header_class + '" data-section-name="' + section_name + '" data-setype="' + setype + '"><td></td><td colspan = 5><span>' + section_name + '</span>' + extra + '</td></tr>';
@@ -304,20 +316,6 @@ jQuery(document).ready(function ($) {
304
 
305
  });
306
 
307
- /*if (the_items) {
308
- var container = null; alert(this.container);
309
- if (this.container) {
310
- container = crb_scan_browser.find('#' + this.container);
311
- }
312
-
313
- if (container.length) {
314
- container.after(the_items);
315
- }
316
- else {
317
- crb_scan_browser.append(the_items);
318
- }
319
- }*/
320
-
321
  $("#crb-critical").html(crb_issues_counter[3]);
322
  $("#crb-warning").html(crb_issues_total);
323
 
@@ -333,7 +331,20 @@ jQuery(document).ready(function ($) {
333
  function cerber_scan_parse(server_response) {
334
  crb_response = $.parseJSON(server_response);
335
  scanner_data = crb_response.cerber_scanner;
 
 
 
 
 
 
 
 
 
 
336
  window.crb_scan_id = scanner_data.scan_id;
 
 
 
337
 
338
  if (scanner_data.errors && scanner_data.errors.length) {
339
  scanner_data.errors.forEach(function (item, index) {
@@ -347,17 +358,20 @@ jQuery(document).ready(function ($) {
347
  }
348
  }
349
 
350
- function cerber_scan_load_last() {
351
  $.post(ajaxurl, {
352
  action: 'cerber_scan_control',
353
- cerber_scan_do: 'get-last-scan',
354
  ajax_nonce: crb_ajax_nonce
355
  },
356
  function (server_response) {
357
  cerber_scan_parse(server_response);
358
- scanner_data.step_issues = '';
359
  cerber_scan_display(true);
360
- });
 
 
 
361
  }
362
 
363
  function cerber_get_issue_txt(index, issue) {
@@ -367,10 +381,14 @@ jQuery(document).ready(function ($) {
367
  if (issue.details.xdata && issue.details.xdata.length) {
368
  attr += ' data-idx="' + index + '" ';
369
  }
370
- if (attr || (issue[0] > 15 && issue[0] < 30)) {
371
  ret = '<a href="#" ' + attr + '>' + ret + '</a>';
372
  }
373
 
 
 
 
 
374
  return ret;
375
  }
376
 
@@ -469,55 +487,51 @@ jQuery(document).ready(function ($) {
469
 
470
  function cerber_delete_files() {
471
  var files_to_delete = crb_scan_browser.find('input[type=checkbox]:checked');
472
- if (files_to_delete.length) {
473
- if (!confirm('Are you sure you want to delete selected files?')){
474
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
  }
476
- var formData = new FormData();
477
- formData.append('action', 'cerber_scan_delete_files');
478
- formData.append('ajax_nonce', crb_ajax_nonce);
479
- formData.append('scan_id', window.crb_scan_id);
480
- $.each(files_to_delete, function () {
481
- formData.append('files[]', $(this).data('file_name'));
482
- });
483
- $.ajax({
484
- url: ajaxurl,
485
- type: 'POST',
486
- data: formData,
487
- contentType: false,
488
- processData: false,
489
- dataType: 'json'
490
- }).done(function (server_response) {
491
- var e = '', title = '';
492
- if (server_response.errors && server_response.errors.length) {
493
- e = '<div style="color: #c91619;"><b>Errors occurred during deletion</b><p>'+server_response.errors.join('</p><p>')+'</p></div>';
494
- }
495
- if (server_response.deleted && server_response.deleted.length) {
496
- e = e + '<div><b>These files has been deleted</b><p>'+server_response.deleted.join('</p><p>')+'</p></div>';
497
- }
498
- if (files_to_delete.length === server_response.number) {
499
- title = 'All files are moved to the quarantine and isolated';
500
- }
501
- else {
502
- title = 'Deleting files';
503
- }
504
- cerber_popup_show(title, e);
505
-
506
- if (server_response.deleted && server_response.deleted.length) {
507
- $.each(server_response.deleted, function (index, file_name) {
508
- crb_scan_browser.find('td[data-file-name="' + file_name + '"]').parent().remove();
509
- });
510
- }
511
 
512
- }).fail(function (jqXHR, textStatus, errorThrown) {
513
- cerber_popup_show('Something went wrong on the server', jqXHR.responseText);
514
- });
 
 
515
 
516
- /*to_delete.map(function () {
517
- return 'files[]=' + $(this).data('file_name');
518
- }).get().join('&');
519
- */
520
- }
521
  }
522
 
523
  function cerber_toggle_file_name(control) {
@@ -535,11 +549,11 @@ jQuery(document).ready(function ($) {
535
  }
536
  if (window.cerber_full_toggler) {
537
  $(this).html($(this).data('file-name'));
538
- $(control).text('Hide full paths');
539
  }
540
  else {
541
  $(this).html($(this).data('short'));
542
- $(control).text('Show full paths');
543
  }
544
  });
545
  }
@@ -551,7 +565,7 @@ jQuery(document).ready(function ($) {
551
  $('#ref-section-name').text($(this).data('section-name'));
552
  crb_enable_ref_form();
553
  crb_upload_form_ul.children().hide();
554
- tb_show("Please upload a reference ZIP archive", '#TB_inline?width=420&height=400&inlineId=crb-ref-upload-dialog');
555
  $('#TB_closeWindowButton').blur();
556
  }
557
  else {
@@ -568,14 +582,14 @@ jQuery(document).ready(function ($) {
568
  var section_type = section.data('setype');
569
  var itype = cerber_get_itype(element);
570
 
571
- if (itype === 18) {
572
  var section_name = section.data('section-name');
573
- cerber_popup_show($(element).text(), cerber_get_issue_explain(section_name));
574
  return;
575
  }
576
 
577
- if (section_type === 20 && itype < 30) {
578
- info.push('<p>' + 'This file contains executable code and may contain obfuscated malware.' + '</p><p>' + 'If this file is a part of a theme or a plugin, it must be located in the theme or the plugin folder. No exception, no excuses.' + '</p>');
579
  }
580
 
581
  // Some data after file inspection?
@@ -588,7 +602,7 @@ jQuery(document).ready(function ($) {
588
  }
589
 
590
  if (section_type > 20) {
591
- info.push(cerber_get_issue_explain());
592
  }
593
 
594
  cerber_popup_show($(element).text(), info, w, h);
@@ -601,55 +615,63 @@ jQuery(document).ready(function ($) {
601
  return '';
602
  }
603
 
604
- if (typeof scanner_data.issues[section_id].issues[idx].details === 'undefined') {
605
  return '';
606
  }
607
 
608
- var xdata = scanner_data.issues[section_id].issues[idx].details.xdata;
609
  if (!xdata.length) {
610
  return '';
611
  }
612
 
613
- if (!crb_scan_strings) {
614
- cerber_load_strings();
615
- return '';
616
- }
617
 
618
  var tokens = [], regs = [], info = '', ls = [];
619
 
620
  $.each(xdata, function (index, e) {
621
  if (e[0] === 1) {
622
- tokens.push('<code>Line ' + e[2] + ': <b>' + e[1] + '</b></code><p>' + crb_scan_strings[e[0]][e[1]][1] + '</p>');
623
  }
624
  else {
625
  ls = [];
626
  $.each(e[2], function (index, s) {
627
  ls.push('<code>Line ' + s[2] + ': <b>' + s[0] + '</b></code>');
628
  });
629
- regs.push(ls.join('</br>') + '<p>' + crb_scan_strings[e[0]][e[1]] + ' (' + e[1] + ')' + '</p>');
630
  }
631
  });
632
 
633
  if (tokens.length) {
634
- info += '<p><b>Suspicious code instruction detected</b></p><div>' + tokens.join('</div><div>') + '</div>';
635
  }
636
  if (regs.length) {
637
- info += '<p><b>Suspicious code signatures detected</b></p><div>' + regs.join('</div><div>') + '</div>';
 
 
638
  }
639
 
640
  return info;
641
  }
642
 
643
  // Explainer for end-user
644
- function cerber_get_issue_explain(subject) {
645
  if (typeof subject === 'undefined' || !subject) {
646
  subject = 'WordPress';
647
  }
648
- var a = 'The scanner recognizes this file as "ownerless" or "not bundled" because it does not belong to any known part of the website and should not be there.';
649
- var text = 'It may remain after upgrading to a newer version of <b>%s</b>.';
650
- var b = 'It also may be a piece of unknown obfuscated malware.';
651
- var d = 'In some rare case it might be a part of a custom-made (bespoke) software.';
652
- return '<p>' + a + '</p><p>' + text.replace('%s', subject) + ' ' + b + ' ' + d + '</p>';
 
 
 
 
 
 
 
 
 
653
  }
654
 
655
  function cerber_get_itype(e) {
@@ -661,6 +683,7 @@ jQuery(document).ready(function ($) {
661
  }
662
 
663
 
 
664
  function cerber_load_strings() {
665
  $.get(ajaxurl, {
666
  action: 'cerber_get_strings',
@@ -674,7 +697,7 @@ jQuery(document).ready(function ($) {
674
  }).fail(function () {
675
  alert('Unable to load strings due to a server error.');
676
  });
677
- }
678
 
679
  // Uploader
680
 
15
 
16
  var crb_response;
17
  var scanner_data;
18
+ var all_issues = {};
19
 
20
  var crb_scan_requests = 0;
21
  var crb_server_errors = 0;
31
  var crb_scan_message = $("#crb-scan-message");
32
  var crb_scan_browser = $("#crb-browse-files");
33
 
34
+ var crb_txt_strings = [];
35
 
36
+ cerber_scan_load_data();
 
 
37
 
38
  crb_scan_controls.find(':button,a').click(function (event) {
39
  var operation = $(event.target).data('control');
72
 
73
  function cerber_scan_start(object) {
74
 
75
+ console.log('Start Scan');
76
+ all_issues = {};
77
  crb_scan_mode = object.data('mode');
78
  crb_scan_requests = 0;
79
  crb_user_stop = false;
100
  }
101
 
102
  function cerber_scan_step(operation) {
103
+ console.log('Request ' + crb_scan_requests);
104
+
105
  if (!operation) {
106
  operation = 'continue_scan';
107
  }
179
  return;
180
  }
181
 
182
+ var smode = scanner_data.mode;
183
+ if (scanner_data.cloud) {
184
+ smode += ', Scheduled';
185
+ }
186
+ else {
187
+ smode += ', Manual';
188
+ }
189
+ smode = '<span style="text-transform: capitalize;">' + smode + '</span>';
190
+
191
  $("#crb-started").html(scanner_data.started);
192
  $("#crb-finished").html(scanner_data.finished);
193
  $("#crb-duration").html(scanner_data.duration);
194
  $("#crb-performance").html(scanner_data.performance);
195
+ $("#crb-smode").html(smode);
196
 
197
  $("#crb-total-files").html(scanner_data.total.files);
198
  $("#crb-scanned-files").html(scanner_data.scanned.files);
205
 
206
  // Displaying issues
207
 
208
+ var issues;
209
  if (!scanner_data.issues && scanner_data.step_issues) {
210
+ issues = scanner_data.step_issues;
211
+ }
212
+ else {
213
+ issues = scanner_data.issues;
214
  }
 
 
 
 
 
215
 
216
+ $.each(issues, function (section_id) {
217
  var the_items = [];
218
 
219
  if (!this.issues.length) {
270
  }
271
  extra += '<span class="crb-it-' + issue_type_id + ' scan-ilabel">' + crb_scan_msg_issues[issue_type_id] + '</span>';
272
  if (issue_type_id === 5) {
273
+ extra += ' &mdash; <a href="#" class="crb-issue-link" data-itype="' + issue_type_id + '" data-section-name="' + section_name + ' v. ' + version + '">' + crb_txt_strings['explain'][9] + '</a>';
274
  }
275
 
276
  section_header = '<tr id="' + section_id + '" class="' + section_header_class + '" data-section-name="' + section_name + '" data-setype="' + setype + '"><td></td><td colspan = 5><span>' + section_name + '</span>' + extra + '</td></tr>';
316
 
317
  });
318
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
  $("#crb-critical").html(crb_issues_counter[3]);
320
  $("#crb-warning").html(crb_issues_total);
321
 
331
  function cerber_scan_parse(server_response) {
332
  crb_response = $.parseJSON(server_response);
333
  scanner_data = crb_response.cerber_scanner;
334
+
335
+ if (scanner_data.issues) {
336
+ all_issues = scanner_data.issues;
337
+ }
338
+ else if (scanner_data.step_issues) {
339
+ $.each(scanner_data.step_issues, function (section_id, value) {
340
+ all_issues[section_id] = value;
341
+ });
342
+ }
343
+
344
  window.crb_scan_id = scanner_data.scan_id;
345
+ if (crb_response.strings) {
346
+ crb_txt_strings = crb_response.strings;
347
+ }
348
 
349
  if (scanner_data.errors && scanner_data.errors.length) {
350
  scanner_data.errors.forEach(function (item, index) {
358
  }
359
  }
360
 
361
+ function cerber_scan_load_data() {
362
  $.post(ajaxurl, {
363
  action: 'cerber_scan_control',
364
+ cerber_scan_do: 'get_last_scan',
365
  ajax_nonce: crb_ajax_nonce
366
  },
367
  function (server_response) {
368
  cerber_scan_parse(server_response);
369
+ //scanner_data.step_issues = [];
370
  cerber_scan_display(true);
371
+ }
372
+ ).fail(function (jqXHR, textStatus, errorThrown) {
373
+ console.error('WP CERBER SCANNER ERROR: Unable to get scanner data from server. Server error code: ' + jqXHR.status);
374
+ });
375
  }
376
 
377
  function cerber_get_issue_txt(index, issue) {
381
  if (issue.details.xdata && issue.details.xdata.length) {
382
  attr += ' data-idx="' + index + '" ';
383
  }
384
+ if (attr || (issue[0] > 14 && issue[0] < 55)) {
385
  ret = '<a href="#" ' + attr + '>' + ret + '</a>';
386
  }
387
 
388
+ if (issue[3]) {
389
+ ret += '<p>' + crb_scan_msg_issues[issue[3]] + '</p>';
390
+ }
391
+
392
  return ret;
393
  }
394
 
487
 
488
  function cerber_delete_files() {
489
  var files_to_delete = crb_scan_browser.find('input[type=checkbox]:checked');
490
+ if (!files_to_delete.length) {
491
+ return;
492
+ }
493
+ if (!confirm('Are you sure you want to delete selected files?')) {
494
+ return;
495
+ }
496
+ var formData = new FormData();
497
+ formData.append('action', 'cerber_scan_delete_files');
498
+ formData.append('ajax_nonce', crb_ajax_nonce);
499
+ formData.append('scan_id', window.crb_scan_id);
500
+ $.each(files_to_delete, function () {
501
+ formData.append('files[]', $(this).data('file_name'));
502
+ });
503
+ $.ajax({
504
+ url: ajaxurl,
505
+ type: 'POST',
506
+ data: formData,
507
+ contentType: false,
508
+ processData: false,
509
+ dataType: 'json'
510
+ }).done(function (server_response) {
511
+ var e = '', title = '';
512
+ if (server_response.errors && server_response.errors.length) {
513
+ e = '<div style="color: #c91619;"><b>Errors occurred during deletion</b><p>' + server_response.errors.join('</p><p>') + '</p></div>';
514
  }
515
+ if (server_response.deleted && server_response.deleted.length) {
516
+ e = e + '<div><b>These files has been deleted</b><p>' + server_response.deleted.join('</p><p>') + '</p></div>';
517
+ }
518
+ if (files_to_delete.length === server_response.number) {
519
+ title = 'All files are moved to the quarantine and isolated';
520
+ }
521
+ else {
522
+ title = 'Deleting files';
523
+ }
524
+ cerber_popup_show(title, e);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
525
 
526
+ if (server_response.deleted && server_response.deleted.length) {
527
+ $.each(server_response.deleted, function (index, file_name) {
528
+ crb_scan_browser.find('td[data-file-name="' + file_name + '"]').parent().remove();
529
+ });
530
+ }
531
 
532
+ }).fail(function (jqXHR, textStatus, errorThrown) {
533
+ cerber_popup_show('Something went wrong on the server', jqXHR.responseText);
534
+ });
 
 
535
  }
536
 
537
  function cerber_toggle_file_name(control) {
549
  }
550
  if (window.cerber_full_toggler) {
551
  $(this).html($(this).data('file-name'));
552
+ //$(control).text('Hide full paths');
553
  }
554
  else {
555
  $(this).html($(this).data('short'));
556
+ //$(control).text('Show full paths');
557
  }
558
  });
559
  }
565
  $('#ref-section-name').text($(this).data('section-name'));
566
  crb_enable_ref_form();
567
  crb_upload_form_ul.children().hide();
568
+ tb_show(crb_txt_strings['explain'][8], '#TB_inline?width=420&height=400&inlineId=crb-ref-upload-dialog');
569
  $('#TB_closeWindowButton').blur();
570
  }
571
  else {
582
  var section_type = section.data('setype');
583
  var itype = cerber_get_itype(element);
584
 
585
+ if (itype === 15 || itype === 18) {
586
  var section_name = section.data('section-name');
587
+ cerber_popup_show($(element).text(), cerber_get_issue_explain(itype, section_name));
588
  return;
589
  }
590
 
591
+ if (section_type === 20 && itype <= 25) {
592
+ info.push('<p>' + crb_txt_strings['explain'][0] + '</p>');
593
  }
594
 
595
  // Some data after file inspection?
602
  }
603
 
604
  if (section_type > 20) {
605
+ info.push(cerber_get_issue_explain(itype));
606
  }
607
 
608
  cerber_popup_show($(element).text(), info, w, h);
615
  return '';
616
  }
617
 
618
+ if (typeof all_issues[section_id].issues[idx].details === 'undefined') {
619
  return '';
620
  }
621
 
622
+ var xdata = all_issues[section_id].issues[idx].details.xdata;
623
  if (!xdata.length) {
624
  return '';
625
  }
626
 
627
+ var itype = all_issues[section_id].issues[idx][0];
 
 
 
628
 
629
  var tokens = [], regs = [], info = '', ls = [];
630
 
631
  $.each(xdata, function (index, e) {
632
  if (e[0] === 1) {
633
+ tokens.push('<code>Line ' + e[2] + ': <b>' + e[1] + '</b></code><p>' + crb_txt_strings[e[0]][e[1]][1] + '</p>');
634
  }
635
  else {
636
  ls = [];
637
  $.each(e[2], function (index, s) {
638
  ls.push('<code>Line ' + s[2] + ': <b>' + s[0] + '</b></code>');
639
  });
640
+ regs.push(ls.join('</br>') + '<p>' + crb_txt_strings[e[0]][e[1]] + ' (' + e[1] + ')' + '</p>');
641
  }
642
  });
643
 
644
  if (tokens.length) {
645
+ info += '<p><b> ' + crb_txt_strings['explain'][3] + '</b></p><div>' + tokens.join('</div><div>') + '</div>';
646
  }
647
  if (regs.length) {
648
+ var title = (itype === 26) ? crb_txt_strings['explain'][5] : crb_txt_strings['explain'][4];
649
+
650
+ info += '<p><b>' + title + '</b></p><div>' + regs.join('</div><div>') + '</div>';
651
  }
652
 
653
  return info;
654
  }
655
 
656
  // Explainer for end-user
657
+ function cerber_get_issue_explain(itype, subject) {
658
  if (typeof subject === 'undefined' || !subject) {
659
  subject = 'WordPress';
660
  }
661
+ subject = '<b>' + subject + '</b>';
662
+ var ret = [];
663
+ switch (itype) {
664
+ case 15:
665
+ ret.push(crb_txt_strings['explain'][6]);
666
+ ret.push(crb_txt_strings['explain'][7].replace('%s', subject));
667
+ break;
668
+ default:
669
+ ret.push(crb_txt_strings['explain'][1]);
670
+ ret.push(crb_txt_strings['explain'][2].replace('%s', subject));
671
+ break;
672
+ }
673
+
674
+ return '<p>'+ ret.join('</p><p>') + '</p>'
675
  }
676
 
677
  function cerber_get_itype(e) {
683
  }
684
 
685
 
686
+ /*
687
  function cerber_load_strings() {
688
  $.get(ajaxurl, {
689
  action: 'cerber_get_strings',
697
  }).fail(function () {
698
  alert('Unable to load strings due to a server error.');
699
  });
700
+ }*/
701
 
702
  // Uploader
703
 
assets/tpicker/jquery.timepicker.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .ui-timepicker-wrapper{overflow-y:auto;max-height:150px;width:6.5em;background:#fff;border:1px solid #ddd;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);outline:0;z-index:10052;margin:0}.ui-timepicker-wrapper.ui-timepicker-with-duration{width:13em}.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-30,.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-60{width:11em}.ui-timepicker-list{margin:0;padding:0;list-style:none}.ui-timepicker-duration{margin-left:5px;color:#888}.ui-timepicker-list:hover .ui-timepicker-duration{color:#888}.ui-timepicker-list li{padding:3px 0 3px 5px;cursor:pointer;white-space:nowrap;color:#000;list-style:none;margin:0}.ui-timepicker-list:hover .ui-timepicker-selected{background:#fff;color:#000}li.ui-timepicker-selected,.ui-timepicker-list li:hover,.ui-timepicker-list .ui-timepicker-selected:hover{background:#1980EC;color:#fff}li.ui-timepicker-selected .ui-timepicker-duration,.ui-timepicker-list li:hover .ui-timepicker-duration{color:#ccc}.ui-timepicker-list li.ui-timepicker-disabled,.ui-timepicker-list li.ui-timepicker-disabled:hover,.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled{color:#888;cursor:default}.ui-timepicker-list li.ui-timepicker-disabled:hover,.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled{background:#f2f2f2}
assets/tpicker/jquery.timepicker.min.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ /*!
2
+ * jquery-timepicker v1.11.14 - A jQuery timepicker plugin inspired by Google Calendar. It supports both mouse and keyboard navigation.
3
+ * Copyright (c) 2018 Jon Thornton - http://jonthornton.github.com/jquery-timepicker/
4
+ * License: MIT
5
+ */
6
+
7
+ !function(a){"object"==typeof exports&&exports&&"object"==typeof module&&module&&module.exports===exports?a(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){function b(a){var b=a[0];return b.offsetWidth>0&&b.offsetHeight>0}function c(b){if(b.minTime&&(b.minTime=t(b.minTime)),b.maxTime&&(b.maxTime=t(b.maxTime)),b.durationTime&&"function"!=typeof b.durationTime&&(b.durationTime=t(b.durationTime)),"now"==b.scrollDefault)b.scrollDefault=function(){return b.roundingFunction(t(new Date),b)};else if(b.scrollDefault&&"function"!=typeof b.scrollDefault){var c=b.scrollDefault;b.scrollDefault=function(){return b.roundingFunction(t(c),b)}}else b.minTime&&(b.scrollDefault=function(){return b.roundingFunction(b.minTime,b)});if("string"===a.type(b.timeFormat)&&b.timeFormat.match(/[gh]/)&&(b._twelveHourTime=!0),b.showOnFocus===!1&&b.showOn.indexOf("focus")!=-1&&b.showOn.splice(b.showOn.indexOf("focus"),1),b.disableTimeRanges.length>0){for(var d in b.disableTimeRanges)b.disableTimeRanges[d]=[t(b.disableTimeRanges[d][0]),t(b.disableTimeRanges[d][1])];b.disableTimeRanges=b.disableTimeRanges.sort(function(a,b){return a[0]-b[0]});for(var d=b.disableTimeRanges.length-1;d>0;d--)b.disableTimeRanges[d][0]<=b.disableTimeRanges[d-1][1]&&(b.disableTimeRanges[d-1]=[Math.min(b.disableTimeRanges[d][0],b.disableTimeRanges[d-1][0]),Math.max(b.disableTimeRanges[d][1],b.disableTimeRanges[d-1][1])],b.disableTimeRanges.splice(d,1))}return b}function d(b){var c=b.data("timepicker-settings"),d=b.data("timepicker-list");if(d&&d.length&&(d.remove(),b.data("timepicker-list",!1)),c.useSelect){d=a("<select />",{"class":"ui-timepicker-select"}),b.attr("name")&&d.attr("name","ui-timepicker-"+b.attr("name"));var g=d}else{d=a("<ul />",{"class":"ui-timepicker-list"});var g=a("<div />",{"class":"ui-timepicker-wrapper",tabindex:-1});g.css({display:"none",position:"absolute"}).append(d)}if(c.noneOption)if(c.noneOption===!0&&(c.noneOption=c.useSelect?"Time...":"None"),a.isArray(c.noneOption)){for(var i in c.noneOption)if(parseInt(i,10)==i){var k=e(c.noneOption[i],c.useSelect);d.append(k)}}else{var k=e(c.noneOption,c.useSelect);d.append(k)}if(c.className&&g.addClass(c.className),(null!==c.minTime||null!==c.durationTime)&&c.showDuration){"function"==typeof c.step?"function":c.step;g.addClass("ui-timepicker-with-duration"),g.addClass("ui-timepicker-step-"+c.step)}var l=c.minTime;"function"==typeof c.durationTime?l=t(c.durationTime()):null!==c.durationTime&&(l=c.durationTime);var n=null!==c.minTime?c.minTime:0,o=null!==c.maxTime?c.maxTime:n+v-1;o<n&&(o+=v),o===v-1&&"string"===a.type(c.timeFormat)&&c.show2400&&(o=v);var p=c.disableTimeRanges,w=0,x=p.length,z=c.step;"function"!=typeof z&&(z=function(){return c.step});for(var i=n,A=0;i<=o;A++,i+=60*z(A)){var B=i,C=s(B,c);if(c.useSelect){var D=a("<option />",{value:C});D.text(C)}else{var D=a("<li />");D.addClass(B%v<v/2?"ui-timepicker-am":"ui-timepicker-pm"),D.data("time",u(B,c)),D.text(C)}if((null!==c.minTime||null!==c.durationTime)&&c.showDuration){var E=r(i-l,c.step);if(c.useSelect)D.text(D.text()+" ("+E+")");else{var F=a("<span />",{"class":"ui-timepicker-duration"});F.text(" ("+E+")"),D.append(F)}}w<x&&(B>=p[w][1]&&(w+=1),p[w]&&B>=p[w][0]&&B<p[w][1]&&(c.useSelect?D.prop("disabled",!0):D.addClass("ui-timepicker-disabled"))),d.append(D)}if(g.data("timepicker-input",b),b.data("timepicker-list",g),c.useSelect)b.val()&&d.val(f(t(b.val()),c)),d.on("focus",function(){a(this).data("timepicker-input").trigger("showTimepicker")}),d.on("blur",function(){a(this).data("timepicker-input").trigger("hideTimepicker")}),d.on("change",function(){m(b,a(this).val(),"select")}),m(b,d.val(),"initial"),b.hide().after(d);else{var G=c.appendTo;"string"==typeof G?G=a(G):"function"==typeof G&&(G=G(b)),G.append(g),j(b,d),d.on("mousedown click","li",function(c){b.off("focus.timepicker"),b.on("focus.timepicker-ie-hack",function(){b.off("focus.timepicker-ie-hack"),b.on("focus.timepicker",y.show)}),h(b)||b[0].focus(),d.find("li").removeClass("ui-timepicker-selected"),a(this).addClass("ui-timepicker-selected"),q(b)&&(b.trigger("hideTimepicker"),d.on("mouseup.timepicker click.timepicker","li",function(a){d.off("mouseup.timepicker click.timepicker"),g.hide()}))})}}function e(b,c){var d,e,f;return"object"==typeof b?(d=b.label,e=b.className,f=b.value):"string"==typeof b?(d=b,f=""):a.error("Invalid noneOption value"),c?a("<option />",{value:f,"class":e,text:d}):a("<li />",{"class":e,text:d}).data("time",String(f))}function f(a,b){if(a=b.roundingFunction(a,b),null!==a)return s(a,b)}function g(b){if(b.target!=window){var c=a(b.target);c.closest(".ui-timepicker-input").length||c.closest(".ui-timepicker-wrapper").length||(y.hide(),a(document).unbind(".ui-timepicker"),a(window).unbind(".ui-timepicker"))}}function h(a){var b=a.data("timepicker-settings");return(window.navigator.msMaxTouchPoints||"ontouchstart"in document)&&b.disableTouchKeyboard}function i(b,c,d){if(!d&&0!==d)return!1;var e=b.data("timepicker-settings"),f=!1,d=e.roundingFunction(d,e);return c.find("li").each(function(b,c){var e=a(c);if("number"==typeof e.data("time"))return e.data("time")==d?(f=e,!1):void 0}),f}function j(a,b){b.find("li").removeClass("ui-timepicker-selected");var c=a.data("timepicker-settings"),d=t(l(a),c);if(null!==d){var e=i(a,b,d);if(e){var f=e.offset().top-b.offset().top;(f+e.outerHeight()>b.outerHeight()||f<0)&&b.scrollTop(b.scrollTop()+e.position().top-e.outerHeight()),(c.forceRoundTime||e.data("time")===d)&&e.addClass("ui-timepicker-selected")}}}function k(b,c){if("timepicker"!=c){var d=a(this);if(""===this.value)return void m(d,null,c);if(!d.is(":focus")||b&&"change"==b.type){var e=d.data("timepicker-settings"),f=t(this.value,e);if(null===f)return void d.trigger("timeFormatError");var g=!1;if(null!==e.minTime&&null!==e.maxTime&&(f<e.minTime||f>e.maxTime)&&(g=!0),a.each(e.disableTimeRanges,function(){if(f>=this[0]&&f<this[1])return g=!0,!1}),e.forceRoundTime){var h=e.roundingFunction(f,e);h!=f&&(f=h,c=null)}var i=s(f,e);g?(m(d,i,"error")||b&&"change"==b.type)&&d.trigger("timeRangeError"):m(d,i,c)}}}function l(a){return a.is("input")?a.val():a.data("ui-timepicker-value")}function m(a,b,c){if(a.is("input")){a.val(b);var d=a.data("timepicker-settings");d.useSelect&&"select"!=c&&a.data("timepicker-list")&&a.data("timepicker-list").val(f(t(b),d))}return a.data("ui-timepicker-value")!=b?(a.data("ui-timepicker-value",b),"select"==c?a.trigger("selectTime").trigger("changeTime").trigger("change","timepicker"):["error","initial"].indexOf(c)==-1&&a.trigger("changeTime"),!0):(["error","initial"].indexOf(c)==-1&&a.trigger("selectTime"),!1)}function n(a){switch(a.keyCode){case 13:case 9:return;default:a.preventDefault()}}function o(c){var d=a(this),e=d.data("timepicker-list");if(!e||!b(e)){if(40!=c.keyCode)return!0;y.show.call(d.get(0)),e=d.data("timepicker-list"),h(d)||d.focus()}switch(c.keyCode){case 13:return q(d)&&(k.call(d.get(0),{type:"change"}),y.hide.apply(this)),c.preventDefault(),!1;case 38:var f=e.find(".ui-timepicker-selected");return f.length?f.is(":first-child")||(f.removeClass("ui-timepicker-selected"),f.prev().addClass("ui-timepicker-selected"),f.prev().position().top<f.outerHeight()&&e.scrollTop(e.scrollTop()-f.outerHeight())):(e.find("li").each(function(b,c){if(a(c).position().top>0)return f=a(c),!1}),f.addClass("ui-timepicker-selected")),!1;case 40:return f=e.find(".ui-timepicker-selected"),0===f.length?(e.find("li").each(function(b,c){if(a(c).position().top>0)return f=a(c),!1}),f.addClass("ui-timepicker-selected")):f.is(":last-child")||(f.removeClass("ui-timepicker-selected"),f.next().addClass("ui-timepicker-selected"),f.next().position().top+2*f.outerHeight()>e.outerHeight()&&e.scrollTop(e.scrollTop()+f.outerHeight())),!1;case 27:e.find("li").removeClass("ui-timepicker-selected"),y.hide();break;case 9:y.hide();break;default:return!0}}function p(c){var d=a(this),e=d.data("timepicker-list"),f=d.data("timepicker-settings");if(!e||!b(e)||f.disableTextInput)return!0;if("paste"===c.type||"cut"===c.type)return void setTimeout(function(){f.typeaheadHighlight?j(d,e):e.hide()},0);switch(c.keyCode){case 96:case 97:case 98:case 99:case 100:case 101:case 102:case 103:case 104:case 105:case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:case 65:case 77:case 80:case 186:case 8:case 46:f.typeaheadHighlight?j(d,e):e.hide()}}function q(a){var b=a.data("timepicker-settings"),c=a.data("timepicker-list"),d=null,e=c.find(".ui-timepicker-selected");return!e.hasClass("ui-timepicker-disabled")&&(e.length&&(d=e.data("time")),null!==d&&("string"!=typeof d&&(d=s(d,b)),m(a,d,"select")),!0)}function r(a,b){a=Math.abs(a);var c,d,e=Math.round(a/60),f=[];return e<60?f=[e,w.mins]:(c=Math.floor(e/60),d=e%60,30==b&&30==d&&(c+=w.decimal+5),f.push(c),f.push(1==c?w.hr:w.hrs),30!=b&&d&&(f.push(d),f.push(w.mins))),f.join(" ")}function s(b,c){if("number"!=typeof b)return null;var d=parseInt(b%60),e=parseInt(b/60%60),f=parseInt(b/3600%24),g=new Date(1970,0,2,f,e,d,0);if(isNaN(g.getTime()))return null;if("function"===a.type(c.timeFormat))return c.timeFormat(g);for(var h,i,j="",k=0;k<c.timeFormat.length;k++)switch(i=c.timeFormat.charAt(k)){case"a":j+=g.getHours()>11?w.pm:w.am;break;case"A":j+=g.getHours()>11?w.PM:w.AM;break;case"g":h=g.getHours()%12,j+=0===h?"12":h;break;case"G":h=g.getHours(),b===v&&(h=c.show2400?24:0),j+=h;break;case"h":h=g.getHours()%12,0!==h&&h<10&&(h="0"+h),j+=0===h?"12":h;break;case"H":h=g.getHours(),b===v&&(h=c.show2400?24:0),j+=h>9?h:"0"+h;break;case"i":var e=g.getMinutes();j+=e>9?e:"0"+e;break;case"s":d=g.getSeconds(),j+=d>9?d:"0"+d;break;case"\\":k++,j+=c.timeFormat.charAt(k);break;default:j+=i}return j}function t(a,b){if(""===a||null===a)return null;if("object"==typeof a)return 3600*a.getHours()+60*a.getMinutes()+a.getSeconds();if("string"!=typeof a)return a;a=a.toLowerCase().replace(/[\s\.]/g,""),"a"!=a.slice(-1)&&"p"!=a.slice(-1)||(a+="m");var c="("+w.am.replace(".","")+"|"+w.pm.replace(".","")+"|"+w.AM.replace(".","")+"|"+w.PM.replace(".","")+")?",d=new RegExp("^"+c+"([0-9]?[0-9])\\W?([0-5][0-9])?\\W?([0-5][0-9])?"+c+"$"),e=a.match(d);if(!e)return null;var f=parseInt(1*e[2],10),g=e[1]||e[5],h=f,i=1*e[3]||0,j=1*e[4]||0;if(f<=12&&g){var k=g==w.pm||g==w.PM;h=12==f?k?12:0:f+(k?12:0)}else if(b){var l=3600*f+60*i+j;if(l>=v+(b.show2400?1:0)){if(b.wrapHours===!1)return null;h=f%24}}var m=3600*h+60*i+j;if(f<12&&!g&&b&&b._twelveHourTime&&b.scrollDefault){var n=m-b.scrollDefault();n<0&&n>=v/-2&&(m=(m+v/2)%v)}return m}function u(a,b){return a==v&&b.show2400?a:a%v}var v=86400,w={am:"am",pm:"pm",AM:"AM",PM:"PM",decimal:".",mins:"mins",hr:"hr",hrs:"hrs"},x={appendTo:"body",className:null,closeOnWindowScroll:!1,disableTextInput:!1,disableTimeRanges:[],disableTouchKeyboard:!1,durationTime:null,forceRoundTime:!1,maxTime:null,minTime:null,noneOption:!1,orientation:"l",roundingFunction:function(a,b){if(null===a)return null;if("number"!=typeof b.step)return a;var c=a%(60*b.step),d=b.minTime||0;return c-=d%(60*b.step),c>=30*b.step?a+=60*b.step-c:a-=c,u(a,b)},scrollDefault:null,selectOnBlur:!1,show2400:!1,showDuration:!1,showOn:["click","focus"],showOnFocus:!0,step:30,stopScrollPropagation:!1,timeFormat:"g:ia",typeaheadHighlight:!0,useSelect:!1,wrapHours:!0},y={init:function(b){return this.each(function(){var e=a(this),f=[];for(var g in x)e.data(g)&&(f[g]=e.data(g));var h=a.extend({},x,b,f);if(h.lang&&(w=a.extend(w,h.lang)),h=c(h),e.data("timepicker-settings",h),e.addClass("ui-timepicker-input"),h.useSelect)d(e);else{if(e.prop("autocomplete","off"),h.showOn)for(var i in h.showOn)e.on(h.showOn[i]+".timepicker",y.show);e.on("change.timepicker",k),e.on("keydown.timepicker",o),e.on("keyup.timepicker",p),h.disableTextInput&&e.on("keydown.timepicker",n),e.on("cut.timepicker",p),e.on("paste.timepicker",p),k.call(e.get(0),null,"initial")}})},show:function(c){var e=a(this),f=e.data("timepicker-settings");if(c&&c.preventDefault(),f.useSelect)return void e.data("timepicker-list").focus();h(e)&&e.blur();var k=e.data("timepicker-list");if(!e.prop("readonly")&&(k&&0!==k.length&&"function"!=typeof f.durationTime||(d(e),k=e.data("timepicker-list")),!b(k))){e.data("ui-timepicker-value",e.val()),j(e,k),y.hide(),k.show();var m={};f.orientation.match(/r/)?m.left=e.offset().left+e.outerWidth()-k.outerWidth()+parseInt(k.css("marginLeft").replace("px",""),10):m.left=e.offset().left+parseInt(k.css("marginLeft").replace("px",""),10);var n;n=f.orientation.match(/t/)?"t":f.orientation.match(/b/)?"b":e.offset().top+e.outerHeight(!0)+k.outerHeight()>a(window).height()+a(window).scrollTop()?"t":"b","t"==n?(k.addClass("ui-timepicker-positioned-top"),m.top=e.offset().top-k.outerHeight()+parseInt(k.css("marginTop").replace("px",""),10)):(k.removeClass("ui-timepicker-positioned-top"),m.top=e.offset().top+e.outerHeight()+parseInt(k.css("marginTop").replace("px",""),10)),k.offset(m);var o=k.find(".ui-timepicker-selected");if(!o.length){var p=t(l(e));null!==p?o=i(e,k,p):f.scrollDefault&&(o=i(e,k,f.scrollDefault()))}if(o.length&&!o.hasClass("ui-timepicker-disabled")||(o=k.find("li:not(.ui-timepicker-disabled):first")),o&&o.length){var q=k.scrollTop()+o.position().top-o.outerHeight();k.scrollTop(q)}else k.scrollTop(0);return f.stopScrollPropagation&&a(document).on("wheel.ui-timepicker",".ui-timepicker-wrapper",function(b){b.preventDefault();var c=a(this).scrollTop();a(this).scrollTop(c+b.originalEvent.deltaY)}),a(document).on("touchstart.ui-timepicker mousedown.ui-timepicker",g),a(window).on("resize.ui-timepicker",g),f.closeOnWindowScroll&&a(document).on("scroll.ui-timepicker",g),e.trigger("showTimepicker"),this}},hide:function(c){var d=a(this),e=d.data("timepicker-settings");return e&&e.useSelect&&d.blur(),a(".ui-timepicker-wrapper").each(function(){var c=a(this);if(b(c)){var d=c.data("timepicker-input"),e=d.data("timepicker-settings");e&&e.selectOnBlur&&q(d),c.hide(),d.trigger("hideTimepicker")}}),this},option:function(b,e){return"string"==typeof b&&"undefined"==typeof e?a(this).data("timepicker-settings")[b]:this.each(function(){var f=a(this),g=f.data("timepicker-settings"),h=f.data("timepicker-list");"object"==typeof b?g=a.extend(g,b):"string"==typeof b&&(g[b]=e),g=c(g),f.data("timepicker-settings",g),k.call(f.get(0),{type:"change"},"initial"),h&&(h.remove(),f.data("timepicker-list",!1)),g.useSelect&&d(f)})},getSecondsFromMidnight:function(){return t(l(this))},getTime:function(a){var b=this,c=l(b);if(!c)return null;var d=t(c);if(null===d)return null;a||(a=new Date);var e=new Date(a);return e.setHours(d/3600),e.setMinutes(d%3600/60),e.setSeconds(d%60),e.setMilliseconds(0),e},isVisible:function(){var a=this,c=a.data("timepicker-list");return!(!c||!b(c))},setTime:function(a){var b=this,c=b.data("timepicker-settings");if(c.forceRoundTime)var d=f(t(a),c);else var d=s(t(a),c);return a&&null===d&&c.noneOption&&(d=a),m(b,d,"initial"),k.call(b.get(0),{type:"change"},"initial"),b.data("timepicker-list")&&j(b,b.data("timepicker-list")),this},remove:function(){var a=this;if(a.hasClass("ui-timepicker-input")){var b=a.data("timepicker-settings");return a.removeAttr("autocomplete","off"),a.removeClass("ui-timepicker-input"),a.removeData("timepicker-settings"),a.off(".timepicker"),a.data("timepicker-list")&&a.data("timepicker-list").remove(),b.useSelect&&a.show(),a.removeData("timepicker-list"),this}}};a.fn.timepicker=function(b){return this.length?y[b]?this.hasClass("ui-timepicker-input")?y[b].apply(this,Array.prototype.slice.call(arguments,1)):this:"object"!=typeof b&&b?void a.error("Method "+b+" does not exist on jQuery.timepicker"):y.init.apply(this,arguments):this}});
cerber-lab.php CHANGED
@@ -41,6 +41,7 @@ define( 'LAB_INTERVAL', 180 ); // seconds, push interval
41
  define( 'LAB_DNS_TTL', 3 * 24 * 3600 ); // seconds, interval of updating DNS cache for nodes IPs
42
  define( 'LAB_IP_OK', 100 ); // an ideal, the best possible reputation
43
  define( 'LAB_KEY_LENGTH', 32 );
 
44
 
45
  /**
46
  * Is IP blocked globally in Cerber Lab?
@@ -179,7 +180,9 @@ function lab_api_send_request($workload = array()) {
179
 
180
  $push = lab_get_push();
181
 
182
- if (!$workload && !$push) return false;
 
 
183
 
184
  $key = lab_get_key();
185
 
@@ -560,33 +563,31 @@ function lab_get_push() {
560
  return false;
561
  }
562
  function lab_trunc_push(){
563
- global $wpdb;
564
- $wpdb->query( 'TRUNCATE TABLE ' . CERBER_LAB_TABLE );
 
565
  }
566
 
567
- add_action( 'shutdown', function () {
568
- cerber_push_lab();
569
- } );
570
-
571
  function cerber_push_lab() {
572
  if ( ! crb_get_settings( 'cerberlab' ) ) {
573
  return;
574
  }
575
- // TODO: replace with my own cache code because wp_cache_get doesn't work with expiration
576
- if ( get_transient( '_cerberpush_' ) ) {
577
- //if ( wp_cache_get( '_cerberpush_', 'cerber' ) ) { // wp_cache_get doesn't work with expiration
578
  return;
579
  }
580
  lab_api_send_request();
581
- set_transient( '_cerberpush_', 1, LAB_INTERVAL );
582
- //wp_cache_set( '_cerberpush_', 1, 'cerber', LAB_INTERVAL);
583
  }
584
 
585
- function lab_get_key( $regenerate = false, $nocache = false) {
586
  static $key = null;
587
 
588
  if ( ! isset( $key ) || $nocache ) {
589
- if (is_admin()) {
590
  $key = get_site_option( '_cerberkey_' ); // must be from the session cache only
591
  }
592
  else {
@@ -594,30 +595,58 @@ function lab_get_key( $regenerate = false, $nocache = false) {
594
  }
595
  }
596
 
597
- if ( $regenerate || ! $key || ! is_array( $key ) ) {
 
 
 
 
598
 
599
- if ( is_multisite() ) {
600
- $home = network_home_url();
601
- } else {
602
- $home = home_url();
603
  }
604
- if ( $host = parse_url( $home, PHP_URL_HOST ) ) {
605
- $site_id = md5( $host );
606
- } else {
607
- $site_id = md5( $home );
 
 
 
 
 
 
 
608
  }
 
609
  $new = array( $site_id, time() );
610
  if ( isset( $key[2] ) ) {
611
  $new[2] = $key[2];
612
  }
613
  $key = $new;
 
614
 
615
- update_site_option( '_cerberkey_', $new );
616
  }
617
 
618
  return $key;
619
  }
620
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
621
  function lab_update_key( $lic, $expires = 0 ) {
622
  $key = lab_get_key();
623
  $key[2] = strtoupper( $lic );
@@ -665,7 +694,7 @@ function lab_lab( $with_date = false ) {
665
  if ( empty( $key[2] ) || empty( $key[3] ) ) {
666
  return false;
667
  }
668
- if ( time() > ( $key[3] + 86400 ) ) { // Plus grace period
669
  return false;
670
  }
671
  if ( ! $with_date ) {
@@ -699,7 +728,9 @@ function lab_opt_in(){
699
  global $cerber_shown, $crb_assets_url;
700
 
701
  if ($cerber_shown || crb_get_settings('cerberlab')) return;
702
- if (!cerber_is_admin_page(false)) return;
 
 
703
 
704
  // Avoid more than one message on the screen
705
  // TODO: to many checks!
@@ -910,38 +941,6 @@ function lab_cleanup_cache() {
910
  $wpdb->query( 'TRUNCATE TABLE ' . CERBER_LAB_IP_TABLE );
911
  }
912
 
913
- /**
914
- * Check if the current request is originated from the Cerber Cloud
915
- *
916
- * @return int 1 for the cloud request, 0 otherwise
917
- */
918
- function lab_is_cloud_request() {
919
- static $ret;
920
-
921
- if ( isset( $ret ) ) {
922
- return $ret;
923
- }
924
-
925
- if ( empty( $_GET['cerber_cloud_nid'] ) && empty( $_POST['cerber_cloud_nid'] ) ) {
926
- $ret = 0;
927
- return $ret;
928
- }
929
-
930
- $node_id = absint( $_GET['cerber_cloud_nid'] );
931
- if ( ! $node_id ) {
932
- $node_id = absint( $_POST['cerber_cloud_nid'] );
933
- }
934
-
935
- if ( $node_id && ( lab_get_real_node_id() === $node_id ) ) {
936
- $ret = 1;
937
- }
938
- else {
939
- $ret = 0;
940
- }
941
-
942
- return $ret;
943
- }
944
-
945
  /**
946
  * Return node ID for the current request if it is originated from the Cerber Cloud
947
  *
@@ -950,11 +949,10 @@ function lab_is_cloud_request() {
950
  function lab_get_real_node_id() {
951
  static $ret;
952
 
953
- if ( isset( $ret ) ) {
954
  return $ret;
955
  }
956
 
957
- // Use a cache for all node IPs
958
  $hostname = @gethostbyaddr( cerber_get_remote_ip() );
959
  if ( ! $hostname || filter_var( $hostname, FILTER_VALIDATE_IP ) ) {
960
  $ret = false;
@@ -967,13 +965,13 @@ function lab_get_real_node_id() {
967
 
968
  return $ret;
969
  }
970
- if ( $domain[1] . '.' . $domain[2] != 'cerberlab.net' ) {
971
  $ret = false;
972
 
973
  return $ret;
974
  }
975
 
976
- $ret = absint( substr( $domain[0], 4, 2 ) );
977
 
978
  return $ret;
979
  }
41
  define( 'LAB_DNS_TTL', 3 * 24 * 3600 ); // seconds, interval of updating DNS cache for nodes IPs
42
  define( 'LAB_IP_OK', 100 ); // an ideal, the best possible reputation
43
  define( 'LAB_KEY_LENGTH', 32 );
44
+ define( 'LAB_LICENSE_GRACE', 3600 * 24 * 3 );
45
 
46
  /**
47
  * Is IP blocked globally in Cerber Lab?
180
 
181
  $push = lab_get_push();
182
 
183
+ if ( ! $workload && ! $push ) {
184
+ return false;
185
+ }
186
 
187
  $key = lab_get_key();
188
 
563
  return false;
564
  }
565
  function lab_trunc_push(){
566
+ //global $wpdb;
567
+ //$wpdb->query( 'TRUNCATE TABLE ' . CERBER_LAB_TABLE );
568
+ cerber_db_query( 'TRUNCATE TABLE ' . CERBER_LAB_TABLE );
569
  }
570
 
571
+ register_shutdown_function( 'cerber_push_lab' );
 
 
 
572
  function cerber_push_lab() {
573
  if ( ! crb_get_settings( 'cerberlab' ) ) {
574
  return;
575
  }
576
+ if ( cerber_get_set( '_cerberpush_', null, false ) ) {
577
+ //if ( get_transient( '_cerberpush_' ) ) {
578
+ //if ( wp_cache_get( '_cerberpush_', 'cerber' ) ) { // wp_cache_get doesn't work with expiration
579
  return;
580
  }
581
  lab_api_send_request();
582
+ //set_transient( '_cerberpush_', 1, LAB_INTERVAL );
583
+ cerber_update_set( '_cerberpush_', 1, null, false, time() + LAB_INTERVAL );
584
  }
585
 
586
+ function lab_get_key( $refresh = false, $nocache = false) {
587
  static $key = null;
588
 
589
  if ( ! isset( $key ) || $nocache ) {
590
+ if ( is_admin() ) {
591
  $key = get_site_option( '_cerberkey_' ); // must be from the session cache only
592
  }
593
  else {
595
  }
596
  }
597
 
598
+ if ( $refresh || ! $key || ! is_array( $key ) ) {
599
+
600
+ if ( empty( $key ) || ! is_array( $key ) ) {
601
+ $key = array();
602
+ }
603
 
604
+ if ( empty( $key[0] ) ) {
605
+ $key[0] = lab_gen_site_id();
 
 
606
  }
607
+ else {
608
+ // WP is installed in a subdirectory
609
+ if ( 2 < substr_count( home_url(), '/' ) ) {
610
+ $key[0] = lab_gen_site_id();
611
+ }
612
+ }
613
+
614
+ $key[1] = time();
615
+
616
+ if ( empty( $key[4] ) ) {
617
+ $key[4] = 'SK//' . str_shuffle( '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' );
618
  }
619
+ /*
620
  $new = array( $site_id, time() );
621
  if ( isset( $key[2] ) ) {
622
  $new[2] = $key[2];
623
  }
624
  $key = $new;
625
+ */
626
 
627
+ update_site_option( '_cerberkey_', $key );
628
  }
629
 
630
  return $key;
631
  }
632
 
633
+ // @since 7.1
634
+ function lab_gen_site_id() {
635
+ if ( is_multisite() ) {
636
+ $home = network_home_url();
637
+ }
638
+ else {
639
+ $home = home_url();
640
+ }
641
+
642
+ $home = rtrim( trim( $home ), '/' );
643
+ $id = substr( $home, strpos( $home, '//' ) + 2 );
644
+
645
+ $site_id = md5( $id );
646
+
647
+ return $site_id;
648
+ }
649
+
650
  function lab_update_key( $lic, $expires = 0 ) {
651
  $key = lab_get_key();
652
  $key[2] = strtoupper( $lic );
694
  if ( empty( $key[2] ) || empty( $key[3] ) ) {
695
  return false;
696
  }
697
+ if ( time() > ( $key[3] + LAB_LICENSE_GRACE ) ) {
698
  return false;
699
  }
700
  if ( ! $with_date ) {
728
  global $cerber_shown, $crb_assets_url;
729
 
730
  if ($cerber_shown || crb_get_settings('cerberlab')) return;
731
+ if ( ! cerber_is_admin_page() ) {
732
+ return;
733
+ }
734
 
735
  // Avoid more than one message on the screen
736
  // TODO: to many checks!
941
  $wpdb->query( 'TRUNCATE TABLE ' . CERBER_LAB_IP_TABLE );
942
  }
943
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
944
  /**
945
  * Return node ID for the current request if it is originated from the Cerber Cloud
946
  *
949
  function lab_get_real_node_id() {
950
  static $ret;
951
 
952
+ if ( $ret !== null ) {
953
  return $ret;
954
  }
955
 
 
956
  $hostname = @gethostbyaddr( cerber_get_remote_ip() );
957
  if ( ! $hostname || filter_var( $hostname, FILTER_VALIDATE_IP ) ) {
958
  $ret = false;
965
 
966
  return $ret;
967
  }
968
+ if ( $domain[1] . '.' . $domain[2] !== 'cerberlab.net' ) {
969
  $ret = false;
970
 
971
  return $ret;
972
  }
973
 
974
+ $ret = absint( substr( $domain[0], 4, 2 ) ); // 0-99
975
 
976
  return $ret;
977
  }
cerber-load.php CHANGED
@@ -204,15 +204,16 @@ class WP_Cerber {
204
  $this->uri_prohibited = true;
205
  return true;
206
  }
207
- if ( $this->isDeny() || !empty( $this->options['loginnowp'] ) ) {
208
  cerber_log( 50 );
209
  $this->uri_prohibited = true;
210
  return true;
211
  }
212
  }
213
  elseif ( $script == WP_XMLRPC_SCRIPT || $script == WP_TRACKBACK_SCRIPT ) { // no direct access
214
- if ( $this->isDeny() || ! empty( $this->options['xmlrpc'] ) ) {
215
- cerber_log( 50 ); // @since 5.21
 
216
  $this->uri_prohibited = true;
217
  return true;
218
  }
@@ -1194,7 +1195,10 @@ function cerber_is_registration_prohibited( $sanitized_user_login ) {
1194
  * @return bool
1195
  */
1196
  function crb_is_reg_limit_reached() {
1197
- global $wp_cerber;
 
 
 
1198
 
1199
  if ( ! crb_get_settings( 'reglimit_min' ) || ! crb_get_settings( 'reglimit_num' ) ) {
1200
  return false;
@@ -1490,7 +1494,7 @@ add_action( 'init', function () {
1490
  define( 'CONCATENATE_SCRIPTS', false );
1491
  }
1492
  cerber_access_control();
1493
- cerber_antibot_control();
1494
  }, 0 );
1495
 
1496
  /**
@@ -1620,7 +1624,7 @@ function cerber_access_control() {
1620
  * Antispam & Antibot for forms
1621
  *
1622
  */
1623
- function cerber_antibot_control(){
1624
  global $cerber_status;
1625
 
1626
  if ( !cerber_is_http_post() || cerber_acl_check( null, 'W' ) ) {
@@ -1709,6 +1713,11 @@ function cerber_is_antibot_exception(){
1709
  return true;
1710
  }
1711
 
 
 
 
 
 
1712
  // REST API (except Contact Form 7 submission)
1713
  if ( cerber_is_rest_url() ) {
1714
  if ( false === strpos( $_SERVER['REQUEST_URI'], 'contact-form-7' ) ) {
@@ -2402,6 +2411,10 @@ function cerber_soft_block_add( $ip, $reason_id, $details = '', $duration = null
2402
  function cerber_block_add( $ip = '', $reason_id = 1, $details = '', $duration = null ) {
2403
  global $wpdb;
2404
 
 
 
 
 
2405
  $wp_cerber = get_wp_cerber();
2406
 
2407
  //$wp_cerber->setProcessed();
@@ -2466,7 +2479,7 @@ function cerber_block_add( $ip = '', $reason_id = 1, $details = '', $duration =
2466
  //$count = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_BLOCKS_TABLE );
2467
  $count = cerber_blocked_num();
2468
  if ( $count > $wp_cerber->getSettings( 'above' ) ) {
2469
- cerber_send_notify( 'lockout', '', $ip_address );
2470
  }
2471
  }
2472
 
@@ -3258,7 +3271,7 @@ function cerber_enable_citadel() {
3258
 
3259
  // Notify admin
3260
  if ( $wp_cerber->getSettings( 'cinotify' ) ) {
3261
- cerber_send_notify( 'citadel' );
3262
  }
3263
  }
3264
 
@@ -3311,7 +3324,7 @@ remove_action('wp_head', 'wp_shortlink_wp_head', 10, 0 );
3311
  *
3312
  * @return bool
3313
  */
3314
- function cerber_send_notify( $type = '', $msg = '', $ip = '' ) {
3315
  global $wpdb, $wp_cerber;
3316
  if ( ! $type ) {
3317
  return false;
@@ -3350,7 +3363,7 @@ function cerber_send_notify( $type = '', $msg = '', $ip = '' ) {
3350
 
3351
  switch ( $type ) {
3352
  case 'citadel':
3353
- $max = $wpdb->get_var( 'SELECT MAX(stamp) FROM ' . CERBER_LOG_TABLE . ' WHERE activity = 7' );
3354
  if ($max) {
3355
  $last_date = cerber_date( $max );
3356
  $last = $wpdb->get_row( 'SELECT * FROM ' . CERBER_LOG_TABLE . ' WHERE stamp = ' . $max . ' AND activity = 7' );
@@ -3371,10 +3384,11 @@ function cerber_send_notify( $type = '', $msg = '', $ip = '' ) {
3371
  //$body .= __('Change notification settings','wp-cerber').': '.cerber_admin_link();
3372
  break;
3373
  case 'lockout':
3374
- $max = $wpdb->get_var( 'SELECT MAX(stamp) FROM ' . CERBER_LOG_TABLE . ' WHERE activity IN (10,11)' );
3375
  if ($max){
3376
  $last_date = cerber_date( $max );
3377
- $last = $wpdb->get_row( 'SELECT * FROM ' . CERBER_LOG_TABLE . ' WHERE stamp = ' . $max . ' AND activity IN (10,11)' );
 
3378
  }
3379
  else $last = null;
3380
  if ( ! $last ) { // workaround for the empty log table
@@ -3383,11 +3397,10 @@ function cerber_send_notify( $type = '', $msg = '', $ip = '' ) {
3383
  $last->user_login = 'test';
3384
  }
3385
 
3386
- //if ( ! $active = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_BLOCKS_TABLE ) ) {
3387
  if ( ! $active = cerber_blocked_num() ) {
3388
  $active = 0;
3389
  }
3390
- //if ( $ip && ( $block = cerber_get_block( $ip ) ) ) {
3391
  if ( $last->ip && ( $block = cerber_get_block( $last->ip ) ) ) {
3392
  $reason = $block->reason;
3393
  }
@@ -3434,7 +3447,6 @@ function cerber_send_notify( $type = '', $msg = '', $ip = '' ) {
3434
  $body .= __( 'Getting Started Guide', 'wp-cerber' ) . "\n\n";
3435
  $body .= 'https://wpcerber.com/getting-started/' . "\n\n";
3436
  $body .= 'Be in touch with the developer. Subscribe to Cerber\'s newsletter: http://wpcerber.com/subscribe-newsletter/';
3437
- //$body .= get_bloginfo( 'name' );
3438
  break;
3439
  case 'newlurl':
3440
  $subj .= __( 'New Custom login URL', 'wp-cerber' );
@@ -3455,6 +3467,13 @@ function cerber_send_notify( $type = '', $msg = '', $ip = '' ) {
3455
  $body .= nl2br($msg);
3456
  }
3457
  break;
 
 
 
 
 
 
 
3458
  }
3459
 
3460
  $to_list = cerber_get_email( $type, true );
@@ -3568,16 +3587,11 @@ function cerber_generate_report($period = 7){
3568
  //$in = implode( ',', crb_get_activity_set( 'malicious' ) );
3569
  //$link_base = '<a href="' . cerber_activity_link( array( 2 ) ) . '">';
3570
  $base_url = cerber_admin_link( 'activity' );
3571
- $css_table = 'width: 95%; max-width: 1000px; margin:0 auto; margin-bottom: 10px; background-color: #f5f5f5; text-align: center;';
3572
  $css_td = 'padding: 0.5em 0.5em 0.5em 1em; text-align: left;';
3573
- $css_boder = 'border-bottom: solid 2px #f9f9f9;';
3574
 
3575
- if (is_multisite()) {
3576
- $site_name = get_site_option( 'site_name' );
3577
- }
3578
- else {
3579
- $site_name = get_option( 'blogname' );
3580
- }
3581
 
3582
  $ret .= '<div style="' . $css_table . '"><div style="margin:0 auto; text-align: center;"><p style="font-size: 130%; padding-top: 0.5em;">' . $site_name .'</p><p style="padding-bottom: 1em;">'. __('Weekly Report','wp-cerber'). '</p></div></div>';
3583
 
@@ -3591,12 +3605,12 @@ function cerber_generate_report($period = 7){
3591
 
3592
  // Activities counters
3593
  $rows = array();
3594
- $rows[] = '<td style="'.$css_td.$css_boder.'" colspan="2"><p style="line-height: 1.5em; font-weight: bold;">'.__('Activity details','wp-cerber').'</p></td>';
3595
  $activites = $wpdb->get_results( 'SELECT activity, COUNT(activity) cnt FROM ' . CERBER_LOG_TABLE . ' WHERE stamp > ' . $stamp . ' GROUP by activity ORDER BY cnt DESC' );
3596
  if ( $activites ) {
3597
  $lables = cerber_get_labels();
3598
  foreach ( $activites as $a ) {
3599
- $rows[] = '<td style="'.$css_boder.$css_td.'">' . $lables[ $a->activity ] . '</td><td style="padding: 0.5em; text-align: center; width:10%;'.$css_boder.'"><a href="'.$base_url.'&filter_activity='.$a->activity.'">' . $a->cnt . '</a></td>';
3600
  }
3601
  }
3602
  $ret .= '<table style="border-collapse: collapse; '.$css_table.'"><tr>' . implode( '</tr><tr>', $rows ) . '</tr></table>';
@@ -3605,9 +3619,9 @@ function cerber_generate_report($period = 7){
3605
  $activites = $wpdb->get_results( 'SELECT user_login, COUNT(user_login) cnt FROM ' . CERBER_LOG_TABLE . ' WHERE activity = 51 AND stamp > ' . $stamp . ' GROUP by user_login ORDER BY cnt DESC LIMIT 10' );
3606
  if ( $activites ) {
3607
  $rows = array();
3608
- $rows[] = '<td style="'.$css_td.$css_boder.'" colspan="2"><p style="line-height: 1.5em; font-weight: bold;">'.__('Attempts to log in with non-existent username','wp-cerber').'</p></td>';
3609
  foreach ( $activites as $a ) {
3610
- $rows[] = '<td style="'.$css_boder.$css_td.'">' . htmlspecialchars($a->user_login) . '</td><td style="padding: 0.5em; text-align: center; width:10%;'.$css_boder.'"><a href="'.$base_url.'&filter_login='.$a->user_login.'">' . $a->cnt . '</a></td>';
3611
  }
3612
  $ret .= '<table style="border-collapse: collapse; '.$css_table.'"><tr>' . implode( '</tr><tr>', $rows ) . '</tr></table>';
3613
  }
@@ -3661,9 +3675,7 @@ function cerber_do_hourly($force = false) {
3661
  $wpdb->query( 'DELETE FROM ' . CERBER_TRAF_TABLE . ' WHERE stamp < ' . ( $time - $days * 24 * 3600 ) );
3662
  }
3663
 
3664
- if ( crb_get_settings( 'cerberlab' ) ) {
3665
- cerber_push_lab();
3666
- }
3667
 
3668
  $wpdb->query( 'DELETE FROM ' . CERBER_LAB_IP_TABLE . ' WHERE expires < ' . $time );
3669
 
@@ -3698,7 +3710,7 @@ add_action( 'cerber_hourly_2', function () {
3698
  && date( 'G', time() + $gmt_offset ) == crb_get_settings( 'wreports-time' )
3699
  //&& ! get_site_transient( 'cerber_wreport' )
3700
  ) {
3701
- $result = cerber_send_notify( 'report' );
3702
  //set_site_transient( 'cerber_wreport', 'sent', 7200 );
3703
  update_site_option( '_cerber_report', array( time(), $result ) );
3704
  }
@@ -3724,6 +3736,8 @@ add_action( 'cerber_hourly_2', function () {
3724
  }
3725
  }
3726
 
 
 
3727
  // Keep folder locked
3728
  cerber_get_the_folder();
3729
 
@@ -3759,7 +3773,7 @@ function cerber_do_daily() {
3759
  }
3760
  if ( ! in_array( $new['ver'], $history ) ) {
3761
  if ( crb_get_settings( 'notify-new-ver' ) ) {
3762
- cerber_send_notify( 'new_version', 'Read more: https://wpcerber.com/?plugin_version=' . $new['ver'] );
3763
  }
3764
  $history[] = $new['ver'];
3765
  update_site_option( '_cerber_notify_new', $history );
@@ -3949,7 +3963,7 @@ function cerber_log( $activity, $login = '', $user_id = 0, $ip = null ) {
3949
  $msg .= __( 'View activity in dashboard', 'wp-cerber' ) . ': ' . $link;
3950
  $msg .= "\n\n" . __( 'To unsubscribe click here', 'wp-cerber' ) . ': ' . cerber_admin_link( 'activity' ) . '&unsubscribeme=' . $hash;
3951
 
3952
- cerber_send_notify( 'subs', $msg, $ip );
3953
 
3954
  break; // Just one notification letter per event
3955
  }
@@ -4119,6 +4133,8 @@ function cerber_set_up() {
4119
  cerber_stop_activating( '<h3>' . __( "Can't activate WP Cerber due to a database error.", 'wp-cerber' ) . '</h3>'.$e);
4120
  }
4121
 
 
 
4122
  // Check for existing options
4123
  $opt = cerber_get_options();
4124
  $new = true;
@@ -4169,7 +4185,7 @@ function cerber_set_up() {
4169
  return;
4170
  }
4171
 
4172
- cerber_send_notify( 'activated' );
4173
 
4174
  $pi = get_file_data( cerber_plugin_file(), array( 'Version' => 'Version' ), 'plugin' );
4175
  $pi ['time'] = time();
@@ -4204,6 +4220,7 @@ function cerber_upgrade_all() {
4204
  cerber_push_the_news( CERBER_VER );
4205
  update_site_option( '_cerber_up', array( 'v' => CERBER_VER, 't' => time() ) );
4206
  cerber_delete_expired_set( true );
 
4207
  }
4208
  }
4209
 
@@ -4335,9 +4352,9 @@ function cerber_create_db($recreate = true) {
4335
  ';
4336
  }
4337
 
4338
- if ( ! cerber_is_table( CERBER_SCAN_TABLE ) ) {
4339
  $sql[] = '
4340
- CREATE TABLE IF NOT EXISTS ' . CERBER_SCAN_TABLE . ' (
4341
  scan_id INT(10) UNSIGNED NOT NULL,
4342
  scan_type INT(10) UNSIGNED NOT NULL DEFAULT 1,
4343
  scan_mode INT(10) UNSIGNED NOT NULL DEFAULT 0,
@@ -4389,7 +4406,9 @@ function cerber_create_db($recreate = true) {
4389
  function cerber_upgrade_db( $force = false ) {
4390
  global $wpdb;
4391
  $wpdb->hide_errors();
4392
- if ($force) $wpdb->suppress_errors();
 
 
4393
  $db_errors = array();
4394
  $sql = array();
4395
 
@@ -4432,6 +4451,14 @@ function cerber_upgrade_db( $force = false ) {
4432
  $sql[] = 'ALTER TABLE ' . CERBER_LOG_TABLE . ' ADD INDEX session_index (session_id)';
4433
  }
4434
 
 
 
 
 
 
 
 
 
4435
  if (!empty($sql)) {
4436
  foreach ( $sql as $query ) {
4437
  if ( !$wpdb->query( $query ) && $wpdb->last_error ) {
@@ -4461,8 +4488,7 @@ function cerber_upgrade_db( $force = false ) {
4461
  *
4462
  */
4463
  function cerber_up_data() {
4464
- global $wpdb;
4465
- $ips = $wpdb->get_col( 'SELECT DISTINCT ip FROM ' . CERBER_LOG_TABLE . ' WHERE ip_long = 0 LIMIT 50' );
4466
  if ( ! $ips ) {
4467
  return;
4468
  }
@@ -4472,25 +4498,25 @@ function cerber_up_data() {
4472
  } else {
4473
  $ip_long = 1;
4474
  }
4475
- $wpdb->query( 'UPDATE ' . CERBER_LOG_TABLE . ' SET ip_long = ' . $ip_long . ' WHERE ip = "' . $ip .'" AND ip_long = 0');
4476
  }
4477
  }
4478
 
4479
  /**
4480
- * Upgrade corrupted / from older versions of the plugin rows in ACL
4481
  *
4482
  * @param bool $ipv6 if true Process IPv6 addresses
4483
  *
4484
  */
4485
- function cerber_acl_fixer($ipv6 = false){
4486
  global $wpdb;
4487
 
4488
  // Repair/update IPs without long values
4489
- $rows = $wpdb->get_col( 'SELECT ip FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin = 0 OR ip_long_end = 0' );
4490
- if ( ! $rows ) {
4491
  return;
4492
  }
4493
- foreach ( $rows as $ip ) {
4494
  if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
4495
  continue;
4496
  }
@@ -4504,20 +4530,20 @@ function cerber_acl_fixer($ipv6 = false){
4504
  $end = ip2long( $ip );
4505
  }
4506
 
4507
- $wpdb->query( 'UPDATE ' . CERBER_ACL_TABLE . ' SET ip_long_begin = ' . $begin . ', ip_long_end = ' . $end . ' WHERE ip = "' . $ip .'"');
4508
  }
4509
 
4510
  // Convert old IPv6 to all shortened
4511
  if ( $ipv6 ) {
4512
- $ips = $wpdb->get_col( 'SELECT ip FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin = 0' );
4513
  if ( $ips ) {
4514
  foreach ( $ips as $ip ) {
4515
  if ( ! filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
4516
  continue;
4517
  }
4518
  $short_ip = cerber_short_ipv6( $ip );
4519
- if ($short_ip != $ip) {
4520
- $wpdb->query( 'UPDATE ' . CERBER_ACL_TABLE . ' SET ip = "' . $short_ip . '" WHERE ip = "' . $ip . '"' );
4521
  }
4522
  }
4523
  }
@@ -4537,7 +4563,7 @@ function cerber_clean( $ip ) {
4537
  $pi ['v'] = time();
4538
  $pi ['u'] = get_current_user_id();
4539
  update_site_option( '_cerber_o' . 'ff', $pi );
4540
- $f = 'cerb' . 'er_se' . 'nd_not' . 'ify';
4541
  $f( 'sh' . 'utd' . 'own' );
4542
  }
4543
 
@@ -5045,15 +5071,16 @@ function cerber_prepare_fields( $list ) {
5045
  * @since 6.0
5046
  */
5047
  function cerber_request_time() {
5048
- static $stamp;
5049
 
5050
  if ( ! isset( $stamp ) ) {
 
5051
  if ( ! empty( $_SERVER['REQUEST_TIME_FLOAT'] ) ) { // PHP >= 5.4
5052
- $stamp = $_SERVER['REQUEST_TIME_FLOAT'];
5053
  $stamp = filter_var( $_SERVER['REQUEST_TIME_FLOAT'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION );
5054
  }
5055
- else {
5056
- $stamp = microtime( true );
 
5057
  }
5058
  }
5059
 
204
  $this->uri_prohibited = true;
205
  return true;
206
  }
207
+ if ( ! empty( $this->options['loginnowp'] ) || $this->isDeny() ) {
208
  cerber_log( 50 );
209
  $this->uri_prohibited = true;
210
  return true;
211
  }
212
  }
213
  elseif ( $script == WP_XMLRPC_SCRIPT || $script == WP_TRACKBACK_SCRIPT ) { // no direct access
214
+ //if ( $this->isDeny() || ! empty( $this->options['xmlrpc'] ) ) {
215
+ if ( ! empty( $this->options['xmlrpc'] ) || $this->isDeny() ) {
216
+ cerber_log( 71 );
217
  $this->uri_prohibited = true;
218
  return true;
219
  }
1195
  * @return bool
1196
  */
1197
  function crb_is_reg_limit_reached() {
1198
+
1199
+ if ( ! lab_lab() ) {
1200
+ return false;
1201
+ }
1202
 
1203
  if ( ! crb_get_settings( 'reglimit_min' ) || ! crb_get_settings( 'reglimit_num' ) ) {
1204
  return false;
1494
  define( 'CONCATENATE_SCRIPTS', false );
1495
  }
1496
  cerber_access_control();
1497
+ cerber_post_control();
1498
  }, 0 );
1499
 
1500
  /**
1624
  * Antispam & Antibot for forms
1625
  *
1626
  */
1627
+ function cerber_post_control(){
1628
  global $cerber_status;
1629
 
1630
  if ( !cerber_is_http_post() || cerber_acl_check( null, 'W' ) ) {
1713
  return true;
1714
  }
1715
 
1716
+ // Cloud Scanner
1717
+ if ( cerber_is_cloud_request() ) {
1718
+ return true;
1719
+ }
1720
+
1721
  // REST API (except Contact Form 7 submission)
1722
  if ( cerber_is_rest_url() ) {
1723
  if ( false === strpos( $_SERVER['REQUEST_URI'], 'contact-form-7' ) ) {
2411
  function cerber_block_add( $ip = '', $reason_id = 1, $details = '', $duration = null ) {
2412
  global $wpdb;
2413
 
2414
+ if ( cerber_is_cloud_request() ) {
2415
+ return false;
2416
+ }
2417
+
2418
  $wp_cerber = get_wp_cerber();
2419
 
2420
  //$wp_cerber->setProcessed();
2479
  //$count = $wpdb->get_var( 'SELECT count(ip) FROM ' . CERBER_BLOCKS_TABLE );
2480
  $count = cerber_blocked_num();
2481
  if ( $count > $wp_cerber->getSettings( 'above' ) ) {
2482
+ cerber_send_email( 'lockout', '', $ip_address );
2483
  }
2484
  }
2485
 
3271
 
3272
  // Notify admin
3273
  if ( $wp_cerber->getSettings( 'cinotify' ) ) {
3274
+ cerber_send_email( 'citadel' );
3275
  }
3276
  }
3277
 
3324
  *
3325
  * @return bool
3326
  */
3327
+ function cerber_send_email( $type = '', $msg = '', $ip = '' ) {
3328
  global $wpdb, $wp_cerber;
3329
  if ( ! $type ) {
3330
  return false;
3363
 
3364
  switch ( $type ) {
3365
  case 'citadel':
3366
+ $max = cerber_db_get_var( 'SELECT MAX(stamp) FROM ' . CERBER_LOG_TABLE . ' WHERE activity = 7' );
3367
  if ($max) {
3368
  $last_date = cerber_date( $max );
3369
  $last = $wpdb->get_row( 'SELECT * FROM ' . CERBER_LOG_TABLE . ' WHERE stamp = ' . $max . ' AND activity = 7' );
3384
  //$body .= __('Change notification settings','wp-cerber').': '.cerber_admin_link();
3385
  break;
3386
  case 'lockout':
3387
+ $max = cerber_db_get_var( 'SELECT MAX(stamp) FROM ' . CERBER_LOG_TABLE . ' WHERE activity IN (10,11)' );
3388
  if ($max){
3389
  $last_date = cerber_date( $max );
3390
+ //$last = $wpdb->get_row( 'SELECT * FROM ' . CERBER_LOG_TABLE . ' WHERE stamp = ' . $max . ' AND activity IN (10,11)' );
3391
+ $last = cerber_db_get_row( 'SELECT * FROM ' . CERBER_LOG_TABLE . ' WHERE stamp = ' . $max . ' AND activity IN (10,11)', 5 );
3392
  }
3393
  else $last = null;
3394
  if ( ! $last ) { // workaround for the empty log table
3397
  $last->user_login = 'test';
3398
  }
3399
 
 
3400
  if ( ! $active = cerber_blocked_num() ) {
3401
  $active = 0;
3402
  }
3403
+
3404
  if ( $last->ip && ( $block = cerber_get_block( $last->ip ) ) ) {
3405
  $reason = $block->reason;
3406
  }
3447
  $body .= __( 'Getting Started Guide', 'wp-cerber' ) . "\n\n";
3448
  $body .= 'https://wpcerber.com/getting-started/' . "\n\n";
3449
  $body .= 'Be in touch with the developer. Subscribe to Cerber\'s newsletter: http://wpcerber.com/subscribe-newsletter/';
 
3450
  break;
3451
  case 'newlurl':
3452
  $subj .= __( 'New Custom login URL', 'wp-cerber' );
3467
  $body .= nl2br($msg);
3468
  }
3469
  break;
3470
+ case 'scan':
3471
+ $html_mode = true;
3472
+ $subj = '[' . get_option( 'blogname' ) . '] WP Cerber Security: ' . __( 'Scanner Report', 'wp-cerber' );
3473
+ $body = $msg;
3474
+ $link = cerber_admin_link( 'scan_schedule' );
3475
+ $body .= '<br/>' . __( 'To change reporting settings visit', 'wp-cerber' ) . ' <a href="' . $link . '">' . $link . '</a>';
3476
+ break;
3477
  }
3478
 
3479
  $to_list = cerber_get_email( $type, true );
3587
  //$in = implode( ',', crb_get_activity_set( 'malicious' ) );
3588
  //$link_base = '<a href="' . cerber_activity_link( array( 2 ) ) . '">';
3589
  $base_url = cerber_admin_link( 'activity' );
3590
+ $css_table = 'width: 95%; max-width: 1000px; margin:0 auto; margin-bottom: 10px; background-color: #f5f5f5; text-align: center; font-family: Arial, Helvetica, sans-serif;';
3591
  $css_td = 'padding: 0.5em 0.5em 0.5em 1em; text-align: left;';
3592
+ $css_border = 'border-bottom: solid 2px #f9f9f9;';
3593
 
3594
+ $site_name = ( is_multisite() ) ? get_site_option( 'site_name' ) : get_option( 'blogname' );
 
 
 
 
 
3595
 
3596
  $ret .= '<div style="' . $css_table . '"><div style="margin:0 auto; text-align: center;"><p style="font-size: 130%; padding-top: 0.5em;">' . $site_name .'</p><p style="padding-bottom: 1em;">'. __('Weekly Report','wp-cerber'). '</p></div></div>';
3597
 
3605
 
3606
  // Activities counters
3607
  $rows = array();
3608
+ $rows[] = '<td style="'.$css_td.$css_border.'" colspan="2"><p style="line-height: 1.5em; font-weight: bold;">'.__('Activity details','wp-cerber').'</p></td>';
3609
  $activites = $wpdb->get_results( 'SELECT activity, COUNT(activity) cnt FROM ' . CERBER_LOG_TABLE . ' WHERE stamp > ' . $stamp . ' GROUP by activity ORDER BY cnt DESC' );
3610
  if ( $activites ) {
3611
  $lables = cerber_get_labels();
3612
  foreach ( $activites as $a ) {
3613
+ $rows[] = '<td style="'.$css_border.$css_td.'">' . $lables[ $a->activity ] . '</td><td style="padding: 0.5em; text-align: center; width:10%;'.$css_border.'"><a href="'.$base_url.'&filter_activity='.$a->activity.'">' . $a->cnt . '</a></td>';
3614
  }
3615
  }
3616
  $ret .= '<table style="border-collapse: collapse; '.$css_table.'"><tr>' . implode( '</tr><tr>', $rows ) . '</tr></table>';
3619
  $activites = $wpdb->get_results( 'SELECT user_login, COUNT(user_login) cnt FROM ' . CERBER_LOG_TABLE . ' WHERE activity = 51 AND stamp > ' . $stamp . ' GROUP by user_login ORDER BY cnt DESC LIMIT 10' );
3620
  if ( $activites ) {
3621
  $rows = array();
3622
+ $rows[] = '<td style="'.$css_td.$css_border.'" colspan="2"><p style="line-height: 1.5em; font-weight: bold;">'.__('Attempts to log in with non-existent username','wp-cerber').'</p></td>';
3623
  foreach ( $activites as $a ) {
3624
+ $rows[] = '<td style="'.$css_border.$css_td.'">' . htmlspecialchars($a->user_login) . '</td><td style="padding: 0.5em; text-align: center; width:10%;'.$css_border.'"><a href="'.$base_url.'&filter_login='.$a->user_login.'">' . $a->cnt . '</a></td>';
3625
  }
3626
  $ret .= '<table style="border-collapse: collapse; '.$css_table.'"><tr>' . implode( '</tr><tr>', $rows ) . '</tr></table>';
3627
  }
3675
  $wpdb->query( 'DELETE FROM ' . CERBER_TRAF_TABLE . ' WHERE stamp < ' . ( $time - $days * 24 * 3600 ) );
3676
  }
3677
 
3678
+ cerber_push_lab();
 
 
3679
 
3680
  $wpdb->query( 'DELETE FROM ' . CERBER_LAB_IP_TABLE . ' WHERE expires < ' . $time );
3681
 
3710
  && date( 'G', time() + $gmt_offset ) == crb_get_settings( 'wreports-time' )
3711
  //&& ! get_site_transient( 'cerber_wreport' )
3712
  ) {
3713
+ $result = cerber_send_email( 'report' );
3714
  //set_site_transient( 'cerber_wreport', 'sent', 7200 );
3715
  update_site_option( '_cerber_report', array( time(), $result ) );
3716
  }
3736
  }
3737
  }
3738
 
3739
+ cerber_cloud_sync();
3740
+
3741
  // Keep folder locked
3742
  cerber_get_the_folder();
3743
 
3773
  }
3774
  if ( ! in_array( $new['ver'], $history ) ) {
3775
  if ( crb_get_settings( 'notify-new-ver' ) ) {
3776
+ cerber_send_email( 'new_version', 'Read more: https://wpcerber.com/?plugin_version=' . $new['ver'] );
3777
  }
3778
  $history[] = $new['ver'];
3779
  update_site_option( '_cerber_notify_new', $history );
3963
  $msg .= __( 'View activity in dashboard', 'wp-cerber' ) . ': ' . $link;
3964
  $msg .= "\n\n" . __( 'To unsubscribe click here', 'wp-cerber' ) . ': ' . cerber_admin_link( 'activity' ) . '&unsubscribeme=' . $hash;
3965
 
3966
+ cerber_send_email( 'subs', $msg, $ip );
3967
 
3968
  break; // Just one notification letter per event
3969
  }
4133
  cerber_stop_activating( '<h3>' . __( "Can't activate WP Cerber due to a database error.", 'wp-cerber' ) . '</h3>'.$e);
4134
  }
4135
 
4136
+ lab_get_key( true );
4137
+
4138
  // Check for existing options
4139
  $opt = cerber_get_options();
4140
  $new = true;
4185
  return;
4186
  }
4187
 
4188
+ cerber_send_email( 'activated' );
4189
 
4190
  $pi = get_file_data( cerber_plugin_file(), array( 'Version' => 'Version' ), 'plugin' );
4191
  $pi ['time'] = time();
4220
  cerber_push_the_news( CERBER_VER );
4221
  update_site_option( '_cerber_up', array( 'v' => CERBER_VER, 't' => time() ) );
4222
  cerber_delete_expired_set( true );
4223
+ lab_get_key( true );
4224
  }
4225
  }
4226
 
4352
  ';
4353
  }
4354
 
4355
+ if ( ! cerber_is_table( cerber_get_db_prefix() . CERBER_SCAN_TABLE ) ) {
4356
  $sql[] = '
4357
+ CREATE TABLE IF NOT EXISTS ' . cerber_get_db_prefix(). CERBER_SCAN_TABLE . ' (
4358
  scan_id INT(10) UNSIGNED NOT NULL,
4359
  scan_type INT(10) UNSIGNED NOT NULL DEFAULT 1,
4360
  scan_mode INT(10) UNSIGNED NOT NULL DEFAULT 0,
4406
  function cerber_upgrade_db( $force = false ) {
4407
  global $wpdb;
4408
  $wpdb->hide_errors();
4409
+ if ( $force ) {
4410
+ $wpdb->suppress_errors();
4411
+ }
4412
  $db_errors = array();
4413
  $sql = array();
4414
 
4451
  $sql[] = 'ALTER TABLE ' . CERBER_LOG_TABLE . ' ADD INDEX session_index (session_id)';
4452
  }
4453
 
4454
+ // @since 7.0.3
4455
+ $sql[] = 'DROP TABLE IF EXISTS ' . CERBER_SCAN_TABLE;
4456
+
4457
+ // @since 7.1
4458
+ if ( $force || ! cerber_is_column( cerber_get_db_prefix() . CERBER_SCAN_TABLE, 'file_status' ) ) {
4459
+ $sql[] = 'ALTER TABLE ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . " ADD file_status INT UNSIGNED NOT NULL DEFAULT '0' AFTER scan_status";
4460
+ }
4461
+
4462
  if (!empty($sql)) {
4463
  foreach ( $sql as $query ) {
4464
  if ( !$wpdb->query( $query ) && $wpdb->last_error ) {
4488
  *
4489
  */
4490
  function cerber_up_data() {
4491
+ $ips = cerber_db_get_col( 'SELECT DISTINCT ip FROM ' . CERBER_LOG_TABLE . ' WHERE ip_long = 0 LIMIT 50' );
 
4492
  if ( ! $ips ) {
4493
  return;
4494
  }
4498
  } else {
4499
  $ip_long = 1;
4500
  }
4501
+ cerber_db_query( 'UPDATE ' . CERBER_LOG_TABLE . ' SET ip_long = ' . $ip_long . ' WHERE ip = "' . $ip .'" AND ip_long = 0');
4502
  }
4503
  }
4504
 
4505
  /**
4506
+ * Upgrade corrupted / outdated rows in ACL
4507
  *
4508
  * @param bool $ipv6 if true Process IPv6 addresses
4509
  *
4510
  */
4511
+ function cerber_acl_fixer( $ipv6 = false ) {
4512
  global $wpdb;
4513
 
4514
  // Repair/update IPs without long values
4515
+ $ips = cerber_db_get_col( 'SELECT ip FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin = 0 OR ip_long_end = 0' );
4516
+ if ( ! $ips ) {
4517
  return;
4518
  }
4519
+ foreach ( $ips as $ip ) {
4520
  if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
4521
  continue;
4522
  }
4530
  $end = ip2long( $ip );
4531
  }
4532
 
4533
+ cerber_db_query( 'UPDATE ' . CERBER_ACL_TABLE . ' SET ip_long_begin = ' . $begin . ', ip_long_end = ' . $end . ' WHERE ip = "' . $ip . '"' );
4534
  }
4535
 
4536
  // Convert old IPv6 to all shortened
4537
  if ( $ipv6 ) {
4538
+ $ips = cerber_db_get_col( 'SELECT ip FROM ' . CERBER_ACL_TABLE . ' WHERE ip_long_begin = 0' );
4539
  if ( $ips ) {
4540
  foreach ( $ips as $ip ) {
4541
  if ( ! filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
4542
  continue;
4543
  }
4544
  $short_ip = cerber_short_ipv6( $ip );
4545
+ if ( $short_ip != $ip ) {
4546
+ cerber_db_query( 'UPDATE ' . CERBER_ACL_TABLE . ' SET ip = "' . $short_ip . '" WHERE ip = "' . $ip . '"' );
4547
  }
4548
  }
4549
  }
4563
  $pi ['v'] = time();
4564
  $pi ['u'] = get_current_user_id();
4565
  update_site_option( '_cerber_o' . 'ff', $pi );
4566
+ $f = 'cerb' . 'er_se' . 'nd_em' . 'ail';
4567
  $f( 'sh' . 'utd' . 'own' );
4568
  }
4569
 
5071
  * @since 6.0
5072
  */
5073
  function cerber_request_time() {
5074
+ static $stamp = null;
5075
 
5076
  if ( ! isset( $stamp ) ) {
5077
+
5078
  if ( ! empty( $_SERVER['REQUEST_TIME_FLOAT'] ) ) { // PHP >= 5.4
 
5079
  $stamp = filter_var( $_SERVER['REQUEST_TIME_FLOAT'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION );
5080
  }
5081
+ $mt = microtime( true );
5082
+ if ( ! $stamp || $stamp > ( $mt + 300 ) ) { // Some platforms may have wrong value in 'REQUEST_TIME_FLOAT'
5083
+ $stamp = $mt;
5084
  }
5085
  }
5086
 
cerber-news.php CHANGED
@@ -147,6 +147,13 @@ function cerber_push_the_news( $version ) {
147
  $news['7.0'][] = 'A new setting has been added for Traffic Inspector: Use White IP Access List. When enabled it allows any requests from IP addresses in the White IP access list to bypass all Traffic Inspector security rules.';
148
  $news['7.0'][] = 'Since v 7.0 the redirection from /wp-admin/ to the login page is not blocked if a not logged in user has been logged in once before.';
149
 
 
 
 
 
 
 
 
150
  if ( ! empty( $news[ $version ] ) ) {
151
  //$text = '<h3>What\'s new in WP Cerber '.$version.'</h3>';
152
 
147
  $news['7.0'][] = 'A new setting has been added for Traffic Inspector: Use White IP Access List. When enabled it allows any requests from IP addresses in the White IP access list to bypass all Traffic Inspector security rules.';
148
  $news['7.0'][] = 'Since v 7.0 the redirection from /wp-admin/ to the login page is not blocked if a not logged in user has been logged in once before.';
149
 
150
+ $news['7.2'][] = 'Monitoring files changes and new files.';
151
+ $news['7.2'][] = 'Monitoring changes, detecting malicious redirections and directives in .htaccess files.';
152
+ $news['7.2'][] = 'A new detector for Base64 encoded strings quickly detects obfuscated malware code and trojans.';
153
+ $news['7.2'][] = 'Automated hourly and daily scheduled scans with flexible email alerts and reports.';
154
+ $news['7.2'][] = 'Bug fixed: Unexpected warning messages in the WordPress dashboard.';
155
+ $news['7.2'][] = 'Bug fixed: Some file status links on the scanner results page may not work.';
156
+
157
  if ( ! empty( $news[ $version ] ) ) {
158
  //$text = '<h3>What\'s new in WP Cerber '.$version.'</h3>';
159
 
cerber-scanner.php CHANGED
@@ -45,10 +45,14 @@ define( 'CERBER_FT_OTHER', 12 );
45
 
46
  define( 'CERBER_MAX_SECONDS', 5 );
47
 
 
 
 
48
  define( 'CERBER_SCF', 16 );
49
  define( 'CERBER_PMC', 17 );
50
  define( 'CERBER_USF', 18 );
51
  define( 'CERBER_EXC', 20 );
 
52
  define( 'CERBER_UXT', 30 );
53
 
54
  define( 'CERBER_MALWR_DETECTED', 1000 );
@@ -57,20 +61,26 @@ define( 'CRB_HASH_THEME', 'hash_tm_' );
57
  define( 'CRB_HASH_PLUGIN', 'hash_pl_' );
58
  define( 'CRB_LAST_FILE', 'tmp_last_file' );
59
 
 
 
 
 
 
60
  function cerber_integrity_page() {
61
 
62
- $tab = cerber_get_tab( 'scanner', array( 'scanner', 'scan_settings', 'help' ) );
63
 
64
  ?>
65
  <div class="wrap crb-admin">
66
 
67
- <h2><?php _e( 'Site Integrity', 'wp-cerber' ) ?></h2>
68
 
69
  <h2 class="nav-tab-wrapper cerber-tabs">
70
  <?php
71
 
72
  echo '<a href="' . cerber_admin_link( 'scanner' ) . '" class="nav-tab ' . ( $tab == 'scanner' ? 'nav-tab-active' : '' ) . '"><span class="dashicons dashicons-visibility"></span> ' . __( 'Security Scanner' ) . '</a>';
73
  echo '<a href="' . cerber_admin_link( 'scan_settings' ) . '" class="nav-tab ' . ( $tab == 'scan_settings' ? 'nav-tab-active' : '' ) . '"><span class="dashicons dashicons-admin-settings"></span> ' . __( 'Settings' ) . '</a>';
 
74
  echo '<a href="' . cerber_admin_link( 'help', array( 'page' => cerber_get_admin_page() ) ) . '" class="nav-tab ' . ( $tab == 'help' ? 'nav-tab-active' : '' ) . '"><span class="dashicons dashicons-editor-help"></span> ' . __( 'Help', 'wp-cerber' ) . '</a>';
75
 
76
  echo lab_indicator();
@@ -87,6 +97,9 @@ function cerber_integrity_page() {
87
  case 'scan_settings':
88
  cerber_show_settings_page( 'scanner' );
89
  break;
 
 
 
90
  case 'help':
91
  cerber_show_help();
92
  break;
@@ -110,12 +123,15 @@ function cerber_show_scanner() {
110
 
111
  if ( $scan = cerber_get_scan() ) {
112
  if ( ! $scan['finished'] ) {
113
- if ( $scan['cloud'] ) {
114
- $msg = 'Currently an automatic scan in progress. Please wait until it is finished.';
 
 
 
115
  $status = 1;
116
  }
117
  else {
118
- $msg = sprintf( 'Previous scan started %s has not been completed. Continue scanning?', cerber_date( $scan['started'] ) );
119
  $status = 2;
120
  }
121
  }
@@ -124,13 +140,13 @@ function cerber_show_scanner() {
124
  }
125
  }
126
  else {
127
- $msg = 'It seems this website has never been scanned. To start scanning click the button below.';
128
  }
129
 
130
  $start_quick = '<input data-control="start_scan" data-mode="quick" type="button" value="' . __( 'Start Quick Scan', 'wp-cerber' ) . '" class="button button-primary">';
131
  $start_full = '<input data-control="start_scan" data-mode="full" type="button" value="' . __( 'Start Full Scan', 'wp-cerber' ) . '" class="button button-primary">';
132
  $stop = '<input id="crb-stop-scan" style="display: none;" data-control="stop_scan" type="button" value="' . __( 'Stop Scanning', 'wp-cerber' ) . '" class="button button-primary">';
133
- $continue = '<input id="crb-continue-scan" data-control="continue_scan" type="button" value="' . __( 'Continues Scanning', 'wp-cerber' ) . '" class="button button-primary">';
134
  $controls = '';
135
 
136
  switch ( $status ) {
@@ -163,7 +179,8 @@ function cerber_show_scanner() {
163
  <td>
164
  <?php echo $controls; ?>
165
  </td>
166
- <td><a href="#" data-control="full-paths">Show full paths</a></td>
 
167
  </tr>
168
  </table>
169
  </form>
@@ -182,24 +199,22 @@ function cerber_manual_scan() {
182
 
183
  ob_start(); // Collecting possible junk warnings and notices cause we need clean JSON to be sent
184
 
185
- $response = array();
186
  $console_log = array();
187
- $do = 'stop';
188
 
189
  if ( cerber_is_http_post() && isset( $_POST['cerber_scan_do'] ) ) {
190
- $do = preg_replace( '/[^a-z_\-\d]/i', '', $_POST['cerber_scan_do'] );
191
  $mode = ( isset( $_POST['cerber_scan_mode'] ) ) ? preg_replace( '/[^a-z_\-\d]/i', '', $_POST['cerber_scan_mode'] ) : 'quick';
192
 
193
- $response = cerber_scanner( $do, $mode );
194
 
195
  }
196
  else {
197
  $console_log[] = 'Unknown HTTP request';
198
  }
199
 
200
- if ( ! empty( $response['cerber_scan_do'] ) ) {
201
- $do = $response['cerber_scan_do'];
202
- }
203
 
204
  if ( $cerber_db_errors ) {
205
  $console_log = array_merge( $console_log, $cerber_db_errors );
@@ -207,18 +222,130 @@ function cerber_manual_scan() {
207
 
208
  $console_log[] = 'PHP MEMORY ' . @ini_get( 'memory_limit' );
209
 
 
 
 
 
 
 
 
 
 
 
 
210
  ob_end_clean();
211
 
212
- echo json_encode( array(
213
- 'console_log' => $console_log,
214
- 'cerber_scan_do' => $do,
215
- 'cerber_scanner' => $response,
216
- //'scan' => cerber_get_scan(), // debug only
217
- ) );
218
 
219
  wp_die();
220
  }
221
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  function cerber_scanner( $control, $mode ) {
223
  global $cerber_db_errors, $cerber_scan_mode;
224
 
@@ -241,7 +368,6 @@ function cerber_scanner( $control, $mode ) {
241
 
242
  switch ( $control ) {
243
  case 'start_scan':
244
- cerber_delete_scan();
245
  cerber_update_set( CRB_LAST_FILE, '', 0, false );
246
  cerber_init_scan( $mode );
247
  cerber_step_scanning();
@@ -255,7 +381,7 @@ function cerber_scanner( $control, $mode ) {
255
  $errors[] = 'No scan in progress';
256
  }
257
  break;
258
- case 'get-last-scan':
259
  if ($scan = cerber_get_scan()) {
260
  $filtered = $scan['issues'];
261
  foreach ( $scan['issues'] as $key => $item ) {
@@ -267,6 +393,8 @@ function cerber_scanner( $control, $mode ) {
267
  }
268
  }
269
  }
 
 
270
  }
271
  }
272
  $response['issues'] = $filtered;
@@ -277,21 +405,25 @@ function cerber_scanner( $control, $mode ) {
277
  if ($scan = cerber_get_scan()) {
278
 
279
  $response['scan_id'] = $scan['id'];
 
 
280
 
281
  if ( $scan['finished'] || $scan['aborted'] ) {
282
  $response['cerber_scan_do'] = 'stop';
 
283
  }
284
  else {
285
  $response['cerber_scan_do'] = 'continue_scan';
286
  }
287
 
288
- $response['aborted'] = $scan['aborted'];
289
- $response['errors'] = array_merge( $errors, $scan['errors'] );
 
 
290
  $response['total'] = $scan['total'];
291
- //$response['memory_usage'] = memory_get_usage();
292
- //$response['memory_limit'] = @ini_get( 'memory_limit' );
293
 
294
- if ( ! lab_is_cloud_request() ) {
295
  $response['step_issues'] = $scan['step_issues'];
296
  $response['scanned'] = $scan['scanned'];
297
 
@@ -328,6 +460,9 @@ function cerber_scanner( $control, $mode ) {
328
 
329
  }
330
  }
 
 
 
331
 
332
  if ( $cerber_db_errors ) {
333
  cerber_watchdog( true );
@@ -337,19 +472,7 @@ function cerber_scanner( $control, $mode ) {
337
  }
338
 
339
  function cerber_show_last_scan_results() {
340
- global $wpdb;
341
-
342
- $rows = $wpdb->get_results( 'SELECT * FROM ' . CERBER_SCAN_TABLE . ' WHERE scan_status = 1 AND hash_match !=1' );
343
- if ( ! $rows ) {
344
- return 0;
345
- }
346
- echo '<h3>Last scan results</h3>';
347
- echo '<pre style="background-color: #fff; text-align: left;">';
348
- foreach ( $rows as $row ) {
349
- $mime = wp_check_filetype( $row->file_name );
350
- echo $row->file_name . ' ' . $mime['mode'] . ' ' . $row->file_hash_repo . "\n";
351
- }
352
- echo '</pre>';
353
  }
354
 
355
  function cerber_step_scanning() {
@@ -359,30 +482,31 @@ function cerber_step_scanning() {
359
 
360
  cerber_exec_timer();
361
 
362
- cerber_update_scan( array( 'step_issues' => array() ) );
363
-
364
  if ( ! $scan = cerber_get_scan() ) {
365
  return false;
366
  }
367
 
368
- if ( $scan['finished'] ) {
369
  return true;
370
  }
371
 
372
- $update = array();
373
- $update['next_step'] = $scan['next_step'];
374
- $update['aborted'] = 0;
375
 
 
 
 
376
 
377
  switch ( $scan['next_step'] ) {
378
  case 1:
379
  if ( !$result = cerber_scan_directory( ABSPATH, null, '_crb_save_file_names' ) ) {
380
- $update['aborted'] = 1;
381
  break;
382
  }
383
  else {
384
  $update['total']['folders'] = $result[0];
385
- _crb_save_file_names( array( dirname( ABSPATH ) . DIRECTORY_SEPARATOR . 'wp-config.php' ) );
 
 
386
 
387
  if ( crb_get_settings( 'scan_tmp' ) ) {
388
  $tmp_dir = @ini_get( 'upload_tmp_dir' );
@@ -401,19 +525,19 @@ function cerber_step_scanning() {
401
  }
402
  }
403
 
404
- $update['total']['files'] = cerber_db_get_var( 'SELECT COUNT(scan_id) FROM ' . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan['id'] );
405
- $update['next_step'] ++;
406
  }
407
  break;
408
  case 2:
409
  //$start = time();
410
  $x = 0;
411
  $exceed = false;
412
- if ( $result = cerber_db_get_results( 'SELECT * FROM ' . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan['id'] . ' AND file_hash = ""' ) ) {
413
  foreach ( $result as $row ) {
414
- if ( ! cerber_update_file_info( $row ) ) {
415
  cerber_log_scan_error( 'Unable to update file info. Scanning has been aborted.' );
416
- $update['aborted'] = 1;
417
  break;
418
  }
419
  if ( 0 === ($x % 100) ) {
@@ -426,50 +550,61 @@ function cerber_step_scanning() {
426
  $x++;
427
  }
428
  // Some files might be symlinks
429
- $update['total']['files'] = cerber_db_get_var( 'SELECT COUNT(scan_id) FROM ' . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan['id'] );
430
- $update['total']['parsed'] = cerber_db_get_var( 'SELECT COUNT(scan_id) FROM ' . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan['id'] . ' AND file_type !=0' );
431
  }
432
  else {
433
- $update['aborted'] = 1;
434
  }
435
- if ( ! $exceed && ! $update['aborted'] ) {
436
- $update['next_step'] ++;
437
  }
438
  break;
439
  case 3:
440
- cerber_verify_wp();
441
- $update['next_step'] ++;
442
- break;
 
 
443
  case 4:
 
 
 
 
444
  $remain = cerber_verify_plugins();
445
  if ( ! $remain ) {
446
- $update['next_step'] ++;
447
  }
448
  break;
449
- case 5:
450
  $remain = cerber_verify_themes();
451
  if ( ! $remain ) {
452
- $update['next_step'] ++;
453
  }
454
  break;
455
- case 6:
456
  $remain = cerber_process_files();
457
  if ( ! $remain ) {
458
- $update['next_step'] ++;
459
  }
460
  break;
 
 
 
461
  }
462
 
463
- if ( $update['next_step'] > 6 ) {
464
  $update['finished'] = time();
 
465
  }
466
 
467
- if ( $update['aborted'] ) {
468
  $update['aborted'] = time();
469
  }
470
 
471
- $update['scanned']['files'] = cerber_db_get_var( 'SELECT COUNT(scan_id) FROM ' . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan['id'] . ' AND scan_status > 0' );
472
- $update['scanned']['bytes'] = cerber_db_get_var( 'SELECT SUM(file_size) FROM ' . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan['id'] . ' AND scan_status > 0' );
 
473
 
474
  if ( ! $scan = cerber_get_scan() ) {
475
  return false;
@@ -477,7 +612,34 @@ function cerber_step_scanning() {
477
 
478
  $update['issues'] = cerber_merge_issues( $scan['issues'], $scan['step_issues'] );
479
 
480
- return cerber_update_scan( $update );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
 
482
  }
483
 
@@ -489,27 +651,29 @@ function cerber_step_scanning() {
489
  * @return array|bool
490
  */
491
  function cerber_init_scan( $mode = 'quick' ) {
492
- cerber_delete_scan();
493
 
494
  if ( ! $mode ) {
495
  $mode = 'quick';
496
  }
497
 
498
- $data = array();
499
- $data['mode'] = $mode; // Quick | Full
500
- $data['id'] = time();
501
- $data['started'] = $data['id'];
502
- $data['finished'] = 0;
503
- $data['aborted'] = 0; // If > 0, the scan has been aborted due to unrecoverable errors
504
- $data['errors'] = array(); // Any software, DB, CURL, I/O and other system errors - for diagnostic/debugging
505
- $data['scanned'] = array();
506
- $data['issues'] = array(); // The list of issues found during the scanning (for end user)
507
- $data['total'] = array(); // Counters
508
- $data['total']['issues'] = 0;
509
- $data['integrity'] = array();
510
- $data['ip'] = cerber_get_remote_ip();
511
- $data['cloud'] = lab_is_cloud_request();
512
- $data['step'] = array();
 
 
513
  $data['next_step'] = 1;
514
 
515
  if ( ! cerber_update_set( 'scan', $data, $data['id'] ) ) {
@@ -527,12 +691,13 @@ function cerber_init_scan( $mode = 'quick' ) {
527
  */
528
  function cerber_get_scan_id() {
529
 
530
- $scan = cerber_get_scan();
531
 
532
- if ( $scan ) {
533
- $scan_id = absint( $scan['id'] );
534
  }
535
- else {
 
536
  $scan_id = false;
537
  }
538
 
@@ -547,21 +712,122 @@ function cerber_get_scan_id() {
547
  * @return array|bool
548
  */
549
  function cerber_get_scan( $scan_id = null ) {
550
- global $wpdb;
551
 
552
  // If no ID is specified look for the latest one
553
- if ( $scan_id === null && $all = $wpdb->get_col( 'SELECT the_id FROM ' . cerber_get_db_prefix() . CERBER_SETS_TABLE . ' WHERE the_key = "scan"' ) ) {
554
- $scan_id = max( $all );
555
  }
556
 
557
  if ( ! $scan_id ) {
558
  return false;
559
  }
560
 
561
- return cerber_get_set( 'scan', $scan_id );
 
 
 
562
 
563
  }
564
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
565
  /**
566
  * Save issues (for end user reporting) during the scanning
567
  *
@@ -585,6 +851,7 @@ function cerber_push_issues( $section, $issues = array(), $container = '' ) {
585
  foreach ( $issues as $issue ) {
586
 
587
  $data = array();
 
588
 
589
  if ( isset( $issue['file'] ) ) {
590
 
@@ -596,6 +863,13 @@ function cerber_push_issues( $section, $issues = array(), $container = '' ) {
596
  $data['name'] = $file['file_name'];
597
  $data['type'] = $file['file_type'];
598
 
 
 
 
 
 
 
 
599
  // Is file can be deleted safely
600
 
601
  $allowed = 0;
@@ -631,6 +905,7 @@ function cerber_push_issues( $section, $issues = array(), $container = '' ) {
631
  $issue_type, // Type of issue
632
  $short_name, // Object name
633
  cerber_calculate_risk( $issue ),
 
634
  'data' => $data,
635
  'details' => $details,
636
  );
@@ -718,6 +993,31 @@ function cerber_push_issues( $section, $issues = array(), $container = '' ) {
718
  return $ret;
719
  }
720
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
721
  /**
722
  * Indicator for end-user
723
  *
@@ -726,7 +1026,7 @@ function cerber_push_issues( $section, $issues = array(), $container = '' ) {
726
  * @return int|mixed
727
  */
728
  function cerber_calculate_risk( $issue ) {
729
- $risk = array( 1 => 0, 10 => 1, 11 => 2, 5 => 3, 6 => 3, 7 => 3, 8 => 3);
730
 
731
  if ( isset( $risk[ $issue[0] ] ) ) {
732
  return $risk[ $issue[0] ];
@@ -762,7 +1062,7 @@ function cerber_calculate_risk( $issue ) {
762
  }
763
  return 2;
764
  break;
765
- case 15:
766
  case CERBER_USF:
767
  case CERBER_SCF:
768
  case CERBER_PMC:
@@ -781,7 +1081,7 @@ function cerber_calculate_risk( $issue ) {
781
  return 1;
782
  }
783
 
784
- function cerber_get_risk_desc() {
785
  return array(
786
  '',
787
  'Low',
@@ -790,117 +1090,66 @@ function cerber_get_risk_desc() {
790
  );
791
  }
792
 
793
- function cerber_get_issue_desc( $id = null ) {
794
  $issues = array(
795
  0 => 'To be scanned',
796
- 1 => __( 'Verified' ),
 
 
 
 
 
797
  5 => __( 'Integrity data not found', 'wp-cerber' ),
798
  6 => __( 'Unable to check the integrity of the plugin due to a network error', 'wp-cerber' ),
799
  7 => __( 'Unable to check the integrity of WordPress files due to a network error', 'wp-cerber' ),
800
  8 => __( 'Unable to check the integrity of the theme due to a network error', 'wp-cerber' ),
801
 
802
- 10 => __( "Local file doesn't exist", 'wp-cerber' ),
803
- 11 => 'No local hash found',
804
- 13 => __( 'Unable to process file', 'wp-cerber' ),
805
- 14 => __( 'Unable to open file', 'wp-cerber' ),
806
- 15 => __( 'Content has been modified', 'wp-cerber' ),
807
 
808
- CERBER_SCF => __( 'Suspicious code found', 'wp-cerber' ),
 
 
 
809
  CERBER_PMC => __( 'Potentially malicious code found', 'wp-cerber' ),
810
  CERBER_USF => __( 'Unattended suspicious file', 'wp-cerber' ),
811
  CERBER_EXC => __( 'Executable code found', 'wp-cerber' ),
812
 
813
- CERBER_UXT => __( 'Unwanted extension', 'wp-cerber' ),
 
 
 
 
 
814
  );
815
 
816
  if ( $id !== null ) {
817
- return $issues[ $id ];
818
- }
819
-
820
- return $issues;
821
- }
822
 
823
-
824
- /**
825
- * Merge two lists of issues in a correct way
826
- *
827
- * @param $issues1
828
- * @param $issues2
829
- *
830
- * @return array
831
- */
832
- function cerber_merge_issues( $issues1, $issues2 ) {
833
- if ( ! $issues1 ) {
834
- $issues1 = array();
835
- }
836
- foreach ( $issues2 as $id => $item ) {
837
- if ( ! isset( $issues1[ $id ] ) ) {
838
- //$issues1[ $id ] = array( 'name' => $item['name'], 'issues' => $item['issues'] );
839
- $issues1[ $id ] = $item;
840
  }
841
- else {
842
- $issues1[ $id ]['issues'] = array_merge( $issues1[ $id ]['issues'], $item['issues'] );
843
- }
844
- }
845
-
846
- return $issues1;
847
- }
848
-
849
- /**
850
- * Update scan data by simply merging values in array
851
- *
852
- * @param array $new_data
853
- *
854
- * @return bool
855
- */
856
- function cerber_update_scan( $new_data ) {
857
- if ( ! $old_data = cerber_get_scan() ) {
858
- return false;
859
- }
860
-
861
- if ( isset( $new_data['id'] ) ) {
862
- unset( $new_data['id'] );
863
- }
864
- $data = array_merge( $old_data, $new_data );
865
 
866
- return cerber_update_set( 'scan', $data, $old_data['id'] );
867
- }
868
-
869
- /**
870
- * Update scan data and preserve existing keys in array (scan structure)
871
- *
872
- * @param array $new_data
873
- *
874
- * @return bool
875
- */
876
- function cerber_set_scan( $new_data ) {
877
- if ( ! $scan_data = cerber_get_scan() ) {
878
- return false;
879
  }
880
 
881
- $data = cerber_array_merge_recurively( $scan_data, $new_data );
882
-
883
- return cerber_update_scan( $data );
884
  }
885
 
886
- /**
887
- * Delete scan results from DB
888
- *
889
- * @return bool
890
- */
891
- function cerber_delete_scan( $scan_id = null ) {
892
- if ( ! $scan_id ) {
893
- $scan_id = cerber_get_scan_id(); // Last scan
894
- }
895
- if ( $scan_id && cerber_delete_set( 'scan', $scan_id ) ) {
896
- //cerber_db_query( 'DELETE FROM ' . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan_id );
897
- cerber_db_query( 'DELETE FROM ' . CERBER_SCAN_TABLE );
898
- cerber_delete_set( 'tmp_verify_plugins', $scan_id );
899
 
900
- return true;
 
 
 
 
 
 
 
 
901
  }
902
 
903
- return false;
904
  }
905
 
906
  /**
@@ -946,7 +1195,6 @@ function cerber_verify_plugins() {
946
  return 0;
947
  }
948
 
949
- //$plugins_dir = mb_substr( cerber_get_plugins_dir(), mb_strlen( ABSPATH ) ) . DIRECTORY_SEPARATOR;
950
  $plugins_dir = cerber_get_plugins_dir() . DIRECTORY_SEPARATOR;
951
  $file_count = 0;
952
  $bytes = 0;
@@ -987,10 +1235,10 @@ function cerber_verify_plugins() {
987
  continue;
988
  }
989
 
990
- $file_name = $plugins_dir . $plugin_folder . DIRECTORY_SEPARATOR . $file;
991
  $file_name_hash = sha1( $file_name );
992
  $where = 'scan_id = ' . $scan_id . ' AND file_name_hash = "' . $file_name_hash . '"';
993
- $local_file = cerber_db_get_row( 'SELECT * FROM ' . CERBER_SCAN_TABLE . ' WHERE ' . $where );
994
 
995
  if ( ! $local_file ) {
996
  $issues[] = array( 10, DIRECTORY_SEPARATOR . $plugin_folder . DIRECTORY_SEPARATOR . $file );
@@ -1027,20 +1275,19 @@ function cerber_verify_plugins() {
1027
  $file_hash_repo = 'SHA256 hash not found';
1028
  }
1029
 
1030
- if ( $hash_match ) {
1031
- $status = 1;
1032
- }
1033
- else {
1034
- $status = 15;
1035
  $issues[] = array( $status, $short_name, 'file' => $local_file );
1036
  }
1037
 
1038
- cerber_db_query( 'UPDATE ' . CERBER_SCAN_TABLE . ' SET file_hash_repo = "' . $file_hash_repo . '", hash_match = ' . $hash_match . ', scan_status = ' . $status . ' WHERE ' . $where );
1039
 
1040
  $file_count ++;
1041
  $bytes += absint( $local_file['file_size'] );
1042
 
1043
  }
 
1044
  $verified = 1;
1045
  }
1046
  else {
@@ -1055,6 +1302,7 @@ function cerber_verify_plugins() {
1055
  $verified = 1;
1056
  $status = 1;
1057
  }
 
1058
  $issues[] = array( $status, '', 'plugin' => $plugins[ $plugin ] );
1059
 
1060
  if ( $issues ) {
@@ -1167,7 +1415,7 @@ function cerber_verify_wp() {
1167
  }
1168
 
1169
  // In case the default name 'wp-content' of the CONTENT folder has been changed
1170
- //$wp_content_dir = mb_substr( dirname( cerber_get_plugins_dir() ), mb_strlen( ABSPATH ) );
1171
  $wp_content_dir = basename( dirname( cerber_get_plugins_dir() ) );
1172
  if ( $wp_content_dir != 'wp-content' ) {
1173
  $new_data = array();
@@ -1202,14 +1450,14 @@ function _crb_not_existing( $file_name ) {
1202
  static $themes_prefix, $plugins_prefix;
1203
 
1204
  if ( $themes_prefix == null ) {
1205
- $themes_prefix = basename( dirname( cerber_get_plugins_dir() ) ) . '/themes/';
1206
  }
1207
  if ( 0 === strpos( $file_name, $themes_prefix ) ) {
1208
  return false;
1209
  }
1210
 
1211
  if ( $plugins_prefix == null ) {
1212
- $plugins_prefix = basename( dirname( cerber_get_plugins_dir() ) ) . '/' . basename( cerber_get_plugins_dir() ) . '/';
1213
  }
1214
  if ( 0 === strpos( $file_name, $plugins_prefix ) ) {
1215
  return false;
@@ -1262,17 +1510,24 @@ function cerber_verify_themes() {
1262
  }
1263
 
1264
  /**
1265
- * Inspecting unattended files (remained after integrity checking) for traces of malware
1266
  *
1267
  * @return int
1268
  */
1269
- function cerber_process_files() {
1270
 
1271
  if ( ! $scan = cerber_get_scan() ) {
1272
  return 0;
1273
  }
1274
 
1275
- // -------- Plugins data
 
 
 
 
 
 
 
1276
 
1277
  $plugins = array();
1278
  foreach ( get_plugins() as $key => $item ) {
@@ -1291,7 +1546,7 @@ function cerber_process_files() {
1291
 
1292
  // ---------------------------------------------------------------------------
1293
 
1294
- // -------- Themes data
1295
 
1296
  $themes = wp_get_themes();
1297
 
@@ -1304,203 +1559,212 @@ function cerber_process_files() {
1304
 
1305
  // Prevent hanging
1306
  if ( $f = cerber_get_set( CRB_LAST_FILE, 0, false ) ) {
1307
- cerber_db_query( 'UPDATE ' . CERBER_SCAN_TABLE . ' SET scan_status = 13 WHERE scan_id = ' . $scan['id'] . ' AND file_name_hash = "' . sha1( $f ) . '"' );
 
1308
  cerber_update_set( CRB_LAST_FILE, '', 0, false );
1309
- $m = cerber_get_issue_desc( 13 ) . ' ' . $f . ' size: ' . @filesize( $f ) . ' bytes';
1310
  cerber_log_scan_error( $m );
1311
  }
1312
 
1313
- if ( $files = cerber_db_get_results( 'SELECT * FROM ' . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan['id'] . ' AND scan_status NOT IN (1,14,15)' ) ) {
1314
-
1315
- if ( $unwanted = crb_get_settings( 'scan_uext' ) ) {
1316
- $unwanted = array_map( function ( $ext ) {
1317
- return strtolower( trim( $ext, '. ' ) );
1318
- }, $unwanted );
1319
- }
1320
 
1321
- $x = 0;
1322
 
1323
- foreach ( $files as $file ) {
1324
 
1325
- if ( cerber_is_htaccess( $file['file_name'] ) ) { // || $file['file_size'] == 0
1326
- cerber_db_query( 'UPDATE ' . CERBER_SCAN_TABLE . ' SET scan_status = 1 WHERE scan_id = ' . $scan['id'] . ' AND file_name_hash = "' . $file['file_name_hash'] . '"' );
1327
- continue;
1328
- }
1329
-
1330
- $integrity_verified = false;
1331
- $severity_limit = 6;
1332
- $status = CERBER_USF;
1333
- $section = '';
1334
- $do_not_del = false;
1335
-
1336
- switch ( $file['file_type'] ) {
1337
- case CERBER_FT_WP:
1338
- $section = 'WordPress';
 
 
 
 
 
 
 
 
 
 
1339
  $do_not_del = true;
1340
- if ( ! empty( $scan['integrity']['wordpress'] ) ) {
1341
  $integrity_verified = true;
1342
  }
1343
- break;
1344
- case CERBER_FT_PLUGIN:
1345
- $f = cerber_get_file_folder( $file['file_name'], cerber_get_plugins_dir() );
1346
- if ( isset( $plugins[ $f ] ) ) {
1347
- $section = $plugins[ $f ]['Name'];
1348
- $do_not_del = true;
1349
- if ( ! empty( $plugins[ $f ]['integrity'] ) ) {
1350
- $integrity_verified = true;
1351
- }
1352
- }
1353
- else {
1354
- $severity_limit = 1;
1355
- }
1356
- break;
1357
- case CERBER_FT_THEME:
1358
- $f = cerber_get_file_folder( $file['file_name'], cerber_get_themes_dir() );
1359
- if ( isset( $themes[ $f ] ) ) {
1360
- $section = $themes[ $f ]->get( 'Name' ); // WP_Theme object
1361
- $do_not_del = true;
1362
- if ( ! empty( $scan['integrity']['themes'][ $f ] ) ) {
1363
- $integrity_verified = true;
1364
- }
1365
- $severity_limit = 5;
1366
- }
1367
- else {
1368
- $severity_limit = 1;
1369
- }
1370
- //$status = 1;
1371
- break;
1372
- case CERBER_FT_ROOT:
1373
- if ( cerber_is_htaccess( $file['file_name']) ) {
1374
- $section = 'WordPress';
1375
- }
1376
- if ( ! empty( $scan['integrity']['wordpress'] ) ) {
1377
- $integrity_verified = true;
1378
- }
1379
- $do_not_del = true;
1380
- $severity_limit = 1;
1381
- break;
1382
- case CERBER_FT_CONF:
1383
- $section = 'WordPress';
1384
- $do_not_del = true;
1385
- $severity_limit = 2;
1386
- break;
1387
- case CERBER_FT_UPLOAD:
1388
- $section = 'Uploads folder';
1389
  $severity_limit = 1;
1390
- break;
1391
- case CERBER_FT_MUP:
1392
- $section = 'Must-use plugins';
 
 
 
1393
  $do_not_del = true;
1394
- break;
1395
- case CERBER_FT_OTHER:
 
 
 
 
1396
  $severity_limit = 1;
1397
- break;
1398
- case CERBER_FT_DRIN:
1399
- $section = 'Drop-ins';
1400
- break;
1401
- default:
1402
- $severity_limit = 2;
1403
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1404
 
1405
- }
1406
 
1407
- // Now we're ready to perform inspection
1408
 
1409
- if ( ! $integrity_verified ) {
1410
 
1411
- $result = cerber_inspect_file( $file['file_name'] );
1412
 
1413
- if ( ! is_wp_error( $result ) ) {
1414
- $status = 1;
1415
- if ( $result['severity'] == CERBER_MALWR_DETECTED ) {
1416
- $status = CERBER_PMC;
 
 
 
 
 
 
 
 
 
1417
  }
1418
- /*
1419
- elseif ( $result['severity'] == $severity_limit ) {
1420
- $status = CERBER_USF;
1421
- }*/
1422
- elseif ( $result['severity'] >= $severity_limit ) {
1423
- if ( $result['severity'] == 1 ) {
1424
- $status = CERBER_EXC;
1425
  }
1426
  else {
1427
  $status = CERBER_SCF;
1428
  }
1429
  }
1430
  }
1431
- else {
1432
- $status = 14;
1433
- }
1434
-
1435
  }
1436
  else {
1437
- $result = array();
1438
- }
1439
-
1440
- // An exception for wp-config.php
1441
- if ( $status == CERBER_USF && $file['file_type'] == CERBER_FT_CONF ) {
1442
- $status = 1;
1443
  }
1444
 
1445
- // Unwanted extensions
1446
- if ( $status == 1 && $unwanted ) {
1447
- $f = strtolower( basename( $file['file_name'] ) );
1448
- $e = explode( '.', $f );
1449
- array_shift( $e );
1450
- if ( $e && array_intersect( $unwanted, $e ) ) {
1451
- $status = CERBER_UXT;
1452
- }
 
 
 
 
 
 
 
 
 
1453
  }
 
1454
 
1455
- // There is an issue with file
1456
- if ( $status > 1 ) {
 
1457
 
1458
- if ( ! $section ) {
1459
- $section = 'Unattended files';
1460
 
1461
- $len = 0;
1462
- if ( 0 === strpos( $file['file_name'], rtrim( ABSPATH, '/\\' ) ) ) {
1463
- $len = mb_strlen( ABSPATH ) - 1;
1464
- }
1465
- if ( $len ) {
1466
- $short_name = mb_substr( $file['file_name'], $len );
1467
- }
1468
- else {
1469
- $short_name = $file['file_name'];
1470
- }
1471
  }
1472
  else {
1473
- $short_name = cerber_get_short_name( $file );
1474
  }
 
 
 
 
1475
 
1476
- // Is file can be deleted?
1477
 
1478
- if ( $status >= CERBER_SCF ) {
1479
- if ( $integrity_verified ) {
1480
- $file['fd_allowed'] = 1;
1481
- }
1482
- elseif ( ! $do_not_del || in_array( $file['file_type'], $can_be_deleted ) ) {
1483
- $file['fd_allowed'] = 1;
1484
- }
1485
  }
1486
-
1487
- //$short_name = cerber_get_short_name( $file );
1488
- $issues[ $section ][] = array( $status, $short_name, $result, 'file' => $file );
1489
-
1490
  }
1491
 
1492
- cerber_db_query( 'UPDATE ' . CERBER_SCAN_TABLE . ' SET scan_status = ' . $status . ' WHERE scan_id = ' . $scan['id'] . ' AND file_name_hash = "' . $file['file_name_hash'] . '"' );
 
 
 
 
1493
 
1494
- if ( 0 === ($x % 100) ) {
1495
- if ( cerber_exec_timer() ) {
1496
- $remain = 1;
1497
- break;
1498
- }
1499
  }
1500
- $x++;
1501
  }
 
1502
  }
1503
 
 
1504
  if ( $issues ) {
1505
  foreach ( $issues as $section => $list ) {
1506
  cerber_push_issues( $section, $list );
@@ -1524,6 +1788,10 @@ function cerber_inspect_file( $file_name = '' ) {
1524
  return false;
1525
  }
1526
 
 
 
 
 
1527
  if ( ! cerber_check_extension( $file_name, array( 'php', 'inc', 'phtm', 'phtml', 'phps', 'php2', 'php3', 'php4', 'php5', 'php6', 'php7' ) ) ) {
1528
  $php = false;
1529
 
@@ -1552,8 +1820,11 @@ function cerber_inspect_file( $file_name = '' ) {
1552
 
1553
  if ( is_wp_error( $result ) ) {
1554
  cerber_log_scan_error( $result->get_error_message() );
 
1555
  }
1556
 
 
 
1557
  return $result;
1558
  }
1559
 
@@ -1565,7 +1836,9 @@ function cerber_inspect_file( $file_name = '' ) {
1565
  * @return array|bool|WP_Error
1566
  */
1567
  function cerber_inspect_php( $file_name = '' ) {
1568
- if ( ! $content = @file_get_contents( $file_name ) ) {
 
 
1569
  return new WP_Error( 'cerber-file', cerber_scan_msg( 0, $file_name ) );
1570
  }
1571
 
@@ -1582,7 +1855,7 @@ function cerber_inspect_php( $file_name = '' ) {
1582
  $xdata = array();
1583
  $pos = array();
1584
  $open = null;
1585
- $list = cerber_get_unsafe();
1586
 
1587
  foreach ( $tokens as $token ) {
1588
  if ( ! is_array( $token ) ) {
@@ -1595,6 +1868,12 @@ function cerber_inspect_php( $file_name = '' ) {
1595
  $severity[] = $list[ $token[1] ][0];
1596
  }
1597
  }
 
 
 
 
 
 
1598
  if ( $token[0] == T_OPEN_TAG ) {
1599
  $open = $token[2] - 1;
1600
  }
@@ -1638,7 +1917,11 @@ function cerber_inspect_php( $file_name = '' ) {
1638
 
1639
  // Check for malicious code patterns
1640
 
1641
- foreach ( cerber_get_patterns() as $pa ) {
 
 
 
 
1642
  if ($pa[1] == 2) { // 2 = REGEX
1643
  $matches = array();
1644
  if ( preg_match_all( '/' . $pa[2] . '/i', $code, $matches, PREG_OFFSET_CAPTURE ) ) {
@@ -1721,13 +2004,63 @@ function cerber_inspect_php( $file_name = '' ) {
1721
 
1722
  }
1723
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1724
  /**
1725
  * Unsafe code tokens
1726
  *
1727
  * @return array
1728
  */
1729
- function cerber_get_unsafe(){
1730
  return array(
 
 
1731
  'system' => array( 10, 'May be used to get/change vital system information or to run arbitrary server software.' ),
1732
  'shell_exec' => array(10, 'Executes arbitrary command via shell and returns the complete output as a string.'),
1733
  'exec' => array(10, 'Executes arbitrary programs on the web server.'),
@@ -1741,6 +2074,7 @@ function cerber_get_unsafe(){
1741
  'str_rot13' => array(9, 'Perform the rot13 transform on a string. May be used to obfuscate malware.'),
1742
  'base64_decode' => array(7, 'May be used to obfuscate and hinder detection of malicious code. Pairing with eval function indicates malicious code.'),
1743
  'socket_create' => array(6, 'Creates a network connection with any remote host. May be used to load malicious code from any web server with no restrictions.'),
 
1744
 
1745
  'hexdec' => array(5, 'Hexadecimal to decimal. May be used to obfuscate malware.'),
1746
  'dechex' => array(5, 'Decimal to hexadecimal. May be used to obfuscate malware.'),
@@ -1763,7 +2097,6 @@ function cerber_get_unsafe(){
1763
  'wp_safe_remote_post' => array(3, 'Upload or download data from/to any web server. May be used to load malicious code from an external source.'),
1764
  'wp_remote_head' => array(3, 'Load data from any web server. May be used to load malicious code from an external source.'),
1765
 
1766
- 'create_function' => array(2, 'Create an anonymous (lambda-style) function. Deprecated. A native anonymous function must be used instead.'),
1767
  'call_user_func' => array(2, 'Call any function given by the first parameter. May be used to run malicious code or hinder code inspection.'),
1768
  'call_user_func_array' => array(2, 'Call any function with an array of parameters. May be used to run malicious code or hinder code inspection.'),
1769
  );
@@ -1774,11 +2107,11 @@ function cerber_get_unsafe(){
1774
  *
1775
  * @return array
1776
  */
1777
- function cerber_get_patterns() {
1778
  $list = array(
1779
  array( 'VARF', 2, '\$[a-z0-9\_]+?\((?!\))', 11, 'A variable function call. Usually is used to hinder malware detection.' ), // pattern with function parameter(s): $example(something)
1780
- array( 'IPV4', 2, '(?:[0-9]{1,3}\.){3}[0-9]{1,3}', 6, 'An external IPv4 address. Can cause data leakage.', 'func' => '_is_ip_external' ),
1781
- array( 'IPV6', 2, '(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}', 6, 'An external IPv6 address. Can cause data leakage.', 'func' => '_is_ip_external' ),
1782
  array( 'BCTK', 2, '`[a-z]+`', 10, 'Execute arbitrary command on the web server' ),
1783
  array( 'PIDT', 3, 'php://input', 6, 'Get data or commands from the Internet. Should be used in trusted or verified software only' ),
1784
  array( 'NGET', 3, '$_GET', 3, 'Get data or commands from the Internet. Should be used in trusted or verified software only' ),
@@ -1801,7 +2134,135 @@ function cerber_get_patterns() {
1801
  }
1802
  }
1803
 
1804
- return $list;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1805
  }
1806
 
1807
  function _is_ip_external( $ip ) {
@@ -1815,23 +2276,37 @@ function _is_ip_external( $ip ) {
1815
  return true;
1816
  }
1817
 
1818
- add_action( 'wp_ajax_cerber_get_strings', function () {
1819
- cerber_check_ajax();
1820
- $data = array();
1821
- $data[1] = cerber_get_unsafe();
1822
- $list = array();
1823
- foreach ( cerber_get_patterns() as $p ) {
 
1824
  $list[ $p[0] ] = $p[4];
1825
  }
1826
  $data[2] = $list;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1827
  $data['complete'] = 1;
1828
- echo json_encode( $data );
1829
 
1830
- wp_die();
1831
- } );
1832
 
1833
  /**
1834
- * Verify a set of file using hash data provided as array of $file_name => $hash
1835
  *
1836
  * @param array $hash_data Hash
1837
  * @param string $field Name of DB table field with local hash
@@ -1843,7 +2318,7 @@ add_action( 'wp_ajax_cerber_get_strings', function () {
1843
  */
1844
  function cerber_verify_files( $hash_data, $field = 'file_hash', $local_prefix = '', $type_not_in = array(), $set_type = null, $func = null ) {
1845
  if ( ! $scan = cerber_get_scan() ) {
1846
- return 0;
1847
  }
1848
 
1849
  $set_type = absint( $set_type );
@@ -1854,21 +2329,22 @@ function cerber_verify_files( $hash_data, $field = 'file_hash', $local_prefix =
1854
  $func = null;
1855
  }
1856
 
 
 
 
 
1857
  foreach ( $hash_data as $file_name => $hash ) {
1858
 
1859
  if ( ! cerber_is_file_type_scan( $file_name ) ) {
1860
  continue;
1861
  }
1862
 
 
 
1863
  $file_name_hash = sha1( $local_prefix . $file_name );
1864
  $where = 'scan_id = ' . $scan['id'] . ' AND file_name_hash = "' . $file_name_hash . '"';
1865
- /*
1866
- if ($type_not_in){
1867
- $type_not_in = array_filter( array_map( 'absint', $type_not_in ) );
1868
- $where .= ' AND file_type NOT IN (' . implode( ',', $type_not_in ) . ')';
1869
- }*/
1870
 
1871
- $local_file = cerber_db_get_row( 'SELECT * FROM ' . CERBER_SCAN_TABLE . ' WHERE ' . $where );
1872
 
1873
  if ( ! $local_file ) {
1874
  if ( $func ) {
@@ -1876,7 +2352,7 @@ function cerber_verify_files( $hash_data, $field = 'file_hash', $local_prefix =
1876
  continue;
1877
  }
1878
  }
1879
- $issues[] = array( 10, '/' . ltrim( $file_name, '/' ) );
1880
  continue;
1881
  }
1882
 
@@ -1890,19 +2366,18 @@ function cerber_verify_files( $hash_data, $field = 'file_hash', $local_prefix =
1890
  $issues[] = array( 11, $short_name, 'file' => $local_file );
1891
  continue;
1892
  }
 
1893
  $hash_match = ( $local_file[ $field ] === $hash ) ? 1 : 0;
1894
 
1895
- if ( $hash_match ) {
1896
- $status = 1;
1897
- }
1898
- else {
1899
- $status = 15;
1900
  $issues[] = array( $status, $short_name, 'file' => $local_file );
1901
  }
1902
 
1903
  $file_type = ( ! empty( $set_type ) ) ? $set_type : $local_file['file_type'];
1904
 
1905
- cerber_db_query( 'UPDATE ' . CERBER_SCAN_TABLE . ' SET file_type = ' . $file_type . ', file_hash_repo = "' . $hash . '", hash_match = ' . $hash_match . ', scan_status = ' . $status . ' WHERE ' . $where );
1906
 
1907
  $file_count ++;
1908
 
@@ -2153,14 +2628,18 @@ function cerber_obtain_hash( $url, $nocache = false ) {
2153
  }
2154
 
2155
  function cerber_detect_file( $file_name ) {
 
2156
  static $upload_dir = null;
2157
  static $plugin_dir = null;
2158
  static $theme_dir = null;
2159
  static $content_dir = null;
2160
  static $len = null;
2161
 
 
 
 
2162
  if ( $len === null ) {
2163
- $len = strlen( ABSPATH );
2164
  }
2165
  if ( $content_dir === null ) {
2166
  //$content_dir = mb_substr( dirname( cerber_get_plugins_dir() ), $len );
@@ -2185,10 +2664,10 @@ function cerber_detect_file( $file_name ) {
2185
 
2186
  // Check in a particular order for a better performance
2187
 
2188
- if ( 0 === strpos( $file_name, ABSPATH . 'wp-admin' . DIRECTORY_SEPARATOR ) ) {
2189
  return CERBER_FT_WP; // WP
2190
  }
2191
- if ( 0 === strpos( $file_name, ABSPATH . 'wp-includes' . DIRECTORY_SEPARATOR ) ) {
2192
  return CERBER_FT_WP; // WP
2193
  }
2194
 
@@ -2232,7 +2711,7 @@ function cerber_detect_file( $file_name ) {
2232
  }
2233
 
2234
  if ( basename( $file_name ) == 'wp-config.php' ) {
2235
- if ( ! file_exists( ABSPATH . '/wp-config.php' ) ) {
2236
  return CERBER_FT_CONF;
2237
  }
2238
  }
@@ -2283,7 +2762,7 @@ function cerber_get_file_folder( $file_name, $path ) {
2283
  *
2284
  * @return bool
2285
  */
2286
- function cerber_update_file_info( $file ) {
2287
  static $md5;
2288
  static $hash;
2289
 
@@ -2297,31 +2776,38 @@ function cerber_update_file_info( $file ) {
2297
 
2298
  $type = cerber_detect_file( $file['file_name'] );
2299
  $file_name = $file['file_name'];
 
2300
 
2301
  // A symbolic link in the content folder? Transform it to a real file name
2302
  if ( $type == CERBER_FT_CNT && is_link( $file['file_name'] ) ) {
2303
- $file_name = @readlink( $file['file_name'] );
2304
- if ( is_dir( $file_name ) ) {
 
 
2305
  $delete_it = true;
2306
  }
2307
  else {
2308
- $delete_it = cerber_db_get_row( 'SELECT COUNT(scan_id) FROM ' . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $file['scan_id'] . ' AND file_name = "' . $file_name . '"' );
2309
  }
 
2310
  if ( $delete_it ) {
2311
- return cerber_db_query( 'DELETE FROM ' . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $file['scan_id'] . ' AND file_name_hash = "' . $file['file_name_hash'] . '"' );
2312
  }
 
 
2313
  }
2314
 
2315
  $file_hash = '';
2316
  $file_md5 = '';
2317
 
2318
- if ( is_readable( $file_name ) ) {
2319
  if ( in_array( $type, $md5 ) ) {
2320
  if ( ! $file_md5 = @md5_file( $file_name ) ) {
2321
  $file_md5 = '';
2322
  }
2323
  }
2324
- if ( in_array( $type, $hash ) ) {
 
2325
  if ( ! $file_hash = @hash_file( 'sha256', $file_name ) ) {
2326
  $file_hash = '';
2327
  }
@@ -2331,18 +2817,19 @@ function cerber_update_file_info( $file ) {
2331
  cerber_log_scan_error( cerber_scan_msg( 0, $file_name ) );
2332
  }
2333
 
2334
- $size = filesize( $file_name );
2335
  $size = ( is_numeric( $size ) ) ? $size : 0;
2336
 
2337
- $perms = fileperms( $file_name );
2338
  $perms = ( is_numeric( $perms ) ) ? $perms : 0;
2339
 
2340
- $mtime = filemtime( $file_name );
2341
  $mtime = ( is_numeric( $mtime ) ) ? $mtime : 0;
2342
 
2343
  $is_writable = ( is_writable( $file_name ) ) ? 1 : 0;
2344
 
2345
- if ( ! cerber_db_query( 'UPDATE ' . CERBER_SCAN_TABLE . ' SET file_name = "' . $file_name . '", file_hash = "' . $file_hash . '", file_md5 = "' . $file_md5 . '", file_size = ' . $size . ', file_type = ' . $type . ', file_perms = ' . $perms . ', file_writable = ' . $is_writable . ', file_mtime = ' . $mtime .
 
2346
  ' WHERE scan_id = ' . $file['scan_id'] . ' AND file_name_hash = "' . $file['file_name_hash'] . '"' ) ) {
2347
  return false;
2348
  }
@@ -2350,6 +2837,133 @@ function cerber_update_file_info( $file ) {
2350
  return true;
2351
  }
2352
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2353
 
2354
  /**
2355
  * Recursively creates a list of files in a given folder with a given filename pattern
@@ -2400,7 +3014,8 @@ function cerber_scan_directory( $root, $pattern = null, $function ) {
2400
  continue;
2401
  }
2402
  $file_counter ++;
2403
- $file_name = str_replace( array( '/', '\\' ), DIRECTORY_SEPARATOR, $file_name );
 
2404
  $list[] = $file_name;
2405
  if ( count( $list ) > 200 ) { // packet size, can affect the DB performance if $function saves file names to the DB
2406
  call_user_func( $function, $list );
@@ -2432,6 +3047,10 @@ function cerber_scan_directory( $root, $pattern = null, $function ) {
2432
  return array( $dir_counter, $file_counter );
2433
  }
2434
 
 
 
 
 
2435
  /**
2436
  * Packet saving of file names
2437
  *
@@ -2464,17 +3083,21 @@ function _crb_save_file_names( $list ) {
2464
 
2465
  $sql = '';
2466
 
 
 
2467
  foreach ( $list as $filename ) {
2468
  if ( ! @is_file( $filename ) || ! cerber_is_file_type_scan( $filename ) ) {
2469
  continue;
2470
  }
 
 
2471
  $sha1 = sha1( $filename );
2472
- if ( cerber_db_get_var( 'SELECT COUNT(scan_id) FROM ' . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan_id . ' AND file_name_hash = "' . $sha1 . '"' ) ) {
2473
  continue;
2474
  }
2475
  $filename = cerber_real_escape( $filename );
2476
 
2477
- $sql .= '(' . $scan_id . ',' . $scan_mode . ',"' . $sha1 . '","' . $filename . '"),';
2478
  }
2479
 
2480
  if ( ! $sql ) {
@@ -2483,7 +3106,7 @@ function _crb_save_file_names( $list ) {
2483
 
2484
  $sql = rtrim( $sql, ',' );
2485
 
2486
- $ret = cerber_db_query( 'INSERT INTO ' . CERBER_SCAN_TABLE . ' (scan_id, scan_mode, file_name_hash, file_name) VALUES ' . $sql );
2487
  if ( ! $ret ) {
2488
  cerber_log_scan_error( 'DB Error occurred while saving filenames' );
2489
  }
@@ -2603,6 +3226,7 @@ function cerber_get_set( $key, $id = null, $unserialize = true ) {
2603
 
2604
  if ( $row = cerber_db_get_row( 'SELECT * FROM ' . cerber_get_db_prefix() . CERBER_SETS_TABLE . ' WHERE the_key = "' . $key . '" ' . $and ) ) {
2605
  if ( $row['expires'] > 0 && $row['expires'] < time() ) {
 
2606
  return false;
2607
  }
2608
  if ( $unserialize ) {
@@ -2619,9 +3243,9 @@ function cerber_get_set( $key, $id = null, $unserialize = true ) {
2619
  /**
2620
  * Update/insert value to the key-value storage
2621
  *
2622
- * @param string $key
2623
  * @param $value
2624
- * @param integer $id
2625
  * @param bool $serialize
2626
  * @param integer $expires Unix timestamp (UTC) when this element will be deleted
2627
  *
@@ -2712,14 +3336,16 @@ function cerber_delete_expired_set( $all = false ) {
2712
  }
2713
 
2714
  function cerber_step_desc(){
2715
- static $steps = array(
2716
  '',
2717
- 'Scanning folders for files',
2718
- 'Parsing the list of files',
2719
- 'Verifying the integrity of WordPress',
2720
- 'Verifying the integrity of the plugins',
2721
- 'Verifying the integrity of the themes',
2722
- 'Searching for malicious code'
 
 
2723
  );
2724
 
2725
  return $steps;
@@ -2762,8 +3388,8 @@ function cerber_get_short_name( $file_row ) {
2762
  $len = mb_strlen( dirname( cerber_get_upload_dir() ) );
2763
  break;
2764
  default:
2765
- if ( 0 === strpos( $file_row['file_name'], rtrim( ABSPATH, '/\\' ) ) ) {
2766
- $len = mb_strlen( ABSPATH ) - 1;
2767
  }
2768
  }
2769
 
@@ -2783,6 +3409,7 @@ function cerber_scanner_dashboard( $msg = '' ) {
2783
  <tr><td>Finished</td><td id="crb-finished" data-init="-">-</td></tr>
2784
  <tr><td>Duration</td><td id="crb-duration" data-init="-">-</td></tr>
2785
  <tr><td>Performance</td><td id="crb-performance" data-init="-">-</td></tr>
 
2786
  </table>
2787
  </div>
2788
  <div class="scan-tile">
@@ -2871,13 +3498,13 @@ function cerber_end_ajax( $data = array() ) {
2871
  function cerber_ref_upload_form() {
2872
  ?>
2873
  <div id="crb-ref-upload-dialog" style="display: none;">
2874
- <p>We have not found any integrity data to verify <span id="ref-section-name"></span>.</p>
2875
- <p>You need to upload a ZIP
2876
- archive from which you've installed it. This enables the security scanner to verify the integrity of the
2877
- code and detect malware.</p>
2878
  <form enctype="multipart/form-data">
2879
  <input type="file" name="refile" id="refile" required="required" accept=".zip">
2880
- <input type="submit" name="submit" value="Upload file" class="button button-primary">
 
2881
  <ul style="list-style: none;">
2882
  <li style="display:none;" class="crb-status-msg">Uploading the file, please wait&#8230;</li>
2883
  <li style="display:none;" class="crb-status-msg">Processing the file, please wait&#8230;</li>
@@ -3382,10 +4009,10 @@ add_action( 'wp_ajax_cerber_view_file', function () {
3382
 
3383
  $scan_id = absint( $_GET['scan_id'] );
3384
 
3385
- $the_file = cerber_db_get_row( 'SELECT * FROM ' . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan_id . ' AND file_name = "' . $file_name . '"' );
3386
 
3387
  if ( ! $the_file ) {
3388
- wp_die( 'Access error.' );
3389
  }
3390
 
3391
  if ( ! $source = file_get_contents( $file_name ) ) {
@@ -3395,10 +4022,13 @@ add_action( 'wp_ajax_cerber_view_file', function () {
3395
  $source = htmlspecialchars( $source, ENT_SUBSTITUTE );
3396
 
3397
  if ( ! $source ) {
3398
- $source = 'Unable to display the content of the file. This file contains non-printable characters.';
3399
  }
3400
 
3401
- if ( cerber_detect_exec_extension( $file_name ) || cerber_check_extension( $file_name, array( 'js', 'css', 'inc' ) ) ) {
 
 
 
3402
  $paint = true;
3403
  }
3404
  else {
@@ -3491,7 +4121,7 @@ add_action( 'wp_ajax_cerber_view_file', function () {
3491
  echo '<pre id="crb-file-content" class="brush: php; toolbar: false;">' . $source . '</pre>';
3492
 
3493
  if ( $the_file ) {
3494
- echo '<div id="crb-issue">Issue: ' . cerber_get_issue_desc( $the_file['scan_status'] ) . '</div>';
3495
  }
3496
 
3497
  if ( $paint ) :
@@ -3552,7 +4182,7 @@ add_action( 'wp_ajax_cerber_scan_delete_files', function () {
3552
  continue;
3553
  }
3554
 
3555
- $the_file = cerber_db_get_row( 'SELECT * FROM ' . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan_id . ' AND file_name = "' . $file_name . '"' );
3556
  if ( ! $the_file ) {
3557
  continue;
3558
  }
@@ -3610,11 +4240,13 @@ function cerber_quarantine_move( $file_name, $scan_id ) {
3610
  }
3611
  else {
3612
  if ( ! chmod( $quarantine, 0755 ) ) {
3613
- return new WP_Error( 'cerber-dir', 'Unable to set folder permissions for ' . $quarantine );
3614
  }
3615
  }
3616
 
3617
- cerber_lock_the_folder( $quarantine );
 
 
3618
 
3619
  // Preserve original paths for deleted files in a restore file
3620
  $restore = $quarantine . '.restore';
@@ -3668,7 +4300,7 @@ function cerber_can_be_deleted( $file_name, $check_inclusion = false ) {
3668
  if ( ! file_exists( $file_name ) || ! is_file( $file_name ) || is_link( $file_name ) ) {
3669
  return false;
3670
  }
3671
- //if ( basename( $file_name ) == '.htaccess' ) {
3672
  if ( cerber_is_htaccess( $file_name ) || cerber_is_dropin( $file_name ) ) {
3673
  return false;
3674
  }
@@ -3677,17 +4309,16 @@ function cerber_can_be_deleted( $file_name, $check_inclusion = false ) {
3677
  return false;
3678
  }
3679
 
3680
- if ( basename( $file_name ) == 'wp-config.php' ) {
3681
- // All stuff can contain different directory separators, make them the same
3682
- if ( ! $abspath ) {
3683
- $abspath = str_replace( array( '/', '\\' ), DIRECTORY_SEPARATOR, ABSPATH );
3684
  }
3685
- $file_name = str_replace( array( '/', '\\' ), DIRECTORY_SEPARATOR, $file_name );
3686
 
3687
- if ( $file_name == ABSPATH . 'wp-config.php' ) {
3688
  return false;
3689
  }
3690
- if ( ! file_exists( ABSPATH . 'wp-config.php' ) && $file_name == dirname( ABSPATH ) . DIRECTORY_SEPARATOR . 'wp-config.php' ) {
3691
  return false;
3692
  }
3693
  }
@@ -3727,5 +4358,320 @@ function cerber_scan_msg( $id, $txt = '' ) {
3727
  $ret .= ' ' . $txt;
3728
  }
3729
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3730
  return $ret;
3731
  }
45
 
46
  define( 'CERBER_MAX_SECONDS', 5 );
47
 
48
+ define( 'CERBER_FOK', 1 );
49
+
50
+ define( 'CERBER_IMD', 15 );
51
  define( 'CERBER_SCF', 16 );
52
  define( 'CERBER_PMC', 17 );
53
  define( 'CERBER_USF', 18 );
54
  define( 'CERBER_EXC', 20 );
55
+ define( 'CERBER_DIR', 26 );
56
  define( 'CERBER_UXT', 30 );
57
 
58
  define( 'CERBER_MALWR_DETECTED', 1000 );
61
  define( 'CRB_HASH_PLUGIN', 'hash_pl_' );
62
  define( 'CRB_LAST_FILE', 'tmp_last_file' );
63
 
64
+ define( 'CRB_SCAN_GO', '__CERBER__SECURITY_SCAN_GO__' );
65
+ define( 'CRB_SCAN_STOP', '__CERBER__SECURITY_SCAN_STOP__' );
66
+ define( 'CRB_SCAN_DTB', '__CERBER__SECURITY_SCAN_DATA_B' );
67
+ define( 'CRB_SCAN_DTE', '__CERBER__SECURITY_SCAN_DATA_E' );
68
+
69
  function cerber_integrity_page() {
70
 
71
+ $tab = cerber_get_tab( 'scanner', array( 'scanner', 'scan_settings', 'scan_schedule', 'help' ) );
72
 
73
  ?>
74
  <div class="wrap crb-admin">
75
 
76
+ <h1><?php _e( 'Site Integrity', 'wp-cerber' ) ?></h1>
77
 
78
  <h2 class="nav-tab-wrapper cerber-tabs">
79
  <?php
80
 
81
  echo '<a href="' . cerber_admin_link( 'scanner' ) . '" class="nav-tab ' . ( $tab == 'scanner' ? 'nav-tab-active' : '' ) . '"><span class="dashicons dashicons-visibility"></span> ' . __( 'Security Scanner' ) . '</a>';
82
  echo '<a href="' . cerber_admin_link( 'scan_settings' ) . '" class="nav-tab ' . ( $tab == 'scan_settings' ? 'nav-tab-active' : '' ) . '"><span class="dashicons dashicons-admin-settings"></span> ' . __( 'Settings' ) . '</a>';
83
+ echo '<a href="' . cerber_admin_link( 'scan_schedule' ) . '" class="nav-tab ' . ( $tab == 'scan_schedule' ? 'nav-tab-active' : '' ) . '"><span class="dashicons dashicons-clock"></span> ' . __( 'Scheduling' ) . '</a>';
84
  echo '<a href="' . cerber_admin_link( 'help', array( 'page' => cerber_get_admin_page() ) ) . '" class="nav-tab ' . ( $tab == 'help' ? 'nav-tab-active' : '' ) . '"><span class="dashicons dashicons-editor-help"></span> ' . __( 'Help', 'wp-cerber' ) . '</a>';
85
 
86
  echo lab_indicator();
97
  case 'scan_settings':
98
  cerber_show_settings_page( 'scanner' );
99
  break;
100
+ case 'scan_schedule':
101
+ cerber_show_settings_page( 'schedule' );
102
+ break;
103
  case 'help':
104
  cerber_show_help();
105
  break;
123
 
124
  if ( $scan = cerber_get_scan() ) {
125
  if ( ! $scan['finished'] ) {
126
+ if ( $scan['cloud']
127
+ && cerber_is_cloud_enabled()
128
+ && $scan['started'] > ( time() - 900 )
129
+ ) {
130
+ $msg = __( 'Currently a scheduled scan in progress. Please wait until it is finished.', 'wp_cerber' );
131
  $status = 1;
132
  }
133
  else {
134
+ $msg = sprintf( __( 'Previous scan started %s has not been completed. Continue scanning?', 'wp-cerber' ), cerber_date( $scan['started'] ) );
135
  $status = 2;
136
  }
137
  }
140
  }
141
  }
142
  else {
143
+ $msg = __( 'It seems this website has never been scanned. To start scanning click the button below.', 'wp-cerber' );
144
  }
145
 
146
  $start_quick = '<input data-control="start_scan" data-mode="quick" type="button" value="' . __( 'Start Quick Scan', 'wp-cerber' ) . '" class="button button-primary">';
147
  $start_full = '<input data-control="start_scan" data-mode="full" type="button" value="' . __( 'Start Full Scan', 'wp-cerber' ) . '" class="button button-primary">';
148
  $stop = '<input id="crb-stop-scan" style="display: none;" data-control="stop_scan" type="button" value="' . __( 'Stop Scanning', 'wp-cerber' ) . '" class="button button-primary">';
149
+ $continue = '<input id="crb-continue-scan" data-control="continue_scan" type="button" value="' . __( 'Continue Scanning', 'wp-cerber' ) . '" class="button button-primary">';
150
  $controls = '';
151
 
152
  switch ( $status ) {
179
  <td>
180
  <?php echo $controls; ?>
181
  </td>
182
+ <!-- <td><a href="#" data-control="full-paths">Show full paths</a></td> -->
183
+ <td><a href="#" class="dashicons dashicons-list-view" data-control="full-paths" title="Toggle full/relative paths"></a></td>
184
  </tr>
185
  </table>
186
  </form>
199
 
200
  ob_start(); // Collecting possible junk warnings and notices cause we need clean JSON to be sent
201
 
202
+ $scanner = array();
203
  $console_log = array();
204
+ $scan_do = '';
205
 
206
  if ( cerber_is_http_post() && isset( $_POST['cerber_scan_do'] ) ) {
207
+ $scan_do = preg_replace( '/[^a-z_\-\d]/i', '', $_POST['cerber_scan_do'] );
208
  $mode = ( isset( $_POST['cerber_scan_mode'] ) ) ? preg_replace( '/[^a-z_\-\d]/i', '', $_POST['cerber_scan_mode'] ) : 'quick';
209
 
210
+ $scanner = cerber_scanner( $scan_do, $mode );
211
 
212
  }
213
  else {
214
  $console_log[] = 'Unknown HTTP request';
215
  }
216
 
217
+ $next_do = ( ! empty( $scanner['cerber_scan_do'] ) ) ? $scanner['cerber_scan_do'] : 'stop';
 
 
218
 
219
  if ( $cerber_db_errors ) {
220
  $console_log = array_merge( $console_log, $cerber_db_errors );
222
 
223
  $console_log[] = 'PHP MEMORY ' . @ini_get( 'memory_limit' );
224
 
225
+ $ret = array(
226
+ 'console_log' => $console_log,
227
+ 'cerber_scan_do' => $next_do,
228
+ 'cerber_scanner' => $scanner,
229
+ //'scan' => cerber_get_scan(), // debug only
230
+ );
231
+
232
+ if ( $scan_do != 'continue_scan' ) {
233
+ $ret['strings'] = cerber_get_strings();
234
+ }
235
+
236
  ob_end_clean();
237
 
238
+ echo json_encode( $ret );
 
 
 
 
 
239
 
240
  wp_die();
241
  }
242
 
243
+ add_action( 'plugins_loaded', function () {
244
+ global $cerber_db_errors;
245
+
246
+ if ( ! cerber_is_cloud_request() ) {
247
+ return;
248
+ }
249
+
250
+ ob_start(); // Collecting possible junk warnings and notices cause we need clean JSON to be sent
251
+
252
+ // Load dependencies
253
+ if ( ! function_exists( '_get_dropins' ) ) {
254
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
255
+ }
256
+
257
+ $scanner = array();
258
+ $errors = array();
259
+ $do = '';
260
+
261
+ if ( isset( $_POST['scan_mode'] ) ) {
262
+
263
+ $mode = ( isset( $_POST['scan_mode'] ) ) ? preg_replace( '/[^a-z_\-\d]/i', '', $_POST['scan_mode'] ) : 'quick';
264
+
265
+ if ( cerber_is_cloud_enabled( $mode ) ) {
266
+ if ( $scan = cerber_get_scan() ) {
267
+ if ( $scan['finished'] || $scan['aborted'] ) {
268
+ if ( $scan['finished'] < ( time() - 900 ) ) {
269
+ $do = 'start_scan';
270
+ }
271
+ else {
272
+ $errors['p'] = 'Scan protection interval';
273
+ }
274
+ }
275
+ elseif ( $scan['cloud'] ) {
276
+ if ( $scan['cloud'] == lab_get_real_node_id() ) {
277
+ $do = 'continue_scan';
278
+ }
279
+ else {
280
+ // Restart a hung scan
281
+ if ( $scan['started'] < ( time() - 900 ) ) {
282
+ $do = 'start_scan';
283
+ }
284
+ else {
285
+ $errors['d'] = 'Scan from different node in progress';
286
+ }
287
+ }
288
+ }
289
+ // Restart a hung/abandoned scan
290
+ elseif ( $scan['started'] < ( time() - 900 ) ) {
291
+ $do = 'start_scan';
292
+ }
293
+ }
294
+ else {
295
+ $do = 'start_scan';
296
+ }
297
+
298
+ if ( $do ) {
299
+ $scanner = cerber_scanner( $do, $mode );
300
+ $scanner['errors'] = array(); // We don't process each error
301
+ }
302
+
303
+ }
304
+ else {
305
+ $errors['m'] = 'Mode is disabled';
306
+ }
307
+
308
+ }
309
+ else {
310
+ $errors['u'] = 'Unknown cloud request';
311
+ }
312
+
313
+ if ( ! empty( $scanner['cerber_scan_do'] ) ) {
314
+ $do = $scanner['cerber_scan_do'];
315
+ }
316
+ else {
317
+ $do = 'stop';
318
+ }
319
+
320
+ $db_errors = array_map( function ( $err ) {
321
+ return substr( $err, 0, 1000 );
322
+ }, $cerber_db_errors );
323
+
324
+ $ret = array(
325
+ 'cerber_scanner' => $scanner,
326
+ 'client_errors' => array( $errors, $db_errors ),
327
+ 'mem_limit' => @ini_get( 'memory_limit' ),
328
+ 'ver' => CERBER_VER
329
+ //'scan' => cerber_get_scan(), // debug only
330
+ );
331
+
332
+ ob_end_clean();
333
+
334
+ if ( $do == 'continue_scan' ) {
335
+ echo CRB_SCAN_GO;
336
+ }
337
+ else {
338
+ echo CRB_SCAN_STOP;
339
+ }
340
+
341
+ echo CRB_SCAN_DTB;
342
+ echo json_encode( $ret );
343
+ echo CRB_SCAN_DTE;
344
+
345
+ die();
346
+
347
+ } );
348
+
349
  function cerber_scanner( $control, $mode ) {
350
  global $cerber_db_errors, $cerber_scan_mode;
351
 
368
 
369
  switch ( $control ) {
370
  case 'start_scan':
 
371
  cerber_update_set( CRB_LAST_FILE, '', 0, false );
372
  cerber_init_scan( $mode );
373
  cerber_step_scanning();
381
  $errors[] = 'No scan in progress';
382
  }
383
  break;
384
+ case 'get_last_scan':
385
  if ($scan = cerber_get_scan()) {
386
  $filtered = $scan['issues'];
387
  foreach ( $scan['issues'] as $key => $item ) {
393
  }
394
  }
395
  }
396
+ // We have to refresh indexes for JS in the user browser
397
+ $filtered[ $key ]['issues'] = array_values( $filtered[ $key ]['issues'] );
398
  }
399
  }
400
  $response['issues'] = $filtered;
405
  if ($scan = cerber_get_scan()) {
406
 
407
  $response['scan_id'] = $scan['id'];
408
+ $response['mode'] = $scan['mode'];
409
+ $response['cloud'] = $scan['cloud'];
410
 
411
  if ( $scan['finished'] || $scan['aborted'] ) {
412
  $response['cerber_scan_do'] = 'stop';
413
+ //$response['checksum'] = sha1( serialize( $scan['issues'] ) );
414
  }
415
  else {
416
  $response['cerber_scan_do'] = 'continue_scan';
417
  }
418
 
419
+ $response['aborted'] = $scan['aborted'];
420
+ $response['errors'] = array_merge( $errors, $scan['errors'] );
421
+ $response['errors_total'] = count( $response['errors'] );
422
+
423
  $response['total'] = $scan['total'];
424
+ $response['step'] = $scan['next_step'];
 
425
 
426
+ if ( ! cerber_is_cloud_request() ) {
427
  $response['step_issues'] = $scan['step_issues'];
428
  $response['scanned'] = $scan['scanned'];
429
 
460
 
461
  }
462
  }
463
+ else {
464
+ $response['cerber_scan_do'] = 'stop';
465
+ }
466
 
467
  if ( $cerber_db_errors ) {
468
  cerber_watchdog( true );
472
  }
473
 
474
  function cerber_show_last_scan_results() {
475
+ $mime = wp_check_filetype( $file_name );
 
 
 
 
 
 
 
 
 
 
 
 
476
  }
477
 
478
  function cerber_step_scanning() {
482
 
483
  cerber_exec_timer();
484
 
 
 
485
  if ( ! $scan = cerber_get_scan() ) {
486
  return false;
487
  }
488
 
489
+ if ( $scan['finished'] || $scan['aborted'] ) {
490
  return true;
491
  }
492
 
493
+ cerber_update_scan( array( 'step_issues' => array() ) );
 
 
494
 
495
+ $update = array();
496
+ $next_step = $scan['next_step'];
497
+ $aborted = 0;
498
 
499
  switch ( $scan['next_step'] ) {
500
  case 1:
501
  if ( !$result = cerber_scan_directory( ABSPATH, null, '_crb_save_file_names' ) ) {
502
+ $aborted = 1;
503
  break;
504
  }
505
  else {
506
  $update['total']['folders'] = $result[0];
507
+
508
+ $above = dirname( cerber_get_abspath() ) . DIRECTORY_SEPARATOR;
509
+ _crb_save_file_names( array( $above . 'wp-config.php', $above . '.htaccess' ) );
510
 
511
  if ( crb_get_settings( 'scan_tmp' ) ) {
512
  $tmp_dir = @ini_get( 'upload_tmp_dir' );
525
  }
526
  }
527
 
528
+ $update['total']['files'] = cerber_db_get_var( 'SELECT COUNT(scan_id) FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan['id'] );
529
+ $next_step ++;
530
  }
531
  break;
532
  case 2:
533
  //$start = time();
534
  $x = 0;
535
  $exceed = false;
536
+ if ( $result = cerber_db_get_results( 'SELECT * FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan['id'] . ' AND file_hash = ""' ) ) {
537
  foreach ( $result as $row ) {
538
+ if ( ! cerber_add_file_info( $row ) ) {
539
  cerber_log_scan_error( 'Unable to update file info. Scanning has been aborted.' );
540
+ $aborted = 1;
541
  break;
542
  }
543
  if ( 0 === ($x % 100) ) {
550
  $x++;
551
  }
552
  // Some files might be symlinks
553
+ $update['total']['files'] = cerber_db_get_var( 'SELECT COUNT(scan_id) FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan['id'] );
554
+ $update['total']['parsed'] = cerber_db_get_var( 'SELECT COUNT(scan_id) FROM ' . cerber_get_db_prefix() .CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan['id'] . ' AND file_type !=0' );
555
  }
556
  else {
557
+ $aborted = 1;
558
  }
559
+ if ( ! $exceed && ! $aborted ) {
560
+ $next_step ++;
561
  }
562
  break;
563
  case 3:
564
+ if ( cerber_is_check_fs() ) {
565
+ cerber_check_fs_changes();
566
+ }
567
+ $next_step ++;
568
+ break;
569
  case 4:
570
+ cerber_verify_wp();
571
+ $next_step ++;
572
+ break;
573
+ case 5:
574
  $remain = cerber_verify_plugins();
575
  if ( ! $remain ) {
576
+ $next_step ++;
577
  }
578
  break;
579
+ case 6:
580
  $remain = cerber_verify_themes();
581
  if ( ! $remain ) {
582
+ $next_step ++;
583
  }
584
  break;
585
+ case 7:
586
  $remain = cerber_process_files();
587
  if ( ! $remain ) {
588
+ $next_step ++;
589
  }
590
  break;
591
+ case 8:
592
+ $next_step ++;
593
+ break;
594
  }
595
 
596
+ if ( $next_step > 8 ) {
597
  $update['finished'] = time();
598
+ $update['step_issues'] = array();
599
  }
600
 
601
+ if ( $aborted ) {
602
  $update['aborted'] = time();
603
  }
604
 
605
+ $update['next_step'] = $next_step;
606
+ $update['scanned']['files'] = cerber_db_get_var( 'SELECT COUNT(scan_id) FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan['id'] . ' AND scan_status > 0' );
607
+ $update['scanned']['bytes'] = cerber_db_get_var( 'SELECT SUM(file_size) FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan['id'] . ' AND scan_status > 0' );
608
 
609
  if ( ! $scan = cerber_get_scan() ) {
610
  return false;
612
 
613
  $update['issues'] = cerber_merge_issues( $scan['issues'], $scan['step_issues'] );
614
 
615
+ $ret = cerber_update_scan( $update );
616
+
617
+ if ( isset( $update['finished'] ) || isset( $update['aborted'] ) ) {
618
+ cerber_scan_completed();
619
+ }
620
+
621
+ return $ret;
622
+
623
+ }
624
+
625
+ function cerber_scan_completed() {
626
+ if ( ! cerber_is_cloud_request() || ! lab_lab() || ! cerber_is_cloud_enabled() ) {
627
+ return;
628
+ }
629
+
630
+ if ( ! ( $scan = cerber_get_scan() ) || ! $scan['cloud'] ) {
631
+ return;
632
+ }
633
+
634
+ $report = cerber_scan_report( $scan );
635
+
636
+ if ( ! $report ) {
637
+ return;
638
+ }
639
+
640
+ if ( ! cerber_send_email( 'scan', $report ) ) {
641
+ // Send alert via cloud?
642
+ }
643
 
644
  }
645
 
651
  * @return array|bool
652
  */
653
  function cerber_init_scan( $mode = 'quick' ) {
654
+ cerber_delete_old_scans();
655
 
656
  if ( ! $mode ) {
657
  $mode = 'quick';
658
  }
659
 
660
+ $data = array();
661
+ $data['mode'] = $mode; // Quick | Full
662
+ $data['id'] = time();
663
+ $data['started'] = $data['id'];
664
+ $data['finished'] = 0;
665
+ $data['aborted'] = 0; // If > 0, the scan has been aborted due to unrecoverable errors
666
+ $data['errors'] = array(); // Any software, DB, CURL, I/O and other system errors - for diagnostic/debugging
667
+ $data['scanned'] = array();
668
+ $data['issues'] = array(); // The list of issues
669
+ $data['step_issues'] = array(); // The list of issues during the current step
670
+ $data['total'] = array(); // Counters
671
+ //$data['total']['issues'] = 0;
672
+ $data['integrity'] = array();
673
+ $data['ip'] = cerber_get_remote_ip();
674
+ //$data['cloud'] = lab_is_cloud_request();
675
+ $data['cloud'] = cerber_is_cloud_request();
676
+ //$data['step'] = array();
677
  $data['next_step'] = 1;
678
 
679
  if ( ! cerber_update_set( 'scan', $data, $data['id'] ) ) {
691
  */
692
  function cerber_get_scan_id() {
693
 
694
+ $scan_id = null;
695
 
696
+ if ( $all = cerber_db_get_col( 'SELECT the_id FROM ' . cerber_get_db_prefix() . CERBER_SETS_TABLE . ' WHERE the_key = "scan"' ) ) {
697
+ $scan_id = max( $all ); // There is no index for the_id column, so it should be faster
698
  }
699
+
700
+ if ( ! $scan_id ) {
701
  $scan_id = false;
702
  }
703
 
712
  * @return array|bool
713
  */
714
  function cerber_get_scan( $scan_id = null ) {
 
715
 
716
  // If no ID is specified look for the latest one
717
+ if ( $scan_id === null && $all = cerber_db_get_col( 'SELECT the_id FROM ' . cerber_get_db_prefix() . CERBER_SETS_TABLE . ' WHERE the_key = "scan"' ) ) {
718
+ $scan_id = max( $all ); // There is no index for the_id column, so it should be faster
719
  }
720
 
721
  if ( ! $scan_id ) {
722
  return false;
723
  }
724
 
725
+ $scan = cerber_get_set( 'scan', $scan_id );
726
+ $scan['mode_h'] = ( $scan['mode'] == 'full' ) ? __( 'Full Scan', 'wp-cerber' ) : __( 'Quick Scan', 'wp-cerber' );
727
+
728
+ return $scan;
729
 
730
  }
731
 
732
+ /**
733
+ * Update scan data by simply merging values in array
734
+ *
735
+ * @param array $new_data
736
+ *
737
+ * @return bool
738
+ */
739
+ function cerber_update_scan( $new_data ) {
740
+ if ( ! $old_data = cerber_get_scan() ) {
741
+ return false;
742
+ }
743
+
744
+ if ( isset( $new_data['id'] ) ) {
745
+ unset( $new_data['id'] );
746
+ }
747
+ $data = array_merge( $old_data, $new_data );
748
+
749
+ return cerber_update_set( 'scan', $data, $old_data['id'] );
750
+ }
751
+
752
+ /**
753
+ * Update scan data and preserve existing keys in array (scan structure)
754
+ *
755
+ * @param array $new_data
756
+ *
757
+ * @return bool
758
+ */
759
+ function cerber_set_scan( $new_data ) {
760
+ if ( ! $scan_data = cerber_get_scan() ) {
761
+ return false;
762
+ }
763
+
764
+ $data = cerber_array_merge_recurively( $scan_data, $new_data );
765
+
766
+ return cerber_update_scan( $data );
767
+ }
768
+
769
+ /**
770
+ * Delete all outdated scans and their results except the several ones
771
+ *
772
+ */
773
+ function cerber_delete_old_scans() {
774
+ if ( ! $scans = cerber_db_get_results( 'SELECT * FROM ' . cerber_get_db_prefix() . CERBER_SETS_TABLE . ' WHERE the_key = "scan" ORDER BY the_id DESC' ) ) {
775
+ return;
776
+ }
777
+
778
+ $limit = 2; // How many results we keep in the DB as a history
779
+ $q_list = array();
780
+ $q = 0;
781
+ $f_list = array();
782
+ $f = 0;
783
+
784
+ foreach ( $scans as $item ) {
785
+ $scan = unserialize( $item['the_value'] );
786
+ if ( $scan['mode'] == 'quick' && $q < $limit ) {
787
+ $q_list[] = $scan['id'];
788
+ $q ++;
789
+ }
790
+ elseif ( $scan['mode'] == 'full' && $f < $limit ) {
791
+ $f_list[] = $scan['id'];
792
+ $f ++;
793
+ }
794
+ elseif ($q >= $limit && $f >= $limit ){
795
+ break;
796
+ }
797
+ }
798
+
799
+ $keep = array_merge( $q_list, $f_list );
800
+ $all = array_column( $scans, 'the_id' );
801
+ $delete = array_diff( $all, $keep );
802
+
803
+ if ( ! $delete ) {
804
+ return;
805
+ }
806
+
807
+ foreach ( $delete as $scan_id ) {
808
+ cerber_delete_scan( $scan_id );
809
+ }
810
+
811
+ }
812
+
813
+ /**
814
+ * Delete a single scan
815
+ *
816
+ * @return bool
817
+ */
818
+ function cerber_delete_scan( $scan_id ) {
819
+ $scan_id = absint( $scan_id );
820
+ if ( $scan_id && cerber_delete_set( 'scan', $scan_id ) ) {
821
+ cerber_db_query( 'DELETE FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan_id );
822
+ //cerber_db_query( 'DELETE FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE );
823
+ cerber_delete_set( 'tmp_verify_plugins', $scan_id );
824
+
825
+ return true;
826
+ }
827
+
828
+ return false;
829
+ }
830
+
831
  /**
832
  * Save issues (for end user reporting) during the scanning
833
  *
851
  foreach ( $issues as $issue ) {
852
 
853
  $data = array();
854
+ $extra_issue = 0;
855
 
856
  if ( isset( $issue['file'] ) ) {
857
 
863
  $data['name'] = $file['file_name'];
864
  $data['type'] = $file['file_type'];
865
 
866
+ if ( $file['file_status'] > 0 ) {
867
+ $extra_issue = $file['file_status'];
868
+ if ( $extra_issue == $issue[0] ) {
869
+ $extra_issue = 0;
870
+ }
871
+ }
872
+
873
  // Is file can be deleted safely
874
 
875
  $allowed = 0;
905
  $issue_type, // Type of issue
906
  $short_name, // Object name
907
  cerber_calculate_risk( $issue ),
908
+ $extra_issue,
909
  'data' => $data,
910
  'details' => $details,
911
  );
993
  return $ret;
994
  }
995
 
996
+ /**
997
+ * Merge two lists of issues in a correct way
998
+ *
999
+ * @param $issues1
1000
+ * @param $issues2
1001
+ *
1002
+ * @return array
1003
+ */
1004
+ function cerber_merge_issues( $issues1, $issues2 ) {
1005
+ if ( ! $issues1 ) {
1006
+ $issues1 = array();
1007
+ }
1008
+ foreach ( $issues2 as $id => $item ) {
1009
+ if ( ! isset( $issues1[ $id ] ) ) {
1010
+ //$issues1[ $id ] = array( 'name' => $item['name'], 'issues' => $item['issues'] );
1011
+ $issues1[ $id ] = $item;
1012
+ }
1013
+ else {
1014
+ $issues1[ $id ]['issues'] = array_merge( $issues1[ $id ]['issues'], $item['issues'] );
1015
+ }
1016
+ }
1017
+
1018
+ return $issues1;
1019
+ }
1020
+
1021
  /**
1022
  * Indicator for end-user
1023
  *
1026
  * @return int|mixed
1027
  */
1028
  function cerber_calculate_risk( $issue ) {
1029
+ $risk = array( CERBER_FOK => 0, 10 => 1, 11 => 2, 5 => 3, 6 => 3, 7 => 3, 8 => 3);
1030
 
1031
  if ( isset( $risk[ $issue[0] ] ) ) {
1032
  return $risk[ $issue[0] ];
1062
  }
1063
  return 2;
1064
  break;
1065
+ case CERBER_IMD:
1066
  case CERBER_USF:
1067
  case CERBER_SCF:
1068
  case CERBER_PMC:
1081
  return 1;
1082
  }
1083
 
1084
+ function cerber_get_risk_label() {
1085
  return array(
1086
  '',
1087
  'Low',
1090
  );
1091
  }
1092
 
1093
+ function cerber_get_issue_label( $id = null ) {
1094
  $issues = array(
1095
  0 => 'To be scanned',
1096
+ CERBER_FOK => __( 'Verified', 'wp-cerber' ),
1097
+
1098
+ // 0-4 must not use
1099
+
1100
+ // >4 is a real issue
1101
+
1102
  5 => __( 'Integrity data not found', 'wp-cerber' ),
1103
  6 => __( 'Unable to check the integrity of the plugin due to a network error', 'wp-cerber' ),
1104
  7 => __( 'Unable to check the integrity of WordPress files due to a network error', 'wp-cerber' ),
1105
  8 => __( 'Unable to check the integrity of the theme due to a network error', 'wp-cerber' ),
1106
 
1107
+ 10 => __( "Local file doesn't exist", 'wp-cerber' ),
1108
+ 11 => 'No local hash found',
1109
+ 13 => __( 'Unable to process file', 'wp-cerber' ),
1110
+ 14 => __( 'Unable to open file', 'wp-cerber' ),
 
1111
 
1112
+ CERBER_IMD => __( 'Checksum mismatch', 'wp-cerber' ), // Integrity
1113
+
1114
+ // 16-25 PHP related -------------------------
1115
+ CERBER_SCF => __( 'Suspicious code found', 'wp-cerber' ),
1116
  CERBER_PMC => __( 'Potentially malicious code found', 'wp-cerber' ),
1117
  CERBER_USF => __( 'Unattended suspicious file', 'wp-cerber' ),
1118
  CERBER_EXC => __( 'Executable code found', 'wp-cerber' ),
1119
 
1120
+ // Other -------------------------------------
1121
+ CERBER_DIR => __( 'Suspicious directives found', 'wp-cerber' ),
1122
+ CERBER_UXT => __( 'Unwanted file extension', 'wp-cerber' ),
1123
+
1124
+ 50 => __( 'Content has been modified', 'wp-cerber' ), // Previous scan
1125
+ 51 => __( 'New file', 'wp-cerber' ),
1126
  );
1127
 
1128
  if ( $id !== null ) {
1129
+ if ( is_array( $id ) ) {
 
 
 
 
1130
 
1131
+ return array_intersect_key( $issues, array_flip( $id ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1132
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1133
 
1134
+ return $issues[ $id ];
 
 
 
 
 
 
 
 
 
 
 
 
1135
  }
1136
 
1137
+ return $issues;
 
 
1138
  }
1139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1140
 
1141
+ function cerber_get_qs( $v = null ) {
1142
+ $q = array(
1143
+ 0 => __( 'Disabled', 'wp-cerber' ),
1144
+ 1 => __( 'Every hour', 'wp-cerber' ),
1145
+ 3 => __( 'Every 3 hours', 'wp-cerber' ),
1146
+ 6 => __( 'Every 6 hours', 'wp-cerber' ),
1147
+ );
1148
+ if ( $v ) {
1149
+ return $q[ $v ];
1150
  }
1151
 
1152
+ return $q;
1153
  }
1154
 
1155
  /**
1195
  return 0;
1196
  }
1197
 
 
1198
  $plugins_dir = cerber_get_plugins_dir() . DIRECTORY_SEPARATOR;
1199
  $file_count = 0;
1200
  $bytes = 0;
1235
  continue;
1236
  }
1237
 
1238
+ $file_name = $plugins_dir . $plugin_folder . DIRECTORY_SEPARATOR . cerber_normal_path( $file );
1239
  $file_name_hash = sha1( $file_name );
1240
  $where = 'scan_id = ' . $scan_id . ' AND file_name_hash = "' . $file_name_hash . '"';
1241
+ $local_file = cerber_db_get_row( 'SELECT * FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' WHERE ' . $where );
1242
 
1243
  if ( ! $local_file ) {
1244
  $issues[] = array( 10, DIRECTORY_SEPARATOR . $plugin_folder . DIRECTORY_SEPARATOR . $file );
1275
  $file_hash_repo = 'SHA256 hash not found';
1276
  }
1277
 
1278
+ $status = ( $hash_match ) ? CERBER_FOK : CERBER_IMD;
1279
+
1280
+ if ( $status > CERBER_FOK ) {
 
 
1281
  $issues[] = array( $status, $short_name, 'file' => $local_file );
1282
  }
1283
 
1284
+ cerber_db_query( 'UPDATE ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' SET file_hash_repo = "' . $file_hash_repo . '", hash_match = ' . $hash_match . ', scan_status = ' . $status . ' WHERE ' . $where );
1285
 
1286
  $file_count ++;
1287
  $bytes += absint( $local_file['file_size'] );
1288
 
1289
  }
1290
+
1291
  $verified = 1;
1292
  }
1293
  else {
1302
  $verified = 1;
1303
  $status = 1;
1304
  }
1305
+
1306
  $issues[] = array( $status, '', 'plugin' => $plugins[ $plugin ] );
1307
 
1308
  if ( $issues ) {
1415
  }
1416
 
1417
  // In case the default name 'wp-content' of the CONTENT folder has been changed
1418
+
1419
  $wp_content_dir = basename( dirname( cerber_get_plugins_dir() ) );
1420
  if ( $wp_content_dir != 'wp-content' ) {
1421
  $new_data = array();
1450
  static $themes_prefix, $plugins_prefix;
1451
 
1452
  if ( $themes_prefix == null ) {
1453
+ $themes_prefix = basename( dirname( cerber_get_plugins_dir() ) ) . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR;
1454
  }
1455
  if ( 0 === strpos( $file_name, $themes_prefix ) ) {
1456
  return false;
1457
  }
1458
 
1459
  if ( $plugins_prefix == null ) {
1460
+ $plugins_prefix = basename( dirname( cerber_get_plugins_dir() ) ) . DIRECTORY_SEPARATOR . basename( cerber_get_plugins_dir() ) . DIRECTORY_SEPARATOR;
1461
  }
1462
  if ( 0 === strpos( $file_name, $plugins_prefix ) ) {
1463
  return false;
1510
  }
1511
 
1512
  /**
1513
+ * Inspecting unattended files (remain after integrity checking) for traces of malware and other issue
1514
  *
1515
  * @return int
1516
  */
1517
+ function cerber_process_files(){
1518
 
1519
  if ( ! $scan = cerber_get_scan() ) {
1520
  return 0;
1521
  }
1522
 
1523
+ $not_in = CERBER_FOK . ',14,' . CERBER_IMD;
1524
+
1525
+ if ( !$files = cerber_db_get_results( 'SELECT * FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE .
1526
+ ' WHERE scan_id = ' . $scan['id'] . ' AND scan_status NOT IN ('.$not_in.')' ) ) {
1527
+ return 0;
1528
+ }
1529
+
1530
+ // Plugins data -------------------
1531
 
1532
  $plugins = array();
1533
  foreach ( get_plugins() as $key => $item ) {
1546
 
1547
  // ---------------------------------------------------------------------------
1548
 
1549
+ // Themes data -------------------
1550
 
1551
  $themes = wp_get_themes();
1552
 
1559
 
1560
  // Prevent hanging
1561
  if ( $f = cerber_get_set( CRB_LAST_FILE, 0, false ) ) {
1562
+ //cerber_db_query( 'UPDATE ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' SET scan_status = 13 WHERE scan_id = ' . $scan['id'] . ' AND file_name_hash = "' . sha1( $f ) . '"' );
1563
+ cerber_update_file_status( sha1( $f ), 13, $scan['id'] );
1564
  cerber_update_set( CRB_LAST_FILE, '', 0, false );
1565
+ $m = cerber_get_issue_label( 13 ) . ' ' . $f . ' size: ' . @filesize( $f ) . ' bytes';
1566
  cerber_log_scan_error( $m );
1567
  }
1568
 
1569
+ if ( $unwanted = crb_get_settings( 'scan_uext' ) ) {
1570
+ $unwanted = array_map( function ( $ext ) {
1571
+ return strtolower( trim( $ext, '. ' ) );
1572
+ }, $unwanted );
1573
+ }
 
 
1574
 
1575
+ $x = 0;
1576
 
1577
+ foreach ( $files as $file ) {
1578
 
1579
+ /*if ( cerber_is_htaccess( $file['file_name'] ) ) { // || $file['file_size'] == 0
1580
+ //cerber_db_query( 'UPDATE ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' SET scan_status = 1 WHERE scan_id = ' . $scan['id'] . ' AND file_name_hash = "' . $file['file_name_hash'] . '"' );
1581
+ cerber_update_file_status( $file['file_name_hash'], 1, $scan['id'] );
1582
+ continue;
1583
+ }*/
1584
+
1585
+ $integrity_verified = false;
1586
+ $severity_limit = 6;
1587
+ $status = CERBER_USF;
1588
+ $section = '';
1589
+ $do_not_del = false;
1590
+
1591
+ switch ( $file['file_type'] ) {
1592
+ case CERBER_FT_WP:
1593
+ $section = 'WordPress';
1594
+ $do_not_del = true;
1595
+ if ( ! empty( $scan['integrity']['wordpress'] ) ) {
1596
+ $integrity_verified = true;
1597
+ }
1598
+ break;
1599
+ case CERBER_FT_PLUGIN:
1600
+ $f = cerber_get_file_folder( $file['file_name'], cerber_get_plugins_dir() );
1601
+ if ( isset( $plugins[ $f ] ) ) {
1602
+ $section = $plugins[ $f ]['Name'];
1603
  $do_not_del = true;
1604
+ if ( ! empty( $plugins[ $f ]['integrity'] ) ) {
1605
  $integrity_verified = true;
1606
  }
1607
+ }
1608
+ else {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1609
  $severity_limit = 1;
1610
+ }
1611
+ break;
1612
+ case CERBER_FT_THEME:
1613
+ $f = cerber_get_file_folder( $file['file_name'], cerber_get_themes_dir() );
1614
+ if ( isset( $themes[ $f ] ) ) {
1615
+ $section = $themes[ $f ]->get( 'Name' ); // WP_Theme object
1616
  $do_not_del = true;
1617
+ if ( ! empty( $scan['integrity']['themes'][ $f ] ) ) {
1618
+ $integrity_verified = true;
1619
+ }
1620
+ $severity_limit = 5;
1621
+ }
1622
+ else {
1623
  $severity_limit = 1;
1624
+ }
1625
+ //$status = 1;
1626
+ break;
1627
+ case CERBER_FT_ROOT:
1628
+ if ( cerber_is_htaccess( $file['file_name'] ) ) {
1629
+ $section = 'WordPress';
1630
+ }
1631
+ //if ( ! empty( $scan['integrity']['wordpress'] ) ) {
1632
+ // $integrity_verified = true;
1633
+ //}
1634
+ $do_not_del = true;
1635
+ $severity_limit = 1;
1636
+ break;
1637
+ case CERBER_FT_CONF:
1638
+ $section = 'WordPress';
1639
+ $do_not_del = true;
1640
+ $severity_limit = 2;
1641
+ break;
1642
+ case CERBER_FT_UPLOAD:
1643
+ $section = 'Uploads folder';
1644
+ $severity_limit = 1;
1645
+ break;
1646
+ case CERBER_FT_MUP:
1647
+ $section = 'Must-use plugins';
1648
+ $do_not_del = true;
1649
+ break;
1650
+ case CERBER_FT_OTHER:
1651
+ $severity_limit = 1;
1652
+ break;
1653
+ case CERBER_FT_DRIN:
1654
+ $section = 'Drop-ins';
1655
+ break;
1656
+ default:
1657
+ $severity_limit = 2;
1658
+ break;
1659
 
1660
+ }
1661
 
1662
+ // Now we're ready to perform inspection
1663
 
1664
+ if ( ! $integrity_verified ) {
1665
 
1666
+ $result = cerber_inspect_file( $file['file_name'] );
1667
 
1668
+ // TODO: refactor this!
1669
+ if ( ! is_wp_error( $result ) ) {
1670
+ $status = CERBER_FOK;
1671
+ if ( $result['severity'] == CERBER_MALWR_DETECTED ) {
1672
+ $status = CERBER_PMC;
1673
+ }
1674
+ /*
1675
+ elseif ( $result['severity'] == $severity_limit ) {
1676
+ $status = CERBER_USF;
1677
+ }*/
1678
+ elseif ( $result['severity'] >= $severity_limit ) {
1679
+ if ( $result['severity'] == 1 ) {
1680
+ $status = CERBER_EXC;
1681
  }
1682
+ else {
1683
+ if ( cerber_is_htaccess( $file['file_name'] ) ) {
1684
+ $status = CERBER_DIR;
 
 
 
 
1685
  }
1686
  else {
1687
  $status = CERBER_SCF;
1688
  }
1689
  }
1690
  }
 
 
 
 
1691
  }
1692
  else {
1693
+ $status = 14;
 
 
 
 
 
1694
  }
1695
 
1696
+ }
1697
+ else {
1698
+ $result = array();
1699
+ }
1700
+
1701
+ // An exception for wp-config.php
1702
+ if ( $status == CERBER_USF && $file['file_type'] == CERBER_FT_CONF ) {
1703
+ $status = CERBER_FOK;
1704
+ }
1705
+
1706
+ // Unwanted extensions
1707
+ if ( $status == CERBER_FOK && $unwanted ) {
1708
+ $f = strtolower( basename( $file['file_name'] ) );
1709
+ $e = explode( '.', $f );
1710
+ array_shift( $e );
1711
+ if ( $e && array_intersect( $unwanted, $e ) ) {
1712
+ $status = CERBER_UXT;
1713
  }
1714
+ }
1715
 
1716
+ if ( $status == CERBER_FOK && $file['file_status'] > 0 ) {
1717
+ $status = $file['file_status'];
1718
+ }
1719
 
1720
+ // There is an issue with this file
1721
+ if ( $status > CERBER_FOK ) {
1722
 
1723
+ if ( ! $section ) {
1724
+ $section = 'Unattended files';
1725
+
1726
+ $len = 0;
1727
+ if ( 0 === strpos( $file['file_name'], rtrim( cerber_get_abspath(), '/\\' ) ) ) {
1728
+ $len = mb_strlen( cerber_get_abspath() ) - 1;
1729
+ }
1730
+ if ( $len ) {
1731
+ $short_name = mb_substr( $file['file_name'], $len );
 
1732
  }
1733
  else {
1734
+ $short_name = $file['file_name'];
1735
  }
1736
+ }
1737
+ else {
1738
+ $short_name = cerber_get_short_name( $file );
1739
+ }
1740
 
1741
+ // Is file can be deleted?
1742
 
1743
+ if ( $status >= CERBER_SCF ) {
1744
+ if ( $integrity_verified ) {
1745
+ $file['fd_allowed'] = 1;
1746
+ }
1747
+ elseif ( ! $do_not_del || in_array( $file['file_type'], $can_be_deleted ) ) {
1748
+ $file['fd_allowed'] = 1;
 
1749
  }
 
 
 
 
1750
  }
1751
 
1752
+ $issues[ $section ][] = array( $status, $short_name, $result, 'file' => $file );
1753
+ }
1754
+
1755
+ //cerber_db_query( 'UPDATE ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' SET scan_status = ' . $status . ' WHERE scan_id = ' . $scan['id'] . ' AND file_name_hash = "' . $file['file_name_hash'] . '"' );
1756
+ cerber_update_file_status( $file['file_name_hash'], $status , $scan['id'] );
1757
 
1758
+ if ( 0 === ( $x % 100 ) ) {
1759
+ if ( cerber_exec_timer() ) {
1760
+ $remain = 1;
1761
+ break;
 
1762
  }
 
1763
  }
1764
+ $x ++;
1765
  }
1766
 
1767
+
1768
  if ( $issues ) {
1769
  foreach ( $issues as $section => $list ) {
1770
  cerber_push_issues( $section, $list );
1788
  return false;
1789
  }
1790
 
1791
+ if ( cerber_is_htaccess( $file_name ) ) {
1792
+ return cerber_inspect_htaccess( $file_name );
1793
+ }
1794
+
1795
  if ( ! cerber_check_extension( $file_name, array( 'php', 'inc', 'phtm', 'phtml', 'phps', 'php2', 'php3', 'php4', 'php5', 'php6', 'php7' ) ) ) {
1796
  $php = false;
1797
 
1820
 
1821
  if ( is_wp_error( $result ) ) {
1822
  cerber_log_scan_error( $result->get_error_message() );
1823
+ return $result;
1824
  }
1825
 
1826
+
1827
+
1828
  return $result;
1829
  }
1830
 
1836
  * @return array|bool|WP_Error
1837
  */
1838
  function cerber_inspect_php( $file_name = '' ) {
1839
+ static $patterns;
1840
+
1841
+ if ( false === ( $content = @file_get_contents( $file_name ) ) ) {
1842
  return new WP_Error( 'cerber-file', cerber_scan_msg( 0, $file_name ) );
1843
  }
1844
 
1855
  $xdata = array();
1856
  $pos = array();
1857
  $open = null;
1858
+ $list = cerber_get_php_unsafe();
1859
 
1860
  foreach ( $tokens as $token ) {
1861
  if ( ! is_array( $token ) ) {
1868
  $severity[] = $list[ $token[1] ][0];
1869
  }
1870
  }
1871
+ if ( $token[0] == T_CONSTANT_ENCAPSED_STRING ) {
1872
+ if ( cerber_check_string( $token[1] ) ) {
1873
+ $xdata[] = array( 1, 'base64_encoded_string', $token[2], $token[0] );
1874
+ $severity[] = 10;
1875
+ }
1876
+ }
1877
  if ( $token[0] == T_OPEN_TAG ) {
1878
  $open = $token[2] - 1;
1879
  }
1917
 
1918
  // Check for malicious code patterns
1919
 
1920
+ if ( ! $patterns ) {
1921
+ $patterns = cerber_get_php_patterns();
1922
+ }
1923
+
1924
+ foreach ( $patterns as $pa ) {
1925
  if ($pa[1] == 2) { // 2 = REGEX
1926
  $matches = array();
1927
  if ( preg_match_all( '/' . $pa[2] . '/i', $code, $matches, PREG_OFFSET_CAPTURE ) ) {
2004
 
2005
  }
2006
 
2007
+ function cerber_check_string( $str ) {
2008
+
2009
+ $str = trim( $str, '\'"' );
2010
+
2011
+ if ( strlen( $str ) < 8 ) {
2012
+ return false;
2013
+ }
2014
+
2015
+ if ( preg_match( '/[\-_\!\?\;\*]/', $str ) ) {
2016
+ return false;
2017
+ }
2018
+
2019
+ $all = str_split( $str );
2020
+ $chars = array_count_values( $all );
2021
+ $total = count( $all );
2022
+ $distribution = array();
2023
+ foreach ( $chars as $char => $entrances ) {
2024
+ $distribution[ $char ] = $entrances / $total * 1000;
2025
+ }
2026
+
2027
+ $dev = cerber_stand_deviation( $distribution );
2028
+
2029
+ if ( $dev >= 9 && $dev <= 12 ) { // Typical Base64 encoded string
2030
+ return true;
2031
+ }
2032
+
2033
+ return false;
2034
+ }
2035
+
2036
+ /**
2037
+ * Calculate Standard Deviation of a given array
2038
+ *
2039
+ * @param array $arr
2040
+ *
2041
+ * @return float
2042
+ */
2043
+ function cerber_stand_deviation( $arr ) {
2044
+ $count = count( $arr );
2045
+ $variance = 0.0;
2046
+ $average = array_sum( $arr ) / $count;
2047
+
2048
+ foreach ( $arr as $value ) {
2049
+ $variance += pow( ( $value - $average ), 2 );
2050
+ }
2051
+
2052
+ return (float) sqrt( $variance / $count );
2053
+ }
2054
+
2055
  /**
2056
  * Unsafe code tokens
2057
  *
2058
  * @return array
2059
  */
2060
+ function cerber_get_php_unsafe(){
2061
  return array(
2062
+ 'base64_encoded_string' => array( 10, 'Base64 encoded string found.' ),
2063
+
2064
  'system' => array( 10, 'May be used to get/change vital system information or to run arbitrary server software.' ),
2065
  'shell_exec' => array(10, 'Executes arbitrary command via shell and returns the complete output as a string.'),
2066
  'exec' => array(10, 'Executes arbitrary programs on the web server.'),
2074
  'str_rot13' => array(9, 'Perform the rot13 transform on a string. May be used to obfuscate malware.'),
2075
  'base64_decode' => array(7, 'May be used to obfuscate and hinder detection of malicious code. Pairing with eval function indicates malicious code.'),
2076
  'socket_create' => array(6, 'Creates a network connection with any remote host. May be used to load malicious code from any web server with no restrictions.'),
2077
+ 'create_function' => array(6, 'Create an anonymous (lambda-style) function. Deprecated. A native anonymous function must be used instead.'),
2078
 
2079
  'hexdec' => array(5, 'Hexadecimal to decimal. May be used to obfuscate malware.'),
2080
  'dechex' => array(5, 'Decimal to hexadecimal. May be used to obfuscate malware.'),
2097
  'wp_safe_remote_post' => array(3, 'Upload or download data from/to any web server. May be used to load malicious code from an external source.'),
2098
  'wp_remote_head' => array(3, 'Load data from any web server. May be used to load malicious code from an external source.'),
2099
 
 
2100
  'call_user_func' => array(2, 'Call any function given by the first parameter. May be used to run malicious code or hinder code inspection.'),
2101
  'call_user_func_array' => array(2, 'Call any function with an array of parameters. May be used to run malicious code or hinder code inspection.'),
2102
  );
2107
  *
2108
  * @return array
2109
  */
2110
+ function cerber_get_php_patterns() {
2111
  $list = array(
2112
  array( 'VARF', 2, '\$[a-z0-9\_]+?\((?!\))', 11, 'A variable function call. Usually is used to hinder malware detection.' ), // pattern with function parameter(s): $example(something)
2113
+ array( 'IPV4', 2, '(?:[0-9]{1,3}\.){3}[0-9]{1,3}', 6, 'A suspicious external IPv4 address found. Can cause data leakage.', 'func' => '_is_ip_external' ),
2114
+ array( 'IPV6', 2, '(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}', 6, 'A suspicious external IPv6 address found. Can cause data leakage.', 'func' => '_is_ip_external' ),
2115
  array( 'BCTK', 2, '`[a-z]+`', 10, 'Execute arbitrary command on the web server' ),
2116
  array( 'PIDT', 3, 'php://input', 6, 'Get data or commands from the Internet. Should be used in trusted or verified software only' ),
2117
  array( 'NGET', 3, '$_GET', 3, 'Get data or commands from the Internet. Should be used in trusted or verified software only' ),
2134
  }
2135
  }
2136
 
2137
+ return $list;
2138
+ }
2139
+
2140
+ function cerber_inspect_htaccess( $file_name = '' ) {
2141
+ if ( false === ( $lines = @file( $file_name ) ) ) {
2142
+ return new WP_Error( 'cerber-file', cerber_scan_msg( 0, $file_name ) );
2143
+ }
2144
+
2145
+ $pats = cerber_get_ht_patterns();
2146
+ $severity = array();
2147
+ $xdata = array();
2148
+
2149
+ foreach ( $lines as $n => $line ) {
2150
+ if ( false !== ( $p = strpos( $line, '#' ) ) ) {
2151
+ $line = substr( $line, 0, $p );
2152
+ }
2153
+ $line = trim( $line );
2154
+ if ( ! $line ) {
2155
+ continue;
2156
+ }
2157
+
2158
+ foreach ( $pats as $pa ) {
2159
+ if ($pa[1] == 2) { // 2 = REGEX
2160
+ $matches = array();
2161
+ if ( preg_match_all( '/' . $pa[2] . '/i', $line, $matches, PREG_OFFSET_CAPTURE ) ) {
2162
+
2163
+ if ( ! empty( $pa['not_func'] ) && function_exists( $pa['not_func'] ) ) {
2164
+ foreach ( $matches[0] as $key => $match ) {
2165
+ if ( call_user_func( $pa['not_func'], $match[0], $line ) ) {
2166
+ unset( $matches[0][ $key ] );
2167
+ }
2168
+ }
2169
+ }
2170
+
2171
+ if ( ! empty( $pa['func'] ) && function_exists( $pa['func'] ) ) {
2172
+ foreach ( $matches[0] as $key => $match ) {
2173
+ if ( ! call_user_func( $pa['func'], $match[0], $line ) ) {
2174
+ unset( $matches[0][ $key ] );
2175
+ }
2176
+ }
2177
+ }
2178
+
2179
+ if ( ! empty( $matches[0] ) ) {
2180
+ $m = array_values( $matches[0] );
2181
+ $m[0][2] = $n + 1;
2182
+ $xdata[] = array( 2, $pa[0], $m );
2183
+ $severity[] = $pa[3];
2184
+ }
2185
+ }
2186
+ }
2187
+ else {
2188
+ if ( false !== stripos( $line, $pa[2] ) ) {
2189
+ $xdata[] = array( 2, $pa[0], array( array( $pa[2], 0, $n + 1 ) ) );
2190
+ $severity[] = $pa[3];
2191
+ }
2192
+ }
2193
+ }
2194
+
2195
+ }
2196
+
2197
+ $max = 0;
2198
+ if ( $severity ) {
2199
+ $max = max( $severity );
2200
+ }
2201
+
2202
+ return array( 'severity' => $max, 'xdata' => $xdata );
2203
+
2204
+ }
2205
+
2206
+ function cerber_get_ht_patterns() {
2207
+ static $ret;
2208
+ if ( $ret !== null ) {
2209
+ return $ret;
2210
+ }
2211
+ //$pat = cerber_get_patterns();
2212
+ $ret = array(
2213
+ //array( 'R4IP', 2, '(?:[0-9]{1,3}\.){3}[0-9]{1,3}', 6, 'A suspicious redirection to another, probably phishing website.', 'func' => '_is_rewrite_rule' ),
2214
+ //array( 'R6IP', 2, '(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}', 6, 'A suspicious redirection to another, probably phishing website.', 'func' => '_is_rewrite_rule' ),
2215
+ array( 'IPV4', 2, '(?:[0-9]{1,3}\.){3}[0-9]{1,3}', 6, 'A suspicious external IPv4 address found. Can cause data leakage.', 'func' => '_is_ip_external' ),
2216
+ array( 'IPV6', 2, '(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}', 6, 'A suspicious external IPv6 address found. Can cause data leakage.', 'func' => '_is_ip_external' ),
2217
+ array( 'RWEB', 2, '(https?:\/\/[^\s]+)', 6, 'A suspicious redirection to another, probably phishing website.', 'func' => '_is_unsafe_redirect_rule' ),
2218
+ array( 'RFTP', 2, '(ftps?:\/\/.+)', 10, 'A suspicious redirection to another, probably phishing website.', 'func' => '_is_unsafe_redirect_rule' ),
2219
+ array( 'PHPC', 2, 'php_value\s+(.+)', 10, 'An unsafe, suspicious PHP configuration command. Normally must not be here.', 'func' => '_is_unsafe_php_value' ),
2220
+ );
2221
+ return $ret;
2222
+ }
2223
+
2224
+ function _is_unsafe_php_value( $found, $line ) {
2225
+ $cmd_list = array( 'asp_tags', 'auto_append_file', 'auto_prepend_file', 'register_globals', 'include_path', 'open_basedir', 'user_ini', 'upload_tmp_dir' );
2226
+ if ( false !== crb_stripos_multi( $found, $cmd_list ) ) {
2227
+ return true;
2228
+ }
2229
+
2230
+ return false;
2231
+ }
2232
+
2233
+ function _is_unsafe_redirect_rule( $found, $line ) {
2234
+ static $allowed, $coms;
2235
+
2236
+ $line = trim( $line );
2237
+
2238
+ if ( ! $coms ) {
2239
+ $coms = array( 'RewriteRule', 'RewriteMap', 'ErrorDocument' );
2240
+ }
2241
+
2242
+ if ( 0 !== crb_stripos_multi( $line, $coms ) ) {
2243
+ return false;
2244
+ }
2245
+
2246
+ if ( ! $allowed ) {
2247
+ $allowed = array( home_url(), 'https://%{HTTP_HOST}', 'http://%{HTTP_HOST}' );
2248
+ }
2249
+
2250
+ if ( 0 !== crb_stripos_multi( $found, $allowed ) ) {
2251
+ return true;
2252
+ }
2253
+
2254
+ return false;
2255
+ }
2256
+
2257
+ function crb_stripos_multi( &$str, &$list ) {
2258
+ foreach ( $list as $item ) {
2259
+ $pos = stripos( $str, $item );
2260
+ if ( false !== $pos ) {
2261
+ return $pos;
2262
+ }
2263
+ }
2264
+
2265
+ return false;
2266
  }
2267
 
2268
  function _is_ip_external( $ip ) {
2276
  return true;
2277
  }
2278
 
2279
+
2280
+ function cerber_get_strings() {
2281
+ $data = array();
2282
+ $data[1] = cerber_get_php_unsafe();
2283
+ $list = array();
2284
+ $pats = array_merge( cerber_get_php_patterns(), cerber_get_ht_patterns() );
2285
+ foreach ( $pats as $p ) {
2286
  $list[ $p[0] ] = $p[4];
2287
  }
2288
  $data[2] = $list;
2289
+
2290
+ $data['explain'] = array(
2291
+ 'This file contains executable code and may contain obfuscated malware. If this file is a part of a theme or a plugin, it must be located in the theme or the plugin folder. No exception, no excuses.',
2292
+ 'The scanner recognizes this file as "ownerless" or "not bundled" because it does not belong to any known part of the website and should not be there.',
2293
+ 'It may remain after upgrading to a newer version of %s. It also may be a piece of unknown obfuscated malware. In a rare case it might be a part of a custom-made (bespoke) plugin or theme.',
2294
+ __( 'Suspicious code instruction found', 'wp-cerber' ),
2295
+ __( 'Suspicious code signatures found', 'wp-cerber' ),
2296
+ __( 'Suspicious directives found', 'wp-cerber' ),
2297
+ 'The contents of the file has been changed and does match what exists in the official WordPress repository or a reference file you\'ve uploaded earlier. The file may have been infected by malware or has been tampered with.',
2298
+ __( 'To solve this issue you have to reinstall %s or update it to the latest version.', 'wp-cerber' ),
2299
+ __( 'Please upload a reference ZIP archive', 'wp-cerber' ),
2300
+ __( 'Resolve issue', 'wp-cerber' ),
2301
+ );
2302
+
2303
  $data['complete'] = 1;
 
2304
 
2305
+ return $data;
2306
+ }
2307
 
2308
  /**
2309
+ * Verify files using hash data provided as array of $file_name => $hash
2310
  *
2311
  * @param array $hash_data Hash
2312
  * @param string $field Name of DB table field with local hash
2318
  */
2319
  function cerber_verify_files( $hash_data, $field = 'file_hash', $local_prefix = '', $type_not_in = array(), $set_type = null, $func = null ) {
2320
  if ( ! $scan = cerber_get_scan() ) {
2321
+ return array();
2322
  }
2323
 
2324
  $set_type = absint( $set_type );
2329
  $func = null;
2330
  }
2331
 
2332
+ $table = cerber_get_db_prefix() . CERBER_SCAN_TABLE;
2333
+
2334
+ $local_prefix = cerber_normal_path( $local_prefix );
2335
+
2336
  foreach ( $hash_data as $file_name => $hash ) {
2337
 
2338
  if ( ! cerber_is_file_type_scan( $file_name ) ) {
2339
  continue;
2340
  }
2341
 
2342
+ $file_name = cerber_normal_path( $file_name );
2343
+
2344
  $file_name_hash = sha1( $local_prefix . $file_name );
2345
  $where = 'scan_id = ' . $scan['id'] . ' AND file_name_hash = "' . $file_name_hash . '"';
 
 
 
 
 
2346
 
2347
+ $local_file = cerber_db_get_row( 'SELECT * FROM ' . $table . ' WHERE ' . $where );
2348
 
2349
  if ( ! $local_file ) {
2350
  if ( $func ) {
2352
  continue;
2353
  }
2354
  }
2355
+ $issues[] = array( 10, DIRECTORY_SEPARATOR . ltrim( $file_name, DIRECTORY_SEPARATOR ) );
2356
  continue;
2357
  }
2358
 
2366
  $issues[] = array( 11, $short_name, 'file' => $local_file );
2367
  continue;
2368
  }
2369
+
2370
  $hash_match = ( $local_file[ $field ] === $hash ) ? 1 : 0;
2371
 
2372
+ $status = ( $hash_match ) ? CERBER_FOK : CERBER_IMD;
2373
+
2374
+ if ( $status > CERBER_FOK ) {
 
 
2375
  $issues[] = array( $status, $short_name, 'file' => $local_file );
2376
  }
2377
 
2378
  $file_type = ( ! empty( $set_type ) ) ? $set_type : $local_file['file_type'];
2379
 
2380
+ cerber_db_query( 'UPDATE ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' SET file_type = ' . $file_type . ', file_hash_repo = "' . $hash . '", hash_match = ' . $hash_match . ', scan_status = ' . $status . ' WHERE ' . $where );
2381
 
2382
  $file_count ++;
2383
 
2628
  }
2629
 
2630
  function cerber_detect_file( $file_name ) {
2631
+ static $abspath = null;
2632
  static $upload_dir = null;
2633
  static $plugin_dir = null;
2634
  static $theme_dir = null;
2635
  static $content_dir = null;
2636
  static $len = null;
2637
 
2638
+ if ( $abspath === null ) {
2639
+ $abspath = cerber_get_abspath();
2640
+ }
2641
  if ( $len === null ) {
2642
+ $len = strlen( $abspath );
2643
  }
2644
  if ( $content_dir === null ) {
2645
  //$content_dir = mb_substr( dirname( cerber_get_plugins_dir() ), $len );
2664
 
2665
  // Check in a particular order for a better performance
2666
 
2667
+ if ( 0 === strpos( $file_name, $abspath . 'wp-admin' . DIRECTORY_SEPARATOR ) ) {
2668
  return CERBER_FT_WP; // WP
2669
  }
2670
+ if ( 0 === strpos( $file_name, $abspath . 'wp-includes' . DIRECTORY_SEPARATOR ) ) {
2671
  return CERBER_FT_WP; // WP
2672
  }
2673
 
2711
  }
2712
 
2713
  if ( basename( $file_name ) == 'wp-config.php' ) {
2714
+ if ( ! file_exists( $abspath . '/wp-config.php' ) ) {
2715
  return CERBER_FT_CONF;
2716
  }
2717
  }
2762
  *
2763
  * @return bool
2764
  */
2765
+ function cerber_add_file_info( $file ) {
2766
  static $md5;
2767
  static $hash;
2768
 
2776
 
2777
  $type = cerber_detect_file( $file['file_name'] );
2778
  $file_name = $file['file_name'];
2779
+ $update_file_name = '';
2780
 
2781
  // A symbolic link in the content folder? Transform it to a real file name
2782
  if ( $type == CERBER_FT_CNT && is_link( $file['file_name'] ) ) {
2783
+
2784
+ $file_name = @readlink( $file['file_name'] );
2785
+
2786
+ if ( is_dir( $file_name ) ) {
2787
  $delete_it = true;
2788
  }
2789
  else {
2790
+ $delete_it = cerber_db_get_var( 'SELECT COUNT(scan_id) FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $file['scan_id'] . ' AND file_name = "' . cerber_real_escape( $file_name ) . '"' );
2791
  }
2792
+
2793
  if ( $delete_it ) {
2794
+ return cerber_db_query( 'DELETE FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $file['scan_id'] . ' AND file_name_hash = "' . $file['file_name_hash'] . '"' );
2795
  }
2796
+
2797
+ $update_file_name = ' file_name="'.cerber_real_escape( $file_name ).'",';
2798
  }
2799
 
2800
  $file_hash = '';
2801
  $file_md5 = '';
2802
 
2803
+ if ( @is_readable( $file_name ) ) {
2804
  if ( in_array( $type, $md5 ) ) {
2805
  if ( ! $file_md5 = @md5_file( $file_name ) ) {
2806
  $file_md5 = '';
2807
  }
2808
  }
2809
+ //if ( cerber_is_check_fs() || in_array( $type, $hash ) || cerber_is_htaccess( $file_name ) ) {
2810
+ if ( cerber_is_check_fs() || in_array( $type, $hash ) ) {
2811
  if ( ! $file_hash = @hash_file( 'sha256', $file_name ) ) {
2812
  $file_hash = '';
2813
  }
2817
  cerber_log_scan_error( cerber_scan_msg( 0, $file_name ) );
2818
  }
2819
 
2820
+ $size = @filesize( $file_name );
2821
  $size = ( is_numeric( $size ) ) ? $size : 0;
2822
 
2823
+ $perms = @fileperms( $file_name );
2824
  $perms = ( is_numeric( $perms ) ) ? $perms : 0;
2825
 
2826
+ $mtime = @filemtime( $file_name );
2827
  $mtime = ( is_numeric( $mtime ) ) ? $mtime : 0;
2828
 
2829
  $is_writable = ( is_writable( $file_name ) ) ? 1 : 0;
2830
 
2831
+ //if ( ! cerber_db_query( 'UPDATE ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' SET file_name = "' . $file_name . '", file_hash = "' . $file_hash . '", file_md5 = "' . $file_md5 . '", file_size = ' . $size . ', file_type = ' . $type . ', file_perms = ' . $perms . ', file_writable = ' . $is_writable . ', file_mtime = ' . $mtime .
2832
+ if ( ! cerber_db_query( 'UPDATE ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' SET '.$update_file_name.' file_hash = "' . $file_hash . '", file_md5 = "' . $file_md5 . '", file_size = ' . $size . ', file_type = ' . $type . ', file_perms = ' . $perms . ', file_writable = ' . $is_writable . ', file_mtime = ' . $mtime .
2833
  ' WHERE scan_id = ' . $file['scan_id'] . ' AND file_name_hash = "' . $file['file_name_hash'] . '"' ) ) {
2834
  return false;
2835
  }
2837
  return true;
2838
  }
2839
 
2840
+ /**
2841
+ * @param string $file_name_hash
2842
+ * @param int $status
2843
+ * @param int $scan_id
2844
+ *
2845
+ * @return bool|mysqli_result|resource
2846
+ */
2847
+ function cerber_update_file_status( $file_name_hash, $status, $scan_id ) {
2848
+ return cerber_db_query( 'UPDATE ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' SET scan_status = ' . $status . ' WHERE scan_id = ' . $scan_id . ' AND file_name_hash = "' . $file_name_hash . '"' );
2849
+ }
2850
+
2851
+ function cerber_is_check_fs() {
2852
+ if ( crb_get_settings( 'scan_imod' ) || crb_get_settings( 'scan_inew' ) ) {
2853
+ return true;
2854
+ }
2855
+
2856
+ return false;
2857
+ }
2858
+
2859
+ /**
2860
+ * Are there any changes/new files
2861
+ *
2862
+ * @return int
2863
+ */
2864
+ function cerber_check_fs_changes() {
2865
+
2866
+ $scan_id = cerber_get_scan_id();
2867
+
2868
+ $prev_id = cerber_get_prev_scan_id( $scan_id );
2869
+
2870
+ if ( $prev_id ) {
2871
+ cerber_cmp_scans( $prev_id, $scan_id );
2872
+ }
2873
+
2874
+ return 0;
2875
+ }
2876
+
2877
+ function cerber_get_prev_scan_id( $scan_id = 0 ) {
2878
+ global $cerber_scan_mode;
2879
+
2880
+ if ( ! $scans = cerber_db_get_results( 'SELECT * FROM ' . cerber_get_db_prefix() . CERBER_SETS_TABLE
2881
+ . ' WHERE the_key = "scan" AND the_id < ' . $scan_id . ' ORDER BY the_id DESC' )
2882
+ ) {
2883
+ return 0;
2884
+ }
2885
+
2886
+ $prev_id = 0;
2887
+ foreach ( $scans as $item ) {
2888
+ $scan = unserialize( $item['the_value'] );
2889
+ if ( $scan['mode'] == $cerber_scan_mode ) {
2890
+ $prev_id = $scan['id'];
2891
+ break;
2892
+ }
2893
+ }
2894
+
2895
+ return $prev_id;
2896
+ }
2897
+
2898
+ function cerber_cmp_scans( $prev_id, $scan_id ) {
2899
+
2900
+ $p_files = cerber_db_get_results( 'SELECT file_name_hash, file_hash, file_md5, file_size FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $prev_id);
2901
+
2902
+ $n_files = cerber_db_get_results( 'SELECT file_name_hash, file_hash, file_md5, file_size FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan_id);
2903
+
2904
+ if ( ! $p_files || ! $n_files ) {
2905
+ return 0;
2906
+ }
2907
+
2908
+ $prev_files = array();
2909
+ foreach ( $p_files as $file ) {
2910
+ $prev_files[$file['file_name_hash']] = $file;
2911
+ }
2912
+
2913
+ $new_files = array();
2914
+ foreach ( $n_files as $file ) {
2915
+ $new_files[$file['file_name_hash']] = $file;
2916
+ }
2917
+
2918
+ $inew = crb_get_settings( 'scan_inew' );
2919
+ $imod = crb_get_settings( 'scan_imod' );
2920
+
2921
+ $update = array();
2922
+ foreach ( $new_files as $key => $file ) {
2923
+ $status = 0;
2924
+ if ( ! isset( $prev_files[ $key ] ) ) {
2925
+ if ( $inew ) {
2926
+ $status = 51;
2927
+ }
2928
+ }
2929
+ elseif ( $imod ) {
2930
+ $status = cerber_cmp_files( $prev_files[ $key ], $new_files[ $key ] );
2931
+ }
2932
+ if ( $status > 0 ) {
2933
+ $update[ $key ] = $status;
2934
+ }
2935
+ }
2936
+
2937
+ if ( ! $update ) {
2938
+ return 0;
2939
+ }
2940
+
2941
+ $table = cerber_get_db_prefix() . CERBER_SCAN_TABLE;
2942
+ foreach ( $update as $key => $status ) {
2943
+ cerber_db_query( 'UPDATE ' . $table . ' SET file_status = ' . $status . ' WHERE scan_id = ' . $scan_id . ' AND file_name_hash = "' . $key . '"' );
2944
+ }
2945
+
2946
+ return 0;
2947
+
2948
+ }
2949
+
2950
+ function cerber_cmp_files( $prev, $new ) {
2951
+ if ( ! empty( $prev['file_hash'] ) && ! empty( $new['file_hash'] ) ) {
2952
+ if ( $prev['file_hash'] != $new['file_hash'] ) {
2953
+ return 50;
2954
+ }
2955
+ }
2956
+ elseif ( ! empty( $prev['file_md5'] ) && ! empty( $new['file_md5'] ) ) {
2957
+ if ( $prev['file_md5'] != $new['file_md5'] ) {
2958
+ return 50;
2959
+ }
2960
+ }
2961
+ elseif ( $prev['file_size'] != $new['file_size'] ) {
2962
+ return 50;
2963
+ }
2964
+
2965
+ return 0;
2966
+ }
2967
 
2968
  /**
2969
  * Recursively creates a list of files in a given folder with a given filename pattern
3014
  continue;
3015
  }
3016
  $file_counter ++;
3017
+ //$file_name = str_replace( array( '/', '\\' ), DIRECTORY_SEPARATOR, $file_name );
3018
+ //$file_name = cerber_norm_file_name( $file_name );
3019
  $list[] = $file_name;
3020
  if ( count( $list ) > 200 ) { // packet size, can affect the DB performance if $function saves file names to the DB
3021
  call_user_func( $function, $list );
3047
  return array( $dir_counter, $file_counter );
3048
  }
3049
 
3050
+ function cerber_normal_path( $file_name ) {
3051
+ return str_replace( array( '/', '\\' ), DIRECTORY_SEPARATOR, $file_name );
3052
+ }
3053
+
3054
  /**
3055
  * Packet saving of file names
3056
  *
3083
 
3084
  $sql = '';
3085
 
3086
+ $table = cerber_get_db_prefix() . CERBER_SCAN_TABLE;
3087
+
3088
  foreach ( $list as $filename ) {
3089
  if ( ! @is_file( $filename ) || ! cerber_is_file_type_scan( $filename ) ) {
3090
  continue;
3091
  }
3092
+ $filename = cerber_normal_path( $filename );
3093
+
3094
  $sha1 = sha1( $filename );
3095
+ if ( cerber_db_get_var( 'SELECT COUNT(scan_id) FROM ' . $table . ' WHERE scan_id = ' . $scan_id . ' AND file_name_hash = "' . $sha1 . '"' ) ) {
3096
  continue;
3097
  }
3098
  $filename = cerber_real_escape( $filename );
3099
 
3100
+ $sql .= '(' . $scan_id . ',' . $scan_mode . ',"' . $sha1 . '","' . $filename . '"),';
3101
  }
3102
 
3103
  if ( ! $sql ) {
3106
 
3107
  $sql = rtrim( $sql, ',' );
3108
 
3109
+ $ret = cerber_db_query( 'INSERT INTO ' . $table . ' (scan_id, scan_mode, file_name_hash, file_name) VALUES ' . $sql );
3110
  if ( ! $ret ) {
3111
  cerber_log_scan_error( 'DB Error occurred while saving filenames' );
3112
  }
3226
 
3227
  if ( $row = cerber_db_get_row( 'SELECT * FROM ' . cerber_get_db_prefix() . CERBER_SETS_TABLE . ' WHERE the_key = "' . $key . '" ' . $and ) ) {
3228
  if ( $row['expires'] > 0 && $row['expires'] < time() ) {
3229
+ cerber_delete_set( $key, $id );
3230
  return false;
3231
  }
3232
  if ( $unserialize ) {
3243
  /**
3244
  * Update/insert value to the key-value storage
3245
  *
3246
+ * @param string $key A unique key for the data set
3247
  * @param $value
3248
+ * @param integer $id An additional numerical key
3249
  * @param bool $serialize
3250
  * @param integer $expires Unix timestamp (UTC) when this element will be deleted
3251
  *
3336
  }
3337
 
3338
  function cerber_step_desc(){
3339
+ $steps = array(
3340
  '',
3341
+ __( 'Scanning folders for files', 'wp-cerber' ),
3342
+ __( 'Parsing the list of files', 'wp-cerber' ),
3343
+ __( 'Checking for new and modified files', 'wp-cerber' ),
3344
+ __( 'Verifying the integrity of WordPress', 'wp-cerber' ),
3345
+ __( 'Verifying the integrity of the plugins', 'wp-cerber' ),
3346
+ __( 'Verifying the integrity of the themes', 'wp-cerber' ),
3347
+ __( 'Searching for malicious code', 'wp-cerber' ),
3348
+ __( 'Finalizing the scan', 'wp-cerber' ),
3349
  );
3350
 
3351
  return $steps;
3388
  $len = mb_strlen( dirname( cerber_get_upload_dir() ) );
3389
  break;
3390
  default:
3391
+ if ( 0 === strpos( $file_row['file_name'], rtrim( cerber_get_abspath(), '/\\' ) ) ) {
3392
+ $len = mb_strlen( cerber_get_abspath() ) - 1;
3393
  }
3394
  }
3395
 
3409
  <tr><td>Finished</td><td id="crb-finished" data-init="-">-</td></tr>
3410
  <tr><td>Duration</td><td id="crb-duration" data-init="-">-</td></tr>
3411
  <tr><td>Performance</td><td id="crb-performance" data-init="-">-</td></tr>
3412
+ <tr><td>Mode</td><td id="crb-smode" data-init="-">-</td></tr>
3413
  </table>
3414
  </div>
3415
  <div class="scan-tile">
3498
  function cerber_ref_upload_form() {
3499
  ?>
3500
  <div id="crb-ref-upload-dialog" style="display: none;">
3501
+ <p><?php _e( 'We have not found any integrity data to verify', 'wp-cerber' ); ?><span
3502
+ id="ref-section-name"></span>.</p>
3503
+ <p><?php _e( "You have to upload a ZIP archive from which you've installed it. This enables the security scanner to verify the integrity of the code and detect malware.", 'wp-cerber' ); ?></p>
 
3504
  <form enctype="multipart/form-data">
3505
  <input type="file" name="refile" id="refile" required="required" accept=".zip">
3506
+ <input type="submit" name="submit" value="<?php _e( 'Upload file', 'wp-cerber' ); ?>"
3507
+ class="button button-primary">
3508
  <ul style="list-style: none;">
3509
  <li style="display:none;" class="crb-status-msg">Uploading the file, please wait&#8230;</li>
3510
  <li style="display:none;" class="crb-status-msg">Processing the file, please wait&#8230;</li>
4009
 
4010
  $scan_id = absint( $_GET['scan_id'] );
4011
 
4012
+ $the_file = cerber_db_get_row( 'SELECT * FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan_id . ' AND file_name = "' . $file_name . '"' );
4013
 
4014
  if ( ! $the_file ) {
4015
+ wp_die( __( 'File access error. Possibly scan results are outdated. Please run Quick or Full Scan.', 'wp-cerber' ) );
4016
  }
4017
 
4018
  if ( ! $source = file_get_contents( $file_name ) ) {
4022
  $source = htmlspecialchars( $source, ENT_SUBSTITUTE );
4023
 
4024
  if ( ! $source ) {
4025
+ $source = 'Unable to display the contents of the file. This file contains non-printable characters.';
4026
  }
4027
 
4028
+ if ( cerber_detect_exec_extension( $file_name )
4029
+ || cerber_check_extension( $file_name, array( 'js', 'css', 'inc' ) )
4030
+ || cerber_is_htaccess( $file_name )
4031
+ ) {
4032
  $paint = true;
4033
  }
4034
  else {
4121
  echo '<pre id="crb-file-content" class="brush: php; toolbar: false;">' . $source . '</pre>';
4122
 
4123
  if ( $the_file ) {
4124
+ echo '<div id="crb-issue">Issue: ' . cerber_get_issue_label( $the_file['scan_status'] ) . '</div>';
4125
  }
4126
 
4127
  if ( $paint ) :
4182
  continue;
4183
  }
4184
 
4185
+ $the_file = cerber_db_get_row( 'SELECT * FROM ' . cerber_get_db_prefix() . CERBER_SCAN_TABLE . ' WHERE scan_id = ' . $scan_id . ' AND file_name = "' . $file_name . '"' );
4186
  if ( ! $the_file ) {
4187
  continue;
4188
  }
4240
  }
4241
  else {
4242
  if ( ! chmod( $quarantine, 0755 ) ) {
4243
+ return new WP_Error( 'cerber-dir', 'Unable to set directory permissions for ' . $quarantine );
4244
  }
4245
  }
4246
 
4247
+ if ( ! cerber_lock_the_folder( $quarantine ) ) {
4248
+ return new WP_Error( 'cerber-dir', 'Unable to lock the directory ' . $quarantine );
4249
+ }
4250
 
4251
  // Preserve original paths for deleted files in a restore file
4252
  $restore = $quarantine . '.restore';
4300
  if ( ! file_exists( $file_name ) || ! is_file( $file_name ) || is_link( $file_name ) ) {
4301
  return false;
4302
  }
4303
+
4304
  if ( cerber_is_htaccess( $file_name ) || cerber_is_dropin( $file_name ) ) {
4305
  return false;
4306
  }
4309
  return false;
4310
  }
4311
 
4312
+ if ( basename( $file_name ) == 'wp-config.php' ) {
4313
+ if ( $abspath !== null ) {
4314
+ $abspath = cerber_get_abspath();
 
4315
  }
4316
+ $file_name = cerber_normal_path( $file_name );
4317
 
4318
+ if ( $file_name == $abspath . 'wp-config.php' ) {
4319
  return false;
4320
  }
4321
+ if ( ! file_exists( $abspath . 'wp-config.php' ) && $file_name == dirname( $abspath ) . DIRECTORY_SEPARATOR . 'wp-config.php' ) {
4322
  return false;
4323
  }
4324
  }
4358
  $ret .= ' ' . $txt;
4359
  }
4360
 
4361
+ return $ret;
4362
+ }
4363
+
4364
+ /**
4365
+ * Return the number of node if the request is originated from the Cerber Cloud, false otherwise
4366
+ *
4367
+ * @return bool|integer
4368
+ */
4369
+ function cerber_is_cloud_request() {
4370
+ static $ret = null;
4371
+
4372
+ if ( $ret !== null) {
4373
+ return $ret;
4374
+ }
4375
+
4376
+ if ( ! cerber_is_http_post() || empty( $_POST['cerber-cloud-key'] ) ) {
4377
+ $ret = false;
4378
+
4379
+ return $ret;
4380
+ }
4381
+
4382
+ $key = lab_get_key();
4383
+ if ( ! isset( $key[4] ) ) {
4384
+ $key = lab_get_key( true );
4385
+ }
4386
+ if ( $key[4] != $_POST['cerber-cloud-key'] ) {
4387
+ $ret = false;
4388
+
4389
+ return $ret;
4390
+ }
4391
+
4392
+ $ret = lab_get_real_node_id();
4393
+
4394
+ return $ret;
4395
+ }
4396
+
4397
+
4398
+ // TODO: debug, remove from production!
4399
+ /*
4400
+ add_action( 'init', function () {
4401
+ if ( ! empty( $_GET['scan-report'] ) && is_user_logged_in() ) {
4402
+ $scan = cerber_get_scan();
4403
+ $report = cerber_scan_report( $scan );
4404
+ if ( ! $report ) {
4405
+ echo 'Nothing to report';
4406
+ }
4407
+ echo $report;
4408
+ //cerber_send_email( 'scan', $report );
4409
+ die();
4410
+ }
4411
+ } );*/
4412
+
4413
+ /**
4414
+ * Creates a user report
4415
+ *
4416
+ * @param array $scan
4417
+ *
4418
+ * @return bool|string False if there is nothing to report
4419
+ */
4420
+ function cerber_scan_report( $scan ) {
4421
+ global $cerber_scan_mode;
4422
+
4423
+ $include = crb_get_settings( 'scan_reinc' );
4424
+
4425
+ $severity = array_intersect_key( array( 0, 1, 2, 3 ), $include ); // Severity are 0-4
4426
+ $types = array_keys( $include );
4427
+
4428
+ if ( ! $last_filtered = cerber_filter_issues( $scan, $types, $severity ) ) {
4429
+ return false;
4430
+ }
4431
+
4432
+ $issues = $last_filtered;
4433
+
4434
+ if ( ! $cerber_scan_mode ) {
4435
+ $cerber_scan_mode = $scan['mode'];
4436
+ }
4437
+ if ( $prev_id = cerber_get_prev_scan_id( $scan['id'] ) ) {
4438
+ $prev_scan = cerber_get_scan( $prev_id );
4439
+ }
4440
+ else {
4441
+ $prev_scan = null;
4442
+ }
4443
+
4444
+ $re = crb_get_settings( 'scan_relimit' );
4445
+ $prev_filtered = null;
4446
+ if ( $re > 1 ) {
4447
+ if ( $prev_scan ) {
4448
+ $prev_filtered = cerber_filter_issues( $prev_scan, $types, $severity );
4449
+ }
4450
+ }
4451
+
4452
+ if ( $prev_filtered ) {
4453
+ switch ( $re ) {
4454
+ case 3:
4455
+ $last_comp = $last_filtered;
4456
+ // Remove "xx ago" that always changing from scan to scan and affect checksum
4457
+ array_walk_recursive( $last_comp, function ( &$e, $key ) {
4458
+ if ( $key === 'time' ) {
4459
+ $e = '';
4460
+ }
4461
+ } );
4462
+ array_walk_recursive( $prev_filtered, function ( &$e, $key ) {
4463
+ if ( $key === 'time' ) {
4464
+ $e = '';
4465
+ }
4466
+ } );
4467
+ $hash1 = sha1( serialize( $last_comp ) );
4468
+ $hash2 = sha1( serialize( $prev_filtered ) );
4469
+ if ( $hash1 == $hash2 ) {
4470
+ return false;
4471
+ }
4472
+ break;
4473
+ case 5:
4474
+ $issues = cerber_get_new_issues( $prev_filtered, $last_filtered );
4475
+ break;
4476
+ }
4477
+ }
4478
+
4479
+ if ( ! $issues ) {
4480
+ return false;
4481
+ }
4482
+
4483
+
4484
+ // Generating the report
4485
+
4486
+ $base_url = cerber_admin_link( 'scanner' );
4487
+ $site_name = ( is_multisite() ) ? get_site_option( 'site_name' ) : get_option( 'blogname' );
4488
+
4489
+ $css_table = 'width: 95%; max-width: 1000px; margin:0 auto; margin-bottom: 10px; background-color: #f5f5f5; text-align: center; color: #000; font-family: Arial, Helvetica, sans-serif;';
4490
+ $css_td = 'padding: 0.5em 0.5em 0.5em 1em; text-align: left;';
4491
+ $css_border = 'border-bottom: solid 2px #f9f9f9;';
4492
+
4493
+ $ret = '';
4494
+
4495
+ $mode = ( $scan['mode'] == 'full' ) ? __( 'Full Scan Report', 'wp-cerber' ) : __( 'Quick Scan Report', 'wp-cerber' );
4496
+ $mode = '<a href="' . $base_url . '">' . $mode . '</a>';
4497
+
4498
+ // Summary
4499
+ $summary[] = '';
4500
+
4501
+ $diff = '';
4502
+ if ( ! empty( $prev_scan['scanned']['files'] ) ) {
4503
+ $diff = $scan['scanned']['files'] - $prev_scan['scanned']['files'];
4504
+ if ( absint( $diff ) > 0 ) {
4505
+ if ( $diff > 0 ) {
4506
+ $diff = '+' . $diff;
4507
+ }
4508
+ $diff = ' (' . $diff . ')';
4509
+ }
4510
+ }
4511
+ $summary[] = __( 'Files scanned', 'wp-cerber' ) . ' <b>' . $scan['scanned']['files'] . '</b>' . $diff;
4512
+
4513
+ // TODO: refactor, keep the counter it in $scan
4514
+ $tot = 0;
4515
+ foreach ( $scan['issues'] as $sec ) {
4516
+ foreach ( $sec['issues'] as $i ) {
4517
+ if ( $i[0] > CERBER_FOK ) {
4518
+ $tot ++;
4519
+ }
4520
+ }
4521
+ }
4522
+
4523
+ $diff = '';
4524
+ if ( ! empty( $prev_scan['issues'] ) ) {
4525
+ $prev_tot = 0;
4526
+ foreach ( $prev_scan['issues'] as $sec ) {
4527
+ foreach ( $sec['issues'] as $i ) {
4528
+ if ( $i[0] > CERBER_FOK ) {
4529
+ $prev_tot ++;
4530
+ }
4531
+ }
4532
+ }
4533
+
4534
+ if ( $prev_tot ) {
4535
+ $diff = $tot - $prev_tot;
4536
+ if ( absint( $diff ) > 0 ) {
4537
+ if ( $diff > 0 ) {
4538
+ $diff = '+' . $diff;
4539
+ }
4540
+ $diff = ' (' . $diff . ')';
4541
+ }
4542
+ }
4543
+ }
4544
+
4545
+ $summary[] = __( 'Issues total', 'wp-cerber' ) . ' <b>' . $tot . '</b>'.$diff;
4546
+ $summary = implode(' &nbsp;|&nbsp; ',$summary);
4547
+
4548
+
4549
+ $ret .= '<div style="' . $css_table . '"><div style="margin:0 auto; text-align: center;"><p style="font-size: 130%; padding-top: 0.5em;">' . $site_name . '</p><p style="padding-bottom: 1em;">' . $mode . $summary . '</p></div></div>';
4550
+
4551
+ // Issues
4552
+
4553
+ $isize = crb_get_settings( 'scan_isize' );
4554
+ $cols = ( $isize ) ? 3 : 2;
4555
+
4556
+ if ( $issues ) {
4557
+ $conames = array( 'crb-plugins' => 'plugin', 'crb-themes' => 'theme', 'crb-wordpress' => 'files' );
4558
+ $rows = array();
4559
+ //$rows[] = '<td style="'.$css_td.$css_border.'" colspan="2"><p style="line-height: 1.5em; font-weight: bold;">Issues</p></td>';
4560
+ foreach ( $issues as $section_id => $section ) {
4561
+ $c = ( isset( $conames[ $section['container'] ] ) ) ? ' ' . $conames[ $section['container'] ] : '';
4562
+ $rows[] = '<td style="' . $css_border . $css_td . '" colspan="'.$cols.'"><b>' . $section['name'] . $c . '</b></td>';
4563
+ $i = 0;
4564
+ foreach ( $section['issues'] as $single_issue ) {
4565
+ if ( $single_issue[0] < 10 ) {
4566
+ continue;
4567
+ }
4568
+ $i ++;
4569
+ $color = ( $single_issue[2] > 2 ) ? ' color: #dc2f34;' : '';
4570
+ //$bgcolor = ( $i % 2 == 0 ) ? ' bgcolor: #fff;' : '';
4571
+ $size = ( $isize ) ? '<td>' . $single_issue['data']['size'] . '</td>' : '';
4572
+ $rows[] = '<td style="' . $css_border . $css_td . ' font-size:94%; font-family: Menlo, Consolas, Monaco, monospace;">' . $single_issue[1] . '</td><td style="padding: 0.5em; text-align: center; ' . $color . $css_border . '">' . cerber_get_issue_label( $single_issue[0] ) . '</td>'.$size;
4573
+ }
4574
+ if ( ! $i ) {
4575
+ array_pop( $rows );
4576
+ }
4577
+ }
4578
+
4579
+ if ( ! $rows ) {
4580
+ return false;
4581
+ }
4582
+
4583
+ $ret .= '<table style="border-collapse: collapse; ' . $css_table . '"><tr>' . implode( '</tr><tr>', $rows ) . '</tr></table>';
4584
+ }
4585
+
4586
+ // Errors
4587
+
4588
+ if ( crb_get_settings( 'scan_ierrors' ) && $scan['errors']) {
4589
+ $ret .= '<table style="' . $css_table . '"><tr><td style="'.$css_td.' font-size:80%;" ><p style="font-weight: bold; margin:0;">Some errors occurred during the scan</p><ol style="padding-left: 1em;"><li>'.implode('</li><li>',$scan['errors']).'</li></ol></td></tr></table>';
4590
+ }
4591
+
4592
+ $ret = '<div style="width:100%; padding: 1em; margin:0; text-align: center; background-color: #f9f9f9;">' . $ret . '</div>';
4593
+
4594
+ $ret .= '<p>' . __( 'To view full report visit', 'wp-cerber' ) . ' <a href="' . $base_url . '">' . $base_url . '</a></p>';
4595
+
4596
+ return $ret;
4597
+
4598
+ }
4599
+
4600
+ /**
4601
+ * Filter out a list of issues for a user report
4602
+ *
4603
+ * @param array $scan
4604
+ * @param array $types
4605
+ * @param array $severity
4606
+ *
4607
+ * @return array
4608
+ */
4609
+ function cerber_filter_issues( $scan, $types, $severity ) {
4610
+ //$scan = cerber_get_scan($scan_id);
4611
+ $result = array();
4612
+ if ( empty( $scan['issues'] ) ) {
4613
+ return $result;
4614
+ }
4615
+ if ( $scan['issues'] ) {
4616
+ foreach ( $scan['issues'] as $section_id => $section ) {
4617
+ $list = array();
4618
+ foreach ( $section['issues'] as $issue ) {
4619
+ if ( in_array( $issue[2], $severity ) ) {
4620
+ $list[] = $issue;
4621
+ }
4622
+ elseif ( in_array( $issue[0], $types ) ) {
4623
+ $list[] = $issue;
4624
+ }
4625
+ elseif ( $issue[3] && in_array( $issue[3], $types ) ) {
4626
+ $list[] = $issue;
4627
+ }
4628
+ }
4629
+
4630
+ if ( $list ) {
4631
+ $result[ $section_id ] = $section;
4632
+ $result[ $section_id ]['issues'] = $list;
4633
+ }
4634
+ }
4635
+ }
4636
+
4637
+ return $result;
4638
+ }
4639
+
4640
+ function cerber_get_new_issues( $list_a, $list_b ) {
4641
+ $ret = array();
4642
+ foreach ( $list_b as $key => $new ) {
4643
+ if ( ! isset( $list_a[ $key ] ) ) {
4644
+ $ret[ $key ] = $new;
4645
+ continue;
4646
+ }
4647
+
4648
+ $new_elements = array();
4649
+ foreach ( $new['issues'] as $i => $b_issue ) {
4650
+ if ( ! empty( $b_issue[1] ) ) {
4651
+ $found = 0;
4652
+ foreach ( $list_a[ $key ]['issues'] as $a_issue ) {
4653
+ if ( $a_issue['data']['name'] == $b_issue['data']['name'] ) {
4654
+ $found = 1;
4655
+ break;
4656
+ }
4657
+ }
4658
+ if ( ! $found ) {
4659
+ $new_elements[] = $i;
4660
+ }
4661
+ }
4662
+ }
4663
+
4664
+ if ( $new_elements ) {
4665
+ $ret[ $key ] = $new;
4666
+ $all = array_keys( $new['issues'] );
4667
+ $diff = array_diff( $all, $new_elements );
4668
+
4669
+ foreach ( $diff as $i ) {
4670
+ unset( $ret[ $key ]['issues'][ $i ] );
4671
+ }
4672
+ }
4673
+
4674
+ }
4675
+
4676
  return $ret;
4677
  }
cerber-tools.php CHANGED
@@ -372,6 +372,7 @@ function cerber_show_wp_diag(){
372
  array( 'Content folder', dirname( cerber_get_plugins_dir() ) ),
373
  //array( 'Plugins folder (WP_PLUGIN_DIR) ', WP_PLUGIN_DIR ),
374
  array( 'Plugins folder', cerber_get_plugins_dir() ),
 
375
  array( 'Must use plugin folder (WPMU_PLUGIN_DIR) ', WPMU_PLUGIN_DIR ),
376
  array( 'Folder for temporary files', ini_get( 'upload_tmp_dir' ) ),
377
  array( 'Folder for session data', session_save_path() ),
372
  array( 'Content folder', dirname( cerber_get_plugins_dir() ) ),
373
  //array( 'Plugins folder (WP_PLUGIN_DIR) ', WP_PLUGIN_DIR ),
374
  array( 'Plugins folder', cerber_get_plugins_dir() ),
375
+ array( 'Themes folder', cerber_get_themes_dir() ),
376
  array( 'Must use plugin folder (WPMU_PLUGIN_DIR) ', WPMU_PLUGIN_DIR ),
377
  array( 'Folder for temporary files', ini_get( 'upload_tmp_dir' ) ),
378
  array( 'Folder for session data', session_save_path() ),
changelog.txt CHANGED
@@ -1,3 +1,11 @@
 
 
 
 
 
 
 
 
1
  = 7.0 =
2
  * Cerber Security Scanner: system integrity checker, malware detector and malware removal tool.
3
  * New: a new setting for Traffic Inspector: Use White IP Access List.
1
+ = 7.2 =
2
+ * New: Monitoring new and changed files.
3
+ * New: Detecting malicious redirections and directives in .htaccess files.
4
+ * New: Automated hourly and daily scheduled scans with flexible email reports.
5
+ * Update: Added a protection from logging wrong time stamps on some not correctly configured servers.
6
+ * Bug fixed: Unexpected warning messages in the WordPress dashboard.
7
+ * Bug fixed: Some file status links on the scanner results page may not work.
8
+
9
  = 7.0 =
10
  * Cerber Security Scanner: system integrity checker, malware detector and malware removal tool.
11
  * New: a new setting for Traffic Inspector: Use White IP Access List.
common.php CHANGED
@@ -68,7 +68,7 @@ function cerber_admin_link($tab = '', $args = array()){
68
  elseif ( in_array( $tab, array( 'geo' ) ) ) {
69
  $page = 'cerber-rules';
70
  }
71
- elseif ( in_array( $tab, array( 'scanner', 'scan_settings' ) ) ) {
72
  $page = 'cerber-integrity';
73
  }
74
  else {
@@ -959,17 +959,53 @@ function cerber_auto_date( $time ) {
959
  * @return string
960
  */
961
  function cerber_date( $timestamp ) {
 
 
 
 
 
 
962
  $timestamp = absint( $timestamp );
963
- $gmt_offset = get_option( 'gmt_offset' ) * 3600;
964
- if ( $df = crb_get_settings( 'dateformat' ) ) {
965
- return date_i18n( $df, $gmt_offset + $timestamp );
 
 
 
 
 
966
  }
967
- else {
968
- $tf = get_option( 'time_format' );
969
- $df = get_option( 'date_format' );
970
 
971
- return date_i18n( $df, $gmt_offset + $timestamp ) . ', ' . date_i18n( $tf, $gmt_offset + $timestamp );
 
972
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
973
  }
974
 
975
  function cerber_percent($one,$two){
@@ -1125,17 +1161,22 @@ function cerber_detect_browser( $ua ) {
1125
  elseif (0 === strpos( $ua, 'Wget/' )){
1126
  return htmlentities( $ua );
1127
  }
1128
-
1129
- $browsers = array( 'Firefox' => 'Firefox',
1130
- 'OPR' => 'Opera',
1131
- 'Opera' => 'Opera',
1132
- 'YaBrowser' => 'Yandex Browser',
1133
- 'Trident' => 'Internet Explorer',
1134
- 'IE' => 'Internet Explorer',
1135
- 'Edge' => 'Microsoft Edge',
1136
- 'Chrome' => 'Chrome',
1137
- 'Safari' => 'Safari',
1138
- 'Lynx' => 'Lynx',
 
 
 
 
 
1139
  );
1140
 
1141
  $systems = array( 'Android' , 'Linux', 'Windows', 'iPhone', 'iPad', 'Macintosh', 'OpenBSD', 'Unix' );
@@ -1167,7 +1208,7 @@ function cerber_detect_browser( $ua ) {
1167
  $ret = __( 'Unknown', 'wp-cerber' );
1168
  }
1169
 
1170
- return htmlentities($ret);
1171
  }
1172
 
1173
  /**
@@ -1202,6 +1243,15 @@ function cerber_is_crawler( $ua ) {
1202
  return 0;
1203
  }
1204
 
 
 
 
 
 
 
 
 
 
1205
 
1206
  /**
1207
  * Natively escape an SQL query
@@ -1214,13 +1264,15 @@ function cerber_is_crawler( $ua ) {
1214
  * @return string
1215
  * @since 6.0
1216
  */
1217
- function cerber_real_escape($string){
1218
- global $wpdb;
1219
- if ( $wpdb->use_mysqli ) {
1220
- $escaped = mysqli_real_escape_string( $wpdb->dbh, $string );
 
 
1221
  }
1222
  else {
1223
- $escaped = mysql_real_escape_string( $string, $wpdb->dbh );
1224
  }
1225
 
1226
  return $escaped;
@@ -1239,10 +1291,6 @@ function cerber_real_escape($string){
1239
  function cerber_db_query( $query ) {
1240
  global $cerber_db_errors;
1241
 
1242
- if ( ! isset( $cerber_db_errors ) ) {
1243
- $cerber_db_errors = array();
1244
- }
1245
-
1246
  $db = cerber_get_db();
1247
 
1248
  if ( ! $db ) {
@@ -1251,7 +1299,7 @@ function cerber_db_query( $query ) {
1251
  return false;
1252
  }
1253
 
1254
- if ( $db->use_mysqli ) {
1255
  $ret = mysqli_query( $db->dbh, $query );
1256
  if ( ! $ret ) {
1257
  $cerber_db_errors[] = mysqli_error( $db->dbh ) . ' for the query: ' . $query;
@@ -1273,7 +1321,7 @@ function cerber_db_get_results( $query, $type = MYSQLI_ASSOC ) {
1273
  $ret = array();
1274
 
1275
  if ( $result = cerber_db_query( $query ) ) {
1276
- if ( $db->use_mysqli ) {
1277
  //$ret = $result->fetch_all( $type );
1278
  if ( $type == MYSQLI_ASSOC ) {
1279
  while ( $row = mysqli_fetch_assoc( $result ) ) {
@@ -1298,21 +1346,58 @@ function cerber_db_get_results( $query, $type = MYSQLI_ASSOC ) {
1298
  $ret[] = $row;
1299
  }
1300
  }
 
1301
  }
1302
  }
1303
 
1304
  return $ret;
1305
  }
1306
 
1307
- function cerber_db_get_row( $query ) {
1308
- $db = cerber_get_db();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1309
 
1310
  if ( $result = cerber_db_query( $query ) ) {
1311
- if ( $db->use_mysqli ) {
1312
- $ret = mysqli_fetch_array( $result, MYSQLI_ASSOC );
 
 
 
1313
  }
1314
  else {
1315
- $ret = mysql_fetch_array( $result, MYSQL_ASSOC ); // For compatibility reason only
 
 
 
1316
  }
1317
  }
1318
  else {
@@ -1323,15 +1408,16 @@ function cerber_db_get_row( $query ) {
1323
  }
1324
 
1325
  function cerber_db_get_var( $query ) {
1326
- $db = cerber_get_db();
1327
 
1328
  if ( $result = cerber_db_query( $query ) ) {
1329
- if ( $db->use_mysqli ) {
1330
  //$r = $result->fetch_row();
1331
  $r = mysqli_fetch_row( $result );
 
1332
  }
1333
  else {
1334
  $r = mysql_fetch_row( $result ); // For compatibility reason only
 
1335
  }
1336
 
1337
  return $r[0];
@@ -1340,14 +1426,23 @@ function cerber_db_get_var( $query ) {
1340
  return false;
1341
  }
1342
 
 
 
 
1343
  function cerber_get_db() {
1344
  global $wpdb, $cerber_db_errors;
1345
  static $db;
1346
 
1347
- if ( ! isset( $db ) || ! is_object( $db ) ) {
 
 
 
 
 
1348
  // Check for connected DB handler
1349
  if ( ! is_object( $wpdb ) || empty( $wpdb->dbh ) ) {
1350
  if ( ! $db = cerber_db_connect() ) {
 
1351
  return false;
1352
  }
1353
  }
68
  elseif ( in_array( $tab, array( 'geo' ) ) ) {
69
  $page = 'cerber-rules';
70
  }
71
+ elseif ( in_array( $tab, array( 'scanner', 'scan_settings', 'scan_schedule' ) ) ) {
72
  $page = 'cerber-integrity';
73
  }
74
  else {
959
  * @return string
960
  */
961
  function cerber_date( $timestamp ) {
962
+ static $gmt_offset;
963
+
964
+ if ( $gmt_offset === null) {
965
+ $gmt_offset = get_option( 'gmt_offset' ) * 3600;
966
+ }
967
+
968
  $timestamp = absint( $timestamp );
969
+ return date_i18n( cerber_get_dt_format(), $gmt_offset + $timestamp );
970
+ }
971
+
972
+ function cerber_get_dt_format() {
973
+ static $ret;
974
+
975
+ if ( $ret !== null) {
976
+ return $ret;
977
  }
 
 
 
978
 
979
+ if ( $ret = crb_get_settings( 'dateformat' ) ) {
980
+ return $ret;
981
  }
982
+
983
+ $tf = get_option( 'time_format' );
984
+ $df = get_option( 'date_format' );
985
+ $ret = $df . ', ' . $tf;
986
+
987
+ return $ret;
988
+ }
989
+
990
+ function cerber_is_ampm() {
991
+ if ( 'a' == strtolower( substr( trim( get_option( 'time_format' ) ), - 1 ) ) ) {
992
+ return true;
993
+ }
994
+
995
+ return false;
996
+ }
997
+
998
+ function cerber_sec_from_time( $time ) {
999
+ list( $h, $m ) = explode( ':', trim( $time ) );
1000
+ $h = absint( $h );
1001
+ $m = absint( $m );
1002
+ $ret = $h * 3600 + $m * 60;
1003
+
1004
+ if ( strpos( strtolower( $time ), 'pm' ) ) {
1005
+ $ret += 12 * 3600;
1006
+ }
1007
+
1008
+ return $ret;
1009
  }
1010
 
1011
  function cerber_percent($one,$two){
1161
  elseif (0 === strpos( $ua, 'Wget/' )){
1162
  return htmlentities( $ua );
1163
  }
1164
+ elseif (0 === strpos( $ua, 'WordPress/' )){
1165
+ list( $ret ) = explode( ';', $ua, 2 );
1166
+ return htmlentities( $ret );
1167
+ }
1168
+
1169
+ $browsers = array(
1170
+ 'Firefox' => 'Firefox',
1171
+ 'OPR' => 'Opera',
1172
+ 'Opera' => 'Opera',
1173
+ 'YaBrowser' => 'Yandex Browser',
1174
+ 'Trident' => 'Internet Explorer',
1175
+ 'IE' => 'Internet Explorer',
1176
+ 'Edge' => 'Microsoft Edge',
1177
+ 'Chrome' => 'Chrome',
1178
+ 'Safari' => 'Safari',
1179
+ 'Lynx' => 'Lynx',
1180
  );
1181
 
1182
  $systems = array( 'Android' , 'Linux', 'Windows', 'iPhone', 'iPad', 'Macintosh', 'OpenBSD', 'Unix' );
1208
  $ret = __( 'Unknown', 'wp-cerber' );
1209
  }
1210
 
1211
+ return htmlentities( $ret );
1212
  }
1213
 
1214
  /**
1243
  return 0;
1244
  }
1245
 
1246
+ function cerber_db_use_mysqli() {
1247
+ static $mysqli;
1248
+ if ( $mysqli === null ) {
1249
+ $db = cerber_get_db();
1250
+ $mysqli = $db->use_mysqli;
1251
+ }
1252
+
1253
+ return $mysqli;
1254
+ }
1255
 
1256
  /**
1257
  * Natively escape an SQL query
1264
  * @return string
1265
  * @since 6.0
1266
  */
1267
+ function cerber_real_escape( $string ) {
1268
+
1269
+ $db = cerber_get_db();
1270
+
1271
+ if ( cerber_db_use_mysqli() ) {
1272
+ $escaped = mysqli_real_escape_string( $db->dbh, $string );
1273
  }
1274
  else {
1275
+ $escaped = mysql_real_escape_string( $string, $db->dbh );
1276
  }
1277
 
1278
  return $escaped;
1291
  function cerber_db_query( $query ) {
1292
  global $cerber_db_errors;
1293
 
 
 
 
 
1294
  $db = cerber_get_db();
1295
 
1296
  if ( ! $db ) {
1299
  return false;
1300
  }
1301
 
1302
+ if ( cerber_db_use_mysqli() ) {
1303
  $ret = mysqli_query( $db->dbh, $query );
1304
  if ( ! $ret ) {
1305
  $cerber_db_errors[] = mysqli_error( $db->dbh ) . ' for the query: ' . $query;
1321
  $ret = array();
1322
 
1323
  if ( $result = cerber_db_query( $query ) ) {
1324
+ if ( cerber_db_use_mysqli() ) {
1325
  //$ret = $result->fetch_all( $type );
1326
  if ( $type == MYSQLI_ASSOC ) {
1327
  while ( $row = mysqli_fetch_assoc( $result ) ) {
1346
  $ret[] = $row;
1347
  }
1348
  }
1349
+ mysql_free_result( $result ); // For compatibility reason only
1350
  }
1351
  }
1352
 
1353
  return $ret;
1354
  }
1355
 
1356
+ function cerber_db_get_row( $query, $type = MYSQLI_ASSOC ) {
1357
+
1358
+ if ( $result = cerber_db_query( $query ) ) {
1359
+ if ( cerber_db_use_mysqli() ) {
1360
+ if ($type == 5) {
1361
+ $ret = $result->fetch_object();
1362
+ }
1363
+ else {
1364
+ $ret = $result->fetch_array( $type );
1365
+ }
1366
+ $result->free();
1367
+ }
1368
+ else {
1369
+ if ($type == 5) {
1370
+ $ret = mysql_fetch_object( $result ); // For compatibility reason only
1371
+ }
1372
+ else {
1373
+ $ret = mysql_fetch_array( $result, MYSQL_ASSOC ); // For compatibility reason only
1374
+ }
1375
+ mysql_free_result( $result ); // For compatibility reason only
1376
+ }
1377
+ }
1378
+ else {
1379
+ $ret = false;
1380
+ }
1381
+
1382
+ return $ret;
1383
+ }
1384
+
1385
+ function cerber_db_get_col( $query ) {
1386
+
1387
+ $ret = array();
1388
 
1389
  if ( $result = cerber_db_query( $query ) ) {
1390
+ if ( cerber_db_use_mysqli() ) {
1391
+ while ( $row = $result->fetch_row() ) {
1392
+ $ret[] = $row[0];
1393
+ }
1394
+ $result->free();
1395
  }
1396
  else {
1397
+ while ( $row = mysql_fetch_row( $result ) ) { // For compatibility reason only
1398
+ $ret[] = $row[0];
1399
+ }
1400
+ mysql_free_result( $result ); // For compatibility reason only
1401
  }
1402
  }
1403
  else {
1408
  }
1409
 
1410
  function cerber_db_get_var( $query ) {
 
1411
 
1412
  if ( $result = cerber_db_query( $query ) ) {
1413
+ if ( cerber_db_use_mysqli() ) {
1414
  //$r = $result->fetch_row();
1415
  $r = mysqli_fetch_row( $result );
1416
+ $result->free();
1417
  }
1418
  else {
1419
  $r = mysql_fetch_row( $result ); // For compatibility reason only
1420
+ mysql_free_result( $result ); // For compatibility reason only
1421
  }
1422
 
1423
  return $r[0];
1426
  return false;
1427
  }
1428
 
1429
+ /**
1430
+ * @return bool|wpdb
1431
+ */
1432
  function cerber_get_db() {
1433
  global $wpdb, $cerber_db_errors;
1434
  static $db;
1435
 
1436
+ if ( ! isset( $cerber_db_errors ) ) {
1437
+ $cerber_db_errors = array();
1438
+ }
1439
+
1440
+ //if ( ! isset( $db ) || ! is_object( $db ) ) {
1441
+ if ( ! isset( $db ) ) {
1442
  // Check for connected DB handler
1443
  if ( ! is_object( $wpdb ) || empty( $wpdb->dbh ) ) {
1444
  if ( ! $db = cerber_db_connect() ) {
1445
+ $cerber_db_errors[] = 'Unable to connect to the DB';
1446
  return false;
1447
  }
1448
  }
dashboard.php CHANGED
@@ -45,7 +45,7 @@ else {
45
  }
46
  function cerber_admin_menu() {
47
 
48
- if ( cerber_is_admin_page( false ) ) {
49
  cerber_check_environment();
50
  }
51
 
@@ -416,7 +416,7 @@ function cerber_admin_request(){
416
  if ( $test = cerber_get_get( 'testnotify' ) ) {
417
  //$to = implode(', ',cerber_get_email());
418
  $to = cerber_get_email( $test );
419
- if ( cerber_send_notify( $test ) ) {
420
  cerber_admin_message( __( 'Email has been sent to', 'wp-cerber' ) . ' ' . $to );
421
  }
422
  else {
@@ -1031,7 +1031,7 @@ function cerber_user_extra_view( $user_id, $context = 'activity' ) {
1031
  /*
1032
  Check if currently displayed page is a Cerber admin dashboard page with optional checking a set of GET params
1033
  */
1034
- function cerber_is_admin_page( $force = true, $params = array() ) {
1035
 
1036
  if ( ! is_admin() ) {
1037
  return false;
@@ -1237,9 +1237,10 @@ function cerber_quick_w(){
1237
  $status = ( '' === crb_get_settings( 'tienabled' ) ) ? '<span style="color: red;">'.__('disabled','wp-cerber').'</span>' : __('enabled','wp-cerber');
1238
  echo '<tr class="with-padding"><td>'.__('Traffic Inspector','wp-cerber').'</td><td><b>'.$status.'</b></td></tr>';
1239
 
1240
- if (lab_lab()){
1241
- $status = ( !lab_is_cloud_ok() ) ? '<span style="color: red;">'.__('no connection','wp-cerber').'</span>' : __('active','wp-cerber');
1242
- echo '<tr><td>Cloud Protection</td><td><b>'.$status.'</b></td></tr>';
 
1243
  }
1244
 
1245
  $s = '';
@@ -1247,7 +1248,15 @@ function cerber_quick_w(){
1247
  if ( WEEK_IN_SECONDS < ( time() - $scan['finished'] ) ) {
1248
  $s = 'style="color: red;"';
1249
  }
1250
- echo '<tr ' . $s . '><td>Malware scan</td><td><b><a href="'.cerber_admin_link( 'scanner' ).'">' . cerber_auto_date( $scan['finished'] ) . '</a></b></td></tr>';
 
 
 
 
 
 
 
 
1251
 
1252
  /*
1253
  $dev = crb_get_settings('pbdevice');
@@ -1288,30 +1297,42 @@ function cerber_show_scan_help() {
1288
 
1289
  <h2>Using the scanner</h2>
1290
 
1291
- <p>To start scanning, click either the Start quick scan button, or the Start full scan button. Do not close the browser window while the scan in progress. You may just open a new browser tab to do something else on the website. Once the scan is finished you can close the windows, the results are stored in the local database until the next scan.</p>
 
 
1292
 
1293
- <p>Depending on server performance and the number of files, the Quick Scan may take about 3-5 minutes and the Full Scan can take about ten minutes or less.</p>
1294
 
1295
- <p>During the scan, the plugin verifies plugins, themes, and WordPress by trying to download checksum data from the wordpress.org. If the integrity data is not available, you can upload appropriate source ZIP archive for a plugin or a theme. The plugin will use it to detect changes in files. You need to do it once, after the first scan.</p>
1296
 
1297
  <h2>What's the Quick Scan?</h2>
1298
 
1299
- <p>During the Quick Scan, the scanner verifies the integrity and inspects code of all files with executable extensions only.</p>
1300
 
1301
  <h2>What's the Full Scan?</h2>
1302
 
1303
- <p>During the Full Scan, the scanner verifies the integrity and examines the content of all files on the website.</p>
 
 
 
 
 
 
1304
 
1305
- <p><a href="https://wpcerber.com/wordpress-security-scanner/" target="_blank">Read more on www.wpcerber.com</a></p>
 
 
 
 
 
 
1306
 
1307
  </td>
1308
  <td>
1309
 
1310
  <h2>Interpreting scan results</h2>
1311
 
1312
- <p>The scanner will show you a list of issues and possible actions you can take. If the integrity of an object has been verified, you see a green mark Verified. If you see the "Integrity data not found" message, please upload a reference ZIP archive by clicking "Resolve issue". For the rest of issues, click on an appropriate issue link. To view the content of a file, click on its name.</p>
1313
-
1314
- <p>The scanner shows you short file names, to view full file names with absolute path, click the Show full paths link.</p>
1315
 
1316
  <h2>Deleting files</h2>
1317
 
@@ -1319,7 +1340,7 @@ function cerber_show_scan_help() {
1319
 
1320
  <h2>Restoring deleted files</h2>
1321
 
1322
- <p>If you delete an important file by chance, you can restore the file from a quarantine folder. The location of the folder is shown on the Tools / Diagnostic page. This folder is not accessible from the Internet. To restore a deleted file you need to use a file manager in you hosting control panel. The original name and location of the deleted file is saved in the .restore file. Its a text file so you can open it in a browser or a file viewer.</p>
1323
 
1324
  <h2>Troubleshooting</h2>
1325
 
@@ -1327,6 +1348,8 @@ function cerber_show_scan_help() {
1327
 
1328
  <p>The scanner requires the CURL library to be enabled for PHP scripts. Usually, it's enabled by default.</p>
1329
 
 
 
1330
  </td>
1331
  </tr>
1332
  </table>
@@ -1376,6 +1399,14 @@ function cerber_show_general_help() {
1376
  <input type="text" style="width: 80%;" name="s" placeholder="Enter term to search"><input type="submit" value="Search" class="button button-primary">
1377
  </form>
1378
 
 
 
 
 
 
 
 
 
1379
  <h3>Traffic Inspector</h3>
1380
 
1381
  <p>Traffic Inspector is a set of specialized request inspection algorithms that acts as an additional protection layer (firewall) for your WordPress</p>
@@ -1673,8 +1704,11 @@ function cerber_show_aside($page){
1673
  $aside[] = '<div class="crb-box" id = "crb-blog">
1674
  <div class="crb-box-inner">
1675
  <!-- <h3><span class="dashicons-before dashicons-lightbulb"></span> Read Cerber\'s blog</h3> -->
1676
- <h3>Security tips & recipes</h3>
1677
 
 
 
 
1678
  <p><a href="https://wpcerber.com/wordpress-traffic-inspector-how-to/" target="_blank">Quick tips for Traffic Inspector</a>
1679
  <p><a href="https://wpcerber.com/traffic-inspector-in-a-nutshell/" target="_blank">Traffic Inspector in a nutshell</a>
1680
  <p><a href="https://wpcerber.com/wordpress-ip-address-detection/" target="_blank">Solving problem with incorrect IP address detection</a>
@@ -1717,7 +1751,7 @@ function cerber_show_admin_notice(){
1717
  '</p></div>';
1718
  }
1719
 
1720
- if ( ! cerber_is_admin_page() ) {
1721
  return;
1722
  }
1723
 
@@ -1757,7 +1791,7 @@ function cerber_show_admin_notice(){
1757
  update_site_option('cerber_admin_notice', null);
1758
  update_site_option('cerber_admin_message', null);
1759
 
1760
- if ( ! cerber_is_admin_page( false ) ) {
1761
  return;
1762
  }
1763
 
@@ -2022,16 +2056,24 @@ function cerber_admin_assets() {
2022
 
2023
  $crb_assets_url = plugin_dir_url( __FILE__ ) . 'assets/';
2024
 
2025
- if ( cerber_is_admin_page( false ) ) {
 
2026
  wp_register_style( 'crb_multi_css', $crb_assets_url . 'multi/multi.css', null, CERBER_VER );
2027
  wp_enqueue_style( 'crb_multi_css' );
2028
  wp_enqueue_script( 'crb_multi_js', $crb_assets_url . 'multi/multi.min.js', array(), CERBER_VER );
 
 
 
 
 
2029
  add_thickbox();
2030
  }
2031
 
2032
  if ( ! defined( 'CERBER_BETA' ) ) {
2033
  wp_enqueue_script( 'cerber_js', $crb_assets_url . 'admin.js', array( 'jquery' ), CERBER_VER, true );
2034
- wp_enqueue_script( 'cerber_scan', $crb_assets_url . 'scanner.js', array( 'jquery' ), CERBER_VER, true );
 
 
2035
  }
2036
 
2037
  wp_register_style( 'cerber_css', $crb_assets_url . 'admin.css', null, CERBER_VER );
@@ -2051,20 +2093,15 @@ function cerber_admin_assets() {
2051
  add_action('admin_head', 'cerber_admin_head' );
2052
  add_action('customize_controls_print_scripts', 'cerber_admin_head' ); // @since 5.8.1
2053
  function cerber_admin_head(){
2054
- global $assets_url, $crb_assets_url, $crb_ajax_loader;
2055
 
2056
- $assets_url = cerber_plugin_dir_url() . 'assets/';
2057
 
2058
  $crb_assets_url = cerber_plugin_dir_url() . 'assets/';
2059
  $crb_ajax_loader = $crb_assets_url . 'ajax-loader.gif';
2060
  $crb_ajax_nonce = wp_create_nonce( 'crb-ajax-admin' );
2061
 
2062
- if (lab_lab()) {
2063
- $crb_lab_available = 'true';
2064
- }
2065
- else {
2066
- $crb_lab_available = 'false';
2067
- }
2068
 
2069
  ?>
2070
 
@@ -2074,8 +2111,8 @@ function cerber_admin_head(){
2074
  crb_lab_available = <?php echo $crb_lab_available; ?>;
2075
 
2076
  crb_scan_msg_steps = <?php echo json_encode( cerber_step_desc() ); ?>;
2077
- crb_scan_msg_issues = <?php echo json_encode( cerber_get_issue_desc() ); ?>;
2078
- crb_scan_msg_risks = <?php echo json_encode( cerber_get_risk_desc() ); ?>;
2079
  </script>
2080
 
2081
  <?php
@@ -2131,7 +2168,7 @@ function cerber_admin_head(){
2131
  <?php
2132
  endif;
2133
 
2134
- if ( !cerber_is_admin_page( false ) ) {
2135
  return;
2136
  }
2137
 
@@ -2198,10 +2235,47 @@ function cerber_admin_footer() {
2198
 
2199
  // ------------------------------------------------------
2200
 
2201
- if ( defined( 'CERBER_BETA' ) && cerber_is_admin_page( false ) ) :
 
 
 
 
2202
  ?>
2203
  <script type="text/javascript">
2204
  <?php readfile( dirname( __FILE__ ) . '/assets/admin.js' ); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2205
  </script>
2206
  <?php
2207
  endif;
@@ -2210,12 +2284,14 @@ function cerber_admin_footer() {
2210
 
2211
  add_filter( 'admin_footer_text','cerber_footer_text1');
2212
  function cerber_footer_text1($text){
2213
- if (!cerber_is_admin_page(false)) return $text;
 
 
2214
  return 'If you like how <strong>WP Cerber</strong> protects your website, please <a target="_blank" href="https://wordpress.org/support/plugin/wp-cerber/reviews/#new-post">leave it a &#9733; &#9733; &#9733; &#9733; &#9733; rating</a>. Thanks!';
2215
  }
2216
  add_filter( 'update_footer','cerber_footer_text2', 1000);
2217
  function cerber_footer_text2($text){
2218
- if ( ! cerber_is_admin_page( false ) ) {
2219
  return $text;
2220
  }
2221
  if ( lab_lab() ) {
45
  }
46
  function cerber_admin_menu() {
47
 
48
+ if ( cerber_is_admin_page() ) {
49
  cerber_check_environment();
50
  }
51
 
416
  if ( $test = cerber_get_get( 'testnotify' ) ) {
417
  //$to = implode(', ',cerber_get_email());
418
  $to = cerber_get_email( $test );
419
+ if ( cerber_send_email( $test ) ) {
420
  cerber_admin_message( __( 'Email has been sent to', 'wp-cerber' ) . ' ' . $to );
421
  }
422
  else {
1031
  /*
1032
  Check if currently displayed page is a Cerber admin dashboard page with optional checking a set of GET params
1033
  */
1034
+ function cerber_is_admin_page( $force = false, $params = array() ) {
1035
 
1036
  if ( ! is_admin() ) {
1037
  return false;
1237
  $status = ( '' === crb_get_settings( 'tienabled' ) ) ? '<span style="color: red;">'.__('disabled','wp-cerber').'</span>' : __('enabled','wp-cerber');
1238
  echo '<tr class="with-padding"><td>'.__('Traffic Inspector','wp-cerber').'</td><td><b>'.$status.'</b></td></tr>';
1239
 
1240
+ $lab = lab_lab();
1241
+ if ( $lab ) {
1242
+ $status = ( ! lab_is_cloud_ok() ) ? '<span style="color: red;">' . __( 'no connection', 'wp-cerber' ) . '</span>' : __( 'active', 'wp-cerber' );
1243
+ echo '<tr><td>Cloud Protection</td><td><b>' . $status . '</b></td></tr>';
1244
  }
1245
 
1246
  $s = '';
1248
  if ( WEEK_IN_SECONDS < ( time() - $scan['finished'] ) ) {
1249
  $s = 'style="color: red;"';
1250
  }
1251
+
1252
+ echo '<tr ' . $s . '><td>Last malware scan</td><td><a href="' . cerber_admin_link( 'scanner' ) . '">' . $scan['mode_h'] . ' ' . cerber_auto_date( $scan['started'] ) . '</a></td></tr>';
1253
+
1254
+ $link = cerber_admin_link( 'scan_schedule' );
1255
+ $q = ( ! $lab ) ? __( 'Disabled', 'wp-cerber' ) : cerber_get_qs( crb_get_settings( 'scan_aquick' ) );
1256
+ echo '<tr><td>' . __( 'Quick Scan', 'wp-cerber' ) . '</td><td><a href="' . $link . '">' . $q . '</a></td></tr>';
1257
+ $f = ( ! $lab || !crb_get_settings( 'scan_afull-enabled' ) ) ? __( 'Disabled', 'wp-cerber' ) : crb_get_settings( 'scan_afull' );
1258
+ echo '<tr><td>' . __( 'Full Scan', 'wp-cerber' ) . '</td><td><a href="' . $link . '">' . $f . '</a></td></tr>';
1259
+
1260
 
1261
  /*
1262
  $dev = crb_get_settings('pbdevice');
1297
 
1298
  <h2>Using the scanner</h2>
1299
 
1300
+ <p>To start scanning, click either the Start Quick Scan button or the Start Full Scan button. Do not close the browser window while the scan is in progress. You may just open a new browser tab to do something else on the website. Once the scan is finished you can close the window, the results are stored in the DB until the next scan.</p>
1301
+
1302
+ <p>Depending on server performance and the number of files, the Quick scan may take about 3-5 minutes and the Full scan can take about five minutes or less.</p>
1303
 
1304
+ <p>During the scan, the plugin verifies plugins, themes, and WordPress by trying to retrieve checksum data from wordpress.org. If the integrity data is not available, you can upload an appropriate source ZIP archive for a plugin or a theme. The plugin will use it to detect changes in files. You need to do it once, after the first scan.</p>
1305
 
1306
+ <p>Read more: <a href="https://wpcerber.com/malware-scanner-settings/" target="_blank">Cerber Security Scanner Settings</a></p>
1307
 
1308
  <h2>What's the Quick Scan?</h2>
1309
 
1310
+ <p>During the Quick Scan, the scanner verifies the integrity and inspects the code of all files with executable extensions only.</p>
1311
 
1312
  <h2>What's the Full Scan?</h2>
1313
 
1314
+ <p>During the Full Scan, the scanner verifies the integrity and inspects the contents of all files on the website.</p>
1315
+
1316
+ <p>Read more: <a href="https://wpcerber.com/wordpress-security-scanner-scan-malware-detect/" target="_blank">What Cerber Security Scanner scans and detects</a>
1317
+
1318
+ <h2>Configure scheduled scans</h2>
1319
+
1320
+ <p>In the Automated recurring scan schedule section you set up your schedule. Select desired frequency of the Quick Scan and specify the time of the Full Scan.</p>
1321
 
1322
+ <p>The Scan results reporting section is about reporting. Here you can easily and flexible configure a set of conditions for generating and sending reports.</p>
1323
+
1324
+ <p>The email report will only include issues that match conditions in the Report an issue if any of the following is true filter. So this setting works as a filter for issues you want to get in a email report. The report will only be sent if there are issues to report and the following condition is true.</p>
1325
+
1326
+ <p>The second condition is configured with Send email report. The report will be sent if a selected condition is true. The last option is the most restrictive.</p>
1327
+
1328
+ <p>Read more: <a href="https://wpcerber.com/automated-recurring-malware-scans/" target="_blank">Automated recurring scans and email reporting</a></p>
1329
 
1330
  </td>
1331
  <td>
1332
 
1333
  <h2>Interpreting scan results</h2>
1334
 
1335
+ <p>The scanner shows you a list of issues and possible actions you can take. If the integrity of an object has been verified, you see a green mark Verified. If you see the Integrity data not found message, you need to upload a reference ZIP archive by clicking Resolve issue”. For all other issues, click on an appropriate issue link. To view the content of a file, click on its name.</p>
 
 
1336
 
1337
  <h2>Deleting files</h2>
1338
 
1340
 
1341
  <h2>Restoring deleted files</h2>
1342
 
1343
+ <p>If you delete an important file by chance, you can restore the file from a quarantine folder. The location of the folder is shown on the Tools / Diagnostic page. This folder is not accessible from the Internet. To restore a deleted file you need to use a file manager in your hosting control panel. The original name and location of the deleted file is saved in the .restore file. It's a text file so you can open it in a browser or a file viewer.</p>
1344
 
1345
  <h2>Troubleshooting</h2>
1346
 
1348
 
1349
  <p>The scanner requires the CURL library to be enabled for PHP scripts. Usually, it's enabled by default.</p>
1350
 
1351
+ <p>Read more: <a href="https://wpcerber.com/wordpress-security-scanner/" target="_blank">Malware Scanner & Integrity Checker</a></p>
1352
+
1353
  </td>
1354
  </tr>
1355
  </table>
1399
  <input type="text" style="width: 80%;" name="s" placeholder="Enter term to search"><input type="submit" value="Search" class="button button-primary">
1400
  </form>
1401
 
1402
+ <h3>Troubleshooting</h3>
1403
+
1404
+ <p><a href="https://wpcerber.com/antispam-exception-for-specific-http-request/">Configuring HTTP request exceptions for the antispam engine</a></p>
1405
+
1406
+ <p><a href="https://wpcerber.com/wordpress-probing-for-vulnerable-php-code/">I’m getting "Probing for vulnerable PHP code"</a></p>
1407
+
1408
+ <p><a href="https://wpcerber.com/firewall-http-requests-are-being-blocked/">Some legitimate HTTP requests are being blocked</a></p>
1409
+
1410
  <h3>Traffic Inspector</h3>
1411
 
1412
  <p>Traffic Inspector is a set of specialized request inspection algorithms that acts as an additional protection layer (firewall) for your WordPress</p>
1704
  $aside[] = '<div class="crb-box" id = "crb-blog">
1705
  <div class="crb-box-inner">
1706
  <!-- <h3><span class="dashicons-before dashicons-lightbulb"></span> Read Cerber\'s blog</h3> -->
1707
+ <h3>Documentation & How to</h3>
1708
 
1709
+ <p><a href="https://wpcerber.com/wordpress-security-scanner-scan-malware-detect/" target="_blank">What Cerber Security Scanner scans and detects</a>
1710
+ <p><a href="https://wpcerber.com/automated-recurring-malware-scans/" target="_blank">Automated recurring scans and email reporting</a>
1711
+ <p><a href="https://wpcerber.com/wordpress-security-scanner/" target="_blank">Malware Scanner & Integrity Checker</a>
1712
  <p><a href="https://wpcerber.com/wordpress-traffic-inspector-how-to/" target="_blank">Quick tips for Traffic Inspector</a>
1713
  <p><a href="https://wpcerber.com/traffic-inspector-in-a-nutshell/" target="_blank">Traffic Inspector in a nutshell</a>
1714
  <p><a href="https://wpcerber.com/wordpress-ip-address-detection/" target="_blank">Solving problem with incorrect IP address detection</a>
1751
  '</p></div>';
1752
  }
1753
 
1754
+ if ( ! cerber_is_admin_page( true ) ) {
1755
  return;
1756
  }
1757
 
1791
  update_site_option('cerber_admin_notice', null);
1792
  update_site_option('cerber_admin_message', null);
1793
 
1794
+ if ( ! cerber_is_admin_page() ) {
1795
  return;
1796
  }
1797
 
2056
 
2057
  $crb_assets_url = plugin_dir_url( __FILE__ ) . 'assets/';
2058
 
2059
+ if ( cerber_is_admin_page() ) {
2060
+
2061
  wp_register_style( 'crb_multi_css', $crb_assets_url . 'multi/multi.css', null, CERBER_VER );
2062
  wp_enqueue_style( 'crb_multi_css' );
2063
  wp_enqueue_script( 'crb_multi_js', $crb_assets_url . 'multi/multi.min.js', array(), CERBER_VER );
2064
+
2065
+ wp_register_style( 'crb_tpicker_css', $crb_assets_url . 'tpicker/jquery.timepicker.min.css', null, CERBER_VER );
2066
+ wp_enqueue_style( 'crb_tpicker_css' );
2067
+ wp_enqueue_script( 'crb_tpicker', $crb_assets_url . 'tpicker/jquery.timepicker.min.js', array(), CERBER_VER );
2068
+
2069
  add_thickbox();
2070
  }
2071
 
2072
  if ( ! defined( 'CERBER_BETA' ) ) {
2073
  wp_enqueue_script( 'cerber_js', $crb_assets_url . 'admin.js', array( 'jquery' ), CERBER_VER, true );
2074
+ if ( cerber_is_admin_page( false, array( 'page' => 'cerber-integrity' ) ) ) {
2075
+ wp_enqueue_script( 'cerber_scan', $crb_assets_url . 'scanner.js', array( 'jquery' ), CERBER_VER, true );
2076
+ }
2077
  }
2078
 
2079
  wp_register_style( 'cerber_css', $crb_assets_url . 'admin.css', null, CERBER_VER );
2093
  add_action('admin_head', 'cerber_admin_head' );
2094
  add_action('customize_controls_print_scripts', 'cerber_admin_head' ); // @since 5.8.1
2095
  function cerber_admin_head(){
2096
+ global $crb_assets_url, $crb_ajax_loader;
2097
 
2098
+ //$assets_url = cerber_plugin_dir_url() . 'assets/';
2099
 
2100
  $crb_assets_url = cerber_plugin_dir_url() . 'assets/';
2101
  $crb_ajax_loader = $crb_assets_url . 'ajax-loader.gif';
2102
  $crb_ajax_nonce = wp_create_nonce( 'crb-ajax-admin' );
2103
 
2104
+ $crb_lab_available = ( lab_lab() ) ? 'true' : 'false';
 
 
 
 
 
2105
 
2106
  ?>
2107
 
2111
  crb_lab_available = <?php echo $crb_lab_available; ?>;
2112
 
2113
  crb_scan_msg_steps = <?php echo json_encode( cerber_step_desc() ); ?>;
2114
+ crb_scan_msg_issues = <?php echo json_encode( cerber_get_issue_label() ); ?>;
2115
+ crb_scan_msg_risks = <?php echo json_encode( cerber_get_risk_label() ); ?>;
2116
  </script>
2117
 
2118
  <?php
2168
  <?php
2169
  endif;
2170
 
2171
+ if ( ! cerber_is_admin_page() ) {
2172
  return;
2173
  }
2174
 
2235
 
2236
  // ------------------------------------------------------
2237
 
2238
+ if ( ! cerber_is_admin_page() ) {
2239
+ return;
2240
+ }
2241
+
2242
+ if ( defined( 'CERBER_BETA' ) ) :
2243
  ?>
2244
  <script type="text/javascript">
2245
  <?php readfile( dirname( __FILE__ ) . '/assets/admin.js' ); ?>
2246
+ <?php readfile( dirname( __FILE__ ) . '/assets/scanner.js' ); ?>
2247
+ </script>
2248
+ <?php
2249
+ endif;
2250
+
2251
+ // Time pickers
2252
+ $format = 'H:i';
2253
+ if ( cerber_is_ampm() ) {
2254
+ $format = 'h:i A';
2255
+ }
2256
+ ?>
2257
+ <script type="text/javascript">
2258
+ jQuery(document).ready(function ($) {
2259
+ $('.crb-tpicker').timepicker({
2260
+ 'step': 20,
2261
+ 'forceRoundTime': true,
2262
+ 'timeFormat': '<?php echo $format; ?>'
2263
+ });
2264
+ });
2265
+ </script>
2266
+ <?php
2267
+
2268
+ if ( !lab_lab() && cerber_is_admin_page( false, array( 'tab' => 'scan_schedule' ) ) ) :
2269
+ ?>
2270
+ <script type="text/javascript">
2271
+ jQuery(document).ready(function ($) {
2272
+ $('input').attr('disabled', 'disabled');
2273
+ $('select').attr('disabled', 'disabled');
2274
+ $('.crb-slider').css('background-color', '#888');
2275
+ $('th').add('td').add('h2').css('color', '#888');
2276
+
2277
+ $('.crb-main h2').first().before('<div class="crb-pro-req">These features are available in a professional version of the plugin. Please read more: <a href="https://wpcerber.com/pro/" target="_blank">https://wpcerber.com/pro/</a></div>');
2278
+ });
2279
  </script>
2280
  <?php
2281
  endif;
2284
 
2285
  add_filter( 'admin_footer_text','cerber_footer_text1');
2286
  function cerber_footer_text1($text){
2287
+ if ( ! cerber_is_admin_page() ) {
2288
+ return $text;
2289
+ }
2290
  return 'If you like how <strong>WP Cerber</strong> protects your website, please <a target="_blank" href="https://wordpress.org/support/plugin/wp-cerber/reviews/#new-post">leave it a &#9733; &#9733; &#9733; &#9733; &#9733; rating</a>. Thanks!';
2291
  }
2292
  add_filter( 'update_footer','cerber_footer_text2', 1000);
2293
  function cerber_footer_text2($text){
2294
+ if ( ! cerber_is_admin_page() ) {
2295
  return $text;
2296
  }
2297
  if ( lab_lab() ) {
languages/wp-cerber.pot CHANGED
@@ -5,7 +5,7 @@ msgstr ""
5
  "Project-Id-Version: WP Cerber\n"
6
  "Report-Msgid-Bugs-To: \n"
7
  "POT-Creation-Date: Tue Sep 08 2015 21:38:11 GMT+0300\n"
8
- "POT-Revision-Date: Wed Jun 13 2018 12:10:43 GMT+0300\n"
9
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
10
  "Last-Translator: \n"
11
  "Language-Team: \n"
@@ -24,7 +24,7 @@ msgstr ""
24
  "esc_html_x:1,2c;comments_number_link:2,3;t:1;st:1;trans:1;transChoice:1,2\n"
25
  "X-Generator: Loco - https://localise.biz/"
26
 
27
- #: ../dashboard.php:52 ../settings.php:446
28
  msgid "WP Cerber Security"
29
  msgstr ""
30
 
@@ -37,8 +37,8 @@ msgstr ""
37
  msgid "Cerber Dashboard"
38
  msgstr ""
39
 
40
- #: ../dashboard.php:54 ../dashboard.php:1252 ../dashboard.php:1893 ../settings.
41
- #: php:451
42
  msgid "Dashboard"
43
  msgstr ""
44
 
@@ -46,7 +46,7 @@ msgstr ""
46
  msgid "Cerber Traffic Inspector"
47
  msgstr ""
48
 
49
- #: ../dashboard.php:56 ../dashboard.php:1238 ../dashboard.php:2639
50
  msgid "Traffic Inspector"
51
  msgstr ""
52
 
@@ -54,11 +54,11 @@ msgstr ""
54
  msgid "Cerber Security Rules"
55
  msgstr ""
56
 
57
- #: ../dashboard.php:60 ../dashboard.php:2299
58
  msgid "Security Rules"
59
  msgstr ""
60
 
61
- #: ../dashboard.php:64 ../cerber-scanner.php:67
62
  msgid "Site Integrity"
63
  msgstr ""
64
 
@@ -66,8 +66,8 @@ msgstr ""
66
  msgid "Cerber antispam settings"
67
  msgstr ""
68
 
69
- #: ../dashboard.php:67 ../dashboard.php:1255 ../cerber-load.php:4153 ../settings.
70
- #: php:197
71
  msgid "Antispam"
72
  msgstr ""
73
 
@@ -83,8 +83,8 @@ msgstr ""
83
  msgid "Remove"
84
  msgstr ""
85
 
86
- #: ../dashboard.php:133 ../dashboard.php:699 ../dashboard.php:2969 ../cerber-load.
87
- #: php:3909
88
  msgid "IP"
89
  msgstr ""
90
 
@@ -100,7 +100,7 @@ msgstr ""
100
  msgid "Expires"
101
  msgstr ""
102
 
103
- #: ../dashboard.php:137 ../cerber-load.php:3394
104
  msgid "Reason"
105
  msgstr ""
106
 
@@ -126,7 +126,7 @@ msgid "No lockouts at the moment. The sky is clear."
126
  msgstr ""
127
 
128
  #: ../dashboard.php:171 ../dashboard.php:674 ../dashboard.php:877 ../dashboard.
129
- #: php:1233 ../dashboard.php:2794 ../cerber-load.php:4144 ../settings.php:423
130
  msgid "White IP Access List"
131
  msgstr ""
132
 
@@ -135,7 +135,7 @@ msgid "These IPs will never be locked out"
135
  msgstr ""
136
 
137
  #: ../dashboard.php:173 ../dashboard.php:675 ../dashboard.php:880 ../dashboard.
138
- #: php:1234 ../dashboard.php:2795
139
  msgid "Black IP Access List"
140
  msgstr ""
141
 
@@ -186,8 +186,8 @@ msgstr ""
186
  msgid "Address %s was added to Black IP Access List"
187
  msgstr ""
188
 
189
- #: ../dashboard.php:353 ../dashboard.php:2724 ../whois.php:223 ../whois.php:254 ..
190
- #: /common.php:881 ../common.php:1160
191
  msgid "Unknown"
192
  msgstr ""
193
 
@@ -208,7 +208,7 @@ msgstr ""
208
  msgid "Lockout for %s was removed"
209
  msgstr ""
210
 
211
- #: ../dashboard.php:445 ../dashboard.php:1717
212
  msgid "Settings saved"
213
  msgstr ""
214
 
@@ -216,7 +216,7 @@ msgstr ""
216
  msgid "IP address"
217
  msgstr ""
218
 
219
- #: ../dashboard.php:538 ../dashboard.php:702 ../dashboard.php:2967
220
  msgid "Date"
221
  msgstr ""
222
 
@@ -224,7 +224,7 @@ msgstr ""
224
  msgid "Event"
225
  msgstr ""
226
 
227
- #: ../dashboard.php:538 ../dashboard.php:704 ../dashboard.php:2972
228
  msgid "Local User"
229
  msgstr ""
230
 
@@ -236,11 +236,11 @@ msgstr ""
236
  msgid "User ID"
237
  msgstr ""
238
 
239
- #: ../dashboard.php:538 ../dashboard.php:705 ../cerber-load.php:3917
240
  msgid "Username used"
241
  msgstr ""
242
 
243
- #: ../dashboard.php:679 ../dashboard.php:883 ../dashboard.php:2799 ../common.php:
244
  #: 852
245
  msgid "Locked out"
246
  msgstr ""
@@ -301,7 +301,7 @@ msgstr ""
301
  msgid "Failed login attempts"
302
  msgstr ""
303
 
304
- #: ../dashboard.php:1129 ../dashboard.php:1216
305
  msgid "Never"
306
  msgstr ""
307
 
@@ -313,7 +313,7 @@ msgstr ""
313
  msgid "Cerber Quick View"
314
  msgstr ""
315
 
316
- #: ../dashboard.php:1220 ../dashboard.php:1241
317
  msgid "active"
318
  msgstr ""
319
 
@@ -353,13 +353,13 @@ msgstr ""
353
  msgid "Last lockout"
354
  msgstr ""
355
 
356
- #: ../dashboard.php:1233 ../dashboard.php:1234 ../dashboard.php:1873
357
  msgid "entry"
358
  msgid_plural "entries"
359
  msgstr[0] ""
360
  msgstr[1] ""
361
 
362
- #: ../dashboard.php:1235 ../settings.php:100
363
  msgid "Citadel mode"
364
  msgstr ""
365
 
@@ -367,245 +367,257 @@ msgstr ""
367
  msgid "enabled"
368
  msgstr ""
369
 
370
- #: ../dashboard.php:1241
371
  msgid "no connection"
372
  msgstr ""
373
 
374
- #: ../dashboard.php:1253 ../dashboard.php:1544 ../cerber-load.php:3900 ..
375
- #: /settings.php:105 ../settings.php:453
 
 
 
 
 
 
 
 
 
 
 
 
376
  msgid "Activity"
377
  msgstr ""
378
 
379
- #: ../dashboard.php:1254
380
  msgid "Traffic"
381
  msgstr ""
382
 
383
- #: ../dashboard.php:1384 ../settings.php:80
384
  msgid "My site is behind a reverse proxy"
385
  msgstr ""
386
 
387
- #: ../dashboard.php:1523
388
  msgid "in the last 24 hours"
389
  msgstr ""
390
 
391
- #: ../dashboard.php:1529 ../dashboard.php:1559
392
  msgid "View all"
393
  msgstr ""
394
 
395
- #: ../dashboard.php:1537 ../common.php:804
396
  msgid "User registered"
397
  msgstr ""
398
 
399
- #: ../dashboard.php:1538
400
  msgid "All suspicious activity"
401
  msgstr ""
402
 
403
- #: ../dashboard.php:1560
404
  msgid "Recently locked out IP addresses"
405
  msgstr ""
406
 
407
- #: ../dashboard.php:1585
408
  msgid "Confused about some settings?"
409
  msgstr ""
410
 
411
- #: ../dashboard.php:1586
412
  msgid "You can easily load default recommended settings using button below"
413
  msgstr ""
414
 
415
- #: ../dashboard.php:1588
416
  msgid "Load default settings"
417
  msgstr ""
418
 
419
- #: ../dashboard.php:1590
420
  msgid "Are you sure?"
421
  msgstr ""
422
 
423
- #: ../dashboard.php:1596
424
  msgid "doesn't affect Custom login URL and Access Lists"
425
  msgstr ""
426
 
427
- #: ../dashboard.php:1597 ../cerber-load.php:3426 ../cerber-load.php:4146
428
  msgid "Getting Started Guide"
429
  msgstr ""
430
 
431
- #: ../dashboard.php:1700
432
  msgid "Attention! Citadel mode is now active. Nobody is able to log in."
433
  msgstr ""
434
 
435
- #: ../dashboard.php:1701
436
  msgid "Deactivate"
437
  msgstr ""
438
 
439
- #: ../dashboard.php:1702 ../dashboard.php:2170
440
  msgid "View Activity"
441
  msgstr ""
442
 
443
- #: ../dashboard.php:1803
444
  msgid "Subscribe"
445
  msgstr ""
446
 
447
- #: ../dashboard.php:1804 ../cerber-tools.php:273
448
  msgid "Unsubscribe"
449
  msgstr ""
450
 
451
- #: ../dashboard.php:1832
452
  msgid "You've subscribed"
453
  msgstr ""
454
 
455
- #: ../dashboard.php:1835
456
  msgid "You've unsubscribed"
457
  msgstr ""
458
 
459
- #: ../dashboard.php:1894
460
  msgid "Main settings"
461
  msgstr ""
462
 
463
- #: ../dashboard.php:2304
464
  msgid "Countries"
465
  msgstr ""
466
 
467
- #: ../dashboard.php:2367
468
  #, php-format
469
  msgid "Permitted for one country"
470
  msgid_plural "Permitted for %d countries"
471
  msgstr[0] ""
472
  msgstr[1] ""
473
 
474
- #: ../dashboard.php:2370
475
  #, php-format
476
  msgid "Not permitted for one country"
477
  msgid_plural "Not permitted for %d countries"
478
  msgstr[0] ""
479
  msgstr[1] ""
480
 
481
- #: ../dashboard.php:2378
482
  msgid "No rule"
483
  msgstr ""
484
 
485
- #: ../dashboard.php:2434
486
  msgid "Start typing here to find a country"
487
  msgstr ""
488
 
489
- #: ../dashboard.php:2517
490
  msgid "Click on a country name to add it to the list of selected countries"
491
  msgstr ""
492
 
493
- #: ../dashboard.php:2521
494
  #, php-format
495
  msgctxt "to is a marker of infinitive, e.g. \"to use it\""
496
  msgid "Selected countries are permitted to %s, other countries are not permitted to"
497
  msgstr ""
498
 
499
- #: ../dashboard.php:2524
500
  #, php-format
501
  msgctxt "to is a marker of infinitive, e.g. \"to use it\""
502
  msgid "Selected countries are not permitted to %s, other countries are permitted to"
503
  msgstr ""
504
 
505
- #: ../dashboard.php:2541
506
  msgid "Submit forms"
507
  msgstr ""
508
 
509
- #: ../dashboard.php:2542
510
  msgid "Post comments"
511
  msgstr ""
512
 
513
- #: ../dashboard.php:2543
514
  msgid "Log in to the website"
515
  msgstr ""
516
 
517
- #: ../dashboard.php:2544
518
  msgid "Register on the website"
519
  msgstr ""
520
 
521
- #: ../dashboard.php:2545
522
  msgid "Use XML-RPC"
523
  msgstr ""
524
 
525
- #: ../dashboard.php:2546
526
  msgid "Use REST API"
527
  msgstr ""
528
 
529
- #: ../dashboard.php:2590
530
  msgid "Security rules have been updated"
531
  msgstr ""
532
 
533
- #: ../dashboard.php:2644
534
  msgid "Live traffic"
535
  msgstr ""
536
 
537
- #: ../dashboard.php:2645 ../cerber-tools.php:91 ../cerber-tools.php:100 ../cerber-
538
- #: scanner.php:73
539
  msgid "Settings"
540
  msgstr ""
541
 
542
- #: ../dashboard.php:2646 ../settings.php:471 ../cerber-tools.php:51 ../cerber-
543
- #: scanner.php:74
544
  msgid "Help"
545
  msgstr ""
546
 
547
- #: ../dashboard.php:2968
548
  msgid "Request"
549
  msgstr ""
550
 
551
- #: ../dashboard.php:2970
552
  msgid "Host Info"
553
  msgstr ""
554
 
555
- #: ../dashboard.php:2971
556
  msgid "User Agent"
557
  msgstr ""
558
 
559
- #: ../dashboard.php:2988
560
  msgid "No requests have been logged."
561
  msgstr ""
562
 
563
- #: ../dashboard.php:2996
564
  msgid "All requests"
565
  msgstr ""
566
 
567
- #: ../dashboard.php:2997 ../settings.php:168
568
  msgid "Logged in users"
569
  msgstr ""
570
 
571
- #: ../dashboard.php:2998
572
  msgid "Not logged in visitors"
573
  msgstr ""
574
 
575
- #: ../dashboard.php:2999
576
  msgid "Form submissions"
577
  msgstr ""
578
 
579
- #: ../dashboard.php:3000
580
  msgid "Page Not Found"
581
  msgstr ""
582
 
583
- #: ../dashboard.php:3001
584
  msgid "REST API"
585
  msgstr ""
586
 
587
- #: ../dashboard.php:3002
588
  msgid "XML-RPC"
589
  msgstr ""
590
 
591
- #: ../dashboard.php:3006
592
  msgid "Longer than"
593
  msgstr ""
594
 
595
- #: ../dashboard.php:3019
596
  msgid "Refresh"
597
  msgstr ""
598
 
599
- #: ../dashboard.php:3239
600
  msgid "Any"
601
  msgstr ""
602
 
603
- #: ../dashboard.php:3281
604
  msgid "Advanced search"
605
  msgstr ""
606
 
607
  #. Name of the plugin
608
- msgid "WP Cerber Security & Antispam"
609
  msgstr ""
610
 
611
  #. URI of the plugin
@@ -649,11 +661,11 @@ msgid "Lockouts occurred"
649
  msgstr ""
650
 
651
  #: ../common.php:206 ../common.php:263 ../common.php:268 ../common.php:273 ..
652
- #: /cerber-load.php:668 ../cerber-load.php:680 ../cerber-load.php:687 ../cerber-
653
- #: load.php:934 ../cerber-load.php:1153 ../cerber-load.php:1159 ../cerber-load.
654
- #: php:1164 ../cerber-load.php:1169 ../cerber-load.php:1175 ../cerber-load.php:
655
- #: 1182 ../cerber-load.php:1283 ../cerber-load.php:1420 ../settings.php:851 ..
656
- #: /settings.php:922
657
  msgid "ERROR:"
658
  msgstr ""
659
 
@@ -818,48 +830,48 @@ msgstr ""
818
  msgid "%s ago"
819
  msgstr ""
820
 
821
- #: ../common.php:1078 ../settings.php:222
822
  msgid "New version is available"
823
  msgstr ""
824
 
825
- #: ../common.php:1085
826
  #, php-format
827
  msgid "Update to version %s of WP Cerber"
828
  msgstr ""
829
 
830
- #: ../common.php:1104
831
  msgid "Not specified"
832
  msgstr ""
833
 
834
- #: ../common.php:1641
835
  msgid "Unable to create the directory"
836
  msgstr ""
837
 
838
- #: ../common.php:1646
839
  msgid "Destination folder access denied"
840
  msgstr ""
841
 
842
- #: ../common.php:1649
843
  msgid "File not found"
844
  msgstr ""
845
 
846
- #: ../common.php:1652
847
  msgid "Unable to copy the file"
848
  msgstr ""
849
 
850
- #: ../common.php:1658
851
  msgid "Unable to delete the file"
852
  msgstr ""
853
 
854
- #: ../cerber-news.php:173
855
  msgid "Cool!"
856
  msgstr ""
857
 
858
- #: ../cerber-lab.php:722
859
  msgid "Want to make WP Cerber even more powerful?"
860
  msgstr ""
861
 
862
- #: ../cerber-lab.php:723
863
  msgid ""
864
  "Allow WP Cerber to send locked out malicious IP addresses to Cerber Lab. "
865
  "This helps the plugin team to develop new algorithms for WP Cerber that will "
@@ -867,982 +879,1050 @@ msgid ""
867
  "everyday. You can disable the sending in the plugin settings at any time."
868
  msgstr ""
869
 
870
- #: ../cerber-lab.php:724
871
  msgid "OK, nail them all"
872
  msgstr ""
873
 
874
- #: ../cerber-lab.php:725
875
  msgid "NO, maybe later"
876
  msgstr ""
877
 
878
- #: ../cerber-lab.php:726 ../settings.php:427
879
  msgid "Know more"
880
  msgstr ""
881
 
882
- #: ../cerber-load.php:360
883
  msgid "You are not allowed to log in. Ask your administrator for assistance."
884
  msgstr ""
885
 
886
- #: ../cerber-load.php:366
887
  #, php-format
888
  msgid "You have reached the login attempts limit. Please try again in %d minutes."
889
  msgstr ""
890
 
891
- #: ../cerber-load.php:385
892
  #, php-format
893
  msgid "You have only one attempt remaining."
894
  msgid_plural "You have %d attempts remaining."
895
  msgstr[0] ""
896
  msgstr[1] ""
897
 
898
- #: ../cerber-load.php:697
899
  msgid ""
900
  "Human verification failed. Please click the square box in the reCAPTCHA "
901
  "block below."
902
  msgstr ""
903
 
904
- #: ../cerber-load.php:798
905
  msgid ""
906
  "> > > Translator of WP Cerber? To get the PRO license for free, drop your "
907
  "contacts here: https://wpcerber.com/contact/"
908
  msgstr ""
909
 
910
- #: ../cerber-load.php:946
911
  #, php-format
912
  msgid ""
913
  "<strong>ERROR</strong>: The password you entered for the username %s is "
914
  "incorrect."
915
  msgstr ""
916
 
917
- #: ../cerber-load.php:1154 ../cerber-load.php:1160 ../cerber-load.php:1176 ..
918
- #: /cerber-load.php:1183
919
  msgid "You are not allowed to register."
920
  msgstr ""
921
 
922
- #: ../cerber-load.php:1170
923
  msgid "Username is not allowed. Please choose another one."
924
  msgstr ""
925
 
926
- #: ../cerber-load.php:1420
927
  msgid "Sorry, human verification failed."
928
  msgstr ""
929
 
930
- #: ../cerber-load.php:3226
931
  msgid "We're sorry, you are not allowed to proceed"
932
  msgstr ""
933
 
934
- #: ../cerber-load.php:3336
935
  msgid "WP Cerber notify"
936
  msgstr ""
937
 
938
- #: ../cerber-load.php:3358
939
  msgid "Citadel mode is activated"
940
  msgstr ""
941
 
942
- #: ../cerber-load.php:3360
943
  #, php-format
944
  msgid "Citadel mode is activated after %d failed login attempts in %d minutes."
945
  msgstr ""
946
 
947
- #: ../cerber-load.php:3361
948
  #, php-format
949
  msgid "Last failed attempt was at %s from IP %s with user login: %s."
950
  msgstr ""
951
 
952
- #: ../cerber-load.php:3362 ../cerber-load.php:3941
953
  msgid "View activity in dashboard"
954
  msgstr ""
955
 
956
- #: ../cerber-load.php:3387
957
  msgid "unspecified"
958
  msgstr ""
959
 
960
- #: ../cerber-load.php:3390
961
  msgid "Number of lockouts is increasing"
962
  msgstr ""
963
 
964
- #: ../cerber-load.php:3392
965
  msgid "Number of active lockouts"
966
  msgstr ""
967
 
968
- #: ../cerber-load.php:3393
969
  #, php-format
970
  msgid "Last lockout was added: %s for IP %s"
971
  msgstr ""
972
 
973
- #: ../cerber-load.php:3395
974
  msgid "View activity for this IP"
975
  msgstr ""
976
 
977
- #: ../cerber-load.php:3396
978
  msgid "View lockouts in dashboard"
979
  msgstr ""
980
 
981
- #: ../cerber-load.php:3399 ../cerber-load.php:3401
982
  msgid "A new version of WP Cerber is available to install"
983
  msgstr ""
984
 
985
- #: ../cerber-load.php:3400
986
  msgid "Hi!"
987
  msgstr ""
988
 
989
- #: ../cerber-load.php:3403 ../cerber-load.php:3414
990
  msgid "Website"
991
  msgstr ""
992
 
993
- #: ../cerber-load.php:3406 ../cerber-load.php:3407
994
  msgid "The WP Cerber security plugin has been deactivated"
995
  msgstr ""
996
 
997
- #: ../cerber-load.php:3409
998
  msgid "Not logged in"
999
  msgstr ""
1000
 
1001
- #: ../cerber-load.php:3415
1002
  msgid "By user"
1003
  msgstr ""
1004
 
1005
- #: ../cerber-load.php:3416
1006
  msgid "From IP address"
1007
  msgstr ""
1008
 
1009
- #: ../cerber-load.php:3419
1010
  msgid "From country"
1011
  msgstr ""
1012
 
1013
- #: ../cerber-load.php:3423
1014
  msgid "The WP Cerber security plugin is now active"
1015
  msgstr ""
1016
 
1017
- #: ../cerber-load.php:3424 ../cerber-load.php:4143
1018
  msgid "WP Cerber is now active and has started protecting your site"
1019
  msgstr ""
1020
 
1021
- #: ../cerber-load.php:3432
1022
  msgid "New Custom login URL"
1023
  msgstr ""
1024
 
1025
- #: ../cerber-load.php:3436 ../cerber-load.php:3437
1026
  msgid "A new activity has been recorded"
1027
  msgstr ""
1028
 
1029
- #: ../cerber-load.php:3442
1030
  msgid "Weekly report"
1031
  msgstr ""
1032
 
1033
- #: ../cerber-load.php:3445
1034
  msgid "To change reporting settings visit"
1035
  msgstr ""
1036
 
1037
- #: ../cerber-load.php:3471
 
 
 
 
1038
  msgid "Your login page:"
1039
  msgstr ""
1040
 
1041
- #: ../cerber-load.php:3475
1042
  msgid "Your license is valid until"
1043
  msgstr ""
1044
 
1045
- #: ../cerber-load.php:3478
1046
  msgid "This message was sent by"
1047
  msgstr ""
1048
 
1049
- #: ../cerber-load.php:3499
1050
  #, php-format
1051
  msgid "Your last sign-in was %s from %s"
1052
  msgstr ""
1053
 
1054
- #: ../cerber-load.php:3574
1055
  msgid "Weekly Report"
1056
  msgstr ""
1057
 
1058
- #: ../cerber-load.php:3586
1059
  msgid "Activity details"
1060
  msgstr ""
1061
 
1062
- #: ../cerber-load.php:3600
1063
  msgid "Attempts to log in with non-existent username"
1064
  msgstr ""
1065
 
1066
- #: ../cerber-load.php:3913
1067
  msgid "User"
1068
  msgstr ""
1069
 
1070
- #: ../cerber-load.php:3921
1071
  msgid "Search string"
1072
  msgstr ""
1073
 
1074
- #: ../cerber-load.php:3942
1075
  msgid "To unsubscribe click here"
1076
  msgstr ""
1077
 
1078
- #: ../cerber-load.php:4098
1079
  #, php-format
1080
  msgid "The WP Cerber requires PHP %s or higher. You are running"
1081
  msgstr ""
1082
 
1083
- #: ../cerber-load.php:4102
1084
  #, php-format
1085
  msgid "The WP Cerber requires WordPress %s or higher. You are running"
1086
  msgstr ""
1087
 
1088
- #: ../cerber-load.php:4111
1089
  msgid "Can't activate WP Cerber due to a database error."
1090
  msgstr ""
1091
 
1092
- #: ../cerber-load.php:4144
1093
  msgid "Your IP address is added to the"
1094
  msgstr ""
1095
 
1096
- #: ../cerber-load.php:4151 ../settings.php:459
1097
  msgid "Main Settings"
1098
  msgstr ""
1099
 
1100
- #: ../cerber-load.php:4152 ../settings.php:462 ../cerber-tools.php:92 ../cerber-
1101
  #: tools.php:101 ../cerber-tools.php:182
1102
  msgid "Access Lists"
1103
  msgstr ""
1104
 
1105
- #: ../cerber-load.php:4154 ../settings.php:464
1106
  msgid "Hardening"
1107
  msgstr ""
1108
 
1109
- #: ../cerber-load.php:4155 ../settings.php:79 ../settings.php:103 ../settings.php:
1110
- #: 469
1111
  msgid "Notifications"
1112
  msgstr ""
1113
 
1114
- #: ../cerber-load.php:4156
1115
  msgid "Import settings"
1116
  msgstr ""
1117
 
1118
- #: ../settings.php:71
1119
  msgid "Plugin initialization"
1120
  msgstr ""
1121
 
1122
- #: ../settings.php:72
1123
  msgid "Load security engine"
1124
  msgstr ""
1125
 
1126
- #: ../settings.php:72
1127
  msgid "Legacy mode"
1128
  msgstr ""
1129
 
1130
- #: ../settings.php:72
1131
  msgid "Standard mode"
1132
  msgstr ""
1133
 
1134
- #: ../settings.php:74
1135
  msgid "Limit login attempts"
1136
  msgstr ""
1137
 
1138
- #: ../settings.php:75
1139
  msgid "Attempts"
1140
  msgstr ""
1141
 
1142
- #: ../settings.php:76
1143
  msgid "Lockout duration"
1144
  msgstr ""
1145
 
1146
- #: ../settings.php:76 ../settings.php:102
1147
  msgid "minutes"
1148
  msgstr ""
1149
 
1150
- #: ../settings.php:77
1151
  msgid "Aggressive lockout"
1152
  msgstr ""
1153
 
1154
- #: ../settings.php:78 ../settings.php:269
1155
  msgid "Use White IP Access List"
1156
  msgstr ""
1157
 
1158
- #: ../settings.php:78
1159
  msgid "Apply limit login rules to IP addresses in the White IP Access List"
1160
  msgstr ""
1161
 
1162
- #: ../settings.php:80
1163
  msgid "Site connection"
1164
  msgstr ""
1165
 
1166
- #: ../settings.php:82
1167
  msgid "Proactive security rules"
1168
  msgstr ""
1169
 
1170
- #: ../settings.php:83
1171
  msgid "Block subnet"
1172
  msgstr ""
1173
 
1174
- #: ../settings.php:83
1175
  msgid "Always block entire subnet Class C of intruders IP"
1176
  msgstr ""
1177
 
1178
- #: ../settings.php:84
1179
  msgid "Non-existent users"
1180
  msgstr ""
1181
 
1182
- #: ../settings.php:84
1183
  msgid "Immediately block IP when attempting to login with a non-existent username"
1184
  msgstr ""
1185
 
1186
- #: ../settings.php:85
1187
- msgid "Redirect dashboard requests"
1188
  msgstr ""
1189
 
1190
- #: ../settings.php:85
1191
  msgid ""
1192
- "Disable automatic redirecting to the login page when /wp-admin/ is requested "
1193
  "by an unauthorized request"
1194
  msgstr ""
1195
 
1196
- #: ../settings.php:86
1197
  msgid "Request wp-login.php"
1198
  msgstr ""
1199
 
1200
- #: ../settings.php:86
1201
  msgid "Immediately block IP after any request to wp-login.php"
1202
  msgstr ""
1203
 
1204
- #: ../settings.php:87
1205
  msgid "Display 404 page"
1206
  msgstr ""
1207
 
1208
- #: ../settings.php:87
1209
  msgid "Use 404 template from the active theme"
1210
  msgstr ""
1211
 
1212
- #: ../settings.php:87
1213
  msgid "Display simple 404 page"
1214
  msgstr ""
1215
 
1216
- #: ../settings.php:89
1217
  msgid "Custom login page"
1218
  msgstr ""
1219
 
1220
- #: ../settings.php:90
1221
  msgid "Custom login URL"
1222
  msgstr ""
1223
 
1224
- #: ../settings.php:95
1225
  msgid "Custom login URL may contain only letters, numbers, dashes and underscores"
1226
  msgstr ""
1227
 
1228
- #: ../settings.php:96
1229
  msgid "must not overlap with the existing pages or posts slug"
1230
  msgstr ""
1231
 
1232
- #: ../settings.php:98
1233
  msgid "Disable wp-login.php"
1234
  msgstr ""
1235
 
1236
- #: ../settings.php:98
1237
  msgid "Block direct access to wp-login.php and return HTTP 404 Not Found Error"
1238
  msgstr ""
1239
 
1240
- #: ../settings.php:101
1241
  msgid "Threshold"
1242
  msgstr ""
1243
 
1244
- #: ../settings.php:102
1245
  msgid "Duration"
1246
  msgstr ""
1247
 
1248
- #: ../settings.php:103
1249
  msgid "Send notification to admin email"
1250
  msgstr ""
1251
 
1252
- #: ../settings.php:103 ../settings.php:597 ../settings.php:719
1253
  msgid "Click to send test"
1254
  msgstr ""
1255
 
1256
- #: ../settings.php:106 ../settings.php:344
1257
  msgid "Keep records for"
1258
  msgstr ""
1259
 
1260
- #: ../settings.php:106 ../settings.php:180 ../settings.php:348 ../settings.php:399
1261
  msgid "days"
1262
  msgstr ""
1263
 
1264
- #: ../settings.php:107
1265
  msgid "Cerber Lab connection"
1266
  msgstr ""
1267
 
1268
- #: ../settings.php:107
1269
  msgid "Send malicious IP addresses to the Cerber Lab"
1270
  msgstr ""
1271
 
1272
- #: ../settings.php:108
1273
  msgid "Cerber Lab protocol"
1274
  msgstr ""
1275
 
1276
- #: ../settings.php:109
1277
  msgid "Use file"
1278
  msgstr ""
1279
 
1280
- #: ../settings.php:109
1281
  msgid "Write failed login attempts to the file"
1282
  msgstr ""
1283
 
1284
- #: ../settings.php:111
1285
  msgid "Preferences"
1286
  msgstr ""
1287
 
1288
- #: ../settings.php:112
1289
  msgid "Drill down IP"
1290
  msgstr ""
1291
 
1292
- #: ../settings.php:112
1293
  msgid "Retrieve extra WHOIS information for IP"
1294
  msgstr ""
1295
 
1296
- #: ../settings.php:113
1297
  msgid "Date format"
1298
  msgstr ""
1299
 
1300
- #: ../settings.php:113
1301
  #, php-format
1302
  msgid "if empty, the default format %s will be used"
1303
  msgstr ""
1304
 
1305
- #: ../settings.php:120
1306
  msgid "Hardening WordPress"
1307
  msgstr ""
1308
 
1309
- #: ../settings.php:121
1310
  msgid "Stop user enumeration"
1311
  msgstr ""
1312
 
1313
- #: ../settings.php:121
1314
  msgid "Block access to user pages like /?author=n and user data via REST API"
1315
  msgstr ""
1316
 
1317
- #: ../settings.php:122
1318
  msgid "Protect admin scripts"
1319
  msgstr ""
1320
 
1321
- #: ../settings.php:122
1322
  msgid "Block unauthorized access to load-scripts.php and load-styles.php"
1323
  msgstr ""
1324
 
1325
- #: ../settings.php:123
1326
  msgid "Disable XML-RPC"
1327
  msgstr ""
1328
 
1329
- #: ../settings.php:123
1330
  msgid "Block access to the XML-RPC server (including Pingbacks and Trackbacks)"
1331
  msgstr ""
1332
 
1333
- #: ../settings.php:124
1334
  msgid "Disable feeds"
1335
  msgstr ""
1336
 
1337
- #: ../settings.php:124
1338
  msgid "Block access to the RSS, Atom and RDF feeds"
1339
  msgstr ""
1340
 
1341
- #: ../settings.php:125
1342
  msgid "Disable REST API"
1343
  msgstr ""
1344
 
1345
- #: ../settings.php:125
1346
  msgid "Block access to the WordPress REST API except the following"
1347
  msgstr ""
1348
 
1349
- #: ../settings.php:126
1350
  msgid "Allow REST API for logged in users"
1351
  msgstr ""
1352
 
1353
- #: ../settings.php:133
1354
  msgid ""
1355
  "Specify REST API namespaces to be allowed if REST API is disabled. One "
1356
  "string per line."
1357
  msgstr ""
1358
 
1359
- #: ../settings.php:143
1360
  msgid "User related settings"
1361
  msgstr ""
1362
 
1363
- #: ../settings.php:144
1364
  msgid "Registration limit"
1365
  msgstr ""
1366
 
1367
- #: ../settings.php:145
1368
  msgid "Prohibited usernames"
1369
  msgstr ""
1370
 
1371
- #: ../settings.php:151
1372
  msgid ""
1373
  "Usernames from this list are not allowed to log in or register. Any IP "
1374
  "address, have tried to use any of these usernames, will be immediately "
1375
  "blocked. Use comma to separate logins."
1376
  msgstr ""
1377
 
1378
- #: ../settings.php:151
1379
  msgid "To specify a REGEX pattern wrap a pattern in two forward slashes."
1380
  msgstr ""
1381
 
1382
- #: ../settings.php:153
1383
  msgid "User session expire"
1384
  msgstr ""
1385
 
1386
- #: ../settings.php:153
1387
  msgid "in minutes (leave empty to use default WP value)"
1388
  msgstr ""
1389
 
1390
- #: ../settings.php:154
1391
  msgid "Sort users in dashboard"
1392
  msgstr ""
1393
 
1394
- #: ../settings.php:154
1395
  msgid "by date of registration"
1396
  msgstr ""
1397
 
1398
- #: ../settings.php:161
1399
  msgid "Cerber antispam engine"
1400
  msgstr ""
1401
 
1402
- #: ../settings.php:162
1403
  msgid "Comment form"
1404
  msgstr ""
1405
 
1406
- #: ../settings.php:162
1407
  msgid "Protect comment form with bot detection engine"
1408
  msgstr ""
1409
 
1410
- #: ../settings.php:163 ../settings.php:188
1411
  msgid "Registration form"
1412
  msgstr ""
1413
 
1414
- #: ../settings.php:163
1415
  msgid "Protect registration form with bot detection engine"
1416
  msgstr ""
1417
 
1418
- #: ../settings.php:164
1419
  msgid "Other forms"
1420
  msgstr ""
1421
 
1422
- #: ../settings.php:164
1423
  msgid "Protect all forms on the website with bot detection engine"
1424
  msgstr ""
1425
 
1426
- #: ../settings.php:166
1427
  msgid "Adjust antispam engine"
1428
  msgstr ""
1429
 
1430
- #: ../settings.php:167
1431
  msgid "Safe mode"
1432
  msgstr ""
1433
 
1434
- #: ../settings.php:167
1435
  msgid "Use less restrictive policies (allow AJAX)"
1436
  msgstr ""
1437
 
1438
- #: ../settings.php:168
1439
  msgid "Disable bot detection engine for logged in users"
1440
  msgstr ""
1441
 
1442
- #: ../settings.php:169
1443
  msgid "Query whitelist"
1444
  msgstr ""
1445
 
1446
- #: ../settings.php:175
1447
  msgid ""
1448
  "Enter a part of query string or query path to exclude a request from "
1449
  "inspection by the engine. One item per line."
1450
  msgstr ""
1451
 
1452
- #: ../settings.php:175 ../settings.php:280
1453
  msgid "To specify a REGEX pattern, enclose a whole line in two braces."
1454
  msgstr ""
1455
 
1456
- #: ../settings.php:178
1457
  msgid "Comment processing"
1458
  msgstr ""
1459
 
1460
- #: ../settings.php:179
1461
  msgid "If a spam comment detected"
1462
  msgstr ""
1463
 
1464
- #: ../settings.php:179
1465
  msgid "Deny it completely"
1466
  msgstr ""
1467
 
1468
- #: ../settings.php:179
1469
  msgid "Mark it as spam"
1470
  msgstr ""
1471
 
1472
- #: ../settings.php:180
1473
  msgid "Trash spam comments"
1474
  msgstr ""
1475
 
1476
- #: ../settings.php:180
1477
  msgid "Move spam comments to trash after"
1478
  msgstr ""
1479
 
1480
- #: ../settings.php:183
1481
  msgid "reCAPTCHA settings"
1482
  msgstr ""
1483
 
1484
- #: ../settings.php:184
1485
  msgid "Site key"
1486
  msgstr ""
1487
 
1488
- #: ../settings.php:185
1489
  msgid "Secret key"
1490
  msgstr ""
1491
 
1492
- #: ../settings.php:186
1493
  msgid "Invisible reCAPTCHA"
1494
  msgstr ""
1495
 
1496
- #: ../settings.php:186
1497
  msgid "Enable invisible reCAPTCHA"
1498
  msgstr ""
1499
 
1500
- #: ../settings.php:186
1501
  msgid ""
1502
  "(do not enable it unless you get and enter the Site and Secret keys for the "
1503
  "invisible version)"
1504
  msgstr ""
1505
 
1506
- #: ../settings.php:188
1507
  msgid "Enable reCAPTCHA for WordPress registration form"
1508
  msgstr ""
1509
 
1510
- #: ../settings.php:189
1511
  msgid "Enable reCAPTCHA for WooCommerce registration form"
1512
  msgstr ""
1513
 
1514
- #: ../settings.php:191
1515
  msgid "Lost password form"
1516
  msgstr ""
1517
 
1518
- #: ../settings.php:191
1519
  msgid "Enable reCAPTCHA for WordPress lost password form"
1520
  msgstr ""
1521
 
1522
- #: ../settings.php:192
1523
  msgid "Enable reCAPTCHA for WooCommerce lost password form"
1524
  msgstr ""
1525
 
1526
- #: ../settings.php:194
1527
  msgid "Login form"
1528
  msgstr ""
1529
 
1530
- #: ../settings.php:194
1531
  msgid "Enable reCAPTCHA for WordPress login form"
1532
  msgstr ""
1533
 
1534
- #: ../settings.php:195
1535
  msgid "Enable reCAPTCHA for WooCommerce login form"
1536
  msgstr ""
1537
 
1538
- #: ../settings.php:197
1539
  msgid "Enable reCAPTCHA for WordPress comment form"
1540
  msgstr ""
1541
 
1542
- #: ../settings.php:198
1543
  msgid "Disable reCAPTCHA for logged in users"
1544
  msgstr ""
1545
 
1546
- #: ../settings.php:200
1547
  msgid "Limit attempts"
1548
  msgstr ""
1549
 
1550
- #: ../settings.php:200
1551
  #, php-format
1552
  msgid "Lock out IP address for %s minutes after %s failed attempts within %s minutes"
1553
  msgstr ""
1554
 
1555
- #: ../settings.php:206
1556
  msgid "Email notifications"
1557
  msgstr ""
1558
 
1559
- #: ../settings.php:209 ../settings.php:244
1560
  msgid "Email Address"
1561
  msgstr ""
1562
 
1563
- #: ../settings.php:213 ../settings.php:249 ../settings.php:312
1564
  msgid "Use comma to specify multiple values"
1565
  msgstr ""
1566
 
1567
- #: ../settings.php:218
1568
  #, php-format
1569
  msgid "if empty, the admin email %s will be used"
1570
  msgstr ""
1571
 
1572
- #: ../settings.php:221
1573
  msgid "Notification limit"
1574
  msgstr ""
1575
 
1576
- #: ../settings.php:221
1577
  msgid "notification letters allowed per hour (0 means unlimited)"
1578
  msgstr ""
1579
 
1580
- #: ../settings.php:227
1581
  msgid "Push notifications"
1582
  msgstr ""
1583
 
1584
- #: ../settings.php:234
1585
  msgid "All connected devices"
1586
  msgstr ""
1587
 
1588
- #: ../settings.php:235
1589
  msgid "No devices found"
1590
  msgstr ""
1591
 
1592
- #: ../settings.php:237
1593
  msgid "Not available"
1594
  msgstr ""
1595
 
1596
- #: ../settings.php:241
1597
  msgid "Weekly reports"
1598
  msgstr ""
1599
 
1600
- #: ../settings.php:242
1601
  msgid "Enable reporting"
1602
  msgstr ""
1603
 
1604
- #: ../settings.php:254
1605
  msgid "if empty, email from notification settings will be used"
1606
  msgstr ""
1607
 
1608
- #: ../settings.php:262
1609
  msgid "Inspection"
1610
  msgstr ""
1611
 
1612
- #: ../settings.php:263
1613
  msgid "Enable traffic inspection"
1614
  msgstr ""
1615
 
1616
- #: ../settings.php:274
1617
  msgid "Request whitelist"
1618
  msgstr ""
1619
 
1620
- #: ../settings.php:280
1621
  msgid ""
1622
  "Enter a request URI to exclude the request from inspection. One item per "
1623
  "line."
1624
  msgstr ""
1625
 
1626
- #: ../settings.php:283
1627
  msgid "Logging"
1628
  msgstr ""
1629
 
1630
- #: ../settings.php:284
1631
  msgid "Logging mode"
1632
  msgstr ""
1633
 
1634
- #: ../settings.php:290
1635
  msgid "Logging disabled"
1636
  msgstr ""
1637
 
1638
- #: ../settings.php:291
1639
  msgid "Smart"
1640
  msgstr ""
1641
 
1642
- #: ../settings.php:292
1643
  msgid "All traffic"
1644
  msgstr ""
1645
 
1646
- #: ../settings.php:296
1647
  msgid "Ignore crawlers"
1648
  msgstr ""
1649
 
1650
- #: ../settings.php:301
1651
  msgid "Save request fields"
1652
  msgstr ""
1653
 
1654
- #: ../settings.php:306
1655
  msgid "Mask these form fields"
1656
  msgstr ""
1657
 
1658
- #: ../settings.php:317
1659
  msgid "Save request headers"
1660
  msgstr ""
1661
 
1662
- #: ../settings.php:323
1663
  msgid "Save $_SERVER"
1664
  msgstr ""
1665
 
1666
- #: ../settings.php:329
1667
  msgid "Save request cookies"
1668
  msgstr ""
1669
 
1670
- #: ../settings.php:336
1671
  msgid "Page generation time threshold"
1672
  msgstr ""
1673
 
1674
- #: ../settings.php:341
1675
  msgid "milliseconds"
1676
  msgstr ""
1677
 
1678
- #: ../settings.php:357
1679
  msgid "Scanner settings"
1680
  msgstr ""
1681
 
1682
- #: ../settings.php:358
1683
  msgid "Custom signatures"
1684
  msgstr ""
1685
 
1686
- #: ../settings.php:364
1687
  msgid ""
1688
  "Specify custom PHP code signatures. One item per line. To specify a REGEX "
1689
  "pattern, enclose a whole line in two braces."
1690
  msgstr ""
1691
 
1692
- #: ../settings.php:366
1693
  msgid "Unwanted file extensions"
1694
  msgstr ""
1695
 
1696
- #: ../settings.php:372
1697
  msgid ""
1698
  "Specify file extensions to search for. Full scan only. Use comma to separate "
1699
  "items."
1700
  msgstr ""
1701
 
1702
- #: ../settings.php:374
1703
  msgid "Directories to exclude"
1704
  msgstr ""
1705
 
1706
- #: ../settings.php:380
1707
  msgid ""
1708
- "Specify directories to exclude from scanning. One item per line. Use with "
1709
- "caution."
 
 
 
 
1710
  msgstr ""
1711
 
1712
- #: ../settings.php:382
 
 
 
 
1713
  msgid "Scan temporary directory"
1714
  msgstr ""
1715
 
1716
- #: ../settings.php:388
1717
  msgid "Scan session directory"
1718
  msgstr ""
1719
 
1720
- #: ../settings.php:394
1721
  msgid "Delete quarantined files after"
1722
  msgstr ""
1723
 
1724
- #: ../settings.php:409
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1725
  msgid "Make your protection smarter!"
1726
  msgstr ""
1727
 
1728
- #: ../settings.php:413
1729
  msgid ""
1730
  "Please enable Permalinks to use this feature. Set Permalink Settings to "
1731
  "something other than Default."
1732
  msgstr ""
1733
 
1734
- #: ../settings.php:416
1735
  msgid "Be careful about enabling these options."
1736
  msgstr ""
1737
 
1738
- #: ../settings.php:416
1739
  msgid "If you forget your Custom login URL, you will be unable to log in."
1740
  msgstr ""
1741
 
1742
- #: ../settings.php:420
1743
  msgid ""
1744
  "In the Citadel mode nobody is able to log in except IPs from the White IP "
1745
  "Access List. Active user sessions will not be affected."
1746
  msgstr ""
1747
 
1748
- #: ../settings.php:423
1749
  msgid "These settings do not affect hosts from the "
1750
  msgstr ""
1751
 
1752
- #: ../settings.php:426
1753
  msgid ""
1754
  "Before you can start using reCAPTCHA, you have to obtain Site key and Secret "
1755
  "key on the Google website"
1756
  msgstr ""
1757
 
1758
- #: ../settings.php:457
1759
  msgid "Lockouts"
1760
  msgstr ""
1761
 
1762
- #: ../settings.php:466
1763
  msgid "Users"
1764
  msgstr ""
1765
 
1766
- #: ../settings.php:578 ../settings.php:700
1767
  #, php-format
1768
  msgid "%s allowed retries in %s minutes"
1769
  msgstr ""
1770
 
1771
- #: ../settings.php:583 ../settings.php:705
1772
  #, php-format
1773
  msgid "%s allowed registrations in %s minutes from one IP"
1774
  msgstr ""
1775
 
1776
- #: ../settings.php:588 ../settings.php:710
1777
  #, php-format
1778
  msgid "Increase lockout duration to %s hours after %s lockouts in the last %s hours"
1779
  msgstr ""
1780
 
1781
- #: ../settings.php:595 ../settings.php:717
1782
  msgid "Notify admin if the number of active lockouts above"
1783
  msgstr ""
1784
 
1785
- #: ../settings.php:600 ../settings.php:722
1786
  #, php-format
1787
  msgid "Enable after %s failed login attempts in last %s minutes"
1788
  msgstr ""
1789
 
1790
- #: ../settings.php:808
1791
  msgid "Sunday"
1792
  msgstr ""
1793
 
1794
- #: ../settings.php:809
1795
  msgid "Monday"
1796
  msgstr ""
1797
 
1798
- #: ../settings.php:810
1799
  msgid "Tuesday"
1800
  msgstr ""
1801
 
1802
- #: ../settings.php:811
1803
  msgid "Wednesday"
1804
  msgstr ""
1805
 
1806
- #: ../settings.php:812
1807
  msgid "Thursday"
1808
  msgstr ""
1809
 
1810
- #: ../settings.php:813
1811
  msgid "Friday"
1812
  msgstr ""
1813
 
1814
- #: ../settings.php:814
1815
  msgid "Saturday"
1816
  msgstr ""
1817
 
1818
  #. translators: preposition of time
1819
- #: ../settings.php:824
1820
  msgctxt "preposition of time"
1821
  msgid "at"
1822
  msgstr ""
1823
 
1824
- #: ../settings.php:840
1825
  msgid "Click to send now"
1826
  msgstr ""
1827
 
1828
- #: ../settings.php:852
1829
  msgid "Plugin initialization mode has not been changed"
1830
  msgstr ""
1831
 
1832
- #: ../settings.php:872 ../settings.php:873
1833
  msgid "Attention! You have changed the login URL! The new login URL is"
1834
  msgstr ""
1835
 
1836
- #: ../settings.php:874 ../settings.php:875
1837
  msgid ""
1838
  "If you use a caching plugin, you have to add your new login URL to the list "
1839
  "of pages not to cache."
1840
  msgstr ""
1841
 
1842
- #: ../settings.php:953 ../settings.php:965
1843
  msgid "<strong>ERROR</strong>: please enter a valid email address."
1844
  msgstr ""
1845
 
 
 
 
 
 
 
 
 
1846
  #: ../cerber-tools.php:48
1847
  msgid "Export & Import"
1848
  msgstr ""
@@ -1896,7 +1976,7 @@ msgstr ""
1896
  msgid "What do you want to import?"
1897
  msgstr ""
1898
 
1899
- #: ../cerber-tools.php:102
1900
  msgid "Upload file"
1901
  msgstr ""
1902
 
@@ -1920,106 +2000,241 @@ msgstr ""
1920
  msgid "Antispam and bot detection settings"
1921
  msgstr ""
1922
 
1923
- #: ../cerber-scanner.php:72
1924
  msgid "Security Scanner"
1925
  msgstr ""
1926
 
1927
- #: ../cerber-scanner.php:135
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1928
  msgid "Start Quick Scan"
1929
  msgstr ""
1930
 
1931
- #: ../cerber-scanner.php:136
1932
  msgid "Start Full Scan"
1933
  msgstr ""
1934
 
1935
- #: ../cerber-scanner.php:137
1936
  msgid "Stop Scanning"
1937
  msgstr ""
1938
 
1939
- #: ../cerber-scanner.php:138
1940
- msgid "Continues Scanning"
1941
  msgstr ""
1942
 
1943
- #: ../cerber-scanner.php:162
1944
  msgid "Delete"
1945
  msgstr ""
1946
 
1947
- #: ../cerber-scanner.php:1639
1948
  msgid "Verified"
1949
  msgstr ""
1950
 
1951
- #: ../cerber-scanner.php:1640
1952
  msgid "Integrity data not found"
1953
  msgstr ""
1954
 
1955
- #: ../cerber-scanner.php:1641
1956
  msgid "Unable to check the integrity of the plugin due to a network error"
1957
  msgstr ""
1958
 
1959
- #: ../cerber-scanner.php:1642
1960
  msgid "Unable to check the integrity of WordPress files due to a network error"
1961
  msgstr ""
1962
 
1963
- #: ../cerber-scanner.php:1643
1964
  msgid "Unable to check the integrity of the theme due to a network error"
1965
  msgstr ""
1966
 
1967
- #: ../cerber-scanner.php:1645
1968
  msgid "Local file doesn't exist"
1969
  msgstr ""
1970
 
1971
- #: ../cerber-scanner.php:1647 ../cerber-scanner.php:4518
 
 
 
 
1972
  msgid "Unable to open file"
1973
  msgstr ""
1974
 
1975
- #: ../cerber-scanner.php:1648
1976
- msgid "Content has been modified"
1977
  msgstr ""
1978
 
1979
- #: ../cerber-scanner.php:1650
1980
  msgid "Suspicious code found"
1981
  msgstr ""
1982
 
1983
- #: ../cerber-scanner.php:1651
1984
  msgid "Potentially malicious code found"
1985
  msgstr ""
1986
 
1987
- #: ../cerber-scanner.php:1652
1988
  msgid "Unattended suspicious file"
1989
  msgstr ""
1990
 
1991
- #: ../cerber-scanner.php:1653
1992
  msgid "Executable code found"
1993
  msgstr ""
1994
 
1995
- #: ../cerber-scanner.php:1655
1996
- msgid "Unwanted extension"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1997
  msgstr ""
1998
 
1999
- #: ../cerber-scanner.php:2609
2000
  msgid "Custom signature found"
2001
  msgstr ""
2002
 
2003
- #: ../cerber-scanner.php:3595
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2004
  msgid "Files to scan"
2005
  msgstr ""
2006
 
2007
- #: ../cerber-scanner.php:3603
2008
  msgid "Critical issues"
2009
  msgstr ""
2010
 
2011
- #: ../cerber-scanner.php:3607
2012
  msgid "Issues total"
2013
  msgstr ""
2014
 
2015
- #: ../cerber-scanner.php:3963
 
 
 
 
 
 
 
 
 
 
 
2016
  msgid "The directory is not writable"
2017
  msgstr ""
2018
 
2019
- #: ../cerber-scanner.php:3981
2020
  msgid "Unable to create WP CERBER directory"
2021
  msgstr ""
2022
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2023
  #. Description of the plugin
2024
  msgid ""
2025
  "This is a standard boot module for WP Cerber Security & Antispam plugin. It "
5
  "Project-Id-Version: WP Cerber\n"
6
  "Report-Msgid-Bugs-To: \n"
7
  "POT-Creation-Date: Tue Sep 08 2015 21:38:11 GMT+0300\n"
8
+ "POT-Revision-Date: Mon Jul 09 2018 15:34:08 GMT+0300\n"
9
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
10
  "Last-Translator: \n"
11
  "Language-Team: \n"
24
  "esc_html_x:1,2c;comments_number_link:2,3;t:1;st:1;trans:1;transChoice:1,2\n"
25
  "X-Generator: Loco - https://localise.biz/"
26
 
27
+ #: ../dashboard.php:52 ../settings.php:540
28
  msgid "WP Cerber Security"
29
  msgstr ""
30
 
37
  msgid "Cerber Dashboard"
38
  msgstr ""
39
 
40
+ #: ../dashboard.php:54 ../dashboard.php:1268 ../dashboard.php:1941 ../settings.
41
+ #: php:545
42
  msgid "Dashboard"
43
  msgstr ""
44
 
46
  msgid "Cerber Traffic Inspector"
47
  msgstr ""
48
 
49
+ #: ../dashboard.php:56 ../dashboard.php:1238 ../dashboard.php:2733
50
  msgid "Traffic Inspector"
51
  msgstr ""
52
 
54
  msgid "Cerber Security Rules"
55
  msgstr ""
56
 
57
+ #: ../dashboard.php:60 ../dashboard.php:2393
58
  msgid "Security Rules"
59
  msgstr ""
60
 
61
+ #: ../dashboard.php:64 ../cerber-scanner.php:76
62
  msgid "Site Integrity"
63
  msgstr ""
64
 
66
  msgid "Cerber antispam settings"
67
  msgstr ""
68
 
69
+ #: ../dashboard.php:67 ../dashboard.php:1271 ../cerber-load.php:4177 ../settings.
70
+ #: php:200
71
  msgid "Antispam"
72
  msgstr ""
73
 
83
  msgid "Remove"
84
  msgstr ""
85
 
86
+ #: ../dashboard.php:133 ../dashboard.php:699 ../dashboard.php:3063 ../cerber-load.
87
+ #: php:3931
88
  msgid "IP"
89
  msgstr ""
90
 
100
  msgid "Expires"
101
  msgstr ""
102
 
103
+ #: ../dashboard.php:137 ../cerber-load.php:3415
104
  msgid "Reason"
105
  msgstr ""
106
 
126
  msgstr ""
127
 
128
  #: ../dashboard.php:171 ../dashboard.php:674 ../dashboard.php:877 ../dashboard.
129
+ #: php:1233 ../dashboard.php:2888 ../cerber-load.php:4168 ../settings.php:517
130
  msgid "White IP Access List"
131
  msgstr ""
132
 
135
  msgstr ""
136
 
137
  #: ../dashboard.php:173 ../dashboard.php:675 ../dashboard.php:880 ../dashboard.
138
+ #: php:1234 ../dashboard.php:2889
139
  msgid "Black IP Access List"
140
  msgstr ""
141
 
186
  msgid "Address %s was added to Black IP Access List"
187
  msgstr ""
188
 
189
+ #: ../dashboard.php:353 ../dashboard.php:2818 ../whois.php:223 ../whois.php:254 ..
190
+ #: /common.php:881 ../common.php:1208
191
  msgid "Unknown"
192
  msgstr ""
193
 
208
  msgid "Lockout for %s was removed"
209
  msgstr ""
210
 
211
+ #: ../dashboard.php:445 ../dashboard.php:1765
212
  msgid "Settings saved"
213
  msgstr ""
214
 
216
  msgid "IP address"
217
  msgstr ""
218
 
219
+ #: ../dashboard.php:538 ../dashboard.php:702 ../dashboard.php:3061
220
  msgid "Date"
221
  msgstr ""
222
 
224
  msgid "Event"
225
  msgstr ""
226
 
227
+ #: ../dashboard.php:538 ../dashboard.php:704 ../dashboard.php:3066
228
  msgid "Local User"
229
  msgstr ""
230
 
236
  msgid "User ID"
237
  msgstr ""
238
 
239
+ #: ../dashboard.php:538 ../dashboard.php:705 ../cerber-load.php:3939
240
  msgid "Username used"
241
  msgstr ""
242
 
243
+ #: ../dashboard.php:679 ../dashboard.php:883 ../dashboard.php:2893 ../common.php:
244
  #: 852
245
  msgid "Locked out"
246
  msgstr ""
301
  msgid "Failed login attempts"
302
  msgstr ""
303
 
304
+ #: ../dashboard.php:1129 ../dashboard.php:1216 ../common.php:949
305
  msgid "Never"
306
  msgstr ""
307
 
313
  msgid "Cerber Quick View"
314
  msgstr ""
315
 
316
+ #: ../dashboard.php:1220 ../dashboard.php:1242
317
  msgid "active"
318
  msgstr ""
319
 
353
  msgid "Last lockout"
354
  msgstr ""
355
 
356
+ #: ../dashboard.php:1233 ../dashboard.php:1234 ../dashboard.php:1921
357
  msgid "entry"
358
  msgid_plural "entries"
359
  msgstr[0] ""
360
  msgstr[1] ""
361
 
362
+ #: ../dashboard.php:1235 ../settings.php:101
363
  msgid "Citadel mode"
364
  msgstr ""
365
 
367
  msgid "enabled"
368
  msgstr ""
369
 
370
+ #: ../dashboard.php:1242
371
  msgid "no connection"
372
  msgstr ""
373
 
374
+ #: ../dashboard.php:1255 ../dashboard.php:1257 ../cerber-scanner.php:1143
375
+ msgid "Disabled"
376
+ msgstr ""
377
+
378
+ #: ../dashboard.php:1256 ../cerber-scanner.php:726
379
+ msgid "Quick Scan"
380
+ msgstr ""
381
+
382
+ #: ../dashboard.php:1258 ../cerber-scanner.php:726
383
+ msgid "Full Scan"
384
+ msgstr ""
385
+
386
+ #: ../dashboard.php:1269 ../dashboard.php:1589 ../cerber-load.php:3922 ..
387
+ #: /settings.php:106 ../settings.php:547
388
  msgid "Activity"
389
  msgstr ""
390
 
391
+ #: ../dashboard.php:1270
392
  msgid "Traffic"
393
  msgstr ""
394
 
395
+ #: ../dashboard.php:1429 ../settings.php:81
396
  msgid "My site is behind a reverse proxy"
397
  msgstr ""
398
 
399
+ #: ../dashboard.php:1568
400
  msgid "in the last 24 hours"
401
  msgstr ""
402
 
403
+ #: ../dashboard.php:1574 ../dashboard.php:1604
404
  msgid "View all"
405
  msgstr ""
406
 
407
+ #: ../dashboard.php:1582 ../common.php:804
408
  msgid "User registered"
409
  msgstr ""
410
 
411
+ #: ../dashboard.php:1583
412
  msgid "All suspicious activity"
413
  msgstr ""
414
 
415
+ #: ../dashboard.php:1605
416
  msgid "Recently locked out IP addresses"
417
  msgstr ""
418
 
419
+ #: ../dashboard.php:1630
420
  msgid "Confused about some settings?"
421
  msgstr ""
422
 
423
+ #: ../dashboard.php:1631
424
  msgid "You can easily load default recommended settings using button below"
425
  msgstr ""
426
 
427
+ #: ../dashboard.php:1633
428
  msgid "Load default settings"
429
  msgstr ""
430
 
431
+ #: ../dashboard.php:1635
432
  msgid "Are you sure?"
433
  msgstr ""
434
 
435
+ #: ../dashboard.php:1641
436
  msgid "doesn't affect Custom login URL and Access Lists"
437
  msgstr ""
438
 
439
+ #: ../dashboard.php:1642 ../cerber-load.php:3447 ../cerber-load.php:4170
440
  msgid "Getting Started Guide"
441
  msgstr ""
442
 
443
+ #: ../dashboard.php:1748
444
  msgid "Attention! Citadel mode is now active. Nobody is able to log in."
445
  msgstr ""
446
 
447
+ #: ../dashboard.php:1749
448
  msgid "Deactivate"
449
  msgstr ""
450
 
451
+ #: ../dashboard.php:1750 ../dashboard.php:2225
452
  msgid "View Activity"
453
  msgstr ""
454
 
455
+ #: ../dashboard.php:1851
456
  msgid "Subscribe"
457
  msgstr ""
458
 
459
+ #: ../dashboard.php:1852 ../cerber-tools.php:273
460
  msgid "Unsubscribe"
461
  msgstr ""
462
 
463
+ #: ../dashboard.php:1880
464
  msgid "You've subscribed"
465
  msgstr ""
466
 
467
+ #: ../dashboard.php:1883
468
  msgid "You've unsubscribed"
469
  msgstr ""
470
 
471
+ #: ../dashboard.php:1942
472
  msgid "Main settings"
473
  msgstr ""
474
 
475
+ #: ../dashboard.php:2398
476
  msgid "Countries"
477
  msgstr ""
478
 
479
+ #: ../dashboard.php:2461
480
  #, php-format
481
  msgid "Permitted for one country"
482
  msgid_plural "Permitted for %d countries"
483
  msgstr[0] ""
484
  msgstr[1] ""
485
 
486
+ #: ../dashboard.php:2464
487
  #, php-format
488
  msgid "Not permitted for one country"
489
  msgid_plural "Not permitted for %d countries"
490
  msgstr[0] ""
491
  msgstr[1] ""
492
 
493
+ #: ../dashboard.php:2472
494
  msgid "No rule"
495
  msgstr ""
496
 
497
+ #: ../dashboard.php:2528
498
  msgid "Start typing here to find a country"
499
  msgstr ""
500
 
501
+ #: ../dashboard.php:2611
502
  msgid "Click on a country name to add it to the list of selected countries"
503
  msgstr ""
504
 
505
+ #: ../dashboard.php:2615
506
  #, php-format
507
  msgctxt "to is a marker of infinitive, e.g. \"to use it\""
508
  msgid "Selected countries are permitted to %s, other countries are not permitted to"
509
  msgstr ""
510
 
511
+ #: ../dashboard.php:2618
512
  #, php-format
513
  msgctxt "to is a marker of infinitive, e.g. \"to use it\""
514
  msgid "Selected countries are not permitted to %s, other countries are permitted to"
515
  msgstr ""
516
 
517
+ #: ../dashboard.php:2635
518
  msgid "Submit forms"
519
  msgstr ""
520
 
521
+ #: ../dashboard.php:2636
522
  msgid "Post comments"
523
  msgstr ""
524
 
525
+ #: ../dashboard.php:2637
526
  msgid "Log in to the website"
527
  msgstr ""
528
 
529
+ #: ../dashboard.php:2638
530
  msgid "Register on the website"
531
  msgstr ""
532
 
533
+ #: ../dashboard.php:2639
534
  msgid "Use XML-RPC"
535
  msgstr ""
536
 
537
+ #: ../dashboard.php:2640
538
  msgid "Use REST API"
539
  msgstr ""
540
 
541
+ #: ../dashboard.php:2684
542
  msgid "Security rules have been updated"
543
  msgstr ""
544
 
545
+ #: ../dashboard.php:2738
546
  msgid "Live traffic"
547
  msgstr ""
548
 
549
+ #: ../dashboard.php:2739 ../cerber-tools.php:91 ../cerber-tools.php:100 ../cerber-
550
+ #: scanner.php:82
551
  msgid "Settings"
552
  msgstr ""
553
 
554
+ #: ../dashboard.php:2740 ../settings.php:565 ../cerber-tools.php:51 ../cerber-
555
+ #: scanner.php:84
556
  msgid "Help"
557
  msgstr ""
558
 
559
+ #: ../dashboard.php:3062
560
  msgid "Request"
561
  msgstr ""
562
 
563
+ #: ../dashboard.php:3064
564
  msgid "Host Info"
565
  msgstr ""
566
 
567
+ #: ../dashboard.php:3065
568
  msgid "User Agent"
569
  msgstr ""
570
 
571
+ #: ../dashboard.php:3082
572
  msgid "No requests have been logged."
573
  msgstr ""
574
 
575
+ #: ../dashboard.php:3090
576
  msgid "All requests"
577
  msgstr ""
578
 
579
+ #: ../dashboard.php:3091 ../settings.php:171
580
  msgid "Logged in users"
581
  msgstr ""
582
 
583
+ #: ../dashboard.php:3092
584
  msgid "Not logged in visitors"
585
  msgstr ""
586
 
587
+ #: ../dashboard.php:3093
588
  msgid "Form submissions"
589
  msgstr ""
590
 
591
+ #: ../dashboard.php:3094
592
  msgid "Page Not Found"
593
  msgstr ""
594
 
595
+ #: ../dashboard.php:3095
596
  msgid "REST API"
597
  msgstr ""
598
 
599
+ #: ../dashboard.php:3096
600
  msgid "XML-RPC"
601
  msgstr ""
602
 
603
+ #: ../dashboard.php:3100
604
  msgid "Longer than"
605
  msgstr ""
606
 
607
+ #: ../dashboard.php:3113
608
  msgid "Refresh"
609
  msgstr ""
610
 
611
+ #: ../dashboard.php:3333
612
  msgid "Any"
613
  msgstr ""
614
 
615
+ #: ../dashboard.php:3375
616
  msgid "Advanced search"
617
  msgstr ""
618
 
619
  #. Name of the plugin
620
+ msgid "WP Cerber Security, Antispam & Malware Scan"
621
  msgstr ""
622
 
623
  #. URI of the plugin
661
  msgstr ""
662
 
663
  #: ../common.php:206 ../common.php:263 ../common.php:268 ../common.php:273 ..
664
+ #: /cerber-load.php:669 ../cerber-load.php:681 ../cerber-load.php:688 ../cerber-
665
+ #: load.php:933 ../cerber-load.php:1152 ../cerber-load.php:1158 ../cerber-load.
666
+ #: php:1163 ../cerber-load.php:1168 ../cerber-load.php:1174 ../cerber-load.php:
667
+ #: 1181 ../cerber-load.php:1285 ../cerber-load.php:1422 ../settings.php:960 ..
668
+ #: /settings.php:1029
669
  msgid "ERROR:"
670
  msgstr ""
671
 
830
  msgid "%s ago"
831
  msgstr ""
832
 
833
+ #: ../common.php:1121 ../settings.php:225
834
  msgid "New version is available"
835
  msgstr ""
836
 
837
+ #: ../common.php:1128
838
  #, php-format
839
  msgid "Update to version %s of WP Cerber"
840
  msgstr ""
841
 
842
+ #: ../common.php:1147
843
  msgid "Not specified"
844
  msgstr ""
845
 
846
+ #: ../common.php:1756
847
  msgid "Unable to create the directory"
848
  msgstr ""
849
 
850
+ #: ../common.php:1761
851
  msgid "Destination folder access denied"
852
  msgstr ""
853
 
854
+ #: ../common.php:1764
855
  msgid "File not found"
856
  msgstr ""
857
 
858
+ #: ../common.php:1767
859
  msgid "Unable to copy the file"
860
  msgstr ""
861
 
862
+ #: ../common.php:1773
863
  msgid "Unable to delete the file"
864
  msgstr ""
865
 
866
+ #: ../cerber-news.php:176
867
  msgid "Cool!"
868
  msgstr ""
869
 
870
+ #: ../cerber-lab.php:753
871
  msgid "Want to make WP Cerber even more powerful?"
872
  msgstr ""
873
 
874
+ #: ../cerber-lab.php:754
875
  msgid ""
876
  "Allow WP Cerber to send locked out malicious IP addresses to Cerber Lab. "
877
  "This helps the plugin team to develop new algorithms for WP Cerber that will "
879
  "everyday. You can disable the sending in the plugin settings at any time."
880
  msgstr ""
881
 
882
+ #: ../cerber-lab.php:755
883
  msgid "OK, nail them all"
884
  msgstr ""
885
 
886
+ #: ../cerber-lab.php:756
887
  msgid "NO, maybe later"
888
  msgstr ""
889
 
890
+ #: ../cerber-lab.php:757 ../settings.php:521
891
  msgid "Know more"
892
  msgstr ""
893
 
894
+ #: ../cerber-load.php:361
895
  msgid "You are not allowed to log in. Ask your administrator for assistance."
896
  msgstr ""
897
 
898
+ #: ../cerber-load.php:367
899
  #, php-format
900
  msgid "You have reached the login attempts limit. Please try again in %d minutes."
901
  msgstr ""
902
 
903
+ #: ../cerber-load.php:386
904
  #, php-format
905
  msgid "You have only one attempt remaining."
906
  msgid_plural "You have %d attempts remaining."
907
  msgstr[0] ""
908
  msgstr[1] ""
909
 
910
+ #: ../cerber-load.php:698
911
  msgid ""
912
  "Human verification failed. Please click the square box in the reCAPTCHA "
913
  "block below."
914
  msgstr ""
915
 
916
+ #: ../cerber-load.php:797
917
  msgid ""
918
  "> > > Translator of WP Cerber? To get the PRO license for free, drop your "
919
  "contacts here: https://wpcerber.com/contact/"
920
  msgstr ""
921
 
922
+ #: ../cerber-load.php:945
923
  #, php-format
924
  msgid ""
925
  "<strong>ERROR</strong>: The password you entered for the username %s is "
926
  "incorrect."
927
  msgstr ""
928
 
929
+ #: ../cerber-load.php:1153 ../cerber-load.php:1159 ../cerber-load.php:1175 ..
930
+ #: /cerber-load.php:1182
931
  msgid "You are not allowed to register."
932
  msgstr ""
933
 
934
+ #: ../cerber-load.php:1169
935
  msgid "Username is not allowed. Please choose another one."
936
  msgstr ""
937
 
938
+ #: ../cerber-load.php:1422
939
  msgid "Sorry, human verification failed."
940
  msgstr ""
941
 
942
+ #: ../cerber-load.php:3247
943
  msgid "We're sorry, you are not allowed to proceed"
944
  msgstr ""
945
 
946
+ #: ../cerber-load.php:3357
947
  msgid "WP Cerber notify"
948
  msgstr ""
949
 
950
+ #: ../cerber-load.php:3379
951
  msgid "Citadel mode is activated"
952
  msgstr ""
953
 
954
+ #: ../cerber-load.php:3381
955
  #, php-format
956
  msgid "Citadel mode is activated after %d failed login attempts in %d minutes."
957
  msgstr ""
958
 
959
+ #: ../cerber-load.php:3382
960
  #, php-format
961
  msgid "Last failed attempt was at %s from IP %s with user login: %s."
962
  msgstr ""
963
 
964
+ #: ../cerber-load.php:3383 ../cerber-load.php:3963
965
  msgid "View activity in dashboard"
966
  msgstr ""
967
 
968
+ #: ../cerber-load.php:3408
969
  msgid "unspecified"
970
  msgstr ""
971
 
972
+ #: ../cerber-load.php:3411
973
  msgid "Number of lockouts is increasing"
974
  msgstr ""
975
 
976
+ #: ../cerber-load.php:3413
977
  msgid "Number of active lockouts"
978
  msgstr ""
979
 
980
+ #: ../cerber-load.php:3414
981
  #, php-format
982
  msgid "Last lockout was added: %s for IP %s"
983
  msgstr ""
984
 
985
+ #: ../cerber-load.php:3416
986
  msgid "View activity for this IP"
987
  msgstr ""
988
 
989
+ #: ../cerber-load.php:3417
990
  msgid "View lockouts in dashboard"
991
  msgstr ""
992
 
993
+ #: ../cerber-load.php:3420 ../cerber-load.php:3422
994
  msgid "A new version of WP Cerber is available to install"
995
  msgstr ""
996
 
997
+ #: ../cerber-load.php:3421
998
  msgid "Hi!"
999
  msgstr ""
1000
 
1001
+ #: ../cerber-load.php:3424 ../cerber-load.php:3435
1002
  msgid "Website"
1003
  msgstr ""
1004
 
1005
+ #: ../cerber-load.php:3427 ../cerber-load.php:3428
1006
  msgid "The WP Cerber security plugin has been deactivated"
1007
  msgstr ""
1008
 
1009
+ #: ../cerber-load.php:3430
1010
  msgid "Not logged in"
1011
  msgstr ""
1012
 
1013
+ #: ../cerber-load.php:3436
1014
  msgid "By user"
1015
  msgstr ""
1016
 
1017
+ #: ../cerber-load.php:3437
1018
  msgid "From IP address"
1019
  msgstr ""
1020
 
1021
+ #: ../cerber-load.php:3440
1022
  msgid "From country"
1023
  msgstr ""
1024
 
1025
+ #: ../cerber-load.php:3444
1026
  msgid "The WP Cerber security plugin is now active"
1027
  msgstr ""
1028
 
1029
+ #: ../cerber-load.php:3445 ../cerber-load.php:4167
1030
  msgid "WP Cerber is now active and has started protecting your site"
1031
  msgstr ""
1032
 
1033
+ #: ../cerber-load.php:3452
1034
  msgid "New Custom login URL"
1035
  msgstr ""
1036
 
1037
+ #: ../cerber-load.php:3456 ../cerber-load.php:3457
1038
  msgid "A new activity has been recorded"
1039
  msgstr ""
1040
 
1041
+ #: ../cerber-load.php:3462
1042
  msgid "Weekly report"
1043
  msgstr ""
1044
 
1045
+ #: ../cerber-load.php:3465 ../cerber-load.php:3475
1046
  msgid "To change reporting settings visit"
1047
  msgstr ""
1048
 
1049
+ #: ../cerber-load.php:3472
1050
+ msgid "Scanner Report"
1051
+ msgstr ""
1052
+
1053
+ #: ../cerber-load.php:3498
1054
  msgid "Your login page:"
1055
  msgstr ""
1056
 
1057
+ #: ../cerber-load.php:3502
1058
  msgid "Your license is valid until"
1059
  msgstr ""
1060
 
1061
+ #: ../cerber-load.php:3505
1062
  msgid "This message was sent by"
1063
  msgstr ""
1064
 
1065
+ #: ../cerber-load.php:3526
1066
  #, php-format
1067
  msgid "Your last sign-in was %s from %s"
1068
  msgstr ""
1069
 
1070
+ #: ../cerber-load.php:3596
1071
  msgid "Weekly Report"
1072
  msgstr ""
1073
 
1074
+ #: ../cerber-load.php:3608
1075
  msgid "Activity details"
1076
  msgstr ""
1077
 
1078
+ #: ../cerber-load.php:3622
1079
  msgid "Attempts to log in with non-existent username"
1080
  msgstr ""
1081
 
1082
+ #: ../cerber-load.php:3935
1083
  msgid "User"
1084
  msgstr ""
1085
 
1086
+ #: ../cerber-load.php:3943
1087
  msgid "Search string"
1088
  msgstr ""
1089
 
1090
+ #: ../cerber-load.php:3964
1091
  msgid "To unsubscribe click here"
1092
  msgstr ""
1093
 
1094
+ #: ../cerber-load.php:4120
1095
  #, php-format
1096
  msgid "The WP Cerber requires PHP %s or higher. You are running"
1097
  msgstr ""
1098
 
1099
+ #: ../cerber-load.php:4124
1100
  #, php-format
1101
  msgid "The WP Cerber requires WordPress %s or higher. You are running"
1102
  msgstr ""
1103
 
1104
+ #: ../cerber-load.php:4133
1105
  msgid "Can't activate WP Cerber due to a database error."
1106
  msgstr ""
1107
 
1108
+ #: ../cerber-load.php:4168
1109
  msgid "Your IP address is added to the"
1110
  msgstr ""
1111
 
1112
+ #: ../cerber-load.php:4175 ../settings.php:553
1113
  msgid "Main Settings"
1114
  msgstr ""
1115
 
1116
+ #: ../cerber-load.php:4176 ../settings.php:556 ../cerber-tools.php:92 ../cerber-
1117
  #: tools.php:101 ../cerber-tools.php:182
1118
  msgid "Access Lists"
1119
  msgstr ""
1120
 
1121
+ #: ../cerber-load.php:4178 ../settings.php:558
1122
  msgid "Hardening"
1123
  msgstr ""
1124
 
1125
+ #: ../cerber-load.php:4179 ../settings.php:80 ../settings.php:104 ../settings.php:
1126
+ #: 563
1127
  msgid "Notifications"
1128
  msgstr ""
1129
 
1130
+ #: ../cerber-load.php:4180
1131
  msgid "Import settings"
1132
  msgstr ""
1133
 
1134
+ #: ../settings.php:72
1135
  msgid "Plugin initialization"
1136
  msgstr ""
1137
 
1138
+ #: ../settings.php:73
1139
  msgid "Load security engine"
1140
  msgstr ""
1141
 
1142
+ #: ../settings.php:73
1143
  msgid "Legacy mode"
1144
  msgstr ""
1145
 
1146
+ #: ../settings.php:73
1147
  msgid "Standard mode"
1148
  msgstr ""
1149
 
1150
+ #: ../settings.php:75
1151
  msgid "Limit login attempts"
1152
  msgstr ""
1153
 
1154
+ #: ../settings.php:76
1155
  msgid "Attempts"
1156
  msgstr ""
1157
 
1158
+ #: ../settings.php:77
1159
  msgid "Lockout duration"
1160
  msgstr ""
1161
 
1162
+ #: ../settings.php:77 ../settings.php:103
1163
  msgid "minutes"
1164
  msgstr ""
1165
 
1166
+ #: ../settings.php:78
1167
  msgid "Aggressive lockout"
1168
  msgstr ""
1169
 
1170
+ #: ../settings.php:79 ../settings.php:278
1171
  msgid "Use White IP Access List"
1172
  msgstr ""
1173
 
1174
+ #: ../settings.php:79
1175
  msgid "Apply limit login rules to IP addresses in the White IP Access List"
1176
  msgstr ""
1177
 
1178
+ #: ../settings.php:81
1179
  msgid "Site connection"
1180
  msgstr ""
1181
 
1182
+ #: ../settings.php:83
1183
  msgid "Proactive security rules"
1184
  msgstr ""
1185
 
1186
+ #: ../settings.php:84
1187
  msgid "Block subnet"
1188
  msgstr ""
1189
 
1190
+ #: ../settings.php:84
1191
  msgid "Always block entire subnet Class C of intruders IP"
1192
  msgstr ""
1193
 
1194
+ #: ../settings.php:85
1195
  msgid "Non-existent users"
1196
  msgstr ""
1197
 
1198
+ #: ../settings.php:85
1199
  msgid "Immediately block IP when attempting to login with a non-existent username"
1200
  msgstr ""
1201
 
1202
+ #: ../settings.php:86
1203
+ msgid "Disable dashboard redirection"
1204
  msgstr ""
1205
 
1206
+ #: ../settings.php:86
1207
  msgid ""
1208
+ "Disable automatic redirection to the login page when /wp-admin/ is requested "
1209
  "by an unauthorized request"
1210
  msgstr ""
1211
 
1212
+ #: ../settings.php:87
1213
  msgid "Request wp-login.php"
1214
  msgstr ""
1215
 
1216
+ #: ../settings.php:87
1217
  msgid "Immediately block IP after any request to wp-login.php"
1218
  msgstr ""
1219
 
1220
+ #: ../settings.php:88
1221
  msgid "Display 404 page"
1222
  msgstr ""
1223
 
1224
+ #: ../settings.php:88
1225
  msgid "Use 404 template from the active theme"
1226
  msgstr ""
1227
 
1228
+ #: ../settings.php:88
1229
  msgid "Display simple 404 page"
1230
  msgstr ""
1231
 
1232
+ #: ../settings.php:90
1233
  msgid "Custom login page"
1234
  msgstr ""
1235
 
1236
+ #: ../settings.php:91
1237
  msgid "Custom login URL"
1238
  msgstr ""
1239
 
1240
+ #: ../settings.php:96
1241
  msgid "Custom login URL may contain only letters, numbers, dashes and underscores"
1242
  msgstr ""
1243
 
1244
+ #: ../settings.php:97
1245
  msgid "must not overlap with the existing pages or posts slug"
1246
  msgstr ""
1247
 
1248
+ #: ../settings.php:99
1249
  msgid "Disable wp-login.php"
1250
  msgstr ""
1251
 
1252
+ #: ../settings.php:99
1253
  msgid "Block direct access to wp-login.php and return HTTP 404 Not Found Error"
1254
  msgstr ""
1255
 
1256
+ #: ../settings.php:102
1257
  msgid "Threshold"
1258
  msgstr ""
1259
 
1260
+ #: ../settings.php:103
1261
  msgid "Duration"
1262
  msgstr ""
1263
 
1264
+ #: ../settings.php:104
1265
  msgid "Send notification to admin email"
1266
  msgstr ""
1267
 
1268
+ #: ../settings.php:104 ../settings.php:694 ../settings.php:816
1269
  msgid "Click to send test"
1270
  msgstr ""
1271
 
1272
+ #: ../settings.php:107 ../settings.php:353
1273
  msgid "Keep records for"
1274
  msgstr ""
1275
 
1276
+ #: ../settings.php:107 ../settings.php:183 ../settings.php:357 ../settings.php:422
1277
  msgid "days"
1278
  msgstr ""
1279
 
1280
+ #: ../settings.php:108
1281
  msgid "Cerber Lab connection"
1282
  msgstr ""
1283
 
1284
+ #: ../settings.php:108
1285
  msgid "Send malicious IP addresses to the Cerber Lab"
1286
  msgstr ""
1287
 
1288
+ #: ../settings.php:109
1289
  msgid "Cerber Lab protocol"
1290
  msgstr ""
1291
 
1292
+ #: ../settings.php:110
1293
  msgid "Use file"
1294
  msgstr ""
1295
 
1296
+ #: ../settings.php:110
1297
  msgid "Write failed login attempts to the file"
1298
  msgstr ""
1299
 
1300
+ #: ../settings.php:112
1301
  msgid "Preferences"
1302
  msgstr ""
1303
 
1304
+ #: ../settings.php:113
1305
  msgid "Drill down IP"
1306
  msgstr ""
1307
 
1308
+ #: ../settings.php:113
1309
  msgid "Retrieve extra WHOIS information for IP"
1310
  msgstr ""
1311
 
1312
+ #: ../settings.php:114
1313
  msgid "Date format"
1314
  msgstr ""
1315
 
1316
+ #: ../settings.php:114
1317
  #, php-format
1318
  msgid "if empty, the default format %s will be used"
1319
  msgstr ""
1320
 
1321
+ #: ../settings.php:121
1322
  msgid "Hardening WordPress"
1323
  msgstr ""
1324
 
1325
+ #: ../settings.php:122
1326
  msgid "Stop user enumeration"
1327
  msgstr ""
1328
 
1329
+ #: ../settings.php:122
1330
  msgid "Block access to user pages like /?author=n and user data via REST API"
1331
  msgstr ""
1332
 
1333
+ #: ../settings.php:123
1334
  msgid "Protect admin scripts"
1335
  msgstr ""
1336
 
1337
+ #: ../settings.php:123
1338
  msgid "Block unauthorized access to load-scripts.php and load-styles.php"
1339
  msgstr ""
1340
 
1341
+ #: ../settings.php:124
1342
  msgid "Disable XML-RPC"
1343
  msgstr ""
1344
 
1345
+ #: ../settings.php:124
1346
  msgid "Block access to the XML-RPC server (including Pingbacks and Trackbacks)"
1347
  msgstr ""
1348
 
1349
+ #: ../settings.php:125
1350
  msgid "Disable feeds"
1351
  msgstr ""
1352
 
1353
+ #: ../settings.php:125
1354
  msgid "Block access to the RSS, Atom and RDF feeds"
1355
  msgstr ""
1356
 
1357
+ #: ../settings.php:126
1358
  msgid "Disable REST API"
1359
  msgstr ""
1360
 
1361
+ #: ../settings.php:126
1362
  msgid "Block access to the WordPress REST API except the following"
1363
  msgstr ""
1364
 
1365
+ #: ../settings.php:127
1366
  msgid "Allow REST API for logged in users"
1367
  msgstr ""
1368
 
1369
+ #: ../settings.php:134
1370
  msgid ""
1371
  "Specify REST API namespaces to be allowed if REST API is disabled. One "
1372
  "string per line."
1373
  msgstr ""
1374
 
1375
+ #: ../settings.php:144
1376
  msgid "User related settings"
1377
  msgstr ""
1378
 
1379
+ #: ../settings.php:146
1380
  msgid "Registration limit"
1381
  msgstr ""
1382
 
1383
+ #: ../settings.php:148
1384
  msgid "Prohibited usernames"
1385
  msgstr ""
1386
 
1387
+ #: ../settings.php:154
1388
  msgid ""
1389
  "Usernames from this list are not allowed to log in or register. Any IP "
1390
  "address, have tried to use any of these usernames, will be immediately "
1391
  "blocked. Use comma to separate logins."
1392
  msgstr ""
1393
 
1394
+ #: ../settings.php:154
1395
  msgid "To specify a REGEX pattern wrap a pattern in two forward slashes."
1396
  msgstr ""
1397
 
1398
+ #: ../settings.php:156
1399
  msgid "User session expire"
1400
  msgstr ""
1401
 
1402
+ #: ../settings.php:156
1403
  msgid "in minutes (leave empty to use default WP value)"
1404
  msgstr ""
1405
 
1406
+ #: ../settings.php:157
1407
  msgid "Sort users in dashboard"
1408
  msgstr ""
1409
 
1410
+ #: ../settings.php:157
1411
  msgid "by date of registration"
1412
  msgstr ""
1413
 
1414
+ #: ../settings.php:164
1415
  msgid "Cerber antispam engine"
1416
  msgstr ""
1417
 
1418
+ #: ../settings.php:165
1419
  msgid "Comment form"
1420
  msgstr ""
1421
 
1422
+ #: ../settings.php:165
1423
  msgid "Protect comment form with bot detection engine"
1424
  msgstr ""
1425
 
1426
+ #: ../settings.php:166 ../settings.php:191
1427
  msgid "Registration form"
1428
  msgstr ""
1429
 
1430
+ #: ../settings.php:166
1431
  msgid "Protect registration form with bot detection engine"
1432
  msgstr ""
1433
 
1434
+ #: ../settings.php:167
1435
  msgid "Other forms"
1436
  msgstr ""
1437
 
1438
+ #: ../settings.php:167
1439
  msgid "Protect all forms on the website with bot detection engine"
1440
  msgstr ""
1441
 
1442
+ #: ../settings.php:169
1443
  msgid "Adjust antispam engine"
1444
  msgstr ""
1445
 
1446
+ #: ../settings.php:170
1447
  msgid "Safe mode"
1448
  msgstr ""
1449
 
1450
+ #: ../settings.php:170
1451
  msgid "Use less restrictive policies (allow AJAX)"
1452
  msgstr ""
1453
 
1454
+ #: ../settings.php:171
1455
  msgid "Disable bot detection engine for logged in users"
1456
  msgstr ""
1457
 
1458
+ #: ../settings.php:172
1459
  msgid "Query whitelist"
1460
  msgstr ""
1461
 
1462
+ #: ../settings.php:178
1463
  msgid ""
1464
  "Enter a part of query string or query path to exclude a request from "
1465
  "inspection by the engine. One item per line."
1466
  msgstr ""
1467
 
1468
+ #: ../settings.php:178 ../settings.php:289
1469
  msgid "To specify a REGEX pattern, enclose a whole line in two braces."
1470
  msgstr ""
1471
 
1472
+ #: ../settings.php:181
1473
  msgid "Comment processing"
1474
  msgstr ""
1475
 
1476
+ #: ../settings.php:182
1477
  msgid "If a spam comment detected"
1478
  msgstr ""
1479
 
1480
+ #: ../settings.php:182
1481
  msgid "Deny it completely"
1482
  msgstr ""
1483
 
1484
+ #: ../settings.php:182
1485
  msgid "Mark it as spam"
1486
  msgstr ""
1487
 
1488
+ #: ../settings.php:183
1489
  msgid "Trash spam comments"
1490
  msgstr ""
1491
 
1492
+ #: ../settings.php:183
1493
  msgid "Move spam comments to trash after"
1494
  msgstr ""
1495
 
1496
+ #: ../settings.php:186
1497
  msgid "reCAPTCHA settings"
1498
  msgstr ""
1499
 
1500
+ #: ../settings.php:187
1501
  msgid "Site key"
1502
  msgstr ""
1503
 
1504
+ #: ../settings.php:188
1505
  msgid "Secret key"
1506
  msgstr ""
1507
 
1508
+ #: ../settings.php:189
1509
  msgid "Invisible reCAPTCHA"
1510
  msgstr ""
1511
 
1512
+ #: ../settings.php:189
1513
  msgid "Enable invisible reCAPTCHA"
1514
  msgstr ""
1515
 
1516
+ #: ../settings.php:189
1517
  msgid ""
1518
  "(do not enable it unless you get and enter the Site and Secret keys for the "
1519
  "invisible version)"
1520
  msgstr ""
1521
 
1522
+ #: ../settings.php:191
1523
  msgid "Enable reCAPTCHA for WordPress registration form"
1524
  msgstr ""
1525
 
1526
+ #: ../settings.php:192
1527
  msgid "Enable reCAPTCHA for WooCommerce registration form"
1528
  msgstr ""
1529
 
1530
+ #: ../settings.php:194
1531
  msgid "Lost password form"
1532
  msgstr ""
1533
 
1534
+ #: ../settings.php:194
1535
  msgid "Enable reCAPTCHA for WordPress lost password form"
1536
  msgstr ""
1537
 
1538
+ #: ../settings.php:195
1539
  msgid "Enable reCAPTCHA for WooCommerce lost password form"
1540
  msgstr ""
1541
 
1542
+ #: ../settings.php:197
1543
  msgid "Login form"
1544
  msgstr ""
1545
 
1546
+ #: ../settings.php:197
1547
  msgid "Enable reCAPTCHA for WordPress login form"
1548
  msgstr ""
1549
 
1550
+ #: ../settings.php:198
1551
  msgid "Enable reCAPTCHA for WooCommerce login form"
1552
  msgstr ""
1553
 
1554
+ #: ../settings.php:200
1555
  msgid "Enable reCAPTCHA for WordPress comment form"
1556
  msgstr ""
1557
 
1558
+ #: ../settings.php:201
1559
  msgid "Disable reCAPTCHA for logged in users"
1560
  msgstr ""
1561
 
1562
+ #: ../settings.php:203
1563
  msgid "Limit attempts"
1564
  msgstr ""
1565
 
1566
+ #: ../settings.php:203
1567
  #, php-format
1568
  msgid "Lock out IP address for %s minutes after %s failed attempts within %s minutes"
1569
  msgstr ""
1570
 
1571
+ #: ../settings.php:209
1572
  msgid "Email notifications"
1573
  msgstr ""
1574
 
1575
+ #: ../settings.php:212 ../settings.php:253 ../settings.php:484
1576
  msgid "Email Address"
1577
  msgstr ""
1578
 
1579
+ #: ../settings.php:216 ../settings.php:258 ../settings.php:321 ../settings.php:488
1580
  msgid "Use comma to specify multiple values"
1581
  msgstr ""
1582
 
1583
+ #: ../settings.php:221
1584
  #, php-format
1585
  msgid "if empty, the admin email %s will be used"
1586
  msgstr ""
1587
 
1588
+ #: ../settings.php:224
1589
  msgid "Notification limit"
1590
  msgstr ""
1591
 
1592
+ #: ../settings.php:224
1593
  msgid "notification letters allowed per hour (0 means unlimited)"
1594
  msgstr ""
1595
 
1596
+ #: ../settings.php:230
1597
  msgid "Push notifications"
1598
  msgstr ""
1599
 
1600
+ #: ../settings.php:238
1601
  msgid "All connected devices"
1602
  msgstr ""
1603
 
1604
+ #: ../settings.php:241
1605
  msgid "No devices found"
1606
  msgstr ""
1607
 
1608
+ #: ../settings.php:245
1609
  msgid "Not available"
1610
  msgstr ""
1611
 
1612
+ #: ../settings.php:250
1613
  msgid "Weekly reports"
1614
  msgstr ""
1615
 
1616
+ #: ../settings.php:251
1617
  msgid "Enable reporting"
1618
  msgstr ""
1619
 
1620
+ #: ../settings.php:263 ../settings.php:493
1621
  msgid "if empty, email from notification settings will be used"
1622
  msgstr ""
1623
 
1624
+ #: ../settings.php:271
1625
  msgid "Inspection"
1626
  msgstr ""
1627
 
1628
+ #: ../settings.php:272
1629
  msgid "Enable traffic inspection"
1630
  msgstr ""
1631
 
1632
+ #: ../settings.php:283
1633
  msgid "Request whitelist"
1634
  msgstr ""
1635
 
1636
+ #: ../settings.php:289
1637
  msgid ""
1638
  "Enter a request URI to exclude the request from inspection. One item per "
1639
  "line."
1640
  msgstr ""
1641
 
1642
+ #: ../settings.php:292
1643
  msgid "Logging"
1644
  msgstr ""
1645
 
1646
+ #: ../settings.php:293
1647
  msgid "Logging mode"
1648
  msgstr ""
1649
 
1650
+ #: ../settings.php:299
1651
  msgid "Logging disabled"
1652
  msgstr ""
1653
 
1654
+ #: ../settings.php:300
1655
  msgid "Smart"
1656
  msgstr ""
1657
 
1658
+ #: ../settings.php:301
1659
  msgid "All traffic"
1660
  msgstr ""
1661
 
1662
+ #: ../settings.php:305
1663
  msgid "Ignore crawlers"
1664
  msgstr ""
1665
 
1666
+ #: ../settings.php:310
1667
  msgid "Save request fields"
1668
  msgstr ""
1669
 
1670
+ #: ../settings.php:315
1671
  msgid "Mask these form fields"
1672
  msgstr ""
1673
 
1674
+ #: ../settings.php:326
1675
  msgid "Save request headers"
1676
  msgstr ""
1677
 
1678
+ #: ../settings.php:332
1679
  msgid "Save $_SERVER"
1680
  msgstr ""
1681
 
1682
+ #: ../settings.php:338
1683
  msgid "Save request cookies"
1684
  msgstr ""
1685
 
1686
+ #: ../settings.php:345
1687
  msgid "Page generation time threshold"
1688
  msgstr ""
1689
 
1690
+ #: ../settings.php:350
1691
  msgid "milliseconds"
1692
  msgstr ""
1693
 
1694
+ #: ../settings.php:366
1695
  msgid "Scanner settings"
1696
  msgstr ""
1697
 
1698
+ #: ../settings.php:367
1699
  msgid "Custom signatures"
1700
  msgstr ""
1701
 
1702
+ #: ../settings.php:373
1703
  msgid ""
1704
  "Specify custom PHP code signatures. One item per line. To specify a REGEX "
1705
  "pattern, enclose a whole line in two braces."
1706
  msgstr ""
1707
 
1708
+ #: ../settings.php:375
1709
  msgid "Unwanted file extensions"
1710
  msgstr ""
1711
 
1712
+ #: ../settings.php:381
1713
  msgid ""
1714
  "Specify file extensions to search for. Full scan only. Use comma to separate "
1715
  "items."
1716
  msgstr ""
1717
 
1718
+ #: ../settings.php:383
1719
  msgid "Directories to exclude"
1720
  msgstr ""
1721
 
1722
+ #: ../settings.php:389
1723
  msgid ""
1724
+ "Specify directories to exclude from scanning. Use absolute paths. One item "
1725
+ "per line."
1726
+ msgstr ""
1727
+
1728
+ #: ../settings.php:391
1729
+ msgid "Monitor new files"
1730
  msgstr ""
1731
 
1732
+ #: ../settings.php:398
1733
+ msgid "Monitor modified files"
1734
+ msgstr ""
1735
+
1736
+ #: ../settings.php:404
1737
  msgid "Scan temporary directory"
1738
  msgstr ""
1739
 
1740
+ #: ../settings.php:411
1741
  msgid "Scan session directory"
1742
  msgstr ""
1743
 
1744
+ #: ../settings.php:417
1745
  msgid "Delete quarantined files after"
1746
  msgstr ""
1747
 
1748
+ #: ../settings.php:432
1749
+ msgid "Launch Quick Scan"
1750
+ msgstr ""
1751
+
1752
+ #: ../settings.php:439
1753
+ msgid "Launch Full Scan"
1754
+ msgstr ""
1755
+
1756
+ #: ../settings.php:449
1757
+ msgid "Low severity"
1758
+ msgstr ""
1759
+
1760
+ #: ../settings.php:449
1761
+ msgid "Medium severity"
1762
+ msgstr ""
1763
+
1764
+ #: ../settings.php:449
1765
+ msgid "High severity"
1766
+ msgstr ""
1767
+
1768
+ #: ../settings.php:450
1769
+ msgid "Report an issue if any of the following is true"
1770
+ msgstr ""
1771
+
1772
+ #: ../settings.php:458
1773
+ msgid "Send email report"
1774
+ msgstr ""
1775
+
1776
+ #: ../settings.php:464
1777
+ msgid "After every scan"
1778
+ msgstr ""
1779
+
1780
+ #: ../settings.php:465
1781
+ msgid "If any changes in scan results occurred"
1782
+ msgstr ""
1783
+
1784
+ #: ../settings.php:466
1785
+ msgid "If new issues found"
1786
+ msgstr ""
1787
+
1788
+ #: ../settings.php:470
1789
+ msgid "Include file sizes"
1790
+ msgstr ""
1791
+
1792
+ #: ../settings.php:477
1793
+ msgid "Include scan errors"
1794
+ msgstr ""
1795
+
1796
+ #: ../settings.php:503
1797
  msgid "Make your protection smarter!"
1798
  msgstr ""
1799
 
1800
+ #: ../settings.php:507
1801
  msgid ""
1802
  "Please enable Permalinks to use this feature. Set Permalink Settings to "
1803
  "something other than Default."
1804
  msgstr ""
1805
 
1806
+ #: ../settings.php:510
1807
  msgid "Be careful about enabling these options."
1808
  msgstr ""
1809
 
1810
+ #: ../settings.php:510
1811
  msgid "If you forget your Custom login URL, you will be unable to log in."
1812
  msgstr ""
1813
 
1814
+ #: ../settings.php:514
1815
  msgid ""
1816
  "In the Citadel mode nobody is able to log in except IPs from the White IP "
1817
  "Access List. Active user sessions will not be affected."
1818
  msgstr ""
1819
 
1820
+ #: ../settings.php:517
1821
  msgid "These settings do not affect hosts from the "
1822
  msgstr ""
1823
 
1824
+ #: ../settings.php:520
1825
  msgid ""
1826
  "Before you can start using reCAPTCHA, you have to obtain Site key and Secret "
1827
  "key on the Google website"
1828
  msgstr ""
1829
 
1830
+ #: ../settings.php:551
1831
  msgid "Lockouts"
1832
  msgstr ""
1833
 
1834
+ #: ../settings.php:560
1835
  msgid "Users"
1836
  msgstr ""
1837
 
1838
+ #: ../settings.php:675 ../settings.php:797
1839
  #, php-format
1840
  msgid "%s allowed retries in %s minutes"
1841
  msgstr ""
1842
 
1843
+ #: ../settings.php:680 ../settings.php:802
1844
  #, php-format
1845
  msgid "%s allowed registrations in %s minutes from one IP"
1846
  msgstr ""
1847
 
1848
+ #: ../settings.php:685 ../settings.php:807
1849
  #, php-format
1850
  msgid "Increase lockout duration to %s hours after %s lockouts in the last %s hours"
1851
  msgstr ""
1852
 
1853
+ #: ../settings.php:692 ../settings.php:814
1854
  msgid "Notify admin if the number of active lockouts above"
1855
  msgstr ""
1856
 
1857
+ #: ../settings.php:697 ../settings.php:819
1858
  #, php-format
1859
  msgid "Enable after %s failed login attempts in last %s minutes"
1860
  msgstr ""
1861
 
1862
+ #: ../settings.php:918
1863
  msgid "Sunday"
1864
  msgstr ""
1865
 
1866
+ #: ../settings.php:919
1867
  msgid "Monday"
1868
  msgstr ""
1869
 
1870
+ #: ../settings.php:920
1871
  msgid "Tuesday"
1872
  msgstr ""
1873
 
1874
+ #: ../settings.php:921
1875
  msgid "Wednesday"
1876
  msgstr ""
1877
 
1878
+ #: ../settings.php:922
1879
  msgid "Thursday"
1880
  msgstr ""
1881
 
1882
+ #: ../settings.php:923
1883
  msgid "Friday"
1884
  msgstr ""
1885
 
1886
+ #: ../settings.php:924
1887
  msgid "Saturday"
1888
  msgstr ""
1889
 
1890
  #. translators: preposition of time
1891
+ #: ../settings.php:934
1892
  msgctxt "preposition of time"
1893
  msgid "at"
1894
  msgstr ""
1895
 
1896
+ #: ../settings.php:950
1897
  msgid "Click to send now"
1898
  msgstr ""
1899
 
1900
+ #: ../settings.php:961
1901
  msgid "Plugin initialization mode has not been changed"
1902
  msgstr ""
1903
 
1904
+ #: ../settings.php:981 ../settings.php:982
1905
  msgid "Attention! You have changed the login URL! The new login URL is"
1906
  msgstr ""
1907
 
1908
+ #: ../settings.php:983 ../settings.php:984
1909
  msgid ""
1910
  "If you use a caching plugin, you have to add your new login URL to the list "
1911
  "of pages not to cache."
1912
  msgstr ""
1913
 
1914
+ #: ../settings.php:1059 ../settings.php:1071 ../settings.php:1184
1915
  msgid "<strong>ERROR</strong>: please enter a valid email address."
1916
  msgstr ""
1917
 
1918
+ #: ../settings.php:1189
1919
+ msgid "The schedule has been updated"
1920
+ msgstr ""
1921
+
1922
+ #: ../settings.php:1192
1923
+ msgid "Unable to updated the schedule"
1924
+ msgstr ""
1925
+
1926
  #: ../cerber-tools.php:48
1927
  msgid "Export & Import"
1928
  msgstr ""
1976
  msgid "What do you want to import?"
1977
  msgstr ""
1978
 
1979
+ #: ../cerber-tools.php:102 ../cerber-scanner.php:3506
1980
  msgid "Upload file"
1981
  msgstr ""
1982
 
2000
  msgid "Antispam and bot detection settings"
2001
  msgstr ""
2002
 
2003
+ #: ../cerber-scanner.php:81
2004
  msgid "Security Scanner"
2005
  msgstr ""
2006
 
2007
+ #: ../cerber-scanner.php:83
2008
+ msgid "Scheduling"
2009
+ msgstr ""
2010
+
2011
+ #: ../cerber-scanner.php:130
2012
+ msgid "Currently a scheduled scan in progress. Please wait until it is finished."
2013
+ msgstr ""
2014
+
2015
+ #: ../cerber-scanner.php:134
2016
+ #, php-format
2017
+ msgid "Previous scan started %s has not been completed. Continue scanning?"
2018
+ msgstr ""
2019
+
2020
+ #: ../cerber-scanner.php:143
2021
+ msgid ""
2022
+ "It seems this website has never been scanned. To start scanning click the "
2023
+ "button below."
2024
+ msgstr ""
2025
+
2026
+ #: ../cerber-scanner.php:146
2027
  msgid "Start Quick Scan"
2028
  msgstr ""
2029
 
2030
+ #: ../cerber-scanner.php:147
2031
  msgid "Start Full Scan"
2032
  msgstr ""
2033
 
2034
+ #: ../cerber-scanner.php:148
2035
  msgid "Stop Scanning"
2036
  msgstr ""
2037
 
2038
+ #: ../cerber-scanner.php:149
2039
+ msgid "Continue Scanning"
2040
  msgstr ""
2041
 
2042
+ #: ../cerber-scanner.php:178
2043
  msgid "Delete"
2044
  msgstr ""
2045
 
2046
+ #: ../cerber-scanner.php:1096
2047
  msgid "Verified"
2048
  msgstr ""
2049
 
2050
+ #: ../cerber-scanner.php:1102
2051
  msgid "Integrity data not found"
2052
  msgstr ""
2053
 
2054
+ #: ../cerber-scanner.php:1103
2055
  msgid "Unable to check the integrity of the plugin due to a network error"
2056
  msgstr ""
2057
 
2058
+ #: ../cerber-scanner.php:1104
2059
  msgid "Unable to check the integrity of WordPress files due to a network error"
2060
  msgstr ""
2061
 
2062
+ #: ../cerber-scanner.php:1105
2063
  msgid "Unable to check the integrity of the theme due to a network error"
2064
  msgstr ""
2065
 
2066
+ #: ../cerber-scanner.php:1107
2067
  msgid "Local file doesn't exist"
2068
  msgstr ""
2069
 
2070
+ #: ../cerber-scanner.php:1109
2071
+ msgid "Unable to process file"
2072
+ msgstr ""
2073
+
2074
+ #: ../cerber-scanner.php:1110 ../cerber-scanner.php:4350
2075
  msgid "Unable to open file"
2076
  msgstr ""
2077
 
2078
+ #: ../cerber-scanner.php:1112
2079
+ msgid "Checksum mismatch"
2080
  msgstr ""
2081
 
2082
+ #: ../cerber-scanner.php:1115
2083
  msgid "Suspicious code found"
2084
  msgstr ""
2085
 
2086
+ #: ../cerber-scanner.php:1116
2087
  msgid "Potentially malicious code found"
2088
  msgstr ""
2089
 
2090
+ #: ../cerber-scanner.php:1117
2091
  msgid "Unattended suspicious file"
2092
  msgstr ""
2093
 
2094
+ #: ../cerber-scanner.php:1118
2095
  msgid "Executable code found"
2096
  msgstr ""
2097
 
2098
+ #: ../cerber-scanner.php:1121 ../cerber-scanner.php:2296
2099
+ msgid "Suspicious directives found"
2100
+ msgstr ""
2101
+
2102
+ #: ../cerber-scanner.php:1122
2103
+ msgid "Unwanted file extension"
2104
+ msgstr ""
2105
+
2106
+ #: ../cerber-scanner.php:1124
2107
+ msgid "Content has been modified"
2108
+ msgstr ""
2109
+
2110
+ #: ../cerber-scanner.php:1125
2111
+ msgid "New file"
2112
+ msgstr ""
2113
+
2114
+ #: ../cerber-scanner.php:1144
2115
+ msgid "Every hour"
2116
+ msgstr ""
2117
+
2118
+ #: ../cerber-scanner.php:1145
2119
+ msgid "Every 3 hours"
2120
+ msgstr ""
2121
+
2122
+ #: ../cerber-scanner.php:1146
2123
+ msgid "Every 6 hours"
2124
  msgstr ""
2125
 
2126
+ #: ../cerber-scanner.php:2133
2127
  msgid "Custom signature found"
2128
  msgstr ""
2129
 
2130
+ #: ../cerber-scanner.php:2294
2131
+ msgid "Suspicious code instruction found"
2132
+ msgstr ""
2133
+
2134
+ #: ../cerber-scanner.php:2295
2135
+ msgid "Suspicious code signatures found"
2136
+ msgstr ""
2137
+
2138
+ #: ../cerber-scanner.php:2298
2139
+ #, php-format
2140
+ msgid ""
2141
+ "To solve this issue you have to reinstall %s or update it to the latest "
2142
+ "version."
2143
+ msgstr ""
2144
+
2145
+ #: ../cerber-scanner.php:2299
2146
+ msgid "Please upload a reference ZIP archive"
2147
+ msgstr ""
2148
+
2149
+ #: ../cerber-scanner.php:2300
2150
+ msgid "Resolve issue"
2151
+ msgstr ""
2152
+
2153
+ #: ../cerber-scanner.php:3341
2154
+ msgid "Scanning folders for files"
2155
+ msgstr ""
2156
+
2157
+ #: ../cerber-scanner.php:3342
2158
+ msgid "Parsing the list of files"
2159
+ msgstr ""
2160
+
2161
+ #: ../cerber-scanner.php:3343
2162
+ msgid "Checking for new and modified files"
2163
+ msgstr ""
2164
+
2165
+ #: ../cerber-scanner.php:3344
2166
+ msgid "Verifying the integrity of WordPress"
2167
+ msgstr ""
2168
+
2169
+ #: ../cerber-scanner.php:3345
2170
+ msgid "Verifying the integrity of the plugins"
2171
+ msgstr ""
2172
+
2173
+ #: ../cerber-scanner.php:3346
2174
+ msgid "Verifying the integrity of the themes"
2175
+ msgstr ""
2176
+
2177
+ #: ../cerber-scanner.php:3347
2178
+ msgid "Searching for malicious code"
2179
+ msgstr ""
2180
+
2181
+ #: ../cerber-scanner.php:3348
2182
+ msgid "Finalizing the scan"
2183
+ msgstr ""
2184
+
2185
+ #: ../cerber-scanner.php:3417
2186
  msgid "Files to scan"
2187
  msgstr ""
2188
 
2189
+ #: ../cerber-scanner.php:3425
2190
  msgid "Critical issues"
2191
  msgstr ""
2192
 
2193
+ #: ../cerber-scanner.php:3429 ../cerber-scanner.php:4545
2194
  msgid "Issues total"
2195
  msgstr ""
2196
 
2197
+ #: ../cerber-scanner.php:3501
2198
+ msgid "We have not found any integrity data to verify"
2199
+ msgstr ""
2200
+
2201
+ #: ../cerber-scanner.php:3503
2202
+ msgid ""
2203
+ "You have to upload a ZIP archive from which you've installed it. This "
2204
+ "enables the security scanner to verify the integrity of the code and detect "
2205
+ "malware."
2206
+ msgstr ""
2207
+
2208
+ #: ../cerber-scanner.php:3790
2209
  msgid "The directory is not writable"
2210
  msgstr ""
2211
 
2212
+ #: ../cerber-scanner.php:3808
2213
  msgid "Unable to create WP CERBER directory"
2214
  msgstr ""
2215
 
2216
+ #: ../cerber-scanner.php:4015
2217
+ msgid ""
2218
+ "File access error. Possibly scan results are outdated. Please run Quick or "
2219
+ "Full Scan."
2220
+ msgstr ""
2221
+
2222
+ #: ../cerber-scanner.php:4495
2223
+ msgid "Full Scan Report"
2224
+ msgstr ""
2225
+
2226
+ #: ../cerber-scanner.php:4495
2227
+ msgid "Quick Scan Report"
2228
+ msgstr ""
2229
+
2230
+ #: ../cerber-scanner.php:4511
2231
+ msgid "Files scanned"
2232
+ msgstr ""
2233
+
2234
+ #: ../cerber-scanner.php:4594
2235
+ msgid "To view full report visit"
2236
+ msgstr ""
2237
+
2238
  #. Description of the plugin
2239
  msgid ""
2240
  "This is a standard boot module for WP Cerber Security & Antispam plugin. It "
readme.txt CHANGED
@@ -5,19 +5,20 @@ Tags: security, malware scanner, antispam, firewall, limit login attempts, custo
5
  Requires at least: 4.5
6
  Requires PHP: 5.4
7
  Tested up to: 4.9
8
- Stable tag: 7.0
9
  License: GPLv2
10
 
11
  Protection against hacker attacks and bots. Malware scanner & integrity checker. Monitor user activity. Antispam reCAPTCHA. Limit login attempts.
12
 
13
  == Description ==
14
 
15
- Defends WordPress against brute force attacks by limiting the number of login attempts through the login form, XML-RPC / REST API requests or using auth cookies.
 
16
  Restricts access with the Black IP Access List and the White IP Access List.
17
  Tracks user and intruder activity with powerful email, mobile and desktop notifications.
18
  Stop spam: activates Cerber antispam engine and Google reCAPTCHA for protecting registration, contact and comments forms.
19
  Hardening WordPress with a set of security rules and comprehensive algorithms.
20
- Malware scanner & integrity checker.
21
 
22
  **Features you will love**
23
 
@@ -27,7 +28,8 @@ Malware scanner & integrity checker.
27
  * Create **Custom login URL** ([rename wp-login.php](https://wpcerber.com/how-to-rename-wp-login-php/)).
28
  * Cerber antispam engine for protecting any contact form. Automatically detects and moves spam comments to trash or deny it completely.
29
  * Log users, bots, hacker and other suspicious activities.
30
- * Scan and verify the integrity of all WordPress files, plugins and themes.
 
31
  * Cool notifications with powerful event filters.
32
  * Hide wp-login.php, wp-signup.php and wp-register.php from possible attacks.
33
  * Hide wp-admin (dashboard) when a user isn't logged in.
@@ -63,9 +65,21 @@ You will be able to create a **Black IP Access List** or **White IP Access List*
63
 
64
  Moreover, you can create your Custom login page and forget about automatic attacks to the default wp-login.php, which takes your attention and consumes a lot of server resources. If an attacker tries to access wp-login.php they will be blocked and get a 404 Error response.
65
 
66
- = Malware scanner & integrity checker. =
67
 
68
- The main purpose of the scanner is to provide a handy diagnostic tool to monitor all files on a website, verify the integrity of WordPress, plugins, themes and to detect and remove malware. [Read more about malware scanner](https://wpcerber.com/wordpress-security-scanner/).
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
  = Log, filter out and export activities =
71
 
@@ -294,6 +308,21 @@ To get access to your dashboard you need to copy the WP Cerber Reset folder to t
294
 
295
  == Changelog ==
296
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297
  = 6.7.5 =
298
  * A new button View Activity has been added to the user edit page in the WordPress dashboard.
299
  * Miscellaneous code optimizations: performance of database routines and SQL queries are improved.
@@ -456,113 +485,6 @@ To get access to your dashboard you need to copy the WP Cerber Reset folder to t
456
  * Fixed bug: reCAPTCHA for an ordinary WordPress login form is incompatible with a WooCommerce login form.
457
  * Fixed issue: In some cases the plugin log first digits of an IP address as an ID of existing user.
458
 
459
- = 3.0 =
460
- * New: [reCAPTCHA to protect WordPress forms spam registrations. Also available for lost password and login forms.](https://wpcerber.com/how-to-setup-recaptcha/)
461
- * New: Registration, XML RCP, WP REST API are controlled by IP Access Lists now. If a particular IP address is locked out or blacklisted registration is impossible.
462
- * New: Action Get WHOIS info and trigger IP locked out to create automation scenarios with the [jetFlow.io automation plugin](http://jetflow.io).
463
- * New: Notification emails will contain Reason of a lockout.
464
- * New: The activity DB table will be optimized after removing old records daily.
465
- * Update: Column Username on the Activity tab now shows real value that submitted with WordPress login form.
466
- * Update: Text domain is updated to 'wp-cerber'
467
- * Fixed issue: If a user enter correct email address and wrong password to log in, IP address is locked immediately.
468
-
469
- = 2.9 =
470
- * New: Checking for a prohibited username (login). You can specify list of logins manually on the new settings page (Users).
471
- * New: Rate limiting for notification letters. Set it on the main settings page.
472
- * New: If new user registration disabled, automatic redirection from wp-register.php to the login page is blocked (404 error). Remote IP will be locked out.
473
- * New: You can set user session expiration timeout.
474
- * New: Define constant CERBER_IP_KEY if you want the plugin to use it as a key to get IP address from $_SERVER variable.
475
- * Update: Improved WP-CLI compatibility.
476
- * Update: All dates are displayed in a localized format with date_i18n function.
477
- * Fixed bugs: incorrect admin URL in notification letters for multisite with multiple domains configuration, lack of error message on the login form if IP is blocked, CSRF vulnerability on the import settings page
478
- * Removed calls of deprecated function get_currentuserinfo().
479
-
480
- = 2.7.2 =
481
- * Fixed bug for non-English WordPress configuration: the plugin is unable to block IP in some server environment. If you have configured language other than English you have to install this release.
482
-
483
- = 2.7.1 =
484
- * Fixed two small bugs related to 1) unable to remove IP subnet from the Access Lists and 2) getting IP address in case of reverse proxy doesn't work properly.
485
-
486
- = 2.7 =
487
-
488
- * New: Now you can view extra WHOIS information for IP addresses in the activity log including country, network info, abuse contact, etc.
489
- * New: Added ability to disable WP REST API, see [Hardening WordPress](https://wpcerber.com/hardening-wordpress/)
490
- * New: Added ability to add IP address to the Black List from the Activity tab. Nail it!
491
- * New: Added Spanish translation, thanks to Ismael.
492
- * New: Added ability to set numbers of displayed rows (lines) on the Activity and Lockout tabs. Click Screen Options on the top-right.
493
- * Fixed minor security issue: Actions to remove IP on the Access Lists tab were not protected against CSRF attacks. Thanks to Gerard.
494
- * Update: Small changes on the dashboard widget.
495
- * Update: Action taken by the plugin (plugin makes a decision) now marked with dark vertical bar on the right side of the labels (Activity tab).
496
-
497
- = 2.0.1.6 =
498
- * New: Added Reason column on the Lockouts screen which will display cause of blocking particular IP.
499
- * New: Added Hardening WP with options: disable XML-RPC completely, disable user enumeration, disable feeds (RSS, Atom, RSD).
500
- * New: Added Custom email address for notifications.
501
- * New: Added Dutch and Czech translations.
502
- * New: Added Quick info about IP on Activity tab.
503
- * Update: Removed option 'Allow whitelist in Citadel mode'. Now this whitelist is enabled by default all the time.
504
- * Update: For notifications on the multisite installation the admin email address from the Network Settings will be used.
505
- * Fixed Bug: Disable wp-login.php doesn't work for subfolder installation.
506
- * Fixed Bug: Custom login URL doesn't work without trailing slash.
507
- * Fixed Bug: Any request to wp-signup.php reveal hidden Custom login URL.
508
-
509
- = 1.9 =
510
- * Code refactoring and cleaning up.
511
- * Unlocalized strings was localized.
512
-
513
- = 1.8.1 =
514
- * Fixed minor bug: no content (empty cells) in the custom colums added by other plugins on the Users screen in the Dashboard.
515
-
516
- = 1.8 =
517
- * New! added Hostname column for the Activity and Lockouts tabs.
518
- * New! added ability to write failed login attempts to the specified file or to the syslog file. Use it to protect site with fail2ban.
519
- * Added Ukrainian translation (Український переклад).
520
-
521
- = 1.7 =
522
- * Added ability to remove old records from the user activity log. Log will be cleaned up automatically. Check out new Keep records for field on the settings page.
523
- * Added pagination for the Activity and Lockouts tabs.
524
- * Added German (Deutsch) translation, thanks to mario.
525
- * Added ability to reset settings to the recommended defaults at any time.
526
-
527
- = 1.6 =
528
- * New: beautiful widget for the dashboard to keep an eye on things. Get quick analytic with trends over 24 hours and ability to manually deactivate Citadel mode.
529
- * French translation added, thanks to hardesfred.
530
- * Hardening WordPress. Removed automatically redirection from /login/ to the login page, from /admin/ and /dashboard/ to the dashboard.
531
- * Fixed issue with lost password link in the multisite mode.
532
- * Now compatible with User Switching plugin.
533
- * Added ability to manually deactivate Citadel mode, once it automatically switches on.
534
-
535
- = 1.5 =
536
- * New feature: importing and exporting settings and access lists from/to the file.
537
- * Limited notifications in the dashboard.
538
-
539
- = 1.4 =
540
- * Added support Multisite mode for limit login attempts.
541
- * Added Number of comments column on the Users screen in dashboard.
542
- * Updated notification settings.
543
- * Updated languages files.
544
-
545
- = 1.3 =
546
- * Fixed issue with hanging up during redirect to /wp-admin/ on some circumstance.
547
- * Fixed minor issue with limit login attempts for non-admin users.
548
- * Added Date of registration column on the Users screen in dashboard.
549
- * Some UI improvements on access-list screen.
550
- * Performance optimization & code refactoring.
551
-
552
- = 1.2 =
553
- * Added localization & internationalization files. You can use Loco Translate plugin to make your own translation.
554
- * Added Russian translation.
555
- * Added headers for failed attempts to use such headers with [fail2ban](http://www.fail2ban.org).
556
-
557
- = 1.1 =
558
- * Added ability to filter out Activity List by IP, username or particular event. You can see what happens and when it happened with particular IP or username. When IP reaches limit login attempts and when it was blocked.
559
- * Added protection from adding to the Black IP Access List subnet belongs to current user's session IP.
560
- * Added option to work with site/server behind reverse proxy.
561
- * Update installation instruction.
562
-
563
- = 1.0 =
564
- * Initial version
565
-
566
  == Other Notes ==
567
 
568
  1. If you want to test out plugin's features, do this from another computer and remove that computer's network from the White Access List. Cerber is smart enough to recognize "the boss".
5
  Requires at least: 4.5
6
  Requires PHP: 5.4
7
  Tested up to: 4.9
8
+ Stable tag: 7.2
9
  License: GPLv2
10
 
11
  Protection against hacker attacks and bots. Malware scanner & integrity checker. Monitor user activity. Antispam reCAPTCHA. Limit login attempts.
12
 
13
  == Description ==
14
 
15
+ Defends WordPress against hacker attacks, spam, trojans and malware.
16
+ Mitigate brute force attacks by limiting the number of login attempts through the login form, XML-RPC / REST API requests or using auth cookies.
17
  Restricts access with the Black IP Access List and the White IP Access List.
18
  Tracks user and intruder activity with powerful email, mobile and desktop notifications.
19
  Stop spam: activates Cerber antispam engine and Google reCAPTCHA for protecting registration, contact and comments forms.
20
  Hardening WordPress with a set of security rules and comprehensive algorithms.
21
+ Malware scanner, integrity checker, file monitor.
22
 
23
  **Features you will love**
24
 
28
  * Create **Custom login URL** ([rename wp-login.php](https://wpcerber.com/how-to-rename-wp-login-php/)).
29
  * Cerber antispam engine for protecting any contact form. Automatically detects and moves spam comments to trash or deny it completely.
30
  * Log users, bots, hacker and other suspicious activities.
31
+ * Verify the integrity of all WordPress files, plugins and themes.
32
+ * Monitor file changes and new files.
33
  * Cool notifications with powerful event filters.
34
  * Hide wp-login.php, wp-signup.php and wp-register.php from possible attacks.
35
  * Hide wp-admin (dashboard) when a user isn't logged in.
65
 
66
  Moreover, you can create your Custom login page and forget about automatic attacks to the default wp-login.php, which takes your attention and consumes a lot of server resources. If an attacker tries to access wp-login.php they will be blocked and get a 404 Error response.
67
 
68
+ = Malware scanner =
69
 
70
+ Cerber Security Scanner is a sophisticated and extremely powerful tool that thoroughly scans every folder and inspects every file on a website for traces of malware, trojans, backdoors, changed and new files.
71
+
72
+ [Read more about malware scanner](https://wpcerber.com/wordpress-security-scanner/).
73
+
74
+ = Integrity checker =
75
+
76
+ The scanner checks if all WordPress folders and files match what exist in the official WordPress core repository, compares your plugins and themes with what are in the official WordPress repository and alerts you to any changes. As with scanning free plugins and themes, the scanner scans and verifies commercial plugins and themes that are installed manually.
77
+
78
+ = Automated recurring scans and email reporting =
79
+
80
+ Cerber Security Scanner allows you to easily configure your schedule for automated recurring scanning. Once the schedule is configured the scanner will automatically perform the scan of the website and send a email report with results of the scan.
81
+
82
+ [Read more about automated scans](https://wpcerber.com/automated-recurring-malware-scans/).
83
 
84
  = Log, filter out and export activities =
85
 
308
 
309
  == Changelog ==
310
 
311
+ = 7.2 =
312
+ * New: Monitoring new and changed files.
313
+ * New: Detecting malicious redirections and directives in .htaccess files.
314
+ * New: [Automated hourly and daily scheduled scans with flexible email reports](https://wpcerber.com/automated-recurring-malware-scans/).
315
+ * Update: Added a protection from logging wrong time stamps on some not correctly configured servers.
316
+ * Bug fixed: Unexpected warning messages in the WordPress dashboard.
317
+ * Bug fixed: Some file status links on the scanner results page may not work.
318
+
319
+ = 7.0 =
320
+ * Cerber Security Scanner: [integrity checker, malware detector and malware removal tool](https://wpcerber.com/wordpress-security-scanner/).
321
+ * New: a new setting for Traffic Inspector: Use White IP Access List.
322
+ * Update: the redirection from /wp-admin/ to the login page is not blocked for a user that has been logged in once before.
323
+ * Bug fixed: the limit to the number of new user registrations is calculated the way that allows one additional registration within a given period of time.
324
+ * [Read more](https://wpcerber.com/wp-cerber-security-7-0/)
325
+
326
  = 6.7.5 =
327
  * A new button View Activity has been added to the user edit page in the WordPress dashboard.
328
  * Miscellaneous code optimizations: performance of database routines and SQL queries are improved.
485
  * Fixed bug: reCAPTCHA for an ordinary WordPress login form is incompatible with a WooCommerce login form.
486
  * Fixed issue: In some cases the plugin log first digits of an IP address as an ID of existing user.
487
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
488
  == Other Notes ==
489
 
490
  1. If you want to test out plugin's features, do this from another computer and remove that computer's network from the White Access List. Cerber is smart enough to recognize "the boss".
settings.php CHANGED
@@ -42,6 +42,7 @@ define('CERBER_OPT_C','cerber-recaptcha');
42
  define('CERBER_OPT_N','cerber-notifications');
43
  define('CERBER_OPT_T','cerber-traffic');
44
  define('CERBER_OPT_S','cerber-scanner');
 
45
 
46
  /**
47
  * A set of Cerber setting (WP options)
@@ -50,7 +51,7 @@ define('CERBER_OPT_S','cerber-scanner');
50
  */
51
 
52
  function cerber_get_setting_list() {
53
- return array( CERBER_OPT, CERBER_OPT_H, CERBER_OPT_U, CERBER_OPT_C, CERBER_OPT_N, CERBER_OPT_T, CERBER_OPT_S );
54
  }
55
 
56
  /*
@@ -59,7 +60,7 @@ function cerber_get_setting_list() {
59
  add_action('admin_init', 'cerber_settings_init');
60
  function cerber_settings_init(){
61
 
62
- if ( ! cerber_is_admin_page( false ) && ! strpos( $_SERVER['REQUEST_URI'], '/options.php' ) ) {
63
  return;
64
  }
65
 
@@ -141,7 +142,9 @@ function cerber_settings_init(){
141
  $tab='users'; // 'cerber-users' settings
142
  register_setting( 'cerberus-'.$tab, CERBER_OPT_U);
143
  add_settings_section('us', __('User related settings','wp-cerber'), 'cerber_sapi_section', CERBER_OPT_U);
144
- if (lab_lab()) add_settings_field('reglimit',__('Registration limit','wp-cerber'),'cerberus_field_show', CERBER_OPT_U,'us',array('group'=>$tab,'option'=>'reglimit','type'=>'reglimit'));
 
 
145
  add_settings_field( 'prohibited', __( 'Prohibited usernames', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_U, 'us',
146
  array( 'group' => $tab,
147
  'setting' => 'prohibited',
@@ -228,13 +231,19 @@ function cerber_settings_init(){
228
  add_settings_field('pbtoken','Pushbullet access token','cerber_field_show',CERBER_OPT_N,'pushit',array('group'=>$group,'setting'=>'pbtoken','type'=>'text','size'=>60));
229
 
230
  $set = array();
231
- if (cerber_is_admin_page(false, array('tab'=>'notifications'))){
232
  $set = cerber_pb_get_devices();
233
- if (is_array($set)){
234
- if (!empty($set)) $set = array('all' => __('All connected devices','wp-cerber')) + $set;
235
- else $set = array('N' => __('No devices found','wp-cerber'));
 
 
 
 
 
 
 
236
  }
237
- else $set = array('N' => __('Not available','wp-cerber'));
238
  }
239
  add_settings_field('pbdevice','Pushbullet device','cerber_field_show',CERBER_OPT_N,'pushit',array('group'=>$group,'setting'=>'pbdevice','type'=>'select','set'=>$set));
240
 
@@ -377,7 +386,20 @@ function cerber_settings_init(){
377
  'type' => 'textarea',
378
  'delimiter' => "\n",
379
  'list' => true,
380
- 'label' => __( 'Specify directories to exclude from scanning. One item per line. Use with caution.', 'wp-cerber' )
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  ) );
382
  add_settings_field( 'scan_tmp', __( 'Scan temporary directory', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_S, 'smain',
383
  array(
@@ -385,6 +407,7 @@ function cerber_settings_init(){
385
  'setting' => 'scan_tmp',
386
  'type' => 'checkbox',
387
  ) );
 
388
  add_settings_field( 'scan_sess', __( 'Scan session directory', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_S, 'smain',
389
  array(
390
  'group' => $group,
@@ -399,6 +422,77 @@ function cerber_settings_init(){
399
  'label' => __( 'days', 'wp-cerber' ),
400
  'size' => 3
401
  ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
  }
403
  /*
404
  Generate HTML for each sections on a settings page
@@ -510,18 +604,21 @@ function cerber_settings_page(){
510
  <?php
511
  }
512
  /*
513
- * Display settings screen (one tab)
514
  *
515
  */
516
- function cerber_show_settings_page($group = null){
517
- if (is_multisite()) $action = ''; // Settings API doesn't work in multisite. Post data will be handled in the cerber_ms_update()
518
- else $action ='options.php';
519
- // Display form with settings fields via Settings API
520
- echo '<form method="post" action="'.$action.'">';
521
-
522
- settings_fields( 'cerberus-'.$group ); // option group name, the same as used in register_setting().
523
- do_settings_sections( 'cerber-'.$group ); // the same as used in add_settings_section() $page
524
- echo '<div style="padding-left: 220px">';
 
 
 
525
  submit_button();
526
  echo '</div>';
527
  echo '</form>';
@@ -728,15 +825,28 @@ function cerber_field_show($args){
728
  $html.= '<label for="'.$args['setting'].'">'.$label.'</label>';
729
  break;
730
  case 'textarea':
731
- $html='<textarea class="large-text code" id="'.$args['setting'].'" name="'.$name.'" '.$disabled.' />'.$value.'</textarea>';
732
- $html.= '<br><label for="'.$args['setting'].'">'.$label.'</label>';
733
  break;
734
  case 'select':
735
- $html=cerber_select($name,$args['set'],$value);
 
 
 
 
 
 
 
 
 
736
  break;
737
  case 'reptime':
738
  $html = cerber_time_select( $args, $settings );
739
  break;
 
 
 
 
740
  case 'text':
741
  default:
742
  $size = '';
@@ -766,14 +876,14 @@ function cerber_field_show($args){
766
  break;
767
  }
768
 
769
- if (!empty($args['enabled'])){
770
- $name = 'cerber-'.$args['group'].'['.$args['setting'].'-enabled]';
771
  $value = 0;
772
  if ( isset( $settings[ $args['setting'] . '-enabled' ] ) ) {
773
  $value = $settings[ $args['setting'] . '-enabled' ];
774
  }
775
  $checkbox = '<label class="crb-switch"><input class="screen-reader-text" type="checkbox" id="' . $args['setting'] . '-enabled" name="' . $name . '" value="1" ' . checked( 1, $value, false ) . ' /><span class="crb-slider round"></span></label>' . $args['enabled'];
776
- $html = $checkbox . $html;
777
  }
778
 
779
  echo $html."\n";
@@ -843,8 +953,7 @@ function cerber_time_select($args, $settings){
843
  /*
844
  Sanitizing users input for Main Settings
845
  */
846
- add_filter( 'pre_update_option_'.CERBER_OPT, 'cerber_sanitize_m', 10, 3 );
847
- function cerber_sanitize_m($new, $old, $option) {
848
 
849
  $ret = cerber_set_boot_mode( $new['boot-mode'], $old['boot-mode'] );
850
  if ( is_wp_error( $ret ) ) {
@@ -874,7 +983,7 @@ function cerber_sanitize_m($new, $old, $option) {
874
  $msg[] = __( 'If you use a caching plugin, you have to add your new login URL to the list of pages not to cache.', 'wp-cerber' );
875
  $msg_e[] = __( 'If you use a caching plugin, you have to add your new login URL to the list of pages not to cache.', 'wp-cerber' );
876
  cerber_admin_notice( $msg );
877
- cerber_send_notify( 'newlurl', $msg_e );
878
  }
879
  } else {
880
  $new['loginpath'] = '';
@@ -898,22 +1007,20 @@ function cerber_sanitize_m($new, $old, $option) {
898
  }
899
 
900
  return $new;
901
- }
902
  /*
903
  Sanitizing/checking user input for User tab settings
904
  */
905
- add_filter( 'pre_update_option_'.CERBER_OPT_U, 'cerber_sanitize_u', 10, 3 );
906
- function cerber_sanitize_u($new, $old, $option) {
907
 
908
  $new['prohibited'] = cerber_text2array($new['prohibited'], ',', 'strtolower');
909
 
910
  return $new;
911
- }
912
  /*
913
  Sanitizing/checking user input for reCAPTCHA tab settings
914
  */
915
- add_filter( 'pre_update_option_'.CERBER_OPT_C, 'cerber_sanitize_c', 10, 3 );
916
- function cerber_sanitize_c($new, $old, $option) {
917
  global $wp_cerber;
918
  // Check ability to make external HTTP requests
919
  if ($wp_cerber && !empty($new['sitekey']) && !empty($new['secretkey'])) {
@@ -935,12 +1042,11 @@ function cerber_sanitize_c($new, $old, $option) {
935
  }
936
 
937
  return $new;
938
- }
939
  /*
940
  Sanitizing/checking user input for Notifications tab settings
941
  */
942
- add_filter( 'pre_update_option_'.CERBER_OPT_N, 'cerber_sanitize_n', 10, 3 );
943
- function cerber_sanitize_n($new, $old, $option) {
944
 
945
  $emails = cerber_text2array( $new['email'], ',' );
946
 
@@ -977,13 +1083,12 @@ function cerber_sanitize_n($new, $old, $option) {
977
  }
978
 
979
  return $new;
980
- }
981
 
982
  /*
983
  Sanitizing/checking user input for Hardening tab settings
984
  */
985
- add_filter( 'pre_update_option_'.CERBER_OPT_H, 'cerber_sanitize_h', 10, 3 );
986
- function cerber_sanitize_h($new, $old, $option) {
987
 
988
  $new['restwhite'] = cerber_text2array($new['restwhite'], "\n");
989
 
@@ -1007,17 +1112,16 @@ function cerber_sanitize_h($new, $old, $option) {
1007
  }
1008
 
1009
  return $new;
1010
- }
1011
  /*
1012
  Sanitizing/checking user input for Traffic Inspector tab settings
1013
  */
1014
- add_filter( 'pre_update_option_'.CERBER_OPT_T, 'cerber_sanitize_t', 10, 3 );
1015
- function cerber_sanitize_t($new, $old, $option) {
1016
 
1017
  $new['tiwhite'] = cerber_text2array( $new['tiwhite'], "\n" );
1018
  foreach ( $new['tiwhite'] as $item ) {
1019
  if ( strrpos( $item, '?' ) ) {
1020
- cerber_admin_notice( 'You may not specify the query string with question mark: ' . htmlspecialchars( $item ) );
1021
  }
1022
  if ( strrpos( $item, '://' ) ) {
1023
  cerber_admin_notice( 'You may not specify the full URL: ' . htmlspecialchars( $item ) );
@@ -1035,17 +1139,20 @@ function cerber_sanitize_t($new, $old, $option) {
1035
  }
1036
 
1037
  return $new;
1038
- }
1039
 
1040
  /*
1041
  Sanitizing/checking user input for Security Scanner settings
1042
  */
1043
- add_filter( 'pre_update_option_' . CERBER_OPT_S, 'cerber_sanitize_s', 10, 3 );
1044
- function cerber_sanitize_s( $new, $old, $option ) {
1045
 
1046
  $list = cerber_text2array( $new['scan_exclude'], "\n" );
1047
  $list = array_filter( $list, function ( $item ) {
1048
- return @is_dir( $item );
 
 
 
 
1049
  } );
1050
  $new['scan_exclude'] = $list;
1051
 
@@ -1053,7 +1160,40 @@ function cerber_sanitize_s( $new, $old, $option ) {
1053
  $new['scan_uext'] = cerber_text2array( $new['scan_uext'], "," );
1054
 
1055
  return $new;
1056
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1057
 
1058
  /**
1059
  * Let's sanitize them all
@@ -1229,14 +1369,14 @@ function cerber_get_defaults($field = null) {
1229
 
1230
  ),
1231
  CERBER_OPT_H => array(
1232
- 'stopenum' => 1,
1233
- 'adminphp' => 0,
1234
- 'xmlrpc' => 0,
1235
- 'nofeeds' => 0,
1236
- 'norest' => 0,
1237
- 'restauth' => 0,
1238
- 'restwhite' => 'oembed',
1239
- 'hashauthor' => 0,
1240
  'cleanhead' => 1,
1241
  ),
1242
  CERBER_OPT_U => array(
@@ -1273,39 +1413,51 @@ function cerber_get_defaults($field = null) {
1273
  'recaptcha-within' => 30,
1274
  ),
1275
  CERBER_OPT_N => array(
1276
- 'email' => '',
1277
- 'emailrate' => 12,
1278
  'notify-new-ver' => '1',
1279
- 'pbtoken' => '',
1280
- 'pbdevice' => '',
1281
- 'wreports-day' => '1', // workaround, see cerber_upgrade_options()
1282
- 'wreports-time' => 9,
1283
- 'email-report' => '',
1284
  'enable-report' => '1', // workaround, see cerber_upgrade_options()
1285
  ),
1286
  CERBER_OPT_T => array(
1287
- 'tienabled' => '1',
1288
- 'tiipwhite' => 0,
1289
- 'tiwhite' => '',
1290
- 'timode' => '1',
1291
- 'tinocrabs' => '1',
1292
- 'tifields' => 0,
1293
- 'timask' => '',
1294
- 'tihdrs' => 0,
1295
- 'tisenv' => 0,
1296
- 'ticandy' => 0,
1297
- 'tithreshold' => '',
1298
- 'tikeeprec' => 7,
1299
- ),
1300
  CERBER_OPT_S => array(
1301
- 'scan_cpt' => '',
1302
- 'scan_uext' => '',
1303
- 'scan_exclude' => '',
1304
- 'scan_tmp' => '1',
1305
- 'scan_sess' => '1',
 
 
1306
  'scan_qcleanup' => '30',
 
 
 
 
 
 
 
 
 
 
1307
  )
1308
- );
1309
  if ( $field ) {
1310
  foreach ( $all_defaults as $option ) {
1311
  if ( isset( $option[ $field ] ) ) {
@@ -1432,10 +1584,14 @@ function crb_get_settings( $option = '' ) {
1432
  $united = array();
1433
 
1434
  if ( is_multisite() ) {
1435
- $set = $wpdb->get_col( 'SELECT meta_value FROM ' . $wpdb->sitemeta . ' WHERE meta_key ' . $in );
 
 
1436
  }
1437
  else {
1438
- $set = $wpdb->get_col( 'SELECT option_value FROM ' . $wpdb->options . ' WHERE option_name ' . $in );
 
 
1439
  }
1440
 
1441
  foreach ( $set as $item ) {
@@ -1488,15 +1644,19 @@ function cerber_get_site_option($option = '', $unserialize = true){
1488
  return get_site_option( $option, null );
1489
  }
1490
 
1491
- if (isset($values[$option])){
1492
- return $values[$option];
1493
- }
1494
 
1495
  if ( is_multisite() ) {
1496
- $value = $wpdb->get_var( 'SELECT meta_value FROM ' . $wpdb->sitemeta . ' WHERE meta_key = "' . $option . '"' );
 
 
1497
  }
1498
  else {
1499
- $value = $wpdb->get_var( 'SELECT option_value FROM ' . $wpdb->options . ' WHERE option_name = "' . $option . '"' );
 
 
1500
  }
1501
 
1502
  if ( $value ) {
@@ -1538,10 +1698,10 @@ function cerber_load_defaults() {
1538
  *
1539
  * @return array|string Email address(es) for notifications
1540
  */
1541
- function cerber_get_email($type = '', $array = false) {
1542
  $email = '';
1543
 
1544
- if ( $type == 'report' ) {
1545
  $email = crb_get_settings( 'email-' . $type );
1546
  }
1547
 
@@ -1549,7 +1709,7 @@ function cerber_get_email($type = '', $array = false) {
1549
  $email = crb_get_settings( 'email' );
1550
  }
1551
 
1552
- if ( !$array && is_array( $email ) ) { // @since 4.9
1553
  $email = implode( ', ', $email );
1554
  }
1555
 
@@ -1562,3 +1722,62 @@ function cerber_get_email($type = '', $array = false) {
1562
 
1563
  return $email;
1564
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  define('CERBER_OPT_N','cerber-notifications');
43
  define('CERBER_OPT_T','cerber-traffic');
44
  define('CERBER_OPT_S','cerber-scanner');
45
+ define('CERBER_OPT_E','cerber-schedule');
46
 
47
  /**
48
  * A set of Cerber setting (WP options)
51
  */
52
 
53
  function cerber_get_setting_list() {
54
+ return array( CERBER_OPT, CERBER_OPT_H, CERBER_OPT_U, CERBER_OPT_C, CERBER_OPT_N, CERBER_OPT_T, CERBER_OPT_S, CERBER_OPT_E );
55
  }
56
 
57
  /*
60
  add_action('admin_init', 'cerber_settings_init');
61
  function cerber_settings_init(){
62
 
63
+ if ( ! cerber_is_admin_page() && ! strpos( $_SERVER['REQUEST_URI'], '/options.php' ) ) {
64
  return;
65
  }
66
 
142
  $tab='users'; // 'cerber-users' settings
143
  register_setting( 'cerberus-'.$tab, CERBER_OPT_U);
144
  add_settings_section('us', __('User related settings','wp-cerber'), 'cerber_sapi_section', CERBER_OPT_U);
145
+ if (lab_lab()) {
146
+ add_settings_field('reglimit',__('Registration limit','wp-cerber'),'cerberus_field_show', CERBER_OPT_U,'us',array('group'=>$tab,'option'=>'reglimit','type'=>'reglimit'));
147
+ }
148
  add_settings_field( 'prohibited', __( 'Prohibited usernames', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_U, 'us',
149
  array( 'group' => $tab,
150
  'setting' => 'prohibited',
231
  add_settings_field('pbtoken','Pushbullet access token','cerber_field_show',CERBER_OPT_N,'pushit',array('group'=>$group,'setting'=>'pbtoken','type'=>'text','size'=>60));
232
 
233
  $set = array();
234
+ if ( cerber_is_admin_page( false, array( 'tab' => 'notifications' ) ) ) {
235
  $set = cerber_pb_get_devices();
236
+ if ( is_array( $set ) ) {
237
+ if ( ! empty( $set ) ) {
238
+ $set = array( 'all' => __( 'All connected devices', 'wp-cerber' ) ) + $set;
239
+ }
240
+ else {
241
+ $set = array( 'N' => __( 'No devices found', 'wp-cerber' ) );
242
+ }
243
+ }
244
+ else {
245
+ $set = array( 'N' => __( 'Not available', 'wp-cerber' ) );
246
  }
 
247
  }
248
  add_settings_field('pbdevice','Pushbullet device','cerber_field_show',CERBER_OPT_N,'pushit',array('group'=>$group,'setting'=>'pbdevice','type'=>'select','set'=>$set));
249
 
386
  'type' => 'textarea',
387
  'delimiter' => "\n",
388
  'list' => true,
389
+ 'label' => __( 'Specify directories to exclude from scanning. Use absolute paths. One item per line.', 'wp-cerber' )
390
+ ) );
391
+ add_settings_field( 'scan_inew', __( 'Monitor new files', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_S, 'smain',
392
+ array(
393
+ 'group' => $group,
394
+ 'setting' => 'scan_inew',
395
+ 'type' => 'checkbox',
396
+ ) );
397
+
398
+ add_settings_field( 'scan_imod', __( 'Monitor modified files', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_S, 'smain',
399
+ array(
400
+ 'group' => $group,
401
+ 'setting' => 'scan_imod',
402
+ 'type' => 'checkbox',
403
  ) );
404
  add_settings_field( 'scan_tmp', __( 'Scan temporary directory', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_S, 'smain',
405
  array(
407
  'setting' => 'scan_tmp',
408
  'type' => 'checkbox',
409
  ) );
410
+
411
  add_settings_field( 'scan_sess', __( 'Scan session directory', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_S, 'smain',
412
  array(
413
  'group' => $group,
422
  'label' => __( 'days', 'wp-cerber' ),
423
  'size' => 3
424
  ) );
425
+
426
+ // Scanner Schedule -----------------------------------------------------------------------------
427
+
428
+ $group = 'schedule'; // 'cerber-scanner' settings
429
+ register_setting( 'cerberus-' . $group, CERBER_OPT_E );
430
+
431
+ add_settings_section( 's1', 'Automated recurring scan schedule', 'cerber_sapi_section', CERBER_OPT_E );
432
+ add_settings_field( 'scan_aquick', __( 'Launch Quick Scan', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_E, 's1',
433
+ array(
434
+ 'group' => $group,
435
+ 'setting' => 'scan_aquick',
436
+ 'type' => 'select',
437
+ 'set' => cerber_get_qs(),
438
+ ) );
439
+ add_settings_field( 'scan_afull', __( 'Launch Full Scan', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_E, 's1',
440
+ array(
441
+ 'group' => $group,
442
+ 'setting' => 'scan_afull',
443
+ 'type' => 'timepicker',
444
+ 'enabled' => 'once a day at'
445
+ ) );
446
+
447
+ add_settings_section( 's2', 'Scan results reporting', 'cerber_sapi_section', CERBER_OPT_E );
448
+
449
+ $list = array( 1 => __('Low severity','wp-cerber'), 2 => __('Medium severity','wp-cerber'), 3 => __('High severity','wp-cerber')) + cerber_get_issue_label( array( CERBER_IMD, CERBER_UXT, 50, 51 ) );
450
+ add_settings_field( 'scan_reinc', __( 'Report an issue if any of the following is true', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_E, 's2',
451
+ array(
452
+ 'group' => $group,
453
+ 'setting' => 'scan_reinc',
454
+ 'type' => 'checkbox_set',
455
+ 'set' => $list,
456
+ ) );
457
+
458
+ add_settings_field( 'scan_relimit', __( 'Send email report', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_E, 's2',
459
+ array(
460
+ 'group' => $group,
461
+ 'setting' => 'scan_relimit',
462
+ 'type' => 'select',
463
+ 'set' => array(
464
+ 1 => __( 'After every scan', 'wp-cerber' ),
465
+ 3 => __( 'If any changes in scan results occurred', 'wp-cerber' ),
466
+ 5 => __( 'If new issues found', 'wp-cerber' ),
467
+ )
468
+ ) );
469
+
470
+ add_settings_field( 'scan_isize', __( 'Include file sizes', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_E, 's2',
471
+ array(
472
+ 'group' => $group,
473
+ 'setting' => 'scan_isize',
474
+ 'type' => 'checkbox',
475
+ ) );
476
+
477
+ add_settings_field( 'scan_ierrors', __( 'Include scan errors', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_E, 's2',
478
+ array(
479
+ 'group' => $group,
480
+ 'setting' => 'scan_ierrors',
481
+ 'type' => 'checkbox',
482
+ ) );
483
+
484
+ add_settings_field( 'email-scan', __( 'Email Address', 'wp-cerber' ), 'cerber_field_show', CERBER_OPT_E, 's2',
485
+ array( 'group' => $group,
486
+ 'setting' => 'email-scan',
487
+ 'type' => 'text',
488
+ 'placeholder' => __( 'Use comma to specify multiple values', 'wp-cerber' ),
489
+ 'delimiter' => ',',
490
+ 'list' => true,
491
+ 'size' => 60,
492
+ 'maxlength' => 1000,
493
+ 'label' => sprintf( __( 'if empty, email from notification settings will be used', 'wp-cerber' ), $def_email )
494
+ ) );
495
+
496
  }
497
  /*
498
  Generate HTML for each sections on a settings page
604
  <?php
605
  }
606
  /*
607
+ * Display a settings page (a single tab)
608
  *
609
  */
610
+ function cerber_show_settings_page( $group = null ) {
611
+ if ( is_multisite() ) {
612
+ $action = ''; // Settings API doesn't work in multisite. Post data will be handled in the cerber_ms_update()
613
+ }
614
+ else {
615
+ $action = 'options.php'; // Display form with settings fields via Settings API
616
+ }
617
+ echo '<form method="post" action="' . $action . '">';
618
+
619
+ settings_fields( 'cerberus-' . $group ); // option group name, the same as used in register_setting().
620
+ do_settings_sections( 'cerber-' . $group ); // the same as used in add_settings_section() $page
621
+ echo '<div style="padding-left: 220px">';
622
  submit_button();
623
  echo '</div>';
624
  echo '</form>';
825
  $html.= '<label for="'.$args['setting'].'">'.$label.'</label>';
826
  break;
827
  case 'textarea':
828
+ $html = '<textarea class="large-text code" id="' . $args['setting'] . '" name="' . $name . '" ' . $disabled . ' />' . $value . '</textarea>';
829
+ $html .= '<br><label for="' . $args['setting'] . '">' . $label . '</label>';
830
  break;
831
  case 'select':
832
+ $html = cerber_select( $name, $args['set'], $value );
833
+ break;
834
+ case 'checkbox_set':
835
+ $html = '<div class="crb-checkbox_set" style="line-height: 2em;">';
836
+ foreach ( $args['set'] as $key => $item ) {
837
+ $v = ( ! empty( $value[ $key ] ) ) ? $value[ $key ] : 0;
838
+ $html .= '<input type="checkbox" value="1" name="' . $name . '[' . $key . ']" ' . checked( 1, $v, false ) . $disabled . '/>' . $item . '</br>';
839
+ }
840
+ $html .= '</div>';
841
+ //$html='<textarea class="large-text code" id="'.$args['setting'].'" name="'.$name.'" '.$disabled.' />'.$value.'</textarea>';
842
  break;
843
  case 'reptime':
844
  $html = cerber_time_select( $args, $settings );
845
  break;
846
+ case 'timepicker':
847
+ $html = '<input class="crb-tpicker" type="text" size="7" id="' . $args['setting'] . '" name="' . $name . '" value="' . $value . '"' . $disabled . '/>';
848
+ $html .= ' <label for="' . $args['setting'] . '">' . $label . '</label>';
849
+ break;
850
  case 'text':
851
  default:
852
  $size = '';
876
  break;
877
  }
878
 
879
+ if ( ! empty( $args['enabled'] ) ) {
880
+ $name = 'cerber-' . $args['group'] . '[' . $args['setting'] . '-enabled]';
881
  $value = 0;
882
  if ( isset( $settings[ $args['setting'] . '-enabled' ] ) ) {
883
  $value = $settings[ $args['setting'] . '-enabled' ];
884
  }
885
  $checkbox = '<label class="crb-switch"><input class="screen-reader-text" type="checkbox" id="' . $args['setting'] . '-enabled" name="' . $name . '" value="1" ' . checked( 1, $value, false ) . ' /><span class="crb-slider round"></span></label>' . $args['enabled'];
886
+ $html = $checkbox . ' ' . $html;
887
  }
888
 
889
  echo $html."\n";
953
  /*
954
  Sanitizing users input for Main Settings
955
  */
956
+ add_filter( 'pre_update_option_'.CERBER_OPT, function ($new, $old, $option) {
 
957
 
958
  $ret = cerber_set_boot_mode( $new['boot-mode'], $old['boot-mode'] );
959
  if ( is_wp_error( $ret ) ) {
983
  $msg[] = __( 'If you use a caching plugin, you have to add your new login URL to the list of pages not to cache.', 'wp-cerber' );
984
  $msg_e[] = __( 'If you use a caching plugin, you have to add your new login URL to the list of pages not to cache.', 'wp-cerber' );
985
  cerber_admin_notice( $msg );
986
+ cerber_send_email( 'newlurl', $msg_e );
987
  }
988
  } else {
989
  $new['loginpath'] = '';
1007
  }
1008
 
1009
  return $new;
1010
+ }, 10, 3 );
1011
  /*
1012
  Sanitizing/checking user input for User tab settings
1013
  */
1014
+ add_filter( 'pre_update_option_'.CERBER_OPT_U, function ($new, $old, $option) {
 
1015
 
1016
  $new['prohibited'] = cerber_text2array($new['prohibited'], ',', 'strtolower');
1017
 
1018
  return $new;
1019
+ }, 10, 3 );
1020
  /*
1021
  Sanitizing/checking user input for reCAPTCHA tab settings
1022
  */
1023
+ add_filter( 'pre_update_option_'.CERBER_OPT_C, function ($new, $old, $option) {
 
1024
  global $wp_cerber;
1025
  // Check ability to make external HTTP requests
1026
  if ($wp_cerber && !empty($new['sitekey']) && !empty($new['secretkey'])) {
1042
  }
1043
 
1044
  return $new;
1045
+ }, 10, 3 );
1046
  /*
1047
  Sanitizing/checking user input for Notifications tab settings
1048
  */
1049
+ add_filter( 'pre_update_option_'.CERBER_OPT_N, function ($new, $old, $option) {
 
1050
 
1051
  $emails = cerber_text2array( $new['email'], ',' );
1052
 
1083
  }
1084
 
1085
  return $new;
1086
+ }, 10, 3 );
1087
 
1088
  /*
1089
  Sanitizing/checking user input for Hardening tab settings
1090
  */
1091
+ add_filter( 'pre_update_option_'.CERBER_OPT_H, function ($new, $old, $option) {
 
1092
 
1093
  $new['restwhite'] = cerber_text2array($new['restwhite'], "\n");
1094
 
1112
  }
1113
 
1114
  return $new;
1115
+ }, 10, 3 );
1116
  /*
1117
  Sanitizing/checking user input for Traffic Inspector tab settings
1118
  */
1119
+ add_filter( 'pre_update_option_'.CERBER_OPT_T, function ($new, $old, $option) {
 
1120
 
1121
  $new['tiwhite'] = cerber_text2array( $new['tiwhite'], "\n" );
1122
  foreach ( $new['tiwhite'] as $item ) {
1123
  if ( strrpos( $item, '?' ) ) {
1124
+ cerber_admin_notice( 'You may not specify the query string with a question mark: ' . htmlspecialchars( $item ) );
1125
  }
1126
  if ( strrpos( $item, '://' ) ) {
1127
  cerber_admin_notice( 'You may not specify the full URL: ' . htmlspecialchars( $item ) );
1139
  }
1140
 
1141
  return $new;
1142
+ }, 10, 3 );
1143
 
1144
  /*
1145
  Sanitizing/checking user input for Security Scanner settings
1146
  */
1147
+ add_filter( 'pre_update_option_' . CERBER_OPT_S, function ( $new, $old, $option ) {
 
1148
 
1149
  $list = cerber_text2array( $new['scan_exclude'], "\n" );
1150
  $list = array_filter( $list, function ( $item ) {
1151
+ if ( ! @is_dir( $item ) ) {
1152
+ cerber_admin_notice( 'Directory does not exist: ' . htmlspecialchars( $item ) );
1153
+ return false;
1154
+ }
1155
+ return true;
1156
  } );
1157
  $new['scan_exclude'] = $list;
1158
 
1160
  $new['scan_uext'] = cerber_text2array( $new['scan_uext'], "," );
1161
 
1162
  return $new;
1163
+ }, 10, 3 );
1164
+
1165
+ /*
1166
+ Sanitizing/checking user input for Scanner Schedule settings
1167
+ */
1168
+ add_filter( 'pre_update_option_' . CERBER_OPT_E, function ( $new, $old, $option ) {
1169
+ $new['scan_aquick'] = absint( $new['scan_aquick'] );
1170
+ $new['scan_afull-enabled'] = ( empty( $new['scan_afull-enabled'] ) ) ? 0 : 1;
1171
+
1172
+ $sec = cerber_sec_from_time( $new['scan_afull'] );
1173
+ if ( ! $sec || ! ( $sec >= 0 && $sec <= 86400 ) ) {
1174
+ $new['scan_afull'] = '01:00';
1175
+ }
1176
+
1177
+ $emails = cerber_text2array( $new['email-scan'], ',' );
1178
+ $new['email-scan'] = array();
1179
+ foreach ( $emails as $item ) {
1180
+ if ( is_email( $item ) ) {
1181
+ $new['email-scan'][] = $item;
1182
+ }
1183
+ else {
1184
+ cerber_admin_notice( __( '<strong>ERROR</strong>: please enter a valid email address.' ) );
1185
+ }
1186
+ }
1187
+
1188
+ if ( cerber_cloud_sync( $new ) ) {
1189
+ cerber_admin_message( __( 'The schedule has been updated', 'wp-cerber' ) );
1190
+ }
1191
+ else {
1192
+ cerber_admin_message( __( 'Unable to updated the schedule', 'wp-cerber' ) );
1193
+ }
1194
+
1195
+ return $new;
1196
+ }, 10, 3 );
1197
 
1198
  /**
1199
  * Let's sanitize them all
1369
 
1370
  ),
1371
  CERBER_OPT_H => array(
1372
+ 'stopenum' => 1,
1373
+ 'adminphp' => 0,
1374
+ 'xmlrpc' => 0,
1375
+ 'nofeeds' => 0,
1376
+ 'norest' => 0,
1377
+ 'restauth' => 0,
1378
+ 'restwhite' => 'oembed',
1379
+ 'hashauthor' => 0,
1380
  'cleanhead' => 1,
1381
  ),
1382
  CERBER_OPT_U => array(
1413
  'recaptcha-within' => 30,
1414
  ),
1415
  CERBER_OPT_N => array(
1416
+ 'email' => '',
1417
+ 'emailrate' => 12,
1418
  'notify-new-ver' => '1',
1419
+ 'pbtoken' => '',
1420
+ 'pbdevice' => '',
1421
+ 'wreports-day' => '1', // workaround, see cerber_upgrade_options()
1422
+ 'wreports-time' => 9,
1423
+ 'email-report' => '',
1424
  'enable-report' => '1', // workaround, see cerber_upgrade_options()
1425
  ),
1426
  CERBER_OPT_T => array(
1427
+ 'tienabled' => '1',
1428
+ 'tiipwhite' => 0,
1429
+ 'tiwhite' => '',
1430
+ 'timode' => '1',
1431
+ 'tinocrabs' => '1',
1432
+ 'tifields' => 0,
1433
+ 'timask' => '',
1434
+ 'tihdrs' => 0,
1435
+ 'tisenv' => 0,
1436
+ 'ticandy' => 0,
1437
+ 'tithreshold' => '',
1438
+ 'tikeeprec' => 7,
1439
+ ),
1440
  CERBER_OPT_S => array(
1441
+ 'scan_cpt' => '',
1442
+ 'scan_uext' => '',
1443
+ 'scan_exclude' => '',
1444
+ 'scan_inew' => '1',
1445
+ 'scan_imod' => '1',
1446
+ 'scan_tmp' => '1',
1447
+ 'scan_sess' => '1',
1448
  'scan_qcleanup' => '30',
1449
+ ),
1450
+ CERBER_OPT_E => array(
1451
+ 'scan_aquick' => 0,
1452
+ 'scan_afull' => '0' . rand( 1, 5 ) . ':00',
1453
+ 'scan_afull-enabled' => 0,
1454
+ 'scan_reinc' => array( 3 => 1, CERBER_IMD => 1, 50 => 1, 51 => 1 ),
1455
+ 'scan_relimit' => 3,
1456
+ 'scan_isize' => 0,
1457
+ 'scan_ierrors' => 0,
1458
+ 'email-scan' => ''
1459
  )
1460
+ );
1461
  if ( $field ) {
1462
  foreach ( $all_defaults as $option ) {
1463
  if ( isset( $option[ $field ] ) ) {
1584
  $united = array();
1585
 
1586
  if ( is_multisite() ) {
1587
+ //$set = $wpdb->get_col( 'SELECT meta_value FROM ' . $wpdb->sitemeta . ' WHERE meta_key ' . $in );
1588
+ // since 7.1.6
1589
+ $set = cerber_db_get_col( 'SELECT meta_value FROM ' . $wpdb->sitemeta . ' WHERE meta_key ' . $in );
1590
  }
1591
  else {
1592
+ //$set = $wpdb->get_col( 'SELECT option_value FROM ' . $wpdb->options . ' WHERE option_name ' . $in );
1593
+ // since 7.1.6
1594
+ $set = cerber_db_get_col( 'SELECT option_value FROM ' . $wpdb->options . ' WHERE option_name ' . $in );
1595
  }
1596
 
1597
  foreach ( $set as $item ) {
1644
  return get_site_option( $option, null );
1645
  }
1646
 
1647
+ if ( isset( $values[ $option ] ) ) {
1648
+ return $values[ $option ];
1649
+ }
1650
 
1651
  if ( is_multisite() ) {
1652
+ // @since 7.1
1653
+ //$value = $wpdb->get_var( 'SELECT meta_value FROM ' . $wpdb->sitemeta . ' WHERE meta_key = "' . $option . '"' );
1654
+ $value = cerber_db_get_var( 'SELECT meta_value FROM ' . $wpdb->sitemeta . ' WHERE meta_key = "' . $option . '"' );
1655
  }
1656
  else {
1657
+ // @since 7.1
1658
+ //$value = $wpdb->get_var( 'SELECT option_value FROM ' . $wpdb->options . ' WHERE option_name = "' . $option . '"' );
1659
+ $value = cerber_db_get_var( 'SELECT option_value FROM ' . $wpdb->options . ' WHERE option_name = "' . $option . '"' );
1660
  }
1661
 
1662
  if ( $value ) {
1698
  *
1699
  * @return array|string Email address(es) for notifications
1700
  */
1701
+ function cerber_get_email( $type = '', $array = false ) {
1702
  $email = '';
1703
 
1704
+ if ( in_array( $type, array( 'report', 'scan' ) ) ) {
1705
  $email = crb_get_settings( 'email-' . $type );
1706
  }
1707
 
1709
  $email = crb_get_settings( 'email' );
1710
  }
1711
 
1712
+ if ( ! $array && is_array( $email ) ) { // @since 4.9
1713
  $email = implode( ', ', $email );
1714
  }
1715
 
1722
 
1723
  return $email;
1724
  }
1725
+
1726
+ /**
1727
+ * Sync a set of scanner/uptime bots settings with the cloud
1728
+ *
1729
+ * @param $data
1730
+ *
1731
+ * @return bool
1732
+ */
1733
+ function cerber_cloud_sync( $data = array() ) {
1734
+ if ( ! $data ) {
1735
+ $data = crb_get_settings();
1736
+ }
1737
+ $e = ( empty( $data['scan_afull-enabled'] ) ) ? 0 : 1;
1738
+ $set = array(
1739
+ absint( $data['scan_aquick'] ),
1740
+ $e,
1741
+ cerber_sec_from_time( $data['scan_afull'] ),
1742
+ cerber_get_email( 'scan', true )
1743
+ );
1744
+ if ( lab_api_send_request( array(
1745
+ 'scan_scheduling' => array( // Is used for scheduled scans
1746
+ 'client' => $set,
1747
+ 'site_url' => home_url(),
1748
+ 'gmt_offset' => (int) get_option( 'gmt_offset' ),
1749
+ 'dtf' => cerber_get_dt_format(),
1750
+ )
1751
+ ) ) ) {
1752
+ return true;
1753
+ }
1754
+
1755
+ return false;
1756
+ }
1757
+
1758
+ /**
1759
+ * Is a cloud based service enabled by the site owner
1760
+ *
1761
+ * @return bool False if nothing cloud related is enabled
1762
+ */
1763
+ function cerber_is_cloud_enabled( $what = '' ) {
1764
+ $data = crb_get_settings();
1765
+
1766
+ $s = array( 'quick' => 'scan_aquick', 'full' => 'scan_afull-enabled' );
1767
+
1768
+ if ( $what ) {
1769
+ if ( ! empty( $data[ $s[ $what ] ] ) ) {
1770
+ return true;
1771
+ }
1772
+
1773
+ return false;
1774
+ }
1775
+
1776
+ foreach ( $s as $item ) {
1777
+ if ( ! empty( $data[ $item ] ) ) {
1778
+ return true;
1779
+ }
1780
+ }
1781
+
1782
+ return false;
1783
+ }
wp-cerber.php CHANGED
@@ -5,7 +5,7 @@
5
  Description: Protects WordPress against brute force attacks, bots and hackers. Antispam protection with the Cerber antispam engine and reCAPTCHA. Comprehensive control of user and bot activity. Restrict login by IP access lists. Limit login attempts. Know more: <a href="https://wpcerber.com">wpcerber.com</a>.
6
  Author: Gregory
7
  Author URI: https://wpcerber.com
8
- Version: 7.0
9
  Text Domain: wp-cerber
10
  Domain Path: /languages
11
  Network: true
@@ -31,7 +31,7 @@
31
 
32
  */
33
 
34
- define( 'CERBER_VER', '7.0' );
35
 
36
  function cerber_plugin_file() {
37
  return __FILE__;
@@ -78,12 +78,21 @@ function cerber_get_upload_dir() {
78
  static $dir = null;
79
  if ( $dir === null ) {
80
  $wp_upload_dir = wp_upload_dir();
81
- $dir = $wp_upload_dir['path'];
82
  }
83
 
84
  return $dir;
85
  }
86
 
 
 
 
 
 
 
 
 
 
87
  require_once( dirname( __FILE__ ) . '/cerber-load.php' );
88
  cerber_init();
89
 
5
  Description: Protects WordPress against brute force attacks, bots and hackers. Antispam protection with the Cerber antispam engine and reCAPTCHA. Comprehensive control of user and bot activity. Restrict login by IP access lists. Limit login attempts. Know more: <a href="https://wpcerber.com">wpcerber.com</a>.
6
  Author: Gregory
7
  Author URI: https://wpcerber.com
8
+ Version: 7.2
9
  Text Domain: wp-cerber
10
  Domain Path: /languages
11
  Network: true
31
 
32
  */
33
 
34
+ define( 'CERBER_VER', '7.2' );
35
 
36
  function cerber_plugin_file() {
37
  return __FILE__;
78
  static $dir = null;
79
  if ( $dir === null ) {
80
  $wp_upload_dir = wp_upload_dir();
81
+ $dir = cerber_normal_path( $wp_upload_dir['path'] );
82
  }
83
 
84
  return $dir;
85
  }
86
 
87
+ function cerber_get_abspath() {
88
+ static $abspath;
89
+ if ( $abspath === null ) {
90
+ $abspath = cerber_normal_path( ABSPATH );
91
+ }
92
+
93
+ return $abspath;
94
+ }
95
+
96
  require_once( dirname( __FILE__ ) . '/cerber-load.php' );
97
  cerber_init();
98