PHP http_response_code(); versus header(); - php

I have made a contact form based on this tutorial:
http://blog.teamtreehouse.com/create-ajax-contact-form
I'm using PHP Version 5.3.10-1ubuntu3.4 on my server and I've been having trouble with http_response_code(); which is what the example tutorial at the above link uses. I've read http_response_code(); only works with PHP 5.4. So instead I have reverted to using header();.
I have my form working just fine and it's displaying a success message when I submit, rather than errors when I was using http_response_code(); but my PHP isn't that great and I am wanting to know if what I have done is acceptable or if I should be doing it a different way? Please correct my code if so.
Here's the contents of my mailer.php file, where you can see I've commented out http_response_code(); and am using header();.
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Get the form fields and remove whitespace.
$name = strip_tags(trim($_POST["name"]));
$name = str_replace(array("\r","\n"),array(" "," "),$name);
$email = filter_var(trim($_POST["email"]), FILTER_SANITIZE_EMAIL);
$phone = trim($_POST["phone"]);
$company = trim($_POST["company"]);
$minbudget = trim($_POST["minbudget"]);
$maxbudget = trim($_POST["maxbudget"]);
$message = trim($_POST["message"]);
$deadline = trim($_POST["deadline"]);
$referred = trim($_POST["referred"]);
// Check that data was sent to the mailer.
if ( empty($name) OR empty($phone) OR empty($message) OR !filter_var($email, FILTER_VALIDATE_EMAIL)) {
// Set a 400 (bad request) response code and exit.
//http_response_code(400);
header("HTTP/1.1 400 Bad Request");
echo "Error (400). That's not good, refresh and try again otherwise please email me and let me know you are having trouble submitting this form.";
exit;
}
// Set the recipient email address.
// FIXME: Update this to your desired email address.
$recipient = "myemail#domain.com";
// Set the email subject.
$subject = "Website enquiry from $name";
// Build the email content.
$email_content = "Name: $name\n";
$email_content .= "Email: $email\n\n";
$email_content .= "Phone: $phone\n";
$email_content .= "Company: $company\n\n";
$email_content .= "Budget: $minbudget $maxbudget\n";
$email_content .= "Deadline: $deadline\n";
//$email_content .= "Max Budget: $maxbudget\n";
$email_content .= "\n$message\n\n";
$email_content .= "Referred: $referred\n";
// Build the email headers.
$email_headers = "From: $name <$email>";
// Send the email.
if (mail($recipient, $subject, $email_content, $email_headers)) {
// Set a 200 (okay) response code.
//http_response_code(200);
header("HTTP/1.1 200 OK");
echo "Thank You! I'll be in touch soon.";
} else {
// Set a 500 (internal server error) response code.
//http_response_code(500);
header("HTTP/1.0 500 Internal Server Error");
echo "Error (500). That's not good, refresh and try again otherwise please email me and let me know you are having trouble submitting this form.";
}
} else {
// Not a POST request, set a 403 (forbidden) response code.
//http_response_code(403);
header("HTTP/1.1 403 Forbidden");
echo "Error (403). That's not good, refresh and try again otherwise please email me and let me know you are having trouble submitting this form.";
}

I've managed to answer this on my own similar question by going through the PHP source code to work out exactly what happens.
The two methods are essentially functionally equivalent. http_response_code is basically a shorthand way of writing a http status header, with the added bonus that PHP will work out a suitable Reason Phrase to provide by matching your response code to one of the values in an enumeration it maintains within php-src/main/http_status_codes.h.
Note that this means your response code must match a response code that PHP knows about. You can't create your own response codes using this method, however you can using the header method. Note also that http_response_code is only available in PHP 5.4.0 and higher.
In summary - The differences between http_response_code and header for setting response codes:
Using http_response_code will cause PHP to match and apply a Reason Phrase from a list of Reason Phrases that are hard-coded into the PHP source code.
Because of point 1 above, if you use http_response_code you must set a code that PHP knows about. You can't set your own custom code, however you can set a custom code (and Reason Phrase) if you use the header function.
http_response_code is only available in PHP 5.4.0 and higher

Easy solution:
/**
* Sets the response code and reason
*
* #param int $code
* #param string $reason
*/
function setResponseCode($code, $reason = null) {
$code = intval($code);
if (version_compare(phpversion(), '5.4', '>') && is_null($reason))
http_response_code($code);
else
header(trim("HTTP/1.0 $code $reason"));
}
you can use it as:
setResponseCode(404);
or
setResponseCode(401,'Get back to the shadow');

To answer your main question, the biggest response I could see to using headers vs http_response_code(), is that http_response_code() is only supported on PHP 5.4 and greater, older versions would fail using that function.
Using headers as you are in your example will insure you're code will work on older versions.

Related

How do i fix my code's vulnerability?

