Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
source :rubygems

group :dev do
gem 'rails', '2.3.14'
gem 'rake'
gem 'jeweler'
gem 'erubis'
gem 'test-unit', '>=2.5.2'
end
43 changes: 43 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
GEM
remote: http://rubygems.org/
specs:
actionmailer (2.3.14)
actionpack (= 2.3.14)
actionpack (2.3.14)
activesupport (= 2.3.14)
rack (~> 1.1.0)
activerecord (2.3.14)
activesupport (= 2.3.14)
activeresource (2.3.14)
activesupport (= 2.3.14)
activesupport (2.3.14)
erubis (2.7.0)
git (1.2.5)
jeweler (1.8.4)
bundler (~> 1.0)
git (>= 1.2.5)
rake
rdoc
json (1.7.5)
rack (1.1.3)
rails (2.3.14)
actionmailer (= 2.3.14)
actionpack (= 2.3.14)
activerecord (= 2.3.14)
activeresource (= 2.3.14)
activesupport (= 2.3.14)
rake (>= 0.8.3)
rake (0.9.2.2)
rdoc (3.12)
json (~> 1.4)
test-unit (2.5.2)

PLATFORMS
ruby

DEPENDENCIES
erubis
jeweler
rails (= 2.3.14)
rake
test-unit (>= 2.5.2)
10 changes: 3 additions & 7 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
require 'bundler/setup'
require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'
require 'rdoc/task'

desc 'Default: run unit tests.'
task :default => :test

desc 'Test the rails_xss plugin.'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
Rake::TestTask.new(:default) do |t|
t.pattern = 'test/**/*_test.rb'
t.verbose = true
end
Expand Down
118 changes: 101 additions & 17 deletions lib/rails_xss/string_ext.rb
Original file line number Diff line number Diff line change
@@ -1,26 +1,110 @@
require 'active_support/deprecation'

ActiveSupport::SafeBuffer.class_eval do
def concat(value)
if value.html_safe?
super(value)
else
super(ERB::Util.h(value))

module ActiveSupport #:nodoc:
class SafeBuffer < String
UNSAFE_STRING_METHODS = %w(
capitalize chomp chop delete downcase gsub lstrip next reverse rstrip
slice squeeze strip sub succ swapcase tr tr_s upcase prepend
)

alias_method :original_concat, :concat
private :original_concat

class SafeConcatError < StandardError
def initialize
super 'Could not concatenate to the buffer because it is not html safe.'
end
end
end
alias << concat
UNSAFE_STRING_METHODS = ["capitalize", "chomp", "chop", "delete", "downcase", "gsub", "lstrip", "next", "reverse", "rstrip", "slice", "squeeze", "strip", "sub", "succ", "swapcase", "tr", "tr_s", "upcase"].freeze

for unsafe_method in UNSAFE_STRING_METHODS
class_eval <<-EOT, __FILE__, __LINE__ + 1
def #{unsafe_method}(*args)
super.to_str
def [](*args)
if args.size < 2
super
else
if html_safe?
new_safe_buffer = super
new_safe_buffer.instance_eval { @html_safe = true }
new_safe_buffer
else
to_str[*args]
end
end

def #{unsafe_method}!(*args)
raise TypeError, "Cannot modify SafeBuffer in place"
end

def safe_concat(value)
raise SafeConcatError unless html_safe?
original_concat(value)
end

def initialize(*)
@html_safe = true
super
end

def initialize_copy(other)
super
@html_safe = other.html_safe?
end

def clone_empty
self[0, 0]
end

def concat(value)
if !html_safe? || value.html_safe?
super(value)
else
super(ERB::Util.h(value))
end
EOT
end
alias << concat

def +(other)
dup.concat(other)
end

def %(args)
args = Array(args).map do |arg|
if !html_safe? || arg.html_safe?
arg
else
ERB::Util.h(arg)
end
end

self.class.new(super(args))
end

def html_safe?
defined?(@html_safe) && @html_safe
end

