I'm attempting to use the VirusTotal API to return the virus scan for a certain file. I've been able to get my current PHP code to upload the file to VirusTotal as well as get the results in an array. My question is, how would I get the [detected] value from every virus scanner under the scans object? My PHP code is below as well as a link to the output of the array.
require_once('VirusTotalApiV2.php');
/* Initialize the VirusTotalApi class. */
$api = new VirusTotalAPIV2('');
if (!isset($_GET["hash"])) {
$result = $api->scanFile('file.exe');
$scanId = $api->getScanID($result);
$api->displayResult($result);
} else {
$report = $api->getFileReport($_GET["hash"]);
$api->displayResult($report);
print($api->getSubmissionDate($report) . '<br>');
print($api->getReportPermalink($report, TRUE) . '<br>');
}
http://joshua-ferrara.com/viruscan/VirusTotalApiV2Test.php?hash=46faf763525b75b408c927866923f4ac82a953d67efe80173848921609dc7a44
You would probably have to iterate each object under scans in a for loop and either store them in yet another array or echo them out of just want to print. For example
$detectedA = {nProtect, CAT-QuickHeal, McAfee...nth};
$datContainer = array();
for ($i = 0; i < $api.length ; i++){
//Either store in an array
$api->$scans->detectedA(i)-> detected = $datContainer(i);
//Or echo it all
echo $api->$scans->detectedA(i)->detected;
return true;
}
Granted that's probably not the way you access that object but the idea still applies.
This description of stdClass demonstrates how you can not only store arbitrary tuples of data in an object without defining a class, but also how you can cast an arbitrary object as an array - which would then let you iterate over the sub-objects in your case.
Or, if I've misunderstood your question and you're actually getting an array back from the VirusTotal API and not a stdClass instance, then all you need to do is loop.
Store the scans into an array (of scans), then just loop through the array as usual.
foreach($scans as $scan) echo $scan->detected;
Or, if I'm not quite understanding the question right, is detected an array (or an object)?
Edit because of your comments -
The object returned holds an object of objects, so you need to do some casting.
foreach((array)$scans as $scanObj) {
$scan=(array)$scanObj;
foreach($scan as $anti) {
print $anti->detected; } }
Related
Not sure what issue was with first pastebin code, here is another attempt.
I am connecting to Vimeo Live API, in doing so the response is huge > 500kb in total - I have an example with only one object here -> there are over 20 it returns. I have a better idea of what Im doing in JS than PHP, but returning the huge array or json to the browser doesn't seem like a good idea and its use of repeated ajax calls isn't good either. So this question is two fold, both in theory and practice. Is this a good design and how do I filter the result in PHP and only send what I need back to browser.
Here is the design, or at least what I think is best:
page loads, sends ajax request to PHP script
PHP script connects to API and gets response in an array (example of one object)
Search through the array for 'metadata->connections->live_video' for one that has an associated array containing [status] => streaming'
If one (there will only be one at a time) is found, return that whole object and that object only, not the entire array.
At this time I do not have a complete understanding of how this data should be returned or formatted for ease of sifting through. Ive tried using json_encode on the array, which gets nicely formatted JSON but I can't iterate through it and can only get single objects like data[0]->metadata->connections->live_video. Ive tried json_encode, then json_decode and Im back to a similar array structure of what is originally sent.
However, in the browser I am able to return the whole array and in the success function of the ajax call sift through it via JS like so:
let live_stream = json.data.filter(function(value, key) {
let connection = value.metadata.connections['live_video'];
return connection && connection.status === 'streaming';
});
I know this isn't the right way, I know I need to sift through the array, find the object / key Im looking for and only return that. Any advice is appreciated, once I get this figured out, I can apply it in a range of ways for this project.
The closest I can get in PHP is:
function live_event() {
global xxx;
$lib = xxx;
$response = xxx;
$body = $response['body'];
header('Content-Type: application/json');
$jsonstr = json_encode($body);
$json = json_decode($jsonstr);
foreach ($json->data as $item) {
if ($item->uri == "/live_events/2354796") {
echo"one";
}
}
}
and this:
function live_event() {
$global xxx;
$lib = xxx;
$response = xxx;
$body = $response['body'];
header('Content-Type: application/json');
$jsonstr = json_encode($body);
$json = json_decode($jsonstr,true);
$results = array_filter($json['data'], function($item) {
return $item['metadata']['connections']['live_video']['status'] == "streaming";
});
var_dump($results);
}
last one gets me this error "Warning: Trying to access array offset on value of type null in /var/www/vhosts/mysite.com/httpdocs/SSI/Vimeo.php on line 31" is there something similar to optional chaining in PHP? if its null I don't want it to log an error.
This at least output "one" as there is only one object with [uri]=>"/live_events/2354796". I can't get it to return that entire object or search one more nested array deeper.
There are a few things that come to mind.
OBJECTS:
If you're using PHP 8 you could use the safe access operator
function live_event() {
//...
$results = []
foreach ($json->data as $item) {
if($item?->metadata?->connections?->live_video?->status == 'streaming'){
$results[] = $item;
}
}
return $results;
}
ARRAYS:
For lower versions of PHP it's better to work with arrays when dealing with keys that may or may not exists.
Generally speaking whatever fetch library you're working with will allow you set the output to either array or object. If Object is your only option then yes doing the old json_decode(json_encode($data), true) is the way to go.
checking first isset(). Assuming that's it's desired to filter out results without that key.
function live_event() {
//...
$results = array_filter($json['data'], function($item) {
if(!isset($item['metadata']['connections']['live_video']['status']))
return false;
return $item['metadata']['connections']['live_video']['status'] == "streaming";
});
header('Content-Type: application/json');
echo json_encode([
"status" => true,
"data" => $results
]);
}
or you can always just use the age old trick of suppressing the error with the # symbol. TBH i'm not sure where the # symbol would go to suppress the error, perhaps in front of the filter function definition.
function live_event() {
//...
$results = array_filter($json['data'], function($item) {
return #$item['metadata']['connections']['live_video']['status'] == "streaming";
});
return $results;
}
My php script returns data to the web client where it is processed by javaScript.
If data is found it is stored in an associative array / object. If no data is found I would like to send a blank associative array.
The only example I have seen on line is in the manual where you create an empty class and then instantiate an object from that.
Below is my code and the results it produces on the web client side
$sql = 'select job, client, project from jobs j left join client c on c.key = j.cKey where j.key='.$this->p['reckey'];
if ( $result = $db->query($sql) )
{
if ($result->num_rows > 0)
{
$l = mysqli_fetch_all( $result, $resulttype = MYSQLI_ASSOC );
$this->res_array['info'] = $l[0];
}else{
$this->errors[] = 'No such job # '.$this->p['reckey'];
$this->res_array['info']=[];
}
}else{
$this->errors[] = 'Query failed!';
$this->res_array['info']=[];
}
$this->res_array['errors'] = $this->errors;
echo json_encode ($this->res_array);
Here are two examples of what the data looks like when it arrives at the web client before it is decoded by JSON. Note the difference in the "info" element.
response {"info":{"job":"999","client":"My Company, Inc. ","project":"This Project"},"errors":[]}
error response {"info":[ ],"errors":["No such job # 0"]}
In the successful response I have an object/associative array where I would use the
for (variable in object) {...}
In the blank response I just get the standard array [ ] square brackets where I would use the
for (step = 0; step < info.length; step++) {}
This occurs of course because I am specifying a blank array in the php code above.
My question is simple how can I change my php code so a blank associtive array is transmitted?
The only example I have seen on line is in the manual where you create an empty class and then instantiate an object from that.
Sounds like you've answered your own question!
Since in JavaScript an object and an associative array are basically the same thing all you have to do is replace this line:
$this->res_array['info']=[];
With this one:
$this->res_array["info"] = new StdClass;
Or if you want to make the change only before sending the response you could check for an empty info array and replace it with an empty class.
if(!count($this->res_array["info"]))
$this->res_array["info"] = new StdClass;
I would suggest to take the best of both worlds, and let PHP generate an array of associative arrays, even though you expect at the most one, but at least you'd use the same structure for when you have none.
So change:
$this->res_array['info'] = $l[0];
to:
$this->res_array['info'] = $l;
And then in JavaScript do:
for (var step = 0; step < info.length; step++) {
for (variable in info[step]) {
// ...
}
}
... and if you still need to, you can deal with the no-data condition separately in JavaScript. Something like:
if (errors.length) {
// deal with this case...
}
I"m creating a PHP script that handles JSON input (via a $_POST variable). It"s extracts data from the JSON and uploads it to an SQL database. I want the JSON in a particular format:
$object = json_decode('{
"key_a":[{"value_a":10,"value_b":7},{"value_a":10,"value_b":7},{"value_a":10,"value_b":7}],
"key_b":[{"value_a":10,"value_b":7}],
"key_c":[{"value_a":10,"value_b":7},{"value_a":10,"value_b":7}]
}',true);
Basically, an object with keys in, each of which should hold an array (no matter what size it is). I use json_decode(json,true) to convert it to an associative array (as opposed to object). I"ve had to add lots of checks in for each of the keys, checking if they"re objects or arrays (as the ASP.net page that the extract comes from converts arrays with single objects in, to objects - removing the array that holds them). The checks then convert them back to arrays, if there"s an object where I"d like an array holding an object:
if(is_object($object["key_b"]))
{
$a = array();
$a[] = $object["key"];
$object["key"] = $a;
}
I then iterate through the array, adding the values to rows in an SQL database. This all works fine, but when converting back to JSON with json_encode, any keys that hold arrays with only one object in, remove the array, and leave just the object under that key:
echo(json_encode($object));
// RETURNED JSON
'{
"key_a":[{"value_a":10,"value_b":7},{"value_a":10,"value_b":7},{"value_a":10,"value_b":7}],
"key_b":{"value_a":10,"value_b":7},
"key_c":[{"value_a":10,"value_b":7},{"value_a":10,"value_b":7}]
}'
You see, key_b no longer holds an array, but an object! This is really annoying, as I plan to create a JavaScript script that iterates through the arrays, adding one DOM element (div) for each of the objects.
Why does this happen? Is there any way to keep them as arrays, even if there"s only one object in the array?
I"ve tried:
if(is_object($object["key_b"]))
{
$a = array();
$a[] = array_values($object["key"]);
$object["key"] = $a;
}
and
if(is_object($object["key_b"]))
{
$a = array();
$a[0] = array_values($object["key"]);
$object["key"] = $a;
}
But it seems like nothing prevents json_encode from affecting the JSON in this way.
It"s not hard to get around this - but it means adding one check per key (checking whether it"s an array or value), which is particularly time consuming as the data extract that comes through is really big.
Any advice would be greatly appreciated.
EDIT: changed ' to " in JSON - though, this is only an example I just wrote to show the structure.
EDIT: I'm using references to cut my coding time down, if this changes anything?:
$t =& $object["key_b"];
if(is_object($t))
{
$a = array();
$a[] = $t;
$t = $a;
}
It appears using is_object() on a key of an associative array will not return true. I just knocked up this example, to prove this:
$json = json_decode('{"job_details":{"a":[{"x":5},{"y":23},{"z":18}],"b":{"x":19},"c":[{"x":64},{"y":132}]}}',true);
echo(json_encode($json)."<br><br>");
$t =& $json["job_details"]["b"];
if(is_object($t))
{
$a = array();
$a[] = $t;
$t = $a;
echo("IS OBJECT<br><br>");
}
echo(json_encode($json));
I will find another means of checking what value is held within an associative arrays key.
I was actually trying to find whether the value in the key is an associative array or not (not an object) - I just didn't realise they were different in PHP.
I must just use this custom function:
function is_assoc($array)
{
return (bool)count(array_filter(array_keys($array), 'is_string'));
}
From: How to check if PHP array is associative or sequential?
Which returns true if the value is an associative array.
I've just started out learning PHP/JSON and I've kind of worked out how to output an array from an json file. My aim is to output all the album titles in <li>'s (in this case they are called collectionName in the json file). I think I maybe going about it the wrong way though.
$artistId = '644708';
$otherAlbumsURL = 'http://itunes.apple.com/lookup?id='. $artistId .'&entity=album';
$a = (array)json_decode(file_get_contents($otherAlbumsURL));
var_dump($a);
If you want an array, just use:
$a = json_decode(file_get_contents($otherAlbumsURL), true);
var_dump($a);
Setting the second parameter in json_decode to TRUE will give you an associative array instead of an object.
Judging from the response of the URL, you'll need to loop through the result like this in order to get any available collection names (the first array element doesn't contain a collection name because it is information about the artist. i.e. it isn't an album):
$artistInfo = $a['results'][0]; //Assign artist info to its own variable.
unset($a['results'][0]); //Delete artist info from the array.
//Loop through the results
foreach($a['results'] as $result){
//$result['collectionName'] has the collection name.
echo $result['collectionName'] . '<br>';
}
I want to get polygon coordinates from below String.
{"polygon":{"type":"Feature","properties":[],"geometry":{"type":"Polygon","coordinates":[[[-7302732.4720101,6527844.6333235],[-3193477.8319711,6606116.1502766],[-5111129.9973226,5001550.0527375],[-6637424.5779086,4884142.7773079],[-7772361.5737289,5158093.0866438],[-7302732.4720101,6527844.6333235]]]},"crs":{"type":"name","properties":{"name":"urn:ogc:def:crs:OGC:1.3:CRS84"}}}}
This is GeoJson string that i decode to array with below code:
$polygon = CJSON::decode($str);
when i want to get polygon i get error!
$var= $polygon->polygon;
or with below code:
$polygon = CJSON::decode($str,true);
$var = $polygon['polygon'];
although for getting coordinates:
foreach($polygon as $key=>$value)
$coordinates = $value['coordinates'];
or
$coordinates = $value[coordinates];
how can i get coordinates from geojson that i send from javascript to php for saving on postgresql with postgis?
$polygon->polygon->geometry->coordinates[0]
or
$polygon['polygon']['geometry']['coordinates'][0]
what you have is a multidimensional array/object not sure which its being output to when decoded in your case as it appears you have a class doing it I would have just used json_decode, but anyway. Yea from the looks of it, polygon is the main object, then in it is geometry which is an object that has type and coordinates, and then coordinates has multiple objects/arrays in it.
the above samples if I typed them right will show the first set of coordinates in that object. Of course you could run it through a loop ie:
In the case that it is an object assuming your Class decodes as an object and not an array. Not exactly sure what $polygon = CJSON::decode($str,true); does. But if its anything like json_decode() then you should be all set.
This is my method of breaking down the object as you present here, its worth noting you may want to check counts, and see if the object is set first, or if the property exists in the object to prevent other means of the code breaking down the road. But what I have here is just pure example at its core, it will server its purpose though. But will not error handle which is why I say you may want to elaborate further on it doing those checks.
Anyway heres my code:
<?php
$str = '{"polygon":{"type":"Feature","properties":[],"geometry":{"type":"Polygon","coordinates":[[[-7302732.4720101,6527844.6333235],[-3193477.8319711,6606116.1502766],[-5111129.9973226,5001550.0527375],[-6637424.5779086,4884142.7773079],[-7772361.5737289,5158093.0866438],[-7302732.4720101,6527844.6333235]]]},"crs":{"type":"name","properties":{"name":"urn:ogc:def:crs:OGC:1.3:CRS84"}}}}';
$polygon = json_decode($str);
echo'<pre>';print_r($polygon);echo'</pre>';
$set = 1;
foreach($polygon->polygon->geometry->coordinates[0] as $coordinates)
{
echo 'Set '.$set.': ';$set++;
echo $coordinates[0].','.$coordinates[1].'<br>';
}
?>
see it in action http://7pz.net/geojson-parse.php (scroll to the bottom)
This should give you an array of all the coordinates and print them out line by line:
$string = '{"polygon":{"type":"Feature","properties":[],"geometry":{"type":"Polygon","coordinates":[[[-7302732.4720101,6527844.6333235],[-3193477.8319711,6606116.1502766],[-5111129.9973226,5001550.0527375],[-6637424.5779086,4884142.7773079],[-7772361.5737289,5158093.0866438],[-7302732.4720101,6527844.6333235]]]},"crs":{"type":"name","properties":{"name":"urn:ogc:def:crs:OGC:1.3:CRS84"}}}}';
$json = json_decode($string);
$coords_array = $json->polygon->geometry->coordinates[0];
foreach($coords_array as $c_a) {
echo $c_a[0] . "," .$c_a[1] . "<br>";
}
Access with:
$coords_array[0];
$coords_array[1];
$coords_array[2];
etc.
Basically you can turn the JSON string into an object and access each element with the -> notation.
I usally use a site called http://jsonviewer.stack.hu/ to decode JSON and find the path I need, then simply write them out as they appear, as in as in the above - $json->polygon->geometry->coordinates;.
Try it out yourself on the site.