Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package rubygem-cgi for openSUSE:Factory 
checked in at 2026-09-29 17:46:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-cgi (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-cgi.new.383539 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-cgi"

Tue Sep 29 17:46:04 2026 rev:2 rq:1380830 version:0.5.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-cgi/rubygem-cgi.changes  2026-01-05 
14:51:36.110385065 +0100
+++ /work/SRC/openSUSE:Factory/.rubygem-cgi.new.383539/rubygem-cgi.changes      
2026-09-29 17:46:24.385755733 +0200
@@ -1,0 +2,17 @@
+Sat Sep 26 16:25:38 UTC 2026 - Andrea Manzini <[email protected]>
+
+- Update to 0.5.2 (also covers skipped 0.5.1):
+  * Handle a POST request with a missing/empty Content-Length instead
+    of raising TypeError/ArgumentError (gh#ruby/cgi#56)
+  * Fix CGI.unescapeHTML raising Encoding::CompatibilityError in the
+    pure-Ruby fallback on mixed non-ASCII input (gh#ruby/cgi#103)
+  * Fix escape_html/h/unescape_html aliases to actually dispatch to
+    the C extension instead of the slower pure-Ruby implementation
+  * Harden CGI::Session's file-store filename hashing: use SHA-256
+    instead of MD5, and add a configurable :digest option (default
+    stays MD5 for backward compatibility)
+  * Various documentation improvements
+- Run spec-cleaner (tag order, License operator casing normalized to
+  the SPDX "AND")
+
+-------------------------------------------------------------------

Old:
----
  cgi-0.5.0.gem

New:
----
  cgi-0.5.2.gem

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rubygem-cgi.spec ++++++
--- /var/tmp/diff_new_pack.TJ0Z9d/_old  2026-09-29 17:46:30.076993820 +0200
+++ /var/tmp/diff_new_pack.TJ0Z9d/_new  2026-09-29 17:46:30.078993904 +0200
@@ -16,26 +16,25 @@
 #
 
 
+%define mod_name cgi
+%define mod_full_name %{mod_name}-%{version}
 #
 # This file was generated with a gem2rpm.yml and not just plain gem2rpm.
 # All sections marked as MANUAL, license headers, summaries and descriptions
 # can be maintained in that file. Please consult this file before editing any
 # of those fields
 #
-
 Name:           rubygem-cgi
-Version:        0.5.0
+Version:        0.5.2
 Release:        0
-%define mod_name cgi
-%define mod_full_name %{mod_name}-%{version}
-BuildRequires:  ruby-macros >= 5
-BuildRequires:  %{rubydevel >= 2.5.0}
-BuildRequires:  %{rubygem gem2rpm}
+Summary:        Support for the Common Gateway Interface protocol
+License:        Ruby AND BSD-2-Clause
 URL:            https://github.com/ruby/cgi
 Source:         https://rubygems.org/gems/%{mod_full_name}.gem
 Source1:        gem2rpm.yml
-Summary:        Support for the Common Gateway Interface protocol
-License:        Ruby and BSD-2-Clause
+BuildRequires:  %{rubydevel >= 2.5.0}
+BuildRequires:  %{rubygem gem2rpm}
+BuildRequires:  ruby-macros >= 5
 
 %description
 Support for the Common Gateway Interface protocol.
@@ -49,7 +48,7 @@
   --no-rdoc --no-ri \
   --doc-files="COPYING README.md" \
   -f
-%gem_cleanup
+%{gem_cleanup}
 
 %gem_packages
 

++++++ cgi-0.5.0.gem -> cgi-0.5.2.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/README.md new/README.md
--- old/README.md       2025-06-04 05:38:29.000000000 +0200
+++ new/README.md       2026-06-23 09:06:24.000000000 +0200
@@ -22,11 +22,15 @@
 
 And then execute:
 
-    $ bundle
+```bash
+bundle
+```
 
 Or install it yourself as:
 
-    $ gem install cgi
+```bash
+gem install cgi
+```
 
 ## Usage
 
@@ -73,7 +77,6 @@
 end
 ```
 
-
 ### Restore form values from file
 
 ```ruby
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ext/cgi/escape/escape.c new/ext/cgi/escape/escape.c
--- old/ext/cgi/escape/escape.c 2025-06-04 05:38:29.000000000 +0200
+++ new/ext/cgi/escape/escape.c 2026-06-23 09:06:24.000000000 +0200
@@ -45,6 +45,7 @@
 static VALUE
 optimized_escape_html(VALUE str)
 {
+    VALUE escaped;
     VALUE vbuf;
     char *buf = ALLOCV_N(char, vbuf, escaped_length(str));
     const char *cstr = RSTRING_PTR(str);
@@ -63,7 +64,6 @@
         }
     }
 
-    VALUE escaped;
     if (RSTRING_LEN(str) < (dest - buf)) {
         escaped = rb_str_new(buf, dest - buf);
         preserve_original_state(str, escaped);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/cgi/cookie.rb new/lib/cgi/cookie.rb
--- old/lib/cgi/cookie.rb       2025-06-04 05:38:29.000000000 +0200
+++ new/lib/cgi/cookie.rb       2026-06-23 09:06:24.000000000 +0200
@@ -40,9 +40,11 @@
   class Cookie < Array
     @@accept_charset="UTF-8" unless defined?(@@accept_charset)
 
+    # :stopdoc:
     TOKEN_RE = %r"\A[[!-~]&&[^()<>@,;:\\\"/?=\[\]{}]]+\z"
     PATH_VALUE_RE = %r"\A[[ -~]&&[^;]]*\z"
     DOMAIN_VALUE_RE = 
%r"\A\.?(?<label>(?!-)[-A-Za-z0-9]+(?<!-))(?:\.\g<label>)*\z"
+    # :startdoc:
 
     # Create a new CGI::Cookie object.
     #
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/cgi/core.rb new/lib/cgi/core.rb
--- old/lib/cgi/core.rb 2025-06-04 05:38:29.000000000 +0200
+++ new/lib/cgi/core.rb 2026-06-23 09:06:24.000000000 +0200
@@ -72,91 +72,267 @@
 
   private :env_table, :stdinput, :stdoutput
 
-  # Create an HTTP header block as a string.
-  #
   # :call-seq:
-  #   http_header(content_type_string="text/html")
-  #   http_header(headers_hash)
-  #
-  # Includes the empty line that ends the header block.
+  #    http_header(content_type = 'text/html') -> string
+  #    http_header(headers) -> string
   #
-  # +content_type_string+::
-  #   If this form is used, this string is the <tt>Content-Type</tt>
-  # +headers_hash+::
-  #   A Hash of header values. The following header keys are recognized:
+  # Creates and returns an HTTP header section as a multi-line string.
   #
-  #   type:: The Content-Type header.  Defaults to "text/html"
-  #   charset:: The charset of the body, appended to the Content-Type header.
-  #   nph:: A boolean value.  If true, prepend protocol string and status
-  #         code, and date; and sets default values for "server" and
-  #         "connection" if not explicitly set.
-  #   status::
-  #     The HTTP status code as a String, returned as the Status header.  The
-  #     values are:
-  #
-  #     OK:: 200 OK
-  #     PARTIAL_CONTENT:: 206 Partial Content
-  #     MULTIPLE_CHOICES:: 300 Multiple Choices
-  #     MOVED:: 301 Moved Permanently
-  #     REDIRECT:: 302 Found
-  #     NOT_MODIFIED:: 304 Not Modified
-  #     BAD_REQUEST:: 400 Bad Request
-  #     AUTH_REQUIRED:: 401 Authorization Required
-  #     FORBIDDEN:: 403 Forbidden
-  #     NOT_FOUND:: 404 Not Found
-  #     METHOD_NOT_ALLOWED:: 405 Method Not Allowed
-  #     NOT_ACCEPTABLE:: 406 Not Acceptable
-  #     LENGTH_REQUIRED:: 411 Length Required
-  #     PRECONDITION_FAILED:: 412 Precondition Failed
-  #     SERVER_ERROR:: 500 Internal Server Error
-  #     NOT_IMPLEMENTED:: 501 Method Not Implemented
-  #     BAD_GATEWAY:: 502 Bad Gateway
-  #     VARIANT_ALSO_VARIES:: 506 Variant Also Negotiates
-  #
-  #   server:: The server software, returned as the Server header.
-  #   connection:: The connection type, returned as the Connection header (for
-  #                instance, "close".
-  #   length:: The length of the content that will be sent, returned as the
-  #            Content-Length header.
-  #   language:: The language of the content, returned as the Content-Language
-  #              header.
-  #   expires:: The time on which the current content expires, as a +Time+
-  #             object, returned as the Expires header.
-  #   cookie::
-  #     A cookie or cookies, returned as one or more Set-Cookie headers.  The
-  #     value can be the literal string of the cookie; a CGI::Cookie object;
-  #     an Array of literal cookie strings or Cookie objects; or a hash all of
-  #     whose values are literal cookie strings or Cookie objects.
+  # The string always includes:
   #
-  #     These cookies are in addition to the cookies held in the
-  #     @output_cookies field.
+  # - Header +Content-Type+ (with a default value if none given).
+  # - A trailing newline, which delimits the header block;
+  #   that last line is omitted from the examples below.
+  #
+  # <b>In Brief</b>
+  #
+  #   headers = {
+  #     'charset' => 'iso-2022-jp',
+  #     'connection' => 'keep-alive',
+  #     'cookie' => 'foo=0',
+  #     'expires' => Time.now + (60 * 60 * 24 * 365),
+  #     'language' => 'en-US, en-CA',
+  #     'length' =>  4096,
+  #     'nph' => true,
+  #     'server' => 'Apache/2.4.1 (Unix)',
+  #     'status' => 'OK',
+  #     'type' => 'text/xml',
+  #     MyHeader: true
+  #   }
+  #
+  #   puts cgi.http_header(headers)
+  #   HTTP/1.0 200 OK
+  #   Date: Mon, 01 Dec 2025 22:08:22 GMT
+  #   Server: Apache/2.4.1 (Unix)
+  #   Connection: keep-alive
+  #   Content-Type: text/xml; charset=iso-2022-jp
+  #   Content-Length: 4096
+  #   Content-Language: en-US, en-CA
+  #   Expires: Tue, 01 Dec 2026 22:05:30 GMT
+  #   Set-Cookie: foo=0
+  #   MyHeader: true
+  #
+  #   headers.delete('nph')
+  #
+  #   puts cgi.http_header(headers)
+  #   Status: 200 OK
+  #   Server: Apache/2.4.1 (Unix)
+  #   Connection: keep-alive
+  #   Content-Type: text/xml; charset=iso-2022-jp
+  #   Content-Length: 4096
+  #   Content-Language: en-US, en-CA
+  #   Expires: Tue, 01 Dec 2026 22:05:30 GMT
+  #   Set-Cookie: foo=0
+  #   MyHeader: true
+  #
+  # <b>Arguments</b>
+  #
+  # With no argument given,
+  # includes only header +Content-Type+ with its default value 
<tt>'text/html'</tt>:
+  #
+  #   puts cgi.http_header
+  #   Content-Type: text/html
+  #
+  # With string argument +content_type+ given,
+  # includes header +Content-Type+ with the given value:
+  #
+  #   puts cgi.http_header('text/xml')
+  #   Content-Type: text/xml
+  #
+  # With hash argument +headers+ given,
+  # includes a header for hash entry, whose name is based on the entry's key,
+  # and whose value is the entry's value.
+  #
+  # <i>Recognized Keys</i>
+  #
+  # The following keys are recognized;
+  # each is a lowercase string:
+  #
+  # <tt>'charset'</tt>::
+  #   The character set of the body; appended to the +Content-Type+ header:
+  #
+  #     puts cgi.http_header('charset' => 'iso-2022-jp')
+  #     Content-Type: text/html; charset=iso-2022-jp
+  #
+  # <tt>'connection'</tt>::
+  #   Sets header +Connection+ to the given string:
+  #
+  #     puts cgi.http_header('connection' => 'keep-alive')
+  #     Connection: keep-alive
+  #     Content-Type: text/html
+  #
+  # <tt>'cookie'</tt>::
+  #   Sets one or more +Set-Cookie+ headers to the given value, which may be:
+  #
+  #   - String cookie.
+  #   - CGI::Cookie object.
+  #   - Array of string cookies and CGI::Cookie objects.
+  #   - A hash whose values are string cookies and CGI::Cookie objects
+  #     (the keys are not used).
+  #
+  #   Examples:
+  #
+  #     foo_string = 'foo=0'
+  #     bar_string = 'bar=1'
+  #     foo_cookie = CGI::Cookie.new('foo', '0')
+  #     bar_cookie = CGI::Cookie.new('bar', '1')
+  #
+  #     puts cgi.http_header('cookie' => foo_string)
+  #     Content-Type: text/html
+  #     Set-Cookie: foo=0
+  #
+  #     puts cgi.http_header('cookie' => foo_cookie)
+  #     Content-Type: text/html
+  #     Set-Cookie: foo=0; path=
+  #
+  #     puts cgi.http_header('cookie' => [foo_cookie, bar_string])
+  #     Content-Type: text/html
+  #     Set-Cookie: foo=0; path=
+  #     Set-Cookie: bar=1
+  #
+  #     puts cgi.http_header('cookie' => {foo: foo_cookie, bar: bar_string})
+  #     Content-Type: text/html
+  #     Set-Cookie: foo=0; path=
+  #     Set-Cookie: bar=1
+  #
+  #   These cookies are in addition to the cookies held
+  #   in the <tt>@output_cookies</tt> variable.
+  #
+  # <tt>'expires'</tt>::
+  #   Sets header +Expires+ to the given time,
+  #   which must be a {Time}[https://docs.ruby-lang.org/en/master/Time.html] 
object:
+  #
+  #     puts cgi.http_header('expires' => Time.now + (60 * 60 * 24 * 365))
+  #     Content-Type: text/html
+  #     Expires: Tue, 01 Dec 2026 23:42:37 GMT
+  #
+  # <tt>'language'</tt>::
+  #   Sets header +Content-Language+ to the given string:
+  #
+  #     puts cgi.http_header('language' => 'en-US, en-CA')
+  #     Content-Type: text/html
+  #     Content-Language: en-US, en-CA
+  #
+  # <tt>'length'</tt>::
+  #   Sets header +Content-Length+ to the given value,
+  #   which may be an integer or a string:
+  #
+  #     puts cgi.http_header('length' =>  4096)
+  #     Content-Type: text/html
+  #     Content-Length: 4096
+  #
+  #     puts cgi.http_header('length' =>  '4096')
+  #     Content-Type: text/html
+  #     Content-Length: 4096
+  #
+  # <tt>'nph'</tt>::
+  #   If +true+:
+  #
+  #   - Adds protocol string and status code as first line.
+  #   - Adds date as second line.
+  #   - Adds headers +Server+ with no value,
+  #     and +Connection+ with default value <tt>'close'</tt>;
+  #     either or both values may be overridden with explicit values.
+  #
+  #   Examples:
+  #
+  #     puts cgi.http_header('nph' => true)
+  #     HTTP/1.0 200 OK
+  #     Date: Mon, 01 Dec 2025 19:42:22 GMT
+  #     Server:
+  #     Connection: close
+  #     Content-Type: text/html
+  #
+  #     puts cgi.http_header('nph' => true, 'server' => 'Apache/2.4.1 (Unix)', 
'connection' => 'keep-alive')
+  #     HTTP/1.0 200 OK
+  #     Date: Mon, 01 Dec 2025 20:00:41 GMT
+  #     Server: Apache/2.4.1 (Unix)
+  #     Connection: keep-alive
+  #     Content-Type: text/html
+  #
+  # <tt>'server'</tt>::
+  #   Sets header +Server+ to the given string:
+  #
+  #     puts cgi.http_header('server' => 'Apache/2.4.1 (Unix)')
+  #     Server: Apache/2.4.1 (Unix)
+  #     Content-Type: text/html
+  #
+  # <tt>'status'</tt>::
+  #   Sets header +Status+ to the given string:
+  #
+  #     puts cgi.http_header('status' => '666 MyVeryOwnStatus')
+  #     Status: 666 MyVeryOwnStatus
+  #     Content-Type: text/html
+  #
+  #   If the given string is a key in the hash constant +CGI::HTTP_STATUS+,
+  #   the status becomes the value for that key:
+  #
+  #     CGI::HTTP_STATUS
+  #     # =>
+  #     {"OK" => "200 OK",
+  #      "PARTIAL_CONTENT" => "206 Partial Content",
+  #      "MULTIPLE_CHOICES" => "300 Multiple Choices",
+  #      "MOVED" => "301 Moved Permanently",
+  #      "REDIRECT" => "302 Found",
+  #      "NOT_MODIFIED" => "304 Not Modified",
+  #      "BAD_REQUEST" => "400 Bad Request",
+  #      "AUTH_REQUIRED" => "401 Authorization Required",
+  #      "FORBIDDEN" => "403 Forbidden",
+  #      "NOT_FOUND" => "404 Not Found",
+  #      "METHOD_NOT_ALLOWED" => "405 Method Not Allowed",
+  #      "NOT_ACCEPTABLE" => "406 Not Acceptable",
+  #      "LENGTH_REQUIRED" => "411 Length Required",
+  #      "PRECONDITION_FAILED" => "412 Precondition Failed",
+  #      "SERVER_ERROR" => "500 Internal Server Error",
+  #      "NOT_IMPLEMENTED" => "501 Method Not Implemented",
+  #      "BAD_GATEWAY" => "502 Bad Gateway",
+  #      "VARIANT_ALSO_VARIES" => "506 Variant Also Negotiates"}
+  #
+  #     puts cgi.http_header('status' => 'OK')
+  #     Status: 200 OK
+  #     Content-Type: text/html
+  #
+  #     puts cgi.http_header('status' => 'NOT_FOUND')
+  #     Status: 404 Not Found
+  #     Content-Type: text/html
+  #
+  # <tt>'type'</tt>::
+  #   Sets +Content-Type+, overriding the default value <tt>'text/html'</tt>:
+  #
+  #     puts cgi.http_header('type' => 'text/xml')
+  #     Content-Type: text/xml
+  #
+  # <i>Unrecognized Keys</i>
+  #
+  # Headers may also be set for unrecognized keys;
+  # an unrecognized key becomes a header name with the given value:
+  #
+  #   puts cgi.http_header('length' => 0)  # Recognized key (lowercase string).
+  #   Content-Type: text/html
+  #   Content-Length: 0
+  #
+  #   puts cgi.http_header('Length' => 0)  # Unrecognized key (string key not 
lowercase).
+  #   Content-Type: text/html
+  #   Length: 0
+  #
+  #   puts cgi.http_header(length: 0)      # Unrecognized key (symbol key not 
string)
+  #   Content-Type: text/html
+  #   length: 0
   #
