recaptcha 0.3.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  rdoc
2
2
  pkg
3
+ Gemfile.lock
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ == 0.3.5 / 2012-05-02
2
+
3
+ * I18n for error messages
4
+ * Rails: delete flash keys if unused
5
+
1
6
  == 0.3.4 / 2011-12-13
2
7
 
3
8
  * Rails 3
@@ -25,4 +30,4 @@
25
30
  == 0.1.0 / 2008-2-8
26
31
 
27
32
  * 1 major enhancement
28
- * Initial Gem Release
33
+ * Initial Gem Release
@@ -17,31 +17,18 @@ call these methods and the keys can't be found.
17
17
 
18
18
  == About this fork
19
19
 
20
- This fork tries to introduces a more convenient way to configure recaptcha's
20
+ This fork tries to introduce a more convenient way to configure recaptcha's
21
21
  settings. The API will be inspired by {Thoughtbot's
22
22
  Hoptoad}[http://robots.thoughtbot.com/post/344833329/mygem-configure-block].
23
23
 
24
24
  == Rails Installation
25
25
 
26
- reCAPTCHA for Rails, add this to your Gemfile:
26
+ reCAPTCHA for Rails > 3.0, add this to your Gemfile:
27
27
 
28
28
  gem "recaptcha", :require => "recaptcha/rails"
29
29
 
30
- Or, it can be installed as a gem:
31
-
32
- config.gem "recaptcha", :lib => "recaptcha/rails"
33
-
34
- Or, as a standard rails plugin:
35
-
36
- script/plugin install git://github.com/ambethia/recaptcha.git
37
-
38
- == Merb Installation
39
-
40
- reCAPTCHA can also be used in a Merb application when installed as a gem:
41
-
42
- dependency "alm-recaptcha", ">=0.2.2.1", :require_as => "recaptcha/merb"
43
-
44
- Initial Merb compatability funded by ALM Labs.
30
+ Rails apps below 3.0 are no longer supported, but you can install an older
31
+ release and view it's README.
45
32
 
46
33
  == Setting up your API Keys
47
34
 
@@ -56,7 +43,7 @@ into a +config/initializers/recaptcha.rb+ when used in a Rails project.
56
43
  Recaptcha.configure do |config|
57
44
  config.public_key = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
58
45
  config.private_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
59
- config.proxy = 'http://myrpoxy.com.au:8080'
46
+ config.proxy = 'http://myproxy.com.au:8080'
60
47
  end
61
48
 
62
49
  This way, you may also set additional options to fit recaptcha into your
@@ -66,15 +53,16 @@ deployment environment.
66
53
 
67
54
  If you want to temporarily overwrite the configuration you set with `Recaptcha.configure` (when testing, for example), you can use a `Recaptcha#with_configuration` block:
68
55
 
69
- Recaptcha.configure(:public_key => '12345') do
56
+ Recaptcha.with_configuration(:public_key => '12345') do
70
57
  # Do stuff with the overwritten public_key.
71
58
  end
72
59
 
73
- === Shell environment
60
+ === Heroku & Shell environment
74
61
 
75
62
  Or, you can keep your keys out of your code base by exporting the following
76
63
  environment variables. You might do this in the .profile/rc, or equivalent for
77
- the user running your application:
64
+ the user running your application. This would also be the preffered method
65
+ in an Heroku deployment.
78
66
 
79
67
  export RECAPTCHA_PUBLIC_KEY = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
80
68
  export RECAPTCHA_PRIVATE_KEY = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
@@ -102,9 +90,9 @@ And, add +verify_recaptcha+ logic to each form action that you've protected.
102
90
 
103
91
  Some of the options available:
104
92
 
105
- <tt>:ssl</tt>:: Uses secure http for captcha widget (default +false+)
93
+ <tt>:ssl</tt>:: Uses secure http for captcha widget (default +false+, but can be changed by setting +config.use_ssl_by_default+)
106
94
  <tt>:noscript</tt>:: Include <noscript> content (default +true+)
107
- <tt>:display</tt>:: Takes a hash containing the +theme+ and +tabindex+ options per the API. (default +nil+)
95
+ <tt>:display</tt>:: Takes a hash containing the +theme+ and +tabindex+ options per the API. (default +nil+), options: 'red', 'white', 'blackglass', 'clean', 'custom'
108
96
  <tt>:ajax</tt>:: Render the dynamic AJAX captcha per the API. (default +false+)
109
97
  <tt>:public_key</tt>:: Your public API key, takes precedence over the ENV variable (default +nil+)
110
98
  <tt>:error</tt>:: Override the error code returned from the reCAPTCHA API (default +nil+)
@@ -136,13 +124,20 @@ Some of the options available:
136
124
  end
137
125
 
138
126
  == I18n support
139
- reCAPTCHA passes two types of error explanation to a linked model. It will use the I18n gem
140
- to translate the default error message if I18n is available. To customize the messages to your locale,
127
+ reCAPTCHA passes two types of error explanation to a linked model. It will use the I18n gem
128
+ to translate the default error message if I18n is available. To customize the messages to your locale,
141
129
  add these keys to your I18n backend:
142
130
 
143
131
  <tt>recaptcha.errors.verification_failed</tt>:: error message displayed if the captcha words didn't match
144
132
  <tt>recaptcha.errors.recaptcha_unavailable</tt>:: displayed if a timout error occured while attempting to verify the captcha
145
133
 
134
+ Also you can translate API response errors to human friendly by adding translations to the locale (+config/locales/en.yml+):
135
+
136
+ en:
137
+ recaptcha:
138
+ errors:
139
+ incorrect-captcha-sol: 'Fail'
140
+
146
141
  == TODO
147
142
  * Remove Rails/ActionController dependencies
148
143
  * Framework agnostic
@@ -3,10 +3,12 @@ require 'recaptcha/client_helper'
3
3
  require 'recaptcha/verify'
4
4
 
5
5
  module Recaptcha
6
- RECAPTCHA_API_SERVER_URL = 'http://www.google.com/recaptcha/api'
6
+ RECAPTCHA_API_SERVER_URL = '//www.google.com/recaptcha/api'
7
7
  RECAPTCHA_API_SECURE_SERVER_URL = 'https://www.google.com/recaptcha/api'
8
8
  RECAPTCHA_VERIFY_URL = 'http://www.google.com/recaptcha/api/verify'
9
+ USE_SSL_BY_DEFAULT = false
9
10
 
11
+ HANDLE_TIMEOUTS_GRACEFULLY = true
10
12
  SKIP_VERIFY_ENV = ['test', 'cucumber']
11
13
 
12
14
  # Gives access to the current Configuration.
@@ -6,12 +6,13 @@ module Recaptcha
6
6
  # Default options
7
7
  key = options[:public_key] ||= Recaptcha.configuration.public_key
8
8
  raise RecaptchaError, "No public key specified." unless key
9
- error = options[:error] ||= (defined? flash ? flash[:recaptcha_error] : "")
9
+ error = options[:error] ||= ((defined? flash) ? flash[:recaptcha_error] : "")
10
10
  uri = Recaptcha.configuration.api_server_url(options[:ssl])
11
+ lang = options[:display] && options[:display][:lang] ? options[:display][:lang].to_sym : ""
11
12
  html = ""
12
13
  if options[:display]
13
14
  html << %{<script type="text/javascript">\n}
14
- html << %{ var RecaptchaOptions = #{options[:display].to_json};\n}
15
+ html << %{ var RecaptchaOptions = #{hash_to_json(options[:display])};\n}
15
16
  html << %{</script>\n}
16
17
  end
17
18
  if options[:ajax]
@@ -31,7 +32,8 @@ module Recaptcha
31
32
  EOS
32
33
  else
33
34
  html << %{<script type="text/javascript" src="#{uri}/challenge?k=#{key}}
34
- html << %{#{error ? "&amp;error=#{CGI::escape(error)}" : ""}"></script>\n}
35
+ html << %{#{error ? "&amp;error=#{CGI::escape(error)}" : ""}}
36
+ html << %{#{lang ? "&amp;lang=#{lang}" : ""}"></script>\n}
35
37
  unless options[:noscript] == false
36
38
  html << %{<noscript>\n }
37
39
  html << %{<iframe src="#{uri}/noscript?k=#{key}" }
@@ -47,5 +49,19 @@ module Recaptcha
47
49
  end
48
50
  return (html.respond_to?(:html_safe) && html.html_safe) || html
49
51
  end # recaptcha_tags
52
+
53
+ private
54
+
55
+ def hash_to_json(hash)
56
+ result = "{"
57
+ result << hash.map do |k, v|
58
+ if ! v.is_a?(String) || k.to_s == "callback"
59
+ "\"#{k}\": #{v}"
60
+ else
61
+ "\"#{k}\": \"#{v}\""
62
+ end
63
+ end.join(", ")
64
+ result << "}"
65
+ end
50
66
  end # ClientHelper
51
67
  end # Recaptcha
@@ -1,6 +1,6 @@
1
1
  module Recaptcha
2
2
  # This class enables detailed configuration of the recaptcha services.
3
- #
3
+ #
4
4
  # By calling
5
5
  #
6
6
  # Recaptcha.configuration # => instance of Recaptcha::Configuration
@@ -13,7 +13,7 @@ module Recaptcha
13
13
  # you are able to perform configuration updates.
14
14
  #
15
15
  # Your are able to customize all attributes listed below. All values have
16
- # sensitive default and will very likely not need to be changed.
16
+ # sensitive default and will very likely not need to be changed.
17
17
  #
18
18
  # Please note that the public and private key for the reCAPTCHA API Access
19
19
  # have no useful default value. The keys may be set via the Shell enviroment
@@ -34,19 +34,24 @@ module Recaptcha
34
34
  :skip_verify_env,
35
35
  :private_key,
36
36
  :public_key,
37
- :proxy
37
+ :proxy,
38
+ :handle_timeouts_gracefully,
39
+ :use_ssl_by_default
38
40
 
39
41
  def initialize #:nodoc:
40
- @nonssl_api_server_url = RECAPTCHA_API_SERVER_URL
41
- @ssl_api_server_url = RECAPTCHA_API_SECURE_SERVER_URL
42
- @verify_url = RECAPTCHA_VERIFY_URL
43
- @skip_verify_env = SKIP_VERIFY_ENV
42
+ @nonssl_api_server_url = RECAPTCHA_API_SERVER_URL
43
+ @ssl_api_server_url = RECAPTCHA_API_SECURE_SERVER_URL
44
+ @verify_url = RECAPTCHA_VERIFY_URL
45
+ @skip_verify_env = SKIP_VERIFY_ENV
46
+ @handle_timeouts_gracefully = HANDLE_TIMEOUTS_GRACEFULLY
47
+ @use_ssl_by_default = USE_SSL_BY_DEFAULT
44
48
 
45
49
  @private_key = ENV['RECAPTCHA_PRIVATE_KEY']
46
50
  @public_key = ENV['RECAPTCHA_PUBLIC_KEY']
47
51
  end
48
52
 
49
- def api_server_url(ssl = false) #:nodoc:
53
+ def api_server_url(ssl = nil) #:nodoc:
54
+ ssl = use_ssl_by_default if ssl.nil?
50
55
  ssl ? ssl_api_server_url : nonssl_api_server_url
51
56
  end
52
57
  end
@@ -34,25 +34,39 @@ module Recaptcha
34
34
  end
35
35
  answer, error = recaptcha.body.split.map { |s| s.chomp }
36
36
  unless answer == 'true'
37
- flash[:recaptcha_error] = error
37
+ flash[:recaptcha_error] = if defined?(I18n)
38
+ I18n.translate("recaptcha.errors.#{error}", {:default => error})
39
+ else
40
+ error
41
+ end
42
+
38
43
  if model
39
44
  message = "Word verification response is incorrect, please try again."
40
- message = I18n.translate(:'recaptcha.errors.verification_failed', {:default => message}) if defined?(I18n)
45
+ message = I18n.translate('recaptcha.errors.verification_failed', {:default => message}) if defined?(I18n)
41
46
  model.errors.add attribute, options[:message] || message
42
47
  end
43
48
  return false
44
49
  else
45
- flash[:recaptcha_error] = nil
50
+ flash.delete(:recaptcha_error)
46
51
  return true
47
52
  end
48
53
  rescue Timeout::Error
49
- flash[:recaptcha_error] = "recaptcha-not-reachable"
50
- if model
51
- message = "Oops, we failed to validate your word verification response. Please try again."
52
- message = I18n.translate(:'recaptcha.errors.recaptcha_unreachable', :default => message) if defined?(I18n)
53
- model.errors.add attribute, options[:message] || message
54
+ if Recaptcha.configuration.handle_timeouts_gracefully
55
+ flash[:recaptcha_error] = if defined?(I18n)
56
+ I18n.translate('recaptcha.errors.recaptcha_unreachable', {:default => 'Recaptcha unreachable.'})
57
+ else
58
+ 'Recaptcha unreachable.'
59
+ end
60
+
61
+ if model
62
+ message = "Oops, we failed to validate your word verification response. Please try again."
63
+ message = I18n.translate('recaptcha.errors.recaptcha_unreachable', :default => message) if defined?(I18n)
64
+ model.errors.add attribute, options[:message] || message
65
+ end
66
+ return false
67
+ else
68
+ raise RecaptchaError, "Recaptcha unreachable."
54
69
  end
55
- return false
56
70
  rescue Exception => e
57
71
  raise RecaptchaError, e.message, e.backtrace
58
72
  end
@@ -1,3 +1,3 @@
1
1
  module Recaptcha
2
- VERSION = "0.3.4"
2
+ VERSION = "0.3.5"
3
3
  end
@@ -19,7 +19,17 @@ class RecaptchaClientHelperTest < Test::Unit::TestCase
19
19
 
20
20
  def test_recaptcha_tags
21
21
  # Might as well match something...
22
- assert_match /http:\/\/www.google.com\/recaptcha\/api\/challenge/, recaptcha_tags
22
+ assert_match /"\/\/www.google.com\/recaptcha\/api\/challenge/, recaptcha_tags
23
+ end
24
+
25
+ def test_ssl_by_default
26
+ Recaptcha.configuration.use_ssl_by_default = true
27
+ assert_match /https:\/\/www.google.com\/recaptcha\/api\/challenge/, recaptcha_tags
28
+ end
29
+
30
+ def test_relative_protocol_by_default_without_ssl
31
+ Recaptcha.configuration.use_ssl_by_default = false
32
+ assert_match /\/\/www.google.com\/recaptcha\/api\/challenge/, recaptcha_tags(:ssl => false)
23
33
  end
24
34
 
25
35
  def test_recaptcha_tags_with_ssl
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'test/unit'
4
4
  require 'rubygems'
5
+ require 'active_support'
5
6
  require 'active_support/core_ext/string'
6
7
  require 'mocha'
7
8
  require 'i18n'
@@ -70,7 +71,17 @@ class RecaptchaVerifyTest < Test::Unit::TestCase
70
71
  def test_timeout
71
72
  expect_http_post(Timeout::Error, :exception => true)
72
73
  assert !@controller.verify_recaptcha()
73
- assert_equal "recaptcha-not-reachable", @controller.flash[:recaptcha_error]
74
+ assert_equal "Recaptcha unreachable.", @controller.flash[:recaptcha_error]
75
+ end
76
+
77
+ def test_timeout_when_handle_timeouts_gracefully_disabled
78
+ Recaptcha.with_configuration(:handle_timeouts_gracefully => false) do
79
+ expect_http_post(Timeout::Error, :exception => true)
80
+ assert_raise Recaptcha::RecaptchaError, "Recaptcha unreachable." do
81
+ assert @controller.verify_recaptcha()
82
+ end
83
+ assert_nil @controller.flash[:recaptcha_error]
84
+ end
74
85
  end
75
86
 
76
87
  def test_message_should_use_i18n
@@ -79,8 +90,12 @@ class RecaptchaVerifyTest < Test::Unit::TestCase
79
90
  verification_failed_default = "Word verification response is incorrect, please try again."
80
91
  recaptcha_unreachable_translated = "Netzwerkfehler, bitte versuchen Sie es später erneut."
81
92
  recaptcha_unreachable_default = "Oops, we failed to validate your word verification response. Please try again."
82
- I18n.expects(:translate).with(:'recaptcha.errors.verification_failed', :default => verification_failed_default).returns(verification_failed_translated)
83
- I18n.expects(:translate).with(:'recaptcha.errors.recaptcha_unreachable', :default => recaptcha_unreachable_default).returns(recaptcha_unreachable_translated)
93
+
94
+ I18n.expects(:translate).with('recaptcha.errors.bad-news', {:default => 'bad-news'})
95
+ I18n.expects(:translate).with('recaptcha.errors.recaptcha_unreachable', {:default => 'Recaptcha unreachable.'})
96
+
97
+ I18n.expects(:translate).with('recaptcha.errors.verification_failed', :default => verification_failed_default).returns(verification_failed_translated)
98
+ I18n.expects(:translate).with('recaptcha.errors.recaptcha_unreachable', :default => recaptcha_unreachable_default).returns(recaptcha_unreachable_translated)
84
99
 
85
100
  errors = mock
86
101
  errors.expects(:add).with(:base, verification_failed_translated)
@@ -95,6 +110,22 @@ class RecaptchaVerifyTest < Test::Unit::TestCase
95
110
 
96
111
  end
97
112
 
113
+ def test_it_translates_api_response_with_i18n
114
+ api_error_translated = "Bad news, body :("
115
+ expect_http_post(response_with_body("false\nbad-news"))
116
+ I18n.expects(:translate).with('recaptcha.errors.bad-news', :default => 'bad-news').returns(api_error_translated)
117
+
118
+ assert !@controller.verify_recaptcha
119
+ assert_equal api_error_translated, @controller.flash[:recaptcha_error]
120
+ end
121
+
122
+ def test_it_fallback_to_api_response_if_i18n_translation_is_missing
123
+ expect_http_post(response_with_body("false\nbad-news"))
124
+
125
+ assert !@controller.verify_recaptcha
126
+ assert_equal 'bad-news', @controller.flash[:recaptcha_error]
127
+ end
128
+
98
129
  private
99
130
 
100
131
  class TestController
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: recaptcha
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-13 00:00:00.000000000Z
12
+ date: 2013-02-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mocha
16
- requirement: &70162456439800 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70162456439800
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: rake
27
- requirement: &70162456438320 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *70162456438320
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: activesupport
38
- requirement: &70162456437340 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *70162456437340
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: i18n
49
- requirement: &70162456435080 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,7 +69,12 @@ dependencies:
54
69
  version: '0'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *70162456435080
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  description: This plugin adds helpers for the reCAPTCHA API
59
79
  email:
60
80
  - jasper@ambethia.com
@@ -65,11 +85,9 @@ files:
65
85
  - .gitignore
66
86
  - CHANGELOG
67
87
  - Gemfile
68
- - Gemfile.lock
69
88
  - LICENSE
70
89
  - README.rdoc
71
90
  - Rakefile
72
- - VERSION
73
91
  - init.rb
74
92
  - lib/recaptcha.rb
75
93
  - lib/recaptcha/client_helper.rb
@@ -94,21 +112,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
94
112
  - - ! '>='
95
113
  - !ruby/object:Gem::Version
96
114
  version: '0'
97
- segments:
98
- - 0
99
- hash: -241857000290141400
100
115
  required_rubygems_version: !ruby/object:Gem::Requirement
101
116
  none: false
102
117
  requirements:
103
118
  - - ! '>='
104
119
  - !ruby/object:Gem::Version
105
120
  version: '0'
106
- segments:
107
- - 0
108
- hash: -241857000290141400
109
121
  requirements: []
110
122
  rubyforge_project: recaptcha
111
- rubygems_version: 1.8.11
123
+ rubygems_version: 1.8.23
112
124
  signing_key:
113
125
  specification_version: 3
114
126
  summary: Helpers for the reCAPTCHA API
@@ -1,26 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- recaptcha (0.3.4)
5
-
6
- GEM
7
- remote: http://rubygems.org/
8
- specs:
9
- activesupport (3.1.3)
10
- multi_json (~> 1.0)
11
- i18n (0.6.0)
12
- metaclass (0.0.1)
13
- mocha (0.10.0)
14
- metaclass (~> 0.0.1)
15
- multi_json (1.0.3)
16
- rake (0.9.2.2)
17
-
18
- PLATFORMS
19
- ruby
20
-
21
- DEPENDENCIES
22
- activesupport
23
- i18n
24
- mocha
25
- rake
26
- recaptcha!
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.3.2