0

(Have spent the entire day with this, partly because PHP, Eclipse and web programming in general are not my specialty. Maybe someone here could help).

My code in register.php won't redirect to verify.php. Here's the code:

header ( "Location: verify.php" );
die ( "Redirecting to activation" );

It simply prints Redirecting to activation in the browser and remains on register.php.

Things that I have already tried:

  • I have ensured that the code actually performs everything up to just above the header line.
  • My file doesn't have any html or white spaces before the <?php block.
  • Adding ob_start() at the top doesn't appear to change anything.
  • the <?php block doesn't have any echo or print.

Edit

As asked, here's the entire register.php:

<?php
require 'config.php';

function isValid() {
    try {
        $url = 'https://www.google.com/recaptcha/api/siteverify';

        $data = array (
                'secret' => 'asdf4234234kljsd32902341',
                'response' => $_POST ['g-recaptcha-response'],
                'remoteip' => $_SERVER ['REMOTE_ADDR']
        );

        $options = array (
                'http' => array (
                        'header' => "Content-type: application/x-www-form-urlencoded\r\n",
                        'method' => 'POST',
                        'content' => http_build_query ( $data )
                )
        );

        $context = stream_context_create ( $options );
        $result = file_get_contents ( $url, false, $context );
        return json_decode ( $result )->success;
    } catch ( Exception $e ) {
        return $e->getMessage ();
    }
}
function RunScalarQuery($db, $q, $params) {
    try {
        $stmt = $db->prepare ( $q );
        $result = $stmt->execute ( $params );
    } catch ( PDOException $ex ) {
        die ( "Failed to run query: " . $ex->getMessage () );
    }

    $row = $stmt->fetch ();
    if ($row)
        return $row [0];
        else
            return null;
}
function SendMail($smtpServer, $username, $pwd, $port, $from, $fromName, $to, $toName, $cc, $bcc, $subject, $body, $altBody) {
    require 'PHPMailerAutoload.php';

    $mail = new PHPMailer ();

    $mail->isSMTP (); // Set mailer to use SMTP
    $mail->Host = $smtpServer; // Specify main and backup SMTP servers
    $mail->SMTPAuth = true; // Enable SMTP authentication
    $mail->Username = $username; // SMTP username
    $mail->Password = $pwd; // SMTP password
    $mail->SMTPSecure = 'ssl'; // Enable TLS encryption, `ssl` also accepted
    $mail->Port = $port; // TCP port to connect to

    $mail->setFrom ( $from, $fromName );
    $mail->addAddress ( $to, $toName ); // Add a recipient
    if (! empty ( $cc ))
        $mail->addCC ( $cc );


        if (! empty ( $bcc ))
            $mail->addBCC ( $bcc );

            $mail->isHTML ( true ); // Set email format to HTML

            $mail->Subject = $subject;
            $mail->Body = $body;
            $mail->AltBody = $altBody;

            if ($mail->send ()) {
                return true;
            } else {
                return $mail->ErrorInfo;
            }
}

