kandr-easy_captcha 0.9.1 → 0.9.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11bebd70d6cf9b22081b0ff6c38f481109f020b99b1103302a0471b018b3b864
4
- data.tar.gz: 46596fd88348b900b684fd38c4fb5990d0222ff61e73c94bb48cd72911977be0
3
+ metadata.gz: 6a9098d3c82557be66d9f3769ef7a815d1bea207b9b0de7931cde92c5289766e
4
+ data.tar.gz: 4df8b4194f3e77b338e1193f8f0973da28cdcf52c332beee4dfbca1338a21bbe
5
5
  SHA512:
6
- metadata.gz: 1c0faf3191fa7552525afd84bcfd2dd8fe649fba50ea5c2baad551a13018fce093a16d6e9aafe04b392ec617cf7985cac5dc2bd2b34ccc461d8a96166ddcbd11
7
- data.tar.gz: be513a62747ac506cbd861ae7498d27c729ef0002e349d119d6631f5fc9d511d925bc90174d3561f06c21d9d5f1646d5e47bdd723bcd764c24af1e7285c11589
6
+ metadata.gz: 1f103d10c86ebd21a5e7c2e364d63c3a58d84276e225b03d499498f929d742ca304ea6b53af277de01aa8ffb56b1af7d2ceb8defbec730b32cd3b11d88add2ae
7
+ data.tar.gz: 9050a9ba91f71fc3a4990b84ba013604539add8a3ad291e5a9ef73a8e21d08d4e68f6b9c289e75bb531ddc56037fa60338c743019f1e57f3cb77eec46a150c62
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails'
4
+ require 'action_controller'
5
+ require 'active_record'
6
+ require 'active_support'
7
+
8
+ # Captcha-Plugin for Rails
9
+ module EasyCaptcha
10
+ autoload :Espeak, 'easy_captcha/espeak'
11
+ autoload :Captcha, 'easy_captcha/captcha'
12
+ autoload :CaptchaController, 'easy_captcha/captcha_controller'
13
+ autoload :ModelHelpers, 'easy_captcha/model_helpers'
14
+ autoload :ViewHelpers, 'easy_captcha/view_helpers'
15
+ autoload :ControllerHelpers, 'easy_captcha/controller_helpers'
16
+ autoload :Generator, 'easy_captcha/generator'
17
+
18
+ DEFAULT_CONFIG = {
19
+ cache: false,
20
+ cache_expire: nil,
21
+ cache_temp_dir: nil,
22
+ cache_size: 500,
23
+ captcha_character_pool: %w[2 3 4 5 6 7 9 A C D E F G H J K L M N P Q R S T U X Y Z],
24
+ captcha_character_count: 6,
25
+ captcha_image_height: 40,
26
+ captcha_image_width: 140
27
+ }.freeze
28
+
29
+ # Cache
30
+ mattr_accessor :cache
31
+
32
+ # Cache temp
33
+ mattr_accessor :cache_temp_dir
34
+
35
+ # Cache size
36
+ mattr_accessor :cache_size
37
+
38
+ # Cache expire
39
+ mattr_accessor :cache_expire
40
+
41
+ # Chars
42
+ mattr_accessor :captcha_character_pool
43
+
44
+ # Length
45
+ mattr_accessor :captcha_character_count
46
+
47
+ # Image dimensions
48
+ mattr_accessor :captcha_image_height, :captcha_image_width
49
+
50
+ class << self
51
+ # to configure easy_captcha
52
+ # for a sample look the readme.rdoc file
53
+ def setup
54
+ DEFAULT_CONFIG.map do |k, v|
55
+ send("#{k}=", v) if respond_to? "#{k}=".to_sym
56
+ end
57
+ yield self if block_given?
58
+ end
59
+
60
+ def cache? #:nodoc:
61
+ cache
62
+ end
63
+
64
+ # select generator and configure this
65
+ def generator(generator = nil, &block)
66
+ resolve_generator(generator, &block) unless generator.nil?
67
+ @generator
68
+ end
69
+
70
+ def espeak=(state)
71
+ @espeak = state.is_a?(TrueClass) ? Espeak.new : false
72
+ end
73
+
74
+ def espeak(&block)
75
+ @espeak = Espeak.new(&block) if block_given?
76
+ @espeak ||= false
77
+ end
78
+
79
+ def espeak?
80
+ !espeak.is_a?(FalseClass)
81
+ end
82
+
83
+ def init
84
+ require 'easy_captcha/routes'
85
+ ActiveRecord::Base.include ModelHelpers
86
+ ActionController::Base.include ControllerHelpers
87
+ ActionView::Base.include ViewHelpers
88
+
89
+ # set default generator
90
+ generator :default
91
+ end
92
+
93
+ private
94
+
95
+ def resolve_generator(generator, &block)
96
+ generator = generator.to_s if generator.is_a? Symbol
97
+ if generator.is_a? String
98
+ generator.gsub!(/^[a-z]|\s+[a-z]/, &:upcase)
99
+ generator = "EasyCaptcha::Generator::#{generator}".constantize
100
+ end
101
+ @generator = generator.new(&block)
102
+ end
103
+ end
104
+ end
105
+
106
+ EasyCaptcha.init
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyCaptcha
4
+ # captcha generation class
5
+ class Captcha
6
+ # code for captcha generation
7
+ attr_reader :code
8
+ # blob of generated captcha image
9
+ attr_reader :image
10
+
11
+ # generate captcha by code
12
+ def initialize(code)
13
+ @code = code
14
+ generate_captcha
15
+ end
16
+
17
+ def inspect #:nodoc:
18
+ "<EasyCaptcha::Captcha @code=#{code}>"
19
+ end
20
+
21
+ private
22
+
23
+ def generate_captcha #:nodoc:
24
+ @image = EasyCaptcha.generator.generate(@code)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyCaptcha
4
+ # captcha controller
5
+ class CaptchaController < ActionController::Base
6
+ before_action :overwrite_cache_control
7
+
8
+ # send the generated image to browser
9
+ def captcha
10
+ if (params[:format] == 'wav') && EasyCaptcha.espeak?
11
+ send_data(generate_speech_captcha, disposition: 'inline', type: 'audio/wav')
12
+ else
13
+ send_data(generate_captcha, disposition: 'inline', type: 'image/png')
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ # Overwrite cache control for Samsung Galaxy S3 (remove no-store)
20
+ def overwrite_cache_control
21
+ response.headers['Cache-Control'] = 'no-cache, max-age=0, must-revalidate'
22
+ response.headers['Pragma'] = 'no-cache'
23
+ response.headers['Expires'] = 'Fri, 01 Jan 1990 00:00:00 GMT'
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyCaptcha
4
+ # rubocop:disable Metrics/ModuleLength
5
+ # helper class for ActionController
6
+ module ControllerHelpers
7
+ def self.included(base) #:nodoc:
8
+ base.class_eval do
9
+ helper_method :valid_captcha?, :captcha_valid?
10
+ end
11
+ end
12
+
13
+ # generate captcha image and return it as blob
14
+ def generate_captcha
15
+ Rails.logger.info("#{Time.now}: generate_captcha in EasyCaptcha. params: #{params}.")
16
+ # create image
17
+ image = generate_captcha_image
18
+ # cache image
19
+ cache_image(image) if EasyCaptcha.cache
20
+ # return image
21
+ image
22
+ end
23
+
24
+ # generate speech by captcha from session
25
+ def generate_speech_captcha
26
+ fail 'espeak disabled' unless EasyCaptcha.espeak?
27
+ if EasyCaptcha.cache && cache_audio_file_exists?
28
+ load_cache_audio_file
29
+ else
30
+ new_audio_captcha_file
31
+ end
32
+ end
33
+
34
+ # return cache path of captcha image
35
+ def captcha_cache_path
36
+ "#{EasyCaptcha.cache_temp_dir}/#{current_captcha_code}.png"
37
+ end
38
+
39
+ # return cache path of speech captcha
40
+ def speech_captcha_cache_path
41
+ "#{EasyCaptcha.cache_temp_dir}/#{current_captcha_code}.wav"
42
+ end
43
+
44
+ # current active captcha from session
45
+ def current_captcha_code
46
+ session[:captcha] ||= generate_captcha_code
47
+ end
48
+
49
+ # generate captcha code, save in session and return
50
+ # rubocop:disable Metrics/AbcSize, Naming/MemoizedInstanceVariableName
51
+ def generate_captcha_code
52
+ @captcha_code ||= begin
53
+ length = EasyCaptcha.captcha_character_count
54
+ # overwrite `current_captcha_code`
55
+ session[:captcha] = Array.new(length) { EasyCaptcha.captcha_character_pool.sample }.join
56
+ Rails.logger.info(
57
+ "#{Time.now}: generate_captcha_code in EasyCaptcha. " \
58
+ "session[:captcha]: #{session[:captcha]} " \
59
+ "length: #{length}, " \
60
+ "original length: #{EasyCaptcha.captcha_character_count} " \
61
+ "chars count: #{EasyCaptcha.captcha_character_pool.size}."
62
+ )
63
+ session[:captcha]
64
+ end
65
+ end
66
+ # rubocop:enable Metrics/AbcSize, Naming/MemoizedInstanceVariableName
67
+
68
+ # validate given captcha code
69
+ def captcha_valid?(code)
70
+ return false if session[:captcha].to_s.blank? || code.to_s.blank?
71
+ session[:captcha].to_s == code.to_s
72
+ end
73
+ alias_method :valid_captcha?, :captcha_valid?
74
+
75
+ def captcha_invalid?(code)
76
+ !captcha_valid?(code)
77
+ end
78
+ alias_method :invalid_captcha?, :captcha_invalid?
79
+
80
+ # reset the captcha code in session for security after each request
81
+ def reset_last_captcha_code!
82
+ session.delete(:captcha)
83
+ end
84
+
85
+ private
86
+
87
+ def ensure_cache_dir
88
+ # create cache dir
89
+ FileUtils.mkdir_p(EasyCaptcha.cache_temp_dir)
90
+ end
91
+
92
+ def cached_captcha_files
93
+ ensure_cache_dir
94
+ # select all generated captcha image files from cache
95
+ Dir.glob("#{EasyCaptcha.cache_temp_dir}*.png")
96
+ end
97
+
98
+ # Grab random file from the cached files, return its file data
99
+ # rubocop:disable Metrics/AbcSize
100
+ def chose_image_from_cache
101
+ cache_files = cached_captcha_files
102
+
103
+ return nil if cache_files.size < EasyCaptcha.cache_size
104
+
105
+ file = File.open(cache_files.samlpe)
106
+ session[:captcha] = File.basename(file.path, '.*')
107
+
108
+ if file.mtime < EasyCaptcha.cache_expire.ago
109
+ # remove expired cached image
110
+ remove_cached_image_file(file)
111
+ # return nil
112
+ session[:captcha] = nil
113
+ else
114
+ # return file data from cache
115
+ file.readlines.join
116
+ end
117
+ end
118
+ # rubocop:enable Metrics/AbcSize
119
+
120
+ def remove_cached_image_file(file)
121
+ File.unlink(file.path)
122
+ # remove speech version
123
+ audio_file = file.path.gsub(/png\z/, 'wav')
124
+ File.unlink(audio_file) if File.exist?(audio_file)
125
+ end
126
+
127
+ def cache_image(image)
128
+ code = current_captcha_code
129
+ # write captcha for caching
130
+ File.open(captcha_cache_path(code), 'w') { |f| f.write image }
131
+ # write speech file if u create a new captcha image
132
+ EasyCaptcha.espeak.generate(code, speech_captcha_cache_path(code)) if EasyCaptcha.espeak?
133
+ end
134
+
135
+ def generate_captcha_image
136
+ if EasyCaptcha.cache
137
+ image = chose_image_from_cache
138
+ return image if image
139
+ end
140
+ # Default, if cache not enabled or an expired cache image was chosen, make a new one
141
+ Captcha.new(current_captcha_code).image
142
+ end
143
+
144
+ def load_cache_audio_file
145
+ File.read(speech_captcha_cache_path)
146
+ end
147
+
148
+ def new_audio_captcha_file
149
+ wav_file = Tempfile.new("#{current_captcha_code}.wav")
150
+ EasyCaptcha.espeak.generate(current_captcha_code, wav_file.path)
151
+ File.read(wav_file.path)
152
+ end
153
+
154
+ def cache_audio_file_exists?
155
+ File.exist?(speech_captcha_cache_path)
156
+ end
157
+ end
158
+ # rubocop:enable Metrics/ModuleLength
159
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyCaptcha
4
+ # espeak wrapper
5
+ class Espeak
6
+ DEFAULT_CONFIG = {
7
+ amplitude: 80..120,
8
+ pitch: 30..70,
9
+ gap: 80,
10
+ voice: nil
11
+ }.freeze
12
+
13
+ attr_writer :amplitude, :pitch, :gap, :voice
14
+
15
+ # generator for captcha images
16
+ def initialize
17
+ set_defaults
18
+ yield self if block_given?
19
+ end
20
+
21
+ # set default values
22
+ def set_defaults
23
+ DEFAULT_CONFIG.map do |k, v|
24
+ send("#{k}=", v) if respond_to? "#{k}=".to_sym
25
+ end
26
+ end
27
+
28
+ # return amplitude
29
+ def amplitude
30
+ @amplitude.is_a?(Range) ? @amplitude.to_a.sample : @amplitude.to_i
31
+ end
32
+
33
+ # return amplitude
34
+ def pitch
35
+ @pitch.is_a?(Range) ? @pitch.to_a.sample : @pitch.to_i
36
+ end
37
+
38
+ def gap
39
+ @gap.to_i
40
+ end
41
+
42
+ def voice
43
+ (@voice.is_a?(Array) ? @voice.sample : @voice).try(:gsub, /[^A-Za-z0-9\-+]/, '')
44
+ end
45
+
46
+ # generate wav file by captcha
47
+ def generate(captcha, wav_file)
48
+ cmd = [
49
+ 'espeak -g 10',
50
+ espeak_amplitude_param,
51
+ espeak_pitch_param,
52
+ espeak_gap_param,
53
+ espeak_voice_param,
54
+ "-w #{wav_file}",
55
+ "'#{get_code(captcha)}'"
56
+ ].compact.join(' ')
57
+
58
+ `#{cmd}`
59
+ true
60
+ end
61
+
62
+ def espeak_amplitude_param
63
+ "-a #{amplitude}" unless @amplitude.nil?
64
+ end
65
+
66
+ def espeak_pitch_param
67
+ "-p #{pitch}" unless @pitch.nil?
68
+ end
69
+
70
+ def espeak_gap_param
71
+ "-g #{gap}" unless @gap.nil?
72
+ end
73
+
74
+ def espeak_voice_param
75
+ "-v '#{voice}'" unless @voice.nil?
76
+ end
77
+
78
+ def get_code(captcha)
79
+ case captcha
80
+ when Captcha
81
+ code = captcha.code
82
+ when String
83
+ code = captcha
84
+ else
85
+ fail ArgumentError, 'invalid captcha'
86
+ end
87
+ # add spaces
88
+ code.each_char.to_a.join(' ')
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyCaptcha
4
+ # module for generators
5
+ module Generator
6
+ autoload :Base, 'easy_captcha/generator/base'
7
+ autoload :Default, 'easy_captcha/generator/default'
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyCaptcha
4
+ module Generator
5
+ # base class for generators
6
+ class Base
7
+ # generator for captcha images
8
+ def initialize
9
+ defaults
10
+ yield self if block_given?
11
+ end
12
+
13
+ # default values for generator
14
+ def defaults; end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,199 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rmagick'
4
+
5
+ # EasyCaptcha module
6
+ module EasyCaptcha
7
+ # Generator submodule
8
+ module Generator
9
+ # rubocop:disable Metrics/ClassLength
10
+ # default generator
11
+ class Default < Base
12
+ DEFAULT_CONFIG = {
13
+ background_image: nil,
14
+ blur: true,
15
+ blur_radius: 1,
16
+ blur_sigma: 2,
17
+ font: File.expand_path('../../../resources/captcha.ttf', __dir__),
18
+ font_fill_color: '#333333',
19
+ font_size: 24,
20
+ font_stroke: 0,
21
+ font_stroke_color: '#000000',
22
+ image_background_color: '#FFFFFF',
23
+ implode: 0.05,
24
+ sketch: true,
25
+ sketch_radius: 3,
26
+ sketch_sigma: 1,
27
+ wave: true,
28
+ wave_amplitude: (3..5),
29
+ wave_length: (60..100)
30
+ }.freeze
31
+
32
+ # set default values
33
+ def defaults
34
+ DEFAULT_CONFIG.map do |k, v|
35
+ send("#{k}=", v)
36
+ end
37
+ end
38
+
39
+ # Gaussian Blur
40
+ attr_accessor :blur, :blur_radius, :blur_sigma
41
+
42
+ # Font
43
+ attr_accessor :font_size, :font_fill_color, :font, :font_family, :font_stroke, :font_stroke_color
44
+
45
+ # Background
46
+ attr_accessor :image_background_color, :background_image
47
+
48
+ # Implode
49
+ attr_accessor :implode
50
+
51
+ # Sketch
52
+ attr_accessor :sketch, :sketch_radius, :sketch_sigma
53
+
54
+ # Wave
55
+ attr_accessor :wave, :wave_length, :wave_amplitude
56
+
57
+ # The CAPTCHA code
58
+ attr_reader :code
59
+
60
+ # The CAPTCHA image
61
+ attr_reader :image
62
+
63
+ def blur? #:nodoc:
64
+ @blur
65
+ end
66
+
67
+ def sketch? #:nodoc:
68
+ @sketch
69
+ end
70
+
71
+ def wave? #:nodoc:
72
+ @wave
73
+ end
74
+
75
+ # generate image
76
+ def generate(code)
77
+ @code = code
78
+ render_code_in_image
79
+ apply_blur
80
+ apply_wave
81
+ apply_sketch
82
+ apply_implode
83
+ apply_crop
84
+ create_blob
85
+ set_image_encoding
86
+ free_canvas
87
+ @image
88
+ end
89
+
90
+ def create_blob
91
+ @image = begin
92
+ if generator_config.background_image.present?
93
+ create_composite_blob
94
+ else
95
+ canvas.to_blob { self.format = 'PNG' }
96
+ end
97
+ end
98
+ end
99
+
100
+ def create_composite_blob
101
+ # Background Random Position
102
+ gravity = [
103
+ Magick::CenterGravity,
104
+ Magick::EastGravity,
105
+ Magick::NorthEastGravity,
106
+ Magick::NorthGravity,
107
+ Magick::NorthWestGravity,
108
+ Magick::SouthGravity,
109
+ Magick::SouthEastGravity,
110
+ Magick::SouthWestGravity,
111
+ Magick::WestGravity
112
+ ].sample
113
+
114
+ background = Magick::Image.read(generator_config.background_image).first
115
+ background.composite!(canvas, gravity, Magick::OverCompositeOp)
116
+ background = background.crop(gravity, EasyCaptcha.captcha_image_width, EasyCaptcha.captcha_image_height)
117
+ background.to_blob { self.format = 'PNG' }
118
+ end
119
+
120
+ def set_image_encoding
121
+ @image = image.force_encoding 'UTF-8' if image.respond_to? :force_encoding
122
+ end
123
+
124
+ def free_canvas
125
+ @canvas.destroy! if canvas.respond_to?('destroy!')
126
+ end
127
+
128
+ private
129
+
130
+ def apply_blur
131
+ return unless blur?
132
+ @canvas = canvas.blur_image(generator_config.blur_radius, generator_config.blur_sigma)
133
+ end
134
+
135
+ def apply_crop
136
+ # Crop image because to big after waveing
137
+ @canvas = canvas.crop(Magick::CenterGravity, EasyCaptcha.captcha_image_width, EasyCaptcha.captcha_image_height)
138
+ end
139
+
140
+ def apply_implode
141
+ @canvas = canvas.implode(generator_config.implode.to_f) if generator_config.implode.is_a? Float
142
+ end
143
+
144
+ def apply_sketch
145
+ return unless sketch? && canvas.respond_to?(:sketch)
146
+ @canvas = canvas.sketch(generator_config.sketch_radius, generator_config.sketch_sigma, rand(180))
147
+ end
148
+
149
+ def apply_wave
150
+ return unless wave?
151
+ @canvas = canvas.wave(random_wave_amplitude, random_wave_length)
152
+ end
153
+
154
+ def canvas
155
+ config = generator_config
156
+ @canvas = nil if @canvas.respond_to?('destroyed?') && @canvas.destroyed?
157
+ @canvas ||= Magick::Image.new(EasyCaptcha.captcha_image_width, EasyCaptcha.captcha_image_height) do |_variable|
158
+ self.background_color = config.image_background_color unless config.image_background_color.nil?
159
+ self.background_color = 'none' if config.background_image.present?
160
+ end
161
+ end
162
+
163
+ def generator_config
164
+ @generator_config ||= self
165
+ end
166
+
167
+ def random_wave_amplitude
168
+ rand(
169
+ generator_config.wave_amplitude.last - generator_config.wave_amplitude.first
170
+ ) + generator_config.wave_amplitude.first
171
+ end
172
+
173
+ def random_wave_length
174
+ rand(
175
+ generator_config.wave_length.last - generator_config.wave_length.first
176
+ ) + generator_config.wave_length.first
177
+ end
178
+
179
+ # rubocop:disable Metrics/AbcSize
180
+ def render_code_in_image
181
+ config = generator_config
182
+ # Render the text in the image
183
+ Magick::Draw.new.annotate(canvas, 0, 0, 0, 0, code.gsub(/%/, '\%')) do
184
+ self.gravity = Magick::CenterGravity
185
+ self.font = config.font
186
+ self.font_weight = Magick::LighterWeight
187
+ self.fill = config.font_fill_color
188
+ if config.font_stroke.to_i.positive?
189
+ self.stroke = config.font_stroke_color
190
+ self.stroke_width = config.font_stroke
191
+ end
192
+ self.pointsize = config.font_size
193
+ end
194
+ end
195
+ # rubocop:enable Metrics/AbcSize
196
+ end
197
+ # rubocop:enable Metrics/ClassLength
198
+ end
199
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyCaptcha
4
+ module ModelHelpers #:nodoc:
5
+ # helper class for ActiveRecord
6
+ def self.included(base) #:nodoc:
7
+ base.extend ClassMethods
8
+ end
9
+
10
+ module ClassMethods #:nodoc:
11
+ # to activate model captcha validation
12
+ def acts_as_easy_captcha
13
+ include InstanceMethods
14
+ attr_accessor :captcha, :captcha_verification
15
+ end
16
+ end
17
+
18
+ module InstanceMethods #:nodoc:
19
+ # validate captcha
20
+ def captcha_valid?
21
+ return true if captcha.present? && captcha_verification.present? && captcha_verification_match?
22
+ errors.add(:captcha, :invalid)
23
+ false
24
+ end
25
+ alias_method :valid_captcha?, :captcha_valid?
26
+
27
+ def captcha_verification_match?
28
+ captcha.to_s.casecmp(captcha_verification.to_s).zero?
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch #:nodoc:
4
+ module Routing #:nodoc:
5
+ class Mapper #:nodoc:
6
+ # call to add default captcha route
7
+ def captcha_route
8
+ get '/captcha' => 'easy_captcha/captcha#captcha', action: :captcha, as: :captcha
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyCaptcha
4
+ VERSION = '0.9.2'
5
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyCaptcha
4
+ # helper class for ActionView
5
+ module ViewHelpers
6
+ # generate an image_tag for captcha image
7
+ def captcha_tag(*args)
8
+ options = { alt: 'captcha', width: EasyCaptcha.captcha_image_width, height: EasyCaptcha.captcha_image_height }
9
+ options.merge! args.extract_options!
10
+ image_tag(captcha_path(i: Time.now.to_i), options)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyCaptcha
4
+ module Generators #:nodoc:
5
+ class InstallGenerator < Rails::Generators::Base #:nodoc:
6
+ source_root File.expand_path('../templates', __dir__)
7
+
8
+ desc 'Install easy_captcha'
9
+
10
+ def copy_initializer #:nodoc:
11
+ template 'easy_captcha.rb', 'config/initializers/easy_captcha.rb'
12
+ end
13
+
14
+ def add_devise_routes #:nodoc:
15
+ route 'captcha_route'
16
+ end
17
+
18
+ def add_after_filter #:nodoc:
19
+ inject_into_class 'app/controllers/application_controller.rb', ApplicationController do
20
+ " # reset captcha code after each request for security\n after_filter :reset_last_captcha_code!\n\n"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ EasyCaptcha.setup do |config|
4
+ # #####
5
+ # # Cache
6
+ # config.cache = true
7
+ # # Cache temp dir from Rails.root
8
+ # config.cache_temp_dir = Rails.root + 'tmp' + 'captchas'
9
+ # # Cache max number of images to cache
10
+ # config.cache_size = 500
11
+ # # Cache max length of time to cache an image
12
+ # config.cache_expire = 1.days
13
+ #
14
+ # #####
15
+ # # CAPTCHA
16
+ # # Chars available for CAPTCHA
17
+ # config.captcha_character_pool = %w(2 3 4 5 6 7 9 A C D E F G H J K L M N P Q R S T U X Y Z)
18
+ #
19
+ # # Length of CAPTCHA string
20
+ # config.captcha_character_count = 6
21
+ #
22
+ # # CAPTCHA Image dimensions
23
+ # config.captcha_image_height = 40
24
+ # config.captcha_image_width = 140
25
+
26
+ # #####
27
+ # # eSpeak
28
+ # # Enable eSpeak using all defaults:
29
+ # config.espeak = true
30
+ #
31
+ # # Enable eSpeak using custom config:
32
+ # config.espeak do |espeak|
33
+ # Amplitude, 0 to 200
34
+ # espeak.amplitude = 80..120
35
+ #
36
+ # Word gap. Pause between words
37
+ # espeak.gap = 80
38
+ #
39
+ # Pitch adjustment, 0 to 99
40
+ # espeak.pitch = 30..70
41
+ #
42
+ # Use voice file of this name from espeak-data/voices
43
+ # espeak.voice = nil
44
+ # end
45
+
46
+ # #####
47
+ # # Generator
48
+ # config.generator :default do |generator|
49
+ # # Blur
50
+ # generator.blur = true
51
+ # generator.blur_radius = 1
52
+ # generator.blur_sigma = 2
53
+ #
54
+ # # Font
55
+ # generator.font_family = File.expand_path('../../resources/afont.ttf', __FILE__)
56
+ # generator.font_fill_color = '#333333'
57
+ # generator.font_size = 24
58
+ # generator.font_stroke = 0
59
+ # generator.font_stroke_color = '#000000'
60
+ #
61
+ # # Image
62
+ # generator.image_background_color = "#FFFFFF"
63
+ #
64
+ # # Implode
65
+ # generator.implode = 0.1
66
+ #
67
+ # # Sketch
68
+ # generator.sketch = true
69
+ # generator.sketch_radius = 3
70
+ # generator.sketch_sigma = 1
71
+ #
72
+ # # Wave
73
+ # generator.wave = true
74
+ # generator.wave_amplitude = (3..5)
75
+ # generator.wave_length = (60..100)
76
+ # end
77
+ end
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kandr-easy_captcha
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marco Scholl
@@ -50,6 +50,21 @@ extra_rdoc_files:
50
50
  files:
