Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<?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

This comment has been minimized.

Copy link
Owner Author

@yansern 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
@ghost

This comment has been minimized.

Copy link

@ghost ghost commented Nov 11, 2014

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

@usb248

This comment has been minimized.

Copy link

@usb248 usb248 commented May 19, 2015

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

@rusxakep

This comment has been minimized.

Copy link

@rusxakep 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
You can’t perform that action at this time.