ob_start();
if (! empty ( $_POST )) {
    // Ensure that the user fills out fields
    if (empty ( $_POST ['username'] )) {
        die ( "Please enter a username." );
    }
    if (empty ( $_POST ['inputPassword'] )) {
        die ( "Please enter a password." );
    }
    if (! filter_var ( $_POST ['inputEmail'], FILTER_VALIDATE_EMAIL )) {
        die ( "Invalid E-Mail Address" );
    }

    $Res = isValid ();
    if (! $Res) {
        die ( $Res );
    }

    // Check if the username is already taken
    $UsernameExists = RunScalarQuery ( $db, "SELECT 1 FROM `users` WHERE username = :username", array (
            ':username' => $_POST ['username']
    ) );

    if ($UsernameExists != null) {
        die ( "This username is already in use" );
    }

    $EmailExists = RunScalarQuery ( $db, "SELECT 1 FROM `users` WHERE email = :email", array (
            ':email' => $_POST ['email']
    ) );

    if ($EmailExists != null) {
        die ( "This email address is already registered" );
    }

    // Add row to database
    $query = "
    INSERT INTO users (username, password, salt, email, token, ActivationCode)
                VALUES (:username, :password, :salt, :email, :token, :code)";

    // Security measures
    $salt = dechex ( mt_rand ( 0, 2147483647 ) ) . dechex ( mt_rand ( 0, 2147483647 ) );
    $password = hash ( 'sha256', $_POST ['inputPassword'] . $salt );
    for($round = 0; $round < 65536; $round ++) {
        $password = hash ( 'sha256', $password . $salt );
    }

    $token = dechex ( mt_rand ( 0, 2147483647 ) ) . dechex ( mt_rand ( 0, 2147483647 ) );
    $token = hash ( 'sha256', $token );
    for($round = 0; $round < 256; $round ++) {
        $token = hash ( 'sha256', $token . $salt );
    }

    // activation code
    $act_code = mt_rand ( 10000000, 99999999 );

    $query_params = array (
            ':username' => $_POST ['username'],
            ':password' => $password,
            ':salt' => $salt,
            ':email' => $_POST ['inputEmail'],
            ':token' => $token,
            ':code' => $act_code
    );

    try {
        $stmt = $db->prepare ( $query );
        $result = $stmt->execute ( $query_params );
    } catch ( PDOException $ex ) {
        die ( "Failed to run query: " . $ex->getMessage () );
    }

    $_SESSION ['registered_email'] = $_POST ['inputEmail'];

    $mailContent = file_get_contents ( 'VerificationEmail.html' );

    $mailContent = str_replace ( "[UserName]", $_POST ['username'], $mailContent );
    $mailContent = str_replace ( "[Email]", $_POST ['inputEmail'], $mailContent );
    $mailContent = str_replace ( "[Code]", $act_code, $mailContent );
    $mailContent = str_replace ( "[EncodedEmail]", urlencode ( $_POST ['inputEmail'] ), $mailContent );

//  SendMail(...); //localhost version

    SendMail ( ...); //online version

    header ( "Location: verify.php" );
    die ( "Redirecting to activation" );
    exit();
}

$head_content = '<link href="Content/full.css" rel="stylesheet">
                <link href="Content/signin.css" rel="stylesheet">
                <link href="Content/validetta.css" rel="stylesheet" type="text/css" media="screen">
                <script src="https://www.google.com/recaptcha/api.js" async defer></script>';
$body_class = 'class="full"';
$menu_content = '';
$body_content = 'register_body.php';
$script_content = 'register_script.php';
include ('master.php');

