glue 0.20.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/CHANGELOG +161 -110
  2. data/INSTALL +12 -12
  3. data/README +1 -1
  4. data/Rakefile +43 -45
  5. data/doc/AUTHORS +5 -5
  6. data/doc/LICENSE +3 -3
  7. data/doc/RELEASES +32 -24
  8. data/install.rb +7 -17
  9. data/lib/facet/object/alias_class.rb +12 -0
  10. data/lib/glue.rb +35 -35
  11. data/lib/glue/array.rb +46 -46
  12. data/lib/glue/aspects.rb +199 -209
  13. data/lib/glue/attribute.rb +15 -15
  14. data/lib/glue/autoreload.rb +1 -1
  15. data/lib/glue/builder.rb +48 -0
  16. data/lib/glue/builder/xml.rb +114 -0
  17. data/lib/glue/cache.rb +189 -0
  18. data/lib/glue/configuration.rb +108 -90
  19. data/lib/glue/flexob.rb +17 -17
  20. data/lib/glue/hash.rb +71 -71
  21. data/lib/glue/helper.rb +12 -12
  22. data/lib/glue/idgen.rb +9 -0
  23. data/lib/glue/idgen/md5.rb +24 -0
  24. data/lib/glue/idgen/sequential.rb +15 -0
  25. data/lib/glue/literal_method.rb +44 -0
  26. data/lib/glue/localization.rb +130 -0
  27. data/lib/glue/logger.rb +98 -98
  28. data/lib/glue/misc.rb +7 -7
  29. data/lib/glue/mixins.rb +19 -19
  30. data/lib/glue/number.rb +8 -8
  31. data/lib/glue/object.rb +2 -2
  32. data/lib/glue/pool.rb +43 -43
  33. data/lib/glue/property.rb +392 -392
  34. data/lib/glue/sanitize.rb +34 -34
  35. data/lib/glue/settings.rb +1 -1
  36. data/lib/glue/snapshot.rb +104 -0
  37. data/lib/glue/string.rb +129 -129
  38. data/lib/glue/time.rb +53 -53
  39. data/lib/glue/uri.rb +162 -162
  40. data/lib/glue/validation.rb +421 -421
  41. data/lib/vendor/blankslate.rb +53 -0
  42. data/test/glue/builder/tc_xml.rb +56 -0
  43. data/test/glue/tc_aspects.rb +90 -90
  44. data/test/glue/tc_attribute.rb +11 -11
  45. data/test/glue/tc_builder.rb +30 -0
  46. data/test/glue/tc_configuration.rb +97 -97
  47. data/test/glue/tc_flexob.rb +10 -10
  48. data/test/glue/tc_hash.rb +23 -23
  49. data/test/glue/tc_localization.rb +49 -0
  50. data/test/glue/tc_logger.rb +31 -31
  51. data/test/glue/tc_numbers.rb +9 -9
  52. data/test/glue/tc_property.rb +67 -67
  53. data/test/glue/tc_property_mixins.rb +17 -17
  54. data/test/glue/tc_property_type_checking.rb +13 -13
  55. data/test/glue/tc_strings.rb +94 -94
  56. data/test/glue/tc_uri.rb +65 -65
  57. data/test/glue/tc_validation.rb +196 -196
  58. metadata +26 -4
data/lib/glue/sanitize.rb CHANGED
@@ -8,41 +8,41 @@ VERBOTEN_TAGS = %w(form script) unless defined?(VERBOTEN_TAGS)
8
8
  VERBOTEN_ATTRS = /^on/i unless defined?(VERBOTEN_ATTRS)
9
9
 
10
10
  class String
11
- # Sanitizes the given HTML by making form and script tags into regular
12
- # text, and removing all "onxxx" attributes (so that arbitrary Javascript
13
- # cannot be executed). Also removes href attributes that start with
14
- # "javascript:".
15
- #
16
- # Returns the sanitized text.
17
- def self.sanitize(html)
18
- # only do this if absolutely necessary
19
- if html.index("<")
20
- tokenizer = HTML::Tokenizer.new(html)
21
- new_text = ""
11
+ # Sanitizes the given HTML by making form and script tags into regular
12
+ # text, and removing all "onxxx" attributes (so that arbitrary Javascript
13
+ # cannot be executed). Also removes href attributes that start with
14
+ # "javascript:".
15
+ #
16
+ # Returns the sanitized text.
17
+ def self.sanitize(html)
18
+ # only do this if absolutely necessary
19
+ if html.index("<")
20
+ tokenizer = HTML::Tokenizer.new(html)
21
+ new_text = ""
22
22
 
23
- while token = tokenizer.next
24
- node = HTML::Node.parse(nil, 0, 0, token, false)
25
- new_text << case node
26
- when HTML::Tag
27
- if VERBOTEN_TAGS.include?(node.name)
28
- node.to_s.gsub(/</, "&lt;")
29
- else
30
- if node.closing != :close
31
- node.attributes.delete_if { |attr,v| attr =~ VERBOTEN_ATTRS }
32
- if node.attributes["href"] =~ /^javascript:/i
33
- node.attributes.delete "href"
34
- end
35
- end
36
- node.to_s
37
- end
38
- else
39
- node.to_s.gsub(/</, "&lt;")
40
- end
41
- end
23
+ while token = tokenizer.next
24
+ node = HTML::Node.parse(nil, 0, 0, token, false)
25
+ new_text << case node
26
+ when HTML::Tag
27
+ if VERBOTEN_TAGS.include?(node.name)
28
+ node.to_s.gsub(/</, "&lt;")
29
+ else
30
+ if node.closing != :close
31
+ node.attributes.delete_if { |attr,v| attr =~ VERBOTEN_ATTRS }
32
+ if node.attributes["href"] =~ /^javascript:/i
33
+ node.attributes.delete "href"
34
+ end
35
+ end
36
+ node.to_s
37
+ end
38
+ else
39
+ node.to_s.gsub(/</, "&lt;")
40
+ end
41
+ end
42
42
 
43
- html = new_text
44
- end
43
+ html = new_text
44
+ end
45
45
 
46
- html
47
- end
46
+ html
47
+ end
48
48
  end
data/lib/glue/settings.rb CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  require 'glue/configuration'
4
4
 
5
- # * George Moschovitis <gm@navel.gr>
5
+ # * George Moschovitis <gm@navel.gr>
@@ -0,0 +1,104 @@
1
+ module Glue
2
+
3
+ # Class Snapshot simply represents a collection of objects from
4
+ # which snapshots were taken via their methods #take_snapshot.
5
+ # It provides methods to add an object to a snapshot
6
+ # (method Glue::Snapshot#add) as well as to restore all objects
7
+ # of the snapshot to their state stored in the snapshot (method
8
+ # Glue::Snapshot#restore).
9
+ #
10
+ # In Wee, this class is used to backtracking the state of
11
+ # components (or decorations/presenters). Components that want
12
+ # an undo-facility to be implemented (triggered for example by
13
+ # a browsers back-button), have to overwrite the
14
+ # Wee::Component#backtrack_state method.
15
+
16
+ class Snapshot
17
+ def initialize
18
+ @objects = Hash.new
19
+ end
20
+
21
+ def add(object)
22
+ oid = object.object_id
23
+ @objects[oid] = [object, object.take_snapshot] unless @objects.include?(oid)
24
+ end
25
+
26
+ def restore
27
+ @objects.each_value { |object, value| object.restore_snapshot(value) }
28
+ end
29
+ end
30
+
31
+ module DupReplaceSnapshotMixin
32
+ def take_snapshot
33
+ dup
34
+ end
35
+
36
+ def restore_snapshot(snap)
37
+ replace(snap)
38
+ end
39
+ end
40
+
41
+ # Implements a value holder. In Wee this is useful for
42
+ # backtracking the reference assigned to an instance variable
43
+ # (not the object itself!). An example where this is used is the
44
+ # <tt>@__decoration</tt> attribute of class Wee::Component.
45
+
46
+ class ValueHolder
47
+ attr_accessor :value
48
+
49
+ def initialize(value=nil)
50
+ @value = value
51
+ end
52
+
53
+ def take_snapshot
54
+ @value
55
+ end
56
+
57
+ def restore_snapshot(value)
58
+ @value = value
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ #--
65
+ # Extend some base classes of Ruby (Object, Array, String, Hash,
66
+ # Struct) for the two methods #take_snapshot and
67
+ # #restore_snapshot, required by Snapshot.
68
+ #++
69
+
70
+ class Object
71
+ def take_snapshot
72
+ snap = Hash.new
73
+ instance_variables.each do |iv|
74
+ snap[iv] = instance_variable_get(iv)
75
+ end
76
+ snap
77
+ end
78
+
79
+ def restore_snapshot(snap)
80
+ instance_variables.each do |iv|
81
+ instance_variable_set(iv, snap[iv])
82
+ end
83
+ end
84
+ end
85
+
86
+ class Array; include Glue::DupReplaceSnapshotMixin end
87
+
88
+ class String; include Glue::DupReplaceSnapshotMixin end
89
+
90
+ class Hash; include Glue::DupReplaceSnapshotMixin end
91
+
92
+ class Struct
93
+ def take_snapshot
94
+ snap = Hash.new
95
+ each_pair {|k,v| snap[k] = v}
96
+ snap
97
+ end
98
+
99
+ def restore_snapshot(snap)
100
+ snap.each_pair {|k,v| send(k.to_s + "=", v)}
101
+ end
102
+ end
103
+
104
+ # * Michael Neumann <mneumann@ntecs.de>
data/lib/glue/string.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  # * Anastasios Koutoumanos <ak@navel.gr>
3
3
  # * Elias Karakoulakis <ekarak@ktismata.com>