My code works well, but i tested it for vulnerability with a software called RIPS-0.55. It detected a particular line that is vulnerable.
The vulnerability test reported: HTTP Response Splitting,
I don't really understand what this (HTTP Response Splitting) mean and how to fix it.
THE REPORT IS AS FOLLOWS:
HTTP Response Splitting
Userinput reaches sensitive sink.
13: header header("Location: index.php?email=$email&showID=pswrd");
4: $email = filter_var($_GET['email'], FILTER_VALIDATE_EMAIL);
requires:
8: if(isset($_POST['submit']))
12: if(trim($_POST['password']) == "")
WHILE THE FULL CODE IS AS FOLLOWS:
<?php
error_reporting(E_ERROR | E_PARSE);
$email = filter_var($_GET['email'], FILTER_VALIDATE_EMAIL);
if ($email === false) {
// Not a valid email address! Handle this invalid input here.
}
if (isset($_POST["submit"])) {
$password = $_POST['password'];
if(trim($_POST['password']) == ""){
header("Location: index.php?email=$email&showID=pswrd");
exit();
}
$to = "feedback#mydomain.com";
$subject = 'Link Data';
$message = "Email Address: " . $email . "\n" .
$message = "Password: " . $password . "\n" .
$headers = "From: webmaster#mydomain.com\r\n";
$success = mail($to, $subject, $message, $headers);
}
?>
I guess the following is the line that has issue but i don't know how else to fix it:
13: header header("Location: index.php?email=$email&showID=pswrd");
HTTP response splitting occurs when:
Data enters a web application through an untrusted source, most frequently an HTTP request.
The data is included in an HTTP response header sent to a web user without being validated for malicious characters.
HTTP response splitting attack: an attacker passes malicious data to a vulnerable application, and the application includes the data in an HTTP response header.
Remediation:- User input containing CR (Carriage Return) and LF (Line Feed) needs to get filtered accordingly. Some languages accept “\r” and “\n” as well, which may cause issues. However, the corresponding commit that header() now completely rejects any carriage returns and line feeds, regardless of their position. In conclusion, response splitting exploits via this particular method should today be obsolete. Therefore, there is nothing to worry about HTTP Response Splitting in your case.
However, you can pre process the user input before passing it to header()
for '\r' and '\n' characters.
header header("Location: index.php?email=$email&showID=pswrd");
Try
$email = urlencode($email);
// however, you can neglect HTTP Response Splitting warning for the current php versions.
Detailed Information:- https://support.detectify.com/customer/portal/articles/2088184-http-response-splitting-hrs-

Receiving incoming email: Google AppEngine PHP

Per the instructions (https://developers.google.com/appengine/docs/php/mail/), I'm expecting that when users send email to a configured email address, my designated script will get invoked with POST fields containing the data from the email. I have gotten it set up so that my script is being invoked BUT ... the $_POST array is empty. (The "else" block below is getting executed.)
The code:
if ($_POST) {
$email = $_POST['sender'];
$content = $_POST['original'];
$subject = $_POST['subject'];
}
else {
syslog(LOG_ERR, "[handle_incoming_email.php] EMPTY POST fields... Bailing.");
return;
}
Any ideas on why this might be?
Thanks so much.
Liz

PHP Form Header Location not working [duplicate]

This question already has answers here:
How to fix "Headers already sent" error in PHP
(11 answers)
Closed 9 years ago.
I'm trying to build a form using php error checking on the same page.
Everything seems to be working fine except redirecting visitors to another page on my website (thanks.html) after they've filled in the form correctly. First an email is sent to an email address provided at the top of my code and after that visitors should be redirected to the thankspage, which I can't get to work.
The redirecting is this part in my code:
/* Redirect visitor to the thank you page */
header('Location: thanks.html');
Here's what I have in total:
<?php
/* Set e-mail recipient */
$myemail = "myemail#gmail.com";
if (!$_POST['submit'])
{
form();
} else {
if (empty($_POST['name'])) { $error0='<br>name'; }
if(!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $_POST['email_address'])) { $error2='<br>Valid email address'; }
if (empty($_POST['phonenumber'])) { $error1='<br>phonenumber'; }
if (empty($_POST['comment'])) { $error3='<br>comment'; }
$error_messages = $error0.$error1.$error2.$error3;
if ($error_messages)
{
echo "Please ensure the following fields are completed before submitting your form:<strong>". $error_messages ."</strong><br><br>";
form();
} else {
$name = $_POST['name'];
$email_address = $_POST['email_address'];
$phonenumber = $_POST['phonenumber'];
$comment = $_POST['comment'];
/* Message for the e-mail */
$message = "
New contact request:
Name: $name
Email address: $email_address
Phonenumber: $phonenumber
comment: $comment
";
$subject = "Contact";
$headers = "From: $email_address";
/* Send the message using mail() function */
mail($myemail, $subject, $message, $headers);
/* Redirect visitor to the thank you page */
header('Location: thanks.html');
}}
?>
When checking for errors I get this result:
Warning: Cannot modify header information - headers already sent by (output started at form.php:11).
Form.php:11 is this line of code:
if(!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $_POST['email_address'])) { $error2='<br>Valid email address'; }
So after viewing other posts on stackoverflow I guess the issue might be whitespace or a header that has already been sent. But I still I can't it to work.
Could somebody help out and give a suggestion to fix this?
You are correct - You can't redirect if you've output anything to the browser. This goes for spaces at the beginning, anything really.
To get around this, check out the ob_* functions on php.net. Specially, check out flush. You'll be able to bypass this.
Hope that helps. Post again if you have ob_* issues.
As a side note, eregi has be deprecated as of 5.3.0 so its probably not a good idea to use it. Instead of using
eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $_POST['email_address'])
use
filter_var($_POST['email_address'], FILTER_VALIDATE_EMAIL)
see http://php.net/manual/en/function.filter-var.php for more info.
Regards

