Jump to content

Recommended Posts

Hi All,

 

So I have basically started this form from the initial source code again as I was running into just too many problems and trying to fix them all at once just wasn't working. I have now worked through all the other error / notice messages I was getting, and am now on the part of submitting the new password to the database.

 

When submitting the "new" password it does not update in my table in my database. Any ideas why?

 

Form Code:

<?php
include_once 'db_connect.php';
include_once 'functions.php';
include_once 'formatting_includes.php';	
sec_session_start();
if (login_check($mysqli) == true) 
	{
    $logged = 'in';
	} 
	


$show = 'emailForm'; //which form step to show by default
if(!isset($_SESSION['lockout']))
   $_SESSION['lockout'] = false;
if (isset($_SESSION['lockout']) && $_SESSION['lockout'] == true && (mktime() > $_SESSION['lastTime'] + 900))

{
    $_SESSION['lockout'] = false;
    $_SESSION['badCount'] = 0;
}
if (isset($_POST['subStep']) && !isset($_GET['a']) && $_SESSION['lockout'] != true)
{
    switch($_POST['subStep'])
    {
        case 1:
            //we just submitted an email or username for verification
            $result = checkUNEmail($_POST['username'],$_POST['email']);
            if ($result['status'] == false )
            {
                $error = true;
                $show = 'userNotFound';
            } else {
                $error = false;
                $show = 'securityForm';
                $securityUser = $result['id'];
            }
        break;
        case 2:
            //we just submitted the security question for verification
            if ($_POST['user_id'] != "" && $_POST['security_a'] != "")
            {
                $result = checkSecAnswer($_POST['user_id'],$_POST['security_a']);
                if ($result == true)
                {
                    //answer was right
                    $error = false;
					$securityUser = $_POST['user_id'];
                    $show = 'successPage';
                    $passwordMessage = sendPasswordEmail($_POST['user_id']);
                    $_SESSION['badCount'] = 0;
                } else {
                    //answer was wrong
                    $error = true;
                    $show = 'securityForm';
                    $securityUser = $_POST['user_id'];
                    $_SESSION['badCount']++;
                }
            } else {
                $error = true;
                $show = 'securityForm';
                $securityUser = $_POST['user_id'];					
            }
        break;
        case 3:
            //we are submitting a new password (only for encrypted)
            if ($_POST['user_id'] == '' || $_POST['security_key'] == '') header("location: ../login.php");
            if (strcmp($_POST['password'],$_POST['confirmpwd']) != 0 || trim($_POST['password']) == '')
            {
                $error = true;
                $show = 'recoverForm';
            } else {
                $error = false;
                $show = 'recoverSuccess';
                updateUserPassword($_POST['user_id'],$_POST['password'],$_POST['security_key']);
            }
        break;
    }
}

elseif (isset($_GET['a']) && $_GET['a'] == 'recover' && $_GET['email'] != "") {
    $show = 'invalidKey';
    $result = checkEmailKey($_GET['email'],urldecode(base64_decode($_GET['u'])));
    if ($result == false)
    {
        $error = true;
        $show = 'invalidKey';
    } elseif ($result['status'] == true) {
        $error = false;
        $show = 'recoverForm';
        $securityUser = $result['user_id'];
    }
}
if (isset($_SESSION['badCount']) && ($_SESSION['badCount'] >= 3))
{
    $show = 'speedLimit';
    $_SESSION['lockout'] = true;
    $_SESSION['lastTime'] = '' ? mktime() : $_SESSION['lastTime'];
}
?>

	 


<!doctype html>
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Password Recovery</title>
<link href="css/styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="header"></div>
<div id="page">

