cgi 0.3.2 → 0.3.6
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.
Potentially problematic release.
This version of cgi might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ext/cgi/escape/escape.c +199 -154
- data/lib/cgi/cookie.rb +36 -8
- data/lib/cgi/core.rb +28 -17
- data/lib/cgi/util.rb +41 -8
- data/lib/cgi.rb +2 -2
- metadata +2 -9
- data/Gemfile +0 -8
- data/Rakefile +0 -17
- data/cgi.gemspec +0 -31
- data/rakelib/changelogs.rake +0 -34
- data/rakelib/epoch.rake +0 -5
- data/rakelib/sync_tool.rake +0 -6
- data/rakelib/version.rake +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef7c6fbc3fed4edb75963f96b0b7a150dca2d296730f28eb42844e7582f73ddb
|
4
|
+
data.tar.gz: 6dff4891d8e6b75480346969bef5efd4e33c323a8e6dbe2196e07abf5d4b4366
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b6abc351ceaf68ededa9d590fdd7adfb1fe8b32d4818128be7fb10867788cf32de65ea5d11cd4d7a38dc1a4adf19c1faee1b6a3689aeccea943178d18b09f8d
|
7
|
+
data.tar.gz: 1d805aede830aabc0c7d7ca577d8bd2bca541956d37cadeda9262a5e5ee01af5d940d4e135b907deadc16d20ef5a8357b2d4bb8817fc4241491f8305030e3d2e
|
data/ext/cgi/escape/escape.c
CHANGED
@@ -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
|
-
|
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
|
-
|
85
|
-
|
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
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
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
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
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
|
-
|
175
|
-
|
176
|
-
|
174
|
+
rb_str_cat(dest, cstr + beg, len - beg);
|
175
|
+
preserve_original_state(str, dest);
|
176
|
+
return dest;
|
177
177
|
}
|
178
178
|
else {
|
179
|
-
|
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
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
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
|
-
|
236
|
-
|
237
|
-
|
235
|
+
rb_str_cat(dest, cstr + beg, len - beg);
|
236
|
+
preserve_original_state(str, dest);
|
237
|
+
return dest;
|
238
238
|
}
|
239
239
|
else {
|
240
|
-
|
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
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
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
|
-
|
288
|
-
|
289
|
-
|
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
|
-
|
293
|
-
|
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
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
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
|
-
|
320
|
+
return optimized_escape_html(str);
|
321
321
|
}
|
322
322
|
else {
|
323
|
-
|
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
|
-
|
340
|
+
return optimized_unescape_html(str);
|
341
341
|
}
|
342
342
|
else {
|
343
|
-
|
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
|
-
|
360
|
+
return optimized_escape(str, 1);
|
361
361
|
}
|
362
362
|
else {
|
363
|
-
|
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
|
-
|
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
|
-
|
391
|
-
|
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
|
-
|
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
|
-
|
76
|
-
|
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
|
-
|
91
|
+
self.name = options["name"]
|
88
92
|
value = Array(options["value"])
|
89
93
|
# simple support for IE
|
90
|
-
|
91
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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=
|
9
|
-
|
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
|
16
|
+
buffer = string.b
|
17
|
+
buffer.gsub!(/([^ a-zA-Z0-9_.\-~]+)/) do |m|
|
15
18
|
'%' + m.unpack('H2' * m.bytesize).join('%').upcase
|
16
|
-
end
|
19
|
+
end
|
20
|
+
buffer.tr!(' ', '+')
|
21
|
+
buffer.force_encoding(encoding)
|
17
22
|
end
|
18
23
|
|
19
|
-
# URL-decode
|
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
|
23
|
-
str=string.tr('+', ' ')
|
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
|
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.
|
291
|
+
VERSION = "0.3.6"
|
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.
|
4
|
+
version: 0.3.6
|
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-
|
11
|
+
date: 2022-11-28 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
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
|
data/rakelib/changelogs.rake
DELETED
@@ -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
data/rakelib/sync_tool.rake
DELETED
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
|