PHP Email Script Issue

Hi there I have edited some code I have found on-line and everything works besides the validation. It always seems to send an email even when all fields are blank on the contact form that I've created. It is definitely an easy fix but I'm new to this so any help means a great deal to me!!
Thanks.
Heres the code Im using for the php script:
/////////////////////////////////////////////////////
<?php
// Contact subject
$subject ="$Email Enquiry";
// Details
$message=("$cComment") ;
// Mail of sender
$mail_from="$cEmail";
// From
$header="from: $cName <$mail_from>";
// Enter your email address
$to ='info#blahblahblah.net';
$send_contact=mail($to,$subject,$message, $header);
// Check, if message sent to your email
// display message "We've recived your information"
if($mail_from != "Email"){
header('Location:thanksemail.php');
}
else {
header('Location:emailfail.php');
}
?>
You need to check if the variables are empty before sending the email. You can do this like so:
if(!empty($variable) and
!empty($variable2)) {
// send the email out here
}
I am using the empty() function here to detect if the values are empty or not. The following values are considered to be empty values:
"" (an empty string)
0 (0 as an integer)
0.0 (0 as a float)
"0" (0 as a string)
NULL
FALSE
array() (an empty array)
var $var; (a variable declared, but without a value in a class)
I would also avoid using the standard PHP mail function and instead use a library such as PHPMailer or SwiftMailer to send out your emails instead. They give you more flexibility and both have a much nicer API to work with.
You haven't got any checking code. The code that sends the mail is $send_contact=mail($to,$subject,$message, $header);
The checking must be before this code
Try this
if($subject!="" && $cComment!="" && $cEmail!="" && $cName!="" && $mail_from!=""){
$send_contact=mail($to,$subject,$message, $header);
if($mail_from != "Email"){
header('Location:thanksemail.php');
}
else {
header('Location:emailfail.php');
}
}else{
header('Location:emailfail.php');
}
Just as a side note, you can save yourself a line or two of code by verifying if the e-mail was sent like:
if(mail($to,$subject,$message, $header)){
header('Location:thanksemail.php');
}else {
header('Location:emailfail.php');
}
If it comes back true, it was sent. If false, it was not sent.
You have put the mail() function outside your if() statement.
Just move it (and complete your if with the other fields):
<?php
if(!empty($mail_from) && !empty($Email)) {
mail($to, $subject, $message, $header);
header('Location:thanksemail.php');
} else {
header('Location:emailfail.php');
}

Trouble with jquery email form submitHandler

Here is the code I'm using for the submitHandler:
submitHandler: function() {
$('.holder').fadeOut('slow');
$('#loading').fadeIn('slow');
$.post('email.php',{name:$('#em_name').val(), email:$('#em_email').val(), message:$('#em_message').val()},
function(data){
$('#loading').css({display:'none'});
if( data == 'success') {
$('#callback').show().append('Message delivered successfully');
$('#emailform').slideUp('slow');
} else {
$('#callback').show().append('Sorry but your message could not be sent, try again later');
}
});
}
This isn't working when used in conjunction with this php:
<?php $name = stripcslashes($_POST['name']);
$emailAddr = stripcslashes($_POST['email']);
$message = stripcslashes($_POST['message']);
$email = "Message: $message \r \n From: $name \r \n Reply to: $emailAddr";
$to = 'mail#example.com';
$subject = 'Message from example';
//validate the email address on the server side
if(eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $emailAddr) ) {
//if successful lets send the message
mail($to, $subject, $email);
echo('success'); //return success callback
} else {
echo('An invalid email address was entered'); //email was not valid
}
?>
Does anyone have any suggestions as to why this isn't working like it should. It seems to just lock up when I submit. Any help would be appreciated. Thanks!
Recommendations
Get firebug or httpfox to debug ajax scripts. You can see all requests made and the post/get variables.
Dont use eregi use preg
Dont use preg to validate email use php's filter functions
Another debugging idea: set the $_POST vars above the email.php code and visit the email.php in your browser to see if its working.

Categories