Any alternative to curl_exec()? - php

I am trying to make a sort of license checking script, but as not all hosts allow curl_exec, I would like to know, if there is any alternative way of making a call-back?
This is how I do it with curl:
curl_setopt($ch, CURLOPT_URL, $url."/my_script.php");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $info);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_exec($ch);

You can simply use file_get_contents() with URLs:
file_get_contents('http://www.google.com');
This may be disabled, though, with just a simple INI option allow_url_fopen.
Alternatively, you may use fsockopen(), which should be available on most systems.
With fsockopen() you can open a socket to a HTTP server, then communicate using standard fwrite() and fread(). The downside is that you must write HTTP request headers by yourself, and you must also parse HTTP response headers too. If you look at fsockopen() on PHP's manual, you can see plenty of examples: http://fr2.php.net/fsockopen
My suggestion is to use cURL as primary option, file_get_contents() as secondary (if ini_get('allow_url_fopen') returns a positive result) and implement solutions likefsockopen() as fallback.

You could switch curl_multi_exec, but that's probably disabled as well.
Alternatively, use the HTTP stream wrapper. To configure a POST request, you'll need to set up your own HTTP context.

Related

How to add the custom headers to https requesting curl PHP script?

In curl PHP script, we add the headers by the curl_setopt CURLOPT_HTTPHEADER option. It works fine with HTTP request like search.yahoo.com but I tried it with the HTTPS request it doesn't work.
I have disable SSL peer verification by setting CURLOPT_SSL_VERIFYPEER option to false. Is there way to implement it?
here is a quick solution
add curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); before curl_exec()
here $ch curl_init() object;
Do refer here for alternative solution
first of all you need to download the CA certificate with your browser and save it as X.509. This will make you able to accept all certificates issued by the CA. Then use the following CURL options:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_CAINFO, "path_to_CA_certificate.crt");
CURLOPT_VERIFYHOST has different options, you can try 0 first in order to aviod CN check, and if it works then try with 2.
Hope it helps.

php curl vs cli curl, posting xml

UPDATED THANKS TO ANSWERS:
Can someone point out the difference between:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_root);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, "xml"); // tried http_build_query also
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Added this, still no good
return curl_exec($ch); // returns false
and:
$curl = "curl -X POST -d 'xml' {$api_root}";
return `$curl`; // returns expected xml from server
AND/OR
More generally, are there any good breakdowns out there for conversion/reference between php's libcurl default values/headers and those of curl on the command line?
I know this is almost a dupe of curl CLI to curl PHP and CLI CURL -> PHP CURL but I'm hoping for something more definitive.
When you use backticks then PHP invokes a shell. This can be dangerous, especially when you include variables in the command. If someone has a way to influence the value of $api_root they would be able to invoke any command on your system.
Using the API is much safer and probably faster as well as the curl libraries are loaded into PHP.
As for why it's not working it seems others have answered that question :)
curl_exec returns true or false by default. You need to specify CURLOPT_RETURNTRANSFER:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
Since curl_exec is returning false (not NULL as indicated in the original question), try using curl_error() to determine why it's returning false.
TFM (read it): curl_exec(), curl_setopt()
Edit for posterity's sake:
The OP discovered that an SSL issue was the hindrance. The both libcurl (as called through PHP) and the curl command-line do SSL peer verification for every transaction, unless the user explicitly disables it.
The likely scenario is that the shell environment is using a different CA bundle than PHP's libcurl implementation. To remedy this, set CURLOPT_CAINFO to be the same as the shell's CURL_CA_BUNDLE environment variable and then peer verification should work.
#OP: I'd be curious to know if the above suggestion is confirmed working in your case, or if there is something else different with the SSL configuration.
in your php example you are missing
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
from php manual:
curl_exec
Returns TRUE on success or FALSE on failure. However, if the CURLOPT_RETURNTRANSFER option is set, it will return the result on success, FALSE on failure.
Add this line:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
To match the CLI version:
$curl = "curl -X POST -d 'xml' {$api_root}";
return `$curl`; // returns expected xml from server
I also needed:
// Thanks to all the answers
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// This appears to default false on CLI, true in libcurl
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

PHP curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false) too slow

I use this method to get facebook api data. just a search query. but I find use curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); cost more time during a curl time (over 10+ seconds).
Is there other curl method can run faster?
NOTE: I am now testing in localhost
$url = "https://graph.facebook.com/search?access_token=".$token."&q=dallas&type=post&scope=publish_stream,offline_access,user_status,read_stream";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 2);
//curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__). '/file.crt'); the way as Lumbendil recommend, download a crt file via firefox. still slowly.
$body= curl_exec($ch);
curl_close ($ch);
PS:I do not want to use a SDK, becuase I failed set SDK in localhost test. Although I have read many articles of how to set in localhost. I have set http://127.0.0.1/facebook as my callback url. But just failed. So I still want to get an easy curl way.
Thanks.
You could use a .crt file and verify against that instead of ignoring SSL verification, as explained here.
To keep all the information in one place: In your code, you should write the following:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_CAINFO, '/path/to/crt/file.crt');
To obtain the certificate, you should go with the browser to the page, and then with "view certificate" you have to export it. Remember that you must export it as X.509 Certificate (PEM) for this to work. For a more detailed guide on how to export the certificate, visit the link provided.
If ignoring to check a certificate takes 10 seconds, the problem is not with the certificate or with the checking and quite frankly, it probably isn't with SSL at all.
Ignoring to check the certificate should be very fast and not be measurable compared to how long the rest of the SSL handshake procedure takes.
To properly track down the problem, I would recommend you use the curl command line tool and its --trace-ascii and --trace-time options to see what seems to take time. You may need to snoop on the network with wireshark or similar to get an even better picture of what's going on.
I can't see how the other suggestions of adding a certificate check to the mix will make anything faster.
Just a side note, but if you do wish to use the SDK you can work around the local issue by editing your hosts file and adding localhost.local for 127.0.0.1. /etc/hosts on a linux machine and C:\WINDOWS\system32\drivers\etc\hosts on a windows machine.
Then in the Facebook app settings, simply set localhost.local as your domain and set your site url accordingly.
You should be ready to go then.

How to perform cert-based auth with a PHP HTTP client

I need to access a RESTful webservice from PHP (only GET for now). The service can only be accessed over HTTPS with a valid client certificate.
I found plenty of basic auth examples for PHP, but not a single one for client-side cert-based HTTP auth. Is there a PHP HTTP client which can also send certificates to the server?
For now I am using an external application (wget), but this is rather slow and hacky.
Certificate-based authentication is not part of HTTP but part of SSL/TLS.
You can use cURL to do such authentication:
$ch = curl_init('https://example.com/');
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, '1');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, '1');
curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cert/ca.crt');
curl_setopt($ch, CURLOPT_SSLCERT, '/path/to/cert/client-cert.pem');
$response = curl_exec();
curl_close($ch);
See the manual page of curl_setopt for more information on the options.

Accessing files on external server

Is there any way to access files of Third party server using PHP?
Yes. You just fopen them if url_fopen is enabled, or use CURL.
The easiest way - assuming url_fopen_wrappers are enabled - is simply using file_get_contents() with a remote (http://, ftp://) URL.
If you don't want to rely on them being enabled, use CURL - while it requires a PHP extension it's pretty common so chances are high it's enabled even on shared hosting.
Here are examples for both methods:
// using url_fopen_wrappers
$contents = file_get_contents('http://stackoverflow.com');
// using CURL
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://stackoverflow.com');
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$contents = curl_exec($curl);
curl_close($curl);
you could even use copy('thirdPartyFileUrl', 'fileO')

Categories