phingofficial /
phing
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
| 1 | <?php |
||
| 2 | |||
| 3 | /** |
||
| 4 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||
| 5 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||
| 6 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||
| 7 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||
| 8 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||
| 9 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||
| 10 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||
| 11 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||
| 12 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
| 13 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||
| 14 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
| 15 | * |
||
| 16 | * This software consists of voluntary contributions made by many individuals |
||
| 17 | * and is licensed under the LGPL. For more information please see |
||
| 18 | * <http://phing.info>. |
||
| 19 | */ |
||
| 20 | |||
| 21 | namespace Phing\Io; |
||
| 22 | |||
| 23 | use Exception; |
||
| 24 | use Phar; |
||
| 25 | use Phing\Phing; |
||
| 26 | use Phing\Util\StringHelper; |
||
| 27 | |||
| 28 | /** |
||
| 29 | * UnixFileSystem class. This class encapsulates the basic file system functions |
||
| 30 | * for platforms using the unix (posix)-stylish filesystem. It wraps php native |
||
| 31 | * functions suppressing normal PHP error reporting and instead uses Exception |
||
| 32 | * to report and error. |
||
| 33 | * |
||
| 34 | * This class is part of a oop based filesystem abstraction and targeted to run |
||
| 35 | * on all supported php platforms. |
||
| 36 | * |
||
| 37 | * Note: For debugging turn track_errors on in the php.ini. The error messages |
||
| 38 | * and log messages from this class will then be clearer because $php_errormsg |
||
| 39 | * is passed as part of the message. |
||
| 40 | * |
||
| 41 | * FIXME: |
||
| 42 | * - Comments |
||
| 43 | * - Error handling reduced to min, error are handled by PhingFile mainly |
||
| 44 | * |
||
| 45 | * @author Andreas Aderhold, [email protected] |
||
| 46 | */ |
||
| 47 | class UnixFileSystem extends FileSystem |
||
| 48 | { |
||
| 49 | /** |
||
| 50 | * returns OS dependent path separator char. |
||
| 51 | * |
||
| 52 | * @return string |
||
| 53 | */ |
||
| 54 | 510 | public function getSeparator() |
|
| 55 | { |
||
| 56 | 510 | return '/'; |
|
| 57 | } |
||
| 58 | |||
| 59 | /** |
||
| 60 | * returns OS dependent directory separator char. |
||
| 61 | * |
||
| 62 | * @return string |
||
| 63 | */ |
||
| 64 | 7 | public function getPathSeparator() |
|
| 65 | { |
||
| 66 | 7 | return ':'; |
|
| 67 | } |
||
| 68 | |||
| 69 | /** |
||
| 70 | * A normal Unix pathname contains no duplicate slashes and does not end |
||
| 71 | * with a slash. It may be the empty string. |
||
| 72 | * |
||
| 73 | * Check that the given pathname is normal. If not, invoke the real |
||
| 74 | * normalizer on the part of the pathname that requires normalization. |
||
| 75 | * This way we iterate through the whole pathname string only once. |
||
| 76 | * |
||
| 77 | * NOTE: this method no longer expands the tilde (~) character! |
||
| 78 | * |
||
| 79 | * @param string $strPathname |
||
| 80 | * |
||
| 81 | * @return string |
||
| 82 | */ |
||
| 83 | 957 | public function normalize($strPathname) |
|
| 84 | { |
||
| 85 | 957 | if (!strlen($strPathname)) { |
|
| 86 | 3 | return ''; |
|
| 87 | } |
||
| 88 | |||
| 89 | // Start normalising after any scheme that is present. |
||
| 90 | // This prevents phar:///foo being normalised into phar:/foo |
||
| 91 | // Use a regex as some paths may not by parsed by parse_url(). |
||
| 92 | 957 | if (preg_match('{^[a-z][a-z0-9+\-\.]+://}', $strPathname)) { |
|
| 93 | 11 | $i = strpos($strPathname, '://') + 3; |
|
| 94 | } else { |
||
| 95 | 946 | $i = 0; |
|
| 96 | } |
||
| 97 | |||
| 98 | 957 | $n = strlen($strPathname); |
|
| 99 | 957 | $prevChar = 0; |
|
| 100 | 957 | for (; $i < $n; ++$i) { |
|
| 101 | 957 | $c = $strPathname[$i]; |
|
| 102 | 957 | if (('/' === $prevChar) && ('/' === $c)) { |
|
| 103 | 12 | return self::normalizer($strPathname, $n, $i - 1); |
|
|
0 ignored issues
–
show
Bug
Best Practice
introduced
by
Loading history...
|
|||
| 104 | } |
||
| 105 | 957 | $prevChar = $c; |
|
| 106 | } |
||
| 107 | 957 | if ('/' === $prevChar) { |
|
| 108 | 24 | return self::normalizer($strPathname, $n, $n - 1); |
|
| 109 | } |
||
| 110 | |||
| 111 | 953 | return $strPathname; |
|
| 112 | } |
||
| 113 | |||
| 114 | /** |
||
| 115 | * Compute the length of the pathname string's prefix. The pathname |
||
| 116 | * string must be in normal form. |
||
| 117 | * |
||
| 118 | * @param string $pathname |
||
| 119 | * |
||
| 120 | * @return int |
||
| 121 | */ |
||
| 122 | 954 | public function prefixLength($pathname) |
|
| 123 | { |
||
| 124 | 954 | if (0 === strlen($pathname)) { |
|
| 125 | 1 | return 0; |
|
| 126 | } |
||
| 127 | |||
| 128 | 954 | if (class_exists('Phar', false) && method_exists('Phar', 'running')) { |
|
| 129 | 954 | $phar = Phar::running(); |
|
| 130 | 954 | $pharAlias = 'phar://' . Phing::PHAR_ALIAS; |
|
| 131 | |||
| 132 | 954 | if ($phar && 0 === strpos($pathname, $phar)) { |
|
| 133 | return strlen($phar); |
||
| 134 | } |
||
| 135 | |||
| 136 | 954 | if ($phar && 0 === strpos($pathname, $pharAlias)) { |
|
| 137 | return strlen($pharAlias); |
||
| 138 | } |
||
| 139 | } |
||
| 140 | |||
| 141 | 954 | return ('/' === $pathname[0]) ? 1 : 0; |
|
| 142 | } |
||
| 143 | |||
| 144 | /** |
||
| 145 | * Resolve the child pathname string against the parent. |
||
| 146 | * Both strings must be in normal form, and the result |
||
| 147 | * will be in normal form. |
||
| 148 | * |
||
| 149 | * @param string $parent |
||
| 150 | * @param string $child |
||
| 151 | * |
||
| 152 | * @return string |
||
| 153 | */ |
||
| 154 | 498 | public function resolve($parent, $child) |
|
| 155 | { |
||
| 156 | 498 | if ('' === $child) { |
|
| 157 | 2 | return $parent; |
|
| 158 | } |
||
| 159 | |||
| 160 | 498 | if ('/' === $child[0]) { |
|
| 161 | if ('/' === $parent) { |
||
| 162 | return $child; |
||
| 163 | } |
||
| 164 | |||
| 165 | return $parent . $child; |
||
| 166 | } |
||
| 167 | |||
| 168 | 498 | if ('/' === $parent) { |
|
| 169 | return $parent . $child; |
||
| 170 | } |
||
| 171 | |||
| 172 | 498 | return $parent . '/' . $child; |
|
| 173 | } |
||
| 174 | |||
| 175 | /** |
||
| 176 | * @return string |
||
| 177 | */ |
||
| 178 | public function getDefaultParent() |
||
| 179 | { |
||
| 180 | return '/'; |
||
| 181 | } |
||
| 182 | |||
| 183 | /** |
||
| 184 | * @return bool |
||
| 185 | */ |
||
| 186 | 936 | public function isAbsolute(File $f) |
|
| 187 | { |
||
| 188 | 936 | return 0 !== $f->getPrefixLength(); |
|
| 189 | } |
||
| 190 | |||
| 191 | /** |
||
| 192 | * the file resolver. |
||
| 193 | * |
||
| 194 | * @return string |
||
| 195 | */ |
||
| 196 | 936 | public function resolveFile(File $f) |
|
| 197 | { |
||
| 198 | // resolve if parent is a file oject only |
||
| 199 | 936 | if ($this->isAbsolute($f)) { |
|
| 200 | 936 | return $f->getPath(); |
|
| 201 | } |
||
| 202 | |||
| 203 | 112 | return $this->resolve(Phing::getProperty('user.dir'), $f->getPath()); |
|
| 204 | } |
||
| 205 | |||
| 206 | // -- most of the following is mapped to the php natives wrapped by FileSystem |
||
| 207 | |||
| 208 | // -- Attribute accessors -- |
||
| 209 | |||
| 210 | /** |
||
| 211 | * compares file paths lexicographically. |
||
| 212 | * |
||
| 213 | * @return int |
||
| 214 | */ |
||
| 215 | 39 | public function compare(File $f1, File $f2) |
|
| 216 | { |
||
| 217 | 39 | $f1Path = $f1->getPath(); |
|
| 218 | 39 | $f2Path = $f2->getPath(); |
|
| 219 | |||
| 220 | 39 | return strcmp((string) $f1Path, (string) $f2Path); |
|
| 221 | } |
||
| 222 | |||
| 223 | /** |
||
| 224 | * Copy a file, takes care of symbolic links. |
||
| 225 | * |
||
| 226 | * @param File $src source path and name file to copy |
||
| 227 | * @param File $dest destination path and name of new file |
||
| 228 | * |
||
| 229 | * @throws Exception if file cannot be copied |
||
| 230 | */ |
||
| 231 | 29 | public function copy(File $src, File $dest) |
|
| 232 | { |
||
| 233 | 29 | if (!$src->isLink()) { |
|
| 234 | 27 | parent::copy($src, $dest); |
|
| 235 | |||
| 236 | 27 | return; |
|
| 237 | } |
||
| 238 | |||
| 239 | 3 | $srcPath = $src->getAbsolutePath(); |
|
|
0 ignored issues
–
show
|
|||
| 240 | 3 | $destPath = $dest->getAbsolutePath(); |
|
| 241 | |||
| 242 | 3 | $linkTarget = $src->getLinkTarget(); |
|
| 243 | 3 | if (false === @symlink($linkTarget, $destPath)) { |
|
| 244 | $msg = "FileSystem::copy() FAILED. Cannot create symlink from {$destPath} to {$linkTarget}."; |
||
| 245 | |||
| 246 | throw new Exception($msg); |
||
| 247 | } |
||
| 248 | } |
||
| 249 | |||
| 250 | /** |
||
| 251 | * @param string $p |
||
| 252 | * |
||
| 253 | * @return string |
||
| 254 | */ |
||
| 255 | public function fromURIPath($p) |
||
| 256 | { |
||
| 257 | if (StringHelper::endsWith('/', $p) && (strlen($p) > 1)) { |
||
| 258 | // "/foo/" --> "/foo", but "/" --> "/" |
||
| 259 | $p = substr($p, 0, strlen($p) - 1); |
||
| 260 | } |
||
| 261 | |||
| 262 | return $p; |
||
| 263 | } |
||
| 264 | |||
| 265 | /** |
||
| 266 | * Whether file can be deleted. |
||
| 267 | * |
||
| 268 | * @return bool |
||
| 269 | */ |
||
| 270 | 234 | public function canDelete(File $f) |
|
| 271 | { |
||
| 272 | 234 | @clearstatcache(); |
|
|
0 ignored issues
–
show
Are you sure the usage of
clearstatcache() is correct as it seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. Loading history...
|
|||
| 273 | 234 | $dir = dirname($f->getAbsolutePath()); |
|
| 274 | |||
| 275 | 234 | return @is_writable($dir); |
|
| 276 | } |
||
| 277 | |||
| 278 | /** |
||
| 279 | * Normalize the given pathname, whose length is $len, starting at the given |
||
| 280 | * $offset; everything before this offset is already normal. |
||
| 281 | * |
||
| 282 | * @param string $pathname |
||
| 283 | * @param int $len |
||
| 284 | * @param int $offset |
||
| 285 | * |
||
| 286 | * @return string |
||
| 287 | */ |
||
| 288 | 32 | protected function normalizer($pathname, $len, $offset) |
|
| 289 | { |
||
| 290 | 32 | if (0 === $len) { |
|
| 291 | return $pathname; |
||
| 292 | } |
||
| 293 | 32 | $n = (int) $len; |
|
| 294 | 32 | while (($n > 0) && ('/' === $pathname[$n - 1])) { |
|
| 295 | 24 | --$n; |
|
| 296 | } |
||
| 297 | 32 | if (0 === $n) { |
|
| 298 | 8 | return '/'; |
|
| 299 | } |
||
| 300 | 27 | $sb = ''; |
|
| 301 | |||
| 302 | 27 | if ($offset > 0) { |
|
| 303 | 24 | $sb .= substr($pathname, 0, $offset); |
|
| 304 | } |
||
| 305 | 27 | $prevChar = 0; |
|
| 306 | 27 | for ($i = $offset; $i < $n; ++$i) { |
|
| 307 | 12 | $c = $pathname[$i]; |
|
| 308 | 12 | if (('/' === $prevChar) && ('/' === $c)) { |
|
| 309 | 12 | continue; |
|
| 310 | } |
||
| 311 | 12 | $sb .= $c; |
|
| 312 | 12 | $prevChar = $c; |
|
| 313 | } |
||
| 314 | |||
| 315 | 27 | return $sb; |
|
| 316 | } |
||
| 317 | } |
||
| 318 |