Confused why code will only work with ob_start(); - php

I have added some server side validation to a dropdown box on one of my pages and when I did the page wouldn't work anymore. The code I added is as follows:
$show_form = true;
if (isset($_POST['submit'])) {
//All of the server side validations
$validator = new FormValidator();
$validator->addValidation("hospital_name","dontselect=000","No facility was chosen");
if ($validator->ValidateForm()) {
// All the variables from the submission form
$userid = $_SESSION['user_id'];
$hosp = $_POST['hospital_name'];
header('Location: ../site_hospital' . $hosp . '/hospital_submitform.php?usr=' . $userid . '&&hosp=' . $hosp);
exit;
$show_form = false;
} else {
echo "<B style='color:red;'>The following errors occurred:</B>";
$error_hash = $validator->GetErrors();
foreach ($error_hash as $inpname => $inp_err) {
echo "<p style='color:red;'>$inp_err</p>\n";
}
}}
if (true == $show_form) {
Through pure chance I added ob_start(); as part of my debugging to the beginning of the page and suddenly my code worked properly but I have no idea why and I was hoping the community could throw out an educated guess as to why. When the code stopped working it would not execute my header command above, the page would simply refresh and not change location, when I added ob_start(); to the top of the page the page redirected as planned. So the overall question is why would the page not direct using the header command without ob_start? I'm sure alot more detail and code is necessary for a definitive answer but I'm hoping someone has run into this before or has an educated guess that may lead me to my own answers. Thanks for any insight.

it's because you were writing to the output stream and preventing the header from working properly. once you started buffering other outputs, you removed the obstacle to the header's operation.

Related

PHP $_SESSION not working in function

Firstly, I have searched many threads and topics and they all keep saying its function placement but thus far I do not see a issue with my placement. I am desperate to get this is working because I am SICK of looking at 50+ extra lines of repetitive code.
resetpassword.php (RELEVANT CODE):
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/security/sslcheck.php';
$ResetID = $_GET["ID"];
session_start();
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/functionality/error.php';
print_r(array_values($_SESSION));
if(empty($ResetID) && !isset($_SESSION["ERR"]) && !isset($_SESSION["ERR_MSG"])) {
$ResetPassword = "REQUEST";
if(isset($_POST["email-search"]) && !empty($_POST["email-search"])) {
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/functionality/users/request.php';
// Start Request Process
$Request = RequestPasswordReset($_POST["email-search"]);
if($Request === "USER_NOT_FOUND") {
DisplayError("Password Reset Request Failed", "The specified email is not tied to any accounts in our system.", "/account/resetpassword.php");
} else if ($Request === "MAIL_FAILURE") {
DisplayError("Password Reset Request Failed", "Failed to email you the password reset email.", "/account/resetpassword.php");
} else {
DisplayError("Password Reset Request Success", "We have sent a email that contains a link to reset your password.", "/account/resetpassword.php");
}
}
More Relevant Code
<?php
if (isset($_SESSION["ERR"]) && isset($_SESSION["ERR_MSG"])) {
echo '<div id="resetPasswordStatus">';
echo '<h4>' . $_SESSION["ERR"] . '</h4>';
echo '<p>' . $_SESSION["ERR_MSG"] . '</p>';
echo '</div>';
session_destroy();
}
?>
error.php (ALL CODE):
<?php
session_start();
function DisplayError($title, $body, $returnlink) {
$_SESSION["ERR"] = $title;
$_SESSION["ERR_MSG"] = $body;
header("Location: " . $returnlink);
}
?>
I have experiment in many ways with my placement of require_once of error.php, but have found no luck. I understand $_SESSION is a superglobal and require or require_once copy the code right into place where required. However even copying error.php manually into resetpassword.php I was unable to get the function to work. Thank you guys for your help as it really means a lot!
The expected output is after the callback after the request for a password reset, is the alert to display. Code for this alert can be seen under More Relevant Code.
Solution:
In the error.php if you add exit(); after the header redirect it allows for PHP to pause execution while the redirect occurs which prevents the error displaying code from running its code and then wiping the session which leaves the redirect empty in terms of sessions.
You are calling the function after the if statement empty($ResetID)
Your function isn't running if the $_GET['ID'] is not empty so change it to !empty($ResetID)

My php script outputs a blank page

I have a php page that accepts and processes a form submission, the page displays normally when it is requested, however if the page is submitted and its form validation fails, the page suppose to be re-displayed with the form errors, but on page re-display, php displays a blank page when it reaches the error processing block. Here is the code that processes the validation errors:
<?php if(isset($errorLog) and is_array($errorLog)): ?>
<div class="alert alert-danger">
<?php $output = '';
if($errorLog['message'] == '') {
$output = "<ul class='error-list'>";
foreach($errorLog as $key => $value) {
if ($key != 'has_error_occured') {
$output .= "<li><strong>{html($key)}</strong>
<span>{html($value)} </span></li>";
}
}
$output .= "</ul>";
} else {
$msg = $errorLog['message'];
$output .= "<p>{html($msg)}</p>";
}
echo $output;
?>
</div>
<?php endif; ?>
and here is the code that processes the form submission
if(isset($_GET['transfer']) or
(isset($_POST['action']) and $_POST['action'] == TRANSFER)){
$transfer_type = $_GET['ttype'];
if(isset($_POST['action']) and
$_POST['action'] == TRANSFER){
//process money transfer.
$log = process_transfer();
if(isset($log) and is_array($log)){
if($log['has_error_occured']){
$_SESSION['error_log'] = $log;
//unset log
unset($log);
include_once $docRoot . '/users/temp/tranfer.html.php';
exit();
}else{
$_SESSION['transfer_msg'] = "Your international
transfer was processed successfully";
header('Location: ?summary');
}
}
//reload primary page.
header('Location: .');
}else{
include_once $docRoot . '/users/temp/tranfer.html.php';
exit();
}
}
Note:
I have tried passing the error array as a global variable as
you can see in the code snippet above.
I have also tried passing it in a session.
I also have tried using output buffering by appending the ob_start() at the beginning and ob_end_flush() at the end the form script.
I have also added error_reporting(-1); ini_set('display_errors', true); at the start of the form script so as to know if the page encounters any error during processing, all to no avail.
I am using PhpStorm with XAMPP v3.2.1 for development on windows 7.
Please, any help as to the cause of this nightmare will be appreciated. Thanks.
If you wanna use $_GET and $_POST then better use $_REQUEST, it allows to access both $_GET and $_POST
not TRANSFER but it should be "TRANSFER"
if errorlog is session data then it should be
if(isset($_SESSION['errorLog']) and is_array($_SESSION['errorLog'])):
i didn't find any thing created by name message
if($errorLog['message'] == '')
why u used it, i think it must be 'has_error_occured'
I discovered the problem through the output of php_error_log and through the various suggestions in the comments above, the problem problem was that I didn't check if the $erroLog['message'] was set before accessing it. But shouldn't php have outputted a warning instead of resorting to such indeterminate option of not fully executing the rest of the document?

headers already sent only in subdomain

I have a main webpage that logs in and redirects using header() without any problems.
I also have another webpage that would need to log in, so I made another login.php page for it.
Both webpages have the same structure, in fact I just copy-pasted the main webpage into the other webpage and changed var names, etc
If I log in in the main webpage everything is allright, no warnings. But if I log in in the other webpage I get the following warning:
Warning: Cannot modify header information - headers already sent by (output started at /home/aet/platform.corporativelines.com/themes/aet/main.php:12) in /home/aet/platform.corporativelines.com/pages/login.php on line 18
This is main.php:12
<title>AET | <?php print $title ?></title>
And this is login.php line 18
header("Location: /home");
The main webpage have the same in those lines, exactly the same but no warnings... Can someone tell me why?
Both webpages are in a subdomain, but main is just temporary, I'll move it when is finished. Maybe that have something to do... (If you want to visit, "pre" is the temporary subdomain)
The framework is the same for both webpages, the custom session start function have the domain set to ".domain.com" like says here.
PHP Code:
index.php (both websites):
ini_set('display_errors', '1');
//requires and initializations
$hasExpired = $web_user::sec_session_start();
$client = $web_user->login_check(); // FALSE OR CLIENT
$isLogged = false;
$includes1 = array(
'/pages' => $pages . 'pages.php'
);
if ($client != false) {
$isLogged = true;
$includes2 = array(
'/morepages' => $pages . 'morepages.php'
);
}
else {
$includes2 = array(
'/otherpages' => $pages . 'otherpages.php'
);
}
$includes = array_merge($includes1, $includes2);
$url = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
//some more security checks for url
$title = $lang->getW($url);
include('themes/aet/main.php');
main.php (both websites):
<?php
defined('_AET') or die();
?>
<!DOCTYPE html>
//html structure
<title>AET | <?php print $title ?></title>
//body
//main
<?php
$include = '/404';
if (array_key_exists($url, $includes)) {
$include = $url;
}
include($includes[$include]);
?>
login.php (both websites):
// login post, checks and call to function
if ($login_array[0] == "OK") {
header("Location: /home");
}
// login form html
I can say they are the same pages in both webpages.
EDIT: Sorry I have not been clear. In both websites I have ini_set('display_errors', '1'); In the main website I'm not getting any error plus the header() redirection is working fine. In the other website I'm getting the error, if I disable them, the error won't show but neither the redirection will work.
In main.php it looks like you are outputting php comments - check carefully if anything (including white space) is output from PHP before your DOCTYPE (i.e. the first line of HTML output).
If you have a PHP script that does this:
<?php
print "before headers: will cause a problem";
?>
// this will also cause text to be output
<!DOCTYPE html>
<html> ...
you will have a problem. If that is not the case, can you post the entire beginning of main.php.
The "problem" was (first) calling header() after output and (second) having output_buffering enabled.
To solve this, I just moved the login post script (and any other script that calls header()) to another file and include it in index.php before including the main.php (before the HTML/Dom output starts).
if ($url == '/login') {
include('pages/headers/login_post.php');
}
// now we can safely start the DOM output
include('themes/main.php');

Header location works inconsistently on chrome?

So i have this webshop running on a server, it's working fine on every pc i have been able to get my hands on. but for some reason quite often customers still have problems with one header(location ) to a payment site. I checked everything codewise and tried a hundred different ways of breaking the payment link but haven't found one.
I'm assuming it's the header(location: ...) or the fact that it's three in a row (some php only verification pages inbetween) which might give some version trouble but i'm only guessing.
snip out of the index.php
ob_start();
require_once($Content_Path);
$zpfw_page_output = ob_get_contents();
ob_end_clean();
//************************************************
// Include the requested header / footer / etc..
//************************************************
//Here we include the HEADER HTML.
require_once($Config['AbsolutePath'] . '_headers/' . $Config['HeaderFilename']);
//Here we include the PHP PAGE.
echo $zpfw_page_output;
//Here we include the FOOTER HTML.
require_once($Config['AbsolutePath'] . '_footers/' . $Config['FooterFilename']);
The Content page is the only thing that changes ($Content_Path) So the customers puts hit products that he wants to buy in his basket and goes towards checkout, now every post done on our pages go to a posttogethandler to make it seo friendly (the indexpages uses the first 2 parameters (www.google.nl/module/page/test)
to change the content path everything behind that are used as parameters $_Get[Param1] = 'test'
posttogethandler.php:
<?php
if(isset($_POST))
{
include '../../../_bootstrap.php';
if(!empty($_POST['m']) && !empty($_POST['c']))
{
$post_string = '';
foreach($_POST as $key => $postitem)
{
if($key == 'm')
{
}
elseif($key== 'c')
{
}
else
{
$post_string = $post_string.$postitem.'/';
}
}
header('location:'.$Config['AbsoluteURL'].$_POST['m'].'/'.$_POST['c'].'/'.$post_string);
}
}
and for the actual check which creates a mollie payment and sends to person to the payment (again i will shorten it a bit to only containt the code it passes through if nothing is wrong) (No echo commands exist in this file)
<?php
$mollie = new Mollie_API_Client();
$mollie->setApiKey($Config['Mollie']['Api_Key']);
if(!empty($_GET['param1']) && $_GET['param1'] == 'checkout' && !empty($_SESSION['Customer_ID']))
{
/* alot of checks and inserts into mysql database to keep track */
if(!empty($_GET['param3']) && $_GET['param3'] == 'secretcode')
{
//for skipping payment
header('Location: ' . $Config['AbsoluteURL'] . 'account/order/' . $uniqueID);
exit;
}
else
{
$payment = $mollie->payments->create(array(
"amount" => mollieCartPriceIncTaxes($_SESSION['cart'],$_SESSION['Customer_ID'])[0],
"description" => "Payment for ...",
"redirectUrl" => $Config['AbsoluteURL']."account/order/payment/".$uniqueID."",
"webhookUrl" => $Config['AbsoluteURL']."cart/checkout/webhook"
));
$payment = $mollie->payments->get($payment->id);
zp_mysqli_query("Update orders set Order_MollieID = '".$mysqli->real_escape_string($payment->id)."' where Order_ID = '".$mysqli->real_escape_string($uniqueID)."'");
if(!empty($_SESSION['pick_up']))
{
unset($_SESSION['pick_up']);
}
header("Location: " . $payment->getPaymentUrl()."/#");
exit;
}
}
I'll edit it some more in a few hours, need to go now. this is hosted on a server so i've checked for html code being send first but can't find any nor experience any problems with it on any pc i've tried to open the website with.
any pointers would be much appreciated!
EDIT:
It seems to be a problem with redirecting to a page outside of the domain. I'm remaking the page so the button is a direct link to the payment page. This seems to work.

PHP If Statement redirects on a die()

I am creating my own license checker since I often forget when to charge people for software every month. This is in infancy state.
I have an if statement checking a POST variable from another site before the site can run. (I know if the right person understood it he can manipulate it, but no such person!)
I have such statements working in the background, everytime a page loads thats part of the app. I cannot find a damn way around this though.
Here's the problem. When it successfully matches up and the variable returns yes, I have a die(). This takes the user off of the page they are working on, and redirects them to my checker script. I don't want that. If the variable returns yes, I just want the script to die (not do anything except stop), not redirect to a blank page because I put die.
I don't want the script to give a response, in other words.
Here's the snippet I am working with.
I want it to go back to the page it was on before. This script is an include, and the user should not know it's running. If the script completes, it takes the user to a blank page.
Here's the entire process.
License.php submits this form:
<form name="hidsys" method="post" action="../rauth/rauth.php">
<input type="hidden" name="siteid" value="<? echo $value; ?>">
<input type="hidden" name="keytype" value="a6request">
</form>
<script language="JavaScript" type="text/javascript">
setTimeout("document.hidsys.submit(hidsys)" ,1);
</script>
Here's my function and variables:
function rauth($url)
{
$ch = curl_init();
$timeout = 5;
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
$timestamp = date("Y-m-d h:i", $timestamp + 10800);
$token = sha1($_POST['siteid']);
$rogue = sha1(time());
$authKey = md5($_POST['siteid']);
$skeletonKey = $token.$authKey;
$value = 'cca';
It talks to rauth.php:
<?php
// Declarations
$id = $_POST["siteid"];
$rauth_returned = rauth('http://www.mysite.com/rauth/index.php?siteid=' . $id . '&token=' . $token . '&time=' . $timestamp);
if (isset($_POST["siteid"])) {
if( strstr($rauth_returned, 'no')) {
exit('You are not authorized');
}
else if( !strstr($rauth_returned, 'yes')) {
exit('There was an error');
}
}
else {
exit("You can't view this page directly");
}
header('Location:' . $HTTP_REFERER);
?>
And this is the site index it talks to get if it's "authorized" or not:
<?php
if (isset($_GET["siteid"])){
$site = $_GET["siteid"];
switch ($site)
{
case cca:
echo 'yes';
die();
case ccgay:
echo 'no';
die();
default:
echo 'absno';
die();
}
}else{
echo "No data to process.";
die();
}
?>
Everytime a file (index.php) in a different direction than these files runs, it tells license.php to run in the background to simply check on if its allowed to run or not. Every link and every time the site opens it tells license.php to go through the process above. I probably wrote this really stupid but I just need something to help me remember when people don't pay I guess.
Instead of die() use header():
header('Location: http://www.example.com/');
UPDATED:
Try this:
posix_kill(posix_getpid(),9);

Categories