activesupport 3.2.22.5 → 4.0.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 (214) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +364 -135
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -4
  5. data/lib/active_support/backtrace_cleaner.rb +33 -25
  6. data/lib/active_support/basic_object.rb +7 -17
  7. data/lib/active_support/benchmarkable.rb +19 -15
  8. data/lib/active_support/buffered_logger.rb +9 -113
  9. data/lib/active_support/cache/file_store.rb +14 -14
  10. data/lib/active_support/cache/mem_cache_store.rb +24 -30
  11. data/lib/active_support/cache/memory_store.rb +2 -0
  12. data/lib/active_support/cache/strategy/local_cache.rb +48 -37
  13. data/lib/active_support/cache.rb +228 -183
  14. data/lib/active_support/callbacks.rb +201 -253
  15. data/lib/active_support/concern.rb +16 -23
  16. data/lib/active_support/concurrency/latch.rb +27 -0
  17. data/lib/active_support/configurable.rb +69 -12
  18. data/lib/active_support/core_ext/array/access.rb +17 -9
  19. data/lib/active_support/core_ext/array/conversions.rb +115 -55
  20. data/lib/active_support/core_ext/array/extract_options.rb +2 -2
  21. data/lib/active_support/core_ext/array/grouping.rb +21 -22
  22. data/lib/active_support/core_ext/array/uniq_by.rb +12 -9
  23. data/lib/active_support/core_ext/array/wrap.rb +13 -16
  24. data/lib/active_support/core_ext/array.rb +0 -1
  25. data/lib/active_support/core_ext/benchmark.rb +7 -0
  26. data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -24
  27. data/lib/active_support/core_ext/class/attribute.rb +40 -32
  28. data/lib/active_support/core_ext/class/attribute_accessors.rb +14 -12
  29. data/lib/active_support/core_ext/class/delegating_attributes.rb +15 -19
  30. data/lib/active_support/core_ext/class/subclasses.rb +11 -5
  31. data/lib/active_support/core_ext/date/calculations.rb +44 -187
  32. data/lib/active_support/core_ext/date/conversions.rb +16 -38
  33. data/lib/active_support/core_ext/date/zones.rb +25 -2
  34. data/lib/active_support/core_ext/date.rb +5 -0
  35. data/lib/active_support/core_ext/date_and_time/calculations.rb +232 -0
  36. data/lib/active_support/core_ext/date_time/acts_like.rb +0 -1
  37. data/lib/active_support/core_ext/date_time/calculations.rb +77 -62
  38. data/lib/active_support/core_ext/date_time/conversions.rb +21 -33
  39. data/lib/active_support/core_ext/date_time/zones.rb +11 -8
  40. data/lib/active_support/core_ext/date_time.rb +4 -0
  41. data/lib/active_support/core_ext/enumerable.rb +26 -73
  42. data/lib/active_support/core_ext/file/atomic.rb +27 -11
  43. data/lib/active_support/core_ext/file.rb +0 -1
  44. data/lib/active_support/core_ext/hash/conversions.rb +145 -79
  45. data/lib/active_support/core_ext/hash/deep_merge.rb +14 -8
  46. data/lib/active_support/core_ext/hash/diff.rb +5 -4
  47. data/lib/active_support/core_ext/hash/except.rb +1 -9
  48. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -5
  49. data/lib/active_support/core_ext/hash/keys.rb +108 -24
  50. data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -3
  51. data/lib/active_support/core_ext/hash/slice.rb +12 -12
  52. data/lib/active_support/core_ext/hash.rb +0 -1
  53. data/lib/active_support/core_ext/integer/inflections.rb +13 -1
  54. data/lib/active_support/core_ext/integer/time.rb +17 -12
  55. data/lib/active_support/core_ext/kernel/debugger.rb +2 -2
  56. data/lib/active_support/core_ext/kernel/reporting.rb +36 -22
  57. data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -7
  58. data/lib/active_support/core_ext/load_error.rb +7 -5
  59. data/lib/active_support/core_ext/logger.rb +7 -23
  60. data/lib/active_support/core_ext/marshal.rb +21 -0
  61. data/lib/active_support/core_ext/module/aliasing.rb +8 -9
  62. data/lib/active_support/core_ext/module/anonymous.rb +2 -7
  63. data/lib/active_support/core_ext/module/attr_internal.rb +0 -1
  64. data/lib/active_support/core_ext/module/attribute_accessors.rb +12 -10
  65. data/lib/active_support/core_ext/module/delegation.rb +92 -49
  66. data/lib/active_support/core_ext/module/deprecation.rb +19 -3
  67. data/lib/active_support/core_ext/module/introspection.rb +17 -27
  68. data/lib/active_support/core_ext/module/qualified_const.rb +8 -20
  69. data/lib/active_support/core_ext/module/remove_method.rb +1 -5
  70. data/lib/active_support/core_ext/module.rb +1 -3
  71. data/lib/active_support/core_ext/numeric/conversions.rb +135 -0
  72. data/lib/active_support/core_ext/numeric/time.rb +6 -6
  73. data/lib/active_support/core_ext/numeric.rb +1 -0
  74. data/lib/active_support/core_ext/object/acts_like.rb +4 -4
  75. data/lib/active_support/core_ext/object/blank.rb +7 -23
  76. data/lib/active_support/core_ext/object/deep_dup.rb +46 -0
  77. data/lib/active_support/core_ext/object/duplicable.rb +1 -30
  78. data/lib/active_support/core_ext/object/inclusion.rb +8 -7
  79. data/lib/active_support/core_ext/object/instance_variables.rb +7 -12
  80. data/lib/active_support/core_ext/object/to_json.rb +8 -0
  81. data/lib/active_support/core_ext/object/to_param.rb +5 -2
  82. data/lib/active_support/core_ext/object/try.rb +46 -25
  83. data/lib/active_support/core_ext/object/with_options.rb +7 -8
  84. data/lib/active_support/core_ext/object.rb +1 -0
  85. data/lib/active_support/core_ext/proc.rb +3 -0
  86. data/lib/active_support/core_ext/range/conversions.rb +0 -2
  87. data/lib/active_support/core_ext/range/include_range.rb +3 -1
  88. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  89. data/lib/active_support/core_ext/range.rb +0 -2
  90. data/lib/active_support/core_ext/string/access.rb +95 -90
  91. data/lib/active_support/core_ext/string/conversions.rb +27 -38
  92. data/lib/active_support/core_ext/string/encoding.rb +6 -9
  93. data/lib/active_support/core_ext/string/filters.rb +24 -18
  94. data/lib/active_support/core_ext/string/indent.rb +43 -0
  95. data/lib/active_support/core_ext/string/inflections.rb +70 -60
  96. data/lib/active_support/core_ext/string/inquiry.rb +2 -2
  97. data/lib/active_support/core_ext/string/multibyte.rb +41 -64
  98. data/lib/active_support/core_ext/string/output_safety.rb +59 -51
  99. data/lib/active_support/core_ext/string/zones.rb +13 -0
  100. data/lib/active_support/core_ext/string.rb +2 -3
  101. data/lib/active_support/core_ext/struct.rb +6 -0
  102. data/lib/active_support/core_ext/thread.rb +74 -0
  103. data/lib/active_support/core_ext/time/calculations.rb +108 -184
  104. data/lib/active_support/core_ext/time/conversions.rb +27 -51
  105. data/lib/active_support/core_ext/time/marshal.rb +0 -27
  106. data/lib/active_support/core_ext/time/zones.rb +27 -17
  107. data/lib/active_support/core_ext/time.rb +5 -0
  108. data/lib/active_support/core_ext/uri.rb +13 -17
  109. data/lib/active_support/core_ext.rb +3 -2
  110. data/lib/active_support/dependencies/autoload.rb +47 -20
  111. data/lib/active_support/dependencies.rb +160 -141
  112. data/lib/active_support/deprecation/behaviors.rb +44 -30
  113. data/lib/active_support/deprecation/instance_delegator.rb +24 -0
  114. data/lib/active_support/deprecation/method_wrappers.rb +33 -18
  115. data/lib/active_support/deprecation/proxy_wrappers.rb +58 -13
  116. data/lib/active_support/deprecation/reporting.rb +40 -11
  117. data/lib/active_support/deprecation.rb +39 -14
  118. data/lib/active_support/descendants_tracker.rb +34 -19
  119. data/lib/active_support/duration.rb +6 -8
  120. data/lib/active_support/file_update_checker.rb +63 -47
  121. data/lib/active_support/gzip.rb +11 -5
  122. data/lib/active_support/hash_with_indifferent_access.rb +127 -42
  123. data/lib/active_support/i18n.rb +4 -0
  124. data/lib/active_support/i18n_railtie.rb +5 -22
  125. data/lib/active_support/inflections.rb +14 -12
  126. data/lib/active_support/inflector/inflections.rb +108 -71
  127. data/lib/active_support/inflector/methods.rb +181 -160
  128. data/lib/active_support/inflector/transliterate.rb +16 -17
  129. data/lib/active_support/json/decoding.rb +18 -17
  130. data/lib/active_support/json/encoding.rb +93 -39
  131. data/lib/active_support/json/variable.rb +10 -1
  132. data/lib/active_support/key_generator.rb +75 -0
  133. data/lib/active_support/lazy_load_hooks.rb +21 -19
  134. data/lib/active_support/locale/en.yml +100 -3
  135. data/lib/active_support/log_subscriber/test_helper.rb +18 -15
  136. data/lib/active_support/log_subscriber.rb +35 -52
  137. data/lib/active_support/logger.rb +57 -0
  138. data/lib/active_support/logger_silence.rb +24 -0
  139. data/lib/active_support/message_encryptor.rb +38 -35
  140. data/lib/active_support/message_verifier.rb +9 -15
  141. data/lib/active_support/multibyte/chars.rb +80 -333
  142. data/lib/active_support/multibyte/unicode.rb +74 -64
  143. data/lib/active_support/multibyte.rb +5 -28
  144. data/lib/active_support/notifications/fanout.rb +112 -18
  145. data/lib/active_support/notifications/instrumenter.rb +33 -14
  146. data/lib/active_support/notifications.rb +79 -26
  147. data/lib/active_support/number_helper.rb +637 -0
  148. data/lib/active_support/ordered_hash.rb +8 -190
  149. data/lib/active_support/ordered_options.rb +21 -23
  150. data/lib/active_support/per_thread_registry.rb +52 -0
  151. data/lib/active_support/proxy_object.rb +13 -0
  152. data/lib/active_support/rails.rb +27 -0
  153. data/lib/active_support/railtie.rb +12 -32
  154. data/lib/active_support/rescuable.rb +9 -4
  155. data/lib/active_support/string_inquirer.rb +13 -8
  156. data/lib/active_support/subscriber.rb +93 -0
  157. data/lib/active_support/tagged_logging.rb +51 -73
  158. data/lib/active_support/test_case.rb +46 -17
  159. data/lib/active_support/testing/assertions.rb +56 -26
  160. data/lib/active_support/testing/autorun.rb +5 -0
  161. data/lib/active_support/testing/constant_lookup.rb +54 -0
  162. data/lib/active_support/testing/declarative.rb +1 -1
  163. data/lib/active_support/testing/deprecation.rb +0 -19
  164. data/lib/active_support/testing/isolation.rb +29 -58
  165. data/lib/active_support/testing/pending.rb +5 -43
  166. data/lib/active_support/testing/setup_and_teardown.rb +6 -92
  167. data/lib/active_support/testing/tagged_logging.rb +25 -0
  168. data/lib/active_support/time.rb +6 -21
  169. data/lib/active_support/time_with_zone.rb +80 -43
  170. data/lib/active_support/values/time_zone.rb +81 -60
  171. data/lib/active_support/values/unicode_tables.dat +0 -0
  172. data/lib/active_support/version.rb +7 -6
  173. data/lib/active_support/xml_mini/jdom.rb +9 -11
  174. data/lib/active_support/xml_mini/libxml.rb +1 -2
  175. data/lib/active_support/xml_mini/libxmlsax.rb +2 -3
  176. data/lib/active_support/xml_mini/nokogiri.rb +1 -2
  177. data/lib/active_support/xml_mini/nokogirisax.rb +2 -3
  178. data/lib/active_support/xml_mini/rexml.rb +6 -8
  179. data/lib/active_support/xml_mini.rb +35 -17
  180. data/lib/active_support.rb +8 -21
  181. metadata +104 -72
  182. data/lib/active_support/base64.rb +0 -54
  183. data/lib/active_support/core_ext/array/random_access.rb +0 -30
  184. data/lib/active_support/core_ext/date/freeze.rb +0 -33
  185. data/lib/active_support/core_ext/exception.rb +0 -3
  186. data/lib/active_support/core_ext/file/path.rb +0 -5
  187. data/lib/active_support/core_ext/float/rounding.rb +0 -19
  188. data/lib/active_support/core_ext/float.rb +0 -1
  189. data/lib/active_support/core_ext/hash/deep_dup.rb +0 -18
  190. data/lib/active_support/core_ext/io.rb +0 -15
  191. data/lib/active_support/core_ext/module/method_names.rb +0 -14
  192. data/lib/active_support/core_ext/module/synchronization.rb +0 -45
  193. data/lib/active_support/core_ext/process/daemon.rb +0 -23
  194. data/lib/active_support/core_ext/process.rb +0 -1
  195. data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
  196. data/lib/active_support/core_ext/range/cover.rb +0 -3
  197. data/lib/active_support/core_ext/rexml.rb +0 -46
  198. data/lib/active_support/core_ext/string/interpolation.rb +0 -2
  199. data/lib/active_support/core_ext/string/xchar.rb +0 -18
  200. data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +0 -10
  201. data/lib/active_support/memoizable.rb +0 -116
  202. data/lib/active_support/multibyte/exceptions.rb +0 -8
  203. data/lib/active_support/multibyte/utils.rb +0 -60
  204. data/lib/active_support/ruby/shim.rb +0 -22
  205. data/lib/active_support/security_utils.rb +0 -27
  206. data/lib/active_support/testing/mochaing.rb +0 -7
  207. data/lib/active_support/testing/performance/jruby.rb +0 -115
  208. data/lib/active_support/testing/performance/rubinius.rb +0 -113
  209. data/lib/active_support/testing/performance/ruby/mri.rb +0 -57
  210. data/lib/active_support/testing/performance/ruby/yarv.rb +0 -57
  211. data/lib/active_support/testing/performance/ruby.rb +0 -152
  212. data/lib/active_support/testing/performance.rb +0 -317
  213. data/lib/active_support/time/autoload.rb +0 -5
  214. data/lib/active_support/whiny_nil.rb +0 -24
@@ -1,12 +1,15 @@
1
1
  require 'active_support/core_ext/module/attribute_accessors'
2
2
  require 'active_support/core_ext/class/attribute'
3
+ require 'active_support/subscriber'
3
4
 
4
5
  module ActiveSupport
5
- # ActiveSupport::LogSubscriber is an object set to consume ActiveSupport::Notifications
6
- # with the sole purpose of logging them. The log subscriber dispatches notifications to
7
- # a registered object based on its given namespace.
6
+ # ActiveSupport::LogSubscriber is an object set to consume
7
+ # ActiveSupport::Notifications with the sole purpose of logging them.
8
+ # The log subscriber dispatches notifications to a registered object based
9
+ # on its given namespace.
8
10
  #
9
- # An example would be Active Record log subscriber responsible for logging queries:
11
+ # An example would be Active Record log subscriber responsible for logging
12
+ # queries:
10
13
  #
11
14
  # module ActiveRecord
12
15
  # class LogSubscriber < ActiveSupport::LogSubscriber
@@ -20,17 +23,18 @@ module ActiveSupport
20
23
  #
21
24
  # ActiveRecord::LogSubscriber.attach_to :active_record
22
25
  #
23
- # Since we need to know all instance methods before attaching the log subscriber,
24
- # the line above should be called after your <tt>ActiveRecord::LogSubscriber</tt> definition.
26
+ # Since we need to know all instance methods before attaching the log
27
+ # subscriber, the line above should be called after your
28
+ # <tt>ActiveRecord::LogSubscriber</tt> definition.
25
29
  #
