Bug #74472 [Opn->Nab]: readdir strips leading and trailing quotes in a filename
| From: | requinix@php.net | Date: | Wed, 19 Apr 2017 06:27:25 +0000 |
| Subject: | Bug #74472 [Opn->Nab]: readdir strips leading and trailing quotes in a filename | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-208656@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=74472&edit=1
ID: 74472
Updated by: requinix@php.net
Reported by: james at workinout dot com
Summary: readdir strips leading and trailing quotes in a
filename
-Status: Open
+Status: Not a bug
Type: Bug
Package: Filesystem function related
Operating System: osx 10.12
PHP Version: 7.1.4
Block user comment: N
Private report: N
New Comment:
echo will output a thing as it is with no modifications, besides converting it to a string if it
isn't one already. var_dump, being a debugging tool, will output using a representation that
makes it easier to know what the thing's exact type and value is; strings will have quotes
around them to signify that they are strings, for instance.
As you can see, readdir is not stripping quotes because there are no quotes to begin with. You have
code that is adding the quotes somewhere, then on top of it apparently using addslashes which will
escape the quotes with backslashes. I don't know why the code is doing any of that but I'm
confident it should not be.
Like I said, you need to be using escapeshellarg to put strings into shell commands. It does all the
work for you - don't put quotes around the string yourself, don't addslashes yourself.
Previous Comments:
------------------------------------------------------------------------
[2017-04-19 06:18:21] james at workinout dot com
actually, running it all on fedora 25, sorry about that typo
strange. downloaded from drupal.org as far as i remember.
its weird, I know. cant ever recall seeing a filename with
quotes in it. i know about backslashes. used those with
fortran in 1975.
Entry before: {{ THEME SANITIZED }}.behaviors.js (quotes trimmed by readdir() )
Entry after: \'{{ THEME SANITIZED }}.behaviors.js\' (after using addslashes() )
perhaps echo() and var_dump() use different methods. var_dump using getc/putc ? echo not ?
------------------------------------------------------------------------
[2017-04-19 05:37:55] requinix@php.net
Well that's not how the files are bundled. Where did you download it from?
As for the backslashes, those are supposed to be there. That's how escaping works.
https://www.shellscript.sh/escape.html
Besides, I couldn't reproduce what you're describing anyways. And though this is Linux, I
can't imagine it being any different on OSX.
# ls -la
total 4
drwxrwxrwx 2 root root 0 Apr 18 22:33 .
drwxrwxrwx 2 root root 0 Apr 18 22:32 ..
-rw-rw-rw- 1 root root 0 Apr 18 22:32 'foo'
-rw-rw-rw- 1 root root 85 Apr 18 22:33 test.php
# cat test.php
<?php
$h = opendir(".");
while ($f = readdir($h)) {
var_dump($f);
}
closedir($h);
# ~/php/PHP-7.1.4/bin/php test.php
string(1) "."
string(2) ".."
string(5) "'foo'"
string(8) "test.php"
------------------------------------------------------------------------
[2017-04-19 05:28:14] james at workinout dot com
the quotes I AM seeing are when I do ls -al in a bash shell. see below
the filename ON the filesystem has leading and trailing quotes, as I said.
i tried escapeshellarg() but it simply puts in backslashes in front
of the quotes, which of course, creates a filename that does not exist.
drwxr-xr-x 2 james apache 4096 Apr 10 19:21 .
drwxr-xr-x 10 james apache 4096 Apr 10 19:21 ..
-rw-r--r-- 1 james apache 2900 Apr 10 19:21 '{{ THEME SANITIZED }}.behaviors.js'
obviously, the quotes are there...
------------------------------------------------------------------------
[2017-04-19 05:13:38] requinix@php.net
The files don't have quotes.
http://cgit.drupalcode.org/omega/tree/omega/starterkits/default/js?h=7.x-4.x
The filename must be escaped in the shell command, like with escapeshellarg. Not doing so will cause
problems for files that contain spaces or other potentially unsafe characters (such as
'{'). For example,
exec("stat --format=%G " . escapeshellarg($entry));
The fact that the escaped version has quotes is simply because that's the easiest way to make a
string safe.
The quotes you're seeing mentioned somewhere are probably indicative of either PHP code (quotes
form a string) or an actual shell command (author escaped the filename).
------------------------------------------------------------------------
[2017-04-19 04:36:34] james at workinout dot com
Description:
------------
in drupal, some files named with leading and trailing quotes
filename === '{{ THEME SANITIZED }}.behaviors.js'
$entry = readdir() --- > $entry === -> {{ THEME SANITIZED }}.behaviors.js (NO QUOTES)
stat will not work because the stripped quotes are needed: stat
complains like below:
stat --format=%G (command used..)
stat: cannot stat '{{': No such file or directory
stat: cannot stat 'THEME': No such file or directory
stat: cannot stat 'SANITIZED': No such file or directory
stat: cannot stat '}}.behaviors.js': No such file or directory
stat: cannot stat '{{': No such file or directory
stat: cannot stat 'THEME': No such file or directory
stat: cannot stat 'SANITIZED': No such file or directory
stat: cannot stat '}}.behaviors.js': No such file or directory
Test script:
---------------
Solution is to put the quotes back in filename.
$entry = "'" . $entry . "'".
stat works ok then...
if ($handle = opendir($name)) {
while (false !== ($entry = readdir($handle))) {
if (preg_match('/\.$|\..$/', $entry)) {
continue;
}
//special case for filenames with single quotes (they are stripped by readdir() )
// used in omega themes with {{ in the filename..
if(preg_match('/\{/', $entry)) {
$entry = "'" . $entry . "'";
}
<after this, stat will work....
Expected result:
----------------
providing an optional argument in readdir() to not strip leading,trailing quotes would be useful
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=74472&edit=1