How to post file to local file by curl - php

public function curl($source = null, $type = 'get', $fields = array())
{
$result = '';
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $source);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
if (strtolower($type) === 'post') {
curl_setopt($ch, CURLOPT_POST, true);
if (count($fields) !== 0) {
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields));
}
}
$result = curl_exec($ch);
if ($result === false) {
$result = curl_error($ch);
}
curl_close($ch);
return $result;
}
This is my curl function, I would like to do PHPUnit test to check some other upload file function, therefore I need to simulate form post method with file in PHPUnit, the problem is, curl need to give domain name, of course I can get domain by $_SERVER method, but in command line it won't work, how will you do unitest to test a file upload behavior.

Related

Handle TLSv1.2 connection with CURL

I am trying to automate the configuration of x IP cameras from their embbeded web server (Self Signed Certificates). So if you try to connect to a camera through a browser in a normal way (no script), you'll have to add an exception, works fine.
I want to automate this, and all my scripts PHP are ran in a Powershell CLI.
I have the following PHP script :
<?php
include('C:\wamp64\bin\php\php7.0.10\run\Librairie\LIB_parse.php');
include('C:\wamp64\bin\php\php7.0.10\run\Librairie\LIB_http.php');
include('C:\wamp64\bin\php\php7.0.10\run\Librairie\LIB_resolve_addresses.php');
$TableauIP = fopen('C:\wamp64\bin\php\php7.0.10\run\x\Ipcamera.txt', 'r');
$count = 0;
while (($URLcamera = fgets($TableauIP, 4096)) !== false){
$IP_unparsed = $URLcamera;
$Ipcamera = return_between($IP_unparsed, "//", "/", EXCL);
echo("Automatic configuration for : ".$Ipcamera."\n");
echo("...............\n\n");
echo("Downloading page : ".$IP_unparsed."\n\n");
$web_page =http_get($IP_unparsed, $ref = "");
echo "ERROR \n";
var_dump($web_page['ERROR']);
$head_section = return_between($string=$web_page['FILE'], $start="<head>", $end="</head>", $type=EXCL);
$meta_tag_array = parse_array($head_section, $beg_tag="<meta", $close_tag=">");
for($xx=0; $xx<count($meta_tag_array); $xx++){
echo $meta_tag_array[$xx]."\n";
}
for($xx=0; $xx<count($meta_tag_array); $xx++){
$meta_attribute = get_attribute($meta_tag_array[$xx], $attribute="http-equiv");
if(strtolower($meta_attribute)=="refresh"){
$new_page = return_between($meta_tag_array[$xx], $start="URL", $end=">", $type=EXCL);
$new_page = trim(str_replace("", "", $new_page));
$new_page = str_replace("=", "", $new_page);
$new_page = str_replace("\"", "", $new_page);
$new_page = resolve_address($new_page, $IP_unparsed);
}
break;
}
echo "HTML Head redirection detected<br>\n\n";
echo "Redirect page = ".$new_page."\n";
$web_page2 = http_get($new_page, $ref = "");
//$web_page = http_get($IP_unparsed.'/login.cs', $ref = "");
echo "FILE CONTENT \n";
var_dump($web_page2['FILE']);
echo "FILE ERROR \n";
var_dump($web_page2['ERROR']);
// for($xx=0; $xx<count($web_page); $xx++){
// echo($web_page[$xx]);
// }
// echo "ERROR \n";
// var_dump($new_page['ERROR']);
//*******************************
// $web_page = file($new_page);
// for($xx = 0; $xx < count($web_page); $xx++)
// echo $web_page[$xx];
//********************************
// $file_handle = fopen($new_page, "r");
// while (!feof($file_handle))
// {
// echo fgets($file_handle, 4096);
// }
// fclose($file_handle);
$count++;
}
?>
(I left the comments, I've tried different way to display the webpage)
As you can see, I am using the engine WampServer_x64 on a basic Windows 7.
I'm following a redirection to the https://x.x.x.x/login.cs page.
The important part is the download of webpage2.
Here the LIB_parse library (just necessary lines), wrapping curl options in PHP functions :
function http_get($target, $ref)
{
return http($target, $ref, $method="GET", $data_array="", EXCL_HEAD);
}
function http($target, $ref, $method, $data_array, $incl_head)
{
# Initialize PHP/CURL handle
$ch = curl_init();
# Prcess data, if presented
if(is_array($data_array))
{
# Convert data array into a query string (ie animal=dog&sport=baseball)
foreach ($data_array as $key => $value)
{
if(strlen(trim($value))>0)
$temp_string[] = $key . "=" . urlencode($value);
else
$temp_string[] = $key;
}
$query_string = join('&', $temp_string);
}
# HEAD method configuration
if($method == HEAD)
{
curl_setopt($ch, CURLOPT_HEADER, TRUE); // No http head
curl_setopt($ch, CURLOPT_NOBODY, TRUE); // Return body
}
else
{
# GET method configuration
if($method == GET)
{
if(isset($query_string))
$target = $target . "?" . $query_string;
curl_setopt ($ch, CURLOPT_HTTPGET, TRUE);
curl_setopt ($ch, CURLOPT_POST, FALSE);
}
# POST method configuration
if($method == POST)
{
if(isset($query_string))
curl_setopt ($ch, CURLOPT_POSTFIELDS, $query_string);
curl_setopt ($ch, CURLOPT_POST, TRUE);
curl_setopt ($ch, CURLOPT_HTTPGET, FALSE);
}
curl_setopt($ch, CURLOPT_HEADER, $incl_head); // Include head as needed
curl_setopt($ch, CURLOPT_NOBODY, FALSE); // Return body
}
curl_setopt($ch, CURLOPT_COOKIEJAR, COOKIE_FILE); // Cookie management.
curl_setopt($ch, CURLOPT_COOKIEFILE, COOKIE_FILE);
curl_setopt($ch, CURLOPT_TIMEOUT, CURL_TIMEOUT); // Timeout
curl_setopt($ch, CURLOPT_USERAGENT, WEBBOT_NAME); // Webbot name
curl_setopt($ch, CURLOPT_URL, $target); // Target site
curl_setopt($ch, CURLOPT_REFERER, $ref); // Referer value
curl_setopt($ch, CURLOPT_VERBOSE, FALSE); // Minimize logs
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // No certificate
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); // Follow redirects
curl_setopt($ch, CURLOPT_MAXREDIRS, 4); // Limit redirections to four
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); // Return in string
# Create return array
$return_array['FILE'] = curl_exec($ch);
$return_array['STATUS'] = curl_getinfo($ch);
$return_array['ERROR'] = curl_error($ch);
# Close PHP/CURL handle
curl_close($ch);
# Return results
return $return_array;
}
I do not know how to handle the TLS connection with cURL. I've been trying for hours with different stuff .. I have this issue : encrypted alert :
whireshark capture TCP and TLS exchange
I've add this line to the original library :
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
//curl_setopt($ch, CURLOPT_SSLVERSION, 6);
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
I can't get the web page.
Apparently, the SSL version is 1.0.2h.
I have tried many different things .. With many different error types, but always around the SSL certificate stuff..
I have no more ideas where to look..
If you guys can give me a trail ! That would be nice

