Commit 81d2a1ee604e43ebd329dca4487edeb19136d9a5

Authored by Luke Baker
1 parent 3527cdd7

add utf8 monkey patches

Showing 1 changed file with 89 additions and 0 deletions   Show diff stats
config/initializers/utf8_monkey_patches.rb 0 → 100644
... ... @@ -0,0 +1,89 @@
  1 +unless RUBY_VERSION == '1.8.7'
  2 + # Make sure the logger supports encodings properly.
  3 + module ActiveSupport
  4 + class BufferedLogger
  5 + def add(severity, message = nil, progname = nil, &block)
  6 + return if @level > severity
  7 + message = (message || (block && block.call) || progname).to_s
  8 +
  9 + # If a newline is necessary then create a new message ending with a newline.
  10 + # Ensures that the original message is not mutated.
  11 + message = "#{message}\n" unless message[-1] == ?\n
  12 + buffer << message.force_encoding(Encoding.default_external)
  13 + auto_flush
  14 + message
  15 + end
  16 + end
  17 + end
  18 +
  19 + # This makes it so all parameters get converted to UTF-8 before they hit your app. If someone sends invalid UTF-8 to your server, raise an exception.
  20 + # At UserVoice, we rescue this exception and show a custom error page.
  21 + class ActionController::InvalidByteSequenceErrorFromParams < Encoding::InvalidByteSequenceError; end
  22 + class ActionController::Base
  23 +
  24 + def force_utf8_params
  25 + traverse = lambda do |object, block|
  26 + if object.kind_of?(Hash)
  27 + object.each_value { |o| traverse.call(o, block) }
  28 + elsif object.kind_of?(Array)
  29 + object.each { |o| traverse.call(o, block) }
  30 + else
  31 + block.call(object)
  32 + end
  33 + object
  34 + end
  35 + force_encoding = lambda do |o|
  36 + if o.respond_to?(:force_encoding)
  37 + o.force_encoding(Encoding::UTF_8)
  38 + raise ActionController::InvalidByteSequenceErrorFromParams unless o.valid_encoding?
  39 + end
  40 + if o.respond_to?(:original_filename)
  41 + o.original_filename.force_encoding(Encoding::UTF_8)
  42 + raise ActionController::InvalidByteSequenceErrorFromParams unless o.original_filename.valid_encoding?
  43 + end
  44 + end
  45 + traverse.call(params, force_encoding)
  46 + path_str = request.path.to_s
  47 + if path_str.respond_to?(:force_encoding)
  48 + path_str.force_encoding(Encoding::UTF_8)
  49 + raise ActionController::InvalidByteSequenceErrorFromParams unless path_str.valid_encoding?
  50 + end
  51 + end
  52 + before_filter :force_utf8_params
  53 + end
  54 +
  55 +
  56 + # Serialized columns in AR don't support UTF-8 well, so set the encoding on those as well.
  57 + class ActiveRecord::Base
  58 + def unserialize_attribute_with_utf8(attr_name)
  59 + traverse = lambda do |object, block|
  60 + if object.kind_of?(Hash)
  61 + object.each_value { |o| traverse.call(o, block) }
  62 + elsif object.kind_of?(Array)
  63 + object.each { |o| traverse.call(o, block) }
  64 + else
  65 + block.call(object)
  66 + end
  67 + object
  68 + end
  69 + force_encoding = lambda do |o|
  70 + o.force_encoding(Encoding::UTF_8) if o.respond_to?(:force_encoding)
  71 + end
  72 + value = unserialize_attribute_without_utf8(attr_name)
  73 + traverse.call(value, force_encoding)
  74 + end
  75 + alias_method_chain :unserialize_attribute, :utf8
  76 + end
  77 +
  78 + # Make sure the flash sets the encoding to UTF-8 as well.
  79 + module ActionController
  80 + module Flash
  81 + class FlashHash
  82 + def [](k)
  83 + v = super
  84 + v.is_a?(String) ? v.force_encoding("UTF-8") : v
  85 + end
  86 + end
  87 + end
  88 + end
  89 +end
... ...