Determine whether a cookie was set - php

Is there a straightforward way to test whether a cookie has been set during the current request? I'm writing an extension to existing code, so I can't modify the current code to add something like $_COOKIE['something'] = $someValue;. Unfortunately, only setcookie is called, without the event being logged in any other way. I need to know before the client receives the headers, because I need to set the cookie if the existing code hasn't already done so.

Have you tried using isset?
if( ! isset($_COOKIE['something'])) {
$_COOKIE['something'] == $somevalue;
}

Here's my "brute force" solution for now. I'm hoping to find a better method, though. Note that headers_list() gets the headers that are going to be sent to the browser as part of the response, not the headers that were sent by the browser during the request.
foreach (headers_list() as $header) {
list($k, $v) = explode(': ', $header, 2);
if (strtolower($k) != 'set-cookie') {
continue;
}
$name = explode('=', $v, 2)[0];
if ($name == $cookieName) {
return true;
}
}
return false;

Related

PHP, Cookie theft

I store a basket cookie Id which is really uniq, a long random 20 characters string like that: "7irMz2cvpnXpSCkNkBAT"
It's stored on browser not directly in a single Cookie but in a Json global cookie containing multiple values.
I can see Baskets from an admin part and I have sometimes a Basket from let's say a client from New-Zealand falling into the Basket of a someone in India who created an account!
It's all the time the same user stealing the basket Cookie from someone else and putting in it 20 articles which had not been put originally by the client.
I don't know if it's a bot from India or a real person doing that!
How to prevent cookie theft?
I cannot associate a cookie to an IP, people with smartphones for example change sometimes of IP address.
To recover / create / update the cookie I do like that:
// Recovering the Cookies from the Datas Json Object
if(isset($_COOKIE['Datas'])) {
$cookie = json_decode($_COOKIE['Datas']);
if(is_object($cookie)) {
$expiry = $cookie->expiry;
$diff=$expiry-time();
$cookieDatasExpiresDays = floor($diff/(60*60*24));
foreach($cookie->Data as $key => $value) {
$_COOKIE[$key] = $value;
}
} else {
setcookie('Datas', '', -1, '/');
}
}
/**
* Cookie for basket used for non connected users
*/
if((!isset($_COOKIE['Basket']) || $_COOKIE['Basket'] == NULL) &&
!check_bot()) { //We check also if Cookies are enabled
$updateCookie = 'Basket';
$_COOKIE['Basket'] = get_stringSuffle(20, TRUE);
}
if(isset($_COOKIE['Basket'])) {
$cookiesInfos['Basket'] = $_COOKIE['Basket'];
}
...
if($updateCookie != '' && !check_bot()) { //We check also if Cookies are enabled
// Updating Cookie if needed
$cookiesArray = [];
$cookiesArray['Data'] = [];
foreach($cookiesInfos as $key => $val) {
$cookiesArray['Data'][$key] = $val;
}
setcookie('Datas', '', -1, '/');
setcookie('Datas', json_encode($cookiesArray), $expiry, '/');
}
EDIT
As advised by #nice_dev I added the secure options to my call on setcookie:
setcookie('Datas', json_encode($cookiesArray), $expiry, '/', $_SERVER['HTTP_HOST'], TRUE, TRUE);
Note: That's perfect, this modification on the server didn't made me loose any of my Cookie.

Detecting a cookie set using setcookie without a page reload

