PHP json_encode to JS object not usable - php

I have an some PHP that looks like this:
$exec[0] = shell_exec("cat /etc/msm.conf | grep JAR_PATH");
$exec[1] = shell_exec("msm server list");
if(strstr($exec[1],'[ ACTIVE ] "mc-srv" is running. Everything is OK.') !== FALSE){
$exec[1] = 'mc online';
}else{
$exec[1] = 'mc offline';
}
$exec[2] = shell_exec("sudo ts status");
if($exec[2] == 'Server is running'){
$exec[2] = 'ts online';
}else{
$exec[2] = 'ts ofline';
}
echo json_encode($exec,JSON_FORCE_OBJECT);
An AJAX request gets sent to the page and the json is returned.
If I use console.log(JSON.parse(data)) I see this in the console Object {0: "DEFAULT_JAR_PATH="server.jar"↵", 1: "mc online", 2: "ts ofline"} however I can not access any of its methods even if i use an associative array.
but If i create a new object and print that to the console it (in chrome atleast) looks exactly the same in terms of syntax highlighting exect I can access it via obj.method.
What am I doing wrong here?

Based on how the object is being output in the console, it looks like it's being parsed okay by JSON.parse and is valid.
In which case, you should be able to access each method like this:
var obj = JSON.parse(data);
console.log( obj['0'] ); // returns "DEFAULT_JAR_PATH="server.jar""
console.log( obj['1'] ); // returns "mc online"
obj.0 won't work in this case because the method names are numbers.

Related

Passing HTML to Node.js from PHP

