Leaderboard
Popular Content
Showing content with the highest reputation since 06/22/2025 in Posts
-
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.1 point
-
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.1 point
-
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.1 point
-
"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.1 point
-
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.1 point
-
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.1 point
-
One thing that might be helpful is to use the declare to wrap the block of code you want to have evaluated for statement processing. $count = 0; function statements() { global $count; $count++; echo "Statement Count: $count\n"; } register_tick_function('statements'); declare(ticks=5) { for ($x = 0; $x < 10; $x++) { echo "\$x = $x \n"; } } And you get: $x = 0 $x = 1 $x = 2 $x = 3 $x = 4 Statement Count: 1 $x = 5 $x = 6 $x = 7 $x = 8 $x = 9 Statement Count: 21 point
-
E_DEPRECATED and E_USER_DEPRECATED are the same thing, with the one difference that the former is used by the engine and the latter is used by trigger_error. So the question is in what environments do you care/not care about getting messages about using deprecated features and functionality?1 point
-
Thank you gizmola & mac_gyver for your time and help I was aware of the fact that i didnt get anything over, but not sure how to fix that. It works now adding the account number into the url using the $_GET. Yes i am aware of my real url, but thats only for test. Everything will be deleted from that domain when im done1 point
-
Don't. PHP isn't a low-level language like C. You don't have to manage memory like that. PHP has some very smart internal logic and is perfectly capable of handling creating and destroying variables on your behalf. So let it do what it knows how to do.1 point
-
1 point
-
I would suggest using Intervention Library as it makes handling images so much easier. I use the following for my own website -> <?php // Include the configuration file and autoload file from the composer. require_once __DIR__ . '/../config/clearwebconfig.php'; require_once "vendor/autoload.php"; use Intervention\Image\ImageManagerStatic as Image; // Import the ErrorHandler and Database classes from the clearwebconcepts namespace. use clearwebconcepts\{ ErrorHandler, Database, ImageContentManager, LoginRepository as Login }; $errorHandler = new ErrorHandler(); // Register the exception handler method set_exception_handler([$errorHandler, 'handleException']); $database = new Database(); $pdo = $database->createPDO(); $checkStatus = new Login($pdo); // To check for either 'member' or 'sysop' if ($checkStatus->check_security_level(['sysop'])) { // Grant access } else { // Access denied header('location: dashboard.php'); exit(); } function is_ajax_request(): bool { return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest'; } $save_result = false; if (($_SERVER['REQUEST_METHOD'] === 'POST') && isset($_FILES['image'])) { $data = $_POST['cms']; $data['content'] = trim($data['content']); $errors = array(); $exif_data = []; $file_name = $_FILES['image']['name']; // Temporary file: $file_size = $_FILES['image']['size']; $file_tmp = $_FILES['image']['tmp_name']; $thumb_tmp = $_FILES['image']['tmp_name']; $file_type = $_FILES['image']['type']; $file_ext = strtolower(pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION)); /* * Set EXIF data info of image for database table that is * if it contains the info otherwise set to null. */ if ($file_ext === 'jpeg' || $file_ext === 'jpg') { $exif_data = exif_read_data($file_tmp); if (array_key_exists('Make', $exif_data) && array_key_exists('Model', $exif_data)) { $data['Model'] = $exif_data['Make'] . ' ' . $exif_data['Model']; } if (array_key_exists('ExposureTime', $exif_data)) { $data['ExposureTime'] = $exif_data['ExposureTime'] . "s"; } if (array_key_exists('ApertureFNumber', $exif_data['COMPUTED'])) { $data['Aperture'] = $exif_data['COMPUTED']['ApertureFNumber']; } if (array_key_exists('ISOSpeedRatings', $exif_data)) { $data['ISO'] = "ISO " . $exif_data['ISOSpeedRatings']; } if (array_key_exists('FocalLengthIn35mmFilm', $exif_data)) { $data['FocalLength'] = $exif_data['FocalLengthIn35mmFilm'] . "mm"; } } else { $data['Model'] = null; $data['ExposureTime'] = null; $data['Aperture'] = null; $data['ISO'] = null; $data['FocalLength'] = null; } $data['content'] = trim($data['content']); $extensions = array("jpeg", "jpg", "png"); if (in_array($file_ext, $extensions, true) === false) { $errors[] = "extension not allowed, please choose a JPEG or PNG file."; } if ($file_size >= 58720256) { $errors[] = 'File size must be less than or equal to 42 MB'; } /* * Create unique name for image. */ $image_random_string = bin2hex(random_bytes(16)); $image_path = 'assets/image_path/img-entry-' . $image_random_string . '-2048x1365' . '.' . $file_ext; $thumb_path = 'assets/thumb_path/thumb-entry-' . $image_random_string . '-600x400' . '.' . $file_ext; move_uploaded_file($file_tmp, $image_path); move_uploaded_file($thumb_tmp, $thumb_path); // Load the image $image = Image::make($image_path); // Resize the image $image->resize(2048, 1365, function ($constraint) { $constraint->aspectRatio(); $constraint->upsize(); }); // Save the new image $image->save($image_path, 100); // Load the image with Intervention Image $image = Image::make($image_path); // Resize the image while maintaining the aspect ratio $image->resize(600, 400, function ($constraint) { $constraint->aspectRatio(); $constraint->upsize(); }); // Save the thumbnail $image->save($thumb_path, 100); $data['image_path'] = $image_path; $data['thumb_path'] = $thumb_path; /* * If no errors save ALL the information to the * database table. */ if (empty($errors) === true) { // Save to Database Table CMS $timezone = new DateTimeZone('America/Detroit'); // Use your timezone here $today = new DateTime('now', $timezone); $data['date_updated'] = $data['date_added'] = $today->format("Y-m-d H:i:s"); $cms = new ImageContentManager($pdo, $data); $result = $cms->create(); if ($result) { header('Content-Type: application/json'); echo json_encode(['status' => 'success']); exit(); } } else { if (is_ajax_request()) { // Send a JSON response with errors for AJAX requests header('Content-Type: application/json'); echo json_encode(['status' => 'error', 'errors' => $errors]); } } } I log my errors to a log file that I can only see and a person needs to be login to my website even to upload a file. Maybe the above can you help you out a little. Just remember nothing is full proof, but you should make the code as tight as possible.1 point
-
no matter how large you set the max_post_size setting, someone can upload a file that is larger. the size of the file someone tries to upload is out of your control. your code must test for this condition and handle it. also, by increasing the setting beyond a reasonable size, it will allow hackers to flood your server with huge uploaded files, consuming all the available processing and memory on the server, allowing a denial of service (DoS) attack.1 point
-
The warning you are seeing tells you everything you need to know. Nothing to do with file type1 point
This leaderboard is set to New York/GMT-04:00