Jump to content

Filename with "$" is getting missed by preg_match - use escapeshellcmd?


UnluckyForSome

Recommended Posts

I am trying to build a filter for sorting/removing files;

However, upon testing I have noticed a certain type of file which is getting through the net despite being named with a "(Japan)" country identifier (which should be filtered) at the end. I think this is because of the dollar sign ($).

The file in question:

Quiz$Millionaire -(Japan).zip

I get the error below when running the script. It echo's the file correctly, but then when attempting the mv
it reports it with "$Millionaire" missing from the middle of the string!

mv: cannot stat 'Quiz (Japan) (v1.0).zip': No such file or directory

I have been told I need to use $thisGame = escapeshellcmd($thisGame); in the code below, but when I do it messes up my regex matching for everything else - so I think I have to modify my regex? - but I'm a beginner and don't really know how to fix it! Code below:

$gameList = trim(shell_exec("ls -1"));
$gameArray = explode("\n", $gameList);

shell_exec('mkdir -p Removed');

// Do this magic for every file
foreach ($gameArray as $thisGame)
{
    if (!$thisGame) continue;
    // Probably already been removed
    if (!file_exists($thisGame)) continue;

    // Non-Engish speaking countries e.g. (France) or (Japan)
    if (preg_match('%\((Asia|Austria|Brazil|China|Denmark|Finland|France|Germany|Greece|Hungary|Israel|Italy|Japan|Japan, Asia|Korea|Netherlands|Norway|Poland|Portugal|Russia|Scandinavia|Spain|Sweden)\)%', $thisGame))
    {
        echo "{$thisGame} is a foreign language release. Moved to Removed folder.\n";
        shell_exec("mv \"{$thisGame}\" Removed/");
        continue;
    }

}

I've also been told to replace the line:

shell_exec("mv \"{$thisGame}\" Removed/");

with

shell_exec("mv \"" . escapeshellcmd($thisGame) . "\" Removed/");

But unfortunately if I try that I get the error:

mv: cannot stat 'Quiz$Millionaire \(Japan\) \(v1.0\).zip': No such file or directory

 

Could anybody help me? I'd be super greatful! Many thanks

J

Link to comment
Share on other sites

escapeshellcmd is for commands. If you had checked the documentation for it before simply doing what people on the internet told you to do then you would hopefully have seen the red warning:

Quote

Warning: escapeshellcmd() should be used on the whole command string, and it still allows the attacker to pass arbitrary number of arguments. For escaping a single argument escapeshellarg() should be used instead.

On that linked page you would see the description

Quote

escapeshellarg() adds single quotes around a string and quotes/escapes any existing single quotes allowing you to pass a string directly to a shell function and having it be treated as a single safe argument. This function should be used to escape individual arguments to shell functions coming from user input.

It's also to be used when the command is executed. Not earlier. Because it alters the value - which, in contexts like this, is generally called "escaping". This is a very important aspect you need to understand: the difference between what a value is and how a value is interpreted. The value "1+2" is a string with three characters. If you interpreted that value as PHP code you would get 3, a number. The value itself and the value of it interpreted are two things.

escapeshellcmd/arg alter the value so that it will not be interpreted as anything special. That would be like taking "1+2" and adding quotes around it so that PHP considered it to be the three-character string it was originally, but in doing so the value becomes five characters. If you want to examine the value then you must not quote it yet. If you want to do something with the value then you might quote it ("might" depending what you wanted to do). You also wouldn't escape it and add your own quotes because that would be too much.

 

So, after that rambling explanation, can you tell me what your updated code should be?

Link to comment
Share on other sites

7 hours ago, requinix said:

escapeshellcmd is for commands. If you had checked the documentation for it before simply doing what people on the internet told you to do then you would hopefully have seen the red warning:

On that linked page you would see the description

It's also to be used when the command is executed. Not earlier. Because it alters the value - which, in contexts like this, is generally called "escaping". This is a very important aspect you need to understand: the difference between what a value is and how a value is interpreted. The value "1+2" is a string with three characters. If you interpreted that value as PHP code you would get 3, a number. The value itself and the value of it interpreted are two things.

escapeshellcmd/arg alter the value so that it will not be interpreted as anything special. That would be like taking "1+2" and adding quotes around it so that PHP considered it to be the three-character string it was originally, but in doing so the value becomes five characters. If you want to examine the value then you must not quote it yet. If you want to do something with the value then you might quote it ("might" depending what you wanted to do). You also wouldn't escape it and add your own quotes because that would be too much.

 

So, after that rambling explanation, can you tell me what your updated code should be?

Hi Requinx

You're elluding to removing the quotes so it examines the value?

I tried to take the quotes off

shell_exec("mv \"" . escapeshellcmd($thisGame) . "\" Removed/");

to make

shell_exec("mv \"" . escapeshellcmd($thisGame) . \ Removed/");

But i'm getting errors. I'm not quite sure what else to try.

 

Many thanks.

Link to comment
Share on other sites

6 minutes ago, requinix said:

Removing the quotes was part of it.

Can you restate what I said in my post using your own words? Top to bottom.

  • escapeshellcmd is for commands.
  • I'm a buffoon who shouldn't get help from people on the internet
  • Use escapeshellarg for single arguments ---- OK
  • Don't quote the value if you want it examined.

I still can't get the right syntax with escapeshellarg - as I'm a complete beginner.

Please could you show me? Is it

shell_exec(*SOMETHING SOMETHING* escapeshellarg($thisGame) . \ Removed/");

Kind regards.

Link to comment
Share on other sites

35 minutes ago, requinix said:

Removing the quotes was part of it.

Can you restate what I said in my post using your own words? Top to bottom.

The correct syntax is

shell_exec("mv ".escapeshellarg($thisGame)." Removed/");

Why he couldn't just tell me this an hour ago I will never know. Would have taken 10 seconds of his time and saved me an hour of frustration. Getting a newbie to dance around like a monkey for a little bit of advice is a power trip for him, I guess.

While I appreciate your help requinix, please consider being a little less condescending; "
If you had checked the documentation for it before simply doing what people on the internet told you to do".

Thanks again for your help...

Link to comment
Share on other sites

I didn't tell you because the change was so simple. I knew if I poked and prodded you a bit, pointed you in the right direction, that you would figure it out. And you would learn along the way. Because someone saying "use escapeshellarg and remove the embedded quotes around it" would teach you where to get answers but not how to get them. And knowing how to get those answers is what makes skilled developers.

As for being condescending... yeah, I was a bit. People who learn to be developers by copying and pasting stuff from the internet make the rest of us professionals look bad, and it's one of my pet peeves. I'm not saying you're like that, but when I see a glimmer of that that sort of mentality emerging I want to squash it there and then.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.