PHP code example of rosell-dk / htaccess-capability-tester

1. Go to this page and download the library: Download rosell-dk/htaccess-capability-tester library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

rosell-dk / htaccess-capability-tester example snippets



use HtaccessCapabilityTester\HtaccessCapabilityTester;

$hct = new HtaccessCapabilityTester($baseDir, $baseUrl);

if ($hct->moduleLoaded('headers')) {
    // mod_headers is loaded (tested in a real .htaccess by using the "IfModule" directive)
}
if ($hct->rewriteWorks()) {    
    // rewriting works

}
if ($hct->htaccessEnabled() === false) {
    // Apache has been configured to ignore .htaccess files
}

// A bunch of other tests are available - see API

/**
 * @param string $htaccessRules  The rules to check
 * @param string $subSubDir      subdir for the test files. If not supplied, a fingerprint of the rules will be used
 */
public function __construct($htaccessRules, $subSubDir = null)
{
    if (is_null($subSubDir)) {
        $subSubDir = hash('md5', $htaccessRules);
    }

    $test = [
        'subdir' => 'crash-tester/' . $subSubDir,
        'subtests' => [
            [
                'subdir' => 'the-suspect',
                'files' => [
                    ['.htaccess', $htaccessRules],
                    ['request-me.txt', 'thanks'],
                ],
                'request' => [
                    'url' => 'request-me.txt',
                    'bypass-standard-error-handling' => ['all']
                ],
                'interpretation' => [
                    ['success', 'status-code', 'not-equals', '500'],
                ]
            ],
            [
                'subdir' => 'the-innocent',
                'files' => [
                    ['.htaccess', '# I am no trouble'],
                    ['request-me.txt', 'thanks'],
                ],
                'request' => [
                    'url' => 'request-me.txt',
                    'bypass-standard-error-handling' => ['all']
                ],
                'interpretation' => [
                    // The suspect crashed. But if the innocent crashes too, we cannot judge
                    ['inconclusive', 'status-code', 'equals', '500'],

                    // The innocent did not crash. The suspect is guilty!
                    ['failure'],
                ]
            ],
        ]
    ];

    parent::__construct($test);
}

// If we can find anything that works, well the .htaccess must have been proccesed!
if ($hct->serverSignatureWorks()    // Override: None,  Status: Core, REQUIRES PHP
    || $hct->contentDigestWorks()   // Override: Options,  Status: Core
    || $hct->addTypeWorks()         // Override: FileInfo, Status: Base, Module: mime
    || $hct->directoryIndexWorks()  // Override: Indexes,  Status: Base, Module: mod_dir
    || $hct->rewriteWorks()         // Override: FileInfo, Status: Extension, Module: rewrite
    || $hct->headerSetWorks()       // Override: FileInfo, Status: Extension, Module: headers
) {
    $status = true;
} else {
    // The serverSignatureWorks() test is special because if it comes out as a failure,
    // we can be *almost* certain that the .htaccess has been completely disabled

    $serverSignatureWorks = $hct->serverSignatureWorks();
    if ($serverSignatureWorks === false) {
        $status = false;
        $info = 'ServerSignature directive does not work - and it is in core';
    } else {
        // Last bullet in the gun:
        // Try an .htaccess with syntax errors in it.
        // (we do this lastly because it may generate an entry in the error log)
        $crashTestResult = $hct->crashTest('aoeu', 'htaccess-enabled-malformed-htaccess');
        if ($crashTestResult === false) {
            // It crashed, - which means .htaccess is processed!
            $status = true;
            $info = 'syntax error in an .htaccess causes crash';
        } elseif ($crashTestResult === true) {
            // It did not crash. So the .htaccess is not processed, as syntax errors
            // makes servers crash
            $status = false;
            $info = 'syntax error in an .htaccess does not cause crash';
        } elseif (is_null($crashTestResult)) {
            // It did crash. But so did a request to an innocent text file in a directory
            // without a .htaccess file in it. Something is making all requests fail and
            // we cannot judge.
            $status = null;
            $info = 'all requests results in 500 Internal Server Error';
        }
    }
}
return new TestResult($status, $info);

<IfModule mod_setenvif.c>
    Header set X-Response-Header-Test: 1
</IfModule>
<IfModule !mod_setenvif.c>
    Header set X-Response-Header-Test: 0
