Cookies PHP CURL store in clients side - php

I have proxy, and i want to store cookies in clients cookies but when i using the following code its dont works, they dont stores in browser, and if they store somewhere in server anyway they dont works.
$responseInfo = curl_getinfo($ch);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
curl_close($ch);
$responseHeaders = substr($response, 0, $headerSize);
preg_match_all("/Set-Cookie: (.*?)=(.*?);/i",$responseHeaders,$cookies);
array_shift($cookies); //removes first
$i = 0;
foreach($cookies[0] as $name) {
$curl_cookies .= $name."=".$cookies[1][$i].";";
// if(!isset($_COOKIE[$name])) {
// setcookie( $name, $cookies[1][$i], time()+(60*60*24*30) );
// }
// elseif($_COOKIE[$name] != $cookies[1][$i]) {
// setcookie( $name, $cookies[1][$i], time()+(60*60*24*30) );
// }
$i++;
}
curl_setopt($ch, CURLOPT_COOKIE, $curl_cookies);
When i using commented code, and remove
$curl_cookies .= $name."=".$cookies[1][$i].";";
and
curl_setopt($ch, CURLOPT_COOKIE, $curl_cookies);
Cookies are stores in the clients cookies but dont works from websites too.
But when i replace that code to :
curl_setopt($ch, CURLOPT_COOKIEFILE, "cookie.txt");
curl_setopt($ch, CURLOPT_COOKIEJAR, "cookie.txt");
All works fine, but cookies are the same for any user, ofc i can use something like
curl_setopt($ch, CURLOPT_COOKIEFILE, $ip."cookie.txt");
But that way is makes large count of .txt files for each ip which visit my proxy.
Any idea how to storage cookies into clients cookies and make them work?

Related

how do php scripts for data mining from web pages work?

[Edited for better explanation and code included]
Hi! I have a php script on my web server that logs in to my heat pump web interface nibeuplink.com and gets all my temperature readings and so forth and returns them in a json-format.
freeboard.io is a free service for visualizing data, so I'm making a freeboard.io for my heat pump values. in freeboard.io I can add any json data as a data source, so I have added the link to my php-script. It fetches the data once but it seems there is some kind of cached values that it uses after that so they are not updated with new values from the script. freeboard.io uses a get-function to get the url. If i use a normal web browser to run the php script and refresh it, the values are updated - and also immediately updated in freeboard.io. Freeboard.io has a setting to automatically update the data source every 5 seconds.
It seems that there is something that triggers the script correctly when it is fetched from my web browser, but not when it is fetched from freeboard.io that uses a get function every 5 seconds to get new data.
in freeboard I can add headers to the get request, is there some header that would help me here to discard any cached data?
I hope that explains my problem better.
Is there anything i can add to my code in the beginning to always force an override of any cached data?
<?php
/*
* read nibe heatpump values from nibeuplink status web page and return them in json format.
* based on: https://www.symcon.de/forum/threads/25663-Heizung-Nibe-F750-Nibe-Uplink-auslesen-auswerten
* to get the code which is required as parameter, log into nibe uplink, open status page of your heatpump, and check url:
* https://www.nibeuplink.com/System/<code>/Status/Overview
*
* usage: nibe.php?email=<email>&password=<password>&code=<code>
*/
// to add additional debug output to the resulting page:
$debug = false;
date_default_timezone_set('Europe/Helsinki');
$date = time();
// Create temp file to store cookies
$ckfile = tempnam ("/tmp", "CURLCOOKIE");
// URL to login page
$url = "https://www.nibeuplink.com/LogIn";
// Get Login page and its cookies and save cookies in the temp file
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Accepts all CAs
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile); // Stores cookies in the temp file
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
// Now you have the cookie, you can POST login values
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 2);
curl_setopt($ch, CURLOPT_POSTFIELDS, "Email=".$_GET['email']."&Password=".$_GET['password']);
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile); // Uses cookies from the temp file
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // Tells cURL to follow redirects
$output = curl_exec($ch);
curl_setopt($ch, CURLOPT_URL, "https://www.nibeuplink.com/System/".$_GET['code']."/Status/ServiceInfo");
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile);
curl_setopt($ch, CURLOPT_POST, 0);
$result = curl_exec($ch);
$pattern = '/<h3>(.*?)<\/h3>\s*<table[^>]*>.+?<tbody>(.+?)<\/tbody>\s*<\/table>/s';
if ($debug) echo "pattern: <xmp>".$pattern."</xmp><br>";
$pattern2 = '/<tr>\s*<td>(.+?)<span[^>]*>[^<]*<\/span>\s*<\/td>\s*<td>\s*<span[^>]*>([^<]*)<\/span>\s*<\/td>\s*<\/tr>/s';
if ($debug) echo "pattern2: <xmp>".$pattern2."</xmp><br>";
preg_match_all($pattern, $result, $matches);
// build json format from matches
echo '{';
$first = true;
foreach ($matches[1] as $i => $title) {
echo ($first ? '"' : ',"').trim($title).'":{';
$content = $matches[2][$i];
preg_match_all($pattern2, $content, $values);
$nestedFirst = true;
foreach ($values[1] as $j => $field) {
echo ($nestedFirst ? '"' : ',"').trim($field).'":"'.$values[2][$j].'"';
$nestedFirst = false;
}
echo "}";
$first = false;
}
echo ",\"time\":{\"Last fetch\":\"$date\"}";
echo "}";
if ($debug) {
echo "<pre><xmp>";
echo print_r($matches);
echo "<br><br>";
echo $result;
echo "</xmp></pre>";
}
?>
You can make an ajax call to php script to refresh the part of webpage. I don't understand what do you mean by io i.e. are you talking about fetching the data from database and if any changes occurred in database then only newly added records must be fetched. If you mean it in that sense then you can use cookie to track any new records added into database and only if it finds new records it can make ajax call to php script to run your algorithm on fetched total dataset.

Auth lost when doing a curl request to my laravel server

I'm trying to make a curl request to my laravel server, in that request I have to check whether the user of my laravel application is logged in or not. I use this code:
$transferAmount = 200;
//set POST variables
$url = URL::route('post-spend-partner');
$fields = array(
'transferAmount' => urlencode($transferAmount),
'cancelUrl' => urlencode(URL::route('get-return-page-example')),
'returnUrl' => urlencode(URL::route('get-return-page-example')),
);
// New Connection
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($ch, CURLOPT_COOKIESESSION, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
curl_setopt($ch, CURLOPT_URL, $url);
curl_exec($ch);
curl_close($ch);
In the requested url I'm just checking if I'm logged in or not, but it always returns false:
public function postSpendPartner() {
echo "Authenticated? " . (Auth::check() ? 'Yes' : 'No');
}
I know for sure that I'm logged in, if I try the exact same thing with Ajax it completely works!
Does anyone know what I could try, to solve this problem?
Best regards!
Fabrice
Some facts: HTTP is stateless. Session IDs need to be passed to the server in order to continue the session. Session IDs are (most of the time) stored in cookies. Cookies are included in the request.
Using a cookiejar could indeed be one possible solution. The fact that it works using Ajax, and not by re-submitting the request from your server might be because of the session-verification mechanism on the server: Some session implementations lock session IDs to the initial IP address. If the contents of your cookiejar file check out, that might be the culprit.
That aside: re-submitting the request via Curl from your server is a severe codesmell to me. A proper solution would to implement something such as OAuth.
Try sending your cookies as a header with your curl request.
// ...
$cookie_header = "Cookie:";
$headers = [];
foreach($_COOKIE as $key => $val) {
// Do sanitize cookie values
$cookie_header .= " ".$key."=".$value.";";
}
$headers[] = $cookie_header;
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
// ...
You could filter out unnecessary cookie values from $cookie_header.

Cookie functionality on php cross domain proxy using cURL?

first time asker, but many times you helped me back in the day. Great job! I ask this because I'm struggling here with and issue I'm unable to solve, and as my PHP (and cURL) knowledge is so scarce, I'm lost.
The Background
I'm developing a Javascript app, that needs to connect to several different servers and make XMLRPC calls to them. The app is working perfectly running it locally (disabling cross-domain security), but to make it run online I knew I had to use a cross-domain proxy, so after several days of searching and investigating, I didn't found one that could make the work, so I managed to make one myself (not without blood and sweat). Know what? It (almost) works!!!
This is my proxy.php:
<?
function readHeader($ch, $header) {
//extracting data to send it to the client
$headers = explode("\n", $header);
foreach ($headers as $item) {
// $string= str_replace($delimiter, $mainDelim, $string);
if (strpos($item, 'Set-Cookie:') !== false) {
$cookie = trim(substr($item,strlen('Set-Cookie:')));
header('X-Set-Cookie:' . $cookie);
} else {
header($item);
}
}
return strlen($header);
}
$allowed_domains = array('domain1.com', 'domain2.com');
header('Content-Type: text/html; charset=iso-8859-1');
$REFERRER = $_SERVER['HTTP_REFERER'];
if ($REFERRER == '') {
// What do you do here?
exit(header('Location: index.html'));
}
$domain = substr($REFERRER, strpos($REFERRER, '://') + 3);
$domain = substr($domain, 0, strpos($domain, '/'));
if (!in_array($domain, $allowed_domains)) {
exit(header('Location: index.html'));
}
$XMLRPC_SERVICE = $_SERVER['HTTP_X_PROXY_URL'];
$xml = $HTTP_RAW_POST_DATA;
$header[] = "Content-type: text/xml; charset=utf-8";
$header[] = "Connection: close";
$header[] = "Accept: text/xml";
if ($_SERVER['HTTP_X_SET_COOKIE'])
$cookie = $_SERVER['HTTP_X_SET_COOKIE'];
if ($_SERVER['HTTP_X_PROXY_URL'] === "other-domain.com")
$header[] = "x-custom-header: value";
$ch = curl_init($XMLRPC_SERVICE);
//URL to post to
curl_setopt($ch, CURLOPT_URL, $XMLRPC_SERVICE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
if ($cookie)
curl_setopt($ch, CURLOPT_COOKIE, $cookie);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'readHeader');
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo curl_error($ch);
} else {
curl_close($ch);
echo $response;
}
?>
The Issue
As I've said, I got it working partially. In fact, it works for most of the usual XMLRPC needs.
It gets the remote server address from the HTTP_X_PROXY_URL header of the request, and using cURL makes the call and returns the values to the javascript client without issues.
The problem comes when I need to get/send a session cookie (probably when getting it, because the cookie value is pretty different when I make calls directly from the app locally). In any case, I can't get the cookie stuff to work. As you see, I'm surrounding the Set-Cookie browser protection on AJAX calls with my own X-Set-Cookie header, that the proxy gets to use or translates accordingly, but the issue with cookies is here, and I can't use cookies, that are critical for app functionality.

