cgi 0.3.2 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 670bbf0eb15455e6020b95c0ca39481adb722eb4bb60fc797761b66a8f19af81
4
- data.tar.gz: 9e360fdb4a408678f9edda5d3a8035e0bf05e087c946593cbac13d21d22f1998
3
+ metadata.gz: 8ce6875af13620a6db03d330d999d439a8a123d202441f244cfb1384881c3f29
4
+ data.tar.gz: 7c63c709fd47c6f9354d27e90e9154128e5fb3dc4db3460c89d68efd619f2d53
5
5
  SHA512:
6
- metadata.gz: 4115408aa6f5dc3f17b638d9e7fc1ba0e10d4d84172910558c7d01e5ae2bf79fa198111dbd137d1602d2cb8299ae98961ae66f0aaf93bc0cf09912b3565bb664
7
- data.tar.gz: 0e47613d0b6677a7062a87e6b07c7cefe3957d02fb74ed8c385ad0671146eafb0d26ec9efa29cf619b5e30a45b0c0b2bc259161a66b9dc3f778e5699806ad17a
6
+ metadata.gz: 917d92a7163be187b32a5b8584a0f6db25373af60129633038dacbfdaa653b95219af6c657102613d871945d7abd54c06cdbcccb79640f3a7cc85ec6cbcb2c16
7
+ data.tar.gz: c3d26461f58ce39fc85afd3c9889b38a4382fa15cdd22b05283947b0e5bca35e507285cfe2f8f6c1ed34545ccdcf0adc930f2278568028211b4df21d2120fcdb
@@ -37,7 +37,7 @@ escaped_length(VALUE str)
37
37
  {
38
38
  const long len = RSTRING_LEN(str);
39
39
  if (len >= LONG_MAX / HTML_ESCAPE_MAX_LEN) {
40
- ruby_malloc_size_overflow(len, HTML_ESCAPE_MAX_LEN);
40
+ ruby_malloc_size_overflow(len, HTML_ESCAPE_MAX_LEN);
41
41
  }
42
42
  return len * HTML_ESCAPE_MAX_LEN;
43
43
  }
@@ -81,8 +81,8 @@ optimized_unescape_html(VALUE str)
81
81
  enum {UNICODE_MAX = 0x10ffff};
82
82
  rb_encoding *enc = rb_enc_get(str);
83
83
  unsigned long charlimit = (strcasecmp(rb_enc_name(enc), "UTF-8") == 0 ? UNICODE_MAX :
84
- strcasecmp(rb_enc_name(enc), "ISO-8859-1") == 0 ? 256 :
85
- 128);
84
+ strcasecmp(rb_enc_name(enc), "ISO-8859-1") == 0 ? 256 :
85
+ 128);
86
86
  long i, len, beg = 0;
87
87
  size_t clen, plen;
88
88
  int overflow;
@@ -94,89 +94,89 @@ optimized_unescape_html(VALUE str)
94
94
  cstr = RSTRING_PTR(str);
95
95
 
