Page 1 of 1

[solved] getting started with cURL

Posted: Mon Dec 18, 2006 5:29 am
by Skittlewidth
I'm in the process of trying to learn how to use cURL and I don't think I fully understand something.
I've adapted the following code from developer.zend.com

Code: Select all

$url = "http://www.mydomain.co.uk/sphider/admin/auth.php"; 
$ch = curl_init();    // initialize curl handle 

curl_setopt($ch, CURLOPT_URL,$url); // set url to post to 
curl_setopt($ch, CURLOPT_FAILONERROR, 1); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);// allow redirects 
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // return into a variable 
curl_setopt($ch, CURLOPT_TIMEOUT, 5); // times out after 4s 
curl_setopt($ch, CURLOPT_POST, 1); // set POST method 
curl_setopt($ch, CURLOPT_POSTFIELDS, "user=".urlencode('user)."&pass=".urlencode('password)."&submit=".urlencode('Log in')); // add POST fields 
$result = curl_exec($ch); // run the whole process 

print_r(curl_getinfo($ch));  
echo "\n\ncURL error number:" .curl_errno($ch);  
echo "\n\ncURL error:" . curl_error($ch);  
curl_close($ch);
This targets a login script and sends the username and password as post variables. I've altered the login script so that it sends me an email as if it receives those variables and the variables are correct. When I run the cURL script I get those emails so I know the request should have been successful. If you echo the cURL result however you get the login form, and not the page you should have been redirected to, i.e. the admin menu.

CURLOPT_FOLLOWLOCATION is set to true, so as far as I understand it should have followed the header redirect that followed the successful username and password check, no?

Second question, assuming the login script worked and I'm logged in, I then need to visit a second url which is on the admin menu. Do I set the new url after the first curl_exec and then run curl_exec again before the curl session is closed with curl_close, or do I run a new curl routine starting from curl_init? My guess is that the second method would kill the session vars that were initialized by the first curl session.

Posted: Mon Dec 18, 2006 6:11 am
by onion2k
There's a problem with your single quotes in the line of post data. And you've missed off the $ sign on the variables.

Posted: Mon Dec 18, 2006 6:16 am
by Skittlewidth
oops, yeah thats just where I changed the values for the example and must have left off the closing quote....twice!! They aren't variables they're strings, - the user name is 'user' and the password is 'password'. The script I'm running has the values correctly encapsulated. Sorry for the confusion

Posted: Mon Dec 18, 2006 8:29 am
by feyd
How are you performing the redirection on the receiving script?

Posted: Mon Dec 18, 2006 10:14 am
by Skittlewidth
The redirection on the receiving script is simply:

Code: Select all

header("Location: admin.php");
I added an exit() underneath which the script was lacking, incase the whole thing was being confused by the script continuing to process.

However since you asked, it's occured to me that CURL might not like the relative url in the redirect. Should I try putting an absolute url in the header?

Posted: Mon Dec 18, 2006 10:45 am
by feyd
Skittlewidth wrote:However since you asked, it's occured to me that CURL might not like the relative url in the redirect. Should I try putting an absolute url in the header?
It can't hurt. ;)

Posted: Tue Dec 19, 2006 5:51 am
by Skittlewidth
Sadly, that didn't work :(

Here's the code in the auth.php file incase that explains anything:

Code: Select all

<?
	error_reporting(E_ERROR | E_PARSE);	
	$admin = "user";
	$admin_pw = "password";

	session_start();
	
if (isset($_POST['user']) && isset($_POST['pass'])) {
	
	$username = $_POST['user'];
	$password = $_POST['pass'];
	if (($username == $admin) && ($password ==$admin_pw)) {
		$_SESSION['admin'] = $username;
		$_SESSION['admin_pw'] = $password;
	}
	header("Location: http://www.domain.co.uk/sphider/admin/admin.php");
	exit();
} elseif ((isset($_SESSION['admin']) && isset($_SESSION['admin_pw']) &&$_SESSION['admin'] == $admin && $_SESSION['admin_pw'] == $admin_pw ) || (getenv("REMOTE_ADDR")=="")) {

} else {
	
	?>
	<html>
	<head>
	<title>Sphider Admin Login</title>
		<LINK REL=STYLESHEET HREF="admin.css" TYPE="text/css">
	</head>

	<body>
	<center>
	<br><br>
	
	<fieldset style="width:30%;"><legend><b>Sphider Admin Login</b></legend>
	<form action="auth.php" method="post">
	
	<table>
	<tr><td>Username</td><td><input type="text" name="user"></td></tr>
	<tr><td>Password</td><td><input type="password" name="pass"></td></tr>
	<tr><td></td><td><input type="submit" value="Log in" id="submit"></td>
	</tr></table>
	</form>
	</fieldset>
	</center>
	</body>
	</html>
	<?
	exit();
}


