simple_captcha2 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6621a6904b50c409e89e74475975dd3c6c74f149
4
+ data.tar.gz: 265c44d59754f47e0b822072364b1eba94d63a92
5
+ SHA512:
6
+ metadata.gz: a121023c470455b51fecb402780637ba1f3b6a2bfa52b39b27fd6b7a986c788ec02e49c29eb32588598fec10f7cefcc9db10cdf4ea795ac0e1bd9ebd56786dc6
7
+ data.tar.gz: 5c8af3bfd86e3e2e5fe1bb9e1cc6681b3e0e6a2ded5d92834203425c1fae26ad90e6a12c9f82e5c21be49301559a38863944e16202df98cb9b05e8b4a5083ce4
@@ -0,0 +1,244 @@
1
+ =SimpleCaptcha2
2
+
3
+ SimpleCaptcha(2) is the simplest and a robust captcha plugin. Its implementation requires
4
+ adding up a single line in views and in controllers/models.
5
+ SimpleCaptcha2 is available to be used with Rails 3 + 4.
6
+ This is a fork of the popular Rubygem simple_captcha which got abandoned.
7
+
8
+ ==Features
9
+
10
+ * Zero FileSystem usage (secret code moved to db-store and image storage removed).
11
+ * Provides various image styles.
12
+ * Provides three level of complexity of images.
13
+ * Works absolutely fine in distributed environment(session and db based implementation works fine in distributed environment).
14
+ * Implementation is as easy as just writing a single line in your view. "<%= show_simple_captcha %>" within the 'form' tags.
15
+ * Flexible DOM and CSS handling(There is a separate view partial for rendering SimpleCaptcha DOM elements).
16
+ * Automated removal of 1 hour old unmatched simple_captcha data.
17
+
18
+ ==Requirements
19
+
20
+ * {Ruby}[http://ruby-lang.org/] >= 1.8.7
21
+ * {Rails}[http://github.com/rails/rails] >= 3
22
+ * ImageMagick should be installed on your machine to use this plugin.
23
+ visit http://www.imagemagick.org/script/index.php for more details.
24
+
25
+ ==Installation
26
+
27
+ gem 'simple_captcha2'
28
+
29
+ # OR
30
+
31
+ gem 'simple_captcha', :git => 'git://github.com/pludoni/simple-captcha.git'
32
+
33
+ ==Setup
34
+
35
+ After installation, follow these simple steps to setup the plugin. The setup will depend
36
+ on the version of rails your application is using.
37
+
38
+ rails generate simple_captcha
39
+
40
+ rake db:migrate
41
+
42
+ ==Usage
43
+
44
+ ===Controller Based
45
+
46
+ Add the following line in the file "app/controllers/application.rb"
47
+
48
+ ApplicationController < ActionController::Base
49
+ include SimpleCaptcha::ControllerHelpers
50
+ end
51
+
52
+ In the view file within the form tags add this code
53
+
54
+ <%= show_simple_captcha %>
55
+
56
+ and in the controller's action authenticate it as
57
+
58
+ if simple_captcha_valid?
59
+ do this
60
+ else
61
+ do that
62
+ end
63
+
64
+ ===Model Based
65
+
66
+ In the view file within the form tags write this code
67
+
68
+ <%= show_simple_captcha(:object=>"user") %>
69
+
70
+ and in the model class add this code
71
+
72
+ class User < ActiveRecord::Base
73
+ apply_simple_captcha
74
+ end
75
+
76
+ ====FormBuilder helper
77
+
78
+ <%= form_for @user do |form| -%>
79
+ ...
80
+ <%= form.simple_captcha :label => "Enter numbers.." %>
81
+ ...
82
+ <% end -%>
83
+
84
+ ====Validating with captcha
85
+ NOTE: @user.valid? will still work as it should, it will not validate the captcha code.
86
+
87
+ @user.valid_with_captcha?
88
+
89
+ ====Saving with captcha
90
+ NOTE: @user.save will still work as it should, it will not validate the captcha code.
91
+
92
+ @user.save_with_captcha
93
+
94
+ ===Formtastic integration
95
+ SimpleCaptcha detects if your use Formtastic and appends "SimpleCaptcha::CustomFormBuilder".
96
+
97
+ <%= form.input :captcha, :as => :simple_captcha %>
98
+
99
+ ==Options & Examples
100
+ ===View Options
101
+
102
+ * *label* - provides the custom text b/w the image and the text field, the default is "type the code from the image"
103
+
104
+ * *object* - the name of the object of the model class, to implement the model based captcha.
105
+
106
+ * *code_type* - return numeric only if set to 'numeric'
107
+
108
+ ===Global options
109
+
110
+ * *image_style* - provides the specific image style for the captcha image.
111
+ There are eight different styles available with the plugin as...
112
+ 1) simply_blue
113
+ 2) simply_red
114
+ 3) simply_green
115
+ 4) charcoal_grey
116
+ 5) embosed_silver
117
+ 6) all_black
118
+ 7) distorted_black
119
+ 8) almost_invisible
120
+ Default style is 'simply_blue'.
121
+ You can also specify 'random' to select the random image style.
122
+
123
+ * *distortion* - handles the complexity of the image. The :distortion can be set to 'low', 'medium' or 'high'. Default is 'low'.
124
+
125
+ Create "rails_root/config/initializers/simple_captcha.rb"
126
+
127
+ SimpleCaptcha.setup do |sc|
128
+ # default: 100x28
129
+ sc.image_size = '120x40'
130
+
131
+ # default: 5
132
+ sc.length = 6
133
+
134
+ # default: simply_blue
135
+ # possible values:
136
+ # 'embosed_silver',
137
+ # 'simply_red',
138
+ # 'simply_green',
139
+ # 'simply_blue',
140
+ # 'distorted_black',
141
+ # 'all_black',
142
+ # 'charcoal_grey',
143
+ # 'almost_invisible'
144
+ # 'random'
145
+ sc.image_style = 'simply_green'
146
+
147
+ # default: low
148
+ # possible values: 'low', 'medium', 'high', 'random'
149
+ sc.distortion = 'medium'
150
+ end
151
+
152
+ You can add your own style:
153
+
154
+ SimpleCaptcha.setup do |sc|
155
+ sc.image_style = 'mycaptha'
156
+ sc.add_image_style('mycaptha', [
157
+ "-background '#F4F7F8'",
158
+ "-fill '#86818B'",
159
+ "-border 1",
160
+ "-bordercolor '#E0E2E3'"])
161
+ end
162
+
163
+ You can provide the path where image_magick is installed as well:
164
+
165
+ SimpleCaptcha.setup do |sc|
166
+ sc.image_magick_path = '/usr/bin' # you can check this from console by running: which convert
167
+ end
168
+
169
+ You can provide the path where should be stored tmp files.
170
+ It's usefull when you dont have acces to /tmp (default directory)
171
+
172
+ SimpleCaptcha.setup do |sc|
173
+ sc.tmp_path = '/tmp' # or somewhere in project eg. Rails.root.join('tmp/simple_captcha').to_s, make shure directory exists
174
+ end
175
+
176
+
177
+ ===How to change the CSS for SimpleCaptcha DOM elements?
178
+ You can change the CSS of the SimpleCaptcha DOM elements as per your need in this file.
179
+ /app/views/simple_captcha/_simple_captcha.erb
180
+
181
+ ===View's Examples
182
+ ====Controller Based Example
183
+
184
+ <%= show_simple_captcha %>
185
+
186
+ <%= show_simple_captcha(:label => "human authentication") %>
187
+
188
+ ====Model Based Example
189
+
190
+ <%= show_simple_captcha(:object => 'user', :label => "human authentication") %>
191
+
192
+ ====Model Options
193
+
194
+ * *message* - provides the custom message on failure of captcha authentication the default is "Secret Code did not match with the Image"
195
+
196
+ * *add_to_base* - if set to true, appends the error message to the base.
197
+
198
+ =====Model's Example
199
+
200
+ class User < ActiveRecord::Base
201
+ apply_simple_captcha
202
+ end
203
+
204
+ class User < ActiveRecord::Base
205
+ apply_simple_captcha :message => "The secret Image and code were different", :add_to_base => true
206
+ end
207
+
208
+ ==I18n
209
+
210
+ simple_captcha:
211
+ placeholder: "Enter the image value"
212
+ label: "Enter the code in the box:"
213
+ message:
214
+ default: "Secret Code did not match with the Image"
215
+ user: "The secret Image and code were different"
216
+
217
+ ==Contributing
218
+
219
+ For testing, generate a temporary Rails dummy app inside test:
220
+
221
+ rake dummy:setup
222
+ rake app:db:migrate
223
+ rake app:db:migrate RAILS_ENV=test
224
+ export BUNDLE_GEMFILE=$PWD/Gemfile
225
+ cd test/dummy && rake db:migrate db:test:prepare
226
+ rake test
227
+
228
+ Please add test cases when adding new functionality. I started with some basic example integration tests for a very basic coverage.
229
+
230
+ ==Who's who?
231
+
232
+ Enjoy the simplest captcha implementation.
233
+
234
+ Author: Sur
235
+
236
+ Blog: http://expressica.com
237
+
238
+ Contact: sur.max@gmail.com
239
+
240
+ Plugin Homepage: http://expressica.com/simple_captcha
241
+
242
+ Plugin update for rails 3: http://github.com/galetahub
243
+
244
+ Any feedback/comment/issue/donation is welcome!
@@ -0,0 +1,54 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'SimpleCaptcha'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ if File.exists? APP_RAKEFILE
19
+ load 'rails/tasks/engine.rake'
20
+ end
21
+
22
+ namespace :dummy do
23
+ desc 'Setup dummy Rails app for test purpose'
24
+ task :setup do
25
+ require 'rails'
26
+ require 'simple_captcha'
27
+ require File.expand_path('../test/lib/generators/simple_captcha/dummy/dummy_generator', __FILE__)
28
+ SimpleCaptcha::DummyGenerator.start %w(--quiet)
29
+ end
30
+
31
+ desc 'destroy dummy Rails app under test/dummy'
32
+ task :destroy do
33
+ FileUtils.rm_rf "test/dummy" if File.exists?("test/dummy")
34
+ end
35
+
36
+ end
37
+
38
+
39
+
40
+
41
+ Bundler::GemHelper.install_tasks :name => 'simple_captcha2'
42
+
43
+ require 'rake/testtask'
44
+
45
+ Rake::TestTask.new(:test) do |t|
46
+ t.libs << 'lib'
47
+ t.libs << 'test'
48
+ t.pattern = 'test/**/*_test.rb'
49
+ t.verbose = false
50
+ end
51
+
52
+
53
+ task default: :test
54
+
@@ -0,0 +1,4 @@
1
+ SimplaCaptcha
2
+ =============
3
+ # Generate migration and copy view partial
4
+ rails generate simple_captcha
@@ -0,0 +1,21 @@
1
+ require 'rails/generators'
2
+
3
+ class SimpleCaptchaGenerator < Rails::Generators::Base
4
+ include Rails::Generators::Migration
5
+
6
+ def self.source_root
7
+ @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates/'))
8
+ end
9
+
10
+ def self.next_migration_number(dirname)
11
+ Time.now.strftime("%Y%m%d%H%M%S")
12
+ end
13
+
14
+ def create_partial
15
+ template "partial.erb", File.join('app/views', 'simple_captcha', "_simple_captcha.erb")
16
+ end
17
+
18
+ def create_migration
19
+ migration_template "migration.rb", File.join('db/migrate', "create_simple_captcha_data.rb")
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ class CreateSimpleCaptchaData < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :simple_captcha_data do |t|
4
+ t.string :key, :limit => 40
5
+ t.string :value, :limit => 6
6
+ t.timestamps
7
+ end
8
+
9
+ add_index :simple_captcha_data, :key, :name => "idx_key"
10
+ end
11
+
12
+ def self.down
13
+ drop_table :simple_captcha_data
14
+ end
15
+ end
@@ -0,0 +1,37 @@
1
+ <style type="text/CSS">
2
+ .simple_captcha{border: 1px solid #ccc; padding: 5px !important;}
3
+ .simple_captcha,
4
+ .simple_captcha div{display: table;}
5
+ .simple_captcha .simple_captcha_field,
6
+ .simple_captcha .simple_captcha_image{
7
+ border: 1px solid #ccc;
8
+ margin: 0px 0px 2px 0px !important;
9
+ padding: 0px !important;
10
+ }
11
+ .simple_captcha .simple_captcha_image img{
12
+ margin: 0px !important;
13
+ padding: 0px !important;
14
+ width: 110px !important;
15
+ }
16
+ .simple_captcha .simple_captcha_label{font-size: 12px;}
17
+ .simple_captcha .simple_captcha_field input{
18
+ width: 150px !important;
19
+ font-size: 16px;
20
+ border: none;
21
+ background-color: #efefef;
22
+ }
23
+ </style>
24
+
25
+ <div class='simple_captcha'>
26
+ <div class='simple_captcha_image'>
27
+ <%%= simple_captcha_options[:image] %>
28
+ </div>
29
+
30
+ <div class='simple_captcha_field'>
31
+ <%%= simple_captcha_options[:field] %>
32
+ </div>
33
+
34
+ <div class='simple_captcha_label'>
35
+ <%%= simple_captcha_options[:label] %>
36
+ </div>
37
+ </div>
@@ -0,0 +1,66 @@
1
+ # encoding: utf-8
2
+
3
+ module SimpleCaptcha
4
+ class << self
5
+ attr_accessor :always_pass
6
+ end
7
+ self.always_pass = Rails.env.test?
8
+ autoload :Utils, 'simple_captcha/utils'
9
+
10
+ autoload :ImageHelpers, 'simple_captcha/image'
11
+ autoload :ViewHelper, 'simple_captcha/view'
12
+ autoload :ControllerHelpers, 'simple_captcha/controller'
13
+
14
+ autoload :FormBuilder, 'simple_captcha/form_builder'
15
+ autoload :CustomFormBuilder, 'simple_captcha/formtastic'
16
+
17
+ if defined?(ActiveRecord)
18
+ autoload :ModelHelpers, 'simple_captcha/active_record'
19
+ autoload :SimpleCaptchaData, 'simple_captcha/simple_captcha_data'
20
+ else
21
+ autoload :SimpleCaptchaData, 'simple_captcha/simple_captcha_data_mongoid.rb'
22
+ end
23
+
24
+
25
+ autoload :Middleware, 'simple_captcha/middleware'
26
+
27
+ mattr_accessor :image_size
28
+ @@image_size = "100x28"
29
+
30
+ mattr_accessor :length
31
+ @@length = 5
32
+
33
+ # 'embosed_silver',
34
+ # 'simply_red',
35
+ # 'simply_green',
36
+ # 'simply_blue',
37
+ # 'distorted_black',
38
+ # 'all_black',
39
+ # 'charcoal_grey',
40
+ # 'almost_invisible'
41
+ # 'random'
42
+ mattr_accessor :image_style
43
+ @@image_style = 'simply_blue'
44
+
45
+ # 'low', 'medium', 'high', 'random'
46
+ mattr_accessor :distortion
47
+ @@distortion = 'low'
48
+
49
+ # command path
50
+ mattr_accessor :image_magick_path
51
+ @@image_magick_path = ''
52
+
53
+ # tmp directory
54
+ mattr_accessor :tmp_path
55
+ @@tmp_path = nil
56
+
57
+ def self.add_image_style(name, params = [])
58
+ SimpleCaptcha::ImageHelpers.image_styles.update(name.to_s => params)
59
+ end
60
+
61
+ def self.setup
62
+ yield self
63
+ end
64
+ end
65
+
66
+ require 'simple_captcha/engine' if defined?(Rails)
@@ -0,0 +1,74 @@
1
+ module SimpleCaptcha #:nodoc
2
+ module ModelHelpers #:nodoc
3
+ def self.included(base)
4
+ base.extend(SingletonMethods)
5
+ end
6
+
7
+ # To implement model based simple captcha use this method in the model as...
8
+ #
9
+ # class User < ActiveRecord::Base
10
+ #
11
+ # apply_simple_captcha :message => "my customized message"
12
+ #
13
+ # end
14
+ #
15
+ # Customize the error message by using :message, the default message is "Captcha did not match".
16
+ # As in the applications captcha is needed with a very few cases like signing up the new user, but
17
+ # not every time you need to authenticate the captcha with @user.save. So as to maintain simplicity
18
+ # here we have the explicit method to save the instace with captcha validation as...
19
+ #
20
+ # * to validate the instance
21
+ #
22
+ # @user.valid_with_captcha? # whene captcha validation is required.
23
+ #
24
+ # @user.valid? # when captcha validation is not required.
25
+ #
26
+ # * to save the instance
27
+ #
28
+ # @user.save_with_captcha # whene captcha validation is required.
29
+ #
30
+ # @user.save # when captcha validation is not required.
31
+ module SingletonMethods
32
+ def apply_simple_captcha(options = {})
33
+ options = { :add_to_base => false }.merge(options)
34
+
35
+ class_attribute :simple_captcha_options
36
+ self.simple_captcha_options = options
37
+
38
+ unless self.is_a?(ClassMethods)
39
+ include InstanceMethods
40
+ extend ClassMethods
41
+
42
+ attr_accessor :captcha, :captcha_key
43
+ end
44
+ end
45
+ end
46
+
47
+ module ClassMethods
48
+ end
49
+
50
+ module InstanceMethods
51
+
52
+ def valid_with_captcha?
53
+ [valid?, is_captcha_valid?].all?
54
+ end
55
+
56
+ def is_captcha_valid?
57
+ return true if SimpleCaptcha.always_pass
58
+
59
+ if captcha && captcha.upcase.delete(" ") == SimpleCaptcha::Utils::simple_captcha_value(captcha_key)
60
+ SimpleCaptcha::Utils::simple_captcha_passed!(captcha_key)
61
+ return true
62
+ else
63
+ message = simple_captcha_options[:message] || I18n.t(self.class.model_name.to_s.downcase, :scope => [:simple_captcha, :message], :default => :default)
64
+ simple_captcha_options[:add_to_base] ? errors.add(:base, message) : errors.add(:captcha, message)
65
+ return false
66
+ end
67
+ end
68
+
69
+ def save_with_captcha
70
+ valid_with_captcha? && save(:validate => false)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,29 @@
1
+ module SimpleCaptcha #:nodoc
2
+ module ControllerHelpers #:nodoc
3
+ # This method is to validate the simple captcha in controller.
4
+ # It means when the captcha is controller based i.e. :object has not been passed to the method show_simple_captcha.
5
+ #
6
+ # *Example*
7
+ #
8
+ # If you want to save an object say @user only if the captcha is validated then do like this in action...
9
+ #
10
+ # if simple_captcha_valid?
11
+ # @user.save
12
+ # else
13
+ # flash[:notice] = "captcha did not match"
14
+ # redirect_to :action => "myaction"
15
+ # end
16
+ def simple_captcha_valid?
17
+ return true if SimpleCaptcha.always_pass
18
+
19
+ if params[:captcha]
20
+ data = SimpleCaptcha::Utils::simple_captcha_value(params[:captcha_key] || session[:captcha])
21
+ result = data == params[:captcha].delete(" ").upcase
22
+ SimpleCaptcha::Utils::simple_captcha_passed!(session[:captcha]) if result
23
+ return result
24
+ else
25
+ return false
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ require 'rails'
3
+ require 'simple_captcha'
4
+
5
+ module SimpleCaptcha
6
+ class Engine < ::Rails::Engine
7
+ config.before_initialize do
8
+ ActiveSupport.on_load :active_record do
9
+ ActiveRecord::Base.send(:include, SimpleCaptcha::ModelHelpers)
10
+ end
11
+ end
12
+
13
+ config.after_initialize do
14
+ ActionView::Base.send(:include, SimpleCaptcha::ViewHelper)
15
+ ActionView::Helpers::FormBuilder.send(:include, SimpleCaptcha::FormBuilder)
16
+
17
+ if Object.const_defined?("Formtastic")
18
+ require 'simple_captcha/formtastic'
19
+ end
20
+ end
21
+
22
+ config.app_middleware.use SimpleCaptcha::Middleware
23
+ end
24
+ end
25
+
26
+
@@ -0,0 +1,43 @@
1
+ module SimpleCaptcha
2
+ module FormBuilder
3
+ def self.included(base)
4
+ base.send(:include, SimpleCaptcha::ViewHelper)
5
+ base.send(:include, SimpleCaptcha::FormBuilder::ClassMethods)
6
+ base.send(:include, ActionView::Helpers)
7
+ if defined? Sprockets::Helpers
8
+ base.send(:include, Sprockets::Helpers::RailsHelper)
9
+ base.send(:include, Sprockets::Helpers::IsolatedHelper)
10
+ end
11
+
12
+ base.delegate :render, :session, :to => :template
13
+ end
14
+
15
+ module ClassMethods
16
+ # Example:
17
+ # <% form_for :post, :url => posts_path do |form| %>
18
+ # ...
19
+ # <%= form.simple_captcha :label => "Enter numbers.." %>
20
+ # <% end %>
21
+ #
22
+ def simple_captcha(options = {})
23
+ options.update :object => @object_name
24
+ show_simple_captcha(objectify_options(options))
25
+ end
26
+
27
+ private
28
+
29
+ def template
30
+ @template
31
+ end
32
+
33
+ def simple_captcha_field(options={})
34
+ html = {:autocomplete => 'off', :required => 'required', :value => ''}
35
+ html.merge!(options[:input_html] || {})
36
+ html[:placeholder] = options[:placeholder] || I18n.t('simple_captcha.placeholder')
37
+
38
+ text_field(:captcha, html) +
39
+ hidden_field(:captcha_key, {:value => options[:field_value]})
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,15 @@
1
+ if defined? Formtastic
2
+ require 'formtastic/version'
3
+ if Formtastic::VERSION < '2.2'
4
+ raise 'Only Formtastic Version 2.2 or greater is supported by SimpleCaptcha'
5
+ end
6
+
7
+ class SimpleCaptchaInput
8
+ include Formtastic::Inputs::Base
9
+ def to_html
10
+ options.update :object => sanitized_object_name
11
+ builder.send(:show_simple_captcha, options)
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,86 @@
1
+ require 'tempfile'
2
+ module SimpleCaptcha #:nodoc
3
+ module ImageHelpers #:nodoc
4
+
5
+ mattr_accessor :image_styles
6
+ @@image_styles = {
7
+ 'embosed_silver' => ['-fill darkblue', '-shade 20x60', '-background white'],
8
+ 'simply_red' => ['-fill darkred', '-background white'],
9
+ 'simply_green' => ['-fill darkgreen', '-background white'],
10
+ 'simply_blue' => ['-fill darkblue', '-background white'],
11
+ 'distorted_black' => ['-fill darkblue', '-edge 10', '-background white'],
12
+ 'all_black' => ['-fill darkblue', '-edge 2', '-background white'],
13
+ 'charcoal_grey' => ['-fill darkblue', '-charcoal 5', '-background white'],
14
+ 'almost_invisible' => ['-fill red', '-solarize 50', '-background white']
15
+ }
16
+
17
+ DISTORTIONS = ['low', 'medium', 'high']
18
+
19
+ class << self
20
+
21
+ def image_params(key = 'simply_blue')
22
+ image_keys = @@image_styles.keys
23
+
24
+ style = begin
25
+ if key == 'random'
26
+ image_keys[rand(image_keys.length)]
27
+ else
28
+ image_keys.include?(key) ? key : 'simply_blue'
29
+ end
30
+ end
31
+
32
+ @@image_styles[style]
33
+ end
34
+
35
+ def distortion(key='low')
36
+ key =
37
+ key == 'random' ?
38
+ DISTORTIONS[rand(DISTORTIONS.length)] :
39
+ DISTORTIONS.include?(key) ? key : 'low'
40
+ case key.to_s
41
+ when 'low' then return [0 + rand(2), 80 + rand(20)]
42
+ when 'medium' then return [2 + rand(2), 50 + rand(20)]
43
+ when 'high' then return [4 + rand(2), 30 + rand(20)]
44
+ end
45
+ end
46
+ end
47
+
48
+ if RUBY_VERSION < '1.9'
49
+ class Tempfile < ::Tempfile
50
+ # Replaces Tempfile's +make_tmpname+ with one that honors file extensions.
51
+ def make_tmpname(basename, n = 0)
52
+ extension = File.extname(basename)
53
+ sprintf("%s,%d,%d%s", File.basename(basename, extension), $$, n, extension)
54
+ end
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def generate_simple_captcha_image(simple_captcha_key) #:nodoc
61
+ amplitude, frequency = ImageHelpers.distortion(SimpleCaptcha.distortion)
62
+ text = Utils::simple_captcha_value(simple_captcha_key)
63
+
64
+ params = ImageHelpers.image_params(SimpleCaptcha.image_style).dup
65
+ params << "-size #{SimpleCaptcha.image_size}"
66
+ params << "-wave #{amplitude}x#{frequency}"
67
+ #params << "-gravity 'Center'"
68
+ params << "-gravity \"Center\""
69
+ params << "-pointsize 22"
70
+ params << "-implode 0.2"
71
+
72
+ dst = Tempfile.new(RUBY_VERSION < '1.9' ? 'simple_captcha.jpg' : ['simple_captcha', '.jpg'], SimpleCaptcha.tmp_path)
73
+ dst.binmode
74
+
75
+ #params << "label:#{text} '#{File.expand_path(dst.path)}'"
76
+ params << "label:#{text} \"#{File.expand_path(dst.path)}\""
77
+
78
+ SimpleCaptcha::Utils::run("convert", params.join(' '))
79
+
80
+ dst.close
81
+
82
+ File.expand_path(dst.path)
83
+ #dst
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,58 @@
1
+ # encoding: utf-8
2
+ module SimpleCaptcha
3
+ class Middleware
4
+ include SimpleCaptcha::ImageHelpers
5
+
6
+ DEFAULT_SEND_FILE_OPTIONS = {
7
+ :type => 'application/octet-stream'.freeze,
8
+ :disposition => 'attachment'.freeze,
9
+ }.freeze
10
+
11
+ def initialize(app, options={})
12
+ @app = app
13
+ self
14
+ end
15
+
16
+ def call(env) # :nodoc:
17
+ if env["REQUEST_METHOD"] == "GET" && captcha_path?(env['PATH_INFO'])
18
+ make_image(env)
19
+ else
20
+ @app.call(env)
21
+ end
22
+ end
23
+
24
+ protected
25
+ def make_image(env, headers = {}, status = 404)
26
+ request = Rack::Request.new(env)
27
+ code = request.params["code"]
28
+ body = []
29
+
30
+ if !code.blank? && Utils::simple_captcha_value(code)
31
+ #status, headers, body = @app.call(env)
32
+ #status = 200
33
+ #body = generate_simple_captcha_image(code)
34
+ #headers['Content-Type'] = 'image/jpeg'
35
+
36
+ return send_file(generate_simple_captcha_image(code), :type => 'image/jpeg', :disposition => 'inline', :filename => 'simple_captcha.jpg')
37
+ end
38
+
39
+ [status, headers, body]
40
+ end
41
+
42
+ def captcha_path?(request_path)
43
+ request_path.include?('/simple_captcha')
44
+ end
45
+
46
+ def send_file(path, options = {})
47
+ raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)
48
+
49
+ options[:filename] ||= File.basename(path) unless options[:url_based_filename]
50
+
51
+ status = options[:status] || 200
52
+ headers = {"Content-Disposition" => "#{options[:disposition]}; filename='#{options[:filename]}'", "Content-Type" => options[:type], 'Content-Transfer-Encoding' => 'binary', 'Cache-Control' => 'private'}
53
+ response_body = File.open(path, "rb")
54
+
55
+ [status, headers, response_body]
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,32 @@
1
+ module SimpleCaptcha
2
+ class SimpleCaptchaData < ::ActiveRecord::Base
3
+
4
+ if ::ActiveRecord::VERSION::MAJOR >= 3
5
+ # Fixes deprecation warning in Rails 3.2:
6
+ # DEPRECATION WARNING: Calling set_table_name is deprecated. Please use `self.table_name = 'the_name'` instead.
7
+ self.table_name = "simple_captcha_data"
8
+ else
9
+ set_table_name "simple_captcha_data"
10
+ end
11
+ if ::ActiveRecord::VERSION::MAJOR == 3 and defined? attr_protected
12
+ attr_protected
13
+ end
14
+
15
+
16
+ class << self
17
+ def get_data(key)
18
+ where(key: key).first || new(key: key)
19
+ end
20
+
21
+ def remove_data(key)
22
+ delete_all(["#{connection.quote_column_name(:key)} = ?", key])
23
+ clear_old_data(1.hour.ago)
24
+ end
25
+
26
+ def clear_old_data(time = 1.hour.ago)
27
+ return unless Time === time
28
+ delete_all(["#{connection.quote_column_name(:updated_at)} < ?", time])
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ module SimpleCaptcha
2
+ class SimpleCaptchaData
3
+ include Mongoid::Document
4
+ include Mongoid::Timestamps
5
+
6
+ field :key, type: String
7
+ field :value, type: String
8
+
9
+ class << self
10
+ def get_data(key)
11
+ data = where(:key => key).first || new(:key => key)
12
+ end
13
+
14
+ def remove_data(key)
15
+ where(:key => key).delete_all
16
+ clear_old_data(1.hour.ago)
17
+ end
18
+
19
+ def clear_old_data(time = 1.hour.ago)
20
+ return unless Time === time
21
+ where(:updated_at.lte => time).delete_all
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ require 'digest/sha1'
2
+
3
+ module SimpleCaptcha #:nodoc
4
+ module Utils #:nodoc
5
+ # Execute command with params and return output if exit status equal expected_outcodes
6
+ def self.run(cmd, params = "", expected_outcodes = 0)
7
+ command = %Q[#{cmd} #{params}].gsub(/\s+/, " ")
8
+ command = "#{command} 2>&1"
9
+
10
+ unless (image_magick_path = SimpleCaptcha.image_magick_path).blank?
11
+ command = File.join(image_magick_path, command)
12
+ end
13
+
14
+ output = `#{command}`
15
+
16
+ unless [expected_outcodes].flatten.include?($?.exitstatus)
17
+ raise ::StandardError, "Error while running #{cmd}: #{output}"
18
+ end
19
+
20
+ output
21
+ end
22
+
23
+ def self.simple_captcha_value(key) #:nodoc
24
+ SimpleCaptchaData.get_data(key).value rescue nil
25
+ end
26
+
27
+ def self.simple_captcha_passed!(key) #:nodoc
28
+ SimpleCaptchaData.remove_data(key)
29
+ end
30
+
31
+ def self.generate_key(*args)
32
+ args << Time.now.to_s
33
+ Digest::SHA1.hexdigest(args.join)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleCaptcha
2
+ VERSION = "0.2.0".freeze
3
+ end
@@ -0,0 +1,115 @@
1
+ module SimpleCaptcha #:nodoc
2
+ module ViewHelper #:nodoc
3
+
4
+ # Simple Captcha is a very simplified captcha.
5
+ #
6
+ # It can be used as a *Model* or a *Controller* based Captcha depending on what options
7
+ # we are passing to the method show_simple_captcha.
8
+ #
9
+ # *show_simple_captcha* method will return the image, the label and the text box.
10
+ # This method should be called from the view within your form as...
11
+ #
12
+ # <%= show_simple_captcha %>
13
+ #
14
+ # The available options to pass to this method are
15
+ # * label
16
+ # * object
17
+ #
18
+ # <b>Label:</b>
19
+ #
20
+ # default label is "type the text from the image", it can be modified by passing :label as
21
+ #
22
+ # <%= show_simple_captcha(:label => "new captcha label") %>.
23
+ #
24
+ # *Object*
25
+ #
26
+ # This option is needed to create a model based captcha.
27
+ # If this option is not provided, the captcha will be controller based and
28
+ # should be checked in controller's action just by calling the method simple_captcha_valid?
29
+ #
30
+ # To make a model based captcha give this option as...
31
+ #
32
+ # <%= show_simple_captcha(:object => "user") %>
33
+ # and also call the method apply_simple_captcha in the model
34
+ # this will consider "user" as the object of the model class.
35
+ #
36
+ # *Examples*
37
+ # * controller based
38
+ # <%= show_simple_captcha(:label => "Human Authentication: type the text from image above") %>
39
+ # * model based
40
+ # <%= show_simple_captcha(:object => "person", :label => "Human Authentication: type the text from image above") %>
41
+ #
42
+ # Find more detailed examples with sample images here on my blog http://EXPRESSICA.com
43
+ #
44
+ # All Feedbacks/CommentS/Issues/Queries are welcome.
45
+ def show_simple_captcha(options={})
46
+ key = simple_captcha_key(options[:object])
47
+ options[:field_value] = set_simple_captcha_data(key, options)
48
+
49
+ defaults = {
50
+ :image => simple_captcha_image(key, options),
51
+ :label => options[:label] || I18n.t('simple_captcha.label'),
52
+ :field => simple_captcha_field(options)
53
+ }
54
+
55
+ render :partial => 'simple_captcha/simple_captcha', :locals => { :simple_captcha_options => defaults }
56
+ end
57
+
58
+ private
59
+
60
+ def simple_captcha_image(simple_captcha_key, options = {})
61
+ defaults = {}
62
+ defaults[:time] = options[:time] || Time.now.to_i
63
+
64
+ query = defaults.collect{ |key, value| "#{key}=#{value}" }.join('&')
65
+ url = "#{ENV['RAILS_RELATIVE_URL_ROOT']}/simple_captcha?code=#{simple_captcha_key}&#{query}"
66
+
67
+ tag('img', :src => url, :alt => 'captcha')
68
+ end
69
+
70
+ def simple_captcha_field(options={})
71
+ html = {:autocomplete => 'off', :required => 'required'}
72
+ html.merge!(options[:input_html] || {})
73
+ html[:placeholder] = options[:placeholder] || I18n.t('simple_captcha.placeholder')
74
+
75
+ if options[:object]
76
+ text_field(options[:object], :captcha, html.merge(:value => '')) +
77
+ hidden_field(options[:object], :captcha_key, {:value => options[:field_value]})
78
+ else
79
+ text_field_tag(:captcha, nil, html) +
80
+ hidden_field_tag(:captcha_key, options[:field_value])
81
+ end
82
+ end
83
+
84
+ def set_simple_captcha_data(key, options={})
85
+ code_type = options[:code_type]
86
+
87
+ value = generate_simple_captcha_data(code_type)
88
+ data = SimpleCaptcha::SimpleCaptchaData.get_data(key)
89
+ data.value = value
90
+ data.save
91
+ key
92
+ end
93
+
94
+ def generate_simple_captcha_data(code)
95
+ value = ''
96
+
97
+ case code
98
+ when 'numeric' then
99
+ SimpleCaptcha.length.times{value << (48 + rand(10)).chr}
100
+ else
101
+ SimpleCaptcha.length.times{value << (65 + rand(26)).chr}
102
+ end
103
+
104
+ return value
105
+ end
106
+
107
+ def simple_captcha_key(key_name = nil)
108
+ if key_name.nil?
109
+ session[:captcha] ||= SimpleCaptcha::Utils.generate_key(session[:id].to_s, 'captcha')
110
+ else
111
+ SimpleCaptcha::Utils.generate_key(session[:id].to_s, key_name)
112
+ end
113
+ end
114
+ end
115
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_captcha2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Pavlo Galeta
8
+ - Igor Galeta
9
+ - Stefan Wienert
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-12-01 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rails
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '3.1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - '>='
27
+ - !ruby/object:Gem::Version
28
+ version: '3.1'
29
+ - !ruby/object:Gem::Dependency
30
+ name: sqlite3
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: capybara-mechanize
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: pry
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ description: SimpleCaptcha is available to be used with Rails 3 + 4 or above and also
72
+ it provides the backward compatibility with previous versions of Rails.
73
+ email: stwienert@gmail.com
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files:
77
+ - README.rdoc
78
+ files:
79
+ - lib/generators/templates/migration.rb
80
+ - lib/generators/templates/partial.erb
81
+ - lib/generators/USAGE
82
+ - lib/generators/simple_captcha_generator.rb
83
+ - lib/simple_captcha.rb
84
+ - lib/simple_captcha/engine.rb
85
+ - lib/simple_captcha/active_record.rb
86
+ - lib/simple_captcha/controller.rb
87
+ - lib/simple_captcha/middleware.rb
88
+ - lib/simple_captcha/simple_captcha_data_mongoid.rb
89
+ - lib/simple_captcha/simple_captcha_data.rb
90
+ - lib/simple_captcha/utils.rb
91
+ - lib/simple_captcha/form_builder.rb
92
+ - lib/simple_captcha/image.rb
93
+ - lib/simple_captcha/view.rb
94
+ - lib/simple_captcha/formtastic.rb
95
+ - lib/simple_captcha/version.rb
96
+ - Rakefile
97
+ - README.rdoc
98
+ homepage: http://github.com/pludoni/simple-captcha
99
+ licenses: []
100
+ metadata: {}
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 2.0.3
118
+ signing_key:
119
+ specification_version: 4
120
+ summary: SimpleCaptcha is the simplest and a robust captcha plugin.
121
+ test_files: []