PHP & cURL to use existing COOKIEFILE + Adding my own value to save - php

I already have a cookie file saved that I want to reference and update. I also want to specify my own additional cookie values via CURLOPT_COOKIE and save those to my existing cookie file as well.
However, I am unable to get this to work.
My code is:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $website); // Define target site
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); // Return page in string
curl_setopt($ch, CURLOPT_ENCODING , "gzip");
curl_setopt($ch, CURLOPT_COOKIE, "fruit=apple;");
curl_setopt($ch, CURLOPT_COOKIEJAR, "usercookies/cookie_$user.txt"); // Tell cURL where to write cookies
curl_setopt($ch, CURLOPT_COOKIEFILE, "usercookies/cookie_$user.txt"); // Tell cURL which cookies to send
curl_setopt($ch, CURLOPT_TIMEOUT,15);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); // Follow redirects
$returnx = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
My saved cookie file does not reflect the changes I made via curl_setopt($ch, CURLOPT_COOKIE, "fruit=apple;");. The cookiefile saved should show "fruit=apple" but it's still showing the old values or the values returned by the cURL request.
Do I need to reference the entire domain name in order to get it to save?
The cookie file looks something like this:
# Netscape HTTP Cookie File
# http://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
.go.com TRUE / FALSE 1754020486 one AE4F4981
.go.com TRUE / FALSE 1468965260 two B9A1

Cookies you add manually using CURLOPT_COOKIE won't get saved to the cookie jar at the end of the request.
The only case in which it would is if the server sent back a Set-Cookie header for the cookie you sent in order to update it.
The reason is because cURL requests have a cookie structure that holds cookies which gets written at the end of the request. Data only gets in this structure by a) being read from the cookie file in the first place or b) Set-Cookie headers in the response headers.
With a little care you can append your own cookie to that file with something like this:
$domain = '.go.com';
$expire = time() + 3600;
$name = 'fruit';
$value = 'apple';
file_put_contents($cookieJar, "\n$domain\tTRUE\t/\tFALSE\t$expire\t$name\t$value", FILE_APPEND);

Related

How to connecting to the remote site with CURL and header location

I am logging from site A through CURL on site B, I get the cookies from the connection and write to file called cookie.txt.
But when I pass the cookie data to do the final header redirection ('Location: http://examplesiteb.com'), it returns disconnected.
The code I am using for connection is the same as in this other post, but with my modifications following the #ramrider user's suggestion that I suggested passing the cookies in the header, but I'm not sure how this should be done.
Transfer cookies & session from CURL to header location
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_COOKIESESSION, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, 10);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt');
// Download the given URL, and return output
$output = curl_exec($ch);
// Cookie Match
preg_match_all('/^Set-Cookie:\s*([^\r\n]*)/mi', $output, $ms);
$cookies = array();
foreach ($ms[1] as $m) {
list($name, $value) = explode('=', $m, 2);
$cookies[$name] = $value;
header('Set-Cookie: '.rawurlencode($name).'='.rawurlencode($value));
}
//print_r($cookies);
$redirect = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
header("Location: $redirect");
//Close Match
curl_close($ch);
The redirect happens but does not keep logged in.
Below the example cookie file
# Netscape HTTP Cookie File
# http://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_example.com FALSE / FALSE 0 ASP.NET_SessionId 10gtonkebkteuazx24sajlh2
#HttpOnly_example.com FALSE / TRUE 1515800212 DTE 898EC9C0EF0BA3985E402046547931EAA55808E14A2DE469F11F6F6C0CF9A28871C8704BE794885CDF7D3EE1E8B06698166F86C184C5B53FE61FA53CA13682C562E17BCB7B2FA16D7A7180E6EA973735
The users #martijn-pieters and #waqas-bukhary if they can help I thank you, because you deleted my answer in the other post, and I was completing with additional information for others that I can not find a solution.
Thanks
Cookies are tied to the domain that sends them. You cannot set cookies for a different domain.
If "Site B" (where you are using cURL to log in to "Site A") is example.com, and "Site A" is not-example.com, the cookies set by Set-Cookie are for example.com and will not apply to not-example.com.
There is no mechanism to set cookies for a domain other than your own.
See RFC 6265 Section 5.3 (Storage Model) Part 6:
If the domain-attribute is non-empty:
If the canonicalized request-host does not domain-match the domain-attribute:
Ignore the cookie entirely and abort these steps.
This effectively says that a browser must ignore a cookie if site A attempts to set a cookie for site B.