-  #   Other headers can also be set; they are appended as key: value.
+  # This method does not perform charset conversion.
   #
-  # Examples:
+  # It's best to use this method (CGI#http_header), not its aliased method 
+header+,
+  # which is provided only for backward compatibility.
   #
-  #   http_header
-  #     # Content-Type: text/html
+  # Method CGI#http_header is preferred because when +tag_maker+ is 
<tt>'html5'</tt>,
+  # calling method +header+ generates an HTML +header+ element:
   #
-  #   http_header("text/plain")
-  #     # Content-Type: text/plain
+  #   cgi = CGI.new(tag_maker: 'html5')
+  #   puts cgi.http_header  # Works as expected.
+  #   Content-Type: text/html
+  #   puts cgi.header       # Maybe a surprise.
+  #   <HEADER></HEADER>
   #
-  #   http_header("nph"        => true,
-  #               "status"     => "OK",  # == "200 OK"
-  #                 # "status"     => "200 GOOD",
-  #               "server"     => ENV['SERVER_SOFTWARE'],
-  #               "connection" => "close",
-  #               "type"       => "text/html",
-  #               "charset"    => "iso-2022-jp",
-  #                 # Content-Type: text/html; charset=iso-2022-jp
-  #               "length"     => 103,
-  #               "language"   => "ja",
-  #               "expires"    => Time.now + 30,
-  #               "cookie"     => [cookie1, cookie2],
-  #               "my_header1" => "my_value",
-  #               "my_header2" => "my_value")
-  #
-  # This method does not perform charset conversion.
   def http_header(options='text/html')
     if options.is_a?(String)
       content_type = options
