implement escaped params
This commit is contained in:
parent
5535bf89f5
commit
2f2a95da69
|
@ -1,4 +1,5 @@
|
|||
require 'rack/protection'
|
||||
require 'escape_utils'
|
||||
|
||||
module Rack
|
||||
module Protection
|
||||
|
@ -9,10 +10,54 @@ module Rack
|
|||
#
|
||||
# Automatically escapes Rack::Request#params so they can be embedded in HTML
|
||||
# or JavaScript without any further issues. Calls +html_safe+ on the escaped
|
||||
# strings if defined, to avoid double-escaping in Rails.
|
||||
# strings if defined, to avoid double-escaping in Rails. It does only escape
|
||||
# for embedding in HTML and Javascript by default, so you have to take care
|
||||
# of URLs or SQL injection yourself.
|
||||
#
|
||||
# Not Yet Implemented!
|
||||
# Options:
|
||||
# escape:: What escaping modes to use, should be Symbol or Array of Symbols.
|
||||
# Available: :html, :javascript, :url, default: [:html, :javascript]
|
||||
class EscapedParams < Base
|
||||
default_options :escape => [:html, :javascript]
|
||||
|
||||
def initialize(*)
|
||||
super
|
||||
modes = Array options[:escape]
|
||||
code = "def self.escape_string(str) %s end"
|
||||
modes.each { |m| code %= "EscapeUtils.escape_#{m}(%s)"}
|
||||
eval code % 'str'
|
||||
end
|
||||
|
||||
def call(env)
|
||||
request = Request.new(env)
|
||||
get_was = handle(request.GET)
|
||||
post_was = handle(request.POST) rescue nil
|
||||
app.call env
|
||||
ensure
|
||||
request.GET.replace get_was
|
||||
request.POST.replace post_was if post_was
|
||||
end
|
||||
|
||||
def handle(hash)
|
||||
was = hash.dup
|
||||
hash.replace escape(hash)
|
||||
was
|
||||
end
|
||||
|
||||
def escape(object)
|
||||
case object
|
||||
when Hash then escape_hash(object)
|
||||
when Array then object.map { |o| escape(o) }
|
||||
when String then escape_string(object)
|
||||
else raise ArgumentError, "cannot escape #{object.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
def escape_hash(hash)
|
||||
hash = hash.dup
|
||||
hash.each { |k,v| hash[k] = escape(v) }
|
||||
hash
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,4 +2,33 @@ require File.expand_path('../spec_helper.rb', __FILE__)
|
|||
|
||||
describe Rack::Protection::EscapedParams do
|
||||
it_behaves_like "any rack application"
|
||||
|
||||
context 'escaping' do
|
||||
it 'escapes html entities' do
|
||||
mock_app do |env|
|
||||
request = Rack::Request.new(env)
|
||||
[200, {'Content-Type' => 'text/plain'}, [request.params['foo']]]
|
||||
end
|
||||
get '/', :foo => "<bar>"
|
||||
body.should == '<bar>'
|
||||
end
|
||||
|
||||
it 'leaves normal params untouched' do
|
||||
mock_app do |env|
|
||||
request = Rack::Request.new(env)
|
||||
[200, {'Content-Type' => 'text/plain'}, [request.params['foo']]]
|
||||
end
|
||||
get '/', :foo => "bar"
|
||||
body.should == 'bar'
|
||||
end
|
||||
|
||||
it 'copes with nested arrays' do
|
||||
mock_app do |env|
|
||||
request = Rack::Request.new(env)
|
||||
[200, {'Content-Type' => 'text/plain'}, [request.params['foo']['bar']]]
|
||||
end
|
||||
get '/', :foo => {:bar => "<bar>"}
|
||||
body.should == '<bar>'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue