<?php
// Standalone block page renderer used before WordPress is available.

if ( ! function_exists( 'sitefort_block_page_sanitize_server_scalar' ) ) {
    function sitefort_block_page_sanitize_server_scalar( $value ): string {
        if ( ! is_scalar( $value ) ) {
            return '';
        }

        $value = str_replace( "\0", '', (string) $value );
        $value = preg_replace( '/[\x00-\x1F\x7F]/', '', $value );

        return is_string( $value ) ? $value : '';
    }
}

if ( ! defined( 'ABSPATH' ) ) {
    $sitefort_block_page_script = (string) filter_input( INPUT_SERVER, 'SCRIPT_FILENAME', FILTER_CALLBACK, [ 'options' => 'sitefort_block_page_sanitize_server_scalar' ] );
    $sitefort_block_page_path = realpath( __FILE__ );
    if (
        is_string( $sitefort_block_page_script )
        && $sitefort_block_page_path !== false
        && realpath( $sitefort_block_page_script ) === $sitefort_block_page_path
    ) {
        http_response_code( 404 );
        exit;
    }
    unset( $sitefort_block_page_path );
}

if ( ! function_exists( 'sitefort_render_block_page' ) ) {

    function sitefort_render_block_page( int $code, string $message, string $ip = '' ): void {
        $code = in_array( $code, [ 403, 404, 429, 503 ], true ) ? $code : 403;

        // Not every caller sets these; without them the block page would go
        // out as a cacheable HTTP 200.
        if ( ! headers_sent() ) {
            http_response_code( $code );
            header( 'Cache-Control: no-store, no-cache, must-revalidate, max-age=0' );
        }

        $titles = [
            403 => 'Access Denied',
            404 => 'Not Found',
            429 => 'Rate Limited',
            503 => 'Temporarily Unavailable',
        ];
        $subtitles = [
            403 => 'This request was denied by this site\'s security controls.',
            404 => 'The requested resource could not be found on this server.',
            429 => 'Request volume exceeded the allowed rate for this service.',
            503 => 'Access is temporarily restricted while site-wide security controls are in effect.',
        ];

        $title         = $titles[ $code ] ?? 'Access Denied';
        $safe_subtitle = htmlspecialchars( $subtitles[ $code ] ?? '', ENT_QUOTES, 'UTF-8' );
        $safe_msg      = htmlspecialchars( $message, ENT_QUOTES, 'UTF-8' );

        $reason_class = $code === 429 ? ' rate-limit' : ( $code === 503 ? ' unavailable' : '' );
        $items        = $code === 429
            ? '<li>Wait a moment and try again</li><li>Reduce how frequently you are making requests</li>'
            : ( $code === 503
                ? '<li>Wait a few minutes and refresh the page</li><li>Contact the site administrator if this persists</li>'
                : '<li>If you believe this is an error, contact the site administrator</li><li>Include your IP address and the time shown below when reporting this issue</li>'
              );

        $body_html = '<p class="subtitle">' . $safe_subtitle . '</p>
    <div class="reason-box' . $reason_class . '">
      <p>' . $safe_msg . '</p>
    </div>
    <div class="what-to-do">
      <h3>What you can do</h3>
      <ul>' . $items . '
      </ul>
    </div>';

        sitefort_render_branded_page( $code . ' ' . $title, $title, 'HTTP ' . $code, $body_html, $ip );
    }
}

