Instantly share code, notes, and snippets.
-
Save shinzui/556116 to your computer and use it in GitHub Desktop.
Rack middleware to clean post and get params
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# # # # | |
# Rack::NoTags removes < and > from all incoming requests | |
# http://rbjl.net/12-rack-notags | |
# | |
# (c) 2009 - 2010 Jan Lelis | |
# This software is licensed under the MIT license. | |
# # # # | |
module Rack | |
# Sometimes, simple approaches to solve a problem are the best, | |
# because of the danger, that complex ones have holes... | |
# | |
# Usage (Rails) | |
# | |
# In config/environment.rb add: | |
# require 'path/to/rack-notags.rb' | |
# config.middleware.use Rack::NoTags | |
# | |
# You can activate a different filter mode with: | |
# config.middleware.use Rack::NoTags, :paranoid | |
class NoTags | |
PATTERNS = { # replacement => [ array, of, patterns ] | |
:brackets_only => { | |
'<' => %w[ < %3C ], | |
'>' => %w[ > %3E ] | |
}, | |
# similar to Racks escape_html + url_encoded variants | |
:valid_xml => { | |
'<' => %w[ < %3C ], | |
'>' => %w[ > %3E ], | |
'&' => %w[ & %26 ], | |
''' => %w[ ' %27 ], | |
'"' => %w[ " %22 ] | |
}, | |
# encodings which might be interpreted as < or > in some situations | |
:paranoid => { | |
'' => %w[ < > %3C %3E ] + [ | |
/&[lg]t;?/i, | |
/�{0,5}6[02];?/, | |
/�{0,5}3[ce];?/i ] | |
} | |
} | |
def initialize(app, mode = :brackets_only, ignore = {}) | |
@app = app | |
@patterns = PATTERNS[mode.to_sym] # mode selects the right pattern set | |
@ignore = ignore # if one entry of the ignore list matches a post param, | |
# nothing will be filtered | |
end | |
def call(env) | |
# get params in a nice format | |
post_params = Rack::Utils.parse_query(env['rack.input'].read, "&") | |
get_params = Rack::Utils.parse_query(env['QUERY_STRING'], "&") | |
# remove @patterns | |
unless ignore?(post_params) | |
post_params = strip_all(post_params) | |
get_params = strip_all(get_params) | |
end | |
# update envirionment | |
env['rack.input'] = StringIO.new(Rack::Utils.build_query(post_params)) | |
env['QUERY_STRING'] = Rack::Utils.build_query(get_params) | |
# call framework | |
@app.call(env) | |
end | |
private | |
# check if param is on ignore list | |
def ignore?(params) | |
ret = false | |
@ignore.each{ |ign_param, ign_value| | |
params.each{ |param, value| | |
if !value.is_a?(Array) && | |
ign_param.to_s == param.to_s && | |
ign_value.to_s == value.to_s | |
ret = true | |
end | |
} | |
} | |
ret | |
end | |
# applies each 'to-substitute'-pattern to the string | |
def strip(string) | |
begin | |
@patterns.each{ |replacement, patterns| | |
patterns.each{ |pattern| | |
string = string.gsub(pattern, replacement) | |
} | |
} | |
end while catch :still_some do | |
# check if there is still any pattern that needs to be aplied | |
@patterns.each{ |_, patterns| | |
patterns.each{ |pattern| | |
if string[pattern] # like =~ but =~ is not | |
# defined for two strings | |
throw :still_some, true | |
end | |
} | |
} | |
false | |
end | |
string | |
end | |
# looks at every param-element an sends it to the strip method | |
def strip_all(params) | |
ret = {} | |
params.each{ |param, value| | |
ret[strip(param)] = value.is_a?(Array) ? value.map{|v|strip(v)} : strip(value) | |
} | |
ret | |
end | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment