<?php
namespace WebPExpress;
use \WebPExpress\Paths;
class SelfTestHelper
{
public static function deleteFilesInDir($dir, $filePattern = "*")
{
foreach (glob($dir . DIRECTORY_SEPARATOR . $filePattern) as $filename) {
unlink($filename);
}
}
/**
* Remove files in dir and the dir. Does not remove files recursively.
*/
public static function deleteDir($dir)
{
if (@file_exists($dir)) {
self::deleteFilesInDir($dir);
rmdir($dir);
}
}
public static function deleteTestImagesInFolder($rootId)
{
$testDir = Paths::getAbsDirById($rootId) . '/webp-express-test-images';
self::deleteDir($testDir);
}
public static function cleanUpTestImages($rootId, $config)
{
// Clean up test images in source folder
self::deleteTestImagesInFolder($rootId);
// Clean up dummy webp images in cache folder for the root
$cacheDirForRoot = Paths::getCacheDirForImageRoot(
$config['destination-folder'],
$config['destination-structure'],
$rootId
);
$testDir = $cacheDirForRoot . '/webp-express-test-images';
self::deleteDir($testDir);
}
public static function copyFile($source, $destination)
{
$log = [];
if (@copy($source, $destination)) {
return [true, $log];
} else {
$log[] = 'Failed to copy *' . $source . '* to *' . $destination . '*';
if (!@file_exists($source)) {
$log[] = 'The source file was not found';
} else {
if (!@file_exists(dirname($destination))) {
$log[] = 'The destination folder does not exist!';
} else {
$log[] = 'This is probably a permission issue. Check that your webserver has permission to ' .
'write files in the directory (*' . dirname($destination) . '*)';
}
}
return [false, $log];
}
}
public static function randomDigitsAndLetters($length)
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
public static function copyTestImageToRoot($rootId, $imageType = 'jpeg')
{
// TODO: Copy to a subfolder instead
// TODO: Use smaller jpeg / pngs please.
$log = [];
switch ($imageType) {
case 'jpeg':
$fileNameToCopy = 'very-small.jpg';
break;
case 'png':
$fileNameToCopy = 'test.png';
break;
}
$testSource = Paths::getPluginDirAbs() . '/webp-express/test/' . $fileNameToCopy;
$filenameOfDestination = self::randomDigitsAndLetters(6) . '.' . strtoupper($imageType);
//$filenameOfDestination = self::randomDigitsAndLetters(6) . '.' . $imageType;
$log[] = 'Copying ' . strtoupper($imageType) . ' to ' . $rootId . ' folder (*webp-express-test-images/' . $filenameOfDestination . '*)';
$destDir = Paths::getAbsDirById($rootId) . '/webp-express-test-images';
$destination = $destDir . '/' . $filenameOfDestination;
if (!@file_exists($destDir)) {
if (!@mkdir($destDir)) {
$log[count($log) - 1] .= '. FAILED';
$log[] = 'Failed to create folder for test images: ' . $destDir;
return [$log, false, ''];
}
}
list($success, $errors) = self::copyFile($testSource, $destination);
if (!$success) {
$log[count($log) - 1] .= '. FAILED';
$log = array_merge($log, $errors);
return [$log, false, ''];
} else {
$log[count($log) - 1] .= '. ok!';
$log[] = 'We now have a ' . $imageType . ' stored here:';
$log[] = '*' . $destination . '*';
}
return [$log, true, $filenameOfDestination];
}
public static function copyTestImageToUploadFolder($imageType = 'jpeg')
{
return self::copyTestImageToRoot('uploads', $imageType);
}
public static function copyDummyWebPToCacheFolder($rootId, $destinationFolder, $destinationExtension, $destinationStructure, $sourceFileName, $imageType = 'jpeg')
{
$log = [];
$dummyWebP = Paths::getPluginDirAbs() . '/webp-express/test/test.jpg.webp';
$log[] = 'Copying dummy webp to the cache root for ' . $rootId;
$destDir = Paths::getCacheDirForImageRoot($destinationFolder, $destinationStructure, $rootId);
if (!file_exists($destDir)) {
$log[] = 'The folder did not exist. Creating folder at: ' . $destinationFolder;
if (!mkdir($destDir, 0777, true)) {
$log[] = 'Failed creating folder!';
return [$log, false, ''];
}
}
$destDir .= '/webp-express-test-images';
if (!file_exists($destDir)) {
if (!mkdir($destDir, 0755, false)) {
$log[] = 'Failed creating the folder for the test images:';
$log[] = $destDir;
$log[] = 'To run this test, you must grant write permissions';
return [$log, false, ''];
}
}
$filenameOfDestination = ConvertHelperIndependent::appendOrSetExtension(
$sourceFileName,
$destinationFolder,
$destinationExtension,
($rootId == 'uploads')
);
//$filenameOfDestination = $destinationFileNameNoExt . ($destinationExtension == 'append' ? '.' . $imageType : '') . '.webp';
$destination = $destDir . '/' . $filenameOfDestination;
list($success, $errors) = self::copyFile($dummyWebP, $destination);
if (!$success) {
$log[count($log) - 1] .= '. FAILED';
$log = array_merge($log, $errors);
return [$log, false, ''];
} else {
$log[count($log) - 1] .= '. ok!';
$log[] = 'We now have a webp file stored here:';
$log[] = '*' . $destination . '*';
$log[] = '';
}
return [$log, true, $destination];
}
/**
* Perform HTTP request.
*
* @param string $requestUrl URL
* @param array $args Args to pass to wp_remote_get. Note however that "redirection" is set to 0
* @param int $maxRedirects For internal use
* @return array The result
* $success (boolean): If we got a 200 response in the end (after max 2 redirects)
* $log (array) : Message log
* $results : Array of results from wp_remote_get. If no redirection occured, it will only contain one item.
*
*/
public static function remoteGet($requestUrl, $args = [], $maxRedirects = 2)
{
$log = [];
$args['redirection'] = 0;
if (defined('WP_DEBUG') && WP_DEBUG ) {
// Prevent errors with unverified certificates (#379)
$args['sslverify'] = false;
}
$log[] = 'Request URL: ' . $requestUrl;
$results = [];
$wpResult = wp_remote_get($requestUrl, $args);
if (is_wp_error($wpResult)) {
$log[] = 'The remote request errored';
$log[] = $wpResult->get_error_message();
//$log[] = print_r($wpResult, true);
return [false, $log, $results];
}
if (!is_wp_error($wpResult) && !isset($wpResult['headers'])) {
$wpResult['headers'] = [];
}
$results[] = $wpResult;
$responseCode = $wpResult['response']['code'];
$log[] = 'Response: ' . $responseCode . ' ' . $wpResult['response']['message'];
$log = array_merge($log, SelfTestHelper::printHeaders($wpResult['headers']));
if (isset($wpResult['headers']['content-type'])) {
if (strpos($wpResult['headers']['content-type'], 'text/html') !== false) {
if (isset($wpResult['body']) && (!empty($wpResult['body']))) {
$log[] = 'Body:';
$log[] = print_r($wpResult['body'], true);
}
}
}
if (($responseCode == '302') || ($responseCode == '301')) {
if ($maxRedirects > 0) {
if (isset($wpResult['headers']['location'])) {
$url = $wpResult['headers']['location'];
if (strpos($url, 'http') !== 0) {
$url = $requestUrl . $url;
}
$log[] = 'Following that redirect';
list($success, $newLog, $newResult) = self::remoteGet($url, $args, $maxRedirects - 1);
$log = array_merge($log, $newLog);
$results = array_merge($results, $newResult);
return [$success, $log, $results];
}
} else {
$log[] = 'Not following the redirect (max redirects exceeded)';
}
}
$success = ($responseCode == '200');
return [$success, $log, $results];
}
public static function hasHeaderContaining($headers, $headerToInspect, $containString)
{
if (!isset($headers[$headerToInspect])) {
return false;
}
// If there are multiple headers, check all
if (gettype($headers[$headerToInspect]) == 'string') {
$h = [$headers[$headerToInspect]];
} else {
$h = $headers[$headerToInspect];
}
foreach ($h as $headerValue) {
if (stripos($headerValue, $containString) !== false) {
return true;
}
}
return false;
}
public static function hasVaryAcceptHeader($headers)
{
if (!isset($headers['vary'])) {
return false;
}
// There may be multiple Vary headers. Or they might be combined in one.
// Both are acceptable, according to https://stackoverflow.com/a/28799169/842756
if (gettype($headers['vary']) == 'string') {
$varyHeaders = [$headers['vary']];
} else {
$varyHeaders = $headers['vary'];
}
foreach ($varyHeaders as $headerValue) {
$values = explode(',', $headerValue);
foreach ($values as $value) {
if (strtolower($value) == 'accept') {
return true;
}
}
}
return false;
}
/**
* @param string $rule existing|webp-on-demand|webp-realizer
*/
public static function diagnoseNoVaryHeader($rootId, $rule)
{
$log = [];
$log[] = '**However, we did not receive a Vary:Accept header. ' .
'That header should be set in order to tell proxies that the response varies depending on the ' .
'Accept header. Otherwise browsers not supporting webp might get a cached webp and vice versa.**{: .warn}';
$log[] = 'Too technical? ';
$log[] = 'Here is an explanation of what this means: ' .
'Some companies have set up proxies which caches resources. This way, if employee A have downloaded an ' .
'image and employee B requests it, the proxy can deliver the image directly to employee B without needing to ' .
'send a request to the server. ' .
'This is clever, but it can go wrong. If B for some reason is meant to get another image than A, it will not ' .
'happen, as the server does not get the request. That is where the Vary header comes in. It tells the proxy ' .
'that the image is dependent upon something. In this case, we need to signal proxies that the image depends upon ' .
'the "Accept" header, as this is the one browsers use to tell the server if it accepts webps or not. ' .
'We do that using the "Vary:Accept" header. However - it is missing :( ' .
'Which means that employees at (larger) companies might experience problems if some are using browsers ' .
'that supports webp and others are using browsers that does not. Worst case is that the request to an image ' .
'is done with a browser that supports webp, as this will cache the webp in the proxy, and deliver webps to ' .
'all employees - even to those who uses browsers that does not support webp. These employees will get blank images.';
if ($rule == 'existing') {
$log[] = 'So, what should you do? **I would recommend that you either try to fix the problem with the missing Vary:Accept ' .
'header or change to "CDN friendly" mode.**{: .warn}';
} elseif ($rule == 'webp-on-demand') {
$log[] = 'So, what should you do? **I would recommend that you either try to fix the problem with the missing Vary:Accept ' .
'header or disable the "Enable redirection to converter?" option and use another way to get the images converted - ie ' .
'Bulk Convert or Convert on Upload**{: .warn}';
}
return $log;
}
public static function hasCacheControlOrExpiresHeader($headers)
{
if (isset($headers['cache-control'])) {
return true;
}
if (isset($headers['expires'])) {
return true;
}
return false;
}
public static function flattenHeaders($headers)
{
$log = [];
foreach ($headers as $headerName => $headerValue) {
if (gettype($headerValue) == 'array') {
foreach ($headerValue as $i => $value) {
$log[] = [$headerName, $value];
}
} else {
$log[] = [$headerName, $headerValue];
}
}
return $log;
}
public static function printHeaders($headers)
{
$log = [];
$log[] = '#### Response headers:';
$headersFlat = self::flattenHeaders($headers);
//
foreach ($headersFlat as $i => list($headerName, $headerValue)) {
if ($headerName == 'x-webp-express-error') {
$headerValue = '**' . $headerValue . '**{: .error}';
}
$log[] = '- ' . $headerName . ': ' . $headerValue;
}
$log[] = '';
return $log;
}
private static function trueFalseNullString($var)
{
if ($var === true) {
return 'yes';
}
if ($var === false) {
return 'no';
}
return 'could not be determined';
}
public static function systemInfo()
{
$log = [];
$log[] = '#### System info:';
$log[] = '- PHP version: ' . phpversion();
$log[] = '- OS: ' . PHP_OS;
$log[] = '- Server software: ' . $_SERVER["SERVER_SOFTWARE"];
$log[] = '- Document Root status: ' . Paths::docRootStatusText();
if (PathHelper::isDocRootAvailable()) {
$log[] = '- Document Root: ' . $_SERVER['DOCUMENT_ROOT'];
}
if (PathHelper::isDocRootAvailableAndResolvable()) {
if ($_SERVER['DOCUMENT_ROOT'] != realpath($_SERVER['DOCUMENT_ROOT'])) {
$log[] = '- Document Root (symlinked resolved): ' . realpath($_SERVER['DOCUMENT_ROOT']);
}
}
$log[] = '- Document Root: ' . Paths::docRootStatusText();
$log[] = '- Apache module "mod_rewrite" enabled?: ' . self::trueFalseNullString(PlatformInfo::gotApacheModule('mod_rewrite'));
$log[] = '- Apache module "mod_headers" enabled?: ' . self::trueFalseNullString(PlatformInfo::gotApacheModule('mod_headers'));
return $log;
}
public static function wordpressInfo()
{
$log = [];
$log[] = '#### Wordpress info:';
$log[] = '- Version: ' . get_bloginfo('version');
$log[] = '- Multisite?: ' . self::trueFalseNullString(is_multisite());
$log[] = '- Is wp-content moved?: ' . self::trueFalseNullString(Paths::isWPContentDirMoved());
$log[] = '- Is uploads moved out of wp-content?: ' . self::trueFalseNullString(Paths::isUploadDirMovedOutOfWPContentDir());
$log[] = '- Is plugins moved out of wp-content?: ' . self::trueFalseNullString(Paths::isPluginDirMovedOutOfWpContent());
$log[] = '';
$log[] = '#### Image roots (absolute paths)';
foreach (Paths::getImageRootIds() as $rootId) {
$absDir = Paths::getAbsDirById($rootId);
if (PathHelper::pathExistsAndIsResolvable($absDir) && ($absDir != realpath($absDir))) {
$log[] = '*' . $rootId . '*: ' . $absDir . ' (resolved for symlinks: ' . realpath($absDir) . ')';
} else {
$log[] = '*' . $rootId . '*: ' . $absDir;
}
}
$log[] = '#### Image roots (relative to document root)';
foreach (Paths::getImageRootIds() as $rootId) {
$absPath = Paths::getAbsDirById($rootId);
if (PathHelper::canCalculateRelPathFromDocRootToDir($absPath)) {
$log[] = '*' . $rootId . '*: ' . PathHelper::getRelPathFromDocRootToDirNoDirectoryTraversalAllowed($absPath);
} else {
$log[] = '*' . $rootId . '*: ' . 'n/a (not within document root)';
}
}
$log[] = '#### Image roots (URLs)';
foreach (Paths::getImageRootIds() as $rootId) {
$url = Paths::getUrlById($rootId);
$log[] = '*' . $rootId . '*: ' . $url;
}
return $log;
}
public static function configInfo($config)
{
$log = [];
$log[] = '#### WebP Express configuration info:';
$log[] = '- Destination folder: ' . $config['destination-folder'];
$log[] = '- Destination extension: ' . $config['destination-extension'];
$log[] = '- Destination structure: ' . $config['destination-structure'];
//$log[] = 'Image types: ' . ;
//$log[] = '';
$log[] = '(To view all configuration, take a look at the config file, which is stored in *' . Paths::getConfigFileName() . '*)';
//$log[] = '- Config file: (config.json)';
//$log[] = "'''\n" . json_encode($config, JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK | JSON_PRETTY_PRINT) . "\n'''\n";
return $log;
}
public static function htaccessInfo($config, $printRules = true)
{
$log = [];
//$log[] = '*.htaccess info:*';
//$log[] = '- Image roots with WebP Express rules: ' . implode(', ', HTAccess::getRootsWithWebPExpressRulesIn());
$log[] = '#### .htaccess files that WebP Express have placed rules in the following files:';
$rootIds = HTAccess::getRootsWithWebPExpressRulesIn();
foreach ($rootIds as $imageRootId) {
$log[] = '- ' . Paths::getAbsDirById($imageRootId) . '/.htaccess';
}
foreach ($rootIds as $imageRootId) {
$log = array_merge($log, self::rulesInImageRoot($config, $imageRootId));
}
return $log;
}
public static function rulesInImageRoot($config, $imageRootId)
{
$log = [];
$file = Paths::getAbsDirById($imageRootId) . '/.htaccess';
$log[] = '#### WebP rules in *' .
($imageRootId == 'cache' ? 'webp image cache' : $imageRootId) . '*:';
$log[] = 'File: ' . $file;
if (!HTAccess::haveWeRulesInThisHTAccess($file)) {
$log[] = '**NONE!**{: .warn}';
} else {
$weRules = HTAccess::extractWebPExpressRulesFromHTAccess($file);
// remove unindented comments
//$weRules = preg_replace('/^\#\s[^\n\r]*[\n\r]+/ms', '', $weRules);
// remove comments in the beginning
$weRulesArr = preg_split("/\r\n|\n|\r/", $weRules); // https://stackoverflow.com/a/11165332/842756
while ((strlen($weRulesArr[0]) > 0) && ($weRulesArr[0][0] == '#')) {
array_shift($weRulesArr);
}
$weRules = implode("\n", $weRulesArr);
$log[] = '```' . $weRules . '```';
}
return $log;
}
public static function rulesInUpload($config)
{
return self::rulesInImageRoot($config, 'uploads');
}
public static function allInfo($config)
{
$log = [];
$log = array_merge($log, self::systemInfo());
$log = array_merge($log, self::wordpressInfo());
$log = array_merge($log, self::configInfo($config));
$log = array_merge($log, self::capabilityTests($config));
$log = array_merge($log, self::htaccessInfo($config, true));
//$log = array_merge($log, self::rulesInImageRoot($config, 'upload'));
//$log = array_merge($log, self::rulesInImageRoot($config, 'wp-content'));
return $log;
}
public static function capabilityTests($config)
{
$capTests = $config['base-htaccess-on-these-capability-tests'];
$log = [];
$log[] = '#### Live tests of .htaccess capabilities / system configuration:';
$log[] = 'Unless noted otherwise, the tests are run in *wp-content/webp-express/htaccess-capability-tester*. ';
$log[] = 'WebPExpress currently treats the results as they neccessarily applies to all scopes (upload, themes, etc), ';
$log[] = 'but note that a server might be configured to have mod_rewrite disallowed in some folders and allowed in others.';
/*$log[] = 'Exactly what you can do in a *.htaccess* depends on the server setup. WebP Express ' .
'makes some live tests to verify if a certain feature in fact works. This is done by creating ' .
'test files (*.htaccess* files and php files) in a dir inside the content dir and running these. ' .
'These test results are used when creating the rewrite rules. Here are the results:';*/
// $log[] = '';
$log[] = '- .htaccess files enabled?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::htaccessEnabled());
$log[] = '- mod_rewrite working?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::modRewriteWorking());
$log[] = '- mod_headers loaded?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::modHeadersLoaded());
$log[] = '- mod_headers working (header set): ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::modHeaderWorking());
//$log[] = '- passing variables from *.htaccess* to PHP script through environment variable working?: ' . self::trueFalseNullString($capTests['passThroughEnvWorking']);
$log[] = '- passing variables from *.htaccess* to PHP script through environment variable working?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::passThroughEnvWorking());
$log[] = '- Can run php test file in plugins/webp-express/wod/ ?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::canRunTestScriptInWOD());
$log[] = '- Can run php test file in plugins/webp-express/wod2/ ?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::canRunTestScriptInWOD2());
$log[] = '- Directives for granting access like its done in wod/.htaccess allowed?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::grantAllAllowed());
/*$log[] = '- pass variable from *.htaccess* to script through header working?: ' .
self::trueFalseNullString($capTests['passThroughHeaderWorking']);*/
return $log;
}
public static function diagnoseFailedRewrite($config, $headers)
{
if (($config['destination-structure'] == 'image-roots') && (!PathHelper::isDocRootAvailableAndResolvable())) {
$log[] = 'The problem is probably this combination:';
if (!PathHelper::isDocRootAvailable()) {
$log[] = '1. Your document root isn`t available';
} else {
$log[] = '1. Your document root isn`t resolvable for symlinks (it is probably subject to open_basedir restriction)';
}
$log[] = '2. Your document root is symlinked';
$log[] = '3. The wordpress function that tells the path of the uploads folder returns the symlink resolved path';
$log[] = 'I cannot check if your document root is in fact symlinked (as document root isnt resolvable). ' .
'But if it is, there you have it. The line beginning with "RewriteCond %{REQUEST_FILENAME}"" points to your resolved root, ' .
'but it should point to your symlinked root. WebP Express cannot do that for you because it cannot discover what the symlink is. ' .
'Try changing the line manually. When it works, you can move the rules outside the WebP Express block so they dont get ' .
'overwritten. OR you can change your server configuration (document root / open_basedir restrictions)';
}
//$log[] = '## Diagnosing';
//if (PlatformInfo::isNginx()) {
if (strpos($headers['server'], 'nginx') === 0) {
// Nginx
$log[] = 'Notice that you are on Nginx and the rules that WebP Express stores in the *.htaccess* files probably does not ' .
'have any effect. ';
$log[] = 'Please read the "I am on Nginx" section in the FAQ (https://wordpress.org/plugins/webp-express/)';
$log[] = 'And did you remember to restart the nginx service after updating the configuration?';
$log[] = 'PS: If you cannot get the redirect to work, you can simply rely on Alter HTML as described in the FAQ.';
return $log;
}
$modRewriteWorking = HTAccessCapabilityTestRunner::modRewriteWorking();
if ($modRewriteWorking !== null) {
$log[] = 'Running a special designed capability test to test if rewriting works with *.htaccess* files';
}
if ($modRewriteWorking === true) {
$log[] = 'Result: Yes, rewriting works.';
$log[] = 'It seems something is wrong with the *.htaccess* rules then. You could try ' .
'to change "Destination structure" - the rules there are quite different.';
$log[] = 'It could also be that the server has cached the configuration a while. Some servers ' .
'does that. In that case, simply give it a few minutes and try again.';
} elseif ($modRewriteWorking === false) {
$log[] = 'Result: No, rewriting does not seem to work within *.htaccess* rules.';
if (PlatformInfo::definitelyNotGotModRewrite()) {
$log[] = 'It actually seems "mod_write" is disabled on your server. ' .
'**You must enable mod_rewrite on the server**';
} elseif (PlatformInfo::definitelyGotApacheModule('mod_rewrite')) {
$log[] = 'However, "mod_write" *is* enabled on your server. This seems to indicate that ' .
'*.htaccess* files has been disabled for configuration on your server. ' .
'In that case, you need to copy the WebP Express rules from the *.htaccess* files into your virtual host configuration files. ' .
'(WebP Express generates multiple *.htaccess* files. Look in the upload folder, the wp-content folder, etc).';
$log[] = 'It could however alse simply be that your server simply needs some time. ' .
'Some servers caches the *.htaccess* rules for a bit. In that case, simply give it a few minutes and try again.';
} else {
$log[] = 'However, this could be due to your server being a bit slow on picking up changes in *.htaccess*.' .
'Give it a few minutes and try again.';
}
} else {
// The mod_rewrite test could not conclude anything.
if (PlatformInfo::definitelyNotGotApacheModule('mod_rewrite')) {
$log[] = 'It actually seems "mod_write" is disabled on your server. ' .
'**You must enable mod_rewrite on the server**';
} elseif (PlatformInfo::definitelyGotApacheModule('mod_rewrite')) {
$log[] = '"mod_write" is enabled on your server, so rewriting ought to work. ' .
'However, it could be that your server setup has disabled *.htaccess* files for configuration. ' .
'In that case, you need to copy the WebP Express rules from the *.htaccess* files into your virtual host configuration files. ' .
'(WebP Express generates multiple *.htaccess* files. Look in the upload folder, the wp-content folder, etc). ';
} else {
$log[] = 'It seems something is wrong with the *.htaccess* rules. ';
$log[] = 'Or perhaps the server has cached the configuration a while. Some servers ' .
'does that. In that case, simply give it a few minutes and try again.';
}
}
$log[] = 'Note that if you cannot get redirection to work, you can switch to "CDN friendly" mode and ' .
'rely on the "Alter HTML" functionality to point to the webp images. If you do a bulk conversion ' .
'and make sure that "Convert upon upload" is activated, you should be all set. Alter HTML even handles ' .
'inline css (unless you select "picture tag" syntax). It does however not handle images in external css or ' .
'which is added dynamically with javascript.';
$log[] = '## Info for manually diagnosing';
$log = array_merge($log, self::allInfo($config));
return $log;
}
public static function diagnoseWod403or500($config, $rootId, $responseCode)
{
$log = [];
$htaccessRules = SelfTestHelper::rulesInImageRoot($config, $rootId);
$rulesText = implode('', $htaccessRules);
$rulesPointsToWod = (strpos($rulesText, '/wod/') > 0);
$rulesPointsToWod2 = (strpos($rulesText, '/wod2/') !== false);
$log[] = '';
$log[] = '**diagnosing**';
$canRunTestScriptInWod = HTAccessCapabilityTestRunner::canRunTestScriptInWOD();
$canRunTestScriptInWod2 = HTAccessCapabilityTestRunner::canRunTestScriptInWOD2();
$canRunInAnyWod = ($canRunTestScriptInWod || $canRunTestScriptInWod2);
$responsePingPhp = wp_remote_get(Paths::getPluginsUrl() . '/webp-express/wod/ping.php', ['timeout' => 7]);
$pingPhpResponseCode = wp_remote_retrieve_response_code($responsePingPhp);
$responsePingText = wp_remote_get(Paths::getPluginsUrl() . '/webp-express/wod/ping.txt', ['timeout' => 7]);
$pingTextResponseCode = wp_remote_retrieve_response_code($responsePingText);
if ($responseCode == 500) {
$log[] = 'The response was a *500 Internal Server Error*. There can be different reasons for that. ' .
'Lets dig a bit deeper...';
}
$log[] = 'Examining where the *.htaccess* rules in the ' . $rootId . ' folder points to. ';
if ($rulesPointsToWod) {
$log[] = 'They point to **wod**/webp-on-demand.php';
} elseif ($rulesPointsToWod2) {
$log[] = 'They point to **wod2**/webp-on-demand.php';
} else {
$log[] = '**There are no redirect rule to *webp-on-demand.php* in the .htaccess!**{: .warn}';
$log[] = 'Here is the rules:';
$log = array_merge($log, $htaccessRules);
}
if ($rulesPointsToWod) {
$log[] = 'Requesting simple test script "wod/ping.php"... ' .
'Result: ' . ($pingPhpResponseCode == '200' ? 'ok' : 'failed (response code: ' . $pingPhpResponseCode . ')');
//'Result: ' . ($canRunTestScriptInWod ? 'ok' : 'failed');
if ($canRunTestScriptInWod) {
if ($responseCode == '500') {
$log[] = '';
$log[] = '**As the test script works, it would seem that the explanation for the 500 internal server ' .
'error is that the PHP script (webp-on-demand.php) crashes. ' .
'You can help me by enabling debugging and post the error on the support forum on Wordpress ' .
'(https://wordpress.org/support/plugin/webp-express/), or create an issue on github ' .
'(https://github.com/rosell-dk/webp-express/issues)**';
$log[] = '';
}
} else {
$log[] = 'Requesting simple test file "wod/ping.txt". ' .
'Result: ' . ($pingTextResponseCode == '200' ? 'ok' : 'failed (response code: ' . $pingTextResponseCode . ')');
if ($canRunTestScriptInWod2) {
if ($responseCode == 500) {
if ($pingTextResponseCode == '500') {
$log[] = 'The problem appears to be that the *.htaccess* placed in *plugins/webp-express/wod/.htaccess*' .
' contains auth directives ("Allow" and "Request") and your server is set up to go fatal about it. ' .
'Luckily, it seems that running scripts in the "wod2" folder works. ' .
'**What you need to do is simply to click the "Save settings and force new .htacess rules"' .
' button. WebP Express wil then change the .htaccess rules to point to the "wod2" folder**';
} else {
$log[] = 'The problem appears to be running PHP scripts in the "wod". ' .
'Luckily, it seems that running scripts in the "wod2" folder works ' .
'(it has probably something to do with the *.htaccess* file placed in "wod"). ' .
'**What you need to do is simply to click the "Save settings and force new .htacess rules"' .
' button. WebP Express wil then change the .htaccess rules to point to the "wod2" folder**';
}
} elseif ($responseCode == 403) {
$log[] = 'The problem appears to be running PHP scripts in the "wod". ' .
'Luckily, it seems that running scripts in the "wod2" folder works ' .
'(it could perhaps have something to do with the *.htaccess* file placed in "wod", ' .
'although it ought not result in a 403). **What you need to do is simply to click the "Save settings and force new .htacess rules"' .
' button. WebP Express wil then change the .htaccess rules to point to the "wod2" folder**';
}
return $log;
}
}
}
$log[] = 'Requesting simple test script "wod2/ping.php". Result: ' . ($canRunTestScriptInWod2 ? 'ok' : 'failed');
$responsePingText2 = wp_remote_get(Paths::getPluginsUrl() . '/webp-express/wod2/ping.txt', ['timeout' => 7]);
$pingTextResponseCode2 = wp_remote_retrieve_response_code($responsePingText2);
$log[] = 'Requesting simple test file "wod2/ping.txt". ' .
'Result: ' . ($pingTextResponseCode == '200' ? 'ok' : 'failed (response code: ' . $pingTextResponseCode2 . ')');
if ($rulesPointsToWod2) {
if ($canRunTestScriptInWod2) {
if ($responseCode == '500') {
$log[] = '';
$log[] = '**As the test script works, it would seem that the explanation for the 500 internal server ' .
'error is that the PHP script (webp-on-demand.php) crashes. ' .
'You can help me by enabling debugging and post the error on the support forum on Wordpress ' .
'(https://wordpress.org/support/plugin/webp-express/), or create an issue on github ' .
'(https://github.com/rosell-dk/webp-express/issues)**';
$log[] = '';
}
} else {
if ($canRunTestScriptInWod) {
$log[] = '';
$log[] = 'The problem appears to be running PHP scripts in the "wod2" folder. ' .
'Luckily, it seems that running scripts in the "wod" folder works ' .
'**What you need to do is simply to click the "Save settings and force new .htacess rules"' .
' button. WebP Express wil then change the .htaccess rules to point to the "wod" folder**';
$log[] = '';
} else {
if ($responseCode == 500) {
if ($pingTextResponseCode2 == '500') {
$log[] = 'All our requests results in 500 Internal Error. Even ' .
'the request to plugins/webp-express/wod2/ping.txt. ' .
'Surprising!';
} else {
$log[] = 'The internal server error happens for php files, but not txt files. ' .
'It could be the result of a restrictive server configuration or the works of a security plugin. ' .
'Try to examine the .htaccess file in the plugins folder and its parent folders. ' .
'Or try to look in the httpd.conf. Look for the "AllowOverride" and the "AllowOverrideList" directives. ';
}
//$log[] = 'We get *500 Internal Server Error*';
/*
It can for example be that the *.htaccess* ' .
'in the ' . $rootId . ' folder (or a parent folder) contains directives that the server either ' .
'doesnt support or has not allowed (using AllowOverride in ie httpd.conf). It could also be that the redirect succeded, ' .
'but the *.htaccess* in the folder of the script (or a parent folder) results in such problems. Also, ' .
'it could be that the script (webp-on-demand.php) for some reason fails.';
*/
}
}
}
}
return $log;
}
}