PluginProbe
WebTotem Security / 2.4.18
WebTotem Security v2.4.18
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 2.2.4 All 109 releases
wt-security / lib / Helper.php

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

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