PHP cURL Log into website and perform action on different page - php

I am having a little problem with something. I have the following code which uses cURL to log into a website, posting all the required data
<?php
$url = "https://someurl/login.aspx";
$ckfile = tempnam("/tmp", "CURLCOOKIE");
$useragent = $_SERVER['HTTP_USER_AGENT'];
$username = "someuser#hotmail.co.uk";
$password = "somepassword";
$f = fopen('log.txt', 'w');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
$html = curl_exec($ch);
curl_close($ch);
preg_match('~<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="(.*?)" />~', $html, $viewstate);
preg_match('~<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="(.*?)" />~', $html, $eventValidation);
$viewstate = $viewstate[1];
$eventValidation = $eventValidation[1];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile);
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_REFERER, $url);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_STDERR, $f);
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
$postfields = array();
$postfields['__EVENTTARGET'] = "";
$postfields['__EVENTARGUMENT'] = "";
$postfields['__VIEWSTATE'] = $viewstate;
$postfields['__EVENTVALIDATION'] = $eventValidation;
$postfields['btnLogin'] = "Login";
$postfields['txtPassword'] = $password;
$postfields['txtUserName'] = $username;
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
$ret = curl_exec($ch);
So the above code works fine. I do not close curl yet because I need to keep the cookie active. Anyways, once I have logged in using the above, I do
if($ret) {
curl_setopt($ch, CURLOPT_URL, 'https://someurl.com/financial/quote.aspx?id=12345');
curl_setopt($ch, CURLOPT_POST, 0);
$data = curl_exec($ch);
var_dump($data);
}
I can see from the output that I am now on the correct page. However, in the example above, I do not post anything. The page which I go too has a button on it. When looking at what is posted by this button within Firebug I see this
__EVENTARGUMENT
__EVENTTARGET
__EVENTVALIDATION fsudifhsiudgfiusgdf
__VIEWSTATE
__VIEWSTATE_GUID 0f26cc24-ef59-4bc7-87c0-141833df148b
ctl00$PageContent$btn2 Accepted
As such, I have tried to replicate the pushing of this button by doing the following
if($ret) {
curl_setopt($ch, CURLOPT_URL, 'https://someurl.com/financial/quote.aspx?id=12345');
$postfieldsInner = array();
$postfieldsInner['__EVENTTARGET'] = "";
$postfieldsInner['__EVENTARGUMENT'] = "";
$postfieldsInner['__VIEWSTATE'] = "";
$postfieldsInner['__VIEWSTATE_GUID'] = $viewstate;
$postfieldsInner['__EVENTVALIDATION'] = $eventValidation;
$postfieldsInner['ctl00$PageContent$btn2'] = "Accepted";
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfieldsInner);
$content = curl_exec($ch);
if (!$content) {
echo 'An error has occurred: ' . curl_error($ch);
} else {
var_dump($content);
}
}
This time however, the button action does not seem to occur. Am I missing something when making the second request?
Thanks

