@@ -200,7 +200,7 @@ url_unreserved_char(unsigned char c)
200200}
201201
202202static VALUE
203- optimized_escape (VALUE str )
203+ optimized_escape (VALUE str , int plus_escape )
204204{
205205 long i , len , beg = 0 ;
206206 VALUE dest = 0 ;
@@ -220,7 +220,7 @@ optimized_escape(VALUE str)
220220 rb_str_cat (dest , cstr + beg , i - beg );
221221 beg = i + 1 ;
222222
223- if (c == ' ' ) {
223+ if (plus_escape && c == ' ' ) {
224224 rb_str_cat_cstr (dest , "+" );
225225 }
226226 else {
@@ -242,7 +242,7 @@ optimized_escape(VALUE str)
242242}
243243
244244static VALUE
245- optimized_unescape (VALUE str , VALUE encoding )
245+ optimized_unescape (VALUE str , VALUE encoding , int unescape_plus )
246246{
247247 long i , len , beg = 0 ;
248248 VALUE dest = 0 ;
@@ -265,7 +265,7 @@ optimized_unescape(VALUE str, VALUE encoding)
265265 | char_to_number (cstr [i + 2 ]));
266266 clen = 2 ;
267267 }
268- else if (c == '+' ) {
268+ else if (unescape_plus && c == '+' ) {
269269 buf [0 ] = ' ' ;
270270 }
271271 else {
@@ -348,19 +348,19 @@ cgiesc_unescape_html(VALUE self, VALUE str)
348348 * call-seq:
349349 * CGI.escape(string) -> string
350350 *
351- * Returns URL-escaped string.
351+ * Returns URL-escaped string (+application/x-www-form-urlencoded+) .
352352 *
353353 */
354354static VALUE
355- cgiesc_escape (VALUE self , VALUE str )
355+ cgiesc_encode_www_form_component (VALUE self , VALUE str )
356356{
357357 StringValue (str );
358358
359359 if (rb_enc_str_asciicompat_p (str )) {
360- return optimized_escape (str );
360+ return optimized_escape (str , 1 );
361361 }
362362 else {
363- return rb_call_super (1 , & str );
363+ return rb_call_super (1 , & str );
364364 }
365365}
366366
@@ -376,22 +376,65 @@ accept_charset(int argc, VALUE *argv, VALUE self)
376376 * call-seq:
377377 * CGI.unescape(string, encoding=@@accept_charset) -> string
378378 *
379- * Returns URL-unescaped string.
379+ * Returns URL-unescaped string (+application/x-www-form-urlencoded+).
380+ *
381+ */
382+ static VALUE
383+ cgiesc_decode_www_form_component (int argc , VALUE * argv , VALUE self )
384+ {
385+ VALUE str = (rb_check_arity (argc , 1 , 2 ), argv [0 ]);
386+
387+ StringValue (str );
388+
389+ if (rb_enc_str_asciicompat_p (str )) {
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.url_encode(string) -> string
401+ *
402+ * Returns URL-escaped string following RFC 3986.
403+ *
404+ */
405+ static VALUE
406+ cgiesc_url_encode (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.url_decode(string, encoding=@@accept_charset) -> string
421+ *
422+ * Returns URL-unescaped string following RFC 3986.
380423 *
381424 */
382425static VALUE
383- cgiesc_unescape (int argc , VALUE * argv , VALUE self )
426+ cgiesc_url_decode (int argc , VALUE * argv , VALUE self )
384427{
385428 VALUE str = (rb_check_arity (argc , 1 , 2 ), argv [0 ]);
386429
387430 StringValue (str );
388431
389432 if (rb_enc_str_asciicompat_p (str )) {
390- VALUE enc = accept_charset (argc - 1 , argv + 1 , self );
391- return optimized_unescape (str , enc );
433+ VALUE enc = accept_charset (argc - 1 , argv + 1 , self );
434+ return optimized_unescape (str , enc , 0 );
392435 }
393436 else {
394- return rb_call_super (argc , argv );
437+ return rb_call_super (argc , argv );
395438 }
396439}
397440
@@ -414,8 +457,12 @@ InitVM_escape(void)
414457 rb_mUtil = rb_define_module_under (rb_cCGI , "Util" );
415458 rb_define_method (rb_mEscape , "escapeHTML" , cgiesc_escape_html , 1 );
416459 rb_define_method (rb_mEscape , "unescapeHTML" , cgiesc_unescape_html , 1 );
417- rb_define_method (rb_mEscape , "escape" , cgiesc_escape , 1 );
418- rb_define_method (rb_mEscape , "unescape" , cgiesc_unescape , -1 );
460+ rb_define_method (rb_mEscape , "url_encode" , cgiesc_url_encode , 1 );
461+ rb_define_method (rb_mEscape , "url_decode" , cgiesc_url_decode , -1 );
462+ rb_define_method (rb_mEscape , "encode_www_form_component" , cgiesc_encode_www_form_component , 1 );
463+ rb_define_alias (rb_mEscape , "escape" , "encode_www_form_component" );
464+ rb_define_method (rb_mEscape , "decode_www_form_component" , cgiesc_decode_www_form_component , -1 );
465+ rb_define_alias (rb_mEscape , "unescape" , "decode_www_form_component" );
419466 rb_prepend_module (rb_mUtil , rb_mEscape );
420467 rb_extend_object (rb_cCGI , rb_mEscape );
421468}
0 commit comments