ob_flush();
?>
dotNET
  • 33,414
  • 24
  • 162
  • 251
  • 1
    See: http://stackoverflow.com/a/768472/3933332 (*Absolute URL*) – Rizier123 Jun 22 '16 at 21:23
  • @Rizier123: using absolute URL didn't change anything. – dotNET Jun 22 '16 at 21:27
  • @dotNET Does the redirect fails even when you only just have those two lines in the code? – Rizier123 Jun 22 '16 at 21:28
  • 1
    add: `ini_set('display_errors', 'On'); ini_set('html_errors', 0); error_reporting(-1);` to top of register.php –  Jun 22 '16 at 21:29
  • 1
    @JoseManuelAbarcaRodríguez: Added full `register.php` code – dotNET Jun 22 '16 at 21:33
  • How do you ensure that `SendMail ( ...);` is not stopping the script there or crashing? It is even reaching `SendMail ( ...);`? – Jose Manuel Abarca Rodríguez Jun 22 '16 at 21:35
  • Get rid of everything and just keep this one line: `header ( "Location: verify.php" );` What happens? – Thomas Landauer Jun 22 '16 at 21:37
  • @JoseManuelAbarcaRodríguez: I actually receive the sent email in my Mail client. – dotNET Jun 22 '16 at 21:50
  • I would save something in a file BEFORE and AFTER the "header" : `$fil = fopen("test.txt","a"); fwrite($fil, "123"); fclose($fil); `. Save "123" before, and "456" after, for example. – Jose Manuel Abarca Rodríguez Jun 22 '16 at 21:54
  • Wait, replace `fopen("test.txt","w");` by `fopen("test.txt","a");` (oops!). If both lines execute, the file will contain "123456". – Jose Manuel Abarca Rodríguez Jun 22 '16 at 21:57
  • This probably won't fix the issue, but the `header` will redirect before it gets to `die("Redirecting to activation" );` and the `exit;` is redundant. Since you *should* never see the `die( "Redirecting to activation" );` happen, just delete it. – Rasclatt Jun 22 '16 at 22:04
  • 1
    @JoseManuelAbarcaRodríguez From the manual: `die — Equivalent to exit`. The OP is exiting twice, but trying to write to the page with `die()`....but they are redirecting before that...logically that doesn't make sense. – Rasclatt Jun 22 '16 at 22:08
  • 1
    Check your log for a "Headers already sent" warning. – Barmar Jun 22 '16 at 22:10
  • Changed my mind, add `ob_end_clean();` just before `header`. – Jose Manuel Abarca Rodríguez Jun 22 '16 at 22:13
  • 1
    hmm... had to step away for a few minutes. thanks for so many suggestions. not sure what to start with, but i'll try them out and get back. – dotNET Jun 22 '16 at 22:21
  • 1
    @JoseManuelAbarcaRodríguez: LOL. Not that thing. Ramadan days, so I had to take my meal to start day long fast. – dotNET Jun 22 '16 at 22:23
  • @Rasclatt: As I mentioned in the post, I get `Redirecting to activation` line in the browser, so it looks like the `die` line is executing. – dotNET Jun 22 '16 at 22:26
  • Yeah, that is probably messing up your redirect then. Did you remove it and see if it finishes redirecting? If you need messaging, then you may need to have it output that message with a javascript to redirect on a countdown. You can not have browser output in combination with a `header('Location: ....etc');` – Rasclatt Jun 22 '16 at 22:26
  • As @Barmar notes, you may be running into this: http://stackoverflow.com/questions/8028957/how-to-fix-headers-already-sent-error-in-php?rq=1 – Rasclatt Jun 22 '16 at 22:29
  • @Rasclatt Printing something after `header()` shouldn't mess it up, it's only messed up by printing something **before** `header()`. Since the redirect isn't working, he must be printing something before it, and the "Headers already sent" warning message will tell what line that happened on. – Barmar Jun 22 '16 at 22:59
  • @Barmar That is a good point and I stopped and paused on that for a moment, but I never count anything out. It *should* never get to that point as you say and likely has output before. My first comment was that I didn't think it would solve it, but that it was not logical and could be removed (the `die()` portion). – Rasclatt Jun 22 '16 at 23:01
  • @Rasclatt It does get to that point, but the output would be ignored by the browser because it follows the redirect in the header. – Barmar Jun 22 '16 at 23:03
  • @Barmar I think you are right thought, there has to be something before. – Rasclatt Jun 22 '16 at 23:03
  • @Everyone: Phew... figured it out. My `config.php` (first line of the code) had an extra invisible character (like I had to press DEL key twice at the beginning of the file to remove that starting `<` character) at the very start of the file. Don't know where it came from. Removing that char and saving the file got things back on track. Thanks to everyone for participation. Couldn't have discovered it without your input. – dotNET Jun 22 '16 at 23:41

1 Answers1

0

So for any future reader, it is very important to ensure that your script really isn't spitting any content before your issue a redirect. In my case, the script had an invisible, zero-width character at the very start; just before the starting <?php tag. All my attempts to introduce fixes like ob_start() and removing echo and print calls failed till I realized where the problem actually was.

dotNET
  • 33,414
  • 24
  • 162
  • 251