96
96
  for (i = 0; i < len; i++) {
97
- unsigned long cc;
98
- char c = cstr[i];
99
- if (c != '&') continue;
100
- plen = i - beg;
101
- if (++i >= len) break;
102
- c = (unsigned char)cstr[i];
97
+ unsigned long cc;
98
+ char c = cstr[i];
99
+ if (c != '&') continue;
100
+ plen = i - beg;
101
+ if (++i >= len) break;
102
+ c = (unsigned char)cstr[i];
103
103
  #define MATCH(s) (len - i >= (int)rb_strlen_lit(s) && \
104
- memcmp(&cstr[i], s, rb_strlen_lit(s)) == 0 && \
105
- (i += rb_strlen_lit(s) - 1, 1))
106
- switch (c) {
107
- case 'a':
108
- ++i;
109
- if (MATCH("pos;")) {
110
- c = '\'';
111
- }
112
- else if (MATCH("mp;")) {
113
- c = '&';
114
- }
115
- else continue;
116
- break;
117
- case 'q':
118
- ++i;
119
- if (MATCH("uot;")) {
120
- c = '"';
121
- }
122
- else continue;
123
- break;
124
- case 'g':
125
- ++i;
126
- if (MATCH("t;")) {
127
- c = '>';
128
- }
129
- else continue;
130
- break;
131
- case 'l':
132
- ++i;
133
- if (MATCH("t;")) {
134
- c = '<';
135
- }
136
- else continue;
137
- break;
138
- case '#':
139
- if (len - ++i >= 2 && ISDIGIT(cstr[i])) {
140
- cc = ruby_scan_digits(&cstr[i], len-i, 10, &clen, &overflow);
141
- }
142
- else if ((cstr[i] == 'x' || cstr[i] == 'X') && len - ++i >= 2 && ISXDIGIT(cstr[i])) {
143
- cc = ruby_scan_digits(&cstr[i], len-i, 16, &clen, &overflow);
144
- }
145
- else continue;
146
- i += clen;
147
- if (overflow || cc >= charlimit || cstr[i] != ';') continue;
148
- if (!dest) {
149
- dest = rb_str_buf_new(len);
150
- }
151
- rb_str_cat(dest, cstr + beg, plen);
152
- if (charlimit > 256) {
153
- rb_str_cat(dest, buf, rb_enc_mbcput((OnigCodePoint)cc, buf, enc));
154
- }
155
- else {
156
- c = (unsigned char)cc;
157
- rb_str_cat(dest, &c, 1);
158
- }
159
- beg = i + 1;
160
- continue;
161
- default:
162
- --i;
163
- continue;
164
- }
165
- if (!dest) {
166
- dest = rb_str_buf_new(len);
167
- }
168
- rb_str_cat(dest, cstr + beg, plen);
169
- rb_str_cat(dest, &c, 1);
170
- beg = i + 1;
104
+ memcmp(&cstr[i], s, rb_strlen_lit(s)) == 0 && \
105
+ (i += rb_strlen_lit(s) - 1, 1))
106
+ switch (c) {
107
+ case 'a':
108
+ ++i;
109
+ if (MATCH("pos;")) {
110
+ c = '\'';
111
+ }
112
+ else if (MATCH("mp;")) {
113
+ c = '&';
114
+ }
115
+ else continue;
116
+ break;
117
+ case 'q':
118
+ ++i;
119
+ if (MATCH("uot;")) {
120
+ c = '"';
121
+ }
122
+ else continue;
123
+ break;
124
+ case 'g':
125
+ ++i;
126
+ if (MATCH("t;")) {
127
+ c = '>';
128
+ }
129
+ else continue;
130
+ break;
131
+ case 'l':
132
+ ++i;
133
+ if (MATCH("t;")) {
134
+ c = '<';
135
+ }
136
+ else continue;
137
+ break;
138
+ case '#':
139
+ if (len - ++i >= 2 && ISDIGIT(cstr[i])) {
140
+ cc = ruby_scan_digits(&cstr[i], len-i, 10, &clen, &overflow);
141
+ }
142
+ else if ((cstr[i] == 'x' || cstr[i] == 'X') && len - ++i >= 2 && ISXDIGIT(cstr[i])) {
143
+ cc = ruby_scan_digits(&cstr[i], len-i, 16, &clen, &overflow);
144
+ }
145
+ else continue;
146
+ i += clen;
147
+ if (overflow || cc >= charlimit || cstr[i] != ';') continue;
148
+ if (!dest) {
149
+ dest = rb_str_buf_new(len);
150
+ }
151
+ rb_str_cat(dest, cstr + beg, plen);
152
+ if (charlimit > 256) {
153
+ rb_str_cat(dest, buf, rb_enc_mbcput((OnigCodePoint)cc, buf, enc));
154
+ }
155
+ else {
156
+ c = (unsigned char)cc;
157
+ rb_str_cat(dest, &c, 1);
158
+ }
159
+ beg = i + 1;
160
+ continue;
161
+ default:
162
+ --i;
163
+ continue;
164
+ }
165
+ if (!dest) {
166
+ dest = rb_str_buf_new(len);
167
+ }
168
+ rb_str_cat(dest, cstr + beg, plen);
169
+ rb_str_cat(dest, &c, 1);
170
+ beg = i + 1;
171
171
  }
172
172
 
173
173
  if (dest) {
174
- rb_str_cat(dest, cstr + beg, len - beg);
175
- preserve_original_state(str, dest);
176
- return dest;
174
+ rb_str_cat(dest, cstr + beg, len - beg);
175
+ preserve_original_state(str, dest);
176
+ return dest;
177
177
  }
178
178
  else {
179
- return rb_str_dup(str);
179
+ return rb_str_dup(str);
180
180
  }
181
181
  }
182
182
 
@@ -200,7 +200,7 @@ url_unreserved_char(unsigned char c)
200
200
  }
201
201
 
202
202
  static VALUE
