Projet

Général

Profil

Paste
Télécharger (6,01 ko) Statistiques
| Branche: | Révision:

root / drupal7 / misc / typo3 / phar-stream-wrapper / src / Helper.php @ 6b24a280

1
<?php
2
namespace TYPO3\PharStreamWrapper;
3

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

    
14
/**
15
 * Helper provides low-level tools on file name resolving. However it does not
16
 * (and should not) maintain any runtime state information. In order to resolve
17
 * Phar archive paths according resolvers have to be used.
18
 *
19
 * @see \TYPO3\PharStreamWrapper\Resolvable::resolve()
20
 */
21
class Helper
22
{
23
    /*
24
     * Resets PHP's OPcache if enabled as work-around for issues in `include()`
25
     * or `require()` calls and OPcache delivering wrong results.
26
     *
27
     * @see https://bugs.php.net/bug.php?id=66569
28
     */
29
    public static function resetOpCache()
30
    {
31
        if (function_exists('opcache_reset')
32
            && function_exists('opcache_get_status')
33
        ) {
34
            $status = opcache_get_status();
35
            if (!empty($status['opcache_enabled'])) {
36
                opcache_reset();
37
            }
38
        }
39
    }
40

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

    
53
        while (count($parts)) {
54
            $currentPath = implode('/', $parts);
55
            if (@is_file($currentPath) && realpath($currentPath) !== false) {
56
                return $currentPath;
57
            }
58
            array_pop($parts);
59
        }
60

    
61
        return null;
62
    }
63

    
64
    /**
65
     * @param string $path
66
     * @return bool
67
     */
68
    public static function hasPharPrefix($path)
69
    {
70
        return stripos($path, 'phar://') === 0;
71
    }
72

    
73
    /**
74
     * @param string $path
75
     * @return string
76
     */
77
    public static function removePharPrefix($path)
78
    {
79
        $path = trim($path);
80
        if (!static::hasPharPrefix($path)) {
81
            return $path;
82
        }
83
        return substr($path, 7);
84
    }
85

    
86
    /**
87
     * Normalizes a path, removes phar:// prefix, fixes Windows directory
88
     * separators. Result is without trailing slash.
89
     *
90
     * @param string $path
91
     * @return string
92
     */
93
    public static function normalizePath($path)
94
    {
95
        return rtrim(
96
            static::normalizeWindowsPath(
97
                static::removePharPrefix($path)
98
            ),
99
            '/'
100
        );
101
    }
102

    
103
    /**
104
     * Fixes a path for windows-backslashes and reduces double-slashes to single slashes
105
     *
106
     * @param string $path File path to process
107
     * @return string
108
     */
109
    public static function normalizeWindowsPath($path)
110
    {
111
        return str_replace('\\', '/', $path);
112
    }
113

    
114
    /**
115
     * Resolves all dots, slashes and removes spaces after or before a path...
116
     *
117
     * @param string $path Input string
118
     * @return string Canonical path, always without trailing slash
119
     */
120
    private static function getCanonicalPath($path)
121
    {
122
        $path = static::normalizeWindowsPath($path);
123

    
124
        $absolutePathPrefix = '';
125
        if (static::isAbsolutePath($path)) {
126
            if (static::isWindows() && strpos($path, ':/') === 1) {
127
                $absolutePathPrefix = substr($path, 0, 3);
128
                $path = substr($path, 3);
129
            } else {
130
                $path = ltrim($path, '/');
131
                $absolutePathPrefix = '/';
132
            }
133
        }
134

    
135
        $pathParts = explode('/', $path);
136
        $pathPartsLength = count($pathParts);
137
        for ($partCount = 0; $partCount < $pathPartsLength; $partCount++) {
138
            // double-slashes in path: remove element
139
            if ($pathParts[$partCount] === '') {
140
                array_splice($pathParts, $partCount, 1);
141
                $partCount--;
142
                $pathPartsLength--;
143
            }
144
            // "." in path: remove element
145
            if ((isset($pathParts[$partCount]) ? $pathParts[$partCount] : '') === '.') {
146
                array_splice($pathParts, $partCount, 1);
147
                $partCount--;
148
                $pathPartsLength--;
149
            }
150
            // ".." in path:
151
            if ((isset($pathParts[$partCount]) ? $pathParts[$partCount] : '') === '..') {
152
                if ($partCount === 0) {
153
                    array_splice($pathParts, $partCount, 1);
154
                    $partCount--;
155
                    $pathPartsLength--;
156
                } elseif ($partCount >= 1) {
157
                    // Rremove this and previous element
158
                    array_splice($pathParts, $partCount - 1, 2);
159
                    $partCount -= 2;
160
                    $pathPartsLength -= 2;
161
                } elseif ($absolutePathPrefix) {
162
                    // can't go higher than root dir
163
                    // simply remove this part and continue
164
                    array_splice($pathParts, $partCount, 1);
165
                    $partCount--;
166
                    $pathPartsLength--;
167
                }
168
            }
169
        }
170

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

    
174
    /**
175
     * Checks if the $path is absolute or relative (detecting either '/' or
176
     * 'x:/' as first part of string) and returns TRUE if so.
177
     *
178
     * @param string $path File path to evaluate
179
     * @return bool
180
     */
181
    private static function isAbsolutePath($path)
182
    {
183
        // Path starting with a / is always absolute, on every system
184
        // On Windows also a path starting with a drive letter is absolute: X:/
185
        return (isset($path[0]) ? $path[0] : null) === '/'
186
            || static::isWindows() && (
187
                strpos($path, ':/') === 1
188
                || strpos($path, ':\\') === 1
189
            );
190
    }
191

    
192
    /**
193
     * @return bool
194
     */
195
    private static function isWindows()
196
    {
197
        return stripos(PHP_OS, 'WIN') === 0;
198
    }
199
}