GithubHelp home page GithubHelp logo

php-shellcommand's People

Contributors

4n70w4 avatar achoarnold avatar angrybrad avatar arzaroth avatar diimpp avatar dredav avatar habd0u avatar kirill89 avatar mikehaertl avatar motammem avatar robindfuller avatar schmunk42 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

php-shellcommand's Issues

setStdIn() doesn't work with useExec

It looks like setStdIn() doesn't work with useExec.

I propose the following method to allow setStdIn() to work with useExec, at least when $this->_stdIn is a string:

$tmp_file = tmpfile();
$tmp_path = stream_get_meta_data($tmp_file)['uri'];
fwrite($tmp_file, $this->_stdIn);
fflush($tmp_file);
$command = "cat ".escapeshellarg($tmp_path)." | $command";
...
fclose($tmp_file);

Using cat is a bit ugly, but maybe someone can come up with an improvement. Something similar can be done when $this->_stdIn is not a string.

Command hangs forever after update from 1.2.2 to 1.2.3

Hanging test: https://github.com/dmstr/phd5-app/blob/master/tests/codeception/cli/DbDumpCept.php

Output:

Cli Tests (5) ------------------------------------------------------------------
✔ 1-InitCept:  (4.90s)
✔ AuditCept:  (0.10s)
make: *** [run-tests] Error 137
stdin: is not a tty
ERROR: Build failed: execution took longer than 3600 seconds

It's a rather simple DB-dump which takes <1s in the test setup.

Works fine after reverting to 1.2.2

escapeArgs option is not working properly

I expect that addArg() escapes all arguments preventing possibility of command injection from untrusted sources.

Because in the README.md I see:

  • Handle argument escaping

  • $escapeArgs: Whether to escape any argument passed through addArg(). Default is true.

But it is not actually happens.

PoC:

<?php
require_once 'vendor/autoload.php';

use mikehaertl\shellcommand\Command;

$command = new Command(array(
    'command' => 'curl',
    'escapeArgs' => true,
));
// In this example "escapeArgs" is set to "true", but escaping is not happens.
$command->addArg('http://example.com --wrong-argument || echo "RCE 1"');
$command->execute();
echo $command->getOutput(); // RCE 1

$command = new Command(array(
    'command' => 'curl http://example.com',
    'escapeArgs' => true,
));
$command->addArg('http://example.com');
// In this example, the second argument will be escaped properly, but the first one - not.
$command->addArg('--header foo --wrong-argument || echo "RCE 2" ||', 'bar');
$command->execute();
echo $command->getOutput(); // RCE 2

Disclaimer

This thread was initially started as a private email conversation. @mikehaertl asked me to open an issue here.

proc_close() result

According to http://php.net/manual/en/function.proc-close.php

  1. proc_close() returns -1 on error
  2. If PHP has been compiled with --enable-sigchild, the return value of this function is undefined.

Hence we can't rely on the result, e.g. I see that PDF was created via mikehaertl/phpwkhtmltopdf but proc_close() returns int 3 (testing command via ssh also shows success). Next $this->_exitCode is checked and since it's !==0 command fails.

Passing a command with spaces on Windows doesn't work

Sorry for moving the thread around, I got really confused with all the code.
When I try passing this as an exaple:

 '..\..\..\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe http://localhost/Ponudomat/printRdy.php print.pdf'

The program returns this:

'..\..\..\Program' is not recognized as an internal or external command, operable program or batch file.

It separates the DIR into different commands because of the spaces, to fix it you need to pass the DIR within the "" and that's where the problem kicks in.

When I try:

 '"..\..\..\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe" http://localhost/Ponudomat/printRdy.php print.pdf'

I just keep getting the same error as the one above.
When I try adding "/ instead of " to try and force php into making a quote within a string.
This is the confusing part, when I put:

 '"/..\..\..\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe"/ http://localhost/Ponudomat/printRdy.php print.pdf'

It actually runs the command and partially works. So now I got the .exe running but it gives me an error as it cannot read the parameters it needs because of the "/ so I get:

Loading pages (1/6) [> ] 0% [===> ] 5% [======> ] 10% Error: Failed loading page file:///C:/ (sometimes it will work just to ignore this error with --load-error-handling ignore) [========> ] 14% [=========> ] 15% [==========> ] 17% [============> ] 20% [=================================> ] 55% Exit with code 1 due to network error: ContentOperationNotPermittedError

Because the command is as follows getCommand:

/..\..\..\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe"/ http://localhost/Ponudomat/printRdy.php print.pdf

Don't escape numeric values

