I am a newbie to PHP development. I tried following code sample from PHP5 Power Programming book:
<?php
require_once 'DB.php';
require_once 'PEAR.php';
require_once 'Auth.php';
$auth_options = array(
'dsn' => 'mysql://username:password#localhost/database',
'table' => 'users',
'usernamecol' => 'username',
'passwordcol' => 'password',
'db_fields' => '*',
);
PEAR::setErrorHandling(PEAR_ERROR_DIE);
$auth = new Auth('DB', $auth_options);
$auth->start();
if (!$auth->getAuth()) {
exit;
}
if (!empty($_REQUEST['logout'])) {
$auth->logout();
print "<h1>Logged out</h1>\n";
print "Log in again\n";
exit;
}
print "<h1>Logged in!</h1>\n";
if (!empty($_REQUEST['dump'])) {
print "<pre>_authsession = ";
print_r($_SESSION['_authsession']);
print "</pre>\n";
} else {
print "<a href=\"$_SERVER[PHP_SELF]?dump=1\">Dump session</
?a><br>\n";
}
print "Log Out\n";
?>
there are several problems I am having with this code:
First, when I log in I get following warnings:
Warning: session_regenerate_id() [function.session-regenerate-id]: Cannot regenerate session id - headers already sent in /usr/local/php5/lib/php/Auth.php on line 830
Warning: Cannot modify header information - headers already sent by (output started at /home/myaccount/www/www/test.php:2) in /usr/local/php5/lib/php/Auth.php on line 858
Why am I getting these?
Second, when I click on the Dump session link, it asks me to log in again - i.e., does not recognize that I am already authenticated and logged in.
Could some please explain these to me? Thanks.
Sessions are maintained by a cookie passed between the server and the browser in each request containing a session identifier PHP generates. Since cookies are part of HTTP headers, creation of a session by sending a cookie has to happen before your script outputs any content.
That includes whitespace, which is the likely culprit for your error. There can be no whitespaces, including blank lines, spaces, BOMs at the top of the file before the opening <?php tag, including in the included files.
The second error is a side effect of the first error, so once you fix that, it'll go away as well.
Related
spoiler* convoluted code ahead
Context
main.php has a command-line like input, the file's form action attribute is submit.php. submit.php decides what other file to call, based on the input from main.php. In submit.php I adjust variables $url and $data, based on the input, then call file_get_contents with these parameters.
With post requests that do not have session headers I do not have any problem, but once I needed these and tried sending them, I hit a roadblock:
the function file_get_contents itself fails.
the request made by the function is completed successfully
Example and Symptoms
I hit submit on main.php to call submit.php with parameters to make a post request for list/access/index.php:
Server hangs until timeout
On timeout I get the following output.
Warning: file_get_contents(http://localhost/example/list/access/index.php): failed to open stream: HTTP request failed! in /Users/josetaveras/Sites/example/php_toolbox/toolbox.php on line 83
Warning: Cannot modify header information - headers already sent by (output started at /Users/josetaveras/Sites/example/php_toolbox/toolbox.php:83) in /Users/josetaveras/Sites/example/list/submit.php on line 373
When I go back to my main.php I know the post request is completed successfully because the request made in list/access/index.php simply sets a session variable. This variable is visible when going back to main.php.
Relevant code
submit.php
$result = post_request($url,$data,$headers);
header(
'Location: '
.$root_folder_path
.'list/?h='
.$hash
);}
// after post_request we get back to main.php with simple header redirect
toolbox.php
/*
* recursive merging 2 arrays
*/
function rec_array_merge($ar1,$ar2){
foreach($ar2 as $k=>$v){
if(is_array($v)){
if(isset($ar1[$k])){
$ar1[$k] = rec_array_merge($ar1[$k],$v);
}else{
$ar1[$k]=$v;
}
}else{
$ar1[$k]=$v;
}
}
return $ar1;
}
function serialize_array($array,$map_symbol,$separator_symbol){
$returnstr = "";
foreach($array as $k=>$v){
$returnstr.=$k.$map_symbol.$v.$separator_symbol;
}
return $returnstr;
}
function post_request($url,$data,$headers=NULL){
$post_content = http_build_query($data);
$default_headers = Array(
"Content-type"=>"application/x-www-form-urlencoded"
,"Content-Length"=>strlen($post_content)
);
if(isset($headers)){
try{
$headers = rec_array_merge($default_headers,$headers);
}
catch(Exception $e){
print_r($e);
}
}else{
$headers = $default_headers;
}
$serialized = serialize_array($headers,": ","\r\n");
$options = array(
'http' => array(
'header' => $serialized
,'method' => 'POST'
,'content' => $post_content
,'timeout' => 1 // for debugging purposes
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context); // line 83 on toolbox.php
return $result;
}
References
I used How do I send a POST request with PHP? to construct my post_request.
Final thoughts
It is redundant to say that I am not so deft with PHP, and I know and understand that I have bad habits. This leads to a little bit of disorder in the code and many poor choices. My impression is that overall this pattern feels fragile. I'm not trying to reinvent the wheel, but I am pointedly avoiding libraries and packages that facilitate any part of this. I understand that a routing package might help me with all of this.
I appreciate any feedback you may have on this question. All criticism is welcome and I will try to answer as soon as I can but I have limited connectivity and access to my computing devices. Having said all of that, thank you for reading up to this point.
After a few months I finally found the reason why this was happening.
The worst aspect of this is that I am familiar with error_reporting(E_ALL) and ini('error_notice',1) but I completely forgot about it. I did learn about var_dump($http_response_header) so there is that.
Honestly it was in the documentation and I should have found it sooner. Oh well.
I quote myself
With post requests that do not have session headers I do not have any problem, but once I needed these and tried sending them, I hit a roadblock
I was not familiar exactly with how session mechanics work in general, so i mostly ignored the documentation until I found it a few minutes ago. I refer to session_write_close as what I should have read before diving into sessions (or more specifically, attempting to open multiple sessions in a chain of requests (that I thought of as a single request)):
session data is locked to prevent concurrent writes only one script may operate on a session at any time
In my submit.php I open the session to access some variables. I basically forgot to close it before making a new request which itself attempted to modify session data. The fix was to use session_write_close() right before post_request().
Thank you to all who commented.
I am trying to determine why an Image Verification won't display images prior to a press release being issued pointing to the website.
The related image.php file is showing the alt text and a check on Console shows the error "Failed to load resource: the server responded with a status of 502 (Bad Gateway) image.php".
The host has checked things on their end and assures everything is as it should be, suggesting the problem is somewhere within the php code, however the code seems to point to the images as it should, and we are lost as to what is going wrong.
The image.php code follows:
<?php if (!isset($_SESSION)) session_start(); header("(anti-spam-content-type:) image/png");
$enc_num = rand(0, 9999);
$key_num = rand(0, 24);
$hash_string = substr(md5($enc_num), $key_num, 5); // Length of String
$hash_md5 = md5($hash_string);
$_SESSION['verify'] = $hash_md5;
// Fallback
setcookie("verify", $hash_md5, time()+3600, "/");
session_write_close();
// Verification Image Background Selection
$bgs = array("../images/contact/verify/1.png","../images/contact/verify/2.png","../images/contact/verify/3.png");
$background = array_rand($bgs, 1);
// Verification Image Variables
$img_handle = imagecreatefrompng($bgs[$background]);
$text_colour = imagecolorallocate($img_handle, 108, 127, 6);
$font_size = 5;
$size_array = getimagesize($bgs[$background]);
$img_w = $size_array[0];
$img_h = $size_array[1];
$horiz = round(($img_w/2)-((strlen($hash_string)*imagefontwidth(5))/2), 1);
$vert = round(($img_h/2)-(imagefontheight($font_size)/2));
// Make the Verification Image
imagestring($img_handle, $font_size, $horiz, $vert, $hash_string, $text_colour);
imagepng($img_handle);
// Destroy the Image to keep Server Space
imagedestroy($img_handle);
Hmm, this is almost certainly a problem:
<?php if (!isset($_SESSION)) session_start(); header("(anti-spam-content-type:) image/png");
There are two issues here:
An if clause without braces should not have many items on the same line, since this makes it look like the header() is conditional when it is not;
The header is invalid - there is no such HTTP header as (anti-spam-content-type:)
Consider replacing it with:
<?php
if (!isset($_SESSION)) {
session_start();
}
header("Content-Type: image/png");
Following on from the debugging you have done, here are some remarks.
Syntax errors
If there is a syntax error, then yes, it won't work. That seems to be fixed now, it was probably just uploaded wrongly.
Session configuration
Here is the new error you're getting:
Warning: session_start() [function.session-start]: Cannot find save handler 'memcache' - session startup failed in /var/sites/c/charityfilm.co.uk/public_html/brandint/classes/image.php on line 1
Warning: Cannot modify header information - headers already sent by (output started at /var/sites/c/charityfilm.co.uk/public_html/brandint/classes/image.php:1) in /var/sites/c/charityfilm.co.uk/public_html/brandint/classes/image.php on line 1
Warning: Cannot modify header information - headers already sent by (output started at /var/sites/c/charityfilm.co.uk/public_html/brandint/classes/image.php:1) in /var/sites/c/charityfilm.co.uk/public_html/brandint/classes/image.php on line 11
You can ignore the "Cannot modify header information" for now, since it is caused by the outputting of the first error. The first error indicates that you are operating a non-standard session system in PHP. Do you happen to know if there is a Memcache installation on the server?
This arrangement is fine if intentional, but PHP normally uses a file session system. I would expect this is being run as a result of a configuration in your PHP configuration file, usually called php.ini. Unusually, Go Daddy allows this file to be customised even on their shared host offering, which is why I think that might be the thing to check next.
There are three possible solutions:
Modify the php.ini configuration so that it uses the standard session system, though that may well break something else on your website;
Include a library used by your main app to set up the Memcache session system properly;
Make a call just inside your image.php script to change the session system to file-based, for that feature only. This is not ideal, as you don't usually want various features on your website to use different session systems.
Since this is not possible to answer without exploring your server, it is becoming rather too broad for a Stack Overflow question. I suggest you go back to your original developer and ask him/her how to hook into the session system (option 2).
At a stretch, you could examine other PHP scripts in this website, to see what code they call that initialises the memcache session system. However, that's based on the assumption that this is not a misconfiguration, and that some existing code in your system makes use of sessions. If your old developer cannot help, I wonder if it is worth getting a freelancer in for an hour or two?
I know this question has been asked many times but I have seen so many different answers and have tried them all and none have worked for me. So let me provide you with my specific context, and see what you recommend:
I am developing on Mac OS X El Capitan. I am using PHP version 5.5.31. error message
I have output buffering turned on in my php.ini file. I have obsessively checked there is no white space before the header is sent. Here are the lines the code is referring to:
(edit_subject.php:6)
<?php require_once("../includes/session.php");?>
<?php require_once("../includes/db_connection.php");?>
<?php require_once("../includes/functions.php");?>
<?php require_once("../includes/validation_functions.php");?>
<?php find_selected_page();?>
<?php
if(!$current_subject){
**redirect_to("manage_content.php")**;
}
?>
(edit_subject.php:38)
$result = mysqli_query($connection, $query);
if ($result && mysqli_affected_rows($connection) >= 0) {
// Success
$_SESSION["message"] = "Subject edited succesfully.";
**redirect_to("Location: manage_content.php");**
} else {
// Failure
$message = "Subject update failed.";
}
(functions.php:3)
<?php
function redirect_to($new_location) {
redirect_to("Location: . $new_location");
exit;
?>
I've been pulling my hair out for the last 48 hours. I'd appreciate some guidance here.
Thanks,
Chris
The following line is triggering the warning (functions.php line 3):
redirect_to("Location: . $new_location");
It is attempting to send headers, after something has already been output (probably another error/warning considering your syntax is broken). Check your error logs.
try flushing the buffer before redirecting. the problem arises if there is already something outputted and you try changing the header in this case by redirection.
You can use ob_start() at top, and ob_end_flush() to flush before changing the header.
Note: Flushing the buffer only hides the problem, its not the solution. There's some piece of bad practice of coding, try figure that out.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
PHP error: Cannot modify header information – headers already sent
Headers already sent by PHP
if ((isset($username)) && (isset($userid))){
}else{
header( 'Location: teacherlogout.php' ) ;
}
I have an if/else statement above, what I want to do is that if the else statement is met, then navogate to the teacherlogout.php page. But instead of this I am getting an error stating:
Warning: Cannot modify header information - headers already sent by (output started at /:431) in / on line 1654
I don't quite get what I am doing wrong? Line 431 is just a var qremain = <?php echo (int)$_SESSION['textQuestion']; ?>; line of code. Line 1654 is the header( 'Location: teacherlogout.php' ) ; line. What is happeing here?
UPDATE:
Actually will it be better to use ajax to navigate to teacherlogout.php script in background as so:
<?php
}else{
echo "Please Login to Access this Page | <a href='./teacherlogin.php'>Login</a>";
?>
<script type="text/javascript">
$.ajax({
url: "teacherlogout.php",
async: false,
type: "POST",
});
</script>
<?php
}
?>
Cause:
This error is caused if the your PHP scripts are printing to the browser prior to sending headers. A common example is printing the html tags prior to starting a session, or setting a cookie. The error tells the line that needs to be altered (in this case, it is on line 431).
Resolution:
To resolve this error remove the lines from the PHP code that are printing to the browser prior to sending headers.
Another common cause for this error is white space either at the beginning or end of the file. The fix is to remove that whitespace from the file. Read the error message carefully. It says output started at ... followed by a file name and a line number. That is the file (and line) that you need to edit. Ignore the second file name - that is only a file that included the file that has the whitespace. The first file is the one you have to edit, not the second one.
Make sure there isn't any whitespace at the top of your file. For example, if you have a blank line at the top, you will get this error.
(Blank Line Here)
<?php
if ((isset($username)) && (isset($userid))){
} else {
header( 'Location: teacherlogout.php' ) ;
}
?>
header( 'Location: teacherlogout.php' ) ;
The above function (header) only works if there has been no echo (output to screen). Check if something is printed before the function call.
HTML newline (usually considered as a whitespace) may also cause problem. Like a blank new line on page start.
I am experiencing very difficult (hard to find) problem with my PHP login script. I am using sessions to make login work with standard send form and using this script:
public function login($user, $password)
if (!empty($user) && !empty($password))
{
$user = $web->esc($user);
$password = $web->Hash($user, $password);
$db->selectDb('login');
$qw = mysql_query("SELECT * FROM account WHERE username='".$user."' AND pass='".$password."'");
if (mysql_num_rows($qw) > 0)
{
$result = mysql_fetch_array($qw);
$_SESSION['user_name'] = $result['username'];
$_SESSION['user_id'] = $result['id'];
return true;
...
...
And in login I am using something like this:
if(isset($_POST["send"]))
{
if($auth->login($_POST["name"], $_POST["pass"]))
{
header("location: ./");
}
}
else
...
...
It is working quite ok but in Opera and sometimes other browsers there is a problem. When I log in in Opera, Google Chrome etc for example - fill in my form and send it - it just "stucks" on login form and never let me see my page after login - it is working in other browsers - I just do not see the problem why in some browsers it is not wokring. DO you have any idea how to fix this? Thank you.
After an header location: you have to be sure that PHP will no send data.
So try to put the function exit(); just after the header function.
Activate error reporting and display errors.
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('scream.enabled', TRUE);
It should show you a "Warning headers already sent in file file on line line".
It would be preferable if you wrote the error reporting statements somewhere inside the first index.php file and the code was included by your index. Because parse errors in the current file aren't shown it just gives you a white screen.
OK problem solved after having these errors:
Warning: Unknown: open(/var/lib/php5/sess_5019088d181146779ffc848a095c27ff, O_RDWR) failed: No space left on device (28) in Unknown on line 0
Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/var/lib/php5) in Unknown on line 0
In settings in php.ini changing this:
session.save_path = /tmp
Everything works fine thx to Mihai Stancu for error analysis code.