@@ -384,11 +560,14 @@
     stdoutput.print(*options)
   end
 
-  # Parse an HTTP query string into a hash of key=>value pairs.
+  # :call-seq:
+  #    CGI.parse(query_string) -> hash
   #
-  #   params = CGI.parse("query_string")
-  #     # {"name1" => ["value1", "value2", ...],
-  #     #  "name2" => ["value1", "value2", ...], ... }
+  # Returns a new hash built from name/value pairs in the given +query_string+:
+  #
+  #   query = 'foo=0&bar=1&foo=2&bar=3'
+  #   CGI.parse(query)
+  #   # => {"foo" => ["0", "2"], "bar" => ["1", "3"]}
   #
   def self.parse(query)
     params = {}
@@ -478,7 +657,7 @@
 
     ##
     # Parses multipart form elements according to
-    #   http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2
+    #   https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2
     #
     # Returns a hash of multipart form parameters with bodies of type StringIO 
or
     # Tempfile depending on whether the multipart form element exceeds 10 KB
@@ -629,8 +808,8 @@
       string = unless ARGV.empty?
         ARGV.join(' ')
       else
-        if STDIN.tty?
-          STDERR.print(
+        if stdinput.tty?
+          $stderr.print(
             %|(offline mode: enter name=value pairs on standard input)\n|
           )
         end
@@ -659,13 +838,16 @@
     # Handles multipart forms (in particular, forms that involve file uploads).
     # Reads query parameters in the @params field, and cookies into @cookies.
     def initialize_query()
+      content_length = env_table['CONTENT_LENGTH']
+      content_length = nil if content_length == ''
       if ("POST" == env_table['REQUEST_METHOD']) and
         %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?| =~ 
env_table['CONTENT_TYPE']
         current_max_multipart_length = 
@max_multipart_length.respond_to?(:call) ? @max_multipart_length.call : 
@max_multipart_length
         raise StandardError.new("too large multipart data.") if 
env_table['CONTENT_LENGTH'].to_i > current_max_multipart_length
+        raise StandardError.new("no content length for multipart data.") if 
content_length.nil?
         boundary = $1.dup
         @multipart = true
-        @params = read_multipart(boundary, 
Integer(env_table['CONTENT_LENGTH']))
+        @params = read_multipart(boundary, Integer(content_length))
       else
         @multipart = false
         @params = CGI.parse(
@@ -678,7 +860,11 @@
                       end
                     when "POST"
                       stdinput.binmode if defined? stdinput.binmode
-                      stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or ''
+                      if content_length.nil?
+                        stdinput.read or ''
+                      else
+                        stdinput.read(Integer(content_length)) or ''
+                      end
                     else
                       read_from_cmdline
                     end.dup.force_encoding(@accept_charset)
@@ -755,12 +941,75 @@
   #
   @@accept_charset="UTF-8" if false # needed for rdoc?
 
-  # Return the accept character set for all new CGI instances.
+  # :call-seq:
+  #   CGI.accept_charset -> encoding
+  #
+  # Returns the default accept character set to be used for new \CGI instances;
+  # see CGI.accept_charset=.
   def self.accept_charset
     @@accept_charset
   end
 
-  # Set the accept character set for all new CGI instances.
+  # :call-seq:
+  #    CGI.accept_charset = encoding
+  #
+  # Sets the default accept character set to be used for new \CGI instances;
+  # returns the argument.
+  #
+  # The argument may be an Encoding object or an Encoding name;
+  # see 
{Encodings}[https://docs.ruby-lang.org/en/master/language/encodings_rdoc.html]:
+  #
+  #   # The initial value.
+  #   CGI.accept_charset # => #<Encoding:UTF-8>
+  #   CGI.new
+  #   # =>
+  #   #<CGI:0x0000018991db6ae8
+  #    @accept_charset=#<Encoding:UTF-8>,
+  #    @accept_charset_error_block=nil,
+  #    @cookies={},
+  #    @max_multipart_length=134217728,
+  #    @multipart=false,
+  #    @options={accept_charset: #<Encoding:UTF-8>, max_multipart_length: 
134217728},
+  #    @output_cookies=nil,
+  #    @output_hidden=nil,
+  #    @params={}>
+  #
+  #   # Set by Encoding name.
+  #   CGI.accept_charset = 'US-ASCII' # => "US-ASCII"
+  #   CGI.new
+  #   # =>
+  #   #<CGI:0x0000018991cf4100
+  #    @accept_charset="US-ASCII",
+  #    @accept_charset_error_block=nil,
+  #    @cookies={},
+  #    @max_multipart_length=134217728,
+  #    @multipart=false,
+  #    @options={accept_charset: "US-ASCII", max_multipart_length: 134217728},
+  #    @output_cookies=nil,
+  #    @output_hidden=nil,
+  #    @params={}>
+  #
+  #   # Set by Encoding object.
+  #   CGI.accept_charset = Encoding::ASCII_8BIT # => #<Encoding:BINARY 
(ASCII-8BIT)>
+  #   CGI.new
+  #   # =>
+  #   #<CGI:0x0000018991cfc800
+  #    @accept_charset=#<Encoding:BINARY (ASCII-8BIT)>,
+  #    @accept_charset_error_block=nil,
+  #    @cookies={},
+  #    @max_multipart_length=134217728,
+  #    @multipart=false,
+  #    @options={accept_charset: #<Encoding:BINARY (ASCII-8BIT)>, 
max_multipart_length: 134217728},
+  #    @output_cookies=nil,
+  #    @output_hidden=nil,
+  #    @params={}>
+  #
+  # The given encoding is not checked in this method,
+  # but if it is invalid, a call to CGI.new will fail:
+  #
+  #   CGI.accept_charset = 'foo'
+  #   CGI.new  # Raises ArgumentError: unknown encoding name - foo
+  #
   def self.accept_charset=(accept_charset)
     @@accept_charset=accept_charset
   end
@@ -778,75 +1027,199 @@
   #
   @@max_multipart_length= 128 * 1024 * 1024
 
-  # Create a new CGI instance.
-  #
   # :call-seq:
-  #   CGI.new(tag_maker) { block }
-  #   CGI.new(options_hash = {}) { block }
+  #   CGI.new(options = {}) -> new_cgi
+  #   CGI.new(tag_maker) -> new_cgi
+  #   CGI.new(options = {}) {|name, value| ... } -> new_cgi
+  #   CGI.new(tag_maker) {|name, value| ... } -> new_cgi
+  #
+  # Returns a new \CGI object.
+  #
+  # The behavior of this method depends _strongly_ on whether it is called
+  # within a standard \CGI call environment;
+  # that is, whether <tt>ENV['REQUEST_METHOD']</tt> is defined.
+  #
+  # <b>Within a Standard Call Environment</b>
   #
+  # This section assumes that <tt>ENV['REQUEST_METHOD']</tt> is defined;
+  # for example:
   #
-  # <tt>tag_maker</tt>::
-  #   This is the same as using the +options_hash+ form with the value <tt>{
-  #   :tag_maker => tag_maker }</tt> Note that it is recommended to use the
-  #   +options_hash+ form, since it also allows you specify the charset you
-  #   will accept.
-  # <tt>options_hash</tt>::
-  #   A Hash that recognizes three options:
+  #   ENV['REQUEST_METHOD'] # => "GET"
   #
-  #   <tt>:accept_charset</tt>::
-  #     specifies encoding of received query string.  If omitted,
-  #     <tt>@@accept_charset</tt> is used.  If the encoding is not valid, a
-  #     CGI::InvalidEncoding will be raised.
+  # With no argument and no block given, returns a new \CGI object with 
default values:
+  #
+  #   cgi = CGI.new
+  #   cgi
+  #   # =>
+  #   #<CGI:0x00000189917aff00
+  #    @accept_charset=#<Encoding:UTF-8>,
+  #    @accept_charset_error_block=nil,
+  #    @cookies={},
+  #    @max_multipart_length=134217728,
+  #    @multipart=false,
+  #    @options={accept_charset: #<Encoding:UTF-8>, max_multipart_length: 
134217728},
+  #    @output_cookies=nil,
+  #    @output_hidden=nil,
+  #    @params={}>
+  #
+  # With hash argument +options+ given and no block given,
+  # returns a new \CGI object with the given options.
+  #
+  # The options may be:
+  #
+  # - <tt>accept_charset: _encoding_</tt>:
+  #   specifies the encoding of the received query string.
+  #
+  #   Value  _encoding_ may be
+  #   an {Encoding 
object}[https://docs.ruby-lang.org/en/master/encodings_rdoc.html#label-Encoding+Objects]
+  #   or an {encoding 
name}[https://docs.ruby-lang.org/en/master/encodings_rdoc.html#label-Names+and+Aliases]:
+  #
+  #     CGI.new(accept_charset: 'EUC-JP')
+  #
+  #   If the option is not given,
+  #   the default value is the class default encoding.
+  #
+  #   <em>Note:</em> The <tt>accept_charset</tt> method returns the HTTP 
Accept-Charset
+  #   header value, not the configured encoding. The configured encoding is 
used
+  #   internally for query string parsing.
+  #
+  # - <tt>max_multipart_length: _size_</tt>:
+  #   specifies maximum size (in bytes) of multipart data.
+  #
+  #   The _size_ may be:
+  #
+  #   - A positive integer.
+  #
+  #       CGI.new(max_multipart_length: 1024 * 1024)
   #
-  #     Example. Suppose <tt>@@accept_charset</tt> is "UTF-8"
   #
-  #     when not specified:
+  #   - A lambda to be evaluated when the request is parsed.
+  #     This is useful when determining whether to accept multipart data
+  #     (e.g. by consulting a registered user's upload allowance).
   #
-  #         cgi=CGI.new      # @accept_charset # => "UTF-8"
+  #       CGI.new(max_multipart_length: -> {check_filesystem})
   #
-  #     when specified as "EUC-JP":
+  #   If the option is not given, the default is +134217728+, specifying a 
maximum size of 128 megabytes.
   #
-  #         cgi=CGI.new(:accept_charset => "EUC-JP") # => "EUC-JP"
+  #   <em>Note:</em> This option configures internal behavior only.
+  #   There is no public method to retrieve this value after initialization.
   #
-  #   <tt>:tag_maker</tt>::
-  #     String that specifies which version of the HTML generation methods to
-  #     use.  If not specified, no HTML generation methods will be loaded.
+  # - <tt>tag_maker: _html_version_</tt>:
+  #   specifies a version of HTML;
+  #   this determines which tag-generating instance methods
+  #   (such as +html+, +head+, +body+, etc.) are to be loaded.
   #
-  #     The following values are supported:
+  #   Value _html_version_ may be one of:
   #
-  #     "html3":: HTML 3.x
-  #     "html4":: HTML 4.0
-  #     "html4Tr":: HTML 4.0 Transitional
-  #     "html4Fr":: HTML 4.0 with Framesets
-  #     "html5":: HTML 5
+  #   - <tt>'html3'</tt>: {HTML version 
3}[https://www.w3.org/MarkUp/html3/Contents.html].
+  #   - <tt>'html4'</tt>: {HTML version 4}[https://www.w3.org/TR/html4].
+  #   - <tt>'html4Tr'</tt>: {HTML 4.0 
Transitional}[https://www.w3.org/TR/html4/sgml/loosedtd.html].
+  #   - <tt>'html4Fr'</tt>: {HTML 4.0 with 
Framesets}[https://www.w3.org/TR/html4/present/frames.html].
+  #   - <tt>'html5'</tt>: {HTML version 
5}[https://html.spec.whatwg.org/multipage].
   #
-  #   <tt>:max_multipart_length</tt>::
-  #     Specifies maximum length of multipart data. Can be an Integer scalar or
-  #     a lambda, that will be evaluated when the request is parsed. This
-  #     allows more complex logic to be set when determining whether to accept
-  #     multipart data (e.g. consult a registered users upload allowance)
+  #   Example:
   #
-  #     Default is 128 * 1024 * 1024 bytes
+  #     CGI.new(tag_maker: 'html5')
   #
-  #         cgi=CGI.new(:max_multipart_length => 268435456) # simple scalar
+  #   If the option is not given (or if an invalid value is given),
+  #   no tag-generating methods are loaded.
   #
-  #         cgi=CGI.new(:max_multipart_length => -> {check_filesystem}) # 
lambda
+  #   Examples:
   #
-  # <tt>block</tt>::
-  #   If provided, the block is called when an invalid encoding is
-  #   encountered. For example:
+  #     CGI.new.respond_to?(:html)                       # => false  # 
Tag-generating methods not loaded.
+  #     CGI.new(tag_maker: 'html3').respond_to?(:html)   # => true   # 
Tag-generating methods loaded.
+  #     # Tag 'button' is new in HTML 4.
+  #     CGI.new(tag_maker: 'html3').respond_to?(:button) # => false
+  #     CGI.new(tag_maker: 'html4').respond_to?(:button) # => true
+  #     # Tag 'canvas' is new in HTML 5.
+  #     CGI.new(tag_maker: 'html4').respond_to?(:canvas) # => false
+  #     CGI.new(tag_maker: 'html5').respond_to?(:canvas) # => true
+  #     # Value is case-sensitive.
+  #     CGI.new(tag_maker: 'HTML4').respond_to?(:html)   # => false
   #
-  #     encoding_errors={}
-  #     cgi=CGI.new(:accept_charset=>"EUC-JP") do |name,value|
-  #       encoding_errors[name] = value
-  #     end
+  #   You can determine exactly which methods have been loaded;
+  #   this example captures the methods loaded by <tt>'html4'</tt>:
+  #
+  #     methods_loaded = CGI.new('html4').methods - CGI.new.methods
+  #     methods_loaded.size # => 98
+  #     methods_loaded.sort.take(10)
+  #     # => [:a, :abbr, :acronym, :address, :area, :b, :base, :bdo, :big, 
:blockquote]
+  #
+  # With string argument +tag_maker+ given as _tag_maker_ and no block given,
+  # equivalent to <tt>CGI.new(tag_maker: _tag_maker_)</tt>:
+  #
+  #   CGI.new('html5')
+  #
+  # <b>Outside a Standard Call Environment</b>
+  #
+  # This section assumes that <tt>ENV['REQUEST_METHOD']</tt> is not defined;
+  # for example:
+  #
+  #   ENV['REQUEST_METHOD'] # => nil
+  #
+  # In this mode, the method reads its parameters
+  # from the command line or (failing that) from standard input;
+  # returns a new \CGI object.
+  #
+  # Parameters from command line:
+  #
+  #   $ cat t.rb
+  #   require 'cgi'
+  #   cgi = CGI.new
+  #   p cgi.params
+  #   ruby t.rb foo=0 bar=1 foo=2 bar=3
+  #   {"foo" => ["0", "2"], "bar" => ["1", "3"]}
+  #
+  # Parameters from standard input:
+  #
+  #   cgi = CGI.new
+  #   (offline mode: enter name=value pairs on standard input)
+  #   foo=0
+  #   bar=1
+  #   ^D
+  #   cgi.params
+  #   # => {"foo" => ["0"], "bar" => ["1"]}
+  #
+  # The end-of-file character is Ctrl-D on a Unix-like system (as above),
+  # or Ctrl-Z on Windows.
+  #
+  # Otherwise, cookies and other parameters are parsed automatically from the 
standard CGI locations,
+  # which vary according to the request method.
+  #
+  # <b>Options vs Public Methods</b>
+  #
+  # Some initialization options configure internal behavior only and do not 
provide
+  # corresponding public getter methods:
+  #
+  # - <tt>accept_charset</tt>: Configures internal encoding for parsing.
+  #   The <tt>accept_charset</tt> method returns the HTTP Accept-Charset 
header.
+  # - <tt>max_multipart_length</tt>: Configures internal multipart size limits.
+  #   No public getter method is available.
+  # - <tt>tag_maker</tt>: Loads HTML generation methods (publicly accessible).
+  #
+  # <b>Block</b>
+  #
+  # If a block is given, its code is stored as a Proc;
+  # whenever CGI::InvalidEncoding would be raised, the proc is called instead.
+  #
+  # In this example, the proc simply saves the error:
+  #
+  #   encoding_errors = {}
+  #   CGI.new(accept_charset: 'EUC-JP') do |name,value|
+  #     encoding_errors[name] = value
+  #   end
+  #   # =>
+  #   #<CGI:0x000002b0ec11bcd8
+  #    @accept_charset="EUC-JP",
+  #    @accept_charset_error_block=#<Proc:0x000002b0ed2ee190 (irb):146>,
+  #    @cookies={},
+  #    @max_multipart_length=134217728,
+  #    @multipart=false,
+  #    @options={accept_charset: "EUC-JP", max_multipart_length: 134217728},
+  #    @output_cookies=nil,
+  #    @output_hidden=nil,
+  #    @params={}>
   #
