Session Start Failure - php

This is not your average session failed to start question, there is no whitespace, i have not called it in another file etc.
Im currently working on an application as I have started to build my session library, now when I call session_start I get the following error:
A session had already been started - ignoring session_start()
For those who wish to see the source: https://github.com/AdminSpot/ASFramework/blob/master/system/libraries/session.php
This usually means that the session.autostart directive is set to 1, but that's the thing.. it's not, it's set to 0 and I have verified this by doing the following:
Search my entire system for php.ini* files, checked them
Executed the following command php --ini amd validated the ini files
executed the following command php -i | grep session.auto_start. which responded with session.auto_start => Off => Off
Checked the PHPInfo page, see image below
Checked the php.ini files for cgi
There is no htaccess files on nginx
grep -lir "session_start" * only shows my library file
Restarting FastCGI, Nginx and the entire server
I have created a basic test script to test where i have just called session start on it's own.
The phpinfo() call stats the active php.ini is /etc/php5/cgi/php.ini so after running cat /etc/php5/cgi/php.ini | grep session.auto_start I get session.auto_start = 0, so it disabled, Could it be NGinx ?
Has anyone got any idea what's going on, some server information below:
PHP: PHP 5.3.5-1ubuntu7.2 with Suhosin-Patch
MySQL: Ver 14.14 Distrib 5.1.54, for debian-linux-gnu (i686) using readline 6.2
Nginx: Version: nginx/0.8.54
PHPInfo screen:

My first guess would be that you have an auto-prepend file or an .htaccess which is modifying the settings in the meanwhile.
You can use ini_get to retrieve the value of session.auto_start and auto_prepend_file to confirm. phpinfo() should work too.
Edit
Could it be that your session library is being instantiated twice? Since return $this->session_started is an instance variable, that could cause issues. What happens if you set that to a class-level variable?
Side note:
You also have this return $this->session_started = true; at the end of the start() method. It shouldn't matter, but it looks funny.

How about .htaccess containing a php_value session.auto_start 1? PHP on the command line would totally ignore settings overrides in .htaccess files. Remember that commandline PHP and web-based PHP have completely different .ini files in most standard configurations, so checking via command line is a waste of time.
I'd suggest having your script do a phpinfo() immediately before one of your session_start calls and check what the effective settings are there.

And anyway you can just verify if a session has already started or not.
if (!isset($_SESSION)) {
session_start();
}

http://php.net/manual/en/function.session-start.php#90007
Check and see if you are being passed a session cookie. May help you narrow it down.

Related

PHP sessions: $_SESSION is empty running locally on Mac

