Commit 4fe87ea2452f92429c2f7af9d9bc1b54a9928792

Authored by Caio SBA
Committed by Joenio Costa
1 parent fd5c2e61

Adding recaptcha to comments and article suggestion

(ActionItem2075)
Showing 65 changed files with 792 additions and 452 deletions   Show diff stats
app/controllers/my_profile/cms_controller.rb
... ... @@ -285,7 +285,7 @@ class CmsController < MyProfileController
285 285 @task = SuggestArticle.new(params[:task])
286 286 if request.post?
287 287 @task.target = profile
288   - if @task.save
  288 + if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save
289 289 session[:notice] = _('Thanks for your suggestion. The community administrators were notified.')
290 290 redirect_to @back_to
291 291 end
... ...
app/controllers/public/account_controller.rb
... ... @@ -2,8 +2,6 @@ class AccountController < ApplicationController
2 2  
3 3 no_design_blocks
4 4  
5   - inverse_captcha :field => 'e_mail'
6   -
7 5 require_ssl :except => [ :login_popup, :logout_popup, :profile_details ]
8 6  
9 7 before_filter :login_required, :only => [:activation_question, :accept_terms, :activate_enterprise]
... ... @@ -69,7 +67,7 @@ class AccountController < ApplicationController
69 67 @user.person_data = params[:profile_data]
70 68 @person = Person.new(params[:profile_data])
71 69 @person.environment = @user.environment
72   - if request.post? && params[self.icaptcha_field].blank?
  70 + if request.post?
73 71 @user.signup!
74 72 owner_role = Role.find_by_name('owner')
75 73 @user.person.affiliate(@user.person, [owner_role]) if owner_role
... ...
app/controllers/public/contact_controller.rb
... ... @@ -4,10 +4,9 @@ class ContactController < PublicController
4 4  
5 5 needs_profile
6 6  
7   - inverse_captcha :field => 'e_mail'
8 7 def new
9 8 @contact
10   - if request.post? && params[self.icaptcha_field].blank? && params[:confirm] == 'true'
  9 + if request.post? && params[:confirm] == 'true'
11 10 @contact = user.build_contact(profile, params[:contact])
12 11 @contact.city = (!params[:city].blank? && City.exists?(params[:city])) ? City.find(params[:city]).name : nil
13 12 @contact.state = (!params[:state].blank? && State.exists?(params[:state])) ? State.find(params[:state]).name : nil
... ...
app/controllers/public/content_viewer_controller.rb
... ... @@ -2,8 +2,6 @@ class ContentViewerController < ApplicationController
2 2  
3 3 needs_profile
4 4  
5   - inverse_captcha :field => 'e_mail'
6   -
7 5 helper ProfileHelper
8 6 helper TagsHelper
9 7  
... ... @@ -76,7 +74,7 @@ class ContentViewerController < ApplicationController
76 74  
77 75 @form_div = params[:form]
78 76  
79   - if params[:comment] && params[self.icaptcha_field].blank? && params[:confirm] == 'true'
  77 + if params[:comment] && params[:confirm] == 'true'
80 78 @comment = Comment.new(params[:comment])
81 79 if request.post? && @page.accept_comments?
82 80 add_comment
... ... @@ -121,7 +119,7 @@ class ContentViewerController < ApplicationController
121 119 def add_comment
122 120 @comment.author = user if logged_in?
123 121 @comment.article = @page
124   - if @comment.save
  122 + if (@comment.reply_of_id || verify_recaptcha(:model => @comment, :message => _('Please type the words correctly'))) && @comment.save
125 123 @page.touch
126 124 @comment = nil # clear the comment form
127 125 redirect_to :action => 'view_page', :profile => params[:profile], :page => @page.explode_path, :view => params[:view]
... ...
app/models/comment.rb
1 1 class Comment < ActiveRecord::Base
2 2  
3   - has_captcha
4   -
5 3 track_actions :leave_comment, :after_create, :keep_params => ["article.title", "article.url", "title", "url", "body"], :custom_target => :action_tracker_target
6 4  
7 5 validates_presence_of :title, :body
... ...
app/models/suggest_article.rb
1 1 class SuggestArticle < Task
2 2  
3   - has_captcha
4   -
5 3 validates_presence_of :target_id, :article_name, :email, :name, :article_body
6 4  
7 5 settings_items :email, :type => String
... ...
app/views/account/_signup_form.rhtml
... ... @@ -7,8 +7,7 @@
7 7 </div>
8 8 <% end %>
9 9  
10   -<% labelled_form_for :user, @user do |f| %>
11   -<%= icaptcha_field() %>
  10 +<% labelled_form_for :user, @user, :html => { :multipart => true } do |f| %>
12 11  
13 12 <%= hidden_field_tag :invitation_code, @invitation_code %>
14 13  
... ...
app/views/cms/suggest_an_article.rhtml
... ... @@ -18,13 +18,10 @@
18 18  
19 19 <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :object => :task, :abstract_method => 'article_abstract', :body_method => 'article_body'} %>
20 20  
21   - <div id="captcha">
22   - <%= labelled_form_field(_("What is the result of '%s = ?'") % @task.captcha.task, text_field(:task, 'captcha_solution')) %>
23   - <%= hidden_field :task, :captcha_secret %>
24   - <br style="clear: both;">
25   - </div>
26   -
27 21 <%= hidden_field_tag('back_to', @back_to) %>
  22 +
  23 + <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %>
  24 +
28 25 <% button_bar do %>
29 26 <%= submit_button :save, _('Save') %>
30 27 <%= button :cancel, _('Cancel'), @back_to %>
... ...
app/views/contact/new.rhtml
... ... @@ -4,7 +4,6 @@
4 4  
5 5  
6 6 <% labelled_form_for :contact, @contact do |f| %>
7   - <%= icaptcha_field() %>
8 7 <%= hidden_field_tag(:confirm, 'false') %>
9 8  
10 9 <%= required_fields_message %>
... ...
app/views/content_viewer/_comment_form.rhtml
... ... @@ -20,7 +20,6 @@
20 20 </h4>
21 21  
22 22 <% form_tag( url_for(@page.view_url.merge({:only_path => true})), { :class => 'comment_form' } ) do %>
23   - <%= icaptcha_field() %>
24 23 <%= hidden_field_tag(:confirm, 'false') %>
25 24  
26 25 <%= required_fields_message %>
... ... @@ -29,7 +28,6 @@
29 28  
30 29 <%= required labelled_form_field(_('Name'), text_field(:comment, :name)) %>
31 30 <%= required labelled_form_field(_('e-mail'), text_field(:comment, :email)) %>
32   -
33 31 <p>
34 32 <%= _('If you are a registered user, you can login and be automatically recognized.') %>
35 33 </p>
... ... @@ -39,8 +37,7 @@
39 37 <%= required labelled_form_field(_('Title'), text_field(:comment, :title)) %>
40 38 <%= required labelled_form_field(_('Enter your comment'), text_area(:comment, :body, :rows => 5)) %>
41 39  
42   - <%= required labelled_form_field(_("What is the result of '%s = ?'") % @comment.captcha.task, text_field(:comment, :captcha_solution)) %>
43   - <%= hidden_field(:comment, :captcha_secret) %>
  40 + <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) unless logged_in? %>
44 41  
45 42 <% button_bar do %>
46 43 <%= submit_button('add', _('Post comment'), :onclick => "this.form.confirm.value = 'true'; this.disabled = true; this.form.submit(); return true;") %>
... ...
app/views/profile_editor/edit.rhtml
... ... @@ -13,7 +13,6 @@
13 13 <% end %>
14 14 </div>
15 15  
16   -
17 16 <h2><%= _('Privacy options') %></h2>
18 17  
19 18 <% if profile.person? %>
... ...
config/initializers/recaptcha.rb 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +Recaptcha.configure do |config|
  2 + config.public_key = '6LdLTsgSAAAAACYr0rHdF2sVqt3sMaoz_h6uN4k7'
  3 + config.private_key = '6LdLTsgSAAAAADM9Mxg-EFjXc4tCe6zpKiPOEMs8'
  4 +end
... ...
features/comment.feature
... ... @@ -82,11 +82,6 @@ Feature: comment
82 82 And I should be exactly on /booking/article-with-comment
83 83 And I should be moved to anchor "comment_form"
84 84  
85   - Scenario: ask captcha question
86   - Given I am on /booking/article-with-comment
87   - When I follow "Post a comment" within ".post-comment-button"
88   - Then I should see "What is the result of "
89   -
90 85 @selenium
91 86 Scenario: keep comments field filled while trying to do a comment
92 87 Given I am on /booking/article-with-comment
... ...
features/comment_reply.feature
... ... @@ -64,8 +64,7 @@ Feature: comment
64 64  
65 65 @selenium
66 66 Scenario: reply a comment
67   - Given skip comments captcha
68   - And I go to /booking/another-article
  67 + Given I go to /booking/another-article