26
30
  # After configured, whenever a "sql.active_record" notification is published,
27
31
  # it will properly dispatch the event (ActiveSupport::Notifications::Event) to
28
32
  # the sql method.
29
33
  #
30
- # Log subscriber also has some helpers to deal with logging and automatically flushes
31
- # all logs when the request finishes (via action_dispatch.callback notification) in
32
- # a Rails environment.
33
- class LogSubscriber
34
+ # Log subscriber also has some helpers to deal with logging and automatically
35
+ # flushes all logs when the request finishes (via action_dispatch.callback
36
+ # notification) in a Rails environment.
37
+ class LogSubscriber < Subscriber
34
38
  # Embed in a String to clear all previous ANSI sequences.
35
39
  CLEAR = "\e[0m"
36
40
  BOLD = "\e[1m"
@@ -48,79 +52,58 @@ module ActiveSupport
48
52
  mattr_accessor :colorize_logging
49
53
  self.colorize_logging = true
50
54
 
51
- class_attribute :logger
52
-
53
55
  class << self
54
- remove_method :logger
55
56
  def logger
56
- @logger ||= Rails.logger if defined?(Rails)
57
- end
58
-
59
- def attach_to(namespace, log_subscriber=new, notifier=ActiveSupport::Notifications)
60
- log_subscribers << log_subscriber
61
- @@flushable_loggers = nil
62
-
63
- log_subscriber.public_methods(false).each do |event|
64
- next if 'call' == event.to_s
65
-
66
- notifier.subscribe("#{event}.#{namespace}", log_subscriber)
57
+ @logger ||= if defined?(Rails) && Rails.respond_to?(:logger)
58
+ Rails.logger
67
59
  end