def to_s
self
end

def to_param
to_str
end

def encode_with(coder)
coder.represent_scalar nil, to_str
end

UNSAFE_STRING_METHODS.each do |unsafe_method|
if 'String'.respond_to?(unsafe_method)
class_eval <<-EOT, __FILE__, __LINE__ + 1
def #{unsafe_method}(*args, &block) # def capitalize(*args, &block)
to_str.#{unsafe_method}(*args, &block) # to_str.capitalize(*args, &block)
end # end

def #{unsafe_method}!(*args) # def capitalize!(*args)
@html_safe = false # @html_safe = false
super # super
end # end
EOT
end
end
end
end

Expand Down
2 changes: 1 addition & 1 deletion test/active_record_helper_test.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require 'test_helper'
require File.expand_path('../test_helper', __FILE__)

class ActiveRecordHelperTest < ActionView::TestCase
silence_warnings do
Expand Down
10 changes: 10 additions & 0 deletions test/app/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

require(File.join(File.dirname(__FILE__), 'config', 'boot'))

require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'

require 'tasks/rails'
10 changes: 10 additions & 0 deletions test/app/app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Filters added to this controller apply to all controllers in the application.
# Likewise, all the methods added will be available for all controllers.

class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
protect_from_forgery # See ActionController::RequestForgeryProtection for details

# Scrub sensitive parameters from your log
# filter_parameter_logging :password
end
3 changes: 3 additions & 0 deletions test/app/app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Methods added to this helper will be available to all templates in the application.
module ApplicationHelper
end
114 changes: 114 additions & 0 deletions test/app/config/boot.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Don't change this file!
# Configure your app in config/environment.rb and config/environments/*.rb

RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)

module Rails
class << self
def boot!
unless booted?
preinitialize
pick_boot.run
end
end

def booted?
defined? Rails::Initializer
end

def pick_boot
(vendor_rails? ? VendorBoot : GemBoot).new
end

def vendor_rails?
File.exist?("#{RAILS_ROOT}/vendor/rails")
end

def preinitialize
load(preinitializer_path) if File.exist?(preinitializer_path)
end

def preinitializer_path
"#{RAILS_ROOT}/config/preinitializer.rb"
end
end

class Boot
def run
load_initializer
Rails::Initializer.run(:set_load_path)
end
end

class VendorBoot < Boot
def load_initializer
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
Rails::Initializer.run(:install_gem_spec_stubs)
Rails::GemDependency.add_frozen_gem_path
end
end

class GemBoot < Boot
def load_initializer
self.class.load_rubygems
load_rails_gem
require 'initializer'
end

def load_rails_gem
if version = self.class.gem_version
gem 'rails', version
else
gem 'rails'
end
rescue Gem::LoadError => load_error
if load_error.message =~ /Could not find RubyGem rails/
STDERR.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
exit 1
else
raise
end
end

class << self
def rubygems_version
Gem::RubyGemsVersion rescue nil
end

def gem_version
if defined? RAILS_GEM_VERSION
RAILS_GEM_VERSION
elsif ENV.include?('RAILS_GEM_VERSION')
ENV['RAILS_GEM_VERSION']
else
parse_gem_version(read_environment_rb)
end
end

def load_rubygems
min_version = '1.3.2'
require 'rubygems'
unless rubygems_version >= min_version
$stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
exit 1
end

rescue LoadError
$stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
exit 1
end

def parse_gem_version(text)
$1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
end

private
def read_environment_rb
File.read("#{RAILS_ROOT}/config/environment.rb")
end
end
end
end

# All that for this:
Rails.boot!
22 changes: 22 additions & 0 deletions test/app/config/database.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# SQLite version 3.x
# gem install sqlite3-ruby (not necessary on OS X Leopard)
development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
adapter: sqlite3
database: db/test.sqlite3
pool: 5
timeout: 5000

production:
adapter: sqlite3
database: db/production.sqlite3
pool: 5
timeout: 5000
Loading