glue 0.20.0 → 0.21.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|