68
60
  end
69
61
 
70
- def log_subscribers
71
- @@log_subscribers ||= []
72
- end
62
+ attr_writer :logger
73
63
 
74
- def flushable_loggers
75
- @@flushable_loggers ||= begin
76
- loggers = log_subscribers.map(&:logger)
77
- loggers.uniq!
78
- loggers.select { |l| l.respond_to?(:flush) }
79
- end
64
+ def log_subscribers
65
+ subscribers
80
66
  end
81
67
 
82
68
  # Flush all log_subscribers' logger.
83
69
  def flush_all!
84
- flushable_loggers.each { |log| log.flush }
70
+ logger.flush if logger.respond_to?(:flush)
85
71
  end
86
72
  end
87
73
 
88
- def call(message, *args)
89
- return unless logger
74
+ def logger
75
+ LogSubscriber.logger
76
+ end
90
77
 
91
- method = message.split('.').first
92
- begin
93
- send(method, ActiveSupport::Notifications::Event.new(message, *args))
94
- rescue Exception => e
95
- logger.error "Could not log #{message.inspect} event. #{e.class}: #{e.message}"
96
- end
78
+ def start(name, id, payload)
79
+ super if logger
80
+ end
81
+
82
+ def finish(name, id, payload)
83
+ super if logger
84
+ rescue Exception => e
85
+ logger.error "Could not log #{name.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
97
86
  end
98
87
 
99
88
  protected
100
89
 
101
90
  %w(info debug warn error fatal unknown).each do |level|
102
91
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
103
- def #{level}(*args, &block)
104
- return unless logger
105
- logger.#{level}(*args, &block)
92
+ def #{level}(progname = nil, &block)
93
+ logger.#{level}(progname, &block) if logger
106
94
  end
107
95
  METHOD
108
96
  end
109
97
 
110
98
  # Set color by using a string or one of the defined constants. If a third
111
- # option is set to true, it also adds bold to the string. This is based
99
+ # option is set to +true+, it also adds bold to the string. This is based
112
100
  # on the Highline implementation and will automatically append CLEAR to the
113
101
  # end of the returned String.
114
- #
115
102
  def color(text, color, bold=false)
116
103
  return text unless colorize_logging
117
- color = self.class.const_get(color.to_s.upcase) if color.is_a?(Symbol)
104
+ color = self.class.const_get(color.upcase) if color.is_a?(Symbol)
118
105
  bold = bold ? BOLD : ""
119
106
  "#{bold}#{color}#{text}#{CLEAR}"
120
107
  end
121
-
122
- def format_duration(duration)
123
- "%.1fms" % duration
124
- end
125
108
  end
126
109
  end
@@ -0,0 +1,57 @@
1
+ require 'active_support/core_ext/class/attribute_accessors'
2
+ require 'active_support/logger_silence'
3
+ require 'logger'
4
+
5
+ module ActiveSupport
6
+ class Logger < ::Logger
7
+ include LoggerSilence
8
+
9
+ # Broadcasts logs to multiple loggers.
10
+ def self.broadcast(logger) # :nodoc:
11
+ Module.new do
12
+ define_method(:add) do |*args, &block|
13
+ logger.add(*args, &block)
14
+ super(*args, &block)
15
+ end
16
+
17
+ define_method(:<<) do |x|
18
+ logger << x
19
+ super(x)
20
+ end
21
+
22
+ define_method(:close) do
23
+ logger.close
24
+ super()
25
+ end
26
+
27
+ define_method(:progname=) do |name|
28
+ logger.progname = name
29
+ super(name)
30
+ end
31
+
32
+ define_method(:formatter=) do |formatter|
33
+ logger.formatter = formatter
34
+ super(formatter)
35
+ end
36
+
37
+ define_method(:level=) do |level|
38
+ logger.level = level
39
+ super(level)
40
+ end
41
+ end
42
+ end
43
+
44
+ def initialize(*args)
45
+ super
46
+ @formatter = SimpleFormatter.new
47
+ end
48
+
49
+ # Simple formatter which only displays the message.
50
+ class SimpleFormatter < ::Logger::Formatter
51
+ # This method is invoked when a log event occurs
52
+ def call(severity, timestamp, progname, msg)
53
+ "#{String === msg ? msg : msg.inspect}\n"
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,24 @@
1
+ require 'active_support/concern'
2
+
3
+ module LoggerSilence
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ cattr_accessor :silencer
8
+ self.silencer = true
9
+ end
10
+
11
+ # Silences the logger for the duration of the block.
12
+ def silence(temporary_level = Logger::ERROR)
13
+ if silencer
14
+ begin
15
+ old_logger_level, self.level = level, temporary_level
16
+ yield self
17
+ ensure
18
+ self.level = old_logger_level
19
+ end
20
+ else
21
+ yield self
22
+ end
23
+ end
24
+ end
@@ -1,14 +1,22 @@
1
1
  require 'openssl'
2
- require 'active_support/base64'
2
+ require 'base64'
3
+ require 'active_support/core_ext/array/extract_options'
3
4
 
4
5
  module ActiveSupport
5
- # MessageEncryptor is a simple way to encrypt values which get stored somewhere
6
- # you don't trust.
6
+ # MessageEncryptor is a simple way to encrypt values which get stored
7
+ # somewhere you don't trust.
7
8
  #
8
- # The cipher text and initialization vector are base64 encoded and returned to you.
9
+ # The cipher text and initialization vector are base64 encoded and returned
10
+ # to you.
9
11
  #
10
- # This can be used in situations similar to the <tt>MessageVerifier</tt>, but where you don't
11
- # want users to be able to determine the value of the payload.
12
+ # This can be used in situations similar to the <tt>MessageVerifier</tt>, but
13
+ # where you don't want users to be able to determine the value of the payload.
14
+ #
15
+ # salt = SecureRandom.random_bytes(64)
16
+ # key = ActiveSupport::KeyGenerator.new('password').generate_key(salt) # => "\x89\xE0\x156\xAC..."
17
+ # crypt = ActiveSupport::MessageEncryptor.new(key) # => #<ActiveSupport::MessageEncryptor ...>
18
+ # encrypted_data = crypt.encrypt_and_sign('my secret data') # => "NlFBTTMwOUV5UlA1QlNEN2xkY2d6eThYWWh..."
19
+ # crypt.decrypt_and_verify(encrypted_data) # => "my secret data"
12
20
  class MessageEncryptor
13
21
  module NullSerializer #:nodoc:
14
22
  def self.load(value)
@@ -21,40 +29,36 @@ module ActiveSupport
21
29
  end
22
30
 
23
31
  class InvalidMessage < StandardError; end
24
- OpenSSLCipherError = OpenSSL::Cipher.const_defined?(:CipherError) ? OpenSSL::Cipher::CipherError : OpenSSL::CipherError
25
-
26
- def initialize(secret, options = {})
27
- unless options.is_a?(Hash)
28
- ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :cipher => 'algorithm' to specify the cipher algorithm."
29
- options = { :cipher => options }
30
- end
31
-
32
+ OpenSSLCipherError = OpenSSL::Cipher::CipherError
33
+
34
+ # Initialize a new MessageEncryptor. +secret+ must be at least as long as
35
+ # the cipher key size. For the default 'aes-256-cbc' cipher, this is 256
36
+ # bits. If you are using a user-entered secret, you can generate a suitable
37
+ # key with <tt>OpenSSL::Digest::SHA256.new(user_secret).digest</tt> or
38
+ # similar.
39
+ #
40
+ # Options:
41
+ # * <tt>:cipher</tt> - Cipher to use. Can be any cipher returned by
42
+ # <tt>OpenSSL::Cipher.ciphers</tt>. Default is 'aes-256-cbc'.
43
+ # * <tt>:serializer</tt> - Object serializer to use. Default is +Marshal+.
44
+ def initialize(secret, *signature_key_or_options)
45
+ options = signature_key_or_options.extract_options!
46
+ sign_secret = signature_key_or_options.first
32
47
  @secret = secret
48
+ @sign_secret = sign_secret
33
49
  @cipher = options[:cipher] || 'aes-256-cbc'
