kandr-easy_captcha 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
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