PHP to store all variables from loop to use them later - php

I am trying to use some WSDL webservice to do some work with each parameters. This is working absolutely fine; however, once the script is executed, I would like to have "log" emailed to me.
All works fine when I use PRINT, or ECHO inside the loop (this will display all values of different variables from the loop). However, outside of the loop, this will only display ONE variable.
Is there a way to store all variables into array inside of loop so this can be used later on, outside of loop, for example emailing this?
This is what I have tried:
<?php
// API request and response
$requestParams = array(
'Request' => 'Hello'
);
$client = new SoapClient('https://example.com/webservice.asmx?WSDL');
$response = $client->Command($requestParams);
//Load response as XML
$xml = simplexml_load_string($response);
$rows = $xml->children('rs', TRUE)->data->children('z', TRUE)->row;
foreach ($rows as $row) {
$attributes = $row->attributes();
/* XML document contains two columns, first with attribute TO,
second with attribute Ref. This will extract required data */
$To = (string) $attributes->To;
$Ref= (string) $attributes->Ref;
// Here are few more lines in code to do some other work with each variable
// All works absolutely fine until this line
/* I would liket to store all variables so I can use them to email
them as a log in one email */
$ToLog .= "<br>$To</br>";
$RefLog .="<br>$Ref</br>";
}
$to = "nobody#example.com";
$subject = "Script successfully executed";
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$message = $ToLog . $RefLog
mail($to, $subject, $message, $headers);
?>

I think you just need to define both variable before starting the loop, like:
$ToLog = "";
$RefLog = "";
Then if you can put whatever in this variable in side the loop you will get it after the loop, You do not need to take an array.
You do not need to take an array.

try like this
$values = array();
foreach ($rows as $row) {
$values[] = $row->attributes(); //stores the each values to the array
}
print_r($values);

Try something like this
$finalArray = array();
foreach($rows as $row)
{
$finalArray[] = $row["someIndex"];
}
then finalArray should contains all variables from foreach :)

Related

Why my second call on url doesn't work (Laravel,Guzzle)?