34
- @verifier = MessageVerifier.new(@secret, :serializer => NullSerializer)
50
+ @verifier = MessageVerifier.new(@sign_secret || @secret, :serializer => NullSerializer)
35
51
  @serializer = options[:serializer] || Marshal
36
52
  end
37
53
 
38
- def encrypt(value)
39
- ActiveSupport::Deprecation.warn "MessageEncryptor#encrypt is deprecated as it is not safe without a signature. " \
40
- "Please use MessageEncryptor#encrypt_and_sign instead."
41
- _encrypt(value)
42
- end
43
-
44
- def decrypt(value)
45
- ActiveSupport::Deprecation.warn "MessageEncryptor#decrypt is deprecated as it is not safe without a signature. " \
46
- "Please use MessageEncryptor#decrypt_and_verify instead."
47
- _decrypt(value)
48
- end
49
-
50
- # Encrypt and sign a message. We need to sign the message in order to avoid padding attacks.
51
- # Reference: http://www.limited-entropy.com/padding-oracle-attacks
54
+ # Encrypt and sign a message. We need to sign the message in order to avoid
55
+ # padding attacks. Reference: http://www.limited-entropy.com/padding-oracle-attacks.
52
56
  def encrypt_and_sign(value)
53
57
  verifier.generate(_encrypt(value))
54
58
  end
55
59
 
56
- # Decrypt and verify a message. We need to verify the message in order to avoid padding attacks.
57
- # Reference: http://www.limited-entropy.com/padding-oracle-attacks
60
+ # Decrypt and verify a message. We need to verify the message in order to
61
+ # avoid padding attacks. Reference: http://www.limited-entropy.com/padding-oracle-attacks.
58
62
  def decrypt_and_verify(value)
59
63
  _decrypt(verifier.verify(value))
60
64
  end
@@ -63,12 +67,11 @@ module ActiveSupport
63
67
 
64
68
  def _encrypt(value)
65
69
  cipher = new_cipher
66
- # Rely on OpenSSL for the initialization vector
67
- iv = cipher.random_iv
68
-
69
70
  cipher.encrypt
70
71
  cipher.key = @secret
71
- cipher.iv = iv
72
+
73
+ # Rely on OpenSSL for the initialization vector
74
+ iv = cipher.random_iv
72
75
 
73
76
  encrypted_data = cipher.update(@serializer.dump(value))
74
77
  encrypted_data << cipher.final
@@ -1,13 +1,12 @@
1
- require 'active_support/base64'
2
- require 'active_support/deprecation'
1
+ require 'base64'
3
2
  require 'active_support/core_ext/object/blank'
4
3
 
5
4
  module ActiveSupport
6
- # +MessageVerifier+ makes it easy to generate and verify messages which are signed
7
- # to prevent tampering.
5
+ # +MessageVerifier+ makes it easy to generate and verify messages which are
6
+ # signed to prevent tampering.
8
7
  #
9
- # This is useful for cases like remember-me tokens and auto-unsubscribe links where the
10
- # session store isn't suitable or available.
8
+ # This is useful for cases like remember-me tokens and auto-unsubscribe links
9
+ # where the session store isn't suitable or available.
11
10
  #
12
11
  # Remember Me:
13
12
  # cookies[:remember_me] = @verifier.generate([@user.id, 2.weeks.from_now])
@@ -19,20 +18,15 @@ module ActiveSupport
19
18
  # self.current_user = User.find(id)
20
19
  # end
21
20
  #
22
- # By default it uses Marshal to serialize the message. If you want to use another
23
- # serialization method, you can set the serializer attribute to something that responds
24
- # to dump and load, e.g.:
21
+ # By default it uses Marshal to serialize the message. If you want to use
22
+ # another serialization method, you can set the serializer in the options
23
+ # hash upon initialization:
25
24
  #
26
- # @verifier.serializer = YAML
25
+ # @verifier = ActiveSupport::MessageVerifier.new('s3Krit', serializer: YAML)
27
26
  class MessageVerifier
28
27
  class InvalidSignature < StandardError; end
29
28
 
30
29
  def initialize(secret, options = {})
31
- unless options.is_a?(Hash)
32
- ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :digest => 'algorithm' to specify the digest algorithm."
33
- options = { :digest => options }
34
- end
35
-
36
30
  @secret = secret
37
31
  @digest = options[:digest] || 'SHA1'
38
32
  @serializer = options[:serializer] || Marshal