/modules/mod_base/filters/filter_force_escape.erl

https://code.google.com/p/zotonic/ · Erlang · 95 lines · 60 code · 10 blank · 25 comment · 0 complexity · 77950b5ec2a0e7dc0cd9394f461e8ab5 MD5 · raw file

  1. %% @author Roberto Saccon <rsaccon@gmail.com> [http://rsaccon.com]
  2. %% @author Evan Miller <emmiller@gmail.com>
  3. %% @copyright 2008 Roberto Saccon, Evan Miller
  4. %% @doc 'force_escape' filter, escape all html unsafe characters
  5. %%% The MIT License
  6. %%%
  7. %%% Copyright (c) 2007 Roberto Saccon, Evan Miller
  8. %%%
  9. %%% Permission is hereby granted, free of charge, to any person obtaining a copy
  10. %%% of this software and associated documentation files (the "Software"), to deal
  11. %%% in the Software without restriction, including without limitation the rights
  12. %%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. %%% copies of the Software, and to permit persons to whom the Software is
  14. %%% furnished to do so, subject to the following conditions:
  15. %%%
  16. %%% The above copyright notice and this permission notice shall be included in
  17. %%% all copies or substantial portions of the Software.
  18. %%%
  19. %%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. %%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. %%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. %%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. %%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. %%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. %%% THE SOFTWARE.
  26. -module(filter_force_escape).
  27. -export([force_escape/2]).
  28. -author('rsaccon@gmail.com').
  29. -author('emmiller@gmail.com').
  30. force_escape(undefined, _Context) ->
  31. <<>>;
  32. force_escape(Input, _Context) when is_atom(Input) ->
  33. escape1(atom_to_list(Input), []);
  34. force_escape(Input, _Context) when is_list(Input) ->
  35. escape1(Input, []);
  36. force_escape(Input, _Context) when is_binary(Input) ->
  37. escape1(Input, 0);
  38. force_escape(Input, _Context) when is_integer(Input) ->
  39. integer_to_list(Input);
  40. force_escape({{Y,M,D}, {_H,_I,_S}} = Input, Context) when is_integer(Y) andalso is_integer(M) andalso is_integer(D) ->
  41. filter_date:date(Input, "Y-m-d H:i:s", Context);
  42. force_escape({Y,M,D} = Input, Context) when is_integer(Y) andalso is_integer(M) andalso is_integer(D) ->
  43. filter_date:date(Input, "Y-m-d", Context);
  44. force_escape(true, _Context) ->
  45. filter_yesno:yesno(true, _Context);
  46. force_escape(false, _Context) ->
  47. filter_yesno:yesno(false, _Context).
  48. escape1(Binary, Index) when is_binary(Binary) ->
  49. case Binary of
  50. <<Pre:Index/binary, $<, Post/binary>> ->
  51. process_binary_match(Pre, <<"&lt;">>, size(Post), escape1(Post, 0));
  52. <<Pre:Index/binary, $>, Post/binary>> ->
  53. process_binary_match(Pre, <<"&gt;">>, size(Post), escape1(Post, 0));
  54. <<Pre:Index/binary, $&, Post/binary>> ->
  55. process_binary_match(Pre, <<"&amp;">>, size(Post), escape1(Post, 0));
  56. <<Pre:Index/binary, 34, Post/binary>> ->
  57. process_binary_match(Pre, <<"&quot;">>, size(Post), escape1(Post, 0));
  58. <<Pre:Index/binary, 39, Post/binary>> ->
  59. process_binary_match(Pre, <<"&#039;">>, size(Post), escape1(Post, 0));
  60. <<_:Index/binary, _, _/binary>> ->
  61. escape1(Binary, Index + 1);
  62. Binary ->
  63. Binary
  64. end;
  65. escape1([], Acc) ->
  66. lists:reverse(Acc);
  67. escape1("<" ++ Rest, Acc) ->
  68. escape1(Rest, lists:reverse("&lt;", Acc));
  69. escape1(">" ++ Rest, Acc) ->
  70. escape1(Rest, lists:reverse("&gt;", Acc));
  71. escape1("&" ++ Rest, Acc) ->
  72. escape1(Rest, lists:reverse("&amp;", Acc));
  73. escape1("\"" ++ Rest, Acc) ->
  74. escape1(Rest, lists:reverse("&quot;", Acc));
  75. escape1("'" ++ Rest, Acc) ->
  76. escape1(Rest, lists:reverse("&#039;", Acc));
  77. escape1([C | Rest], Acc) ->
  78. escape1(Rest, [C | Acc]).
  79. process_binary_match(Pre, Insertion, SizePost, Post) ->
  80. case {size(Pre), SizePost} of
  81. {0, 0} -> Insertion;
  82. {0, _} -> [Insertion, Post];
  83. {_, 0} -> [Pre, Insertion];
  84. _ -> [Pre, Insertion, Post]
  85. end.