-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.rb
181 lines (170 loc) · 5.62 KB
/
util.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
class CGI
# URL-encode a string.
# url_encoded_string = CGI::escape("'Stop!' said Fred")
# # => "%27Stop%21%27+said+Fred"
def CGI::escape(string)
string.gsub(/([^ a-zA-Z0-9_.-]+)/) do
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
end.tr(' ', '+')
end
# URL-decode a string.
# string = CGI::unescape("%27Stop%21%27+said+Fred")
# # => "'Stop!' said Fred"
def CGI::unescape(string)
enc = string.encoding
string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/) do
[$1.delete('%')].pack('H*').force_encoding(enc)
end
end
TABLE_FOR_ESCAPE_HTML__ = {
'&' => '&',
'"' => '"',
'<' => '<',
'>' => '>',
}
# Escape special characters in HTML, namely &\"<>
# CGI::escapeHTML('Usage: foo "bar" <baz>')
# # => "Usage: foo "bar" <baz>"
def CGI::escapeHTML(string)
string.gsub(/[&\"<>]/, TABLE_FOR_ESCAPE_HTML__)
end
# Unescape a string that has been HTML-escaped
# CGI::unescapeHTML("Usage: foo "bar" <baz>")
# # => "Usage: foo \"bar\" <baz>"
def CGI::unescapeHTML(string)
enc = string.encoding
if [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE].include?(enc)
return string.gsub(Regexp.new('&(amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do
case $1.encode("US-ASCII")
when 'amp' then '&'.encode(enc)
when 'quot' then '"'.encode(enc)
when 'gt' then '>'.encode(enc)
when 'lt' then '<'.encode(enc)
when /\A#0*(\d+)\z/ then $1.to_i.chr(enc)
when /\A#x([0-9a-f]+)\z/i then $1.hex.chr(enc)
end
end
end
asciicompat = Encoding.compatible?(string, "a")
string.gsub(/&(amp|quot|gt|lt|\#[0-9]+|\#x[0-9A-Fa-f]+);/) do
match = $1.dup
case match
when 'amp' then '&'
when 'quot' then '"'
when 'gt' then '>'
when 'lt' then '<'
when /\A#0*(\d+)\z/
n = $1.to_i
if enc == Encoding::UTF_8 or
enc == Encoding::ISO_8859_1 && n < 256 or
asciicompat && n < 128
n.chr(enc)
else
"&##{$1};"
end
when /\A#x([0-9a-f]+)\z/i
n = $1.hex
if enc == Encoding::UTF_8 or
enc == Encoding::ISO_8859_1 && n < 256 or
asciicompat && n < 128
n.chr(enc)
else
"&#x#{$1};"
end
else
"&#{match};"
end
end
end
def CGI::escape_html(str)
escapeHTML(str)
end
def CGI::unescape_html(str)
unescapeHTML(str)
end
# Escape only the tags of certain HTML elements in +string+.
#
# Takes an element or elements or array of elements. Each element
# is specified by the name of the element, without angle brackets.
# This matches both the start and the end tag of that element.
# The attribute list of the open tag will also be escaped (for
# instance, the double-quotes surrounding attribute values).
#
# print CGI::escapeElement('<BR><A HREF="url"></A>', "A", "IMG")
# # "<BR><A HREF="url"></A>"
#
# print CGI::escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"])
# # "<BR><A HREF="url"></A>"
def CGI::escapeElement(string, *elements)
elements = elements[0] if elements[0].kind_of?(Array)
unless elements.empty?
string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do
CGI::escapeHTML($&)
end
else
string
end
end
# Undo escaping such as that done by CGI::escapeElement()
#
# print CGI::unescapeElement(
# CGI::escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG")
# # "<BR><A HREF="url"></A>"
#
# print CGI::unescapeElement(
# CGI::escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])
# # "<BR><A HREF="url"></A>"
def CGI::unescapeElement(string, *elements)
elements = elements[0] if elements[0].kind_of?(Array)
unless elements.empty?
string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do
CGI::unescapeHTML($&)
end
else
string
end
end
def CGI::escape_element(str)
escapeElement(str)
end
def CGI::unescape_element(str)
unescapeElement(str)
end
# Format a +Time+ object as a String using the format specified by RFC 1123.
#
# CGI::rfc1123_date(Time.now)
# # Sat, 01 Jan 2000 00:00:00 GMT
def CGI::rfc1123_date(time)
t = time.clone.gmtime
return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year,
t.hour, t.min, t.sec)
end
# Prettify (indent) an HTML string.
#
# +string+ is the HTML string to indent. +shift+ is the indentation
# unit to use; it defaults to two spaces.
#
# print CGI::pretty("<HTML><BODY></BODY></HTML>")
# # <HTML>
# # <BODY>
# # </BODY>
# # </HTML>
#
# print CGI::pretty("<HTML><BODY></BODY></HTML>", "\t")
# # <HTML>
# # <BODY>
# # </BODY>
# # </HTML>
#
def CGI::pretty(string, shift = " ")
lines = string.gsub(/(?!\A)<(?:.|\n)*?>/, "\n\\0").gsub(/<(?:.|\n)*?>(?!\n)/, "\\0\n")
end_pos = 0
while end_pos = lines.index(/^<\/(\w+)/, end_pos)
element = $1.dup
start_pos = lines.rindex(/^\s*<#{element}/i, end_pos)
lines[start_pos ... end_pos] = "__" + lines[start_pos ... end_pos].gsub(/\n(?!\z)/, "\n" + shift) + "__"
end
lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/, '\1')
end
end