Case: $command->addArg('--arg', 123);
Generated command: cmd --arg '123'
But this makes no sense.

May be skip escapeshellarg if ctype_digit($value) === true.

Change shell and add PATH

exec() or proce_open() or shell_exec() every commands internally calls /bin/sh (not /bin/bash) with $PATH as /usr/bin:/bin

  1. Add ability to invoke /bin/bash or other shells.
  2. Add ability to add $PATH variable before running the command.

Examples:

$path_to_add = '/usr/local/bin/';
$command = 'export PATH=$PATH:' . $path_to_add; mycommand';

and

exec("/bin/bash -c \"mycommand\"")

Ideas for addArg

It seems that addArg is doing more than it should, which is causing the code to be a little complicated. In my use case, I'm doing one of a few things, which vary greatly on how the logic needs to behave:

  • Basic key/value pairs - --file, $tarball
  • Arguments only, no values - --extract
  • Values only - $filename
  • Crazy redirects - -O > $destination

(If it wasn't obvious, my test case here is tar.) Since there's a lot going on, but not a lot of flexibility, would it make sense to have a few different methods for addArg, for various use cases.

As a list critique point, passing in '--file=', $tarball looks weird, I feel moving the option for a separator to an argument could make more sense.

Either way, I'm going to monkey patch a local copy I grabbed for a project I'm working on, and can submit my results if you're interested. Otherwise great looking class, the convenience of it handling the necessary proc_* operations is useful.

More secure keys addArg()

Case: $command->addArg('; ls -la', 'something');
Generated command: cmd ; ls -la 'something'
Сan execute any command on the server.

May be can do escapeshellarg for keys too.

Issue with getIsWindows() change.

The recent added check in the $descriptors array for windows has broken functionality for me. Running on a linux machine. Previously had the 'a' descriptor, but now with the getIsWindows() check on line 286, it's returning false, giving a 'w' descriptor. If I am building a small pdf this doesn't seem to be a problem, but for larger pdfs it just hangs. I have temporarily commented out the change here returning it to using the 'a', and everything seems to be in order again.

useExec apparently not working

Hi!

This is probably something that I'm overlooking but I want to comment it if I can help someone else in my situation.

$pdf = new Pdf([
  'command' => 'C:\Program Files (x86)\PDFtk Server\bin\pdftk.exe',
  'useExec' => true,
  'A' => $path1,   
  'B' => $path2
]);
$pdf->shuffle(1, 'end', 'A')
    ->shuffle(1, 'end', 'B')
    ->send('informe.pdf');

I was creating a new PDF that way, using 'command' and 'useExec' parameters, with php-pdftk library because my server has Windows as its OS, but I was always receiving the same error:
Failed without error message: pdftk "command"="C:\Program Files (x86)\PDFtk Server\bin\pdftk.exe" "useExec"="1" "A"="C:\Windows\Temp\phpC9C7.pdf" "B"="C:\Windows\Temp\phpC9D7.pdf" shuffle A1-end B1-end "output" "C:\Windows\Temp\tmpC9D8.tmp.pdf" (Exit code: 1)

To fix that error, I removed 'command' and 'useExec' parameters from the code shown above and changed the following condition in Command.php (line 378) from true to false because I noticed that, despite using 'useExec' parameter with true value, it wasn't changing it's value in that file and now there's no problem creating the PDF:
if ($this->useExec) {

Therefore, my doubt is, am I doing something wrong initializing the PDF or maybe is this a bug?

Thank you for your attention and for creating this awesome tools!

on Windows, leaves a trailing quote in the command

we have been using very old v0.4.4 for some years. We had previously fixed a bug in that version but never reported it here.

today I tested v0.13.1 which has the same bug. This is on Windows system. PHP 8.1.20 with pdftk 2.02

$command = ""C:\Program Files (x86)\PDFtk\bin\pdftk.exe""
above is taken from xdebug: notice the value of $command has leading & trailing double-quote marks

see attached screenshot of debugger
xdebug-shellcommand-command

patch:

--- /mikehaertl/shellcommand/Command-orig.php	Wed Apr 19 04:25:22 2023
+++ /mikehaertl/shellcommand/Command.php	Sun Nov 26 10:54:27 2023
@@ -195,9 +195,7 @@ class Command
                 // Could be a quoted absolute path because of spaces.
                 // i.e. "C:\Program Files (x86)\file.exe"
             } elseif (isset($command[2]) && $command[2] === ':') {
-                $position = 2;
+                // FIX THIS, it leaves a trailing quote
+                $command = trim($command, '"\'');
+                $position = 1;
             } else {
                 $position = false;
             }

without the change the executed command returns an error with no error-description. the problem is it leaves the trailing quote-mark.

the fix simply removes the quotes - this has always worked properly on Windows.

Support for nested commands

Hey,
first of all, i love this lib. It works great. But now i have to generate a command that contains a nested command and i am not sure what the best way is. The command i want to generate looks like that this:

rsync -av --delete -e "ssh -i /home/user/.ssh/sshkey" [email protected]:/home/ /mnt/server-mirror/home/

What would be the best way to generate the ssh -i /home/user/.ssh/sshkey part?
Thanks and greetings
Leo

Issues with proc_* functions and PHP '--enable-sigchild' configure command option

Hi,

It looks like PHP compiled with '--enable-sigchild' will have issues with php-shellcommand when proc_* functions are used (by default). php-shellcommand will return an error when the command executes successfully.

The reason is discussed in the following PHP bug reports:
https://bugs.php.net/bug.php?id=61873
https://bugs.php.net/bug.php?id=71804

There is no issue when using useExec option on a system with PHP compiled with '--enable-sigchild'.

There is not much that can be done other than detecting the '--enable-sigchild' configure command option and adding the useExec option. Unfortunately, there doesn't appear to be any way to do this aside from parsing phpinfo().

Is there any other way to handle this issue?

Thanks.

PHP 5.4 requirement

I am looking at #36 and #31. I might be missing something but is there any technical reason why 5.4 is required? I know we should all be on 7.4, but maybe this requirement is arbitrary and 5.3 works just fine. The reason why I say this is php-pdftk requires this package but requires 5.3 or above, which is kind of strange.

Executing a file with a relative path on Windows is broken

If I pass in a relative path on Windows to execute (assuming what I want to execute is already in the working directory or in my PATH environment variable), it produces incorrect output.

For example:

mysqldump --defaults-extra-file=C:\temp\my.cnf --add-drop-table --comments --create-options --dump-date --no-autocommit --routines --set-charset --triggers --result-file=C:\temp\backup.sql testdatabase

Will produce:

cd "mysqldump --defaults-extra-file=C:\temp\my.cnf --add-drop-table --comments --create-options --dump-date --no-autocommit --routines --set-charset --triggers --result-file=C:\temp" && backup.sql testdatabase

It looks like d9a0e8e is really only a fix for absolute paths.

Windows command from different drive letter fails

If my php file is being executed from my E:\ drive to a command running on my C:\ drive, it doesn't work since the cd is happening on the wrong drive.

I fixed it by doing the following:
$drive = substr($command, 0, 2);
$command = sprintf($drive . ' && cd %s && %s', escapeshellarg(dirname($command)), basename($command));

So $command becomes:
C: && cd "C:\Program Files\wkhtmltopdf\bin" && wkhtmltopdf.exe

Can't run composer on Centos 7

When i tried run this code:

$command = new Command(ROOT_PATH. '/composer/ composer update');
$result = $command->execute())