203
- optimized_escape(VALUE str)
203
+ optimized_escape(VALUE str, int plus_escape)
204
204
  {
205
205
  long i, len, beg = 0;
206
206
  VALUE dest = 0;
@@ -211,38 +211,38 @@ optimized_escape(VALUE str)
211
211
  cstr = RSTRING_PTR(str);
212
212
 
213
213
  for (i = 0; i < len; ++i) {
214
- const unsigned char c = (unsigned char)cstr[i];
215
- if (!url_unreserved_char(c)) {
216
- if (!dest) {
217
- dest = rb_str_buf_new(len);
218
- }
219
-
220
- rb_str_cat(dest, cstr + beg, i - beg);
221
- beg = i + 1;
222
-
223
- if (c == ' ') {
224
- rb_str_cat_cstr(dest, "+");
225
- }
226
- else {
227
- buf[1] = upper_hexdigits[(c >> 4) & 0xf];
228
- buf[2] = upper_hexdigits[c & 0xf];
229
- rb_str_cat(dest, buf, 3);
230
- }
231
- }
214
+ const unsigned char c = (unsigned char)cstr[i];
215
+ if (!url_unreserved_char(c)) {
216
+ if (!dest) {
217
+ dest = rb_str_buf_new(len);
218
+ }
219
+
220
+ rb_str_cat(dest, cstr + beg, i - beg);
221
+ beg = i + 1;
222
+
223
+ if (plus_escape && c == ' ') {
224
+ rb_str_cat_cstr(dest, "+");
225
+ }
226
+ else {
227
+ buf[1] = upper_hexdigits[(c >> 4) & 0xf];
228
+ buf[2] = upper_hexdigits[c & 0xf];
229
+ rb_str_cat(dest, buf, 3);
230
+ }
231
+ }
232
232
  }
233
233
 
234
234
  if (dest) {
235
- rb_str_cat(dest, cstr + beg, len - beg);
236
- preserve_original_state(str, dest);
237
- return dest;
235
+ rb_str_cat(dest, cstr + beg, len - beg);
236
+ preserve_original_state(str, dest);
237
+ return dest;
238
238
  }
239
239
  else {
240
- return rb_str_dup(str);
240
+ return rb_str_dup(str);
241
241
  }
242
242
  }
243
243
 
244
244
  static VALUE
245
- optimized_unescape(VALUE str, VALUE encoding)
245
+ optimized_unescape(VALUE str, VALUE encoding, int unescape_plus)
246
246
  {
247
247
  long i, len, beg = 0;
248
248
  VALUE dest = 0;
@@ -254,52 +254,52 @@ optimized_unescape(VALUE str, VALUE encoding)
254
254
  cstr = RSTRING_PTR(str);
255
255
 
256
256
  for (i = 0; i < len; ++i) {
257
- char buf[1];
258
- const char c = cstr[i];
259
- int clen = 0;
260
- if (c == '%') {
261
- if (i + 3 > len) break;
262
- if (!ISXDIGIT(cstr[i+1])) continue;
263
- if (!ISXDIGIT(cstr[i+2])) continue;
264
- buf[0] = ((char_to_number(cstr[i+1]) << 4)
265
- | char_to_number(cstr[i+2]));
266
- clen = 2;
267
- }
268
- else if (c == '+') {
269
- buf[0] = ' ';
270
- }
271
- else {
272
- continue;
273
- }
274
-
275
- if (!dest) {
276
- dest = rb_str_buf_new(len);
277
- }
278
-
279
- rb_str_cat(dest, cstr + beg, i - beg);
280
- i += clen;
281
- beg = i + 1;
282
-
283
- rb_str_cat(dest, buf, 1);
257
+ char buf[1];
258
+ const char c = cstr[i];
259
+ int clen = 0;
260
+ if (c == '%') {
261
+ if (i + 3 > len) break;
262
+ if (!ISXDIGIT(cstr[i+1])) continue;
263
+ if (!ISXDIGIT(cstr[i+2])) continue;
264
+ buf[0] = ((char_to_number(cstr[i+1]) << 4)
265
+ | char_to_number(cstr[i+2]));
266
+ clen = 2;
267
+ }
268
+ else if (unescape_plus && c == '+') {
269
+ buf[0] = ' ';
270
+ }
271
+ else {
272
+ continue;
273
+ }
274
+
275
+ if (!dest) {
276
+ dest = rb_str_buf_new(len);
277
+ }
278
+
279
+ rb_str_cat(dest, cstr + beg, i - beg);
280
+ i += clen;
281
+ beg = i + 1;
282
+
283
+ rb_str_cat(dest, buf, 1);
284
284
  }
285
285
 
286
286
  if (dest) {
287
- rb_str_cat(dest, cstr + beg, len - beg);
288
- preserve_original_state(str, dest);
289
- cr = ENC_CODERANGE_UNKNOWN;
287
+ rb_str_cat(dest, cstr + beg, len - beg);
288
+ preserve_original_state(str, dest);
289
+ cr = ENC_CODERANGE_UNKNOWN;
290
290
  }
291
291
  else {
292
- dest = rb_str_dup(str);
293
- cr = ENC_CODERANGE(str);
292
+ dest = rb_str_dup(str);
293
+ cr = ENC_CODERANGE(str);
294
294
  }
295
295
  origenc = rb_enc_get_index(str);
296
296
  if (origenc != encidx) {
297
- rb_enc_associate_index(dest, encidx);
298
- if (!ENC_CODERANGE_CLEAN_P(rb_enc_str_coderange(dest))) {
299
- rb_enc_associate_index(dest, origenc);
300
- if (cr != ENC_CODERANGE_UNKNOWN)
301
- ENC_CODERANGE_SET(dest, cr);
302
- }
297
+ rb_enc_associate_index(dest, encidx);
298
+ if (!ENC_CODERANGE_CLEAN_P(rb_enc_str_coderange(dest))) {
299
+ rb_enc_associate_index(dest, origenc);
300
+ if (cr != ENC_CODERANGE_UNKNOWN)
301
+ ENC_CODERANGE_SET(dest, cr);
302
+ }
303
303
  }
304
304
  return dest;
305
305
  }
@@ -317,10 +317,10 @@ cgiesc_escape_html(VALUE self, VALUE str)
317
317
  StringValue(str);
318
318
 
319
319
  if (rb_enc_str_asciicompat_p(str)) {
320
- return optimized_escape_html(str);
320
+ return optimized_escape_html(str);
321
321
  }
322
322
  else {
323
- return rb_call_super(1, &str);
323
+ return rb_call_super(1, &str);
324
324
  }
325
325
  }
326
326
 
@@ -337,10 +337,10 @@ cgiesc_unescape_html(VALUE self, VALUE str)
337
337
  StringValue(str);
338
338
 
339
339
  if (rb_enc_str_asciicompat_p(str)) {
340
- return optimized_unescape_html(str);
340
+ return optimized_unescape_html(str);
341
341
  }
342
342
  else {
343
- return rb_call_super(1, &str);
343
+ return rb_call_super(1, &str);
344
344
  }
345
345
  }
346
346
 
@@ -348,7 +348,7 @@ cgiesc_unescape_html(VALUE self, VALUE str)
348
348
  * call-seq:
349
349
  * CGI.escape(string) -> string
350
350
  *
351
- * Returns URL-escaped string.
351
+ * Returns URL-escaped string (+application/x-www-form-urlencoded+).
352
352
  *
353
353
  */
354
354
  static VALUE
@@ -357,10 +357,10 @@ cgiesc_escape(VALUE self, VALUE str)
357
357
  StringValue(str);
358
358
 
359
359
  if (rb_enc_str_asciicompat_p(str)) {
360
- return optimized_escape(str);
360
+ return optimized_escape(str, 1);
361
361
  }
362
362
  else {
363
- return rb_call_super(1, &str);
363
+ return rb_call_super(1, &str);
364
364
  }
365
365
  }
366
366
 
@@ -368,7 +368,7 @@ static VALUE
368
368
  accept_charset(int argc, VALUE *argv, VALUE self)
369
369
  {
370
370
  if (argc > 0)
371
- return argv[0];
371
+ return argv[0];
372
372
  return rb_cvar_get(CLASS_OF(self), id_accept_charset);
373
373
  }
374
374
 
@@ -376,7 +376,7 @@ accept_charset(int argc, VALUE *argv, VALUE self)
376
376
  * call-seq:
377
377
  * CGI.unescape(string, encoding=@@accept_charset) -> string
378
378
  *
379
- * Returns URL-unescaped string.
379
+ * Returns URL-unescaped string (+application/x-www-form-urlencoded+).
380
380
  *
381
381
  */
382
382
  static VALUE
@@ -387,11 +387,54 @@ cgiesc_unescape(int argc, VALUE *argv, VALUE self)
387
387
  StringValue(str);
388
388
 
389
389
  if (rb_enc_str_asciicompat_p(str)) {
390
- VALUE enc = accept_charset(argc-1, argv+1, self);
391
- return optimized_unescape(str, enc);
390
+ VALUE enc = accept_charset(argc-1, argv+1, self);
391
+ return optimized_unescape(str, enc, 1);
392
+ }
393
+ else {
394
+ return rb_call_super(argc, argv);
395
+ }
396
+ }
397
+
398
+ /*
399
+ * call-seq:
400
+ * CGI.escapeURIComponent(string) -> string
401
+ *
402
+ * Returns URL-escaped string following RFC 3986.
403
+ *
404
+ */
405
+ static VALUE
406
+ cgiesc_escape_uri_component(VALUE self, VALUE str)
407
+ {
408
+ StringValue(str);
409
+
410
+ if (rb_enc_str_asciicompat_p(str)) {
411
+ return optimized_escape(str, 0);
412
+ }
413
+ else {
414
+ return rb_call_super(1, &str);
415
+ }
416
+ }
417
+
418
+ /*
419
+ * call-seq:
420
+ * CGI.unescapeURIComponent(string, encoding=@@accept_charset) -> string
421
+ *
422
+ * Returns URL-unescaped string following RFC 3986.
423
+ *
424
+ */
425
+ static VALUE
426
+ cgiesc_unescape_uri_component(int argc, VALUE *argv, VALUE self)
427
+ {
428
+ VALUE str = (rb_check_arity(argc, 1, 2), argv[0]);
429
+
430
+ StringValue(str);
431
+
432
+ if (rb_enc_str_asciicompat_p(str)) {
433
+ VALUE enc = accept_charset(argc-1, argv+1, self);
434
+ return optimized_unescape(str, enc, 0);
392
435
  }
393
436
  else {
394
- return rb_call_super(argc, argv);
437
+ return rb_call_super(argc, argv);
395
438
  }
396
439
  }
397
440
 
@@ -414,6 +457,8 @@ InitVM_escape(void)
414
457
  rb_mUtil = rb_define_module_under(rb_cCGI, "Util");
415
458
  rb_define_method(rb_mEscape, "escapeHTML", cgiesc_escape_html, 1);
416
459
  rb_define_method(rb_mEscape, "unescapeHTML", cgiesc_unescape_html, 1);
460
+ rb_define_method(rb_mEscape, "escapeURIComponent", cgiesc_escape_uri_component, 1);
461
+ rb_define_method(rb_mEscape, "unescapeURIComponent", cgiesc_unescape_uri_component, -1);
417
462
  rb_define_method(rb_mEscape, "escape", cgiesc_escape, 1);
418
463
  rb_define_method(rb_mEscape, "unescape", cgiesc_unescape, -1);
419
464
  rb_prepend_module(rb_mUtil, rb_mEscape);
data/lib/cgi/cookie.rb CHANGED
@@ -40,6 +40,10 @@ class CGI
40
40
  class Cookie < Array
41
41
  @@accept_charset="UTF-8" unless defined?(@@accept_charset)
42
42
 
43
+ TOKEN_RE = %r"\A[[!-~]&&[^()<>@,;:\\\"/?=\[\]{}]]+\z"
44
+ PATH_VALUE_RE = %r"\A[[ -~]&&[^;]]*\z"
45
+ DOMAIN_VALUE_RE = %r"\A(?<label>(?!-)[-A-Za-z0-9]+(?<!-))(?:\.\g<label>)*\z"
46
+
43
47
  # Create a new CGI::Cookie object.
44
48
  #
45
49
  # :call-seq:
@@ -72,8 +76,8 @@ class CGI
72
76
  @domain = nil
73
77
  @expires = nil
74
78
  if name.kind_of?(String)
