<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <defaultDocument>
            <files>
                <remove value="index.php" />
                <add value="index.php" />
            </files>
        </defaultDocument>
        <rewrite>
            <rules>
                <rule name="request_filename" stopProcessing="true">
                    <match url="." ignoreCase="false" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="index.php" />
                </rule>
                <!-- The rules below only see paths that exist on disk; everything else was
                     handed to index.php above. Windows finds the same file for a path with
                     doubled slashes (//user/config/..., user//config/...) or with dots or
                     spaces after the name (composer.json.), so the patterns accept those
                     too. -->
                <rule name="user_error_redirect" stopProcessing="true">
                    <match url="^/*user/(.*)\.(txt|md|json|yaml|yml|php|php2|php3|php4|php5|phar|phtml|pl|py|cgi|twig|sh|bat)[. ]*$" ignoreCase="true" />
                    <action type="Redirect" url="error" redirectType="Permanent" />
                </rule>
                <rule name="ignore_folders" stopProcessing="true">
                    <match url="^/*(\.git|cache|bin|logs|backup|tmp|webserver-configs|tests)/" ignoreCase="true" />
                    <action type="Redirect" url="error" redirectType="Permanent" />
                </rule>
                <rule name="cache_folder_scripts" stopProcessing="true">
                    <match url="^/*(images|assets)/(.*)\.(php|php2|php3|php4|php5|php7|php8|phar|phtml|pht|phtm|phps|pl|py|cgi|sh|bat)[. ]*$" ignoreCase="true" />
                    <action type="Redirect" url="error" redirectType="Permanent" />
                </rule>
                <rule name="user_sensitive_folders" stopProcessing="true">
                    <match url="^/*user/+(env/+[^/]+/+)?config/" ignoreCase="true" />
                    <action type="Redirect" url="error" redirectType="Permanent" />
                </rule>
                <!-- Block user/accounts too, but allow avatar images to be served
                     directly, whether stored at user/accounts/avatars/<file> (flatfile
                     accounts) or user/accounts/<username>/<file> (Flex folder storage).
                     SVG is intentionally excluded as a stored-XSS vector. The exception
                     lives in <match url>, which sees the path without the query string. -->
                <rule name="user_accounts" stopProcessing="true">
                    <match url="^/*user/+(env/+[^/]+/+)?accounts/(?![^/]+/[^/]+\.(jpe?g|png|gif|webp|avif|bmp|ico)$)" ignoreCase="true" />
                    <action type="Redirect" url="error" redirectType="Permanent" />
                </rule>
                <!-- Block user/data too, but allow public media uploads (e.g. Flex Object
                     images) to be served directly. SVG is intentionally excluded as a
                     stored-XSS vector. The exception lives in <match url>, which sees the
                     path without the query string. -->
                <rule name="user_data" stopProcessing="true">
                    <match url="^/*user/+(env/+[^/]+/+)?data/(?!.*\.(jpe?g|png|gif|webp|avif|bmp|ico|mp4|webm|ogg|ogv|mov|mp3|wav|m4a|flac|pdf)$)" ignoreCase="true" />
                    <action type="Redirect" url="error" redirectType="Permanent" />
                </rule>
                <!-- Serve page media only through the page route, so plugins can apply the
                     page's `access` rules to it. DO NOT uncomment without first setting
                     `pages.media_route_urls: true` in user/config/system.yaml, or every
                     media URL on the site becomes a 403.
                <rule name="user_pages" stopProcessing="true">
                    <match url="^/*user/+pages/" ignoreCase="true" />
                    <action type="Redirect" url="error" redirectType="Permanent" />
                </rule>
                -->
                <rule name="dotenv" stopProcessing="true">
                    <match url="(^|/)\.env(\.|$)" ignoreCase="true" />
                    <action type="Redirect" url="error" redirectType="Permanent" />
                </rule>
                <rule name="hidden_files_and_directories" stopProcessing="true">
                    <match url="(^|/)\.(?!well-known(?:/|$))" ignoreCase="true" />
                    <action type="Redirect" url="error" redirectType="Permanent" />
                </rule>
                <rule name="system" stopProcessing="true">
                    <match url="^/*system/(.*)\.(txt|xml|md|html|htm|shtml|shtm|json|yaml|yml|php|php2|php3|php4|php5|phar|phtml|pl|py|cgi|twig|sh|bat)[. ]*$" ignoreCase="true" />
                    <action type="Redirect" url="error" redirectType="Permanent" />
                </rule>
                <rule name="vendor" stopProcessing="true">
                    <match url="^/*vendor/(.*)\.(txt|xml|md|html|htm|shtml|shtm|json|yaml|yml|php|php2|php3|php4|php5|phar|phtml|pl|py|cgi|twig|sh|bat)[. ]*$" ignoreCase="true" />
                    <action type="Redirect" url="error" redirectType="Permanent" />
                </rule>
                <rule name="root_files" stopProcessing="true">
                    <match url="^/*(LICENSE\.txt|composer\.lock|composer\.json|nginx\.conf|htaccess\.txt)[. ]*$" ignoreCase="true" />
                    <action type="Redirect" url="error" redirectType="Permanent" />
                </rule>
                <!-- Markdown source files such as README.md and CHANGELOG.md. A page route
                     ending in .md is not a file, so it was handed to index.php above and
                     still reaches Grav's Markdown output. -->
                <rule name="markdown_files" stopProcessing="true">
                    <match url="\.md[. ]*$" ignoreCase="true" />
                    <action type="Redirect" url="error" redirectType="Permanent" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
    <system.web>
        <httpRuntime requestPathInvalidCharacters="&lt;,&gt;,*,%,&amp;,\,?" />
    </system.web>
</configuration>
