Seditio Source
Root |
./othercms/drupal-7.90/misc/typo3/phar-stream-wrapper/src/Helper.php
<?php
namespace TYPO3\PharStreamWrapper;

/*
 * This file is part of the TYPO3 project.
 *
 * It is free software; you can redistribute it and/or modify it under the terms
 * of the MIT License (MIT). For the full copyright and license information,
 * please read the LICENSE file that was distributed with this source code.
 *
 * The TYPO3 project - inspiring people to share!
 */

/**
 * Helper provides low-level tools on file name resolving. However it does not
 * (and should not) maintain any runtime state information. In order to resolve
 * Phar archive paths according resolvers have to be used.
 *
 * @see \TYPO3\PharStreamWrapper\Resolvable::resolve()
 */
class Helper
{
   
/*
     * Resets PHP's OPcache if enabled as work-around for issues in `include()`
     * or `require()` calls and OPcache delivering wrong results.
     *
     * @see https://bugs.php.net/bug.php?id=66569
     */
   
public static function resetOpCache()
    {
        if (
function_exists('opcache_reset')
            &&
function_exists('opcache_get_status')
        ) {
           
$status = opcache_get_status();
            if (!empty(
$status['opcache_enabled'])) {
               
opcache_reset();
            }
        }
    }

   
/**
     * Determines base file that can be accessed using the regular file system.
     * For e.g. "phar:///home/user/bundle.phar/content.txt" that would result
     * into "/home/user/bundle.phar".
     *
     * @param string $path
     * @return string|null
     */
   
public static function determineBaseFile($path)
    {
       
$parts = explode('/', static::normalizePath($path));

        while (
count($parts)) {
           
$currentPath = implode('/', $parts);
            if (@
is_file($currentPath) && realpath($currentPath) !== false) {
                return
$currentPath;
            }
           
array_pop($parts);
        }

        return
null;
    }

   
/**
     * @param string $path
     * @return bool
     */
   
public static function hasPharPrefix($path)
    {
        return
stripos($path, 'phar://') === 0;
    }

   
/**
     * @param string $path
     * @return string
     */
   
public static function removePharPrefix($path)
    {
       
$path = trim($path);
        if (!static::
hasPharPrefix($path)) {
            return
$path;
        }
        return
substr($path, 7);
    }

   
/**
     * Normalizes a path, removes phar:// prefix, fixes Windows directory
     * separators. Result is without trailing slash.
     *
     * @param string $path
     * @return string
     */
   
public static function normalizePath($path)
    {
        return
rtrim(
            static::
normalizeWindowsPath(
                static::
removePharPrefix($path)
            ),
           
'/'
       
);
    }

   
/**
     * Fixes a path for windows-backslashes and reduces double-slashes to single slashes
     *
     * @param string $path File path to process
     * @return string
     */
   
public static function normalizeWindowsPath($path)
    {
        return
str_replace('\\', '/', $path);
    }

   
/**
     * Resolves all dots, slashes and removes spaces after or before a path...
     *
     * @param string $path Input string
     * @return string Canonical path, always without trailing slash
     */
   
private static function getCanonicalPath($path)
    {
       
$path = static::normalizeWindowsPath($path);

       
$absolutePathPrefix = '';
        if (static::
isAbsolutePath($path)) {
            if (static::
isWindows() && strpos($path, ':/') === 1) {
               
$absolutePathPrefix = substr($path, 0, 3);
               
$path = substr($path, 3);
            } else {
               
$path = ltrim($path, '/');
               
$absolutePathPrefix = '/';
            }
        }

       
$pathParts = explode('/', $path);
       
$pathPartsLength = count($pathParts);
        for (
$partCount = 0; $partCount < $pathPartsLength; $partCount++) {
           
// double-slashes in path: remove element
           
if ($pathParts[$partCount] === '') {
               
array_splice($pathParts, $partCount, 1);
               
$partCount--;
               
$pathPartsLength--;
            }
           
// "." in path: remove element
           
if ((isset($pathParts[$partCount]) ? $pathParts[$partCount] : '') === '.') {
               
array_splice($pathParts, $partCount, 1);
               
$partCount--;
               
$pathPartsLength--;
            }
           
// ".." in path:
           
if ((isset($pathParts[$partCount]) ? $pathParts[$partCount] : '') === '..') {
                if (
$partCount === 0) {
                   
array_splice($pathParts, $partCount, 1);
                   
$partCount--;
                   
$pathPartsLength--;
                } elseif (
$partCount >= 1) {
                   
// Rremove this and previous element
                   
array_splice($pathParts, $partCount - 1, 2);
                   
$partCount -= 2;
                   
$pathPartsLength -= 2;
                } elseif (
$absolutePathPrefix) {
                   
// can't go higher than root dir
                    // simply remove this part and continue
                   
array_splice($pathParts, $partCount, 1);
                   
$partCount--;
                   
$pathPartsLength--;
                }
            }
        }

        return
$absolutePathPrefix . implode('/', $pathParts);
    }

   
/**
     * Checks if the $path is absolute or relative (detecting either '/' or
     * 'x:/' as first part of string) and returns TRUE if so.
     *
     * @param string $path File path to evaluate
     * @return bool
     */
   
private static function isAbsolutePath($path)
    {
       
// Path starting with a / is always absolute, on every system
        // On Windows also a path starting with a drive letter is absolute: X:/
       
return (isset($path[0]) ? $path[0] : null) === '/'
           
|| static::isWindows() && (
               
strpos($path, ':/') === 1
               
|| strpos($path, ':\\') === 1
           
);
    }

   
/**
     * @return bool
     */
   
private static function isWindows()
    {
        return
stripos(PHP_OS, 'WIN') === 0;
    }
}