Module: CGI::Util

Included in:
CGI
Defined in:
lib/cgi/util.rb,
lib/cgi/util.rb

Constant Summary collapse

TABLE_FOR_ESCAPE_HTML__ =

The set of special characters and their escaped values

{
  "'" => ''',
  '&' => '&',
  '"' => '"',
  '<' => '&lt;',
  '>' => '&gt;',
}
RFC822_DAYS =

Abbreviated day-of-week names specified by RFC 822

%w[ Sun Mon Tue Wed Thu Fri Sat ]
RFC822_MONTHS =

Abbreviated month names specified by RFC 822

%w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
@@accept_charset =
"UTF-8"

Instance Method Summary collapse

Instance Method Details

#escape(string) ⇒ Object

URL-encode a string.

url_encoded_string = CGI::escape("'Stop!' said Fred")
   # => "%27Stop%21%27+said+Fred"


7
8
9
10
11
12
# File 'lib/cgi/util.rb', line 7

def escape(string)
  encoding = string.encoding
  string.b.gsub(/([^ a-zA-Z0-9_.-]+)/) do |m|
    '%' + m.unpack('H2' * m.bytesize).join('%').upcase
  end.tr(' ', '+').force_encoding(encoding)
end

#escape_element(str) ⇒ Object

Synonym for CGI::escapeElement(str)



147
148
149
# File 'lib/cgi/util.rb', line 147

def escape_element(str)
  escapeElement(str)
end

#escape_html(str) ⇒ Object

Synonym for CGI::escapeHTML(str)



93
94
95
# File 'lib/cgi/util.rb', line 93

def escape_html(str)
  escapeHTML(str)
end

#escapeElement(string, *elements) ⇒ Object

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>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"

print CGI::escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"])
  # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"


115
116
117
118
119
120
121
122
123
124
# File 'lib/cgi/util.rb', line 115

def 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

#escapeHTML(string) ⇒ Object Also known as: h

Escape special characters in HTML, namely &"<>

CGI::escapeHTML('Usage: foo "bar" <baz>')
   # => "Usage: foo &quot;bar&quot; &lt;baz&gt;"


36
37
38
# File 'lib/cgi/util.rb', line 36

def escapeHTML(string)
  string.gsub(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__)
end

#pretty(string, shift = " ") ⇒ Object

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>


190
191
192
193
194
195
196
197
198
199
# File 'lib/cgi/util.rb', line 190

def pretty(string, shift = "  ")
  lines = string.gsub(/(?!\A)<.*?>/m, "\n\\0").gsub(/<.*?>(?!\n)/m, "\\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

#rfc1123_date(time) ⇒ Object

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


166
167
168
169
170
171
# File 'lib/cgi/util.rb', line 166

def 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

#unescape(string, encoding = @@accept_charset) ⇒ Object

URL-decode a string with encoding(optional).

string = CGI::unescape("%27Stop%21%27+said+Fred")
   # => "'Stop!' said Fred"


17
18
19
20
21
22
# File 'lib/cgi/util.rb', line 17

def unescape(string,encoding=@@accept_charset)
  str=string.tr('+', ' ').b.gsub(/((?:%[0-9a-fA-F]{2})+)/) do |m|
    [m.delete('%')].pack('H*')
  end.force_encoding(encoding)
  str.valid_encoding? ? str : str.force_encoding(string.encoding)
end

#unescape_element(str) ⇒ Object

Synonym for CGI::unescapeElement(str)



152
153
154
# File 'lib/cgi/util.rb', line 152

def unescape_element(str)
  unescapeElement(str)
end

#unescape_html(str) ⇒ Object

Synonym for CGI::unescapeHTML(str)



98
99
100
# File 'lib/cgi/util.rb', line 98

def unescape_html(str)
  unescapeHTML(str)
end

#unescapeElement(string, *elements) ⇒ Object

Undo escaping such as that done by CGI::escapeElement()

print CGI::unescapeElement(
        CGI::escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG")
  # "&lt;BR&gt;<A HREF="url"></A>"

print CGI::unescapeElement(
        CGI::escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])
  # "&lt;BR&gt;<A HREF="url"></A>"


135
136
137
138
139
140
141
142
143
144
# File 'lib/cgi/util.rb', line 135

def unescapeElement(string, *elements)
  elements = elements[0] if elements[0].kind_of?(Array)
  unless elements.empty?
    string.gsub(/&lt;\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?&gt;/i) do
      unescapeHTML($&)
    end
  else
    string
  end
end

#unescapeHTML(string) ⇒ Object

Unescape a string that has been HTML-escaped

CGI::unescapeHTML("Usage: foo &quot;bar&quot; &lt;baz&gt;")
   # => "Usage: foo \"bar\" <baz>"


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
# File 'lib/cgi/util.rb', line 43

def unescapeHTML(string)
  return string unless string.include? '&'
  enc = string.encoding
  if enc != Encoding::UTF_8 && [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE].include?(enc)
    return string.gsub(Regexp.new('&(apos|amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do
      case $1.encode(Encoding::US_ASCII)
      when 'apos'                then "'".encode(enc)
      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(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do
    match = $1.dup
    case match
    when 'apos'                then "'"
    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