-  # Finally, if the CGI object is not created in a standard CGI call
-  # environment (that is, it can't locate REQUEST_METHOD in its environment),
-  # then it will run in "offline" mode.  In this mode, it reads its parameters
-  # from the command line or (failing that) from standard input.  Otherwise,
-  # cookies and other parameters are parsed automatically from the standard
-  # CGI locations, which varies according to the REQUEST_METHOD.
   def initialize(options = {}, &block) # :yields: name, value
     @accept_charset_error_block = block_given? ? block : nil
     @options={
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/cgi/escape.rb new/lib/cgi/escape.rb
--- old/lib/cgi/escape.rb       2025-06-04 05:38:29.000000000 +0200
+++ new/lib/cgi/escape.rb       2026-06-23 09:06:24.000000000 +0200
@@ -1,11 +1,15 @@
 # frozen_string_literal: true
 
+# :stopdoc
 class CGI
   module Escape; end
   include Escape
   extend Escape
+  module EscapeExt; end # :nodoc:
 end
+# :startdoc:
 
+# Escape/unescape for CGI, HTML, URI.
 module CGI::Escape
   @@accept_charset = Encoding::UTF_8 unless defined?(@@accept_charset)
 
@@ -128,41 +132,32 @@
                 end
     string = string.b
     string.gsub!(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do
-      match = $1.dup
+      match = $1
       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 n < charlimit
-          n.chr(enc)
-        else
-          "&##{$1};"
-        end
-      when /\A#x([0-9a-f]+)\z/i
-        n = $1.hex
-        if n < charlimit
-          n.chr(enc)
+      else
+        # Numeric character reference. Decode into the binary buffer so that a
+        # non-ASCII byte already present in it never triggers an encoding
+        # compatibility error on concatenation; the trailing force_encoding
+        # re-tags the whole buffer. This mirrors the C extension's
+        # optimized_unescape_html.
+        n = match.start_with?('#x', '#X') ? match[2..-1].hex : 
match[1..-1].to_i
+        if n >= charlimit
+          "&#{match};"            # out of range: keep the reference verbatim
+        elsif charlimit > 256
+          [n].pack('U').b         # UTF-8: code point bytes, surrogates 
included (like rb_enc_mbcput)
         else
-          "&#x#{$1};"
+          n.chr.b                 # ISO-8859-1 / ASCII: single byte
         end
-      else
-        "&#{match};"
       end
     end
     string.force_encoding enc
   end
 
-  # Synonym for CGI.escapeHTML(str)
-  alias escape_html escapeHTML
-  alias h escapeHTML
-
-  # Synonym for CGI.unescapeHTML(str)
-  alias unescape_html unescapeHTML
-
   # TruffleRuby runs the pure-Ruby variant faster, do not use the C extension 
there
   unless RUBY_ENGINE == 'truffleruby'
     begin
@@ -171,6 +166,14 @@
     end
   end
 
+  # Aliases must be defined on EscapeExt so they resolve to the C methods.
+  target = defined?(CGI::EscapeExt) && 
CGI::EscapeExt.method_defined?(:escapeHTML) ? CGI::EscapeExt : self
+  target.module_eval do
+    alias escape_html escapeHTML
+    alias h escapeHTML
+    alias unescape_html unescapeHTML
+  end
+
   # Escape only the tags of certain HTML elements in +string+.
   #
   # Takes an element or elements or array of elements.  Each element
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/cgi/html.rb new/lib/cgi/html.rb
--- old/lib/cgi/html.rb 2025-06-04 05:38:29.000000000 +0200
+++ new/lib/cgi/html.rb 2026-06-23 09:06:24.000000000 +0200
@@ -1006,27 +1006,32 @@
 
   end # Html5
 
+  # HTML version 3 generation class.
   class HTML3
     include Html3
     include HtmlExtension
   end
 
+  # HTML version 4 generation class.
   class HTML4
     include Html4
     include HtmlExtension
   end
 
+  # HTML version 4 transitional generation class.
   class HTML4Tr
     include Html4Tr
     include HtmlExtension
   end
 
+  # HTML version 4 with framesets generation class.
   class HTML4Fr
     include Html4Tr
     include Html4Fr
     include HtmlExtension
   end
 
+  # HTML version 5 generation class.
   class HTML5
     include Html5
     include HtmlExtension
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/cgi/session.rb new/lib/cgi/session.rb
--- old/lib/cgi/session.rb      2025-06-04 05:38:29.000000000 +0200
+++ new/lib/cgi/session.rb      2026-06-23 09:06:24.000000000 +0200
@@ -206,19 +206,28 @@
     #          on Unix systems).
     # prefix:: the prefix to add to the session id when generating
     #          the filename for this session's FileStore file.
-    #          Defaults to "cgi_sid_".
+    #          Defaults to the empty string.
     # suffix:: the prefix to add to the session id when generating
     #          the filename for this session's FileStore file.
     #          Defaults to the empty string.
+    # digest:: the digest algorithm to hash the session id when
+    #          generating the filename for this session's FileStore
+    #          file.  Defaults to "SHA256".
+    # length:: the length of the session id part of the filestore,
+    #          excluding +prefix+ and +suffix+ parts.  Defaults to 16.
     def new_store_file(option={}) # :nodoc:
       dir = option['tmpdir'] || Dir::tmpdir
       prefix = option['prefix']
       suffix = option['suffix']
-      require 'digest/md5'
-      md5 = Digest::MD5.hexdigest(session_id)[0,16]
+      algorithm = option['digest'] || 'SHA256'
+      if String === algorithm
+        require 'digest'
+        algorithm = Digest(algorithm)
+      end
+      digest = algorithm.hexdigest(session_id)[0, option['length'] || 16]
       path = dir+"/"
       path << prefix if prefix
-      path << md5
+      path << digest
       path << suffix if suffix
       if File::exist? path
         hash = nil
@@ -410,6 +419,9 @@
       # suffix:: the prefix to add to the session id when generating
       #          the filename for this session's FileStore file.
       #          Defaults to the empty string.
+      # digest:: the digest algorithm to hash the session id when
+      #          generating the filename for this session's FileStore
+      #          file.  Defaults to "MD5".
       #
       # This session's FileStore file will be created if it does
       # not exist, or opened if it does.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/cgi/util.rb new/lib/cgi/util.rb
--- old/lib/cgi/util.rb 2025-06-04 05:38:29.000000000 +0200
+++ new/lib/cgi/util.rb 2026-06-23 09:06:24.000000000 +0200
@@ -5,6 +5,7 @@
   extend Util
 end
 
+# Utility methods for CGI.
 module CGI::Util
   # Format a +Time+ object as a String using the format specified by RFC 1123.
   #
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/cgi.rb new/lib/cgi.rb
--- old/lib/cgi.rb      2025-06-04 05:38:29.000000000 +0200
+++ new/lib/cgi.rb      2026-06-23 09:06:24.000000000 +0200
@@ -26,7 +26,7 @@
 # The file CGI::Session provides session management functionality; see that
 # class for more details.
 #
-# See http://www.w3.org/CGI/ for more information on the CGI protocol.
+# See https://www.w3.org/CGI/ for more information on the CGI protocol.
 #
 # == Introduction
 #
@@ -42,6 +42,17 @@
 #
 # Read on for more details.  Examples are provided at the bottom.
 #
+# == About the Examples
+#
+# Examples on this page assume that \CGI has been required:
+#
+#   require 'cgi'
+#
+# Unless otherwise stated, examples also assume that environment variable 
'REQUEST_METHOD' exists
+# (which prevents CGI.new from entering its online mode):
+#
+#   ENV.include?('REQUEST_METHOD') # => true
+#
 # == Queries
 #
 # The CGI class dynamically mixes in parameter and cookie-parsing
@@ -148,59 +159,62 @@
 # Escape and unescape methods are defined in cgi/escape.rb.
 # And when include, you can use utility methods like a function.
 #
-# == Examples of use
+# == Examples of Use
 #
-# === Get form values
+# === Form Values
 #
-#   require "cgi"
-#   cgi = CGI.new
-#   value = cgi['field_name']   # <== value string for 'field_name'
-#     # if not 'field_name' included, then return "".
-#   fields = cgi.keys            # <== array of field names
-#
-#   # returns true if form has 'field_name'
-#   cgi.has_key?('field_name')
-#   cgi.has_key?('field_name')
-#   cgi.include?('field_name')
+# ==== Get Form Values
 #
-# CAUTION! <code>cgi['field_name']</code> returned an Array with the old
-# cgi.rb(included in Ruby 1.6)
+# You can use method +cgi.params+ to retrieve form values
+# in a {Hash}[https://docs.ruby-lang.org/en/3.4/Hash.html]:
 #
-# === Get form values as hash
-#
-#   require "cgi"
+#   ENV.update(
+#    'REQUEST_METHOD' => 'GET',
+#    'QUERY_STRING'   => 'a=111&&b=222&c&d='
+#   )
 #   cgi = CGI.new
-#   params = cgi.params
-#
-# cgi.params is a hash.
-#
-#   cgi.params['new_field_name'] = ["value"]  # add new param
-#   cgi.params['field_name'] = ["new_value"]  # change value
-#   cgi.params.delete('field_name')           # delete param
-#   cgi.params.clear                          # delete all params
-#
-#
-# === Save form values to file
-#
-#   require "pstore"
-#   db = PStore.new("query.db")
-#   db.transaction do
-#     db["params"] = cgi.params
+#   cgi.params.class # => Hash
+#   cgi.params       # => {"a" => ["111"], "b" => ["222"], "c" => [], "d" => 
[""]}
+#   cgi.params.keys  # => ["a", "b", "c", "d"]
+#   cgi.params['a']  # => ["111"]  # Returns an array.
+#   cgi.params['d']  # => [""]     # Returns empty string in array if no value.
+#   cgi.params['x']  # => []       # Returns empty array if no key.
+#
+# A \CGI instance has these convenience methods:
+#
+#   # Convenience method for cgi.params.keys.
+#   cgi.keys          # => ["a", "b", "c", "d"]
+#   # Convenience method for cgi.params[key].first.
+#   cgi['a']          # => "111"  # Returns string, not array.
+#   cgi['d']          # => ""     # Returns empty string if no value.
+#   cgi['x']          # => ""     # Returns empty string if no key.
+#   # Convenience method for cgi.params.include?.
+#   cgi.include?('a') # => true
+#   cgi.include?('x') # => false
+#
+# ==== Save and Restore Form Values
+#
+# This example uses {Pstore}[https://docs.ruby-lang.org/en/3.4/PStore.html]
+# to store and retrieve form values:
+#
+#   ENV.update(
+#    'REQUEST_METHOD' => 'GET',
+#    'QUERY_STRING'   => 'a=111&&b=222&c&d='
+#   )
+#   cgi = CGI.new
+#   require 'pstore'
+#   store = PStore.new('params.store')
+#   store.transaction do
+#     store['params'] = cgi.params
 #   end
-#
-#
-# === Restore form values from file
-#
-#   require "pstore"
-#   db = PStore.new("query.db")
-#   db.transaction do
-#     cgi.params = db["params"]
+#   cgi.params.clear # Oops! Lost my params!
+#   store.transaction do
+#     cgi.params = store['params']
 #   end
+#   cgi.params # => {"a" => ["111"], "b" => ["222"], "c" => [], "d" => [""]}
 #
+# ==== Get multipart form values
 #
-# === Get multipart form values
-#
-#   require "cgi"
 #   cgi = CGI.new
 #   value = cgi['field_name']   # <== value string for 'field_name'
 #   value.read                  # <== body of value
@@ -212,7 +226,6 @@
 #
 # === Get cookie values
 #
-#   require "cgi"
 #   cgi = CGI.new
 #   values = cgi.cookies['name']  # <== array of 'name'
 #     # if not 'name' included, then return [].
@@ -222,7 +235,6 @@
 #
 # === Get cookie objects
 #
-#   require "cgi"
 #   cgi = CGI.new
 #   for name, cookie in cgi.cookies
 #     cookie.expires = Time.now + 30
@@ -231,14 +243,12 @@
 #
 #   cgi.cookies # { "name1" => cookie1, "name2" => cookie2, ... }
 #
-#   require "cgi"
 #   cgi = CGI.new
 #   cgi.cookies['name'].expires = Time.now + 30
 #   cgi.out("cookie" => cgi.cookies['name']) {"string"}
 #
 # === Print http header and html string to $DEFAULT_OUTPUT ($>)
 #
-#   require "cgi"
 #   cgi = CGI.new("html4")  # add HTML generation methods
 #   cgi.out do
 #     cgi.html do
@@ -289,7 +299,8 @@
 #
 
 class CGI
-  VERSION = "0.5.0"
+  # The version string
+  VERSION = "0.5.2"
 end
 
 require 'cgi/util'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        2025-06-04 05:38:29.000000000 +0200
+++ new/metadata        2026-06-23 09:06:24.000000000 +0200
@@ -1,13 +1,13 @@
 --- !ruby/object:Gem::Specification
 name: cgi
 version: !ruby/object:Gem::Version
-  version: 0.5.0
+  version: 0.5.2
 platform: ruby
 authors:
 - Yukihiro Matsumoto
 bindir: bin
 cert_chain: []
-date: 2025-06-04 00:00:00.000000000 Z
+date: 2026-06-23 00:00:00.000000000 Z
 dependencies: []
 description: Support for the Common Gateway Interface protocol.
 email:
@@ -38,6 +38,7 @@
 metadata:
   homepage_uri: https://github.com/ruby/cgi
   source_code_uri: https://github.com/ruby/cgi
+  changelog_uri: https://github.com/ruby/cgi/releases
 rdoc_options: []
 require_paths:
 - lib

Reply via email to