PHP and Captcha Submit help

Discussion in 'PHP' started by gilgil2, Jul 27, 2012.

  1. #1
    Hi, it's my first time using captcha with PHP, I think I'm pretty close. I can get it echo everything is right or whatever when the fields are filled in correctly and correct words are entered, but what I can't do is make it run the script from another file when everything does work as I can't use PHP header as html is already there and I tired javascript but the variables weren't passed. Any help will be very appreciated, here is the code:
       <?php 
    
    
        $link = mysql_connect('', '', ''); 
        if (!$link) { 
            die('Could not connect: ' . mysql_error()); 
        } 
        echo 'Connected successfully'; 
        mysql_select_db(); 
    
    
        if (eregi('^[[:alnum:]\.\'\-]{4,30}$', stripslashes(trim($_POST['username']))) ) {
                $username = mysql_real_escape_string($_POST['username']);
                $query = "SELECT username FROM users WHERE username = '$username'";
                $result = @mysql_query($query);
                $num = @mysql_num_rows($result);
    
                if ($num> 0) {
                    $errors[] = '<font color="red">The username you have chosen has already been taken, please try again.</font>';
                } else {
                    $username = mysql_real_escape_string($_POST['username']);
                }
            } else {
                $errors[] = '<font color="red">Please provide a valid username between 4 and 30 characters.</font>';
    
        }
    
        if (!eregi('^[a-zA-Z]+[a-zA-Z0-9_-]*@([a-zA-Z0-9]+){1}(\.[a-zA-Z0-9]+){1,2}', stripslashes(trim($_POST['email'])) )) {
                $errors[] = '<font color="red">Please provide a valid email address.</font>';
            } else {
                $email = mysql_real_escape_string($_POST['email']);
            }
    
        if (!empty($_POST['password1'])) {
                if ($_POST['password1'] != $_POST['password2']) {
                    $errors[] = '<font color="red">The 2 passwords you have entered do not match.</font>';
                } else {
                    $password = $_POST['password1'];
                }
            } else {
                $errors[] = '<font color="red">Please provide a password.</font>';
            }
    
        //Recaptcha script
    
        // call the lib..
        require_once('recaptchalib.php');
    
        // Get a key from http://recaptcha.net/api/getkey
        $publickey = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
        $privatekey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
    
        # was there a reCAPTCHA response?
        if ($_POST["submit"]) {
            $response = recaptcha_check_answer($privatekey,
                $_SERVER["REMOTE_ADDR"],
                $_POST["recaptcha_challenge_field"],
                $_POST["recaptcha_response_field"]);
    
    
    
        if (empty($errors) && ($response->is_valid)) {
    
    *** //Here is where I would to insert the header or whatever to registerscript.php
     ***
    
        } elseif (!empty($errors)) {
                echo '<h3>Error!</h3>
                The following error(s) occured:<br />';
    
                foreach ($errors as $msg) {
                    echo " - <font color=\"red\">$msg</font><br />\n";
                }
        }
    
        else {echo 'Sorry, those words did not match the image';}
    
        }
    
    
    
        ?> 
    
        <html>
    
        <h3>Register</h3>
        <form method="post">
            <p><input type="text" name="username" value="<?php if (isset($_POST['username'])) echo $_POST['username']; ?>" size="30" maxlength="30" /> <small>Username</small></p>
    
            <p><input type="password" name="password1" size="30" maxlength="40" /> <small>Password</small></p>
    
            <p><input type="password" name="password2" size="30" maxlength="40" /> <small>Confirm Password</small></p>
    
            <p><input type="text" name="email" size="30" maxlength="30" value="<?php if(isset($_POST['email'])) echo $_POST['email']; ?>" /> <small>Email Address</small></p>
    
    
          <?php echo recaptcha_get_html($publickey, $error); ?>
        <input style="width: 317px" type="submit" value="submit" name="submit"/>
        </form>
    
        <p>If you are already registered, <a href="http://...login.php">log in</a></p>
    
        </html>
    
    PHP:
    It all works properly, the erros messages etc., so just the redirect bit. I also realise I haven't encrypted password and probably have escaped MySql but will do that before it goes live. Thanks for your help
     
    Solved! View solution.
    gilgil2, Jul 27, 2012 IP
  2. gilgil2

    gilgil2 Member

    Messages:
    71
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    41
    #2
    Sorry to keep pushing this, but does anyone have suggestions? Even if it completely changes everything?Thanks
     
    gilgil2, Jul 30, 2012 IP
  3. Thorlax402

    Thorlax402 Member

    Messages:
    194
    Likes Received:
    2
    Best Answers:
    5
    Trophy Points:
    40
    #3
    Hello there. I was just reading through your file, but I'm not quite sure what the issue is you're describing? Would you mind walking me through the process of reproducing your issue?

    Also, a few other things I noticed about the above code:
    1) I would recommend using preg_match() instead of eregi() as eregi() has been deprecated as of PHP 5.3
    2) Since you don't use the username at all after checking it against the database, there is no need for the else condition here:
    if ($num> 0) {
        $errors[] = '<font color="red">The username you have chosen has already been taken, please try again.</font>';
    } else {
        $username = mysql_real_escape_string($_POST['username']);
    }
    PHP:
     
    Thorlax402, Aug 1, 2012 IP
  4. #4
    You've got a number of issues that to me mean you're learning from a pre 2001ish source... Not only is your logic flow a little... weird, the markup you are outputting seems to have it's head wedged up 1998's backside -- given that's the last time anyone had any business using the FONT tag... What makes an INPUT and it's label a paragraph? Why are you using SMALL instead of LABEL? You're using the outdated and deprecated mysql_ functions... You're even outputting your FONT tags TWICE per $error[] since you have them both when it's defined, and when you output it... let's see... you're using eregi instead of preg -- the former is also having formal support dropped in php, hence the big red warning box on it's page.. for something that PHP's filter command can already check and could be better implemented with even more things checked like actual lengths and if it's got a valid A/MX name.

    The willy nilly and seemingly random indentation style certainly isn't helping make it easier to maintain/understand either. Also might help if you used valid comments instead of all those random characters that are going to just parse wrong.

    Though I think your biggest problem is you're only loading recaptchalib when the SUBMIT was hit -- as such the function to show it on the form isn't present under any other condition. recaptchalib.php needs to be loaded whether the form was submitted or not, so that the recaptcha_get_html function exists for the form to call it!

    I would move the setting of the key and the load of the lib right up to the top of the code.

    Took a few moments to do a quick rewrite "my way"... I made 3 files, one for the actual logic (whcih handles both form and submit), one for the common template stuff, and a CSS file.

    register.php
    
    <?php 
    
    require_once('register.template.php');
    require_once('recaptchalib.php');
    
    // Plug in below keys from http://recaptcha.net/api/getkey
    $publicKey='xxxxxx';
    $privateKey='xxxxxx';
    $errors=array();
    
    $errors['password']='Test Error Condition';
    
    function labelInput($label,$type,$name,$maxLength,$errorName,$showErrorText=true) {
    	global $errors;
    	
    	$id='register'.$name;
    	echo '
    		<div',(isset($errors[$errorName]) ? ' class="error"' : ''),'>
    			<label for="',$id,'">',$label,':</label>
    			<input
    				type="',$type,'"
    				name="',$name,'"
    				id="',$id,'"
    				maxlength="',$maxLength,'"',(
    					isset($_POST[$name]) ? '
    				value="'.htmlspecialchars($_POST[$name]).'"' : ''
    				),'
    			/>',($showErrorText && isset($errors[$errorName]) ? '
    			<p>'.$errors[$errorName].'</p>' : ''
    			),'
    		</div>';
    		
    } // function labelInput
    
    function registerForm() {
    	global $publicKey;
    	
    	theme_header('Registration Form');
    	
    	echo '
    		<form method="post" action="register.php" id="registerForm">
    			<fieldset>
    				<legend><span>Register</span></legend>';
    				
    	labelInput('User Name','text','username',30,'username');
    	labelInput('Password','password','password1',30,'password',false);
    	labelInput('Verify Password','password','password2',30,'password');
    	labelInput('E-Mail Address','text','email',255,'email');
    	
    	echo recaptcha_get_html($publicKey),(
    		isset($errors['captcha']) ?
    		'<p class="error">'.$errors['captcha'].'</p>' :
    		''
    	),'
    				<input type="submit" value="Register" class="submit" />
    				<input type="hidden" name="fromForm" value="registerForm" />
    			</fieldset>
    		</form>
    		<p>
    			If you are already registered, <a href="login.php">log in</a>
    		</p>';
    		
    	theme_footer();
    		
    } // function registerForm
    
    function isValidEmail($address) {
    	if (filter_var($address,FILTER_VALIDATE_EMAIL)==FALSE) {
    		return false;
    	}
    	list($local,$domain)=explode('@',$address);
    	$localLength=strlen($local);
    	$domainLength=strlen($domain);
    	return (
    		($localLength>0 && $localLength<65) &&
    		($domainLength>3 && $domainLength<256) &&
    		(
    			checkdnsrr($domain,'MX') ||
    			checkdnsrr($domain,'A')
    		)
    	);
    } // function isValidEmail
    
    if (isset($_POST['fromForm']) && ($_POST['fromForm']=='registerForm')) {
    
    	try {
    		$db=new PDO('mysql:dbname=test;host=localhost;','username','password');
    		echo 'Connected successfully<br />'; 
    	} catch (PDOException $e) {
    		die ('Connection failed: '.$e->getMessage());
    	}
    
    	if (isset($_POST['username'])) {
    		$userName=trim($_POST['username']);
    		$userNameLength=strlen($userName);
    		if (($userNameLength>3) && ($userNameLength<31)) {
    			$statement=$db->prepare('
    				COUNT(username) AS matches
    				FROM users
    				WHERE username = :username
    			');
    			$statement->execute(array(
    				':username' => $userName
    			));
    			if ($statement->fetchColumn()>0) {
    				$errors['username']='The username you have chosen has already been taken, please try again.';
    			}
    		} else $errors['username']='Please provide a valid username between 4 and 30 characters.';
    	} else $errors['username']='You failed to provide a username';
    
    	if (isset($_POST['email'])) {
    		if (!isValidEmail($_POST['email'])) {
    			$errors['email']='You entered an invalid E-Mail address.';
    		}
    	} else $errors['email']='You failed to enter an E-mail address.';
    
    	if (isset($_POST['password1']) && isset($_POST['password2'])) {
    		if ($_POST['password1']!=$_POST['password2']) {
    			$errors['password']='The two passwords you have entered do not match.';
    		}
    	} else $errors['password']='You failed to fill in both password fields.';
    
    	// was there a reCAPTCHA response?
    	if (
    		isset($_POST['recaptcha_challenge_field']) &&
    		isset($_POST['recaptcha_response_field'])
    	) {
    		$response=recaptcha_check_answer(
    			$privateKey,
    			$_SERVER['REMOTE_ADDR'],
    			$_POST["recaptcha_challenge_field"],
    			$_POST["recaptcha_response_field"]
    		);
    		if ($response->is_valid) {
    			if (count($errors)==0) {
    				// do your registration processing here!
    				theme_header('Registration Successful');
    				echo '<p>Form was filled out correctly</p>';
    				theme_footer();
    			}
    		} else {
    			$errors['captcha']='Sorry, you failed to enter the captcha correctly.';
    			showErrors(); // also calls registerForm
    		}
    	} else {
    		$errors['captcha']='You failed to fill out the captcha properly';
    	}
    	
    	if (count($errors)>0) registerForm();
    	
    } else registerForm();
    
    ?>
    Code (markup):
    register.template.php
    
    <?php
    
    function theme_header($pageTitle='') {
    
    	echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html
    	xmlns="http://www.w3.org/1999/xhtml"
    	lang="en"
    	xml:lang="en"
    ><head>
    
    <meta
    	http-equiv="Content-Type"
    	content="text/html; charset=utf-8"
    />
    
    <link
    	type="text/css"
    	rel="stylesheet"
    	href="screen.css"
    	media="screen,projection,tv"
    />
    
    <title>
    	',(
    		empty($pageTitle) ? '' : $pageTitle.' - '
    	),'Website Name
    </title>
    
    </head><body>
    
    <div id="pageWrapper">';
    
    } // function theme_header
    
    function theme_footer() {
    
    	echo '
    	<div id="footer">
    		Disclaimer here
    	<!-- #footer --></div>
    	
    <!-- #pageWrapper --></div>
    
    </body></html>';
    
    } // function theme_footer
    
    ?>
    Code (markup):
    and the screen.css

    
    /* null margins and padding to give good cross-browser baseline */
    html,body,address,blockquote,div,
    form,fieldset,caption,
    h1,h2,h3,h4,h5,h6,
    hr,ul,li,ol,ul,
    table,tr,td,th,p,img {
    	margin:0;
    	padding:0;
    }
    
    body {
    	font:normal 100%/150% arial,helvetica,sans-serif;
    }
    
    #pageWrapper {
    	min-width:48em;
    	max-width:72em;
    	width:95%;
    	margin:0 auto;
    }
    
    p {
    	padding:0.5em;
    }
    
    #footer {
    	text-align:center;
    	padding:1em;
    }
    
    #registerForm fieldset {
    	overflow:hidden; /* wrap floats */
    	zoom:1; /* trip haslayout, wrap floats legacy IE */
    	padding:0.5em;
    }
    
    #registerForm label {
    	display:inline-block;
    	width:8em;
    	text-align:right;
    }
    
    #registerForm input {
    	width:310px;
    	/* set font since it does NOT inherit right */
    	font:normal 100%/140% arial,helvetica,sans-serif;
    }
    
    #recaptcha_widget_div,
    #registerForm iframe { /* should be our recaptcha */
    	display:block;
    	margin-left:8em;
    
    }
    
    #registerForm .error input {
    	background:#FCC;
    }
    
    #registerForm p.error,
    #registerForm .error p {
    	padding:0 0 0.5em 8px;
    	margin-left:8em;
    	color:#F00;
    }
    
    #registerForm .submit {
    	margin-left:8em;
    }
    
    Code (markup):
    Cleans up the markup into something presentable/modern, appears to be working properly with the recaptcha, cleans up the logic flow, puts the errors in the form instead of as a separate list, and is set up to use PDO instead of the outdated mysql functions. Would be valid XHTML 1.0 Strict if the recaptcha script wasn't badly coded.

    Hope this helps.
     
    Last edited: Aug 2, 2012
    deathshadow, Aug 2, 2012 IP
  5. gilgil2

    gilgil2 Member

    Messages:
    71
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    41
    #5
    Thanks for the help deathshadow.

    I almost have this working now, only I get this message if the captcha is entered inccorectly:

    Fatal error: Call to undefined function showErrors()

    showErrors() appears for the first time at the bottom of register.php and nowhere else. The others errors all work, and if I take showErros() out and type captcha in wrong then it doesn't process the info but also doesn't give an error message, so I think it works apart from showing the error message.

    Any help is very appreciated.
    Gilgil2
     
    gilgil2, Sep 10, 2012 IP
  6. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #6
    Gimme a bit... showerrors should be in the template, appears I forgot to add it...
     
    deathshadow, Sep 10, 2012 IP