glue 0.20.0 → 0.21.0
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/CHANGELOG +161 -110
- data/INSTALL +12 -12
- data/README +1 -1
- data/Rakefile +43 -45
- data/doc/AUTHORS +5 -5
- data/doc/LICENSE +3 -3
- data/doc/RELEASES +32 -24
- data/install.rb +7 -17
- data/lib/facet/object/alias_class.rb +12 -0
- data/lib/glue.rb +35 -35
- data/lib/glue/array.rb +46 -46
- data/lib/glue/aspects.rb +199 -209
- data/lib/glue/attribute.rb +15 -15
- data/lib/glue/autoreload.rb +1 -1
- data/lib/glue/builder.rb +48 -0
- data/lib/glue/builder/xml.rb +114 -0
- data/lib/glue/cache.rb +189 -0
- data/lib/glue/configuration.rb +108 -90
- data/lib/glue/flexob.rb +17 -17
- data/lib/glue/hash.rb +71 -71
- data/lib/glue/helper.rb +12 -12
- data/lib/glue/idgen.rb +9 -0
- data/lib/glue/idgen/md5.rb +24 -0
- data/lib/glue/idgen/sequential.rb +15 -0
- data/lib/glue/literal_method.rb +44 -0
- data/lib/glue/localization.rb +130 -0
- data/lib/glue/logger.rb +98 -98
- data/lib/glue/misc.rb +7 -7
- data/lib/glue/mixins.rb +19 -19
- data/lib/glue/number.rb +8 -8
- data/lib/glue/object.rb +2 -2
- data/lib/glue/pool.rb +43 -43
- data/lib/glue/property.rb +392 -392
- data/lib/glue/sanitize.rb +34 -34
- data/lib/glue/settings.rb +1 -1
- data/lib/glue/snapshot.rb +104 -0
- data/lib/glue/string.rb +129 -129
- data/lib/glue/time.rb +53 -53
- data/lib/glue/uri.rb +162 -162
- data/lib/glue/validation.rb +421 -421
- data/lib/vendor/blankslate.rb +53 -0
- data/test/glue/builder/tc_xml.rb +56 -0
- data/test/glue/tc_aspects.rb +90 -90
- data/test/glue/tc_attribute.rb +11 -11
- data/test/glue/tc_builder.rb +30 -0
- data/test/glue/tc_configuration.rb +97 -97
- data/test/glue/tc_flexob.rb +10 -10
- data/test/glue/tc_hash.rb +23 -23
- data/test/glue/tc_localization.rb +49 -0
- data/test/glue/tc_logger.rb +31 -31
- data/test/glue/tc_numbers.rb +9 -9
- data/test/glue/tc_property.rb +67 -67
- data/test/glue/tc_property_mixins.rb +17 -17
- data/test/glue/tc_property_type_checking.rb +13 -13
- data/test/glue/tc_strings.rb +94 -94
- data/test/glue/tc_uri.rb +65 -65
- data/test/glue/tc_validation.rb +196 -196
- 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
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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(/</, "<")
|
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(/</, "<")
|
40
|
+
end
|
41
|
+
end
|
42
42
|
|
43
|
-
|
44
|
-
|
43
|
+
html = new_text
|
44
|
+
end
|
45
45
|
|
46
|
-
|
47
|
-
|
46
|
+
html
|
47
|
+
end
|
48
48
|
end
|
data/lib/glue/settings.rb
CHANGED
@@ -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
|
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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
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
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
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
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
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
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
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
|
|