PHP shell_exec($cmd) command not working with variables - php

I have a php script that run an http post request with json data using the shell_exec command.
The PHP function receive json encoded data and the url as variables.
I am trying to build the string to be sent to shell_exec command using the above variables.
As you can see in sample code below, the first string ($cmd) has $jsonDataEncoded as variable (the url is clear text). This string works fine with the shell_exec command, and json data are returned from the server.
The second one ($cmd1) has both $jsonDataEncoded and $url as variables. This string DOES NOT work with shell_exec command.
I have tried to compare both strings, even with hexadecimal compare, and they seem qite the same.
Thank you for your suggestion.
Here is the code:
function HttpPost ($url, $jsonDataEncoded)
{
//$url=https://cloud.sample.com/web/api2/v1/auth/login
//$jsonDataEncoded= my encoded json string.
//the following string is working
$cmd = "curl -X POST -H \"Content-Type: application/json\" \
-d '".$jsonDataEncoded. "' \
https://cloud.sample.com/web/api2/v1/auth/login";
//the following string is NOT working
$cmd1 = "curl -X POST -H \"Content-Type: application/json\" \
-d '".$jsonDataEncoded. "' \ ". $url;
$result = shell_exec($cmd);//WORKS
//$result = shell_exec($cmd1);//FAILS
$json = json_decode($result, true);
return $json;
}

You should remove the last \ character, it expects input on a new line. So this should work:
$cmd1 = "curl -X POST -H \"Content-Type: application/json\" \
-d '" . $jsonDataEncoded . "' " . $url;
By the way, using shell_exec isn't a proper way to send POST requests in PHP.
You can use a libary for that:
https://www.php.net/manual/en/book.curl.php
https://www.php.net/file_get_contents

Related

Convert curl with additional parameters into PHP curl

Trying to convert a curl command for building Jenkins jobso I can use it in PHP. Here is what I do:
<?php
$testrun_id = "1744";
$cmd="curl -X POST http://build:f9280f220bfb4c596f83a0#mobile-jenkins.me.com:8080/job/android-job-git/build --data-urlencode json='{"parameter": [{"name":"POST_RESULTS", "value":"true"}, {"name":"RUN_ID", "value":"{$testrun_id}"}, {"name":"CHECK_NAME", "value":"SampleAutomatedPlan"}]}'";
exec($cmd, $result);
?>
Here I am passing 3 parameters to the jenkins job and they are POST_RESULTS with value true, RUN_ID with value of var $testrun_id which is 1744 and CHECK_NAME whose value is SamplAutomatedPlan. When I run this curl command on mac terminal, it works perfectly fine.
What would be the missing things OR errors that gives me Parse error: parse error on that $cmd="curl..." line when I try to run this php script?
You need to escape the double quotes by adding backslashes.
$cmd = "curl -X POST http://build:f9280f220bfb4c596f83a0#mobile-jenkins.me.com:8080/job/android-job-git/build --data-urlencode json='{\"parameter\": [{\"name\":\"POST_RESULTS\", \"value\":\"true\"}, {\"name\":\"RUN_ID\", \"value\":\"{$testrun_id}\"}, {\"name\":\"CHECK_NAME\", \"value\":\"SampleAutomatedPlan\"}]}'";

json_decode deserialization error with curl

I've created a Rest API that is working well, but I noticed a strange thing. For deserializing the content sent by the client I use this code:
var_dump(json_decode(file_get_contents("php://input"), true));
If I send a request with POSTMAN (Chrome Extension), all is working well, see:
but if I use curl with MINGW64, I'll get NULL:
Now in both cases, I checked the encoding type which was with this code:
$content = file_get_contents("php://input");
$encode = mb_detect_encoding($content, "auto");
$json = mb_convert_encoding($content, $encode);
var_dump($json);
and this returns UTF-8
I don't understand why, with curl MINGW64, the console is not working, yet with the extension, or is working. What's happeni.g?
UPDATE
I've executed this function: json_last_error(), and it returned 5. On this site, I saw that the number corresponds to an error:
5 = JSON_ERROR_UTF8
But I have no idea what is wrong.
Since you are submitting JSON data in the body, you need to tell the server the content-type, otherwise cURL is sending it as application/x-www-form-urlencoded.
Additionally, any UTF-8 characters need to be encoded in \uXXXX format to have a valid JSON string.
Try:
curl -i -H "token: company" \
-H "Content-type: application/json" \
-d '{"Code": "R89d", "Descri": "Questo \u00E8 un test"}' \
-X PUT http://localhost/api/customer/add
Edit:
Not sure what you're starting out with, but you can use the following two commands to supply cURL with a proper JSON string.
var=$(php -r 'echo json_encode(["Code" => "R89d", "Descri" => "Questo รจ un test"]);')
curl -v -H "Content-type: application/json" -d "$var" http://sandbox/test.php
Converting encoding to utf-8 worked for me.
$retorno_transaction = mb_convert_encoding($retorno_transaction, 'UTF-8');

