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 30b5cea06d
commit 6392808d31
2 changed files with 38 additions and 15 deletions

View file

@ -2,5 +2,6 @@
loose_unicode = false,
escape_forward_slash = 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([single_quotes|Rest], Opts) ->
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(_, _) ->
{error, badarg}.
valid_flags() ->
[
loose_unicode,
escape_forward_slash,
explicit_end,
single_quotes,
no_jsonp_escapes
].
extract_opts(Opts) ->
extract_parser_opts(Opts, []).
extract_parser_opts([], Acc) -> 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)
; false -> extract_parser_opts(Rest, Acc)
end;
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)
; false -> extract_parser_opts(Rest, Acc)
end.
@ -103,6 +115,10 @@ json_escape(<<C/utf8, Rest/binary>>, Opts, Acc) when C >= 0, C < $\s ->
%% date format
json_escape(<<$/, Rest/binary>>, Opts=#opts{escape_forward_slash=true}, Acc) ->
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
json_escape(<<C/utf8, Rest/binary>>, Opts, Acc)
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_() ->
[
{"json string escaping",
?_assert(json_escape(
<<"\"\\\b\f\n\r\t">>, #opts{}
) =:= <<"\\\"\\\\\\b\\f\\n\\r\\t">>
?_assertEqual(
json_escape(<<"\"\\\b\f\n\r\t">>, #opts{}),
<<"\\\"\\\\\\b\\f\\n\\r\\t">>
)
},
{"json string hex escape",
?_assert(json_escape(
<<1, 2, 3, 11, 26, 30, 31>>, #opts{}
) =:= <<"\\u0001\\u0002\\u0003\\u000b\\u001a\\u001e\\u001f">>
?_assertEqual(
json_escape(<<1, 2, 3, 11, 26, 30, 31>>, #opts{}),
<<"\\u0001\\u0002\\u0003\\u000b\\u001a\\u001e\\u001f">>
)
},
{"jsonp protection",
?_assert(json_escape(
<<226, 128, 168, 226, 128, 169>>, #opts{}
) =:= <<"\\u2028\\u2029">>
?_assertEqual(
json_escape(<<226, 128, 168, 226, 128, 169>>, #opts{}),
<<"\\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",
?_assert(json_escape(<<"/Date(1303502009425)/">>,
#opts{escape_forward_slash=true}
) =:= <<"\\/Date(1303502009425)\\/">>
?_assertEqual(
json_escape(<<"/Date(1303502009425)/">>, #opts{escape_forward_slash=true}),
<<"\\/Date(1303502009425)\\/">>
)
}
].