diff --git a/lib/freedom_patches/safe_buffer.rb b/lib/freedom_patches/safe_buffer.rb new file mode 100644 index 000000000..ea01a9821 --- /dev/null +++ b/lib/freedom_patches/safe_buffer.rb @@ -0,0 +1,37 @@ +# For some reason safe buffer is getting invalid encoding in some cases +# we work around the issue and log the problems +# +# The alternative is a broken website when this happens + +class ActiveSupport::SafeBuffer + def concat(value, raise_encoding_err=false) + if !html_safe? || value.html_safe? + super(value) + else + super(ERB::Util.h(value)) + end + rescue Encoding::CompatibilityError + if raise_encoding_err + raise + else + + unless encoding == Encoding::UTF_8 + self.force_encoding("UTF-8") + unless valid_encoding? + encode!("utf-16","utf-8",:invalid => :replace) + encode!("utf-8","utf-16") + end + Rails.logger.warn("Encountered a non UTF-8 string in SafeBuffer - #{self}") + end + + unless value.encoding == Encoding::UTF_8 + value = value.dup.force_encoding("UTF-8").scrub + Rails.logger.warn("Attempted to concat a non UTF-8 string in SafeBuffer - #{value}") + end + + concat(value,_raise=true) + end + end + + alias << concat +end diff --git a/spec/components/freedom_patches/safe_buffer_spec.rb b/spec/components/freedom_patches/safe_buffer_spec.rb new file mode 100644 index 000000000..34bf78f85 --- /dev/null +++ b/spec/components/freedom_patches/safe_buffer_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' +require_dependency "freedom_patches/safe_buffer" + +describe ActiveSupport::SafeBuffer do + it "can cope with encoding weirdness" do + buffer = ActiveSupport::SafeBuffer.new + buffer << "\330".force_encoding("ASCII-8BIT") + buffer.force_encoding "ASCII-8BIT" + buffer << "hello\330\271" + buffer << "hello#{254.chr}".force_encoding("ASCII-8BIT").freeze + + # we pay a cost for force encoding, the h gets dropped + buffer.should =~ /ello.*hello/ + end +end