# wt-security/2.4.13/lib/Helper.php

WebTotem Security, version 2.4.13. 1,441 lines.

- Page: https://pluginprobe.com/plugins/wt-security/2.4.13/code/lib/Helper.php
- Raw: https://pluginprobe.com/plugins/wt-security/2.4.13/raw/lib/Helper.php
- Modified: 2022-08-23T11:56:58+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/wt-security/2.4.13/code/lib/Helper.php#L10-L20`.

```php
<?php

if (!defined('WEBTOTEM_INIT') || WEBTOTEM_INIT !== true) {
	if (!headers_sent()) {
		header('HTTP/1.1 403 Forbidden');
	}
	exit(1);
}

/**
 * WebTotem Base class for Wordpress.
 */
class WebTotem {

	/**
	 * Returns an URL from the admin dashboard.
	 *
	 * @param  string $url
	 *    Optional trailing of the URL.
	 * @return string
	 *    Full valid URL from the admin dashboard.
	 */
	public static function adminURL($url = '') {
		if (self::isMultiSite() and is_super_admin()) {
			return network_admin_url($url);
		}
		return admin_url($url);
	}

	/**
	 * Define role of current user.
	 *
	 */
	public static function getUserRole() {

		if (defined('WEBTOTEM_USER_ROLE')) {
			return true;
		}
		$current_user = wp_get_current_user();
		if ( !($current_user instanceof WP_User) ){
			$user_role = 0;
		} else {
			$roles = $current_user->roles;

			// TODO добавить суперадмина
			if(in_array('administrator', $roles)){
				$user_role = 1;
			} else {
				$user_role = 0;
			}
		}

		define( 'WEBTOTEM_USER_ROLE', $user_role );

		return true;
	}

	/**
	 * Check whether the current site is working as a multi-site instance.
	 *
	 * @return bool
	 *    Either TRUE or FALSE in case WordPress is being used as a multi-site instance.
	 */
	public static function isMultiSite() {
		return (bool) (function_exists('is_multisite') && is_multisite());
	}

	/**
	 * Returns the md5 hash representing the content of a file.
	 *
	 * @param  string $file
	 *    Relative path to the file.
	 * @return string
	 *    Seven first characters in the hash of the file.
	 */
	public static function fileVersion($file = '') {
		return substr(md5_file(WEBTOTEM_PLUGIN_PATH . '/' . $file), 0, 7);
	}

	/**
	 * Returns the md5 hash representing the content of a file.
	 *
	 * @param  string $image
	 *    Relative path to the file.
	 * @return string
	 *    Seven first characters in the hash of the file.
	 */
	public static function getImagePath($image) {
		return WEBTOTEM_URL. '/includes/img/' . $image;
	}

	/**
	 * Returns user IP address.
	 *
	 * @return string
	 *    Returns user IP address.
	 */
	public static function getUserIP() {
		$arr =  [
			'HTTP_CLIENT_IP',
			'HTTP_X_FORWARDED_FOR',
			'HTTP_X_FORWARDED',
			'HTTP_X_CLUSTER_CLIENT_IP',
			'HTTP_FORWARDED_FOR',
			'HTTP_FORWARDED',
			'HTTP_CF_CONNECTING_IP',
			'REMOTE_ADDR'
		];

		foreach ($arr as $key){
			if (array_key_exists($key, $_SERVER) === true) {
				foreach (explode(',', $_SERVER[$key]) as $ip) {
					$ip = trim($ip);
					$ip = filter_var($ip, FILTER_VALIDATE_IP);
					if (!empty($ip)) {
						return $ip;
					}
				}
			}
		}
		return false;
	}

	/**
   * Check that the training period has passed for the firewall.
   *
   * @param string $created_at
   *   Date when the waf configuration was created.
   *
   * @return bool
   *   Returns boolean.
   */
  public static function isWafTraining($created_at) {
  	if($created_at) {
		  $when_waf_trained = strtotime('+2 day', strtotime($created_at));
		  $today = strtotime('today');

		  return ($when_waf_trained < $today) ? FALSE : TRUE;
	  }
	  return FALSE;
  }

  /**
   * Converting a date to the appropriate format.
   *
   * @param string $date
   *   Date in any format.
   * @param string $format
   *   The format to which you want to convert the date.
   *
   * @return string
   *   Returns converted Date.
   */
  public static function dateFormatter($date, $format = 'M j, Y \/ H:i') {
    if (!$date) {
      return __('Unknown', 'wtotem');
    }

    $time_zone = WebTotemOption::getOption('time_zone_offset');
    $user_time = ($time_zone) ? strtotime($time_zone . 'hours', strtotime($date)) : strtotime($date);

    return date_i18n($format, $user_time);
  }

  /**
   * Get theme mode data.
   *
   * @return array
   *   Returns array with current theme data.
   */
  public static function getThemeMode() {
    $theme_mode = WebTotemOption::getSessionOption('theme_mode');
    return [
      "is_dark_mode" => $theme_mode == 'dark' ? 'wtotem_theme—dark' : '',
      "dark_mode_checked" => $theme_mode == 'dark' ? 'checked' : '',
    ];
  }

	/**
	 * Get current user language.
	 *
	 * @return string
	 *   Returns current language in 2-letter abbreviations
	 */
	public static function getLanguage() {
		$current_language = substr(get_bloginfo('language'), 0,2);
		$language = (in_array($current_language,['ru','en','pl'])) ? $current_language : 'en' ;
		return $language;
	}

  /**
   * Converting a date to the appropriate format.
   *
   * @param string|array $days
   *   Number of days or period to convert.
   *
   * @return array
   *   Returns an array of two values "from" and "to"
   */
  public static function getPeriod($days) {

    if (!$days) {
      $days = 30;
    }

    switch ($days) {

      case is_array($days):
        $to = $days[1] ?: $days[0];
        $period = [
          'from' => strtotime(date('Y-m-d 00:00:01', strtotime($days[0]))),
          'to' => strtotime(date('Y-m-d 23:59:59', strtotime($to))),
        ];
        break;

      case $days <= 1:
        $period = [
          'from' => strtotime('-24 hours'),
          'to' => time(),
        ];
        break;

      default:
        $period = [
          'from' => time() - ($days * 86400),
          'to' => time(),
        ];
    }

    return $period;
  }

	/**
	 * Convert an array to a string with quotation marks.
	 *
	 * @param array $array
	 *   Data array.
	 *
	 * @return string
	 *   Array of data converted to string.
	 */
	public static function convertArrayToString($array) {
		if(empty($array)){
			return '';
		}
		return '"' . implode('","', $array) . '"';
	}

  /**
   * Converting the response to a readable form.
   *
   * @param string $message
   *   Message response from the API server to the request.
   *
   * @return string|bool
   *   Returns a message.
   */
  public static function messageForHuman($message) {

    $definition = $message;

    switch ($message) {
      case 'HOSTS_LIMIT_EXCEEDED':
        $definition = __('Limit of adding sites exceeded.', 'wtotem');
        break;

      case 'USER_ALREADY_REGISTERED':
        $definition = __('A user with this email already exists.', 'wtotem');
        break;

      case 'DUPLICATE_HOST':
        $definition = __('Duplicate host', 'wtotem');
        break;

      case 'INVALID_DOMAIN_NAME':
        $definition = __('Invalid Domain Name', 'wtotem');
        break;
	    default:
		    $definition = str_replace("_", " ", $definition);
		    $definition = ucfirst(strtolower($definition));

    }
    return $definition;
  }

  /**
   * Get the data associated with the status.
   *
   * @param string $status
   *   Module or agent status.
   *
   * @return array
   *   Returns an array with status data.
   */
  public static function getStatusData($status) {
    $path = self::getImagePath('');
	  $status = ($status == "installed") ? 'working' : $status;

    switch ($status) {

      case 'clean':
      case 'up':
      case 'installed':
      case 'working':
        $status_data = [
          'class' => 'is--status--ok',
          'image' => $path . 'check-mark.svg',
          'icon' => $path . 'icon_success_status.svg',
        ];
        break;

      case 'pending':
        $status_data = [
          'class' => 'is--status--pending',
          'image' => $path . 'loading.svg',
          'icon' => $path . 'alert-warning.svg',
        ];
        break;

      case 'pause':
      case 'modified':
        $status_data = [
          'class' => 'is--status--pending',
          'image' => $path . 'warning.svg',
          'icon' => $path . 'alert-warning.svg',
        ];
        break;

      case 'expired':
      case 'no_cert':
      case 'expires':
      case 'open_ports':
      case 'not_supported':
      case 'not_registered':
        $status_data = [
          'class' => 'is--status--warning',
          'image' => $path . 'warning.svg',
          'icon' => $path . 'alert-warning.svg',
        ];
        break;

      case 'invalid':
      case 'error':
      case 'down':
      case 'expires_today':
      case 'infected':
      case 'deface':
      case 'not_installed':
        $status_data = [
          'class' => 'is--status--error',
          'image' => $path . 'warning.svg',
          'icon' => $path . 'alert-warning.svg',
        ];
        break;

      default:
        $status_data = [
          'class' => 'is--status--pending',
          'image' => $path . 'warning.svg',
          'icon' => $path . 'alert-warning.svg',
        ];
    }
    $status_data['name'] = $status;
    $status_data['text'] = self::getStatusText($status);
    $status_data['tooltips'] = self::getTooltips($status);

    return $status_data;
  }

  /**
   * Get a readable status text.
   *
   * @param string $status
   *   Module or agent status.
   *
   * @return string
   *   Returns the status text in the current language.
   */
  public static function getStatusText($status) {
    $statuses = [
      'warning' => __('Warning', 'wtotem'),
      'error' => __('Error', 'wtotem'),
      'success' => __('Success', 'wtotem'),
      'info' => __('Info', 'wtotem'),
      'invalid' => __('Invalid', 'wtotem'),
      'ok' => __('Everything is OK', 'wtotem'),
      'expired' => __('Expired', 'wtotem'),
      'expires' => __('Expires', 'wtotem'),
      'expires_today' => __('Expires today', 'wtotem'),
      'missing' => __('Missing', 'wtotem'),
      'active' => __('Active', 'wtotem'),
      'inactive' => __('Inactive', 'wtotem'),
      'pending' => __('Pending', 'wtotem'),
      'pause' => __('Disabled', 'wtotem'),
      'available' => __('Available', 'wtotem'),
      'not_supported' => __('Not supported', 'wtotem'),
      'not_registered' => __('Not registered', 'wtotem'),
      'unsupported' => __('Unsupported', 'wtotem'),
      'clean' => __('Clean', 'wtotem'),
      'clear' => __('Clear', 'wtotem'),
      'blacklisted' => __('Infected', 'wtotem'),
      'miner_detected' => __('Infected', 'wtotem'),
      'deface' => __('Deface', 'wtotem'),
      'modified' => __('Modified', 'wtotem'),
      'detected' => __('Detected', 'wtotem'),
      'open_ports' => __('Open ports', 'wtotem'),
      'blocked' => __('Blocked', 'wtotem'),
      'connected' => __('Connected', 'wtotem'),
      'attacks_detected' => __('Attacks detected', 'wtotem'),
      'signature_found' => __('Signature found', 'wtotem'),
      'file_changes' => __('File changes', 'wtotem'),
      'no_cert' => __('No cert', 'wtotem'),
      'down' => __('Down', 'wtotem'),
      'up' => __('Up', 'wtotem'),
      'infected' => __('Infected', 'wtotem'),
      'not_installed' => __('Need to install', 'wtotem'),
      'agent_not_available' => __('Agent not available', 'wtotem'),
      'update_error' => __('Update error', 'wtotem'),
      'session_error' => __('Session Error', 'wtotem'),
      'internal_error' => __('Internal Error', 'wtotem'),
      'installing' => __('Installing', 'wtotem'),
      'installed' => __('Installed', 'wtotem'),
      'working' => __('Working', 'wtotem'),
      "critical" => __('Critical', 'wtotem'),
      "deleted" => __('Deleted', 'wtotem'),
      "changed" => __('Changed', 'wtotem'),
      "new" => __('New', 'wtotem'),
      "scanned" => __('Scanned', 'wtotem'),
      "quarantine" => __('In quarantine', 'wtotem'),
    ];

    return (array_key_exists($status, $statuses)) ? $statuses[$status] : $status;
  }

  /**
   * Get tooltips text for status.
   *
   * @param string $status
   *   Module or agent status.
   *
   * @return string
   *   Returns the status tooltip in the current language.
   */
  public static function getTooltips($status) {
    $tooltips = [
      'invalid' => __('Invalid -The certificate is invalid. Please, make sure that relevant certificate details filled correctly.', 'wtotem'),
      'expired' => __('Expired - The certificate has expired. Connection is not secure. Please, renew it.', 'wtotem'),
      'expires' => __('Expires - The certificate expires soon. Please, take actions.', 'wtotem'),
      'expires_today' => __('Expires today - The certificate expires today. Please, take actions.', 'wtotem'),
      'error' => __("Error - Something went wrong. Please, contact us, we'll fix the problem.", 'wtotem'),
      'pending' => __('Pending - System processes your website. Data will be available soon.', 'wtotem'),
      'pause' => __('Pause - The module is paused.', 'wtotem'),
      'clean' => __('Everything is OK - Nothing to worry about. Everything is alright.', 'wtotem'),
      'deface' => __("Deface - Website hacked. Please, contact us, we'll fix the problem.", 'wtotem'),
      'open_ports' => __('Open ports - Open ports detected. Your website is vulnerable to attacks.', 'wtotem'),
      'blocked' => __('Blocked - The module is blocked due to billing issues.', 'wtotem'),
      'no_cert' => __("No cert - You don't have SSL certificate. We recommend you to install it for security concerns.", 'wtotem'),
      'down' => __('Down - The website is not available for visitors.', 'wtotem'),
      'up' => __('Up - The website is available for visitors.', 'wtotem'),
      'infected' => __('Infected - The website site is blacklisted and may have infected files. Please, check antivirus module.', 'wtotem'),
      'installing' => __('It means that the agent installation is in progress. Usually, it takes up to one hour.', 'wtotem'),
      'agent_not_available' => __('We cannot locate the agent right now.', 'wtotem'),
      'update_error' => __('It seems that your agent failed to update due to permissions restrictions.', 'wtotem'),
      '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'),
      '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'),
      'working' => __('Everything is alright.', 'wtotem'),
      'installed' => __('Everything is alright.', 'wtotem'),
      'not_installed' => __('You need to install agent manager to activate antivirus and firewall.', 'wtotem'),
    ];

    return (array_key_exists($status, $tooltips)) ? $tooltips[$status] : '';
  }

	/**
	 * Converting site data.
	 *
	 * @param array $data
	 *   Sites data from WebTotem.
	 *
	 * @return array
	 *   Converted data.
	 */
	public static function allSitesData($data) {

		$local_sites = get_sites();
		$main_host = WebTotemOption::getMainHost();
		$domains = [];

		foreach ($local_sites as $site){
			$domain = untrailingslashit($site->domain . $site->path);
			$domains[$domain] = $domain;
		}

		$sites = [];
		if(array_key_exists('edges', $data)){
			foreach ($data['edges'] as $site) {
				$site = $site['node'];
				// Take sites only from the multisite network.
				if(array_key_exists($site['hostname'], $domains)) {
					unset($domains[$site['hostname']]);
					$sites[] = [
						'hostname' => $site['hostname'],
						'title' => $site['title'],
						'main_host' => $main_host['id'] == $site['id'],
						'host_id' => $site['id'],
						'url' => admin_url('admin.php?page=wtotem_dashboard&hid=' . $site['id']),
						'firewall' => [
							'status' => self::getStatusData($site['firewall']['status']),
						],
						'antivirus' => [
							'status' => self::getStatusData($site['antivirus']['status']),
						],
						'stacks' => self::getStacksData($site['maliciousScript']['stack']),
						'services' => self::getSiteServicesData($site),
					];
				}
			}

		}
		return $sites;
	}

	/**
	 * Converting stacks data.
	 *
	 * @param array $stacks
	 *   Stacks data from WebTotem.
	 *
	 * @return array
	 *   Converted data.
	 */
	protected static function getStacksData($stacks) {
		$apps = file_get_contents(WEBTOTEM_PLUGIN_PATH . '/includes/js/apps.json');
		$apps = json_decode($apps, true);

		$path = 'https://assets.wtotem.net/images/apps/';
		$defaultIcon = WEBTOTEM_URL . '/includes/img/defaultTechnologiesIcon.svg';

		$stackList = array_slice($stacks, 0,3);
		$list = [];
		foreach ($stackList as $key => $stack){
			$list[$key] = [
				'name' => $stack['name'],
				'icon' => $path . ($apps[$stack['name']]['icon'] ?: $defaultIcon),
			];
		}

		if(count($stacks) <= 3){
			$other['count'] = 0;
			$other['names'] = [];
		} else {
			$otherStacks = array_slice($stacks, 3);
			$other['count'] = count($otherStacks);
			foreach ($otherStacks as $stack){
				$other['names'][] = $stack['name'];
			}
		}
		if($other['names']){
			$other['names'] = implode(",", $other['names']);
		}
		return  ['list' => $list, 'other' => $other];
	}

	/**
	 * Converting services data.
	 *
	 * @param $data
	 *   Site data from WebTotem.
	 *
	 * @return array
	 *   Converted data.
	 */
	protected static function getSiteServicesData($data) {

		$services = [
			'ssl' => 'ssl',
			'availability' => 'wa',
			'reputation' => 'rc',
			'ports' => 'ps',
			'deface' => 'dc',
			'domain' => 'dec',
		];

		$list = [];
		$other['count'] = 0;
		$other['names'] = [];

		foreach ($services as $key => $service){
			if(array_key_exists($key, $data) and is_array($data[$key]) and array_key_exists('status', $data[$key])){
				$status = self::getServiceStatus($data[$key]['status']);

				if(in_array($status['color'], ['red', 'yellow'])){
					if(count($list) < 2){
						$color = $status['color'] == 'red' ? 'white/' : '';

						$list[$key] = [
							'status' => $status,
							'icon' => 'services/'. $color . $service . '.svg',
							'name' => self::getServiceName( $service ),
						];
					} else {
						$other['names'][] = self::getServiceName( $service );
						$other['count']++;
					}
				}

			}
		}
		if($other['names']){
			$other['names'] = implode(",", $other['names']);
		}
		return ['list' => $list, 'other' => $other];
	}

	/**
	 * Get the data associated with the status.
	 *
	 * @param string $status
	 *   Module or agent status.
	 *
	 * @return array
	 *   Returns an array with status data.
	 */
	public static function getServiceStatus($status) {
		switch ($status) {

			case 'expired':
			case 'invalid':
			case 'error':
			case 'expires_today':
			case 'down':
			case 'infected':
			case 'deface':
			case 'not_installed':
			case 'quarantine':
				$status_data = [
					'color' => 'red',
				];
				break;

			case 'no_cert':
			case 'expires':
			case 'open_ports':
			case 'modified':
			case 'not_supported':
			case 'not_registered':
			case 'blocked':
			case 'pause':
			case 'internal_error':
			case 'update_error':
			case 'config_error':
			case 'agent_not_available':
			case 'session_error':
				$status_data = [
					'color' => 'yellow',
				];
				break;

			case 'clean':
			case 'installed':
			case 'up':
			case 'scanned':
			case 'working':
				$status_data = [
					'color' => 'green',
				];
				break;

			case 'deleted':
        $status_data = [
	        'color' => 'black',
        ];
        break;

			case 'installing':
			case 'pending':
			default:
				$status_data = [
					'color' => 'gray',
				];
				break;

		}

		return $status_data;
	}

	/**
	 * Get the translation of service.
	 *
	 * @param $service
	 *   Service short name.
	 *
	 * @return string
	 *   Translation of service.
	 */
	public static function getServiceName($service){
		$services = [
			"wa" => __('Availability', 'wtotem'),
			"rc" => __('Reputation', 'wtotem'),
			"ssl" => 'SSL',
			"cms" => __('Technologies', 'wtotem'),
			"dc" => __('Deface', 'wtotem'),
			"ps" => __('Ports', 'wtotem'),
			"waf" => __('Firewall', 'wtotem'),
			"av" => __('Antivirus', 'wtotem'),
			"dec" => __('Domain', 'wtotem'),
		];
		return $services[$service];
	}

  /**
   * Get reports with modules list.
   *
   * @param array $edges
   *   Data on generated reports.
   *
   * @return array
   *   Returns an array with converted data.
   */
  public static function getReports(array $edges) {
    $modulesLang = [
      'wa' => __('Availability log', 'wtotem'),
      'dc' => __('Deface log', 'wtotem'),
      'ps' => __('Port log', 'wtotem'),
      'rc' => __('Reputation log', 'wtotem'),
      'sc' => __('Evaluation log', 'wtotem'),
      'av' => __('Antivirus log', 'wtotem'),
      'waf' => __('Firewall log', 'wtotem'),
    ];

    $reports = [];

    foreach ($edges as $edge) {
      if (in_array(FALSE, $edge["node"])) {
        $arr = [];
        foreach ($edge["node"] as $module => $value) {
          if ($value == TRUE && array_key_exists($module, $modulesLang)) {
            $arr[] = $modulesLang[$module];
          }
        }
        $modules = implode(", ", $arr);
      }
      else {
        $modules = __('All modules', 'wtotem');
      }

      $reports[] = [
        'id' => $edge["node"]['id'],
        'modules' => $modules,
        'created_at' => self::dateFormatter($edge["node"]['createdAt']),
      ];
    }

    return $reports;
  }

  /**
   * Get reputation status description.
   *
   * @param string $status
   *   Reputation status.
   *
   * @return string
   *   Returns a description of the reputation status
   */
  public static function getReputationInfo($status) {
    switch ($status) {
      case 'clean':
        $data = __("Don't worry, your reputation is good", 'wtotem');
        break;

      case 'infected':
        $data = __('Oh, your reputation is bad', 'wtotem');
        break;

      default:
        $data = __('Information is being updated', 'wtotem');
    }
    return $data;
  }

  /**
   * Get blacklists entries counts.
   *
   * @param string $status
   *   Reputation status.
   * @param array $virus_list
   *   Sources where the site can be blacklisted.
   *
   * @return int
   *   Number of references in blacklists.
   */
  public static function blacklistsEntries($status, array $virus_list) {
    $count = 0;
    if ($status != "clean") {
      foreach ($virus_list as &$list) {
        if (!empty($list['virus']['type'])) {
          $count++;
        }
      }
    }
    return $count;
  }

  /**
   * Classification of the rating in the letter grades.
   *
   * @param int $score
   *   Site rating from 1 to 100.
   *
   * @return array
   *   Returns an array of data.
   */
  public static function scoreGrading($score) {
    if ($score < 0 || $score > 100) {
      return ['grade' => '', 'color' => ''];
    }

    $scores = [
      100 => 'A+',
      90 => 'A',
      80 => 'A-',
      70 => 'B+',
      60 => 'B',
      50 => 'B-',
      35 => 'C+',
      20 => 'C',
      0 => 'C-',
    ];

    foreach ($scores as $key => $value) {
      if ($score >= $key) {
        $grade = $value;
        break;
      }
    }

    // Set a color depending on the grade.
    switch ($score) {
      case $score >= 80:
        $color = 'green';
        break;

      case $score >= 50:
        $color = 'orange';
        break;

      default:
        $color = 'red';
    }

    return ['grade' => $grade, 'color' => $color];
  }

  /**
   * Calculate the number of remaining days.
   *
   * @param string $date
   *   Expiry date.
   *
   * @return string
   *   Returns the number of days before the expiration date.
   */
  public static function daysLeft($date) {
    if ((int) $date === 0) {
      $days_left = 0;
    }
    else {
      $now = new \DateTime();
      $expiry_date = new \DateTime();
	    $timestamp = strtotime($date);
	    $expiry_date->setTimestamp($timestamp);
      $days_left = $expiry_date->diff($now)->format("%a");
    }
    return $days_left;
  }

  /**
   * Converting the firewall logs.
   *
   * @param array $logs_
   *   Firewall logs from WebTotem.
   *
   * @return array
   *   Converted array of logs.
   */
  public static function wafLogs(array $logs_) {
    $logs = [];
    foreach ($logs_ as $key => $log) {
      $log = $log['node'];

      $logs[$key]['ip'] = $log['ip'];
      $logs[$key]['request'] = htmlspecialchars(urldecode($log['request']));
      $logs[$key]['time'] = self::dateFormatter($log['time']);
      $logs[$key]['country_code'] = strtolower($log['country']);
      $logs[$key]['country'] = $log['location']['country']['nameEn'];
      $logs[$key]['blocked'] = $log['blocked'] ? __('Blocked IP', 'wtotem') : __('Not blocked', 'wtotem');
    }
    return $logs;
  }

  /**
   * Converting firewall data to json for a D3 chart.
   *
   * @param array $charts
   *   Charts data from WebTotem.
   *
   * @return array
   *   Returns the converted data for chart.
   */
  public static function generateWafChart(array $charts) {
    $sum = 0;
    foreach ($charts as $chart) {
      $sum += $chart['attacks'];
    }
    if ($sum == 0) {
      return ['chart' => FALSE, 'count_attacks' => 0, 'count_blocks' => 0];
    }

    // Get days count.
    $charts_ = $charts;
    $first = array_shift($charts_);
    $last = array_pop($charts_);
    $days = ceil((strtotime($last['time']) - strtotime($first['time'])) / 86400);

    // Set variables.
    $count_attacks = $count_blocks = 0;

    foreach ($charts as $chart) {
      if ($days <= 1) {
        $time_zone = WebTotemOption::getOption('time_zone_offset');
        $userTime = ($time_zone) ? strtotime($time_zone . ' hours', strtotime($chart['time'])) : strtotime($chart['time']);
      }
      if (($chart['attacks'] and $days == 2) or $days != 2) {
        $result[] = [
          'date' => ($days <= 1) ? date("Y-m-d H:00:00", $userTime) : date("Y-m-d", strtotime($chart['time'])),
          'count' => $chart['blocked'],
          'attacks' => $chart['attacks'],
          'blocked' => $chart['blocked'],
        ];
        $count_attacks += $chart['attacks'];
        $count_blocks += $chart['blocked'];
      }
    }

    if (!isset($result)) {
      return [
        'chart' => FALSE,
        'count_attacks' => 0,
        'count_blocks' => 0,
      ];
    }

    return [
      'chart' => json_encode($result),
      'count_attacks' => $count_attacks,
      'count_blocks' => $count_blocks,
      'days' => $days,
    ];
  }

  /**
   * Converting data to json for a D3 chart.
   *
   * @param array $charts
   *   Charts data from WebTotem.
   * @param int $days
   *   The number of days to build the chart.
   *
   * @return bool|string
   *   Returns the converted data for chart.
   */
  public static function generateChart(array $charts, $days = 7) {
    $sum = 0;
    foreach ($charts as $chart) {
      $sum += $chart['value'];
    }
    if ($sum == 0) {
      return FALSE;
    }

    $result = [];

    foreach ($charts as $chart) {
      if ($days <= 1) {
        $time_zone = WebTotemOption::getOption('time_zone_offset');
        $userTime = ($time_zone) ? strtotime($time_zone . 'hours', strtotime($chart['time'])) : strtotime($chart['time']);
      }
      $result[] = [
        'date' => ($days <= 1) ? date("Y-m-d H:00:00", $userTime) : date("Y-m-d", strtotime($chart['time'])),
        'value' => $chart['value'],
      ];
    }

    return json_encode($result, TRUE);
  }

  /**
   * Converting data to json for a D3 chart.
   *
   * @param array $data
   *   Charts data from WebTotem.
   *
   * @return array|bool
   *   Returns the converted data for chart.
   */
  public static function generateAttacksMapChart(array $data) {
    $attacks = [];
	  $countries = [];
	  $labels = [];
    foreach ($data as $value) {
      $attacks[] = $value['attacks'];
      $labels[] = self::getCountryName($value['country']);
	  $countries[] = $value['location']['country']['nameEn'];
    }
    $result = ['attacks' => $attacks, 'countries' => $countries, 'labels' => $labels];

    if (!$attacks) {
      return FALSE;
    }

    return json_encode($result, TRUE);
  }

  /**
   * Reassembling the antivirus logs.
   *
   * @param array $logs_
   *   Antivirus logs from WebTotem.
   *
   * @return array
   *   Reassembled array of logs.
   */
  public static function getAntivirusLogs(array $logs_) {
    $logs = [];
    foreach ($logs_ as $key => $log) {
      $log = $log['node'];

	    $file_info = new SplFileInfo(urldecode($log['filePath']));

      $log['original_path'] = $log['filePath'];
	    $log['file_path'] = $file_info->getPath() . '/';
	    $log['file_name'] = $file_info->getFilename();
      $log['time'] = self::dateFormatter($log['time']);
      $log['permissions_changed'] = $log['permissionsChanged'];
      $log['status'] = self::getStatusData($log['event']);
      $log['class'] = 'wt-text--green';

	    switch ($log['event']) {
		    case 'modified':
		    case 'quarantine':
			    $log['class'] = "wt-text--yellow";
			    break;

		    case 'deleted':
			    $log['class'] = "wt-text--light-gray";
			    break;

		    case 'infected':
			    $log['class'] = "wt-text--red";
			    break;
	    }

      $logs[$key] = $log;
    }
    return $logs;
  }

  /**
   * Reassembling the quarantine logs.
   *
   * @param array $logs_
   *   Quarantine logs from WebTotem.
   *
   * @return array
   *   Reassembled array of logs.
   */
  public static function getQuarantineLogs(array $logs_) {
    $logs = [];
    foreach ($logs_ as $key => $log) {
      $logs[$key] = $log;
      $logs[$key]['path'] = urldecode($log['path']);
      $logs[$key]['date'] = self::dateFormatter($log['date']);
    }

    return $logs;
  }

  /**
   * Generate an array of IP address data.
   *
   * @param array $data
   *   IP addresses data from WebTotem.
   * @param string $list_name
   *   Allow or deny list.
   *
   * @return array
   *   Returns array of data.
   */
  public static function getIpList(array $data, $list_name) {
    $list = [];
    foreach ($data as $item) {
      $list[] = [
        'ip' => $item['ip'],
        'id' => $item['id'],
        'created_at' => self::dateFormatter($item['createdAt']),
        'list_name' => $list_name,
      ];
    }
    return $list;
  }

  /**
   * Generate an array of URL address data.
   *
   * @param array $data
   *   URL addresses data from WebTotem.
   *
   * @return array
   *   Returns array of data.
   */
  public static function getUrlAllowList(array $data) {
    $list = [];
    foreach ($data as $item) {
      $list[] = [
        'url' => $item['url'],
        'id' => $item['id'],
        'created_at' => self::dateFormatter($item['createdAt']),
        'list_name' => 'url_allow',
      ];
    }
    return $list;
  }

  /**
   * Convert IP list to be transferred to WebTotem.
   *
   * @param string $data
   *   IP list.
   *
   * @return string
   *   Returns the converted string.
   */
  public static function convertIpListForApi($data) {
    if (!$data) {
      return FALSE;
    }

    $ips = preg_split("/(?(?=[\s,])[^.]|^$)/", $data);

    if (is_array($ips)) {
      $ips_ = '[';
      foreach ($ips as $ip) {
        if (!empty($ip)) {
          $ips_ .= '"' . $ip . '",';
        }
      }
      $ips_ = substr($ips_, 0, -1);
      $ips_ .= ']';
    }
    else {
      $ips_ = '"' . $ips . '"';
    }

    return $ips_;
  }

  /**
   * Get data of the country with the most attacks.
   *
   * @param array $map
   *   Map logs from WebTotem.
   * @param int $count_attacks
   *   Total attacks.
   *
   * @return array
   *   Returns array of data.
   */
  public static function getMostAttacksData($map) {

    if ($map) {
      $most_attacks_key = array_search(max(array_column($map, 'attacks')), array_column($map, 'attacks'));
	    $total_attacks = array_sum(array_column($map, 'attacks'));

      $data['percent'] = ($total_attacks) ? round($map[$most_attacks_key]['attacks'] / $total_attacks * 100) : 0;
      $data['country'] = self::getCountryName($map[$most_attacks_key]['country']);
      $data['offset'] = 176 / 100 * (100 - $data['percent']);

      return $data;
    }

    return ['percent' => 0, 'country' => FALSE, 'offset' => 0];
  }

  /**
   * Getting the country name by two-letter code.
   *
   * @param string $key
   *   Two-letter code.
   *
   * @return string
   *   Returns country name.
   */
  public static function getCountryName($key) {
    $countries = WebTotemCountryManager::getStandardList();
    $key = (string) $key;

    return (array_key_exists($key, $countries)) ? $countries[$key] : $key;
  }


	/**
	 * Get configs data.
	 *
	 * @param array $array
	 *   Original array.
	 * @param string $key
	 *   The key to use as an index.
	 *
	 * @return array
	 *   Configs data array.
	 */
	public static function getConfigsData(array $array, $key) {
		$configs = self::arrayMapIndex($array, $key);

		foreach ($configs as $service => $config){
			$configs[$service]['checked'] = ($config['isActive']) ? 'checked' : '';
			$configs[$service]['notification_checked'] = (isset($config['notifications']) && $config['notifications']) ? 'checked' : '';
		}

		return $configs;
	}

	/**
	 * Get waf setting data.
	 *
	 * @param array $settings
	 *   Original array.
	 *
	 * @return array
	 *   Configs data array.
	 */
	public static function getWafSettingData(array $settings) {
		$_settings['gdn']['checked'] = (isset($settings['gdn']) && !$settings['gdn']) ? '' : 'checked';
		$_settings['dos'] = [
			'checked'  => (isset($settings['dosProtection']) && !$settings['dosProtection']) ? '' : 'checked',
			'visually' => (isset($settings['dosProtection']) && !$settings['dosProtection']) ? 'visually-hidden' : '',
		];
		$_settings['dos_limit'] = $settings['dosLimit'] ?: 1000;

		$_settings['login_attempt'] = [
			'checked'  => (isset($settings['loginAttemptsProtection']) && !$settings['loginAttemptsProtection']) ? '' : 'checked',
			'visually' => (isset($settings['loginAttemptsProtection']) && !$settings['loginAttemptsProtection']) ? 'visually-hidden' : '',
		];
		$_settings['login_attempt_limit'] = $settings['loginAttemptsLimit'] ?: 20;

		return $_settings;
	}

	/**
	 * Get plugin settings data.
	 *
	 * @return array
	 *   Configs data array.
	 */
	public static function getPluginSettingsData() {

		$settings = WebTotemOption::getPluginSettings();
		$_settings = $settings;

		$_settings['hide_wp_version_checked'] =  $settings['hide_wp_version'] ? 'checked' : '';
		$_settings['recaptcha_checked'] =  $settings['recaptcha'] ? 'checked' : '';

		return $_settings;
	}

	/**
   * Replace array indexes by key.
   *
   * @param array $array
   *   Original array.
   * @param string $key
   *   The key to use as an index.
   *
   * @return array
   *   Returns a new array.
   */
  public static function arrayMapIndex(array $array, $key) {
    $new_array = [];
    foreach ($array as $item) {
      if (array_key_exists($key, $item)) {
        $new_array[$item[$key]] = $item;
      }
    }
    return $new_array;
  }

  /**
   * Generate random string.
   *
   * @param int $length
   *   The required length of the string.
   *
   * @return string
   *   Returns random string.
   */
  public static function generateRandomString( int $length = 10): string {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
      $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
  }

	/**
	 * Encodes the less than, greater than, ampersand,double quote
	 * and single quote characters. Will never double encode entities.
	 *
	 * @see https://developer.wordpress.org/reference/functions/esc_attr/
	 *
	 * @param  string $text
	 *     The text which is to be encoded.
	 *
	 * @return string
	 *    The encoded text with HTML entities.
	 */
	public static function escape($text = '')
	{
		return esc_attr($text);
	}

  /**
   * Get notifications array.
   *
   * @return array
   *   Returns notifications array.
   */
  public static function getNotifications() {

    $notifications_data = WebTotemOption::getNotificationsData();
    $notifications = [];

    foreach ($notifications_data as $notification) {
      switch ($notification['type']) {
        case 'error':
          $image = 'alert-error.svg';
          $class = 'wtotem_alert__title_red';
          break;

        case 'warning':
          $image = 'alert-warning.svg';
          $class = 'wtotem_alert__title_yellow';
          break;

        case 'success':
          $image = 'alert-success.svg';
          $class = 'wtotem_alert__title_green';
          break;

        case 'info':
          $image = 'info-blue.svg';
          $class = 'wtotem_alert__title_blue';
          break;
      }

      $notifications[] = [
        "text" => $notification['notice'],
        "id" => self::generateRandomString(8),
        "type" => self::getStatusText($notification['type']),
        "image" => $image,
        "class" => $class,
      ];
    }

    return $notifications;
  }

  /**
   * Get current agent installation statuses.
   *
   * @param array $agents_statuses
   *   Agents statuses got from the WebTotem API.
   *
   * @return array
   *   Returns an array with agent installation status data.
   */
  public static function getAgentsStatuses(array $agents_statuses) {
    $agents = ['am', 'waf', 'av'];
    $installing_statuses = [
      'not_installed',
      'installing',
      'internal_error',
      'update_error',
      'config_error',
      'session_error',
    ];

    $process_statuses = [];
    $option_statuses = [];

    foreach ($agents as $agent) {
      $status = WebTotemAgentManager::checkInstalledService($agent);
      $option_statuses[$agent] = $status['option_status'] ?: FALSE;

      if ($agent == 'am') {
        if ($status['file_status']) {
          $process_statuses[$agent] = 'installed';
        }
        else {
          $process_statuses[$agent] = 'failed';
        }
      }
      else {
        if ($status['file_status']) {
          if (in_array($agents_statuses[$agent], $installing_statuses)) {
            $process_statuses[$agent] = 'installing';
          }
          elseif ($agents_statuses[$agent] == 'agent_not_available') {
            $process_statuses[$agent] = 'failed';
          }
          else {
            $process_statuses[$agent] = 'installed';
          }
        }
        else {
          $process_statuses[$agent] = 'installing';
        }
      }
    }

    return [
      'process_statuses' => $process_statuses,
      'option_statuses' => $option_statuses,
    ];
  }

}

```