I have an application mostly written in PHP, but there is a npm package that has functionality that I need to incorporate into my application. I must pass a string of HTML into the Node.js application but am having issues in getting things correct. I'm using:
exec('node '.$rootPath.'node/app.js '.$imageId.' email '.escapeshellcmd($emailString).' 2>&1', $output, $retVar);
to send the data to my Node.js application, but I'm unsure as to how to decode it once it gets there and needs to be processed via JavaScript. Is there a way to unescape escapeshellcmd() in JavaScript? Or is there a different way I should pass these long strings of HTML over the command-line?
EDIT: Here is the exact method I'm using to pass my info to Node.js:
try{
$emailString = escapeshellcmd($decoded);
//`node $rootPath'node/app.js' $imageId email $emailString 2>&1`;
exec('node '.$rootPath.'node/app.js '.$imageId.' email "'.$emailString.'" 2>&1', $output, $retVar);
print_r($output);
}catch(Exception $e){
echo $e->getMessage()."\n";
}
And here is app.js:
process.argv.forEach(function(value, index, array){
if(index == 2){
id = value;
}
if(index == 3){
type = value;
}
if(index == 4){
visual = value;
}
});
console.log('******* FROM NODE********');
console.log(visual);
It seems like only the first line is getting passed or collected and printed back, and it looks like it's still encoded (unless the console is re-encoding when printing). Also I'm not sure why it seems to be appending values instead of overwriting them:
Array
(
[0] => ******* FROM NODE********
\<head\>\<style type=text/css\>body \{padding:0\; margin:0\; text-align:center\;.tbl1 \{background-color:\#a53f0f\; color:\#fff\; text-align:center\; font-size:\<body data-gramm=true data-gramm_editor=true data-gramm_id=ccdbd45c-b0bf-4691-9\<table border=0 cellpadding=0 cellspacing=0 style=background-color:
)
Array
(
[0] => ******* FROM NODE********
\<head\>\<style type=text/css\>body \{padding:0\; margin:0\; text-align:center\;.tbl1 \{background-color:\#a53f0f\; color:\#fff\; text-align:center\; font-size:\<body data-gramm=true data-gramm_editor=true data-gramm_id=ccdbd45c-b0bf-4691-9\<table border=0 cellpadding=0 cellspacing=0 style=background-color:
[2] => ******* FROM NODE********
\<html xmlns=http://www.w3.org/1999/xhtml xmlns:v=urn:schemas-microsoft-com:vml \<meta name=viewport content=width=device-width,e\>
)
Note: You should use streams over arguments for data to be processed. This is the common way as commands work in the Unix world.
In your code you try to use escapeshellcmd to escape double quote " an encapsulated argument string. This does not work. There is an escapeshellarg PHP function as well. It will encapsulate the string in single quotes ' and escape characters that are even in single quoted strings treated in a special way by the shell.
Assuming $decoded is something like
$decoded = '<body lang="en">very boring message</body>';
then you do not enclose it into quotes yourself. Let escapeshellarg do the trick.
$emailString = escapeshellarg($decoded);
$imageIdString = escapeshellarg($imageId);
exec("node app.js {$imageIdString} email {$emailString} 2>&1", $output, $retVar);
As mentioned above, you really should consider to work on streams instead of arguments. The advantage is that the data can grow to an arbitrary size. Further more proc_open handles STDOUT and STDERR separately. This can be done like that:
try
{
if($handle = proc_open("node app.js {$imageId} email";, [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $streams))
{
[$stdin, $stdout, $stderr] = $streams;
fwrite($stdin, $decoded);
fclose($stdin);
$output = stream_get_contents($stdout);
fclose($stdout);
$error = stream_get_contents($stderr);
fclose($stderr);
proc_close($handle);
}
echo 'OUTPUT:', PHP_EOL, $output, PHP_EOL;
echo 'ERRORS:', PHP_EOL, $error, PHP_EOL;
}
catch(Exception $e)
{
echo $e->getMessage(), PHP_EOL;
}
Here is an example node.js script handling both, data by arg as well as by stdin:
(() =>
{
'use strict';
console.log('******* FROM NODE********');
const
getStdin = require('get-stdin');
var id, type, visual;
[,, id, type, visual] = process.argv;
// if 4th command line argument is present, use that
if(undefined !== visual)
processData(visual);
// otherwise read data from stdin stream
else
getStdin().then(visual =>
{
processData(visual);
});
function processData(data)
{
console.log('id' , id );
console.log('type', type);
console.log('STDIN:', data);
console.error('no errors');
console.log('******* DONE *******');
}
})();
While Quasimodo's clone's answer does work, his comment on the question made me think about passing the large strings of HTML. I have instead opted to write the html to file and reference with the id.

php - Detect bad request

I have 2 JSON sources and one of them reply 400 Bad request (depend of charge in servers)
So I want that my php code check the answer of both server and select working one
<?php
$server1 = 'server1.lan'
$server2 = 'server2.lan'
/*
Here a code to check and select the working server
*/
$json=file_get_contents('https://'.$workingServer.'/v1/data?source='.$_GET['source']);
$data = json_decode($json);
if (count($data->data)) {
// Cycle through the array
foreach ($data->data as $idx => $data) {
echo "<p>$data->name</p>\n";
?>
Thanks !
Below is an idea of what you may want to implement. Your goal is to get that idea and implement something like that in your own way, with a normal error handling and removal of code duplication:
$json = file_get_contents('https://server1.lan/v1/data');
if ($json === false)
{
$json = file_get_contents('https://server2.lan/v1/data');
if ($json === false)
{
die('Both servers are unavailable');
}
}
file_get_contents returns boolean false on failure, so if the first server is unavailable, call the second. If it is also unavailable, exit the script, or do some sort of error handling that you prefer.
You may want to create an array of possible server names, and use a function that iterates over all of them until it finds a working one, and returns the contents, or throws an exception on failure.
I would also suggest that you use curl, which gives you an option to see the error codes of the request, customize the request itself, and so on.
Check $http_response_header after making the file_get_contents call.
$json = file_get_contents(('https://'.$server1.'/v1/data?source='.$_GET['source']);
if (strpos($http_response_header[0],"400") > 0)
{
$json = file_get_contents(('https://'.$server.'/v1/data?source='.$_GET['source']);
}
See examples at http://php.net/manual/en/reserved.variables.httpresponseheader.php

Pass By Reference to COM Object in PHP

So I'm hoping someone can help and I'm sure this is probably something simple I'm missing. I'm using PHP to access a .net API for a third party software.
Based on the very minimalist documentation on the API I have a working vbsript that connects to the object, performs a login and then does a query which results in the output of the query being dumped to a message box.
Here's the vbscript sample:
'Test device status
Set xxx = CreateObject("The.API.Object.Goes.Here")
'Login
Result = Xxx.LoginToHost("xxx.xxx.xxx.xxx","8989","Administrator","")
if (Result = true) then
MsgBox("OK")
else
MsgBox("Error - " & Xxx.LastError)
WScript.Quit
end if
'Get Status
Result = Xxx.GetDeviceStatus("", out)
if (Result = true) then
MsgBox(out)
else
MsgBox("Error - " & Xxx.LastError)
end if
'Logout
Result = Xxx.Logout()
if (Result = true) then
MsgBox("Logout OK")
else
MsgBox("Error - " & Xxx.LastError)
end if
The Xxx.GetDeviceStatus has two perimeters, the first being a device target or if left blank returns all devices, the second is the string variable to dump the result in.
When the script executes, the second message box contains a list of all devices as I would expect.
In PHP I have:
$obj = new DOTNET("XxxScripting, Version=1.0.XXXX.XXXXXX, Culture=neutral, PublicKeyToken=XXXXXXXXXXXXXXXX","Here.Goes.The.Api");
$obj->LoginToHost('xxx.xxx.xxx.xxx','8989','Administrator','');
$result = $obj->GetDeviceStatus('','out');
echo $result."<br />";
echoing result gives 1 because the value of result is a boolean value and GetDeviceStatus is successful. What I can't figure out is how to get the value of 'out' which is the actual query result.
Any help would be greatly appreciated.
The second parameter of GetDeviceStatus() method call according to the VBScript should pass a variable that will be populated with the output.
However in the PHP example you are just passing the string 'out' which isn't equivalent to what is being done in the VBScript.
Instead try passing a PHP variable to the method and then echoing that variable to screen, like this;
$result = $obj->GetDeviceStatus('', $out);
if ($result)
echo $out."<br />";
After a bit of digging it appears according to the PHP Reference that you need to pass By Reference variables to COM using the VARIANT data type.
Quote from ferozzahid [at] usa [dot] com on PHP - COM Functions
"To pass a parameter by reference to a COM function, you need to pass VARIANT to it. Common data types like integers and strings will not work for it."
With this in mind maybe this will work;
$out = new VARIANT;
$result = $obj->GetDeviceStatus('', $out);
if ($result)
echo $out."<br />";

POSTing binary data over http with Python -> PHP

I'm want to post a binary data string from a Python script to a webserver where a PHP script should pick it up and store it. I receive the whatever I echo in my POST part of the php script on the Python side so I assume, the actual POST works. However, I'm posting 23 Bytes and strlen($_POST['data']) stays 0.
My PHP script to pickj up the data looks like this:
if (isset($_REQUEST["f"]) && $_REQUEST["f"]=="post_status") {
$fname = "status/".time().".bin";
if (file_exists($fname)) {
$fname = $fname."_".rand();
if (file_exists($fname)) {
$fname = $fname."_".rand();
}
}
echo strlen($_POST['data'])." SUCCESS!";
}
and the Python POST script looks like this:
data = statusstr
host = HOST
func = "post_status"
url = "http://{0}{1}?f={2}".format(host,URI,func)
print url
r = urllib2.Request(url, data,{'Content-Type': 'application/octet-stream'})
r.get_method = lambda: 'PUT'
response = urllib2.urlopen(r)
print "RESPONSE " + response.read()
Why does my data not seem to get through, I'm wondering?
Thank you,
PHP will only populate posted values into the $_POST/REQUEST arrays for data that is sent as one of the form data content types. In your case, you need to read in the binary data directly from standard in like this:
$postdata = file_get_contents("php://input");

Json problem in flickr

I have this json but I have no idea how to get 7796249#N02
a:2:{s:4:"user";a:3:{s:2:"id";s:11:"7796249#N02";s:4:"nsid";s:11:"7796249#N02";s:8:"username";a:1:{s:8:"_content";s:9:"ilhan.z.y";}}s:4:"stat";s:2:"ok";}
That is a serialized PHP array, not JSON. Use:
$array = unserialize('that response goes in here');
What language are you using? In Groovy, for example, you would do something like this:
import groovyx.net.http.*
#Grab(group='org.codehaus.groovy.modules.http-builder',
module='http-builder', version='0.5.0' )
def http = new HTTPBuilder( 'http://twitter.com/statuses/' )
http.get( path: 'user_timeline.json',
query: [id:'httpbuilder', count:5] ) { resp, json ->
println resp.status
json.each { // iterate over JSON 'status' object in the response:
println it.created_at
println ' ' + it.text
}
}
Edit after PHP tag added:
I'm not a PHP guy, but it looks like json_decode is what you need to use.

Categories