Thursday, February 19, 2009

How to Add CAPTCHA Security Images to Wildflower Comments

So you love Wildflower CMS for CakePHP, and you've used it to create a number of blogs. However you've noticed something. You are getting comment spammed.

Put simply, Wildflower doesn't have a good solution for preventing comment spam.

Initial Setup

1) Download the latest Wildflower development copy to your system. You can find the latest code for Wildflower on GitHub.

2) Set up your development environment. This includes:
  • Apache virtual host setup to point to your wildflower/app/webroot folder
  • Setup your local database called "wildflower"
  • Modify your hosts file so that it points to the Apache domain
  • Restart Apache.
3) At this point you should have a working copy of Wildflower.

Download Securimage CAPTCHA

You can download Securimage here:

Securimage Download
  • Grab the zip file and unpack it into your app/vendors/ directory.
  • Download the words.zip file and extract to app/vendors/securimage/words/
Building the Dynamic Image

  • Edit app/webroot/.htaccess and add the following line:

RewriteEngine On
RewriteRule ^img/captcha.jpg$ captcha.php [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-d
...
  • Test the image by going to http://yourvirtualhost/img/captcha.jpg

Create the Form View

Copy
  • ~/wildflower/views/wild_posts/view.ctp
to
  • /app/views/plugins/wildflower/wild_psts/view.ctp
(Create the directories as needed)
  • Now edit /app/views/plugins/wildflower/wild_psts/view.ctp and add the following two lines in the Comments Form.

$form->input('url', array('label' => 'Website URL (optional)')),
$form->input('content', array('label' => 'Message', 'type' => 'textbox')),
$html->image('captcha.jpg', array('alt'=>'Code', 'id'=>'security_image')),
$form->input('security_code', array('label' => 'Enter the word.')),
$form->hidden('post_id', array('value' => $post['WildPost']['id'])),


Process the Form


  • Open up ~/wildflower/models/wild_comment.php
  • Add the following Validation Rule:

public $validate = array(
'name' => VALID_NOT_EMPTY,
'email' => array('rule' => 'email', 'message' => 'Please enter a valid email address'),
'url' => array('rule' => 'url', 'message' => 'Please enter a valid URL', 'allowEmpty' => true),
'security_code' => array('rule'=>'validSecurityCode', 'message'=>'The word you entered was not correct.', 'allowEmpty' => false),
'content' => VALID_NOT_EMPTY
);
  • Add the following Function:
function validSecurityCode() {
if (!empty($this->data[$this->name]['security_code']) && strtolower($this->data[$this->name]['security_code']) != strtolower($_SESSION['securimage_code_value'])) {
unset($this->data[$this->name]['security_code']);
return false;
}
return true;
}

Try to add a comment to a blog post and see what happens.



Thursday, February 12, 2009

Writing Bad Test Cases


So, you spend days and days writing test cases and you find out that they become more of a hassle than you expected. Here are some common mistakes in writing test cases which may help you in your test case development.

1) Your test case creates live data. When you do a quick test case to try to make sure your function works, sometimes you simply set it up to create a new record in your database. This can happen in several ways.
  • You connect to a Live API with your test case. This could actually send credit card transactions, or send live records to your other application, which dilutes live data with fake records. This could lead to bad reporting in the long run.
  • You connect to your live database to test your functions. This is a really bad idea. Make sure your connection string points to a test database or you may end up losing mission-critical data.
2) You change your code to accommodate for test cases. This is a mistake as well. Your code should do what it was intended to do. If you need to add debug lines or incorporate new functionality into your code so that test cases will work, then chances are you either need to go back and study up on test case development or you need to redesign your code so that test cases will not interfere with the system process.

3) You make test cases depend on each other. This is a temptation that should be avoided. When you are running test cases, each function should be independent, even though test cases run linearly. You should not have one test function that presets data, and then assume that that function was called by the test suite.

For instance, let's say I have a test called testLoadUserData and that function loads user information into the variable $this->userdata for testing. Then under than I have a test for testShowUserData. It would be a mistake to assume that $this->userdata still exists in testShowUserData. Why? Because sometimes we comment out tests so the page doesn't take so long to load. This could breat testShowUserData if it depends on other tests. A better solution would be to write a loadVariables function and call it in each test case.

The goal of test cases is to help write modular functions. Often times poorly designed code will cause problems in developing test cases. If you write bad test cases, just consider it a learning experience, and keep at it until it works well.

Good code is poetic in nature.

Monday, February 09, 2009

5 Tips for Cake PHP Development

  1. Don't over-complicate your code.

  2. Work within the constraints of Cake.

  3. Make it work, then go back and make it work better.

  4. Skinny Controllers, fat models.

  5. Test Test Unit Test.