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>
This commit is contained in:
2025-09-23 10:22:32 +02:00
commit 37cf714058
553 changed files with 55249 additions and 0 deletions

9
vendor/rosell-dk/file-util/LICENSE vendored Normal file
View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) 2018 Bjørn Rosell
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

22
vendor/rosell-dk/file-util/README.md vendored Normal file
View File

@@ -0,0 +1,22 @@
# File Util
[![Build Status](https://github.com/rosell-dk/file-util/workflows/build/badge.svg)](https://github.com/rosell-dk/file-util/actions/workflows/php.yml)
[![Software License](https://img.shields.io/badge/license-MIT-418677.svg)](https://github.com/rosell-dk/file-util/blob/master/LICENSE)
[![Coverage](https://img.shields.io/endpoint?url=https://little-b.it/file-util/code-coverage/coverage-badge.json)](http://little-b.it/file-util/code-coverage/coverage/index.html)
[![Latest Stable Version](https://img.shields.io/packagist/v/rosell-dk/file-util.svg)](https://packagist.org/packages/rosell-dk/file-util)
[![Minimum PHP Version](https://img.shields.io/packagist/php-v/rosell-dk/file-util)](https://php.net)
Just a bunch of handy methods for dealing with files and paths:
- *FileExists::fileExists($path)*:\
A well-behaved version of *file_exists* that throws upon failure rather than emitting a warning
- *FileExists::fileExistsTryHarder($path)*:\
Also well-behaved. Tries FileExists::fileExists(). In case of failure, tries exec()-based implementation
- *PathValidator::checkPath($path)*:\
Check if path looks valid and doesn't contain suspecious patterns
- *PathValidator::checkFilePathIsRegularFile($path)*:\
Check if path points to a regular file (and doesnt match suspecious patterns)

View File

@@ -0,0 +1,69 @@
{
"name": "rosell-dk/file-util",
"description": "Functions for dealing with files and paths",
"type": "library",
"license": "MIT",
"keywords": ["files", "path", "util"],
"scripts": {
"ci": [
"@test",
"@phpcs-all",
"@composer validate --no-check-all --strict",
"@phpstan-global"
],
"phpunit": "phpunit --coverage-text",
"test": "phpunit --coverage-text=build/coverage.txt --coverage-clover=build/coverage.clover --coverage-html=build/coverage --whitelist=src tests",
"test-no-cov": "phpunit --no-coverage tests",
"test-41": "phpunit --no-coverage --configuration 'phpunit-41.xml.dist'",
"test-with-coverage": "phpunit --coverage-text --configuration 'phpunit-with-coverage.xml.dist'",
"test-41-with-coverage": "phpunit --coverage-text --configuration 'phpunit-41.xml.dist'",
"cs-fix-all": [
"php-cs-fixer fix src"
],
"cs-fix": "php-cs-fixer fix",
"cs-dry": "php-cs-fixer fix --dry-run --diff",
"phpcs": "phpcs --standard=phpcs-ruleset.xml",
"phpcs-all": "phpcs --standard=phpcs-ruleset.xml src",
"phpcbf": "phpcbf --standard=PSR2",
"phpstan": "vendor/bin/phpstan analyse src --level=4",
"phpstan-global-old": "~/.composer/vendor/bin/phpstan analyse src --level=4",
"phpstan-global": "~/.config/composer/vendor/bin/phpstan analyse src --level=4"
},
"extra": {
"scripts-descriptions": {
"ci": "Run tests before CI",
"phpcs": "Checks coding styles (PSR2) of file/dir, which you must supply. To check all, supply 'src'",
"phpcbf": "Fix coding styles (PSR2) of file/dir, which you must supply. To fix all, supply 'src'",
"cs-fix-all": "Fix the coding style of all the source files, to comply with the PSR-2 coding standard",
"cs-fix": "Fix the coding style of a PHP file or directory, which you must specify.",
"test": "Launches the preconfigured PHPUnit"
}
},
"autoload": {
"psr-4": { "FileUtil\\": "src/" }
},
"autoload-dev": {
"psr-4": { "FileUtil\\Tests\\": "tests/" }
},
"authors": [
{
"name": "Bjørn Rosell",
"homepage": "https://www.bitwise-it.dk/contact",
"role": "Project Author"
}
],
"require": {
"php": ">=5.4",
"rosell-dk/exec-with-fallback": "^1.0.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.11",
"phpunit/phpunit": "^9.3",
"squizlabs/php_codesniffer": "3.*",
"phpstan/phpstan": "^1.5",
"mikey179/vfsstream": "^1.6"
},
"config": {
"sort-packages": true
}
}

View File

@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<ruleset name="Custom Standard">
<description>PSR2 without line ending rule - let git manage the EOL cross the platforms</description>
<rule ref="PSR2" />
<rule ref="Generic.Files.LineEndings">
<exclude name="Generic.Files.LineEndings.InvalidEOLChar"/>
</rule>
</ruleset>

View File

@@ -0,0 +1,96 @@
<?php
namespace FileUtil;
use FileUtil\FileExistsUsingExec;
/**
* A fileExist function free of deception
*
* @package FileUtil
* @author Bjørn Rosell <it@rosell.dk>
*/
class FileExists
{
private static $lastWarning;
/**
* A warning handler that registers that a warning has occured and suppresses it.
*
* The function is a callback used with "set_error_handler".
* It is declared public because it needs to be accessible from the point where the warning is triggered.
*
* @param integer $errno
* @param string $errstr
* @param string $errfile
* @param integer $errline
*
* @return void
*/
public static function warningHandler($errno, $errstr, $errfile, $errline)
{
self::$lastWarning = [$errstr, $errno];
// Suppress the warning by returning void
return;
}
/**
* A well behaved replacement for file_exist that throws upon failure rather than emitting a warning.
*
* @throws \Exception Throws an exception in case file_exists emits a warning
* @return boolean True if file exists. False if it doesn't.
*/
public static function fileExists($path)
{
// There is a challenges here:
// We want to suppress warnings, but at the same time we want to know that it happened.
// We achieve this by registering an error handler
set_error_handler(
array('FileUtil\FileExists', "warningHandler"),
E_WARNING | E_USER_WARNING | E_NOTICE | E_USER_NOTICE
);
self::$lastWarning = null;
$found = @file_exists($path);
// restore previous error handler immediately
restore_error_handler();
// If file_exists returns true, we can rely on there being a file there
if ($found) {
return true;
}
// file_exists returned false.
// this result is only trustworthy if no warning was emitted.
if (is_null(self::$lastWarning)) {
return false;
}
list($errstr, $errno) = self::$lastWarning;
throw new \Exception($errstr, $errno);
}
/**
* A fileExist doing the best it can.
*
* @throws \Exception If it cannot be determined if the file exists
* @return boolean|null True if file exists. False if it doesn't.
*/
public static function fileExistsTryHarder($path)
{
try {
$result = self::fileExists($path);
} catch (\Exception $e) {
try {
$result = FileExistsUsingExec::fileExists($path);
} catch (\Exception $e) {
throw new \Exception('Cannot determine if file exists or not');
} catch (\Throwable $e) {
throw new \Exception('Cannot determine if file exists or not');
}
}
return $result;
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace FileUtil;
use ExecWithFallback\ExecWithFallback;
/**
* A fileExist implementation using exec()
*
* @package FileUtil
* @author Bjørn Rosell <it@rosell.dk>
*/
class FileExistsUsingExec
{
/**
* A fileExist based on an exec call.
*
* @throws \Exception If exec cannot be called
* @return boolean|null True if file exists. False if it doesn't.
*/
public static function fileExists($path)
{
if (!ExecWithFallback::anyAvailable()) {
throw new \Exception(
'cannot determine if file exists using exec() or similar - the function is unavailable'
);
}
// Lets try to find out by executing "ls path/to/cwebp"
ExecWithFallback::exec('ls ' . $path, $output, $returnCode);
if (($returnCode == 0) && (isset($output[0]))) {
return true;
}
// We assume that "ls" command is general available!
// As that failed, we can conclude the file does not exist.
return false;
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace FileUtil;
use FileUtil\FileExists;
/**
*
*
* @package FileUtil
* @author Bjørn Rosell <it@rosell.dk>
*/
class PathValidator
{
/**
* Check if path looks valid and doesn't contain suspecious patterns.
* The path must meet the following criteria:
*
* - It must be a string
* - No NUL character
* - No control characters between 0-20
* - No phar stream wrapper
* - No php stream wrapper
* - No glob stream wrapper
* - Not empty path
*
* @throws \Exception In case the path doesn't meet all criteria
*/
public static function checkPath($path)
{
if (gettype($path) !== 'string') {
throw new \Exception('File path must be string');
}
if (strpos($path, chr(0)) !== false) {
throw new \Exception('NUL character is not allowed in file path!');
}
if (preg_match('#[\x{0}-\x{1f}]#', $path)) {
// prevents line feed, new line, tab, charater return, tab, ets.
throw new \Exception('Control characters #0-#20 not allowed in file path!');
}
// Prevent phar stream wrappers (security threat)
if (preg_match('#^phar://#', $path)) {
throw new \Exception('phar stream wrappers are not allowed in file path');
}
if (preg_match('#^(php|glob)://#', $path)) {
throw new \Exception('php and glob stream wrappers are not allowed in file path');
}
if (empty($path)) {
throw new \Exception('File path is empty!');
}
}
/**
* Check if path points to a regular file (and doesnt match suspecious patterns).
*
* @throws \Exception In case the path doesn't point to a regular file or matches suspecious patterns
*/
public static function checkFilePathIsRegularFile($path)
{
self::checkPath($path);
if (!FileExists::fileExists($path)) {
throw new \Exception('File does not exist');
}
if (@is_dir($path)) {
throw new \Exception('Expected a regular file, not a dir');
}
}
}