File "SanityCheck.txt"
Full Path: /var/www/html/wordpress/wp-content/plugins/wp-optimize/vendor/rosell-dk/webp-convert/src/Helpers/SanityCheck.txt
File size: 7.41 KB
MIME-type: text/x-php
Charset: utf-8
<?php
namespace WebPConvert\Helpers;
use WebPConvert\Helpers\Sanitize;
use WebPConvert\Exceptions\SanityException;
class SanityCheck
{
/**
*
* @param string $input string to test for NUL char
*/
public static function mustBeString($input, $errorMsg = 'String expected')
{
if (gettype($input) !== 'string') {
throw new SanityException($errorMsg);
}
return $input;
}
/**
* The NUL character is a demon, because it can be used to bypass other tests
* See https://st-g.de/2011/04/doing-filename-checks-securely-in-PHP.
*
* @param string $input string to test for NUL char
*/
public static function noNUL($input, $errorMsg = 'NUL character is not allowed')
{
self::mustBeString($input);
if (strpos($input, chr(0)) !== false) {
throw new SanityException($errorMsg);
}
return $input;
}
/**
* Prevent control chararters (#00 - #20).
*
* This prevents line feed, new line, tab, charater return, tab, ets.
* https://www.rapidtables.com/code/text/ascii-table.html
*
* @param string $input string to test for control characters
*/
public static function noControlChars($input)
{
self::mustBeString($input);
self::noNUL($input);
if (preg_match('#[\x{0}-\x{1f}]#', $input)) {
throw new SanityException('Control characters are not allowed');
}
return $input;
}
/**
*
* @param mixed $input something that may not be empty
*/
public static function notEmpty($input, $errorMsg = 'Must be non-empty')
{
if (empty($input)) {
throw new SanityException($input);
}
return $input;
}
public static function noDirectoryTraversal($input, $errorMsg = 'Directory traversal is not allowed')
{
self::mustBeString($input);
self::noControlChars($input);
if (preg_match('#\.\.\/#', $input)) {
throw new SanityException($errorMsg);
}
return $input;
}
public static function noStreamWrappers($input, $errorMsg = 'Stream wrappers are not allowed')
{
self::mustBeString($input);
self::noControlChars($input);
// Prevent stream wrappers ("phar://", "php://" and the like)
// https://www.php.net/manual/en/wrappers.phar.php
if (preg_match('#^\\w+://#', Sanitize::removeNUL($input))) {
throw new SanityException($errorMsg);
}
return $input;
}
public static function path($input)
{
self::notEmpty($input);
self::mustBeString($input);
self::noControlChars($input);
self::noDirectoryTraversal($input);
self::noStreamWrappers($input);
return $input;
}
public static function pathWithoutDirectoryTraversal($input)
{
return self::path($input);
}
public static function absPathMicrosoftStyle($input, $errorMsg = 'Not an fully qualified Windows path')
{
// On microsoft we allow [drive letter]:\
if (!preg_match("#^[A-Z]:\\\\|/#", $input)) {
throw new SanityException($errorMsg . ':' . $input);
}
return $input;
}
public static function absPath($input, $errorMsg = 'Not an absolute path')
{
if ((strpos($input, '/') !== 0)) {
// Check if we are on Microsoft
$onMicrosoft = false;
if (isset($_SERVER['SERVER_SOFTWARE'])) {
if (strpos(strtolower($_SERVER['SERVER_SOFTWARE']), 'microsoft') !== false) {
$onMicrosoft = true;
}
}
switch (PHP_OS) {
case "WINNT":
case "WIN32":
case "INTERIX":
case "UWIN":
case "UWIN-W7":
$onMicrosoft = true;
break;
}
if (!$onMicrosoft) {
throw new SanityException($errorMsg . ':' . $input);
}
self::absPathMicrosoftStyle($input);
}
return self::path($input);
}
public static function pathBeginsWith($input, $beginsWith, $errorMsg = 'Path is outside allowed path')
{
self::path($input);
if (!(strpos($input, $beginsWith) === 0)) {
throw new SanityException($errorMsg);
}
return $input;
}
public static function findClosestExistingFolderSymLinksExpanded($input) {
$levelsUp = 1;
//echo 'input:' . $input;
while (true) {
$dir = dirname($input, $levelsUp);
//echo 'dir:' . $dir . '<br>';
$realPathResult = realpath($dir);
if ($realPathResult !== false) {
return $realPathResult;
}
if (($dir == '/') || (strlen($dir) < 4)) {
return $dir;
}
$levelsUp++;
}
return '/';
}
public static function pathBeginsWithSymLinksExpanded($input, $beginsWith, $errorMsg = 'Path is outside allowed path') {
$closestExistingFolder = self::findClosestExistingFolderSymLinksExpanded($input);
//throw new SanityException('hm.' . $input . ' : <br>' . $closestExistingFolder);
self::pathBeginsWith($closestExistingFolder, $beginsWith, $errorMsg);
}
public static function absPathExists($input, $errorMsg = 'Path does not exist')
{
self::absPath($input);
if (@!file_exists($input)) {
throw new SanityException($errorMsg);
}
return $input;
}
public static function absPathExistsAndIsDir(
$input,
$errorMsg = 'Path points to a file (it should point to a directory)'
) {
self::absPathExists($input);
if (!is_dir($input)) {
throw new SanityException($errorMsg);
}
return $input;
}
public static function absPathExistsAndIsFile(
$input,
$errorMsg = 'Path points to a directory (it should not do that)'
) {
self::absPathExists($input, 'File does not exist');
if (@is_dir($input)) {
throw new SanityException($errorMsg);
}
return $input;
}
public static function absPathExistsAndIsNotDir(
$input,
$errorMsg = 'Path points to a directory (it should point to a file)'
) {
self::absPathExistsAndIsFile($input, $errorMsg);
return $input;
}
public static function pregMatch($pattern, $input, $errorMsg = 'Does not match expected pattern')
{
self::noNUL($input);
self::mustBeString($input);
if (!preg_match($pattern, $input)) {
throw new SanityException($errorMsg);
}
return $input;
}
public static function isJSONArray($input, $errorMsg = 'Not a JSON array')
{
self::noNUL($input);
self::mustBeString($input);
self::notEmpty($input);
if ((strpos($input, '[') !== 0) || (!is_array(json_decode($input)))) {
throw new SanityException($errorMsg);
}
return $input;
}
public static function isJSONObject($input, $errorMsg = 'Not a JSON object')
{
self::noNUL($input);
self::mustBeString($input);
self::notEmpty($input);
if ((strpos($input, '{') !== 0) || (!is_object(json_decode($input)))) {
throw new SanityException($errorMsg);
}
return $input;
}
}