Permalink
Browse files

Initial import of ReCAPTCHA plugin

  • Loading branch information...
ambethia committed May 26, 2007
0 parents commit 613c843d66f95b82e152778483311843ab769f3a
Showing with 201 additions and 0 deletions.
  1. +19 −0 LICENSE
  2. +39 −0 README
  3. +22 −0 Rakefile
  4. +3 −0 init.rb
  5. +1 −0 install.rb
  6. +63 −0 lib/recaptcha.rb
  7. +4 −0 tasks/recaptcha_tasks.rake
  8. +49 −0 test/recaptcha_test.rb
  9. +1 −0 uninstall.rb
19 LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2007 Jason L Perry
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
39 README
@@ -0,0 +1,39 @@
+= ReCAPTCHA
+
+Author:: Jason L Perry (http://ambethia.com)
+Copyright:: Copyright (c) 2007 Jason L Perry
+License:: MIT
+
+This plugin adds helpers for the ReCAPTCHA API (http://recaptcha.net/). In your views you can use
+the +recaptcha_tags+ method to embed the needed javascript, and you can validate in your controllers
+with +verify_recaptcha+.
+
+You'll want to add your public and private API keys in the environment variables RECAPTCHA_PUBLIC_KEY
+and RECAPTCHA_PRIVATE_KEY, respectively. You could also specify them in config/environment.rb if you
+are so inclined.
+
+== +recaptcha_tags+
+
+Some of the options available:
+
+<tt>:ssl</tt>:: Uses secure http for captcha widget (default +false+)
+<tt>:noscript</tt>:: Include <noscript> content (default +true+)
+
+== +verify_recaptcha+
+
+This method returns +true+ or +false+ after processing the parameters from the ReCAPTCHA widget. Why
+isn't this a model validation? Because that violates MVC. Use can use it like this, or how ever you like. Passing in the ActiveRecord object is optional, if you do--and the captcha fails to
+verify--an error will be added to the object for you to use.
+
+ respond_to do |format|
+ if verify_recaptcha(@post) && @post.save
+ # ...
+ else
+ # ...
+ end
+ end
+
+== TODO
+* Add some helpers to use in before_filter and what not
+* Add support for themes and tabindex
+* Better documentation
@@ -0,0 +1,22 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the recaptcha plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the recaptcha plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'Recaptcha'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
@@ -0,0 +1,3 @@
+require 'recaptcha.rb'
+ActionView::Base.send :include, Ambethia::ReCaptcha::Helper
+ActionController::Base.send :include, Ambethia::ReCaptcha::Controller
@@ -0,0 +1 @@
+# Install hook code here
@@ -0,0 +1,63 @@
+# ReCAPTCHA
+module Ambethia
+ module ReCaptcha
+ RECAPTCHA_API_SERVER = 'http://api.recaptcha.net';
+ RECAPTCHA_API_SECURE_SERVER = 'https://api-secure.recaptcha.net';
+ RECAPTCHA_VERIFY_SERVER = 'api-verify.recaptcha.net';
+
+ module Helper
+ # Your public API can be specified in the +options+ hash or preferably the environment
+ # variable +RECAPTCHA_PUBLIC_KEY+.
+ def recaptcha_tags(options = {})
+ # Default options
+ key = options[:public_key] ||= ENV['RECAPTCHA_PUBLIC_KEY']
+ error = options[:error] ||= session[:recaptcha_error]
+ uri = options[:ssl] ? RECAPTCHA_API_SECURE_SERVER : RECAPTCHA_API_SERVER
+ xhtml = Builder::XmlMarkup.new :target => out=(''), :indent => 2 # Because I can.
+ xhtml.script :type => "text/javascript", :src => "#{uri}/challenge?k=#{key}&error=#{error}"
+ unless options[:noscript] == false
+ xhtml.noscript do
+ xhtml.iframe(:src => "#{uri}/noscript?k=#{key}",
+ :height => options[:iframe_height] ||= 300,
+ :width => options[:iframe_width] ||= 500,
+ :frameborder => 0) {}; xhtml.br
+ xhtml.textarea(:name => "recaptcha_challenge_field", :rows => 3, :cols => 40) {}
+ xhtml.input :name => "recaptcha_response_field",
+ :type => "hidden", :value => "manual_challenge"
+ end
+ end
+ raise ReCaptchaError, "No public key specified." unless key
+ return out
+ end # recaptcha_tags
+ end # Helpers
+
+ module Controller
+ # Your private API key must be specified in the environment variable +RECAPTCHA_PRIVATE_KEY+
+ def verify_recaptcha(model = nil)
+ raise ReCaptchaError, "No private key specified." unless ENV['RECAPTCHA_PRIVATE_KEY']
+ begin
+ recaptcha = Net::HTTP.post_form URI.parse("http://#{RECAPTCHA_VERIFY_SERVER}/verify"), {
+ :privatekey => ENV['RECAPTCHA_PRIVATE_KEY'],
+ :remoteip => request.remote_ip,
+ :challenge => params[:recaptcha_challenge_field],
+ :response => params[:recaptcha_response_field]
+ }
+ answer, error = recaptcha.body.split.map(&:chomp)
+ unless answer == 'true'
+ session[:recaptcha_error] = error
+ model.errors.add_to_base "Captcha response is incorrect, please try again." if model
+ return false
+ else
+ session[:recaptcha_error] = nil
+ return true
+ end
+ rescue Exception => e
+ raise ReCaptchaError, e
+ end
+ end # verify_recaptcha
+ end # ControllerHelpers
+
+ class ReCaptchaError < StandardError; end
+
+ end # ReCaptcha
+end # Ambethia
@@ -0,0 +1,4 @@
+# desc "Explaining what the task does"
+# task :recaptcha do
+# # Task goes here
+# end
@@ -0,0 +1,49 @@
+require 'test/unit'
+require 'builder'
+require File.dirname(__FILE__) + '/../lib/recaptcha'
+
+class ReCaptchaTest < Test::Unit::TestCase
+ include Ambethia::ReCaptcha
+ include Ambethia::ReCaptcha::Helper
+ include Ambethia::ReCaptcha::Controller
+
+ attr_accessor :session
+
+ def setup
+ @session = {}
+ ENV['RECAPTCHA_PUBLIC_KEY'] = '0000000000000000000000000000000000000000'
+ ENV['RECAPTCHA_PRIVATE_KEY'] = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
+ end
+
+ def test_recaptcha_tags
+ # Might as well match something...
+ assert_match /http:\/\/api.recaptcha.net/, recaptcha_tags
+ end
+
+ def test_recaptcha_tags_with_ssl
+ assert_match /https:\/\/api-secure.recaptcha.net/, recaptcha_tags(:ssl => true)
+ end
+
+ def test_recaptcha_tags_without_noscript
+ assert_no_match /noscript/, recaptcha_tags(:noscript => false)
+ end
+
+ def test_should_raise_exception_without_public_key
+ assert_raise ReCaptchaError do
+ ENV['RECAPTCHA_PUBLIC_KEY'] = nil
+ recaptcha_tags
+ end
+ end
+
+ def test_should_raise_exception_without_private_key
+ assert_raise ReCaptchaError do
+ ENV['RECAPTCHA_PRIVATE_KEY'] = nil
+ verify_recaptcha
+ end
+ end
+
+ def test_should_verify_recaptcha
+ # TODO Mock this, or figure something out...
+ end
+
+end
@@ -0,0 +1 @@
+# Uninstall hook code here

0 comments on commit 613c843

Please sign in to comment.