inquisition 0.2 → 0.3

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.
@@ -1,4 +1,4 @@
1
- = inquisition
1
+ = Inquisition
2
2
 
3
3
  == Introduction
4
4
 
@@ -9,14 +9,21 @@ It keeps your strings heresy-free.
9
9
 
10
10
  Inquisition offers you three methods on Object:
11
11
 
12
- cleanse_attr *attributes
13
- cleanse_attr_reader *attributes
14
- cleanse_attr_writer *attributes
12
+ cleanse_attr *attributes, options
13
+ cleanse_attr_reader *attributes, options
14
+ cleanse_attr_writer *attributes, options
15
15
 
16
16
  These methods will wrap your getters and/or setters for an attribute through a
17
17
  HTML5 Sanitizer. This should help to protect against most kinds of cross site
18
18
  scripting attacks.
19
19
 
20
+ For example:
21
+
22
+ cleanse_attr :name, :allow => {:name => /(<strong>)/}
23
+
24
+ The above example will clean all values written to or read from the name
25
+ attribute, but will not remove strong tags.
26
+
20
27
  == Installation
21
28
 
22
29
  sudo gem install thumblemonks-inquisition
@@ -10,6 +10,14 @@ module Inquisition
10
10
  klass.extend(ClassMethods)
11
11
  end
12
12
 
13
+ def self.sanitize(value, allow)
14
+ if allow && match = Regexp.new(allow).match(value)
15
+ [HTML5libSanitize.sanitize_html(match.pre_match), match.to_a.first, self.sanitize(match.post_match, allow)].join
16
+ else
17
+ HTML5libSanitize.sanitize_html(value)
18
+ end
19
+ end
20
+
13
21
  module ClassMethods
14
22
  def sanitize_attribute(*attributes)
15
23
  sanitize_attribute_reader(*attributes)
@@ -17,34 +25,49 @@ module Inquisition
17
25
  end
18
26
 
19
27
  def sanitize_attribute_reader(*attributes)
20
- write_inheritable_attribute(:cleansed_attr_readers, attributes)
21
- class_inheritable_reader(:cleansed_attr_readers)
22
-
23
- define_method(:read_attribute_with_cleansing) do |attribute|
24
- value = read_attribute_without_cleansing(attribute)
25
- if cleansed_attr_readers.include?(attribute.to_sym) && !value.blank?
26
- HTML5libSanitize.sanitize_html(value)
27
- else
28
- value
28
+ options = attributes.last.is_a?(::Hash) ? attributes.pop : {}
29
+ if respond_to?(:cleansed_attr_readers)
30
+ write_inheritable_attribute(:cleansed_attr_readers, cleansed_attr_readers.concat(attributes))
31
+ write_inheritable_attribute(:cleansed_attr_reader_options, cleansed_attr_reader_options.merge(options))
32
+ else
33
+ write_inheritable_attribute(:cleansed_attr_readers, attributes)
34
+ write_inheritable_attribute(:cleansed_attr_reader_options, options)
35
+ class_inheritable_reader(:cleansed_attr_readers)
36
+ class_inheritable_reader(:cleansed_attr_reader_options)
37
+
38
+ define_method(:read_attribute_with_cleansing) do |attribute|
39
+ value = read_attribute_without_cleansing(attribute)
40
+ if cleansed_attr_readers.include?(attribute.to_sym) && !value.blank?
41
+ Inquisition.sanitize(value,cleansed_attr_reader_options[:allow][attribute.to_sym])
42
+ else
43
+ value
44
+ end
29
45
  end
46
+ alias_method_chain :read_attribute, :cleansing
30
47
  end
31
- alias_method_chain :read_attribute, :cleansing
32
48
 
33
49
  attributes.each { |attr| define_method(attr.to_sym) { read_attribute(attr.to_sym) } }
34
50
  end
35
51
 
36
52
  def sanitize_attribute_writer(*attributes)
37
- write_inheritable_attribute(:cleansed_attr_writers, attributes)
38
- class_inheritable_reader(:cleansed_attr_writers)
53
+ options = attributes.last.is_a?(::Hash) ? attributes.pop : {}
54
+ if respond_to?(:cleansed_attr_writers)
55
+ write_inheritable_attribute(:cleansed_attr_writers, cleansed_attr_writers.concat(attributes))
56
+ write_inheritable_attribute(:cleansed_attr_writer_options, cleansed_attr_writer_options.merge(options))
57
+ else
58
+ write_inheritable_attribute(:cleansed_attr_writers, attributes)
59
+ write_inheritable_attribute(:cleansed_attr_writer_options, options)
60
+ class_inheritable_reader(:cleansed_attr_writers)
61
+ class_inheritable_reader(:cleansed_attr_writer_options)
39
62
 
