PluginProbe
WebTotem Security / 2.4.25
WebTotem Security v2.4.25
3.0.2 3.0.1 3.0.0 trunk 1.0 1.1 1.2 1.3 1.3.1 1.3.2 1.3.3 2.0 2.1 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.1 2.2.2 2.2.3 All 110 releases
wt-security / lib / Helper.php

Helper.php in WebTotem Security 2.4.25, at lib/Helper.php

1,880 lines 50.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('WEBTOTEM_INIT') || WEBTOTEM_INIT !== true) {
4 if (!headers_sent()) {
5 header('HTTP/1.1 403 Forbidden');
6 }
7 exit(1);
8 }
9
10 /**
11 * WebTotem Base class for Wordpress.
12 */
13 class WebTotem {
14
15 /**
16 * Returns an URL from the admin dashboard.
17 *
18 * @param string $url
19 * Optional trailing of the URL.
20 * @return string
21 * Full valid URL from the admin dashboard.
22 */
23 public static function adminURL($url = '') {
24 if (self::isMultiSite() and is_super_admin()) {
25 return network_admin_url($url);
26 }
27 return admin_url($url);
28 }
29
30 /**
31 * Define role of current user.
32 *
33 */
34 public static function getUserRole() {
35
36 if (defined('WEBTOTEM_USER_ROLE')) {
37 return true;
38 }
39 $current_user = wp_get_current_user();
40 if ( !($current_user instanceof WP_User) ){
41 $user_role = 0;
42 } else {
43 $roles = $current_user->roles;
44
45 if(in_array('administrator', $roles)) {
46 $user_role = 1;
47 } elseif(in_array('editor', $roles) or current_user_can('publish_posts')) {
48 $user_role = 2;
49 } else {
50 $user_role = 0;
51 }
52 }
53
54 define( 'WEBTOTEM_USER_ROLE', $user_role );
55
56 return true;
57 }
58
59 /**
60 * Check whether the current site is working as a multi-site instance.
61 *
62 * @return bool
63 * Either TRUE or FALSE in case WordPress is being used as a multi-site instance.
64 */
65 public static function isMultiSite() {
66 return (bool) ( (function_exists('is_multisite') && is_multisite()) || (defined('MULTISITE') && MULTISITE == true) );
67 }
68
69
70 /**
71 * Get user email.
72 *
73 * @return string
74 * Returns user email.
75 */
76 public static function getUserEmail() {
77 $email = WebTotemOption::getOption( "user_email" );
78 if(!$email){
79 if(WebTotemOption::isActivated()) {
80 $email = WebTotemAPI::getEmail();
81 }
82 WebTotemOption::setOptions(['user_email' => $email]);
83 }
84 return $email;
85 }
86
87 /**
88 * Returns the md5 hash representing the content of a file.
89 *
90 * @param string $file
91 * Relative path to the file.
92 * @return string
93 * Seven first characters in the hash of the file.
94 */
95 public static function fileVersion($file = '') {
96 return substr(md5_file(WEBTOTEM_PLUGIN_PATH . '/' . $file), 0, 7);
97 }
98
99 /**
100 * Returns full path to image.
101 *
102 * @param string $image
103 * Relative path to the file.
104 * @return string
105 * Full path to image.
106 */
107 public static function getImagePath($image) {
108 return WEBTOTEM_URL. '/includes/img/' . $image;
109 }
110
111 /**
112 * Checking whether the current domain belongs to the kz domain zone.
113 *
114 * @return bool
115 * true is returned if the domain belongs to the kz domain zone.
116 */
117 public static function isKz() {
118 $is_kz = json_decode(WebTotemOption::getOption('is_kz'), true);
119 if(is_array($is_kz)){
120 return $is_kz['value'];
121 }
122
123 if(function_exists('idn_to_utf')){
124 $host = idn_to_utf8($_SERVER['HTTP_HOST']);
125 } else {
126 $host = $_SERVER['HTTP_HOST'];
127 }
128
129 $parts = explode('.', $host);
130 $domain_zone = $parts[count($parts)-1];
131
132 if($domain_zone === 'kz' or $domain_zone === 'қаз'){
133 $is_kz['value'] = true;
134 } else {
135 $is_kz['value'] = false;
136 }
137
138 WebTotemOption::setOptions(['is_kz' => $is_kz]);
139
140 return $is_kz['value'];
141 }
142
143 /**
144 * Convert object to array.
145 *
146 * @param array $data
147 * Array.
148 * @return array
149 * Returns array.
150 */
151 public static function convertObjectToArray($data){
152
153 if(!is_array($data)) $data = (array)$data;
154 array_walk_recursive($data, function(&$item){
155 if(is_object($item)) $item = (array)$item;
156 });
157
158 return $data;
159 }
160
161 /**
162 * Removing duplicates by one key.
163 *
164 * @param array $array
165 * Array.
166 * @param string $key
167 * Delete duplicates with the same key.
168 *
169 * @return array
170 * Returns array.
171 */
172 public static function arrayUniqueKey($array, $key) {
173 $tmp = $key_array = array();
174 $i = 0;
175
176 foreach ($array as $val) {
177 if (!in_array($val[$key], $key_array)) {
178 $key_array[$i] = $val[$key];
179 $tmp[$i] = $val;
180 }
181 $i++;
182 }
183 return $tmp;
184 }
185
186 /**
187 * Returns user IP address.
188 *
189 * @return string
190 * Returns user IP address.
191 */
192 public static function getUserIP() {
193 $arr = [
194 'HTTP_CLIENT_IP',
195 'HTTP_X_FORWARDED_FOR',
196 'HTTP_X_FORWARDED',
197 'HTTP_X_CLUSTER_CLIENT_IP',
198 'HTTP_FORWARDED_FOR',
199 'HTTP_FORWARDED',
200 'HTTP_CF_CONNECTING_IP',
201 'REMOTE_ADDR'
202 ];
203
204 foreach ($arr as $key){
205 if (array_key_exists($key, $_SERVER) === true) {
206 foreach (explode(',', $_SERVER[$key]) as $ip) {
207 $ip = trim($ip);
208 $ip = filter_var($ip, FILTER_VALIDATE_IP);
209 if (!empty($ip)) {
210 return $ip;
211 }
212 }
213 }
214 }
215 return false;
216 }
217
218 /**
219 * Convert the file size to а human-readable format.
220 *
221 * @param string $bytes
222 * File size in bytes.
223 * @param string $decimals
224 * The number of characters after the decimal point.
225 *
226 * @return string
227 * Returns the file size in a human-readable format.
228 */
229 public static function humanFilesize($bytes, $decimals = 2) {
230 $factor = floor((strlen($bytes) - 1) / 3);
231 $unit_of_measurement = ($factor > 0) ? substr("KMGT", $factor - 1, 1) : '';
232 return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . $unit_of_measurement . 'B';
233 }
234
235 /**
236 * Check whether the file is publicly accessible.
237 *
238 * @param string $url
239 * http link to the file.
240 * @param string $path
241 * The path to the file.
242 *
243 * @return bool
244 */
245 public static function isPubliclyAccessible($url, $path) {
246 $response = wp_remote_get($url);
247
248 if ((int) floor(((int) wp_remote_retrieve_response_code($response) / 100)) === 2) {
249 $handle = @fopen($path, 'r');
250 if ($handle) {
251 $contents = fread($handle, 700);
252 fclose($handle);
253 $remoteContents = substr(wp_remote_retrieve_body($response), 0, 700);
254
255 return $contents === $remoteContents;
256 }
257 }
258 return false;
259 }
260
261 /**
262 * Check that the training period has passed for the firewall.
263 *
264 * @param string $created_at
265 * Date when the waf configuration was created.
266 *
267 * @return bool
268 * Returns boolean.
269 */
270 public static function isWafTraining($created_at) {
271 if($created_at) {
272 $when_waf_trained = strtotime('+2 day', strtotime($created_at));
273 $today = strtotime('today');
274
275 return ($when_waf_trained < $today) ? FALSE : TRUE;
276 }
277 return FALSE;
278 }
279
280 /**
281 * Check if the data for the period is available.
282 *
283 * @param string $created_at
284 * Date when the agent manager was created.
285 *
286 * @return array
287 * Returns an array with periods.
288 */
289 public static function isPeriodAvailable($created_at) {
290
291 $diff = strtotime(gmdate("Y-m-d H:i:s")) - strtotime($created_at);
292 $daysCount = floor($diff / 86400);
293
294 return [
295 'monthly' => $daysCount > 7,
296 'yearly' => $daysCount > 30,
297 ];
298
299 }
300
301
302
303 /**
304 * Converting a date to the appropriate format.
305 *
306 * @param string $date
307 * Date in any format.
308 * @param string $format
309 * The format to which you want to convert the date.
310 *
311 * @return string
312 * Returns converted Date.
313 */
314 public static function dateFormatter($date, $format = 'M j, Y \/ H:i') {
315 if (!$date) {
316 return __('Unknown', 'wtotem');
317 }
318
319 $time_zone = WebTotemOption::getOption('time_zone_offset');
320 $user_time = ($time_zone) ? strtotime($time_zone . 'hours', strtotime($date)) : strtotime($date);
321
322 return date_i18n($format, $user_time);
323 }
324
325 /**
326 * Get theme mode data.
327 *
328 * @return array
329 * Returns array with current theme data.
330 */
331 public static function getThemeMode() {
332 $theme_mode = WebTotemOption::getSessionOption('theme_mode');
333 return [
334 "is_dark_mode" => $theme_mode == 'dark' ? 'wtotem_theme—dark' : '',
335 "dark_mode_checked" => $theme_mode == 'dark' ? 'checked' : '',
336 ];
337 }
338
339 /**
340 * Get current user language.
341 *
342 * @return string
343 * Returns current language in 2-letter abbreviations
344 */
345 public static function getLanguage() {
346 $current_language = substr(get_bloginfo('language'), 0,2);
347 $language = (in_array($current_language,['ru','en','pl'])) ? $current_language : 'en' ;
348 return $language;
349 }
350
351 /**
352 * Converting a date to the appropriate format.
353 *
354 * @param string|array $days
355 * Number of days or period to convert.
356 *
357 * @return array
358 * Returns an array of two values "from" and "to"
359 */
360 public static function getPeriod($days) {
361
362 if (!$days) {
363 $days = 30;
364 }
365
366 switch ($days) {
367
368 case is_array($days):
369 $to = $days[1] ?: $days[0];
370 $period = [
371 'from' => strtotime(date('Y-m-d 00:00:01', strtotime(self::formatDate($days[0])))),
372 'to' => strtotime(date('Y-m-d 23:59:59', strtotime(self::formatDate($to)))),
373 ];
374 break;
375
376 case $days <= 1:
377 $period = [
378 'from' => strtotime('-24 hours'),
379 'to' => time(),
380 ];
381 break;
382
383 default:
384 $period = [
385 'from' => time() - ($days * 86400),
386 'to' => time(),
387 ];
388 }
389
390 return $period;
391 }
392
393 /**
394 * Converting a date from "j M, Y" format to 'd-m-Y' format.
395 *
396 * @return string
397 * Returns date in new format
398 */
399 public static function formatDate($date){
400 $month = [
401 'Jan' => 'Янв',
402 'Feb' => 'Фев',
403 'Mar' => 'Мар',
404 'Apr' => 'Апр',
405 'May' => 'Май',
406 'Jun' => 'Июн',
407 'Jul' => 'Июл',
408 'Aug' => 'Авг',
409 'Sep' => 'Сен',
410 'Oct' => 'Окт',
411 'Nov' => 'Ноя',
412 'Dec' => 'Дек',
413 ];
414
415 foreach ($month as $key => $value) {
416 if (strpos($date, $value)) {
417 $date = str_replace($value, $key, $date);
418 }
419 }
420
421 $pattern = '/^(\d{1,2})\s+([a-zA-Z]+),\s+(\d{4})$/';
422
423 if (preg_match($pattern, $date, $matches)) {
424 $monthNumber = date_parse($matches[2])['month'];
425
426 return sprintf('%02d-%02d-%04d', $matches[1], $monthNumber, $matches[3]);
427 }
428
429 return $date;
430
431 }
432
433 /**
434 * Convert an array to a string with quotation marks.
435 *
436 * @param array $array
437 * Data array.
438 *
439 * @return string
440 * Array of data converted to string.
441 */
442 public static function convertArrayToString($array) {
443 if(empty($array)){
444 return '';
445 }
446 return '"' . implode('","', $array) . '"';
447 }
448
449 /**
450 * Converting the response to a readable form.
451 *
452 * @param string $message
453 * Message response from the API server to the request.
454 *
455 * @return string|bool
456 * Returns a message.
457 */
458 public static function messageForHuman($message) {
459
460 $definition = $message;
461
462 switch ($message) {
463 case 'HOSTS_LIMIT_EXCEEDED':
464 $definition = __('Limit of adding sites exceeded.', 'wtotem');
465 break;
466
467 case 'USER_ALREADY_REGISTERED':
468 $definition = __('A user with this email already exists.', 'wtotem');
469 break;
470
471 case 'DUPLICATE_HOST':
472 $definition = __('Duplicate host', 'wtotem');
473 break;
474
475 case 'INVALID_DOMAIN_NAME':
476 $definition = __('Invalid Domain Name', 'wtotem');
477 break;
478 default:
479 $definition = str_replace("_", " ", $definition);
480 $definition = ucfirst(strtolower($definition));
481
482 }
483 return $definition;
484 }
485
486 /**
487 * Get the data associated with the status.
488 *
489 * @param string $status
490 * Module or agent status.
491 *
492 * @return array
493 * Returns an array with status data.
494 */
495 public static function getStatusData($status) {
496 $path = self::getImagePath('');
497 $status = ($status == "installed") ? 'working' : $status;
498
499 switch ($status) {
500
501 case 'clean':
502 case 'up':
503 case 'installed':
504 case 'working':
505 case 'good':
506 $status_data = [
507 'class' => 'is--status--ok',
508 'image' => $path . 'check-mark.svg',
509 'icon' => $path . 'icon_success_status.svg',
510 ];
511 break;
512
513 case 'pending':
514 $status_data = [
515 'class' => 'is--status--pending',
516 'image' => $path . 'loading.svg',
517 'icon' => $path . 'alert-warning.svg',
518 ];
519 break;
520
521 case 'pause':
522 case 'modified':
523 $status_data = [
524 'class' => 'is--status--pending',
525 'image' => $path . 'warning.svg',
526 'icon' => $path . 'alert-warning.svg',
527 ];
528 break;
529
530 case 'expired':
531 case 'no_cert':
532 case 'expires':
533 case 'open_ports':
534 case 'warning':
535 case 'not_supported':
536 case 'not_registered':
537 $status_data = [
538 'class' => 'is--status--warning',
539 'image' => $path . 'warning.svg',
540 'icon' => $path . 'alert-warning.svg',
541 ];
542 break;
543
544 case 'invalid':
545 case 'revoked':
546 case 'untrusted':
547 case 'not_found':
548 case 'wrong_host':
549 case 'error':
550 case 'down':
551 case 'expires_today':
552 case 'infected':
553 case 'deface':
554 case 'not_installed':
555 $status_data = [
556 'class' => 'is--status--error',
557 'image' => $path . 'warning.svg',
558 'icon' => $path . 'alert-warning.svg',
559 ];
560 break;
561
562 default:
563 $status_data = [
564 'class' => 'is--status--pending',
565 'image' => $path . 'warning.svg',
566 'icon' => $path . 'alert-warning.svg',
567 ];
568 }
569 $status_data['name'] = $status;
570 $status_data['text'] = self::getStatusText($status);
571 $status_data['tooltips'] = self::getTooltips($status);
572
573 return $status_data;
574 }
575
576 /**
577 * Get a readable status text.
578 *
579 * @param string $status
580 * Module or agent status.
581 *
582 * @return string
583 * Returns the status text in the current language.
584 */
585 public static function getStatusText($status) {
586 $statuses = [
587 'warning' => __('Warning', 'wtotem'),
588 'error' => __('Error', 'wtotem'),
589 'success' => __('Success', 'wtotem'),
590 'info' => __('Info', 'wtotem'),
591 'invalid' => __('Invalid', 'wtotem'),
592 'ok' => __('Everything is OK', 'wtotem'),
593 'expired' => __('Expired', 'wtotem'),
594 'expires' => __('Expires', 'wtotem'),
595 'expires_today' => __('Expires today', 'wtotem'),
596 'missing' => __('Missing', 'wtotem'),
597 'active' => __('Active', 'wtotem'),
598 'inactive' => __('Inactive', 'wtotem'),
599 'pending' => __('Pending', 'wtotem'),
600 'pause' => __('Disabled', 'wtotem'),
601 'available' => __('Available', 'wtotem'),
602 'not_supported' => __('Not supported', 'wtotem'),
603 'not_registered' => __('Not registered', 'wtotem'),
604 'unsupported' => __('Unsupported', 'wtotem'),
605 'clean' => __('Clean', 'wtotem'),
606 'clear' => __('Clear', 'wtotem'),
607 'blacklisted' => __('Infected', 'wtotem'),
608 'miner_detected' => __('Infected', 'wtotem'),
609 'deface' => __('Deface', 'wtotem'),
610 'modified' => __('Modified', 'wtotem'),
611 'detected' => __('Detected', 'wtotem'),
612 'open_ports' => __('Open ports', 'wtotem'),
613 'blocked' => __('Blocked', 'wtotem'),
614 'connected' => __('Connected', 'wtotem'),
615 'attacks_detected' => __('Attacks detected', 'wtotem'),
616 'signature_found' => __('Signature found', 'wtotem'),
617 'file_changes' => __('File changes', 'wtotem'),
618 'no_cert' => __('No cert', 'wtotem'),
619 'down' => __('Down', 'wtotem'),
620 'up' => __('Up', 'wtotem'),
621 'infected' => __('Infected', 'wtotem'),
622 'not_installed' => __('Need to install', 'wtotem'),
623 'agent_not_available' => __('Agent not available', 'wtotem'),
624 'update_error' => __('Update error', 'wtotem'),
625 'session_error' => __('Session Error', 'wtotem'),
626 'internal_error' => __('Internal Error', 'wtotem'),
627 'installing' => __('Installing', 'wtotem'),
628 'installed' => __('Installed', 'wtotem'),
629 'working' => __('Working', 'wtotem'),
630 "critical" => __('Critical', 'wtotem'),
631 "deleted" => __('Deleted', 'wtotem'),
632 "changed" => __('Changed', 'wtotem'),
633 "new" => __('New', 'wtotem'),
634 "scanned" => __('Scanned', 'wtotem'),
635 "quarantine" => __('In quarantine', 'wtotem'),
636 "good" => __('Good', 'wtotem'),
637 "wrong_host" => __('Wrong host', 'wtotem'),
638 "revoked" => __('Revoked', 'wtotem'),
639 "untrusted" => __('Untrusted', 'wtotem'),
640 "not_found" => __('Not found', 'wtotem'),
641 ];
642
643 return (array_key_exists($status, $statuses)) ? $statuses[$status] : $status;
644 }
645
646 /**
647 * Get tooltips text for status.
648 *
649 * @param string $status
650 * Module or agent status.
651 *
652 * @return string
653 * Returns the status tooltip in the current language.
654 */
655 public static function getTooltips($status) {
656 $tooltips = [
657 'invalid' => __('Invalid -The certificate is invalid. Please, make sure that relevant certificate details filled correctly.', 'wtotem'),
658 'expired' => __('Expired - The certificate has expired. Connection is not secure. Please, renew it.', 'wtotem'),
659 'expires' => __('Expires - The certificate expires soon. Please, take actions.', 'wtotem'),
660 'expires_today' => __('Expires today - The certificate expires today. Please, take actions.', 'wtotem'),
661 'error' => __("Error - Something went wrong. Please, contact us, we'll fix the problem.", 'wtotem'),
662 'pending' => __('Pending - System processes your website. Data will be available soon.', 'wtotem'),
663 'pause' => __('Pause - The module is paused.', 'wtotem'),
664 'clean' => __('Everything is OK - Nothing to worry about. Everything is alright.', 'wtotem'),
665 'deface' => __("Deface - Website hacked. Please, contact us, we'll fix the problem.", 'wtotem'),
666 'open_ports' => __('Open ports - Open ports detected. Your website is vulnerable to attacks.', 'wtotem'),
667 'blocked' => __('Blocked - The module is blocked due to billing issues.', 'wtotem'),
668 'no_cert' => __("No cert - You don't have SSL certificate. We recommend you to install it for security concerns.", 'wtotem'),
669 'down' => __('Down - The website is not available for visitors.', 'wtotem'),
670 'up' => __('Up - The website is available for visitors.', 'wtotem'),
671 'infected' => __('Infected - The website site is blacklisted and may have infected files. Please, check antivirus module.', 'wtotem'),
672 'installing' => __('It means that the agent installation is in progress. Usually, it takes up to one hour.', 'wtotem'),
673 'agent_not_available' => __('We cannot locate the agent right now.', 'wtotem'),
674 'update_error' => __('It seems that your agent failed to update due to permissions restrictions.', 'wtotem'),
675 'session_error' => __('This means that the agent did not create a secure session. Possible causes include network issues, wrong server configuration, third-party firewalls. Please contact our support..', 'wtotem'),
676 'internal_error' => __('It means that the server is overloaded or there might be some problems with the connection. Usually, the issue resolves itself within 10-15 minutes. If the status does not change during two hours, please cordially contact our support..', 'wtotem'),
677 'working' => __('Everything is alright.', 'wtotem'),
678 'installed' => __('Everything is alright.', 'wtotem'),
679 'not_installed' => __('You need to install agent manager to activate antivirus and firewall.', 'wtotem'),
680 ];
681
682 return (array_key_exists($status, $tooltips)) ? $tooltips[$status] : '';
683 }
684
685 /**
686 * Converting site data.
687 *
688 * @param array $data
689 * Sites data from WebTotem.
690 *
691 * @return array
692 * Converted data.
693 */
694 public static function allSitesData($data) {
695
696 $local_sites = get_sites();
697 $main_host = WebTotemOption::getMainHost();
698 $domains = [];
699
700 foreach ($local_sites as $site){
701 $domain = untrailingslashit($site->domain . $site->path);
702 $domains[$domain] = $domain;
703 }
704
705 $sites = [];
706 if(array_key_exists('edges', $data)){
707 foreach ($data['edges'] as $site) {
708 $site = $site['node'];
709 // Take sites only from the multisite network.
710 if(array_key_exists($site['hostname'], $domains)) {
711 unset($domains[$site['hostname']]);
712 $sites[] = [
713 'hostname' => $site['hostname'],
714 'title' => $site['title'],
715 'main_host' => $main_host['id'] == $site['id'],
716 'host_id' => $site['id'],
717 'url' => admin_url('admin.php?page=wtotem_dashboard&hid=' . $site['id']),
718 'firewall' => [
719 'status' => self::getStatusData($site['firewall']['status']),
720 ],
721 'antivirus' => [
722 'status' => self::getStatusData($site['antivirus']['status']),
723 ],
724 'stacks' => self::getStacksData($site['maliciousScript']['stack']),
725 'services' => self::getSiteServicesData($site),
726 ];
727 }
728 }
729
730 }
731 return $sites;
732 }
733
734 /**
735 * Converting stacks data.
736 *
737 * @param array $stacks
738 * Stacks data from WebTotem.
739 *
740 * @return array
741 * Converted data.
742 */
743 protected static function getStacksData($stacks) {
744 $apps = file_get_contents(WEBTOTEM_PLUGIN_PATH . '/includes/js/apps.json');
745 $apps = json_decode($apps, true);
746
747 $path = 'https://assets.wtotem.net/images/apps/';
748 $defaultIcon = WEBTOTEM_URL . '/includes/img/defaultTechnologiesIcon.svg';
749
750 $stackList = array_slice($stacks, 0,3);
751 $list = [];
752 foreach ($stackList as $key => $stack){
753 $list[$key] = [
754 'name' => $stack['name'],
755 'icon' => $path . ($apps[$stack['name']]['icon'] ?: $defaultIcon),
756 ];
757 }
758
759 if(count($stacks) <= 3){
760 $other['count'] = 0;
761 $other['names'] = [];
762 } else {
763 $otherStacks = array_slice($stacks, 3);
764 $other['count'] = count($otherStacks);
765 foreach ($otherStacks as $stack){
766 $other['names'][] = $stack['name'];
767 }
768 }
769 if($other['names']){
770 $other['names'] = implode(",", $other['names']);
771 }
772 return ['list' => $list, 'other' => $other];
773 }
774
775 /**
776 * Converting services data.
777 *
778 * @param $data
779 * Site data from WebTotem.
780 *
781 * @return array
782 * Converted data.
783 */
784 protected static function getSiteServicesData($data) {
785
786 $services = [
787 'ssl' => 'ssl',
788 'availability' => 'wa',
789 'reputation' => 'rc',
790 'ports' => 'ps',
791 'deface' => 'dc',
792 'domain' => 'dec',
793 ];
794
795 $list = [];
796 $other['count'] = 0;
797 $other['names'] = [];
798
799 foreach ($services as $key => $service){
800 if(array_key_exists($key, $data) and is_array($data[$key]) and array_key_exists('status', $data[$key])){
801 $status = self::getServiceStatus($data[$key]['status']);
802
803 if(in_array($status['color'], ['red', 'yellow'])){
804 if(count($list) < 2){
805 $color = $status['color'] == 'red' ? 'white/' : '';
806
807 $list[$key] = [
808 'status' => $status,
809 'icon' => 'services/'. $color . $service . '.svg',
810 'name' => self::getServiceName( $service ),
811 ];
812 } else {
813 $other['names'][] = self::getServiceName( $service );
814 $other['count']++;
815 }
816 }
817
818 }
819 }
820 if($other['names']){
821 $other['names'] = implode(",", $other['names']);
822 }
823 return ['list' => $list, 'other' => $other];
824 }
825
826 /**
827 * Get the data associated with the status.
828 *
829 * @param string $status
830 * Module or agent status.
831 *
832 * @return array
833 * Returns an array with status data.
834 */
835 public static function getServiceStatus($status) {
836 switch ($status) {
837
838 case 'expired':
839 case 'invalid':
840 case 'error':
841 case 'expires_today':
842 case 'down':
843 case 'infected':
844 case 'deface':
845 case 'not_installed':
846 case 'quarantine':
847 $status_data = [
848 'color' => 'red',
849 ];
850 break;
851
852 case 'no_cert':
853 case 'expires':
854 case 'open_ports':
855 case 'modified':
856 case 'not_supported':
857 case 'not_registered':
858 case 'blocked':
859 case 'pause':
860 case 'internal_error':
861 case 'update_error':
862 case 'config_error':
863 case 'agent_not_available':
864 case 'session_error':
865 $status_data = [
866 'color' => 'yellow',
867 ];
868 break;
869
870 case 'clean':
871 case 'installed':
872 case 'up':
873 case 'scanned':
874 case 'working':
875 $status_data = [
876 'color' => 'green',
877 ];
878 break;
879
880 case 'deleted':
881 $status_data = [
882 'color' => 'black',
883 ];
884 break;
885
886 case 'installing':
887 case 'pending':
888 default:
889 $status_data = [
890 'color' => 'gray',
891 ];
892 break;
893
894 }
895
896 return $status_data;
897 }
898
899 /**
900 * Get the translation of service.
901 *
902 * @param $service
903 * Service short name.
904 *
905 * @return string
906 * Translation of service.
907 */
908 public static function getServiceName($service){
909 $services = [
910 "wa" => __('Availability', 'wtotem'),
911 "rc" => __('Reputation', 'wtotem'),
912 "ssl" => 'SSL',
913 "cms" => __('Technologies', 'wtotem'),
914 "dc" => __('Deface', 'wtotem'),
915 "ps" => __('Ports', 'wtotem'),
916 "waf" => __('Firewall', 'wtotem'),
917 "av" => __('Antivirus', 'wtotem'),
918 "dec" => __('Domain', 'wtotem'),
919 ];
920 return $services[$service];
921 }
922
923 /**
924 * Get reports with modules list.
925 *
926 * @param array $edges
927 * Data on generated reports.
928 *
929 * @return array
930 * Returns an array with converted data.
931 */
932 public static function getReports(array $edges) {
933 $modulesLang = [
934 'wa' => __('Availability log', 'wtotem'),
935 'dc' => __('Deface log', 'wtotem'),
936 'ps' => __('Port log', 'wtotem'),
937 'rc' => __('Reputation log', 'wtotem'),
938 'sc' => __('Evaluation log', 'wtotem'),
939 'av' => __('Antivirus log', 'wtotem'),
940 'waf' => __('Firewall log', 'wtotem'),
941 ];
942
943 $reports = [];
944
945 foreach ($edges as $edge) {
946 if (in_array(FALSE, $edge["node"])) {
947 $arr = [];
948 foreach ($edge["node"] as $module => $value) {
949 if ($value == TRUE && array_key_exists($module, $modulesLang)) {
950 $arr[] = $modulesLang[$module];
951 }
952 }
953 $modules = implode(", ", $arr);
954 }
955 else {
956 $modules = __('All modules', 'wtotem');
957 }
958
959 $reports[] = [
960 'id' => $edge["node"]['id'],
961 'modules' => $modules,
962 'created_at' => self::dateFormatter($edge["node"]['createdAt']),
963 ];
964 }
965
966 return $reports;
967 }
968
969 /**
970 * Get reputation status description.
971 *
972 * @param string $status
973 * Reputation status.
974 *
975 * @return string
976 * Returns a description of the reputation status
977 */
978 public static function getReputationInfo($status) {
979 switch ($status) {
980 case 'clean':
981 $data = __("Don't worry, your reputation is good", 'wtotem');
982 break;
983
984 case 'infected':
985 $data = __('Oh, your reputation is bad', 'wtotem');
986 break;
987
988 default:
989 $data = __('Information is being updated', 'wtotem');
990 }
991 return $data;
992 }
993
994 /**
995 * Get blacklists entries counts.
996 *
997 * @param string $status
998 * Reputation status.
999 * @param array $virus_list
1000 * Sources where the site can be blacklisted.
1001 *
1002 * @return int
1003 * Number of references in blacklists.
1004 */
1005 public static function blacklistsEntries($status, array $virus_list) {
1006 $count = 0;
1007 if ($status != "clean") {
1008 foreach ($virus_list as &$list) {
1009 if (!empty($list['virus']['type'])) {
1010 $count++;
1011 }
1012 }
1013 }
1014 return $count;
1015 }
1016
1017 /**
1018 * Classification of the rating in the letter grades.
1019 *
1020 * @param int $score
1021 * Site rating from 1 to 100.
1022 *
1023 * @return array
1024 * Returns an array of data.
1025 */
1026 public static function scoreGrading($score) {
1027 if ($score < 0 || $score > 100) {
1028 return ['grade' => '', 'color' => ''];
1029 }
1030
1031 $scores = [
1032 100 => 'A+',
1033 90 => 'A',
1034 80 => 'A-',
1035 70 => 'B+',
1036 60 => 'B',
1037 50 => 'B-',
1038 35 => 'C+',
1039 20 => 'C',
1040 0 => 'C-',
1041 ];
1042
1043 foreach ($scores as $key => $value) {
1044 if ($score >= $key) {
1045 $grade = $value;
1046 break;
1047 }
1048 }
1049
1050 // Set a color depending on the grade.
1051 switch ($score) {
1052 case $score >= 80:
1053 $color = 'green';
1054 break;
1055
1056 case $score >= 50:
1057 $color = 'orange';
1058 break;
1059
1060 default:
1061 $color = 'red';
1062 }
1063
1064 return ['grade' => $grade, 'color' => $color];
1065 }
1066
1067 /**
1068 * Calculate the number of remaining days.
1069 *
1070 * @param string $date
1071 * Expiry date.
1072 *
1073 * @return string
1074 * Returns the number of days before the expiration date.
1075 */
1076 public static function daysLeft($date) {
1077 if ((int) $date === 0) {
1078 $days_left = 0;
1079 }
1080 else {
1081 $now = new \DateTime();
1082 $expiry_date = new \DateTime();
1083 $timestamp = strtotime($date);
1084 $expiry_date->setTimestamp($timestamp);
1085 $days_left = $expiry_date->diff($now)->format("%a");
1086 }
1087 return $days_left;
1088 }
1089
1090 /**
1091 * Converting the firewall logs.
1092 *
1093 * @param array $logs_
1094 * Firewall logs from WebTotem.
1095 *
1096 * @return array
1097 * Converted array of logs.
1098 */
1099 public static function wafLogs(array $logs_) {
1100 $logs = [];
1101 foreach ($logs_ as $key => $log) {
1102 $log = $log['node'];
1103
1104 $logs[$key]['ip'] = $log['ip'];
1105 $logs[$key]['request'] = htmlspecialchars(urldecode($log['request']));
1106 $logs[$key]['time'] = self::dateFormatter($log['time']);
1107 $logs[$key]['country_code'] = strtolower($log['country']);
1108 $logs[$key]['country'] = $log['location']['country']['nameEn'];
1109 $logs[$key]['blocked'] = $log['blocked'] ? __('Blocked IP', 'wtotem') : __('Not blocked', 'wtotem');
1110
1111 $more = [
1112 'ip' => $log['ip'],
1113 'proxy_ip' => $log['proxyIp'],
1114 'source' => $log['source'],
1115 'request' => htmlspecialchars(urldecode($log['request'])),
1116 'user_agent' => $log['userAgent'],
1117 'time' => self::dateFormatter($log['time']),
1118 'type' => $log['type'],
1119 'category' => $log['category'],
1120 'country' => $log['location']['country']['nameEn'],
1121 'payload' => htmlspecialchars(urldecode($log['payload'])),
1122 ];
1123
1124 $logs[$key]['more'] = json_encode($more);
1125 }
1126 return $logs;
1127 }
1128
1129 /**
1130 * Converting firewall data to json for a D3 chart.
1131 *
1132 * @param array $charts
1133 * Charts data from WebTotem.
1134 *
1135 * @return array
1136 * Returns the converted data for chart.
1137 */
1138 public static function generateWafChart(array $charts) {
1139 $sum = 0;
1140 foreach ($charts as $chart) {
1141 $sum += $chart['attacks'];
1142 }
1143 if ($sum == 0) {
1144 return ['chart' => FALSE, 'count_attacks' => 0, 'count_blocks' => 0];
1145 }
1146
1147 // Get days count.
1148 $charts_ = $charts;
1149 $first = array_shift($charts_);
1150 $last = array_pop($charts_);
1151 $days = ceil((strtotime($last['time']) - strtotime($first['time'])) / 86400);
1152
1153 // Set variables.
1154 $count_attacks = $count_blocks = 0;
1155
1156 foreach ($charts as $chart) {
1157 if ($days <= 1) {
1158 $time_zone = WebTotemOption::getOption('time_zone_offset');
1159 $userTime = ($time_zone) ? strtotime($time_zone . ' hours', strtotime($chart['time'])) : strtotime($chart['time']);
1160 }
1161 if (($chart['attacks'] and $days == 2) or $days != 2) {
1162 $result[] = [
1163 'date' => ($days <= 1) ? date("Y-m-d H:00:00", $userTime) : date("Y-m-d", strtotime($chart['time'])),
1164 'count' => $chart['blocked'],
1165 'attacks' => $chart['attacks'],
1166 'blocked' => $chart['blocked'],
1167 ];
1168 $count_attacks += $chart['attacks'];
1169 $count_blocks += $chart['blocked'];
1170 }
1171 }
1172
1173 if (!isset($result)) {
1174 return [
1175 'chart' => FALSE,
1176 'count_attacks' => 0,
1177 'count_blocks' => 0,
1178 'days' => 0,
1179 ];
1180 }
1181
1182 return [
1183 'chart' => json_encode($result),
1184 'count_attacks' => $count_attacks,
1185 'count_blocks' => $count_blocks,
1186 'days' => $days,
1187 ];
1188 }
1189
1190 /**
1191 * Converting data to json for a D3 chart.
1192 *
1193 * @param array $charts
1194 * Charts data from WebTotem.
1195 * @param int $days
1196 * The number of days to build the chart.
1197 *
1198 * @return bool|string
1199 * Returns the converted data for chart.
1200 */
1201 public static function generateChart(array $charts, $days = 7) {
1202 $sum = 0;
1203 foreach ($charts as $chart) {
1204 $sum += $chart['value'];
1205 }
1206 if ($sum == 0) {
1207 return FALSE;
1208 }
1209
1210 $result = [];
1211
1212 foreach ($charts as $chart) {
1213 if ($days <= 1) {
1214 $time_zone = WebTotemOption::getOption('time_zone_offset');
1215 $userTime = ($time_zone) ? strtotime($time_zone . 'hours', strtotime($chart['time'])) : strtotime($chart['time']);
1216 }
1217 $result[] = [
1218 'date' => ($days <= 1) ? date("Y-m-d H:00:00", $userTime) : date("Y-m-d", strtotime($chart['time'])),
1219 'value' => $chart['value'],
1220 ];
1221 }
1222
1223 return json_encode($result, TRUE);
1224 }
1225
1226 /**
1227 * Converting data to json for a D3 chart.
1228 *
1229 * @param array $data
1230 * Charts data from WebTotem.
1231 *
1232 * @return array|bool
1233 * Returns the converted data for chart.
1234 */
1235 public static function generateAttacksMapChart(array $data) {
1236 $attacks = [];
1237 $countries = [];
1238 $labels = [];
1239 foreach ($data as $value) {
1240 $attacks[] = $value['attacks'];
1241 $labels[] = self::getCountryName($value['country']);
1242 $countries[] = $value['location']['country']['nameEn'];
1243 }
1244 $result = ['attacks' => $attacks, 'countries' => $countries, 'labels' => $labels];
1245
1246 if (!$attacks) {
1247 return FALSE;
1248 }
1249
1250 return json_encode($result, TRUE);
1251 }
1252
1253 /**
1254 * Reassembling the antivirus logs.
1255 *
1256 * @param array $logs_
1257 * Antivirus logs from WebTotem.
1258 *
1259 * @return array
1260 * Reassembled array of logs.
1261 */
1262 public static function getAntivirusLogs(array $logs_) {
1263 $logs = [];
1264 foreach ($logs_ as $key => $log) {
1265 $log = $log['node'];
1266
1267 $file_info = new SplFileInfo(urldecode($log['filePath']));
1268
1269 $log['original_path'] = $log['filePath'];
1270 $log['file_path'] = $file_info->getPath() . '/';
1271 $log['file_name'] = $file_info->getFilename();
1272 $log['time'] = self::dateFormatter($log['time']);
1273 $log['permissions_changed'] = $log['permissionsChanged'];
1274 $log['status'] = self::getStatusData($log['event']);
1275 $log['class'] = 'wt-text--green';
1276
1277 switch ($log['event']) {
1278 case 'modified':
1279 case 'quarantine':
1280 $log['class'] = "wt-text--yellow";
1281 break;
1282
1283 case 'deleted':
1284 $log['class'] = "wt-text--light-gray";
1285 break;
1286
1287 case 'infected':
1288 $log['class'] = "wt-text--red";
1289 break;
1290 }
1291
1292 $logs[$key] = $log;
1293 }
1294 return $logs;
1295 }
1296
1297 /**
1298 * Get open path data.
1299 *
1300 * @param array $_ports
1301 * Open ports array.
1302 *
1303 * @return array
1304 * Reassembled array of open ports.
1305 */
1306 public static function getOpenPortsData($ports) {
1307 if(!$ports){
1308 return [];
1309 }
1310 foreach ($ports as $key => $port) {
1311 $summary = '';
1312 if($port['cveList']){
1313 foreach ($port['cveList'] as $item){
1314 $summary .= '<p>' . $item['summary'] . '</p>';
1315 }
1316 }
1317 $ports[$key]['cve_summary'] = $summary;
1318 }
1319 return $ports;
1320 }
1321
1322
1323 /**
1324 * Reassembling the quarantine logs.
1325 *
1326 * @param array $logs_
1327 * Quarantine logs from WebTotem.
1328 *
1329 * @return array
1330 * Reassembled array of logs.
1331 */
1332 public static function getQuarantineLogs(array $logs_) {
1333 $logs = [];
1334 foreach ($logs_ as $key => $log) {
1335 $logs[$key] = $log;
1336 $logs[$key]['path'] = urldecode($log['path']);
1337 $logs[$key]['date'] = self::dateFormatter($log['date']);
1338 }
1339
1340 return $logs;
1341 }
1342
1343 /**
1344 * Generate an array of IP address data.
1345 *
1346 * @param array $data
1347 * IP addresses data from WebTotem.
1348 * @param string $list_name
1349 * Allow or deny list.
1350 *
1351 * @return array
1352 * Returns array of data.
1353 */
1354 public static function getIpList(array $data, $list_name) {
1355 $list = [];
1356 foreach ($data as $item) {
1357 $list[] = [
1358 'ip' => $item['ip'],
1359 'id' => $item['id'],
1360 'created_at' => self::dateFormatter($item['createdAt']),
1361 'list_name' => $list_name,
1362 ];
1363 }
1364 return $list;
1365 }
1366
1367 /**
1368 * Generate an array of URL address data.
1369 *
1370 * @param array $data
1371 * URL addresses data from WebTotem.
1372 *
1373 * @return array
1374 * Returns array of data.
1375 */
1376 public static function getUrlAllowList(array $data) {
1377 $list = [];
1378 foreach ($data as $item) {
1379 $list[] = [
1380 'url' => $item['url'],
1381 'id' => $item['id'],
1382 'created_at' => self::dateFormatter($item['createdAt']),
1383 'list_name' => 'url_allow',
1384 ];
1385 }
1386 return $list;
1387 }
1388
1389 /**
1390 * Convert IP list to be transferred to WebTotem.
1391 *
1392 * @param string $data
1393 * IP list.
1394 *
1395 * @return string
1396 * Returns the converted string.
1397 */
1398 public static function convertIpListForApi($data) {
1399 if (!$data) {
1400 return FALSE;
1401 }
1402
1403 $ips = preg_split("/(?(?=[\s,])[^.]|^$)/", $data);
1404
1405 if (is_array($ips)) {
1406 $ips_ = '[';
1407 foreach ($ips as $ip) {
1408 if (!empty($ip)) {
1409 $ips_ .= '"' . $ip . '",';
1410 }
1411 }
1412 $ips_ = substr($ips_, 0, -1);
1413 $ips_ .= ']';
1414 }
1415 else {
1416 $ips_ = '"' . $ips . '"';
1417 }
1418
1419 return $ips_;
1420 }
1421
1422 /**
1423 * Get data of the country with the most attacks.
1424 *
1425 * @param array $map
1426 * Map logs from WebTotem.
1427 *
1428 * @return array
1429 * Returns array of data.
1430 */
1431 public static function getMostAttacksData($map) {
1432
1433 if ($map) {
1434 $most_attacks_key = array_search(max(array_column($map, 'attacks')), array_column($map, 'attacks'));
1435 $total_attacks = array_sum(array_column($map, 'attacks'));
1436
1437 $data['percent'] = ($total_attacks) ? round($map[$most_attacks_key]['attacks'] / $total_attacks * 100) : 0;
1438 $data['country'] = self::getCountryName($map[$most_attacks_key]['country']);
1439 $data['offset'] = 176 / 100 * (100 - $data['percent']);
1440
1441 return $data;
1442 }
1443
1444 return ['percent' => 0, 'country' => FALSE, 'offset' => 0];
1445 }
1446
1447 /**
1448 * Get data on the three most attacking countries.
1449 *
1450 * @param array $map
1451 * Map logs from WebTotem.
1452 *
1453 * @return array
1454 * Returns array of data.
1455 */
1456 public static function getTreeMostAttacksData($map) {
1457 $total_attacks = array_sum(array_column($map, 'attacks'));
1458
1459 if ($map) {
1460 array_multisort (array_column($map, 'attacks'), SORT_DESC, $map);
1461 $data = array_slice($map, 0, 3);
1462
1463 foreach ($data as $key => $value){
1464 $data[$key]['percent'] = round($value['attacks'] / $total_attacks * 100);
1465 $data[$key]['country'] = self::getCountryName($value['country']);
1466 }
1467
1468 return $data;
1469 }
1470
1471 return [];
1472 }
1473
1474 /**
1475 * Getting the country name by two-letter code.
1476 *
1477 * @param string $key
1478 * Two-letter code.
1479 *
1480 * @return string
1481 * Returns country name.
1482 */
1483 public static function getCountryName($key) {
1484 $countries = WebTotemCountryManager::getStandardList();
1485 $key = (string) $key;
1486
1487 return (array_key_exists($key, $countries)) ? $countries[$key] : $key;
1488 }
1489
1490 /**
1491 * Get configs data.
1492 *
1493 * @param array $array
1494 * Original array.
1495 * @param string $key
1496 * The key to use as an index.
1497 *
1498 * @return array
1499 * Configs data array.
1500 */
1501 public static function getConfigsData(array $array, $key) {
1502 $configs = self::arrayMapIndex($array, $key);
1503
1504 foreach ($configs as $service => $config){
1505 $configs[$service]['checked'] = ($config['isActive']) ? 'checked' : '';
1506 $configs[$service]['notification_checked'] = (isset($config['notifications']) && $config['notifications']) ? 'checked' : '';
1507 }
1508
1509 return $configs;
1510 }
1511
1512 /**
1513 * Get waf setting data.
1514 *
1515 * @param array $settings
1516 * Original array.
1517 *
1518 * @return array
1519 * Configs data array.
1520 */
1521 public static function getWafSettingData(array $settings) {
1522 $_settings['gdn']['checked'] = (isset($settings['gdn']) && !$settings['gdn']) ? '' : 'checked';
1523 $_settings['dos'] = [
1524 'checked' => (isset($settings['dosProtection']) && !$settings['dosProtection']) ? '' : 'checked',
1525 'visually' => (isset($settings['dosProtection']) && !$settings['dosProtection']) ? 'visually-hidden' : '',
1526 ];
1527 $_settings['dos_limit'] = $settings['dosLimit'] ?: 1000;
1528
1529 $_settings['login_attempt'] = [
1530 'checked' => (isset($settings['loginAttemptsProtection']) && !$settings['loginAttemptsProtection']) ? '' : 'checked',
1531 'visually' => (isset($settings['loginAttemptsProtection']) && !$settings['loginAttemptsProtection']) ? 'visually-hidden' : '',
1532 ];
1533 $_settings['login_attempt_limit'] = $settings['loginAttemptsLimit'] ?: 20;
1534
1535 return $_settings;
1536 }
1537
1538 /**
1539 * Get plugin settings data.
1540 *
1541 * @return array
1542 * Configs data array.
1543 */
1544 public static function getPluginSettingsData() {
1545
1546 $settings = WebTotemOption::getPluginSettings();
1547 $_settings = $settings;
1548
1549 $_settings['hide_wp_version_checked'] = (array_key_exists('hide_wp_version', $settings) and $settings['hide_wp_version']) ? 'checked' : '';
1550 $_settings['recaptcha_checked'] = (array_key_exists('recaptcha', $settings) and $settings['recaptcha']) ? 'checked' : '';
1551 $_settings['two_factor_checked'] = (array_key_exists('two_factor', $settings) and $settings['two_factor']) ? 'checked' : '';
1552
1553 return $_settings;
1554 }
1555
1556 /**
1557 * Replace array indexes by key.
1558 *
1559 * @param array $array
1560 * Original array.
1561 * @param string $key
1562 * The key to use as an index.
1563 *
1564 * @return array
1565 * Returns a new array.
1566 */
1567 public static function arrayMapIndex(array $array, $key) {
1568 $new_array = [];
1569 foreach ($array as $item) {
1570 if (array_key_exists($key, $item)) {
1571 $new_array[$item[$key]] = $item;
1572 }
1573 }
1574 return $new_array;
1575 }
1576
1577 /**
1578 * Generate random string.
1579 *
1580 * @param int $length
1581 * The required length of the string.
1582 *
1583 * @return string
1584 * Returns random string.
1585 */
1586 public static function generateRandomString( int $length = 10): string {
1587 $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-';
1588 $charactersLength = strlen($characters);
1589 $randomString = '';
1590 for ($i = 0; $i < $length; $i++) {
1591 $randomString .= $characters[rand(0, $charactersLength - 1)];
1592 }
1593 return $randomString;
1594 }
1595
1596 /**
1597 * Encodes the less than, greater than, ampersand,double quote
1598 * and single quote characters. Will never double encode entities.
1599 *
1600 * @see https://developer.wordpress.org/reference/functions/esc_attr/
1601 *
1602 * @param string $text
1603 * The text which is to be encoded.
1604 *
1605 * @return string
1606 * The encoded text with HTML entities.
1607 */
1608 public static function escape($text = '') {
1609 return esc_attr($text);
1610 }
1611
1612 /**
1613 * Throw generic exception.
1614 *
1615 * @throws Exception
1616 *
1617 * @param string $message
1618 * Error or information message.
1619 * @param string $type
1620 * Either info or error.
1621 *
1622 * @return bool
1623 * False all the time, used for debug.
1624 */
1625 public static function throwException($message, $type = 'error') {
1626 if (defined('WTOTEM_THROW_EXCEPTIONS') && WTOTEM_THROW_EXCEPTIONS === true && is_string($message) ) {
1627 $message = str_replace( '<strong>WebTotem:</strong>', ($type === 'error' ? __('Error:', 'wtotem') : __('Info:', 'wtotem')), $message );
1628 throw new Exception($message, $type === 'error' ? 157 : 333);
1629 }
1630 return false;
1631 }
1632
1633 /**
1634 * Get audit logs data
1635 *
1636 * @return array
1637 */
1638 public static function getAuditLogs($data, $dates_count) {
1639 $logs = [];
1640 foreach ($data as $datum){
1641 $date_time = strtotime($datum['created_at']);
1642 $date = date_i18n('M j, Y', $date_time);
1643
1644 $logs[$date]['date'] = $date;
1645 $logs[$date]['count'] = $dates_count[$date];
1646 $logs[$date]['logs'][] = [
1647 'time' => date_i18n('H:i', $date_time),
1648 'user_name' => $datum['user_name'],
1649 'status' => $datum['status'],
1650 'title' => $datum['title'],
1651 'event' => $datum['event'],
1652 'description' => $datum['description'],
1653 'ip' => $datum['ip'],
1654 'viewed' => (int) !$datum['viewed']
1655 ];
1656 }
1657 return $logs;
1658 }
1659
1660 /**
1661 * Get confidential files data
1662 *
1663 * @return array
1664 */
1665 public static function getConfidentialFiles($data) {
1666 foreach ($data as $key => $datum){
1667 $data[$key]['modified_at'] = date_i18n('M j, Y \/ H:i', strtotime($datum['modified_at']));
1668 $data[$key]['size'] = self::humanFilesize($datum['size']);
1669 $data[$key]['name'] = urldecode($datum['name']);
1670 $data[$key]['path'] = urldecode($datum['path']);
1671 }
1672 return $data;
1673 }
1674
1675 /**
1676 * Building navigation and forming a template
1677 *
1678 * @param integer $limit
1679 * number of entries per 1 page
1680 * @param integer $count_all
1681 * total number of all entries
1682 * @param integer $currentPage
1683 * the number of the page being viewed
1684 * @param integer $nextPrev
1685 * Show the "Forward" and "Back" buttons
1686 * @return mixed
1687 * Generated navigation template ready for output
1688 */
1689 public static function paginationBuild($limit, $count_all, $currentPage = 1, $nextPrev = true) {
1690 if( $limit < 1 OR $count_all <= $limit ) return '';
1691 $count_pages = ceil( $count_all / $limit );
1692
1693 $spread = 3;
1694 $separator = "<i>...</i>";
1695 $wrap = "<div class=\"wtotem_pagination\">{pages}</div>";
1696
1697 $nextTitle = '';
1698 $prevTitle = '';
1699
1700 $currentPage = intval( $currentPage );
1701 if( $currentPage < 1 ) $currentPage = 1;
1702
1703 $shift_start = max( $currentPage - $spread, 2 );
1704 $shift_end = min( $currentPage + $spread, $count_pages-1 );
1705 if( $shift_end < $spread * 2 ) {
1706 $shift_end = min( $spread * 2, $count_pages-1 );
1707 }
1708 if( $shift_end == $count_pages - 1 AND $shift_start > 3 ) {
1709 $shift_start = max( 3, min( $count_pages - $spread * 2 + 1, $shift_start ) );
1710 }
1711
1712 $list = self::getPaginationItem( 1, $currentPage );
1713
1714 if ($shift_start == 3) {
1715 $list .= self::getPaginationItem( 2, $currentPage );
1716 } elseif ( $shift_start > 3 ) {
1717 $list .= $separator;
1718 }
1719
1720 for( $i = $shift_start; $i <= $shift_end; $i++ ) {
1721 $list .= self::getPaginationItem( $i, $currentPage );
1722 }
1723
1724 $last_page = $count_pages - 1;
1725 if( $shift_end == $last_page-1 ){
1726 $list .= self::getPaginationItem( $last_page, $currentPage );
1727 } elseif( $shift_end < $last_page ) {
1728 $list .= $separator;
1729 }
1730
1731 $list .= self::getPaginationItem( $count_pages, $currentPage );
1732
1733 if( $nextPrev ) {
1734 $list = self::getPaginationItem(
1735 $currentPage > 1 ? $currentPage - 1 : 0,
1736 $currentPage,
1737 $nextTitle,
1738 true )
1739 . $list
1740 . self::getPaginationItem(
1741 $currentPage < $count_pages ? $currentPage + 1 : 0,
1742 $currentPage,
1743 $prevTitle,
1744 true
1745 );
1746 }
1747
1748 return str_replace( "{pages}", $list, $wrap );
1749 }
1750
1751 /**
1752 * Button/Link Formation
1753 * @param int $page_num
1754 * page number
1755 * @param string $currentPage
1756 * current page
1757 * @param string $page_name
1758 * if specified, the text will be displayed instead of the page number
1759 * @return string
1760 * span block with active page or link.
1761 */
1762 public static function getPaginationItem( $page_num, $currentPage, $page_name = '' ) {
1763 if($page_num === 0){return '';}
1764 $page_name = $page_name ?: $page_num;
1765
1766 if( $currentPage == $page_num ) {
1767 return "<span class=\"wtotem_pagination__number wtotem_pagination__number_active\">{$page_name}</span>";
1768 } else {
1769 return "<a href=\"#\" data-page=\"{$page_num}\" class=\"wtotem_pagination__number\">{$page_name}</a>";
1770 }
1771 }
1772
1773 /**
1774 * Get notifications array.
1775 *
1776 * @return array
1777 * Returns notifications array.
1778 */
1779 public static function getNotifications() {
1780
1781 $notifications_data = WebTotemOption::getNotificationsData();
1782 $notifications = [];
1783
1784 foreach ($notifications_data as $notification) {
1785 switch ($notification['type']) {
1786 case 'error':
1787 $image = 'alert-error.svg';
1788 $class = 'wtotem_alert__title_red';
1789 break;
1790
1791 case 'warning':
1792 $image = 'alert-warning.svg';
1793 $class = 'wtotem_alert__title_yellow';
1794 break;
1795
1796 case 'success':
1797 $image = 'alert-success.svg';
1798 $class = 'wtotem_alert__title_green';
1799 break;
1800
1801 case 'info':
1802 $image = 'info-blue.svg';
1803 $class = 'wtotem_alert__title_blue';
1804 break;
1805 }
1806
1807 $notifications[] = [
1808 "text" => $notification['notice'],
1809 "id" => self::generateRandomString(8),
1810 "type" => self::getStatusText($notification['type']),
1811 "type_raw" => $notification['type'],
1812 "image" => $image,
1813 "class" => $class,
1814 ];
1815 }
1816
1817 return $notifications;
1818 }
1819
1820 /**
1821 * Get current agent installation statuses.
1822 *
1823 * @param array $agents_statuses
1824 * Agents statuses got from the WebTotem API.
1825 *
1826 * @return array
1827 * Returns an array with agent installation status data.
1828 */
1829 public static function getAgentsStatuses(array $agents_statuses) {
1830 $agents = ['am', 'waf', 'av'];
1831 $installing_statuses = [
1832 'not_installed',
1833 'installing',
1834 'internal_error',
1835 'update_error',
1836 'config_error',
1837 'session_error',
1838 ];
1839
1840 $process_statuses = [];
1841 $option_statuses = [];
1842
1843 foreach ($agents as $agent) {
1844 $status = WebTotemAgentManager::checkInstalledService($agent);
1845 $option_statuses[$agent] = $status['option_status'] ?: FALSE;
1846
1847 if ($agent == 'am') {
1848 if ($status['file_status']) {
1849 $process_statuses[$agent] = 'installed';
1850 }
1851 else {
1852 $process_statuses[$agent] = 'failed';
1853 }
1854 }
1855 else {
1856 if ($status['file_status']) {
1857 if (in_array($agents_statuses[$agent], $installing_statuses)) {
1858 $process_statuses[$agent] = 'installing';
1859 }
1860 elseif ($agents_statuses[$agent] == 'agent_not_available') {
1861 $process_statuses[$agent] = 'failed';
1862 }
1863 else {
1864 $process_statuses[$agent] = 'installed';
1865 }
1866 }
1867 else {
1868 $process_statuses[$agent] = 'installing';
1869 }
1870 }
1871 }
1872
1873 return [
1874 'process_statuses' => $process_statuses,
1875 'option_statuses' => $option_statuses,
1876 ];
1877 }
1878
1879 }
1880