Accessing the SPtrans API, authorization failing on information requests

I'm trying to use the SPtrans API (http://www.sptrans.com.br/desenvolvedores/APIOlhoVivo.aspx), which is supposed to provide public transport information for the Sao Paulo (Brazil) area.
I'm trying to get in using PHP and curl.
I'm able to put in the requests and can authenticate myself (with a post request to /Login/Autenticar?token={token}. The post request returns a 'true' (and only a 'true').
(It seems that I need to put the token both as a GET and a POST.)
However, if I then put in an information (GET) request, for example to /Linha/Buscar?termosBusca={termosBusca}, I get a consistent return of "Authorization has been denied for this request." message.
You can see this (not) working at:
http://00qq.com/sptrans/index.php
Any thoughts or ideas on this would be extremely helpful.
Here's the code that picks up the data:
function getResult($accesspoint, $page, $postData, $post = true) {
$ch = curl_init();
$t = http_build_query($postData);
$url = $accesspoint.$page."?".$t;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if ($post == true) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
}
curl_setopt($ch, CURLOPT_HEADER, 0);
$output = curl_exec($ch);
curl_close($ch);
$output = object_to_array(json_decode($output));
return $output;
}
Update
#chesterbr put me on the right track: I had to create, collect and store cookies upon authentication and then use those upon subsequent requests. Below is a proof of concept.
$site["sptrans"]["accesspoint"] = "http://api.olhovivo.sptrans.com.br/v0";
$site["sptrans"]["page"]["Login"] = "/Login/Autenticar";
$site["sptrans"]["page"]["Parada"] = "/Parada/Buscar";
$site["sptrans"]["page"]["Linha"] = "/Linha/Buscar";
$site["sptrans"]["token"] = ""; //This should contain your token.
error_reporting(E_ALL);
ini_set('display_errors', 1);
function object_to_array($data) {
if (is_array($data) || is_object($data)) {
$result = array();
foreach ($data as $key => $value)
$result[$key] = object_to_array($value);
return $result;
}
return $data;
}
function getResult($accesspoint, $page, $postData, $cookie, $post = true) {
$ch = curl_init();
$t = http_build_query($postData);
$url = $accesspoint.$page."?".$t;
// print $url."<br />";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt ($ch, CURLOPT_COOKIEFILE, $cookie);
// curl_setopt($ch, CURLOPT_COOKIESESSION, true);
if ($post == true) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
}
curl_setopt($ch, CURLOPT_HEADER, 0);
$output = curl_exec($ch);
curl_close($ch);
$output = object_to_array(json_decode($output));
return $output;
}
//Create a cookie for the duration of the page.
$ckfile = tempnam ("cache/cookies", "spt.");
print "Authentication<br />";
$postData["token"] = $site["sptrans"]["token"];
$output = getResult($site["sptrans"]["accesspoint"], $site["sptrans"]["page"]["Login"], $postData, $ckfile);
print_r ($output);
unset($postData);
print "<hr />";
print "Linha<br />";
$postData["termosBusca"] = "8000";
$output = getResult($site["sptrans"]["accesspoint"], $site["sptrans"]["page"]["Linha"], $postData, $ckfile, false);
print_r ($output);
unset($postData);
print "<hr />";
print "Parada<br />";
$postData["termosBusca"] = "Afonso";
$output = getResult($site["sptrans"]["accesspoint"], $site["sptrans"]["page"]["Parada"], $postData, $ckfile, false);
print_r ($output);
unset($postData);
print "<hr />";
//Delete the cookie
unlink($ckfile);
You can see this work at http://00qq.com/sptrans/index.php
The API requires you to store the cookies from the authentication call and include them in subsequent ones (otherwise, the server can't know those calls belong to the same session, since HTTP is stateless by default).
You can make that in PHP by configuring the cURL library as described in: https://stackoverflow.com/a/12885587. See also http://www.php.net/manual/en/function.curl-setopt.php for more information on such options (search for "COOKIE" options).

How to read CURL POST on remote server?

This is my cURL POST function:
public function curlPost($url, $data)
{
$fields = '';
foreach($data as $key => $value) {
$fields .= $key . '=' . $value . '&';
}
rtrim($fields, '&');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, count($data));
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
}
$this->curlPost('remoteServer', array(data));
How do I read the POST on the remote server?
The remote server is using PHP... but what var in $_POST[] should I read
for e.g:- $_POST['fields'] or $_POST['result']
You code works but i'll advice you to add 2 other things
A. CURLOPT_FOLLOWLOCATION because of HTTP 302
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
B. return in case you need to output the result
return $result ;
Example
function curlPost($url, $data) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
$result = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
return $result;
}
print(curlPost("http://yahoo.com", array()));
Another Example
print(curlPost("http://your_SITE", array("greeting"=>"Hello World")));
To read your post you can use
print($_REQUEST['greeting']);
or
print($_POST['greeting']);
as a normal POST request ... all data posted can be found in $_POST ... except files of course :) add an &action=request1 for example to URL
if ($_GET['action'] == 'request1') {
print_r ($_POST);
}
EDIT: To see the POST vars use the folowing in your POST handler file
if ($_GET['action'] == 'request1') {
ob_start();
print_r($_POST);
$contents = ob_get_contents();
ob_end_clean();
error_log($contents, 3, 'log.txt' );
}