<?php switch($show) {
    case 'emailForm': ?>
    <h2>Password Recovery</h2>
    <p>You can use this form to recover your password if you have forgotten it. Because your password is securely encrypted in our database, it is impossible actually recover your password, but we will email you a link that will enable you to reset it securely. Enter either your username or your email address below to get started.</p>
    <form action="<?= $_SERVER['PHP_SELF']; ?>" method="post">
        <div class="fieldGroup"><label for="username">Username</label><div class="field"><input type="text" name="username" id="username" value="" maxlength="20"></div></div>
        <div class="fieldGroup"><label>- OR -</label></div>
        <div class="fieldGroup"><label for="email">Email</label><div class="field"><input type="text" name="email" id="email" value="" maxlength="255"></div></div>
        <input type="hidden" name="subStep" value="1" />
        <div class="fieldGroup"><input type="submit" value="Submit" style="margin-left: 150px;" /></div>
        <div class="clear"></div>
    </form>
    <?php break; case 'securityForm': ?>
    <h2>Password Recovery</h2>
    <p>Please answer the security question below:</p>
    <?php if ($error == true) { ?><span class="error">You must answer the security question correctly to receive your lost password.</span><?php } ?>
    <form action="<?= $_SERVER['PHP_SELF']; ?>" method="post">
        <div class="fieldGroup">
			<label>Question</label>
				<div class="field"><?= getSecurityQuestion($securityUser); ?></div>
		</div>
			
        <div class="fieldGroup">
			<label for="security_a">Answer</label>
				<div class="field"><input type="text" name="security_a" id="security_a" value="" maxlength="255"></div>
		</div>
        <input type="hidden" name="subStep" value="2" />
		<input type="hidden" name="user_id" value="<?php echo $securityUser; ?>" />		

        <div class="fieldGroup"><input type="submit" value="Submit" style="margin-left: 150px;" /></div>
        <div class="clear"></div>
    </form>
 
     
     <?php break; case 'userNotFound': ?><br>    
	 <h2>Password Recovery</h2><br>    
	 <p>The username or email you entered was not found in our database.<br /><br />
	 <a href="?">Click here</a> to try again.</p><br>    
	 <?php break; case 'successPage': ?><br>    
	 <h2>Password Recovery</h2><br>    
	 <p>An email has been sent to you with instructions on how to reset your password. 
	 <strong>(Mail will not send unless you have an smtp server running locally.)</strong>
	 <br /><br /><a href="../login.php">Return</a> to the login page. </p><br>    
	 <p>This is the message that would appear in the email:</p><br>    
	 <div class="message"><?= $passwordMessage;?></div><br>    
	
	
	 <?php break;
case 'recoverForm': ?>
    <h2>Password Recovery</h2>
    <p>Welcome back, <?= getUserName($securityUser=='' ? $_POST['user_id'] : $securityUser); ?>.</p>
    <p>In the fields below, enter your new password.</p>
    <?php if ($error == true) { ?><span class="error">The new passwords must match and must not be empty.</span><?php } ?>
    <form action="<?= $_SERVER['PHP_SELF']; ?>" method="post">
        <div class="fieldGroup"><label for="password">New Password</label><div class="field"><input type="password" class="input" name="password" id="password" value="" maxlength="20"></div></div>
        <div class="fieldGroup"><label for="confirmpwd">Confirm Password</label><div class="field"><input type="password" class="input" name="confirmpwd" id="confirmpwd" value="" maxlength="20"></div></div>
        <input type="hidden" name="subStep" value="3" />
        <input type="hidden" name="user_id" value="<?= $securityUser=='' ? $_POST['user_id'] : $securityUser; ?>" />
        <input type="hidden" name="security_key" value="<?= $_GET['email']=='' ? $_POST['security_key'] : $_GET['email']; ?>" />
    <input class="bt_login" type="button" value="Reset" onClick="return resetformhash(this.form,this.form.password,this.form.confirmpwd);" style="margin-left: 150px;"/>
        <div class="clear"></div>
    </form>
    <?php break; case 'invalidsecurity_key': ?>
    <h2>Invalid security_key</h2>
    <p>The security_key that you entered was invalid. Either you did not copy the entire security_key from the email, you are trying to use the security_key after it has expired (3 days after request), or you have already used the security_key in which case it is deactivated.<br /><br /><a href="login.php">Return</a> to the login page. </p>
    <?php break; case 'recoverSuccess': ?>
    <h2>Password Reset</h2>
    <p>Congratulations! your password has been reset successfully.</p><br /><br /><a href="login.php">Return</a> to the login page. </p>
    <?php break; case 'speedLimit': ?>
    <h2>Warning</h2>
    <p>You have answered the security question wrong too many times. You will be locked out for 15 minutes, after which you can try again.</p><br /><br /><a href="login.php">Return</a> to the login page. </p>
    <?php break; }
    ob_flush();
    $mysqli->close();
