get_software() ); if ( '' === $software ) { return self::UNKNOWN; } // LiteSpeed is checked first; it does not identify as Apache. if ( false !== strpos( $software, 'litespeed' ) ) { return self::LITESPEED; } if ( false !== strpos( $software, 'nginx' ) ) { return self::NGINX; } if ( false !== strpos( $software, 'apache' ) ) { return self::APACHE; } return self::UNKNOWN; } /** * Returns the Apache version, when the server states one. * * @return string Version string such as 2.4.62, or an empty string. */ public function get_apache_version(): string { if ( self::APACHE !== $this->get_type() ) { return ''; } if ( ! preg_match( '#apache/([0-9]+(?:\.[0-9]+)*)#i', $this->get_software(), $matches ) ) { return ''; } return $matches[1]; } /** * Whether this is an Apache release too old for the rules we write. * * @return bool True when Apache is older than 2.4. */ public function is_legacy_apache(): bool { $version = $this->get_apache_version(); if ( '' === $version ) { return false; } return version_compare( $version, '2.4', '<' ); } /** * Whether the server reads .htaccess files. * * @return bool True when the .htaccess layer can work. */ public function supports_htaccess(): bool { $type = $this->get_type(); if ( self::APACHE === $type ) { return ! $this->is_legacy_apache(); } if ( self::LITESPEED === $type ) { return true; } // Core sets this global for the same purpose. if ( function_exists( 'got_mod_rewrite' ) && got_mod_rewrite() ) { return true; } return false; } /** * Whether the site is served by nginx, so the copy-paste snippet applies. * * @return bool True on nginx. */ public function is_nginx(): bool { return self::NGINX === $this->get_type(); } /** * Returns a plain-language description of what this means for the user. * * @return string Human-readable explanation. */ public function describe(): string { switch ( $this->get_type() ) { case self::APACHE: if ( $this->is_legacy_apache() ) { return sprintf( /* translators: %s: Apache version string, such as 2.2.34. */ __( 'Your site runs Apache %s. The .htaccess rules this plugin writes need Apache 2.4, so that layer has been switched off here rather than writing rules that would block nothing.', 'ai-blackout' ), $this->get_apache_version() ); } return __( 'Your site runs on Apache, so the .htaccess layer works here.', 'ai-blackout' ); case self::LITESPEED: return __( 'Your site runs on LiteSpeed, which reads .htaccess, so that layer works here.', 'ai-blackout' ); case self::NGINX: return __( 'Your site runs on nginx, which does not read .htaccess. Use the nginx snippet instead. A plugin cannot write nginx configuration.', 'ai-blackout' ); default: return __( 'Your server did not identify itself, so the .htaccess layer has been switched off rather than reporting protection that may not exist.', 'ai-blackout' ); } } }