add 'no_jsonp_escapes' flag/option to not escape u+2028 and u+2029

This commit is contained in:
alisdair sullivan 2012-03-15 23:06:19 -07:00
parent 8dafdb32b3
commit aef1f71690
2 changed files with 38 additions and 15 deletions

View file

@ -2,5 +2,6 @@
loose_unicode = false, loose_unicode = false,
escape_forward_slash = false, escape_forward_slash = false,
explicit_end = false, explicit_end = false,
single_quotes = false single_quotes = false,
no_jsonp_escapes = false
}). }).

View file

@ -45,21 +45,33 @@ parse_opts([explicit_end|Rest], Opts) ->
parse_opts(Rest, Opts#opts{explicit_end=true}); parse_opts(Rest, Opts#opts{explicit_end=true});
parse_opts([single_quotes|Rest], Opts) -> parse_opts([single_quotes|Rest], Opts) ->
parse_opts(Rest, Opts#opts{single_quotes=true}); parse_opts(Rest, Opts#opts{single_quotes=true});
parse_opts([no_jsonp_escapes|Rest], Opts) ->
parse_opts(Rest, Opts#opts{no_jsonp_escapes=true});
parse_opts(_, _) -> parse_opts(_, _) ->
{error, badarg}. {error, badarg}.
valid_flags() ->
[
loose_unicode,
escape_forward_slash,
explicit_end,
single_quotes,
no_jsonp_escapes
].
extract_opts(Opts) -> extract_opts(Opts) ->
extract_parser_opts(Opts, []). extract_parser_opts(Opts, []).
extract_parser_opts([], Acc) -> Acc; extract_parser_opts([], Acc) -> Acc;
extract_parser_opts([{K,V}|Rest], Acc) -> extract_parser_opts([{K,V}|Rest], Acc) ->
case lists:member(K, [loose_unicode, escape_forward_slash, explicit_end, single_quotes]) of case lists:member(K, valid_flags()) of
true -> extract_parser_opts(Rest, [{K,V}] ++ Acc) true -> extract_parser_opts(Rest, [{K,V}] ++ Acc)
; false -> extract_parser_opts(Rest, Acc) ; false -> extract_parser_opts(Rest, Acc)
end; end;
extract_parser_opts([K|Rest], Acc) -> extract_parser_opts([K|Rest], Acc) ->
case lists:member(K, [loose_unicode, escape_forward_slash, explicit_end, single_quotes]) of case lists:member(K, valid_flags()) of
true -> extract_parser_opts(Rest, [K] ++ Acc) true -> extract_parser_opts(Rest, [K] ++ Acc)
; false -> extract_parser_opts(Rest, Acc) ; false -> extract_parser_opts(Rest, Acc)
end. end.
@ -103,6 +115,10 @@ json_escape(<<C/utf8, Rest/binary>>, Opts, Acc) when C >= 0, C < $\s ->
%% date format %% date format
json_escape(<<$/, Rest/binary>>, Opts=#opts{escape_forward_slash=true}, Acc) -> json_escape(<<$/, Rest/binary>>, Opts=#opts{escape_forward_slash=true}, Acc) ->
json_escape(Rest, Opts, <<Acc/binary, $\\, $/>>); json_escape(Rest, Opts, <<Acc/binary, $\\, $/>>);
%% skip escaping u+2028 and u+2029
json_escape(<<C/utf8, Rest/binary>>, Opts=#opts{no_jsonp_escapes=true}, Acc)
when C == 16#2028; C == 16#2029 ->
json_escape(Rest, Opts, <<Acc/binary, C/utf8>>);
%% escape u+2028 and u+2029 to avoid problems with jsonp %% escape u+2028 and u+2029 to avoid problems with jsonp
json_escape(<<C/utf8, Rest/binary>>, Opts, Acc) json_escape(<<C/utf8, Rest/binary>>, Opts, Acc)
when C == 16#2028; C == 16#2029 -> when C == 16#2028; C == 16#2029 ->
@ -143,27 +159,33 @@ to_hex(X) -> X + 48. %% ascii "1" is [49], "2" is [50], etc...
binary_escape_test_() -> binary_escape_test_() ->
[ [
{"json string escaping", {"json string escaping",
?_assert(json_escape( ?_assertEqual(
<<"\"\\\b\f\n\r\t">>, #opts{} json_escape(<<"\"\\\b\f\n\r\t">>, #opts{}),
) =:= <<"\\\"\\\\\\b\\f\\n\\r\\t">> <<"\\\"\\\\\\b\\f\\n\\r\\t">>
) )
}, },
{"json string hex escape", {"json string hex escape",
?_assert(json_escape( ?_assertEqual(
<<1, 2, 3, 11, 26, 30, 31>>, #opts{} json_escape(<<1, 2, 3, 11, 26, 30, 31>>, #opts{}),
) =:= <<"\\u0001\\u0002\\u0003\\u000b\\u001a\\u001e\\u001f">> <<"\\u0001\\u0002\\u0003\\u000b\\u001a\\u001e\\u001f">>
) )
}, },
{"jsonp protection", {"jsonp protection",
?_assert(json_escape( ?_assertEqual(
<<226, 128, 168, 226, 128, 169>>, #opts{} json_escape(<<226, 128, 168, 226, 128, 169>>, #opts{}),
) =:= <<"\\u2028\\u2029">> <<"\\u2028\\u2029">>
)
},
{"no jsonp escapes",
?_assertEqual(
json_escape(<<226, 128, 168, 226, 128, 169>>, #opts{no_jsonp_escapes=true}),
<<226, 128, 168, 226, 128, 169>>
) )
}, },
{"microsoft i hate your date format", {"microsoft i hate your date format",
?_assert(json_escape(<<"/Date(1303502009425)/">>, ?_assertEqual(
#opts{escape_forward_slash=true} json_escape(<<"/Date(1303502009425)/">>, #opts{escape_forward_slash=true}),
) =:= <<"\\/Date(1303502009425)\\/">> <<"\\/Date(1303502009425)\\/">>
) )
} }
]. ].