?>


<!--PAGE CONTENT-->
</div>
</body>
</html>


Password Functions:

function checkUNEmail($username,$email)
{
    global $mysqli;
    $error = array('status'=>false,'user_id'=>0);
    if (isset($email) && trim($email) != '') {
        //email was entered
        if ($stmt = $mysqli->prepare("SELECT id FROM members WHERE email = ? LIMIT 1"))
        {
            $stmt->bind_param('s',trim($email));
            $stmt->execute();
            $stmt->store_result();
            $numRows = $stmt->num_rows();
            $stmt->bind_result($user_id);
            $stmt->fetch();
            $stmt->close();
            if ($numRows >= 1) return array('status'=>true,'id'=>$user_id);
        } else { return $error; }
    } elseif (isset($username) && trim($username) != '') {
        //username was entered
        if ($stmt = $mysqli->prepare("SELECT id FROM members WHERE username = ? LIMIT 1"))
        {
            $stmt->bind_param('s',trim($username));
            $stmt->execute();
            $stmt->store_result();
            $numRows = $stmt->num_rows();
            $stmt->bind_result($user_id);
            $stmt->fetch();
            $stmt->close();
            if ($numRows >= 1) return array('status'=>true,'id'=>$user_id);
        } else { return $error; }
    } else {
        //nothing was entered;
        return $error;
    }
}



function getSecurityQuestion($user_id)
{
    global $mysqli;
    $questions = array();
    $questions[0] = "What is your mother's maiden name?";
    $questions[1] = "What city were you born in?";
    $questions[2] = "What is your favorite colour?";
    $questions[3] = "What year did you graduate from High School?";
    $questions[4] = "What is your pet's name?";
    $questions[5] = "What is your favorite model of car?";
    if ($stmt = $mysqli->prepare("SELECT security_q FROM members WHERE id = ? LIMIT 1"))
    {
        $stmt->bind_param('i',$user_id);
        $stmt->execute();
        $stmt->store_result();
        $stmt->bind_result($security_q);
        $stmt->fetch();
        $stmt->close();
        return $questions[$security_q];
    } else {
        return false;
    }
}
 
function checkSecAnswer($user_id, $security_a)
{
    global $mysqli;
    if ($stmt = $mysqli->prepare("SELECT username FROM members WHERE id = ? AND LOWER(security_a) = ? LIMIT 1"))
    {
        $security_a = strtolower($security_a);
        $stmt->bind_param('is',$user_id, $security_a);
        $stmt->execute();
        $stmt->store_result();
        $numRows = $stmt->num_rows();
        $stmt->close();
        if ($numRows >= 1) { return true; }
    } else {
        return false;
    }
}




