roger01 Posted August 15, 2016 Share Posted August 15, 2016 HelloI want to run a contest on my website and i am asking visitors to post their names and BTC addresses and i'll use random.org's list randomizer to pick one from the listwhat i did so far: <?php if ($_POST) { $name = $_POST['commentName']; $txt = $_POST['commentBTC']; $handle = fopen("comments.html","a"); fwrite($handle, "<b>" . $name . "</b> : " . $txt . "<br/>"); fclose($handle); } ?> and ] <form action="" method="POST" onsubmit="return checkform(this);"> Some Name: <input type="text" maxlength="10" name="commentName"/><br> BTC Address: <input type="text" maxlength="34" pattern="^[123][a-km-zA-HJ-NP-Z1-9]{25,34}$" name="commentBTC" required/><br> so i get a html list, which is great. the problem is that some visitors are signing up multiple times is there a way to check 'comments.html' for 'commentBTC' and if exists, to deny signing up?i can drop the 'commentName' field if it's easier to have only a bitcoin address list.help? thank you! Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/ Share on other sites More sharing options...
requinix Posted August 15, 2016 Share Posted August 15, 2016 Don't store comments in a text file. Get a database. Even a SQLite database will do the job, if you don't have a real one available. Then all you have to do is run a query on the database to see if the BTC address (being the most reliable piece of information you have) has already been entered. Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536171 Share on other sites More sharing options...
Barand Posted August 15, 2016 Share Posted August 15, 2016 ... or add a UNIQUE key to the field to make it impossible to add the same one twice Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536173 Share on other sites More sharing options...
Jacques1 Posted August 15, 2016 Share Posted August 15, 2016 You also don't need random.org to pick a random visitor. PHP itself provides several random number generators from toy-grade to cryptography-grade. Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536174 Share on other sites More sharing options...
roger01 Posted August 15, 2016 Author Share Posted August 15, 2016 thank you for your answers! meanwhile, i got a lot of weird POST submissions so i came up with this (i found the code, actually): <?php session_start(); if (isset($_POST['message'])) { if (isset($_SESSION['token']) && $_POST['token'] == $_SESSION['token']) { $message = htmlentities($_POST['message']); $ipaddy = $_SERVER['REMOTE_ADDR']; $fp = fopen('./btcs.txt', 'a'); fwrite($fp, "$ipaddy $message <br /> \n"); fclose($fp); } } $token = md5(uniqid(rand(), true)); $_SESSION['token'] = $token; ?> <form method="POST" onsubmit="return checkform(this);"> <input type="hidden" name="token" value="<?php echo $token; ?>" /> <input type="text" maxlength="34" pattern="^[12][a-km-zA-HJ-NP-Z1-9]{25,34}$" name="message" required><br /> <input type="submit" value="Sign-up!"> i wanted to have the ips stored aswell so i can iptables drop whoever uses post injection or whatever but in don't want to show it on the website so i'm using this: <?php $lines = file('btcs.txt'); foreach ($lines as $line) { $parts = explode(' ', $line); echo isset($parts[1]) ? $parts[1] : 'N/A'; echo "<br>"; } ?> i'm just trying to run this for a couple of days so i don't need anything fancy like store it in a sql. however, it would be nice if the last part of the code will remove the duplicate btc addresses (there still are visitors that post the same btc address over and over again:), anyone knows how to do that? thank you very much! Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536175 Share on other sites More sharing options...
Jacques1 Posted August 15, 2016 Share Posted August 15, 2016 (edited) If you want to make use of this forum, it's a good idea to actually listen to the advice you get. Most of us are professional developers, so we know a bit about implementing features like this. When requinix tells you to use an SQL database, he means it. That code you've “found somewhere” is nonsense. You can spend the rest of your time trying to fix it, but you'll still end up with up cheaters sabotaging your contest. This leaves you with two options: You accept that the contest is just a fun project and let users post whatever they want. Or you take this seriously and set it up in a way that it actually works. Even the cheapest hoster today has MySQL, so I'm sure you already have a database and probably even phpmyadmin (which is a graphical administration tool). Here's the table definition: CREATE TABLE contest_submissions ( contest_submission_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, btc_address VARCHAR(35) NOT NULL UNIQUE, username VARCHAR(10) NOT NULL, ip_address VARCHAR(15) NOT NULL ); People who try to post a large number of requests can be stopped with CAPTCHAs like reCAPTCHA. Edited August 15, 2016 by Jacques1 Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536178 Share on other sites More sharing options...
roger01 Posted August 15, 2016 Author Share Posted August 15, 2016 i know you are right. my php knowledge is next to 0 and i was trying to avoid the sql method because i have no idea how to do it and couldn't allow myself to ask here 'hey can someone write up a whole script for me?' so that's why i dogged that answer, not because i don't want to do. thank you for your answer, i've managed to get something really medieval working, getting the btc addresses in a txt and running a crontab every 5 minutes with uniq and awk that txt Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536180 Share on other sites More sharing options...
Jacques1 Posted August 15, 2016 Share Posted August 15, 2016 my php knowledge is next to 0 That's why we have this forum: To help people solve problems which exceed their current knowledge. While you were busy writing your cronjob hack, I've written the script. It took me ~10 minutes, 2 queries (CREATE and INSERT) and ~50 lines of plain PHP code. That's not exactly rocket science. And unlike your hack, it actually solves the problem. But if you prefer to run a cronjob every 5 minutes, go ahead. Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536181 Share on other sites More sharing options...
Barand Posted August 15, 2016 Share Posted August 15, 2016 If you are intent on using a text file then store it as json encoded data. Take advantage of the fact that an array key must be unique and make the BTC the key. To get the current submissions and put in an array $submissions = json_decode(file_get_contents('btcs.json'), true); to add a new submission if (isset($submissions[$btc]) { // error - already exists! } else { $submissions[$btc] = [ 'username' => $username , 'ip' => $ip ]; } to save the data, reverse the first code file_put_contents('btcs.json', json_encode($submissions)); However, you really should get to grips with using a database. It has so many advantages and it's a move you'll need to make sometime. Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536182 Share on other sites More sharing options...
roger01 Posted August 15, 2016 Author Share Posted August 15, 2016 (edited) That's why we have this forum: To help people solve problems which exceed their current knowledge. While you were busy writing your cronjob hack, I've written the script. It took me ~10 minutes, 2 queries (CREATE and INSERT) and ~50 lines of plain PHP code. That's not exactly rocket science. And unlike your hack, it actually solves the problem. But if you prefer to run a cronjob every 5 minutes, go ahead. well may i have it? Edited August 15, 2016 by roger01 Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536183 Share on other sites More sharing options...
Jacques1 Posted August 15, 2016 Share Posted August 15, 2016 You already have the table definition. Did you create that table? Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536184 Share on other sites More sharing options...
roger01 Posted August 15, 2016 Author Share Posted August 15, 2016 (edited) yes, but i only used two columns: SELECT * FROM `contest_submissions` ; +-----------------------+------------------------------------+---------------+ | contest_submission_id | btc_address | ip_address | +-----------------------+------------------------------------+---------------+ | 1 | 1KZsSb1ZsQrB1FXzFdnhFL2GuPGTjUKLhi | 192.168.100.3 | +-----------------------+------------------------------------+---------------+ 1 row in set (0.00 sec) oh, and i made botw btc_address and ip_aadress unique, i hope there won't be problems Edited August 15, 2016 by roger01 Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536185 Share on other sites More sharing options...
Jacques1 Posted August 15, 2016 Share Posted August 15, 2016 Making the IP address unique is a bad idea, because this will lock out many legitimate users. In fact, the IP address is most definitely shared among many people, be it due to an Internet connection with multiple users, a proxy server, a VPN, Tor etc. Once you've blocked a couple of big services, large parts of the Internet population will be unable to visit your site. At the same time, an actual attacker can easily obtain a new address. If you want to limit abuse, install reCAPCHA. It's much more effective against attackers and much less harmful for legitimate users. The recommend way to access a MySQL database with PHP is via PDO. It should already be installed on the server: <?php // database credentials const DB_HOST = 'localhost'; const DB_USER = '???'; const DB_PASSWORD = '???'; const DB_NAME = '???'; const DB_CHARSET = 'UTF8'; // MySQL error codes const MYSQL_ER_DUP_ENTRY = 1062; // establish a database connection $dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset='.DB_CHARSET; $database_connection = new PDO($dsn, DB_USER, DB_PASSWORD, [ PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]); // test connection var_dump( $database_connection->query('select * from contest_submissions')->fetchAll() ); Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536186 Share on other sites More sharing options...
roger01 Posted August 15, 2016 Author Share Posted August 15, 2016 (edited) if i understand this correctly, this is for reading the columns, right? i've managed to gather something up to insert into the table by using this in insert.php: $ipaddy = mysqli_real_escape_string($link, $_SERVER['REMOTE_ADDR']); $btcaddy = mysqli_real_escape_string($link, $_POST['message']); $sql = "INSERT INTO contest_submissions (btc_address, ip_address) VALUES ('$ipaddy', '$btcaddy')"; if(mysqli_query($link, $sql)){ echo "Records added successfully."; } else{ echo "ERROR: Could not able to execute $sql. " . mysqli_error($link); and <form action="insert.php"> but while using the txt file, i had this code writing the file: if (isset($_POST['message'])) { if (isset($_SESSION['token']) && $_POST['token'] == $_SESSION['token']) { $message = htmlentities($_POST['message']); $ipaddy = $_SERVER['REMOTE_ADDR']; $fp = fopen('./messages.txt', 'a'); fwrite($fp, "$ipaddy $message <br /> \n"); fclose($fp); } } $token = md5(uniqid(rand(), true)); $_SESSION['token'] = $token; and i've noticed there weren't any trash POST like ZAP' ZAP" ZAP ZAP' ZAP" ZAP%<br/> ZAP%' whatever this was.. could it be that the mysql will be flooded upon with that trash if the simple script is used? Edited August 15, 2016 by roger01 Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536189 Share on other sites More sharing options...
Barand Posted August 15, 2016 Share Posted August 15, 2016 $sql = "INSERT INTO contest_submissions (btc_address, ip_address) VALUES ('$ipaddy', '$btcaddy')"; The values are the wrong way round. You are putting the $btcaddy into the ip_address column Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536190 Share on other sites More sharing options...
Jacques1 Posted August 15, 2016 Share Posted August 15, 2016 (edited) And you need to stop copying and pasting random code from the Internet. mysqli is poor, manual escaping is poor, and printing internal error messages on the screen is really not a good idea. Did you run the PDO code I gave you? Then you need to use a prepared statement and also catch errors which are caused by duplicate Bitcoin addresses: // process POST request if ($_SERVER['REQUEST_METHOD'] == 'POST') { $errors = []; // TODO: validate the $_POST input // try to insert input; if there's a duplicate value, this will fail try { $contest_insert_stmt = $database_connection->prepare(' INSERT INTO contest_submissions (btc_address, ip_address) VALUES (:btc_address, :ip_address) '); $contest_insert_stmt->execute([ 'btc_address' => $_POST['btc_address'], 'ip_address' => $_SERVER['REMOTE_ADDR'], ]); } catch (PDOException $contest_insert_exception) { // was the error caused by a duplicate value? if ($contest_insert_exception->errorInfo[1] == MYSQL_ER_DUP_ENTRY) { $errors[] = 'This Bitcoin address has already been entered.'; } else { // a different error, rethrow exception throw $contest_insert_exception; } } } Edited August 15, 2016 by Jacques1 Quote Link to comment https://forums.phpfreaks.com/topic/301896-restrict-form-usage-once-per-visitor/#findComment-1536193 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.