164 lines
4.6 KiB
Ruby
164 lines
4.6 KiB
Ruby
#
|
|
# Copyright (C) 2015 Instructure, Inc.
|
|
#
|
|
# This file is part of Canvas.
|
|
#
|
|
# Canvas is free software: you can redistribute it and/or modify it under
|
|
# the terms of the GNU Affero General Public License as published by the Free
|
|
# Software Foundation, version 3 of the License.
|
|
#
|
|
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
# details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License along
|
|
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
# This is an initializer, but needs to be required earlier in the load process,
|
|
# and before canvas-jobs
|
|
|
|
# We need to make sure that safe_yaml is loaded *after* the YAML engine
|
|
# is switched to Syck. Otherwise we
|
|
# won't have access to (safe|unsafe)_load.
|
|
require 'yaml'
|
|
|
|
require 'syck'
|
|
YAML::ENGINE.yamler = 'syck' if defined?(YAML::ENGINE)
|
|
|
|
require 'safe_yaml'
|
|
|
|
trusted_tags = SafeYAML::TRUSTED_TAGS.dup
|
|
trusted_tags << 'tag:yaml.org,2002:merge'
|
|
SafeYAML.send(:remove_const, :TRUSTED_TAGS)
|
|
SafeYAML.const_set(:TRUSTED_TAGS, trusted_tags.freeze)
|
|
|
|
module FixSafeYAMLNullMerge
|
|
def merge_into_hash(hash, array)
|
|
return unless array
|
|
super
|
|
end
|
|
end
|
|
SafeYAML::Resolver.prepend(FixSafeYAMLNullMerge)
|
|
|
|
SafeYAML::OPTIONS.merge!(
|
|
default_mode: :safe,
|
|
deserialize_symbols: true,
|
|
raise_on_unknown_tag: true,
|
|
# This tag whitelist is syck specific. We'll need to tweak it when we upgrade to psych.
|
|
# See the tests in spec/lib/safe_yaml_spec.rb
|
|
whitelisted_tags: %w[
|
|
tag:ruby.yaml.org,2002:symbol
|
|
tag:yaml.org,2002:float
|
|
tag:yaml.org,2002:float#exp
|
|
tag:yaml.org,2002:float#inf
|
|
tag:yaml.org,2002:str
|
|
tag:yaml.org,2002:timestamp
|
|
tag:yaml.org,2002:timestamp#iso8601
|
|
tag:yaml.org,2002:timestamp#spaced
|
|
tag:yaml.org,2002:map:HashWithIndifferentAccess
|
|
tag:yaml.org,2002:map:ActiveSupport::HashWithIndifferentAccess
|
|
tag:ruby.yaml.org,2002:object:Class
|
|
tag:ruby.yaml.org,2002:object:OpenStruct
|
|
tag:ruby.yaml.org,2002:object:Scribd::Document
|
|
tag:ruby.yaml.org,2002:object:Mime::Type
|
|
tag:ruby.yaml.org,2002:object:URI::HTTP
|
|
tag:ruby.yaml.org,2002:object:URI::HTTPS
|
|
tag:ruby.yaml.org,2002:object:OpenObject
|
|
tag:yaml.org,2002:map:WeakParameters
|
|
] + %w[
|
|
!ruby/symbol
|
|
!binary
|
|
!float
|
|
!float#exp
|
|
!float#inf
|
|
!str
|
|
!timestamp
|
|
!timestamp#iso8601
|
|
!timestamp#spaced
|
|
!map:HashWithIndifferentAccess
|
|
!map:ActiveSupport::HashWithIndifferentAccess
|
|
!map:WeakParameters
|
|
!ruby/hash:HashWithIndifferentAccess
|
|
!ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
!ruby/hash:WeakParameters
|
|
!ruby/object:Class
|
|
!ruby/object:OpenStruct
|
|
!ruby/object:Scribd::Document
|
|
!ruby/object:Mime::Type
|
|
!ruby/object:URI::HTTP
|
|
!ruby/object:URI::HTTPS
|
|
!ruby/object:OpenObject
|
|
!ruby/object:DateTime
|
|
]
|
|
)
|
|
|
|
module Syckness
|
|
TAG = "#GETDOWNWITHTHESYCKNESS\n"
|
|
|
|
module SyckDumper
|
|
def dump(*args)
|
|
Psych.dump(*args)
|
|
end
|
|
end
|
|
|
|
module PsychDumper
|
|
def dump(*args)
|
|
yaml = super
|
|
yaml += TAG if yaml.is_a?(String)
|
|
yaml
|
|
end
|
|
end
|
|
|
|
module SafeLoader
|
|
require "safe_yaml/psych_resolver"
|
|
require "safe_yaml/safe_to_ruby_visitor"
|
|
|
|
def load(yaml, *args)
|
|
if yaml.is_a?(String) && yaml.end_with?(TAG)
|
|
SafeYAML::PsychResolver.new.resolve_node(Psych.parse(yaml))
|
|
else
|
|
super
|
|
end
|
|
end
|
|
end
|
|
|
|
module UnsafeLoader
|
|
def unsafe_load(yaml, *args)
|
|
if yaml.is_a?(String) && yaml.end_with?(TAG)
|
|
Psych.load(yaml)
|
|
else
|
|
super
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
[Object, Hash, Struct, Array, Exception, String, Symbol, Range, Regexp, Time,
|
|
Date, Integer, Float, Rational, Complex, TrueClass, FalseClass, NilClass].each do |klass|
|
|
klass.class_eval do
|
|
alias :to_yaml :psych_to_yaml
|
|
end
|
|
end
|
|
|
|
Syck.singleton_class.prepend(Syckness::SyckDumper)
|
|
Psych.singleton_class.prepend(Syckness::PsychDumper)
|
|
SafeYAML.singleton_class.prepend(Syckness::SafeLoader)
|
|
YAML.singleton_class.prepend(Syckness::UnsafeLoader)
|
|
|
|
SafeYAML::PsychResolver.class_eval do
|
|
attr_accessor :aliased_nodes
|
|
end
|
|
|
|
module MaintainAliases
|
|
def accept(node)
|
|
if node.respond_to?(:anchor) && node.anchor && @resolver.get_node_type(node) != :alias
|
|
@resolver.aliased_nodes[node.anchor] = node
|
|
end
|
|
super
|
|
end
|
|
end
|
|
SafeYAML::SafeToRubyVisitor.prepend(MaintainAliases)
|
|
|