sanitized_attributes 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/Rakefile +46 -0
- data/VERSION +1 -0
- data/lib/sanitized_attributes.rb +90 -0
- data/lib/sanitized_attributes/sanitized_attribute.rb +48 -0
- data/sanitized_attributes.gemspec +57 -0
- data/spec/sanitized_attributes_spec.rb +67 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +9 -0
- metadata +15 -5
data/.document
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "sanitized_attributes"
|
8
|
+
gem.summary = %Q{HTML-sanitizing attribute accessors for Ruby and Rails}
|
9
|
+
gem.description = %Q{A wrapper to make automatic sanitization of incoming data easier. Uses the sanitize gem and works in both plain Ruby and Rails projects.}
|
10
|
+
gem.email = "matthew.boeh@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/mboeh/sanitized_attributes"
|
12
|
+
gem.authors = ["Matthew Boeh", "CrowdCompass, Inc."]
|
13
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
+
gem.add_dependency "sanitize", "> 0"
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'spec/rake/spectask'
|
22
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
23
|
+
spec.libs << 'lib' << 'spec'
|
24
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
30
|
+
spec.rcov = true
|
31
|
+
spec.rcov_opts = ['--exclude', File.expand_path("~/.rvm"), "--exclude", "spec"]
|
32
|
+
end
|
33
|
+
|
34
|
+
task :spec => :check_dependencies
|
35
|
+
|
36
|
+
task :default => :spec
|
37
|
+
|
38
|
+
require 'rake/rdoctask'
|
39
|
+
Rake::RDocTask.new do |rdoc|
|
40
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
41
|
+
|
42
|
+
rdoc.rdoc_dir = 'rdoc'
|
43
|
+
rdoc.title = "sanitized_attributes #{version}"
|
44
|
+
rdoc.rdoc_files.include('README*')
|
45
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
46
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.1.1
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sanitize'
|
3
|
+
require 'sanitized_attributes/sanitized_attribute'
|
4
|
+
|
5
|
+
module SanitizedAttributes
|
6
|
+
|
7
|
+
def self.included(into)
|
8
|
+
into.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
def add_option(name, &blk)
|
14
|
+
@option_transforms = nil
|
15
|
+
@options ||= {}
|
16
|
+
@options[name] = blk
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_profile(name, options = {})
|
20
|
+
@profiles ||= {}
|
21
|
+
@profiles[name] = options
|
22
|
+
end
|
23
|
+
|
24
|
+
def profile(name)
|
25
|
+
@profiles ||= {}
|
26
|
+
@profiles[name] || {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def sanitize_options(options)
|
30
|
+
pr =
|
31
|
+
if options.kind_of?(Symbol)
|
32
|
+
profile(options)
|
33
|
+
else
|
34
|
+
options
|
35
|
+
end
|
36
|
+
o = merge_options(default_profile, pr)
|
37
|
+
o
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
def default_profile
|
43
|
+
merge_options(profile(:default), obligatory_options)
|
44
|
+
end
|
45
|
+
|
46
|
+
def merge_options(ops, new_ops)
|
47
|
+
final_ops = ops.dup
|
48
|
+
new_ops.each do |key,val|
|
49
|
+
old = final_ops[key]
|
50
|
+
if key == :transformers
|
51
|
+
final_ops[key] ||= []
|
52
|
+
final_ops[key] = ([old] + [val]).flatten.uniq.compact
|
53
|
+
else
|
54
|
+
final_ops[key] = val
|
55
|
+
end
|
56
|
+
final_ops.delete(key) if final_ops[key].nil?
|
57
|
+
end
|
58
|
+
return final_ops
|
59
|
+
end
|
60
|
+
|
61
|
+
def obligatory_options
|
62
|
+
{ :transformers => option_transforms }
|
63
|
+
end
|
64
|
+
|
65
|
+
def option_transforms
|
66
|
+
@option_transforms ||=
|
67
|
+
begin
|
68
|
+
if @options
|
69
|
+
@options.map do |name, tproc|
|
70
|
+
lambda do |env|
|
71
|
+
tproc.call(env, env[:config][name]) if env[:config][name]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
else
|
75
|
+
[]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
module ClassMethods
|
83
|
+
|
84
|
+
def sanitize_attribute(attr_name, options = {})
|
85
|
+
SanitizedAttribute.add(self, attr_name, options)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module SanitizedAttributes; class SanitizedAttribute
|
2
|
+
|
3
|
+
def initialize(attr_name, options = {})
|
4
|
+
@attr_name = attr_name
|
5
|
+
@options = options
|
6
|
+
end
|
7
|
+
|
8
|
+
def sanitize(content)
|
9
|
+
Sanitize.clean("<SPURIOUS-TOPLEVEL>" + content + "</SPURIOUS-TOPLEVEL>", sanitize_config).gsub(%r{</?SPURIOUS-TOPLEVEL>}, "")
|
10
|
+
end
|
11
|
+
|
12
|
+
def define_ar_writer_method(klass)
|
13
|
+
this = self
|
14
|
+
attr_name = @attr_name
|
15
|
+
klass.send(:define_method, "#{@attr_name}=") {|value|
|
16
|
+
send(:write_attribute, attr_name, this.sanitize(value))
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def define_writer_method(klass)
|
21
|
+
this = self
|
22
|
+
attr_name = @attr_name
|
23
|
+
klass.send(:define_method, "#{@attr_name}_with_sanitization=") {|value|
|
24
|
+
send("#{attr_name}_without_sanitization=", this.sanitize(value))
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def sanitize_config
|
31
|
+
SanitizedAttributes.sanitize_options(@options)
|
32
|
+
end
|
33
|
+
|
34
|
+
class << self
|
35
|
+
|
36
|
+
def add(klass, attr_name, options = {})
|
37
|
+
attrib = new(attr_name, options)
|
38
|
+
if klass.respond_to?(:alias_method_chain)
|
39
|
+
attrib.define_ar_writer_method(klass)
|
40
|
+
else
|
41
|
+
attrib.define_writer_method(klass)
|
42
|
+
klass.send(:alias_method, "#{attr_name}_without_sanitization=", "#{attr_name}=")
|
43
|
+
klass.send(:alias_method, "#{attr_name}=", "#{attr_name}_with_sanitization=")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end; end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{sanitized_attributes}
|
8
|
+
s.version = "1.1.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Matthew Boeh", "CrowdCompass, Inc."]
|
12
|
+
s.date = %q{2011-01-27}
|
13
|
+
s.description = %q{A wrapper to make automatic sanitization of incoming data easier. Uses the sanitize gem and works in both plain Ruby and Rails projects.}
|
14
|
+
s.email = %q{matthew.boeh@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"LICENSE",
|
22
|
+
"README.rdoc",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"lib/sanitized_attributes.rb",
|
26
|
+
"lib/sanitized_attributes/sanitized_attribute.rb",
|
27
|
+
"sanitized_attributes.gemspec",
|
28
|
+
"spec/sanitized_attributes_spec.rb",
|
29
|
+
"spec/spec.opts",
|
30
|
+
"spec/spec_helper.rb"
|
31
|
+
]
|
32
|
+
s.homepage = %q{http://github.com/mboeh/sanitized_attributes}
|
33
|
+
s.require_paths = ["lib"]
|
34
|
+
s.rubygems_version = %q{1.3.7}
|
35
|
+
s.summary = %q{HTML-sanitizing attribute accessors for Ruby and Rails}
|
36
|
+
s.test_files = [
|
37
|
+
"spec/sanitized_attributes_spec.rb",
|
38
|
+
"spec/spec_helper.rb"
|
39
|
+
]
|
40
|
+
|
41
|
+
if s.respond_to? :specification_version then
|
42
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
43
|
+
s.specification_version = 3
|
44
|
+
|
45
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
46
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
47
|
+
s.add_runtime_dependency(%q<sanitize>, ["> 0"])
|
48
|
+
else
|
49
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
50
|
+
s.add_dependency(%q<sanitize>, ["> 0"])
|
51
|
+
end
|
52
|
+
else
|
53
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
54
|
+
s.add_dependency(%q<sanitize>, ["> 0"])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "SanitizedAttributes" do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@klass = Class.new do
|
7
|
+
include SanitizedAttributes
|
8
|
+
attr_accessor :orz
|
9
|
+
attr_accessor :vux
|
10
|
+
end
|
11
|
+
SanitizedAttributes.add_option(:no_empties) do |env, forbidden_empties|
|
12
|
+
if env[:node].content.empty?
|
13
|
+
if forbidden_empties.include?(env[:node_name])
|
14
|
+
{:node => Nokogiri::XML::Text.new("", env[:node].document)}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
SanitizedAttributes.add_option(:gsub) do |env, substitutions|
|
19
|
+
env[:node].children.each do |node|
|
20
|
+
if node.kind_of?(Nokogiri::XML::Text)
|
21
|
+
text = node.content
|
22
|
+
substitutions.each do |regex, subst|
|
23
|
+
text.gsub!(regex, subst)
|
24
|
+
end
|
25
|
+
node.content = text
|
26
|
+
end
|
27
|
+
end
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
SanitizedAttributes.add_profile(:default, :gsub => { "\r" => "" })
|
31
|
+
SanitizedAttributes.add_profile(:quotes_only, :elements => %w[blockquote])
|
32
|
+
end
|
33
|
+
|
34
|
+
it "removes all HTML by default" do
|
35
|
+
@klass.module_eval do
|
36
|
+
sanitize_attribute :orz
|
37
|
+
end
|
38
|
+
obj = @klass.new
|
39
|
+
obj.orz = "<a>Orz are not *many bubbles* like <p/>*campers*. <p></p>Orz <b>are just</b> Orz. <p>- Orz</p>"
|
40
|
+
obj.orz.should == "Orz are not *many bubbles* like *campers*. Orz are just Orz. - Orz"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "allows a default sanitizing profile to be set up" do
|
44
|
+
SanitizedAttributes.add_profile(:default, Sanitize::Config::BASIC)
|
45
|
+
@klass.module_eval do
|
46
|
+
sanitize_attribute :orz
|
47
|
+
end
|
48
|
+
obj = @klass.new
|
49
|
+
obj.orz = "<a>Orz are not *many bubbles* like <p/>*campers*. <p></p>Orz <b>are just</b> Orz. <p>- Orz</p>"
|
50
|
+
obj.orz.should == "<a rel=\"nofollow\">Orz are not *many bubbles* like <p></p>*campers*. <p></p>Orz <b>are just</b> Orz. <p>- Orz</p></a>"
|
51
|
+
SanitizedAttributes.add_profile(:default, Sanitize::Config::BASIC.merge(:no_empties => %w[p]))
|
52
|
+
obj.orz = "<a>Orz are not *many bubbles* like <p/>*campers*. <p></p>Orz <b>are just</b> Orz. <p>- Orz</p>"
|
53
|
+
obj.orz.should == "<a rel=\"nofollow\">Orz are not *many bubbles* like *campers*. Orz <b>are just</b> Orz. <p>- Orz</p></a>"
|
54
|
+
end
|
55
|
+
|
56
|
+
it "sanitizes attributes with custom options and profiles" do
|
57
|
+
@klass.module_eval do
|
58
|
+
sanitize_attribute :orz, :elements => %w[p], :no_empties => %w[p]
|
59
|
+
sanitize_attribute :vux, :quotes_only
|
60
|
+
end
|
61
|
+
obj = @klass.new
|
62
|
+
obj.vux = "<blockquote>Our special today is <b>particle fragmentation!</b></blockquote> - VUX"
|
63
|
+
obj.vux.should == "<blockquote>Our special today is particle fragmentation!</blockquote> - VUX"
|
64
|
+
obj.orz = "\r\nOrz are not *many bubbles* like <p/>*campers*. <p></p>Orz <b>\r\nare just</b> Orz. <p>- Orz</p>"
|
65
|
+
obj.orz.should == "\nOrz are not *many bubbles* like *campers*. Orz \nare just Orz. <p>- Orz</p>"
|
66
|
+
end
|
67
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sanitized_attributes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 1.1.
|
9
|
+
- 1
|
10
|
+
version: 1.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matthew Boeh
|
@@ -59,8 +59,17 @@ extra_rdoc_files:
|
|
59
59
|
- LICENSE
|
60
60
|
- README.rdoc
|
61
61
|
files:
|
62
|
+
- .document
|
62
63
|
- LICENSE
|
63
64
|
- README.rdoc
|
65
|
+
- Rakefile
|
66
|
+
- VERSION
|
67
|
+
- lib/sanitized_attributes.rb
|
68
|
+
- lib/sanitized_attributes/sanitized_attribute.rb
|
69
|
+
- sanitized_attributes.gemspec
|
70
|
+
- spec/sanitized_attributes_spec.rb
|
71
|
+
- spec/spec.opts
|
72
|
+
- spec/spec_helper.rb
|
64
73
|
has_rdoc: true
|
65
74
|
homepage: http://github.com/mboeh/sanitized_attributes
|
66
75
|
licenses: []
|
@@ -95,5 +104,6 @@ rubygems_version: 1.3.7
|
|
95
104
|
signing_key:
|
96
105
|
specification_version: 3
|
97
106
|
summary: HTML-sanitizing attribute accessors for Ruby and Rails
|
98
|
-
test_files:
|
99
|
-
|
107
|
+
test_files:
|
108
|
+
- spec/sanitized_attributes_spec.rb
|
109
|
+
- spec/spec_helper.rb
|