Replace PHP's realpath()
Thanks to Sven Arduwie's code (pointed out by Pekka) and some modification, I've built a (hopefully) better implementation:
/**
* This function is to replace PHP's extremely buggy realpath().
* @param string The original path, can be relative etc.
* @return string The resolved path, it might not exist.
*/
function truepath($path){
// whether $path is unix or not
$unipath=strlen($path)==0 || $path{0}!='/';
// attempts to detect if path is relative in which case, add cwd
if(strpos($path,':')===false && $unipath)
$path=getcwd().DIRECTORY_SEPARATOR.$path;
// resolve path parts (single dot, double dot and double delimiters)
$path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
$parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
$absolutes = array();
foreach ($parts as $part) {
if ('.' == $part) continue;
if ('..' == $part) {
array_pop($absolutes);
} else {
$absolutes[] = $part;
}
}
$path=implode(DIRECTORY_SEPARATOR, $absolutes);
// resolve any symlinks
if(file_exists($path) && linkinfo($path)>0)$path=readlink($path);
// put initial separator that could have been lost
$path=!$unipath ? '/'.$path : $path;
return $path;
}
NB: Unlike PHP's realpath
, this function does not return false on error; it returns a path which is as far as it could to resolving these quirks.
Note 2: Apparently some people can't read properly. Truepath() does not work on network resources including UNC and URLs. It works for the local file system only.
Laravel | Change realPath value of file()
This should do the trick, it assumes your <input
with file is named file
:
public function store(UploadRequest $request)
{
if ($request->hasFile('file')) { // depends on your FormRequest validation if `file` field is required or not
$path = $request->file->storePublicly(public_path('/uploads'));
}
Project::create(array_merge($request->except('file'), ['file' => $path])); // do some array manipulation
return $request->all();
}
And this for uploading multiple files:
public function store(UploadRequest $request)
{
foreach ($request->file() as $key => $file) {
if ($request->hasFile($key)) {
$path = $request->$key->storePublicly('/uploads');
}
$keys[] = $key;
$paths[] = $path;
}
$data = $request->except($keys);
$data = array_merge($data, array_combine($keys, $paths));
Project::create($data);
return back()->with('success', 'Project has been created successfully.');
}
Sanitize file path in PHP without realpath()
Not sure why you wouldn't want to use realpath
but path name sanitisation is a very simple concept, along the following lines:
- If the path is relative (does not start with
/
), prefix it with the current working directory and/
, making it an absolute path. - Replace all sequences of more than one
/
with a single one (a). - Replace all occurrences of
/./
with/
. - Remove
/.
if at the end. - Replace
/anything/../
with/
. - Remove
/anything/..
if at the end.
The text anything
in this case means the longest sequence of characters that aren't /
.
Note that those rules should be applied continuously until such time as none of them result in a change. In other words, do all six (one pass). If the string changed, then go back and do all six again (another pass). Keep doing that until the string is the same as before the pass just executed.
Once those steps are done, you have a canonical path name that can be checked for a valid pattern. Most likely that will be anything that doesn't start with ../
(in other words, it doesn't try to move above the starting point. There may be other rules you want to apply but that's outside the scope of this question.
(a) If you're working on a system that treats //
at the start of a path as special, make sure you replace multiple /
characters at the start with two of them. This is the only place where POSIX allows (but does not mandate) special handling for multiples, in all other cases, multiple /
characters are equivalent to a single one.
Replacing php realpth when outputing to users
I would use configuration variables $privatePath
and $publicPath
.
So you can concat whichever you want to the relative paths to your directories or files.
For your example:
$privatePath = '/mnt/wef66/d2/81/557642661/htdocs/';
$publicPath = 'www.example.com/';
$pic1RelativePath = 'useruploads/myfiles/imagefolder/mosaic_1.jpg';
$pic1privatePath = $privatePath . $pic1RelativePath;
// /mnt/wef66/d2/81/557642661/htdocs/useruploads/myfiles/imagefolder/mosaic_1.jpg
$pic1publicPath = $publicPath . $pic1RelativePath;
// www.example.com/useruploads/myfiles/imagefolder/mosaic_1.jpg
I think this is easier and more efficient than replacing the paths with regex.
EDIT:
If you have all the real paths in an array, you can loop through it and replace easily all the private paths with the public paths this way:
$paths = [
'/mnt/wef66/d2/81/557642661/htdocs/useruploads/myfiles/imagefolder/mosaic_1.jpg',
'/mnt/wef66/d2/81/557642661/htdocs/useruploads/myfiles/imagefolder/room_home_1.jpg',
'/mnt/wef66/d2/81/557642661/htdocs/useruploads/myfiles/imagefolder'
];
foreach ($paths as &$path) {
$path = str_replace($privatePath, $publicPath, $path);
}
print_r($paths);
Changing Base Path In PHP
The function chdir()
does this.
For example:
echo ('BEFORE = '.realpath('.')); // BEFORE = C:\ABC\XYZ\123\ZZZ
chdir('C:/Some/Other/Folder');
echo ('AFTER = '.realpath('.')); // AFTER = C:\Some\Other\Folder
PHP realpath on Windows Case Issue
Turns out
do {
$to = realpath($to);
} while (realpath($to) !== false && $to !== realpath($to));
is the only way.
https://bugs.php.net/bug.php?id=61933
Related Topics
Extract Url's from a String Using PHP
Why Are Escape Characters Being Added to the Value of the Hidden Input
Understanding Doctrine Cascade Operations
How Add Custom Validation Rules When Using Form Request Validation in Laravel 5
List of Us Time Zones for PHP to Use
Memory Optimization in PHP Array
Decoding Numeric HTML Entities via PHP
Friend of a Friend in PHP/Mysql
Add a Checkout Checkbox Field That Enable a Percentage Fee in Woocommerce
Symfony2 - How to Switch from "Dev" to "Prod"
How to Send JSON Response in Symfony2 Controller
How to Keep the Chinese or Other Foreign Language as They Are Instead of Converting Them into Codes
How to Pass Array Through Hidden Field
Sort Array by Object Property in PHP
Problems with Lib-Icu Dependency When Installing Symfony 2.3.X via Composer