Passing arguments from PHP to a remote shell script

I am executing a shell script located on a remote machine from a PHP script. So, let's say that PHP script runs on A and shell script runs on B (10.0.0.37).
I have the following code which runs well
$cmd = "ssh 10.0.0.37 /usr/tmp/script.sh";
exec($cmd, $output);
Now, I want to pass arguments to the shell script, preferably in JSON format.
The output of echo json_encode($arg) is as follows:
[{"original_name":"pdf_convert","changed_name":"pdf_convert_1"},{"original_name":"video_encode","changed_name":"video_encode_1"},{"original_name":"video_transcode","changed_name":"video_transcode_1"}]
I want to pass this as an argument to the shell script. So,
$data = json_encode($data);
$cmd = "ssh 10.0.0.37 /usr/tmp/script.sh $data";
exec($cmd, $output);
However, I see that the argument is not correctly read by the shell script. I tried putting single quotes around $data, didn't work. Also, tried using escapeshellarg($data), still did not work.
Edit
The output of echo escapeshellarg($data) is
'[{"original_name":"pdf_convert","changed_name":"pdf_convert_1"},{"original_name":"video_encode","changed_name":"video_encode_1"},{"original_name":"video_transcode","changed_name":"video_transcode_1"}]'
Also, if there is any other format which can be parsed easily in a shell script, then I would lie to use that format (not necessarily JSON). I see that I may have to use 'jq' to parse json which needs me to install an additional package.
Bash isn't very good at accepting a JSON string in as arguments...
One way to get around bash trying to parse the arguments is for your php script to write the JSON string to a file, and for the bash script to parse that file with jq
I was able to use serilaize to send the json data. Below is the code.
$data = json_encode($arg)
$data = escapeshellarg($data);
$data = serialize($data);
$data = str_replace('"','\"',$data);
$cmd = "ssh 10.0.0.37 /usr/tmp/script.sh $data";
I can now get the data in the shell script.
PHP:
<?php
$json = '[{"original_name":"pdf_convert","changed_name":"pdf_convert_1"},{"original_name":"video_encode","changed_name":"video_encode_1"},{"original_name":"video_transcode","changed_name":"video_transcode_1"}]';
$cmd = $json;
$cmd = addslashes($cmd);
// addslashes does not escapes curly braces
$cmd = strtr($cmd, array('{' => '\\{', '}' => '\\}'));
$cmd = escapeshellarg($cmd);
$cmd = "ssh localhost echo $cmd";
echo "\n$cmd\n\n";
exec($cmd, $output);
var_dump($output)
Shell (/tmp/1.sh):
#!/bin/sh
echo "$1"
Shell Output:
ssh localhost /tmp/1.sh '[\{\"original_name\":\"pdf_convert\",\"changed_name\":\"pdf_convert_1\"\},\{\"original_name\":\"video_encode\",\"changed_name\":\"video_encode_1\"\},\{\"original_name\":\"video_transcode\",\"changed_name\":\"video_transcode_1\"\}]'
array(1) {
[0]=>
string(200) "[{"original_name":"pdf_convert","changed_name":"pdf_convert_1"},{"original_name":"video_encode","changed_name":"video_encode_1"},{"original_name":"video_transcode","changed_name":"video_transcode_1"}]"
}

running exec command in php does not function