function sendPasswordEmail($user_id)
{
    global $mysqli;
    if ($stmt = $mysqli->prepare("SELECT username, email, password FROM members WHERE id = ? LIMIT 1"))
    {
        $stmt->bind_param('i',$user_id);
        $stmt->execute();
        $stmt->store_result();
        $stmt->bind_result($username, $email, $password);
        $stmt->fetch();
        $stmt->close();
        $expFormat = mktime(date("H"), date("i"), date("s"), date("m")  , date("d")+3, date("Y"));
        $expDate = date("Y-m-d H:i:s",$expFormat);
        $salt = hash('sha512', uniqid(openssl_random_pseudo_bytes(16), TRUE));		
        $security_key = hash('sha512',$username . '_' . $email . rand(0,10000) .$expDate . $salt);
        if ($stmt = $mysqli->prepare("INSERT INTO password_reset (user_id, security_key, expiry_date) VALUES (?,?,?)"))
        {
            $stmt->bind_param('iss',$user_id, $security_key, $expDate);
            $stmt->execute();
            $stmt->close();
            $passwordLink = "<a href=\"?a=recover&email=" . $security_key . "&u=" . urlencode(base64_encode($user_id)) . "\">http://jhbvcstracking/resetpwd.php?a=recover&email=" . $security_key . "&u=" . urlencode(base64_encode($user_id)) . "</a>";
            $message = "Dear $username,\r\n";
            $message .= "Please visit the following link to reset your password:\r\n";
            $message .= "-----------------------\r\n";
            $message .= "$passwordLink\r\n";
            $message .= "-----------------------\r\n";
            $message .= "Please be sure to copy the entire link into your browser. The link will expire after 3 days for security reasons.\r\n\r\n";
            $message .= "If you did not request this forgotten password email, no action is needed, your password will not be reset as long as the link above is not visited. However, you may want to log into your account and change your security password and answer, as someone may have guessed it.\r\n\r\n";
            $message .= "Thanks,\r\n";
            $message .= "-- Our site team";
            $headers .= "From: Our Site <webmaster@oursite.com
			
<script type='text/javascript'>
/* <![CDATA[ */
(function(){try{var s,a,i,j,r,c,l,b=document.getElementsByTagName('script');l=b[b.length-1].previousSibling;a=l.getAttribute('data-cfemail');if(a){s='';r=parseInt(a.substr(0,2),16);for(j=2;a.length-j;j+=2){c=parseInt(a.substr(j,2),16)^r;s+=String.fromCharCode(c);}s=document.createTextNode(s);l.parentNode.replaceChild(s,l);}}catch(e){}})();
/* ]]> */
</script>> \n";
            $headers .= "To-Sender: \n";
            $headers .= "X-Mailer: PHP\n"; // mailer
            $headers .= "Reply-To: webmaster@oursite.com<script type='text/javascript'>
/* <![CDATA[ */
(function(){try{var s,a,i,j,r,c,l,b=document.getElementsByTagName('script');l=b[b.length-1].previousSibling;a=l.getAttribute('data-cfemail');if(a){s='';r=parseInt(a.substr(0,2),16);for(j=2;a.length-j;j+=2){c=parseInt(a.substr(j,2),16)^r;s+=String.fromCharCode(c);}s=document.createTextNode(s);l.parentNode.replaceChild(s,l);}}catch(e){}})();
/* ]]> */
</script>\n"; // Reply address
            $headers .= "Return-Path: webmaster@oursite.com<script type='text/javascript'>
/* <![CDATA[ */
(function(){try{var s,a,i,j,r,c,l,b=document.getElementsByTagName('script');l=b[b.length-1].previousSibling;a=l.getAttribute('data-cfemail');if(a){s='';r=parseInt(a.substr(0,2),16);for(j=2;a.length-j;j+=2){c=parseInt(a.substr(j,2),16)^r;s+=String.fromCharCode(c);}s=document.createTextNode(s);l.parentNode.replaceChild(s,l);}}catch(e){}})();
/* ]]> */
</script>\n"; //Return Path for errors
            $headers .= "Content-Type: text/html; charset=iso-8859-1"; //Enc-type
            $subject = "Your Lost password";
            @mail($email,$subject,$message,$headers);
            return str_replace("\r\n","<br/ >",$message);
        }
    }
}


function checkEmailKey($security_key,$user_id)
{
    global $mysqli;
    $curDate = date("Y-m-d H:i:s");
    if ($stmt = $mysqli->prepare("SELECT user_id FROM password_reset WHERE security_key = ? AND user_id = ? AND expiry_date >= ?"))
    {
        $stmt->bind_param('sis',$security_key, $user_id, $curDate);
        $stmt->execute();
        $stmt->execute();
        $stmt->store_result();
        $numRows = $stmt->num_rows();
        $stmt->bind_result($user_id);
        $stmt->fetch();
        $stmt->close();
        if ($numRows > 0 && $user_id != '')
        {
            return array('status'=>true,'user_id'=>$user_id);
        }
    }
    return false;
}
 
function updateUserPassword($user_id, $password, $security_key)
{
    global $mysqli;
    if (checkEmailsecurity_key($security_key,$user_id) === false) return false;
    if ($stmt = $mysqli->prepare("UPDATE members SET password = ? WHERE id = ?"))
    {
        $password = hash('sha512',trim($password) . $salt);
        $stmt->bind_param('si',$password,$user_id);
        $stmt->execute();
        $stmt->close();
        $stmt = $mysqli->prepare("DELETE FROM password_reset WHERE security_key = ?");
        $stmt->bind_param('s',$security_key);
        $stmt->execute();
    }
}
 
function getUserName($user_id)
{
    global $mysqli;
    if ($stmt = $mysqli->prepare("SELECT username FROM members WHERE id = ?"))
    {
        $stmt->bind_param('i',$user_id);
        $stmt->execute();
        $stmt->store_result();
        $stmt->bind_result($username);
        $stmt->fetch();
        $stmt->close();
    }
    return $username;
}

