custom_captcha 0.1.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.
Files changed (40) hide show
  1. data/.gitignore +4 -0
  2. data/.rspec +1 -0
  3. data/CHANGELOG +4 -0
  4. data/Gemfile +4 -0
  5. data/Guardfile +22 -0
  6. data/README.markdown +107 -0
  7. data/Rakefile +2 -0
  8. data/app/controllers/custom_captcha/captcha_images_controller.rb +28 -0
  9. data/app/views/custom_captcha/captcha_images/change.html.erb +2 -0
  10. data/app/views/custom_captcha/captcha_images/change.js.erb +3 -0
  11. data/app/views/custom_captcha/captcha_images/show.html.erb +2 -0
  12. data/app/views/custom_captcha/captcha_styles/_default.html.erb +10 -0
  13. data/config/locales/custom_captcha.en.yml +6 -0
  14. data/config/routes.rb +9 -0
  15. data/custom_captcha.gemspec +31 -0
  16. data/lib/custom_captcha.rb +39 -0
  17. data/lib/custom_captcha/action_controller_extension.rb +42 -0
  18. data/lib/custom_captcha/action_view_extension.rb +56 -0
  19. data/lib/custom_captcha/active_record_extension.rb +51 -0
  20. data/lib/custom_captcha/common_methods.rb +13 -0
  21. data/lib/custom_captcha/configuration.rb +107 -0
  22. data/lib/custom_captcha/engine.rb +5 -0
  23. data/lib/custom_captcha/errors.rb +5 -0
  24. data/lib/custom_captcha/image.rb +86 -0
  25. data/lib/custom_captcha/railtie.rb +25 -0
  26. data/lib/custom_captcha/utils.rb +94 -0
  27. data/lib/custom_captcha/version.rb +4 -0
  28. data/lib/generators/custom_captcha/install/USAGE +8 -0
  29. data/lib/generators/custom_captcha/install/install_generator.rb +49 -0
  30. data/lib/generators/custom_captcha/install/templates/README +18 -0
  31. data/lib/generators/custom_captcha/uninstall/USAGE +8 -0
  32. data/lib/generators/custom_captcha/uninstall/templates/README +2 -0
  33. data/lib/generators/custom_captcha/uninstall/uninstall_generator.rb +38 -0
  34. data/lib/generators/custom_captcha/utils.rb +12 -0
  35. data/lib/tasks/.gitkeep +0 -0
  36. data/lib/tasks/custom_captcha_utils.rake +26 -0
  37. data/spec/configuration_spec.rb +19 -0
  38. data/spec/image_spec.rb +10 -0
  39. data/spec/spec_helper.rb +6 -0
  40. metadata +165 -0
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,4 @@
1
+ == 0.1.0
2
+
3
+ * First release
4
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
@@ -0,0 +1,22 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^spec/.+_spec\.rb$})
11
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
12
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
13
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
14
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
15
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
16
+ watch('spec/spec_helper.rb') { "spec" }
17
+ watch('config/routes.rb') { "spec/routing" }
18
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
19
+ # Capybara request specs
20
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
21
+ end
22
+
@@ -0,0 +1,107 @@
1
+ == CustomCaptcha
2
+
3
+ CustomCaptcha is a simple and custom captcha plugin for Rails3.
4
+
5
+
6
+ == Supported versions
7
+
8
+ * Ruby 1.8.7, 1.9.2, 1.9.3
9
+
10
+ * Rails 3.0.x, 3.1
11
+
12
+ * ImageMagick should be installed on your machine to use this plugin.
13
+
14
+
15
+ == Installation
16
+
17
+ In your app's `Gemfile`, add:
18
+
19
+ gem "custom_captcha", :git => "git://github.com/vkill/custom_captcha.git"
20
+
21
+ Then run:
22
+
23
+ bundle
24
+ rails generate custom_captcha:install
25
+
26
+ If you want to modify default captcha images storage location, edit your `config/initializers/custom_captcha.rb`
27
+
28
+ Then run:
29
+
30
+ bundle exec rake custom_captcha:generate_images[100]
31
+
32
+
33
+ == Base Usage
34
+
35
+ === View helper
36
+
37
+ In the view file within the form tags add this code
38
+
39
+ <%= display_custom_captcha %>
40
+
41
+ and in the controller's action authenticate it as
42
+
43
+ if custom_captcha_valid?(params[:custom_captcha])
44
+ flash[:notice] = "captcha did match."
45
+ else
46
+ flash[:notice] = "captcha did not match."
47
+ end
48
+
49
+ === FormBuilder helper
50
+
51
+ In the model class add this code
52
+
53
+ class User < ActiveRecord::Basse
54
+ apply_custom_captcha
55
+ end
56
+
57
+ and in the view file within the form tags write this code
58
+
59
+ <%= form_for @user do |form| -%>
60
+ ...
61
+ <%= form.custom_captcha %>
62
+ ...
63
+ <% end -%>
64
+
65
+
66
+ == Usage your custom captcha area template
67
+
68
+ first, copy and modify your custom captcha area template
69
+
70
+ cd app/views/custom_captcha/captcha_styles/
71
+ cp _default.html.erb _mycaptcha.html.erb
72
+
73
+ and then in the view file your the use of
74
+
75
+ <%= display_custom_captcha(:template => :mycaptcha) %>
76
+
77
+
78
+ == Options & Examples
79
+
80
+ === Helper Options, View helper and FormBuilder helper
81
+
82
+ * *template* - use your custom template
83
+
84
+ * *label_text* - custom label text
85
+
86
+ * *key_id* - custom captcha hidden input key id
87
+
88
+ * *key_name* - custom captcha hidden input key name
89
+
90
+ * *field_name* - custom captcha input field name
91
+
92
+ * *img_id* - custom captcha img id
93
+
94
+ * *change_text* - custom change text
95
+
96
+ === Examples
97
+
98
+ <%= display_custom_captcha(:img_id => :captcha, :label_text => "captcha", :field_name => :captcha %>
99
+
100
+
101
+ == I18n supported
102
+
103
+
104
+ == Copyright
105
+
106
+ Copyright (c) 2011 vkill.net .
107
+
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,28 @@
1
+ class CustomCaptcha::CaptchaImagesController < ApplicationController
2
+
3
+ respond_to :html, :js, :json
4
+
5
+ def show
6
+ @image_file_path = read_image_file_path(params[:key])
7
+ respond_to do |format|
8
+ format.html {
9
+ send_file(@image_file_path, :type => 'image/jpeg', :disposition => 'inline', :filename => 'custom_captcha.jpg')
10
+ }
11
+ format.json { render :json => {:image_file_path => @image_file_path} }
12
+ end
13
+ end
14
+
15
+ def change
16
+ @img_id = params[:img_id] || CustomCaptcha::DEFAULTVALUE[:img_id]
17
+ @key_id = params[:key_id] || CustomCaptcha::DEFAULTVALUE[:key_id]
18
+ @key = choice_image_file_path_and_write_session_cache()
19
+ @img_src = show_captcha_image_path(@key)
20
+
21
+ respond_to do |format|
22
+ format.js
23
+ format.json { render :json => {@img_id => @img_src, @key_id => @key} }
24
+ end
25
+ end
26
+
27
+ end
28
+
@@ -0,0 +1,2 @@
1
+ if you see this message, please mail to administrator!
2
+
@@ -0,0 +1,3 @@
1
+ $("img#<%= @img_id %>").attr("src", "<%= @img_src %>")
2
+ $("input#<%= @key_id %>").attr("value", "<%= @key %>")
3
+
@@ -0,0 +1,2 @@
1
+ if you see this message, please mail to administrator!
2
+
@@ -0,0 +1,10 @@
1
+ <br/>
2
+
3
+ <%= label_tag captcha[:label_text] %>
4
+ <%= text_field_tag captcha[:field_name] %>
5
+ <%= hidden_field_tag captcha[:key_name], captcha[:key], :id => captcha[:key_id] %>
6
+ <%= image_tag captcha[:img_src], :id => captcha[:img_id], :alt => captcha[:label_text] %>
7
+ <%= link_to captcha[:change_text], captcha[:change_url], :remote => true %>
8
+
9
+ <br/>
10
+
@@ -0,0 +1,6 @@
1
+ en:
2
+ custom_captcha:
3
+ label: "captcha"
4
+ change: "changing a picture"
5
+ message: "Secret Code did not match with the Image"
6
+
@@ -0,0 +1,9 @@
1
+ Rails.application.routes.draw do
2
+ match "captcha_images/change" => "custom_captcha/captcha_images#change",
3
+ :as => :change_captcha_images
4
+
5
+ match "captcha_images/:key" => "custom_captcha/captcha_images#show",
6
+ :as => :show_captcha_image,
7
+ :constraints => { :key => /[A-Za-z0-9]{32,40}/ }
8
+ end
9
+
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "custom_captcha/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "custom_captcha"
7
+ s.version = CustomCaptcha::VERSION
8
+ s.date = Date.today
9
+ s.authors = ["vkill"]
10
+ s.email = ["vkill.net@gmail.com"]
11
+ s.homepage = "https://github.com/vkill/custom_captcha"
12
+ s.summary = "A simple and custom captcha for Rails3."
13
+ s.description = "A simple and custom captcha for Rails3."
14
+
15
+ s.rubyforge_project = "custom_captcha"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_development_dependency 'bundler'
23
+ s.add_development_dependency "rake"
24
+ s.add_development_dependency "rspec"
25
+ s.add_development_dependency "guard-rspec"
26
+ s.add_dependency "rails", "~> 3.0"
27
+ s.add_dependency "rmagick", "~> 2.13.1"
28
+ s.add_dependency 'jquery-rails', "~> 1.0.16"
29
+
30
+ end
31
+
@@ -0,0 +1,39 @@
1
+ require "active_support/concern"
2
+ require "active_support/core_ext/object"
3
+ require "active_support/core_ext/class/attribute_accessors"
4
+ require "active_support/core_ext/module/attribute_accessors"
5
+ require "securerandom"
6
+ require "RMagick"
7
+ include Magick
8
+ require "tmpdir"
9
+ require "fileutils"
10
+ require "digest/md5"
11
+ require "find"
12
+
13
+ require 'custom_captcha/errors'
14
+ require 'custom_captcha/version'
15
+ require 'custom_captcha/configuration'
16
+ require 'custom_captcha/utils'
17
+ require 'custom_captcha/image'
18
+
19
+ require "rails"
20
+ require "custom_captcha/engine"
21
+ require "custom_captcha/railtie"
22
+
23
+ module CustomCaptcha
24
+ DEFAULTVALUE = {
25
+ :field_name => :custom_captcha,
26
+ :key_name => :custom_captcha_key,
27
+ :key_id => :custom_captcha_key,
28
+ :img_id => :custom_captcha_img,
29
+ :template => 'default'
30
+ }
31
+ class << self
32
+ def configure(&block)
33
+ CustomCaptcha::Configuration.configure(&block)
34
+ end
35
+ end
36
+ # init configuration
37
+ CustomCaptcha::Configuration.init_config()
38
+ end
39
+
@@ -0,0 +1,42 @@
1
+ module CustomCaptcha
2
+ module ActionControllerExtension
3
+ extend ActiveSupport::Concern
4
+ included do
5
+ include CustomCaptcha::CommonMethods
6
+ helper_method :choice_image_file_path_and_write_session_cache,
7
+ :read_captcha_digested, :read_image_file_path
8
+ end
9
+ module ClassMethods
10
+ end
11
+ module InstanceMethods
12
+ def custom_captcha_valid?(captcha_value=nil)
13
+ if CustomCaptcha::Configuration.disable? or Rails.env.test?
14
+ return true
15
+ end
16
+ captcha_value ||= params[CustomCaptcha::DEFAULTVALUE[:field_name]]
17
+ if captcha_value
18
+ CustomCaptcha::Utils.captcha_value_valid?(captcha_value, read_captcha_digested())
19
+ else
20
+ return false
21
+ end
22
+ end
23
+
24
+ def choice_image_file_path_and_write_session_cache
25
+ image_file_path, captcha_digested, key =
26
+ CustomCaptcha::Utils.choice_image_file_path_and_generate_captcha_digested_key
27
+ session[:captcha_digested] = captcha_digested
28
+ Rails.cache.write(key, [image_file_path, captcha_digested])
29
+ key
30
+ end
31
+
32
+ def read_captcha_digested
33
+ session[:captcha_digested]
34
+ end
35
+
36
+ def read_image_file_path(key)
37
+ Rails.cache.read(key)[0] rescue nil
38
+ end
39
+ end
40
+ end
41
+ end
42
+
@@ -0,0 +1,56 @@
1
+ module CustomCaptcha
2
+ module ActionViewExtension
3
+ module Base
4
+ extend ActiveSupport::Concern
5
+ included do
6
+ include CustomCaptcha::CommonMethods
7
+ end
8
+ module ClassMethods
9
+ end
10
+ module InstanceMethods
11
+ def display_custom_captcha(options={})
12
+ return "" if CustomCaptcha::Configuration.disable?
13
+ options[:key] = choice_image_file_path_and_write_session_cache
14
+
15
+ options[:field_name] ||= CustomCaptcha::DEFAULTVALUE[:field_name]
16
+ options[:key_name] ||= CustomCaptcha::DEFAULTVALUE[:key_name]
17
+ options[:key_id] ||= CustomCaptcha::DEFAULTVALUE[:key_id]
18
+ options[:img_id] ||= CustomCaptcha::DEFAULTVALUE[:img_id]
19
+
20
+ options[:img_src] = show_captcha_image_path(options[:key])
21
+ options[:template] ||= CustomCaptcha::DEFAULTVALUE[:template]
22
+ options[:label_text] ||= I18n.t('custom_captcha.label')
23
+ options[:change_text] ||= I18n.t('custom_captcha.change')
24
+ options[:change_url] = change_captcha_images_path(:img_id => options[:img_id], :key_id => options[:key_id])
25
+ render "custom_captcha/captcha_styles/#{options[:template].to_s}", :captcha => options
26
+ end
27
+ end
28
+ end
29
+
30
+ module Helpers
31
+ module FormBuilder
32
+ extend ActiveSupport::Concern
33
+ included do
34
+ include CustomCaptcha::CommonMethods
35
+ end
36
+ module ClassMethods
37
+ end
38
+ module InstanceMethods
39
+ def custom_captcha(options={})
40
+ return "" unless (@object.custom_captcha_key rescue nil)
41
+ options[:object_name] = @object_name.to_s
42
+ options[:key] = @object.custom_captcha_key
43
+
44
+ options[:field_name] = object_field_name options[:object_name], CustomCaptcha::DEFAULTVALUE[:field_name]
45
+ options[:key_name] = object_field_name options[:object_name], CustomCaptcha::DEFAULTVALUE[:key_name]
46
+ options[:key_id] = object_field_id options[:object_name], CustomCaptcha::DEFAULTVALUE[:key_id]
47
+ options[:img_id] = object_field_id options[:object_name], CustomCaptcha::DEFAULTVALUE[:img_id]
48
+
49
+ @template.display_custom_captcha(options)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+
@@ -0,0 +1,51 @@
1
+ module CustomCaptcha
2
+ module ActiveRecordExtension
3
+ extend ActiveSupport::Concern
4
+ included do
5
+ include CustomCaptcha::CommonMethods
6
+ extend ClassMethods
7
+ end
8
+ module ClassMethods
9
+ def apply_custom_captcha
10
+ attr_accessor :custom_captcha, :custom_captcha_key
11
+
12
+ after_initialize do
13
+ after_initialize if custom_captcha_need_valid?
14
+ end
15
+
16
+ validate :valid_custom_captcha, :if => :custom_captcha_need_valid?
17
+
18
+ include CustomCaptcha::ActiveRecordExtension::InstanceMethods
19
+ end
20
+ end
21
+ module InstanceMethods
22
+ def after_initialize
23
+ self.custom_captcha_key ||= choice_image_file_path_and_write_cache
24
+ end
25
+
26
+ def valid_custom_captcha
27
+ unless CustomCaptcha::Utils.captcha_value_valid?(custom_captcha, read_captcha_digested())
28
+ errors.add(:custom_captcha, I18n.t('custom_captcha.message'))
29
+ end
30
+ end
31
+
32
+ def custom_captcha_need_valid?
33
+ !CustomCaptcha::Configuration.disable? and !Rails.env.test?
34
+ end
35
+
36
+ private
37
+ def choice_image_file_path_and_write_cache
38
+ image_file_path, captcha_digested, key =
39
+ CustomCaptcha::Utils.choice_image_file_path_and_generate_captcha_digested_key
40
+ Rails.cache.write(key, [image_file_path, captcha_digested])
41
+ key
42
+ end
43
+
44
+ def read_captcha_digested
45
+ Rails.cache.read(self.custom_captcha_key)[1] rescue ""
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+
@@ -0,0 +1,13 @@
1
+ module CustomCaptcha
2
+ module CommonMethods
3
+ private
4
+ def object_field_name(object_name, field_name)
5
+ object_name.to_s + "[" + field_name.to_s + "]"
6
+ end
7
+
8
+ def object_field_id(object_name, field_name)
9
+ object_name.to_s + "_" + field_name.to_s
10
+ end
11
+ end
12
+ end
13
+
@@ -0,0 +1,107 @@
1
+ module CustomCaptcha
2
+ module Configuration
3
+
4
+ mattr_accessor :image_columns,
5
+ :image_rows,
6
+ :image_style,
7
+ :text_range,
8
+ :text_length,
9
+ :images_path,
10
+ :enable,
11
+ :salt
12
+ mattr_reader :images_path_definite
13
+
14
+ class << self
15
+
16
+ def configure
17
+ yield self
18
+ # make inage files path and defined @@images_path_definite
19
+ make_and_define_images_path()
20
+ # reload all image files key
21
+ CustomCaptcha::Utils.reload_image_files_paths()
22
+ end
23
+
24
+ def reset_config
25
+ configure do |config|
26
+ config.image_columns = default_image_columns()
27
+ config.image_rows = default_image_rows()
28
+ config.image_style = CustomCaptcha::Image.image_style.keys.first
29
+ config.text_range = default_text_range()
30
+ config.text_length = default_text_length()
31
+ config.images_path = default_images_path()
32
+ config.enable = true
33
+ config.salt = SecureRandom.hex(10)
34
+ end
35
+ make_and_define_images_path()
36
+ end
37
+ alias_method :init_config, :reset_config
38
+
39
+ def disable?
40
+ !@@enable
41
+ end
42
+
43
+ #image columns setting
44
+ def default_image_columns
45
+ 120
46
+ end
47
+ def image_columns
48
+ image_columns = @@image_columns.to_i.blank? ? default_image_columns() : @@image_columns
49
+ end
50
+
51
+ #image rows setting
52
+ def default_image_rows
53
+ 40
54
+ end
55
+ def image_rows
56
+ image_rows = @@image_rows.to_i.blank? ? default_image_rows() : @@image_rows
57
+ end
58
+
59
+ #image style setting
60
+ def default_image_style
61
+
62
+ end
63
+
64
+ #image text range setting
65
+ def default_text_range
66
+ ('a'..'z').to_a + (0..9).to_a
67
+ end
68
+ def text_range
69
+ text_range = @@text_range.to_a.blank? ? default_text_range() : @@text_range
70
+ end
71
+
72
+ #image text length setting
73
+ def default_text_length
74
+ 5
75
+ end
76
+ def text_length
77
+ text_length = @@text_length.to_i.blank? ? default_text_length() : @@text_length
78
+ if 4 < text_length or text_length < 10
79
+ text_length
80
+ else
81
+ default_text_length()
82
+ end
83
+ end
84
+
85
+ #images path setting
86
+ def default_images_path
87
+ File.join(Dir::tmpdir, 'captcha_images')
88
+ end
89
+ def images_path
90
+ images_path = @@images_path.to_s.blank? ? default_images_path() : @@images_path
91
+ end
92
+
93
+ #images path make and define
94
+ def make_and_define_images_path
95
+ images_path = images_path()
96
+ begin
97
+ FileUtils.mkdir_p images_path
98
+ rescue
99
+ raise CustomCaptcha::MakeImagePathError
100
+ else
101
+ @@images_path_definite = images_path
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+
@@ -0,0 +1,5 @@
1
+ module CustomCaptcha
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
5
+
@@ -0,0 +1,5 @@
1
+ module CustomCaptcha
2
+ class MakeImagePathError < StandardError; end
3
+ class InitImageFilesKeyError < StandardError; end
4
+ end
5
+
@@ -0,0 +1,86 @@
1
+ module CustomCaptcha
2
+ module Image
3
+ mattr_reader :image_style
4
+ @@image_style = {
5
+ :simply_blue => {:background_color => :white, :text_fill => :darkblue, :text_font_family => :helvetica}
6
+ }
7
+ #image text length and image text font_size proportion
8
+ @@font_size = {
9
+ 4 => 46,
10
+ 5 => 41,
11
+ 6 => 36,
12
+ 7 => 31,
13
+ 8 => 26,
14
+ 9 => 21,
15
+ 10 => 16
16
+ }
17
+
18
+ class << self
19
+ def create(number=1, &block)
20
+ image_style_simply_blue = @@image_style[:simply_blue]
21
+ image_style = @@image_style[CustomCaptcha::Configuration.image_style] || image_style_simply_blue
22
+ options = {}
23
+ options[:background_color] = image_style[:background_color] || image_style_simply_blue[:background_color]
24
+ options[:text_fill] = image_style[:text_fill] || image_style_simply_blue[:text_fill]
25
+ options[:text_font_family] = image_style[:text_font_family] || image_style_simply_blue[:text_font_family]
26
+ image_files = create_image_files(number, options, &block)
27
+ end
28
+ end
29
+
30
+ private
31
+ class << self
32
+ def generate_image_text
33
+ text_range = CustomCaptcha::Configuration.text_range
34
+ text_length = CustomCaptcha::Configuration.text_length
35
+ text_range.to_a.sort_by!{rand()}.take(text_length).join()
36
+ end
37
+
38
+ def generate_image_file_path(text)
39
+ File.join(
40
+ CustomCaptcha::Utils.image_file_dirname(),
41
+ [
42
+ CustomCaptcha::Utils.image_file_basename(text),
43
+ CustomCaptcha::Utils.image_file_extname()
44
+ ].join()
45
+ )
46
+ end
47
+
48
+ def create_image_files(number, options={}, &block)
49
+ columns = CustomCaptcha::Configuration.image_columns
50
+ rows = CustomCaptcha::Configuration.image_rows
51
+
52
+ image_files = []
53
+ number.to_i.times do |n|
54
+ canvas = Magick::ImageList.new
55
+ canvas.new_image(columns, rows) {
56
+ self.background_color = options[:background_color].to_s
57
+ }
58
+ text = Magick::Draw.new
59
+ text.font_family = options[:text_font_family].to_s
60
+ text.fill = options[:text_fill].to_s
61
+ text.gravity = Magick::CenterGravity
62
+
63
+ image_text = generate_image_text()
64
+ text.annotate(canvas, 0,0,0,0, image_text) {
65
+ self.pointsize = @@font_size[image_text.length]
66
+ }
67
+ image_file = generate_image_file_path(image_text)
68
+ begin
69
+ canvas.write(image_file)
70
+ rescue
71
+ yield(number, n+1, "failed", image_file) if block
72
+ next
73
+ else
74
+ yield(number, n+1, "succeed", image_file) if block
75
+ image_files << image_file
76
+ ensure
77
+ canvas.clear
78
+ end
79
+ end
80
+ image_files
81
+ end
82
+
83
+ end
84
+ end
85
+ end
86
+
@@ -0,0 +1,25 @@
1
+ require 'custom_captcha/common_methods'
2
+ require 'custom_captcha/action_controller_extension'
3
+ require 'custom_captcha/action_view_extension'
4
+ require 'custom_captcha/active_record_extension'
5
+
6
+ module CustomCaptcha
7
+ class Railtie < ::Rails::Railtie
8
+ initializer 'custom_captcha' do |app|
9
+ ActiveSupport.on_load :action_controller do
10
+ ActionController::Base.send :include, CustomCaptcha::ActionControllerExtension
11
+ end
12
+
13
+ ActiveSupport.on_load :action_view do
14
+ ActionView::Base.send :include, CustomCaptcha::ActionViewExtension::Base
15
+ ActionView::Helpers::FormBuilder.send :include,
16
+ CustomCaptcha::ActionViewExtension::Helpers::FormBuilder
17
+ end
18
+
19
+ ActiveSupport.on_load :active_record do
20
+ include CustomCaptcha::ActiveRecordExtension
21
+ end
22
+ end
23
+ end
24
+ end
25
+
@@ -0,0 +1,94 @@
1
+ module CustomCaptcha
2
+ module Utils
3
+
4
+ mattr_reader :image_files_paths, :image_files_paths_choice_size
5
+ @@image_files_paths = []
6
+ @@image_files_paths_choice_size = @@image_files_paths.size
7
+
8
+ class << self
9
+
10
+ def generate_image_files(number=1, &block)
11
+ CustomCaptcha::Image.create(number, &block)
12
+ end
13
+
14
+ def clear_image_files
15
+ FileUtils.rm_r Dir[File.join(image_file_dirname(), "**", "*")]
16
+ end
17
+
18
+ def reload_image_files_paths
19
+ @@image_files_paths.clear
20
+ reset_image_files_paths()
21
+ end
22
+ alias_method :init_image_files_paths, :reload_image_files_paths
23
+
24
+
25
+ def choice_image_file_path_and_generate_captcha_digested_key
26
+ image_file_path = random_choice_image_file_path
27
+ captcha_digested = get_captcha_digested(image_file_path)
28
+ key = hexdigest_text([Time.now.to_i, SecureRandom.hex(10)].join())
29
+ [image_file_path, captcha_digested, key]
30
+ end
31
+
32
+ def captcha_value_valid?(captcha_value, captcha_digested)
33
+ image_file_basename_suffix(captcha_value) == captcha_digested
34
+ end
35
+
36
+ end
37
+
38
+ private
39
+ class << self
40
+ def hexdigest_text(text)
41
+ Digest::MD5.hexdigest([text.to_s.downcase, CustomCaptcha::Configuration.salt].join())
42
+ end
43
+
44
+ def image_file_dirname
45
+ CustomCaptcha::Configuration.images_path_definite
46
+ end
47
+
48
+ def image_file_basename_prefix
49
+ # ("a".."z").to_a.sort_by!{rand()}.take(8).join()
50
+ SecureRandom.hex(4)
51
+ end
52
+
53
+ def image_file_basename_suffix(text)
54
+ hexdigest_text(text)
55
+ end
56
+
57
+ def image_file_basename(text)
58
+ [image_file_basename_prefix, image_file_basename_suffix(text)].join()
59
+ end
60
+
61
+ def image_file_extname
62
+ ".gif"
63
+ end
64
+
65
+ # if image file path empty, then auto generating 3 image file.
66
+ def reset_image_files_paths
67
+ if @@image_files_paths.blank? or @@image_files_paths_choice_size == 0
68
+ n = 0
69
+ while true
70
+ @@image_files_paths = Dir[File.join(image_file_dirname(), ["[a-z0-9]*", image_file_extname()].join())]
71
+ break unless self.image_files_paths.blank?
72
+ generate_image_files(3)
73
+ raise InitImageFilesKeyError if n >= 3
74
+ n += 1
75
+ end
76
+ @@image_files_paths.sort_by!{rand()}
77
+ @@image_files_paths_choice_size = @@image_files_paths.size
78
+ end
79
+ end
80
+
81
+ def random_choice_image_file_path
82
+ reset_image_files_paths()
83
+ @@image_files_paths_choice_size -= 1
84
+ @@image_files_paths[@@image_files_paths_choice_size]
85
+ end
86
+
87
+ def get_captcha_digested(image_file_path)
88
+ image_file_basename = File.basename(image_file_path, image_file_extname())
89
+ image_file_basename[-32..-1]
90
+ end
91
+ end
92
+ end
93
+ end
94
+
@@ -0,0 +1,4 @@
1
+ module CustomCaptcha
2
+ VERSION = "0.1.0"
3
+ end
4
+
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ rails generate install Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,49 @@
1
+ require File.expand_path('../../utils', __FILE__)
2
+
3
+ class CustomCaptcha::InstallGenerator < Rails::Generators::Base
4
+
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ include CustomCaptcha::Generators::Utils::InstanceMethods
8
+
9
+ desc "Creates CustomCaptcha initializer and copy locale files to your application."
10
+
11
+ def create_initializer
12
+ data_custom_captcha_rb = %Q/
13
+ CustomCaptcha.configure do |config|
14
+ config.image_columns = 120
15
+ config.image_rows = 40
16
+ config.image_style = "simply_blue"
17
+ config.text_range = ("a".."z").to_a
18
+ config.text_length = 5
19
+ config.images_path = Rails.root.join("public", "system", "captcha_images").to_s
20
+ config.enable = true
21
+ config.salt = "#{ SecureRandom.hex(20) }"
22
+ end
23
+ /
24
+ initializer "custom_captcha.rb", data_custom_captcha_rb
25
+ end
26
+
27
+ def create_locale
28
+ copy_file "../../../../../config/locales/custom_captcha.en.yml", "config/locales/custom_captcha.en.yml"
29
+ end
30
+
31
+ def create_views
32
+ filename_pattern = File.expand_path("../../../../../app/views/custom_captcha/captcha_styles/*", __FILE__)
33
+ Dir[filename_pattern].each do |f|
34
+ copy_file f, "app/views/custom_captcha/captcha_styles/#{File.basename f}"
35
+ end
36
+ end
37
+
38
+ def test_rakes
39
+ display "test generate and clear images..."
40
+ rake("custom_captcha:generate_images[1]")
41
+ rake("custom_captcha:clear_images")
42
+ end
43
+
44
+ def show_readme
45
+ display "Succeed! custom_captcha has been installed."
46
+ readme("README")
47
+ end
48
+ end
49
+
@@ -0,0 +1,18 @@
1
+ ===============================================================================
2
+
3
+ Some setup you must do manually:
4
+
5
+ 1. Modify captcha images directory in config/initializers/custom_captcha.rb.
6
+ For example:
7
+
8
+ config.images_path = Rails.root.join("public", "captcha_images").to_s
9
+
10
+ 2. Generate captcha images.
11
+
12
+ # bundle exec rake custom_captcha:generate_images[100]
13
+
14
+
15
+ Homepage: https://github.com/vkill/custom_captcha
16
+ by: vkill
17
+ ===============================================================================
18
+
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ rails generate uninstall Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,2 @@
1
+ Homepage: https://github.com/vkill/custom_captcha
2
+
@@ -0,0 +1,38 @@
1
+ require File.expand_path('../../utils', __FILE__)
2
+
3
+ class CustomCaptcha::UninstallGenerator < Rails::Generators::Base
4
+
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ include CustomCaptcha::Generators::Utils::InstanceMethods
8
+
9
+ desc "Remove CustomCaptcha initializer and remove locale files from your application."
10
+
11
+ def clear_images
12
+ rake("custom_captcha:clear_images")
13
+ end
14
+
15
+ def destroy_initializer
16
+ remove_file "config/initializers/custom_captcha.rb"
17
+ end
18
+
19
+ def destroy_locale
20
+ remove_file "config/locales/custom_captcha.en.yml"
21
+ end
22
+
23
+ def destroy_views
24
+ # filename_pattern = File.expand_path("../../../../../app/views/custom_captcha/captcha_styles/*", __FILE__)
25
+ # Dir[filename_pattern].each do |f|
26
+ # copy_file f, "app/views/custom_captcha/captcha_styles/#{File.basename f}"
27
+ # end
28
+ Dir["app/views/custom_captcha/captcha_styles/*"].each do |f|
29
+ remove_file f
30
+ end
31
+ end
32
+
33
+ def show_readme
34
+ display "Done! custom_captcha has been uninstalled."
35
+ readme("README")
36
+ end
37
+ end
38
+
@@ -0,0 +1,12 @@
1
+ module CustomCaptcha
2
+ module Generators
3
+ module Utils
4
+ module InstanceMethods
5
+ def display(output, color = :green)
6
+ say(" - #{output}", color)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
12
+
File without changes
@@ -0,0 +1,26 @@
1
+ #encoding: utf-8
2
+
3
+ require "rubygems"
4
+ require "bundler/setup"
5
+
6
+ require "custom_captcha"
7
+
8
+ namespace :custom_captcha do
9
+ desc "Generate {count} captcha images."
10
+ task :generate_images, [:count] => :environment do |t, args|
11
+ args.with_defaults(:count => 3)
12
+ count = args[:count].to_i
13
+ CustomCaptcha::Utils.generate_image_files(count) do |number, n, state, image_file|
14
+ puts " - [%s/%s] %s Generating %s" % [ n, number, state.capitalize!, image_file ]
15
+ end
16
+ end
17
+
18
+ desc "Clear captcha images."
19
+ task :clear_images => :environment do |t|
20
+ print "\r - Clearing captcha images..."
21
+ CustomCaptcha::Utils.clear_image_files()
22
+ print "done\n"
23
+ end
24
+
25
+ end
26
+
@@ -0,0 +1,19 @@
1
+ #encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe CustomCaptcha::Configuration do
5
+
6
+ it "should set a configuration" do
7
+ CustomCaptcha::Configuration.text_length.should == 5
8
+ CustomCaptcha.configure do |config|
9
+ config.text_length = 6
10
+ end
11
+ CustomCaptcha::Configuration.text_length.should == 6
12
+ end
13
+
14
+ it "should define images path and create images path" do
15
+ CustomCaptcha::Configuration.make_and_define_images_path()
16
+ File.exist?(CustomCaptcha::Configuration.images_path_definite).should be_true
17
+ end
18
+ end
19
+
@@ -0,0 +1,10 @@
1
+ #encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe CustomCaptcha::Image do
5
+
6
+ it "should create a image" do
7
+ CustomCaptcha::Image.create().should be_true
8
+ end
9
+ end
10
+
@@ -0,0 +1,6 @@
1
+ #encoding: utf-8
2
+
3
+ require "rubygems"
4
+ require "bundler/setup"
5
+ require "custom_captcha"
6
+
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: custom_captcha
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - vkill
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: &70249600 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70249600
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &70249330 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70249330
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &70249040 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70249040
47
+ - !ruby/object:Gem::Dependency
48
+ name: guard-rspec
49
+ requirement: &70248730 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70248730
58
+ - !ruby/object:Gem::Dependency
59
+ name: rails
60
+ requirement: &70248350 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: '3.0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *70248350
69
+ - !ruby/object:Gem::Dependency
70
+ name: rmagick
71
+ requirement: &70248000 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 2.13.1
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: *70248000
80
+ - !ruby/object:Gem::Dependency
81
+ name: jquery-rails
82
+ requirement: &70247670 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ version: 1.0.16
88
+ type: :runtime
89
+ prerelease: false
90
+ version_requirements: *70247670
91
+ description: A simple and custom captcha for Rails3.
92
+ email:
93
+ - vkill.net@gmail.com
94
+ executables: []
95
+ extensions: []
96
+ extra_rdoc_files: []
97
+ files:
98
+ - .gitignore
99
+ - .rspec
100
+ - CHANGELOG
101
+ - Gemfile
102
+ - Guardfile
103
+ - README.markdown
104
+ - Rakefile
105
+ - app/controllers/custom_captcha/captcha_images_controller.rb
106
+ - app/views/custom_captcha/captcha_images/change.html.erb
107
+ - app/views/custom_captcha/captcha_images/change.js.erb
108
+ - app/views/custom_captcha/captcha_images/show.html.erb
109
+ - app/views/custom_captcha/captcha_styles/_default.html.erb
110
+ - config/locales/custom_captcha.en.yml
111
+ - config/routes.rb
112
+ - custom_captcha.gemspec
113
+ - lib/custom_captcha.rb
114
+ - lib/custom_captcha/action_controller_extension.rb
115
+ - lib/custom_captcha/action_view_extension.rb
116
+ - lib/custom_captcha/active_record_extension.rb
117
+ - lib/custom_captcha/common_methods.rb
118
+ - lib/custom_captcha/configuration.rb
119
+ - lib/custom_captcha/engine.rb
120
+ - lib/custom_captcha/errors.rb
121
+ - lib/custom_captcha/image.rb
122
+ - lib/custom_captcha/railtie.rb
123
+ - lib/custom_captcha/utils.rb
124
+ - lib/custom_captcha/version.rb
125
+ - lib/generators/custom_captcha/install/USAGE
126
+ - lib/generators/custom_captcha/install/install_generator.rb
127
+ - lib/generators/custom_captcha/install/templates/README
128
+ - lib/generators/custom_captcha/uninstall/USAGE
129
+ - lib/generators/custom_captcha/uninstall/templates/README
130
+ - lib/generators/custom_captcha/uninstall/uninstall_generator.rb
131
+ - lib/generators/custom_captcha/utils.rb
132
+ - lib/tasks/.gitkeep
133
+ - lib/tasks/custom_captcha_utils.rake
134
+ - spec/configuration_spec.rb
135
+ - spec/image_spec.rb
136
+ - spec/spec_helper.rb
137
+ homepage: https://github.com/vkill/custom_captcha
138
+ licenses: []
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ none: false
145
+ requirements:
146
+ - - ! '>='
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ none: false
151
+ requirements:
152
+ - - ! '>='
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubyforge_project: custom_captcha
157
+ rubygems_version: 1.8.10
158
+ signing_key:
159
+ specification_version: 3
160
+ summary: A simple and custom captcha for Rails3.
161
+ test_files:
162
+ - spec/configuration_spec.rb
163
+ - spec/image_spec.rb
164
+ - spec/spec_helper.rb
165
+ has_rdoc: