If you visit my script "page.php" in the URL. A 500 Error appears. If you submit through a form it works.
<?php
## send forgot pass
$a=$_REQUEST['email_address'];
include("template.funcs.php");
$yz = mysql_connect("","","");
mysql_select_db("", $yz);
$b=mysql_real_escape_string($a);
$d=mysql_query("SELECT * FROM `customers` WHERE `customers_email` = '".$b."'");
if (mysql_affected_rows()==0){
header("Location: cart.php?pass=notsent");
}else{
send_registration_email($b,'','','');
header("Location: cart.php?pass=sent");
}
mysql_close($yz);
?>
A 500 error is a server side error, and I've found the best way to fix this is to check the logs on your server.
On the other hand, looking at your code, you may not have defined $_REQUEST['email_address']. Try this:
<?php
if (isset($_REQUEST['email_address'])) {
## send forgot pass
$a=$_REQUEST['email_address'];
include("template.funcs.php");
$yz = mysql_connect("","","");
mysql_select_db("", $yz);
$b=mysql_real_escape_string($a);
$d=mysql_query("SELECT * FROM `customers` WHERE `customers_email` = '".$b."'");
if (mysql_affected_rows()==0){
header("Location: cart.php?pass=notsent");
}else{
send_registration_email($b,'','','');
header("Location: cart.php?pass=sent");
}
mysql_close($yz);
}
?>
I would assume this has something to do with $_REQUEST['email_address'] not being defined on normal page load...
Use useful variable names. Use indenting appropriately. Only escape input before inserting it into your database. Group often used functionality in functions. Don't use $_REQUEST. Fail fast. A few hints which massively increase your code quality.
Now have a look at this:
include("template.funcs.php");
function Redirect($to)
{
header("Location: " . $to);
exit();
}
if ($_SERVER['REQUEST_METHOD' != "POST" || !isset($_POST['email_address']))
{
Redirect("cart.php?pass=notsent");
// or redirect to your "forgot password" form
}
$mailAddress = $_POST['email_address'];
$dbconn = mysql_connect("","","");
mysql_select_db("", $dbconn);
mysql_query("SELECT * FROM `customers` WHERE `customers_email` = '".mysql_real_escape_string($mailAddress)."'");
if (mysql_affected_rows() == 0)
{
Redirect("cart.php?pass=notsent");
}
send_registration_email($mailAddress,'','','');
Redirect("cart.php?pass=sent");
Related
I have a page that connects to a MySQL database via PHP. On this page the data is fetched to load an image and its related details. This page all work OK when the page is loaded.
I also have a module included on this page where users can create a board (which will hold images) along a certain theme.
On other pages this board module works OK, but on a page where a $_GET request happens, which is needed to identify a user's username or an image filename (depending on the page), the board module doesn't work correctly. When you create a new board it fails and I get a PHP error saying Undefined variable: filename in with reference to the line of code ':filename' => $filename in the execute function below.
When this boards module is used to create a new board name I have some JavaScript fetch() code on the page that prevents a hard refresh. I'm not sure if this is causing the problem (although this JS is also used on the pages that don't have a problem, i.e. no $_GET request). On pages where this is no $_GET request everything works as expected.
Note: in the code below $connection is the database connection from a db.php file
PHP on pageload that loads the image and related data
isset($_GET['filename']) ? $filename = $_GET['filename'] : header("Location: login.php");
$image_stmt = $connection->prepare("SELECT * FROM `lj_imageposts` WHERE `filename` = :filename");
$image_stmt -> execute([
':filename' => $filename // variable that returns the error
]);
$image_row = $image_stmt->fetch();
// if the GET url parameter doesn't exist/changed
if ($image_row == 0) { header ("Location: index.php"); exit; }
$db_userid = htmlspecialchars($image_row['user_id']);
$db_image_id = htmlspecialchars($image_row['image_id']);
$db_image_title = htmlspecialchars($image_row['image_title']);
$db_image_filename = htmlspecialchars($image_row['filename']);
$db_image_ext = htmlspecialchars($image_row['file_extension']);
$db_username = htmlspecialchars($image_row['username']);
?>
---- HTML OUTPUT THAT INCORPORATES THE ABOVE VARIABLES
PHP for the boards module
if (isset($_POST['submit-board-name'])) {
$create_board_name = $_POST['create-board-name'];
if(strlen(trim($create_board_name)) < 10) {
$error[] = "Board name must be at least 10 characters long";
}
if(strlen(trim($create_board_name)) > 150) {
$error[] = "Board name can be at less than 150 characters long";
}
if(!isset($error)) {
try {
$createBoardSQL = "INSERT INTO lj_boards (board_name, user_id) VALUES (:board_name, :user_id )";
$bstmt = $connection->prepare($createBoardSQL);
$bstmt->execute([
':board_name' => $create_board_name,
':user_id' => $db_id
]);
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
}
} else {
// give values an empty string to avoid an error being thrown before form submission if empty
$create_board_name = "";
}
This first line is unnecessarily cryptic, making the mistake harder to spot (and harder to fix):
isset($_GET['filename']) ? $filename = $_GET['filename'] : header("Location: login.php");
It's pretending to be an expression, but it's actually an if statement in disguise - it consists of nothing but side effects. Let's write it out more clearly:
if ( isset($_GET['filename']) ) {
$filename = $_GET['filename'];
}
else {
header("Location: login.php");
}
Now we can look more clearly at what each branch does:
The if branch sets a variable. If the code takes that branch, everything should be fine.
The else branch sets a header to be included when PHP sends the response. It doesn't do anything else, and it doesn't set the variable, so if this path is taken, you'll have a problem later.
What you probably intended to happen was for the else branch to set that header and then immediately stop processing. For that you need an exit; statement (also known as die;
if ( isset($_GET['filename']) ) {
$filename = $_GET['filename'];
}
else {
header("Location: login.php");
exit;
}
This question already has answers here:
How to fix "Headers already sent" error in PHP
(11 answers)
Closed 6 years ago.
I built a website locally with WAMP server, and everything worked fine, then ported over to web server on GoDaddy, and my redirect function suddenly stopped working.
Simple site at (www.minute.tech), you can test out the one form I have, goes to the form_processing.php, but should redirect back to the index page with a message. When you go back to the index page after the failed redirect, it still shows the proper message of "Booyah!...", and inputs the email into my database.
Any ideas why it won't redirect on my web server, but will on my local WAMP server with the same code? Cheers!
Here's my redirect function in sessions.php:
function redirect_to($new_location) {
header("Location: " . $new_location);
exit();
}
Here's process_email.php where I redirect:
<?php require_once("sessions.php"); ?>
<?php require_once("db_connection.php"); ?>
<?php require_once("functions.php"); ?>
<?php
if(isset($_POST['submit']) && !empty($_POST['email'])){
//Process form
$email = $_POST['email'];
$email = mysql_prep($email);
$techcheck = (isset($_POST['techcheck'])) ? 1 : 0;
// 2. Perform database query
$query = "INSERT INTO signups (";
$query .= " email, techcheck";
$query .= ") VALUES (";
$query .= "'{$email}', $techcheck";
$query .= ")";
$result = mysqli_query($connection, $query);
if ($result) {
// Success
$_SESSION["good_message"] = "Booyah! We will keep you posted on progress.";
redirect_to("../index.php");
} else {
//Failure
$_SESSION["bad_message"] = "Failed to accept email.";
redirect_to("../index.php");
}
} else {
//This can be an accidental GET request
$_SESSION["bad_message"] = "That is not a valid email! Please try again.";
redirect_to("../index.php");
}
?>
You have to start object for header function sometimes
Add this code to all pages
<?php ob_start(); ?>
Do with JS.
<?php
function redirect_to($new_location) { ?>
<script>window.location="<?php echo $new_location; ?>";</script>
<?php } ?>
Remove all the empty spaces. Some server set-ups will be okay with output before the header redirect but the vast majority of servers will not redirect properly. Turn on error reporting and it will probably tell you have output before the redirect:
<?php
// ^---- Just do one open tag
require_once("sessions.php"); // Remove close tag, possible empty space after
require_once("db_connection.php"); // Remove close tag, possible empty space after
require_once("functions.php"); // Remove close tag, possible empty space after
// Remove the close and open php tags
if(isset($_POST['submit']) && !empty($_POST['email'])){
//Process form
$email = $_POST['email'];
$email = mysql_prep($email);
$techcheck = (isset($_POST['techcheck'])) ? 1 : 0;
// 2. Perform database query
$query = "INSERT INTO signups (";
$query .= " email, techcheck";
$query .= ") VALUES (";
$query .= "'{$email}', $techcheck";
$query .= ")";
$result = mysqli_query($connection, $query);
if ($result) {
// Success
$_SESSION["good_message"] = "Booyah! We will keep you posted on progress.";
redirect_to("../index.php");
} else {
//Failure
$_SESSION["bad_message"] = "Failed to accept email.";
redirect_to("../index.php");
}
} else {
//This can be an accidental GET request
$_SESSION["bad_message"] = "That is not a valid email! Please try again.";
redirect_to("../index.php");
}
// If you have no more content below this point, just remove the close php tag
// it is not required and is a possible source of empty space down the line...
Also, you should not be using mysql_ anymore, it is deprecated and removed in PHP 7. Also, bind parameters instead of doing this parameter right into the sql:
$query .= "'{$email}', $techcheck";
After doing my SQL Schema (Different types of users redirected to same page (index.php) with different content), I'm starting to make my login system.
I now have this:
function login($email,$password){
$mysqli = $this ->dbConnect();
if($mysqli){
$strQuery = "SELECT USERS.ID, USERS.EMAIL, TYPES.NAME FROM `USERS` LEFT JOIN `TYPES` ON USERS.TYPEID = TYPES.ID WHERE `EMAIL` = '$email' AND `PASSWORD` = '$password'";
$recordSet = $mysqli->query($strQuery);
$row = $recordset->fetch_assoc();
if($recordset->num_rows>0){
$_SESSION['auth'] = $row['ID'];
$_SESSION['username'] = $row['EMAIL'];
$_SESSION['type'] = $row['NAME'];
header ("location:"index.php");
return true;
}
//....
}
}
Does this look good? Is the query right? Any suggestions for improvement?
UPDATE
I have my login working now. And it's redirecting to index.php. But in index php I don't have acess to the $_SESSIONS variables i have stored on my function login. Is there any problem with the attribuitions? Placing the header inside the function not good?
Thanks :)
I summarized the previous comments.
1. Issue: you didn't used the same variables
function login($email,$password){ and $strQuery = " ... WHERE EMAIL = '$email' AND PASSWORD = '$password'";
2. Recomendation: use the same namming convention
On your SQL request you used two way to use fields: USERS.EMAIL and EMAIL = (with ` arround).
Use the same. This will be easier for later & debugging.
i.e.: of course, you should not use table.field each time. Not mandatory for example if you have only one table OR if the fields are not shared between them. For my perosnnal usage, I always use this table.field. This will prevent any future issue :)
3. Protect your data from any injection
Example:
$post_email = isset($_POST['email']) ? htmlspecialchars($_POST['email']) : null;
Alter call
$this->login($post_email, ...)
And finally use something like this to protect your data:
$email = $mysqli->real_escape_string($email);
and you are ready for your request:
" SELECT [..] FROM users as u [...] WHERE u.email = '$email' "
4. Or use specific functions
Example (real_escape_string not needed anymore):
$stmt = $dbConnection->prepare('SELECT * FROM users WHERE email = ? AND password = ?');
$stmt->bind_param('s', $email);
$stmt->bind_param('s', $password);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// do something with $row
}
http://php.net/manual/fr/class.mysqli.php
5. Sessions
If you want to activate sessions on a spacific page, the first code (at the first line) should be session_start().
Calling this method will activate the sessions and load the $_SESSION variable with content.
<?php // index.php
session_start(); // first line
// ... code
var_dump($_SESSION);
?>
&
<?php // page.php
session_start(); // first line
// ... code
$_SESSION['test'] = time();
Header('Location: index.php');
?>
Visit index.php -> nothing on the debug
Visit page.php -> you will be redirected on index.php
On index.php -> you will have data
Enjoy session :p
6. Handle specific data
To begin with, you should coose a way to store the credential access (ACL) for each user. For example, store on the database some values as 100001, and each number is a yes/no access for a specific action (binary access mode) ; another system is to store the level '1,2,3,4,5' ... or 'member,customer,admin, ...'. So many ways :)
I will choose the USER.ACCESS = member|customer|admin solution
On the login page
// is user successfully logged
$_SESSION['access'] = $row['access']; // member|customer|admin
// Header('Location: index.php');
On any page of your site:
if( in_array($_SESSION['access'], ['member', 'admin']) ) {
echo 'You are a member, you can see this part';
}
if( in_array($_SESSION['access'], ['customer', 'admin']) ) {
echo 'You are a customer, you can see this part';
}
Or
if( checkAccess() ) {
echo 'Welcome user !';
if( checkAccess(['member', 'customer']) ) {
echo 'This is a section for member, customer or admin :)';
}
if( checkAccess('member') ) {
echo 'You are a member, you can see this part';
}
if( checkAccess('customer') ) {
echo 'You are a customer, you can see this part';
}
}
function checkAccess($types = null) {
if( !isset($_SESSION['access']) )
return false; // not logged
if( is_null($types) )
retun true; // if empty, provide info about loggin.
// admin has always access to all sections of the website
$hasAccess = in_array($_SESSION['access'], ((array) $types) + ['admin']);
return $hasAccess; // user is logged + has accessor not ?
}
Of course, you can also use includes
if( checkAccess('member') ) {
include 'secret_page_for_member.php';
}
Or, at the begening of the included page:
<?php
if( !checkAccess('admin') ) {
return '403 - Not authorized';
// die('403');
// throw new Exception('403');
}
// your code
?>
I'm having issues to send an occuring error to another page.
I have already created the page the error will be sent to, and I've tried a header function. But that doesn't seem to work. Here is the php code that I am using for the page.
<?php
if(isset($_POST['username'], $_POST['password'])){
//login the user here
$connect = mysql_connect("","","")or die(mysql_error());
mysql_select_db("")or die(mysql_error());
$errors = array();
$username = strip_tags(mysql_real_escape_string($_POST['username']));
$password = strip_tags(mysql_real_escape_string($_POST['password']));
if (empty($Regi_Username) || empty($Regi_password)) {
$errors[] = 'All fields are requerid';
} else {
if (strlen($Regi_Username) > 25) {
$errors[] = 'Username is to long';
}
if (strlen($password) > 25) {
$errors[] = 'Password is to long';
}
}
$password = md5($_POST['password']);
$loginquery = "SELECT * FROM regi WHERE username='$username' and password='$password'" or die(mysql_error());
$result = mysql_query($loginquery);
$count = mysql_num_rows($result);
mysql_close();
if($count==1){
$seconds = 2000 + time();
setcookie(loggedin, date("F jS - g:i a"), $seconds);
header("location:member.php");
} else {
echo 'Wrong username and password please try agian.';
}
}
?>
Pass the GET variable in your URL like..
header('Location:page.php?err=1');
exit;
On the other page use this
if(isset($_GET['err'] && $_GET['err'] == 1) {
echo 'Error Occured';
}
Here is a session based approach. This is the best way to pass messages from one page to another as they are stored in the user's session (a piece of data related to each user and stored in the server side) and not in the browser (like cookies or URL GET parameters, which can be easily corrupted), so it is really quite harder to manipulate the messages from 3rd parties.
Page process.php:
<?php
// Very top of your page
session_start();
$_SESSION['errors'] = array();
// Do stuff now...
// ...
// Hey it's a X error!
$_SESSION['errors']['X'] = 'Message for X error';
// Continue doing stuff...
// ...
// OMG! It's a Y error now!
$_SESSION['errors']['Y'] = 'Message for Y error';
// Keep doing stuff till you're done...
// All right, process is finished. Any Errors?
if (count($_SESSION['errors']) > 0) {
// It seems there's been any errors
// time to redirect to error-displaying page
header('Location: error-page.php');
exit;
}
Page error-page.php:
<?php
// Very top of your page
session_start();
// Let's check if there is any error stored in the session.
// In the case no errors found, it is better to redirect to another page...
// ...why anybody would end in this page if no errors were thrown?
if (!isset($_SESSION['errors']) || !is_array($_SESSION['errors']) || empty($_SESSION['errors'])) {
header('Location: home.php');
exit;
}
// If we reach this point it means there's at least an error
foreach ($_SESSION['errors'] as $errorCode => $errorMessage) {
// Here we can display the errors...
echo '<p>Error ', $errorCode, ': ', $errorMessage, '</p>', PHP_EOL;
}
// You can also do stuff only if a certain error is received
if (array_key_exists('X', $_SESSION['errors'])) {
// Error `X` was thrown
echo '<p>Oh no! It seems you suffered a X error!!</p>', PHP_EOL;
echo 'Click here to go back home.', PHP_EOL;
}
// At the end you should to remove errors from the session
$_SESSION['errors'] = array();
// or
unset($_SESSION['errors']);
You could use Alien's method, but it'd better if you use Session:
// Assume you init the session already; Use json_encode since you use array for $errors
$_SESSION['errors_msg'] = json_encode($errors);
header("location:member.php");
// Remember to exit here after we call header-redirect
exit;
Besides, there are a lot of problems is your currently code:
Use salt for hashing password
Use mysqli over mysql
Filtering input, escaping output
.. Read other recommendations here in this topic ..
Please read http://www.phptherightway.com/. There is a lot of right recommendation (of course not all) for PHP.
My JS function expects a certain return from the PHP code in case of a failure.
function showResult(data)
{
if (data == 'save_failed') {
document.getElementById('result').innerHTML = 'Unfortunately, we were not able to save your information. Please contact an admin.';
return false;
} else {
$("#notify").clearForm().clearFields().resetForm();
document.getElementById('result').innerHTML = 'Thank you for signing up with us.';
return false;
}
}
This works fin when I echo 'save_failed'; in case of an explicit error, but it does not work in the case of die statements, such as this one:
mysql_connect("host", "user", "pass") or die('save_failed');
I entered a wrong hostname but the JS function did not receive the 'save_failed' return.
PHP script:
if (!(empty($_POST['name']) && empty($_POST['email'])))
{
//sanitizing inputs for MySQL insertion
$name = mysql_real_escape_string($_POST['name']);
$email = mysql_real_escape_string($_POST['email']);
//connecting to db
mysql_connect("host", "user", "pass") or die('save_failed');
mysql_select_db("table") or die('save_failed');
//inserting into table
mysql_query("INSERT INTO notify (name, email) VALUES('" . $name . "', '" . $email . "' ) ")
or die('save_failed');
}
else
{
echo 'save_failed';
}
Even though die("save_failed") will output "save_failed", it will not stop any previous output in your script from being sent.
Ensure that if you go to the script yourself then you are receiving just "save_failed" in the page source and no erroneous characters
I would propose another strategy in dealing with errors.
Use output buffering to ensure no data will be send to client (eg. the beginning of a HTML-Document)
Start using Exceptions. They represent fatal errors, but with the ability to determine the exact line and parameters the error occurred.
The Browser tries to evaluate the type of response based on the content type header. If you want it to display simple text use
header('Content-Type: text/plain');
Use a global Exception handler, to transform the messages the way you like.
Works for me! Most servers have enough power today to use these, little more advanced methods.
It is not a good idea to use die to pass some information to the page. Normally, there will be other data in the response string.
An easier way is to embed PHP code in your JS code. An example will be like this:
<script type="text/javascript">
data = "<?php echo('Save Failed'); ?>";
</script>