I know there are similar other questions here, but none of them solved my problem.
The problem: I'm setting data into $_SESSION, but in upcoming calls it is appearing as empty.
What I did to try solving it?
Make sure to run an up-to-date version of PHP
Make sure to know which php.ini is used
Log status of $_SESSION before and after setting it
Set various variables as suggested in other questions and forums
Here below I provide all the info I could supply, and hoping somebody will be able to suggest a solution!
I have installed PHP on my Mac using brew install php
I am running it locally for software development using this command:
php -S localhost:8099 -d display_errors=on -t .
[Tue Nov 17 23:12:55 2020] PHP 7.4.11 Development Server (http://localhost:8099) started
I'm calling session_start(); at the beginning of my script.
I am setting values into $_SESSION, but it is always empty when I am testing it in the following calls:
$ses = json_encode($_SESSION);
site_log("before: {$ses}");
session_regenerate_id();
$_SESSION["upath"] = 'XXXXXX';
$ses = json_encode($_SESSION);
site_log("after: {$ses}");
The result is always the same (while I'm expecting to see it on first call but not for the following calls):
20201118_040124_484 before: []
20201118_040124_485 after: {"upath":"XXXXXX"}
I was trying to follow many ideas from web forums:
Verify which is the INI file:
php -i | grep 'Configuration File'
>Configuration File (php.ini) Path => /usr/local/etc/php/7.4
>Loaded Configuration File => /usr/local/etc/php/7.4/php.ini
I was setting various INI file variables:
session.save_path = "/Users/myuser/Prog/MyApp/sessions"
+
chmod 777 /Users/myuser/Prog/MyApp/sessions
+
session.use_cookies = 1
+
session.cookie_secure = 0
But the result is still the same. Any idea please?
The following link points to the result of calling phpinfo(): link
So finally I have found a solution.
It is based on information provided here: Session cookie not being set
As #deceze was commenting correctly to my question, the first steps to debug such problem are these:
Check whether session files are created in the save_path folder (in my case: yes)
Use the dev-tools of the browser to see if cookies are set for the site (in my case: no)
So the actual problem is: why cookies are not set?
The solution:
Add an entry to alias 127.0.0.1 as a 'dot com' name. This is what I did:
# for Mac! see linked answer for other platforms
sudo vi /private/etc/hosts
# add this line:
127.0.0.1 mylocal.com
Activate the local php server for this domain (from the site root folder):
php -S mylocal.com:8099 -d display_errors=on -t .
Load the site from the php server. I'm using Brackets, and I had to open the menu: File -> Project Settings and set the live preview base URL to be:
http://mylocal.com:8099/
Some variables in the INI file might need to be set too, as already detailed in the question above
Hoping this info will help to others!

php.ini warning page has more than 1000 fields

After reaching so many entries PhpMyAdmin started showing this warning:
Warning: a form on this page has more than 1000 fields. On submission, >some of the fields might be ignored, due to PHP's max_input_vars >configuration.
I have tried to change out the field from 1000 to 10000, then restarted php.ini.
[ ok ] Restarting php7.0-fpm (via systemctl): php7.0-fpm.service.
/etc/init.d/php7.0-fpm restart
Nothing seems to work so I can export mysql database. Please help me get this correct so I can get this database exported. Many thanks.
Solution Found.
First of, be sure that you are editing the right php.ini file. To do that you can check what it is with phpinfo().
Then restart php to reload php.ini, depending on how you installed it, it could be done like that :
brew services restart php72
Restart apache as well to be sure :
sudo apachectl -k restart
Then put the following statement in a test.php file :
echo ini_get('max_input_vars'); and check it.
At this point you will see it is correctly updated.
If you still have phpmyadmin showing error after that, you should then hard refresh your phpmyadmin page : it can be done with CMD+SHIFT+R on a Mac.
The reason for this is that phpmyadmin's local javascript file is gettting passed the value of max_input_vars from php and is responsible for deciding to display the error or not. So if the javascript local file isn't updated for caching reasons for example, then you just have to refresh it and problem gone : )

Why is putenv() needed on an already defined environment variable?

When php is used as an apache module, an environment variable coming from an apache SetEnv directive is available to php's getenv(), but it does not appear to be available to C extensions through stdlib's getenv(). At least it happens with the pgsql module.
If the variable is reinstantiated with the php code:
putenv("varname=".getenv("varname"));
then it becomes available to the extension's code.
The question: why is that reinstantiation necessary? How is the core php environment distinct from the "standard" (stdlib) environment?
This occurs with: PHP Version 5.3.10-1ubuntu3.17 in Ubuntu 12.04, as an apache module. When run from the command line, the above workaround is not necessary.
From this other question: Using .pgpass from Apache libphp5.so it appears that this workaround is also necessary for php-5.4 under FreeBSD so it's not just Ubuntu or php-5.3.
It doesn't depend on variables_order having E in it. I've tried both EGPCS and GPCS, and $_ENV is not populated when E is not there, as expected, but that doesn't change the result of getenv(), as documented, or apparently the result of stdlib's getenv() from inside extensions.
Demo of the problem with the pgsql module. It's built on top of the libpq shared library written in C, which calls getenv() on a handful of optional PG* environment variables.
In apache configuration file, under a <VirtualHost>, I'm setting this to make connection attempts fail:
SetEnv PGHOST doesnotexist
and not specifying a host in the pg_connect call, so PGHOST must be taken when present.
First try:
$v=getenv("PGHOST");
echo "PGHOST=$v\n";
$cnx=pg_connect("user=daniel");
if ($cnx) {
echo "Connection is successful.";
}
Result:
PGHOST=doesnotexist
Connection is successful.
So PGHOST is getting ignored, despite being in the environment.
Second try, now putting again PGHOST into the environment even though it's already there:
$v=getenv("PGHOST");
echo "PGHOST=$v\n";
putenv("PGHOST=".getenv("PGHOST"));
$cnx=pg_connect("user=daniel");
if ($cnx) {
echo "Connection is successful.";
}
Result (failure to connect to the specified host, as expected):
PGHOST=doesnotexist
Warning: pg_connect(): Unable to connect to PostgreSQL server:
could not translate host name "doesnotexist" to address:
Name or service not known in /var/www/test/pgtest2.php on line 8
The reason is this:
The environment values you get from getenv()[PHP] (the php function) are different than the environment you query with getenv()[C] (the C lib function). What getenv()[PHP] does, is checking with the registered sapi for a match (http://lxr.php.net/xref/PHP_5_6/ext/standard/basic_functions.c#3999).
The apache2 sapi does this through its own environment context (http://lxr.php.net/xref/PHP_5_6/sapi/apache2handler/sapi_apache2.c#253), not the standard OS environment from the apache process itself.
ONLY when there is no match found, it will check at the environment of the actual process. So this is why getenv()[PHP] returns a value, but getenv()[C] does not.
Now, the "hack" is a simple one as well: putenv()[PHP], stores the given key/value in the environment of the running process, which is why it can be found later on by getenv()[c].

Temporarily disable cURL for testing purposes

I am writing a class that detects whether cURL is available, does one thing if it is, and another if it isn't. I therefore need to know how to disable cURL temporarily to test this class. I do not want to change the PHP INI file. Any ideas much appreciated.
Just wondering, Im writing an alternative for if cURL is unavailble, how likely is this? Am I wasting my time. Is cURL usually available?
Curl is enabled / disabled in your php.ini. You can't enable and disable it any other way.
Open php.ini find the below and put a semi colon before it to comment it out:
extension=php_curl.dll
AFAIK there is no way to do this at run time, because modules are loaded during PHP startup, before any of you code is executed. The only way to do it is by disabling (or rather, not enabling) an extension in php.ini. You probably can't even do that with cURL, as it will probably be compiled in, not dynamically loaded.
Having said that - why not just change the check to test your "if not available" code - presumably you have a block something like this:
if (curl_exists()) { //obviously there is no such function, but you must have some condition that determines this
// Do stuff using curl
} else {
// Do something horrible
}
well, just change it to this temporarily:
if (!curl_exists()) {
// etc etc
I think the best option is to change your detection script to allow disabling it with a manual configuration.
You cannot disable function on the fly. You need to change php.ini for that.
http://www.php.net/manual/en/function.dl.php
dl — Loads a PHP extension at runtime
bool dl ( string $library )
Loads the PHP extension given by the parameter library.
Use extension_loaded() to test whether a given extension is already available or not. This works on both built-in extensions and dynamically loaded ones (either through php.ini or dl()).
Warning:
This function has been removed from some SAPI's in PHP 5.3.
<?php
// Example loading an extension based on OS
if (!extension_loaded('sqlite')) {
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
dl('php_sqlite.dll');
} else {
dl('sqlite.so');
}
}
//this deals with sqlite but would be easy to figure out how to use it for cURL :)
?>
So you can comment out the loading of cURL extension in php.ini and then "dynamically load" it when needed.
HTH
probably the easiest way is by open file curl.ini, Im use ubuntu 12.04 and file located at
/etc/php5/apache2/conf.d/curl.ini
leave a comment by adding semicolon before extension=curl.so
You can see the location of curl.ini through phpinfo ();
dont forget to restart the Apache
sudo service apache2 restart
Curl is available as long its extension is loaded (which is mostly by default).
You can check what curl extension provides by the following command:
php --re curl
which gives you list of functions, classes and its methods.
To temporary disable curl extension, you can run PHP with -n to simply ignore your php.ini, for example:
$ php -n -r "print_r(curl_version());"
Fatal error: Call to undefined function curl_version() in Command line code on line 1
Here is working example:
$ php -r "print_r(curl_version());"
Array
(
[version_number] => 463623
...

How to troubleshoot PHP session file empty issue?

I have a very simple test page for PHP session.
<?php
session_start();
if (isset($_SESSIONS['views']))
{
$_SESSIONS['views'] = $_SESSIONS['pv'] + 1;
}
else
{
$_SESSIONS['views'] = 0;
}
var_dump($_SESSIONS);
?>
After refreshing the page, it always show
array
'views' => int 0
The environment is XAMPP 1.7.3. I checked phpInfo(). The session is enabled.
Session Support enabled
Registered save handlers files user sqlite
Registered serializer handlers php php_binary wddx
Directive Local Value Master Value
session.auto_start Off Off
session.bug_compat_42 On On
When the page is accessed, there is session file sess_lnrk7ttpai8187v9q6iok74p20 created in my "D:\xampp\tmp" folder. But the content is empty.
With Firebug, I can see cookies about the session.
Cookie PHPSESSID=lnrk7ttpai8187v9q6iok74p20
It seems session data is not flushed to files.
Is there any way or direction to trouble shoot this issue?
Thanks.
BTW, it is $_SESSION not $_SESSIONS.
Hence why it isn't saving the data.
The variable you need to set is called $_SESSION not $_SESSIONS
Heres what I did ...
Install sqlite for php if older than php5 (installed and enabled by default since php5).
In your php.ini (for the location see phpinfo() or run>php -i) change the line ..
session.save_handler = files
to
session.save_handler = sqlite
Then in the same file (php.ini) make sure NOTICES are turned on
error_reporting = E_ALL
restart apache if you changed php.ini
/etc/init.d/apache2 restart
Now you will be getting a sensible error message most likely revealing you dont have correct permissions to your session.save_path so ...
Find out your web services user and group unless known.
There are several ways to do so but I placed this line temporarily in my php code ...
print_r(posix_getpwuid(posix_getuid()));
And I found that user www-data and group www-data were set for this web user by my ispconfig3.
Make a session directory on your web path (probably /var/www) for the web user.
sudo mkdir /var/www/whatever;
sudo chown <user_from_last_step>:<group_from_last_step> /var/www/whatever
eg>sudo chown www-data:www-data /var/www/whatever
Again in your php.ini file make sure session.save_path is commented out, something like ...
;session.save_path = /var/lib/php5
but not
session.save_path = /var/lib/php5
restart apache if you edited php.ini
Now go to your php code (Many have a SetEnv.php ish type script which does some global stuff and is imported by all files) and add the following line BEFORE you call session_start() ...
ini_set('session.save_path', '0;0750;/var/www/whatever');
Note that we set session.save_path in your code rather than in php.ini to help keep it secure, so to replace 'whatever' with something inventive would be useful.
By now it should appear to be working, but not quite, it doesent work accross ajax requests for some reason that I dont care about related to sqlite ... so ...
Go back to your php.ini file and change the line ...
session.save_handler = sqlite
back to
session.save_handler = files.
restart apache
Fixed :) Hopefully :|
use $_SESSION and check it by print_r($_SESSION);
<?php
session_start();
if (isset($_SESSION['views']))
{
$_SESSION['views'] = $_SESSION['pv'] + 1;
}
else
{
$_SESSION['views'] = 0;
}
echo "<pre>";
print_r($_SESSION);
?>

Categories