diff options
Diffstat (limited to 'ext/cgi')
| -rw-r--r-- | ext/cgi/escape/depend | 158 | ||||
| -rw-r--r-- | ext/cgi/escape/escape.c | 412 | ||||
| -rw-r--r-- | ext/cgi/escape/extconf.rb | 6 |
3 files changed, 409 insertions, 167 deletions
diff --git a/ext/cgi/escape/depend b/ext/cgi/escape/depend index 8d4736616f..05b59bfdea 100644 --- a/ext/cgi/escape/depend +++ b/ext/cgi/escape/depend @@ -4,9 +4,167 @@ escape.o: $(arch_hdrdir)/ruby/config.h escape.o: $(hdrdir)/ruby.h escape.o: $(hdrdir)/ruby/assert.h escape.o: $(hdrdir)/ruby/backward.h +escape.o: $(hdrdir)/ruby/backward/2/assume.h +escape.o: $(hdrdir)/ruby/backward/2/attributes.h +escape.o: $(hdrdir)/ruby/backward/2/bool.h +escape.o: $(hdrdir)/ruby/backward/2/inttypes.h +escape.o: $(hdrdir)/ruby/backward/2/limits.h +escape.o: $(hdrdir)/ruby/backward/2/long_long.h +escape.o: $(hdrdir)/ruby/backward/2/stdalign.h +escape.o: $(hdrdir)/ruby/backward/2/stdarg.h escape.o: $(hdrdir)/ruby/defines.h escape.o: $(hdrdir)/ruby/encoding.h escape.o: $(hdrdir)/ruby/intern.h +escape.o: $(hdrdir)/ruby/internal/abi.h +escape.o: $(hdrdir)/ruby/internal/anyargs.h +escape.o: $(hdrdir)/ruby/internal/arithmetic.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/char.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/double.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/int.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/long.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/short.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +escape.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +escape.o: $(hdrdir)/ruby/internal/assume.h +escape.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +escape.o: $(hdrdir)/ruby/internal/attr/artificial.h +escape.o: $(hdrdir)/ruby/internal/attr/cold.h +escape.o: $(hdrdir)/ruby/internal/attr/const.h +escape.o: $(hdrdir)/ruby/internal/attr/constexpr.h +escape.o: $(hdrdir)/ruby/internal/attr/deprecated.h +escape.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +escape.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +escape.o: $(hdrdir)/ruby/internal/attr/error.h +escape.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +escape.o: $(hdrdir)/ruby/internal/attr/forceinline.h +escape.o: $(hdrdir)/ruby/internal/attr/format.h +escape.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +escape.o: $(hdrdir)/ruby/internal/attr/noalias.h +escape.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +escape.o: $(hdrdir)/ruby/internal/attr/noexcept.h +escape.o: $(hdrdir)/ruby/internal/attr/noinline.h +escape.o: $(hdrdir)/ruby/internal/attr/nonnull.h +escape.o: $(hdrdir)/ruby/internal/attr/noreturn.h +escape.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +escape.o: $(hdrdir)/ruby/internal/attr/pure.h +escape.o: $(hdrdir)/ruby/internal/attr/restrict.h +escape.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +escape.o: $(hdrdir)/ruby/internal/attr/warning.h +escape.o: $(hdrdir)/ruby/internal/attr/weakref.h +escape.o: $(hdrdir)/ruby/internal/cast.h +escape.o: $(hdrdir)/ruby/internal/compiler_is.h +escape.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +escape.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +escape.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +escape.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +escape.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +escape.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +escape.o: $(hdrdir)/ruby/internal/compiler_since.h +escape.o: $(hdrdir)/ruby/internal/config.h +escape.o: $(hdrdir)/ruby/internal/constant_p.h +escape.o: $(hdrdir)/ruby/internal/core.h +escape.o: $(hdrdir)/ruby/internal/core/rarray.h +escape.o: $(hdrdir)/ruby/internal/core/rbasic.h +escape.o: $(hdrdir)/ruby/internal/core/rbignum.h +escape.o: $(hdrdir)/ruby/internal/core/rclass.h +escape.o: $(hdrdir)/ruby/internal/core/rdata.h +escape.o: $(hdrdir)/ruby/internal/core/rfile.h +escape.o: $(hdrdir)/ruby/internal/core/rhash.h +escape.o: $(hdrdir)/ruby/internal/core/robject.h +escape.o: $(hdrdir)/ruby/internal/core/rregexp.h +escape.o: $(hdrdir)/ruby/internal/core/rstring.h +escape.o: $(hdrdir)/ruby/internal/core/rstruct.h +escape.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +escape.o: $(hdrdir)/ruby/internal/ctype.h +escape.o: $(hdrdir)/ruby/internal/dllexport.h +escape.o: $(hdrdir)/ruby/internal/dosish.h +escape.o: $(hdrdir)/ruby/internal/encoding/coderange.h +escape.o: $(hdrdir)/ruby/internal/encoding/ctype.h +escape.o: $(hdrdir)/ruby/internal/encoding/encoding.h +escape.o: $(hdrdir)/ruby/internal/encoding/pathname.h +escape.o: $(hdrdir)/ruby/internal/encoding/re.h +escape.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +escape.o: $(hdrdir)/ruby/internal/encoding/string.h +escape.o: $(hdrdir)/ruby/internal/encoding/symbol.h +escape.o: $(hdrdir)/ruby/internal/encoding/transcode.h +escape.o: $(hdrdir)/ruby/internal/error.h +escape.o: $(hdrdir)/ruby/internal/eval.h +escape.o: $(hdrdir)/ruby/internal/event.h +escape.o: $(hdrdir)/ruby/internal/fl_type.h +escape.o: $(hdrdir)/ruby/internal/gc.h +escape.o: $(hdrdir)/ruby/internal/glob.h +escape.o: $(hdrdir)/ruby/internal/globals.h +escape.o: $(hdrdir)/ruby/internal/has/attribute.h +escape.o: $(hdrdir)/ruby/internal/has/builtin.h +escape.o: $(hdrdir)/ruby/internal/has/c_attribute.h +escape.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +escape.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +escape.o: $(hdrdir)/ruby/internal/has/extension.h +escape.o: $(hdrdir)/ruby/internal/has/feature.h +escape.o: $(hdrdir)/ruby/internal/has/warning.h +escape.o: $(hdrdir)/ruby/internal/intern/array.h +escape.o: $(hdrdir)/ruby/internal/intern/bignum.h +escape.o: $(hdrdir)/ruby/internal/intern/class.h +escape.o: $(hdrdir)/ruby/internal/intern/compar.h +escape.o: $(hdrdir)/ruby/internal/intern/complex.h +escape.o: $(hdrdir)/ruby/internal/intern/cont.h +escape.o: $(hdrdir)/ruby/internal/intern/dir.h +escape.o: $(hdrdir)/ruby/internal/intern/enum.h +escape.o: $(hdrdir)/ruby/internal/intern/enumerator.h +escape.o: $(hdrdir)/ruby/internal/intern/error.h +escape.o: $(hdrdir)/ruby/internal/intern/eval.h +escape.o: $(hdrdir)/ruby/internal/intern/file.h +escape.o: $(hdrdir)/ruby/internal/intern/hash.h +escape.o: $(hdrdir)/ruby/internal/intern/io.h +escape.o: $(hdrdir)/ruby/internal/intern/load.h +escape.o: $(hdrdir)/ruby/internal/intern/marshal.h +escape.o: $(hdrdir)/ruby/internal/intern/numeric.h +escape.o: $(hdrdir)/ruby/internal/intern/object.h +escape.o: $(hdrdir)/ruby/internal/intern/parse.h +escape.o: $(hdrdir)/ruby/internal/intern/proc.h +escape.o: $(hdrdir)/ruby/internal/intern/process.h +escape.o: $(hdrdir)/ruby/internal/intern/random.h +escape.o: $(hdrdir)/ruby/internal/intern/range.h +escape.o: $(hdrdir)/ruby/internal/intern/rational.h +escape.o: $(hdrdir)/ruby/internal/intern/re.h +escape.o: $(hdrdir)/ruby/internal/intern/ruby.h +escape.o: $(hdrdir)/ruby/internal/intern/select.h +escape.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +escape.o: $(hdrdir)/ruby/internal/intern/set.h +escape.o: $(hdrdir)/ruby/internal/intern/signal.h +escape.o: $(hdrdir)/ruby/internal/intern/sprintf.h +escape.o: $(hdrdir)/ruby/internal/intern/string.h +escape.o: $(hdrdir)/ruby/internal/intern/struct.h +escape.o: $(hdrdir)/ruby/internal/intern/thread.h +escape.o: $(hdrdir)/ruby/internal/intern/time.h +escape.o: $(hdrdir)/ruby/internal/intern/variable.h +escape.o: $(hdrdir)/ruby/internal/intern/vm.h +escape.o: $(hdrdir)/ruby/internal/interpreter.h +escape.o: $(hdrdir)/ruby/internal/iterator.h +escape.o: $(hdrdir)/ruby/internal/memory.h +escape.o: $(hdrdir)/ruby/internal/method.h +escape.o: $(hdrdir)/ruby/internal/module.h +escape.o: $(hdrdir)/ruby/internal/newobj.h +escape.o: $(hdrdir)/ruby/internal/scan_args.h +escape.o: $(hdrdir)/ruby/internal/special_consts.h +escape.o: $(hdrdir)/ruby/internal/static_assert.h +escape.o: $(hdrdir)/ruby/internal/stdalign.h +escape.o: $(hdrdir)/ruby/internal/stdbool.h +escape.o: $(hdrdir)/ruby/internal/stdckdint.h +escape.o: $(hdrdir)/ruby/internal/symbol.h +escape.o: $(hdrdir)/ruby/internal/value.h +escape.o: $(hdrdir)/ruby/internal/value_type.h +escape.o: $(hdrdir)/ruby/internal/variable.h +escape.o: $(hdrdir)/ruby/internal/warning_push.h +escape.o: $(hdrdir)/ruby/internal/xmalloc.h escape.o: $(hdrdir)/ruby/missing.h escape.o: $(hdrdir)/ruby/onigmo.h escape.o: $(hdrdir)/ruby/oniguruma.h diff --git a/ext/cgi/escape/escape.c b/ext/cgi/escape/escape.c index 47188819cd..4773186603 100644 --- a/ext/cgi/escape/escape.c +++ b/ext/cgi/escape/escape.c @@ -8,7 +8,7 @@ RUBY_EXTERN const signed char ruby_digit36_to_number_table[]; #define upper_hexdigits (ruby_hexdigits+16) #define char_to_number(c) ruby_digit36_to_number_table[(unsigned char)(c)] -static VALUE rb_cCGI, rb_mUtil, rb_mEscape; +static VALUE rb_cCGI, rb_mEscape, rb_mEscapeExt; static ID id_accept_charset; #define HTML_ESCAPE_MAX_LEN 6 @@ -32,11 +32,22 @@ preserve_original_state(VALUE orig, VALUE dest) rb_enc_associate(dest, rb_enc_get(orig)); } +static inline long +escaped_length(VALUE str) +{ + const long len = RSTRING_LEN(str); + if (len >= LONG_MAX / HTML_ESCAPE_MAX_LEN) { + ruby_malloc_size_overflow(len, HTML_ESCAPE_MAX_LEN); + } + return len * HTML_ESCAPE_MAX_LEN; +} + static VALUE optimized_escape_html(VALUE str) { + VALUE escaped; VALUE vbuf; - char *buf = ALLOCV_N(char, vbuf, RSTRING_LEN(str) * HTML_ESCAPE_MAX_LEN); + char *buf = ALLOCV_N(char, vbuf, escaped_length(str)); const char *cstr = RSTRING_PTR(str); const char *end = cstr + RSTRING_LEN(str); @@ -53,7 +64,6 @@ optimized_escape_html(VALUE str) } } - VALUE escaped; if (RSTRING_LEN(str) < (dest - buf)) { escaped = rb_str_new(buf, dest - buf); preserve_original_state(str, escaped); @@ -71,9 +81,9 @@ optimized_unescape_html(VALUE str) enum {UNICODE_MAX = 0x10ffff}; rb_encoding *enc = rb_enc_get(str); unsigned long charlimit = (strcasecmp(rb_enc_name(enc), "UTF-8") == 0 ? UNICODE_MAX : - strcasecmp(rb_enc_name(enc), "ISO-8859-1") == 0 ? 256 : - 128); - long i, len, beg = 0; + strcasecmp(rb_enc_name(enc), "ISO-8859-1") == 0 ? 256 : + 128); + long i, j, len, beg = 0; size_t clen, plen; int overflow; const char *cstr; @@ -84,89 +94,108 @@ optimized_unescape_html(VALUE str) cstr = RSTRING_PTR(str); for (i = 0; i < len; i++) { - unsigned long cc; - char c = cstr[i]; - if (c != '&') continue; - plen = i - beg; - if (++i >= len) break; - c = (unsigned char)cstr[i]; + unsigned long cc; + char c = cstr[i]; + if (c != '&') continue; + plen = i - beg; + if (++i >= len) break; + c = (unsigned char)cstr[i]; + j = i; #define MATCH(s) (len - i >= (int)rb_strlen_lit(s) && \ - memcmp(&cstr[i], s, rb_strlen_lit(s)) == 0 && \ - (i += rb_strlen_lit(s) - 1, 1)) - switch (c) { - case 'a': - ++i; - if (MATCH("pos;")) { - c = '\''; - } - else if (MATCH("mp;")) { - c = '&'; - } - else continue; - break; - case 'q': - ++i; - if (MATCH("uot;")) { - c = '"'; - } - else continue; - break; - case 'g': - ++i; - if (MATCH("t;")) { - c = '>'; - } - else continue; - break; - case 'l': - ++i; - if (MATCH("t;")) { - c = '<'; - } - else continue; - break; - case '#': - if (len - ++i >= 2 && ISDIGIT(cstr[i])) { - cc = ruby_scan_digits(&cstr[i], len-i, 10, &clen, &overflow); - } - else if ((cstr[i] == 'x' || cstr[i] == 'X') && len - ++i >= 2 && ISXDIGIT(cstr[i])) { - cc = ruby_scan_digits(&cstr[i], len-i, 16, &clen, &overflow); - } - else continue; - i += clen; - if (overflow || cc >= charlimit || cstr[i] != ';') continue; - if (!dest) { - dest = rb_str_buf_new(len); - } - rb_str_cat(dest, cstr + beg, plen); - if (charlimit > 256) { - rb_str_cat(dest, buf, rb_enc_mbcput((OnigCodePoint)cc, buf, enc)); - } - else { - c = (unsigned char)cc; - rb_str_cat(dest, &c, 1); - } - beg = i + 1; - continue; - default: - --i; - continue; - } - if (!dest) { - dest = rb_str_buf_new(len); - } - rb_str_cat(dest, cstr + beg, plen); - rb_str_cat(dest, &c, 1); - beg = i + 1; + memcmp(&cstr[i], s, rb_strlen_lit(s)) == 0 && \ + (i += rb_strlen_lit(s) - 1, 1)) + switch (c) { + case 'a': + ++i; + if (MATCH("pos;")) { + c = '\''; + } + else if (MATCH("mp;")) { + c = '&'; + } + else { + i = j; + continue; + } + break; + case 'q': + ++i; + if (MATCH("uot;")) { + c = '"'; + } + else { + i = j; + continue; + } + break; + case 'g': + ++i; + if (MATCH("t;")) { + c = '>'; + } + else { + i = j; + continue; + } + break; + case 'l': + ++i; + if (MATCH("t;")) { + c = '<'; + } + else { + i = j; + continue; + } + break; + case '#': + if (len - ++i >= 2 && ISDIGIT(cstr[i])) { + cc = ruby_scan_digits(&cstr[i], len-i, 10, &clen, &overflow); + } + else if ((cstr[i] == 'x' || cstr[i] == 'X') && len - ++i >= 2 && ISXDIGIT(cstr[i])) { + cc = ruby_scan_digits(&cstr[i], len-i, 16, &clen, &overflow); + } + else { + i = j; + continue; + } + i += clen; + if (overflow || cc >= charlimit || cstr[i] != ';') { + i = j; + continue; + } + if (!dest) { + dest = rb_str_buf_new(len); + } + rb_str_cat(dest, cstr + beg, plen); + if (charlimit > 256) { + rb_str_cat(dest, buf, rb_enc_mbcput((OnigCodePoint)cc, buf, enc)); + } + else { + c = (unsigned char)cc; + rb_str_cat(dest, &c, 1); + } + beg = i + 1; + continue; + default: + --i; + continue; + } + if (!dest) { + dest = rb_str_buf_new(len); + } + rb_str_cat(dest, cstr + beg, plen); + rb_str_cat(dest, &c, 1); + beg = i + 1; } if (dest) { - rb_str_cat(dest, cstr + beg, len - beg); - preserve_original_state(str, dest); - return dest; + rb_str_cat(dest, cstr + beg, len - beg); + preserve_original_state(str, dest); + return dest; } else { - return rb_str_dup(str); + return rb_str_dup(str); } } @@ -190,7 +219,7 @@ url_unreserved_char(unsigned char c) } static VALUE -optimized_escape(VALUE str) +optimized_escape(VALUE str, int plus_escape) { long i, len, beg = 0; VALUE dest = 0; @@ -201,38 +230,38 @@ optimized_escape(VALUE str) cstr = RSTRING_PTR(str); for (i = 0; i < len; ++i) { - const unsigned char c = (unsigned char)cstr[i]; - if (!url_unreserved_char(c)) { - if (!dest) { - dest = rb_str_buf_new(len); - } - - rb_str_cat(dest, cstr + beg, i - beg); - beg = i + 1; - - if (c == ' ') { - rb_str_cat_cstr(dest, "+"); - } - else { - buf[1] = upper_hexdigits[(c >> 4) & 0xf]; - buf[2] = upper_hexdigits[c & 0xf]; - rb_str_cat(dest, buf, 3); - } - } + const unsigned char c = (unsigned char)cstr[i]; + if (!url_unreserved_char(c)) { + if (!dest) { + dest = rb_str_buf_new(len); + } + + rb_str_cat(dest, cstr + beg, i - beg); + beg = i + 1; + + if (plus_escape && c == ' ') { + rb_str_cat_cstr(dest, "+"); + } + else { + buf[1] = upper_hexdigits[(c >> 4) & 0xf]; + buf[2] = upper_hexdigits[c & 0xf]; + rb_str_cat(dest, buf, 3); + } + } } if (dest) { - rb_str_cat(dest, cstr + beg, len - beg); - preserve_original_state(str, dest); - return dest; + rb_str_cat(dest, cstr + beg, len - beg); + preserve_original_state(str, dest); + return dest; } else { - return rb_str_dup(str); + return rb_str_dup(str); } } static VALUE -optimized_unescape(VALUE str, VALUE encoding) +optimized_unescape(VALUE str, VALUE encoding, int unescape_plus) { long i, len, beg = 0; VALUE dest = 0; @@ -244,52 +273,52 @@ optimized_unescape(VALUE str, VALUE encoding) cstr = RSTRING_PTR(str); for (i = 0; i < len; ++i) { - char buf[1]; - const char c = cstr[i]; - int clen = 0; - if (c == '%') { - if (i + 3 > len) break; - if (!ISXDIGIT(cstr[i+1])) continue; - if (!ISXDIGIT(cstr[i+2])) continue; - buf[0] = ((char_to_number(cstr[i+1]) << 4) - | char_to_number(cstr[i+2])); - clen = 2; - } - else if (c == '+') { - buf[0] = ' '; - } - else { - continue; - } - - if (!dest) { - dest = rb_str_buf_new(len); - } - - rb_str_cat(dest, cstr + beg, i - beg); - i += clen; - beg = i + 1; - - rb_str_cat(dest, buf, 1); + char buf[1]; + const char c = cstr[i]; + int clen = 0; + if (c == '%') { + if (i + 3 > len) break; + if (!ISXDIGIT(cstr[i+1])) continue; + if (!ISXDIGIT(cstr[i+2])) continue; + buf[0] = ((char_to_number(cstr[i+1]) << 4) + | char_to_number(cstr[i+2])); + clen = 2; + } + else if (unescape_plus && c == '+') { + buf[0] = ' '; + } + else { + continue; + } + + if (!dest) { + dest = rb_str_buf_new(len); + } + + rb_str_cat(dest, cstr + beg, i - beg); + i += clen; + beg = i + 1; + + rb_str_cat(dest, buf, 1); } if (dest) { - rb_str_cat(dest, cstr + beg, len - beg); - preserve_original_state(str, dest); - cr = ENC_CODERANGE_UNKNOWN; + rb_str_cat(dest, cstr + beg, len - beg); + preserve_original_state(str, dest); + cr = ENC_CODERANGE_UNKNOWN; } else { - dest = rb_str_dup(str); - cr = ENC_CODERANGE(str); + dest = rb_str_dup(str); + cr = ENC_CODERANGE(str); } origenc = rb_enc_get_index(str); if (origenc != encidx) { - rb_enc_associate_index(dest, encidx); - if (!ENC_CODERANGE_CLEAN_P(rb_enc_str_coderange(dest))) { - rb_enc_associate_index(dest, origenc); - if (cr != ENC_CODERANGE_UNKNOWN) - ENC_CODERANGE_SET(dest, cr); - } + rb_enc_associate_index(dest, encidx); + if (!ENC_CODERANGE_CLEAN_P(rb_enc_str_coderange(dest))) { + rb_enc_associate_index(dest, origenc); + if (cr != ENC_CODERANGE_UNKNOWN) + ENC_CODERANGE_SET(dest, cr); + } } return dest; } @@ -307,10 +336,10 @@ cgiesc_escape_html(VALUE self, VALUE str) StringValue(str); if (rb_enc_str_asciicompat_p(str)) { - return optimized_escape_html(str); + return optimized_escape_html(str); } else { - return rb_call_super(1, &str); + return rb_call_super(1, &str); } } @@ -327,10 +356,10 @@ cgiesc_unescape_html(VALUE self, VALUE str) StringValue(str); if (rb_enc_str_asciicompat_p(str)) { - return optimized_unescape_html(str); + return optimized_unescape_html(str); } else { - return rb_call_super(1, &str); + return rb_call_super(1, &str); } } @@ -338,7 +367,7 @@ cgiesc_unescape_html(VALUE self, VALUE str) * call-seq: * CGI.escape(string) -> string * - * Returns URL-escaped string. + * Returns URL-escaped string (+application/x-www-form-urlencoded+). * */ static VALUE @@ -347,10 +376,10 @@ cgiesc_escape(VALUE self, VALUE str) StringValue(str); if (rb_enc_str_asciicompat_p(str)) { - return optimized_escape(str); + return optimized_escape(str, 1); } else { - return rb_call_super(1, &str); + return rb_call_super(1, &str); } } @@ -358,7 +387,7 @@ static VALUE accept_charset(int argc, VALUE *argv, VALUE self) { if (argc > 0) - return argv[0]; + return argv[0]; return rb_cvar_get(CLASS_OF(self), id_accept_charset); } @@ -366,7 +395,7 @@ accept_charset(int argc, VALUE *argv, VALUE self) * call-seq: * CGI.unescape(string, encoding=@@accept_charset) -> string * - * Returns URL-unescaped string. + * Returns URL-unescaped string (+application/x-www-form-urlencoded+). * */ static VALUE @@ -377,17 +406,64 @@ cgiesc_unescape(int argc, VALUE *argv, VALUE self) StringValue(str); if (rb_enc_str_asciicompat_p(str)) { - VALUE enc = accept_charset(argc-1, argv+1, self); - return optimized_unescape(str, enc); + VALUE enc = accept_charset(argc-1, argv+1, self); + return optimized_unescape(str, enc, 1); + } + else { + return rb_call_super(argc, argv); + } +} + +/* + * call-seq: + * CGI.escapeURIComponent(string) -> string + * + * Returns URL-escaped string following RFC 3986. + * + */ +static VALUE +cgiesc_escape_uri_component(VALUE self, VALUE str) +{ + StringValue(str); + + if (rb_enc_str_asciicompat_p(str)) { + return optimized_escape(str, 0); + } + else { + return rb_call_super(1, &str); + } +} + +/* + * call-seq: + * CGI.unescapeURIComponent(string, encoding=@@accept_charset) -> string + * + * Returns URL-unescaped string following RFC 3986. + * + */ +static VALUE +cgiesc_unescape_uri_component(int argc, VALUE *argv, VALUE self) +{ + VALUE str = (rb_check_arity(argc, 1, 2), argv[0]); + + StringValue(str); + + if (rb_enc_str_asciicompat_p(str)) { + VALUE enc = accept_charset(argc-1, argv+1, self); + return optimized_unescape(str, enc, 0); } else { - return rb_call_super(argc, argv); + return rb_call_super(argc, argv); } } void Init_escape(void) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + id_accept_charset = rb_intern_const("@@accept_charset"); InitVM(escape); } @@ -395,13 +471,17 @@ Init_escape(void) void InitVM_escape(void) { - rb_cCGI = rb_define_class("CGI", rb_cObject); - rb_mEscape = rb_define_module_under(rb_cCGI, "Escape"); - rb_mUtil = rb_define_module_under(rb_cCGI, "Util"); - rb_define_method(rb_mEscape, "escapeHTML", cgiesc_escape_html, 1); - rb_define_method(rb_mEscape, "unescapeHTML", cgiesc_unescape_html, 1); - rb_define_method(rb_mEscape, "escape", cgiesc_escape, 1); - rb_define_method(rb_mEscape, "unescape", cgiesc_unescape, -1); - rb_prepend_module(rb_mUtil, rb_mEscape); - rb_extend_object(rb_cCGI, rb_mEscape); + rb_cCGI = rb_define_class("CGI", rb_cObject); + rb_mEscapeExt = rb_define_module_under(rb_cCGI, "EscapeExt"); + rb_mEscape = rb_define_module_under(rb_cCGI, "Escape"); + rb_define_method(rb_mEscapeExt, "escapeHTML", cgiesc_escape_html, 1); + rb_define_method(rb_mEscapeExt, "unescapeHTML", cgiesc_unescape_html, 1); + rb_define_method(rb_mEscapeExt, "escapeURIComponent", cgiesc_escape_uri_component, 1); + rb_define_alias(rb_mEscapeExt, "escape_uri_component", "escapeURIComponent"); + rb_define_method(rb_mEscapeExt, "unescapeURIComponent", cgiesc_unescape_uri_component, -1); + rb_define_alias(rb_mEscapeExt, "unescape_uri_component", "unescapeURIComponent"); + rb_define_method(rb_mEscapeExt, "escape", cgiesc_escape, 1); + rb_define_method(rb_mEscapeExt, "unescape", cgiesc_unescape, -1); + rb_prepend_module(rb_mEscape, rb_mEscapeExt); + rb_extend_object(rb_cCGI, rb_mEscapeExt); } diff --git a/ext/cgi/escape/extconf.rb b/ext/cgi/escape/extconf.rb index 16e8ff224d..73acd89ca8 100644 --- a/ext/cgi/escape/extconf.rb +++ b/ext/cgi/escape/extconf.rb @@ -1,3 +1,7 @@ require 'mkmf' -create_makefile 'cgi/escape' +if RUBY_ENGINE == 'truffleruby' + File.write("Makefile", dummy_makefile($srcdir).join("")) +else + create_makefile 'cgi/escape' +end |
