How to POST an XML file using cURL on php? - php

I am using a local server on my computer and i am trying to make 2 php scripts to send an xml file and receive it.
To send the xml file i use this code :
<?php
/*
* XML Sender/Client.
*/
// Get our XML. You can declare it here or even load a file.
$file = 'http://localhost/iPM/books.xml';
if(!$xml_builder = simplexml_load_file($file))
exit('Failed to open '.$file);
// We send XML via CURL using POST with a http header of text/xml.
$ch = curl_init();
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, "http://localhost/iPM/receiver.php");
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_builder);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($ch, CURLOPT_REFERER, 'http://localhost/iPM/receiver.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$ch_result = curl_exec($ch);
curl_close($ch);
// Print CURL result.
echo $ch_result;
?>
To receive the xml file i use this code :
<?php
/*
* XML Server.
*/
// We use php://input to get the raw $_POST results.
$xml_post = file_get_contents('php://input');
// If we receive data, save it.
if ($xml_post) {
$xml_file = 'received_xml_' . date('Y_m_d-H-i-s') . '.xml';
$fh = fopen($xml_file, 'w') or die();
fwrite($fh, $xml_post);
fclose($fh);
// Return, as we don't want to cause a loop by processing the code below.
return;
}
?>
When i run the post script i get this error :
Notice: Array to string conversion in C:\xampp\htdocs\iPM\main.php on line 17
which refers to line :
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_builder);
which i dont know what exactly does. The xml file i receive is created but when i open it i get this :
XML Parsing Error: syntax error
Location: file:///C:/xampp/htdocs/iPM/received_xml_2013_01_14-01-06-09.xml
Line Number 1, Column 1:
I tried to comment this specific line as i thought the problem lies there but then when i run my post script i get this error :
Request entity too large!
The POST method does not allow the data transmitted, or the data volume exceeds the capacity limit.
If you think this is a server error, please contact the webmaster.
Error 413
but the xml file is only 5kbs so this is not the problem.
Does anyone have any idea what i should do here? All i am trying to do is make a script to send an xml file and a script to receive it and save it as an xml.

curl_setopt($ch, CURLOPT_POSTFIELDS, $foo) sets your request's body, the data to be posted. It expects $foo to be a set of key-value pairs provided either as an array:
$foo = array(
'foo' => 'some value',
'bar' => 2
);
or as a percent-encoded string:
$foo = 'foo=some%20value&bar=2'
Instead, you're providing $xml_builder variable which is a SimpleXMLElement object returned by simplexml_load_file($file).
Try this:
$postfields = array(
'xml' => $your_xml_as_string; // get it with file_get_contents() for example
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
Then on the receiving end:
$received_xml = $_POST['xml'];

Related

sending xml string using php curl but not as post parameter

:)
I'm trying to send an XML using curl but not as post parameter. what I mean is this.
for example.
the receiving side of that XML won't be able to recieve the XML using $_POST variable.
he will need to use the following code:
$xmlStr=null;
$file=fopen('php://input','r');
$xmlStr=fgets($file);
I want to be able to send an xml string using curl via https.
so the following would be wrong:
public static function HttpsNoVerify($url,$postFields=null,$verbose=false) {
// Initialize session and set URL.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
// Set so curl_exec returns the result instead of outputting it.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
if ($postFields !=null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
}
if ($verbose) {
curl_setopt($ch, CURLOPT_VERBOSE, 1);
}
// Get the response and close the channel.
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
because here i can use HttpsNoVerify($url,array('xml_file'=>'xml..')); and that
will paste it as post parameter. and i want it as post output.
so please I hope i explained myself properly and I explained exactly what I don't want to do.
how can I do what i want to do?
thanks! :)
kfir
Just directly pass the xml string as second parameter instead of an associative array item,
HttpsNoVerify($url, 'xml ..');
This will eventually call
curl_setopt($ch, CURLOPT_POSTFIELDS, "xml ...");
Which will be put in php://input for the remote server.

PHP , read XML file sent via cURL

