cgi 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of cgi might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +7 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +97 -0
- data/Rakefile +13 -0
- data/bin/console +7 -0
- data/bin/setup +6 -0
- data/cgi.gemspec +25 -0
- data/ext/cgi/escape/depend +17 -0
- data/ext/cgi/escape/escape.c +409 -0
- data/ext/cgi/escape/extconf.rb +3 -0
- data/lib/cgi.rb +296 -0
- data/lib/cgi/cookie.rb +188 -0
- data/lib/cgi/core.rb +888 -0
- data/lib/cgi/html.rb +1035 -0
- data/lib/cgi/session.rb +534 -0
- data/lib/cgi/session/pstore.rb +101 -0
- data/lib/cgi/util.rb +223 -0
- data/lib/cgi/version.rb +3 -0
- metadata +65 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# cgi/session/pstore.rb - persistent storage of marshalled session data
|
4
|
+
#
|
5
|
+
# Documentation: William Webber (william@williamwebber.com)
|
6
|
+
#
|
7
|
+
# == Overview
|
8
|
+
#
|
9
|
+
# This file provides the CGI::Session::PStore class, which builds
|
10
|
+
# persistent of session data on top of the pstore library. See
|
11
|
+
# cgi/session.rb for more details on session storage managers.
|
12
|
+
|
13
|
+
require_relative '../session'
|
14
|
+
require 'pstore'
|
15
|
+
|
16
|
+
class CGI
|
17
|
+
class Session
|
18
|
+
# PStore-based session storage class.
|
19
|
+
#
|
20
|
+
# This builds upon the top-level PStore class provided by the
|
21
|
+
# library file pstore.rb. Session data is marshalled and stored
|
22
|
+
# in a file. File locking and transaction services are provided.
|
23
|
+
class PStore
|
24
|
+
# Create a new CGI::Session::PStore instance
|
25
|
+
#
|
26
|
+
# This constructor is used internally by CGI::Session. The
|
27
|
+
# user does not generally need to call it directly.
|
28
|
+
#
|
29
|
+
# +session+ is the session for which this instance is being
|
30
|
+
# created. The session id must only contain alphanumeric
|
31
|
+
# characters; automatically generated session ids observe
|
32
|
+
# this requirement.
|
33
|
+
#
|
34
|
+
# +option+ is a hash of options for the initializer. The
|
35
|
+
# following options are recognised:
|
36
|
+
#
|
37
|
+
# tmpdir:: the directory to use for storing the PStore
|
38
|
+
# file. Defaults to Dir::tmpdir (generally "/tmp"
|
39
|
+
# on Unix systems).
|
40
|
+
# prefix:: the prefix to add to the session id when generating
|
41
|
+
# the filename for this session's PStore file.
|
42
|
+
# Defaults to the empty string.
|
43
|
+
#
|
44
|
+
# This session's PStore file will be created if it does
|
45
|
+
# not exist, or opened if it does.
|
46
|
+
def initialize(session, option={})
|
47
|
+
dir = option['tmpdir'] || Dir::tmpdir
|
48
|
+
prefix = option['prefix'] || ''
|
49
|
+
id = session.session_id
|
50
|
+
require 'digest/md5'
|
51
|
+
md5 = Digest::MD5.hexdigest(id)[0,16]
|
52
|
+
path = dir+"/"+prefix+md5
|
53
|
+
path.untaint
|
54
|
+
if File::exist?(path)
|
55
|
+
@hash = nil
|
56
|
+
else
|
57
|
+
unless session.new_session
|
58
|
+
raise CGI::Session::NoSession, "uninitialized session"
|
59
|
+
end
|
60
|
+
@hash = {}
|
61
|
+
end
|
62
|
+
@p = ::PStore.new(path)
|
63
|
+
@p.transaction do |p|
|
64
|
+
File.chmod(0600, p.path)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Restore session state from the session's PStore file.
|
69
|
+
#
|
70
|
+
# Returns the session state as a hash.
|
71
|
+
def restore
|
72
|
+
unless @hash
|
73
|
+
@p.transaction do
|
74
|
+
@hash = @p['hash'] || {}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
@hash
|
78
|
+
end
|
79
|
+
|
80
|
+
# Save session state to the session's PStore file.
|
81
|
+
def update
|
82
|
+
@p.transaction do
|
83
|
+
@p['hash'] = @hash
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Update and close the session's PStore file.
|
88
|
+
def close
|
89
|
+
update
|
90
|
+
end
|
91
|
+
|
92
|
+
# Close and delete the session's PStore file.
|
93
|
+
def delete
|
94
|
+
path = @p.path
|
95
|
+
File::unlink path
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
# :enddoc:
|
data/lib/cgi/util.rb
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
class CGI
|
3
|
+
module Util; end
|
4
|
+
include Util
|
5
|
+
extend Util
|
6
|
+
end
|
7
|
+
module CGI::Util
|
8
|
+
@@accept_charset="UTF-8" unless defined?(@@accept_charset)
|
9
|
+
# URL-encode a string.
|
10
|
+
# url_encoded_string = CGI::escape("'Stop!' said Fred")
|
11
|
+
# # => "%27Stop%21%27+said+Fred"
|
12
|
+
def escape(string)
|
13
|
+
encoding = string.encoding
|
14
|
+
string.b.gsub(/([^ a-zA-Z0-9_.\-~]+)/) do |m|
|
15
|
+
'%' + m.unpack('H2' * m.bytesize).join('%').upcase
|
16
|
+
end.tr(' ', '+').force_encoding(encoding)
|
17
|
+
end
|
18
|
+
|
19
|
+
# URL-decode a string with encoding(optional).
|
20
|
+
# string = CGI::unescape("%27Stop%21%27+said+Fred")
|
21
|
+
# # => "'Stop!' said Fred"
|
22
|
+
def unescape(string,encoding=@@accept_charset)
|
23
|
+
str=string.tr('+', ' ').b.gsub(/((?:%[0-9a-fA-F]{2})+)/) do |m|
|
24
|
+
[m.delete('%')].pack('H*')
|
25
|
+
end.force_encoding(encoding)
|
26
|
+
str.valid_encoding? ? str : str.force_encoding(string.encoding)
|
27
|
+
end
|
28
|
+
|
29
|
+
# The set of special characters and their escaped values
|
30
|
+
TABLE_FOR_ESCAPE_HTML__ = {
|
31
|
+
"'" => ''',
|
32
|
+
'&' => '&',
|
33
|
+
'"' => '"',
|
34
|
+
'<' => '<',
|
35
|
+
'>' => '>',
|
36
|
+
}
|
37
|
+
|
38
|
+
# Escape special characters in HTML, namely '&\"<>
|
39
|
+
# CGI::escapeHTML('Usage: foo "bar" <baz>')
|
40
|
+
# # => "Usage: foo "bar" <baz>"
|
41
|
+
def escapeHTML(string)
|
42
|
+
enc = string.encoding
|
43
|
+
unless enc.ascii_compatible?
|
44
|
+
if enc.dummy?
|
45
|
+
origenc = enc
|
46
|
+
enc = Encoding::Converter.asciicompat_encoding(enc)
|
47
|
+
string = enc ? string.encode(enc) : string.b
|
48
|
+
end
|
49
|
+
table = Hash[TABLE_FOR_ESCAPE_HTML__.map {|pair|pair.map {|s|s.encode(enc)}}]
|
50
|
+
string = string.gsub(/#{"['&\"<>]".encode(enc)}/, table)
|
51
|
+
string.encode!(origenc) if origenc
|
52
|
+
return string
|
53
|
+
end
|
54
|
+
string.gsub(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__)
|
55
|
+
end
|
56
|
+
|
57
|
+
begin
|
58
|
+
require 'cgi/escape'
|
59
|
+
rescue LoadError
|
60
|
+
end
|
61
|
+
|
62
|
+
# Unescape a string that has been HTML-escaped
|
63
|
+
# CGI::unescapeHTML("Usage: foo "bar" <baz>")
|
64
|
+
# # => "Usage: foo \"bar\" <baz>"
|
65
|
+
def unescapeHTML(string)
|
66
|
+
enc = string.encoding
|
67
|
+
unless enc.ascii_compatible?
|
68
|
+
if enc.dummy?
|
69
|
+
origenc = enc
|
70
|
+
enc = Encoding::Converter.asciicompat_encoding(enc)
|
71
|
+
string = enc ? string.encode(enc) : string.b
|
72
|
+
end
|
73
|
+
string = string.gsub(Regexp.new('&(apos|amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do
|
74
|
+
case $1.encode(Encoding::US_ASCII)
|
75
|
+
when 'apos' then "'".encode(enc)
|
76
|
+
when 'amp' then '&'.encode(enc)
|
77
|
+
when 'quot' then '"'.encode(enc)
|
78
|
+
when 'gt' then '>'.encode(enc)
|
79
|
+
when 'lt' then '<'.encode(enc)
|
80
|
+
when /\A#0*(\d+)\z/ then $1.to_i.chr(enc)
|
81
|
+
when /\A#x([0-9a-f]+)\z/i then $1.hex.chr(enc)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
string.encode!(origenc) if origenc
|
85
|
+
return string
|
86
|
+
end
|
87
|
+
return string unless string.include? '&'
|
88
|
+
charlimit = case enc
|
89
|
+
when Encoding::UTF_8; 0x10ffff
|
90
|
+
when Encoding::ISO_8859_1; 256
|
91
|
+
else 128
|
92
|
+
end
|
93
|
+
string.gsub(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do
|
94
|
+
match = $1.dup
|
95
|
+
case match
|
96
|
+
when 'apos' then "'"
|
97
|
+
when 'amp' then '&'
|
98
|
+
when 'quot' then '"'
|
99
|
+
when 'gt' then '>'
|
100
|
+
when 'lt' then '<'
|
101
|
+
when /\A#0*(\d+)\z/
|
102
|
+
n = $1.to_i
|
103
|
+
if n < charlimit
|
104
|
+
n.chr(enc)
|
105
|
+
else
|
106
|
+
"&##{$1};"
|
107
|
+
end
|
108
|
+
when /\A#x([0-9a-f]+)\z/i
|
109
|
+
n = $1.hex
|
110
|
+
if n < charlimit
|
111
|
+
n.chr(enc)
|
112
|
+
else
|
113
|
+
"&#x#{$1};"
|
114
|
+
end
|
115
|
+
else
|
116
|
+
"&#{match};"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Synonym for CGI::escapeHTML(str)
|
122
|
+
alias escape_html escapeHTML
|
123
|
+
|
124
|
+
# Synonym for CGI::unescapeHTML(str)
|
125
|
+
alias unescape_html unescapeHTML
|
126
|
+
|
127
|
+
# Escape only the tags of certain HTML elements in +string+.
|
128
|
+
#
|
129
|
+
# Takes an element or elements or array of elements. Each element
|
130
|
+
# is specified by the name of the element, without angle brackets.
|
131
|
+
# This matches both the start and the end tag of that element.
|
132
|
+
# The attribute list of the open tag will also be escaped (for
|
133
|
+
# instance, the double-quotes surrounding attribute values).
|
134
|
+
#
|
135
|
+
# print CGI::escapeElement('<BR><A HREF="url"></A>', "A", "IMG")
|
136
|
+
# # "<BR><A HREF="url"></A>"
|
137
|
+
#
|
138
|
+
# print CGI::escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"])
|
139
|
+
# # "<BR><A HREF="url"></A>"
|
140
|
+
def escapeElement(string, *elements)
|
141
|
+
elements = elements[0] if elements[0].kind_of?(Array)
|
142
|
+
unless elements.empty?
|
143
|
+
string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do
|
144
|
+
CGI::escapeHTML($&)
|
145
|
+
end
|
146
|
+
else
|
147
|
+
string
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Undo escaping such as that done by CGI::escapeElement()
|
152
|
+
#
|
153
|
+
# print CGI::unescapeElement(
|
154
|
+
# CGI::escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG")
|
155
|
+
# # "<BR><A HREF="url"></A>"
|
156
|
+
#
|
157
|
+
# print CGI::unescapeElement(
|
158
|
+
# CGI::escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])
|
159
|
+
# # "<BR><A HREF="url"></A>"
|
160
|
+
def unescapeElement(string, *elements)
|
161
|
+
elements = elements[0] if elements[0].kind_of?(Array)
|
162
|
+
unless elements.empty?
|
163
|
+
string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do
|
164
|
+
unescapeHTML($&)
|
165
|
+
end
|
166
|
+
else
|
167
|
+
string
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# Synonym for CGI::escapeElement(str)
|
172
|
+
alias escape_element escapeElement
|
173
|
+
|
174
|
+
# Synonym for CGI::unescapeElement(str)
|
175
|
+
alias unescape_element unescapeElement
|
176
|
+
|
177
|
+
# Abbreviated day-of-week names specified by RFC 822
|
178
|
+
RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
|
179
|
+
|
180
|
+
# Abbreviated month names specified by RFC 822
|
181
|
+
RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
|
182
|
+
|
183
|
+
# Format a +Time+ object as a String using the format specified by RFC 1123.
|
184
|
+
#
|
185
|
+
# CGI::rfc1123_date(Time.now)
|
186
|
+
# # Sat, 01 Jan 2000 00:00:00 GMT
|
187
|
+
def rfc1123_date(time)
|
188
|
+
t = time.clone.gmtime
|
189
|
+
return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
|
190
|
+
RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year,
|
191
|
+
t.hour, t.min, t.sec)
|
192
|
+
end
|
193
|
+
|
194
|
+
# Prettify (indent) an HTML string.
|
195
|
+
#
|
196
|
+
# +string+ is the HTML string to indent. +shift+ is the indentation
|
197
|
+
# unit to use; it defaults to two spaces.
|
198
|
+
#
|
199
|
+
# print CGI::pretty("<HTML><BODY></BODY></HTML>")
|
200
|
+
# # <HTML>
|
201
|
+
# # <BODY>
|
202
|
+
# # </BODY>
|
203
|
+
# # </HTML>
|
204
|
+
#
|
205
|
+
# print CGI::pretty("<HTML><BODY></BODY></HTML>", "\t")
|
206
|
+
# # <HTML>
|
207
|
+
# # <BODY>
|
208
|
+
# # </BODY>
|
209
|
+
# # </HTML>
|
210
|
+
#
|
211
|
+
def pretty(string, shift = " ")
|
212
|
+
lines = string.gsub(/(?!\A)<.*?>/m, "\n\\0").gsub(/<.*?>(?!\n)/m, "\\0\n")
|
213
|
+
end_pos = 0
|
214
|
+
while end_pos = lines.index(/^<\/(\w+)/, end_pos)
|
215
|
+
element = $1.dup
|
216
|
+
start_pos = lines.rindex(/^\s*<#{element}/i, end_pos)
|
217
|
+
lines[start_pos ... end_pos] = "__" + lines[start_pos ... end_pos].gsub(/\n(?!\z)/, "\n" + shift) + "__"
|
218
|
+
end
|
219
|
+
lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/, '\1')
|
220
|
+
end
|
221
|
+
|
222
|
+
alias h escapeHTML
|
223
|
+
end
|
data/lib/cgi/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cgi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Hiroshi SHIBATA
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-11-06 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Support for the Common Gateway Interface protocol.
|
14
|
+
email:
|
15
|
+
- hsbt@ruby-lang.org
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".gitignore"
|
21
|
+
- ".travis.yml"
|
22
|
+
- Gemfile
|
23
|
+
- LICENSE.txt
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
26
|
+
- bin/console
|
27
|
+
- bin/setup
|
28
|
+
- cgi.gemspec
|
29
|
+
- ext/cgi/escape/depend
|
30
|
+
- ext/cgi/escape/escape.c
|
31
|
+
- ext/cgi/escape/extconf.rb
|
32
|
+
- lib/cgi.rb
|
33
|
+
- lib/cgi/cookie.rb
|
34
|
+
- lib/cgi/core.rb
|
35
|
+
- lib/cgi/html.rb
|
36
|
+
- lib/cgi/session.rb
|
37
|
+
- lib/cgi/session/pstore.rb
|
38
|
+
- lib/cgi/util.rb
|
39
|
+
- lib/cgi/version.rb
|
40
|
+
homepage: https://github.com/ruby/cgi
|
41
|
+
licenses:
|
42
|
+
- BSD-2-Clause
|
43
|
+
metadata:
|
44
|
+
homepage_uri: https://github.com/ruby/cgi
|
45
|
+
source_code_uri: https://github.com/ruby/cgi
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubygems_version: 3.0.3
|
62
|
+
signing_key:
|
63
|
+
specification_version: 4
|
64
|
+
summary: Support for the Common Gateway Interface protocol.
|
65
|
+
test_files: []
|