I’m trying to view images in different network folders. Everything works but as soon there’s a folder have "&" in its name, I can’t view the content. The URL stops after "&" so it can’t find the folder in question.
I’ve looked at other questions similar to this problem but none of them worked (where also many could use strreplace() for a single URL which in my case don’t work when I have hundreds of folders)
Running on Windows Server 2022 with IIS.
My code:
<?php
$selectedDir = isset($_GET["dir"]) ? $_GET["dir"] : "";
//echo $selectedDir;
echo '<h1> '.$selectedDir.' </h1>';
$dirs = "\\serverimages\moreimages/$selectedDir";
$dir = new DirectoryIterator($dirs);
foreach ($dir as $fileinfo) {
if ($fileinfo->isDir() && !$fileinfo->isDot()) {
$directorypath = $selectedDir."/".$fileinfo->getFilename();
echo "<a href='?dir=".$directorypath."'>".$fileinfo->getFilename()."</a><br><br>";
}
elseif (stripos($fileinfo, '.jpg') !== false || stripos($fileinfo, '.png') !== false) {
?>
<?php echo '<a target="_blank" href="'."IntraimagesVD_images/$selectedDir/".$fileinfo.'"/>'; ?>
<?php echo '<img src="'."IntraimagesVD_images/$selectedDir/".$fileinfo.'"/> </a>'; ?>
<?php
}
}
?>
(For clarification the different paths if it’s any help:
"\serverimagesmoreimages/" is the UNC path.
"IntraimagesVD_images/" is the Virtual Directory path in IIS.)
I will try to provide as much info as I can in advance.
The folder name is: 35144 MAN T&B T2-L62
PHP_errors log:
PHP Fatal error: Uncaught UnexpectedValueException: DirectoryIterator::__construct(serverimagesmoreimages//35000-35999/35144 MAN T): The system cannot find the file specifi (code: 2) in C:inetpubwwwrootIntraimagesindex.php:38
Tried var_dump $selectedDir
which says:
string(28) "%2F35000-35999%2F35144+MAN+T"
URL in my web browser says: …/?dir=/35000-35999/35144 MAN T&B T2-L62
What I’ve tried
urlencode
the $selectedDir
Change some settings in php.ini to %26:
arg_separator.output = "&"
arg_separator.input = ";&"
Do I need to insert "%26" in the URL instead of "&"? If so, I have no idea how.
EDIT
I tried with:
str_replace("&","%26",$selectedDir);
but the URL and $selectedDir
don’t contain "&" since it stops right before "&" so I guess there’s nothing to replace…?
2
Answers
Rather than the single
DirectoryIterator
as above the following uses recursive iterators to illustrate that ampersands need not be an issue in UNC paths if proper escaping of backslash characters is observed.Given some test folders on a local network share that have files and sub-folders where the names contain the ampersand…
Example output from the above:
The ampsersand characters do not hinder the scanning of nor traversal of files and folders. Whether the practise of using said characters in paths is advisable or not is another matter.
It requires you to first understand what is happening here, as otherwise it is easy to miss.
It starts here:
The contents of that array member is not what you think. You will find anything removed from the string starting with (and including) the first ampersand (&).
If you then look into all the array keys of
$_GET
, you will notice that after the "dir" entry the next key is the continuation of the pathname you’d like to use.This is because of how PHP parses the incoming request URL, specifically the query-info part. That is the part at the end of a URL starting with the first question mark.
So this is basically missing URL encoding, and as you can imagine, PHP has that.
So when you build the URL to be clicked, like having the pathname of the directory for the dir parameter, encode the pathname value properly.
Your script needs to speak the same language, otherwise things may end up unexpected. This is also why it is easy to miss.
Build the query of the URL (http_build_query) to have a proper href attribute value.
And for debugging purposes
will display you the HTML of
$selectedDir
, use htmlspecialchars then.Both suggestions should be a good example how the data is processed between your PHP scripts and the Browser and back in your PHP scripts.
Example Script
If you have PHP on your own computer, you can save this file into one of your directories (create a new one), then open cmd.exe and change into that directory and run the PHP development server:
It will display you a http URL you can use to run the example. You will then see how the browser interacts with your PHP script in the terminal:
You stop the PHP development webserver by pressing ctrl + c.