I'm working on a Captcha class and i'm almost done, there is one thing that doesn't work
In the file where I put the form, I start with this line:
include 'captcha.php';
$captcha = Captcha::tryCaptcha(2,4,'#000', '#ffffff');
and this is the captch construct:
static $do_generate = TRUE;
function __construct($aantal_letters = 2, $aantal_cijfers = 4, $voorgrond = '#000000', $achtergond = '#ffffff') {
session_start();
if (self::$do_generate == TRUE) {
$letters = substr(str_shuffle('ABCDEGHJKLMNPQRSTUVWXYZ'),0 ,$aantal_letters);
$cijfers = substr(str_shuffle('23456789'),0 ,$aantal_cijfers);
$imgbreed = 18 * ($aantal_letters + $aantal_cijfers);
$_SESSION['imgbreed'] = $imgbreed;
$_SESSION['captcha'] = $letters . $cijfers;
$_SESSION['voorgrond'] = $this->hex2rgb($voorgrond);
$_SESSION['achtergond'] = $this->hex2rgb($achtergond);
}
}
so in other words I put my stuff in a session if the static var $do_generate == TRUE
So when I post the form, the captcha is getting checked by a procesor.php
like this:
if (Captcha::captcha_uitkomst() == TRUE) {
echo "Great";
} else {
echo "Wrong";
}
And this is the captcha function that checks the etered captcha code:
static function captcha_uitkomst() {
if (strcmp($_SESSION['captcha'], strtoupper(str_replace(' ', '', $_POST['captcha-invoer']))) == 0) {
return TRUE;
} else {
echo "test";
self::$do_generate = FALSE;
return FALSE;
}
}
If I enter a correct captcha code, it's all good, that works I get the echo great.
If wrong I get the echo Wrong,
Perfect, but.... when I go back to form (hit backspace one history back) to enter a correct captcha, it regenerates a new captcha.
In the class: captcha_uitkomst you see that I made the self::do_generate FALSE
And the echo 'TEST' works when it's false, (just for checking)
What am I doing wrong
When you hit "back", the page is reloaded. You get a new CAPTCHA.
The premise of your question is fundamentally flawed, as you have just randomly assumed that this shouldn't happen, whereas in reality this is entirely by design.
It wouldn't be a very effective CAPTCHA if you could repeatedly get it wrong then go back and try again; any bot could just start brute forcing it and learning from the experience.
Related
I have a strange problem with Google Captcha. I've tried all kinds of php codes from different tutorials, but the result is exactly the same every time...
The problem is this:
it shows up correctly
if you check the box, it works correctly
if you then send the form it works correctly
but... if you don't check the box, the form is still sent!
So, in other words, it's only on the form as a decorative piece. What could be the problem? It's probably something very simple, but I'm totally missing it.
Help or insights are very much appreciated! Thanks in advance!
Addendum
The following is the code that came with the template I used:
require_once('recaptcha-php-1.11/recaptchalib.php');
if ($use_captcha == 1) {
$resp = null;
$error = null;
$reCaptcha = new ReCaptcha($secret);
$secret = "MY SECRET KEY HERE";
$captcha_error_message = '<div class="pi-alert-danger fade in"><button type="button" class="pi-close" data-dismiss="alert"><i class="icon-cancel"></i></button><p>Bewijs dat je geen robot bent!</p></div>';
if (isset($_POST["captcha_response"]) && $_POST["captcha_response"] != '') {
$resp = $reCaptcha->verifyResponse(
$_SERVER["REMOTE_ADDR"],
$_POST["captcha_response"]
);
if ($resp && $resp->success != true) {
echo $captcha_error_message;
exit();
}
} else {
echo $captcha_error_message;
exit();
}
}
You have to check if the captcha was solved (at your PHP-Script which do anything with the Form-data)
Like this:
function checkCaptcha($recaptchaResponse) {
$recaptchaPrivateKey = 'Your Private Key';
if(! $recaptchaResponse)
return false;
$recaptchaObj = new ReCaptcha($recaptchaPrivateKey);
$response = $recaptchaObj->verifyResponse($_SERVER["REMOTE_ADDR"], $recaptchaResponse);
if($response != null && $response->success)
return true;
return false;
}
If you don't include a function like this to your form function, your server will say, the form is okay, because it don't know about the captcha.
Note, that you have to include the Google-captcha Libarys-File as well. You can find it here:
https://github.com/google/recaptcha/blob/1.0.0/php/recaptchalib.php (Worked for NoCaptcha as well)
i have a php code and when i add some gets variables i get error, 500, i tested it with ajax and without ajax(directly writing the url on the adress bar)
When i go with localhost/ajax/test.php?did=1 everything is fine but when i go with localhost/ajax/test.php?did=1&task=1 the problem happens
all the functions are created before on the ../php/core.php
Here is the code
<?php
require '../php/core.php';
$did = floor($_GET['did']);
if (device_exist($did) && amlogedin() && intouch_get($uid, $did) == 2) {
$task = floor($_GET['task']);
$id = safestring($_GET['id']);
switch ($task) {
case 1:
if (feature_removefeature($did, $fid)) {
echo donemsg("Feature Removed");
}
break;
}
design_makefeturelist($did);
}
else {
echo 'Sorry, some thing is wrong';
}
Almost sure that you've got an error in the feature_removefeature or donemsg function. Because after you set task=1 it will enter the case 1: statement. You could replace the if with a simple echo "lala"; to check it out.
ps. Is $fid already set?
<?php
$site = site_url();
$tec = $site;
$tecget = $site . '/';
$tecgetwo = substr($site, 7);
$gett = get_option('FPMobileget');
if (strpos($gett, "http://www.") === 0) {
$gettt = substr($gett, 11);
$getttc = 'http://' . $gettt;
}
elseif (strpos($gett, "www.") === 0) {
$getwww = substr($gett, 4);
$getwwwc = 'http://' . $getwww;
}
elseif (strpos($gett, "http://") === 0) {
$gethttp = substr($gtt, 7);
}
if (($gett == $tec) || ($gett == $tecget) || ($getwwwc == $tec) || ($getttc == $tec) || ($gett == $tecgetwo)) {
echo "you entered the same url";
echo '<div class="error"><p style="color:#F00">Warning -error</p></div>';
delete_option('FPMobileget');
}
else {
echo "success";
}
?>
i want to check user url input with the current site url whether they are same or not,if it is same i want to throw a error message to the user in admin menu simultaneously i want to clear the text field.i used get_option('FPMobileget') to get user input from text-box. so i used delete_option to clear text field when condition satisfy(if url are same).Here user may enter url in different way so i have undergone some string function to take care of that.here all works fine but error messages were displayed on top, but not next to text-box. all works fine here but i want to display the error message next to textbox thats it.this is my first Question in stackoverflow,since i'm new to stackoverflow. Thanks in advance.
Make the whole thing a function, convert your error message a string (not use echo) and use return $errorstring; to send the string back to the form.
You can then put $errorstring on the form wherever you want.
I'm having issues to send an occuring error to another page.
I have already created the page the error will be sent to, and I've tried a header function. But that doesn't seem to work. Here is the php code that I am using for the page.
<?php
if(isset($_POST['username'], $_POST['password'])){
//login the user here
$connect = mysql_connect("","","")or die(mysql_error());
mysql_select_db("")or die(mysql_error());
$errors = array();
$username = strip_tags(mysql_real_escape_string($_POST['username']));
$password = strip_tags(mysql_real_escape_string($_POST['password']));
if (empty($Regi_Username) || empty($Regi_password)) {
$errors[] = 'All fields are requerid';
} else {
if (strlen($Regi_Username) > 25) {
$errors[] = 'Username is to long';
}
if (strlen($password) > 25) {
$errors[] = 'Password is to long';
}
}
$password = md5($_POST['password']);
$loginquery = "SELECT * FROM regi WHERE username='$username' and password='$password'" or die(mysql_error());
$result = mysql_query($loginquery);
$count = mysql_num_rows($result);
mysql_close();
if($count==1){
$seconds = 2000 + time();
setcookie(loggedin, date("F jS - g:i a"), $seconds);
header("location:member.php");
} else {
echo 'Wrong username and password please try agian.';
}
}
?>
Pass the GET variable in your URL like..
header('Location:page.php?err=1');
exit;
On the other page use this
if(isset($_GET['err'] && $_GET['err'] == 1) {
echo 'Error Occured';
}
Here is a session based approach. This is the best way to pass messages from one page to another as they are stored in the user's session (a piece of data related to each user and stored in the server side) and not in the browser (like cookies or URL GET parameters, which can be easily corrupted), so it is really quite harder to manipulate the messages from 3rd parties.
Page process.php:
<?php
// Very top of your page
session_start();
$_SESSION['errors'] = array();
// Do stuff now...
// ...
// Hey it's a X error!
$_SESSION['errors']['X'] = 'Message for X error';
// Continue doing stuff...
// ...
// OMG! It's a Y error now!
$_SESSION['errors']['Y'] = 'Message for Y error';
// Keep doing stuff till you're done...
// All right, process is finished. Any Errors?
if (count($_SESSION['errors']) > 0) {
// It seems there's been any errors
// time to redirect to error-displaying page
header('Location: error-page.php');
exit;
}
Page error-page.php:
<?php
// Very top of your page
session_start();
// Let's check if there is any error stored in the session.
// In the case no errors found, it is better to redirect to another page...
// ...why anybody would end in this page if no errors were thrown?
if (!isset($_SESSION['errors']) || !is_array($_SESSION['errors']) || empty($_SESSION['errors'])) {
header('Location: home.php');
exit;
}
// If we reach this point it means there's at least an error
foreach ($_SESSION['errors'] as $errorCode => $errorMessage) {
// Here we can display the errors...
echo '<p>Error ', $errorCode, ': ', $errorMessage, '</p>', PHP_EOL;
}
// You can also do stuff only if a certain error is received
if (array_key_exists('X', $_SESSION['errors'])) {
// Error `X` was thrown
echo '<p>Oh no! It seems you suffered a X error!!</p>', PHP_EOL;
echo 'Click here to go back home.', PHP_EOL;
}
// At the end you should to remove errors from the session
$_SESSION['errors'] = array();
// or
unset($_SESSION['errors']);
You could use Alien's method, but it'd better if you use Session:
// Assume you init the session already; Use json_encode since you use array for $errors
$_SESSION['errors_msg'] = json_encode($errors);
header("location:member.php");
// Remember to exit here after we call header-redirect
exit;
Besides, there are a lot of problems is your currently code:
Use salt for hashing password
Use mysqli over mysql
Filtering input, escaping output
.. Read other recommendations here in this topic ..
Please read http://www.phptherightway.com/. There is a lot of right recommendation (of course not all) for PHP.
well i'm writing a php code to edit tags and data inside those tags but i'm having big trouble getting my head around the thing.
basically i have an xml file similar to this but bigger
<users>
<user1>
<password></password>
</user1>
</users>
and the php code i'm using to try and change the user1 tag is this
function mod_user() {
// Get global Variables
global $access_level;
// Pull the data from the form
$entered_new_username = $_POST['mod_user_new_username'];
$entered_pass = $_POST['mod_user_new_password'];
$entered_confirm_pass = $_POST['mod_user_confirm_new_password'];
$entered_new_roll = $_POST['mod_user_new_roll'];
$entered_new_access_level = $_POST['mod_user_new_access_level'];
// Grab the old username from the last page as well so we know who we are looking for
$current_username = $_POST['mod_user_old_username'];
// !!-------- First thing is first. we need to run checks to make sure that this operation can be completed ----------------!!
// Check to see if the user exist. we just use the normal phaser since we are only reading and it's much easier to make loop through
$xml = simplexml_load_file('../users/users.xml');
// read the xml file find the user to be modified
foreach ($xml->children() as $xml_user_get)
{
$xml_user = ($xml_user_get->getName());
if ($xml_user == $entered_new_username){
// Set array to send data back
//$a = array ("error"=>103, "entered_user"=>$new_user, "entered_roll"=>$new_roll, "entered_access"=>$new_access_level);
// Add to session to be sent back to other page
// $_SESSION['add_error'] = $a;
die("Username Already exist - Pass");
// header('location: ../admin.php?page=usermanage&task=adduser');
}
}
// Check the passwords and make sure they match
if ($entered_pass == $entered_confirm_pass) {
// Encrypt the new password and unset the old password variables so they don't stay in memory un-encrytped
$new_password = hash('sha512', $entered_pass);
unset ($entered_pass, $entered_confirm_pass, $_POST['mod_user_new_password'], $_POST['mod_user_confirm_pass']);
}
else {
die("passwords did not match - Pass");
}
if ($entered_new_access_level != "") {
if ($entered_new_access_level < $access_level){
die("Access level is not sufficiant to grant access - Pass");
}
}
// Now to load up the xml file and commit changes.
$doc = new DOMDocument;
$doc->formatOutput = true;
$doc->perserveWhiteSpace = false;
$doc->load('../users/users.xml');
$old_user = $doc->getElementsByTagName('users')->item(0)->getElementsByTagName($current_username)->item(0);
// For initial debugging - to be deleted
if ($old_user == $current_username)
echo "old username found and matches";
// Check the variables to see if there is something to change in the data.
if ($entered_new_username != "") {
$xml_old_user = $doc->getElementsByTagName('users')->item(0)->getElementsByTagName($current_username)->item(0)->replaceChild($entered_new_username, $old_user);
echo "Username is now: " . $current_username;
}
if ($new_pass != "") {
$current_password = $doc->getElementsByTagName($current_user)->item(0)->getElementsByTagName('password')->item(0)->nodeValue;
//$replace_password = $doc
}
}
when run with just the username entered for change i get this error
Catchable fatal error: Argument 1 passed to DOMNode::replaceChild() must be an instance of DOMNode, string given, called in E:\xampp\htdocs\CGS-Intranet\admin\html\useraction.php on line 252 and defined in E:\xampp\htdocs\CGS-Intranet\admin\html\useraction.php on line 201
could someone explain to me how to do this or show me how they'd do it.. it might make a little sense to me to see how it's done :s
thanks
$entered_new_username is a string so you'll need to wrap it with a DOM object, via something like$doc->createElement()
$xml_old_user = $doc->getElementsByTagName('users')->item(0)->getElementsByTagName($current_username)->item(0)->replaceChild($doc->createElement($entered_new_username), $old_user);
This may not be quite right, but hopefully it points you in the correct direction.
alright got it writing and replacing the node that i want but i have ran into other issues i have to work out (IE: it's replacing the whole tree rather then just changing the node name)
anyway the code i used is
// For initial debugging - to be deleted
if ($old_user == $current_username)
echo "old username found and matches";
// Check the variables to see if there is something to change in the data.
if ($entered_new_username != "") {
try {
$new_node_name = $doc->createElement($entered_new_username);
$old_user->parentNode->replaceChild($new_node_name, $old_user);
}
catch (DOMException $e) {
echo $e;
}
echo "Username is now: " . $current_username;
}
if ($new_pass != "") {
$current_password = $doc->getElementsByTagName($current_user)->item(0)->getElementsByTagName('password')->item(0)->nodeValue;
//$replace_password = $doc
}
$doc->save('../users/users.xml');