This is a function where i call 2 api, from first i get client_id which i used in second url. Problem is that after i call second url my page is loading without end.
Page image
public function getDevices(){
$route='http://localhost:8000/api/devices';
$device= new Client();
$answer= $device->request('GET', $route);
$body = $answer->getBody();
$status = 'true';
$message = 'Data found!';
$final= json_decode($body);
$id_array = array();
foreach ($finalas $item) {
// Add each id value in your array
$id_array[]= $item->clientId;
}
foreach($id_array as $my_id) {
$answer2= $client->request('GET', 'http://localhost:8080/api/devices/deviceAvailability/' . $my_id );
$body2 = $response2->getBody();
$final2= json_decode($body2);
}
return view('new.home', ['clients' => $final, 'status'=> $final2]);
I think
return view('new.home', ['clients' => $final, 'status'=> $final2])
is wrong. Because $final is decoded variable, maybe $final contains several types of variables.
In php, you can not set parameter that contains several types of variables.
Please do like that.
return view('new.home', ['clients' => $body, 'status'=> $final2]);
That's because json encoded variable is only a string.
I want your result.

How to Send via email the Entire Request in PHP

I'm trying to create a php that sends via email all possible information about the request. Currently I'm using something like:
Email request php:
<?php
$remoteIp = $_SERVER['REMOTE_ADDR'];
$remoteHost = $_SERVER['HTTP_HOST'];
$remoteRef = $_SERVER['HTTP_REFERER'];
$remoteUrl = $_SERVER['REQUEST_URI'];
$userAgent = $_SERVER['HTTP_USER_AGENT'];
$yourEmailAddress = "user#mail.com";
$emailSubject = "New request from: ".$remoteIp;
$emailContent = "The URL Request was made to: $remoteUrl
The request REFERER was: $remoteRef
The IP was $remoteIp
The User Agent was: $userAgent";
// send the message
mail($yourEmailAddress, $emailSubject, $emailContent);
?>
I like to add the Entire http request (GET OR POST) to the email been send so $emailContent it look like this:
$emailContent = "The URL Request was made to: $remoteUrl
The request REFERER was: $remoteRef
The IP was $remoteIp
The User Agent was: $userAgent"
The Full request was:
$fullrequest";
Looking around I found this https://gist.github.com/magnetikonline/650e30e485c0f91f2f40 which allows you to create file but I'm not sure on how to put it together with my PHP so it sends me an email with the request. (Creating the file is not necessary)
This PHP I like to integrate to my Email request php
<?php
// https://gist.github.com/magnetikonline/650e30e485c0f91f2f40
class DumpHTTPRequestToFile {
public function execute($targetFile) {
$data = sprintf(
"%s %s %s\n\nHTTP headers:\n",
$_SERVER['REQUEST_METHOD'],
$_SERVER['REQUEST_URI'],
$_SERVER['SERVER_PROTOCOL']
);
foreach ($this->getHeaderList() as $name => $value) {
$data .= $name . ': ' . $value . "\n";
}
$data .= "\nRequest body:\n";
file_put_contents(
$targetFile,
$data . file_get_contents('php://input') . "\n"
);
echo("Done!\n\n");
}
private function getHeaderList() {
$headerList = [];
foreach ($_SERVER as $name => $value) {
if (preg_match('/^HTTP_/',$name)) {
// convert HTTP_HEADER_NAME to Header-Name
$name = strtr(substr($name,5),'_',' ');
$name = ucwords(strtolower($name));
$name = strtr($name,' ','-');
// add to list
$headerList[$name] = $value;
}
}
return $headerList;
}
}
(new DumpHTTPRequestToFile)->execute('./dumprequest.txt');
Can any one help me to add class DumpHTTPRequestToFile to $fullrequest?
Something like
<?php
$message="The following request was made:\n";
foreach($_REQUEST as $k=>$v){
$message.=$k." : ".$v."\n\n";
}
mail($to_address, $subject, $message, $headers);
?>
Replace $_REQUEST with the super global of your choice. Or run similar loops across multiple superglobals ($_SERVER, etc) if $_REQUEST doesn't have all you want in it.

Broken links inside PHP emailer with AngularJS

I have an AngularJS app that sends emails using a PHP document.
The email body includes two links to images that are populated with a JS variables.
Most of the emails arrive good and the links work, but in some of them, the links (both or one of them) will come out broken, looking like this:
https://blabla.com/register/uploads/Frankfurt2018-22-03-2018-16-07-52.!
Or like this:
https://blabla.com/register/uploads/KoelnerListe2%21
Or like this:
https://blabla.com/register/upload!
It's weird cause sometimes is both links, sometimes is only one, and most of the times are correct.
The link variable comes from the Angular app and looks like this:
$scope.sendapplication = function(){
$scope.photoor = "https://blabla.com/register/uploads/"+$scope.photoor;
$scope.photosmall = "https://blabla.com/register/uploads/"+$scope.photo;
$scope.exhibitor = {
'img':$scope.photosmall,
'imgoriginal':$scope.photoor,
};
var $promise=$http.post('emailtest.php',$scope.exhibitor);
$promise.then(function (data) {
...
});
};
And in the php file I do this:
$contentType = explode(';', $_SERVER['CONTENT_TYPE']); // Check all available Content-Type
$rawBody = file_get_contents("php://input"); // Read body
$data = array(); // Initialize default data array
if(in_array('application/json', $contentType)) {
$data = json_decode($rawBody); // Then decode it
$photo = $data->img;
$photooriginal = $data->imgoriginal;
} else {
parse_str($data, $data); // If not JSON, just do same as PHP default method
}
header('Content-Type: application/json; charset=UTF-8');
echo json_encode(array( // Return data
'data' => $data
));
$sabine = 'blabla#gmail.com';
$headerss = "From: ".$galleryname."<".$email.">\r\nReturn-path: ".$email."";
$headerss .= "Reply-To: ".$galleryname."<".$email.">";
$headerss .= "MIME-Version: 1.0\r\n";
$headerss .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$recipient = $sabine;
$subjects = "Registration for ".$fairumlaut." - ".$galleryname."";
$bodys .= "<p><strong>Original photo</strong>: Link</p>";
$bodys .= "<p><strong>Web resized photo</strong>: Link</p>";
$bodys .= "<p></p>";
mail($recipient, $subjects, $bodys, $headerss);
What could cause such weird behaviour?
wrap the link in urlencode function. This will solve your issue.
update: or if I read your code I would have seen that the links are coming from JS. Try encodeURI().. ;)

