mirror of
https://github.com/gitlabhq/gitlabhq.git
synced 2025-08-01 16:46:16 +00:00
63 lines
1.8 KiB
Ruby
63 lines
1.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Gitlab
|
|
module FogbugzImport
|
|
module NokogiriBackendWithLimits
|
|
extend ActiveSupport::XmlMini_Nokogiri
|
|
|
|
module Conversions
|
|
module Document
|
|
def to_hash
|
|
if ActiveSupport::XmlMini.backend == Gitlab::FogbugzImport::NokogiriBackendWithLimits
|
|
check_object_count!(root)
|
|
end
|
|
|
|
super
|
|
end
|
|
|
|
private
|
|
|
|
def check_object_count!(document)
|
|
objects = object_count(document)
|
|
return if objects <= XmlAdapter::MAX_ALLOWED_OBJECTS
|
|
|
|
raise XmlAdapter::ResponseTooLargeError,
|
|
"XML exceeds permitted complexity: #{objects}/#{XmlAdapter::MAX_ALLOWED_OBJECTS} objects"
|
|
end
|
|
|
|
def object_count(object)
|
|
return 0 if object.text? || object.cdata?
|
|
return 1 unless object.children.any?
|
|
|
|
1 + object.children.sum { |v| object_count(v) }
|
|
end
|
|
end
|
|
end
|
|
|
|
Nokogiri::XML::Document.include(Conversions::Document)
|
|
end
|
|
|
|
class XmlAdapter
|
|
ResponseTooLargeError = Class.new(StandardError)
|
|
|
|
MAX_ALLOWED_BYTES = 5.megabytes
|
|
MAX_ALLOWED_OBJECTS = 250_000
|
|
|
|
def self.parse(xml)
|
|
if xml.bytesize > MAX_ALLOWED_BYTES
|
|
raise ResponseTooLargeError, "XML exceeds permitted size: #{xml.bytesize}/#{MAX_ALLOWED_BYTES} bytes"
|
|
end
|
|
|
|
# We use ActiveSupport::XmlMini to get a simplified hash structure,
|
|
# aligned with what we were previously expecting from Crack, but we use
|
|
# Nokogiri for performance and security reasons.
|
|
ActiveSupport::XmlMini.with_backend(NokogiriBackendWithLimits) do
|
|
Hash.from_xml(xml)['response']
|
|
rescue Nokogiri::XML::SyntaxError
|
|
nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|