40
- define_method(:write_attribute_with_cleansing) do |attribute, value|
41
- if cleansed_attr_writers.include?(attribute.to_sym) && !value.blank?
42
- value = HTML5libSanitize.sanitize_html(value)
63
+ define_method(:write_attribute_with_cleansing) do |attribute, value|
64
+ if cleansed_attr_writers.include?(attribute.to_sym) && !value.blank?
65
+ Inquisition.sanitize(value,cleansed_attr_writer_options[:allow][attribute.to_sym])
66
+ end
67
+ write_attribute_without_cleansing(attribute, value)
43
68
  end
44
-
45
- write_attribute_without_cleansing(attribute, value)
69
+ alias_method_chain :write_attribute, :cleansing
46
70
  end
47
- alias_method_chain :write_attribute, :cleansing
48
71
  end
49
72
  end #Class Methods
50
73
  end #Inquisition
@@ -47,4 +47,41 @@ class InquisitionTest < Test::Unit::TestCase
47
47
  assert_equal nil, @whisky.name
48
48
  end
49
49
  end
50
+
51
+ context "allowing a single character" do
52
+ setup do
53
+ @dumb_phrase = "Central Time (US & Canada)"
54
+ @clean_dumb = "Central Time (US &amp; Canada)"
55
+ @whisky = Whisky.new(:description => @dumb_phrase, :name => @dumb_phrase)
56
+ end
57
+
58
+ should "allow ampersands in the description" do
59
+ assert_equal @dumb_phrase, @whisky.description
60
+ end
61
+
62
+ should "not allow ampersands in the name" do
63
+ assert_equal @clean_dumb, @whisky.name
64
+ end
65
+ end
66
+
67
+ context "allowing a regexp" do
68
+ setup do
69
+ @dumb_phrase = "<buttes> hey guy, I think <buttes> about <buttes>, because i have no clear opinion on <buttes>"
70
+ @clean_phrase = "&lt;buttes&gt; hey guy, I think &lt;buttes&gt; about &lt;buttes&gt;, because i have no clear opinion on &lt;buttes&gt;"
71
+ @whisky = Whisky.new(:measure => @dumb_phrase, :name => @dumb_phrase)
72
+ end
73
+
74
+ should "allow the regexp'd phrase in the measure" do
75
+ assert_equal @dumb_phrase, @whisky.measure
76
+ end
77
+
78
+ should "not allow the regexp'd phrase in the name" do
79
+ assert_equal @clean_phrase, @whisky.name
80
+ end
81
+
82
+ should "still clean non-matched parts" do
83
+ @whisky.measure = "<script>alert('Cragganmore')</script>"
84
+ assert_equal "&lt;script&gt;alert('Cragganmore')&lt;/script&gt;", @whisky.measure
85
+ end
86
+ end
50
87
  end
@@ -3,7 +3,7 @@ ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => File
3
3
  class CreateSchema < ActiveRecord::Migration
4
4
  def self.up
5
5
  create_table :whiskies, :force => true do |t|
6
- t.string :name, :origin, :description
6
+ t.string :name, :origin, :description, :measure
7
7
  t.integer :abv
8
8
  end
9
9
  create_table :animals, :force => true do |t|
@@ -21,7 +21,7 @@ class Animal < ActiveRecord::Base
21
21
  end
22
22
 
23
23
  class Whisky < ActiveRecord::Base
24
- sanitize_attribute :name, :description
24
+ sanitize_attribute :name, :description, :measure, :allow => { :description => "&", :measure => /(<buttes>)/ }
25
25
 
26
26
  def drink
27
27
  "You quaffed #{description}"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inquisition
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.2"
4
+ version: "0.3"
5
5
  platform: ruby
6
6
  authors:
7
7
  - toothrot
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-06 00:00:00 -05:00
12
+ date: 2009-11-11 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -69,7 +69,7 @@ requirements: []
69
69
  rubyforge_project:
70
70
  rubygems_version: 1.3.5
71
71
  signing_key:
72
- specification_version: 2
72
+ specification_version: 3
73
73
  summary: Inquisition is a fancy way to protect your ActiveRecord attributes from XSS
74
74
  test_files: []
75
75