Unable to exchange Session Data in CURL

I call invoke.php using CURL from curl.php from my localhost. In invoke.php i store some data in session. But when i try to access those session data from curl.php, don't get those session data. How i get those values?
Content of curl.php
`include_once ('session.php');
$handles = array();
$urlArray = array('http://localhost/invoke.php' );
foreach($urlArray as $url){
// create a new single curl handle
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
// add this handle to the multi handle
curl_multi_add_handle($mh,$ch);
// put the handles in an array to loop this later on
$handles[] = $ch;
}
// execute the multi handle
$running=null;
do {
curl_multi_exec($mh,$running);
// added a usleep for 0.25 seconds to reduce load
usleep (250000);
} while ($running > 0);
// get the content of the urls (if there is any)
for($i=0;$i
{
// get the content of the handle
// $output.= curl_multi_getcontent($handles[$i]);
// remove the handle from the multi handle
curl_multi_remove_handle($mh,$handles[$i]);
}
echo SessionHandler :: getData('DATA');
`
Content of invoke.php
include_once ('session.php');
echo SessionHandler :: setData('DATA', 'HELLO WORLD');
There are two possible issues:
You can't be sure that both scripts will access same session (have same session id), actually I can bet they have separate sessions. Of course, you could enforce that by sending the session id from invoke.php to curl.php by adding an extra parameter tot the URL and then use that parameter to force the session id in curl.php
Second possible issue is that the session variables are read on session_start (that's when the $_SESSION is populated), but you modify the session content after you start the session (in session.php, I assume), that's why any changes (even if the conditions on 1. will be met), will not reflect into already opened session in invoke.php. I think you should force session to close and restart it.
I had the same issue. This is how I resolved it:
function getContent($url){
$cookiesStr = '';
foreach($_COOKIE as $k => $v){
$cookiesStr.= $k . '=' . $v . '; ';
}#end COOKIE
$cookiesStr = rtrim($cookiesStr, ' ');
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt ($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_COOKIE, $cookiesStr);
ob_start();
curl_exec ($ch);
curl_close ($ch);
$string = ob_get_contents();
ob_end_clean();
return $string;
}#end getContent
You have to have a tmp cookie jar or it will produce an infinite loop. You have to send cookies or you will not get a result.
I able to solve this problem. I set curl_
setopt($ch, CURLOPT_COOKIE,session_name().'='.session_id());
to use same session id and use php's session_write_close() function to write session data.

How to let Curl use same cookie as the browser from PHP

I have a PHP script that does an HTTP request on behalf of the browser and the outputs the response to the browser. Problem is when I click the links from the browser on this page it complains about cookie variables. I'm assuming it needs the browsers cookie(s) for the site.
how can I intercept and forward it to the remote site?
This is how I forward all browser cookies to curl and also return all cookies for the curl request back to the browser. For this I needed to solve some problems like getting cookies from curl, parsing http header, sending multiple cookies and session locking:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// get http header for cookies
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
// forward current cookies to curl
$cookies = array();
foreach ($_COOKIE as $key => $value)
{
if ($key != 'Array')
{
$cookies[] = $key . '=' . $value;
}
}
curl_setopt( $ch, CURLOPT_COOKIE, implode(';', $cookies) );
// Stop session so curl can use the same session without conflicts
session_write_close();
$response = curl_exec($ch);
curl_close($ch);
// Session restart
session_start();
// Seperate header and body
list($header, $body) = explode("\r\n\r\n", $response, 2);
// extract cookies form curl and forward them to browser
preg_match_all('/^(Set-Cookie:\s*[^\n]*)$/mi', $header, $cookies);
foreach($cookies[0] AS $cookie)
{
header($cookie, false);
}
echo $body;
In fact, it is possible. You just have to take the cookie ofthe browser and pass it as a parameter to curl to mimik the browser.
It's like a session jacking...
Here is a sample code:
// Init curl connection
$curl = curl_init('http://otherserver.com/');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
// You can add your GET or POST param
// Retrieving session ID
$strCookie = 'PHPSESSID=' . $_COOKIE['PHPSESSID'] . '; path=/';
// We pass the sessionid of the browser within the curl request
curl_setopt( $curl, CURLOPT_COOKIE, $strCookie );
// We receive the answer as if we were the browser
$curl_response = curl_exec($curl);
It works very well if your purpose is to call another website, but this will fail if you call your web server (the same that is launching the curl command). It's because your session file is still open/locked by this script so the URL you are calling can't access it.
If you want to bypass that restriction (call a page on the same server), you have to close the session file with this code before you execute the curl :
$curl = curl_init('http://sameserver.com/');
//...
session_write_close();
$curl_response = curl_exec($curl);
Hope this will help someone :)
From curl_setopt:
By default, libcurl always stores and loads all cookies, independent if they are session cookies or not.
However you may need to set cookies directly, which can be done using:
curl_setopt($ch, CURLOPT_COOKIE, 'foo=bar');
Which is the same as the Set-Cookie HTTP header. Check you're not using curl_setopt($ch, CURLOPT_COOKIESESSION, true) as this will make libcurl ignore some cookies.
You can't.
If you curl the request, you will need to parse the output, and replace all links so they go thru your server.
www.yourdomain.com/f?=www.someotherdomain.com/realpage
The only way this would work is if you use persistent cookies in your curl request. CURL can keep cookies itself. Assign a session ID to the cookie file (in curl) so subsequent requests get the same cookies. When a user clicks a link, you will need to curl the request again.
It is a security issue to allow site1 to set cookies for site2. Imagine if you could set cookies in the browser for paypal and trick the user into thinking they had logged int or some other malicious action.
The Cookie is usually sent with the HTTP request header like
Host stackoverflow.com
User-Agent ...
Accept-Language en-us,en;q=0.5
Referer http://stackoverflow.com/unanswered
Cookie bla=blabla;blubb=blu
So I guess that just have to modify the cookie part in your header.
PiTheNumber's answer was great but I ran into some issues with it that caused it to still print the headers to the page. So I adjusted it to use the more reliable curl_getinfo function. This version also follows redirects.
public function get_page_content( $url ) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_HEADER, 1);
// Forward current cookies to curl
$cookies = array();
foreach ($_COOKIE as $key => $value) {
if ($key != 'Array') {
$cookies[] = $key . '=' . $value;
}
}
curl_setopt( $ch, CURLOPT_COOKIE, implode(';', $cookies) );
$destination = $url;
while ($destination) {
session_write_close();
curl_setopt($ch, CURLOPT_URL, $destination);
$response = curl_exec($ch);
$curl_info = curl_getinfo($ch);
$destination = $curl_info["redirect_url"];
session_start();
}
curl_close($ch);
$headers = substr($response, 0, $curl_info["header_size"]);
$body = substr($response, $curl_info["header_size"]);
// Extract cookies from curl and forward them to browser
preg_match_all('/^(Set-Cookie:\s*[^\n]*)$/mi', $headers, $cookies);
foreach($cookies[0] AS $cookie) {
header($cookie, false);
}
return $body;
}

Categories