These are the messages I am getting from my form when I hit submit:

 
Password Recovery

Welcome back,

TestAgent2.

In the fields below, enter your new password.

The new passwords must match and must not be empty.

 

 

I am validating the password fields (i.e length, matching password and confirmation, character types etc) using javascript.) So I know that the "new" password I a testing with is correct and matching.

 

Thanks

The new passwords must match and must not be empty.

 

 

that message is the result of a conditional test in your code having a true value. have you looked at the values being tested by that conditional statement so that you would know which one(s) are not the expected values and are causing that message to be output?

Edited by mac_gyver

I did a

 var_dump($_POST);exit;

here are the results of that.

 

array(6) { ["password"]=> string(0) "" ["confirmpwd"]=> string(0) "" ["subStep"]=> string(1) "3" ["user_id"]=> string(2) "40" ["security_key"]=> string(128) "0cb130754bf129d2618c95e521c974c8d6fb696447b67f6144ef58687dbc7d9b02ac877bf1e70baf6f9d7c6e8139889bd19a27f718432e44841f68e7cea424c5" ["p"]=> string(128) "e13efc991a9bf44bbb4da87cdbb725240184585ccaf270523170e008cf2a3b85f45f86c3da647f69780fb9e971caf5437b3d06d418355a68c9760c70a31d05c7" }

 

This is where I did the check:

        case 3:
            //we are submitting a new password (only for encrypted)
            if ($_POST['user_id'] == '' || $_POST['security_key'] == '') header("location: ../login.php");
			
            if (strcmp($_POST['password'],$_POST['confirmpwd']) != 0 || trim($_POST['password']) == '')
			{
                $error = true;
                $show = 'recoverForm';
				var_dump($_POST);exit; 
            } else {
                $error = false;
                $show = 'recoverSuccess';
                updateUserPassword($_POST['user_id'],$_POST['password'],$_POST['security_key']);
            }
        break;
here are the results of that.

 

 

yes, but did you look at that and even try to solve the problem?

 

at this point, all you are doing is dumping your code, errors, and data on a forum and expecting someone else to fix your code for you. make an attempt and others will help you when you truly get stuck with a coding problem. where you are stuck at now is not even looking at what is happening in your code.

mac_gyver, if you recall I have been looking at this problem for almost two weeks now. I have tried various solutions, and closed off a previous thread on the advice of another forum member. I had gone all the way back to starting over with the original source code and cleaning out the notices / errors piece by piece.
 

The last time I had gotten this far in my code my table was being updated, but the information that was being submitted did not work for logging in and the account would end up being corrupted. I just don't want to go back to a point where I need to restart because of all the changes.

 

Edited by SalientAnimal

