implement escaped params
This commit is contained in:
parent
5535bf89f5
commit
2f2a95da69
|
@ -1,4 +1,5 @@
|
||||||
require 'rack/protection'
|
require 'rack/protection'
|
||||||
|
require 'escape_utils'
|
||||||
|
|
||||||
module Rack
|
module Rack
|
||||||
module Protection
|
module Protection
|
||||||
|
@ -9,10 +10,54 @@ module Rack
|
||||||
#
|
#
|
||||||
# Automatically escapes Rack::Request#params so they can be embedded in HTML
|
# Automatically escapes Rack::Request#params so they can be embedded in HTML
|
||||||
# or JavaScript without any further issues. Calls +html_safe+ on the escaped
|
# 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
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,4 +2,33 @@ require File.expand_path('../spec_helper.rb', __FILE__)
|
||||||
|
|
||||||
describe Rack::Protection::EscapedParams do
|
describe Rack::Protection::EscapedParams do
|
||||||
it_behaves_like "any rack application"
|
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
|
end
|
||||||
|
|
Loading…
Reference in New Issue