I have this code where I send data in an XML file via cURL to a press office. Now I want a feedback from the press that my orders are confirmed or done. I would like to have that in an XML file as well. I know how I send file via curl, now I would like to know how do i receive them so i can read out the data. Any suggestions are welcome.
this is how i send my XML:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $incomm_prod_server);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 4);
curl_setopt($ch, CURLOPT_POSTFIELDS, str_replace('{voucher_code}', $voucher_code, $xml_data));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: close'));
So this is what i do on the ither side to get the XML:
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
$result_xml = simplexml_load_string(curl_exec($ch));
But i get bool(false) as result back, so there is no xml sent?
EDIT: I can access the data like this:
if ( $_SERVER['REQUEST_METHOD'] === 'POST' ){
$postText = file_get_contents('php://input');
}
die(var_dump($postText));
I edit one last time, maybe it will help others, i access now my xml this way:
if ( $_SERVER['REQUEST_METHOD'] === 'POST' ){
$postText = file_get_contents('php://input');
}
$xml = new SimpleXMLElement($postText);
$packing_number = $xml->xpath('/feedback/packing_number');
$packing_status = $xml->xpath('/feedback/packing_status');
this will give you an array back, you can access it like:
$packing_number[0]
or just loop trough it.
Ok so the code you posted above doesn't really send the XML file. All it does is place the content of that XML file into a $_POST variable attached to the request.
To receive data (on the other side), all you have to do is take a look into the $_POST variable and your XML data should be there. You'd setup a script and data would be posted to it (possibly using the same method you are using above), and the content will be accessible to you.

Getting xml file through command-line php script

How do I get the content of an xml file through a command line php script? If I access this link through the IE browser, I am able to get the XML file: http://alerts.weather.gov/cap/ma.php?x=0. If I try to get the file through command line with c:\path\php.exe get_advisory_upd.php, the script shows an error host did not respond in allowed time. This seems to be a security issue. I must have a scheduled task to get that xml at specified intervals. How do I do that? file_get_contents() returned that same error, simplexml_load_file() might not have shown any errors, but did not get the xml file.
PHP Script get_advisory_upd.php:
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
$file = 'atom-advisory-MAZ015_UPD.txt';
$newfile = 'atom-advisory-MAZ015.txt.bak';
if (!copy($file, $newfile)) {
echo "Failed to copy $file...\n";
}
/* $contents = file_get_contents('http://alerts.weather.gov/cap/ma.php?x=0'); */
// Use cURL to get the RSS feed into a PHP string variable.
$ref_url = "http://192.x.x.x/weather/get_advisory_upd.php";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://alerts.weather.gov/cap/ma.php?x=0');
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_REFERER, $ref_url);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1000);
$contents = curl_exec($ch);
echo 'Curl error: '. curl_error($ch);
curl_close($ch);
/* $contents = simplexml_load_file('http://alerts.weather.gov/cap/ma.php?x=0');
echo "contents \n".$contents; */
file_put_contents($file, $contents);
?>
UPDATE
I am running this script from an intranet. As y_a_v_a suggested I specified the CURLOPT_REFERER option to tell the remote host my url. I do that with
$ref_url = "http://192.x.x.x/weather/get_advisory_upd.php";
curl_setopt($ch, CURLOPT_REFERER, $ref_url);
Is there a different way to specify the URL?
Set a sane CURLOPT_REFERER and set CURLOPT_CONNECTTIMEOUT to zero and run your script. Verify what happens by adding
$curl_error = curl_error($ch);
and dump $curl_error after you closed the curl action.

Having trouble making a local copy of an xml feed using php