75
- @name = name
76
- @path = (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
79
+ self.name = name
80
+ self.path = (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
77
81
  @secure = false
78
82
  @httponly = false
79
83
  return super(value)
@@ -84,11 +88,11 @@ class CGI
84
88
  raise ArgumentError, "`name' required"
85
89
  end
86
90
 
87
- @name = options["name"]
91
+ self.name = options["name"]
88
92
  value = Array(options["value"])
89
93
  # simple support for IE
90
- @path = options["path"] || (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
91
- @domain = options["domain"]
94
+ self.path = options["path"] || (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
95
+ self.domain = options["domain"]
92
96
  @expires = options["expires"]
93
97
  @secure = options["secure"] == true
94
98
  @httponly = options["httponly"] == true
@@ -97,11 +101,35 @@ class CGI
97
101
  end
98
102
 
99
103
  # Name of this cookie, as a +String+
100
- attr_accessor :name
104
+ attr_reader :name
105
+ # Set name of this cookie
106
+ def name=(str)
107
+ if str and !TOKEN_RE.match?(str)
108
+ raise ArgumentError, "invalid name: #{str.dump}"
109
+ end
110
+ @name = str
111
+ end
112
+
101
113
  # Path for which this cookie applies, as a +String+
102
- attr_accessor :path
114
+ attr_reader :path
115
+ # Set path for which this cookie applies
116
+ def path=(str)
117
+ if str and !PATH_VALUE_RE.match?(str)
118
+ raise ArgumentError, "invalid path: #{str.dump}"
119
+ end
120
+ @path = str
121
+ end
122
+
103
123
  # Domain for which this cookie applies, as a +String+
104
- attr_accessor :domain
124
+ attr_reader :domain
125
+ # Set domain for which this cookie applies
126
+ def domain=(str)
127
+ if str and ((str = str.b).bytesize > 255 or !DOMAIN_VALUE_RE.match?(str))
128
+ raise ArgumentError, "invalid domain: #{str.dump}"
129
+ end
130
+ @domain = str
131
+ end
132
+
105
133
  # Time at which this cookie expires, as a +Time+
106
134
  attr_accessor :expires
107
135
  # True if this cookie is secure; false otherwise
data/lib/cgi/core.rb CHANGED
@@ -188,17 +188,28 @@ class CGI
188
188
  # Using #header with the HTML5 tag maker will create a <header> element.
189
189
  alias :header :http_header
190
190
 
191
+ def _no_crlf_check(str)
192
+ if str
193
+ str = str.to_s
194
+ raise "A HTTP status or header field must not include CR and LF" if str =~ /[\r\n]/
195
+ str
196
+ else
197
+ nil
198
+ end
199
+ end
200
+ private :_no_crlf_check
201
+
191
202
  def _header_for_string(content_type) #:nodoc:
192
203
  buf = ''.dup
193
204
  if nph?()
194
- buf << "#{$CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'} 200 OK#{EOL}"
205
+ buf << "#{_no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0'} 200 OK#{EOL}"
195
206
  buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
196
- buf << "Server: #{$CGI_ENV['SERVER_SOFTWARE']}#{EOL}"
207
+ buf << "Server: #{_no_crlf_check($CGI_ENV['SERVER_SOFTWARE'])}#{EOL}"
197
208
  buf << "Connection: close#{EOL}"
198
209
  end
199
- buf << "Content-Type: #{content_type}#{EOL}"
210
+ buf << "Content-Type: #{_no_crlf_check(content_type)}#{EOL}"
200
211
  if @output_cookies
201
- @output_cookies.each {|cookie| buf << "Set-Cookie: #{cookie}#{EOL}" }
212
+ @output_cookies.each {|cookie| buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}" }
202
213
  end
203
214
  return buf
204
215
  end # _header_for_string
@@ -213,9 +224,9 @@ class CGI
213
224
  ## NPH
214
225
  options.delete('nph') if defined?(MOD_RUBY)
215
226
  if options.delete('nph') || nph?()
216
- protocol = $CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'
227
+ protocol = _no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0'
217
228
  status = options.delete('status')
218
- status = HTTP_STATUS[status] || status || '200 OK'
229
+ status = HTTP_STATUS[status] || _no_crlf_check(status) || '200 OK'
219
230
  buf << "#{protocol} #{status}#{EOL}"
220
231
  buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
221
232
  options['server'] ||= $CGI_ENV['SERVER_SOFTWARE'] || ''
@@ -223,38 +234,38 @@ class CGI
223
234
  end
224
235
  ## common headers
225
236
  status = options.delete('status')
226
- buf << "Status: #{HTTP_STATUS[status] || status}#{EOL}" if status
237
+ buf << "Status: #{HTTP_STATUS[status] || _no_crlf_check(status)}#{EOL}" if status
227
238
  server = options.delete('server')
228
- buf << "Server: #{server}#{EOL}" if server
239
+ buf << "Server: #{_no_crlf_check(server)}#{EOL}" if server
229
240
  connection = options.delete('connection')
230
- buf << "Connection: #{connection}#{EOL}" if connection
241
+ buf << "Connection: #{_no_crlf_check(connection)}#{EOL}" if connection
231
242
  type = options.delete('type')
232
- buf << "Content-Type: #{type}#{EOL}" #if type
243
+ buf << "Content-Type: #{_no_crlf_check(type)}#{EOL}" #if type
233
244
  length = options.delete('length')
234
- buf << "Content-Length: #{length}#{EOL}" if length
245
+ buf << "Content-Length: #{_no_crlf_check(length)}#{EOL}" if length
235
246
  language = options.delete('language')
236
- buf << "Content-Language: #{language}#{EOL}" if language
247
+ buf << "Content-Language: #{_no_crlf_check(language)}#{EOL}" if language
237
248
  expires = options.delete('expires')
238
249
  buf << "Expires: #{CGI.rfc1123_date(expires)}#{EOL}" if expires
239
250
  ## cookie
240
251
  if cookie = options.delete('cookie')
241
252
  case cookie
242
253
  when String, Cookie
243
- buf << "Set-Cookie: #{cookie}#{EOL}"
254
+ buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}"
244
255
  when Array
245
256
  arr = cookie
246
- arr.each {|c| buf << "Set-Cookie: #{c}#{EOL}" }
257
+ arr.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
247
258
  when Hash
248
259
  hash = cookie
249
- hash.each_value {|c| buf << "Set-Cookie: #{c}#{EOL}" }
260
+ hash.each_value {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
250
261
  end
251
262
  end
252
263
  if @output_cookies
253
- @output_cookies.each {|c| buf << "Set-Cookie: #{c}#{EOL}" }
264
+ @output_cookies.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
254
265
  end
255
266
  ## other headers
256
267
  options.each do |key, value|
257
- buf << "#{key}: #{value}#{EOL}"
268
+ buf << "#{_no_crlf_check(key)}: #{_no_crlf_check(value)}#{EOL}"
258
269
  end
259
270
  return buf
260
271
  end # _header_for_hash
data/lib/cgi/util.rb CHANGED
@@ -5,24 +5,57 @@ class CGI
5
5
  extend Util
6
6
  end
7
7
  module CGI::Util
8
- @@accept_charset="UTF-8" unless defined?(@@accept_charset)
9
- # URL-encode a string.
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 (+"+"+)
10
12
  # url_encoded_string = CGI.escape("'Stop!' said Fred")
11
13
  # # => "%27Stop%21%27+said+Fred"
12
14
  def escape(string)
13
15
  encoding = string.encoding
14
- string.b.gsub(/([^ a-zA-Z0-9_.\-~]+)/) do |m|
16
+ buffer = string.b
17
+ buffer.gsub!(/([^ a-zA-Z0-9_.\-~]+)/) do |m|
15
18
  '%' + m.unpack('H2' * m.bytesize).join('%').upcase
16
- end.tr(' ', '+').force_encoding(encoding)
19
+ end
20
+ buffer.tr!(' ', '+')
21
+ buffer.force_encoding(encoding)
17
22
  end
18
23
 
19
- # URL-decode a string with encoding(optional).
24
+ # URL-decode an application/x-www-form-urlencoded string with encoding(optional).
20
25
  # string = CGI.unescape("%27Stop%21%27+said+Fred")
21
26
  # # => "'Stop!' said Fred"
22
- def unescape(string,encoding=@@accept_charset)
23
- str=string.tr('+', ' ').b.gsub(/((?:%[0-9a-fA-F]{2})+)/) do |m|
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.escape("'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
+
50
+ # URL-decode a string following RFC 3986 with encoding(optional).
51
+ # string = CGI.unescape("%27Stop%21%27+said%20Fred")
52
+ # # => "'Stop!'+said Fred"
53
+ def unescapeURIComponent(string, encoding = @@accept_charset)
54
+ str = string.b
55
+ str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m|
24
56
  [m.delete('%')].pack('H*')
25
- end.force_encoding(encoding)
57
+ end
58
+ str.force_encoding(encoding)
26
59
  str.valid_encoding? ? str : str.force_encoding(string.encoding)
27
60
  end
28
61
 
data/lib/cgi.rb CHANGED
@@ -162,7 +162,7 @@
162
162
  # cgi.has_key?('field_name')
163
163
  # cgi.include?('field_name')
164
164
  #
165
- # CAUTION! cgi['field_name'] returned an Array with the old
165
+ # CAUTION! <code>cgi['field_name']</code> returned an Array with the old
166
166
  # cgi.rb(included in Ruby 1.6)
167
167
  #
168
168
  # === Get form values as hash
@@ -288,7 +288,7 @@
288
288
  #
289
289
 
290
290
  class CGI
291
- VERSION = "0.3.2"
291
+ VERSION = "0.3.5"
292
292
  end
293
293
 
294
294
  require 'cgi/core'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cgi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yukihiro Matsumoto
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-03 00:00:00.000000000 Z
11
+ date: 2022-11-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Support for the Common Gateway Interface protocol.
14
14
  email:
@@ -18,11 +18,8 @@ extensions:
18
18
  - ext/cgi/escape/extconf.rb
19
19
  extra_rdoc_files: []
20
20
  files:
21
- - Gemfile
22
21
  - LICENSE.txt
23
22
  - README.md
24
- - Rakefile
25
- - cgi.gemspec
26
23
  - ext/cgi/escape/depend
27
24
  - ext/cgi/escape/escape.c
28
25
  - ext/cgi/escape/extconf.rb
@@ -33,10 +30,6 @@ files:
33
30
  - lib/cgi/session.rb
34
31
  - lib/cgi/session/pstore.rb
35
32
  - lib/cgi/util.rb
36
- - rakelib/changelogs.rake
37
- - rakelib/epoch.rake
38
- - rakelib/sync_tool.rake
39
- - rakelib/version.rake
40
33
  homepage: https://github.com/ruby/cgi
41
34
  licenses:
42
35
  - Ruby
data/Gemfile DELETED
@@ -1,8 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- group :development do
4
- gem "bundler"
5
- gem "rake"
6
- gem "rake-compiler"
7
- gem "test-unit"
8
- end
data/Rakefile DELETED
@@ -1,17 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
3
-
4
- require 'rake/extensiontask'
5
- extask = Rake::ExtensionTask.new("cgi/escape") do |x|
6
- x.lib_dir.sub!(%r[(?=/|\z)], "/#{RUBY_VERSION}/#{x.platform}")
7
- end
8
-
9
- Rake::TestTask.new(:test) do |t|
10
- t.libs << "lib/#{RUBY_VERSION}/#{extask.platform}"
11
- t.libs << "test/lib"
12
- t.ruby_opts << "-rhelper"
13
- t.test_files = FileList['test/**/test_*.rb']
14
- end
15
-
16
- task :default => :test
17
- task :test => :compile
data/cgi.gemspec DELETED
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- name = File.basename(__FILE__, ".gemspec")
4
- version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
5
- break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
6
- /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
7
- end rescue nil
8
- end
9
-
10
- Gem::Specification.new do |spec|
11
- spec.name = name
12
- spec.version = version
13
- spec.authors = ["Yukihiro Matsumoto"]
14
- spec.email = ["matz@ruby-lang.org"]
15
-
16
- spec.summary = %q{Support for the Common Gateway Interface protocol.}
17
- spec.description = %q{Support for the Common Gateway Interface protocol.}
18
- spec.homepage = "https://github.com/ruby/cgi"
19
- spec.licenses = ["Ruby", "BSD-2-Clause"]
20
- spec.required_ruby_version = ">= 2.5.0"
21
-
22
- spec.metadata["homepage_uri"] = spec.homepage
23
- spec.metadata["source_code_uri"] = spec.homepage
24
-
25
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
26
- `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{\A(?:(?:test|spec|features)/|\.git)}) }
27
- end
28
- spec.extensions = ["ext/cgi/escape/extconf.rb"]
29
- spec.executables = []
30
- spec.require_paths = ["lib"]
31
- end
@@ -1,34 +0,0 @@
1
- task "build" => "changelogs"
2
-
3
- changelog = proc do |output, ver = nil, prev = nil|
4
- ver &&= Gem::Version.new(ver)
5
- range = [[prev], [ver, "HEAD"]].map {|ver, branch| ver ? "v#{ver.to_s}" : branch}.compact.join("..")
6
- IO.popen(%W[git log --format=fuller --topo-order --no-merges #{range}]) do |log|
7
- line = log.gets
8
- FileUtils.mkpath(File.dirname(output))
9
- File.open(output, "wb") do |f|
10
- f.print "-*- coding: utf-8 -*-\n\n", line
11
- log.each_line do |line|
12
- line.sub!(/^(?!:)(?:Author|Commit)?(?:Date)?: /, ' \&')
13
- line.sub!(/ +$/, '')
14
- f.print(line)
15
- end
16
- end
17
- end
18
- end
19
-
20
- tags = IO.popen(%w[git tag -l v[0-9]*]).grep(/v(.*)/) {$1}
21
- tags.sort_by! {|tag| tag.scan(/\d+/).map(&:to_i)}
22
- tags.inject(nil) do |prev, tag|
23
- task("logs/ChangeLog-#{tag}") {|t| changelog[t.name, tag, prev]}
24
- tag
25
- end
26
-
27
- desc "Make ChangeLog"
28
- task "ChangeLog", [:ver, :prev] do |t, ver: nil, prev: tags.last|
29
- changelog[t.name, ver, prev]
30
- end
31
-
32
- changelogs = ["ChangeLog", *tags.map {|tag| "logs/ChangeLog-#{tag}"}]
33
- task "changelogs" => changelogs
34
- CLOBBER.concat(changelogs) << "logs"
data/rakelib/epoch.rake DELETED
@@ -1,5 +0,0 @@
1
- task "build" => "date_epoch"
2
-
3
- task "date_epoch" do
4
- ENV["SOURCE_DATE_EPOCH"] = IO.popen(%W[git -C #{__dir__} log -1 --format=%ct], &:read).chomp
5
- end
@@ -1,6 +0,0 @@
1
- task :sync_tool do
2
- require 'fileutils'
3
- FileUtils.cp "../ruby/tool/lib/core_assertions.rb", "./test/lib"
4
- FileUtils.cp "../ruby/tool/lib/envutil.rb", "./test/lib"
5
- FileUtils.cp "../ruby/tool/lib/find_executable.rb", "./test/lib"
6
- end
data/rakelib/version.rake DELETED
@@ -1,44 +0,0 @@
1
- class << (helper = Bundler::GemHelper.instance)
2
- def update_gemspec
3
- path = gemspec.loaded_from
4
- File.open(path, "r+b") do |f|
5
- d = f.read
6
- if d.sub!(/^(_VERSION\s*=\s*)".*"/) {$1 + gemspec.version.to_s.dump}
7
- f.rewind
8
- f.truncate(0)
9
- f.print(d)
10
- end
11
- end
12
- end
13
-
14
- def commit_bump
15
- sh(%W[git commit -m bump\ up\ to\ #{gemspec.version}
16
- #{gemspec.loaded_from}])
17
- end
18
-
19
- def version=(v)
20
- gemspec.version = v
21
- update_gemspec
22
- commit_bump
23
- end
24
- end
25
-
26
- major, minor, teeny = helper.gemspec.version.segments
27
-
28
- task "bump:teeny" do
29
- helper.version = Gem::Version.new("#{major}.#{minor}.#{teeny+1}")
30
- end
31
-
32
- task "bump:minor" do
33
- helper.version = Gem::Version.new("#{major}.#{minor+1}.0")
34
- end
35
-
36
- task "bump:major" do
37
- helper.version = Gem::Version.new("#{major+1}.0.0")
38
- end
39
-
40
- task "bump" => "bump:teeny"
41
-
42
- task "tag" do
43
- helper.__send__(:tag_version)
44
- end