I am developing a WordPress plugin for a client to interact with Rightmove's Realtime Data API. I have been sent example PHP code from Rightmove to use. In order to interact with Rightmove's API, you need to have been generated and given a security certificate from Rightmove. I have been sent that and have the password for it. Before executing the curl, the code uses the stat() function on the certificate. Below is the code (with the password crossed out for obvious reasons).
$url = 'https://adfapi.adftest.rightmove.com/';
$ch = curl_init();
$cert = plugins_url("safetech-righmove-realtime-data-feed-realhomes/safetech.pem");
if (!stat($cert)){
die('No cert');
}
curl_setopt_array($ch, array(
CURLOPT_URL => $url,
CURLOPT_VERBOSE => 1,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSLVERSION => 5,
CURLOPT_SSLCERT => $cert,
CURLOPT_SSLCERTPASSWD => 'xxxxxxxx'
));
if(!curl_exec($ch)) {
echo 'Curl error: ' . curl_error($ch);
}
curl_close($ch);
As you can if the stat fails, it stops the code and prints "No cert". This exactly what is happening. I have uploaded the certificate into the plugins folder and can access it by manually going to the URL in the browser. So the file clearly exists.
If I comment out the if statement and just execute the curl, Rightmove returns an authentication error, implying the certificate is not being used? I have tried using the file_exists() function but that still returns the "No cert" error.
The .pem file has read permissions.
Any idea what is causing the issue? I've been trying various things for hours with no result.
Related
I'm trying to simply read the Philips Hue lights information from my home with the following code:
$fp = fopen(dirname(__FILE__).'/errorlog.txt', 'a');
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'http://119.119.20.20:2827/api/Js82jH2lao-pAiws89S9A-k9hHsukw72/lights',
CURLOPT_VERBOSE => true,
CURLOPT_STDERR => $fp
));
$resp = curl_exec($ch);
curl_close($ch);
print_r($resp);
It returns nothing. Looking at errorlog.txt it says:
* About to connect() to 119.119.20.20 port 2827 (#0)
* Trying 119.119.20.20... * Connection refused
* couldn't connect to host
* Closing connection #0
I'm able to read the data and change light settings through a site like hurl.it which tells me I've setup my router correctly. allow_url_fopen on my server is on. I'm using curl because I want to do a PUT request as well. I don't want to use a library for simply turning on and off an light.
How can I make this work?
Edit to clarify: I'm using an external server to host the php, which communicates to my Philips Hue bridge at home. You can assume I forwarded my port correctly. No VPN.
My guess is it's a users/permissions issue.
Does www-data/http user have permission to use curl on your server? All php scripts will be executed as that user so without correct permissions curl will fail giving this error.
Which user created the php script? Have you changed file permissions to allow other users correct privileges?
Having said all that, you stated that you don't want to use a library for something so simple, why even bother with curl? file_get_contents can PUT, POST etc out of the box.
Get status from bridge as associative array:
$result = json_decode(file_get_contents('http://119.119.20.20:2827/api/Js82jH2lao-pAiws89S9A-k9hHsukw72/lights'), true);
Turn off all lights with a PUT request:
$data = '{"on":false}';
$result = file_get_contents('http://119.119.20.20:2827/api/Js82jH2lao-pAiws89S9A-k9hHsukw72/groups/0/action', null, stream_context_create(array(
'http' => array(
'method' => 'PUT',
'header' => 'Content-Type: application/json' . "\r\n"
. 'Content-Length: ' . strlen($data) . "\r\n",
'content' => $data
),
)));
Just tried it on my Hue setup. Works for me.
So, I am creating a script that will automatically logging in the user to a remote site. it's work as expected, but when user browse any pages in the remote site, it's keep asking user to login again.
how to prevent this? is this possible to do so? here is the current code:
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL=>$url,
CURLOPT_HEADER=>false,
CURLOPT_RETURNTRANSFER=>true,
CURLOPT_FOLLOWLOCATION=>true,
CURLOPT_POST=>true,
CURLOPT_POSTFIELDS=>$login,
CURLOPT_COOKIEFILE=>$rootPath.'/tmpfile/cookie.txt',
CURLOPT_COOKIEJAR=>$rootPath.'/tmpfile/cookie.txt'
));
$content = curl_exec($ch);
Your code seems workable. But most of the cases the common mistake is not closing the curl handle before making second one. So close it, and reinitialize it again.
curl_close($ch);
If this still doesn't solve your problem, then you can debug your code for following things.
1) Check what you have inside the cookie.txt file. You can print the content of the file just after the login request.
2) Run the script with verbose mode enabled to see what requests are sending for user browsing pages.
CURLOPT_VERBOSE => true,
3) You can also manually copy the cookie from the file (or from browser) and use it for the 'user browse' request and check whether the cookie works or not.
CURLOPT_HTTPHEADER => array("Cookie: session-x=hello-kookie"), // example
I'm using Google reCaptcha for my webpage.
In testing mode everything works fine. No SSL.
When I test my webpage in production environment the following errors occures:
Warning: file_get_contents(): SSL operation failed with code
1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in
/vendor/google/recaptcha/src/ReCaptcha/RequestMethod/Post.php
on line 68 Warning: file_get_contents():
Failed to enable crypto in
/vendor/google/recaptcha/src/ReCaptcha/RequestMethod/Post.php
on line 68 Warning:
file_get_contents(https://www.google.com/recaptcha/api/siteverify):
failed to open stream: operation failed in
/vendor/google/recaptcha/src/ReCaptcha/RequestMethod/Post.php
on line 68 ["invalid-json"]
I'm calling the reCaptcha API like this:
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
async defer></script>
as described on the developer page from google.
I'm hosting my webpage at hoststar.ch. There is TSL 1.2 running.
I hope somebody could help me.
In response to your last comment I realise you cannot change Google's reCaptcha api - what I meant was simply to do a file_get_contents actually on example.com ( it does exist ) as a test to see if you can retrieve any content using that method as some webhosts disable the associated functionality.
However, with respect to the Google reCatcha API you might need to specify additional parameters to the file_get_contents function call, notably setting the context options specifically for SSL.
$secret = 'Your google secret';
$captcha = trim( $_POST['g-recaptcha-response'] );
$ip = $_SERVER['REMOTE_ADDR'];
$url = "https://www.google.com/recaptcha/api/siteverify?secret={$secret}&response={$captcha}&remoteip={$ip}";
$options=array(
'ssl'=>array(
'cafile' => '/path/to/cacert.pem',
'verify_peer' => true,
'verify_peer_name' => true,
),
);
$context = stream_context_create( $options );
$res=json_decode( file_get_contents( $url, FILE_TEXT, $context ) );
if( $res->success ){/* all good */}
else{ /* captcha failed */ }
If you don't already have a copy of cacert.pem or ca-bundle.crt you can download them from their respective links. The path to the cafile can use either - save a copy to your host and correct the path to suit your environment.
Change file_get_contents to curl. Here is the code,
Change-
$verify=file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret={$secret}&response={$response}");
$captcha_success=json_decode($verify); /*store json response*/
To this code :
$ch = curl_init("https://www.google.com/recaptcha/api/siteverify?secret={$secret}&response={$response}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$verify = curl_exec($ch);
$captcha_success=json_decode($verify); /*store json response*/
Please note $secret is the secret key stored on server side and $response is the recaptcha response send through post from front end.
I am attempting to use #abraham's TwitterOAuth 0.5.3 library for PHP, but when I make a request to request a token for the 3-legged authorization, I receive an HTTP 500 as a response.
Here is how I have the code set up in PHP:
<?php
/* Start session and load library. */
session_start();
require_once('config.php');
require_once('twitteroauth/autoload.php');
use Abraham\TwitterOAuth\TwitterOAuth;
/* Build TwitterOAuth object with client credentials. */
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);
/* Get temporary credentials. */
// Error occurs on the following line, unable to dump $request_token
$request_token = $connection->oauth('oauth/request_token', array('oauth_callback' => OAUTH_CALLBACK));
//print_r($request_token); // <-- Never reached!!
I know that this problem is not within the Twitter API, as I have verified that I can access my Twitter account via the Dev console.
In addition, I have verified to some degree that the TwiterOAuth library is working, by following the Authorization flow example provided with the library. The example can also access my Twitter account.
I just can't figure out what is going on as I am unable to properly authorize my PHP application to have access to my Twitter account.
What am I doing wrong?
It turns out that a response was never obtained. As a result, attempting to process a response, when there was none resulted in errors on the server side.
One of the PHP functions that Twitter OAuth relies upon is curl. I had tested to see if curl_init existed:
print function_exists('curl_init') ? 'curl_init is enabled' : 'curl_init is disabled';
and I erroneously assumed that curl_exec was also enabled. (Why would you leave curl_init enabled, but only disable curl_exec?)
That assumption was incorrect as my web hosting provider has disabled curl_exec "due to security concerns" and I was unaware of this. In addition, my call to use the Twitter API has worked in the past, so this was new behavior.
It took me a while to come back to testing curl_exec. I verified that I was receiving a valid TwitterOauth object and eventually wound my way into the TwitterOauth class and into the request function.
I was receiving no curl error, but was the response from curl_exec was null (not TRUE or FALSE as expected). I thought that this was unusual and at first thought that curl was missing a configuration option.
However, it was not.
So, if you run into problems with this library (which has worked great for me in the past), it may be that your hosting provider disabled curl_exec.
You can test this scenario via the following PHP code:
print function_exists('curl_exec') ? 'curl_exec is enabled' : 'curl_exec is disabled';
My problem was fixed in another way. After checking (as per jhenderson2099 answer) that my hosting had curl_exec enabled (which it did). I found out that my problem was caused by two lines in src/TwitterOauth.php (TwitterOauth class):
$bundlePath = CaBundle::getSystemCaRootBundlePath(); <-- Comment this line
$options = [
// CURLOPT_VERBOSE => true,
CURLOPT_CONNECTTIMEOUT => $this->connectionTimeout,
CURLOPT_HEADER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_USERAGENT => $this->userAgent,
$this->curlCaOpt($bundlePath) => $bundlePath,<-- Comment this line
];
so that your code will look like this:
//$bundlePath = CaBundle::getSystemCaRootBundlePath();
$options = [
// CURLOPT_VERBOSE => true,
CURLOPT_CONNECTTIMEOUT => $this->connectionTimeout,
CURLOPT_HEADER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_USERAGENT => $this->userAgent,
//$this->curlCaOpt($bundlePath) => $bundlePath,
];
I am trying to perform a Bing Search by using the Windows Azure Marketplace API, I have downloaded their guide and sample code. The code prepares a HTTPS request with basic authentication, however I am constantly getting the following error:
Warning: file_get_contents(https://api.datamarket.azure.com/Data.ashx/Bing/SearchWeb/Web?Query=%27washburn%27&Adult=%27Off%27&$top=50&$format=Atom): failed to open stream: Connection refused
The php code (from Microsoft's document):
$context = stream_context_create(array(
'http' => array(
'proxy' => 'tcp://127.0.0.1:8888',
'request_fulluri' => true,
'header' => "Authorization: Basic " . base64_encode($accountKey.":".$accountKey)
)
));
Does anyone know what is causing the error please? I have correctly set the $accountKey and I tested it in a browser. What puzzles me a little is 127.0.0.1:8888 and also base64_encode($accountKey.":".$accountKey) , how come you need the $accountKey both before and after the : while when using a browser you are supposed to leave the username blank and just input the account key into the password field?
I have solved it and here is what I have found for future people that would be doing the same thing:
I commented out the line where it says:
'proxy' => 'tcp://127.0.0.1:8888',
'request_fulluri' => true,
and also set base64_encode("ignored:".$accountKey) instead
Base on what I read on MSDN, the username part is said to be ignored, so it shouldn't matter what value it is. I was thinking perhaps the length or the special characters in the key screwed things up so I replaces it with ignored (or anything really).
That did the trick and I can parse the returned JSON data. Good luck!