tiny_captcha 0.0.1 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/app/controllers/tiny_captcha/application_controller.rb +1 -0
- data/app/controllers/tiny_captcha/images_controller.rb +21 -0
- data/app/helpers/tiny_captcha/application_helper.rb +1 -0
- data/config/locales/en/tiny_captcha.en.yml +9 -0
- data/config/locales/zh-CN/tiny_captcha.zh-CN.yml +8 -0
- data/config/routes.rb +4 -0
- data/lib/generators/USAGE +4 -0
- data/lib/generators/templates/migration.rb +16 -0
- data/lib/generators/templates/partial.erb +37 -0
- data/lib/generators/tiny_captcha_generator.rb +22 -0
- data/lib/tiny_captcha.rb +64 -1
- data/lib/tiny_captcha/active_record.rb +93 -0
- data/lib/tiny_captcha/controller.rb +58 -0
- data/lib/tiny_captcha/engine.rb +28 -1
- data/lib/tiny_captcha/form_builder.rb +43 -0
- data/lib/tiny_captcha/formtastic.rb +12 -0
- data/lib/tiny_captcha/image.rb +85 -0
- data/lib/tiny_captcha/middleware.rb +70 -0
- data/lib/tiny_captcha/tiny_captcha_data.rb +36 -0
- data/lib/tiny_captcha/tiny_captcha_data_mongoid.rb +26 -0
- data/lib/tiny_captcha/utils.rb +80 -0
- data/lib/tiny_captcha/version.rb +2 -1
- data/lib/tiny_captcha/view.rb +99 -0
- data/test/dummy/app/controllers/application_controller.rb +1 -0
- data/test/dummy/app/helpers/application_helper.rb +1 -0
- data/test/dummy/config/application.rb +1 -0
- data/test/dummy/config/boot.rb +1 -0
- data/test/dummy/config/environment.rb +1 -0
- data/test/dummy/config/environments/development.rb +1 -0
- data/test/dummy/config/environments/production.rb +1 -0
- data/test/dummy/config/environments/test.rb +1 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +1 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +1 -0
- data/test/dummy/config/initializers/inflections.rb +1 -0
- data/test/dummy/config/initializers/mime_types.rb +1 -0
- data/test/dummy/config/initializers/secret_token.rb +1 -0
- data/test/dummy/config/initializers/session_store.rb +1 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +1 -0
- data/test/dummy/config/routes.rb +1 -0
- data/test/integration/navigation_test.rb +1 -0
- data/test/test_helper.rb +1 -0
- data/test/tiny_captcha_test.rb +1 -0
- metadata +85 -82
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a7470acbf45a2f9152ed8f19180067c67714090e
|
4
|
+
data.tar.gz: 6a9fb11adfc2d802b7a2579be6d279d48e83ec6b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e4590af09ba5857c23fe31f597afeef564b461f90dcacfd3f93fa24f62acbaf99f08f1a28878f7760f8eb60b55e15b903885dfd84cb08805f5ecac018c376a7e
|
7
|
+
data.tar.gz: e88bfba0336b263b24f8f3b041b258e16e11e2897cfd334a23bca7565f7bd9e144b86aa1542a7cf91f42e873e08f5fef3759be525f3cf0ae157239f185f8b466
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module TinyCaptcha
|
3
|
+
class ImagesController < ::ActionController::Base
|
4
|
+
#
|
5
|
+
# params:
|
6
|
+
# - object
|
7
|
+
#
|
8
|
+
def new
|
9
|
+
@tiny_captcha_options = generate_tiny_captcha_options(:object => params[:object])
|
10
|
+
|
11
|
+
respond_to do |format|
|
12
|
+
format.json {
|
13
|
+
render :json => {
|
14
|
+
:tiny_captcha_options => @tiny_captcha_options
|
15
|
+
}
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
data/config/routes.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
class CreateTinyCaptchaData < ActiveRecord::Migration
|
3
|
+
def self.up
|
4
|
+
create_table :tiny_captcha_data do |t|
|
5
|
+
t.string :key, :limit => 40
|
6
|
+
t.string :value, :limit => 6
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
|
10
|
+
add_index :tiny_captcha_data, :key
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :tiny_captcha_data
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<style type="text/CSS">
|
2
|
+
.tiny_captcha{border: 1px solid #ccc; padding: 5px !important;}
|
3
|
+
.tiny_captcha,
|
4
|
+
.tiny_captcha div{display: table;}
|
5
|
+
.tiny_captcha .tiny_captcha_field,
|
6
|
+
.tiny_captcha .tiny_captcha_image{
|
7
|
+
border: 1px solid #ccc;
|
8
|
+
margin: 0px 0px 2px 0px !important;
|
9
|
+
padding: 0px !important;
|
10
|
+
}
|
11
|
+
.tiny_captcha .tiny_captcha_image img{
|
12
|
+
margin: 0px !important;
|
13
|
+
padding: 0px !important;
|
14
|
+
width: 110px !important;
|
15
|
+
}
|
16
|
+
.tiny_captcha .tiny_captcha_label{font-size: 12px;}
|
17
|
+
.tiny_captcha .tiny_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='tiny_captcha'>
|
26
|
+
<div class='tiny_captcha_image'>
|
27
|
+
<%%= tiny_captcha_options[:image] %>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<div class='tiny_captcha_field'>
|
31
|
+
<%%= tiny_captcha_options[:field] %>
|
32
|
+
</div>
|
33
|
+
|
34
|
+
<div class='tiny_captcha_label'>
|
35
|
+
<%%= tiny_captcha_options[:label] %>
|
36
|
+
</div>
|
37
|
+
</div>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'rails/generators'
|
3
|
+
|
4
|
+
class TinyCaptchaGenerator < Rails::Generators::Base
|
5
|
+
include Rails::Generators::Migration
|
6
|
+
|
7
|
+
def self.source_root
|
8
|
+
@source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates/'))
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.next_migration_number(dirname)
|
12
|
+
Time.now.strftime("%Y%m%d%H%M%S")
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_partial
|
16
|
+
template "partial.erb", File.join('app/views', 'tiny_captcha', "_tiny_captcha.erb")
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_migration
|
20
|
+
migration_template "migration.rb", File.join('db/migrate', "create_tiny_captcha_data.rb")
|
21
|
+
end
|
22
|
+
end
|
data/lib/tiny_captcha.rb
CHANGED
@@ -1,4 +1,67 @@
|
|
1
|
-
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
2
|
|
3
3
|
module TinyCaptcha
|
4
|
+
autoload :Utils, 'tiny_captcha/utils'
|
5
|
+
|
6
|
+
autoload :ImageHelpers, 'tiny_captcha/image'
|
7
|
+
autoload :ViewHelper, 'tiny_captcha/view'
|
8
|
+
autoload :ControllerHelpers, 'tiny_captcha/controller'
|
9
|
+
|
10
|
+
autoload :FormBuilder, 'tiny_captcha/form_builder'
|
11
|
+
autoload :CustomFormBuilder, 'tiny_captcha/formtastic'
|
12
|
+
|
13
|
+
if defined?(ActiveRecord)
|
14
|
+
autoload :ModelHelpers, 'tiny_captcha/active_record'
|
15
|
+
autoload :TinyCaptchaData, 'tiny_captcha/tiny_captcha_data'
|
16
|
+
else
|
17
|
+
autoload :TinyCaptchaData, 'tiny_captcha/tiny_captcha_data_mongoid.rb'
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
autoload :Middleware, 'tiny_captcha/middleware'
|
22
|
+
|
23
|
+
mattr_accessor :image_size
|
24
|
+
@@image_size = "100x28"
|
25
|
+
|
26
|
+
mattr_accessor :length
|
27
|
+
@@length = 6
|
28
|
+
|
29
|
+
# 'embosed_silver',
|
30
|
+
# 'simply_red',
|
31
|
+
# 'simply_green',
|
32
|
+
# 'simply_blue',
|
33
|
+
# 'distorted_black',
|
34
|
+
# 'all_black',
|
35
|
+
# 'charcoal_grey',
|
36
|
+
# 'almost_invisible'
|
37
|
+
# 'random'
|
38
|
+
mattr_accessor :image_style
|
39
|
+
@@image_style = 'simply_blue'
|
40
|
+
|
41
|
+
# 'low', 'medium', 'high', 'random'
|
42
|
+
mattr_accessor :distortion
|
43
|
+
@@distortion = 'low'
|
44
|
+
|
45
|
+
# command path
|
46
|
+
mattr_accessor :image_magick_path
|
47
|
+
@@image_magick_path = ''
|
48
|
+
|
49
|
+
# tmp directory
|
50
|
+
mattr_accessor :tmp_path
|
51
|
+
@@tmp_path = nil
|
52
|
+
|
53
|
+
mattr_accessor :image_show_path
|
54
|
+
@@image_show_path = '/tiny_captcha/images/show'
|
55
|
+
|
56
|
+
def self.add_image_style(name, params = [])
|
57
|
+
::TinyCaptcha::ImageHelpers.image_styles.update(name.to_s => params)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.setup
|
61
|
+
yield self
|
62
|
+
end
|
4
63
|
end
|
64
|
+
|
65
|
+
I18n.load_path += Dir[Pathname.new(__FILE__).join('..', '..', 'config', 'locales', '**', '*.{rb,yml}').to_s]
|
66
|
+
|
67
|
+
require 'tiny_captcha/engine' if defined?(Rails)
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module TinyCaptcha #:nodoc
|
3
|
+
module ModelHelpers #:nodoc
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(SingletonMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
# To implement model based simple captcha use this method in the model as...
|
9
|
+
#
|
10
|
+
# class User < ActiveRecord::Base
|
11
|
+
#
|
12
|
+
# apply_tiny_captcha :message => "my customized message"
|
13
|
+
#
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# Customize the error message by using :message, the default message is "Captcha did not match".
|
17
|
+
# As in the applications captcha is needed with a very few cases like signing up the new user, but
|
18
|
+
# not every time you need to authenticate the captcha with @user.save. So as to maintain simplicity
|
19
|
+
# here we have the explicit method to save the instace with captcha validation as...
|
20
|
+
#
|
21
|
+
# * to validate the instance
|
22
|
+
#
|
23
|
+
# @user.valid_with_captcha? # whene captcha validation is required.
|
24
|
+
#
|
25
|
+
# @user.valid? # when captcha validation is not required.
|
26
|
+
#
|
27
|
+
# * to save the instance
|
28
|
+
#
|
29
|
+
# @user.save_with_captcha # whene captcha validation is required.
|
30
|
+
#
|
31
|
+
# @user.save # when captcha validation is not required.
|
32
|
+
module SingletonMethods
|
33
|
+
def apply_tiny_captcha(options = {})
|
34
|
+
options = { :add_to_base => false }.merge(options)
|
35
|
+
|
36
|
+
class_attribute :tiny_captcha_options
|
37
|
+
self.tiny_captcha_options = options
|
38
|
+
|
39
|
+
unless self.is_a?(ClassMethods)
|
40
|
+
include InstanceMethods
|
41
|
+
extend ClassMethods
|
42
|
+
|
43
|
+
attr_accessor :captcha, :captcha_key
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
module ClassMethods
|
49
|
+
end
|
50
|
+
|
51
|
+
module InstanceMethods
|
52
|
+
|
53
|
+
def valid_with_captcha?
|
54
|
+
[valid?, is_captcha_valid?].all?
|
55
|
+
end
|
56
|
+
|
57
|
+
def tiny_captcha_valid?
|
58
|
+
self.errors[:captcha].empty?
|
59
|
+
end
|
60
|
+
|
61
|
+
def is_captcha_valid?
|
62
|
+
return true if Rails.env.test?
|
63
|
+
|
64
|
+
if captcha && captcha.upcase.delete(" ") == ::TinyCaptcha::Utils::tiny_captcha_value(captcha_key)
|
65
|
+
::TinyCaptcha::Utils::tiny_captcha_passed!(captcha_key)
|
66
|
+
return true
|
67
|
+
else
|
68
|
+
message = tiny_captcha_options[:message] || I18n.t(
|
69
|
+
self.class.model_name.to_s.downcase, :scope => [:tiny_captcha, :message], :default => :default
|
70
|
+
)
|
71
|
+
|
72
|
+
# tiny_captcha_options[:add_to_base] ? errors.add(:base, message) : errors.add(:captcha, message)
|
73
|
+
errors.add(:captcha, message)
|
74
|
+
return false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def update_attributes_with_captcha *args
|
79
|
+
valid_with_captcha? && update_attributes(*args)
|
80
|
+
end
|
81
|
+
|
82
|
+
def save_with_captcha
|
83
|
+
# valid_with_captcha? && save(:validate => false)
|
84
|
+
valid_with_captcha? && self.save
|
85
|
+
end
|
86
|
+
|
87
|
+
def save_with_captcha!
|
88
|
+
valid_with_captcha? && self.save!
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module TinyCaptcha #:nodoc
|
3
|
+
module ControllerHelpers #:nodoc
|
4
|
+
def self.included base
|
5
|
+
base.class_eval do
|
6
|
+
include InstanceMethods
|
7
|
+
helper_method :generate_tiny_captcha_options
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
# This method is to validate the simple captcha in controller.
|
13
|
+
# It means when the captcha is controller based i.e. :object has not been passed to the method show_tiny_captcha.
|
14
|
+
#
|
15
|
+
# *Example*
|
16
|
+
#
|
17
|
+
# If you want to save an object say @user only if the captcha is validated then do like this in action...
|
18
|
+
#
|
19
|
+
# if tiny_captcha_valid?
|
20
|
+
# @user.save
|
21
|
+
# else
|
22
|
+
# flash[:notice] = "captcha did not match"
|
23
|
+
# redirect_to :action => "myaction"
|
24
|
+
# end
|
25
|
+
def tiny_captcha_valid?
|
26
|
+
return true if Rails.env.test?
|
27
|
+
|
28
|
+
if params[:captcha]
|
29
|
+
data = TinyCaptcha::Utils::tiny_captcha_value(params[:captcha_key] || session[:captcha])
|
30
|
+
result = data == params[:captcha].delete(" ").upcase
|
31
|
+
TinyCaptcha::Utils::tiny_captcha_passed!(session[:captcha]) if result
|
32
|
+
return result
|
33
|
+
else
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# 生成验证的信息
|
39
|
+
# options:
|
40
|
+
# - object
|
41
|
+
def generate_tiny_captcha_options *args
|
42
|
+
options = args.extract_options!
|
43
|
+
|
44
|
+
key = TinyCaptcha::Utils.generate_key_use_session(
|
45
|
+
session, options[:object]
|
46
|
+
)
|
47
|
+
|
48
|
+
{
|
49
|
+
:image_url => ::TinyCaptcha::Utils.generate_image_url(key, request.base_url, options),
|
50
|
+
:label => options[:label] || I18n.t('tiny_captcha.label'),
|
51
|
+
:captcha_key => ::TinyCaptcha::Utils.set_tiny_captcha_data(key, options),
|
52
|
+
:object => options[:object]
|
53
|
+
}
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/tiny_captcha/engine.rb
CHANGED
@@ -1,5 +1,32 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'rails'
|
3
|
+
require 'tiny_captcha'
|
4
|
+
|
1
5
|
module TinyCaptcha
|
2
6
|
class Engine < ::Rails::Engine
|
3
|
-
|
7
|
+
config.before_initialize do
|
8
|
+
ActiveSupport.on_load :active_record do
|
9
|
+
ActiveRecord::Base.send(:include, TinyCaptcha::ModelHelpers)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
config.after_initialize do
|
14
|
+
ActionView::Base.send(:include, TinyCaptcha::ViewHelper)
|
15
|
+
ActionView::Helpers::FormBuilder.send(:include, TinyCaptcha::FormBuilder)
|
16
|
+
|
17
|
+
ActionController::Base.send :include, ::TinyCaptcha::ControllerHelpers
|
18
|
+
|
19
|
+
if Object.const_defined?("Formtastic")
|
20
|
+
if Formtastic.const_defined?("Helpers")
|
21
|
+
Formtastic::Helpers::FormHelper.builder = TinyCaptcha::CustomFormBuilder
|
22
|
+
else
|
23
|
+
Formtastic::SemanticFormHelper.builder = TinyCaptcha::CustomFormBuilder
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
config.app_middleware.use TinyCaptcha::Middleware
|
4
29
|
end
|
5
30
|
end
|
31
|
+
|
32
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module TinyCaptcha
|
3
|
+
module FormBuilder
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:include, TinyCaptcha::ViewHelper)
|
6
|
+
base.send(:include, TinyCaptcha::FormBuilder::ClassMethods)
|
7
|
+
base.send(:include, ActionView::Helpers)
|
8
|
+
# base.send(:include, Sprockets::Helpers::RailsHelper)
|
9
|
+
# base.send(:include, Sprockets::Helpers::IsolatedHelper)
|
10
|
+
|
11
|
+
base.delegate :render, :session, :to => :template
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
# Example:
|
16
|
+
# <% form_for :post, :url => posts_path do |form| %>
|
17
|
+
# ...
|
18
|
+
# <%= form.tiny_captcha :label => "Enter numbers.." %>
|
19
|
+
# <% end %>
|
20
|
+
#
|
21
|
+
def tiny_captcha(options = {})
|
22
|
+
options.update :object => @object_name
|
23
|
+
show_tiny_captcha(objectify_options(options))
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def template
|
29
|
+
@template
|
30
|
+
end
|
31
|
+
|
32
|
+
def tiny_captcha_field(options={})
|
33
|
+
html = {:autocomplete => 'off', :required => 'required', :value => ''}
|
34
|
+
html.merge!(options[:input_html] || {})
|
35
|
+
html[:placeholder] = options[:placeholder] || I18n.t('tiny_captcha.placeholder')
|
36
|
+
|
37
|
+
text_field(:captcha, html) + hidden_field(:captcha_key, {
|
38
|
+
:value => options[:captcha_key], :class => 'captcha-key'
|
39
|
+
})
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module TinyCaptcha
|
3
|
+
class CustomFormBuilder < Formtastic::FormBuilder
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def tiny_captcha_input(method, options)
|
8
|
+
options.update :object => sanitized_object_name
|
9
|
+
self.send(:show_tiny_captcha, options)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'tempfile'
|
3
|
+
module TinyCaptcha #:nodoc
|
4
|
+
module ImageHelpers #:nodoc
|
5
|
+
|
6
|
+
mattr_accessor :image_styles
|
7
|
+
@@image_styles = {
|
8
|
+
'embosed_silver' => ['-fill darkblue', '-shade 20x60', '-background white'],
|
9
|
+
'simply_red' => ['-fill darkred', '-background white'],
|
10
|
+
'simply_green' => ['-fill darkgreen', '-background white'],
|
11
|
+
'simply_blue' => ['-fill darkblue', '-background white'],
|
12
|
+
'distorted_black' => ['-fill darkblue', '-edge 10', '-background white'],
|
13
|
+
'all_black' => ['-fill darkblue', '-edge 2', '-background white'],
|
14
|
+
'charcoal_grey' => ['-fill darkblue', '-charcoal 5', '-background white'],
|
15
|
+
'almost_invisible' => ['-fill red', '-solarize 50', '-background white']
|
16
|
+
}
|
17
|
+
|
18
|
+
DISTORTIONS = ['low', 'medium', 'high']
|
19
|
+
|
20
|
+
class << self
|
21
|
+
|
22
|
+
def image_params(key = 'simply_blue')
|
23
|
+
image_keys = @@image_styles.keys
|
24
|
+
|
25
|
+
style = begin
|
26
|
+
if key == 'random'
|
27
|
+
image_keys[rand(image_keys.length)]
|
28
|
+
else
|
29
|
+
image_keys.include?(key) ? key : 'simply_blue'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
@@image_styles[style]
|
34
|
+
end
|
35
|
+
|
36
|
+
def distortion(key='low')
|
37
|
+
key =
|
38
|
+
key == 'random' ?
|
39
|
+
DISTORTIONS[rand(DISTORTIONS.length)] :
|
40
|
+
DISTORTIONS.include?(key) ? key : 'low'
|
41
|
+
case key.to_s
|
42
|
+
when 'low' then return [2 + rand(2), 80 + rand(20)]
|
43
|
+
when 'medium' then return [4 + rand(2), 50 + rand(20)]
|
44
|
+
when 'high' then return [6 + rand(2), 30 + rand(20)]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
if RUBY_VERSION < '1.9'
|
50
|
+
class Tempfile < ::Tempfile
|
51
|
+
# Replaces Tempfile's +make_tmpname+ with one that honors file extensions.
|
52
|
+
def make_tmpname(basename, n = 0)
|
53
|
+
extension = File.extname(basename)
|
54
|
+
sprintf("%s,%d,%d%s", File.basename(basename, extension), $$, n, extension)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def generate_tiny_captcha_image(tiny_captcha_key) #:nodoc
|
62
|
+
amplitude, frequency = ImageHelpers.distortion(TinyCaptcha.distortion)
|
63
|
+
text = Utils::tiny_captcha_value(tiny_captcha_key)
|
64
|
+
|
65
|
+
params = ImageHelpers.image_params(TinyCaptcha.image_style).dup
|
66
|
+
params << "-size #{TinyCaptcha.image_size}"
|
67
|
+
params << "-wave #{amplitude}x#{frequency}"
|
68
|
+
params << "-gravity \"Center\""
|
69
|
+
params << "-pointsize 22"
|
70
|
+
params << "-implode 0.2"
|
71
|
+
|
72
|
+
dst = Tempfile.new(RUBY_VERSION < '1.9' ? 'tiny_captcha.jpg' : ['tiny_captcha', '.jpg'], TinyCaptcha.tmp_path)
|
73
|
+
dst.binmode
|
74
|
+
|
75
|
+
params << "label:#{text} \"#{File.expand_path(dst.path)}\""
|
76
|
+
|
77
|
+
TinyCaptcha::Utils::run("convert", params.join(' '))
|
78
|
+
|
79
|
+
dst.close
|
80
|
+
|
81
|
+
File.expand_path(dst.path)
|
82
|
+
#dst
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module TinyCaptcha
|
3
|
+
class Middleware
|
4
|
+
include TinyCaptcha::ImageHelpers
|
5
|
+
|
6
|
+
DEFAULT_SEND_FILE_OPTIONS = {
|
7
|
+
:type => 'application/octet-stream'.freeze,
|
8
|
+
:disposition => 'attachment'.freeze,
|
9
|
+
}.freeze
|
10
|
+
|
11
|
+
CODE_KEY = 'code'
|
12
|
+
|
13
|
+
def initialize(app, options={})
|
14
|
+
@app = app
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(env) # :nodoc:
|
19
|
+
if env["REQUEST_METHOD"] == "GET" && env['PATH_INFO'].start_with?(::TinyCaptcha.image_show_path)
|
20
|
+
# /tiny_captcha/images/show?code=abcdefg
|
21
|
+
make_image(env)
|
22
|
+
else
|
23
|
+
@app.call(env)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def render_json(env, data={}, headers={}, status=404)
|
30
|
+
body = []
|
31
|
+
body << data.to_json
|
32
|
+
headers['Content-Type'] = 'application/json'
|
33
|
+
[status, headers, body]
|
34
|
+
end
|
35
|
+
|
36
|
+
def make_image(env, headers = {}, status = 404)
|
37
|
+
request = Rack::Request.new(env)
|
38
|
+
code = request.params[CODE_KEY]
|
39
|
+
body = []
|
40
|
+
|
41
|
+
if !code.blank? && ::TinyCaptcha::Utils::tiny_captcha_value(code)
|
42
|
+
#status, headers, body = @app.call(env)
|
43
|
+
#status = 200
|
44
|
+
#body = generate_tiny_captcha_image(code)
|
45
|
+
#headers['Content-Type'] = 'image/jpeg'
|
46
|
+
|
47
|
+
return send_file(
|
48
|
+
generate_tiny_captcha_image(code),
|
49
|
+
:type => 'image/jpeg',
|
50
|
+
:disposition => 'inline',
|
51
|
+
:filename => 'tiny_captcha.jpg'
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
[status, headers, body]
|
56
|
+
end
|
57
|
+
|
58
|
+
def send_file(path, options = {})
|
59
|
+
raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)
|
60
|
+
|
61
|
+
options[:filename] ||= File.basename(path) unless options[:url_based_filename]
|
62
|
+
|
63
|
+
status = options[:status] || 200
|
64
|
+
headers = {"Content-Disposition" => "#{options[:disposition]}; filename='#{options[:filename]}'", "Content-Type" => options[:type], 'Content-Transfer-Encoding' => 'binary', 'Cache-Control' => 'private'}
|
65
|
+
response_body = File.open(path, "rb")
|
66
|
+
|
67
|
+
[status, headers, response_body]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module TinyCaptcha
|
3
|
+
class TinyCaptchaData < ::ActiveRecord::Base
|
4
|
+
def self.rails3?
|
5
|
+
::ActiveRecord::VERSION::MAJOR == 3
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.rails4?
|
9
|
+
::ActiveRecord::VERSION::MAJOR == 4
|
10
|
+
end
|
11
|
+
|
12
|
+
if rails3? || rails4?
|
13
|
+
self.table_name = "tiny_captcha_data"
|
14
|
+
else
|
15
|
+
set_table_name "tiny_captcha_data"
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_accessible :key, :value
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def get_data(key)
|
22
|
+
data = find_by_key(key) || new(:key => key)
|
23
|
+
end
|
24
|
+
|
25
|
+
def remove_data(key)
|
26
|
+
delete_all(["#{connection.quote_column_name(:key)} = ?", key])
|
27
|
+
clear_old_data(1.hour.ago)
|
28
|
+
end
|
29
|
+
|
30
|
+
def clear_old_data(time = 1.hour.ago)
|
31
|
+
return unless Time === time
|
32
|
+
delete_all(["#{connection.quote_column_name(:updated_at)} < ?", time])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module TinyCaptcha
|
3
|
+
class TinyCaptchaData
|
4
|
+
include Mongoid::Document
|
5
|
+
include Mongoid::Timestamps
|
6
|
+
|
7
|
+
field :key, type: String
|
8
|
+
field :value, type: String
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def get_data(key)
|
12
|
+
data = where(:key => key).first || new(:key => key)
|
13
|
+
end
|
14
|
+
|
15
|
+
def remove_data(key)
|
16
|
+
where(:key => key).delete_all
|
17
|
+
clear_old_data(1.hour.ago)
|
18
|
+
end
|
19
|
+
|
20
|
+
def clear_old_data(time = 1.hour.ago)
|
21
|
+
return unless Time === time
|
22
|
+
where(:updated_at.lte => time).delete_all
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'digest/sha1'
|
3
|
+
|
4
|
+
module TinyCaptcha #:nodoc
|
5
|
+
module Utils #:nodoc
|
6
|
+
# Execute command with params and return output if exit status equal expected_outcodes
|
7
|
+
def self.run(cmd, params = "", expected_outcodes = 0)
|
8
|
+
command = %Q[#{cmd} #{params}].gsub(/\s+/, " ")
|
9
|
+
command = "#{command} 2>&1"
|
10
|
+
|
11
|
+
unless (image_magick_path = TinyCaptcha.image_magick_path).blank?
|
12
|
+
command = File.join(image_magick_path, command)
|
13
|
+
end
|
14
|
+
|
15
|
+
output = `#{command}`
|
16
|
+
|
17
|
+
unless [expected_outcodes].flatten.include?($?.exitstatus)
|
18
|
+
raise ::StandardError, "Error while running #{cmd}: #{output}"
|
19
|
+
end
|
20
|
+
|
21
|
+
output
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.tiny_captcha_value(key) #:nodoc
|
25
|
+
TinyCaptchaData.get_data(key).value rescue nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.tiny_captcha_passed!(key) #:nodoc
|
29
|
+
TinyCaptchaData.remove_data(key)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.generate_key(*args)
|
33
|
+
args << Time.now.to_s
|
34
|
+
Digest::SHA1.hexdigest(args.join)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.set_tiny_captcha_data(key, options={})
|
38
|
+
code_type = options[:code_type]
|
39
|
+
|
40
|
+
data = TinyCaptcha::TinyCaptchaData.get_data(key)
|
41
|
+
data.value = generate_tiny_captcha_data(code_type)
|
42
|
+
data.save
|
43
|
+
key
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.generate_tiny_captcha_data(code)
|
47
|
+
value = ''
|
48
|
+
|
49
|
+
case code
|
50
|
+
when 'numeric' then
|
51
|
+
::TinyCaptcha.length.times{value << (48 + rand(10)).chr}
|
52
|
+
else
|
53
|
+
::TinyCaptcha.length.times{value << (65 + rand(26)).chr}
|
54
|
+
end
|
55
|
+
|
56
|
+
return value
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.generate_image_url key, *args
|
60
|
+
options = args.extract_options!
|
61
|
+
|
62
|
+
defaults = {}
|
63
|
+
defaults[:time] = options[:time] || Time.now.to_i
|
64
|
+
|
65
|
+
base_url = args.first || ENV['RAILS_RELATIVE_URL_ROOT']
|
66
|
+
|
67
|
+
"#{base_url}#{::TinyCaptcha.image_show_path}?code=#{key}&#{defaults.to_query}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.generate_key_use_session session, *args
|
71
|
+
key_name = args.first
|
72
|
+
|
73
|
+
if key_name.nil?
|
74
|
+
session[:captcha] ||= TinyCaptcha::Utils.generate_key(session[:id].to_s, 'captcha')
|
75
|
+
else
|
76
|
+
TinyCaptcha::Utils.generate_key(session[:id].to_s, key_name)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/tiny_captcha/version.rb
CHANGED
@@ -0,0 +1,99 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module TinyCaptcha #:nodoc
|
3
|
+
module ViewHelper #:nodoc
|
4
|
+
|
5
|
+
# Tiny Captcha is a very simplified captcha.
|
6
|
+
#
|
7
|
+
# It can be used as a *Model* or a *Controller* based Captcha depending on what options
|
8
|
+
# we are passing to the method show_tiny_captcha.
|
9
|
+
#
|
10
|
+
# *show_tiny_captcha* method will return the image, the label and the text box.
|
11
|
+
# This method should be called from the view within your form as...
|
12
|
+
#
|
13
|
+
# <%= show_tiny_captcha %>
|
14
|
+
#
|
15
|
+
# The available options to pass to this method are
|
16
|
+
# * label
|
17
|
+
# * object
|
18
|
+
#
|
19
|
+
# <b>Label:</b>
|
20
|
+
#
|
21
|
+
# default label is "type the text from the image", it can be modified by passing :label as
|
22
|
+
#
|
23
|
+
# <%= show_tiny_captcha(:label => "new captcha label") %>.
|
24
|
+
#
|
25
|
+
# *Object*
|
26
|
+
#
|
27
|
+
# This option is needed to create a model based captcha.
|
28
|
+
# If this option is not provided, the captcha will be controller based and
|
29
|
+
# should be checked in controller's action just by calling the method tiny_captcha_valid?
|
30
|
+
#
|
31
|
+
# To make a model based captcha give this option as...
|
32
|
+
#
|
33
|
+
# <%= show_tiny_captcha(:object => "user") %>
|
34
|
+
# and also call the method apply_tiny_captcha in the model
|
35
|
+
# this will consider "user" as the object of the model class.
|
36
|
+
#
|
37
|
+
# *Examples*
|
38
|
+
# * controller based
|
39
|
+
# <%= show_tiny_captcha(:label => "Human Authentication: type the text from image above") %>
|
40
|
+
# * model based
|
41
|
+
# <%= show_tiny_captcha(:object => "person", :label => "Human Authentication: type the text from image above") %>
|
42
|
+
#
|
43
|
+
# Find more detailed examples with sample images here on my blog http://EXPRESSICA.com
|
44
|
+
#
|
45
|
+
# All Feedbacks/CommentS/Issues/Queries are welcome.
|
46
|
+
#
|
47
|
+
#
|
48
|
+
# eg. show_tiny_captcha :label => '', :captcha_key => '', :image_url => ''
|
49
|
+
def show_tiny_captcha(*args)
|
50
|
+
options = args.extract_options!
|
51
|
+
|
52
|
+
options[:captcha_key] ||= set_tiny_captcha_data(
|
53
|
+
(
|
54
|
+
args.first || tiny_captcha_key(options[:object])
|
55
|
+
),
|
56
|
+
options
|
57
|
+
)
|
58
|
+
|
59
|
+
key = options[:captcha_key]
|
60
|
+
|
61
|
+
defaults = {
|
62
|
+
:image => tiny_captcha_image(key, options),
|
63
|
+
:label => options[:label] || I18n.t('tiny_captcha.label'),
|
64
|
+
:field => tiny_captcha_field(options)
|
65
|
+
}
|
66
|
+
|
67
|
+
render :partial => 'tiny_captcha/tiny_captcha', :locals => { :tiny_captcha_options => defaults }
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def tiny_captcha_image(key, options = {})
|
73
|
+
url = options[:image_url] || ::TinyCaptcha::Utils.generate_image_url(key, options)
|
74
|
+
tag('img', :src => url, :alt => 'captcha', :class => 'captcha-image')
|
75
|
+
end
|
76
|
+
|
77
|
+
def tiny_captcha_field(options={})
|
78
|
+
html = {:autocomplete => 'off', :required => 'required'}
|
79
|
+
html.merge!(options[:input_html] || {})
|
80
|
+
html[:placeholder] = options[:placeholder] || I18n.t('tiny_captcha.placeholder')
|
81
|
+
|
82
|
+
if options[:object]
|
83
|
+
text_field(options[:object], :captcha, html.merge(:value => '')) +
|
84
|
+
hidden_field(options[:object], :captcha_key, {:value => options[:captcha_key], :class => 'captcha-key'})
|
85
|
+
else
|
86
|
+
text_field_tag(:captcha, nil, html) +
|
87
|
+
hidden_field_tag(:captcha_key, options[:captcha_key], :class => 'captcha-key')
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def set_tiny_captcha_data(key, options={})
|
92
|
+
::TinyCaptcha::Utils.set_tiny_captcha_data key, options
|
93
|
+
end
|
94
|
+
|
95
|
+
def tiny_captcha_key(key_name = nil)
|
96
|
+
TinyCaptcha::Utils.generate_key_use_session session, key_name
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/test/dummy/config/boot.rb
CHANGED
data/test/dummy/config/routes.rb
CHANGED
data/test/test_helper.rb
CHANGED
data/test/tiny_captcha_test.rb
CHANGED
metadata
CHANGED
@@ -1,62 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tiny_captcha
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.3
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- happy
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-01-23 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rails
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 4.0.0
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- - ~>
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: 4.0.0
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: tiny_util
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: sqlite3
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - ">="
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
description: Description of TinyCaptcha.
|
@@ -66,115 +59,125 @@ executables: []
|
|
66
59
|
extensions: []
|
67
60
|
extra_rdoc_files: []
|
68
61
|
files:
|
69
|
-
-
|
70
|
-
-
|
62
|
+
- MIT-LICENSE
|
63
|
+
- README.rdoc
|
64
|
+
- Rakefile
|
71
65
|
- app/assets/javascripts/tiny_captcha/application.js
|
72
66
|
- app/assets/stylesheets/tiny_captcha/application.css
|
67
|
+
- app/controllers/tiny_captcha/application_controller.rb
|
68
|
+
- app/controllers/tiny_captcha/images_controller.rb
|
73
69
|
- app/helpers/tiny_captcha/application_helper.rb
|
70
|
+
- app/views/layouts/tiny_captcha/application.html.erb
|
71
|
+
- config/locales/en/tiny_captcha.en.yml
|
72
|
+
- config/locales/zh-CN/tiny_captcha.zh-CN.yml
|
74
73
|
- config/routes.rb
|
75
|
-
- lib/
|
76
|
-
- lib/
|
74
|
+
- lib/generators/USAGE
|
75
|
+
- lib/generators/templates/migration.rb
|
76
|
+
- lib/generators/templates/partial.erb
|
77
|
+
- lib/generators/tiny_captcha_generator.rb
|
77
78
|
- lib/tasks/tiny_captcha_tasks.rake
|
78
79
|
- lib/tiny_captcha.rb
|
79
|
-
-
|
80
|
-
-
|
81
|
-
-
|
82
|
-
-
|
83
|
-
-
|
84
|
-
-
|
85
|
-
-
|
86
|
-
-
|
80
|
+
- lib/tiny_captcha/active_record.rb
|
81
|
+
- lib/tiny_captcha/controller.rb
|
82
|
+
- lib/tiny_captcha/engine.rb
|
83
|
+
- lib/tiny_captcha/form_builder.rb
|
84
|
+
- lib/tiny_captcha/formtastic.rb
|
85
|
+
- lib/tiny_captcha/image.rb
|
86
|
+
- lib/tiny_captcha/middleware.rb
|
87
|
+
- lib/tiny_captcha/tiny_captcha_data.rb
|
88
|
+
- lib/tiny_captcha/tiny_captcha_data_mongoid.rb
|
89
|
+
- lib/tiny_captcha/utils.rb
|
90
|
+
- lib/tiny_captcha/version.rb
|
91
|
+
- lib/tiny_captcha/view.rb
|
87
92
|
- test/dummy/README.rdoc
|
88
|
-
- test/dummy/config.ru
|
89
93
|
- test/dummy/Rakefile
|
90
|
-
- test/dummy/app/views/layouts/application.html.erb
|
91
|
-
- test/dummy/app/controllers/application_controller.rb
|
92
94
|
- test/dummy/app/assets/javascripts/application.js
|
93
95
|
- test/dummy/app/assets/stylesheets/application.css
|
96
|
+
- test/dummy/app/controllers/application_controller.rb
|
94
97
|
- test/dummy/app/helpers/application_helper.rb
|
95
|
-
- test/dummy/
|
96
|
-
- test/dummy/
|
97
|
-
- test/dummy/
|
98
|
-
- test/dummy/
|
99
|
-
- test/dummy/config
|
100
|
-
- test/dummy/config/
|
101
|
-
- test/dummy/config/
|
98
|
+
- test/dummy/app/views/layouts/application.html.erb
|
99
|
+
- test/dummy/bin/bundle
|
100
|
+
- test/dummy/bin/rails
|
101
|
+
- test/dummy/bin/rake
|
102
|
+
- test/dummy/config.ru
|
103
|
+
- test/dummy/config/application.rb
|
104
|
+
- test/dummy/config/boot.rb
|
105
|
+
- test/dummy/config/database.yml
|
106
|
+
- test/dummy/config/environment.rb
|
102
107
|
- test/dummy/config/environments/development.rb
|
103
|
-
- test/dummy/config/
|
108
|
+
- test/dummy/config/environments/production.rb
|
109
|
+
- test/dummy/config/environments/test.rb
|
104
110
|
- test/dummy/config/initializers/backtrace_silencers.rb
|
105
|
-
- test/dummy/config/initializers/mime_types.rb
|
106
|
-
- test/dummy/config/initializers/inflections.rb
|
107
111
|
- test/dummy/config/initializers/filter_parameter_logging.rb
|
108
|
-
- test/dummy/config/initializers/
|
112
|
+
- test/dummy/config/initializers/inflections.rb
|
113
|
+
- test/dummy/config/initializers/mime_types.rb
|
114
|
+
- test/dummy/config/initializers/secret_token.rb
|
109
115
|
- test/dummy/config/initializers/session_store.rb
|
116
|
+
- test/dummy/config/initializers/wrap_parameters.rb
|
117
|
+
- test/dummy/config/locales/en.yml
|
110
118
|
- test/dummy/config/routes.rb
|
111
|
-
- test/dummy/
|
112
|
-
- test/dummy/
|
113
|
-
- test/dummy/
|
114
|
-
- test/dummy/
|
119
|
+
- test/dummy/public/404.html
|
120
|
+
- test/dummy/public/422.html
|
121
|
+
- test/dummy/public/500.html
|
122
|
+
- test/dummy/public/favicon.ico
|
115
123
|
- test/integration/navigation_test.rb
|
124
|
+
- test/test_helper.rb
|
125
|
+
- test/tiny_captcha_test.rb
|
116
126
|
homepage: http://github.com/xiuxian123/tiny_passport
|
117
127
|
licenses: []
|
128
|
+
metadata: {}
|
118
129
|
post_install_message:
|
119
130
|
rdoc_options: []
|
120
131
|
require_paths:
|
121
132
|
- lib
|
122
133
|
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
-
none: false
|
124
134
|
requirements:
|
125
|
-
- -
|
135
|
+
- - ">="
|
126
136
|
- !ruby/object:Gem::Version
|
127
137
|
version: '0'
|
128
|
-
segments:
|
129
|
-
- 0
|
130
|
-
hash: 965235565
|
131
138
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
-
none: false
|
133
139
|
requirements:
|
134
|
-
- -
|
140
|
+
- - ">="
|
135
141
|
- !ruby/object:Gem::Version
|
136
142
|
version: '0'
|
137
|
-
segments:
|
138
|
-
- 0
|
139
|
-
hash: 965235565
|
140
143
|
requirements: []
|
141
144
|
rubyforge_project:
|
142
|
-
rubygems_version:
|
145
|
+
rubygems_version: 2.2.1
|
143
146
|
signing_key:
|
144
|
-
specification_version:
|
147
|
+
specification_version: 4
|
145
148
|
summary: Summary of TinyCaptcha.
|
146
149
|
test_files:
|
147
|
-
- test/tiny_captcha_test.rb
|
148
|
-
- test/test_helper.rb
|
149
|
-
- test/dummy/bin/bundle
|
150
|
-
- test/dummy/bin/rake
|
151
|
-
- test/dummy/bin/rails
|
152
|
-
- test/dummy/README.rdoc
|
153
|
-
- test/dummy/config.ru
|
154
|
-
- test/dummy/Rakefile
|
155
|
-
- test/dummy/app/views/layouts/application.html.erb
|
156
|
-
- test/dummy/app/controllers/application_controller.rb
|
157
150
|
- test/dummy/app/assets/javascripts/application.js
|
158
151
|
- test/dummy/app/assets/stylesheets/application.css
|
152
|
+
- test/dummy/app/controllers/application_controller.rb
|
159
153
|
- test/dummy/app/helpers/application_helper.rb
|
160
|
-
- test/dummy/
|
161
|
-
- test/dummy/
|
162
|
-
- test/dummy/
|
163
|
-
- test/dummy/
|
164
|
-
- test/dummy/config/
|
165
|
-
- test/dummy/config/
|
166
|
-
- test/dummy/config/
|
154
|
+
- test/dummy/app/views/layouts/application.html.erb
|
155
|
+
- test/dummy/bin/bundle
|
156
|
+
- test/dummy/bin/rails
|
157
|
+
- test/dummy/bin/rake
|
158
|
+
- test/dummy/config/application.rb
|
159
|
+
- test/dummy/config/boot.rb
|
160
|
+
- test/dummy/config/database.yml
|
161
|
+
- test/dummy/config/environment.rb
|
167
162
|
- test/dummy/config/environments/development.rb
|
168
|
-
- test/dummy/config/
|
163
|
+
- test/dummy/config/environments/production.rb
|
164
|
+
- test/dummy/config/environments/test.rb
|
169
165
|
- test/dummy/config/initializers/backtrace_silencers.rb
|
170
|
-
- test/dummy/config/initializers/mime_types.rb
|
171
|
-
- test/dummy/config/initializers/inflections.rb
|
172
166
|
- test/dummy/config/initializers/filter_parameter_logging.rb
|
173
|
-
- test/dummy/config/initializers/
|
167
|
+
- test/dummy/config/initializers/inflections.rb
|
168
|
+
- test/dummy/config/initializers/mime_types.rb
|
169
|
+
- test/dummy/config/initializers/secret_token.rb
|
174
170
|
- test/dummy/config/initializers/session_store.rb
|
171
|
+
- test/dummy/config/initializers/wrap_parameters.rb
|
172
|
+
- test/dummy/config/locales/en.yml
|
175
173
|
- test/dummy/config/routes.rb
|
176
|
-
- test/dummy/config
|
177
|
-
- test/dummy/
|
178
|
-
- test/dummy/
|
179
|
-
- test/dummy/
|
174
|
+
- test/dummy/config.ru
|
175
|
+
- test/dummy/public/404.html
|
176
|
+
- test/dummy/public/422.html
|
177
|
+
- test/dummy/public/500.html
|
178
|
+
- test/dummy/public/favicon.ico
|
179
|
+
- test/dummy/Rakefile
|
180
|
+
- test/dummy/README.rdoc
|
180
181
|
- test/integration/navigation_test.rb
|
182
|
+
- test/test_helper.rb
|
183
|
+
- test/tiny_captcha_test.rb
|