Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

First pass at honeypot captcha

  • Loading branch information...
commit 066aca7bdd3b026c7a2b13fdae575c889c1a9d18 1 parent fe48ff0
Curtis Miller authored April 09, 2010
35  LICENSE
... ...
@@ -1,20 +1,21 @@
1  
-Copyright (c) 2009 curtis
  1
+The MIT License
2 2
 
3  
-Permission is hereby granted, free of charge, to any person obtaining
4  
-a copy of this software and associated documentation files (the
5  
-"Software"), to deal in the Software without restriction, including
6  
-without limitation the rights to use, copy, modify, merge, publish,
7  
-distribute, sublicense, and/or sell copies of the Software, and to
8  
-permit persons to whom the Software is furnished to do so, subject to
9  
-the following conditions:
  3
+Copyright (c) 2010 Curtis Miller
10 4
 
11  
-The above copyright notice and this permission notice shall be
12  
-included in all copies or substantial portions of the Software.
  5
+Permission is hereby granted, free of charge, to any person obtaining a copy
  6
+of this software and associated documentation files (the "Software"), to deal
  7
+in the Software without restriction, including without limitation the rights
  8
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9
+copies of the Software, and to permit persons to whom the Software is
  10
+furnished to do so, subject to the following conditions:
13 11
 
14  
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17  
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18  
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19  
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20  
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  12
+The above copyright notice and this permission notice shall be included in
  13
+all copies or substantial portions of the Software.
  14
+
  15
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21
+THE SOFTWARE.
62  README.markdown
Source Rendered
... ...
@@ -0,0 +1,62 @@
  1
+# honeypot-captcha
  2
+
  3
+A simple way to add honeypot captchas in your Rails forms.
  4
+
  5
+## Honeypot Captcha
  6
+
  7
+Honeypot captchas work off the premise that you can present different form
  8
+fields to a spam bot than you do to a real user. Spam bots will typically try
  9
+to fill all fields in a form and will not take into account CSS styles.
  10
+
  11
+We add bogus fields to a form and then check to see if those fields are
  12
+submitted with values. If they are, we assume that we encountered a spam bot.
  13
+
  14
+# Usage
  15
+
  16
+I've tried to make it pretty simple to add a honeypot captcha, but I'm open to
  17
+any suggestions you may have.
  18
+
  19
+## form_for
  20
+
  21
+Simply specify that the form has a honeypot in the HTML options hash:
  22
+
  23
+<% form_for Comment.new, :html => { :honeypot => true } do |form| -%>
  24
+  ...
  25
+<% end -%>
  26
+
  27
+## form_tag with block
  28
+
  29
+Simply specify that the form has a honeypot in the options hash:
  30
+
  31
+<% form_tag comments_path, :honeypot => true do -%>
  32
+  ...
  33
+<% end -%>
  34
+
  35
+## form_tag without block
  36
+
  37
+Simply specify that the form has a honeypot in the options hash:
  38
+
  39
+<%= form_tag comments_path, :honeypot => true -%>
  40
+  ...
  41
+</form>
  42
+
  43
+### References
  44
+
  45
