Files
WebP-eXpress/vendor/rosell-dk/htaccess-capability-tester/src/Testers/ModuleLoadedTester.php
Malin 37cf714058 WebP Express CloudHost.es Fix v0.25.9-cloudhost
 Fixed bulk conversion getting stuck on missing files
 Added robust error handling and timeout protection
 Improved JavaScript response parsing
 Added file existence validation
 Fixed missing PHP class imports
 Added comprehensive try-catch error recovery

🔧 Key fixes:
- File existence checks before conversion attempts
- 30-second timeout protection per file
- Graceful handling of 500 errors and JSON parsing issues
- Automatic continuation to next file on failures
- Cache busting for JavaScript updates

🎯 Result: Bulk conversion now completes successfully even with missing files

🚀 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-23 10:22:32 +02:00

370 lines
10 KiB
PHP

<?php
namespace HtaccessCapabilityTester\Testers;
use \HtaccessCapabilityTester\TestResult;
/**
* Class for testing if a module is loaded.
*
* @package HtaccessCapabilityTester
* @author Bjørn Rosell <it@rosell.dk>
* @since Class available since 0.7
*/
class ModuleLoadedTester extends AbstractTester
{
/* @var string A valid Apache module name (ie "rewrite") */
protected $moduleName;
/**
* Constructor.
*
* @return void
*/
public function __construct($moduleName)
{
$this->moduleName = $moduleName;
}
/**
* Child classes must implement this method, which tells which subdir the
* test files are to be put.
*
* @return string A subdir for the test files
*/
public function getSubDir()
{
return 'module-loaded/' . $this->moduleName;
}
/**
* Register the test files using the "registerTestFile" method
*
* @return void
*/
public function registerTestFiles()
{
// No test files for this test
}
private function getServerSignatureBasedTest()
{
// Test files, method : Using ServerSignature
// --------------------------------------------------
// Requires (in order not to be inconclusive):
// - Override: All
// - Status: Core
// - Directives: ServerSignature, IfModule
// - PHP?: Yes
$php = <<<'EOD'
<?php
if (isset($_SERVER['SERVER_SIGNATURE']) && ($_SERVER['SERVER_SIGNATURE'] != '')) {
echo 1;
} else {
echo 0;
}
EOD;
$htaccess = <<<'EOD'
# The beauty of this trick is that ServerSignature is available in core.
# (it requires no modules and cannot easily be made forbidden)
# However, it requires PHP to check for the effect
ServerSignature Off
<IfModule mod_xxx.c>
ServerSignature On
</IfModule>
EOD;
$htaccess = str_replace('mod_xxx', 'mod_' . $this->moduleName, $htaccess);
return [
'subdir' => $this->getSubDir() . '/server-signature',
'files' => [
['.htaccess', $htaccess],
['test.php', $php],
],
'request' => 'test.php',
'interpretation' => [
['success', 'body', 'equals', '1'],
['failure', 'body', 'equals', '0'],
// This time we do not fail for 500 because it is very unlikely that any of the
// directives used are forbidden
]
];
}
/**
* @return array
*/
private function getRewriteBasedTest()
{
// Test files, method: Using Rewrite
// --------------------------------------------------
// Requires (in order not to be inconclusive)
// - Module: mod_rewrite
// - Override: FileInfo
// - Directives: RewriteEngine, RewriteRule and IfModule
// - PHP?: No
$htaccess = <<<'EOD'
RewriteEngine On
<IfModule mod_xxx.c>
RewriteRule ^request-me\.txt$ 1.txt [L]
</IfModule>
<IfModule !mod_xxx.c>
RewriteRule ^request-me\.txt$ 0.txt [L]
</IfModule>
EOD;
$htaccess = str_replace('mod_xxx', 'mod_' . $this->moduleName, $htaccess);
return [
'subdir' => $this->getSubDir() . '/rewrite',
'files' => [
['.htaccess', $htaccess],
['0.txt', '0'],
['1.txt', '1'],
['request-me.txt', 'Redirect failed even though rewriting has been proven to work. Strange!'],
],
'request' => 'request-me.txt',
'interpretation' => [
['success', 'body', 'equals', '1'],
['failure', 'body', 'equals', '0'],
//['inconclusive', 'status-code', 'not-equals', '200'],
]
];
}
/**
* @return array
*/
private function getHeaderSetBasedTest()
{
// Test files, method: Using Response Header
// --------------------------------------------------
// Requires (in order not to be inconclusive)
// - Module: mod_headers
// - Override: FileInfo
// - Directives: Header and IfModule
// - PHP?: No
$htaccess = <<<'EOD'
<IfModule mod_xxx.c>
Header set X-Response-Header-Test: 1
</IfModule>
<IfModule !mod_xxx.c>
Header set X-Response-Header-Test: 0
</IfModule>
EOD;
$htaccess = str_replace('mod_xxx', 'mod_' . $this->moduleName, $htaccess);
return [
'subdir' => $this->getSubDir() . '/header-set',
'files' => [
['.htaccess', $htaccess],
['request-me.txt', 'thanks'],
],
'request' => 'request-me.txt',
'interpretation' => [
['success', 'headers', 'contains-key-value', 'X-Response-Header-Test', '1'],
['failure', 'headers', 'contains-key-value', 'X-Response-Header-Test', '0'],
]
];
}
/**
* @return array
*/
private function getContentDigestBasedTest()
{
// Test files, method: Using ContentDigest
// --------------------------------------------------
//
// Requires (in order not to be inconclusive)
// - Module: None - its in core
// - Override: Options
// - Directives: ContentDigest
// - PHP?: No
$htaccess = <<<'EOD'
<IfModule mod_xxx.c>
ContentDigest On
</IfModule>
<IfModule !mod_xxx.c>
ContentDigest Off
</IfModule>
EOD;
$htaccess = str_replace('mod_xxx', 'mod_' . $this->moduleName, $htaccess);
return [
'subdir' => $this->getSubDir() . '/content-digest',
'files' => [
['.htaccess', $htaccess],
['request-me.txt', 'thanks'],
],
'request' => 'request-me.txt',
'interpretation' => [
['success', 'headers', 'contains-key', 'Content-MD5'],
['failure', 'headers', 'not-contains-key', 'Content-MD5'],
]
];
}
/**
* @return array
*/
private function getDirectoryIndexBasedTest()
{
// Test files, method: Using DirectoryIndex
// --------------------------------------------------
//
// Requires (in order not to be inconclusive)
// - Module: mod_dir (Status: Base)
// - Override: Indexes
// - Directives: DirectoryIndex
// - PHP?: No
$htaccess = <<<'EOD'
<IfModule mod_xxx.c>
DirectoryIndex 1.html
</IfModule>
<IfModule !mod_xxx.c>
DirectoryIndex 0.html
</IfModule>
EOD;
$htaccess = str_replace('mod_xxx', 'mod_' . $this->moduleName, $htaccess);
return [
'subdir' => $this->getSubDir() . '/directory-index',
'files' => [
['.htaccess', $htaccess],
['0.html', '0'],
['1.html', '1'],
],
'request' => '', // empty - in order to request the index
'interpretation' => [
['success', 'body', 'equals', '1'],
['failure', 'body', 'equals', '0'],
]
];
}
/**
* @return array
*/
private function getAddTypeBasedTest()
{
// Test files, method: Using AddType
// --------------------------------------------------
//
// Requires (in order not to be inconclusive)
// - Module: mod_mime
// - Override: FileInfo
// - Directives: AddType and IfModule
// - PHP?: No
$htaccess = <<<'EOD'
<IfModule mod_xxx.c>
AddType image/gif .test
</IfModule>
<IfModule !mod_xxx.c>
AddType image/jpeg .test
</IfModule>
EOD;
$htaccess = str_replace('mod_xxx', 'mod_' . $this->moduleName, $htaccess);
return [
'subdir' => $this->getSubDir() . '/add-type',
'files' => [
['.htaccess', $htaccess],
['request-me.test', 'hi'],
],
'request' => 'request-me.test',
'interpretation' => [
['success', 'headers', 'contains-key-value', 'Content-Type', 'image/gif'],
['failure', 'headers', 'contains-key-value', 'Content-Type', 'image/jpeg'],
]
];
}
/**
* @return bool|null
*/
private function run2()
{
$hct = $this->getHtaccessCapabilityTester();
$testResult = $hct->customTest($this->getServerSignatureBasedTest());
if (!is_null($testResult)) {
// PHP
return $testResult;
}
if ($hct->contentDigestWorks()) {
// Override: Options
return $hct->customTest($this->getContentDigestBasedTest());
}
if ($hct->addTypeWorks()) {
// Override: FileInfo, Status: Base (mod_mime)
return $hct->customTest($this->getAddTypeBasedTest());
}
if ($hct->directoryIndexWorks()) {
// Override: Indexes, Status: Base (mod_dir)
return $hct->customTest($this->getDirectoryIndexBasedTest());
}
if ($hct->rewriteWorks()) {
// Override: FileInfo, Module: mod_rewrite
return $hct->customTest($this->getRewriteBasedTest());
}
if ($hct->headerSetWorks()) {
//Override: FileInfo, Module: mod_headers
return $hct->customTest($this->getHeaderSetBasedTest());
}
return null;
}
/**
* Run the test.
*
* @param string $baseDir Directory on the server where the test files can be put
* @param string $baseUrl The base URL of the test files
*
* @return TestResult Returns a test result
*/
public function run($baseDir, $baseUrl)
{
$this->prepareForRun($baseDir, $baseUrl);
$hct = $this->getHtaccessCapabilityTester();
$htaccessEnabledTest = $hct->htaccessEnabled();
if ($htaccessEnabledTest === false) {
return new TestResult(false, '.htaccess files are ignored');
} elseif (is_null($htaccessEnabledTest)) {
// We happen to know that if that test cannot establish anything,
// then none of the usual weapons works - we can surrender right away
return new TestResult(null, 'no methods available - we surrender early');
}
$status = $this->run2();
if (is_null($status)) {
return new TestResult(null, 'no methods worked');
} else {
return new TestResult($status, '');
}
}
}