Jump to content

All Activity

This stream auto-updates

  1. Today
  2. Hi everyone, I'm working on a project that involves pet-related content, specifically about male cats. I want to add an anchor text in HTML that links to my website with the word kedi (which means "cat" in Turkish). Here’s what I’m trying to achieve: I want to link the word kedi with my url (Mentioned in anchor text) Is this the correct and SEO-friendly way to do it? Also, does adding rel="nofollow" or target="_blank" impact SEO in such internal linking cases? Any tips would be appreciated
  3. Which is a bad fix. What you did was make your site dramatically less secure, by allowing people to create cookies without going through https:// which is a really bad idea. Is this an issue that only comes up in development, perhaps because you don't have a local cert installed? When you have a problem you really have to do a better job of describing the environment under which you had a problem. 99% of the time, if you had working code and it stops working, there is an explanation for that having to do with some environmental change. One tip: on your register/login script, as with any other pure PHP scripts, you should remove the ending PHP tag. I believe that someone else explained to you on another thread, that using session variables to handle bad login attempts and lockouts is another really bad idea. People wanting to brute force won't accept a session cookie, so all that logic will have no effect on those people or their automated brute force scripting. You have to log bad attempts using some sort of persistence (typically a table related to your user table) which include the datetime/timestamp and the IP address. You can then lock out an account for a period of time, as well as locking out IP addresses that might be trying a range of different email/password combinations. You want to prevent both.
  4. Yesterday
  5. for anybody wondering I fixed it I changed setcookie('email', $email, time() + (60 * 60 * 24 * 30), "/", "", true, true); to setcookie('email', $email, time() + (60 * 60 * 24 * 30), "/", "", false, true);
  6. my code was working jus fine yesterday but when I woke up today and tried it out it wouldn't create cookies, and I'm wondering why? <?php session_start(); require_once 'config.php'; if (!isset($_SESSION['email']) && isset($_COOKIE['email'], $_COOKIE['remember_token'])) { $email = $_COOKIE['email']; $token = $_COOKIE['remember_token']; $stmt = $conn->prepare("SELECT u.*, rt.token FROM users u INNER JOIN remember_tokens rt ON u.id = rt.user_id WHERE u.email = ? AND rt.token = ? AND rt.expires_at > NOW()"); $stmt->bind_param("ss", $email, $token); $stmt->execute(); $result = $stmt->get_result(); if ($result->num_rows > 0) { $user = $result->fetch_assoc(); // Set session variables $_SESSION['username'] = $user['username']; $_SESSION['email'] = $user['email']; $_SESSION['role'] = $user['role']; $_SESSION['location'] = $user['location']; $_SESSION['used_remember_me'] = true; $newToken = bin2hex(random_bytes(32)); $expiresAt = date('Y-m-d H:i:s', time() + (60 * 60 * 24 * 30)); $updateStmt = $conn->prepare("UPDATE remember_tokens SET token = ?, expires_at = ? WHERE user_id = ?"); $updateStmt->bind_param("ssi", $newToken, $expiresAt, $user['id']); $updateStmt->execute(); $updateStmt->close(); setcookie('remember_token', $newToken, time() + (60 * 60 * 24 * 30), "/", "", true, true); if ($user['role'] === 'admin') { header("Location: admin.php"); } else { header("Location: index.php"); } exit(); } else { setcookie('remember_token', '', time() - 3600, "/"); setcookie('email', '', time() - 3600, "/"); } $stmt->close(); } $errors = [ 'login' => $_SESSION['login_error'] ?? '', 'register' => $_SESSION['register_error'] ?? '' ]; $successMessage = $_SESSION['register_success'] ?? ''; $activeForm = $_SESSION['active_form'] ?? 'login'; $loginAttempts = $_SESSION['login_attempts'] ?? 0; $lockoutTime = $_SESSION['lockout_time'] ?? 0; unset($_SESSION['login_error'], $_SESSION['register_error'], $_SESSION['register_success'], $_SESSION['active_form']); function showError($error) { return !empty($error) ? "<p class='error-message'>" . htmlspecialchars($error) . "</p>" : ""; } function showSuccess($message) { return !empty($message) ? "<p class='success-message'>" . htmlspecialchars($message) . "</p>" : ""; } function isActiveForm($formName, $activeForm) { return $formName === $activeForm ? 'active' : ''; } $currentTime = time(); $remainingLockoutTime = 0; $isLocked = false; if ($loginAttempts >= 3) { if (($currentTime - $lockoutTime) < 40) { $isLocked = true; $remainingLockoutTime = 40 - ($currentTime - $lockoutTime); } else { $_SESSION['login_attempts'] = 0; $_SESSION['lockout_time'] = 0; } } ?> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f5f5f5; } .container { display: flex; flex-direction: column; justify-content: center; align-items: center; min-height: 100vh; width: 100%; padding: 20px; box-sizing: border-box; } .form-box { width: 100%; max-width: 450px; padding: 30px; background: #0061af; border-radius: 10px; display: none; margin: 10px 0; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); } .form-box.active { display: block; } .logo-container { text-align: center; margin-bottom: 20px; } .logo-container img { width: 120px; height: auto; } h2 { font-size: 28px; text-align: center; margin-bottom: 20px; color: white; } input, select { width: 100%; padding: 12px; border: none; outline: none; font-size: 16px; margin-bottom: 20px; border-radius: 6px; background-color: rgba(255, 255, 255, 0.9); } button { display: flex; align-items: center; justify-content: center; background-color: #f3f7fe; color: #3b82f6; border: none; cursor: pointer; border-radius: 8px; width: 100%; height: 45px; transition: 0.3s; text-decoration: none; font-size: 16px; font-weight: 600; margin-bottom: 15px; } button:hover { background-color: #3b82f6; box-shadow: 0 0 0 5px #3b83f65f; color: #fff; } .error-message { padding: 12px; background: #f8d7da; border-radius: 6px; color: #a42834; text-align: center; margin-bottom: 20px; } .success-message { padding: 12px; background: #d4edda; border-radius: 6px; color: #155724; text-align: center; margin-bottom: 20px; } .form-footer { text-align: center; color: white; margin-top: 15px; } .form-footer a { color: #aad4ff; text-decoration: none; } .form-footer a:hover { text-decoration: underline; } .sso-button { background-color: #0078d4 !important; color: white !important; } .sso-button:hover { background-color: #106ebe !important; box-shadow: 0 0 0 5px rgba(0, 120, 212, 0.3) !important; } .divider { display: flex; align-items: center; margin: 20px 0; color: white; } .divider::before, .divider::after { content: ""; flex: 1; border-bottom: 1px solid rgba(255, 255, 255, 0.3); } .divider-text { padding: 0 10px; } ::-webkit-scrollbar { width: 10px; } ::-webkit-scrollbar-track { background: #f1f1f1; } ::-webkit-scrollbar-thumb { background: #0061af; } ::-webkit-scrollbar-thumb:hover { background: #0363b1; } #countdown { padding: 12px; background: #ffeeba; border-radius: 6px; color: #856404; text-align: center; margin-bottom: 20px; font-weight: bold; } .remember-me { display: flex; align-items: center; margin-bottom: 20px; color: white; } .remember-me input { width: auto; margin-right: 10px; margin-bottom: 0; } </style> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ALnasser | Ticketing System</title> <link rel="icon" type="image/x-icon" href="alnasser.png"> <link href="style.css" rel="stylesheet" type="text/css"> </head> <body> <div class="container"> <div class="form-box <?= isActiveForm('login', $activeForm); ?>" id="login-form"> <form action="login_register.php" method="post"> <center><img width="30%" height="auto" src="alnasser_nobg.png" alt="ALnasser Logo"></center> <h2>Login</h2> <?= showError($errors['login']); ?> <button type="button" class="sso-button" onclick="window.location.href='windows_login.php'"> Sign in with Windows Domain Account </button> <div class="divider"><span class="divider-text">OR</span></div> <input type="email" name="email" placeholder="Email" required> <input type="password" name="password" placeholder="Password" required> <div class="remember-me"> <input type="checkbox" id="remember_me" name="remember_me"> <label for="remember_me">Remember me for 30 days</label> </div> <?php if ($isLocked): ?> <div id="countdown">Too many failed attempts. Please try again in <span id="time"></span> seconds.</div> <button type="submit" name="login" disabled style="cursor: not-allowed; background-color: #ccc;">Login</button> <?php else: ?> <button type="submit" name="login">Login</button> <?php endif; ?> <p class="form-footer">Don't have an account? <a href="#" onclick="showForm('register-form')">Register</a></p> </form> </div> <div class="form-box <?= isActiveForm('register', $activeForm); ?>" id="register-form"> <form action="login_register.php" method="post"> <center><img width="30%" height="auto" src="alnasser_nobg.png" alt="ALnasser Logo"></center> <h2>Register</h2> <?= showError($errors['register']); ?> <?= showSuccess($successMessage); ?> <input type="text" name="username" placeholder="Username" required> <input type="email" name="email" placeholder="Email" pattern="[a-zA-Z0-9._%+-]+@alnasser\.eg$" required> <input type="password" name="password" placeholder="Password" required> <select name="role" required> <option value="">--Select Role--</option> <option value="user">User</option> <option value="admin">Admin</option> <option value="technician">Technician</option> </select> <select name="location" required> <option value="">--Select Location--</option> <option value="Asiout">Asiout</option> <option value="Zizinia">Zizinia</option> <option value="Aswan">Aswan</option> <option value="Helwan">Helwan</option> <option value="Menia">Menia</option> <option value="Mokattam">Mokattam</option> <option value="Arcadia">Arcadia</option> <option value="October">October</option> <option value="Tagamoa">Tagamoa</option> <option value="Maadi">Maadi</option> <option value="Heliopolis">Heliopolis</option> <option value="Nasr city">Nasr city</option> <option value="Obour">Obour</option> <option value="Qena">Qena</option> <option value="Smouha">Smouha</option> <option value="Haram">Haram</option> <option value="Sohag1">Sohag1</option> <option value="Bani Suef">Bani Suef</option> <option value="Mohandseen">Mohandseen</option> <option value="Tanta">Tanta</option> <option value="Mahalla">Mahalla</option> <option value="Zaqaziq">Zaqaziq</option> <option value="Shebeen">Shebeen</option> <option value="Qusseya">Qusseya</option> <option value="Mansoura2">Mansoura2</option> <option value="Luxor">Luxor</option> <option value="Damanhor">Damanhor</option> <option value="Hadayek">Hadayek</option> <option value="Agami">Agami</option> <option value="Suez">Suez</option> <option value="Fisal">Fisal</option> <option value="ismailia">ismailia</option> <option value="Mansoura 3">Mansoura 3</option> <option value="Abas el3qad">Abas el3qad</option> <option value="mohy eldeen">mohy eldeen</option> <option value="Sohag2">Sohag2</option> <option value="Zaharaa El-Maadi">Zaharaa El-Maadi</option> <option value="Gesr Al-Suez">Gesr Al-Suez</option> <option value="Shoubra">Shoubra</option> <option value="Fayoum">Fayoum</option> <option value="Hurghada">Hurghada</option> <option value="Sharm ElSheikh">Sharm ElSheikh</option> <option value="Mashaal">Mashaal</option> <option value="Victoria">Victoria</option> <option value="Al Rehab">Al Rehab</option> <option value="Madinaty">Madinaty</option> <option value="Mall of Egypt">Mall of Egypt</option> <option value="Gardenia">Gardenia</option> <option value="Tanta 2">Tanta 2</option> <option value="Port Said">Port Said</option> <option value="Town Center Mall">Town Center Mall</option> <option value="Office">Office</option> <option value="Online">Online</option> </select> <button type="submit" name="register">Register</button> <p class="form-footer">Already have an account? <a href="#" onclick="showForm('login-form')">Login</a></p> </form> </div> </div> <script src="script.js"></script> <script> <?php if ($isLocked): ?> let remainingTime = <?= $remainingLockoutTime ?>; const countdownElement = document.getElementById('time'); function updateCountdown() { if (remainingTime > 0) { countdownElement.textContent = remainingTime; remainingTime--; setTimeout(updateCountdown, 1000); } else { window.location.reload(); } } updateCountdown(); <?php endif; ?> function showForm(formId) { document.querySelectorAll('.form-box').forEach(box => box.classList.remove('active')); document.getElementById(formId).classList.add('active'); } window.onload = function() { const activeFormId = '<?= htmlspecialchars($activeForm) ?>-form'; showForm(activeFormId); }; </script> </body> </html> <?php session_start(); require_once 'config.php'; if (isset($_POST['register'])) { $username = trim($_POST['username']); $email = trim($_POST['email']); $password_raw = $_POST['password']; $role = $_POST['role']; $location = $_POST['location']; if (!preg_match('/^[a-zA-Z0-9_]+$/', $username)) { $_SESSION['register_error'] = 'Username can only contain letters, numbers, and underscores.'; $_SESSION['active_form'] = 'register'; header("Location: login&signup.php"); exit(); } if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $_SESSION['register_error'] = 'Invalid email format.'; $_SESSION['active_form'] = 'register'; header("Location: login&signup.php"); exit(); } if (!preg_match('/@alnasser\.eg$/', $email)) { $_SESSION['register_error'] = 'Only @alnasser.eg email addresses are allowed.'; $_SESSION['active_form'] = 'register'; header("Location: login&signup.php"); exit(); } if (strlen($password_raw) < 8 || !preg_match('/[A-Za-z]/', $password_raw) || !preg_match('/[0-9]/', $password_raw) || !preg_match('/[^A-Za-z0-9]/', $password_raw)) { $_SESSION['register_error'] = 'Password must be at least 8 characters long and include letters, numbers, and symbols.'; $_SESSION['active_form'] = 'register'; header("Location: login&signup.php"); exit(); } $password_hashed = password_hash($password_raw, PASSWORD_DEFAULT); $stmt = $conn->prepare("SELECT email FROM users WHERE email = ?"); $stmt->bind_param("s", $email); $stmt->execute(); $checkEmail = $stmt->get_result(); if ($checkEmail->num_rows > 0) { $_SESSION['register_error'] = 'Email is already registered.'; $_SESSION['active_form'] = 'register'; } else { $stmt = $conn->prepare("INSERT INTO users (username, email, password, role, location) VALUES (?, ?, ?, ?, ?)"); $stmt->bind_param("sssss", $username, $email, $password_hashed, $role, $location); if ($stmt->execute()) { $_SESSION['active_form'] = 'login'; $_SESSION['register_success'] = 'Registration successful! Please login.'; } else { error_log("Registration failed: " . $stmt->error); $_SESSION['register_error'] = 'Registration failed. Please try again.'; $_SESSION['active_form'] = 'register'; } } $stmt->close(); $conn->close(); header("Location: login&signup.php"); exit(); } if (isset($_POST['login'])) { $email = trim($_POST['email']); $password = $_POST['password']; $loginAttempts = $_SESSION['login_attempts'] ?? 0; $lockoutTime = $_SESSION['lockout_time'] ?? 0; $currentTime = time(); if ($loginAttempts >= 3 && ($currentTime - $lockoutTime < 40)) { $_SESSION['login_error'] = 'Account locked due to too many failed attempts. Please wait.'; $_SESSION['active_form'] = 'login'; header("Location: login&signup.php"); exit(); } if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $_SESSION['login_error'] = 'Invalid email format.'; $_SESSION['active_form'] = 'login'; header("Location: login&signup.php"); exit(); } if (!preg_match('/@alnasser\.eg$/', $email)) { $_SESSION['login_error'] = 'Only @alnasser.eg email addresses are allowed.'; $_SESSION['active_form'] = 'login'; header("Location: login&signup.php"); exit(); } $stmt = $conn->prepare("SELECT * FROM users WHERE email = ?"); $stmt->bind_param("s", $email); $stmt->execute(); $result = $stmt->get_result(); if ($result->num_rows > 0) { $user = $result->fetch_assoc(); if (password_verify($password, $user['password'])) { $_SESSION['username'] = $user['username']; $_SESSION['email'] = $user['email']; $_SESSION['role'] = $user['role']; $_SESSION['location'] = $user['location']; $_SESSION['login_attempts'] = 0; $_SESSION['lockout_time'] = 0; if (!empty($_POST['remember_me'])) { $token = bin2hex(random_bytes(32)); $expiresAt = date('Y-m-d H:i:s', time() + (60 * 60 * 24 * 30)); // 30 days $cleanupStmt = $conn->prepare("DELETE FROM remember_tokens WHERE user_id = ?"); $cleanupStmt->bind_param("i", $user['id']); $cleanupStmt->execute(); $cleanupStmt->close(); $tokenStmt = $conn->prepare("INSERT INTO remember_tokens (user_id, token, expires_at, created_at) VALUES (?, ?, ?, NOW())"); $tokenStmt->bind_param("iss", $user['id'], $token, $expiresAt); if ($tokenStmt->execute()) { setcookie('email', $email, time() + (60 * 60 * 24 * 30), "/", "", true, true); setcookie('remember_token', $token, time() + (60 * 60 * 24 * 30), "/", "", true, true); $_SESSION['used_remember_me'] = true; } else { error_log("Failed to store remember token: " . $tokenStmt->error); } $tokenStmt->close(); } else { setcookie('remember_token', '', time() - 3600, "/"); setcookie('email', '', time() - 3600, "/"); $cleanupStmt = $conn->prepare("DELETE FROM remember_tokens WHERE user_id = ?"); $cleanupStmt->bind_param("i", $user['id']); $cleanupStmt->execute(); $cleanupStmt->close(); $_SESSION['used_remember_me'] = false; } $stmt->close(); $conn->close(); if ($user['role'] === 'admin') { header("Location: admin.php"); } else { header("Location: index.php"); } exit(); } else { $_SESSION['login_error'] = 'Incorrect email or password.'; $_SESSION['active_form'] = 'login'; $_SESSION['login_attempts'] = $loginAttempts + 1; if ($_SESSION['login_attempts'] >= 3) { $_SESSION['lockout_time'] = $currentTime; } } } else { $_SESSION['login_error'] = 'Incorrect email or password.'; $_SESSION['active_form'] = 'login'; $_SESSION['login_attempts'] = $loginAttempts + 1; if ($_SESSION['login_attempts'] >= 3) { $_SESSION['lockout_time'] = $currentTime; } } $stmt->close(); $conn->close(); header("Location: login&signup.php"); exit(); } ?>
  7. Last week
  8. here are some implementation practices - the form processing code and form should be on the same page. by putting them on separate pages, you are creating a lot of extra code. by only validating one input at a time and not having the form fields 'sticky', you are providing a poor User eXperience (UX). by storing the 'login_attempts' and 'lockout_time' in session variables, a nefarious user/bot can get unlimited new login attempts by simply not propagating the session id cookie between requests. you must store this data persistently on the server in a database table. the only user related value you should store in a session variable upon successful login is the user id (autoincrement primary index.) you should query on each page request to get any other user data, so that any changes made to the user data will take effect on the very next page request, without requiring the user to log out and back in again. the way a 'remember me' operation should be implemented is that if the remember me checkbox is checked, at the point of successfully verifying the user's credentials, generate a unique token, store that in a cookie and in a database 'remember me' table that also includes the user id, and the current datatime, for a determining token expiration. on any page request, if the remember me token cookie is set, query to find a matching row in the remember me table. if there is a row and the token is not timed out, use the user id from that row to set the session variable that identifies who the logged in user is. the rest of the code then uses this value in the session variable, just like it was set in the login form processing code. the registration process, unless being performed by an administrator, which your code is not doing, should not include the role. the role should not be something that the user can decide when they register. modern php (8+) uses exceptions for database statement errors by default - connection, query, prepare, and execute. any discrete logic you currently have testing the result of these statements should be removed since it will never get executed upon an error. both the username and email must be unique or you should only use the email and forget about a separate username. the correct way of determining if a unique value already exists in a database table is to define the column(s) as a unique index, just attempt to insert the data, and detect in the exception catch logic for the insert query if a duplicate index error (number) occurred. any form processing code should keep for the form data as a set, in an array variable, then operate on elements in this array variable throughout the rest of the code. i.e. don't write out a line of code copying every $_POST variable to a discrete variable. you need to trim ALL the user supplied inputs, mainly so that you can detect if all white-space characters were entered, before validating the data. you need to use an array to hold user/validation errors, and validate all the inputs at once, storing the errors in the array using the field name as the array index. after the end of the validation logic, if there are no errors (the array will be empty), use the submitted form data. in the login validation logic, all you really care about is that the required inputs are are not empty strings, after being trimmed. by providing additional feedback to a nefarious user/bot, you are helping narrow down the values they need to try.
  9. I want to make it so when the email and password and remember_me cookies expire the user is logged out but only if they originally clicked remember me, if they didn't nothing will happen. how do I go about doing that? when I enter index and the cookies expired if I clicked remember me before it then it redirects to login page. if you didn't click remember me, you don't redirect anywhere and no cookies are there. also want to make the cookie password into a hashed password or token. how can I do this? how do I alter my already written code to do this? <?php session_start(); require_once 'config.php'; if (!isset($_SESSION['email']) && isset($_COOKIE['email'], $_COOKIE['password'], $_COOKIE['remember_me'])) { $email = $_COOKIE['email']; $password = $_COOKIE['password']; $stmt = $conn->prepare("SELECT * FROM users WHERE email = ?"); $stmt->bind_param("s", $email); $stmt->execute(); $result = $stmt->get_result(); if ($result->num_rows > 0) { $user = $result->fetch_assoc(); if (password_verify($password, $user['password'])) { $_SESSION['username'] = $user['username']; $_SESSION['email'] = $user['email']; $_SESSION['role'] = $user['role']; $_SESSION['location'] = $user['location']; if ($user['role'] === 'admin') { header("Location: admin.php"); } else { header("Location: index.php"); } exit(); } } setcookie('remember_me', '', time() - 3600, "/"); setcookie('email', '', time() - 3600, "/"); setcookie('password', '', time() - 3600, "/"); $stmt->close(); } $errors = [ 'login' => $_SESSION['login_error'] ?? '', 'register' => $_SESSION['register_error'] ?? '' ]; $successMessage = $_SESSION['register_success'] ?? ''; $activeForm = $_SESSION['active_form'] ?? 'login'; $loginAttempts = $_SESSION['login_attempts'] ?? 0; $lockoutTime = $_SESSION['lockout_time'] ?? 0; unset($_SESSION['login_error'], $_SESSION['register_error'], $_SESSION['register_success'], $_SESSION['active_form']); function showError($error) { return !empty($error) ? "<p class='error-message'>" . htmlspecialchars($error) . "</p>" : ""; } function showSuccess($message) { return !empty($message) ? "<p class='success-message'>" . htmlspecialchars($message) . "</p>" : ""; } function isActiveForm($formName, $activeForm) { return $formName === $activeForm ? 'active' : ''; } $currentTime = time(); $remainingLockoutTime = 0; $isLocked = false; if ($loginAttempts >= 3) { if (($currentTime - $lockoutTime) < 40) { $isLocked = true; $remainingLockoutTime = 40 - ($currentTime - $lockoutTime); } else { $_SESSION['login_attempts'] = 0; $_SESSION['lockout_time'] = 0; } } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ALnasser | Ticketing System</title> <link rel="icon" type="image/x-icon" href="alnasser.png"> <link href="style.css" rel="stylesheet" type="text/css"> </head> <body> <div class="container"> <div class="form-box <?= isActiveForm('login', $activeForm); ?>" id="login-form"> <form action="login_register.php" method="post"> <center><img width="30%" height="auto" src="alnasser_nobg.png" alt="ALnasser Logo"></center> <h2>Login</h2> <?= showError($errors['login']); ?> <button type="button" class="sso-button" onclick="window.location.href='windows_login.php'"> Sign in with Windows Domain Account </button> <div class="divider"><span class="divider-text">OR</span></div> <input type="email" name="email" placeholder="Email" required> <input type="password" name="password" placeholder="Password" required> <div class="remember-me"> <input type="checkbox" id="remember_me" name="remember_me"> <label for="remember">Remember me for 30 days</label> </div> <?php if ($isLocked): ?> <div id="countdown">Too many failed attempts. Please try again in <span id="time"></span> seconds.</div> <button type="submit" name="login" disabled style="cursor: not-allowed; background-color: #ccc;">Login</button> <?php else: ?> <button type="submit" name="login">Login</button> <?php endif; ?> <p class="form-footer">Don't have an account? <a href="#" onclick="showForm('register-form')">Register</a></p> </form> </div> <div class="form-box <?= isActiveForm('register', $activeForm); ?>" id="register-form"> <form action="login_register.php" method="post"> <center><img width="30%" height="auto" src="alnasser_nobg.png" alt="ALnasser Logo"></center> <h2>Register</h2> <?= showError($errors['register']); ?> <?= showSuccess($successMessage); ?> <input type="text" name="username" placeholder="Username" required> <input type="email" name="email" placeholder="Email" pattern="[a-zA-Z0-9._%+-]+@alnasser\.eg$" required> <input type="password" name="password" placeholder="Password" required> <select name="role" required> <option value="">--Select Role--</option> <option value="user">User</option> <option value="admin">Admin</option> <option value="technician">Technician</option> </select> <select name="location" required> <option value="">--Select Location--</option> <option value="Asiout">Asiout</option> <option value="Zizinia">Zizinia</option> <option value="Aswan">Aswan</option> <option value="Helwan">Helwan</option> <option value="Menia">Menia</option> <option value="Mokattam">Mokattam</option> <option value="Arcadia">Arcadia</option> <option value="October">October</option> <option value="Tagamoa">Tagamoa</option> <option value="Maadi">Maadi</option> <option value="Heliopolis">Heliopolis</option> <option value="Nasr city">Nasr city</option> <option value="Obour">Obour</option> <option value="Qena">Qena</option> <option value="Smouha">Smouha</option> <option value="Haram">Haram</option> <option value="Sohag1">Sohag1</option> <option value="Bani Suef">Bani Suef</option> <option value="Mohandseen">Mohandseen</option> <option value="Tanta">Tanta</option> <option value="Mahalla">Mahalla</option> <option value="Zaqaziq">Zaqaziq</option> <option value="Shebeen">Shebeen</option> <option value="Qusseya">Qusseya</option> <option value="Mansoura2">Mansoura2</option> <option value="Luxor">Luxor</option> <option value="Damanhor">Damanhor</option> <option value="Hadayek">Hadayek</option> <option value="Agami">Agami</option> <option value="Suez">Suez</option> <option value="Fisal">Fisal</option> <option value="ismailia">ismailia</option> <option value="Mansoura 3">Mansoura 3</option> <option value="Abas el3qad">Abas el3qad</option> <option value="mohy eldeen">mohy eldeen</option> <option value="Sohag2">Sohag2</option> <option value="Zaharaa El-Maadi">Zaharaa El-Maadi</option> <option value="Gesr Al-Suez">Gesr Al-Suez</option> <option value="Shoubra">Shoubra</option> <option value="Fayoum">Fayoum</option> <option value="Hurghada">Hurghada</option> <option value="Sharm ElSheikh">Sharm ElSheikh</option> <option value="Mashaal">Mashaal</option> <option value="Victoria">Victoria</option> <option value="Al Rehab">Al Rehab</option> <option value="Madinaty">Madinaty</option> <option value="Mall of Egypt">Mall of Egypt</option> <option value="Gardenia">Gardenia</option> <option value="Tanta 2">Tanta 2</option> <option value="Port Said">Port Said</option> <option value="Town Center Mall">Town Center Mall</option> <option value="Office">Office</option> <option value="Online">Online</option> </select> <button type="submit" name="register">Register</button> <p class="form-footer">Already have an account? <a href="#" onclick="showForm('login-form')">Login</a></p> </form> </div> </div> <script src="script.js"></script> <script> <?php if ($isLocked): ?> let remainingTime = <?= $remainingLockoutTime ?>; const countdownElement = document.getElementById('time'); function updateCountdown() { if (remainingTime > 0) { countdownElement.textContent = remainingTime; remainingTime--; setTimeout(updateCountdown, 1000); } else { window.location.reload(); } } updateCountdown(); <?php endif; ?> function showForm(formId) { document.querySelectorAll('.form-box').forEach(box => box.classList.remove('active')); document.getElementById(formId).classList.add('active'); } window.onload = function() { const activeFormId = '<?= htmlspecialchars($activeForm) ?>-form'; showForm(activeFormId); }; </script> </body> </html> <?php session_start(); require_once 'config.php'; if (isset($_POST['register'])) { $username = trim($_POST['username']); $email = trim($_POST['email']); $password_raw = $_POST['password']; $role = $_POST['role']; $location = $_POST['location']; if (!preg_match('/^[a-zA-Z0-9_]+$/', $username)) { $_SESSION['register_error'] = 'Username can only contain letters, numbers, and underscores.'; $_SESSION['active_form'] = 'register'; header("Location: login&signup.php"); exit(); } if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $_SESSION['register_error'] = 'Invalid email format.'; $_SESSION['active_form'] = 'register'; header("Location: login&signup.php"); exit(); } if (!preg_match('/@alnasser\.eg$/', $email)) { $_SESSION['register_error'] = 'Only @alnasser.eg email addresses are allowed.'; $_SESSION['active_form'] = 'register'; header("Location: login&signup.php"); exit(); } if (strlen($password_raw) < 8 || !preg_match('/[A-Za-z]/', $password_raw) || !preg_match('/[0-9]/', $password_raw) || !preg_match('/[^A-Za-z0-9]/', $password_raw)) { $_SESSION['register_error'] = 'Password must be at least 8 characters long and include letters, numbers, and symbols.'; $_SESSION['active_form'] = 'register'; header("Location: login&signup.php"); exit(); } $password_hashed = password_hash($password_raw, PASSWORD_DEFAULT); $stmt = $conn->prepare("SELECT email FROM users WHERE email = ?"); $stmt->bind_param("s", $email); $stmt->execute(); $checkEmail = $stmt->get_result(); if ($checkEmail->num_rows > 0) { $_SESSION['register_error'] = 'Email is already registered.'; $_SESSION['active_form'] = 'register'; } else { $stmt = $conn->prepare("INSERT INTO users (username, email, password, role, location) VALUES (?, ?, ?, ?, ?)"); $stmt->bind_param("sssss", $username, $email, $password_hashed, $role, $location); if ($stmt->execute()) { $_SESSION['active_form'] = 'login'; $_SESSION['register_success'] = 'Registration successful! Please login.'; } else { error_log("Registration failed: " . $stmt->error); $_SESSION['register_error'] = 'Registration failed. Please try again.'; $_SESSION['active_form'] = 'register'; } } $stmt->close(); $conn->close(); header("Location: login&signup.php"); exit(); } if (isset($_POST['login'])) { $email = trim($_POST['email']); $password = $_POST['password']; $loginAttempts = $_SESSION['login_attempts'] ?? 0; $lockoutTime = $_SESSION['lockout_time'] ?? 0; $currentTime = time(); if ($loginAttempts >= 3 && ($currentTime - $lockoutTime < 40)) { $_SESSION['login_error'] = 'Account locked due to too many failed attempts. Please wait.'; $_SESSION['active_form'] = 'login'; header("Location: login&signup.php"); exit(); } if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $_SESSION['login_error'] = 'Invalid email format.'; $_SESSION['active_form'] = 'login'; header("Location: login&signup.php"); exit(); } if (!preg_match('/@alnasser\.eg$/', $email)) { $_SESSION['login_error'] = 'Only @alnasser.eg email addresses are allowed.'; $_SESSION['active_form'] = 'login'; header("Location: login&signup.php"); exit(); } $stmt = $conn->prepare("SELECT * FROM users WHERE email = ?"); $stmt->bind_param("s", $email); $stmt->execute(); $result = $stmt->get_result(); if ($result->num_rows > 0) { $user = $result->fetch_assoc(); if (password_verify($password, $user['password'])) { $_SESSION['username'] = $user['username']; $_SESSION['email'] = $user['email']; $_SESSION['role'] = $user['role']; $_SESSION['location'] = $user['location']; $_SESSION['login_attempts'] = 0; $_SESSION['lockout_time'] = 0; if (!empty($_POST['remember_me'])) { setcookie('remember_me', '1', time() + (60 * 60 * 24 * 30), "/"); setcookie('email', $_POST['email'], time() + (60* 60 * 24 * 30), "/"); setcookie('password', $_POST['password'], time() + (60* 60 * 24 * 30), "/"); } else { setcookie('remember_me', '', time() - 3600, "/"); setcookie('email', '', time() - 3600, "/"); setcookie('password', '', time() - 3600, "/"); } $stmt->close(); $conn->close(); if ($user['role'] === 'admin') { header("Location: admin.php"); } else { header("Location: index.php"); } exit(); } else { $_SESSION['login_error'] = 'Incorrect email or password.'; $_SESSION['active_form'] = 'login'; $_SESSION['login_attempts'] = $loginAttempts + 1; if ($_SESSION['login_attempts'] >= 3) { $_SESSION['lockout_time'] = $currentTime; } } } else { $_SESSION['login_error'] = 'Incorrect email or password.'; $_SESSION['active_form'] = 'login'; $_SESSION['login_attempts'] = $loginAttempts + 1; if ($_SESSION['login_attempts'] >= 3) { $_SESSION['lockout_time'] = $currentTime; } } $stmt->close(); $conn->close(); header("Location: login&signup.php"); exit(); }
  10. C++ OOP is more complicated, so you should not be having issues picking up PHP OOP. For example, PHP OOP doesn't have templates/ operator overloading or multiple inheritance. The best examples of how to apply OOP are those you find in some of the better known component libraries, and in particular those associated with Symfony and Laravel. For everyday use, you want to learn about the Design Patterns described in the Gang of Four book. You don't have to buy this book to learn about these OOP design patterns but many people do, and it's a common text book from my understanding. There are similar books specific to PHP, but I can't personally vouch for any of them. One of the most important OOP design patterns is the Dependency Injection pattern (sometimes called "Inversion of Control"). There are a number of well regarded frameworks that fundamentally are Dependency Injection frameworks. Spring (for Java) was one of the first I was aware of, and for PHP Symfony and Laravel are both DI frameworks, as are any number of other frameworks, given the advantages of the pattern. You want to read about Dependency Injection. There's an article here, that talks about DI and has some examples: https://php-di.org/doc/understanding-di.html Coming from C++, you should already have a good handle on inheritance, methods, constructors, variable scoping, static variables and methods, etc. You want to learn about PHP Interfaces and more recent PHP additions like traits. For free video material, there are any number of tutorials and free courses that cover PHP OOP. I have frequently recommended this channel, and many experienced PHP developers seem to agree with me, that he does a good job covering the syntax and providing examples.
  11. Hello developers , I am learning PHP and I have an obstacle at OOP, when I read about it on any website like w3school I understand most of it but I don't know how to apply on it , and when I went to move towards in PHP I see that this thing need deep knowledge about OOP and I move in this cycle , NOTE: I already learned OOP with C++ in college so I just read about OOP in PHP and I don't see full course on youtube because I don't want to hear the same principle again , if what I am doing is wrong please tell me . Thank You.
  12. @mac_gyver yes, I had discovered that, but it wasn't the actual fix. The real issue was that my test for is_file was flawed; it didn't drill down to actually test the specified file. if (is_file($subDir)) { //needed to become if (is_file($directory.'/'.$subDir)) { After both adjustments, everything is running better than expected!
  13. the above line is missing any { }, so the only line of code that gets executed for an is_dir() is the - echo '<strong>'.$directory .'</strong> <br>'; all the rest of the lines get executed regardless of what $directory is. i recommend that you always format your code so that you can see when it is actually doing.
  14. I thought this made sense, but it wouldn't work until I removed lines that I thought would provide extra validation: $dir = 'rootFolder'; $directories = scandir($dir); foreach($directories as $directory){ if($directory=='.' or $directory=='..' ){ echo 'dot'; }else{ if(is_dir($directory)) echo '<strong>'.$directory .'</strong> <br>'; $filePath = scandir($directory); foreach($filePath as $subDir){ if($subDir=='.' or $subDir=='..' ){ echo 'dot2 <br>'; }else { // if (is_file($subDir)) { //Only provided PHP files but NO IMAGES echo $subDir . "<br>"; } } // } } } } I'm just feeling down one level of a director to see what I've get. It seemed like a simple exercise until I tried to list the files. Obviously, of it's not a directory it MUST be a file, but why did quantifying it as a file not recognize my files as a file??
  15. Hi Emmanuel, Welcome to the PHP Freaks community! We’re excited to have passionate developers like you join the conversation. At Trophy Developers, we specialize in web design and development in Uganda, and it's always great to connect with fellow professionals who share a deep interest in PHP and building user-focused applications. Your experience across diverse projects sounds impressive, and we’re especially glad to see your enthusiasm for continuous learning and collaboration. If you're ever exploring areas like progressive web apps (PWAs), clean architecture, or performance optimization, we'd be happy to share insights from our work too. Looking forward to learning from your contributions and growing alongside you in this community!
  16. The main issue I see with AI coding tools is that you still need to be able to understand the syntax and code that the AI tools generate. As with anything that is changing rapidly, a significant investment in time is required. From what I've seen demonstrated (and beyond the simple things I have available to me when I'm using VSCode) there are some impressive demonstrations I've seen where new features can be added to existing well structured and formalized code (typically already built in a framework that provides a formalized base) and I could see how AI can be a very effective way of producing what many code generation and boilerplate tools do now, to various degrees of effectiveness. What I've seen in these demonstrations is that the people who are using the tools have spent a lot of time preparing them, determining what types of groundwork and templating is needed, understanding the most effective prompts to construct, and in general, spending a lot of time (and money) in the AI tools. There are also significant privacy and security concerns in sending all of your code up into an AI hive, which is also absorbing that for its own ongoing LLM training. I would also point out that the top practitioners in the PHP development world, employ a variety of tools, and practices, using their IDE and various plugins to produce better tested and more standardized code. Static analysis, unit testing and other automated testing tools, etc. In the world of object oriented programming there is an entire layer of sophistication in regards to the employment of OOP design patterns which are often used by those who have developed expertise and experience. As one quite simple but important example, more than a few PHP frameworks, including the community leading ones (Laravel and Symfony) are built upon the foundational design pattern of Dependency Injection. To be effective with either of these frameworks, a developer needs to know what DI is, what problems it solves, and how to use the pattern in their own code. You generate some AI code, and now you're looking at it, and an obvious question becomes: how is this generated code structured? Does it use a design pattern? If so, which one(s) and were those applied appropriately in regards to the requirements? Did the underlying architecture of the code come with limits or flaws that will only be obvious when the next feature needs to be added? How is a "vibe" coder who doesn't really understand any of these things, or for that matter the application code they generated going to figure this out?
  17. Great advice from mac_gyver. As it happens, there is another recent thread that overlaps here you should check out, as it includes advice on how to design the database structure you can add that will facilitate the type of server side login restriction mechanism.
  18. Earlier
  19. if you use a cookie or the session to hold this data, it can be bypassed by simply deleting the cookie or not propagating the cookie or session id cookie between requests. you must store this data persistently on the server, in a database table. next, you are not trying to lock the account, you are preventing login attempts for an account, from a device (client type) and its location (ip). if you actually lock the account, it will allow someone to log out and lock out a legitimate user, by just making a bunch of bad login attempts for an account. once you have stored the data in a database table, on each login attempt, you would query to find if, how many, and how long ago the bad login attempts were for the account, for the device (client type) and its location (ip). If the current time is greater than the time limit you have chosen from the last bad attempt, you would process the login attempt.
  20. I am trying to set a cookie for my login_system so that when a user enters wrong email or password for three time than I set a cookie for ten minutes I have done that now I want to check that cookie if it is expired if it is than I will let user to try again if not I will keep his account lock for like ten minutes how to do it?
  21. Absolutely, user's often don't logout intentionally, so you can't depend on that event being recorded. In general, you should be interested in any attempted change to their profile or other "escalation of privilege" or change to the core authentication mechanisms (password reset, password change). Many systems will also include and require a 2nd factor authentication at registration, which unless it's a mobile app, will typically be email. So that's another couple of event types you want to log (email authentication failure, email authentication re-request, email authentication success). Even if you are not prepared to make use of IP logging initially, I'd recommend creating the column in the table as analysis of most events you want to be concerned with (like brute force attacks) will necessitate IP logging if you want to understand where the attacks or coming from, or building in automatic countermeasures like time based IP bans.
  22. @gizmola Yes, I had considered IP tracking for the types of instances that you mentioned. Thankfully, this isn't (as of yet) for users that would be ill-intentioned (but it's good to know the expansion potential). As a side note, recording the time of logout seems reasonable when the user clicks the button. But what is the process of the user simply shuts down the browser?
  23. I just want to add a different opinion to the subject. I am more into speed and efficiency and i am always willing to rewrite my own code to find faster and better ways of accomplishing the same tasks. I've spent three years rewriting my website code and it is faster, smarter and better than all of the previous code. I do hate the fact that we do not yet have vision code or machine learning code in php (built-in features added to the language). Vision would be nice here but coding it will be a pain. Anyway, i hate it when people make unnecessary variables and also use long variable names. Each letter used in a variable name is stored in memory. Memory saving code is always better, no matter what someone else will say. I have started using single letter variables and i love it. The code is cleaner and easier to read. Sometimes a legend is necessary as a multi-line comment but the single character variable works. OP: The names array should not be coded in such a manner if it is not to be used in the manner that it is coded (bob_smith will be used as bob_smith). I think that once you start finding reasons to separate the names (last name only), you will discover that this method is not a good idea. I do not know why php coders waste memory with variables and variable names but complain about multi-dimensional arrays. I would rather see someone use a database or a multi-dimensional array when it comes to names. Gizmola pointed out rank, such as Senior (Sr.) or Junior (Jr.), which is a good point. Other naming conventions will also cause a problem. I think that anyone in this position should use a multi-dimensional array which separates first and last names, stores titles and ranks et cetera. Then finding matching names is easier and it simplifies performing other data crunching ideas that have yet to be thought of. And it becomes easier to add info to the arrays or remove info from the arrays. as a note for users that want to save memory, i am including example code that reuses the foreach variable, rather than creating a second or third variable. Also, this code is 2-3 milliseconds faster. I am certain that this code can also be tweaked for speed and memory but it serves as a model of code reusability and memory-saving techniques. I'd like to see more people writing faster, smarter, better code - myself included. $names = ['bob_jones', 'sam_smith', 'jane_doe', 'john_smith', 'jill_jackson', 'matt_jones', 'john_doe', 'emily_smith']; $sn = []; //surnames foreach ($names as $x) { $x = substr($x, strpos($x, '_') +1); empty($sn[$x]) ? $sn[$x] = 1 : $sn[$x]++; } print_r($sn);
  24. "Revolution"? lol. It's another Whatever from the tech world. It's not the first fad used to pump up stock prices, and it won't be the last. The current state of glorified autocomplete systems AI contributes just about as much value to the world as The Blockchain does. You remember that whole thing? Wasn't that long ago when The Blockchain was being called a "revolution" too... The next Whatever will happen in a few weeks, or months, or years, and every publicly-traded company will jump on that as fast as they can too. (Make sure you're not still holding onto all of your NVDA when that happens.) And I'm sure that'll bring its own "revolution" too.
  25. Done this for many systems: 100% agree with Barand. I will go one step further and make this an "event" table where the system can insert rows for other events. Off the top of my head other events (in an event_type table or enum) would be a list like this: login logout bad password attempt change password reset password request etc. A simple table like this is common, has and has the benefit (with proper indexing) of allowing for the types of analysis and controls Barand listed. It also allows for mitigating brute force password attempts, as you can use this table to limit the number of login attempts within a given time period for a specific user, and lock the account after a certain number of attempts. Beyond the relationship to the User table (by Id) and a timestamp, you also typically want to store the IP address of the client. If it's mysql, the best way to do this (and natively support both IPv4 and IPv6) is to store the IP as VARBINARY(16) and use the INET6_ATON() and INET6_NTOA() functions to convert the IP when storing and retrieving. Small tables like this, with a clear design scale very well, as MySQL/MariaDB (using the InnoDB engine) is tuned to maximize Select & Insert concurrency. Often people will attempt to use a column or 2 in the user table, which they repeatedly update (ie. "last_login") which reduces concurrency, and is also less valuable than having a full history.
  26. Logging every login by a registered user is the favoured option. Not only does it give you an audit trail of the logins but it adds functionality, such as being able to count logins in different time periods or determine most popular login times etc.
  27. I'm considering setting up a webpage and tracking logins. For simplicity, let's say an account is required with an email address. So, [email protected] cannot do anything until he created his account. Now I want to know how often he logs in. Is there a recommended or best practice to gathering and storing this data before it becomes cumbersome or unuseful? Or is it as simple as connecting a table that associates a timestamp with every login by a registered user and just letting it run? (I'm wondering if there's something more efficient and less storage reliant)
  28. I recently dabbled with some AI after a webinar that proclaimed its wonders. Luke everything else, some features were good, others not so much. I asked it for some code and immediately recognized the response was accepted from W3. LOL Are there any worthwhile AI applications that are especially helpful for PHP? Javascript? HTML or CSS? Curious, but still prefer finding my own answers and coming to phpfreaks when stumped.
  29. @gizmola Sorry for the delay in my return to comment (but had some personal situations), and yes, I did realize the similarity. I very much wanted to use Barand's method (to try something new and more brief) but it wouldn't operate (I think an extra parenthesis) and the FOREACH solution was more in line with my understanding and existing code. If I recall correctly, I adapted this method successfully. Thanks to all that helped.
  1. Load more activity
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.