htaccess = $htaccess; $this->server = $server; } /** * Returns the check identifier. * * @return string Identifier. */ public function get_id(): string { return 'htaccess'; } /** * Whether a loopback request is required. * * @return bool False. */ public function needs_loopback(): bool { return false; } /** * Runs the check. * * @return Result The finding. */ public function run(): Result { $label = __( 'Server-level blocking (.htaccess)', 'ai-blackout' ); $applied = $this->htaccess->is_applied(); $detail = array( 'server_type' => $this->server->get_type(), 'apache_version' => $this->server->get_apache_version(), 'supported' => $this->server->supports_htaccess(), 'path' => $this->htaccess->get_path(), 'block_found' => $applied, 'stale' => $applied && $this->htaccess->is_stale(), ); if ( aiblackout_is_disabled() ) { return new Result( $this->get_id(), $label, Result::INACTIVE, __( 'AI Blackout is switched off by the AIBLACKOUT_DISABLE setting in wp-config.php.', 'ai-blackout' ), __( 'Even if rules are present in .htaccess, this plugin is not managing them.', 'ai-blackout' ), __( 'Remove the AIBLACKOUT_DISABLE line from wp-config.php to turn protection back on.', 'ai-blackout' ), $detail ); } if ( ! $this->server->supports_htaccess() ) { if ( $this->server->is_legacy_apache() ) { return new Result( $this->get_id(), $label, Result::INFO, $this->server->describe(), __( 'This layer cannot block anything on Apache 2.2. The rules we write use the Apache 2.4 access syntax, and writing a block that parses and then blocks nothing would be worse than writing none at all.', 'ai-blackout' ), __( 'Ask your host to move you to Apache 2.4 or later. Version 2.2 stopped receiving security fixes in 2018. Until then blocking happens in your PHP layer, which a page cache can skip, or at the edge with Cloudflare.', 'ai-blackout' ), $detail ); } return new Result( $this->get_id(), $label, $this->server->is_nginx() ? Result::INFO : Result::UNKNOWN, $this->server->describe(), $this->server->is_nginx() ? __( 'This layer cannot work here. nginx does not read .htaccess files. Blocking has to happen in your PHP layer, which a page cache can skip, or in a CDN in front of your site.', 'ai-blackout' ) : __( 'We could not confirm what web server this site runs on, so we cannot promise this layer would work. It has been left off rather than reporting protection we cannot verify.', 'ai-blackout' ), $this->server->is_nginx() ? __( 'Add the nginx rule to your server configuration, or send it to your host and ask them to add it. If you have no server access at all, a CDN in front of your site can block these requests instead. That is set up in the CDN, not here.', 'ai-blackout' ) : __( 'Ask your host which web server your site runs on.', 'ai-blackout' ), $detail ); } if ( ! $this->htaccess->knows_site_root() ) { return new Result( $this->get_id(), $label, Result::UNKNOWN, __( 'We could not work out which folder your site is served from, so we cannot read or write .htaccess.', 'ai-blackout' ), __( 'This layer cannot be checked or applied until that is resolved. It is reported as unknown rather than as missing rules, because nothing has gone wrong with the file. We simply cannot find it.', 'ai-blackout' ), __( 'Check that the WordPress Address and Site Address in Settings → General match how your site is actually reached, then run this again.', 'ai-blackout' ), $detail ); } if ( empty( $this->htaccess->build_rules() ) ) { return new Result( $this->get_id(), $label, $applied ? Result::BROKEN : Result::INFO, $applied ? __( 'Blocking rules are still in .htaccess, but no crawler is set to be blocked.', 'ai-blackout' ) : __( 'No rules are needed here, because no crawler is set to be blocked.', 'ai-blackout' ), $applied ? __( 'Your server is refusing crawlers that your settings no longer refuse. The two disagree.', 'ai-blackout' ) : __( 'Your robots.txt still asks AI crawlers to stay away, and your declaration is still published. Nothing is being turned away at the door, which is what you chose.', 'ai-blackout' ), $applied ? __( 'Save your choices again. That rewrites the file to match them, removing the rules.', 'ai-blackout' ) : '', $detail ); } if ( ! $applied ) { return new Result( $this->get_id(), $label, Result::BROKEN, __( 'Crawlers are set to be blocked, but no AI Blackout rules were found in .htaccess.', 'ai-blackout' ), __( 'This layer is not blocking anything. Either the file could not be written, or something removed the rules -- usually another plugin rewriting the file, or a host that resets it.', 'ai-blackout' ), __( 'Save your choices again to rewrite the file. If the rules disappear again, another plugin or your host is overwriting it.', 'ai-blackout' ), $detail ); } if ( $this->htaccess->is_stale() ) { return new Result( $this->get_id(), $label, Result::BROKEN, __( 'Blocking rules are present in .htaccess, but they do not match which crawlers you currently have set to block.', 'ai-blackout' ), __( 'Your server is still refusing whichever crawlers were blocked the last time this was applied -- not necessarily the ones your current choices ask for. Something you meant to block may be getting through, or something you meant to allow may still be refused.', 'ai-blackout' ), __( 'Save your choices again. That rewrites the file to match them.', 'ai-blackout' ), $detail ); } return new Result( $this->get_id(), $label, Result::PROTECTED_STATE, __( 'Blocking rules are present in .htaccess and your server reads them.', 'ai-blackout' ), __( 'Blocked AI crawlers are refused by the web server itself, before WordPress runs. This keeps working even when pages are served from a cache.', 'ai-blackout' ), '', $detail ); } }