So, a couple of things jump out at me:
You're assuming that the magic values for __VIEWSTATE and __EVENTVALIDATION won't change. This is unlikely to be the case. You should pull those values again after fetching the data page.
You're passing the $viewstate variable as the value for __VIEWSTATE on the initial login, but you leave that blank on the subsequent post and instead pass $viewstate as __VIEWSTATE_GUID. Not sure if this is intentional or not.
You're using an array for CURL_POSTFIELDS which may cause problems. The documentation says:
Passing an array to CURLOPT_POSTFIELDS will encode the data as multipart/form-data, while passing a URL-encoded string will encode the data as application/x-www-form-urlencoded.
And, very important, do NOT disable certificate validation, fix your server setup instead.
A few other suggestions, perhaps more a matter of style than substance though.
Passing an empty string as CURLOPT_COOKIEFILE will enable session handling without the need to save to a file.
You don't need to do curl_close() and curl_init() multiple times in a script; just reuse the existing handle. This saves having to redefine the options and reuse the session cookies.
Use curl_setopt_array() for cleaner code.
curl_exec() returns false on error, you should check for it explicitly.
Here's how I'd clean up the code:
<?php
$url = "https://someurl/login.aspx";
$ckfile = tempnam("/tmp", "CURLCOOKIE");
$useragent = $_SERVER['HTTP_USER_AGENT'];
$username = "someuser#hotmail.co.uk";
$password = "somepassword";
$viewstate_pattern = '~<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="(.*?)" />~';
$eventval_pattern = '~<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="(.*?)" />~';
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_COOKIEFILE => "",
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERAGENT => $useragent,
]);
// Getting the login form
$html = curl_exec($ch);
if ($html !== false) {
preg_match($viewstate_pattern, $html, $viewstate);
preg_match($evenval_pattern, $html, $eventValidation);
$viewstate = $viewstate[1];
$eventValidation = $eventValidation[1];
$postfields = http_build_query([
"__EVENTTARGET"=>"",
"__EVENTARGUMENT"=>"",
"__VIEWSTATE"=>$viewstate,
"__EVENTVALIDATION"=>$eventValidation,
"btnLogin"=>"Login",
"txtPassword"=>$password,
"txtUserName"=>$username,
]);
curl_setopt_array($ch, [
CURLOPT_REFERER=>$url,
CURLOPT_POST=>true,
CURLOPT_POSTFIELDS=>$postfields,
]);
// Submitting the login form
$html = curl_exec($ch);
if ($html !== false) {
curl_setopt_array($ch, [
CURLOPT_URL=>'https://someurl.com/financial/quote.aspx?id=12345',
CURLOPT_POST=>false,
]);
// Getting the data page
$html = curl_exec($ch);
if ($html !== false) {
preg_match($viewstate_pattern, $html, $viewstate);
preg_match($evenval_pattern, $html, $eventValidation);
$viewstate = $viewstate[1];
$eventValidation = $eventValidation[1];
$postfieldsInner = http_build_query([
"__EVENTTARGET"=>"",
"__EVENTARGUMENT"=>"",
// Should this be empty?
"__VIEWSTATE"=>"",
"__VIEWSTATE_GUID"=>$viewstate,
"__EVENTVALIDATION"=>$eventValidation,
'ctl00$PageContent$btn2'=>"Accepted",
]);
curl_setopt_array($ch, [
CURLOPT_POST=>true,
CURLOPT_POSTFIELDS=>$postfieldsInner,
]);
// Posting the data page
$html = curl_exec($ch);
if ($html === false) {
echo 'An error has occurred: ' . curl_error($ch);
} else {
var_dump($html);
}
} else {
// Error getting the data page
}
} else {
// Error submitting the login page
}
} else {
// Error getting the login page
}
curl_close();

Related

$_POST via cURL not working

