The setup is simple. A Joomla eCommerce site (MySQL back-end) that sends data (cURL post) to another database backed application (ASP with MS SQL) after a Joomla account has been created.
The problem is that sometimes this data is stored on the receiving database without any white spaces. For example: an address collected on the Joomla site is stored in the database as "123 example road" but on the receiving database it's being stored as "123exampleroad". This doesn't happen all of the time - so I'm rather baffled at what the cause might be.
Has anyone experienced such an issue? Any help is appreciated.
This is what the cURL code looks like:
//create array of data to be posted
foreach( $registrationfields as $field ) {
if( $field->name == 'email') $field->name = 'user_email';
if( $field->name == 'delimiter_sendregistration') continue;
if( $field->type == 'captcha') continue;
if( $field->type == 'delimiter') continue;
switch($field->name) {
case 'country':
require_once(CLASSPATH.'ps_country.php');
$country = new ps_country();
$dbc = $country->get_country_by_code($dbbt->f($field->name));
if( $dbc !== false ) $val = $dbc->f('country_name');
break;
default:
$val = $dbbt->f($field->name);
break;
}
$post_data[$field->name] = $val;
}
$post_data['order_id'] = $order_id;
$post_data['order_date'] = $order_date;
$post_data['order_status'] = $order_status;
$post_data['username'] = $username;
//traverse array and prepare data for posting (key1=value1)
foreach ( $post_data as $key => $value) {
$post_items[] = $key . '=' . $value;
}
//create the final string to be posted using implode()
$post_string = implode ('&', $post_items);
//create cURL connection
$curl_connection =
curl_init('http://--url-here');
//set options
curl_setopt($curl_connection, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($curl_connection, CURLOPT_USERAGENT,
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
curl_setopt($curl_connection, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_connection, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl_connection, CURLOPT_FOLLOWLOCATION, 1);
//set data to be posted
curl_setopt($curl_connection, CURLOPT_POSTFIELDS, $post_string);
//perform our request
$result = curl_exec($curl_connection);
//show information regarding the request
print_r(curl_getinfo($curl_connection));
echo curl_errno($curl_connection) . '-' .
curl_error($curl_connection);
//close the connection
curl_close($curl_connection);
Try to send your data encoded as one parameter using base64. Don't use native phpfunctions as they may output special characters like slash. Use functions listed in first answer to this post.
I think that problem lays in how curl encodes spaces (%20) and how your destination script reads them.
example (using functions from link):
...
$post_string = implode ('&', $post_items);
$post_string = myBase64_encode($post_string);
...
This issue was fixed after I re-factored the code. Instead of modifying the array using a loop and then an "implode" to form a string - like so:
//traverse array and prepare data for posting (key1=value1)
foreach ( $post_data as $key => $value) {
$post_items[] = $key . '=' . $value;
}
//create the final string to be posted using implode()
$post_string = implode ('&', $post_items);
I used the "http_build_query" function instead, which accomplishes the same thing without causing errors.
$post_string = http_build_query($post_data) . "\n";
Related
I'm using curl in php to communicate between two servers. We have it working properly for POST and multi-dimensional arrays, but it didn't work for files. We got it working for files, but then it didn't work for multi-dimensional arrays. The two ways are using,
$post = $_POST;
//get files and include in data
foreach($_FILES as $name=>$info)
{
if( strlen($info['tmp_name']) )
{
$post[$name] = "#{$info['tmp_name']};filename={$info['name']};type={$info['type']}";
}
}
//$post = http_build_query( $_POST ); //works for multi-dimensional arrays (not files) and not doing this works for files and 1-d data
//use curl to pass information
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post); //string vs array
//test on recieving end
die(print_r($_POST, true) . print_r($_FILES,true));
Is there a way to handle both files and single/multi-dimensional post data?
You could try to put the file in base64, this way it becomes a string instead of binary data.
Ran a couple tests, and saw information on PHP website where someone commented on how it doesn't work for both (php,apache,curl). There solution showed a specific example with hardcoded results to meet their needs, but I expanded the concept to be more generic and handle both single d, multi-d, and file data.
//encode function found online for specific CURL use (on curl side)
function _encode($arrays, &$new = array(), $prefix = null)
{
if ( is_object( $arrays ) )
{
$arrays = get_object_vars( $arrays );
}
foreach ( $arrays as $key => $value ) {
$k = isset( $prefix ) ? $prefix . '[' . $key . ']' : $key;
if ( is_array( $value ) OR is_object( $value ) ) {
$this->_encode( $value, $new, $k );
} else {
$new[$k] = $value;
}
}
}
//use on curl side
$post = $_POST;
//get files and include in data
foreach($_FILES as $name=>$info)
{
if( strlen($info['tmp_name']) )
{
$post[$name] = "#{$info['tmp_name']};filename={$info['name']};type={$info['type']}";
}
}
//encode post generically to cover every use case (files, single d, multi-d, any form setup without hardcoding)
$encoded = array();
_encode( $post, $encoded );
//use curl to pass information
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post); //pass as an array
//test on recieving end
die(print_r($_POST, true) . print_r($_FILES,true)); //everything as expected
I'm having an extrange issue when receiving parameters from a POST cURL request. No matter how I encode it (json, url, rawurl, utf8, base64...) before POSTing it, I am not able to perform any decoding operation through the array elements, via loop. I'm giving you the details.
From the consuming controller, in some other php (Yii) app, I build my request like this:
private function callTheApi($options)
{
$url = "http://api.call.com/url/api";
$params = array( 'api_key' => $this->api_key,
'domain' => $this->domain,
'date' => $options['date'],
'keys' => $options['keys'] // This is an array
);
// Following some good advice from Daniel Vandersluis here:
// http://stackoverflow.com/questions/3772096/posting-multidimensional-array-with-php-and-curl
if (is_array($params['keys'])
{
foreach ($params['keys'] as $id => $name)
{
$params['keys[' . $id . ']'] = $name;
}
unset($params['keys']);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: multipart/form-data; charset=utf-8'));
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_USERAGENT,
"Mozilla/5.0 (Windows; U; Windows NT 5.0; en; rv:1.9.0.4) "
. "Gecko/2009011913 Firefox/3.0.6");
$output = curl_exec($ch);
$error = curl_errno($ch);
$error_text = curl_error($ch);
curl_close($ch);
if (!$output || $error != 0)
die("<br><hr>Problems...<br>"
. "Line:" . __LINE__ . " dataExtractor.php<br>"
. "Error: " . $error . " - " . $error_text . "<hr>"
. $url . "<hr>");
sleep(1);
return json_decode($output, true);
}
And in the api itself, this is the function:
public function api()
{
$params = $_POST;
foreach($params as $k=>$v){
if($k=='domain') $domain = $v;
if($k=='date') $date = $v;
if($k=='api_key') $api_key = $v;
if($k=='keys') $keys = $v;
}
echo json_encode($keys);
// All my logic would be here, after parsing the array correctly.
}
Ok, now for the problems:
If i leave everything like stated before, it works. I have my $keys array in the api, and I can use it however I want. The "echo json_encode($keys)" sentence returns the array ALMOST as it should be. But the problem is some values of the array are corrupted in the cURL operation. Values such as spanish characters á, é ,í, ó, ú OR ü are simply not present in the array_values.
If some key in the $keys array was spanish word "alimentación" in the original array, once it's been cURLed to the api, it becomes "alimentacin". There, the ó is not there anymore.
So, my chances are encoding each value in the array to a safely transferred value, so that I can decode it later. But what do you know, I can't.
I've tried urlencoding, rawurlencoding, json_encoding, base64_encoding... each value of the array. And if I return the received array from the api, it contains the encoded values all right. BUT.
If I loop the array in the api for decoding, and then try to return it, no matter what decoding function I'm applying to its values, the output is ALWAYS "NULL".
I have no clue what I'm doing wrong here. Not even close.
So any help would be much appreciated. Thanks in advance, community.
When you create cUrl params array you should know that keys cannot be utf8.
And when you add some parameters in foreach loop
$params['keys[' . $id . ']'] = $name;
$id can be utf8 character.
To avoid that I recommend you to use json_encode
$params = array(
'api_key' => $this->api_key,
'domain' => $this->domain,
'date' => $options['date'],
'keys' => json_encode($options['keys']) // This is an array
);
In your api in this case you should change nothing.
I have code that works fine for anything before 5.3, and now this code won't work in php 5.3:
foreach($_GET as $key => $value) {
$params .= "&";
$params .= $key."=".$value;
}
$fields = array(
'mode'=>urlencode('native'),
'cookie_file'=>urlencode($data['cookie_file']),
'full_status'=>urlencode('1'),
'remove_cookies'=>urlencode('1'),
'url'=>urlencode("http://www.domainblocked.com/blocked_name.php?" . $params)
);
//url-ify the data for the POST
$fields_string = "";
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
$fields_string = rtrim($fields_string,'&');
//open connection
$ch = curl_init();
$get_url = $proxy."?".$fields_string;
print $get_url;
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL,$get_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//execute post
$html = curl_exec($ch);
The file $proxy refers to a PHP proxy which complains it never gets the $_GET['url'] variable despite the $get_url being:
http://www.domainblocked.com/proxy.php?mode=native&cookie_file=%2Ftmp%2FCURLCOOKIEQ1N7ki&full_status=1&remove_cookies=1&url=http%3A%2F%2Fwww.domainblocked.com%2Fblocked_name.php%3F%26room%3D3043542%3B3332215%3B4875165%3B6917670%3B7055833%3B7454057%3B7747396%3B8321764%3B8331103%3B8362498%3B8406246%3B8406305%3B8406671%3B8406728%3B8406965%3B9213754%3B9895515%3B9898865%3B9904319%3B9904558%3B9908327%3B9910403%3B9910760%3B9916830%3B9918045%3B9919351%3B9919603%26avatar69323038%3D%26avatar1%3D6268520%3B6713654%3B7347874%3B7738193%3B7780315%3B8493140%3B8501371%3B8752968%3B9487253%3B9524370%3B9811618%3B10196605%3B10519485%26avatar69527829%3D%26avatar2%3D223055%3B2690693%3B4228334%3B6251471%3B6270797%3B6713654%3B7122151%3B7198849%3B7644202%3B7868916%3B8501371%3B8698810%3B8739013%3B8739767%3B9142768%26avatar38051172%3D%26avatar3%3D4792397%3B6285528%3B7204362%3B7518963%3B7773830%3B7776340%3B8403813%3B8501371%3B9481162%3B9520771%3B9751483%3B9971760%3B9997875%3B10109398%3B10117824%26avatar227598%3D%26avatar4%3D1962690%3B4223019%3B5707484%3B6127072%3B7162053%3B7172244%3B7988191%3B8239420
therefore $_GET['url'] on the proxy file should be http%3A%2F%2Fwww.domainblocked.com%2Fblocked_name.php%3F%26room%3D3043542%3B3332215%3B4875165%3B6917670%3B7055833%3B7454057%3B7747396%3B8321764%3B8331103%3B8362498%3B8406246%3B8406305%3B8406671%3B8406728%3B8406965%3B9213754%3B9895515%3B9898865%3B9904319%3B9904558%3B9908327%3B9910403%3B9910760%3B9916830%3B9918045%3B9919351%3B9919603%26avatar69323038%3D%26avatar1%3D6268520%3B6713654%3B7347874%3B7738193%3B7780315%3B8493140%3B8501371%3B8752968%3B9487253%3B9524370%3B9811618%3B10196605%3B10519485%26avatar69527829%3D%26avatar2%3D223055%3B2690693%3B4228334%3B6251471%3B6270797%3B6713654%3B7122151%3B7198849%3B7644202%3B7868916%3B8501371%3B8698810%3B8739013%3B8739767%3B9142768%26avatar38051172%3D%26avatar3%3D4792397%3B6285528%3B7204362%3B7518963%3B7773830%3B7776340%3B8403813%3B8501371%3B9481162%3B9520771%3B9751483%3B9971760%3B9997875%3B10109398%3B10117824%26avatar227598%3D%26avatar4%3D1962690%3B4223019%3B5707484%3B6127072%3B7162053%3B7172244%3B7988191%3B8239420
But it never gets it.
If I dont urlencode the $_GET['url'] then it this:
http://www.domainblocked.com/proxy.php?mode=native&cookie_file=%2Ftmp%2FCURLCOOKIEjtmYSU&full_status=1&remove_cookies=1&url=http://www.domainblocked.com/blocked_name.php?&room=3043542;3332215;4875165;6917670;7055833;7454057;7747396;8321764;8331103;8362498;8406246;8406305;8406671;8406728;8406965;9213754;9895515;9898865;9904319;9904558;9908327;9910403;9910760;9916830;9918045;9919351;9919603&avatar69323038=&avatar1=6268520;6713654;7347874;7738193;7780315;8493140;8501371;8752968;9487253;9524370;9811618;10196605;10519485&avatar69527829=&avatar2=223055;2690693;4228334;6251471;6270797;6713654;7122151;7198849;7644202;7868916;8501371;8698810;8739013;8739767;9142768&avatar38051172=&avatar3=4792397;6285528;7204362;7518963;7773830;7776340;8403813;8501371;9481162;9520771;9751483;9971760;9997875;10109398;10117824&avatar227598=&avatar4=1962690;4223019;5707484;6127072;7162053;7172244;7988191;8239420
Which the proxy receieve $_GET['url'] but it's only http://www.domainblocked.com/blocked_name.php?
So I think it has to do with something with the & or urlencode in 5.3
foreach($_GET as $key => $value) {
$params .= "&";
$params .= $key."=".$value;
}
Switch this (and similar code) with http_build_query(). It will handle all the encoding.
I'm trying to convert this PHP cURL function to work with my rails app. The piece of code is from an SMS payment gateway that needs to verify the POST paramters. Since I'm a big PHP noob I have no idea how to handle this problem.
$verify_url = 'http://smsgatewayadress';
$fields = '';
$d = array(
'merchant_ID' => $_POST['merchant_ID'],
'local_ID' => $_POST['local_ID'],
'total' => $_POST['total'],
'ipn_verify' => $_POST['ipn_verify'],
'timeout' => 10,
);
foreach ($d as $k => $v)
{
$fields .= $k . "=" . urlencode($v) . "&";
}
$fields = substr($fields, 0, strlen($fields)-1);
$ch = curl_init($verify_url); //this initiates a HTTP connection to $verify_url, the connection headers will be stored in $ch
curl_setopt($ch, CURLOPT_POST, 1); //sets the delivery method as POST
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields); //The data that is being sent via POST. From what I can see the cURL lib sends them as a string that is built in the foreach loop above
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); //This verifies if the target url sends a redirect header and if it does cURL follows that link
curl_setopt($ch, CURLOPT_HEADER, 0); //This ignores the headers from the answer
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //This specifies that the curl_exec function below must return the result to the accesed URL
$result = curl_exec($ch); //It ransfers the data via POST to the URL, it gets read and returns the result
if ($result == true)
{
//confirmed
$can_download = true;
}
else
{
//failed
$can_download = false;
}
}
if (strpos($_SERVER['REQUEST_URI'], 'ipn.php'))
echo $can_download ? '1' : '0'; //we tell the sms sever that we processed the request
I've googled a cURL lib counterpart in Rails and found a ton of options but none that I could understand and use in the same way this script does.
If anyone could give me a hand with converting this script from php to ruby it would be greatly appreciated.
The most direct approach might be to use the Ruby curb library, which is the most straightforward wrapper for cURL. A lot of the options in Curl::Easy map directly to what you have here. A basis might be:
url = "http://smsgatewayadress/"
Curl::Easy.http_post(url,
Curl::PostField.content('merchant_ID', params[:merchant_ID]),
# ...
)
Is there something simpler than the following.
I am trying to make a GET request to a PHP script and then exit the current script.
I think this is a job for CURL but is there something simpler as I don't want to really worry about enabling the CURL php extension?
In addition, will the below start the PHP script and then just come back and not wait for it to finish?
//set GET variables
$url = 'http://domain.com/get-post.php';
$fields = array(
'lname'=>urlencode($last_name),
'fname'=>urlencode($first_name)
);
//url-ify the data for the GET
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string,'&');
//open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_GET,count($fields));
curl_setopt($ch,CURLOPT_GETFIELDS,$fields_string);
//execute GET
$result = curl_exec($ch);
//close connection
curl_close($ch);
I want to run the other script which contains functions when a condition is met so a simple include won't work as the if condition wraps around the functions, right?
Please note, I am on windows machine and the code I am writing will only be used on a Windows OS.
Thanks all for any help and advice
$url = 'http://domain.com/get-post.php?lname=' . urlencode($last_name) . '&fname=' . urlencode($first_name);
$html = file_get_contents($url);
If you want to use the query string assembly method (from the code you posted):
//set GET variables
$url = 'http://domain.com/get-post.php';
$fields = array(
'lname'=>urlencode($last_name),
'fname'=>urlencode($first_name)
);
//url-ify the data for the GET
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string,'&');
$html = file_get_contents($url . '?' . $fields_string);
See:
http://php.net/manual/en/function.file-get-contents.php