summaryrefslogtreecommitdiff
path: root/ext/cgi/escape
diff options
context:
space:
mode:
Diffstat (limited to 'ext/cgi/escape')
-rw-r--r--ext/cgi/escape/depend5
-rw-r--r--ext/cgi/escape/escape.c118
-rw-r--r--ext/cgi/escape/extconf.rb6
3 files changed, 100 insertions, 29 deletions
diff --git a/ext/cgi/escape/depend b/ext/cgi/escape/depend
index e3904d0695..05b59bfdea 100644
--- a/ext/cgi/escape/depend
+++ b/ext/cgi/escape/depend
@@ -53,6 +53,7 @@ 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
@@ -121,7 +122,6 @@ 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/gc.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
@@ -138,6 +138,7 @@ 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
@@ -152,12 +153,12 @@ 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/rgengc.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
diff --git a/ext/cgi/escape/escape.c b/ext/cgi/escape/escape.c
index 068647747d..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
@@ -45,6 +45,7 @@ escaped_length(VALUE str)
static VALUE
optimized_escape_html(VALUE str)
{
+ VALUE escaped;
VALUE vbuf;
char *buf = ALLOCV_N(char, vbuf, escaped_length(str));
const char *cstr = RSTRING_PTR(str);
@@ -63,7 +64,6 @@ 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);
@@ -83,7 +83,7 @@ optimized_unescape_html(VALUE 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;
+ long i, j, len, beg = 0;
size_t clen, plen;
int overflow;
const char *cstr;
@@ -100,6 +100,7 @@ optimized_unescape_html(VALUE str)
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))
@@ -112,28 +113,40 @@ optimized_unescape_html(VALUE str)
else if (MATCH("mp;")) {
c = '&';
}
- else continue;
+ else {
+ i = j;
+ continue;
+ }
break;
case 'q':
++i;
if (MATCH("uot;")) {
c = '"';
}
- else continue;
+ else {
+ i = j;
+ continue;
+ }
break;
case 'g':
++i;
if (MATCH("t;")) {
c = '>';
}
- else continue;
+ else {
+ i = j;
+ continue;
+ }
break;
case 'l':
++i;
if (MATCH("t;")) {
c = '<';
}
- else continue;
+ else {
+ i = j;
+ continue;
+ }
break;
case '#':
if (len - ++i >= 2 && ISDIGIT(cstr[i])) {
@@ -142,9 +155,15 @@ optimized_unescape_html(VALUE str)
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;
+ else {
+ i = j;
+ continue;
+ }
i += clen;
- if (overflow || cc >= charlimit || cstr[i] != ';') continue;
+ if (overflow || cc >= charlimit || cstr[i] != ';') {
+ i = j;
+ continue;
+ }
if (!dest) {
dest = rb_str_buf_new(len);
}
@@ -200,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;
@@ -220,7 +239,7 @@ optimized_escape(VALUE str)
rb_str_cat(dest, cstr + beg, i - beg);
beg = i + 1;
- if (c == ' ') {
+ if (plus_escape && c == ' ') {
rb_str_cat_cstr(dest, "+");
}
else {
@@ -242,7 +261,7 @@ optimized_escape(VALUE 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;
@@ -265,7 +284,7 @@ optimized_unescape(VALUE str, VALUE encoding)
| char_to_number(cstr[i+2]));
clen = 2;
}
- else if (c == '+') {
+ else if (unescape_plus && c == '+') {
buf[0] = ' ';
}
else {
@@ -348,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
@@ -357,7 +376,7 @@ 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);
@@ -376,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
@@ -388,7 +407,50 @@ cgiesc_unescape(int argc, VALUE *argv, VALUE self)
if (rb_enc_str_asciicompat_p(str)) {
VALUE enc = accept_charset(argc-1, argv+1, self);
- return optimized_unescape(str, enc);
+ 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);
@@ -409,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