Hi I'm new to PHP and I would like some help please.
I 've created a contact form and i would like to add some captcha. I have created some gif images, that have numbers with some noise added on, and named the code_01.gif for no1, code_02.gif for no2 etc etc. I have put some of them on my form, staticly, for display purposes like this:
<img src="images/code_01.gif" />
<img src="images/code_07.gif" />
<img src="images/code_01.gif" />
<img src="images/code_08.gif" />
<img src="images/code_03.gif" />
<img src="images/code_07.gif" />
<input name="captcha" type="text" id="captcha" />
I would like to add some functionality to display randomly the image codes every time and also check to see if the input matches with the 6 digits that displayed.
Any help would be appreciated.
Simple PHP Captcha
This is one of the easiest CAPTCHA scripts you will ever use. While it doesn’t obscure the text, it will serve its purpose well for many people who need a low-level CAPTCHA solution. This script requires little-to-no setup. The only dependency is the PHP GD library.
It can be as simple as this to use, but it is also configurable:
<?php
session_start();
include("captcha.php");
$_SESSION['captcha'] = captcha();
echo '<img src="' . $_SESSION['captcha']['image_src'] . '" alt="CAPTCHA" />';
?>
Demo: http://labs.abeautifulsite.net/simple-php-captcha/
You can also use this: Securimage
Securimage is an open-source free PHP CAPTCHA script for generating complex images and CAPTCHA codes to protect forms from spam and abuse. It can be easily added into existing forms on your website to provide protection from spam bots. It can run on most any webserver as long as you have PHP installed, and GD support within PHP. Securimage does everything from generating the CAPTCHA images to validating the typed code. Audible codes can be streamed to the browser with Flash for the vision impaired.
Here is a simple math captha type thing I found long ago.
Advantages:
- No Images so less bandwidth usage.
- No external dependency.
FLOW PROCESS
In form.php:
Select one random number $n1
Select another random number $n2
Compute $n1 & $n2 with various math oprations and store it as $result, so that the resulant number is unpredicatble & unaligned with $n1+$n2
Echo "What is $n1 + $n2?"
Ask user to input the answer of question asked in step 4.
Add $result as hidden value in the form.
On submit, the $_POST values are processed by check.php.
In check.php:
If $_POST["answer"] is set, store it in $answer
Compute the $answer in same manner as it was computed in step 3 of form.php
Now, if $answer is equal to $_POST["result"], it is verified that User is Human.
Keep in mind that $answer is answer submitted by user & $result is our result after doing math operations on the $answer.
CODE:
File:form.php
<?php
$n1 = rand(1,15);
$n2 = rand(1,15);
//start making our result unpredictable & non-aligned with hidden value
$result = $n1+$n2;
$result = ($result*3)-2;
$result = ($result+4)*5;
$question="what is $n1 + $n2?";
?>
<form method="post" action="check.php">
<?php echo $question.PHP_EOL; ?>
<input name="answer" type="text"><br />
<input type="hidden" name="result" value="<?php echo $result; ?>">
</form>
File:check.php
<?php
if(isset($_POST["answer")){
$answer = $_POST["answer"];
// start doing same math on $answer
$answer = ($answer*3)-2;
$answer = ($answer+4)*5;
if($answer == $_POST["result"]{
// echo Hurray, you are Human..
// Do anything here..
}else{
echo "Wrong Answer";
}
Logic Implementation at http://codepad.org/2MtULNhZ
The key is in making the encoding & decoding formula harder. So that somebody looking at hidden form value result and Question should not find out the relation in between both of them.
Related
I am facing a problem related to auto fill in form.
Actually i am running a trust charity website which collects fund from donor.
Problem :
When i have entered a donation for one cause and again i want to enter donation for the same cause but with different credit card detail.
then i am strange the form where i need to enter detail card related is retained all of the information from the previous donation so everything was entered.
I have tried autocomplete="off" in form and also in input.
rename the input for each pageload. generate a prefix, and put it in a hidden field in the form.
$prefix = date("U"); //lets use unix time for this.
...
<input type="hidden" name="prefix" value="<?php echo $prefix; ?>"/>
<input type="text" name="<?php echo $prefix; ?>_cardnumber" />
...
And when processing look for
$_POST[$_POST['prefix'].'_cardnumber']
Try adding a unique identifier to the beginning or end of the id's or names of the form elements.
Alternatively there is this:
autocomplete = ”off” is not valid markup with XHTML Transitional,
which is a common DOCTYPE.Use this to keep a valid markup
from
if (document.getElementsByTagName) {
var inputElements = document.getElementsByTagName(“input”);
for (i = 0; inputElements[i]; i++) {
if (inputElements[i].className && (inputElements[i].className.indexOf(“disableAutoComplete”) != -1)) {
inputElements[i].setAttribute(“autocomplete”, ”off”);
}
}
}
From http://css-tricks.com/snippets/html/autocomplete-off/
If this is Google Chrome then it actually has a feature which ignores autocomplete settings from the current web form and will actually pull data from it's own "personal program cache" and populate the fields for you as a convenience. It also does this when it recognizes address fields. Thomas Martin Klein's answer will probably work best but I have not tested it before so Chrome may be smart enough to recognize your algorithm anyways. Good luck!
I am using secureImage which is a simple way to implement captcha,
i follow the guideline there to add the code, however, the checking is always invalid even i have input the correct value
It is the website of that plugin, within ten lines of code:
And this is my code:
in html form
<img id="captcha" src="http://www.phpcaptcha.org/securimage3/securimage_show.php?0.6905195268336684" alt="CAPTCHA Image">
<input type="text" class="required" name="captcha_code" size="10" maxlength="6">
in verification php
include_once '../plugin/securimage/securimage.php';
$securimage = new Securimage();
if ($securimage->check($_POST['captcha_code']) == false) {
die ("<div class='alert alert-success'><strong>The security code entered was incorrect.</strong><br /><br />Please go <a href='javascript:history.go(-1)'>back</a> and try again.</div>");
}
I have checked the post value, that is exactly what i have inputted. I would like to know which data the plugin used to compare with my input, however, i can not do this by echo the $secureimage
Thank you
To compare the randomly generated image with the code entered by a user a valid session is required. Please check this quick start guide and read the section about putting session_start() on top of your PHP script.
If you are too lazy to code, maybe you can try at http://www.google.com/recaptcha. It's widely used, I think it is better than the secureimage. You can get a php implementation at this site. I am if sorry if I don't answer your questions directly, this was because mr.GolezTrol suggested to not to use it.
In the script below, you will see a value that is submitted in the form titled "shorturl." Ultimately I would like to take that value and use it to generate a unique URL that displays all of the submitted data from the form.
Here is the form where a user will submits the data:
<html>
<body>
<p>Required fields are <b>bold</b></p>
<form action="contact.php" method="post">
<p><b>Author's Name:</b> <input type="text" name="author" /><br />
<p>Company Name: <input type="text" name="company" /><br />
<p>Address:<br /><textarea name="address" rows="5" cols="40"></textarea></p>
<p>Phone Number: <input type="text" name="phone" /><br />
<b>Title:</b> <input type="text" name="title" /><br />
<p><b>One Word Description:</b> <input type="text" name="shorturl" /><br />
<p><b>Full Description:</b><br />
<textarea name="comments" rows="10" cols="40"></textarea></p>
<p><input type="submit" value="submit"></p>
<p> </p>
</form>
</body>
</html>
The next bit of code is the contact.php page that will output the user data:
<?php
/* Check all form inputs using check_input function */
$author = check_input($_POST['author'], "Enter your name");
$company = check_input($_POST['company']);
$address = check_input($_POST['address']);
$phone = check_input($_POST['phone']);
$shorturl = check_input($_POST['shorturl'], "Provide a single word description");
$title = check_input($_POST['title'], "Write a title");
$comments = check_input($_POST['comments'], "Provide a full description");
/* Functions we used */
function check_input($data, $problem='')
{
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
if ($problem && strlen($data) == 0)
{
show_error($problem);
}
return $data;
}
function show_error($myError)
{
?>
<html>
<body>
<b>Please correct the following error:</b><br />
<?php echo $myError; ?>
</body>
</html>
<?php
exit();
}
?>
<head>
<title><?php echo $_POST['title']; ?></title>
</head>
<body>
<p>
<b><?php echo $_POST['title']; ?></b><br>
Created by:<br>
<?php echo $_POST['author']; ?><br>
<?php echo $_POST['company']; ?><br>
Contact: <br>
<?php echo $_POST['phone']; ?><br>
<?php echo $_POST['address']; ?><br>
Flyer Description: <br>
<?php echo $_POST['comments']; ?><br>
</p>
</body>
</html>
As you will see if you run this form, the function is pretty basic. Here is where I need the assistance. In the initial form the "shorturl" value is taken. The function of the shorturl value is as follows:
If this form was hosted on examplesite.com, then I would ultimately like for the form that is created to be available with submitted answers at examplesite.com/shorturl
First of all, how do I verify that this is in fact a single word via PHP? If a user submits the shorturl value as "House" then I need the form to return the value as true, but if the user submits "Big House" then the value is false and they need to alter the value to something that is acceptable such as "BigHouse"
Secondly, I need to verify that the shorturl value is unique to the site. In other words, once a shorturl has been used, that value needs to be sent to the MySQL database so that it will not be replicated by another user. To continue our example, if someone already had "House" as their shorturl value then the full URL of examplesite.com/House is already taken. Then if a new user comes and tries to use "House" the submission will produce an error message that says the name is taken.
And finally, how do I get all of this information to auto-generate a unique webpage with the form results? For an example let's continue examplesite.com/House
Right now, when a user submits the form, the data is displayed on examplesite.com/contact.php. How do I generate a URL which would display the form data and be unique as defined by the shorturl and be viewable to a third party site visitor without submitting new data?
Wow. I hope that all makes sense.
I know there are several questions in here, so if you can only assist with one step that is fine. If you can tackle this entire issue then more power to you :)
I have done a fair amount of research on this and I am thinking that the first 2 questions should be able to be solved with PHP, but the third might involve a mod_rewrite function of some sort. I cannot thank you enough for getting this far with my query and many many thanks if you can provide a solution.
This should do a good job of verifying $shorturl:
if (preg_match('/[^a-z0-9]/i', $shorturl)) {
// $shorturl contains characters other than just numbers or
// letters such as a tab, space, or special chars you probably don't want
}
As for making sure the url is unique:
if (!mysql_num_rows(mysql_query("SELECT id FROM contact WHERE url = '$shorturl' LIMIT 1")) {
// it is unique, yay
}
And you would insert the urls like so:
mysql_query("INSERT INTO contact (url) VALUES ('$shorturl')");
As for autogenerating the content, that shouldn't be that tricky. First, you will need to insert all the form data into the database, I would do this at the same time you insert the url. For dynamically retrieving the data, (using such a short url) you will need to do a tiny bit of .htaccess modification.
Here is an example of what your .htaccess might look like for a user to be able to go to domain.com/shorturl while the actual scripts being ran (and what they will see) are at domain.com/contact.php?short_url=shorturl
RewriteEngine on
# don't rewrite if the file exists
RewriteCond %{REQUEST_FILENAME} !-f
# don't rewrite if the directory exists
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ contact.php?short_url=$1
At this point the rest is just capturing the GET variable as $_GET['short_url'] within contact.php (or anywhere you want this script to reside, as long as you change the RewriteRule accordingly) and returning the rest of the the information you captured using database queries, maybe something like:
$short_url = mysql_real_escape_string($_GET['short_url']);
$sql = "SELECT * FROM contact WHERE url = '$short_url'";
$user_data = mysql_fetch_array(mysql_query($sql));
extract($user_data);
// with extract, all of $user_data's keys are now variables and their respective values
// are contained within those variables
// $user_data['company'] now becomes simply $company, for example
echo "Company: $company";
// etc...
I hope this helps :)
I agree with Wylie. I also agree with you (Presto) that your post is a little hard to get at times x). Either way, I will try to answer your questions as fully as possible, based on what I understand what you mean.
1) The best way to check if it's a single word is by checking word delimiters. The most typical word delimiter is the space, but things like hyphens, commas, and periods are obviously delimiters as well. In your case, the best way to determine what to allow is to consider what will correctly parse as a URL and what won't. For example, you should not allow the plus sign (+) to be used.
You can do several things to prevent these kinds of breaks. You can either correct it, or refuse it. In other words, you can either replace/ remove 'illegal characters' without any additional interaction/ approval of the user, or you can simply bounce it back to the users stating that it is invalid and that they will need to fix it. You can do this at a server level (PHP) or at a client and server level (Javascript for direct check, and PHP as a fail safe). Depending on how tolerant you'll be, and whether you will fix or refuse a string, you should either use a str_ireplace() type of function, or you should use regexp (preg_match()). There is, at this point, no way for me to tell you which one to use.
2) I can't say what's the best way to do this, as this very strongly depends on your system setup, but if it would make sense in your system, I would use MySQL for this task and store the names of the 'page directory' in a table with at least two rows: id and shorturl (as you refer to it). The id should be the primary key and you'll use this id to identify (/ JOIN) data that is needed to be displayed on the web page. The shorturl column should be index as 'UNIQUE'. This way, if you try to insert another value in that table column, MySQL will throw you an error (I believe errno 1169). Because of this, you can simply run the insert query after a user has submitted your form (and your PHP code has checked it) and you can then just check for that errno to see if the name has been used before.
3) Depending on how you set up your web server, you can do several things. Writing a mod_rewrite file is of course possible (and fairly easy, as you can build it in PHP and just write it to your web server). Another way you can do it is to fetch the shorturl that the visitor typed in his/ her address bar and then cross check that with your database table (like the one from point two above here) and then do an internal redirect, using the header() function in PHP.
Let me know if that was of any help, or if things are still unclear.
Ok, this might be obvious but its not clicking quite yet. I am creating a forum/blog esque app.
I grab the posts from the database rather securely but commenting is beginning to be a little more difficult. (I could just be paranoid, right?).
How do I add a comment without exposing the id of the parent message? (like in a hidden form field or query string, or something).
I guess I am a bit paranoid that someone might go into the code with firebug or something and change the hidden form field value to something else before submitting. I guess I would have to make sure the user has permission to comment to that particular post/category?
Things to note :
The user is already logged in.
Its not a public post
I would recommend that you setup your database like so:
Comments
---------
id
encodedID
authorID
parentID
message
Then, for the form field have two hidden values, one will be the encodedID, and the second will be a hash that you make. I would recommend the hash to be:
<?php
$hash = sha1(md5($encodedID . $userID . $_SERVER['REMOTE_ADDR'] . "abc1234"));
?>
Then, when the user submits the form, validate that the hash is valid for the specific encodedID and user. Here is a brief code write up:
<?php
if(isset($_POST['submit']))
{
//Get the variables and all and sanitize the input of 'message'
if(sha1(md5($_POST['value1']. $userID . $_SERVER['REMOTE_ADDR'] . "abc1234")) == $_POST['value2'])
{
//User is valid.
}
else
{
//Invalid user.
//Document this.
}
}
$value1 = $encodedID; //Grab this from your database
$value2 = sha1(md5($value1 . $userID . $_SERVER['REMOTE_ADDR'] . "abc1234"));
?>
<form method="post" action="comment.php">
<input type="text" name="message" />
<input type="hidden" name="value1" value="<?php echo $value1; ?>" />
<input type="hidden" name="value2" value="<?php echo $value2; ?>" />
<input type="submit" name="submit" value="Comment" />
</form>
Edit: Just a small tip, but I would recommend that you change value1 and value2 to something abstract, don't call it encodedID or anything like that, just so that it confuses any users that will attempt to try and break it.
And yes md5 and sha1 are not completely secure, but for this case it will work since you want to be able to process the comments fast and efficiently.
That might be an overkill but if you really want to hide the post_id of the current message then you should consider using session. So instead of using something like this on your form:
<form action="/postcomment.php" method="post" >
<input name="post_id" type="hidden" value="123" />
<textarea name="message"></textarea>
</form>
Reduce it to something like this:
<?php $_SESSION['post_id'] = '123'; ?>
<form action="/postcomment.php" method="post" >
<textarea name="message"></textarea>
</form>
Of course this is "yucky" coding but at least you get the idea.
Oh, don't forget to validate EVERYTHING on postcomment.php. Also escape ALL string input values and make sure all numeric inouts are numbers indeed (multiply them by one?).
[EDIT: Due to insistent public demand, may I, if you please, amend the aforementioned:]
Instead of:
<?php $_SESSION['post_id'] = '123'; ?>
Generate a form id:
<?php $_SESSION['form_id'] = $_SESSION['user_id'].'_'.md5(time()); ?>
Then generate the unique post_id:
<?php $_SESSION[$_SESSION['form_id'].'_post_id'] = '123'; ?>
After submitting get the post_id:
<?php $post_id = $_SESSION[$_SESSION['form_id'].'_post_id']; ?>
you could assign the form an "id" as a hidden field and create a database table to track form ids and their associated post ids, that way when the form gets submitted you could check the post id in the db without ever sending it to the client based on the form id that is returned with the post
You're asking the wrong question here: instead of being concerned about the user getting some internal ID that means nothing outside your application, your primary concern should be about keeping them from doing anything unpleasant with it.
Imagine I just started sending POST requests to add a comment for every ID between 1 and 10,000. I'm sure to hit a real post sooner or later.
Rule #1 about writing secure web applications: Don't trust the user.
In other words, yes, you should check to make sure that they have permission to comment when you receive the results back from the from.
entering total value of two numbers in a text box to prevent spam
<?php
$rand = rand(2,9);
$rand1 = rand(2,9);
echo $rand." + ".$rand1;
?>
<span class="stred">*</span>
</label>
</td>
<td>
<div class="input-container">
<input name="randm" class="intext" id="county" type="text" />
</div>
How do I verify this value of both in a POST method??
There is nothing to verify in your code. You cannot compare the received value, because you did not keep the originals. You throw away $rand and $rand1 in the snippet that you have shown.
You need to keep them in the session (don't forget session_start() beforehand) like so:
$_SESSION["rand"] = $rand + $rand1;
Then you might be able to do this when you receive the form:
if (strlen($_POST["randm"]) && ($_POST["randm"] == $_SESSION["rand"])) {
$_SESSION["rand"] = ""; // unset afterwards to prevent replays
I would use a CAPTCHA instead. With math problems, you still have to display the equation for users to solve, which opens the door for a spammer to write a script to parse the operands from your HTML, solve the math problem, and submit a POST request containing the correct answer. Automating such a script would allow for the continuous misuse of your form, a scenario which is actually not as unlikely or difficult to accomplish as one might think.
reCATCHA is a good option should you choose to go the CAPTCHA route.