In php,I have to find whether a directory exist. IF it exists not a problem (I will display the hyperlink for that using the dirname)
Here is the sample in which I need help.
dir_name is the directory name
$url = system(~'ls -d /home/myapps/rel/".$dir_name"');
echo $url;(this does not work)
if(preg_match("/No such/",$url)) {
echo'Ther is no match'
}
else{
}
In my code the if block is never executed.(it should execute if the directory does not exist) ;(
Why don't you use is_dir() ?
http://php.net/manual/en/function.is-dir.php
As others have told, is_dir is the right way to go.
I'll point out why your existing program does not work. This will be useful in cases when you want to run an external command and then parse its output.
You have a unwanted ~ in your call
to system.
Variable interpolation does not
happen in single quotes. So you need
do something like:
system('ls -d /home/myapps/rel/'.$dir_name); or
system("ls -d /home/myapps/rel/$dir_name");
Even with the above changes it does
not work because if the dir does not
exist, ls issues the "....not
found" error on stderr and not on
stdout and system just returns the
last line of the stdout. To fix
this we need to redirect stderr of
the command to stdout as:
system("ls -d /home/myapps/rel/$dir_name 2>&1");
You also need to remember that
system returns only the last
line of the output. In the current
case if works, but in some other
cases if the external command being
run spits many lines of error/output
system will not work and you'll have
to use exec which allows you to
collect entire output lines in an
array. Something like:
exec("ls -d /home/myapps/rel/$dir_name 2>&1",$output_arr);
then you can search for your err string in the array $output_arr
So now you have the error message(if the dir does not exist) in $url and then check for the presence of string "No such".
Some more problems with the approach:
Some implementation of bash throw a
different err message when you list
for a non existing file. One I've
seen is /foo/bar not found and this
can cause your solution to break.
Also if the value of $dir_name
contains the string No such ( weird
but possible) your solution will
break.
http://php.net/manual/en/function.file-exists.php
bool file_exists ( string $filename )
Returns true if file or directory exists. If you then need to find it out if its directory or file use is_dir()
Related
I just cannot fathom how to get the PHP exec() or shell_exec() functions to treat a '*' character as a wildcard. Is there some way to properly encode / escape this character so it makes it through to the shell?
This is on windows (via CLI shell script if that matters, Terminal or a git-bash yields the same results).
Take the following scenario:
C:\temp\ contains a bunch of png images.
echo exec('ls C:\temp\*');
// output: ls: cannot access 'C:\temp\*': No such file or directory
Permissions is not the problem:
echo exec('ls C:\temp\exmaple.png');
// output: C:\temp\example.png
Therefore the * character is the problem and is being treated as a literal filename rather than a wildcard. The file named * does not exist, so from that point of view, it's not wrong...
It also does not matter if I use double quotes to encase the command:
echo exec("ls C:\temp\*");
// output: ls: cannot access 'C:\temp\*': No such file or directory
I have also tried other things like:
exec(escapeshellcmd('ls C:\temp\*'));
exec('ls C:\temp\\\*');
exec('ls "C:\temp\*"');
exec('ls "C:\temp\"*');
And nothing works...
I'm pretty confused that I cannot find any other posts discussing this but maybe I'm just missing it. At this point I have already worked around the issue by manually programming a glob loop and using the internal copy() function on each file individually, but it's really bugging me that I do not understand how to make the wildcard work via shell command.
EDIT:
Thanks to #0stone0 - The answer provided did not particularly answer my initial question but I had not tried using forward slashes in the path and when I do:
exec('ls C:/temp/*')
It works correctly, and as 0stone0 said, it only returns the last line of the output, which is fine since this was just for proof of concept as I was not actually attempting to parse the output.
Also, on a side note, since posting this question my system had been updated to Win11 22H2 and now for some reason the original test code (with the backslashes) no longer returns the "Cannot access / no file" error message. Instead it just returns an empty string and has no output set to the &$output parameter either. That being said, I'm not sure if the forward slashes would have worked on my system prior to the 22H2 update.
exec() only returns the last output line by default.
The wildcard probably works, but the output is just truncated.
Pass an variable by ref to exec() and log that:
<?php
$output = [];
exec('ls -lta /tmp/*', $output);
var_dump($output);
Without any additional changes, this returns the same as when I run ls -lta /tmp/* in my Bash terminal
That said, glob() is still the preferred way of getting data like this especcially since
You shouldn't parse the output of ls
I have a C code that I have to execute through PHP,
I have used exec('./sys'), sys is my executable file.
I have also tried system(), passthrough(), shell_exec() and they are not giving output.
When I executed exec('who'); it gives the output.
What can I do to execute sys?
Each of those methods you reference will execute your sys file, but you need to make sure you are executing the correct path. Your working path is determined by what script is actually executing PHP. For example, if you're executing your code through apache or the command line your working directory may be different. Lets assume this file structure:
+ src/
| + script.php
| + sys
I would recommend using PHP's __DIR__ magic variable in your script.php to always reference the current file's directory, and then work from there:
// script.php
exec(__DIR__ . "/sys");
Retrieving output can be done a couple different ways. If you want to store the output of the script in a variable, I would recommend using exec according the the manual:
Parameters ΒΆ
command
The command that will be executed.
output
If the output argument is present, then the specified array will be filled with every line of output from the command. Trailing whitespace, such as \n, is not included in this array. Note that if the array already contains some elements, exec() will append to the end of the array. If you do not want the function to append elements, call unset() on the array before passing it to exec().
return_var
If the return_var argument is present along with the output argument, then the return status of the executed command will be written to this variable.
exec will return the first line of output, but if you want more than that you need to pass a variable by reference:
// script.php
$output = array();
exec(__DIR__ . "/sys", $output);
$output will then contain an array of each line of output from the command. However if you want to run your sys script and directly pass through the output then use passthru(__DIR__ . "/sys"); For example, if you wanted to execute a command that required input on the command line, passthru would be the best option.
So I need to found out if an upload from a user is images/ video and what type. I currently use
"filetype"=>system("file -i -b ".$_FILES['file']['tmp_name'])
which is inserted into my MongoDB collection via this
$s3file='http://'.$bucket.'.s3.amazonaws.com/'.$actual_image_name;
$collection = static::db()->media;
$datetime = time();
$mediaupload = array("owner"=>$_SESSION['user_information'][0]['_id'],"filelink"=>$s3file,"filetype"=>system("file -i -b ".$_FILES['file']['tmp_name']),"filesize"=>$size,"uploadtime"=>$datetime,"ownerid"=>$_SESSION["user_information"][0]['_id']);
$collection->insert($mediaupload);
$media = $collection->findOne($mediaupload);
However what I am noticing is it echos the result out to the PHP page - which is not what I need it to do. i know it is the system function because when I remove that function it does not echo the uploaded file type to the php code.
I am wondering therefor how can i still run that system file -i -b function and get it to include into the MongoDB database but not echo the result into the public php page return.
Try something like (for multi-line output)
exec("file -i -b ".$_FILES['file']['tmp_name'], $output);
array("filetype"=>$output);
It may look a little unorthodox, but exec uses its second input parameter as a way to pass the output information back to you - the output of file will be stored as an array into $output.
From the docs:
If the output argument is present, then the specified array will be
filled with every line of output from the command. Trailing
whitespace, such as \n, is not included in this array. Note that if
the array already contains some elements, exec() will append to the
end of the array. If you do not want the function to append elements,
call unset() on the array before passing it to exec().
If you simply want the first line from the output, use the simpler version:
array("filetype"=>exec("file -i -b ".$_FILES['file']['tmp_name']));
I have switched the system to exec() and that seems to of fixed my issue
I'd like to run something like (in myProgram.sh):
java -cp whatever.jar com.my.program $1
within PHP and read the output.
So far I have something like:
$processOrderCommand = 'bash -c "exec nohup setsid /myProgram.sh ' . $arg1 . ' > /dev/null 2>&1 &"';
exec($processOrderCommand);
But what I'd really like is to be able to get the output of the java program within the PHP script and not just execute it as another thread.
How can this be done?
You can do this :
exec($processOrderCommand, $output);
From the documentation :
If the output argument is present, then the specified array will be filled with every line of output from the command. Trailing whitespace, such as \n, is not included in this array. Note that if the array already contains some elements, exec() will append to the end of the array. If you do not want the function to append elements, call unset() on the array before passing it to exec().
For a better control on your execution you can take a look at proc_open()
Resources :
php.net - exec()
php.net - proc_open()
The key is that the classpaths need to be absolute within the shell_exec
PHP script.
Or at least that's the only way I could get it to correctly work. Basically it's almost impossible to tell from environment to environment what the relative directory is that the php script is running the JVM.
As well, it helped to put the absolute path location for java, such as usr/.../bin/java
I'm writing a setup/installer script for my application, basically just a nice front end to the configuration file. One of the configuration variables is the executable path for mysql. After the user has typed it in (for example: /path/to/mysql-5.0/bin/mysql or just mysql if it is in their system PATH), I want to verify that it is correct. My initial reaction would be to try running it with "--version" to see what comes back. However, I quickly realised this would lead to me writing this line of code:
shell_exec($somethingAUserHasEntered . " --version");
...which is obviously a Very Bad Thing. Now, this is a setup script which is designed for trusted users only, and ones which probably already have relatively high level access to the system, but still I don't think the above solution is something I want to write.
Is there a better way to verify the executable path? Perhaps one which doesn't expose a massive security hole?
Running arbitrary user commands is like running queries based on user input... Escaping is the key.
First, validate if it is an executable using is_executable().
PHP exposes two functions for this: escapeshellarg() and escapeshellcmd().
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.
escapeshellcmd() escapes any characters in a string that might be used to trick a shell command into executing arbitrary commands.
This should limit the amount of risk.
if(is_executable($somethingAUserHasEntered)) {
shell_exec(escapeshellarg($somethingAUserHasEntered) . " --version");
}
After all, doing rm --version isn't very harmful, and "rm -rf / &&" --version will get you anywhere very fast.
EDIT: Since you mentioned PATH... Here is a quick function to validate if the file is an executable according to PATH rules:
function is_exec($file) {
if(is_executable($file)) return true;
if(realpath($file) == $file) return false; // Absolute Path
$paths = explode(PATH_SEPARATOR, $_ENV['PATH']);
foreach($paths as $path) {
// Make sure it has a trailing slash
$path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
if(is_executable($path . $file)) return true;
}
return false;
}
You could try a simple file_exists call to determine if something exists at that location, along with an is_executable to confirm that it's something you can run.
have you looked at is_dir() or is_link() or is_file() or is_readable()
Hope these help.
system('which '.escapeshellarg($input)) will give you the absolute path to the executable, regardless if it's just the name or an absolute path.