I am maintaining the code for an eCommerce website, they use a highly modified version of osCommerce v2.2 RC2. Was noticing an issue where the session isn't started for a new user until they visit the 2nd page of the site.
Looking at the code, before starting the session, it tries to set a cookie. If it detects the cookie it starts the session. Something along this line:
setcookie('cookie_test', 'please_accept_for_session', time()+60*60*24*30, $cookie_path, $cookie_domain);
if (isset($_COOKIE['cookie_test'])) {
session_start();
...
I found an article here that talks about a situation like this, it states:
The first time you only tell the browser to set the cookie, at the time, there is no cookie data in the request header (which could get from $_COOKIE).
Which explains why it takes two page loads for the session to be started. One to set the cookie and one to get notification from the browser that the cookie is set.
My question is, is there anyway around having to go through two page loads to detect the cookie was successfully set on the users browser?
I found this question that didn't really answer my question completely. The highest voted solution was:
setcookie('uname', $uname, time()+60*30);
$_COOKIE['uname'] = $uname;
Which may make it "work" but it doesn't truely tell me that the script was able to set a cookie successfully.
I also found this question, that suggested accessing the headers_list to find the cookie information like so:
function getcookie($name) {
$cookies = [];
$headers = headers_list();
// see http://tools.ietf.org/html/rfc6265#section-4.1.1
foreach($headers as $header) {
if (strpos($header, 'Set-Cookie: ') === 0) {
$value = str_replace('&', urlencode('&'), substr($header, 12));
parse_str(current(explode(';', $value, 1)), $pair);
$cookies = array_merge_recursive($cookies, $pair);
}
}
return $cookies[$name];
}
// [...]
setcookie('uname', $uname, time() + 60 * 30);
echo "Cookie value: " . getcookie('uname');
Which, again, doesn't seem to be verifying that the cookie was set successfully. All this appears to do is search the headers being sent to the browser for the cookie value.
The only solution I can think of is to redirect on the first visit after setting the cookie. Is there any other way?
Here is the answer:
<?php
function set_cookie($name, $value) {
if (!isset($_COOKIE[$name]) || ($_COOKIE[$name] != $value)) {
$_COOKIE[$name] = $value;
}
setcookie($name, $value, strtotime('+1 week'), '/');
}
// Usage:
set_cookie('username', 'ABC'); //Modify the value to see the change
echo $_COOKIE['username'];

Clear PHP Cookies array

I know how to set PHP cookies in an array but can I clear it without a loop?
For example I'm setting these four cookies
// set the cookies
setcookie("cookie[four]", "cookiefour");
setcookie("cookie[three]", "cookiethree");
setcookie("cookie[two]", "cookietwo");
setcookie("cookie[one]", "cookieone");
// after the page reloads, print them out
if (isset($_COOKIE['cookie'])) {
foreach ($_COOKIE['cookie'] as $name => $value) {
$name = htmlspecialchars($name);
$value = htmlspecialchars($value);
echo "$name : $value <br />\n";
}
}
OUTPUT:
four : cookiefour
three : cookiethree
two : cookietwo
one : cookieone
To clear the cookies, i use the following loop
if (isset($_COOKIE['cookie'])) {
foreach ($_COOKIE['cookie'] as $name => $value) {
setcookie ("cookie[".$name."]", "", time() - 1);
}
}
Are there any way I could clear the cookies without a loop? Thanks in advance
No, you pretty much need to loop through existing cookies as the way to delete/expire a cookie, as you have in your code via setcookie, is one cookie at a time.
Could try
if (isset($_COOKIE['cookie'])) {
setcookie ("cookie", array());
}
or even
if (isset($_COOKIE['cookie'])) {
setcookie ("cookie", array('one'=>'','two'=>'','three'=>'','four'=>'',));
}
if you need the indexes

Infinite loop php redirect based on cookie

I'm currenting busy coding a registration page. The page has three steps and every step has its own cookie value. What I'd like to do is checking for the cookies value and transfer the user to the correct page upon visiting the website
Example:
if the value of $_COOKIE['step'] is 'step_two' it should redirect to: www.domain.com/register.php?step=your_details. If the cookie's not set, it should not redirect and stay on the register.php page.
The redirecting is working 'fine', but it gets into an infinite loop. I really cant think clear anymore as I've been awake for almost 24h now. Therefor I would appreciate it if anyone could push me into the right directions.
Piece of code:
$cookie_value = 'step_2';
setcookie("step",$cookie_value, time()+3600*24);
$cookie_not_set = true;
$cookie_step_two = false;
if (isset($_COOKIE['step'])) {
if ($_COOKIE['step'] == 'step_2') {
$cookie_not_set = false;
$cookie_step_two = true;
header('Location: ?step=your_details');
exit();
}
} else {
$cookie_not_set = true;
}
Thank you.
Nowhere are you actually setting your cookie value, so it won't change. That's why you have an infinite loop.
$_GET and $_COOKIE have nothing to do with each other. It looks like you want:
if ($_GET['step'] === 'your_details')`
...which would be better than using a cookie anyway.
You are going to constantly enter your if condition as there is no other manipulations going on to your cookie data.
if your cookie is set to "step_2" you will enter the loop. No changes are in place, so on the refresh to the page. You will re-enter the step_2 condition and be into a redirect.
I'm also assuming that you understand that your $_GET & $_COOKIE requests are completely different. If not, see #Brads answer
A solution to stop this infinite loop would be:
if (isset($_COOKIE['step'])) {
if ($_COOKIE['step'] == 'step_2') {
$cookie_not_set = false;
$cookie_step_two = true;
$_COOKIE['step'] = 'step_3';
header('Location: ?step=your_details');
exit();
}
But also take note, your true/false validations/changes are local changes and will not be absolute on page refresh
I believe your issue is the redirect is not changing your cookie, so you need to look at the GET var you a re passing if the cookie is set to step_2 thus;
$cookie_not_set = true;
$cookie_step_two = false;
if (isset($_COOKIE['step'])) {
if ($_COOKIE['step'] == 'step_2') {
if( !empty($_GET['step']) && $_GET['step'] == 'your_details' )
{
... you have redirected and now can continue ...
}
else
{
// redirect and set the get var to signal to this script.
$cookie_not_set = false;
$cookie_step_two = true;
header('Location: ?step=your_details');
exit();
}
}
} else {
$cookie_not_set = true;
}

Find real link form redirect 301,302

I see some service sort link(tinyurl,goo.gl,bit.ly ...)
I use php function get_headers do get header and find real link from sort links
this is mycode
function get_furl($url)
{
$furl = false;
// First check response headers
$headers = get_headers($url);
// Test for 301 or 302
if(preg_match('/^HTTP\/\d\.\d\s+(301|302)/',$headers[0]))
{
foreach($headers as $value)
{
if(substr(strtolower($value), 0, 9) == "location:")
{
$furl = trim(substr($value, 9, strlen($value)));
}
}
}
// Set final URL
$furl = ($furl) ? $furl : $url;
return $furl;
}
But some time ,Script was got header time out.Help me code get real link faster.
Geat thanks
You can't do it any faster. Timeouts happen sometimes, and you need to take care of that.
By the way, the strlen() is unnecessary.

Categories