I acknowledge that from what I have posted, it appears that the  array(6) { ["password"]=> string(0) "" ["confirmpwd"]=> string(0) fields are blank as the string length is coming up as 0. However, I know that I have filled in both the fields and these are the fields being populated in my form

This is the form where the user would enter their "new" password, keep in mind some of the functions / checks are done at the top of the code.

case 'recoverForm': ?>
    <h2>Password Recovery</h2>
    <p>Welcome back, <?= getUserName($securityUser=='' ? $_POST['user_id'] : $securityUser); ?>.</p>
    <p>In the fields below, enter your new password.</p>
    <?php if ($error == true) { ?><span class="error">The new passwords must match and must not be empty.</span><?php } ?>
    <form action="<?= $_SERVER['PHP_SELF']; ?>" method="post">
        <div class="fieldGroup"><label for="password">New Password</label><div class="field"><input type="password" class="input" name="password" id="password" value="" maxlength="20"></div></div>
        <div class="fieldGroup"><label for="confirmpwd">Confirm Password</label><div class="field"><input type="password" class="input" name="confirmpwd" id="confirmpwd" value="" maxlength="20"></div></div>
        <input type="hidden" name="subStep" value="3" />
        <input type="hidden" name="user_id" value="<?= $securityUser=='' ? $_POST['user_id'] : $securityUser; ?>" />
        <input type="hidden" name="security_key" value="<?= $_GET['email']=='' ? $_POST['security_key'] : $_GET['email']; ?>" />
    <input class="bt_login" type="button" value="Reset" onClick="return resetformhash(this.form,this.form.password,this.form.confirmpwd);" style="margin-left: 150px;"/>
        <div class="clear"></div>
    </form>

Is there anything else you need to see?

OK - after I cleaned up your code so I could make sense of it, I see that you have no submit button.  Apparently you are using JS to submit your form and so now you have to look at it and determine why the form's password fields are empty.  Must be something you are doing in the JS function that you call in 'resetformhash'

 

Question.

Why all the divs?  Do you really need two divs to enclose one input field?

I explained this in a previous post. The javascript function that is being called appends an element 'p' to the form, and clears the contents of 'password'. The 'p' is a hashed version of 'password', with the process aimed at a security measure of not sending the unhashed password via headers.

Edited by paddyfields

Sorry Guys I wasn't online at all yesterday. Here is the  resetformhash script:

function resetformhash(form, password, conf) 

	{
     // CHECK TO ENSURE THAT ALL FIELDS ON THE FORM HAVE BEEN COMPLETED.
    if (  password.value == ''       || 
          conf.value == '') 
	{
        alert('Please complete all details to reset your password');
        return false;
    }




    // CHECK TO ENSURE THAT THE PASSWORD IS AT LEAST 6 CHARACTERS IN LENGTH - A MORE DETAILED CHECK CAN ALSO BE DONE.
    if (password.value.length < 6)
	{
        alert('Passwords must be at least 6 characters long.  Please try again');
        form.password.focus();
        return false;
    }

   	
    // COMPARE TWO PASSWORDS AND ENSURE THAT THEY MATCH.
    if (password.value != conf.value) 
	{
        alert('Your password and confirmation do not match. Please try again');
        form.password.focus();
        return false;
    }

    // CREATES A NEW ELEMENT TO HASH THE PASSWORD FIELD. 
    var p = document.createElement("input");

    // ADD THE NEWLY CREATED ELEMENT TO THE FORM 
    form.appendChild(p);
    p.name = "p";
    p.type = "hidden";
    p.value = hex_sha512(password.value);

    // ENSURE THAT THE PLAINTEXT PASSWORD ISN'T SENT OVER THE SERVER.
    password.value = "";
    conf.value = "";
	
	
	
	// SUBMIT THE COMPLETED FORM
    form.submit();
    return true;


	
}

So reading what you guys wrote in my absence yesterday, I recall you saying to look out for the "p" as apposed to "password" in the previous thread, however when I did that I was questioned why I did it and eventually changed it back (Unless I changed this in the wrong place.

 

So just to be sure, where in my form am I meant to change "password" to "p"? Would this just be in the check, i.e. 

        case 3:
            //we are submitting a new password (only for encrypted)
            if ($_POST['user_id'] == '' || $_POST['security_key'] == '') header("location: ../login.php");
			
            if (strcmp($_POST['p'],$_POST['confirmpwd']) != 0 || trim($_POST['p']) == '')
			{
                $error = true;
                $show = 'recoverForm';
				var_dump($_POST);exit; 
            } else {
                $error = false;
                $show = 'recoverSuccess';
                updateUserPassword($_POST['user_id'],$_POST['password'],$_POST['security_key']);
            }
        break;

Have you actually tried it?

 

Your 'confirmpwd' is also being cleared by the javascript function, so that will always cause the code processing your form to fail the condition.

 

EDIT: Bare in mind that you'll want to add server side validation if you want this to be harder to mess with, javascript validation can be easily bypassed.

 case 3:

            //we are submitting a new password (only for encrypted)
            if ($_POST['user_id'] == '' || $_POST['security_key'] == '') header("location: ../login.php");
			
            if ($_POST['p'] == '')
            {
                $error = true;
                $show = 'recoverForm';

            } else {

                $error = false;
                $show = 'recoverSuccess';
                updateUserPassword($_POST['user_id'],$_POST['p'],$_POST['security_key']);
            }

        break
Edited by paddyfields

Awesome, my reset form is now resetting the password and I am able to login with the new password. 

 

There is just one notice that I am now getting, but I can try and work on getting rid of that notice. Thanks so much for all the help. Especially to you paddyfields.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.