activesupport 4.0.12 → 7.0.2.4
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +249 -501
- data/MIT-LICENSE +2 -2
- data/README.rdoc +10 -5
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +41 -13
- data/lib/active_support/benchmarkable.rb +7 -15
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +96 -74
- data/lib/active_support/cache/mem_cache_store.rb +211 -103
- data/lib/active_support/cache/memory_store.rb +90 -58
- data/lib/active_support/cache/null_store.rb +19 -7
- data/lib/active_support/cache/redis_cache_store.rb +468 -0
- data/lib/active_support/cache/strategy/local_cache.rb +86 -83
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
- data/lib/active_support/cache.rb +580 -241
- data/lib/active_support/callbacks.rb +812 -425
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +103 -14
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +33 -0
- data/lib/active_support/concurrency/share_lock.rb +226 -0
- data/lib/active_support/configurable.rb +21 -19
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +47 -1
- data/lib/active_support/core_ext/array/conversions.rb +35 -44
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +26 -16
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +10 -7
- data/lib/active_support/core_ext/benchmark.rb +5 -3
- data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +52 -49
- data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
- data/lib/active_support/core_ext/class/subclasses.rb +25 -26
- data/lib/active_support/core_ext/class.rb +4 -4
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +14 -0
- data/lib/active_support/core_ext/date/calculations.rb +31 -18
- data/lib/active_support/core_ext/date/conversions.rb +43 -32
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/date/zones.rb +5 -34
- data/lib/active_support/core_ext/date.rb +7 -4
- data/lib/active_support/core_ext/date_and_time/calculations.rb +198 -66
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +31 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +79 -38
- data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +31 -26
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/date_time.rb +8 -4
- data/lib/active_support/core_ext/digest/uuid.rb +79 -0
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +249 -17
- data/lib/active_support/core_ext/file/atomic.rb +41 -32
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +71 -49
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +14 -5
- data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
- data/lib/active_support/core_ext/hash/keys.rb +39 -56
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -23
- data/lib/active_support/core_ext/hash.rb +10 -8
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +11 -33
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/concern.rb +14 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +9 -78
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +5 -4
- data/lib/active_support/core_ext/load_error.rb +5 -21
- data/lib/active_support/core_ext/module/aliasing.rb +6 -44
- data/lib/active_support/core_ext/module/anonymous.rb +12 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +8 -8
- data/lib/active_support/core_ext/module/attribute_accessors.rb +186 -44
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +157 -0
- data/lib/active_support/core_ext/module/concerning.rb +140 -0
- data/lib/active_support/core_ext/module/delegation.rb +172 -45
- data/lib/active_support/core_ext/module/deprecation.rb +3 -3
- data/lib/active_support/core_ext/module/introspection.rb +23 -38
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/module.rb +13 -10
- data/lib/active_support/core_ext/name_error.rb +45 -4
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +135 -127
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
- data/lib/active_support/core_ext/numeric/time.rb +37 -50
- data/lib/active_support/core_ext/numeric.rb +6 -3
- data/lib/active_support/core_ext/object/acts_like.rb +41 -6
- data/lib/active_support/core_ext/object/blank.rb +70 -20
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
- data/lib/active_support/core_ext/object/duplicable.rb +17 -47
- data/lib/active_support/core_ext/object/inclusion.rb +18 -15
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +244 -0
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +21 -8
- data/lib/active_support/core_ext/object/try.rb +106 -26
- data/lib/active_support/core_ext/object/with_options.rb +64 -5
- data/lib/active_support/core_ext/object.rb +14 -12
- data/lib/active_support/core_ext/pathname/existence.rb +21 -0
- data/lib/active_support/core_ext/pathname.rb +3 -0
- data/lib/active_support/core_ext/range/compare_range.rb +57 -0
- data/lib/active_support/core_ext/range/conversions.rb +37 -15
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/range/each.rb +18 -17
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +7 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +7 -4
- data/lib/active_support/core_ext/regexp.rb +10 -1
- data/lib/active_support/core_ext/securerandom.rb +45 -0
- data/lib/active_support/core_ext/string/access.rb +42 -51
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +18 -13
- data/lib/active_support/core_ext/string/exclude.rb +5 -3
- data/lib/active_support/core_ext/string/filters.rb +97 -7
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +106 -25
- data/lib/active_support/core_ext/string/inquiry.rb +4 -1
- data/lib/active_support/core_ext/string/multibyte.rb +18 -9
- data/lib/active_support/core_ext/string/output_safety.rb +227 -54
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +6 -5
- data/lib/active_support/core_ext/string/zones.rb +4 -1
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +178 -116
- data/lib/active_support/core_ext/time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +37 -25
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/time/zones.rb +44 -42
- data/lib/active_support/core_ext/time.rb +8 -5
- data/lib/active_support/core_ext/uri.rb +4 -25
- data/lib/active_support/core_ext.rb +4 -2
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +226 -0
- data/lib/active_support/dependencies/autoload.rb +3 -1
- data/lib/active_support/dependencies/interlock.rb +49 -0
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +71 -696
- data/lib/active_support/deprecation/behaviors.rb +65 -16
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +16 -2
- data/lib/active_support/deprecation/method_wrappers.rb +62 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +82 -31
- data/lib/active_support/deprecation/reporting.rb +81 -18
- data/lib/active_support/deprecation.rb +19 -11
- data/lib/active_support/descendants_tracker.rb +192 -34
- data/lib/active_support/digest.rb +22 -0
- data/lib/active_support/duration/iso8601_parser.rb +123 -0
- data/lib/active_support/duration/iso8601_serializer.rb +67 -0
- data/lib/active_support/duration.rb +437 -39
- data/lib/active_support/encrypted_configuration.rb +56 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/error_reporter.rb +117 -0
- data/lib/active_support/evented_file_update_checker.rb +170 -0
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +151 -0
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +62 -37
- data/lib/active_support/fork_tracker.rb +71 -0
- data/lib/active_support/gem_version.rb +17 -0
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +207 -54
- data/lib/active_support/html_safe_translation.rb +43 -0
- data/lib/active_support/i18n.rb +10 -6
- data/lib/active_support/i18n_railtie.rb +48 -19
- data/lib/active_support/inflections.rb +19 -12
- data/lib/active_support/inflector/inflections.rb +97 -37
- data/lib/active_support/inflector/methods.rb +192 -157
- data/lib/active_support/inflector/transliterate.rb +83 -33
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/isolated_execution_state.rb +64 -0
- data/lib/active_support/json/decoding.rb +37 -42
- data/lib/active_support/json/encoding.rb +93 -293
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +30 -47
- data/lib/active_support/lazy_load_hooks.rb +54 -21
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +10 -4
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +61 -18
- data/lib/active_support/logger.rb +40 -4
- data/lib/active_support/logger_silence.rb +17 -20
- data/lib/active_support/logger_thread_safe_level.rb +69 -0
- data/lib/active_support/message_encryptor.rb +178 -55
- data/lib/active_support/message_verifier.rb +195 -26
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +45 -92
- data/lib/active_support/multibyte/unicode.rb +44 -377
- data/lib/active_support/multibyte.rb +5 -3
- data/lib/active_support/notifications/fanout.rb +177 -44
- data/lib/active_support/notifications/instrumenter.rb +117 -17
- data/lib/active_support/notifications.rb +106 -39
- data/lib/active_support/number_helper/number_converter.rb +181 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +59 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
- data/lib/active_support/number_helper/rounding_helper.rb +46 -0
- data/lib/active_support/number_helper.rb +152 -394
- data/lib/active_support/option_merger.rb +18 -5
- data/lib/active_support/ordered_hash.rb +8 -6
- data/lib/active_support/ordered_options.rb +43 -7
- data/lib/active_support/parameter_filter.rb +138 -0
- data/lib/active_support/per_thread_registry.rb +24 -11
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +10 -11
- data/lib/active_support/railtie.rb +118 -12
- data/lib/active_support/reloader.rb +130 -0
- data/lib/active_support/rescuable.rb +112 -57
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +38 -0
- data/lib/active_support/string_inquirer.rb +11 -4
- data/lib/active_support/subscriber.rb +109 -39
- data/lib/active_support/tagged_logging.rb +54 -17
- data/lib/active_support/test_case.rb +121 -37
- data/lib/active_support/testing/assertions.rb +177 -39
- data/lib/active_support/testing/autorun.rb +5 -3
- data/lib/active_support/testing/constant_lookup.rb +3 -6
- data/lib/active_support/testing/declarative.rb +10 -22
- data/lib/active_support/testing/deprecation.rb +65 -11
- data/lib/active_support/testing/file_fixtures.rb +38 -0
- data/lib/active_support/testing/isolation.rb +56 -87
- data/lib/active_support/testing/method_call_assertions.rb +70 -0
- data/lib/active_support/testing/parallelization/server.rb +82 -0
- data/lib/active_support/testing/parallelization/worker.rb +103 -0
- data/lib/active_support/testing/parallelization.rb +55 -0
- data/lib/active_support/testing/parallelize_executor.rb +76 -0
- data/lib/active_support/testing/setup_and_teardown.rb +30 -10
- data/lib/active_support/testing/stream.rb +41 -0
- data/lib/active_support/testing/tagged_logging.rb +6 -4
- data/lib/active_support/testing/time_helpers.rb +246 -0
- data/lib/active_support/time.rb +13 -13
- data/lib/active_support/time_with_zone.rb +315 -90
- data/lib/active_support/values/time_zone.rb +306 -135
- data/lib/active_support/version.rb +6 -7
- data/lib/active_support/xml_mini/jdom.rb +117 -115
- data/lib/active_support/xml_mini/libxml.rb +22 -21
- data/lib/active_support/xml_mini/libxmlsax.rb +17 -19
- data/lib/active_support/xml_mini/nokogiri.rb +19 -19
- data/lib/active_support/xml_mini/nokogirisax.rb +16 -17
- data/lib/active_support/xml_mini/rexml.rb +25 -17
- data/lib/active_support/xml_mini.rb +67 -56
- data/lib/active_support.rb +58 -3
- metadata +125 -66
- data/lib/active_support/basic_object.rb +0 -11
- data/lib/active_support/buffered_logger.rb +0 -21
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
- data/lib/active_support/core_ext/date_time/zones.rb +0 -24
- data/lib/active_support/core_ext/hash/diff.rb +0 -14
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/logger.rb +0 -67
- data/lib/active_support/core_ext/marshal.rb +0 -21
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/object/to_json.rb +0 -27
- data/lib/active_support/core_ext/proc.rb +0 -17
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/core_ext/string/encoding.rb +0 -8
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -79
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
- data/lib/active_support/file_watcher.rb +0 -36
- data/lib/active_support/json/variable.rb +0 -18
- data/lib/active_support/testing/pending.rb +0 -14
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,5 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/multibyte"
|
3
4
|
|
4
5
|
class String
|
5
6
|
# == Multibyte proxy
|
@@ -10,12 +11,13 @@ class String
|
|
10
11
|
# encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
|
11
12
|
# class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsulated string.
|
12
13
|
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
14
|
+
# >> "lj".mb_chars.upcase.to_s
|
15
|
+
# => "LJ"
|
16
|
+
#
|
17
|
+
# NOTE: Ruby 2.4 and later support native Unicode case mappings:
|
16
18
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
+
# >> "lj".upcase
|
20
|
+
# => "LJ"
|
19
21
|
#
|
20
22
|
# == Method chaining
|
21
23
|
#
|
@@ -36,11 +38,18 @@ class String
|
|
36
38
|
ActiveSupport::Multibyte.proxy_class.new(self)
|
37
39
|
end
|
38
40
|
|
41
|
+
# Returns +true+ if string has utf_8 encoding.
|
42
|
+
#
|
43
|
+
# utf_8_str = "some string".encode "UTF-8"
|
44
|
+
# iso_str = "some string".encode "ISO-8859-1"
|
45
|
+
#
|
46
|
+
# utf_8_str.is_utf8? # => true
|
47
|
+
# iso_str.is_utf8? # => false
|
39
48
|
def is_utf8?
|
40
49
|
case encoding
|
41
|
-
when Encoding::UTF_8
|
50
|
+
when Encoding::UTF_8, Encoding::US_ASCII
|
42
51
|
valid_encoding?
|
43
|
-
when Encoding::ASCII_8BIT
|
52
|
+
when Encoding::ASCII_8BIT
|
44
53
|
dup.force_encoding(Encoding::UTF_8).valid_encoding?
|
45
54
|
else
|
46
55
|
false
|
@@ -1,39 +1,53 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "erb"
|
4
|
+
require "active_support/core_ext/module/redefine_method"
|
5
|
+
require "active_support/multibyte/unicode"
|
3
6
|
|
4
7
|
class ERB
|
5
8
|
module Util
|
6
|
-
HTML_ESCAPE = {
|
7
|
-
JSON_ESCAPE = {
|
8
|
-
HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+));)/
|
9
|
-
JSON_ESCAPE_REGEXP = /[
|
9
|
+
HTML_ESCAPE = { "&" => "&", ">" => ">", "<" => "<", '"' => """, "'" => "'" }
|
10
|
+
JSON_ESCAPE = { "&" => '\u0026', ">" => '\u003e', "<" => '\u003c', "\u2028" => '\u2028', "\u2029" => '\u2029' }
|
11
|
+
HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+)|(#[xX][\dA-Fa-f]+));)/
|
12
|
+
JSON_ESCAPE_REGEXP = /[\u2028\u2029&><]/u
|
13
|
+
|
14
|
+
# Following XML requirements: https://www.w3.org/TR/REC-xml/#NT-Name
|
15
|
+
TAG_NAME_START_REGEXP_SET = ":A-Z_a-z\u{C0}-\u{D6}\u{D8}-\u{F6}\u{F8}-\u{2FF}\u{370}-\u{37D}\u{37F}-\u{1FFF}" \
|
16
|
+
"\u{200C}-\u{200D}\u{2070}-\u{218F}\u{2C00}-\u{2FEF}\u{3001}-\u{D7FF}\u{F900}-\u{FDCF}" \
|
17
|
+
"\u{FDF0}-\u{FFFD}\u{10000}-\u{EFFFF}"
|
18
|
+
TAG_NAME_START_REGEXP = /[^#{TAG_NAME_START_REGEXP_SET}]/
|
19
|
+
TAG_NAME_FOLLOWING_REGEXP = /[^#{TAG_NAME_START_REGEXP_SET}\-.0-9\u{B7}\u{0300}-\u{036F}\u{203F}-\u{2040}]/
|
20
|
+
TAG_NAME_REPLACEMENT_CHAR = "_"
|
10
21
|
|
11
22
|
# A utility method for escaping HTML tag characters.
|
12
23
|
# This method is also aliased as <tt>h</tt>.
|
13
24
|
#
|
14
|
-
# In your ERB templates, use this method to escape any unsafe content. For example:
|
15
|
-
# <%=h @person.name %>
|
16
|
-
#
|
17
25
|
# puts html_escape('is a > 0 & a < 10?')
|
18
26
|
# # => is a > 0 & a < 10?
|
19
27
|
def html_escape(s)
|
20
|
-
s
|
21
|
-
if s.html_safe?
|
22
|
-
s
|
23
|
-
else
|
24
|
-
s.gsub(/[&"'><]/, HTML_ESCAPE).html_safe
|
25
|
-
end
|
28
|
+
unwrapped_html_escape(s).html_safe
|
26
29
|
end
|
27
30
|
|
28
|
-
|
29
|
-
remove_method(:h)
|
31
|
+
silence_redefinition_of_method :h
|
30
32
|
alias h html_escape
|
31
33
|
|
32
34
|
module_function :h
|
33
35
|
|
34
|
-
singleton_class.
|
36
|
+
singleton_class.silence_redefinition_of_method :html_escape
|
35
37
|
module_function :html_escape
|
36
38
|
|
39
|
+
# HTML escapes strings but doesn't wrap them with an ActiveSupport::SafeBuffer.
|
40
|
+
# This method is not for public consumption! Seriously!
|
41
|
+
def unwrapped_html_escape(s) # :nodoc:
|
42
|
+
s = s.to_s
|
43
|
+
if s.html_safe?
|
44
|
+
s
|
45
|
+
else
|
46
|
+
CGI.escapeHTML(ActiveSupport::Multibyte::Unicode.tidy_bytes(s))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
module_function :unwrapped_html_escape
|
50
|
+
|
37
51
|
# A utility method for escaping HTML without affecting existing escaped entities.
|
38
52
|
#
|
39
53
|
# html_escape_once('1 < 2 & 3')
|
@@ -42,29 +56,93 @@ class ERB
|
|
42
56
|
# html_escape_once('<< Accept & Checkout')
|
43
57
|
# # => "<< Accept & Checkout"
|
44
58
|
def html_escape_once(s)
|
45
|
-
result = s.to_s.gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE)
|
59
|
+
result = ActiveSupport::Multibyte::Unicode.tidy_bytes(s.to_s).gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE)
|
46
60
|
s.html_safe? ? result.html_safe : result
|
47
61
|
end
|
48
62
|
|
49
63
|
module_function :html_escape_once
|
50
64
|
|
51
|
-
# A utility method for escaping HTML entities in JSON strings
|
52
|
-
#
|
65
|
+
# A utility method for escaping HTML entities in JSON strings. Specifically, the
|
66
|
+
# &, > and < characters are replaced with their equivalent unicode escaped form -
|
67
|
+
# \u0026, \u003e, and \u003c. The Unicode sequences \u2028 and \u2029 are also
|
68
|
+
# escaped as they are treated as newline characters in some JavaScript engines.
|
69
|
+
# These sequences have identical meaning as the original characters inside the
|
70
|
+
# context of a JSON string, so assuming the input is a valid and well-formed
|
71
|
+
# JSON value, the output will have equivalent meaning when parsed:
|
72
|
+
#
|
73
|
+
# json = JSON.generate({ name: "</script><script>alert('PWNED!!!')</script>"})
|
74
|
+
# # => "{\"name\":\"</script><script>alert('PWNED!!!')</script>\"}"
|
75
|
+
#
|
76
|
+
# json_escape(json)
|
77
|
+
# # => "{\"name\":\"\\u003C/script\\u003E\\u003Cscript\\u003Ealert('PWNED!!!')\\u003C/script\\u003E\"}"
|
78
|
+
#
|
79
|
+
# JSON.parse(json) == JSON.parse(json_escape(json))
|
80
|
+
# # => true
|
53
81
|
#
|
54
|
-
#
|
55
|
-
#
|
82
|
+
# The intended use case for this method is to escape JSON strings before including
|
83
|
+
# them inside a script tag to avoid XSS vulnerability:
|
56
84
|
#
|
57
|
-
#
|
58
|
-
#
|
85
|
+
# <script>
|
86
|
+
# var currentUser = <%= raw json_escape(current_user.to_json) %>;
|
87
|
+
# </script>
|
59
88
|
#
|
60
|
-
#
|
61
|
-
#
|
89
|
+
# It is necessary to +raw+ the result of +json_escape+, so that quotation marks
|
90
|
+
# don't get converted to <tt>"</tt> entities. +json_escape+ doesn't
|
91
|
+
# automatically flag the result as HTML safe, since the raw value is unsafe to
|
92
|
+
# use inside HTML attributes.
|
93
|
+
#
|
94
|
+
# If your JSON is being used downstream for insertion into the DOM, be aware of
|
95
|
+
# whether or not it is being inserted via <tt>html()</tt>. Most jQuery plugins do this.
|
96
|
+
# If that is the case, be sure to +html_escape+ or +sanitize+ any user-generated
|
97
|
+
# content returned by your JSON.
|
98
|
+
#
|
99
|
+
# If you need to output JSON elsewhere in your HTML, you can just do something
|
100
|
+
# like this, as any unsafe characters (including quotation marks) will be
|
101
|
+
# automatically escaped for you:
|
102
|
+
#
|
103
|
+
# <div data-user-info="<%= current_user.to_json %>">...</div>
|
104
|
+
#
|
105
|
+
# WARNING: this helper only works with valid JSON. Using this on non-JSON values
|
106
|
+
# will open up serious XSS vulnerabilities. For example, if you replace the
|
107
|
+
# +current_user.to_json+ in the example above with user input instead, the browser
|
108
|
+
# will happily eval() that string as JavaScript.
|
109
|
+
#
|
110
|
+
# The escaping performed in this method is identical to those performed in the
|
111
|
+
# Active Support JSON encoder when +ActiveSupport.escape_html_entities_in_json+ is
|
112
|
+
# set to true. Because this transformation is idempotent, this helper can be
|
113
|
+
# applied even if +ActiveSupport.escape_html_entities_in_json+ is already true.
|
114
|
+
#
|
115
|
+
# Therefore, when you are unsure if +ActiveSupport.escape_html_entities_in_json+
|
116
|
+
# is enabled, or if you are unsure where your JSON string originated from, it
|
117
|
+
# is recommended that you always apply this helper (other libraries, such as the
|
118
|
+
# JSON gem, do not provide this kind of protection by default; also some gems
|
119
|
+
# might override +to_json+ to bypass Active Support's encoder).
|
62
120
|
def json_escape(s)
|
63
121
|
result = s.to_s.gsub(JSON_ESCAPE_REGEXP, JSON_ESCAPE)
|
64
122
|
s.html_safe? ? result.html_safe : result
|
65
123
|
end
|
66
124
|
|
67
125
|
module_function :json_escape
|
126
|
+
|
127
|
+
# A utility method for escaping XML names of tags and names of attributes.
|
128
|
+
#
|
129
|
+
# xml_name_escape('1 < 2 & 3')
|
130
|
+
# # => "1___2___3"
|
131
|
+
#
|
132
|
+
# It follows the requirements of the specification: https://www.w3.org/TR/REC-xml/#NT-Name
|
133
|
+
def xml_name_escape(name)
|
134
|
+
name = name.to_s
|
135
|
+
return "" if name.blank?
|
136
|
+
|
137
|
+
starting_char = name[0].gsub(TAG_NAME_START_REGEXP, TAG_NAME_REPLACEMENT_CHAR)
|
138
|
+
|
139
|
+
return starting_char if name.size == 1
|
140
|
+
|
141
|
+
following_chars = name[1..-1].gsub(TAG_NAME_FOLLOWING_REGEXP, TAG_NAME_REPLACEMENT_CHAR)
|
142
|
+
|
143
|
+
starting_char + following_chars
|
144
|
+
end
|
145
|
+
module_function :xml_name_escape
|
68
146
|
end
|
69
147
|
end
|
70
148
|
|
@@ -80,33 +158,37 @@ class Numeric
|
|
80
158
|
end
|
81
159
|
end
|
82
160
|
|
83
|
-
module ActiveSupport
|
161
|
+
module ActiveSupport # :nodoc:
|
84
162
|
class SafeBuffer < String
|
85
163
|
UNSAFE_STRING_METHODS = %w(
|
86
|
-
capitalize chomp chop delete
|
87
|
-
|
164
|
+
capitalize chomp chop delete delete_prefix delete_suffix
|
165
|
+
downcase lstrip next reverse rstrip scrub slice squeeze strip
|
166
|
+
succ swapcase tr tr_s unicode_normalize upcase
|
88
167
|
)
|
89
168
|
|
169
|
+
UNSAFE_STRING_METHODS_WITH_BACKREF = %w(gsub sub)
|
170
|
+
|
90
171
|
alias_method :original_concat, :concat
|
91
172
|
private :original_concat
|
92
173
|
|
174
|
+
# Raised when <tt>ActiveSupport::SafeBuffer#safe_concat</tt> is called on unsafe buffers.
|
93
175
|
class SafeConcatError < StandardError
|
94
176
|
def initialize
|
95
|
-
super
|
177
|
+
super "Could not concatenate to the buffer because it is not html safe."
|
96
178
|
end
|
97
179
|
end
|
98
180
|
|
99
181
|
def [](*args)
|
100
|
-
if
|
101
|
-
super
|
182
|
+
if html_safe?
|
183
|
+
new_string = super
|
184
|
+
|
185
|
+
return unless new_string
|
186
|
+
|
187
|
+
new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string)
|
188
|
+
new_safe_buffer.instance_variable_set :@html_safe, true
|
189
|
+
new_safe_buffer
|
102
190
|
else
|
103
|
-
|
104
|
-
new_safe_buffer = super
|
105
|
-
new_safe_buffer.instance_eval { @html_safe = true }
|
106
|
-
new_safe_buffer
|
107
|
-
else
|
108
|
-
to_str[*args]
|
109
|
-
end
|
191
|
+
to_str[*args]
|
110
192
|
end
|
111
193
|
end
|
112
194
|
|
@@ -115,7 +197,7 @@ module ActiveSupport #:nodoc:
|
|
115
197
|
original_concat(value)
|
116
198
|
end
|
117
199
|
|
118
|
-
def initialize(
|
200
|
+
def initialize(str = "")
|
119
201
|
@html_safe = true
|
120
202
|
super
|
121
203
|
end
|
@@ -130,28 +212,53 @@ module ActiveSupport #:nodoc:
|
|
130
212
|
end
|
131
213
|
|
132
214
|
def concat(value)
|
133
|
-
|
134
|
-
super(value)
|
135
|
-
else
|
136
|
-
super(ERB::Util.h(value))
|
215
|
+
unless value.nil?
|
216
|
+
super(implicit_html_escape_interpolated_argument(value))
|
137
217
|
end
|
218
|
+
self
|
138
219
|
end
|
139
220
|
alias << concat
|
140
221
|
|
222
|
+
def insert(index, value)
|
223
|
+
super(index, implicit_html_escape_interpolated_argument(value))
|
224
|
+
end
|
225
|
+
|
226
|
+
def prepend(value)
|
227
|
+
super(implicit_html_escape_interpolated_argument(value))
|
228
|
+
end
|
229
|
+
|
230
|
+
def replace(value)
|
231
|
+
super(implicit_html_escape_interpolated_argument(value))
|
232
|
+
end
|
233
|
+
|
234
|
+
def []=(*args)
|
235
|
+
if args.length == 3
|
236
|
+
super(args[0], args[1], implicit_html_escape_interpolated_argument(args[2]))
|
237
|
+
else
|
238
|
+
super(args[0], implicit_html_escape_interpolated_argument(args[1]))
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
141
242
|
def +(other)
|
142
243
|
dup.concat(other)
|
143
244
|
end
|
144
245
|
|
246
|
+
def *(*)
|
247
|
+
new_string = super
|
248
|
+
new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string)
|
249
|
+
new_safe_buffer.instance_variable_set(:@html_safe, @html_safe)
|
250
|
+
new_safe_buffer
|
251
|
+
end
|
252
|
+
|
145
253
|
def %(args)
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
end
|
254
|
+
case args
|
255
|
+
when Hash
|
256
|
+
escaped_args = args.transform_values { |arg| explicit_html_escape_interpolated_argument(arg) }
|
257
|
+
else
|
258
|
+
escaped_args = Array(args).map { |arg| explicit_html_escape_interpolated_argument(arg) }
|
152
259
|
end
|
153
260
|
|
154
|
-
self.class.new(super(
|
261
|
+
self.class.new(super(escaped_args))
|
155
262
|
end
|
156
263
|
|
157
264
|
def html_safe?
|
@@ -167,11 +274,11 @@ module ActiveSupport #:nodoc:
|
|
167
274
|
end
|
168
275
|
|
169
276
|
def encode_with(coder)
|
170
|
-
coder.
|
277
|
+
coder.represent_object nil, to_str
|
171
278
|
end
|
172
279
|
|
173
280
|
UNSAFE_STRING_METHODS.each do |unsafe_method|
|
174
|
-
if
|
281
|
+
if unsafe_method.respond_to?(unsafe_method)
|
175
282
|
class_eval <<-EOT, __FILE__, __LINE__ + 1
|
176
283
|
def #{unsafe_method}(*args, &block) # def capitalize(*args, &block)
|
177
284
|
to_str.#{unsafe_method}(*args, &block) # to_str.capitalize(*args, &block)
|
@@ -184,10 +291,76 @@ module ActiveSupport #:nodoc:
|
|
184
291
|
EOT
|
185
292
|
end
|
186
293
|
end
|
294
|
+
|
295
|
+
UNSAFE_STRING_METHODS_WITH_BACKREF.each do |unsafe_method|
|
296
|
+
class_eval <<-EOT, __FILE__, __LINE__ + 1
|
297
|
+
def #{unsafe_method}(*args, &block) # def gsub(*args, &block)
|
298
|
+
if block # if block
|
299
|
+
to_str.#{unsafe_method}(*args) { |*params| # to_str.gsub(*args) { |*params|
|
300
|
+
set_block_back_references(block, $~) # set_block_back_references(block, $~)
|
301
|
+
block.call(*params) # block.call(*params)
|
302
|
+
} # }
|
303
|
+
else # else
|
304
|
+
to_str.#{unsafe_method}(*args) # to_str.gsub(*args)
|
305
|
+
end # end
|
306
|
+
end # end
|
307
|
+
|
308
|
+
def #{unsafe_method}!(*args, &block) # def gsub!(*args, &block)
|
309
|
+
@html_safe = false # @html_safe = false
|
310
|
+
if block # if block
|
311
|
+
super(*args) { |*params| # super(*args) { |*params|
|
312
|
+
set_block_back_references(block, $~) # set_block_back_references(block, $~)
|
313
|
+
block.call(*params) # block.call(*params)
|
314
|
+
} # }
|
315
|
+
else # else
|
316
|
+
super # super
|
317
|
+
end # end
|
318
|
+
end # end
|
319
|
+
EOT
|
320
|
+
end
|
321
|
+
|
322
|
+
private
|
323
|
+
def explicit_html_escape_interpolated_argument(arg)
|
324
|
+
(!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
|
325
|
+
end
|
326
|
+
|
327
|
+
def implicit_html_escape_interpolated_argument(arg)
|
328
|
+
if !html_safe? || arg.html_safe?
|
329
|
+
arg
|
330
|
+
else
|
331
|
+
arg_string = begin
|
332
|
+
arg.to_str
|
333
|
+
rescue NoMethodError => error
|
334
|
+
if error.name == :to_str
|
335
|
+
str = arg.to_s
|
336
|
+
ActiveSupport::Deprecation.warn <<~MSG.squish
|
337
|
+
Implicit conversion of #{arg.class} into String by ActiveSupport::SafeBuffer
|
338
|
+
is deprecated and will be removed in Rails 7.1.
|
339
|
+
You must explicitly cast it to a String.
|
340
|
+
MSG
|
341
|
+
str
|
342
|
+
else
|
343
|
+
raise
|
344
|
+
end
|
345
|
+
end
|
346
|
+
CGI.escapeHTML(arg_string)
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
def set_block_back_references(block, match_data)
|
351
|
+
block.binding.eval("proc { |m| $~ = m }").call(match_data)
|
352
|
+
rescue ArgumentError
|
353
|
+
# Can't create binding from C level Proc
|
354
|
+
end
|
187
355
|
end
|
188
356
|
end
|
189
357
|
|
190
358
|
class String
|
359
|
+
# Marks a string as trusted safe. It will be inserted into HTML with no
|
360
|
+
# additional escaping performed. It is your responsibility to ensure that the
|
361
|
+
# string contains no malicious content. This method is equivalent to the
|
362
|
+
# +raw+ helper in views. It is recommended that you use +sanitize+ instead of
|
363
|
+
# this method. It should never be called on user input.
|
191
364
|
def html_safe
|
192
365
|
ActiveSupport::SafeBuffer.new(self)
|
193
366
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class String
|
4
4
|
# Strips indentation in heredocs.
|
@@ -17,10 +17,11 @@ class String
|
|
17
17
|
#
|
18
18
|
# the user would see the usage message aligned against the left margin.
|
19
19
|
#
|
20
|
-
# Technically, it looks for the least indented line
|
21
|
-
# that amount of leading whitespace.
|
20
|
+
# Technically, it looks for the least indented non-empty line
|
21
|
+
# in the whole string, and removes that amount of leading whitespace.
|
22
22
|
def strip_heredoc
|
23
|
-
|
24
|
-
|
23
|
+
gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "").tap do |stripped|
|
24
|
+
stripped.freeze if frozen?
|
25
|
+
end
|
25
26
|
end
|
26
27
|
end
|
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/conversions"
|
4
|
+
require "active_support/core_ext/time/zones"
|
2
5
|
|
3
6
|
class String
|
4
7
|
# Converts String to a TimeWithZone in the current zone if Time.zone or Time.zone_default
|
@@ -1,13 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/conversions"
|
4
|
+
require "active_support/core_ext/string/filters"
|
5
|
+
require "active_support/core_ext/string/multibyte"
|
6
|
+
require "active_support/core_ext/string/starts_ends_with"
|
7
|
+
require "active_support/core_ext/string/inflections"
|
8
|
+
require "active_support/core_ext/string/access"
|
9
|
+
require "active_support/core_ext/string/behavior"
|
10
|
+
require "active_support/core_ext/string/output_safety"
|
11
|
+
require "active_support/core_ext/string/exclude"
|
12
|
+
require "active_support/core_ext/string/strip"
|
13
|
+
require "active_support/core_ext/string/inquiry"
|
14
|
+
require "active_support/core_ext/string/indent"
|
15
|
+
require "active_support/core_ext/string/zones"
|