Im trying my hand at using curl to post some data, I am not reciving my post content and can not find the source of the problem
curl.php
<?php
$data = array("user_email" => "22" , "pass" => "22" );
$string = http_build_query($data);
$ch = curl_init("http://localhost:8888/290_project/test.php"); //this is where post data goes too, also starts curl
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
curl_close($ch) //ends curl
?>
test.php
<?php
if(isset($_POST['user_email'], $_POST['pass'])) {
$name = $_POST['user_email'];
$pass = $_POST['pass'];
echo $name;
echo $pass;
} else {
echo "error";
} ?>
Every time I get my error response meaning the post data is not going through. I have tried everything I could think of to trouble shoot;I must be over looking something I am simply not yet familiar with?
Please set CURLOPT_URL to http://localhost:8888.....
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://localhost:8888/290_project/test.php");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
if(!curl_errno($ch)){
$info = curl_getinfo($ch);
} else {
echo 'Curl error: ' . curl_error($ch);
}
curl_close($ch) //ends curl
?>
With curl_getinfo() - Gets information about the last transfer.
For more detail read below link:- http://php.net/manual/en/function.curl-getinfo.php
I have edited the answer, The reason for error is not curl.
http_build_query($data, '', '&');
Following is working example. Please try this.
$postData = array(
'user_name' => 'abcd',
'password' => 'asdfghj',
'redirect' => 'yes',
'user_login' => '1'
);
$url='http://localhost:8888/290_project/test.php';
$ch = curl_init();
//Set the URL to work with
curl_setopt($ch, CURLOPT_URL, $url);
// ENABLE HTTP POST
curl_setopt($ch, CURLOPT_POST, 1);
//Set the post parameters
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//execute the request
$store = curl_exec($ch);
print_r($store);
curl_close($ch)
You have an error in your php code:
edit:
if(isset($_POST['user_email'], $_POST['pass'])) {
to:
if(isset($_POST['user_email']) && isset($_POST['pass'])) {

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).

Trying to get data from aspx page after post + PHP

I want to get the data from the following page : http://kovv.mavari.be/kalender.aspx when you press on the submit button and the dropdownlists have no selected values. (So the page where you see a big table)
I've tried to follow a tutorial you can find here: http://www.mishainthecloud.com/2009/12/screen-scraping-aspnet-application-in.html.
This is what I have so far:
public function teamsoostVlaanderen()
{
$url = "http://kovv.mavari.be/kalender.aspx";
$regs=array();
$cookies = '../src/VolleyScout/VolleyScoutBundle/Resources/doc/cookie.txt';
// regular expressions to parse out the special ASP.NET
// values for __VIEWSTATE and __EVENTVALIDATION
$regexViewstate = '/__VIEWSTATE\" value=\"(.*)\"/i';
$regexEventVal = '/__EVENTVALIDATION\" value=\"(.*)\"/i';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$data=curl_exec($ch);
$viewstate = $this->regexExtract($data,$regexViewstate,$regs,1);
$eventval = $this->regexExtract($data, $regexEventVal,$regs,1);
$postData = '__VIEWSTATE='.rawurlencode($viewstate)
.'&__EVENTVALIDATION='.rawurlencode($eventval)
.'&ctl00_ContentPlaceHolder1_ddlGeslacht'
.'&ctl00$ContentPlaceHolder1$ddlReeks'
.'&ctl00_ContentPlaceHolder1_ddlDatum'
.'&ctl00$ContentPlaceHolder1$btnZoek:zoek'
;
curl_setOpt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookies);
$data = curl_exec($ch);
echo $data;
curl_close($ch);
die();
}
public function regexExtract($text, $regex, $regs, $nthValue)
{
if (preg_match($regex, $text, $regs)) {
$result = $regs[$nthValue];
}
else {
$result = "";
}
return $result;
}
But I still get the page without a post (so not with the table). When I check my cookies.txt file it's empty, maybe there's the problem? Can somebody help me find the problem?
Appropriate regex:
$regexViewstate = '/__VIEWSTATE\" value=\"([^"]*)\"/i';
$regexEventVal = '/__EVENTVALIDATION\" value=\"([^"]*)\"/i';
And missing the equal sign from your post parameters:
$postData = '__VIEWSTATE='.rawurlencode($viewstate)
.'&__EVENTVALIDATION='.rawurlencode($eventval)
.'&ctl00_ContentPlaceHolder1_ddlGeslacht='
.'&ctl00$ContentPlaceHolder1$ddlReeks='
.'&ctl00_ContentPlaceHolder1_ddlDatum='
.'&ctl00$ContentPlaceHolder1$btnZoek=zoek'

Curl login Joomla 1.6/3.0

I am trying to login Joomla 1.6/3.0 by curl in PHP but not success.
I had try method from joomla 1.5
$uname = "id";
$upswd = "pswd";
$url = "http://www.somewebpage.com";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url );
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE );
curl_setopt($ch, CURLOPT_COOKIEJAR, './cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, './cookie.txt');
curl_setopt($ch, CURLOPT_HEADER, FALSE );
$ret = curl_exec($ch);
if (!preg_match('/name="([a-zA-z0-9]{32})"/', $ret, $spoof)) {
preg_match("/name='([a-zA-z0-9]{32})'/", $ret, $spoof);
}
// POST fields
$postfields = array();
$postfields['username'] = urlencode($uname);
$postfields['passwd'] = urlencode($upswd);
$postfields['lang'] = '';
$postfields['option'] = 'com_login';
$postfields['task'] = 'login';
$postfields[$spoof[1]] = '1';
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
$ret = curl_exec($ch);
But it 's show forbidden
Joomla! normally from the web browser will send a token, to make sure the form was posted from a browser (and not from somewhere outside, like you are trying to do).
If it's not posted from a browser, an error like 'The most recent request was denied because it contained an invalid security token. Please refresh the page and try again.'
You may want to look for an autentication plugin that supports what you are trying to do. For example the Autologin plugin.

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' );
}

Categories