$settings_dir = "../settings";
include "$settings_dir/database.php";

?>
I'm fairly confident it's something I'm doing wrong rather than this script, but maybe it will help someone explain to me what the approach should be. Just to recap, after logging in I want to then navigate to another page.

Posted: Tue Dec 19, 2006 6:23 am
by volka
I've tested your script with

Code: Select all

<?php // auth.php
if ( isset($_POST['user'],$_POST['pass'])
	&& 'user'===$_POST['user'] && 'password'===$_POST['pass'] ) {
		header('Location: http://www.php.net/downloads.php');
		die();
}
?>
<html>
	<head><title>login</title></head>
	<body>
		<form method="post" action="auth.php">
			<div>
				<input type="text" name="user" />
				<input type="text" name="pass" />
				<input type="submit" />
			</div>
		</form>
	</body>
</html>
and

Code: Select all

<?php
$url = "http://localhost/auth.php";
$ch = curl_init();    // initialize curl handle

curl_setopt($ch, CURLOPT_URL,$url); // set url to post to
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);// allow redirects
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // return into a variable
curl_setopt($ch, CURLOPT_TIMEOUT, 5); // times out after 4s
curl_setopt($ch, CURLOPT_POST, 1); // set POST method
curl_setopt($ch, CURLOPT_POSTFIELDS, "user=".urlencode('user')."&pass=".urlencode('password')."&submit=".urlencode('Log in')); // add POST fields
$result = curl_exec($ch); // run the whole process

print_r(curl_getinfo($ch)); 
echo "\n\ncURL error number:" .curl_errno($ch); 
echo "\n\ncURL error:" . curl_error($ch); 
curl_close($ch);
it got redirected to php.net as expected.

Posted: Tue Dec 19, 2006 6:36 am
by onion2k
Sessions won't work in cURL unless you set the COOKIE_JAR option.

Code: Select all

curl_setopt ($curl, CURLOPT_COOKIEFILE, "cookie.txt");
curl_setopt ($curl, CURLOPT_COOKIEJAR, "cookie.txt");
Not sure if you actually need both, but that's what I used agggggges ago when I wrote a script to log into forums. On Windows you'll need to specify a full path like c:/apache/htdocs/womble/cookies/cookie.txt.

Posted: Tue Dec 19, 2006 7:45 am
by Skittlewidth
Yeah I think its almost certainly a session issue. I copied the auth.php script and tried directing to other sites and pages and it worked fine. Then I thought I'd make it redirect to the page I'm trying to get at, and it didn't work because it includes the auth.php script and the sessions aren't set.

I'm looking into the CURLOPT_COOKIEJAR option now, thanks.

Posted: Tue Dec 19, 2006 7:58 am
by Skittlewidth
Ok, after trying the cookie_jar thing (and possibly doing it wrong) I finally got things to work using this function in the user comments on php.net for curl_setopt

Code: Select all

function read_header($ch, $string)
{
   global $location; #keep track of location/redirects
   global $cookiearr; #store cookies here
   global $ch; 
       # ^overrides the function param $ch
       # this is okay because we need to 
       # update the global $ch with 
       # new cookies
   
   $length = strlen($string);
   if(!strncmp($string, "Location:", 9))
   { #keep track of last redirect
     $location = trim(substr($string, 9, -1));
   }
   if(!strncmp($string, "Set-Cookie:", 11))
   { #get the cookie
     $cookiestr = trim(substr($string, 11, -1));
     $cookie = explode(';', $cookiestr);
     $cookie = explode('=', $cookie[0]);
     $cookiename = trim(array_shift($cookie)); 
     $cookiearr[$cookiename] = trim(implode('=', $cookie));
   }
   $cookie = "";
   if(trim($string) == "") 
   {  #execute only at end of header
     foreach ($cookiearr as $key=>$value)
     {
       $cookie .= "$key=$value; ";
     }
     curl_setopt($ch, CURLOPT_COOKIE, $cookie);
   }

   return $length;
}


$url = "http://www.domain.co.uk/sphider/admin/auth2.php";
$ch = curl_init();    // initialize curl handle

curl_setopt($ch, CURLOPT_URL,$url); // set url to post to
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);// allow redirects
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // return into a variable
curl_setopt($ch, CURLOPT_TIMEOUT, 500);
curl_setopt($ch, CURLOPT_POST, 1); // set POST method
curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
curl_setopt($ch, CURLOPT_POSTFIELDS, "user=".urlencode('user')."&pass=".urlencode('password')."&submit=".urlencode('Log in')); 
// add POST fields
$result = curl_exec($ch); // run the whole process

print_r(curl_getinfo($ch));
echo "\n\ncURL error number:" .curl_errno($ch);
echo "\n\ncURL error:" . curl_error($ch);
curl_close($ch);
echo $result;
Thanks for all your suggestions though, I've learned a lot! Next task....setting up a cron job....