</IfModule>
yaml
subdir: pass-info-from-rewrite-to-script-through-env
files:
  - filename: '.htaccess'
    content: |
      <IfModule mod_rewrite.c>

          # Testing if we can pass environment variable from .htaccess to script in a RewriteRule
          # We pass document root, because that can easily be checked by the script

          RewriteEngine On
          RewriteRule ^test\.php$ - [E=PASSTHROUGHENV:%{DOCUMENT_ROOT},L]

      </IfModule>
  - filename: 'test.php'
    content: |
      

      /**
       *  Get environment variable set with mod_rewrite module
       *  Return false if the environment variable isn't found
       */
      function getEnvPassedInRewriteRule($envName) {
          // Environment variables passed through the REWRITE module have "REWRITE_" as a prefix
          // (in Apache, not Litespeed, if I recall correctly).
          // Multiple iterations causes multiple REWRITE_ prefixes, and we get many environment variables set.
          // We simply look for an environment variable that ends with what we are looking for.
          // (so make sure to make it unique)
          $len = strlen($envName);
          foreach ($_SERVER as $key => $item) {
              if (substr($key, -$len) == $envName) {
                  return $item;
              }
          }
          return false;
      }

      $result = getEnvPassedInRewriteRule('PASSTHROUGHENV');
      if ($result === false) {
          echo '0';
          exit;
      }
      echo ($result == $_SERVER['DOCUMENT_ROOT'] ? '1' : '0');

request:
  url: 'test.php'

interpretation:
  - ['success', 'body', 'equals', '1']
  - ['failure', 'body', 'equals', '0']
  - ['inconclusive', 'body', 'begins-with', '']
  - ['inconclusive']
 
yaml
subdir: pass-info-from-rewrite-to-script-through-request-header
files:
  - filename: '.htaccess'
    content: |
      <IfModule mod_rewrite.c>
          RewriteEngine On

          # Testing if we can pass an environment variable through a request header
          # We pass document root, because that can easily be checked by the script

          <IfModule mod_headers.c>
            RequestHeader set PASSTHROUGHHEADER "%{PASSTHROUGHHEADER}e" env=PASSTHROUGHHEADER
          </IfModule>
          RewriteRule ^test\.php$ - [E=PASSTHROUGHHEADER:%{DOCUMENT_ROOT},L]

      </IfModule>
  - filename: 'test.php'
    content: |
      
      if (isset($_SERVER['HTTP_PASSTHROUGHHEADER'])) {
          echo ($_SERVER['HTTP_PASSTHROUGHHEADER'] == $_SERVER['DOCUMENT_ROOT'] ? 1 : 0);
          exit;
      }
      echo '0';

request:
  url: 'test.php'

interpretation:
  - ['success', 'body', 'equals', '1']
  - ['failure', 'body', 'equals', '0']
  - ['inconclusive', 'body', 'begins-with', '']
  - ['inconclusive']
yaml
subdir: request-header
files:
  - filename: '.htaccess'
    content: |
      <IfModule mod_headers.c>
          # Certain hosts seem to strip non-standard request headers,
          # so we use a standard one to avoid a false negative
          RequestHeader set User-Agent "request-header-test"
      </IfModule>
  - filename: 'test.php'
    content: |
      
      if (isset($_SERVER['HTTP_USER_AGENT'])) {
          echo  $_SERVER['HTTP_USER_AGENT'] == 'request-header-test' ? 1 : 0;
      } else {
          echo 0;
      }

request:
  url: 'test.php'

interpretation:
  - ['success', 'body', 'equals', '1']
  - ['failure', 'body', 'equals', '0']
  - ['inconclusive', 'body', 'begins-with', '']
yaml
subdir: server-signature
subtests:
  - subdir: on
    files:
    - filename: '.htaccess'
      content: |
        ServerSignature On
    - filename: 'test.php'
      content: |
      
      if (isset($_SERVER['SERVER_SIGNATURE']) && ($_SERVER['SERVER_SIGNATURE'] != '')) {
          echo 1;
      } else {
          echo 0;
      }
    request:
      url: 'test.php'
    interpretation:
      - ['inconclusive', 'body', 'isEmpty']
      - ['inconclusive', 'status-code', 'not-equals', '200']
      - ['failure', 'body', 'equals', '0']

  - subdir: off
    files:
    - filename: '.htaccess'
      content: |
        ServerSignature Off
    - filename: 'test.php'
      content: |
      
      if (isset($_SERVER['SERVER_SIGNATURE']) && ($_SERVER['SERVER_SIGNATURE'] != '')) {
          echo 0;
      } else {
          echo 1;
      }
    request:
      url: 'test.php'
    interpretation:
      - ['inconclusive', 'body', 'isEmpty']
      - ['success', 'body', 'equals', '1']
      - ['failure', 'body', 'equals', '0']
      - ['inconclusive']