I'm trying to save a local copy of an xml file, and then open it with simple xml, but i'm getting some errors.. here's my code:
$feedURL = "https://gdata.youtube.com/feeds/api/users/manitobachildhealth/favorites";
//$xml = file_get_contents("$feedURL");
$xml = file_get_contents($feedURL);
file_put_contents("video.xml", $xml);
// read feed into SimpleXML object
//$sxml = simplexml_load_file($feedURL);
$sxml = simplexml_load_file('video.xml');
The error i'm getting is as follows:
Warning: file_get_contents(https://gdata.youtube.com/feeds/api/users/manitobachildhealth/favorites) [function.file-get-contents]: failed to open stream: Result too large in D:\wamp\www\videos2.php on line 48
I'm not sure why it would be too large of a result, it only returns 6kb of xml. what am i doing wrong?
Update:
This is running on a windows platform using WAMP server - not ideal, but i'm stuck with it.
Update 2:
I've tried using curl and fwrite to achieve a similar result, as suggested below, but it won't write the xml file to the local server. It doesn't give me any errors though.
update 3:
This is obviously a very specific problem with the hosting environment, but I'm not sure where to start looking for the problem. Using curl works great on a linux-based dev server, but is causing problems on this windows-based production server. An extra help in troubleshooting this issue would be most appreciated!
Correct answer for the question:
It is possible you are having the same problem as of this question: CURL and HTTPS, "Cannot resolve host" (DNS-Issue)
Other Details:
You can use SimpleXML to load and save the xml data
$xml = new SimpleXMLElement('https://gdata.youtube.com/feeds/api/users/manitobachildhealth/favorites', NULL, TRUE);
$xml->asXML('video.xml');
I have tested the code above in a WAMP server and it works fine.
Update:
If the above returns error message "[simplexmlelement.--construct]: I/O warning : failed to load external entity ...." It's possible that your server does not allow to include external data or the php file/script does not have the right permission.
Try the following:
1. echo the content of the xml file.
$xml = new SimpleXMLElement('https://gdata.youtube.com/feeds/api/users/manitobachildhealth/favorites', NULL, TRUE);
echo htmlentities($xml->asXML());
If you managed to retrieved the xml content and print it to the browser, then your server is allowing to include external content and most likely the problem with the file permission. Make sure file/script have the right to create xml file.
If the above still does not work try using cURL.
function getPageContent($options)
{
$default = array(
'agent' => $_SERVER['HTTP_USER_AGENT'],
'url' => '',
'referer' => 'http://'.$_SERVER['HTTP_HOST'],
'header' => 0,
'timeout' => 5,
'user' => '',
'proxy' => '',
);
$options = array_merge($default, $options);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $options['url']);
curl_setopt($ch, CURLOPT_HEADER, $options['header']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if ($options['proxy'] != '') {
curl_setopt($ch, CURLOPT_PROXY, $options['proxy']);
}
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $options['timeout']);
curl_setopt($ch, CURLOPT_REFERER, $options['referer']);
curl_setopt($ch, CURLOPT_USERAGENT, $options['agent']);
if ($options['user'] != '') {
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $options['user']);
}
$result = array();
$result['content'] = curl_exec($ch);
$result['info'] = curl_getinfo($ch);
$result['error'] = curl_error($ch);
curl_close($ch);
return $result;
}
$result = getPageContent(array(
'proxy' => '[ip or address]:[port]', // if needed
'user' => '[username]:[password]', // if needed
'url' => 'http://gdata.youtube.com/feeds/api/users/manitobachildhealth/favorites'
));
if (empty($result['error'])) {
// ok
// content of xml file
echo htmlentities($result['content']);
// file
$filename = 'video.xml';
// Open File
if (!$fp = fopen($filename, 'wt')) {
die("Unable to open '$filename'\n\n");
}
// write content to file
fwrite($fp, $result['content']);
// close file
fclose($fp);
} else {
// failed
echo '<pre>';
echo 'Error details;';
print_r ($result['error']);
echo '<hr />Other info:';
print_r ($result['info']);
echo '</pre>';
}
Have you tried using curl and fwrite to get the contents and write them to a local file?
$ch = curl_init("https://gdata.youtube.com/feeds/api/users/manitobachildhealth/favorites");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
fwrite("video.xml",$output);

PUT string of data to XML server using PHP

I need to put a string of data like so: '< client>...<\client>' onto an XMl server (example url:'http://example.appspot.com/examples') using PHP.
(Context: Adding a new client's details to the server).
I have tried using CURLOPT_PUT, with a file and with just a string (since it requires CURLOPT_INFILESIZE and CURLOPT_INFILE) but it does not work!
Are there any other PHP functions that could be used to do such a thing? I have been looking around but PUT requests information is sparse.
Thanks.
// Start curl
$ch = curl_init();
// URL for curl
$url = "http://example.appspot.com/examples";
// Put string into a temporary file
$putString = '<client>the RAW data string I want to send</client>';
/** use a max of 256KB of RAM before going to disk */
$putData = fopen('php://temp/maxmemory:256000', 'w');
if (!$putData) {
die('could not open temp memory data');
}
fwrite($putData, $putString);
fseek($putData, 0);
// Headers
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Binary transfer i.e. --data-BINARY
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $url);
// Using a PUT method i.e. -XPUT
curl_setopt($ch, CURLOPT_PUT, true);
// Instead of POST fields use these settings
curl_setopt($ch, CURLOPT_INFILE, $putData);
curl_setopt($ch, CURLOPT_INFILESIZE, strlen($putString));
$output = curl_exec($ch);
echo $output;
// Close the file
fclose($putData);
// Stop curl
curl_close($ch);
since I haven't worked with cURL so far I can't really answer to that topic. If you'd like to use cURL I'd suggest looking at the server log and see what actually didn't work (so: Was the output of the request really what it's supposed to be?)
If you don't mind switching over to another technology/library I'd suggest you to use the Zend HTTP Client which is really straight forward to use, simple to include and should satisfy all your needs. Especially as performing a PUT Request is as simple as that:
<?php
// of course, perform require('Zend/...') and
// $client = new Zend_HTTP_Client() stuff before
// ...
[...]
$xml = '<yourxmlstuffhere>.....</...>';
$client->setRawData($xml)->setEncType('text/xml')->request('PUT');
?>
Code sample is from: Zend Framework Docs # RAW-Data Requests
Another way to add string body to the PUT request with CURL in PHP is:
<?php
$data = 'My string';
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); // Define method type
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // Set data to the body request
?>
I hope this helps!

Categories