Put API data into a table using php

I am using the insert PHP plugin for wordpress to get API data into my pages.
so I would replace "" on the last line with "[/insert_php]".
my code
[insert_php]
$url = 'https://www.eobot.com/api.aspx?idspeed=285967&json=true';
$args = array (
'method' => 'GET'
);
$response = wp_remote_request($url, $args);
$body = wp_remote_retrieve_body($response);
print_r($body);
[/insert_php]
returns
MiningSHA-256:0.00000000;MiningScrypt:0.00000000;CloudSHA-256:12.72592330;Cloud2SHA-256:0.01894240;CloudScrypt:0.00000000;
I have searched, and maybe I am not using the correct terms, and cannot find my solution or answer. I feel like it should be a lot easier than it is. I feel I should be able to take the array from the body and give each its own variable then use the variables to build a table with PHP. Where am I going wrong? Should I first store this in a php file on my server then create a table, then use the insert php function to build the table that way?
I have tried your code and its working fine for me in local mechine i think you just need to put json_decode for get proper format.
[insert_php]
$url = 'https://www.eobot.com/api.aspx?idspeed=285967&json=true';
$args = array (
'method' => 'GET'
);
$response = wp_remote_request($url, $args);
$body = wp_remote_retrieve_body($response);
print_r($body);
echo "<pre>";
$data = json_decode($body);
print_r($data);
[/insert_php]
Getting this type of output.
stdClass Object
(
[MiningSHA-256] => 0.00000000
[MiningScrypt] => 0.00000000
[CloudSHA-256] => 12.72656020
[Cloud2SHA-256] => 0.01894240
[CloudScrypt] => 0.00000000
)
Please try above code and let me know.
I've checked the code and it is doing what you programmed it do. Please check you're using correct API URL and once you're using the correct API URL use json_decode function to decode json data returned API and add once you've correct data converted into array, you can create table.
For example:
<?php
$body = wp_remote_retrieve_body($response);
$table_data = json_decode($body);
$html = array();
if(!empty($table_data)){
$html[] = '<table>';
foreach($table_data as $rows){
$html[] = '<tr>';
foreach($row as $column){
$html[] = '<td>'. $column . '</td>';
}
$html[] = '</tr>';
}
$html ='</table>';
}
$html = implode("\n", $html);
echo $html;
?>
PS: This code is only an example, please adjust it your data.

Manually parse raw multipart/form-data data with PHP