Why is CURLOPT_COOKIEJAR somehow saving different cookie values than the Set-Cookie header?

TL;DR:
I have some very simple PHP code utilizing cURL that makes single HTTP requests (in practice, to a Diaspora* pod, though that shouldn't be relevant to the question). The code takes note of any cookies returned by the web server and then manually sets those values to libcurl's CURLOPT_COOKIE. However, in trying to hunt down a bug, I'm finding that when I use CURLOPT_COOKIEFILE and CURLOPT_COOKIEJAR, the values of the cookies in the cookie file are different than when I use CURLOPT_COOKIE. Why is this the case? (See code below.)
PRIOR RESEARCH
I have already looked other questions such as this one that suggest various ways of manipulating libcurl's options to keep the same resource handle around and the cookies in memory, but this is not suitable to my application. I need to access the cookie values directly and notably not on a filesystem (to save them into a database, but again, this should not matter with regards to the question).
CODE
For completeness, here is a test case for code I am using:
<?php
// This function simply extracts the cookie set by a webserver by looking at the full HTTP source traffic.
function readCookie ($str) {
$m = array();
preg_match('/Set-Cookie: (.*?);/', $str, $m);
return (!empty($m[1])) ? $m[1] : false;
}
// This function does the same for the CSRF token required for login.
function parseAuthenticityToken ($str) {
$m = array();
preg_match('/content="(.*?)" name="csrf-token"/', $str, $m);
return (!empty($m[1])) ? $m[1] : false;
}
// Get first page, to find the CSRF token.
$ch = curl_init('https://diasp.org/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$resp = curl_exec($ch);
curl_close($ch);
$csrf_token = parseAuthenticityToken($resp);
$params = array(
'user[username]' => 'my_username',
'user[password]' => 'my_password',
'authenticity_token' => $csrf_token
);
// Make POST request to the log in controller.
$ch = curl_init('https://diasp.org/users/sign_in');
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// In order to work, the COOKIEFILE/JAR options must be used. Why?
//curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/test_cookiejar');
//curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/test_cookiejar');
$resp = curl_exec($ch);
curl_close($resp);
$cookies = readCookie($resp);
// Even if the login is successful, this fails if and only if no COOKIEFILE/JAR is specified.
// Why?
$ch = curl_init('https://diasp.org/stream');
curl_setopt($ch, CURLOPT_COOKIE, $cookies);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// If I use COOKIEFILE here, the request works. What is this line doing that CURLOPT_COOKIE is not?
//curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/test_cookiejar');
$resp = curl_exec($ch);
curl_close($ch);
var_dump($resp);
SUMMARY
I am making very simple, step-by-step, procedural calls to a web server. These requests are being made one after the other, and the resulting output (of the entire HTTP conversation, including headers), is saved in a variable, which is then read and the values of the cookies are parsed from the Set-Cookie HTTP header lines. However, these values are never the same as the values that libcurl writes to the COOKIEFILE if those lines are uncommented.
What am I doing wrong with CURLOPT_COOKIE or what am I not doing with it that the CURLOPT_COOKIEFILE and CURLOPT_COOKIEJAR options are doing? Is it encoded or decoded in some reversible way? Thanks in advance.
You probably did not notice the difference between CURLOPT_COOKIE and CURLOPT_COOKIELIST/FILE/JAR. The both handle cookies but, CURLOPT_COOKIE does not store the cookies you set this time in the memory, or store them in the cookie file specified by CURLOPT_COOKIEJAR; instread, CURLOPT_COOKIELIST does.
There is a mechanism called cookie engine in libcurl. It is triggered enabled when you set any one of CURLOPT_COOKIELIST/FILE/JAR, libcurl takes care of sending/parsing/reading/storing cookies in all subsequent session.
CURLOPT_COOKIE is just a quick hack way to set a extra cookie for one go.

Using cookie in curl call with PHP

I need to fetch some data from external site. To do this I need to load a site that creates some cookie and gives a simple math calculation to generate new link. This part is easy:
$cr = curl_init($url);
curl_setopt($cr, CURLOPT_RETURNTRANSFER, true);
curl_setopt($cr, CURLOPT_COOKIEJAR, 'cookie.txt');
$html = curl_exec($cr);
curl_close($cr);
After those calls I have cookies stored in cookie.txt:
# Netscape HTTP Cookie File
# http://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
domain FALSE / FALSE 0 PHPSESSID o89t753egbp9pq9084n38eg2m1
Now, the question is: how can I load this cookie to use it in my next call to some other site (in the same domain ofcourse)?
You can use
curl_setopt($cr, CURLOPT_COOKIEFILE, 'cookie.txt');
curl_setopt($cr, CURLOPT_COOKIEJAR, 'cookie.txt');
in both requests.
A cookie is a header, then you can simply use the command setcookie($name,$value), or if you prefer, using the header php call, using Cookie for header name.
Remember, you don't have to send output to the client before the setcookie command.
You have to read file and split it.

PHP How to perform an http request passing cookies and save result to a string

I would like to perform an http request and pass all cookies received by the current script (in particular session identifying cookies) to this request. Then I would like to save the result in a string for further manipulation. What is the best way to do this in PHP ?
cURL ? - it is simple and supprot cookies .
Edit 19.1 - Here is example
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.example.com/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
$output = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
CURLOPT_COOKIEJAR is file where cURL put cookies sent from server and CURLOPT_COOKIEFILE is file with cookies for sending by cURL ( setting it to same one will make it cookies file ).
Another option is manually read cookies from result ( set CURLOPT_HEADER to '1' - it will put result header into $output ) and send cookies via CURLOPT_COOKIE ( set it to list of cookies in format 'foo=bar;bar=foo;' )
Note - libcurl must be enabled in php.ini

curl not sending cookie value

I am tring to read a cookie value which I got after login by sending a POST request.
Then I want to sent that cookie value with another POST request using Curl to another action. But after sending this when I am trying to see all posted header it does display that I have send any cookie value. This value is not available to my posted URL so not able to access the information due to authentication. Please tell me where I have done something wrong:
$URL1 = "http://www.getinf.com/iconf/user?action=buGroup";
$postfields1 = "device=mapp&type=ajax&name1=ra&cc1=91&min1=90name2=imm&cc2=91&min2=97";
// sends a post request
$ch1 = curl_init();
curl_setopt($ch1, CURLOPT_URL,$URL1);
curl_setopt($ch1, CURLOPT_POST, 1);
curl_setopt($ch1, CURLOPT_COOKIE,'JSESSIONID=199FFF6355DEA87F3D72E692E7514AD2');
curl_setopt($ch1, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch1, CURLOPT_HEADER,true);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch1, CURLOPT_POSTFIELDS, $postfields1);
$result = curl_exec($ch1);
print_r(headers_list());// displays all post request data
$ret = ReturnVal($result);
print_r(get_headers($URL1, 1)); //
curl_close ($ch1);
So what is wrong in this code that is preventing JSESSIONID value accessible as a cookie value?
Check the comments (or search "cookie") on this page in the php docs:
Whats not mentioned in the
documentation is that you have to set
CURLOPT_COOKIEJAR to a file for the
CURL handle to actually use cookies,
if it is not set then cookies will not
be parsed.
Try changing CURLOPT_cookie to CURLOPT_COOKIE
CURLOPT_COOKIESESSION is used to start a new Cookie session and ignore all cookies stored.
From PHP.net: Use CURLOPT_COOKIESESSION = TRUE to mark this as a new cookie "session". It will force libcurl to ignore all cookies it is about to load that are "session cookies" from the previous session. By default, libcurl always stores and loads all cookies, independent if they are session cookies or not. Session cookies are cookies without expiry date and they are meant to be alive and existing for this "session" only.
use: curl_setopt($ch, CURLOPT_COOKIESESSION, false);

Categories