51
51
  - LICENSE.txt
52
52
  - README.md
53
+ - lib/easy_captcha.rb
54
+ - lib/easy_captcha/captcha.rb
55
+ - lib/easy_captcha/captcha_controller.rb
56
+ - lib/easy_captcha/controller_helpers.rb
57
+ - lib/easy_captcha/espeak.rb
58
+ - lib/easy_captcha/generator.rb
59
+ - lib/easy_captcha/generator/base.rb
60
+ - lib/easy_captcha/generator/default.rb
61
+ - lib/easy_captcha/model_helpers.rb
62
+ - lib/easy_captcha/routes.rb
63
+ - lib/easy_captcha/version.rb
64
+ - lib/easy_captcha/view_helpers.rb
65
+ - lib/generators/easy_captcha/install_generator.rb
66
+ - lib/generators/templates/easy_captcha.rb
67
+ - resources/captcha.ttf
53
68
  - spec/easy_captcha/captcha_controller_spec.rb
54
69
  - spec/easy_captcha/captcha_spec.rb
55
70
  - spec/easy_captcha/controller_helpers_spec.rb
@@ -83,8 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
98
  - !ruby/object:Gem::Version
84
99
  version: 2.7.0
85
100
  requirements: []
86
- rubyforge_project:
87
- rubygems_version: 2.7.3
101
+ rubygems_version: 3.1.4
88
102
  signing_key:
89
103
  specification_version: 4
90
104
  summary: CAPTCHA Plugin for Rails