human_detector 1.0.0.rc

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Gnomeslab, Lda.
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.
data/README.md ADDED
@@ -0,0 +1,2 @@
1
+ Work in Progress.
2
+ Stay tuned, and meanwhile, visit http://gnomeslab.com
@@ -0,0 +1,22 @@
1
+ require 'rails/generators/active_record'
2
+
3
+ module HumanDetector
4
+
5
+ module Generators
6
+
7
+ class HumanDetectorGenerator < ActiveRecord::Generators::Base
8
+ desc "Generates the migration required to support HumanDetector Ruby Gem."
9
+
10
+ namespace "human_detector"
11
+
12
+ source_root File.expand_path('../templates', __FILE__)
13
+
14
+ def generate_migration
15
+ migration_template 'create_human_detector_questions.rb', 'db/migrate/create_human_detector_questions.rb'
16
+ end # generate_human_detector
17
+
18
+ end # HumanDetectorGenerator
19
+
20
+ end # Generators
21
+
22
+ end # HumanDetector
@@ -0,0 +1,52 @@
1
+ require 'human_detector'
2
+
3
+ class CreateHumanDetectorQuestions < ActiveRecord::Migration
4
+ def self.up
5
+ create_table :human_detector_questions, :force => true do |t|
6
+ t.string :title, :null => false
7
+ t.string :answer, :null => false
8
+ t.timestamps
9
+ end
10
+
11
+ 5.times { |i| HumanDetector::Question.create(:title => "How much is #{i} + #{i * 2}?", :answer => "#{i + i * 2}") }
12
+ 5.times { |i| HumanDetector::Question.create(:title => "Complete the sequence: #{i}, #{i+1}, #{i+2}, __ ?",
13
+ :answer => "#{i+3}") }
14
+ 5.times { |i| HumanDetector::Question.create(:title => "Complete the sequence: #{i}, __, #{i+2}, #{i+3} ?",
15
+ :answer => "#{i+1}") }
16
+ { 0 => "zero",
17
+ 1 => "one",
18
+ 2 => "two",
19
+ 3 => "three",
20
+ 4 => "four",
21
+ 5 => "five",
22
+ 6 => "six",
23
+ 7 => "seven",
24
+ 8 => "eight",
25
+ 9 => "nine",
26
+ 10 => "ten" }.each { |k,v| HumanDetector::Question.create(:title=> "#{k} in English (e.g. #{v})?", :answer=> v) }
27
+
28
+ 10.times do |i|
29
+ HumanDetector::Question.create(:title => "Which year was in 2010 minus #{i + 1} (e.g. #{2010 - (i + 1)})?",
30
+ :answer => (2010 - (i + 1)).to_s)
31
+ end
32
+
33
+ 100.times do |i|
34
+ HumanDetector::Question.create(:title => "Is #{i} and even number (e.g. #{i.even? ? 'yes' : 'no'})?",
35
+ :answer => i.even? ? "yes" : "no")
36
+ HumanDetector::Question.create(:title => "Is #{i} an odd number (e.g. #{i.even? ? 'no' : 'yes'})?",
37
+ :answer => i.even? ? 'no' : 'yes')
38
+ end
39
+
40
+ HumanDetector::Question.create(:title => 'Are you a bot (e.g. yes)?', :answer => 'no')
41
+ HumanDetector::Question.create(:title => 'Are you a sure? (e.g. no)?', :answer => 'yes')
42
+ HumanDetector::Question.create(:title => 'Are you alive? (e.g. no)?', :answer => 'yes')
43
+ HumanDetector::Question.create(:title => 'Are you human? (e.g. no)?', :answer => 'yes')
44
+ HumanDetector::Question.create(:title => 'Do you live on earth (e.g. yes)?', :answer => 'yes')
45
+ HumanDetector::Question.create(:title => 'Are you spamming (e.g. no)?', :answer => 'no')
46
+ HumanDetector::Question.create(:title => 'Are you a spam bot (e.g. yes)?', :answer => 'no')
47
+ end
48
+
49
+ def self.down
50
+ drop_table :human_detector_questions
51
+ end
52
+ end
@@ -0,0 +1,33 @@
1
+ require 'openssl'
2
+
3
+ module HumanDetector
4
+
5
+ class Cipher
6
+ def self.encrypt(text)
7
+ aes_wrapper :encrypt, text
8
+ end # encrypt
9
+
10
+ def self.decrypt(text)
11
+ aes_wrapper :decrypt, text
12
+ end # decrypt
13
+
14
+ private
15
+ def self.aes_wrapper(direction, text)
16
+ return nil unless text
17
+
18
+ aes = OpenSSL::Cipher::Cipher.new('aes-256-cbc').send(direction)
19
+ aes.key = '484758fc806d09ad70af78e51cda016f4072a20f7e48ee9ab898dd0466b11b4f'
20
+
21
+ if direction == :encrypt
22
+ aes.iv = iv = aes.random_iv
23
+ URI.escape(ActiveSupport::Base64.encode64(iv + (aes.update(text) + aes.final)))
24
+ else
25
+ raw = ActiveSupport::Base64.decode64 URI.unescape(text)
26
+ aes.iv = raw.slice! 0, 16
27
+ aes.update(raw) + aes.final
28
+ end
29
+ end
30
+
31
+ end # Cipher
32
+
33
+ end # HumanDetector
@@ -0,0 +1,11 @@
1
+ module HumanDetector
2
+
3
+ class Question < ActiveRecord::Base
4
+ set_table_name 'human_detector_questions'
5
+
6
+ validates :title, :presence => true
7
+ validates :answer, :presence => true
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,32 @@
1
+ module HumanDetector
2
+
3
+ module ActionController
4
+
5
+ module SpamDetected
6
+
7
+ HUMAN_DETECTOR_DEFAULT_OPTIONS = { :flash => { :error => 'Invalid captcha answer' },
8
+ :input_name => 'human_detector_answer' }
9
+
10
+ private
11
+ def human_detected?(options = {})
12
+ !spam_detected?(options)
13
+ end
14
+
15
+ def spam_detected?(options = {})
16
+ options.reverse_merge! HUMAN_DETECTOR_DEFAULT_OPTIONS
17
+
18
+ return false if params.include?('human_detector_question_id') && params[options[:input_name]] ==
19
+ Question.find_by_id(HumanDetector::Cipher.decrypt(params['human_detector_question_id']).
20
+ gsub(/(_\S+)/, '')).try(:answer)
21
+
22
+ options[:flash] = { :error => options[:flash] } if options[:flash].is_a?(String)
23
+ flash.merge! options[:flash]
24
+
25
+ return true
26
+ end
27
+
28
+ end # Filter
29
+
30
+ end # ActionController
31
+
32
+ end # HumanDetector
@@ -0,0 +1,9 @@
1
+ module HumanDetector
2
+
3
+ module ActionController
4
+
5
+ autoload :SpamDetected, 'human_detector/rails_ext/action_controller/spam_detected'
6
+
7
+ end # ActionController
8
+
9
+ end # HumanDetector
@@ -0,0 +1,21 @@
1
+ module HumanDetector
2
+
3
+ module ActionView
4
+
5
+ module Helper
6
+
7
+ def human_detector_tag(options = {})
8
+ options.reverse_merge! :renderer => HumanDetector::Renderers::Default
9
+
10
+ options[:renderer].send(:render,
11
+ self,
12
+ Cipher.encrypt("#{(question = Question.random).id}_#{controller.session[:session_id]}"),
13
+ question.title,
14
+ options.except(:renderer))
15
+ end # human_detector_tag
16
+
17
+ end # Helper
18
+
19
+ end # ActionView
20
+
21
+ end # HumanDetector
@@ -0,0 +1,9 @@
1
+ module HumanDetector
2
+
3
+ module ActionView
4
+
5
+ autoload :Helper, 'human_detector/rails_ext/action_view/helper'
6
+
7
+ end # ActionView
8
+
9
+ end # HumanDetector
@@ -0,0 +1,26 @@
1
+ module HumanDetector
2
+
3
+ module Renderers
4
+
5
+ class Default
6
+
7
+ def self.render(view, id, title, options = {})
8
+ options.reverse_merge!({ :label_css => 'human_detector_question',
9
+ :input_css => 'human_detector_answer',
10
+ :input_name => 'human_detector_answer',
11
+ :label_prefix => '',
12
+ :label_sufix => '',
13
+ :input_text => '' })
14
+
15
+ output = view.label_tag(options[:input_name],
16
+ (options[:label_prefix].html_safe << title << options[:label_sufix].html_safe),
17
+ :class => options[:label_css])
18
+ output << view.text_field_tag(options[:input_name], options[:input_text], :class => options[:input_css])
19
+ output.tap { |s| s << view.hidden_field_tag('human_detector_question_id', id) }
20
+ end # render
21
+
22
+ end # Default
23
+
24
+ end # Renderers
25
+
26
+ end # HumanDetector
@@ -0,0 +1,9 @@
1
+ module HumanDetector
2
+
3
+ module Renderers
4
+
5
+ autoload :Default, 'human_detector/renderers/default'
6
+
7
+ end # Renderers
8
+
9
+ end # HumanDetector
@@ -0,0 +1,13 @@
1
+ module HumanDetector
2
+
3
+ autoload :ActionView, 'human_detector/rails_ext/action_view'
4
+ autoload :ActionController, 'human_detector/rails_ext/action_controller'
5
+ autoload :Renderers, 'human_detector/renderers'
6
+ autoload :Question, 'human_detector/question'
7
+ autoload :Cipher, 'human_detector/cipher'
8
+
9
+ end # HumanDetector
10
+
11
+ # Rails extentions
12
+ ActionView::Base.send :include, HumanDetector::ActionView::Helper
13
+ ActionController::Base.send :include, HumanDetector::ActionController::SpamDetected
metadata ADDED
@@ -0,0 +1,216 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: human_detector
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: true
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ - rc
10
+ version: 1.0.0.rc
11
+ platform: ruby
12
+ authors:
13
+ - Gnomeslab, Lda.
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-18 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: actionpack
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ segments:
30
+ - 3
31
+ - 0
32
+ - 0
33
+ version: 3.0.0
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: activerecord
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ segments:
45
+ - 3
46
+ - 0
47
+ - 0
48
+ version: 3.0.0
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: activerecord_random
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 1
61
+ - 0
62
+ - 0
63
+ version: 1.0.0
64
+ type: :runtime
65
+ version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ name: fuubar
68
+ prerelease: false
69
+ requirement: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ~>
73
+ - !ruby/object:Gem::Version
74
+ segments:
75
+ - 0
76
+ - 0
77
+ version: "0.0"
78
+ type: :development
79
+ version_requirements: *id004
80
+ - !ruby/object:Gem::Dependency
81
+ name: sqlite3-ruby
82
+ prerelease: false
83
+ requirement: &id005 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ type: :development
92
+ version_requirements: *id005
93
+ - !ruby/object:Gem::Dependency
94
+ name: ruby-debug19
95
+ prerelease: false
96
+ requirement: &id006 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ segments:
102
+ - 0
103
+ version: "0"
104
+ type: :development
105
+ version_requirements: *id006
106
+ - !ruby/object:Gem::Dependency
107
+ name: rspec
108
+ prerelease: false
109
+ requirement: &id007 !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ type: :development
118
+ version_requirements: *id007
119
+ - !ruby/object:Gem::Dependency
120
+ name: nokogiri
121
+ prerelease: false
122
+ requirement: &id008 !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ type: :development
131
+ version_requirements: *id008
132
+ - !ruby/object:Gem::Dependency
133
+ name: factory_girl_rails
134
+ prerelease: false
135
+ requirement: &id009 !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ segments:
141
+ - 0
142
+ version: "0"
143
+ type: :development
144
+ version_requirements: *id009
145
+ - !ruby/object:Gem::Dependency
146
+ name: database_cleaner
147
+ prerelease: false
148
+ requirement: &id010 !ruby/object:Gem::Requirement
149
+ none: false
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ segments:
154
+ - 0
155
+ version: "0"
156
+ type: :development
157
+ version_requirements: *id010
158
+ description: HumanDetector is a friendly logic captcha for Rails the doesn't require any external system dependency (e.g. external captcha API connections). It uses a simple question that any 7 or more years old human can understand, but that a spambot will not be able to answer. This Gem supports Ruby v1.9.2 and Rails 3.0.x.
159
+ email:
160
+ - mail@gnomeslab.com
161
+ executables: []
162
+
163
+ extensions: []
164
+
165
+ extra_rdoc_files: []
166
+
167
+ files:
168
+ - lib/generators/human_detector/human_detector_generator.rb
169
+ - lib/generators/human_detector/templates/create_human_detector_questions.rb
170
+ - lib/human_detector/cipher.rb
171
+ - lib/human_detector/question.rb
172
+ - lib/human_detector/rails_ext/action_controller/spam_detected.rb
173
+ - lib/human_detector/rails_ext/action_controller.rb
174
+ - lib/human_detector/rails_ext/action_view/helper.rb
175
+ - lib/human_detector/rails_ext/action_view.rb
176
+ - lib/human_detector/renderers/default.rb
177
+ - lib/human_detector/renderers.rb
178
+ - lib/human_detector.rb
179
+ - MIT-LICENSE
180
+ - README.md
181
+ has_rdoc: true
182
+ homepage: http://gnomeslab.com/
183
+ licenses: []
184
+
185
+ post_install_message:
186
+ rdoc_options: []
187
+
188
+ require_paths:
189
+ - lib
190
+ required_ruby_version: !ruby/object:Gem::Requirement
191
+ none: false
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ segments:
196
+ - 0
197
+ version: "0"
198
+ required_rubygems_version: !ruby/object:Gem::Requirement
199
+ none: false
200
+ requirements:
201
+ - - ">="
202
+ - !ruby/object:Gem::Version
203
+ segments:
204
+ - 1
205
+ - 3
206
+ - 7
207
+ version: 1.3.7
208
+ requirements: []
209
+
210
+ rubyforge_project:
211
+ rubygems_version: 1.3.7
212
+ signing_key:
213
+ specification_version: 3
214
+ summary: A logic user friendly captcha for Rails (e.g. How much is 5 + 3?)
215
+ test_files: []
216
+