PHP Curl How to extract header's

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https://test.com");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'x=32423');
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
if(curl_exec($ch) === false)
{
echo 'Curl error: ' . curl_error($ch);
}
else
{
'OK';
}
This is what outputted,when i run this page
access_token=AAAdsfsdfds32432fadfcazdfadsfadsfdas
How do i extract this and pass it a variable?
There is a typo in your postfields. The postfields should be as follows:
curl_setopt($ch, CURLOPT_POSTFIELDS, array('x'=>'32423'));
instead of:
curl_setopt($ch, CURLOPT_POSTFIELDS, 'x=32423'');
First off, you need to change your CURLOPT_HEADERS to true, and you need
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
and
$result=curl_exec($ch)
if( $result=== false)
Then, according to an answer I saw elsewhere on SO, this should get you the headers:
list($headers,$content) = explode("\r\n\r\n",$result,2);
foreach (explode("\r\n",$headers) as $hdr)
print_r($hdr); //see what it gives you and then edit this accordingly.
echo $content;
Sounds like you just want
$token = end(explode('=', $access_token_string));

How do I get a valid response code for an image using PHP CURL on a Linux server?

I am trying to detect whether a URL to an image is valid, behind a firewall or behind an authenticated area. Below is the function that I have written:
private function pingImg($img){
$found = FALSE;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $img);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_NOBODY, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_TIMEOUT, 7);
$result = curl_exec($curl);
if($result !== false){
if(curl_getinfo($curl, CURLINFO_HTTP_CODE) == "401"){
$found = TRUE;
$this->_httpBasicAuthImages = TRUE;
}
//now check for invalid cert
if(stripos($img, "https") !== FALSE){
curl_close($curl);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $img);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_NOBODY, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($curl, CURLOPT_TIMEOUT, 7);
$result = curl_exec($curl);
if(!$result) {
$found = TRUE;
$this->_invalidSSL = TRUE;
}
}
} else {
//stalled ping, probably behind a firewall
$found = TRUE;
$this->_firewallImg = TRUE;
}
curl_close($curl);
return $found;
}
That code works great on our development Windows server (returns all the proper response codes) but unfortunately it does not work on our production Linux server. Basically no response code is returned on the Linux server when an image is behind an authenticated zone (ie 401 status code). The response is blank.
Has anyone encountered this same issue? If so, how do I fix it so the proper response code will be returned on our Linux server?
Thanks for your time.
OK, I found a solution. Not sure its the most elegant (I would rather use CURL for everything) but it works on the Linux server:
#file_get_contents($img, NULL, stream_context_create(array('http'=>array('method' => "HEAD",'follow_location' => 0,'timeout'=>7))));
if (!empty($http_response_header)){
$code = "";
sscanf($http_response_header[0], 'HTTP/%*d.%*d %d', $code);
if($code == "401"){
$found = TRUE;
$this->_httpBasicAuthImages = TRUE;
}}
I hope this helps anyone else encountering the same issue.
More details about the new functionality can be found on the following page: http://hakre.wordpress.com/2011/09/17/head-first-with-php-streams/

Categories