69 68 And I follow "Reply" within ".comment-balloon"
70 69 And I fill in "Name" within "comment-balloon" with "Joey"
71 70 And I fill in "e-mail" within "comment-balloon" with "joey@ramones.com"
... ...
features/step_definitions/noosfero_steps.rb
... ... @@ -368,7 +368,6 @@ Given /^the articles of &quot;(.+)&quot; are moderated$/ do |organization|
368 368 end
369 369  
370 370 Given /^the following comments?$/ do |table|
371   - Comment.skip_captcha!
372 371 table.hashes.each do |item|
373 372 data = item.dup
374 373 article = Article.find_by_name(data.delete("article"))
... ... @@ -388,7 +387,6 @@ Given /^the community &quot;(.+)&quot; is closed$/ do |community|
388 387 end
389 388  
390 389 Given /^someone suggested the following article to be published$/ do |table|
391   - SuggestArticle.skip_captcha!
392 390 table.hashes.map{|item| item.dup}.each do |item|
393 391 target = Community[item.delete('target')]
394 392 task = SuggestArticle.create!(:target => target, :data => item)
... ... @@ -422,10 +420,6 @@ Given /^the environment domain is &quot;([^\&quot;]*)&quot;$/ do |domain|
422 420 d.save(false)
423 421 end
424 422  
425   -Given /^skip comments captcha$/ do
426   - Comment.any_instance.stubs(:skip_captcha?).returns(true)
427   -end
428   -
429 423 When /^([^\']*)'s account is activated$/ do |person|
430 424 Person.find_by_name(person).user.activate
431 425 end
... ...
features/step_definitions/selenium_steps.rb
... ... @@ -93,12 +93,6 @@ When /^I type &quot;([^\&quot;]*)&quot; in TinyMCE field &quot;([^\&quot;]*)&quot;$/ do |value, field_id|
93 93 response.selenium.type("dom=document.getElementById('#{field_id}_ifr').contentDocument.body", value)
94 94 end
95 95  
96   -When /^I answer the captcha$/ do
97   - question = response.selenium.get_text("//label[@for='task_captcha_solution']").match(/What is the result of '(.+) = \?'/)[1]
98   - answer = eval(question)
99   - response.selenium.type("id=task_captcha_solution", answer)
100   -end
101   -
102 96 When /^I refresh the page$/ do
103 97 response.selenium.refresh
104 98 end
... ...
features/suggest_article.feature
... ... @@ -31,7 +31,6 @@ Feature: suggest article
31 31 And I fill in "Email" with "someguy@somewhere.com"
32 32 And I type "This is my suggestion's lead" in TinyMCE field "task_article_abstract"
33 33 And I type "I like free software" in TinyMCE field "task_article_body"
34   - And I answer the captcha
35 34 And I press "Save"
36 35 And I am logged in as "joaosilva"
37 36 And I go to Sample Community's control panel
... ...
public/javascripts/application.js
... ... @@ -662,6 +662,7 @@ function add_comment_reply_form(button, comment_id) {
662 662 var f = container.find('.comment_form');
663 663 if (f.length == 0) {
664 664 f = jQuery('#page-comment-form .comment_form').clone();
  665 + f.find('#dynamic_recaptcha').remove();
665 666 f.find('.fieldWithErrors').map(function() { jQuery(this).replaceWith(jQuery(this).contents()); });
666 667 f.prepend('<input type="hidden" name="comment[reply_of_id]" value="' + comment_id + '" />');
667 668 container.append(f);
... ...
public/stylesheets/application.css
... ... @@ -6136,3 +6136,30 @@ h1#agenda-title {
6136 6136 #user a#pending-tasks-count {
6137 6137 color: #FFFFFF;
6138 6138 }
  6139 +
  6140 +/* Captcha */
  6141 +
  6142 +.comment_reply #recaptcha_area {
  6143 + margin-bottom: 3px !important;
  6144 +}
  6145 +
  6146 +.comment_reply .recaptchatable tr td + td + td {
  6147 + display: none !important;
  6148 +}
  6149 +
  6150 +.comment_reply .recaptcha-container {
  6151 + width: 100%;
  6152 + overflow: hidden;
  6153 +}
  6154 +
  6155 +.comment_reply .recaptcha-container:hover {
  6156 + overflow: visible;
  6157 +}
  6158 +
  6159 +.comment_reply .recaptcha-container tr:hover td {
  6160 + background: transparent;
  6161 +}
  6162 +
  6163 +.comment_reply .recaptcha_image_cell {
  6164 + background: transparent !important;
  6165 +}
... ...
test/functional/account_controller_test.rb
... ... @@ -571,17 +571,6 @@ class AccountControllerTest &lt; Test::Unit::TestCase
571 571  
572 572 # end of enterprise activation tests
573 573  
574   - should 'not be able to signup while inverse captcha field filled' do
575   - assert_no_difference User, :count do
576   - new_user({}, @controller.icaptcha_field => 'bli@bla.email.foo')
577   - end
578   - end
579   -
580   - should 'render inverse captcha field' do
581   - get :signup
582   - assert_tag :tag => 'input', :attributes => { :type => 'text', :name => @controller.icaptcha_field }
583   - end
584   -
585 574 should 'use the current environment for the template of user' do
586 575 template = create_user('test_template', :email => 'test@bli.com', :password => 'pass', :password_confirmation => 'pass').person
587 576 template.boxes.destroy_all
... ...
test/functional/cms_controller_test.rb
... ... @@ -1320,7 +1320,6 @@ class CmsControllerTest &lt; Test::Unit::TestCase
1320 1320 should 'create a task suggest task to a profile' do
1321 1321 c = Community.create!(:name => 'test comm', :identifier => 'test_comm', :moderated_articles => true)
1322 1322  
1323   - SuggestArticle.any_instance.stubs(:skip_captcha?).returns(true)
1324 1323 assert_difference SuggestArticle, :count do
1325 1324 post :suggest_an_article, :profile => c.identifier, :back_to => 'action_view', :task => {:article_name => 'some name', :article_body => 'some body', :email => 'some@localhost.com', :name => 'some name'}
1326 1325 end
... ...
test/functional/contact_controller_test.rb
... ... @@ -74,13 +74,6 @@ class ContactControllerTest &lt; Test::Unit::TestCase
74 74 assert_no_tag :tag => 'select', :attributes => {:name => 'state'}
75 75 end
76 76  
77   - should 'not be able to post contact while inverse captcha field filled' do
78   - post :new, :profile => enterprise.identifier, @controller.icaptcha_field => 'filled', :contact => {:subject => 'Hi', :message => 'Hi, all', :state => '', :city => ''}
79   -
80   - assert_response :success
81   - assert_template 'new'
82   - end
83   -
84 77 should 'not allow if not logged' do
85 78 logout
86 79 get :new, :profile => profile.identifier
... ... @@ -93,12 +86,6 @@ class ContactControllerTest &lt; Test::Unit::TestCase
93 86 assert_equal Person['contact_test_user'], assigns(:contact).sender
94 87 end
95 88  
96   - should 'send contact while inverse captcha field not filled' do
97   - post :new, :profile => enterprise.identifier, :contact => {:subject => 'Hi', :message => 'Hi, all', :state => '', :city => ''}, :confirm => 'true'
98   - assert_response :redirect
99   - assert_redirected_to :action => 'new'
100   - end
101   -
102 89 should 'deliver contact if subject and message are filled' do
103 90 post :new, :profile => enterprise.identifier, :contact => {:subject => 'Hi', :message => 'Hi, all'}, :confirm => 'true'
104 91 assert_response :redirect
... ...
test/functional/content_viewer_controller_test.rb
... ... @@ -15,7 +15,6 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase
15 15  
16 16 @profile = create_user('testinguser').person
17 17 @environment = @profile.environment
18   - Comment.skip_captcha!
19 18 end
20 19 attr_reader :profile, :environment
21 20  
... ... @@ -188,17 +187,6 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase
188 187 end
189 188 end
190 189  
191   - should 'not be able to post comment while inverse captcha field filled' do
192   - profile = create_user('popstar').person
193   - page = profile.articles.build(:name => 'myarticle', :body => 'the body of the text')
194   - page.save!
195   - profile.home_page = page; profile.save!
196   -
197   - assert_no_difference Comment, :count do
198   - post :view_page, :profile => profile.identifier, :page => [ 'myarticle' ], @controller.icaptcha_field => 'filled', :comment => { :title => 'crap!', :body => 'I think that this article is crap', :name => 'Anonymous coward', :email => 'coward@anonymous.com' }
199   - end
200   - end
201   -
202 190 should 'be able to remove comments if is moderator' do
203 191 commenter = create_user('commenter_user').person
204 192 community = Community.create!(:name => 'Community test', :identifier => 'community-test')
... ... @@ -212,15 +200,6 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase
212 200 end
213 201 end
214 202  
215   - should 'render inverse captcha field' do
216   - profile = create_user('popstar').person
217   - page = profile.articles.build(:name => 'myarticle', :body => 'the body of the text')
218   - page.save!
219   - profile.home_page = page; profile.save!
220   - get :view_page, :profile => profile.identifier, :page => [ 'myarticle' ]
221   - assert_tag :tag => 'input', :attributes => { :type => 'text', :name => @controller.icaptcha_field }
222   - end
223   -
224 203 should 'filter html content from body' do
225 204 login_as @profile.identifier
226 205 page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text')
... ...
test/functional/search_controller_test.rb
... ... @@ -17,7 +17,6 @@ class SearchControllerTest &lt; Test::Unit::TestCase
17 17 domain.save!
18 18  
19 19 @product_category = fast_create(ProductCategory)
20   - Comment.skip_captcha!
21 20 end
22 21  
23 22 def create_article_with_optional_category(name, profile, category = nil)
... ...
test/functional/tasks_controller_test.rb
... ... @@ -238,7 +238,6 @@ class TasksControllerTest &lt; Test::Unit::TestCase
238 238 c = fast_create(Community)
239 239 c.add_admin profile
240 240 @controller.stubs(:profile).returns(c)
241   - SuggestArticle.skip_captcha!
242 241 t = SuggestArticle.create!(:article_name => 'test name', :article_abstract => 'test abstract', :article_body => 'test body', :name => 'some name', :email => 'test@localhost.com', :target => c)
243 242  
244 243 get :index
... ... @@ -251,7 +250,6 @@ class TasksControllerTest &lt; Test::Unit::TestCase
251 250 c = fast_create(Community)
252 251 c.affiliate(profile, Profile::Roles.all_roles(profile.environment.id))
253 252 @controller.stubs(:profile).returns(c)
254   - SuggestArticle.skip_captcha!
255 253 t = SuggestArticle.create!(:article_name => 'test name', :article_body => 'test body', :name => 'some name', :email => 'test@localhost.com', :target => c)
256 254  
257 255 post :close, :tasks => {t.id => { :task => {}, :decision => "finish"}}
... ... @@ -263,7 +261,6 @@ class TasksControllerTest &lt; Test::Unit::TestCase
263 261 c = fast_create(Community)
264 262 c.affiliate(profile, Profile::Roles.all_roles(profile.environment.id))
265 263 @controller.stubs(:profile).returns(c)
266   - SuggestArticle.skip_captcha!
267 264 t = SuggestArticle.new
268 265 t.article_name = 'test name'
269 266 t.article_body = 'test body'
... ...
test/unit/article_test.rb
... ... @@ -6,7 +6,6 @@ class ArticleTest &lt; Test::Unit::TestCase
6 6  
7 7 def setup
8 8 @profile = create_user('testing').person
9   - Comment.skip_captcha!
10 9 end
11 10 attr_reader :profile
12 11  
... ...
test/unit/category_finder_test.rb
... ... @@ -7,7 +7,6 @@ class CategoryFinderTest &lt; ActiveSupport::TestCase
7 7 @finder = CategoryFinder.new(@category)
8 8 @product_category = fast_create(ProductCategory, :name => 'Products')
9 9  
10   - Comment.skip_captcha!
11 10 end
12 11  
13 12 should 'search for articles in a specific category' do
... ...
test/unit/category_test.rb
... ... @@ -5,7 +5,6 @@ class CategoryTest &lt; Test::Unit::TestCase
5 5  
6 6 def setup
7 7 @env = fast_create(Environment)
8   - Comment.skip_captcha!
9 8 end
10 9  
11 10 def test_mandatory_field_name
... ...
test/unit/comment_notifier_test.rb
... ... @@ -10,7 +10,6 @@ class CommentNotifierTest &lt; Test::Unit::TestCase
10 10 ActionMailer::Base.deliveries = []
11 11 @profile = create_user('user_comment_test').person
12 12 @article = fast_create(Article, :name => 'Article test', :profile_id => @profile.id, :notify_comments => true)
13   - Comment.skip_captcha!
14 13 end
15 14  
16 15 should 'deliver mail after make aarticle commment' do
... ...
test/unit/comment_test.rb
... ... @@ -3,7 +3,6 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39;
3 3 class CommentTest < Test::Unit::TestCase
4 4  
5 5 def setup
6   - Comment.skip_captcha!
7 6 end
8 7  
9 8 should 'have a name and require it' do
... ... @@ -331,12 +330,4 @@ class CommentTest &lt; Test::Unit::TestCase
331 330 assert_nil Comment.new(:email => 'my@email.com').author_url
332 331 end
333 332  
334   - should 'have the captcha_solution be solved' do
335   - Comment.dont_skip_captcha!
336   - c = Comment.new
337   - assert !c.valid? && c.errors.invalid?(:captcha_solution)
338   - c.skip_captcha!
339   - assert !c.valid? && !c.errors.invalid?(:captcha_solution)
340   - end
341   -
342 333 end
... ...
test/unit/community_test.rb
... ... @@ -4,7 +4,6 @@ class CommunityTest &lt; Test::Unit::TestCase
4 4  
5 5 def setup
6 6 @person = fast_create(Person)
7   - Comment.skip_captcha!
8 7 end
9 8  
10 9 attr_reader :person
... ...
test/unit/forum_helper_test.rb
... ... @@ -12,7 +12,6 @@ class ForumHelperTest &lt; Test::Unit::TestCase
12 12 @environment = Environment.default
13 13 @profile = create_user('forum_helper_test').person
14 14 @forum = fast_create(Forum, :profile_id => profile.id, :name => 'Forum test')
15   - Comment.skip_captcha!
16 15 end
17 16  
18 17 attr :profile
... ...
test/unit/suggest_article_test.rb
... ... @@ -45,18 +45,6 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
45 45 assert t.errors.invalid?(:target_id)
46 46 end
47 47  
48   - should 'have the captcha_solution be solved' do
49   - t = SuggestArticle.new
50   - assert !t.errors.invalid?(:captcha_solution)
51   - t.valid?
52   - assert t.errors.invalid?(:captcha_solution)
53   -
54   - t.skip_captcha!
55   - assert t.skip_captcha?
56   - t.valid?
57   - assert !t.errors.invalid?(:captcha_solution)
58   - end
59   -
60 48 should 'have the article_abstract' do
61 49 t = SuggestArticle.new
62 50 assert t.respond_to?(:article_abstract)
... ...
vendor/plugins/inverse_captcha/README
... ... @@ -1,29 +0,0 @@
1   -InverseCaptcha
2   -==============
3   -
4   -Implement simple Anti-Comment-Spam Technique.
5   -
6   -Basic Usage
7   -===========
8   -
9   -Add method inverse_captcha on controller:
10   -
11   -ps.: dont use this method more than once time on same controller.
12   -
13   - inverse_captcha :field => 'e-mail'[, class => 'ghost']
14   -
15   -Add the field in view form:
16   -
17   - <%= icaptcha_field() %>
18   -
19   -Check if field is blank in your controller:
20   -
21   - if params[controller.icaptcha_field].blank?
22   - do...
23   - else
24   - dont...
25   - end
26   -
27   ----
28   -Joenio Costa <joenio@colivre.coop.br>
29   -Qui Mar 27 15:48:12 BRT 2008
vendor/plugins/inverse_captcha/init.rb
... ... @@ -1,3 +0,0 @@
1   -ActionController::Base.extend(InverseCaptcha::ClassMethods)
2   -ActionController::Base.send(:include, InverseCaptcha::InstanceMethods)
3   -ActionView::Base.send(:include, InverseCaptchaHelper)
vendor/plugins/inverse_captcha/lib/inverse_captcha.rb
... ... @@ -1,18 +0,0 @@
1   -module InverseCaptcha
2   -
3   - module ClassMethods
4   - def inverse_captcha(opt = {})
5   - InverseCaptcha.const_set("ICAPTCHA_FIELD", opt[:field]) unless InverseCaptcha.const_defined? "ICAPTCHA_FIELD"
6   - InverseCaptcha.const_set("ICAPTCHA_LABEL", opt[:label] || N_("Don't fill this field")) unless InverseCaptcha.const_defined? "ICAPTCHA_LABEL"
7   - InverseCaptcha.const_set("ICAPTCHA_STYLECLASS", opt[:class] || 'ghost') unless InverseCaptcha.const_defined? "ICAPTCHA_STYLECLASS"
8   - self.send(:include, InverseCaptcha)
9   - end
10   - end
11   -
12   - module InstanceMethods
13   - def icaptcha_field
14   - ICAPTCHA_FIELD
15   - end
16   - end
17   -
18   -end
vendor/plugins/inverse_captcha/lib/inverse_captcha_helper.rb
... ... @@ -1,11 +0,0 @@
1   -module InverseCaptchaHelper
2   -
3   - def icaptcha_field(opt = {})
4   - label = controller.class::ICAPTCHA_LABEL
5   - field = controller.class::ICAPTCHA_FIELD
6   - opt.merge!({:class => controller.class::ICAPTCHA_STYLECLASS})
7   - stylesheet = "<style type='text/css'> span.#{opt[:class]} { display: none; } </style>"
8   - stylesheet + content_tag('span', labelled_form_field(_(label), text_field_tag(field, nil)), opt)
9   - end
10   -
11   -end
vendor/plugins/rails-math-captcha/MIT-LICENSE
... ... @@ -1,20 +0,0 @@
1   -Copyright (c) 2007 [name of plugin creator]
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:
10   -
11   -The above copyright notice and this permission notice shall be
12   -included in all copies or substantial portions of the Software.
13   -
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.
vendor/plugins/rails-math-captcha/README
... ... @@ -1,45 +0,0 @@
1   -MathCaptcha
2   -===========
3   -
4   -TODO: Create form helpers
5   -
6   -Validates your Model to be saved by a human (or very clever script) by asking
7   -the user to solve a very basic mathematical equation.
8   -
9   -It does not use the session to store the secret, but uses AES from EzCrypto.
10   -
11   -
12   -Requirements
13   -============
14   - * gem ezcrypto
15   - * users who can calculate
16   -
17   -Usage
18   -=====
19   -
20   -In your Model < ActiveRecord::Base
21   -
22   - has_captcha
23   -
24   -
25   -In your form view:
26   -
27   - <%= @model.captcha.task %> = ?
28   - <%= form.text_field :captcha_solution %>
29   - <%= form.hidden_field :captcha_secret %>
30   -
31   -
32   -If you want to skip the validation (in tests/specs), you can
33   -
34   - Model.skip_captcha! # or
35   - @model.skip_captcha!
36   -
37   -and turn that off by
38   -
39   - Model.dont_skip_captcha! # or
40   - @model.dont_skip_captcha!
41   -
42   -
43   -
44   -Copyright (c) 2007 Pat Nakajima, released under the MIT license
45   -Copyright (c) 2009 Niklas Hofer, released under the MIT license
vendor/plugins/rails-math-captcha/Rakefile
... ... @@ -1,22 +0,0 @@
1   -require 'rake'
2   -require 'rake/testtask'
3   -require 'rake/rdoctask'
4   -
5   -desc 'Default: run unit tests.'
6   -task :default => :test
7   -
8   -desc 'Test the math_captcha plugin.'
9   -Rake::TestTask.new(:test) do |t|
10   - t.libs << 'lib'
11   - t.pattern = 'test/**/*_test.rb'
12   - t.verbose = true
13   -end
14   -
15   -desc 'Generate documentation for the math_captcha plugin.'
16   -Rake::RDocTask.new(:rdoc) do |rdoc|
17   - rdoc.rdoc_dir = 'rdoc'
18   - rdoc.title = 'MathCaptcha'
19   - rdoc.options << '--line-numbers' << '--inline-source'
20   - rdoc.rdoc_files.include('README')
21   - rdoc.rdoc_files.include('lib/**/*.rb')
22   -end
vendor/plugins/rails-math-captcha/init.rb
... ... @@ -1 +0,0 @@
1   -require 'math_captcha'
2 0 \ No newline at end of file
vendor/plugins/rails-math-captcha/install.rb
... ... @@ -1 +0,0 @@
1   -# Install hook code here
vendor/plugins/rails-math-captcha/lib/math_captcha.rb
... ... @@ -1,2 +0,0 @@
1   -require 'math_captcha/captcha'
2   -require 'math_captcha/has_captcha'
vendor/plugins/rails-math-captcha/lib/math_captcha/captcha.rb
... ... @@ -1,68 +0,0 @@
1   -require 'rubygems'
2   -require 'ezcrypto'
3   -class Captcha
4   - NUMBERS = (1..9).to_a
5   - OPERATORS = [:+, :-, :*]
6   -
7   - attr_reader :x, :y, :operator
8   -
9   - def initialize(x=nil, y=nil, operator=nil)
10   - @x = x || NUMBERS.sort_by{rand}.first
11   - @y = y || NUMBERS.sort_by{rand}.first
12   - @operator = operator || OPERATORS.sort_by{rand}.first
13   - end
14   -
15   - # Only the #to_secret is shared with the client.
16   - # It can be reused here to create the Captcha again
17   - def self.from_secret(secret)
18   - yml = cipher.decrypt64 secret
19   - args = YAML.load(yml)
20   - new(args[:x], args[:y], args[:operator])
21   - end
22   -
23   - def self.cipher
24   - EzCrypto::Key.with_password key, 'bad_fixed_salt'
25   - end
26   -
27   - def self.key
28   - 'ultrasecret'
29   - end
30   -
31   -
32   - def check(answer)
33   - answer == solution
34   - end
35   -
36   - def task
37   - "#{@x} #{@operator.to_s} #{@y}"
38   - end
39   - def task_with_questionmark
40   - "#{@x} #{@operator.to_s} #{@y} = ?"
41   - end
42   - alias_method :to_s, :task
43   -
44   - def solution
45   - @x.send @operator, @y
46   - end
47   -
48   - def to_secret
49   - cipher.encrypt64(to_yaml)
50   - end
51   -
52   - def to_yaml
53   - YAML::dump({
54   - :x => x,
55   - :y => y,
56   - :operator => operator
57   - })
58   - end
59   -
60   - private
61   - def cipher
62   - @cipher ||= self.class.cipher
63   - end
64   - def reset_cipher
65   - @cipher = nil
66   - end
67   -
68   -end
vendor/plugins/rails-math-captcha/lib/math_captcha/has_captcha.rb
... ... @@ -1,54 +0,0 @@
1   -module MathCaptcha
2   - module HasCaptcha
3   - module InstanceMethods
4   - def must_solve_captcha
5   - self.errors.add(:captcha_solution, "wrong answer.") unless self.captcha.check(self.captcha_solution.to_i)
6   - end
7   - def skip_captcha!
8   - self.class.skip_captcha!
9   - end
10   - def skip_captcha?
11   - self.class.skip_captcha?
12   - end
13   - def captcha
14   - @captcha ||= Captcha.new
15   - end
16   - def captcha_secret=(secret)
17   - @captcha = Captcha.from_secret(secret)
18   - end
19   - def captcha_secret
20   - captcha.to_secret
21   - end
22   - end
23   -
24   - module ClassMethods
25   - def has_captcha
26   - include InstanceMethods
27   - attr_accessor :captcha_solution
28   - dont_skip_captcha!
29   - validates_presence_of :captcha_solution,
30   - :on => :create, :message => "can't be blank",
31   - :unless => Proc.new {|record| record.skip_captcha? }
32   - validate_on_create :must_solve_captcha,
33   - :unless => Proc.new {|record| record.skip_captcha? }
34   - end
35   - def skip_captcha!
36   - @@skip_captcha = true
37   - end
38   - def dont_skip_captcha!
39   - @@skip_captcha = false
40   - end
41   - def skip_captcha?
42   - @@skip_captcha
43   - end
44   - def skipping_captcha(&block)
45   - skipping_before = skip_captcha?
46   - skip_captcha!
47   - yield
48   - dont_skip_captcha! if skipping_before
49   - end
50   - end
51   - end
52   -end
53   -
54   -ActiveRecord::Base.send(:extend, MathCaptcha::HasCaptcha::ClassMethods)
vendor/plugins/rails-math-captcha/spec/captcha_spec.rb
... ... @@ -1,49 +0,0 @@
1   -require 'lib/math_captcha/captcha'
2   -require 'base64'
3   -
4   -describe Captcha do
5   - describe "with a random task" do
6   - before(:each) do
7   - @captcha = Captcha.new
8   - end
9   - it "should have arguments and an operator" do
10   - @captcha.x.should_not be_nil
11   - @captcha.y.should_not be_nil
12   - @captcha.operator.should_not be_nil
13   - end
14   - it "should use numbers bigger than zero" do
15   - @captcha.x.should > 0
16   - @captcha.y.should > 0
17   - end
18   - it "should offer a human readable task" do
19   - @captcha.task.should =~ /^\d+\s*[\+\-\*]\s*\d+$/
20   - end
21   - it "should have a secret to use in forms" do
22   - @captcha.to_secret.should_not be_nil
23   - @captcha.to_secret.should_not be_empty
24   - end
25   -
26   - it "should re-use its cipher" do
27   - @captcha.send(:cipher).should == @captcha.send(:cipher)
28   - end
29   -
30   - it "should have a base64 encoded secret" do
31   - lambda { Base64.decode64(@captcha.to_secret).should_not be_nil }.should_not raise_error
32   - end
33   -
34   - describe "re-creating another from secret" do
35   - before(:each) do
36   - @secret = @captcha.to_secret
37   - @new_captcha = Captcha.from_secret(@secret)
38   - end
39   - it "should have the same arguments and operator" do
40   - @new_captcha.x.should == @captcha.x
41   - @new_captcha.y.should == @captcha.y
42   - @new_captcha.operator.should == @captcha.operator
43   - end
44   - it "should have the same string" do
45   - @new_captcha.task.should == @captcha.task
46   - end
47   - end
48   - end
49   -end
vendor/plugins/rails-math-captcha/spec/spec.opts
... ... @@ -1,4 +0,0 @@
1   ---colour
2   ---format progress
3   ---loadby mtime
4   ---reverse
vendor/plugins/recaptcha/CHANGELOG 0 → 100644
... ... @@ -0,0 +1,23 @@
  1 +== 0.2.2 / 2009-09-14
  2 +
  3 +* Add a timeout to the validator
  4 +* Give the documentation some love
  5 +
  6 +== 0.2.1 / 2009-09-14
  7 +
  8 +* Removed Ambethia namespace, and restructured classes a bit
  9 +* Added an example rails app in the example-rails branch
  10 +
  11 +== 0.2.0 / 2009-09-12
  12 +
  13 +* RecaptchaOptions AJAX API Fix
  14 +* Added 'cucumber' as a test environment to skip
  15 +* Ruby 1.9 compat fixes
  16 +* Added option :message => 'Custom error message' to verify_recaptcha
  17 +* Removed dependency on ActiveRecord constant
  18 +* Add I18n
  19 +
  20 +== 0.1.0 / 2008-2-8
  21 +
  22 +* 1 major enhancement
  23 + * Initial Gem Release
0 24 \ No newline at end of file
... ...
vendor/plugins/recaptcha/Gemfile 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +source 'http://rubygems.org'
  2 +
  3 +gemspec
... ...
vendor/plugins/recaptcha/LICENSE 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +Copyright (c) 2007 Jason L Perry
  2 +
  3 +Permission is hereby granted, free of charge, to any person obtaining a copy
  4 +of this software and associated documentation files (the "Software"), to deal
  5 +in the Software without restriction, including without limitation the rights
  6 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7 +copies of the Software, and to permit persons to whom the Software is
  8 +furnished to do so, subject to the following conditions:
  9 +
  10 +The above copyright notice and this permission notice shall be included in
  11 +all copies or substantial portions of the Software.
  12 +
  13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19 +THE SOFTWARE.
0 20 \ No newline at end of file
... ...
vendor/plugins/recaptcha/README.rdoc 0 → 100644
... ... @@ -0,0 +1,150 @@
  1 += reCAPTCHA
  2 +
  3 +Author:: Jason L Perry (http://ambethia.com)
  4 +Copyright:: Copyright (c) 2007 Jason L Perry
  5 +License:: {MIT}[http://creativecommons.org/licenses/MIT/]
  6 +Info:: http://ambethia.com/recaptcha
  7 +Git:: http://github.com/ambethia/recaptcha/tree/master
  8 +Bugs:: http://github.com/ambethia/recaptcha/issues
  9 +
  10 +This plugin adds helpers for the {reCAPTCHA API}[http://recaptcha.net]. In your
  11 +views you can use the +recaptcha_tags+ method to embed the needed javascript,
  12 +and you can validate in your controllers with +verify_recaptcha+.
  13 +
  14 +Beforehand you need to configure Recaptcha with your custom private and public
  15 +key. You may find detailed examples below. Exceptions will be raised if you
  16 +call these methods and the keys can't be found.
  17 +
  18 +== About this fork
  19 +
  20 +This fork tries to introduces a more convenient way to configure recaptcha's
  21 +settings. The API will be inspired by {Thoughtbot's
  22 +Hoptoad}[http://robots.thoughtbot.com/post/344833329/mygem-configure-block].
  23 +
  24 +== Rails Installation
  25 +
  26 +reCAPTCHA for Rails, add this to your Gemfile:
  27 +
  28 + gem "recaptcha", :require => "recaptcha/rails"
  29 +
  30 +Or, it can be installed as a gem:
  31 +
  32 + config.gem "recaptcha", :lib => "recaptcha/rails"
  33 +
  34 +Or, as a standard rails plugin:
  35 +
  36 + script/plugin install git://github.com/ambethia/recaptcha.git
  37 +
  38 +== Merb Installation
  39 +
  40 +reCAPTCHA can also be used in a Merb application when installed as a gem:
  41 +
  42 + dependency "alm-recaptcha", ">=0.2.2.1", :require_as => "recaptcha/merb"
  43 +
  44 +Initial Merb compatability funded by ALM Labs.
  45 +
  46 +== Setting up your API Keys
  47 +
  48 +There are multiple ways to setup your reCAPTCHA API key once you
  49 +{obtain}[http://recaptcha.net/whyrecaptcha.html] a pair.
  50 +
  51 +=== Recaptcha.configure
  52 +
  53 +You may use the block style configuration. The following code could be placed
  54 +into a +config/initializers/recaptcha.rb+ when used in a Rails project.
  55 +
  56 + Recaptcha.configure do |config|
  57 + config.public_key = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
  58 + config.private_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
  59 + config.proxy = 'http://myrpoxy.com.au:8080'
  60 + end
  61 +
  62 +This way, you may also set additional options to fit recaptcha into your
  63 +deployment environment.
  64 +
  65 +== Recaptcha#with_configuration
  66 +
  67 +If you want to temporarily overwrite the configuration you set with `Recaptcha.configure` (when testing, for example), you can use a `Recaptcha#with_configuration` block:
  68 +
  69 + Recaptcha.configure(:public_key => '12345') do
  70 + # Do stuff with the overwritten public_key.
  71 + end
  72 +
  73 +=== Shell environment
  74 +
  75 +Or, you can keep your keys out of your code base by exporting the following
  76 +environment variables. You might do this in the .profile/rc, or equivalent for
  77 +the user running your application:
  78 +
  79 + export RECAPTCHA_PUBLIC_KEY = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
  80 + export RECAPTCHA_PRIVATE_KEY = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
  81 +
  82 +=== Per call
  83 +
  84 +You can also pass in your keys as options at runtime, for example:
  85 +
  86 + recaptcha_tags :public_key => '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
  87 +
  88 +and later,
  89 +
  90 + verify_recaptcha :private_key => '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
  91 +
  92 +This option might be useful, if the same code base is used for multiple
  93 +reCAPTCHA setups.
  94 +
  95 +== To use 'recaptcha'
  96 +
  97 +Add +recaptcha_tags+ to each form you want to protect.
  98 +
  99 +And, add +verify_recaptcha+ logic to each form action that you've protected.
  100 +
  101 +=== +recaptcha_tags+
  102 +
  103 +Some of the options available:
  104 +
  105 +<tt>:ssl</tt>:: Uses secure http for captcha widget (default +false+)
  106 +<tt>:noscript</tt>:: Include <noscript> content (default +true+)
  107 +<tt>:display</tt>:: Takes a hash containing the +theme+ and +tabindex+ options per the API. (default +nil+)
  108 +<tt>:ajax</tt>:: Render the dynamic AJAX captcha per the API. (default +false+)
  109 +<tt>:public_key</tt>:: Your public API key, takes precedence over the ENV variable (default +nil+)
  110 +<tt>:error</tt>:: Override the error code returned from the reCAPTCHA API (default +nil+)
  111 +
  112 +You can also override the html attributes for the sizes of the generated +textarea+ and +iframe+
  113 +elements, if CSS isn't your thing. Inspect the source of +recaptcha_tags+ to see these options.
  114 +
  115 +=== +verify_recaptcha+
  116 +
  117 +This method returns +true+ or +false+ after processing the parameters from the reCAPTCHA widget. Why
  118 +isn't this a model validation? Because that violates MVC. You can use it like this, or how ever you
  119 +like. Passing in the ActiveRecord object is optional, if you do--and the captcha fails to verify--an
  120 +error will be added to the object for you to use.
  121 +
  122 +Some of the options available:
  123 +
  124 +<tt>:model</tt>:: Model to set errors
  125 +<tt>:attribute</tt>:: Model attribute to receive errors (default :base)
  126 +<tt>:message</tt>:: Custom error message
  127 +<tt>:private_key</tt>:: Your private API key, takes precedence over the ENV variable (default +nil+).
  128 +<tt>:timeout</tt>:: The number of seconds to wait for reCAPTCHA servers before give up. (default +3+)
  129 +
  130 + respond_to do |format|
  131 + if verify_recaptcha(:model => @post, :message => "Oh! It's error with reCAPTCHA!") && @post.save
  132 + # ...
  133 + else
  134 + # ...
  135 + end
  136 + end
  137 +
  138 +== I18n support
  139 +reCAPTCHA passes two types of error explanation to a linked model. It will use the I18n gem
  140 +to translate the default error message if I18n is available. To customize the messages to your locale,
  141 +add these keys to your I18n backend:
  142 +
  143 +<tt>recaptcha.errors.verification_failed</tt>:: error message displayed if the captcha words didn't match
  144 +<tt>recaptcha.errors.recaptcha_unavailable</tt>:: displayed if a timout error occured while attempting to verify the captcha
  145 +
  146 +== TODO
  147 +* Remove Rails/ActionController dependencies
  148 +* Framework agnostic
  149 +* Add some helpers to use in before_filter and what not
  150 +* Better documentation
... ...
vendor/plugins/recaptcha/Rakefile 0 → 100644
... ... @@ -0,0 +1,60 @@
  1 +require 'rake'
  2 +
  3 +begin
  4 + require 'jeweler'
  5 + Jeweler::Tasks.new do |gem|
  6 + gem.name = "recaptcha"
  7 + gem.description = "This plugin adds helpers for the reCAPTCHA API "
  8 + gem.summary = "Helpers for the reCAPTCHA API"
  9 + gem.homepage = "http://ambethia.com/recaptcha"
  10 + gem.authors = ["Jason L. Perry"]
  11 + gem.email = "jasper@ambethia.com"
  12 + gem.files.reject! { |fn| fn.include? ".gitignore" }
  13 + gem.add_development_dependency "mocha"
  14 + gem.add_development_dependency "activesupport"
  15 + end
  16 + Jeweler::GemcutterTasks.new
  17 +rescue LoadError
  18 + puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
  19 +end
  20 +
  21 +require 'rake/rdoctask'
  22 +Rake::RDocTask.new do |rd|
  23 + if File.exist?('VERSION.yml')
  24 + config = YAML.load(File.read('VERSION.yml'))
  25 + version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
  26 + else
  27 + version = ""
  28 + end
  29 +
  30 + rd.main = "README.rdoc"
  31 + rd.rdoc_files.include "README.rdoc", "LICENSE", "lib/**/*.rb"
  32 + rd.rdoc_dir = 'rdoc'
  33 + rd.options << '-N' # line numbers
  34 + rd.options << '-S' # inline source
  35 +end
  36 +
  37 +require 'rake/testtask'
  38 +Rake::TestTask.new(:test) do |test|
  39 + test.libs << 'test'
  40 + test.pattern = 'test/**/*_test.rb'
  41 + # test.verbose = true
  42 +end
  43 +
  44 +begin
  45 + require 'rcov/rcovtask'
  46 + Rcov::RcovTask.new do |test|
  47 + test.libs << 'test'
  48 + test.pattern = 'test/**/*_test.rb'
  49 + test.verbose = true
  50 + end
  51 +rescue LoadError
  52 + task :rcov do
  53 + abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
  54 + end
  55 +end
  56 +
  57 +task :default => :test
  58 +
  59 +
  60 +
... ...
vendor/plugins/recaptcha/VERSION 0 → 100644
... ... @@ -0,0 +1 @@
  1 +0.3.2
... ...
vendor/plugins/recaptcha/init.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +# Rails plugin initialization.
  2 +# You can also install it as a gem:
  3 +# config.gem "ambethia-recaptcha", :lib => "recaptcha/rails", :source => "http://gems.github.com"
  4 +
  5 +require 'recaptcha/rails'
0 6 \ No newline at end of file
... ...
vendor/plugins/recaptcha/lib/recaptcha.rb 0 → 100644
... ... @@ -0,0 +1,58 @@
  1 +require 'recaptcha/configuration'
  2 +require 'recaptcha/client_helper'
  3 +require 'recaptcha/verify'
  4 +
  5 +module Recaptcha
  6 + module VERSION #:nodoc:
  7 + MAJOR = 0
  8 + MINOR = 2
  9 + TINY = 2
  10 + PATCH = 1
  11 +
  12 + STRING = [MAJOR, MINOR, TINY, PATCH].join('.')
  13 + end
  14 +
  15 +
  16 + RECAPTCHA_API_SERVER_URL = 'http://www.google.com/recaptcha/api'
  17 + RECAPTCHA_API_SECURE_SERVER_URL = 'https://www.google.com/recaptcha/api'
  18 + RECAPTCHA_VERIFY_URL = 'http://www.google.com/recaptcha/api/verify'
  19 +
  20 + SKIP_VERIFY_ENV = ['test', 'cucumber']
  21 +
  22 + # Gives access to the current Configuration.
  23 + def self.configuration
  24 + @configuration ||= Configuration.new
  25 + end
  26 +
  27 + # Allows easy setting of multiple configuration options. See Configuration
  28 + # for all available options.
  29 + #--
  30 + # The temp assignment is only used to get a nicer rdoc. Feel free to remove
  31 + # this hack.
  32 + #++
  33 + def self.configure
  34 + config = configuration
  35 + yield(config)
  36 + end
  37 +
  38 + def self.with_configuration(config)
  39 + original_config = {}
  40 +
  41 + config.each do |key, value|
  42 + original_config[key] = configuration.send(key)
  43 + configuration.send("#{key}=", value)
  44 + end
  45 +
  46 + result = yield if block_given?
  47 +
  48 + original_config.each { |key, value| configuration.send("#{key}=", value) }
  49 + result
  50 + end
  51 +
  52 + class RecaptchaError < StandardError
  53 + end
  54 +end
  55 +
  56 +if defined?(Rails)
  57 + require 'recaptcha/rails'
  58 +end
... ...
vendor/plugins/recaptcha/lib/recaptcha/client_helper.rb 0 → 100644
... ... @@ -0,0 +1,51 @@
  1 +module Recaptcha
  2 + module ClientHelper
  3 + # Your public API can be specified in the +options+ hash or preferably
  4 + # using the Configuration.
  5 + def recaptcha_tags(options = {})
  6 + # Default options
  7 + key = options[:public_key] ||= Recaptcha.configuration.public_key
  8 + raise RecaptchaError, "No public key specified." unless key
  9 + error = options[:error] ||= (defined? flash ? flash[:recaptcha_error] : "")
  10 + uri = Recaptcha.configuration.api_server_url(options[:ssl])
  11 + html = ""
  12 + if options[:display]
  13 + html << %{<script type="text/javascript">\n}
  14 + html << %{ var RecaptchaOptions = #{options[:display].to_json};\n}
  15 + html << %{</script>\n}
  16 + end
  17 + if options[:ajax]
  18 + html << <<-EOS
  19 + <div id="dynamic_recaptcha"></div>
  20 + <script type="text/javascript">
  21 + var rc_script_tag = document.createElement('script'),
  22 + rc_init_func = function(){Recaptcha.create("#{key}", document.getElementById("dynamic_recaptcha")#{',RecaptchaOptions' if options[:display]});}
  23 + rc_script_tag.src = "#{uri}/js/recaptcha_ajax.js";
  24 + rc_script_tag.type = 'text/javascript';
  25 + rc_script_tag.onload = function(){rc_init_func.call();};
  26 + rc_script_tag.onreadystatechange = function(){
  27 + if (rc_script_tag.readyState == 'loaded' || rc_script_tag.readyState == 'complete') {rc_init_func.call();}
  28 + };
  29 + (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(rc_script_tag);
  30 + </script>
  31 + EOS
  32 + else
  33 + html << %{<script type="text/javascript" src="#{uri}/challenge?k=#{key}}
  34 + html << %{#{error ? "&amp;error=#{CGI::escape(error)}" : ""}"></script>\n}
  35 + unless options[:noscript] == false
  36 + html << %{<noscript>\n }
  37 + html << %{<iframe src="#{uri}/noscript?k=#{key}" }
  38 + html << %{height="#{options[:iframe_height] ||= 300}" }
  39 + html << %{width="#{options[:iframe_width] ||= 500}" }
  40 + html << %{style="border:none;"></iframe><br/>\n }
  41 + html << %{<textarea name="recaptcha_challenge_field" }
  42 + html << %{rows="#{options[:textarea_rows] ||= 3}" }
  43 + html << %{cols="#{options[:textarea_cols] ||= 40}"></textarea>\n }
  44 + html << %{<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>}
  45 + html << %{</noscript>\n}
  46 + end
  47 + end
  48 + return (html.respond_to?(:html_safe) && html.html_safe) || html
  49 + end # recaptcha_tags
  50 + end # ClientHelper
  51 +end # Recaptcha
... ...
vendor/plugins/recaptcha/lib/recaptcha/configuration.rb 0 → 100644
... ... @@ -0,0 +1,53 @@
  1 +module Recaptcha
  2 + # This class enables detailed configuration of the recaptcha services.
  3 + #
  4 + # By calling
  5 + #
  6 + # Recaptcha.configuration # => instance of Recaptcha::Configuration
  7 + #
  8 + # or
  9 + # Recaptcha.configure do |config|
  10 + # config # => instance of Recaptcha::Configuration
  11 + # end
  12 + #
  13 + # you are able to perform configuration updates.
  14 + #
  15 + # Your are able to customize all attributes listed below. All values have
  16 + # sensitive default and will very likely not need to be changed.
  17 + #
  18 + # Please note that the public and private key for the reCAPTCHA API Access
  19 + # have no useful default value. The keys may be set via the Shell enviroment
  20 + # or using this configuration. Settings within this configuration always take
  21 + # precedence.
  22 + #
  23 + # Setting the keys with this Configuration
  24 + #
  25 + # Recaptcha.configure do |config|
  26 + # config.public_key = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
  27 + # config.private_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
  28 + # end
  29 + #
  30 + class Configuration
  31 + attr_accessor :nonssl_api_server_url,
  32 + :ssl_api_server_url,
  33 + :verify_url,
  34 + :skip_verify_env,
  35 + :private_key,
  36 + :public_key,
  37 + :proxy
  38 +
  39 + def initialize #:nodoc:
  40 + @nonssl_api_server_url = RECAPTCHA_API_SERVER_URL
  41 + @ssl_api_server_url = RECAPTCHA_API_SECURE_SERVER_URL
  42 + @verify_url = RECAPTCHA_VERIFY_URL
  43 + @skip_verify_env = SKIP_VERIFY_ENV
  44 +
  45 + @private_key = ENV['RECAPTCHA_PRIVATE_KEY']
  46 + @public_key = ENV['RECAPTCHA_PUBLIC_KEY']
  47 + end
  48 +
  49 + def api_server_url(ssl = false) #:nodoc:
  50 + ssl ? ssl_api_server_url : nonssl_api_server_url
  51 + end
  52 + end
  53 +end
... ...
vendor/plugins/recaptcha/lib/recaptcha/merb.rb 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +require 'recaptcha'
  2 +
  3 +Merb::GlobalHelpers.send(:include, Recaptcha::ClientHelper)
  4 +Merb::Controller.send(:include, Recaptcha::Verify)
... ...
vendor/plugins/recaptcha/lib/recaptcha/rails.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +require 'net/http'
  2 +require 'recaptcha'
  3 +
  4 +ActionView::Base.send(:include, Recaptcha::ClientHelper)
  5 +ActionController::Base.send(:include, Recaptcha::Verify)
0 6 \ No newline at end of file
... ...
vendor/plugins/recaptcha/lib/recaptcha/railtie.rb 0 → 100644
... ... @@ -0,0 +1,15 @@
  1 +require 'net/http'
  2 +require 'recaptcha'
  3 +module Rails
  4 + module Recaptcha
  5 + class Railtie < Rails::Railtie
  6 + initializer "setup config" do
  7 + begin
  8 + ActionView::Base.send(:include, ::Recaptcha::ClientHelper)
  9 + ActionController::Base.send(:include, ::Recaptcha::Verify)
  10 + end
  11 + end
  12 + end
  13 + end
  14 +end
  15 +
... ...
vendor/plugins/recaptcha/lib/recaptcha/verify.rb 0 → 100644
... ... @@ -0,0 +1,61 @@
  1 +require "uri"
  2 +module Recaptcha
  3 + module Verify
  4 + # Your private API can be specified in the +options+ hash or preferably
  5 + # using the Configuration.
  6 + def verify_recaptcha(options = {})
  7 + if !options.is_a? Hash
  8 + options = {:model => options}
  9 + end
  10 +
  11 + env = options[:env] || ENV['RAILS_ENV']
  12 + return true if Recaptcha.configuration.skip_verify_env.include? env
  13 + model = options[:model]
  14 + attribute = options[:attribute] || :base
  15 + private_key = options[:private_key] || Recaptcha.configuration.private_key
  16 + raise RecaptchaError, "No private key specified." unless private_key
  17 +
  18 + begin
  19 + recaptcha = nil
  20 + if(Recaptcha.configuration.proxy)
  21 + proxy_server = URI.parse(Recaptcha.configuration.proxy)
  22 + http = Net::HTTP::Proxy(proxy_server.host, proxy_server.port)
  23 + else
  24 + http = Net::HTTP
  25 + end
  26 +
  27 + Timeout::timeout(options[:timeout] || 3) do
  28 + recaptcha = http.post_form(URI.parse(Recaptcha.configuration.verify_url), {
  29 + "privatekey" => private_key,
  30 + "remoteip" => request.remote_ip,
  31 + "challenge" => params[:recaptcha_challenge_field],
  32 + "response" => params[:recaptcha_response_field]
  33 + })
  34 + end
  35 + answer, error = recaptcha.body.split.map { |s| s.chomp }
  36 + unless answer == 'true'
  37 + flash[:recaptcha_error] = error
  38 + if model
  39 + message = "Word verification response is incorrect, please try again."
  40 + message = I18n.translate(:'recaptcha.errors.verification_failed', {:default => message}) if defined?(I18n)
  41 + model.errors.add attribute, options[:message] || message
  42 + end
  43 + return false
  44 + else
  45 + flash[:recaptcha_error] = nil
  46 + return true
  47 + end
  48 + rescue Timeout::Error
  49 + flash[:recaptcha_error] = "recaptcha-not-reachable"
  50 + if model
  51 + message = "Oops, we failed to validate your word verification response. Please try again."
  52 + message = I18n.translate(:'recaptcha.errors.recaptcha_unreachable', :default => message) if defined?(I18n)
  53 + model.errors.add attribute, options[:message] || message
  54 + end
  55 + return false
  56 + rescue Exception => e
  57 + raise RecaptchaError, e.message, e.backtrace
  58 + end
  59 + end # verify_recaptcha
  60 + end # Verify
  61 +end # Recaptcha
... ...
vendor/plugins/recaptcha/recaptcha.gemspec 0 → 100644
... ... @@ -0,0 +1,65 @@
  1 +# Generated by jeweler
  2 +# DO NOT EDIT THIS FILE DIRECTLY
  3 +# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
  4 +# -*- encoding: utf-8 -*-
  5 +
  6 +Gem::Specification.new do |s|
  7 + s.name = %q{recaptcha}
  8 + s.version = "0.3.2"
  9 +
  10 + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
  11 + s.authors = ["Jason L. Perry"]
  12 + s.date = %q{2010-12-20}
  13 + s.description = %q{This plugin adds helpers for the reCAPTCHA API }
  14 + s.email = %q{jasper@ambethia.com}
  15 + s.extra_rdoc_files = [
  16 + "LICENSE",
  17 + "README.rdoc"
  18 + ]
  19 + s.files = [
  20 + "CHANGELOG",
  21 + "LICENSE",
  22 + "README.rdoc",
  23 + "Rakefile",
  24 + "VERSION",
  25 + "init.rb",
  26 + "lib/recaptcha.rb",
  27 + "lib/recaptcha/client_helper.rb",
  28 + "lib/recaptcha/configuration.rb",
  29 + "lib/recaptcha/merb.rb",
  30 + "lib/recaptcha/rails.rb",
  31 + "lib/recaptcha/verify.rb",
  32 + "recaptcha.gemspec",
  33 + "tasks/recaptcha_tasks.rake",
  34 + "test/recaptcha_test.rb",
  35 + "test/verify_recaptcha_test.rb"
  36 + ]
  37 + s.homepage = %q{http://ambethia.com/recaptcha}
  38 + s.require_paths = ["lib"]
  39 + s.rubygems_version = %q{1.3.7}
  40 + s.summary = %q{Helpers for the reCAPTCHA API}
  41 + s.test_files = [
  42 + "test/recaptcha_test.rb",
  43 + "test/verify_recaptcha_test.rb"
  44 + ]
  45 +
  46 + if s.respond_to? :specification_version then
  47 + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
  48 + s.specification_version = 3
  49 +
  50 + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
  51 + s.add_development_dependency(%q<mocha>, [">= 0"])
  52 + s.add_development_dependency(%q<activesupport>, [">= 0"])
  53 + s.add_dependency(%q<i18n>, [">= 0"])
  54 + else
  55 + s.add_dependency(%q<mocha>, [">= 0"])
  56 + s.add_dependency(%q<activesupport>, [">= 0"])
  57 + s.add_dependency(%q<i18n>, [">= 0"])
  58 + end
  59 + else
  60 + s.add_dependency(%q<mocha>, [">= 0"])
  61 + s.add_dependency(%q<activesupport>, [">= 0"])
  62 + s.add_dependency(%q<i18n>, [">= 0"])
  63 + end
  64 +end
  65 +
... ...
vendor/plugins/recaptcha/tasks/recaptcha_tasks.rake 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +# desc "Explaining what the task does"
  2 +# task :recaptcha do
  3 +# # Task goes here
  4 +# end
0 5 \ No newline at end of file
... ...
vendor/plugins/recaptcha/test/recaptcha_test.rb 0 → 100644
... ... @@ -0,0 +1,52 @@
  1 +require 'test/unit'
  2 +require 'cgi'
  3 +require File.dirname(File.expand_path(__FILE__)) + '/../lib/recaptcha'
  4 +
  5 +class RecaptchaClientHelperTest < Test::Unit::TestCase
  6 + include Recaptcha
  7 + include Recaptcha::ClientHelper
  8 + include Recaptcha::Verify
  9 +
  10 + attr_accessor :session
  11 +
  12 + def setup
  13 + @session = {}
  14 + Recaptcha.configure do |config|
  15 + config.public_key = '0000000000000000000000000000000000000000'
  16 + config.private_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  17 + end
  18 + end
  19 +
  20 + def test_recaptcha_tags
  21 + # Might as well match something...
  22 + assert_match /http:\/\/www.google.com\/recaptcha\/api\/challenge/, recaptcha_tags
  23 + end
  24 +
  25 + def test_recaptcha_tags_with_ssl
  26 + assert_match /https:\/\/www.google.com\/recaptcha\/api\/challenge/, recaptcha_tags(:ssl => true)
  27 + end
  28 +
  29 + def test_recaptcha_tags_without_noscript
  30 + assert_no_match /noscript/, recaptcha_tags(:noscript => false)
  31 + end
  32 +
  33 + def test_should_raise_exception_without_public_key
  34 + assert_raise RecaptchaError do
  35 + Recaptcha.configuration.public_key = nil
  36 + recaptcha_tags
  37 + end
  38 + end
  39 +
  40 + def test_different_configuration_within_with_configuration_block
  41 + key = Recaptcha.with_configuration(:public_key => '12345') do
  42 + Recaptcha.configuration.public_key
  43 + end
  44 +
  45 + assert_equal('12345', key)
  46 + end
  47 +
  48 + def test_reset_configuration_after_with_configuration_block
  49 + Recaptcha.with_configuration(:public_key => '12345')
  50 + assert_equal('0000000000000000000000000000000000000000', Recaptcha.configuration.public_key)
  51 + end
  52 +end
... ...
vendor/plugins/recaptcha/test/verify_recaptcha_test.rb 0 → 100644
... ... @@ -0,0 +1,120 @@
  1 +# coding: utf-8
  2 +
  3 +require 'test/unit'
  4 +require 'rubygems'
  5 +require 'active_support/core_ext/string'
  6 +require 'mocha'
  7 +require 'i18n'
  8 +require 'net/http'
  9 +require File.dirname(File.expand_path(__FILE__)) + '/../lib/recaptcha'
  10 +
  11 +class RecaptchaVerifyTest < Test::Unit::TestCase
  12 + def setup
  13 + Recaptcha.configuration.private_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  14 + @controller = TestController.new
  15 + @controller.request = stub(:remote_ip => "1.1.1.1")
  16 + @controller.params = {:recaptcha_challenge_field => "challenge", :recaptcha_response_field => "response"}
  17 +
  18 + @expected_post_data = {}
  19 + @expected_post_data["privatekey"] = Recaptcha.configuration.private_key
  20 + @expected_post_data["remoteip"] = @controller.request.remote_ip
  21 + @expected_post_data["challenge"] = "challenge"
  22 + @expected_post_data["response"] = "response"
  23 +
  24 + @expected_uri = URI.parse(Recaptcha.configuration.verify_url)
  25 + end
  26 +
  27 + def test_should_raise_exception_without_private_key
  28 + assert_raise Recaptcha::RecaptchaError do
  29 + Recaptcha.configuration.private_key = nil
  30 + @controller.verify_recaptcha
  31 + end
  32 + end
  33 +
  34 + def test_should_return_false_when_key_is_invalid
  35 + expect_http_post(response_with_body("false\ninvalid-site-private-key"))
  36 +
  37 + assert !@controller.verify_recaptcha
  38 + assert_equal "invalid-site-private-key", @controller.flash[:recaptcha_error]
  39 + end
  40 +
  41 + def test_returns_true_on_success
  42 + @controller.flash[:recaptcha_error] = "previous error that should be cleared"
  43 + expect_http_post(response_with_body("true\n"))
  44 +
  45 + assert @controller.verify_recaptcha
  46 + assert_nil @controller.flash[:recaptcha_error]
  47 + end
  48 +
  49 + def test_errors_should_be_added_to_model
  50 + expect_http_post(response_with_body("false\nbad-news"))
  51 +
  52 + errors = mock
  53 + errors.expects(:add).with(:base, "Word verification response is incorrect, please try again.")
  54 + model = mock(:errors => errors)
  55 +
  56 + assert !@controller.verify_recaptcha(:model => model)
  57 + assert_equal "bad-news", @controller.flash[:recaptcha_error]
  58 + end
  59 +
  60 + def test_returns_true_on_success_with_optional_key
  61 + @controller.flash[:recaptcha_error] = "previous error that should be cleared"
  62 + # reset private key
  63 + @expected_post_data["privatekey"] = 'ADIFFERENTPRIVATEKEYXXXXXXXXXXXXXX'
  64 + expect_http_post(response_with_body("true\n"))
  65 +
  66 + assert @controller.verify_recaptcha(:private_key => 'ADIFFERENTPRIVATEKEYXXXXXXXXXXXXXX')
  67 + assert_nil @controller.flash[:recaptcha_error]
  68 + end
  69 +
  70 + def test_timeout
  71 + expect_http_post(Timeout::Error, :exception => true)
  72 + assert !@controller.verify_recaptcha()
  73 + assert_equal "recaptcha-not-reachable", @controller.flash[:recaptcha_error]
  74 + end
  75 +
  76 + def test_message_should_use_i18n
  77 + I18n.locale = :de
  78 + verification_failed_translated = "Sicherheitscode konnte nicht verifiziert werden."
  79 + verification_failed_default = "Word verification response is incorrect, please try again."
  80 + recaptcha_unreachable_translated = "Netzwerkfehler, bitte versuchen Sie es später erneut."
  81 + recaptcha_unreachable_default = "Oops, we failed to validate your word verification response. Please try again."
  82 + I18n.expects(:translate).with(:'recaptcha.errors.verification_failed', :default => verification_failed_default).returns(verification_failed_translated)
  83 + I18n.expects(:translate).with(:'recaptcha.errors.recaptcha_unreachable', :default => recaptcha_unreachable_default).returns(recaptcha_unreachable_translated)
  84 +
  85 + errors = mock
  86 + errors.expects(:add).with(:base, verification_failed_translated)
  87 + errors.expects(:add).with(:base, recaptcha_unreachable_translated)
  88 + model = mock; model.stubs(:errors => errors)
  89 +
  90 + expect_http_post(response_with_body("false\nbad-news"))
  91 + @controller.verify_recaptcha(:model => model)
  92 +
  93 + expect_http_post(Timeout::Error, :exception => true)
  94 + @controller.verify_recaptcha(:model => model)
  95 +
  96 + end
  97 +
  98 + private
  99 +
  100 + class TestController
  101 + include Recaptcha::Verify
  102 + attr_accessor :request, :params, :flash
  103 +
  104 + def initialize
  105 + @flash = {}
  106 + end
  107 + end
  108 +
  109 + def expect_http_post(response, options = {})
  110 + unless options[:exception]
  111 + Net::HTTP.expects(:post_form).with(@expected_uri, @expected_post_data).returns(response)
  112 + else
  113 + Net::HTTP.expects(:post_form).raises response
  114 + end
  115 + end
  116 +
  117 + def response_with_body(body)
  118 + stub(:body => body)
  119 + end
  120 +end
... ...