4
4
  # (c) 2004-2005 Navel, all rights reserved.
5
- # $Id: string.rb 1 2005-04-11 11:04:30Z gmosx $
5
+ # $Id: string.rb 182 2005-07-22 10:07:50Z gmosx $
6
6
 
7
7
  require 'uri'
8
8
 
@@ -25,137 +25,137 @@ module Glue;
25
25
 
26
26
  module StringUtils
27
27
 
28
- # Move this in String class?
29
- #
30
- # Tests a string for a valid value (non nil, not empty)
31
- #
32
- def self.valid?(string)
33
- return (not ((nil == string) or (string.empty?)))
34
- end
35
-
36
- # returns short abstract of long strings (first 'count'
37
- # characters, chopped at the nearest word, appended by '...')
38
- # force_cutoff: break forcibly at 'count' chars. Does not accept
39
- # count < 2.
40
-
41
- def self.head(string, count = 128, force_cutoff = false, ellipsis="...")
42
- return nil unless string
43
- return nil if count < 2
44
-
45
- if string.size > count
46
- cut_at = force_cutoff ? count : (string.index(' ', count-1) || count)
47
- xstring = string.slice(0, cut_at)
48
- return xstring.chomp(" ") + ellipsis
49
- else
50
- return string
51
- end
52
- end
53
-
54
- # Apply a set of rules (regular expression matches) to the
55
- # string
56
- #
57
- # === Requirements:
58
- # - the rules must be applied in order! So we cannot use a
59
- # hash because the ordering is not guaranteed! we use an
60
- # array instead.
61
- #
62
- # === Input:
63
- # the string to rewrite
64
- # the array containing rule-pairs (match, rewrite)
65
- #
66
- # === Output:
67
- # the rewritten string
68
-
69
- MATCH = 0
70
- REWRITE = 1
71
-
72
- def self.rewrite(string, rules)
73
- return nil unless string
74
-
75
- # gmosx: helps to find bugs
76
- raise ArgumentError.new('The rules parameter is nil') unless rules
77
-
78
- rewritten_string = string.dup
79
-
80
- for rule in rules
81
- rewritten_string.gsub!(rule[MATCH], rule[REWRITE])
82
- end
83
-
84
- return (rewritten_string or string)
85
- end
86
-
87
- # Enforces a maximum width of a string inside an
88
- # html container. If the string exceeds this maximum width
89
- # the string gets wraped.
90
- #
91
- # Not really useful, better use the CSS overflow: hidden
92
- # functionality.
93
- #
94
- # === Input:
95
- # the string to be wrapped
96
- # the enforced width
97
- # the separator used for wrapping
98
- #
99
- # === Output:
100
- # the wrapped string
101
- #
102
- # === Example:
103
- # text = "1111111111111111111111111111111111111111111"
104
- # text = wrap(text, 10, " ")
105
- # p text # => "1111111111 1111111111 1111111111"
106
- #
107
- # See the test cases to better understand the behaviour!
108
-
109
- def self.wrap(string, width = 20, separator = " ")
110
- return nil unless string
111
-
112
- re = /([^#{separator}]{1,#{width}})/
113
- wrapped_string = string.scan(re).join(separator)
114
-
115
- return wrapped_string
116
- end
117
-
118
- # Replace dangerours chars in filenames
28
+ # Move this in String class?
29
+ #
30
+ # Tests a string for a valid value (non nil, not empty)
31
+ #
32
+ def self.valid?(string)
33
+ return (not ((nil == string) or (string.empty?)))
34
+ end
35
+
36
+ # returns short abstract of long strings (first 'count'
37
+ # characters, chopped at the nearest word, appended by '...')
38
+ # force_cutoff: break forcibly at 'count' chars. Does not accept
39
+ # count < 2.
40
+
41
+ def self.head(string, count = 128, force_cutoff = false, ellipsis="...")
42
+ return nil unless string
43
+ return nil if count < 2
44
+
45
+ if string.size > count
46
+ cut_at = force_cutoff ? count : (string.index(' ', count-1) || count)
47
+ xstring = string.slice(0, cut_at)
48
+ return xstring.chomp(" ") + ellipsis
49
+ else
50
+ return string
51
+ end
52
+ end
53
+
54
+ # Apply a set of rules (regular expression matches) to the
55
+ # string
56
+ #
57
+ # === Requirements:
58
+ # - the rules must be applied in order! So we cannot use a
59
+ # hash because the ordering is not guaranteed! we use an
60
+ # array instead.
61
+ #
62
+ # === Input:
63
+ # the string to rewrite
64
+ # the array containing rule-pairs (match, rewrite)
65
+ #
66
+ # === Output:
67
+ # the rewritten string
68
+
69
+ MATCH = 0
70
+ REWRITE = 1
71
+
72
+ def self.rewrite(string, rules)
73
+ return nil unless string
74
+
75
+ # gmosx: helps to find bugs
76
+ raise ArgumentError.new('The rules parameter is nil') unless rules
77
+
78
+ rewritten_string = string.dup
79
+
80
+ for rule in rules
81
+ rewritten_string.gsub!(rule[MATCH], rule[REWRITE])
82
+ end
83
+
84
+ return (rewritten_string or string)
85
+ end
86
+
87
+ # Enforces a maximum width of a string inside an
88
+ # html container. If the string exceeds this maximum width
89
+ # the string gets wraped.
90
+ #
91
+ # Not really useful, better use the CSS overflow: hidden
92
+ # functionality.
93
+ #
94
+ # === Input:
95
+ # the string to be wrapped
96
+ # the enforced width
97
+ # the separator used for wrapping
98
+ #
99
+ # === Output:
100
+ # the wrapped string
101
+ #
102
+ # === Example:
103
+ # text = "1111111111111111111111111111111111111111111"
104
+ # text = wrap(text, 10, " ")
105
+ # p text # => "1111111111 1111111111 1111111111"
106
+ #
107
+ # See the test cases to better understand the behaviour!
108
+
109
+ def self.wrap(string, width = 20, separator = " ")
110
+ return nil unless string
111
+
112
+ re = /([^#{separator}]{1,#{width}})/
113
+ wrapped_string = string.scan(re).join(separator)
114
+
115
+ return wrapped_string
116
+ end
117
+
118
+ # Replace dangerours chars in filenames
119
119
  =begin
120
- def self.rationalize_filename(filename)
121
- return nil unless filename
122
- # gmosx: rationalize a copy!!! (add unit test)
123
- xfilename = filename.dup()
124
- # gmosx: replace some dangerous chars!
125
- xfilename.gsub!(/ /, "-")
126
- xfilename.gsub!(/!/, "")
127
- xfilename.gsub!(/'/, "")
128
- xfilename.gsub!(/\(/, "")
129
- xfilename.gsub!(/\)/, "")
130
- # xfilename = self.to_greeklish(xfilename)
131
- return xfilename
132
- end
120
+ def self.rationalize_filename(filename)
121
+ return nil unless filename
122
+ # gmosx: rationalize a copy!!! (add unit test)
123
+ xfilename = filename.dup()
124
+ # gmosx: replace some dangerous chars!
125
+ xfilename.gsub!(/ /, "-")
126
+ xfilename.gsub!(/!/, "")
127
+ xfilename.gsub!(/'/, "")
128
+ xfilename.gsub!(/\(/, "")
129
+ xfilename.gsub!(/\)/, "")
130
+ # xfilename = self.to_greeklish(xfilename)
131
+ return xfilename
132
+ end
133
133
  =end
134
-
135
- # Returns a random string. one possible use is
136
- # password initialization.
137
- #
138
- # === Input:
139
- # the maximum length of the string
140
- #
141
- # === Output:
142
- # the random string
143
-
144
- def self.random(max_length = 8, char_re = /[\w\d]/)
134
+
135
+ # Returns a random string. one possible use is
136
+ # password initialization.
137
+ #
138
+ # === Input:
139
+ # the maximum length of the string
140
+ #
141
+ # === Output:
142
+ # the random string
143
+
144
+ def self.random(max_length = 8, char_re = /[\w\d]/)
145
145
  # gmosx: this is a nice example of input parameter checking.
146
- # this is NOT a real time called method so we can add this
147
- # check. Congrats to the author.
148
- raise ArgumentError.new('char_re must be a regular expression!') unless char_re.is_a?(Regexp)
149
-
150
- string = ""
151
-
152
- while string.length < max_length
153
- ch = rand(255).chr
154
- string << ch if ch =~ char_re
155
- end
156
-
157
- return string
158
- end
146
+ # this is NOT a real time called method so we can add this
147
+ # check. Congrats to the author.
148
+ raise ArgumentError.new('char_re must be a regular expression!') unless char_re.is_a?(Regexp)
149
+
150
+ string = ""
151
+
152
+ while string.length < max_length
153
+ ch = rand(255).chr
154
+ string << ch if ch =~ char_re
155
+ end
156
+
157
+ return string
158
+ end
159
159
 
160
160
  end
161
161