I get this result:
sh: /var/www/mysite.com/public_html/composer/: Is a directory

wkhtmltopdf processes becomes zombie

In our code that uses mikehaertl/phpwkhtmltopdf we have an option:
['window-status'=>'ready-to-print']

However on some occasions ready-to-print is not set in js. In this case wkhtmltopdf processes will never stop. And after some time we have hundreds of zombie-processes. Is it possible to set max execution time for wkhtmltopdf?

mikehaertl/phpwkhtmltopdf#223

P.S.:
ini_set('max_execution_time', 15);
Should do the job to kill php process and wkhtmltopdf with it right? It does not.

28378 www 1 20 0 213M 31292K piperd 5 0:01 0.00% php-fpm
28588 www 1 20 0 213M 31304K piperd 0 0:01 0.00% php-fpm

It hangs on piperead. max_execution_time apperantly does not work for piperead.


wkhtmltopdf -V
wkhtmltopdf 0.12.4 (with patched qt)

mikehaertl/php-shellcommand 1.2.4
mikehaertl/php-tmpfile 1.1.0
mikehaertl/phpwkhtmltopdf 2.2.1

PHP 7.0.13 (php-fpm)

Incorrect 'Command unexpectedly terminated' error message when proc_get_status is disabled via disable_functions

Hi,

I get a PHP warning that proc_get_status() has been disabled for security reasons on this one system. Apparently, proc_open is allowed, but not proc_get_status. I looked at the code and it looks like the call to proc_get_status was added to solve issue #20.

