cgi 0.5.0 → 0.5.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4807bd75c56012fd4b219cd83c6b0fb76006483f176b9a7b19b2658606b11503
4
- data.tar.gz: b49eebc85d48ac1f068dda9fd36570dbb83d2ee787d6d458680996d29554d8ce
3
+ metadata.gz: 9c5aa5b0794db539b4fa7b8a3da82182b587829ac7de10a444ef52447eef3811
4
+ data.tar.gz: 9a90fdb11ac132bd2c5693fa34c9ffdd5f492e66961561ef51bfab109e1deff0
5
5
  SHA512:
6
- metadata.gz: c85c60cdefbe541dd68ebc7c82be5a62635bb3861e7a717d828cff5e2072c583bdb0722d85eb36d18a6f1a28255cad60f8d2879d302c10c94f4c7e2c3100103f
7
- data.tar.gz: c7a7fccaf06fed4326df4fb5dc1bcab429e4c1430bffb010f5a3c46a4c1b53c102c32b7142b6bdda1a090d6c152da34cdc76e4f5a1d67e1bd37a6df6fc7b5f8e
6
+ metadata.gz: aaa90e2e539670dd03dfea7dcc26cb6382eef97fd783bcbc99f509018492386e7160a3944f52eb6fae589bfec628c5d935d5226412243d3267d7781945dd6f70
7
+ data.tar.gz: e9b846ecf59d6834dc02e7f1e1f5eb47ca845f2f85451a85c54c088aa547d01daf3a65651d61d769a86e30da2a242ea826bb231e83cf2421c811b4de67d07144
data/README.md CHANGED
@@ -22,11 +22,15 @@ gem 'cgi'
22
22
 
23
23
  And then execute:
24
24
 
25
- $ bundle
25
+ ```bash
26
+ bundle
27
+ ```
26
28
 
27
29
  Or install it yourself as:
28
30
 
29
- $ gem install cgi
31
+ ```bash
32
+ gem install cgi
33
+ ```
30
34
 
31
35
  ## Usage
32
36
 
@@ -73,7 +77,6 @@ db.transaction do
73
77
  end
74
78
  ```
75
79
 
76
-
77
80
  ### Restore form values from file
78
81
 
79
82
  ```ruby
@@ -45,6 +45,7 @@ escaped_length(VALUE str)
45
45
  static VALUE
46
46
  optimized_escape_html(VALUE str)
47
47
  {
48
+ VALUE escaped;
48
49
  VALUE vbuf;
49
50
  char *buf = ALLOCV_N(char, vbuf, escaped_length(str));
50
51
  const char *cstr = RSTRING_PTR(str);
@@ -63,7 +64,6 @@ optimized_escape_html(VALUE str)
63
64
  }
64
65
  }
65
66
 
66
- VALUE escaped;
67
67
  if (RSTRING_LEN(str) < (dest - buf)) {
68
68
  escaped = rb_str_new(buf, dest - buf);
69
69
  preserve_original_state(str, escaped);
data/lib/cgi/cookie.rb CHANGED
@@ -40,9 +40,11 @@ class CGI
40
40
  class Cookie < Array
41
41
  @@accept_charset="UTF-8" unless defined?(@@accept_charset)
42
42
 
43
+ # :stopdoc:
43
44
  TOKEN_RE = %r"\A[[!-~]&&[^()<>@,;:\\\"/?=\[\]{}]]+\z"
44
45
  PATH_VALUE_RE = %r"\A[[ -~]&&[^;]]*\z"
45
46
  DOMAIN_VALUE_RE = %r"\A\.?(?<label>(?!-)[-A-Za-z0-9]+(?<!-))(?:\.\g<label>)*\z"
47
+ # :startdoc:
46
48
 
47
49
  # Create a new CGI::Cookie object.
48
50
  #
data/lib/cgi/core.rb CHANGED
@@ -72,91 +72,267 @@ class CGI
72
72
 
73
73
  private :env_table, :stdinput, :stdoutput
74
74
 
75
- # Create an HTTP header block as a string.
76
- #
77
75
  # :call-seq:
78
- # http_header(content_type_string="text/html")
79
- # http_header(headers_hash)
76
+ # http_header(content_type = 'text/html') -> string
77
+ # http_header(headers) -> string
80
78
  #
81
- # Includes the empty line that ends the header block.
79
+ # Creates and returns an HTTP header section as a multi-line string.
82
80
  #
83
- # +content_type_string+::
84
- # If this form is used, this string is the <tt>Content-Type</tt>
85
- # +headers_hash+::
86
- # A Hash of header values. The following header keys are recognized:
87
- #
88
- # type:: The Content-Type header. Defaults to "text/html"
89
- # charset:: The charset of the body, appended to the Content-Type header.
90
- # nph:: A boolean value. If true, prepend protocol string and status
91
- # code, and date; and sets default values for "server" and
92
- # "connection" if not explicitly set.
93
- # status::
94
- # The HTTP status code as a String, returned as the Status header. The
95
- # values are:
96
- #
97
- # OK:: 200 OK
98
- # PARTIAL_CONTENT:: 206 Partial Content
99
- # MULTIPLE_CHOICES:: 300 Multiple Choices
100
- # MOVED:: 301 Moved Permanently
101
- # REDIRECT:: 302 Found
102
- # NOT_MODIFIED:: 304 Not Modified
103
- # BAD_REQUEST:: 400 Bad Request
104
- # AUTH_REQUIRED:: 401 Authorization Required
105
- # FORBIDDEN:: 403 Forbidden
106
- # NOT_FOUND:: 404 Not Found
107
- # METHOD_NOT_ALLOWED:: 405 Method Not Allowed
108
- # NOT_ACCEPTABLE:: 406 Not Acceptable
109
- # LENGTH_REQUIRED:: 411 Length Required
110
- # PRECONDITION_FAILED:: 412 Precondition Failed
111
- # SERVER_ERROR:: 500 Internal Server Error
112
- # NOT_IMPLEMENTED:: 501 Method Not Implemented
113
- # BAD_GATEWAY:: 502 Bad Gateway
114
- # VARIANT_ALSO_VARIES:: 506 Variant Also Negotiates
115
- #
116
- # server:: The server software, returned as the Server header.
117
- # connection:: The connection type, returned as the Connection header (for
118
- # instance, "close".
119
- # length:: The length of the content that will be sent, returned as the
120
- # Content-Length header.
121
- # language:: The language of the content, returned as the Content-Language
122
- # header.
123
- # expires:: The time on which the current content expires, as a +Time+
124
- # object, returned as the Expires header.
125
- # cookie::
126
- # A cookie or cookies, returned as one or more Set-Cookie headers. The
127
- # value can be the literal string of the cookie; a CGI::Cookie object;
128
- # an Array of literal cookie strings or Cookie objects; or a hash all of
129
- # whose values are literal cookie strings or Cookie objects.
130
- #
131
- # These cookies are in addition to the cookies held in the
132
- # @output_cookies field.
133
- #
134
- # Other headers can also be set; they are appended as key: value.
135
- #
136
- # Examples:
137
- #
138
- # http_header
139
- # # Content-Type: text/html
81
+ # The string always includes:
140
82
  #
141
- # http_header("text/plain")
142
- # # Content-Type: text/plain
83
+ # - Header +Content-Type+ (with a default value if none given).
84
+ # - A trailing newline, which delimits the header block;
85
+ # that last line is omitted from the examples below.
86
+ #
87
+ # <b>In Brief</b>
88
+ #
89
+ # headers = {
90
+ # 'charset' => 'iso-2022-jp',
91
+ # 'connection' => 'keep-alive',
92
+ # 'cookie' => 'foo=0',
93
+ # 'expires' => Time.now + (60 * 60 * 24 * 365),
94
+ # 'language' => 'en-US, en-CA',
95
+ # 'length' => 4096,
96
+ # 'nph' => true,
97
+ # 'server' => 'Apache/2.4.1 (Unix)',
98
+ # 'status' => 'OK',
99
+ # 'type' => 'text/xml',
100
+ # MyHeader: true
101
+ # }
102
+ #
103
+ # puts cgi.http_header(headers)
104
+ # HTTP/1.0 200 OK
105
+ # Date: Mon, 01 Dec 2025 22:08:22 GMT
106
+ # Server: Apache/2.4.1 (Unix)
107
+ # Connection: keep-alive
108
+ # Content-Type: text/xml; charset=iso-2022-jp
109
+ # Content-Length: 4096
110
+ # Content-Language: en-US, en-CA
111
+ # Expires: Tue, 01 Dec 2026 22:05:30 GMT
112
+ # Set-Cookie: foo=0
113
+ # MyHeader: true
114
+ #
115
+ # headers.delete('nph')
116
+ #
117
+ # puts cgi.http_header(headers)
118
+ # Status: 200 OK
119
+ # Server: Apache/2.4.1 (Unix)
120
+ # Connection: keep-alive
121
+ # Content-Type: text/xml; charset=iso-2022-jp
122
+ # Content-Length: 4096
123
+ # Content-Language: en-US, en-CA
124
+ # Expires: Tue, 01 Dec 2026 22:05:30 GMT
125
+ # Set-Cookie: foo=0
126
+ # MyHeader: true
127
+ #
128
+ # <b>Arguments</b>
129
+ #
130
+ # With no argument given,
131
+ # includes only header +Content-Type+ with its default value <tt>'text/html'</tt>:
132
+ #
133
+ # puts cgi.http_header
134
+ # Content-Type: text/html
135
+ #
136
+ # With string argument +content_type+ given,
137
+ # includes header +Content-Type+ with the given value:
138
+ #
139
+ # puts cgi.http_header('text/xml')
140
+ # Content-Type: text/xml
141
+ #
142
+ # With hash argument +headers+ given,
143
+ # includes a header for hash entry, whose name is based on the entry's key,
144
+ # and whose value is the entry's value.
145
+ #
146
+ # <i>Recognized Keys</i>
147
+ #
148
+ # The following keys are recognized;
149
+ # each is a lowercase string:
150
+ #
151
+ # <tt>'charset'</tt>::
152
+ # The character set of the body; appended to the +Content-Type+ header:
153
+ #
154
+ # puts cgi.http_header('charset' => 'iso-2022-jp')
155
+ # Content-Type: text/html; charset=iso-2022-jp
156
+ #
157
+ # <tt>'connection'</tt>::
158
+ # Sets header +Connection+ to the given string:
159
+ #
160
+ # puts cgi.http_header('connection' => 'keep-alive')
161
+ # Connection: keep-alive
162
+ # Content-Type: text/html
163
+ #
164
+ # <tt>'cookie'</tt>::
165
+ # Sets one or more +Set-Cookie+ headers to the given value, which may be:
166
+ #
167
+ # - String cookie.
168
+ # - CGI::Cookie object.
169
+ # - Array of string cookies and CGI::Cookie objects.
170
+ # - A hash whose values are string cookies and CGI::Cookie objects
171
+ # (the keys are not used).
172
+ #
173
+ # Examples:
174
+ #
175
+ # foo_string = 'foo=0'
176
+ # bar_string = 'bar=1'
177
+ # foo_cookie = CGI::Cookie.new('foo', '0')
178
+ # bar_cookie = CGI::Cookie.new('bar', '1')
179
+ #
180
+ # puts cgi.http_header('cookie' => foo_string)
181
+ # Content-Type: text/html
182
+ # Set-Cookie: foo=0
183
+ #
184
+ # puts cgi.http_header('cookie' => foo_cookie)
185
+ # Content-Type: text/html
186
+ # Set-Cookie: foo=0; path=
187
+ #
188
+ # puts cgi.http_header('cookie' => [foo_cookie, bar_string])
189
+ # Content-Type: text/html
190
+ # Set-Cookie: foo=0; path=
191
+ # Set-Cookie: bar=1
143
192
  #
144
- # http_header("nph" => true,
145
- # "status" => "OK", # == "200 OK"
146
- # # "status" => "200 GOOD",
147
- # "server" => ENV['SERVER_SOFTWARE'],
148
- # "connection" => "close",
149
- # "type" => "text/html",
150
- # "charset" => "iso-2022-jp",
151
- # # Content-Type: text/html; charset=iso-2022-jp
152
- # "length" => 103,
153
- # "language" => "ja",
154
- # "expires" => Time.now + 30,
155
- # "cookie" => [cookie1, cookie2],
156
- # "my_header1" => "my_value",
157
- # "my_header2" => "my_value")
193
+ # puts cgi.http_header('cookie' => {foo: foo_cookie, bar: bar_string})
194
+ # Content-Type: text/html
195
+ # Set-Cookie: foo=0; path=
196
+ # Set-Cookie: bar=1
197
+ #
198
+ # These cookies are in addition to the cookies held
199
+ # in the <tt>@output_cookies</tt> variable.
200
+ #
201
+ # <tt>'expires'</tt>::
202
+ # Sets header +Expires+ to the given time,
203
+ # which must be a {Time}[https://docs.ruby-lang.org/en/master/Time.html] object:
204
+ #
205
+ # puts cgi.http_header('expires' => Time.now + (60 * 60 * 24 * 365))
206
+ # Content-Type: text/html
207
+ # Expires: Tue, 01 Dec 2026 23:42:37 GMT
208
+ #
209
+ # <tt>'language'</tt>::
210
+ # Sets header +Content-Language+ to the given string:
211
+ #
212
+ # puts cgi.http_header('language' => 'en-US, en-CA')
213
+ # Content-Type: text/html
214
+ # Content-Language: en-US, en-CA
215
+ #
216
+ # <tt>'length'</tt>::
217
+ # Sets header +Content-Length+ to the given value,
218
+ # which may be an integer or a string:
219
+ #
220
+ # puts cgi.http_header('length' => 4096)
221
+ # Content-Type: text/html
222
+ # Content-Length: 4096
223
+ #
224
+ # puts cgi.http_header('length' => '4096')
225
+ # Content-Type: text/html
226
+ # Content-Length: 4096
227
+ #
228
+ # <tt>'nph'</tt>::
229
+ # If +true+:
230
+ #
231
+ # - Adds protocol string and status code as first line.
232
+ # - Adds date as second line.
233
+ # - Adds headers +Server+ with no value,
234
+ # and +Connection+ with default value <tt>'close'</tt>;
235
+ # either or both values may be overridden with explicit values.
236
+ #
237
+ # Examples:
238
+ #
239
+ # puts cgi.http_header('nph' => true)
240
+ # HTTP/1.0 200 OK
241
+ # Date: Mon, 01 Dec 2025 19:42:22 GMT
242
+ # Server:
243
+ # Connection: close
244
+ # Content-Type: text/html
245
+ #
246
+ # puts cgi.http_header('nph' => true, 'server' => 'Apache/2.4.1 (Unix)', 'connection' => 'keep-alive')
247
+ # HTTP/1.0 200 OK
248
+ # Date: Mon, 01 Dec 2025 20:00:41 GMT
249
+ # Server: Apache/2.4.1 (Unix)
250
+ # Connection: keep-alive
251
+ # Content-Type: text/html
252
+ #
253
+ # <tt>'server'</tt>::
254
+ # Sets header +Server+ to the given string:
255
+ #
256
+ # puts cgi.http_header('server' => 'Apache/2.4.1 (Unix)')
257
+ # Server: Apache/2.4.1 (Unix)
258
+ # Content-Type: text/html
259
+ #
260
+ # <tt>'status'</tt>::
261
+ # Sets header +Status+ to the given string:
262
+ #
263
+ # puts cgi.http_header('status' => '666 MyVeryOwnStatus')
264
+ # Status: 666 MyVeryOwnStatus
265
+ # Content-Type: text/html
266
+ #
267
+ # If the given string is a key in the hash constant +CGI::HTTP_STATUS+,
268
+ # the status becomes the value for that key:
269
+ #
270
+ # CGI::HTTP_STATUS
271
+ # # =>
272
+ # {"OK" => "200 OK",
273
+ # "PARTIAL_CONTENT" => "206 Partial Content",
274
+ # "MULTIPLE_CHOICES" => "300 Multiple Choices",
275
+ # "MOVED" => "301 Moved Permanently",
276
+ # "REDIRECT" => "302 Found",
277
+ # "NOT_MODIFIED" => "304 Not Modified",
278
+ # "BAD_REQUEST" => "400 Bad Request",
279
+ # "AUTH_REQUIRED" => "401 Authorization Required",
280
+ # "FORBIDDEN" => "403 Forbidden",
281
+ # "NOT_FOUND" => "404 Not Found",
282
+ # "METHOD_NOT_ALLOWED" => "405 Method Not Allowed",
283
+ # "NOT_ACCEPTABLE" => "406 Not Acceptable",
284
+ # "LENGTH_REQUIRED" => "411 Length Required",
285
+ # "PRECONDITION_FAILED" => "412 Precondition Failed",
286
+ # "SERVER_ERROR" => "500 Internal Server Error",
287
+ # "NOT_IMPLEMENTED" => "501 Method Not Implemented",
288
+ # "BAD_GATEWAY" => "502 Bad Gateway",
289
+ # "VARIANT_ALSO_VARIES" => "506 Variant Also Negotiates"}
290
+ #
291
+ # puts cgi.http_header('status' => 'OK')
292
+ # Status: 200 OK
293
+ # Content-Type: text/html
294
+ #
295
+ # puts cgi.http_header('status' => 'NOT_FOUND')
296
+ # Status: 404 Not Found
297
+ # Content-Type: text/html
298
+ #
299
+ # <tt>'type'</tt>::
300
+ # Sets +Content-Type+, overriding the default value <tt>'text/html'</tt>:
301
+ #
302
+ # puts cgi.http_header('type' => 'text/xml')
303
+ # Content-Type: text/xml
304
+ #
305
+ # <i>Unrecognized Keys</i>
306
+ #
307
+ # Headers may also be set for unrecognized keys;
308
+ # an unrecognized key becomes a header name with the given value:
309
+ #
310
+ # puts cgi.http_header('length' => 0) # Recognized key (lowercase string).
311
+ # Content-Type: text/html
312
+ # Content-Length: 0
313
+ #
314
+ # puts cgi.http_header('Length' => 0) # Unrecognized key (string key not lowercase).
315
+ # Content-Type: text/html
316
+ # Length: 0
317
+ #
318
+ # puts cgi.http_header(length: 0) # Unrecognized key (symbol key not string)
319
+ # Content-Type: text/html
320
+ # length: 0
158
321
  #
159
322
  # This method does not perform charset conversion.
323
+ #
324
+ # It's best to use this method (CGI#http_header), not its aliased method +header+,
325
+ # which is provided only for backward compatibility.
326
+ #
327
+ # Method CGI#http_header is preferred because when +tag_maker+ is <tt>'html5'</tt>,
328
+ # calling method +header+ generates an HTML +header+ element:
329
+ #
330
+ # cgi = CGI.new(tag_maker: 'html5')
331
+ # puts cgi.http_header # Works as expected.
332
+ # Content-Type: text/html
333
+ # puts cgi.header # Maybe a surprise.
334
+ # <HEADER></HEADER>
335
+ #
160
336
  def http_header(options='text/html')
161
337
  if options.is_a?(String)
162
338
  content_type = options
@@ -384,11 +560,14 @@ class CGI
384
560
  stdoutput.print(*options)
385
561
  end
386
562
 
387
- # Parse an HTTP query string into a hash of key=>value pairs.
563
+ # :call-seq:
564
+ # CGI.parse(query_string) -> hash
388
565
  #
389
- # params = CGI.parse("query_string")
390
- # # {"name1" => ["value1", "value2", ...],
391
- # # "name2" => ["value1", "value2", ...], ... }
566
+ # Returns a new hash built from name/value pairs in the given +query_string+:
567
+ #
568
+ # query = 'foo=0&bar=1&foo=2&bar=3'
569
+ # CGI.parse(query)
570
+ # # => {"foo" => ["0", "2"], "bar" => ["1", "3"]}
392
571
  #
393
572
  def self.parse(query)
394
573
  params = {}
@@ -478,7 +657,7 @@ class CGI
478
657
 
479
658
  ##
480
659
  # Parses multipart form elements according to
481
- # http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2
660
+ # https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2
482
661
  #
483
662
  # Returns a hash of multipart form parameters with bodies of type StringIO or
484
663
  # Tempfile depending on whether the multipart form element exceeds 10 KB
@@ -629,8 +808,8 @@ class CGI
629
808
  string = unless ARGV.empty?
630
809
  ARGV.join(' ')
631
810
  else
632
- if STDIN.tty?
633
- STDERR.print(
811
+ if stdinput.tty?
812
+ $stderr.print(
634
813
  %|(offline mode: enter name=value pairs on standard input)\n|
635
814
  )
636
815
  end
@@ -659,13 +838,16 @@ class CGI
659
838
  # Handles multipart forms (in particular, forms that involve file uploads).
660
839
  # Reads query parameters in the @params field, and cookies into @cookies.
661
840
  def initialize_query()
841
+ content_length = env_table['CONTENT_LENGTH']
842
+ content_length = nil if content_length == ''
662
843
  if ("POST" == env_table['REQUEST_METHOD']) and
663
844
  %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?| =~ env_table['CONTENT_TYPE']
664
845
  current_max_multipart_length = @max_multipart_length.respond_to?(:call) ? @max_multipart_length.call : @max_multipart_length
665
846
  raise StandardError.new("too large multipart data.") if env_table['CONTENT_LENGTH'].to_i > current_max_multipart_length
847
+ raise StandardError.new("no content length for multipart data.") if content_length.nil?
666
848
  boundary = $1.dup
667
849
  @multipart = true
668
- @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
850
+ @params = read_multipart(boundary, Integer(content_length))
669
851
  else
670
852
  @multipart = false
671
853
  @params = CGI.parse(
@@ -678,7 +860,11 @@ class CGI
678
860
  end
679
861
  when "POST"
680
862
  stdinput.binmode if defined? stdinput.binmode
681
- stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or ''
863
+ if content_length.nil?
864
+ stdinput.read or ''
865
+ else
866
+ stdinput.read(Integer(content_length)) or ''
867
+ end
682
868
  else
683
869
  read_from_cmdline
684
870
  end.dup.force_encoding(@accept_charset)
@@ -755,12 +941,75 @@ class CGI
755
941
  #
756
942
  @@accept_charset="UTF-8" if false # needed for rdoc?
757
943
 
758
- # Return the accept character set for all new CGI instances.
944
+ # :call-seq:
945
+ # CGI.accept_charset -> encoding
946
+ #
947
+ # Returns the default accept character set to be used for new \CGI instances;
948
+ # see CGI.accept_charset=.
759
949
  def self.accept_charset
760
950
  @@accept_charset
761
951
  end
762
952
 
763
- # Set the accept character set for all new CGI instances.
953
+ # :call-seq:
954
+ # CGI.accept_charset = encoding
955
+ #
956
+ # Sets the default accept character set to be used for new \CGI instances;
957
+ # returns the argument.
958
+ #
959
+ # The argument may be an Encoding object or an Encoding name;
960
+ # see {Encodings}[https://docs.ruby-lang.org/en/master/language/encodings_rdoc.html]:
961
+ #
962
+ # # The initial value.
963
+ # CGI.accept_charset # => #<Encoding:UTF-8>
964
+ # CGI.new
965
+ # # =>
966
+ # #<CGI:0x0000018991db6ae8
967
+ # @accept_charset=#<Encoding:UTF-8>,
968
+ # @accept_charset_error_block=nil,
969
+ # @cookies={},
970
+ # @max_multipart_length=134217728,
971
+ # @multipart=false,
972
+ # @options={accept_charset: #<Encoding:UTF-8>, max_multipart_length: 134217728},
973
+ # @output_cookies=nil,
974
+ # @output_hidden=nil,
975
+ # @params={}>
976
+ #
977
+ # # Set by Encoding name.
978
+ # CGI.accept_charset = 'US-ASCII' # => "US-ASCII"
979
+ # CGI.new
980
+ # # =>
981
+ # #<CGI:0x0000018991cf4100
982
+ # @accept_charset="US-ASCII",
983
+ # @accept_charset_error_block=nil,
984
+ # @cookies={},
985
+ # @max_multipart_length=134217728,
986
+ # @multipart=false,
987
+ # @options={accept_charset: "US-ASCII", max_multipart_length: 134217728},
988
+ # @output_cookies=nil,
989
+ # @output_hidden=nil,
990
+ # @params={}>
991
+ #
992
+ # # Set by Encoding object.
993
+ # CGI.accept_charset = Encoding::ASCII_8BIT # => #<Encoding:BINARY (ASCII-8BIT)>
994
+ # CGI.new
995
+ # # =>
996
+ # #<CGI:0x0000018991cfc800
997
+ # @accept_charset=#<Encoding:BINARY (ASCII-8BIT)>,
998
+ # @accept_charset_error_block=nil,
999
+ # @cookies={},
1000
+ # @max_multipart_length=134217728,
1001
+ # @multipart=false,
1002
+ # @options={accept_charset: #<Encoding:BINARY (ASCII-8BIT)>, max_multipart_length: 134217728},
1003
+ # @output_cookies=nil,
1004
+ # @output_hidden=nil,
1005
+ # @params={}>
1006
+ #
1007
+ # The given encoding is not checked in this method,
1008
+ # but if it is invalid, a call to CGI.new will fail:
1009
+ #
1010
+ # CGI.accept_charset = 'foo'
1011
+ # CGI.new # Raises ArgumentError: unknown encoding name - foo
1012
+ #
764
1013
  def self.accept_charset=(accept_charset)
765
1014
  @@accept_charset=accept_charset
766
1015
  end
@@ -778,75 +1027,199 @@ class CGI
778
1027
  #
779
1028
  @@max_multipart_length= 128 * 1024 * 1024
780
1029
 
781
- # Create a new CGI instance.
782
- #
783
1030
  # :call-seq:
784
- # CGI.new(tag_maker) { block }
785
- # CGI.new(options_hash = {}) { block }
1031
+ # CGI.new(options = {}) -> new_cgi
1032
+ # CGI.new(tag_maker) -> new_cgi
1033
+ # CGI.new(options = {}) {|name, value| ... } -> new_cgi
1034
+ # CGI.new(tag_maker) {|name, value| ... } -> new_cgi
1035
+ #
1036
+ # Returns a new \CGI object.
1037
+ #
1038
+ # The behavior of this method depends _strongly_ on whether it is called
1039
+ # within a standard \CGI call environment;
1040
+ # that is, whether <tt>ENV['REQUEST_METHOD']</tt> is defined.
1041
+ #
1042
+ # <b>Within a Standard Call Environment</b>
1043
+ #
1044
+ # This section assumes that <tt>ENV['REQUEST_METHOD']</tt> is defined;
1045
+ # for example:
1046
+ #
1047
+ # ENV['REQUEST_METHOD'] # => "GET"
1048
+ #
1049
+ # With no argument and no block given, returns a new \CGI object with default values:
1050
+ #
1051
+ # cgi = CGI.new
1052
+ # cgi
1053
+ # # =>
1054
+ # #<CGI:0x00000189917aff00
1055
+ # @accept_charset=#<Encoding:UTF-8>,
1056
+ # @accept_charset_error_block=nil,
1057
+ # @cookies={},
1058
+ # @max_multipart_length=134217728,
1059
+ # @multipart=false,
1060
+ # @options={accept_charset: #<Encoding:UTF-8>, max_multipart_length: 134217728},
1061
+ # @output_cookies=nil,
1062
+ # @output_hidden=nil,
1063
+ # @params={}>
1064
+ #
1065
+ # With hash argument +options+ given and no block given,
1066
+ # returns a new \CGI object with the given options.
1067
+ #
1068
+ # The options may be:
786
1069
  #
1070
+ # - <tt>accept_charset: _encoding_</tt>:
1071
+ # specifies the encoding of the received query string.
787
1072
  #
788
- # <tt>tag_maker</tt>::
789
- # This is the same as using the +options_hash+ form with the value <tt>{
790
- # :tag_maker => tag_maker }</tt> Note that it is recommended to use the
791
- # +options_hash+ form, since it also allows you specify the charset you
792
- # will accept.
793
- # <tt>options_hash</tt>::
794
- # A Hash that recognizes three options:
1073
+ # Value _encoding_ may be
1074
+ # an {Encoding object}[https://docs.ruby-lang.org/en/master/encodings_rdoc.html#label-Encoding+Objects]
1075
+ # or an {encoding name}[https://docs.ruby-lang.org/en/master/encodings_rdoc.html#label-Names+and+Aliases]:
795
1076
  #
796
- # <tt>:accept_charset</tt>::
797
- # specifies encoding of received query string. If omitted,
798
- # <tt>@@accept_charset</tt> is used. If the encoding is not valid, a
799
- # CGI::InvalidEncoding will be raised.
1077
+ # CGI.new(accept_charset: 'EUC-JP')
800
1078
  #
801
- # Example. Suppose <tt>@@accept_charset</tt> is "UTF-8"
1079
+ # If the option is not given,
1080
+ # the default value is the class default encoding.
802
1081
  #
803
- # when not specified:
1082
+ # <em>Note:</em> The <tt>accept_charset</tt> method returns the HTTP Accept-Charset
1083
+ # header value, not the configured encoding. The configured encoding is used
1084
+ # internally for query string parsing.
804
1085
  #
805
- # cgi=CGI.new # @accept_charset # => "UTF-8"
1086
+ # - <tt>max_multipart_length: _size_</tt>:
1087
+ # specifies maximum size (in bytes) of multipart data.
806
1088
  #
807
- # when specified as "EUC-JP":
1089
+ # The _size_ may be:
808
1090
  #
809
- # cgi=CGI.new(:accept_charset => "EUC-JP") # => "EUC-JP"
1091
+ # - A positive integer.
1092
+ #
1093
+ # CGI.new(max_multipart_length: 1024 * 1024)
1094
+ #
1095
+ #
1096
+ # - A lambda to be evaluated when the request is parsed.
1097
+ # This is useful when determining whether to accept multipart data
1098
+ # (e.g. by consulting a registered user's upload allowance).
1099
+ #
1100
+ # CGI.new(max_multipart_length: -> {check_filesystem})
1101
+ #
1102
+ # If the option is not given, the default is +134217728+, specifying a maximum size of 128 megabytes.
1103
+ #
1104
+ # <em>Note:</em> This option configures internal behavior only.
1105
+ # There is no public method to retrieve this value after initialization.
1106
+ #
1107
+ # - <tt>tag_maker: _html_version_</tt>:
1108
+ # specifies a version of HTML;
1109
+ # this determines which tag-generating instance methods
1110
+ # (such as +html+, +head+, +body+, etc.) are to be loaded.
1111
+ #
1112
+ # Value _html_version_ may be one of:
1113
+ #
1114
+ # - <tt>'html3'</tt>: {HTML version 3}[https://www.w3.org/MarkUp/html3/Contents.html].
1115
+ # - <tt>'html4'</tt>: {HTML version 4}[https://www.w3.org/TR/html4].
1116
+ # - <tt>'html4Tr'</tt>: {HTML 4.0 Transitional}[https://www.w3.org/TR/html4/sgml/loosedtd.html].
1117
+ # - <tt>'html4Fr'</tt>: {HTML 4.0 with Framesets}[https://www.w3.org/TR/html4/present/frames.html].
1118
+ # - <tt>'html5'</tt>: {HTML version 5}[https://html.spec.whatwg.org/multipage].
1119
+ #
1120
+ # Example:
1121
+ #
1122
+ # CGI.new(tag_maker: 'html5')
1123
+ #
1124
+ # If the option is not given (or if an invalid value is given),
1125
+ # no tag-generating methods are loaded.
1126
+ #
1127
+ # Examples:
1128
+ #
1129
+ # CGI.new.respond_to?(:html) # => false # Tag-generating methods not loaded.
1130
+ # CGI.new(tag_maker: 'html3').respond_to?(:html) # => true # Tag-generating methods loaded.
1131
+ # # Tag 'button' is new in HTML 4.
1132
+ # CGI.new(tag_maker: 'html3').respond_to?(:button) # => false
1133
+ # CGI.new(tag_maker: 'html4').respond_to?(:button) # => true
1134
+ # # Tag 'canvas' is new in HTML 5.
1135
+ # CGI.new(tag_maker: 'html4').respond_to?(:canvas) # => false
1136
+ # CGI.new(tag_maker: 'html5').respond_to?(:canvas) # => true
1137
+ # # Value is case-sensitive.
1138
+ # CGI.new(tag_maker: 'HTML4').respond_to?(:html) # => false
1139
+ #
1140
+ # You can determine exactly which methods have been loaded;
1141
+ # this example captures the methods loaded by <tt>'html4'</tt>:
1142
+ #
1143
+ # methods_loaded = CGI.new('html4').methods - CGI.new.methods
1144
+ # methods_loaded.size # => 98
1145
+ # methods_loaded.sort.take(10)
1146
+ # # => [:a, :abbr, :acronym, :address, :area, :b, :base, :bdo, :big, :blockquote]
1147
+ #
1148
+ # With string argument +tag_maker+ given as _tag_maker_ and no block given,
1149
+ # equivalent to <tt>CGI.new(tag_maker: _tag_maker_)</tt>:
1150
+ #
1151
+ # CGI.new('html5')
1152
+ #
1153
+ # <b>Outside a Standard Call Environment</b>
1154
+ #
1155
+ # This section assumes that <tt>ENV['REQUEST_METHOD']</tt> is not defined;
1156
+ # for example:
1157
+ #
1158
+ # ENV['REQUEST_METHOD'] # => nil
1159
+ #
1160
+ # In this mode, the method reads its parameters
1161
+ # from the command line or (failing that) from standard input;
1162
+ # returns a new \CGI object.
1163
+ #
1164
+ # Parameters from command line:
1165
+ #
1166
+ # $ cat t.rb
1167
+ # require 'cgi'
1168
+ # cgi = CGI.new
1169
+ # p cgi.params
1170
+ # ruby t.rb foo=0 bar=1 foo=2 bar=3
1171
+ # {"foo" => ["0", "2"], "bar" => ["1", "3"]}
1172
+ #
1173
+ # Parameters from standard input:
1174
+ #
1175
+ # cgi = CGI.new
1176
+ # (offline mode: enter name=value pairs on standard input)
1177
+ # foo=0
1178
+ # bar=1
1179
+ # ^D
1180
+ # cgi.params
1181
+ # # => {"foo" => ["0"], "bar" => ["1"]}
810
1182
  #
811
- # <tt>:tag_maker</tt>::
812
- # String that specifies which version of the HTML generation methods to
813
- # use. If not specified, no HTML generation methods will be loaded.
1183
+ # The end-of-file character is Ctrl-D on a Unix-like system (as above),
1184
+ # or Ctrl-Z on Windows.
814
1185
  #
815
- # The following values are supported:
1186
+ # Otherwise, cookies and other parameters are parsed automatically from the standard CGI locations,
1187
+ # which vary according to the request method.
816
1188
  #
817
- # "html3":: HTML 3.x
818
- # "html4":: HTML 4.0
819
- # "html4Tr":: HTML 4.0 Transitional
820
- # "html4Fr":: HTML 4.0 with Framesets
821
- # "html5":: HTML 5
1189
+ # <b>Options vs Public Methods</b>
822
1190
  #
823
- # <tt>:max_multipart_length</tt>::
824
- # Specifies maximum length of multipart data. Can be an Integer scalar or
825
- # a lambda, that will be evaluated when the request is parsed. This
826
- # allows more complex logic to be set when determining whether to accept
827
- # multipart data (e.g. consult a registered users upload allowance)
1191
+ # Some initialization options configure internal behavior only and do not provide
1192
+ # corresponding public getter methods:
828
1193
  #
829
- # Default is 128 * 1024 * 1024 bytes
1194
+ # - <tt>accept_charset</tt>: Configures internal encoding for parsing.
1195
+ # The <tt>accept_charset</tt> method returns the HTTP Accept-Charset header.
1196
+ # - <tt>max_multipart_length</tt>: Configures internal multipart size limits.
1197
+ # No public getter method is available.
1198
+ # - <tt>tag_maker</tt>: Loads HTML generation methods (publicly accessible).
830
1199
  #
831
- # cgi=CGI.new(:max_multipart_length => 268435456) # simple scalar
1200
+ # <b>Block</b>
832
1201
  #
833
- # cgi=CGI.new(:max_multipart_length => -> {check_filesystem}) # lambda
1202
+ # If a block is given, its code is stored as a Proc;
1203
+ # whenever CGI::InvalidEncoding would be raised, the proc is called instead.
834
1204
  #
835
- # <tt>block</tt>::
836
- # If provided, the block is called when an invalid encoding is
837
- # encountered. For example:
1205
+ # In this example, the proc simply saves the error:
838
1206
  #
839
- # encoding_errors={}
840
- # cgi=CGI.new(:accept_charset=>"EUC-JP") do |name,value|
841
- # encoding_errors[name] = value
842
- # end
1207
+ # encoding_errors = {}
1208
+ # CGI.new(accept_charset: 'EUC-JP') do |name,value|
1209
+ # encoding_errors[name] = value
1210
+ # end
1211
+ # # =>
1212
+ # #<CGI:0x000002b0ec11bcd8
1213
+ # @accept_charset="EUC-JP",
1214
+ # @accept_charset_error_block=#<Proc:0x000002b0ed2ee190 (irb):146>,
1215
+ # @cookies={},
1216
+ # @max_multipart_length=134217728,
1217
+ # @multipart=false,
1218
+ # @options={accept_charset: "EUC-JP", max_multipart_length: 134217728},
1219
+ # @output_cookies=nil,
1220
+ # @output_hidden=nil,
1221
+ # @params={}>
843
1222
  #
844
- # Finally, if the CGI object is not created in a standard CGI call
845
- # environment (that is, it can't locate REQUEST_METHOD in its environment),
846
- # then it will run in "offline" mode. In this mode, it reads its parameters
847
- # from the command line or (failing that) from standard input. Otherwise,
848
- # cookies and other parameters are parsed automatically from the standard
849
- # CGI locations, which varies according to the REQUEST_METHOD.
850
1223
  def initialize(options = {}, &block) # :yields: name, value
851
1224
  @accept_charset_error_block = block_given? ? block : nil
852
1225
  @options={
data/lib/cgi/escape.rb CHANGED
@@ -1,11 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :stopdoc
3
4
  class CGI
4
5
  module Escape; end
5
6
  include Escape
6
7
  extend Escape
8
+ module EscapeExt; end # :nodoc:
7
9
  end
10
+ # :startdoc:
8
11
 
12
+ # Escape/unescape for CGI, HTML, URI.
9
13
  module CGI::Escape
10
14
  @@accept_charset = Encoding::UTF_8 unless defined?(@@accept_charset)
11
15
 
@@ -128,41 +132,32 @@ module CGI::Escape
128
132
  end
129
133
  string = string.b
130
134
  string.gsub!(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do
131
- match = $1.dup
135
+ match = $1
132
136
  case match
133
137
  when 'apos' then "'"
134
138
  when 'amp' then '&'
135
139
  when 'quot' then '"'
136
140
  when 'gt' then '>'
137
141
  when 'lt' then '<'
138
- when /\A#0*(\d+)\z/
139
- n = $1.to_i
140
- if n < charlimit
141
- n.chr(enc)
142
- else
143
- "&##{$1};"
144
- end
145
- when /\A#x([0-9a-f]+)\z/i
146
- n = $1.hex
147
- if n < charlimit
148
- n.chr(enc)
142
+ else
143
+ # Numeric character reference. Decode into the binary buffer so that a
144
+ # non-ASCII byte already present in it never triggers an encoding
145
+ # compatibility error on concatenation; the trailing force_encoding
146
+ # re-tags the whole buffer. This mirrors the C extension's
147
+ # optimized_unescape_html.
148
+ n = match.start_with?('#x', '#X') ? match[2..-1].hex : match[1..-1].to_i
149
+ if n >= charlimit
150
+ "&#{match};" # out of range: keep the reference verbatim
151
+ elsif charlimit > 256
152
+ [n].pack('U').b # UTF-8: code point bytes, surrogates included (like rb_enc_mbcput)
149
153
  else
150
- "&#x#{$1};"
154
+ n.chr.b # ISO-8859-1 / ASCII: single byte
151
155
  end
152
- else
153
- "&#{match};"
154
156
  end
155
157
  end
156
158
  string.force_encoding enc
157
159
  end
158
160
 
159
- # Synonym for CGI.escapeHTML(str)
160
- alias escape_html escapeHTML
161
- alias h escapeHTML
162
-
163
- # Synonym for CGI.unescapeHTML(str)
164
- alias unescape_html unescapeHTML
165
-
166
161
  # TruffleRuby runs the pure-Ruby variant faster, do not use the C extension there
167
162
  unless RUBY_ENGINE == 'truffleruby'
168
163
  begin
@@ -171,6 +166,14 @@ module CGI::Escape
171
166
  end
172
167
  end
173
168
 
169
+ # Aliases must be defined on EscapeExt so they resolve to the C methods.
170
+ target = defined?(CGI::EscapeExt) && CGI::EscapeExt.method_defined?(:escapeHTML) ? CGI::EscapeExt : self
171
+ target.module_eval do
172
+ alias escape_html escapeHTML
173
+ alias h escapeHTML
174
+ alias unescape_html unescapeHTML
175
+ end
176
+
174
177
  # Escape only the tags of certain HTML elements in +string+.
175
178
  #
176
179
  # Takes an element or elements or array of elements. Each element
data/lib/cgi/html.rb CHANGED
@@ -1006,27 +1006,32 @@ class CGI
1006
1006
 
1007
1007
  end # Html5
1008
1008
 
1009
+ # HTML version 3 generation class.
1009
1010
  class HTML3
1010
1011
  include Html3
1011
1012
  include HtmlExtension
1012
1013
  end
1013
1014
 
1015
+ # HTML version 4 generation class.
1014
1016
  class HTML4
1015
1017
  include Html4
1016
1018
  include HtmlExtension
1017
1019
  end
1018
1020
 
1021
+ # HTML version 4 transitional generation class.
1019
1022
  class HTML4Tr
1020
1023
  include Html4Tr
1021
1024
  include HtmlExtension
1022
1025
  end
1023
1026
 
1027
+ # HTML version 4 with framesets generation class.
1024
1028
  class HTML4Fr
1025
1029
  include Html4Tr
1026
1030
  include Html4Fr
1027
1031
  include HtmlExtension
1028
1032
  end
1029
1033
 
1034
+ # HTML version 5 generation class.
1030
1035
  class HTML5
1031
1036
  include Html5
1032
1037
  include HtmlExtension
data/lib/cgi/session.rb CHANGED
@@ -206,19 +206,28 @@ class CGI
206
206
  # on Unix systems).
207
207
  # prefix:: the prefix to add to the session id when generating
208
208
  # the filename for this session's FileStore file.
209
- # Defaults to "cgi_sid_".
209
+ # Defaults to the empty string.
210
210
  # suffix:: the prefix to add to the session id when generating
211
211
  # the filename for this session's FileStore file.
212
212
  # Defaults to the empty string.
213
+ # digest:: the digest algorithm to hash the session id when
214
+ # generating the filename for this session's FileStore
215
+ # file. Defaults to "SHA256".
216
+ # length:: the length of the session id part of the filestore,
217
+ # excluding +prefix+ and +suffix+ parts. Defaults to 16.
213
218
  def new_store_file(option={}) # :nodoc:
214
219
  dir = option['tmpdir'] || Dir::tmpdir
215
220
  prefix = option['prefix']
216
221
  suffix = option['suffix']
217
- require 'digest/md5'
218
- md5 = Digest::MD5.hexdigest(session_id)[0,16]
222
+ algorithm = option['digest'] || 'SHA256'
223
+ if String === algorithm
224
+ require 'digest'
225
+ algorithm = Digest(algorithm)
226
+ end
227
+ digest = algorithm.hexdigest(session_id)[0, option['length'] || 16]
219
228
  path = dir+"/"
220
229
  path << prefix if prefix
221
- path << md5
230
+ path << digest
222
231
  path << suffix if suffix
223
232
  if File::exist? path
224
233
  hash = nil
@@ -410,6 +419,9 @@ class CGI
410
419
  # suffix:: the prefix to add to the session id when generating
411
420
  # the filename for this session's FileStore file.
412
421
  # Defaults to the empty string.
422
+ # digest:: the digest algorithm to hash the session id when
423
+ # generating the filename for this session's FileStore
424
+ # file. Defaults to "MD5".
413
425
  #
414
426
  # This session's FileStore file will be created if it does
415
427
  # not exist, or opened if it does.
data/lib/cgi/util.rb CHANGED
@@ -5,6 +5,7 @@ class CGI
5
5
  extend Util
6
6
  end
7
7
 
8
+ # Utility methods for CGI.
8
9
  module CGI::Util
9
10
  # Format a +Time+ object as a String using the format specified by RFC 1123.
10
11
  #
data/lib/cgi.rb CHANGED
@@ -26,7 +26,7 @@
26
26
  # The file CGI::Session provides session management functionality; see that
27
27
  # class for more details.
28
28
  #
29
- # See http://www.w3.org/CGI/ for more information on the CGI protocol.
29
+ # See https://www.w3.org/CGI/ for more information on the CGI protocol.
30
30
  #
31
31
  # == Introduction
32
32
  #
@@ -42,6 +42,17 @@
42
42
  #
43
43
  # Read on for more details. Examples are provided at the bottom.
44
44
  #
45
+ # == About the Examples
46
+ #
47
+ # Examples on this page assume that \CGI has been required:
48
+ #
49
+ # require 'cgi'
50
+ #
51
+ # Unless otherwise stated, examples also assume that environment variable 'REQUEST_METHOD' exists
52
+ # (which prevents CGI.new from entering its online mode):
53
+ #
54
+ # ENV.include?('REQUEST_METHOD') # => true
55
+ #
45
56
  # == Queries
46
57
  #
47
58
  # The CGI class dynamically mixes in parameter and cookie-parsing
@@ -148,59 +159,62 @@
148
159
  # Escape and unescape methods are defined in cgi/escape.rb.
149
160
  # And when include, you can use utility methods like a function.
150
161
  #
151
- # == Examples of use
162
+ # == Examples of Use
152
163
  #
153
- # === Get form values
164
+ # === Form Values
154
165
  #
155
- # require "cgi"
156
- # cgi = CGI.new
157
- # value = cgi['field_name'] # <== value string for 'field_name'
158
- # # if not 'field_name' included, then return "".
159
- # fields = cgi.keys # <== array of field names
160
- #
161
- # # returns true if form has 'field_name'
162
- # cgi.has_key?('field_name')
163
- # cgi.has_key?('field_name')
164
- # cgi.include?('field_name')
166
+ # ==== Get Form Values
165
167
  #
166
- # CAUTION! <code>cgi['field_name']</code> returned an Array with the old
167
- # cgi.rb(included in Ruby 1.6)
168
+ # You can use method +cgi.params+ to retrieve form values
169
+ # in a {Hash}[https://docs.ruby-lang.org/en/3.4/Hash.html]:
168
170
  #
169
- # === Get form values as hash
170
- #
171
- # require "cgi"
171
+ # ENV.update(
172
+ # 'REQUEST_METHOD' => 'GET',
173
+ # 'QUERY_STRING' => 'a=111&&b=222&c&d='
174
+ # )
172
175
  # cgi = CGI.new
173
- # params = cgi.params
174
- #
175
- # cgi.params is a hash.
176
- #
177
- # cgi.params['new_field_name'] = ["value"] # add new param
178
- # cgi.params['field_name'] = ["new_value"] # change value
179
- # cgi.params.delete('field_name') # delete param
180
- # cgi.params.clear # delete all params
181
- #
182
- #
183
- # === Save form values to file
184
- #
185
- # require "pstore"
186
- # db = PStore.new("query.db")
187
- # db.transaction do
188
- # db["params"] = cgi.params
176
+ # cgi.params.class # => Hash
177
+ # cgi.params # => {"a" => ["111"], "b" => ["222"], "c" => [], "d" => [""]}
178
+ # cgi.params.keys # => ["a", "b", "c", "d"]
179
+ # cgi.params['a'] # => ["111"] # Returns an array.
180
+ # cgi.params['d'] # => [""] # Returns empty string in array if no value.
181
+ # cgi.params['x'] # => [] # Returns empty array if no key.
182
+ #
183
+ # A \CGI instance has these convenience methods:
184
+ #
185
+ # # Convenience method for cgi.params.keys.
186
+ # cgi.keys # => ["a", "b", "c", "d"]
187
+ # # Convenience method for cgi.params[key].first.
188
+ # cgi['a'] # => "111" # Returns string, not array.
189
+ # cgi['d'] # => "" # Returns empty string if no value.
190
+ # cgi['x'] # => "" # Returns empty string if no key.
191
+ # # Convenience method for cgi.params.include?.
192
+ # cgi.include?('a') # => true
193
+ # cgi.include?('x') # => false
194
+ #
195
+ # ==== Save and Restore Form Values
196
+ #
197
+ # This example uses {Pstore}[https://docs.ruby-lang.org/en/3.4/PStore.html]
198
+ # to store and retrieve form values:
199
+ #
200
+ # ENV.update(
201
+ # 'REQUEST_METHOD' => 'GET',
202
+ # 'QUERY_STRING' => 'a=111&&b=222&c&d='
203
+ # )
204
+ # cgi = CGI.new
205
+ # require 'pstore'
206
+ # store = PStore.new('params.store')
207
+ # store.transaction do
208
+ # store['params'] = cgi.params
189
209
  # end
190
- #
191
- #
192
- # === Restore form values from file
193
- #
194
- # require "pstore"
195
- # db = PStore.new("query.db")
196
- # db.transaction do
197
- # cgi.params = db["params"]
210
+ # cgi.params.clear # Oops! Lost my params!
211
+ # store.transaction do
212
+ # cgi.params = store['params']
198
213
  # end
214
+ # cgi.params # => {"a" => ["111"], "b" => ["222"], "c" => [], "d" => [""]}
199
215
  #
216
+ # ==== Get multipart form values
200
217
  #
201
- # === Get multipart form values
202
- #
203
- # require "cgi"
204
218
  # cgi = CGI.new
205
219
  # value = cgi['field_name'] # <== value string for 'field_name'
206
220
  # value.read # <== body of value
@@ -212,7 +226,6 @@
212
226
  #
213
227
  # === Get cookie values
214
228
  #
215
- # require "cgi"
216
229
  # cgi = CGI.new
217
230
  # values = cgi.cookies['name'] # <== array of 'name'
218
231
  # # if not 'name' included, then return [].
@@ -222,7 +235,6 @@
222
235
  #
223
236
  # === Get cookie objects
224
237
  #
225
- # require "cgi"
226
238
  # cgi = CGI.new
227
239
  # for name, cookie in cgi.cookies
228
240
  # cookie.expires = Time.now + 30
@@ -231,14 +243,12 @@
231
243
  #
232
244
  # cgi.cookies # { "name1" => cookie1, "name2" => cookie2, ... }
233
245
  #
234
- # require "cgi"
235
246
  # cgi = CGI.new
236
247
  # cgi.cookies['name'].expires = Time.now + 30
237
248
  # cgi.out("cookie" => cgi.cookies['name']) {"string"}
238
249
  #
239
250
  # === Print http header and html string to $DEFAULT_OUTPUT ($>)
240
251
  #
241
- # require "cgi"
242
252
  # cgi = CGI.new("html4") # add HTML generation methods
243
253
  # cgi.out do
244
254
  # cgi.html do
@@ -289,7 +299,8 @@
289
299
  #
290
300
 
291
301
  class CGI
292
- VERSION = "0.5.0"
302
+ # The version string
303
+ VERSION = "0.5.2"
293
304
  end
294
305
 
295
306
  require 'cgi/util'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cgi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yukihiro Matsumoto
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-06-04 00:00:00.000000000 Z
10
+ date: 2026-06-23 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: Support for the Common Gateway Interface protocol.
13
13
  email:
@@ -38,6 +38,7 @@ licenses:
38
38
  metadata:
39
39
  homepage_uri: https://github.com/ruby/cgi
40
40
  source_code_uri: https://github.com/ruby/cgi
41
+ changelog_uri: https://github.com/ruby/cgi/releases
41
42
  rdoc_options: []
42
43
  require_paths:
43
44
  - lib