+* [Honeypot Captcha by Phil Haack](http://haacked.com/archive/2007/09/11/honeypot-captcha.aspx)
  46
+* [Stopping spambots with hashes and honeypots](http://nedbatchelder.com/text/stopbots.html)
  47
+
  48
+## Note on Patches/Pull Requests
  49
+ 
  50
+* Fork the project.
  51
+* Make your feature addition or bug fix.
  52
+* Add tests for it. This is important so I don't break it in a future version unintentionally.
  53
+* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
  54
+* Send me a pull request. Bonus points for topic branches.
  55
+
  56
+## Author
  57
+
  58
+Written by [Curtis Miller](http://millarian.com) of [Flatterline](http://flatterline.com)
  59
+
  60
+## Copyright
  61
+
  62
+Copyright (c) 2010 Curtis Miller. See LICENSE for details.
17  README.rdoc
Source Rendered
... ...
@@ -1,17 +0,0 @@
1  
-= honeypot-captcha
2  
-
3  
-Description goes here.
4  
-
5  
-== Note on Patches/Pull Requests
6  
- 
7  
-* Fork the project.
8  
-* Make your feature addition or bug fix.
9  
-* Add tests for it. This is important so I don't break it in a
10  
-  future version unintentionally.
11  
-* Commit, do not mess with rakefile, version, or history.
12  
-  (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13  
-* Send me a pull request. Bonus points for topic branches.
14  
-
15  
-== Copyright
16  
-
17  
-Copyright (c) 2010 curtis. See LICENSE for details.
4  Rakefile
@@ -5,8 +5,8 @@ begin
5 5
   require 'jeweler'
6 6
   Jeweler::Tasks.new do |gem|
7 7
     gem.name = "honeypot-captcha"
8  
-    gem.summary = %Q{TODO: one-line summary of your gem}
9  
-    gem.description = %Q{TODO: longer description of your gem}
  8
+    gem.summary = %Q{A simple way to add honeypot captchas to Rails forms}
  9
+    gem.description = %Q{A simple way to add honeypot captchas to Rails forms}
10 10
     gem.email = "curtis@flatterline.com"
11 11
     gem.homepage = "http://github.com/curtis/honeypot-captcha"
12 12
     gem.authors = ["curtis"]
2  VERSION
... ...
@@ -1 +1 @@
1  
-0.0.0
  1
+0.0.1
49  honeypot-captcha.gemspec
... ...
@@ -0,0 +1,49 @@
  1
+# Generated by jeweler
  2
+# DO NOT EDIT THIS FILE DIRECTLY
  3
+# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
  4
+# -*- encoding: utf-8 -*-
  5
+
  6
+Gem::Specification.new do |s|
  7
+  s.name = %q{honeypot-captcha}
  8
+  s.version = "0.0.1"
  9
+
  10
+  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
  11
+  s.authors = ["curtis"]
  12
+  s.date = %q{2010-04-09}
  13
+  s.description = %q{A simple way to add honeypot captchas to Rails forms}
  14
+  s.email = %q{curtis@flatterline.com}
  15
+  s.extra_rdoc_files = [
  16
+    "LICENSE",
  17
+     "README.markdown"
  18
+  ]
  19
+  s.files = [
  20
+    ".document",
  21
+     ".gitignore",
  22
+     "LICENSE",
  23
+     "README.markdown",
  24
+     "Rakefile",
  25
+     "VERSION",
  26
+     "honeypot-captcha.gemspec",
  27
+     "lib/honeypot-captcha.rb",
  28
+     "lib/honeypot-captcha/form_tag_helper.rb"
  29
+  ]
  30
+  s.homepage = %q{http://github.com/curtis/honeypot-captcha}
  31
+  s.rdoc_options = ["--charset=UTF-8"]
  32
+  s.require_paths = ["lib"]
  33
+  s.rubygems_version = %q{1.3.5}
  34
+  s.summary = %q{A simple way to add honeypot captchas to Rails forms}
  35
+
  36
+  if s.respond_to? :specification_version then
  37
+    current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
  38
+    s.specification_version = 3
  39
+
  40
+    if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
  41
+      s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
  42
+    else
  43
+      s.add_dependency(%q<rspec>, [">= 1.2.9"])
  44
+    end
  45
+  else
  46
+    s.add_dependency(%q<rspec>, [">= 1.2.9"])
  47
+  end
  48
+end
  49
+
23  lib/honeypot-captcha.rb
... ...
@@ -0,0 +1,23 @@
  1
+require 'honeypot-captcha/form_tag_helper'
  2
+
  3
+module HoneypotCaptcha
  4
+  module SpamProtection
  5
+    def honeypot_fields
  6
+      [:a_comment_body]
  7
+    end
  8
+
  9
+    def protect_from_spam
  10
+      head :ok if honeypot_fields.any? { |f| !params[f].blank? }
  11
+    end
  12
+
  13
+    def self.included(base) # :nodoc:
  14
+      base.send :helper_method, :honeypot_fields
  15
+
  16
+      if base.respond_to? :before_filter
  17
+        base.send :prepend_before_filter, :protect_from_spam, :only => [:create, :update]
  18
+      end
  19
+    end
  20
+  end
  21
+end
  22
+
  23
+ActionController::Base.send(:include, HoneypotCaptcha::SpamProtection) if defined?(ActionController::Base)
33  lib/honeypot-captcha/form_tag_helper.rb
... ...
@@ -0,0 +1,33 @@
  1
+# Override the form_tag helper to add honeypot spam protection to forms.
  2
+module ActionView
  3
+  module Helpers
  4
+    module FormTagHelper
  5
+      def form_tag_with_honeypot(url_for_options = {}, options = {}, *parameters_for_url, &block)
  6
+        honeypot = options.delete(:honeypot)
  7
+        html = form_tag_without_honeypot(url_for_options, options, *parameters_for_url, &block)
  8
+        if honeypot
  9
+          if block_given?
  10
+            html.insert(html.index('</form>'), honey_pot_captcha)
  11
+          else
  12
+            html += honey_pot_captcha
  13
+          end
  14
+        end
  15
+        html
  16
+      end
  17
+      alias_method_chain :form_tag, :honeypot
  18
+
  19
+    private
  20
+
  21
+      def honey_pot_captcha
  22
+        html_ids = []
  23
+        honeypot_fields.collect do |f|
  24
+          html_ids << (html_id = "#{f}_hp_#{Time.now.to_i}")
  25
+          content_tag(:div, send([:text_field_tag, :text_area_tag][rand(2)], f), :id => html_id)
  26
+        end.join +
  27
+        content_tag(:style, :type => 'text/css', :media => 'screen') do
  28
+          "#{html_ids.map { |i| "##{i}" }.join(', ')} { display:none; }"
  29
+        end
  30
+      end
  31
+    end
  32
+  end
  33
+end
7  spec/honeypot-captcha_spec.rb
... ...
@@ -1,7 +0,0 @@
1  
-require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2  
-
3  
-describe "HoneypotCaptcha" do
4  
-  it "fails" do
5  
-    fail "hey buddy, you should probably rename this file and start specing for real"
6  
-  end
7  
-end
1  spec/spec.opts
... ...
@@ -1 +0,0 @@
1  
---color
9  spec/spec_helper.rb
... ...
@@ -1,9 +0,0 @@
1  
-$LOAD_PATH.unshift(File.dirname(__FILE__))
2  
-$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3  
-require 'honeypot-captcha'
4  
-require 'spec'
5  
-require 'spec/autorun'
6  
-
7  
-Spec::Runner.configure do |config|
8  
-  
9  
-end

0 notes on commit 066aca7

Please sign in to comment.
Something went wrong with that request. Please try again.