if ( ! function_exists( 'sitefort_render_branded_page' ) ) {

    /**
     * Branded page shell shared by block and unlock pages.
     *
     * Runs from the pre-WordPress WAF bootstrap, so plain PHP only; no
     * WordPress functions.
     *
     * @param string $body_html Pre-escaped HTML for the body section.
     */
    function sitefort_render_branded_page( string $doc_title, string $title, string $badge, string $body_html, string $ip = '' ): void {
        $safe_doc_title    = htmlspecialchars( $doc_title, ENT_QUOTES, 'UTF-8' );
        $safe_title        = htmlspecialchars( $title, ENT_QUOTES, 'UTF-8' );
        $safe_badge        = htmlspecialchars( $badge, ENT_QUOTES, 'UTF-8' );
        $safe_ip           = htmlspecialchars( $ip, ENT_QUOTES, 'UTF-8' );
        $safe_time         = htmlspecialchars( gmdate( 'Y-m-d H:i:s' ) . ' UTC', ENT_QUOTES, 'UTF-8' );
        $safe_brand_green  = htmlspecialchars( '#00CC66', ENT_QUOTES, 'UTF-8' );
        $safe_brand_navy   = htmlspecialchars( '#071C2C', ENT_QUOTES, 'UTF-8' );
        $icon_path         = dirname( __DIR__, 2 ) . '/assets/images/icon.svg';
        $icon_light_path   = dirname( __DIR__, 2 ) . '/assets/images/icon-light.svg';
        $brand_icon        = '';
        $header_brand_icon = '';

        if ( is_readable( $icon_path ) ) {
            $brand_icon = trim( (string) file_get_contents( $icon_path ) );
        }

        if ( is_readable( $icon_light_path ) ) {
            $header_brand_icon = trim( (string) file_get_contents( $icon_light_path ) );
        }

        if ( $brand_icon === '' ) {
            $brand_icon = '<svg width="32" height="32" viewBox="0 0 512 516" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M272.492 68.9487C253.239 68.9487 234.783 76.5877 221.181 90.1718C207.581 103.754 199.949 122.168 199.949 141.358V167.872C199.949 186.083 185.186 200.846 166.974 200.846C148.763 200.846 134 186.083 134 167.872V141.358C134 104.65 148.601 69.4534 174.578 43.5094C200.554 17.5669 235.775 3 272.492 3C309.209 3 344.431 17.5669 370.406 43.5094C396.383 69.4534 410.984 104.65 410.984 141.358V194.251C410.984 212.462 396.221 227.225 378.01 227.225C359.799 227.225 345.036 212.462 345.036 194.251V141.358C345.036 122.168 337.403 103.754 323.803 90.1718C310.202 76.5877 291.745 68.9487 272.492 68.9487Z" fill="#00CC66" stroke="#00CC66" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M264.527 187.895C192.411 187.895 133.949 246.356 133.949 318.473C133.949 390.589 192.411 449.051 264.527 449.051C306.871 449.051 344.503 428.932 368.416 397.594L388.419 371.379L440.847 411.385L420.844 437.599C384.994 484.582 328.306 515 264.527 515C155.988 515 68 427.012 68 318.473C68 209.934 155.988 121.946 264.527 121.946C330.674 121.946 389.18 154.657 424.745 204.639L443.862 231.506L390.129 269.741L371.011 242.874C347.287 209.533 308.433 187.895 264.527 187.895Z" fill="#071C2C" stroke="#071C2C" stroke-linecap="square" stroke-linejoin="round"/>
<path d="M268.759 352.528C297.897 352.528 321.518 328.907 321.518 299.769C321.518 270.631 297.897 247.01 268.759 247.01C239.621 247.01 216 270.631 216 299.769C216 328.907 239.621 352.528 268.759 352.528Z" fill="#00CC66" stroke="#00CC66" stroke-width="5" stroke-miterlimit="10"/>
<path d="M242.879 313.459H294.638V391.597H242.879V313.459Z" fill="#00CC66" stroke="#00CC66"/>
</svg>';
        }

        if ( $header_brand_icon === '' ) {
            $header_brand_icon = '<svg width="32" height="32" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M272.492 65.9487C253.239 65.9487 234.783 73.5877 221.181 87.1718C207.581 100.754 199.949 119.168 199.949 138.358V164.872C199.949 183.083 185.186 197.846 166.974 197.846C148.763 197.846 134 183.083 134 164.872V138.358C134 101.65 148.601 66.4535 174.578 40.5094C200.554 14.5669 235.775 0 272.492 0C309.209 0 344.431 14.5669 370.406 40.5094C396.383 66.4535 410.984 101.65 410.984 138.358V191.251C410.984 209.462 396.221 224.225 378.01 224.225C359.799 224.225 345.036 209.462 345.036 191.251V138.358C345.036 119.168 337.403 100.754 323.803 87.1718C310.202 73.5877 291.745 65.9487 272.492 65.9487Z" fill="#00CC66"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M264.527 184.895C192.411 184.895 133.949 243.356 133.949 315.473C133.949 387.589 192.411 446.051 264.527 446.051C306.871 446.051 344.503 425.932 368.416 394.594L388.419 368.379L440.847 408.385L420.844 434.599C384.994 481.582 328.306 512 264.527 512C155.988 512 68 424.012 68 315.473C68 206.934 155.988 118.946 264.527 118.946C330.674 118.946 389.18 151.657 424.745 201.639L443.862 228.506L390.129 266.741L371.011 239.874C347.287 206.533 308.433 184.895 264.527 184.895Z" fill="white"/>
<path d="M268.759 349.528C297.897 349.528 321.518 325.907 321.518 296.769C321.518 267.631 297.897 244.01 268.759 244.01C239.621 244.01 216 267.631 216 296.769C216 325.907 239.621 349.528 268.759 349.528Z" fill="#00CC66"/>
<path d="M242.379 309.959H295.138V389.097H242.379V309.959Z" fill="#00CC66"/>
</svg>';
        }

        // This document can render from the extended firewall bootstrap before WordPress loads.
        // wp_enqueue_style() is unavailable in that execution path.
        // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
        echo '<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex, nofollow">
<title>' . $safe_doc_title . '</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
	background:#f0f4f3;color:' . $safe_brand_navy . ';min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px}
.block-container{max-width:560px;width:100%;background:#fff;border-radius:16px;
box-shadow:0 4px 24px rgba(7,28,44,.1);overflow:hidden}
.block-header{background:linear-gradient(135deg,' . $safe_brand_navy . ' 0%,#0f314b 100%);padding:30px 32px 26px;text-align:center}
.brand-icon{width:52px;height:52px;margin:0 auto 14px}
.brand-icon svg{width:100%;height:100%;display:block}
.block-header h1{color:#fff;font-size:26px;font-weight:700;letter-spacing:-.3px}
.block-header .code-badge{display:inline-block;background:rgba(255,255,255,.10);
color:#fff;font-size:13px;font-weight:600;padding:4px 14px;
border-radius:20px;margin-top:12px;letter-spacing:.5px;border:1px solid rgba(255,255,255,.18)}
.block-body{padding:28px 32px}
.block-body .subtitle{font-size:15px;color:#4a5568;line-height:1.6;margin-bottom:16px}
.reason-box{background:#fef3f2;border:1px solid #fecaca;border-left:4px solid #ef4444;border-radius:8px;padding:14px 18px;margin-bottom:20px}
.reason-box.rate-limit{background:#fffbeb;border-color:#fed7aa;border-left-color:#f59e0b}
.reason-box.unavailable{background:#eff6ff;border-color:#bfdbfe;border-left-color:#3b82f6}
.reason-box p{font-size:14px;color:#991b1b;line-height:1.6}
.reason-box.rate-limit p{color:#92400e}
.reason-box.unavailable p{color:#1e40af}
.action-btn{background:' . $safe_brand_green . ';color:#fff;border:0;border-radius:8px;padding:13px 30px;
font-size:15px;font-weight:600;cursor:pointer;display:block;width:100%;max-width:300px;margin:0 auto;text-align:center;
box-shadow:0 2px 8px rgba(0,204,102,.25);transition:background .15s ease}
.action-btn:hover{background:#00b359}
.stack-center{text-align:center;padding:14px 0 8px}
.subject-label{font-size:12px;font-weight:600;letter-spacing:.8px;text-transform:uppercase;color:#6b7280;margin-bottom:10px}
.subject-chip{display:inline-block;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
font-size:19px;font-weight:600;color:' . $safe_brand_navy . ';background:#f8faf9;border:1px solid #e5e7eb;
border-radius:10px;padding:12px 26px;margin-bottom:18px;word-break:break-all}
.stack-center .note{font-size:14px;color:#4a5568;line-height:1.6;max-width:360px;margin:0 auto 24px}
.micro{font-size:12px;color:#9ca3af;text-align:center;margin:12px 0 0}
.what-to-do{margin-bottom:20px}
.what-to-do h3{font-size:13px;font-weight:600;color:#6b7280;text-transform:uppercase;
letter-spacing:.5px;margin-bottom:10px}
.what-to-do ul{list-style:none;padding:0}
.what-to-do li{font-size:14px;color:#4a5568;padding:6px 0 6px 22px;position:relative;line-height:1.5}
.what-to-do li::before{content:"";width:6px;height:6px;background:' . $safe_brand_green . ';border-radius:50%;
position:absolute;left:4px;top:13px}
.ref-bar{background:#f8faf9;border-top:1px solid #e5e7eb;padding:16px 32px;
display:flex;flex-wrap:wrap;justify-content:space-between;gap:8px 24px;font-size:12px;color:#9ca3af}
.ref-bar span{white-space:nowrap}
.ref-bar .label{color:' . $safe_brand_navy . ';font-weight:600}
.powered-by{text-align:center;padding:14px;font-size:12px;color:#9ca3af;display:flex;align-items:center;justify-content:center;gap:6px}
.powered-by svg{flex-shrink:0}
.powered-by .brand-mark{width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center}
.powered-by .brand-mark svg{width:100%;height:100%;display:block}
.powered-by span{color:' . $safe_brand_navy . ';font-weight:600}
@media(max-width:480px){.block-header{padding:24px 20px 20px}
.block-header h1{font-size:22px}.block-body{padding:20px}
.ref-bar{padding:12px 20px;flex-direction:column;gap:4px}}
</style>
</head>
<body>
<div class="block-container">
  <div class="block-header">
    <div class="brand-icon">' . $header_brand_icon . '</div>
    <h1>' . $safe_title . '</h1>
    ' . ( $safe_badge !== '' ? '<span class="code-badge">' . $safe_badge . '</span>' : '' ) . '
  </div>
  <div class="block-body">
    ' . $body_html . '
  </div>
  <div class="ref-bar">
    ' . ( $safe_ip !== '' ? '<span><span class="label">Your IP:</span> ' . $safe_ip . '</span>' : '' ) . '
    <span><span class="label">Time:</span> ' . $safe_time . '</span>
  </div>
  <div class="powered-by">
    <div class="brand-mark">' . $brand_icon . '</div>
    Protected by <span>SiteFort</span>
  </div>
</div>
</body>
</html>';
        // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
    }
}