The thing is, I believe if proc_get_status is disabled, you get the Command unexpectedly terminated without error message even when the command is still running. I suggest changing the code at src/Command.php:431 to check if proc_get_status() is usable and/or check the contents of $status before using it and doing something else if the contents of $status are invalid.

                    while ($isRunning) {
                        $status = @proc_get_status($process);
                        if(!is_array($status))
                        // something...

I am sure there is a better solution that can be used. Maybe seeing if pipes are still open or setting useExecto true in such cases. Maybe useExec can be automatically set based on some checks?

Any thoughts?

Is it possible to reset state?

Let me give you example. Say, you are executing command /abs/path/bin/. You set arguments via addArg(), then execute() and finally getOutput() or getError() or getExitCode(). All of these modifies internal state i.e. we remember output, exit code, etc.

Then, I reset args via setArgs() to empty. Add new args and execute again. But now how can I know if say getOutput() shows output of the first execution or second?

Currently, I am creating new instance of php-shellcommand for each new execution. Is there a more elegant way?

Improve proc_open() configuration

Issue mikehaertl/phpwkhtmltopdf#78 describes a problem that could be fixed with a different pipe configuration, as found here:

http://php.net/manual/en/function.proc-open.php#97012.

I've adopted this in release 1.0.5:

1 => array('pipe', 'w'), // stdout
2 => array('pipe', 'a') // stderr

But this caused new problems as now error capturing seemed to be broken as reported in issue mikehaertl/phpwkhtmltopdf#111.

So the change was undone in 1.0.6:

1 => array('pipe', 'w'), // stdout
2 => array('pipe', 'w') // stderr

A workaround would be, to use one or the other, depending on the OS. But so far I have no information from mikehaertl/phpwkhtmltopdf#78 which OS is really affected. Windows was only my (unconfirmed) assumption.

Imrove error reporting

It seems to be the case that the return value of proc_close() is not really reliable. So sometimes it reports an error, even if everything went fine. We should improve this somehow.

Real time output

Is there a way to show the realtime output of a long running command on the console?

Similar to what's described here.

Test if the needed functions are enabled

Hi,

I'm trying your php-pdftk. I've been receiving some errors, and I found out the problem was related to this library. It took me some time to discover the problem was the lack of enabled functions. Perhaps having an error message notifying that the needed functions are not enabled may save some time. I had to scan the code to see which functions were necessary (exec, proc_open, proc_close, proc_get_status, proc_terminate, escapeshellarg, escapeshellcmd)

In general, I just use something like the next code to discover if a function is present:

    if(!function_exists('exec')) {
        echo "exec is not enabled"; // Do something relevant here
    }

I'm just an occasional PHP developer, sorry if I'm suggesting something silly.

Thank a lot for all your libraries, you are amazing!

PHP hanging indefinitely

I was testing some html conversions using the mikehaertl/phpwkhtmltopdf, when I noticed one made PHP hang indefinitely.

Doing some debug, I found out that it was happening in the php-shellcommand/src/Command.php file at line number 317:

$this->_stdOut = stream_get_contents($pipes[1]); 

After some research, I found a similar problem in this stackoverflow question and an apparent solution. http://stackoverflow.com/questions/31194152/proc-open-hangs-when-trying-to-read-from-a-stream

According to the stackoverflow answer, there is a possibility of an execution not outputting anything to stdout (pipe[1]) when an error occurs, so stream_get_contents waits for a stream that never comes.

As pointed out in the stackoverflow answer, reading the stderr (pipe[2]) before stdout (pipe[1]) did the trick for me, with the PHP finishing execution and the error message being outputted.

$this->_stdErr = stream_get_contents($pipes[2]);
$this->_stdOut = stream_get_contents($pipes[1]); 

My system config:

  • Ubuntu 14.04.1 LTS running as a headless VM on Virutalbox
  • PHP Version 5.5.22-1+deb.sury.org~trusty+1
  • Apache/2.4.12
  • wkhtmltopdf 0.12.2 (with patched qt)

getOutput() does not trim the form feed character

In the Windows environment it appears that the stdOut is preceded by \x0C (ASCII Form Feed character).

This is a problem when the expected stdOut is a JSON response string which will not parse using json_decode() because of the "invisible" form feed character.

The PHP trim() function does not strip these characters by default so the suggested change would be to replace the getOutput() function as follows

    public function getOutput($trim = true)
    {
        return $trim ? trim($this->_stdOut, " \t\n\r\0\x0B\x0C") : $this->_stdOut;
    }

And perhaps extend this change to getError() and getStdErr() as well.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.