<?php
// register_demo_w3.php
// Single-file demo suitable for W3Schools PHP compiler.
// Intent: Demonstrate secure registration flow (CSRF, validation, password_hash) in an environment
// where persistent DB is unavailable. Data is kept in session only for demonstration.
// CSRF token for the session
if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes
(16)); }
$csrf = $_SESSION['csrf_token'];
$errors = [];
$success = null;
// Handle POST submission in same file
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$posted_csrf = $_POST['csrf'] ?? '';
if (empty($posted_csrf) || !hash_equals
($csrf, $posted_csrf)) { $errors[] = 'Invalid CSRF token. Reload and try again.';
} else {
// Normalize inputs
$username = trim((string
)($_POST['username'] ??
'')); $email = trim((string
)($_POST['email'] ??
'')); $password = (string)($_POST['password'] ?? '');
$confirm = (string)($_POST['confirm_password'] ?? '');
if ($username === '') $errors[] = 'Username is required.';
if ($email === '') $errors[] = 'Email is required.';
if ($password === '') $errors[] = 'Password is required.';
if ($confirm === '') $errors[] = 'Please confirm password.';
if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL
)) { $errors[] = 'Invalid email format.';
}
$errors[] = 'Username must be 3–50 characters.';
}
// Password policy
$pw_ok = true;
if (strlen($password) < 8) $pw_ok = false; if (!preg_match('/[A-Z]/', $password)) $pw_ok = false; if (!preg_match('/[a-z]/', $password)) $pw_ok = false; if (!preg_match('/[0-9]/', $password)) $pw_ok = false; if (!preg_match('/[\W_]/', $password)) $pw_ok = false; if (!$pw_ok) $errors[] = 'Password must be 8+ chars and include upper, lower, number and symbol.';
if ($password !== $confirm) $errors[] = 'Passwords do not match.';
// If valid, "save" into session demo storage
if (!isset($_SESSION['demo_users'])) $_SESSION['demo_users'] = [];
foreach ($_SESSION['demo_users'] as $u) {
if ($u['email'] === $email_norm) {
$errors[] = 'An account with this email already exists (demo).';
break;
}
}
$hash = password_hash($password, PASSWORD_DEFAULT);
$_SESSION['demo_users'][] = [
'username' => $username,
'email' => $email_norm,
'password_hash' => $hash,
'created_at' => date(DATE_ATOM
) ];
$success = 'Registration successful (demo users saved to session).';
// rotate token to reduce replay risk
$_SESSION['csrf_token'] = bin2hex(random_bytes
(16)); $csrf = $_SESSION['csrf_token'];
// clear posted values for sticky UI
$_POST = [];
}
}
}
}
// Helper
?>
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><title>Register Demo</title></head>
<body>
<h1>Register (W3Schools Demo)</h1>
<?php if (!empty($errors)): ?> <div style="color:darkred;"><ul><?php foreach ($errors as $e): ?><li><?php echo h($e); ?></li><?php endforeach; ?></ul></div>
<?php endif; ?>
<?php if ($success): ?>
<div style="color:green"><?php echo h($success); ?></div>
<?php endif; ?>
<form method="post" action="">
<input type="hidden" name="csrf" value="<?php echo h($csrf); ?>">
<label>Username:<br><input type="text" name="username" required maxlength="50" value="
<?php echo isset($_POST['username'])?h
($_POST['username']):''; ?>"></label><br><br>
<label>Email:<br><input type="email" name="email" required value="
<?php echo isset($_POST['email'])?h
($_POST['email']):''; ?>"></label><br><br>
<label>Password:<br><input type="password" name="password" required></label><br><br>
<label>Confirm Password:<br><input type="password" name="confirm_password" required></label><br><br>
<button type="submit">Register</button>
</form>
<hr>
<h2>Demo: Registered users (session)</h2>
<?php if (!empty($_SESSION['demo_users'])): ?> <ul>
<?php foreach ($_SESSION['demo_users'] as $u): ?>
<li><?php echo h($u['username']); ?> — <?php echo h($u['email']); ?> — <?php echo h($u['created_at']); ?></li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p>No demo users yet.</p>
<?php endif; ?>
<p><small>Note: This demo stores users in session only. Use a database and stronger infrastructure for production.</small></p>
</body>
</html>