I can't seem to find a real answer to this problem so here I go:
How do you parse raw HTTP request data in multipart/form-data format in PHP? I know that raw POST is automatically parsed if formatted correctly, but the data I'm referring to is coming from a PUT request, which is not being parsed automatically by PHP. The data is multipart and looks something like:
------------------------------b2449e94a11c
Content-Disposition: form-data; name="user_id"
3
------------------------------b2449e94a11c
Content-Disposition: form-data; name="post_id"
5
------------------------------b2449e94a11c
Content-Disposition: form-data; name="image"; filename="/tmp/current_file"
Content-Type: application/octet-stream
�����JFIF���������... a bunch of binary data
I'm sending the data with libcurl like so (pseudo code):
curl_setopt_array(
CURLOPT_POSTFIELDS => array(
'user_id' => 3,
'post_id' => 5,
'image' => '#/tmp/current_file'),
CURLOPT_CUSTOMREQUEST => 'PUT'
);
If I drop the CURLOPT_CUSTOMREQUEST bit, the request is handled as a POST on the server and everything is parsed just fine.
Is there a way to manually invoke PHPs HTTP data parser or some other nice way of doing this?
And yes, I have to send the request as PUT :)
Edit - please read first: this answer is still getting regular hits 7 years later. I have never used this code since then and do not know if there is a better way to do it these days. Please view the comments below and know that there are many scenarios where this code will not work. Use at your own risk.
--
Ok, so with Dave and Everts suggestions I decided to parse the raw request data manually. I didn't find any other way to do this after searching around for about a day.
I got some help from this thread. I didn't have any luck tampering with the raw data like they do in the referenced thread, as that will break the files being uploaded. So it's all regex. This wasnt't tested very well, but seems to be working for my work case. Without further ado and in the hope that this may help someone else someday:
function parse_raw_http_request(array &$a_data)
{
// read incoming data
$input = file_get_contents('php://input');
// grab multipart boundary from content type header
preg_match('/boundary=(.*)$/', $_SERVER['CONTENT_TYPE'], $matches);
$boundary = $matches[1];
// split content by boundary and get rid of last -- element
$a_blocks = preg_split("/-+$boundary/", $input);
array_pop($a_blocks);
// loop data blocks
foreach ($a_blocks as $id => $block)
{
if (empty($block))
continue;
// you'll have to var_dump $block to understand this and maybe replace \n or \r with a visibile char
// parse uploaded files
if (strpos($block, 'application/octet-stream') !== FALSE)
{
// match "name", then everything after "stream" (optional) except for prepending newlines
preg_match('/name=\"([^\"]*)\".*stream[\n|\r]+([^\n\r].*)?$/s', $block, $matches);
}
// parse all other fields
else
{
// match "name" and optional value in between newline sequences
preg_match('/name=\"([^\"]*)\"[\n|\r]+([^\n\r].*)?\r$/s', $block, $matches);
}
$a_data[$matches[1]] = $matches[2];
}
}
Usage by reference (in order not to copy around the data too much):
$a_data = array();
parse_raw_http_request($a_data);
var_dump($a_data);
I used Chris's example function and added some needed functionality, such as R Porter's need for array's of $_FILES. Hope it helps some people.
Here is the class & example usage
<?php
include_once('class.stream.php');
$data = array();
new stream($data);
$_PUT = $data['post'];
$_FILES = $data['file'];
/* Handle moving the file(s) */
if (count($_FILES) > 0) {
foreach($_FILES as $key => $value) {
if (!is_uploaded_file($value['tmp_name'])) {
/* Use getimagesize() or fileinfo() to validate file prior to moving here */
rename($value['tmp_name'], '/path/to/uploads/'.$value['name']);
} else {
move_uploaded_file($value['tmp_name'], '/path/to/uploads/'.$value['name']);
}
}
}
I would suspect the best way to go about it is 'doing it yourself', although you might find inspiration in multipart email parsers that use a similar (if not the exact same) format.
Grab the boundary from the Content-Type HTTP header, and use that to explode the various parts of the request. If the request is very large, keep in mind that you might store the entire request in memory, possibly even multiple times.
The related RFC is RFC2388, which fortunately is pretty short.
I'm surprised no one mentioned parse_str or mb_parse_str:
$result = [];
$rawPost = file_get_contents('php://input');
mb_parse_str($rawPost, $result);
var_dump($result);
http://php.net/manual/en/function.mb-parse-str.php
I haven't dealt with http headers much, but found this bit of code that might help
function http_parse_headers( $header )
{
$retVal = array();
$fields = explode("\r\n", preg_replace('/\x0D\x0A[\x09\x20]+/', ' ', $header));
foreach( $fields as $field ) {
if( preg_match('/([^:]+): (.+)/m', $field, $match) ) {
$match[1] = preg_replace('/(?<=^|[\x09\x20\x2D])./e', 'strtoupper("\0")', strtolower(trim($match[1])));
if( isset($retVal[$match[1]]) ) {
$retVal[$match[1]] = array($retVal[$match[1]], $match[2]);
} else {
$retVal[$match[1]] = trim($match[2]);
}
}
}
return $retVal;
}
From http://php.net/manual/en/function.http-parse-headers.php
Here is a universal solution working with arbitrary multipart/form-data content and tested for POST, PUT, and PATCH:
/**
* Parse arbitrary multipart/form-data content
* Note: null result or null values for headers or value means error
* #return array|null [{"headers":array|null,"value":string|null}]
* #param string|null $boundary
* #param string|null $content
*/
function parse_multipart_content(?string $content, ?string $boundary): ?array {
if(empty($content) || empty($boundary)) return null;
$sections = array_map("trim", explode("--$boundary", $content));
$parts = [];
foreach($sections as $section) {
if($section === "" || $section === "--") continue;
$fields = explode("\r\n\r\n", $section);
if(preg_match_all("/([a-z0-9-_]+)\s*:\s*([^\r\n]+)/iu", $fields[0] ?? "", $matches, PREG_SET_ORDER) === 2) {
$headers = [];
foreach($matches as $match) $headers[$match[1]] = $match[2];
} else $headers = null;
$parts[] = ["headers" => $headers, "value" => $fields[1] ?? null];
}
return empty($parts) ? null : $parts;
}
Update
The function was updated to support arrays in form fields. That is fields like level1[level2] will be translated into proper (multidimensional) arrays.
I've just added a small function to my HTTP20 library, that can help with this. It is made to parse form data for PUT, DELETE and PATCH and add it to respective static variable to simulate $_POST global.
For now it's just for text fields, though, no binary support, since I currently do not have a good use case in my project to properly test it and I'd prefer not to share something I can't test extensively. But if I do get to it at some point - I will update this answer.
Here is the code:
public function multiPartFormParse(): void
{
#Get method
$method = $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] ?? $_SERVER['REQUEST_METHOD'] ?? null;
#Get Content-Type
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
#Exit if not one of the supported methods or wrong content-type
if (!in_array($method, ['PUT', 'DELETE', 'PATCH']) || preg_match('/^multipart\/form-data; boundary=.*$/ui', $contentType) !== 1) {
return;
}
#Get boundary value
$boundary = preg_replace('/(^multipart\/form-data; boundary=)(.*$)/ui', '$2', $contentType);
#Get input stream
$formData = file_get_contents('php://input');
#Exit if failed to get the input or if it's not compliant with the RFC2046
if ($formData === false || preg_match('/^\s*--'.$boundary.'.*\s*--'.$boundary.'--\s*$/muis', $formData) !== 1) {
return;
}
#Strip ending boundary
$formData = preg_replace('/(^\s*--'.$boundary.'.*)(\s*--'.$boundary.'--\s*$)/muis', '$1', $formData);
#Split data into array of fields
$formData = preg_split('/\s*--'.$boundary.'\s*Content-Disposition: form-data;\s*/muis', $formData, 0, PREG_SPLIT_NO_EMPTY);
#Convert to associative array
$parsedData = [];
foreach ($formData as $field) {
$name = preg_replace('/(name=")(?<name>[^"]+)("\s*)(?<value>.*$)/mui', '$2', $field);
$value = preg_replace('/(name=")(?<name>[^"]+)("\s*)(?<value>.*$)/mui', '$4', $field);
#Check if we have multiple keys
if (str_contains($name, '[')) {
#Explode keys into array
$keys = explode('[', trim($name));
$name = '';
#Build JSON array string from keys
foreach ($keys as $key) {
$name .= '{"' . rtrim($key, ']') . '":';
}
#Add the value itself (as string, since in this case it will always be a string) and closing brackets
$name .= '"' . trim($value) . '"' . str_repeat('}', count($keys));
#Convert into actual PHP array
$array = json_decode($name, true);
#Check if we actually got an array and did not fail
if (!is_null($array)) {
#"Merge" the array into existing data. Doing recursive replace, so that new fields will be added, and in case of duplicates, only the latest will be used
$parsedData = array_replace_recursive($parsedData, $array);
}
} else {
#Single key - simple processing
$parsedData[trim($name)] = trim($value);
}
}
#Update static variable based on method value
self::${'_'.strtoupper($method)} = $parsedData;
}
Obviously you can safely remove method check and assignment to a static, if you do not those.
Have you looked at fopen("php://input", "r") for parsing the content?
Headers can also be found as $_SERVER['HTTP_*'], names are always uppercased and dashes become underscores, eg $_SERVER['HTTP_ACCEPT_LANGUAGE'].

Categories