cgi 0.4.2 → 0.5.1

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: a2223dc33d62279bcf8cb78f68d8fb46f22c8d9e396243e22d43ded77291dfe5
4
- data.tar.gz: 70b263423e005129ac529dd41f59324accedd2cf6fd8c260965286ff0f03a399
3
+ metadata.gz: 0f7c88bb08e51fd6b7abd1855b87d05c8af6b8f4e89865f0315f512badcddcb9
4
+ data.tar.gz: fbe294b63d488ae16c123d325b2251a9561da5b474105a0ecbb1ecd880c4cdb6
5
5
  SHA512:
6
- metadata.gz: 9d63be598547392b545cabca27ed6f6765ffa9d8e778335118fa29592c36d8276cc68af052db7abe8e2373c8818072523df6e6aaf65393d09c7c5d16600af6cd
7
- data.tar.gz: 5a27bb456ab0ecee2e504b737f1b7e8f8e2dd3d56f253fd9c08b5ef42fb145dbc1fbb5e3cec9e98866b19d42aa63d58b4b36affa94a25be9e9f46fa2bc03c942
6
+ metadata.gz: 9d4837752a514f02e88f8f3673fa0b0b9a31195df062d79c9d5b51175288f5053409fc337b1613ad27393b92c4394663d4cfd355d30c555b565f79a9102e2feb
7
+ data.tar.gz: 0c465bae726d291b6829b6f0bf9f86d05976bf61529dc8190da4fd73022b37924c7901c3b29fb3cddb7760829aa24ac5cd6999c1f1ad9b4ec825fe0afc63ef19
data/README.md CHANGED
@@ -32,21 +32,19 @@ Or install it yourself as:
32
32
 
33
33
  ### Get form values
34
34
 
35
+ Given a form with the content `field_name=123`:
36
+
35
37
  ```ruby
36
38
  require "cgi"
37
39
  cgi = CGI.new
38
- value = cgi['field_name'] # <== value string for 'field_name'
39
- # if not 'field_name' included, then return "".
40
- fields = cgi.keys # <== array of field names
41
-
42
- # returns true if form has 'field_name'
43
- cgi.has_key?('field_name')
44
- cgi.has_key?('field_name')
45
- cgi.include?('field_name')
46
- ```
40
+ value = cgi['field_name'] # => "123"
41
+ cgi['flowerpot'] # => ""
42
+ fields = cgi.keys # => [ "field_name" ]
47
43
 
48
- CAUTION! cgi['field_name'] returned an Array with the old
49
- cgi.rb(included in Ruby 1.6)
44
+ cgi.has_key?('field_name') # => true
45
+ cgi.include?('field_name') # => true
46
+ cgi.include?('flowerpot') # => false
47
+ ```
50
48
 
51
49
  ### Get form values as hash
52
50
 
@@ -8,7 +8,7 @@ RUBY_EXTERN const signed char ruby_digit36_to_number_table[];
8
8
  #define upper_hexdigits (ruby_hexdigits+16)
9
9
  #define char_to_number(c) ruby_digit36_to_number_table[(unsigned char)(c)]
10
10
 
11
- static VALUE rb_cCGI, rb_mUtil, rb_mEscape;
11
+ static VALUE rb_cCGI, rb_mEscape, rb_mEscapeExt;
12
12
  static ID id_accept_charset;
13
13
 
14
14
  #define HTML_ESCAPE_MAX_LEN 6
@@ -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);
@@ -471,17 +471,17 @@ Init_escape(void)
471
471
  void
472
472
  InitVM_escape(void)
473
473
  {
474
- rb_cCGI = rb_define_class("CGI", rb_cObject);
475
- rb_mEscape = rb_define_module_under(rb_cCGI, "Escape");
476
- rb_mUtil = rb_define_module_under(rb_cCGI, "Util");
477
- rb_define_method(rb_mEscape, "escapeHTML", cgiesc_escape_html, 1);
478
- rb_define_method(rb_mEscape, "unescapeHTML", cgiesc_unescape_html, 1);
479
- rb_define_method(rb_mEscape, "escapeURIComponent", cgiesc_escape_uri_component, 1);
480
- rb_define_alias(rb_mEscape, "escape_uri_component", "escapeURIComponent");
481
- rb_define_method(rb_mEscape, "unescapeURIComponent", cgiesc_unescape_uri_component, -1);
482
- rb_define_alias(rb_mEscape, "unescape_uri_component", "unescapeURIComponent");
483
- rb_define_method(rb_mEscape, "escape", cgiesc_escape, 1);
484
- rb_define_method(rb_mEscape, "unescape", cgiesc_unescape, -1);
485
- rb_prepend_module(rb_mUtil, rb_mEscape);
486
- rb_extend_object(rb_cCGI, rb_mEscape);
474
+ rb_cCGI = rb_define_class("CGI", rb_cObject);
475
+ rb_mEscapeExt = rb_define_module_under(rb_cCGI, "EscapeExt");
476
+ rb_mEscape = rb_define_module_under(rb_cCGI, "Escape");
477
+ rb_define_method(rb_mEscapeExt, "escapeHTML", cgiesc_escape_html, 1);
478
+ rb_define_method(rb_mEscapeExt, "unescapeHTML", cgiesc_unescape_html, 1);
479
+ rb_define_method(rb_mEscapeExt, "escapeURIComponent", cgiesc_escape_uri_component, 1);
480
+ rb_define_alias(rb_mEscapeExt, "escape_uri_component", "escapeURIComponent");
481
+ rb_define_method(rb_mEscapeExt, "unescapeURIComponent", cgiesc_unescape_uri_component, -1);
482
+ rb_define_alias(rb_mEscapeExt, "unescape_uri_component", "unescapeURIComponent");
483
+ rb_define_method(rb_mEscapeExt, "escape", cgiesc_escape, 1);
484
+ rb_define_method(rb_mEscapeExt, "unescape", cgiesc_unescape, -1);
485
+ rb_prepend_module(rb_mEscape, rb_mEscapeExt);
486
+ rb_extend_object(rb_cCGI, rb_mEscapeExt);
487
487
  }
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
@@ -4,12 +4,12 @@
4
4
  # generating HTTP responses.
5
5
  #++
6
6
  class CGI
7
- unless const_defined?(:Util)
8
- module Util
7
+ unless const_defined?(:Escape)
8
+ module Escape
9
9
  @@accept_charset = "UTF-8" # :nodoc:
10
10
  end
11
- include Util
12
- extend Util
11
+ include Escape
12
+ extend Escape
13
13
  end
14
14
 
15
15
  $CGI_ENV = ENV # for FCGI support
@@ -384,11 +384,14 @@ class CGI
384
384
  stdoutput.print(*options)
385
385
  end
386
386
 
387
- # Parse an HTTP query string into a hash of key=>value pairs.
387
+ # :call-seq:
388
+ # CGI.parse(query_string) -> hash
389
+ #
390
+ # Returns a new hash built from name/value pairs in the given +query_string+:
388
391
  #
389
- # params = CGI.parse("query_string")
390
- # # {"name1" => ["value1", "value2", ...],
391
- # # "name2" => ["value1", "value2", ...], ... }
392
+ # query = 'foo=0&bar=1&foo=2&bar=3'
393
+ # CGI.parse(query)
394
+ # # => {"foo" => ["0", "2"], "bar" => ["1", "3"]}
392
395
  #
393
396
  def self.parse(query)
394
397
  params = {}
@@ -629,8 +632,8 @@ class CGI
629
632
  string = unless ARGV.empty?
630
633
  ARGV.join(' ')
631
634
  else
632
- if STDIN.tty?
633
- STDERR.print(
635
+ if stdinput.tty?
636
+ $stderr.print(
634
637
  %|(offline mode: enter name=value pairs on standard input)\n|
635
638
  )
636
639
  end
@@ -778,75 +781,152 @@ class CGI
778
781
  #
779
782
  @@max_multipart_length= 128 * 1024 * 1024
780
783
 
781
- # Create a new CGI instance.
782
- #
783
784
  # :call-seq:
784
- # CGI.new(tag_maker) { block }
785
- # CGI.new(options_hash = {}) { block }
785
+ # CGI.new(options = {}) -> new_cgi
786
+ # CGI.new(tag_maker) -> new_cgi
787
+ # CGI.new(options = {}) {|name, value| ... } -> new_cgi
788
+ # CGI.new(tag_maker) {|name, value| ... } -> new_cgi
789
+ #
790
+ # Returns a new \CGI object.
791
+ #
792
+ # The behavior of this method depends _strongly_ on whether it is called
793
+ # within a standard \CGI call environment;
794
+ # that is, whether <tt>ENV['REQUEST_METHOD']</tt> is defined.
795
+ #
796
+ # <b>Within a Standard Call Environment</b>
797
+ #
798
+ # This section assumes that <tt>ENV['REQUEST_METHOD']</tt> is defined;
799
+ # for example:
800
+ #
801
+ # ENV['REQUEST_METHOD'] # => "GET"
802
+ #
803
+ # With no argument and no block given, returns a new \CGI object with default values:
804
+ #
805
+ # cgi = CGI.new
806
+ # puts cgi.pretty_inspect
807
+ # #<CGI:0x000002b0ea237bc8
808
+ # @accept_charset=#<Encoding:UTF-8>,
809
+ # @accept_charset_error_block=nil,
810
+ # @cookies={},
811
+ # @max_multipart_length=134217728,
812
+ # @multipart=false,
813
+ # @output_cookies=nil,
814
+ # @output_hidden=nil,
815
+ # @params={}>
816
+ #
817
+ # With hash argument +options+ given and no block given,
818
+ # returns a new \CGI object with the given options.
819
+ #
820
+ # The options may be:
821
+ #
822
+ # - <tt>accept_charset: _encoding_</tt>:
823
+ # specifies the encoding of the received query string.
824
+ #
825
+ # Value _encoding_ may be
826
+ # an {Encoding object}[https://docs.ruby-lang.org/en/master/encodings_rdoc.html#label-Encoding+Objects]
827
+ # or an {encoding name}[https://docs.ruby-lang.org/en/master/encodings_rdoc.html#label-Names+and+Aliases]:
828
+ #
829
+ # CGI.new(accept_charset: 'EUC-JP')
830
+ #
831
+ # If the option is not given,
832
+ # the default value is the class default encoding.
833
+ #
834
+ # <em>Note:</em> The <tt>accept_charset</tt> method returns the HTTP Accept-Charset
835
+ # header value, not the configured encoding. The configured encoding is used
836
+ # internally for query string parsing.
837
+ #
838
+ # - <tt>max_multipart_length: _size_</tt>:
839
+ # specifies maximum size (in bytes) of multipart data.
840
+ #
841
+ # The _size_ may be:
842
+ #
843
+ # - A positive integer.
844
+ #
845
+ # CGI.new(max_multipart_length: 1024 * 1024)
846
+ #
847
+ #
848
+ # - A lambda to be evaluated when the request is parsed.
849
+ # This is useful when determining whether to accept multipart data
850
+ # (e.g. by consulting a registered user's upload allowance).
851
+ #
852
+ # CGI.new(max_multipart_length: -> {check_filesystem})
853
+ #
854
+ # If the option is not given, the default is +134217728+, specifying a maximum size of 128 megabytes.
855
+ #
856
+ # <em>Note:</em> This option configures internal behavior only.
857
+ # There is no public method to retrieve this value after initialization.
858
+ #
859
+ # - <tt>tag_maker: _html_version_</tt>:
860
+ # specifies which version of HTML to use in generating tags.
861
+ #
862
+ # Value _html_version_ may be one of:
863
+ #
864
+ # - <tt>'html3'</tt>: {HTML version 3}[https://en.wikipedia.org/wiki/HTML#HTML_3].
865
+ # - <tt>'html4'</tt>: {HTML version 4}[https://en.wikipedia.org/wiki/HTML#HTML_4].
866
+ # - <tt>'html4Tr'</tt>: HTML 4.0 Transitional.
867
+ # - <tt>'html4Fr'</tt>: HTML 4.0 with Framesets.
868
+ # - <tt>'html5'</tt>: {HTML version 5}[https://en.wikipedia.org/wiki/HTML#HTML_5].
786
869
  #
870
+ # Example:
787
871
  #
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:
872
+ # CGI.new(tag_maker: 'html5')
795
873
  #
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.
874
+ # If the option is not given,
875
+ # no HTML generation methods are loaded.
800
876
  #
801
- # Example. Suppose <tt>@@accept_charset</tt> is "UTF-8"
877
+ # With string argument +tag_maker+ given as _tag_maker_ and no block given,
878
+ # equivalent to <tt>CGI.new(tag_maker: _tag_maker_)</tt>:
802
879
  #
803
- # when not specified:
880
+ # CGI.new('html5')
804
881
  #
805
- # cgi=CGI.new # @accept_charset # => "UTF-8"
882
+ # <b>Outside a Standard Call Environment</b>
806
883
  #
807
- # when specified as "EUC-JP":
884
+ # This section assumes that <tt>ENV['REQUEST_METHOD']</tt> is not defined;
885
+ # for example:
808
886
  #
809
- # cgi=CGI.new(:accept_charset => "EUC-JP") # => "EUC-JP"
887
+ # ENV['REQUEST_METHOD'] # => nil
810
888
  #
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.
889
+ # In this mode, the method reads its parameters
890
+ # from the command line or (failing that) from standard input;
891
+ # returns a new \CGI object.
814
892
  #
815
- # The following values are supported:
893
+ # Otherwise, cookies and other parameters are parsed automatically from the standard CGI locations,
894
+ # which vary according to the request method.
816
895
  #
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
896
+ # <b>Options vs Public Methods</b>
822
897
  #
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)
898
+ # Some initialization options configure internal behavior only and do not provide
899
+ # corresponding public getter methods:
828
900
  #
829
- # Default is 128 * 1024 * 1024 bytes
901
+ # - <tt>accept_charset</tt>: Configures internal encoding for parsing.
902
+ # The <tt>accept_charset</tt> method returns the HTTP Accept-Charset header.
903
+ # - <tt>max_multipart_length</tt>: Configures internal multipart size limits.
904
+ # No public getter method is available.
905
+ # - <tt>tag_maker</tt>: Loads HTML generation methods (publicly accessible).
830
906
  #
831
- # cgi=CGI.new(:max_multipart_length => 268435456) # simple scalar
907
+ # <b>Block</b>
832
908
  #
833
- # cgi=CGI.new(:max_multipart_length => -> {check_filesystem}) # lambda
909
+ # If a block is given, its code is stored as a Proc;
910
+ # whenever CGI::InvalidEncoding would be raised, the proc is called instead.
834
911
  #
835
- # <tt>block</tt>::
836
- # If provided, the block is called when an invalid encoding is
837
- # encountered. For example:
912
+ # In this example, the proc simply saves the error:
838
913
  #
839
- # encoding_errors={}
840
- # cgi=CGI.new(:accept_charset=>"EUC-JP") do |name,value|
841
- # encoding_errors[name] = value
842
- # end
914
+ # encoding_errors={}
915
+ # CGI.new(accept_charset: 'EUC-JP') do |name,value|
916
+ # encoding_errors[name] = value
917
+ # end
918
+ # # =>
919
+ # #<CGI:0x000002b0ec11bcd8
920
+ # @accept_charset="EUC-JP",
921
+ # @accept_charset_error_block=#<Proc:0x000002b0ed2ee190 (irb):146>,
922
+ # @cookies={},
923
+ # @max_multipart_length=134217728,
924
+ # @multipart=false,
925
+ # @options={accept_charset: "EUC-JP", max_multipart_length: 134217728},
926
+ # @output_cookies=nil,
927
+ # @output_hidden=nil,
928
+ # @params={}>
843
929
  #
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
930
  def initialize(options = {}, &block) # :yields: name, value
851
931
  @accept_charset_error_block = block_given? ? block : nil
852
932
  @options={
data/lib/cgi/escape.rb ADDED
@@ -0,0 +1,228 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :stopdoc
4
+ class CGI
5
+ module Escape; end
6
+ include Escape
7
+ extend Escape
8
+ module EscapeExt; end # :nodoc:
9
+ end
10
+ # :startdoc:
11
+
12
+ # Escape/unescape for CGI, HTML, URI.
13
+ module CGI::Escape
14
+ @@accept_charset = Encoding::UTF_8 unless defined?(@@accept_charset)
15
+
16
+ # URL-encode a string into application/x-www-form-urlencoded.
17
+ # Space characters (+" "+) are encoded with plus signs (+"+"+)
18
+ # url_encoded_string = CGI.escape("'Stop!' said Fred")
19
+ # # => "%27Stop%21%27+said+Fred"
20
+ def escape(string)
21
+ encoding = string.encoding
22
+ buffer = string.b
23
+ buffer.gsub!(/([^ a-zA-Z0-9_.\-~]+)/) do |m|
24
+ '%' + m.unpack('H2' * m.bytesize).join('%').upcase
25
+ end
26
+ buffer.tr!(' ', '+')
27
+ buffer.force_encoding(encoding)
28
+ end
29
+
30
+ # URL-decode an application/x-www-form-urlencoded string with encoding(optional).
31
+ # string = CGI.unescape("%27Stop%21%27+said+Fred")
32
+ # # => "'Stop!' said Fred"
33
+ def unescape(string, encoding = @@accept_charset)
34
+ str = string.tr('+', ' ')
35
+ str = str.b
36
+ str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m|
37
+ [m.delete('%')].pack('H*')
38
+ end
39
+ str.force_encoding(encoding)
40
+ str.valid_encoding? ? str : str.force_encoding(string.encoding)
41
+ end
42
+
43
+ # URL-encode a string following RFC 3986
44
+ # Space characters (+" "+) are encoded with (+"%20"+)
45
+ # url_encoded_string = CGI.escapeURIComponent("'Stop!' said Fred")
46
+ # # => "%27Stop%21%27%20said%20Fred"
47
+ def escapeURIComponent(string)
48
+ encoding = string.encoding
49
+ buffer = string.b
50
+ buffer.gsub!(/([^a-zA-Z0-9_.\-~]+)/) do |m|
51
+ '%' + m.unpack('H2' * m.bytesize).join('%').upcase
52
+ end
53
+ buffer.force_encoding(encoding)
54
+ end
55
+ alias escape_uri_component escapeURIComponent
56
+
57
+ # URL-decode a string following RFC 3986 with encoding(optional).
58
+ # string = CGI.unescapeURIComponent("%27Stop%21%27+said%20Fred")
59
+ # # => "'Stop!'+said Fred"
60
+ def unescapeURIComponent(string, encoding = @@accept_charset)
61
+ str = string.b
62
+ str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m|
63
+ [m.delete('%')].pack('H*')
64
+ end
65
+ str.force_encoding(encoding)
66
+ str.valid_encoding? ? str : str.force_encoding(string.encoding)
67
+ end
68
+
69
+ alias unescape_uri_component unescapeURIComponent
70
+
71
+ # The set of special characters and their escaped values
72
+ TABLE_FOR_ESCAPE_HTML__ = {
73
+ "'" => '&#39;',
74
+ '&' => '&amp;',
75
+ '"' => '&quot;',
76
+ '<' => '&lt;',
77
+ '>' => '&gt;',
78
+ }
79
+
80
+ # Escape special characters in HTML, namely '&\"<>
81
+ # CGI.escapeHTML('Usage: foo "bar" <baz>')
82
+ # # => "Usage: foo &quot;bar&quot; &lt;baz&gt;"
83
+ def escapeHTML(string)
84
+ enc = string.encoding
85
+ unless enc.ascii_compatible?
86
+ if enc.dummy?
87
+ origenc = enc
88
+ enc = Encoding::Converter.asciicompat_encoding(enc)
89
+ string = enc ? string.encode(enc) : string.b
90
+ end
91
+ table = Hash[TABLE_FOR_ESCAPE_HTML__.map {|pair|pair.map {|s|s.encode(enc)}}]
92
+ string = string.gsub(/#{"['&\"<>]".encode(enc)}/, table)
93
+ string.encode!(origenc) if origenc
94
+ string
95
+ else
96
+ string = string.b
97
+ string.gsub!(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__)
98
+ string.force_encoding(enc)
99
+ end
100
+ end
101
+
102
+ # Unescape a string that has been HTML-escaped
103
+ # CGI.unescapeHTML("Usage: foo &quot;bar&quot; &lt;baz&gt;")
104
+ # # => "Usage: foo \"bar\" <baz>"
105
+ def unescapeHTML(string)
106
+ enc = string.encoding
107
+ unless enc.ascii_compatible?
108
+ if enc.dummy?
109
+ origenc = enc
110
+ enc = Encoding::Converter.asciicompat_encoding(enc)
111
+ string = enc ? string.encode(enc) : string.b
112
+ end
113
+ string = string.gsub(Regexp.new('&(apos|amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do
114
+ case $1.encode(Encoding::US_ASCII)
115
+ when 'apos' then "'".encode(enc)
116
+ when 'amp' then '&'.encode(enc)
117
+ when 'quot' then '"'.encode(enc)
118
+ when 'gt' then '>'.encode(enc)
119
+ when 'lt' then '<'.encode(enc)
120
+ when /\A#0*(\d+)\z/ then $1.to_i.chr(enc)
121
+ when /\A#x([0-9a-f]+)\z/i then $1.hex.chr(enc)
122
+ end
123
+ end
124
+ string.encode!(origenc) if origenc
125
+ return string
126
+ end
127
+ return string unless string.include? '&'
128
+ charlimit = case enc
129
+ when Encoding::UTF_8; 0x10ffff
130
+ when Encoding::ISO_8859_1; 256
131
+ else 128
132
+ end
133
+ string = string.b
134
+ string.gsub!(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do
135
+ match = $1.dup
136
+ case match
137
+ when 'apos' then "'"
138
+ when 'amp' then '&'
139
+ when 'quot' then '"'
140
+ when 'gt' then '>'
141
+ when 'lt' then '<'
142
+ when /\A#0*(\d+)\z/
143
+ n = $1.to_i
144
+ if n < charlimit
145
+ n.chr(enc)
146
+ else
147
+ "&##{$1};"
148
+ end
149
+ when /\A#x([0-9a-f]+)\z/i
150
+ n = $1.hex
151
+ if n < charlimit
152
+ n.chr(enc)
153
+ else
154
+ "&#x#{$1};"
155
+ end
156
+ else
157
+ "&#{match};"
158
+ end
159
+ end
160
+ string.force_encoding enc
161
+ end
162
+
163
+ # Synonym for CGI.escapeHTML(str)
164
+ alias escape_html escapeHTML
165
+ alias h escapeHTML
166
+
167
+ # Synonym for CGI.unescapeHTML(str)
168
+ alias unescape_html unescapeHTML
169
+
170
+ # TruffleRuby runs the pure-Ruby variant faster, do not use the C extension there
171
+ unless RUBY_ENGINE == 'truffleruby'
172
+ begin
173
+ require 'cgi/escape.so'
174
+ rescue LoadError
175
+ end
176
+ end
177
+
178
+ # Escape only the tags of certain HTML elements in +string+.
179
+ #
180
+ # Takes an element or elements or array of elements. Each element
181
+ # is specified by the name of the element, without angle brackets.
182
+ # This matches both the start and the end tag of that element.
183
+ # The attribute list of the open tag will also be escaped (for
184
+ # instance, the double-quotes surrounding attribute values).
185
+ #
186
+ # print CGI.escapeElement('<BR><A HREF="url"></A>', "A", "IMG")
187
+ # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
188
+ #
189
+ # print CGI.escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"])
190
+ # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
191
+ def escapeElement(string, *elements)
192
+ elements = elements[0] if elements[0].kind_of?(Array)
193
+ unless elements.empty?
194
+ string.gsub(/<\/?(?:#{elements.join("|")})\b[^<>]*+>?/im) do
195
+ CGI.escapeHTML($&)
196
+ end
197
+ else
198
+ string
199
+ end
200
+ end
201
+
202
+ # Undo escaping such as that done by CGI.escapeElement()
203
+ #
204
+ # print CGI.unescapeElement(
205
+ # CGI.escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG")
206
+ # # "&lt;BR&gt;<A HREF="url"></A>"
207
+ #
208
+ # print CGI.unescapeElement(
209
+ # CGI.escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])
210
+ # # "&lt;BR&gt;<A HREF="url"></A>"
211
+ def unescapeElement(string, *elements)
212
+ elements = elements[0] if elements[0].kind_of?(Array)
213
+ unless elements.empty?
214
+ string.gsub(/&lt;\/?(?:#{elements.join("|")})\b(?>[^&]+|&(?![gl]t;)\w+;)*(?:&gt;)?/im) do
215
+ unescapeHTML($&)
216
+ end
217
+ else
218
+ string
219
+ end
220
+ end
221
+
222
+ # Synonym for CGI.escapeElement(str)
223
+ alias escape_element escapeElement
224
+
225
+ # Synonym for CGI.unescapeElement(str)
226
+ alias unescape_element unescapeElement
227
+
228
+ end
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
@@ -214,11 +214,11 @@ class CGI
214
214
  dir = option['tmpdir'] || Dir::tmpdir
215
215
  prefix = option['prefix']
216
216
  suffix = option['suffix']
217
- require 'digest/md5'
218
- md5 = Digest::MD5.hexdigest(session_id)[0,16]
217
+ require 'digest'
218
+ sha256 = Digest::SHA256.hexdigest(session_id)[0,16]
219
219
  path = dir+"/"
220
220
  path << prefix if prefix
221
- path << md5
221
+ path << sha256
222
222
  path << suffix if suffix
223
223
  if File::exist? path
224
224
  hash = nil
data/lib/cgi/util.rb CHANGED
@@ -4,220 +4,9 @@ class CGI
4
4
  include Util
5
5
  extend Util
6
6
  end
7
- module CGI::Util
8
- @@accept_charset = Encoding::UTF_8 unless defined?(@@accept_charset)
9
-
10
- # URL-encode a string into application/x-www-form-urlencoded.
11
- # Space characters (+" "+) are encoded with plus signs (+"+"+)
12
- # url_encoded_string = CGI.escape("'Stop!' said Fred")
13
- # # => "%27Stop%21%27+said+Fred"
14
- def escape(string)
15
- encoding = string.encoding
16
- buffer = string.b
17
- buffer.gsub!(/([^ a-zA-Z0-9_.\-~]+)/) do |m|
18
- '%' + m.unpack('H2' * m.bytesize).join('%').upcase
19
- end
20
- buffer.tr!(' ', '+')
21
- buffer.force_encoding(encoding)
22
- end
23
-
24
- # URL-decode an application/x-www-form-urlencoded string with encoding(optional).
25
- # string = CGI.unescape("%27Stop%21%27+said+Fred")
26
- # # => "'Stop!' said Fred"
27
- def unescape(string, encoding = @@accept_charset)
28
- str = string.tr('+', ' ')
29
- str = str.b
30
- str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m|
31
- [m.delete('%')].pack('H*')
32
- end
33
- str.force_encoding(encoding)
34
- str.valid_encoding? ? str : str.force_encoding(string.encoding)
35
- end
36
-
37
- # URL-encode a string following RFC 3986
38
- # Space characters (+" "+) are encoded with (+"%20"+)
39
- # url_encoded_string = CGI.escapeURIComponent("'Stop!' said Fred")
40
- # # => "%27Stop%21%27%20said%20Fred"
41
- def escapeURIComponent(string)
42
- encoding = string.encoding
43
- buffer = string.b
44
- buffer.gsub!(/([^a-zA-Z0-9_.\-~]+)/) do |m|
45
- '%' + m.unpack('H2' * m.bytesize).join('%').upcase
46
- end
47
- buffer.force_encoding(encoding)
48
- end
49
- alias escape_uri_component escapeURIComponent
50
-
51
- # URL-decode a string following RFC 3986 with encoding(optional).
52
- # string = CGI.unescapeURIComponent("%27Stop%21%27+said%20Fred")
53
- # # => "'Stop!'+said Fred"
54
- def unescapeURIComponent(string, encoding = @@accept_charset)
55
- str = string.b
56
- str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m|
57
- [m.delete('%')].pack('H*')
58
- end
59
- str.force_encoding(encoding)
60
- str.valid_encoding? ? str : str.force_encoding(string.encoding)
61
- end
62
-
63
- alias unescape_uri_component unescapeURIComponent
64
-
65
- # The set of special characters and their escaped values
66
- TABLE_FOR_ESCAPE_HTML__ = {
67
- "'" => '&#39;',
68
- '&' => '&amp;',
69
- '"' => '&quot;',
70
- '<' => '&lt;',
71
- '>' => '&gt;',
72
- }
73
-
74
- # Escape special characters in HTML, namely '&\"<>
75
- # CGI.escapeHTML('Usage: foo "bar" <baz>')
76
- # # => "Usage: foo &quot;bar&quot; &lt;baz&gt;"
77
- def escapeHTML(string)
78
- enc = string.encoding
79
- unless enc.ascii_compatible?
80
- if enc.dummy?
81
- origenc = enc
82
- enc = Encoding::Converter.asciicompat_encoding(enc)
83
- string = enc ? string.encode(enc) : string.b
84
- end
85
- table = Hash[TABLE_FOR_ESCAPE_HTML__.map {|pair|pair.map {|s|s.encode(enc)}}]
86
- string = string.gsub(/#{"['&\"<>]".encode(enc)}/, table)
87
- string.encode!(origenc) if origenc
88
- string
89
- else
90
- string = string.b
91
- string.gsub!(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__)
92
- string.force_encoding(enc)
93
- end
94
- end
95
-
96
- # TruffleRuby runs the pure-Ruby variant faster, do not use the C extension there
97
- unless RUBY_ENGINE == 'truffleruby'
98
- begin
99
- require 'cgi/escape'
100
- rescue LoadError
101
- end
102
- end
103
-
104
- # Unescape a string that has been HTML-escaped
105
- # CGI.unescapeHTML("Usage: foo &quot;bar&quot; &lt;baz&gt;")
106
- # # => "Usage: foo \"bar\" <baz>"
107
- def unescapeHTML(string)
108
- enc = string.encoding
109
- unless enc.ascii_compatible?
110
- if enc.dummy?
111
- origenc = enc
112
- enc = Encoding::Converter.asciicompat_encoding(enc)
113
- string = enc ? string.encode(enc) : string.b
114
- end
115
- string = string.gsub(Regexp.new('&(apos|amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do
116
- case $1.encode(Encoding::US_ASCII)
117
- when 'apos' then "'".encode(enc)
118
- when 'amp' then '&'.encode(enc)
119
- when 'quot' then '"'.encode(enc)
120
- when 'gt' then '>'.encode(enc)
121
- when 'lt' then '<'.encode(enc)
122
- when /\A#0*(\d+)\z/ then $1.to_i.chr(enc)
123
- when /\A#x([0-9a-f]+)\z/i then $1.hex.chr(enc)
124
- end
125
- end
126
- string.encode!(origenc) if origenc
127
- return string
128
- end
129
- return string unless string.include? '&'
130
- charlimit = case enc
131
- when Encoding::UTF_8; 0x10ffff
132
- when Encoding::ISO_8859_1; 256
133
- else 128
134
- end
135
- string = string.b
136
- string.gsub!(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do
137
- match = $1.dup
138
- case match
139
- when 'apos' then "'"
140
- when 'amp' then '&'
141
- when 'quot' then '"'
142
- when 'gt' then '>'
143
- when 'lt' then '<'
144
- when /\A#0*(\d+)\z/
145
- n = $1.to_i
146
- if n < charlimit
147
- n.chr(enc)
148
- else
149
- "&##{$1};"
150
- end
151
- when /\A#x([0-9a-f]+)\z/i
152
- n = $1.hex
153
- if n < charlimit
154
- n.chr(enc)
155
- else
156
- "&#x#{$1};"
157
- end
158
- else
159
- "&#{match};"
160
- end
161
- end
162
- string.force_encoding enc
163
- end
164
-
165
- # Synonym for CGI.escapeHTML(str)
166
- alias escape_html escapeHTML
167
-
168
- # Synonym for CGI.unescapeHTML(str)
169
- alias unescape_html unescapeHTML
170
-
171
- # Escape only the tags of certain HTML elements in +string+.
172
- #
173
- # Takes an element or elements or array of elements. Each element
174
- # is specified by the name of the element, without angle brackets.
175
- # This matches both the start and the end tag of that element.
176
- # The attribute list of the open tag will also be escaped (for
177
- # instance, the double-quotes surrounding attribute values).
178
- #
179
- # print CGI.escapeElement('<BR><A HREF="url"></A>', "A", "IMG")
180
- # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
181
- #
182
- # print CGI.escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"])
183
- # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
184
- def escapeElement(string, *elements)
185
- elements = elements[0] if elements[0].kind_of?(Array)
186
- unless elements.empty?
187
- string.gsub(/<\/?(?:#{elements.join("|")})\b[^<>]*+>?/im) do
188
- CGI.escapeHTML($&)
189
- end
190
- else
191
- string
192
- end
193
- end
194
-
195
- # Undo escaping such as that done by CGI.escapeElement()
196
- #
197
- # print CGI.unescapeElement(
198
- # CGI.escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG")
199
- # # "&lt;BR&gt;<A HREF="url"></A>"
200
- #
201
- # print CGI.unescapeElement(
202
- # CGI.escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])
203
- # # "&lt;BR&gt;<A HREF="url"></A>"
204
- def unescapeElement(string, *elements)
205
- elements = elements[0] if elements[0].kind_of?(Array)
206
- unless elements.empty?
207
- string.gsub(/&lt;\/?(?:#{elements.join("|")})\b(?>[^&]+|&(?![gl]t;)\w+;)*(?:&gt;)?/im) do
208
- unescapeHTML($&)
209
- end
210
- else
211
- string
212
- end
213
- end
214
-
215
- # Synonym for CGI.escapeElement(str)
216
- alias escape_element escapeElement
217
-
218
- # Synonym for CGI.unescapeElement(str)
219
- alias unescape_element unescapeElement
220
7
 
8
+ # Utility methods for CGI.
9
+ module CGI::Util
221
10
  # Format a +Time+ object as a String using the format specified by RFC 1123.
222
11
  #
223
12
  # CGI.rfc1123_date(Time.now)
@@ -253,6 +42,7 @@ module CGI::Util
253
42
  end
254
43
  lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/, '\1')
255
44
  end
256
-
257
- alias h escapeHTML
258
45
  end
46
+
47
+ # For backward compatibility
48
+ require 'cgi/escape' unless defined?(CGI::EscapeExt)
data/lib/cgi.rb CHANGED
@@ -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
@@ -144,62 +155,66 @@
144
155
  #
145
156
  # === Utility HTML escape and other methods like a function.
146
157
  #
147
- # There are some utility tool defined in cgi/util.rb .
158
+ # There are some utility tools defined in cgi/util.rb and cgi/escape.rb.
159
+ # Escape and unescape methods are defined in cgi/escape.rb.
148
160
  # And when include, you can use utility methods like a function.
149
161
  #
150
- # == Examples of use
162
+ # == Examples of Use
151
163
  #
152
- # === Get form values
164
+ # === Form Values
153
165
  #
154
- # require "cgi"
155
- # cgi = CGI.new
156
- # value = cgi['field_name'] # <== value string for 'field_name'
157
- # # if not 'field_name' included, then return "".
158
- # fields = cgi.keys # <== array of field names
159
- #
160
- # # returns true if form has 'field_name'
161
- # cgi.has_key?('field_name')
162
- # cgi.has_key?('field_name')
163
- # cgi.include?('field_name')
164
- #
165
- # CAUTION! <code>cgi['field_name']</code> returned an Array with the old
166
- # cgi.rb(included in Ruby 1.6)
166
+ # ==== Get Form Values
167
167
  #
168
- # === Get form values as hash
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]:
169
170
  #
170
- # require "cgi"
171
+ # ENV.update(
172
+ # 'REQUEST_METHOD' => 'GET',
173
+ # 'QUERY_STRING' => 'a=111&&b=222&c&d='
174
+ # )
171
175
  # cgi = CGI.new
172
- # params = cgi.params
173
- #
174
- # cgi.params is a hash.
175
- #
176
- # cgi.params['new_field_name'] = ["value"] # add new param
177
- # cgi.params['field_name'] = ["new_value"] # change value
178
- # cgi.params.delete('field_name') # delete param
179
- # cgi.params.clear # delete all params
180
- #
181
- #
182
- # === Save form values to file
183
- #
184
- # require "pstore"
185
- # db = PStore.new("query.db")
186
- # db.transaction do
187
- # 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
188
209
  # end
189
- #
190
- #
191
- # === Restore form values from file
192
- #
193
- # require "pstore"
194
- # db = PStore.new("query.db")
195
- # db.transaction do
196
- # cgi.params = db["params"]
210
+ # cgi.params.clear # Oops! Lost my params!
211
+ # store.transaction do
212
+ # cgi.params = store['params']
197
213
  # end
214
+ # cgi.params # => {"a" => ["111"], "b" => ["222"], "c" => [], "d" => [""]}
198
215
  #
216
+ # ==== Get multipart form values
199
217
  #
200
- # === Get multipart form values
201
- #
202
- # require "cgi"
203
218
  # cgi = CGI.new
204
219
  # value = cgi['field_name'] # <== value string for 'field_name'
205
220
  # value.read # <== body of value
@@ -211,7 +226,6 @@
211
226
  #
212
227
  # === Get cookie values
213
228
  #
214
- # require "cgi"
215
229
  # cgi = CGI.new
216
230
  # values = cgi.cookies['name'] # <== array of 'name'
217
231
  # # if not 'name' included, then return [].
@@ -221,7 +235,6 @@
221
235
  #
222
236
  # === Get cookie objects
223
237
  #
224
- # require "cgi"
225
238
  # cgi = CGI.new
226
239
  # for name, cookie in cgi.cookies
227
240
  # cookie.expires = Time.now + 30
@@ -230,14 +243,12 @@
230
243
  #
231
244
  # cgi.cookies # { "name1" => cookie1, "name2" => cookie2, ... }
232
245
  #
233
- # require "cgi"
234
246
  # cgi = CGI.new
235
247
  # cgi.cookies['name'].expires = Time.now + 30
236
248
  # cgi.out("cookie" => cgi.cookies['name']) {"string"}
237
249
  #
238
250
  # === Print http header and html string to $DEFAULT_OUTPUT ($>)
239
251
  #
240
- # require "cgi"
241
252
  # cgi = CGI.new("html4") # add HTML generation methods
242
253
  # cgi.out do
243
254
  # cgi.html do
@@ -274,24 +285,26 @@
274
285
  #
275
286
  # === Some utility methods
276
287
  #
277
- # require 'cgi/util'
288
+ # require 'cgi/escape'
278
289
  # CGI.escapeHTML('Usage: foo "bar" <baz>')
279
290
  #
280
291
  #
281
292
  # === Some utility methods like a function
282
293
  #
283
- # require 'cgi/util'
284
- # include CGI::Util
294
+ # require 'cgi/escape'
295
+ # include CGI::Escape
285
296
  # escapeHTML('Usage: foo "bar" <baz>')
286
297
  # h('Usage: foo "bar" <baz>') # alias
287
298
  #
288
299
  #
289
300
 
290
301
  class CGI
291
- VERSION = "0.4.2"
302
+ # The version string
303
+ VERSION = "0.5.1"
292
304
  end
293
305
 
306
+ require 'cgi/util'
307
+ require 'cgi/escape' unless defined?(CGI::EscapeExt)
294
308
  require 'cgi/core'
295
309
  require 'cgi/cookie'
296
- require 'cgi/util'
297
310
  CGI.autoload(:HtmlExtension, 'cgi/html')
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cgi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yukihiro Matsumoto
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-02-26 00:00:00.000000000 Z
10
+ date: 2025-12-10 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: Support for the Common Gateway Interface protocol.
14
13
  email:
@@ -27,6 +26,7 @@ files:
27
26
  - lib/cgi.rb
28
27
  - lib/cgi/cookie.rb
29
28
  - lib/cgi/core.rb
29
+ - lib/cgi/escape.rb
30
30
  - lib/cgi/html.rb
31
31
  - lib/cgi/session.rb
32
32
  - lib/cgi/session/pstore.rb
@@ -38,7 +38,6 @@ licenses:
38
38
  metadata:
39
39
  homepage_uri: https://github.com/ruby/cgi
40
40
  source_code_uri: https://github.com/ruby/cgi
41
- post_install_message:
42
41
  rdoc_options: []
43
42
  require_paths:
44
43
  - lib
@@ -53,8 +52,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
53
52
  - !ruby/object:Gem::Version
54
53
  version: '0'
55
54
  requirements: []
56
- rubygems_version: 3.5.11
57
- signing_key:
55
+ rubygems_version: 3.6.7
58
56
  specification_version: 4
59
57
  summary: Support for the Common Gateway Interface protocol.
60
58
  test_files: []