I am having a problem running this command inside of php's exec command:
UPDATED WORKING CODE:
$results = exec('curl --dump-header - -H "Content-Type: application/json" -X PUT --data #data.json https://website.url --insecure', $output);
if ($results) {
echo "yay!";
var_dump($output);
echo $results;
} else {
var_dump($output);
echo "screw you";
}
originally the script together works in linux but inside php exec the inside single quotes conflicted with php's exec quotes. previous script:
curl --dump-header - -H "Content-Type: application/json" -X PUT --data '{"data": "foo", "data2": "bar"}' https://website.url
I'm wondering what might solve this quotes problem, I thought the escapeshellarg() might do it but to no avail.
Update:
Error from Error page
PHP Warning: escapeshellarg() expects exactly 1 parameter, 0 given
This is a typo. Use the [] to access the $_POST array instead of (). Otherwise name and pass would being empty what will break the command line. Further you'll have to escape incoming posts before using it in a shell command. Otherwise the code is vulnerable for shell cmd injections (what is fatal):
$postname = escapeshellarg($_POST['name']);
$postpass = esacpeshellarg($_POST['pass']);
Also you are missing the spaces before and after the json data. Change it to:
$results = exec('curl --dump-header - -H "Content-Type: application/json" -X PUT --data '.escapeshellarg($jsondata). ' https://website.url');
After that changes the example works for me. But you should note about the php curl extension. I would use it instead of calling curl via exec()
Try this:
$jsondata = '{"data":"'.$_POST['name'].'", "data2":"'.$_POST['pass'].'"}';
$command = "curl --dump-header - -H \"Content-Type: application/json\" -X PUT --data '$jsondata' https://website.url";
$results = exec($command);

Use HTML output of PHP in shell script

I have a PHP script that creates large complex tables. I am attempting to set up a shell script which would accept an ID as an argument and then run the PHP script using the ID and accept the HTML output of the PHP script for use as part of a cURL post to DocRaptor to make a PDF.
Example shell script looks like this and I want the document_content to be my generated HTML.
myHTML = usr/bin/php mytablemaker.php?id=$1
curl -H "Content-Type:application/json" -d'{"user_credentials":"API_KEY", "doc":{"name":"docraptor_sample.pdf", "document_type":"pdf", "test":"true", "document_content":"myHTML"}}' http://docraptor.com/docs > docraptor_sample.pdf
How do I do this correctly?
If that is bash, something like this should work:
myHTML = $(usr/bin/php mytablemaker.php?id=$1)
curl -H "Content-Type:application/json" -d'{"user_credentials":"API_KEY", "doc":{"name":"docraptor_sample.pdf", "document_type":"pdf", "test":"true", "document_content":"'"$myHTML"'"}}' http://docraptor.com/docs > docraptor_sample.pdf
However you don't ask for HTML but for HTML as a json string, so make you PHP script encode the string as json, see json_encode. Or do a addcslashes($output, '"') on the " characters.
See as well:
Bash Scripting: Redirect output into variable
The best way is to modify that mytablemaker.php to take the command line use case into account.
e.g. like this:
if(isset($argv[1])) {
$id=$argv[1];
} else {
$id=$_GET["id"];
}
Then from BASH you do:
# Get HTML from PHP script and escape quotes and
# backslashes in string to comply to the JSON specification
myHTML=$(/usr/bin/php -f mytablemaker.php $1 | sed -e 's/[\\"]/\\&/g')
# Put the value of myHTML in a JSON call and send it to the server
curl -H "Content-Type:application/json" -d'{"user_credentials":"API_KEY", "doc":{"name":"docraptor_sample.pdf", "document_type":"pdf", "test":"true", "document_content":"'"$myHTML"'"}}' http://docraptor.com/docs -o docraptor_sample.pdf
Note the string concatenation done at the last line:
'first part'"second part"'third part'
The examples supplied did not mention a document_url parameter but DocRaptor's error message did.
Working code using what I learned from hakre and anttix!
curl -H "Content-Type:application/json" -d'{"user_credentials":"API_KEY", "doc":{"name":"docraptor_sample.pdf", "document_type":"pdf", "test":"false", "document_url":"'"http://foo.com/tablemaker.php?CTN=$1"'"}}' http://docraptor.com/docs -o docraptor_sample.pdf

Categories