Skip to content

Instantly share code, notes, and snippets.

@yansern
Forked from thsutton/normalise-path.php
Last active September 5, 2015 09:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yansern/5124fae2af1fbc59f949 to your computer and use it in GitHub Desktop.
Save yansern/5124fae2af1fbc59f949 to your computer and use it in GitHub Desktop.
<?php
/**
* Normalise a file path string so that it can be checked safely.
*
* Attempt to avoid invalid encoding bugs by transcoding the path. Then
* remove any unnecessary path components including '.', '..' and ''.
*
* @param $path string
* The path to normalise.
* @param $encoding string
* The name of the path iconv() encoding.
* @return string
* The path, normalised.
*/
function _normalise($path, $encoding="UTF-8") {
// Attempt to avoid path encoding problems.
$path = iconv($encoding, "$encoding//IGNORE//TRANSLIT", $path);
// Process the components
$parts = explode('/', $path);
$safe = array();
foreach ($parts as $idx => $part) {
if (($i>0 && trim($part)=="") || $part=='.') {
continue;
} elseif ('..' == $part) {
array_pop($safe);
continue;
} else {
$safe[] = $part;
}
}
// Return the "clean" path
$path = implode(DIRECTORY_SEPARATOR, $safe);
return $path;
}
@yansern
Copy link
Author

yansern commented Jun 5, 2014

This also handles edge cases including 0, 0.0 and keeps initial root slash intact.

/hello/0//how/../are/../you
==> /hello/0/you

/ /hello/0// / /how/../are/you/./././
==> /hello/0/are/you

/ /hello/0.0/././././////how/../are/you
==> /hello/0.0/are/you

Copy link

ghost commented Nov 11, 2014

On line 25, $i is not defined, I think you meant $idx

@usb248
Copy link

usb248 commented May 19, 2015

First test : ../common
=> common
It's Wrong...

@rusxakep
Copy link

rusxakep commented Sep 5, 2015

28 if (null === array_pop($safe)) $safe[] = '';
34 if (count($safe) == 1) $safe[] = '';

fix 'common' example

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment