activesupport 5.0.7.2 → 5.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (210) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +215 -820
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_support.rb +8 -4
  6. data/lib/active_support/all.rb +3 -3
  7. data/lib/active_support/array_inquirer.rb +7 -5
  8. data/lib/active_support/backtrace_cleaner.rb +4 -4
  9. data/lib/active_support/benchmarkable.rb +3 -3
  10. data/lib/active_support/builder.rb +1 -1
  11. data/lib/active_support/cache.rb +42 -49
  12. data/lib/active_support/cache/file_store.rb +12 -21
  13. data/lib/active_support/cache/mem_cache_store.rb +30 -40
  14. data/lib/active_support/cache/memory_store.rb +11 -13
  15. data/lib/active_support/cache/null_store.rb +4 -4
  16. data/lib/active_support/cache/strategy/local_cache.rb +16 -25
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +8 -9
  18. data/lib/active_support/callbacks.rb +647 -584
  19. data/lib/active_support/concurrency/share_lock.rb +20 -21
  20. data/lib/active_support/configurable.rb +5 -5
  21. data/lib/active_support/core_ext.rb +1 -2
  22. data/lib/active_support/core_ext/array.rb +7 -7
  23. data/lib/active_support/core_ext/array/access.rb +1 -1
  24. data/lib/active_support/core_ext/array/conversions.rb +15 -15
  25. data/lib/active_support/core_ext/array/grouping.rb +1 -1
  26. data/lib/active_support/core_ext/array/inquiry.rb +1 -1
  27. data/lib/active_support/core_ext/array/prepend_and_append.rb +1 -1
  28. data/lib/active_support/core_ext/benchmark.rb +1 -1
  29. data/lib/active_support/core_ext/big_decimal.rb +1 -1
  30. data/lib/active_support/core_ext/big_decimal/conversions.rb +4 -6
  31. data/lib/active_support/core_ext/class.rb +2 -2
  32. data/lib/active_support/core_ext/class/attribute.rb +5 -5
  33. data/lib/active_support/core_ext/class/attribute_accessors.rb +1 -1
  34. data/lib/active_support/core_ext/class/subclasses.rb +18 -4
  35. data/lib/active_support/core_ext/date.rb +5 -5
  36. data/lib/active_support/core_ext/date/acts_like.rb +1 -1
  37. data/lib/active_support/core_ext/date/blank.rb +1 -1
  38. data/lib/active_support/core_ext/date/calculations.rb +8 -8
  39. data/lib/active_support/core_ext/date/conversions.rb +12 -12
  40. data/lib/active_support/core_ext/date/zones.rb +2 -2
  41. data/lib/active_support/core_ext/date_and_time/calculations.rb +27 -22
  42. data/lib/active_support/core_ext/date_and_time/compatibility.rb +9 -1
  43. data/lib/active_support/core_ext/date_and_time/zones.rb +7 -8
  44. data/lib/active_support/core_ext/date_time.rb +5 -5
  45. data/lib/active_support/core_ext/date_time/acts_like.rb +2 -2
  46. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  47. data/lib/active_support/core_ext/date_time/calculations.rb +9 -9
  48. data/lib/active_support/core_ext/date_time/compatibility.rb +2 -13
  49. data/lib/active_support/core_ext/date_time/conversions.rb +12 -12
  50. data/lib/active_support/core_ext/digest/uuid.rb +4 -4
  51. data/lib/active_support/core_ext/enumerable.rb +46 -57
  52. data/lib/active_support/core_ext/file.rb +1 -1
  53. data/lib/active_support/core_ext/file/atomic.rb +4 -4
  54. data/lib/active_support/core_ext/hash.rb +9 -9
  55. data/lib/active_support/core_ext/hash/compact.rb +12 -9
  56. data/lib/active_support/core_ext/hash/conversions.rb +36 -37
  57. data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -2
  58. data/lib/active_support/core_ext/hash/keys.rb +8 -8
  59. data/lib/active_support/core_ext/hash/reverse_merge.rb +1 -1
  60. data/lib/active_support/core_ext/hash/slice.rb +4 -4
  61. data/lib/active_support/core_ext/hash/transform_values.rb +1 -0
  62. data/lib/active_support/core_ext/integer.rb +3 -3
  63. data/lib/active_support/core_ext/integer/inflections.rb +1 -1
  64. data/lib/active_support/core_ext/integer/time.rb +2 -2
  65. data/lib/active_support/core_ext/kernel.rb +4 -4
  66. data/lib/active_support/core_ext/kernel/concern.rb +1 -1
  67. data/lib/active_support/core_ext/kernel/reporting.rb +1 -1
  68. data/lib/active_support/core_ext/load_error.rb +1 -18
  69. data/lib/active_support/core_ext/marshal.rb +2 -2
  70. data/lib/active_support/core_ext/module.rb +11 -12
  71. data/lib/active_support/core_ext/module/aliasing.rb +3 -48
  72. data/lib/active_support/core_ext/module/attr_internal.rb +4 -4
  73. data/lib/active_support/core_ext/module/attribute_accessors.rb +11 -5
  74. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +20 -13
  75. data/lib/active_support/core_ext/module/concerning.rb +1 -1
  76. data/lib/active_support/core_ext/module/delegation.rb +82 -16
  77. data/lib/active_support/core_ext/module/introspection.rb +3 -11
  78. data/lib/active_support/core_ext/module/reachable.rb +2 -2
  79. data/lib/active_support/core_ext/numeric.rb +4 -4
  80. data/lib/active_support/core_ext/numeric/conversions.rb +3 -9
  81. data/lib/active_support/core_ext/numeric/inquiry.rb +21 -21
  82. data/lib/active_support/core_ext/numeric/time.rb +5 -5
  83. data/lib/active_support/core_ext/object.rb +12 -12
  84. data/lib/active_support/core_ext/object/blank.rb +3 -1
  85. data/lib/active_support/core_ext/object/conversions.rb +4 -4
  86. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  87. data/lib/active_support/core_ext/object/duplicable.rb +24 -4
  88. data/lib/active_support/core_ext/object/inclusion.rb +1 -1
  89. data/lib/active_support/core_ext/object/json.rb +26 -12
  90. data/lib/active_support/core_ext/object/to_param.rb +1 -1
  91. data/lib/active_support/core_ext/object/to_query.rb +4 -4
  92. data/lib/active_support/core_ext/object/try.rb +1 -1
  93. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  94. data/lib/active_support/core_ext/range.rb +4 -4
  95. data/lib/active_support/core_ext/range/conversions.rb +1 -1
  96. data/lib/active_support/core_ext/regexp.rb +4 -0
  97. data/lib/active_support/core_ext/securerandom.rb +3 -3
  98. data/lib/active_support/core_ext/string.rb +13 -13
  99. data/lib/active_support/core_ext/string/access.rb +6 -6
  100. data/lib/active_support/core_ext/string/conversions.rb +2 -2
  101. data/lib/active_support/core_ext/string/filters.rb +3 -3
  102. data/lib/active_support/core_ext/string/indent.rb +4 -4
  103. data/lib/active_support/core_ext/string/inflections.rb +10 -14
  104. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  105. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  106. data/lib/active_support/core_ext/string/output_safety.rb +19 -20
  107. data/lib/active_support/core_ext/string/strip.rb +1 -1
  108. data/lib/active_support/core_ext/string/zones.rb +2 -2
  109. data/lib/active_support/core_ext/time.rb +5 -5
  110. data/lib/active_support/core_ext/time/acts_like.rb +1 -1
  111. data/lib/active_support/core_ext/time/calculations.rb +23 -29
  112. data/lib/active_support/core_ext/time/compatibility.rb +1 -10
  113. data/lib/active_support/core_ext/time/conversions.rb +12 -12
  114. data/lib/active_support/core_ext/time/zones.rb +3 -3
  115. data/lib/active_support/core_ext/uri.rb +2 -2
  116. data/lib/active_support/dependencies.rb +45 -47
  117. data/lib/active_support/dependencies/interlock.rb +1 -1
  118. data/lib/active_support/deprecation.rb +8 -8
  119. data/lib/active_support/deprecation/behaviors.rb +3 -3
  120. data/lib/active_support/deprecation/instance_delegator.rb +2 -2
  121. data/lib/active_support/deprecation/method_wrappers.rb +3 -3
  122. data/lib/active_support/deprecation/proxy_wrappers.rb +6 -4
  123. data/lib/active_support/deprecation/reporting.rb +7 -7
  124. data/lib/active_support/duration.rb +30 -26
  125. data/lib/active_support/duration/iso8601_parser.rb +66 -65
  126. data/lib/active_support/duration/iso8601_serializer.rb +11 -9
  127. data/lib/active_support/evented_file_update_checker.rb +59 -60
  128. data/lib/active_support/execution_wrapper.rb +3 -3
  129. data/lib/active_support/executor.rb +1 -1
  130. data/lib/active_support/file_update_checker.rb +54 -50
  131. data/lib/active_support/gem_version.rb +3 -3
  132. data/lib/active_support/gzip.rb +5 -5
  133. data/lib/active_support/hash_with_indifferent_access.rb +10 -20
  134. data/lib/active_support/i18n.rb +5 -5
  135. data/lib/active_support/i18n_railtie.rb +11 -10
  136. data/lib/active_support/inflections.rb +11 -11
  137. data/lib/active_support/inflector.rb +5 -5
  138. data/lib/active_support/inflector/inflections.rb +11 -9
  139. data/lib/active_support/inflector/methods.rb +51 -50
  140. data/lib/active_support/inflector/transliterate.rb +8 -11
  141. data/lib/active_support/json.rb +2 -2
  142. data/lib/active_support/json/decoding.rb +3 -3
  143. data/lib/active_support/json/encoding.rb +8 -7
  144. data/lib/active_support/key_generator.rb +17 -17
  145. data/lib/active_support/lazy_load_hooks.rb +12 -30
  146. data/lib/active_support/log_subscriber.rb +5 -5
  147. data/lib/active_support/log_subscriber/test_helper.rb +9 -9
  148. data/lib/active_support/logger.rb +3 -3
  149. data/lib/active_support/logger_silence.rb +3 -3
  150. data/lib/active_support/logger_thread_safe_level.rb +1 -1
  151. data/lib/active_support/message_encryptor.rb +72 -35
  152. data/lib/active_support/message_verifier.rb +7 -7
  153. data/lib/active_support/multibyte.rb +2 -2
  154. data/lib/active_support/multibyte/chars.rb +23 -21
  155. data/lib/active_support/multibyte/unicode.rb +68 -89
  156. data/lib/active_support/notifications.rb +5 -5
  157. data/lib/active_support/notifications/fanout.rb +3 -3
  158. data/lib/active_support/notifications/instrumenter.rb +5 -5
  159. data/lib/active_support/number_helper.rb +4 -4
  160. data/lib/active_support/number_helper/number_converter.rb +11 -11
  161. data/lib/active_support/number_helper/number_to_currency_converter.rb +3 -3
  162. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -2
  163. data/lib/active_support/number_helper/number_to_human_converter.rb +6 -6
  164. data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -11
  165. data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
  166. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -3
  167. data/lib/active_support/number_helper/number_to_rounded_converter.rb +6 -6
  168. data/lib/active_support/option_merger.rb +1 -1
  169. data/lib/active_support/ordered_hash.rb +3 -3
  170. data/lib/active_support/ordered_options.rb +6 -4
  171. data/lib/active_support/per_thread_registry.rb +5 -5
  172. data/lib/active_support/rails.rb +12 -6
  173. data/lib/active_support/railtie.rb +3 -3
  174. data/lib/active_support/reloader.rb +1 -1
  175. data/lib/active_support/rescuable.rb +8 -14
  176. data/lib/active_support/security_utils.rb +1 -1
  177. data/lib/active_support/string_inquirer.rb +8 -2
  178. data/lib/active_support/subscriber.rb +9 -5
  179. data/lib/active_support/tagged_logging.rb +4 -4
  180. data/lib/active_support/test_case.rb +12 -29
  181. data/lib/active_support/testing/assertions.rb +100 -2
  182. data/lib/active_support/testing/autorun.rb +6 -2
  183. data/lib/active_support/testing/constant_lookup.rb +0 -1
  184. data/lib/active_support/testing/declarative.rb +1 -1
  185. data/lib/active_support/testing/deprecation.rb +3 -2
  186. data/lib/active_support/testing/isolation.rb +13 -22
  187. data/lib/active_support/testing/method_call_assertions.rb +1 -1
  188. data/lib/active_support/testing/setup_and_teardown.rb +2 -2
  189. data/lib/active_support/testing/stream.rb +28 -28
  190. data/lib/active_support/testing/tagged_logging.rb +1 -1
  191. data/lib/active_support/testing/time_helpers.rb +45 -12
  192. data/lib/active_support/time.rb +12 -12
  193. data/lib/active_support/time_with_zone.rb +16 -26
  194. data/lib/active_support/values/time_zone.rb +40 -46
  195. data/lib/active_support/values/unicode_tables.dat +0 -0
  196. data/lib/active_support/version.rb +1 -1
  197. data/lib/active_support/xml_mini.rb +34 -36
  198. data/lib/active_support/xml_mini/jdom.rb +112 -112
  199. data/lib/active_support/xml_mini/libxml.rb +15 -12
  200. data/lib/active_support/xml_mini/libxmlsax.rb +17 -15
  201. data/lib/active_support/xml_mini/nokogiri.rb +13 -11
  202. data/lib/active_support/xml_mini/nokogirisax.rb +15 -14
  203. data/lib/active_support/xml_mini/rexml.rb +9 -9
  204. metadata +8 -19
  205. data/lib/active_support/concurrency/latch.rb +0 -26
  206. data/lib/active_support/core_ext/kernel/debugger.rb +0 -3
  207. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -3
  208. data/lib/active_support/core_ext/module/qualified_const.rb +0 -70
  209. data/lib/active_support/core_ext/struct.rb +0 -3
  210. data/lib/active_support/core_ext/time/marshal.rb +0 -3
@@ -1,5 +1,5 @@
1
- require 'concurrent/map'
2
- require 'openssl'
1
+ require "concurrent/map"
2
+ require "openssl"
3
3
 
4
4
  module ActiveSupport
5
5
  # KeyGenerator is a simple wrapper around OpenSSL's implementation of PBKDF2.
@@ -17,7 +17,7 @@ module ActiveSupport
17
17
  # Returns a derived key suitable for use. The default key_size is chosen
18
18
  # to be compatible with the default settings of ActiveSupport::MessageVerifier.
19
19
  # i.e. OpenSSL::Digest::SHA1#block_length
20
- def generate_key(salt, key_size=64)
20
+ def generate_key(salt, key_size = 64)
21
21
  OpenSSL::PKCS5.pbkdf2_hmac_sha1(@secret, salt, @iterations, key_size)
22
22
  end
23
23
  end
@@ -51,21 +51,21 @@ module ActiveSupport
51
51
 
52
52
  private
53
53
 
54
- # To prevent users from using something insecure like "Password" we make sure that the
55
- # secret they've provided is at least 30 characters in length.
56
- def ensure_secret_secure(secret)
57
- if secret.blank?
58
- raise ArgumentError, "A secret is required to generate an integrity hash " \
59
- "for cookie session data. Set a secret_key_base of at least " \
60
- "#{SECRET_MIN_LENGTH} characters in config/secrets.yml."
61
- end
54
+ # To prevent users from using something insecure like "Password" we make sure that the
55
+ # secret they've provided is at least 30 characters in length.
56
+ def ensure_secret_secure(secret)
57
+ if secret.blank?
58
+ raise ArgumentError, "A secret is required to generate an integrity hash " \
59
+ "for cookie session data. Set a secret_key_base of at least " \
60
+ "#{SECRET_MIN_LENGTH} characters in config/secrets.yml."
61
+ end
62
62
 
63
- if secret.length < SECRET_MIN_LENGTH
64
- raise ArgumentError, "Secret should be something secure, " \
65
- "like \"#{SecureRandom.hex(16)}\". The value you " \
66
- "provided, \"#{secret}\", is shorter than the minimum length " \
67
- "of #{SECRET_MIN_LENGTH} characters."
63
+ if secret.length < SECRET_MIN_LENGTH
64
+ raise ArgumentError, "Secret should be something secure, " \
65
+ "like \"#{SecureRandom.hex(16)}\". The value you " \
66
+ "provided, \"#{secret}\", is shorter than the minimum length " \
67
+ "of #{SECRET_MIN_LENGTH} characters."
68
+ end
68
69
  end
69
- end
70
70
  end
71
71
  end
@@ -15,9 +15,9 @@ module ActiveSupport
15
15
  # end
16
16
  # end
17
17
  #
18
- # When the entirety of +activerecord/lib/active_record/base.rb+ has been
18
+ # When the entirety of +ActiveRecord::Base+ has been
19
19
  # evaluated then +run_load_hooks+ is invoked. The very last line of
20
- # +activerecord/lib/active_record/base.rb+ is:
20
+ # +ActiveRecord::Base+ is:
21
21
  #
22
22
  # ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base)
23
23
  module LazyLoadHooks
@@ -25,51 +25,33 @@ module ActiveSupport
25
25
  base.class_eval do
26
26
  @load_hooks = Hash.new { |h, k| h[k] = [] }
27
27
  @loaded = Hash.new { |h, k| h[k] = [] }
28
- @run_once = Hash.new { |h, k| h[k] = [] }
29
28
  end
30
29
  end
31
30
 
32
31
  # Declares a block that will be executed when a Rails component is fully
33
32
  # loaded.
34
- #
35
- # Options:
36
- #
37
- # * <tt>:yield</tt> - Yields the object that run_load_hooks to +block+.
38
- # * <tt>:run_once</tt> - Given +block+ will run only once.
39
33
  def on_load(name, options = {}, &block)
40
34
  @loaded[name].each do |base|
41
- execute_hook(name, base, options, block)
35
+ execute_hook(base, options, block)
42
36
  end
43
37
 
44
38
  @load_hooks[name] << [block, options]
45
39
  end
46
40
 
41
+ def execute_hook(base, options, block)
42
+ if options[:yield]
43
+ block.call(base)
44
+ else
45
+ base.instance_eval(&block)
46
+ end
47
+ end
48
+
47
49
  def run_load_hooks(name, base = Object)
48
50
  @loaded[name] << base
49
51
  @load_hooks[name].each do |hook, options|
50
- execute_hook(name, base, options, hook)
52
+ execute_hook(base, options, hook)
51
53
  end
52
54
  end
53
-
54
- private
55
-
56
- def with_execution_control(name, block, once)
57
- unless @run_once[name].include?(block)
58
- @run_once[name] << block if once
59
-
60
- yield
61
- end
62
- end
63
-
64
- def execute_hook(name, base, options, block)
65
- with_execution_control(name, block, options[:run_once]) do
66
- if options[:yield]
67
- block.call(base)
68
- else
69
- base.instance_eval(&block)
70
- end
71
- end
72
- end
73
55
  end
74
56
 
75
57
  extend LazyLoadHooks
@@ -1,6 +1,6 @@
1
- require 'active_support/core_ext/module/attribute_accessors'
2
- require 'active_support/core_ext/class/attribute'
3
- require 'active_support/subscriber'
1
+ require "active_support/core_ext/module/attribute_accessors"
2
+ require "active_support/core_ext/class/attribute"
3
+ require "active_support/subscriber"
4
4
 
5
5
  module ActiveSupport
6
6
  # ActiveSupport::LogSubscriber is an object set to consume
@@ -85,7 +85,7 @@ module ActiveSupport
85
85
  logger.error "Could not log #{name.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
86
86
  end
87
87
 
88
- protected
88
+ private
89
89
 
90
90
  %w(info debug warn error fatal unknown).each do |level|
91
91
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
@@ -99,7 +99,7 @@ module ActiveSupport
99
99
  # option is set to +true+, it also adds bold to the string. This is based
100
100
  # on the Highline implementation and will automatically append CLEAR to the
101
101
  # end of the returned String.
102
- def color(text, color, bold=false)
102
+ def color(text, color, bold = false) # :doc:
103
103
  return text unless colorize_logging
104
104
  color = self.class.const_get(color.upcase) if color.is_a?(Symbol)
105
105
  bold = bold ? BOLD : ""
@@ -1,6 +1,6 @@
1
- require 'active_support/log_subscriber'
2
- require 'active_support/logger'
3
- require 'active_support/notifications'
1
+ require "active_support/log_subscriber"
2
+ require "active_support/logger"
3
+ require "active_support/notifications"
4
4
 
5
5
  module ActiveSupport
6
6
  class LogSubscriber
@@ -58,15 +58,15 @@ module ActiveSupport
58
58
  def initialize(level = DEBUG)
59
59
  @flush_count = 0
60
60
  @level = level
61
- @logged = Hash.new { |h,k| h[k] = [] }
61
+ @logged = Hash.new { |h, k| h[k] = [] }
62
62
  end
63
63
 
64
64
  def method_missing(level, message = nil)
65
- if block_given?
66
- @logged[level] << yield
67
- else
68
- @logged[level] << message
69
- end
65
+ if block_given?
66
+ @logged[level] << yield
67
+ else
68
+ @logged[level] << message
69
+ end
70
70
  end
71
71
 
72
72
  def logged(level)
@@ -1,6 +1,6 @@
1
- require 'active_support/logger_silence'
2
- require 'active_support/logger_thread_safe_level'
3
- require 'logger'
1
+ require "active_support/logger_silence"
2
+ require "active_support/logger_thread_safe_level"
3
+ require "logger"
4
4
 
5
5
  module ActiveSupport
6
6
  class Logger < ::Logger
@@ -1,6 +1,6 @@
1
- require 'active_support/concern'
2
- require 'active_support/core_ext/module/attribute_accessors'
3
- require 'concurrent'
1
+ require "active_support/concern"
2
+ require "active_support/core_ext/module/attribute_accessors"
3
+ require "concurrent"
4
4
 
5
5
  module LoggerSilence
6
6
  extend ActiveSupport::Concern
@@ -1,4 +1,4 @@
1
- require 'active_support/concern'
1
+ require "active_support/concern"
2
2
 
3
3
  module ActiveSupport
4
4
  module LoggerThreadSafeLevel # :nodoc:
@@ -1,6 +1,7 @@
1
- require 'openssl'
2
- require 'base64'
3
- require 'active_support/core_ext/array/extract_options'
1
+ require "openssl"
2
+ require "base64"
3
+ require "active_support/core_ext/array/extract_options"
4
+ require "active_support/message_verifier"
4
5
 
5
6
  module ActiveSupport
6
7
  # MessageEncryptor is a simple way to encrypt values which get stored
@@ -30,6 +31,16 @@ module ActiveSupport
30
31
  end
31
32
  end
32
33
 
34
+ module NullVerifier #:nodoc:
35
+ def self.verify(value)
36
+ value
37
+ end
38
+
39
+ def self.generate(value)
40
+ value
41
+ end
42
+ end
43
+
33
44
  class InvalidMessage < StandardError; end
34
45
  OpenSSLCipherError = OpenSSL::Cipher::CipherError
35
46
 
@@ -42,15 +53,17 @@ module ActiveSupport
42
53
  # Options:
43
54
  # * <tt>:cipher</tt> - Cipher to use. Can be any cipher returned by
44
55
  # <tt>OpenSSL::Cipher.ciphers</tt>. Default is 'aes-256-cbc'.
45
- # * <tt>:digest</tt> - String of digest to use for signing. Default is +SHA1+.
56
+ # * <tt>:digest</tt> - String of digest to use for signing. Default is
57
+ # +SHA1+. Ignored when using an AEAD cipher like 'aes-256-gcm'.
46
58
  # * <tt>:serializer</tt> - Object serializer to use. Default is +Marshal+.
47
59
  def initialize(secret, *signature_key_or_options)
48
60
  options = signature_key_or_options.extract_options!
49
61
  sign_secret = signature_key_or_options.first
50
62
  @secret = secret
51
63
  @sign_secret = sign_secret
52
- @cipher = options[:cipher] || 'aes-256-cbc'
53
- @verifier = MessageVerifier.new(@sign_secret || @secret, digest: options[:digest] || 'SHA1', serializer: NullSerializer)
64
+ @cipher = options[:cipher] || "aes-256-cbc"
65
+ @digest = options[:digest] || "SHA1" unless aead_mode?
66
+ @verifier = resolve_verifier
54
67
  @serializer = options[:serializer] || Marshal
55
68
  end
56
69
 
@@ -73,42 +86,66 @@ module ActiveSupport
73
86
 
74
87
  private
75
88
 
76
- def _encrypt(value)
77
- cipher = new_cipher
78
- cipher.encrypt
79
- cipher.key = @secret
89
+ def _encrypt(value)
90
+ cipher = new_cipher
91
+ cipher.encrypt
92
+ cipher.key = @secret
80
93
 
81
- # Rely on OpenSSL for the initialization vector
82
- iv = cipher.random_iv
94
+ # Rely on OpenSSL for the initialization vector
95
+ iv = cipher.random_iv
96
+ cipher.auth_data = "" if aead_mode?
83
97
 
84
- encrypted_data = cipher.update(@serializer.dump(value))
85
- encrypted_data << cipher.final
86
-
87
- "#{::Base64.strict_encode64 encrypted_data}--#{::Base64.strict_encode64 iv}"
88
- end
98
+ encrypted_data = cipher.update(@serializer.dump(value))
99
+ encrypted_data << cipher.final
89
100
 
90
- def _decrypt(encrypted_message)
91
- cipher = new_cipher
92
- encrypted_data, iv = encrypted_message.split("--".freeze).map {|v| ::Base64.strict_decode64(v)}
101
+ blob = "#{::Base64.strict_encode64 encrypted_data}--#{::Base64.strict_encode64 iv}"
102
+ blob << "--#{::Base64.strict_encode64 cipher.auth_tag}" if aead_mode?
103
+ blob
104
+ end
93
105
 
94
- cipher.decrypt
95
- cipher.key = @secret
96
- cipher.iv = iv
106
+ def _decrypt(encrypted_message)
107
+ cipher = new_cipher
108
+ encrypted_data, iv, auth_tag = encrypted_message.split("--".freeze).map { |v| ::Base64.strict_decode64(v) }
109
+
110
+ # Currently the OpenSSL bindings do not raise an error if auth_tag is
111
+ # truncated, which would allow an attacker to easily forge it. See
112
+ # https://github.com/ruby/openssl/issues/63
113
+ raise InvalidMessage if aead_mode? && auth_tag.bytes.length != 16
114
+
115
+ cipher.decrypt
116
+ cipher.key = @secret
117
+ cipher.iv = iv
118
+ if aead_mode?
119
+ cipher.auth_tag = auth_tag
120
+ cipher.auth_data = ""
121
+ end
122
+
123
+ decrypted_data = cipher.update(encrypted_data)
124
+ decrypted_data << cipher.final
125
+
126
+ @serializer.load(decrypted_data)
127
+ rescue OpenSSLCipherError, TypeError, ArgumentError
128
+ raise InvalidMessage
129
+ end
97
130
 
98
- decrypted_data = cipher.update(encrypted_data)
99
- decrypted_data << cipher.final
131
+ def new_cipher
132
+ OpenSSL::Cipher.new(@cipher)
133
+ end
100
134
 
101
- @serializer.load(decrypted_data)
102
- rescue OpenSSLCipherError, TypeError, ArgumentError
103
- raise InvalidMessage
104
- end
135
+ def verifier
136
+ @verifier
137
+ end
105
138
 
106
- def new_cipher
107
- OpenSSL::Cipher.new(@cipher)
108
- end
139
+ def aead_mode?
140
+ @aead_mode ||= new_cipher.authenticated?
141
+ end
109
142
 
110
- def verifier
111
- @verifier
112
- end
143
+ def resolve_verifier
144
+ if aead_mode?
145
+ NullVerifier
146
+ else
147
+ MessageVerifier.new(@sign_secret || @secret, digest: @digest, serializer: NullSerializer)
148
+ end
149
+ end
113
150
  end
114
151
  end
@@ -1,6 +1,6 @@
1
- require 'base64'
2
- require 'active_support/core_ext/object/blank'
3
- require 'active_support/security_utils'
1
+ require "base64"
2
+ require "active_support/core_ext/object/blank"
3
+ require "active_support/security_utils"
4
4
 
5
5
  module ActiveSupport
6
6
  # +MessageVerifier+ makes it easy to generate and verify messages which are
@@ -34,9 +34,9 @@ module ActiveSupport
34
34
  class InvalidSignature < StandardError; end
35
35
 
36
36
  def initialize(secret, options = {})
37
- raise ArgumentError, 'Secret should not be nil.' unless secret
37
+ raise ArgumentError, "Secret should not be nil." unless secret
38
38
  @secret = secret
39
- @digest = options[:digest] || 'SHA1'
39
+ @digest = options[:digest] || "SHA1"
40
40
  @serializer = options[:serializer] || Marshal
41
41
  end
42
42
 
@@ -83,7 +83,7 @@ module ActiveSupport
83
83
  data = signed_message.split("--".freeze)[0]
84
84
  @serializer.load(decode(data))
85
85
  rescue ArgumentError => argument_error
86
- return if argument_error.message =~ %r{invalid base64}
86
+ return if argument_error.message.include?("invalid base64")
87
87
  raise
88
88
  end
89
89
  end
@@ -127,7 +127,7 @@ module ActiveSupport
127
127
  end
128
128
 
129
129
  def generate_digest(data)
130
- require 'openssl' unless defined?(OpenSSL)
130
+ require "openssl" unless defined?(OpenSSL)
131
131
  OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get(@digest).new, @secret, data)
132
132
  end
133
133
  end
@@ -1,7 +1,7 @@
1
1
  module ActiveSupport #:nodoc:
2
2
  module Multibyte
3
- autoload :Chars, 'active_support/multibyte/chars'
4
- autoload :Unicode, 'active_support/multibyte/unicode'
3
+ autoload :Chars, "active_support/multibyte/chars"
4
+ autoload :Unicode, "active_support/multibyte/unicode"
5
5
 
6
6
  # The proxy class returned when calling mb_chars. You can use this accessor
7
7
  # to configure your own proxy class so you can support other encodings. See
@@ -1,7 +1,8 @@
1
- require 'active_support/json'
2
- require 'active_support/core_ext/string/access'
3
- require 'active_support/core_ext/string/behavior'
4
- require 'active_support/core_ext/module/delegation'
1
+ require "active_support/json"
2
+ require "active_support/core_ext/string/access"
3
+ require "active_support/core_ext/string/behavior"
4
+ require "active_support/core_ext/module/delegation"
5
+ require "active_support/core_ext/regexp"
5
6
 
6
7
  module ActiveSupport #:nodoc:
7
8
  module Multibyte #:nodoc:
@@ -15,7 +16,8 @@ module ActiveSupport #:nodoc:
15
16
  # through the +mb_chars+ method. Methods which would normally return a
16
17
  # String object now return a Chars object so methods can be chained.
17
18
  #
18
- # 'The Perfect String '.mb_chars.downcase.strip.normalize # => "the perfect string"
19
+ # 'The Perfect String '.mb_chars.downcase.strip.normalize
20
+ # # => #<ActiveSupport::Multibyte::Chars:0x007fdc434ccc10 @wrapped_string="the perfect string">
19
21
  #
20
22
  # Chars objects are perfectly interchangeable with String objects as long as
21
23
  # no explicit class checks are made. If certain methods do explicitly check
@@ -45,7 +47,7 @@ module ActiveSupport #:nodoc:
45
47
  alias to_s wrapped_string
46
48
  alias to_str wrapped_string
47
49
 
48
- delegate :<=>, :=~, :acts_like_string?, :to => :wrapped_string
50
+ delegate :<=>, :=~, :acts_like_string?, to: :wrapped_string
49
51
 
50
52
  # Creates a new Chars instance by wrapping _string_.
51
53
  def initialize(string)
@@ -56,7 +58,7 @@ module ActiveSupport #:nodoc:
56
58
  # Forward all undefined methods to the wrapped string.
57
59
  def method_missing(method, *args, &block)
58
60
  result = @wrapped_string.__send__(method, *args, &block)
59
- if method.to_s =~ /!$/
61
+ if /!$/.match?(method)
60
62
  self if result
61
63
  else
62
64
  result.kind_of?(String) ? chars(result) : result
@@ -86,7 +88,7 @@ module ActiveSupport #:nodoc:
86
88
  end
87
89
 
88
90
  # Works like <tt>String#slice!</tt>, but returns an instance of
89
- # Chars, or nil if the string was not modified. The string will not be
91
+ # Chars, or +nil+ if the string was not modified. The string will not be
90
92
  # modified if the range given is out of bounds
91
93
  #
92
94
  # string = 'Welcome'
@@ -105,7 +107,7 @@ module ActiveSupport #:nodoc:
105
107
  #
106
108
  # 'Café'.mb_chars.reverse.to_s # => 'éfaC'
107
109
  def reverse
108
- chars(Unicode.unpack_graphemes(@wrapped_string).reverse.flatten.pack('U*'))
110
+ chars(Unicode.unpack_graphemes(@wrapped_string).reverse.flatten.pack("U*"))
109
111
  end
110
112
 
111
113
  # Limits the byte size of the string to a number of bytes without breaking
@@ -133,7 +135,7 @@ module ActiveSupport #:nodoc:
133
135
 
134
136
  # Converts characters in the string to the opposite case.
135
137
  #
136
- # 'El Cañón".mb_chars.swapcase.to_s # => "eL cAÑÓN"
138
+ # 'El Cañón'.mb_chars.swapcase.to_s # => "eL cAÑÓN"
137
139
  def swapcase
138
140
  chars Unicode.swapcase(@wrapped_string)
139
141
  end
@@ -142,15 +144,15 @@ module ActiveSupport #:nodoc:
142
144
  #
143
145
  # 'über'.mb_chars.capitalize.to_s # => "Über"
144
146
  def capitalize
145
- (slice(0) || chars('')).upcase + (slice(1..-1) || chars('')).downcase
147
+ (slice(0) || chars("")).upcase + (slice(1..-1) || chars("")).downcase
146
148
  end
147
149
 
148
150
  # Capitalizes the first letter of every word, when possible.
149
151
  #
150
- # "ÉL QUE SE ENTERÓ".mb_chars.titleize # => "Él Que Se Enteró"
151
- # "日本語".mb_chars.titleize # => "日本語"
152
+ # "ÉL QUE SE ENTERÓ".mb_chars.titleize.to_s # => "Él Que Se Enteró"
153
+ # "日本語".mb_chars.titleize.to_s # => "日本語"
152
154
  def titleize
153
- chars(downcase.to_s.gsub(/\b('?\S)/u) { Unicode.upcase($1)})
155
+ chars(downcase.to_s.gsub(/\b('?\S)/u) { Unicode.upcase($1) })
154
156
  end
155
157
  alias_method :titlecase, :titleize
156
158
 
@@ -170,7 +172,7 @@ module ActiveSupport #:nodoc:
170
172
  # 'é'.length # => 2
171
173
  # 'é'.mb_chars.decompose.to_s.length # => 3
172
174
  def decompose
173
- chars(Unicode.decompose(:canonical, @wrapped_string.codepoints.to_a).pack('U*'))
175
+ chars(Unicode.decompose(:canonical, @wrapped_string.codepoints.to_a).pack("U*"))
174
176
  end
175
177
 
176
178
  # Performs composition on all the characters.
@@ -178,7 +180,7 @@ module ActiveSupport #:nodoc:
178
180
  # 'é'.length # => 3
179
181
  # 'é'.mb_chars.compose.to_s.length # => 2
180
182
  def compose
181
- chars(Unicode.compose(@wrapped_string.codepoints.to_a).pack('U*'))
183
+ chars(Unicode.compose(@wrapped_string.codepoints.to_a).pack("U*"))
182
184
  end
183
185
 
184
186
  # Returns the number of grapheme clusters in the string.
@@ -209,21 +211,21 @@ module ActiveSupport #:nodoc:
209
211
  end
210
212
  end
211
213
 
212
- protected
214
+ private
213
215
 
214
- def translate_offset(byte_offset) #:nodoc:
216
+ def translate_offset(byte_offset)
215
217
  return nil if byte_offset.nil?
216
- return 0 if @wrapped_string == ''
218
+ return 0 if @wrapped_string == ""
217
219
 
218
220
  begin
219
- @wrapped_string.byteslice(0...byte_offset).unpack('U*').length
221
+ @wrapped_string.byteslice(0...byte_offset).unpack("U*").length
220
222
  rescue ArgumentError
221
223
  byte_offset -= 1
222
224
  retry
223
225
  end
224
226
  end
225
227
 
226
- def chars(string) #:nodoc:
228
+ def chars(string)
227
229
  self.class.new(string)
228
230
  end
229
231
  end