toppage_handler.erl 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. %% Feel free to use, reuse and abuse the code in this file.
  2. %% @doc Pastebin handler.
  3. -module(toppage_handler).
  4. %% REST Callbacks
  5. -export([init/3]).
  6. -export([allowed_methods/2]).
  7. -export([content_types_provided/2]).
  8. -export([content_types_accepted/2]).
  9. -export([resource_exists/2]).
  10. -export([post_is_create/2]).
  11. -export([create_path/2]).
  12. %% Callback Callbacks
  13. -export([create_paste/2]).
  14. -export([paste_html/2]).
  15. -export([paste_text/2]).
  16. init(_Transport, _Req, []) ->
  17. % For the random number generator:
  18. {X, Y, Z} = now(),
  19. random:seed(X, Y, Z),
  20. {upgrade, protocol, cowboy_rest}.
  21. allowed_methods(Req, State) ->
  22. {[<<"GET">>, <<"POST">>], Req, State}.
  23. content_types_provided(Req, State) ->
  24. {[
  25. {{<<"text">>, <<"plain">>, []}, paste_text},
  26. {{<<"text">>, <<"html">>, []}, paste_html}
  27. ], Req, State}.
  28. content_types_accepted(Req, State) ->
  29. {[{{<<"application">>, <<"x-www-form-urlencoded">>, []}, create_paste}],
  30. Req, State}.
  31. resource_exists(Req, _State) ->
  32. case cowboy_req:binding(paste_id, Req) of
  33. {undefined, Req2} ->
  34. {true, Req2, index};
  35. {PasteID, Req2} ->
  36. case valid_path(PasteID) and file_exists(PasteID) of
  37. true -> {true, Req2, PasteID};
  38. false -> {false, Req2, PasteID}
  39. end
  40. end.
  41. post_is_create(Req, State) ->
  42. {true, Req, State}.
  43. create_path(Req, State) ->
  44. {<<$/, (new_paste_id())/binary>>, Req, State}.
  45. create_paste(Req, State) ->
  46. {<<$/, PasteID/binary>>, Req2} = cowboy_req:meta(put_path, Req),
  47. {ok, [{<<"paste">>, Paste}], Req3} = cowboy_req:body_qs(Req2),
  48. ok = file:write_file(full_path(PasteID), Paste),
  49. {true, Req3, State}.
  50. paste_html(Req, index) ->
  51. {read_file("index.html"), Req, index};
  52. paste_html(Req, Paste) ->
  53. {Style, Req2} = cowboy_req:qs_val(<<"lang">>, Req, plain),
  54. {format_html(Paste, Style), Req2, Paste}.
  55. paste_text(Req, index) ->
  56. {read_file("index.txt"), Req, index};
  57. paste_text(Req, Paste) ->
  58. {Style, Req2} = cowboy_req:qs_val(<<"lang">>, Req, plain),
  59. {format_text(Paste, Style), Req2, Paste}.
  60. % Private
  61. read_file(Name) ->
  62. {ok, Binary} = file:read_file(full_path(Name)),
  63. Binary.
  64. full_path(Name) ->
  65. {ok, Cwd} = file:get_cwd(),
  66. filename:join([Cwd, "priv", Name]).
  67. file_exists(Name) ->
  68. case file:read_file_info(full_path(Name)) of
  69. {ok, _Info} -> true;
  70. {error, _Reason} -> false
  71. end.
  72. valid_path(<<>>) -> true;
  73. valid_path(<<$., _T/binary>>) -> false;
  74. valid_path(<<$/, _T/binary>>) -> false;
  75. valid_path(<<_Char, T/binary>>) -> valid_path(T).
  76. new_paste_id() ->
  77. Initial = random:uniform(62) - 1,
  78. new_paste_id(<<Initial>>, 7).
  79. new_paste_id(Bin, 0) ->
  80. Chars = <<"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890">>,
  81. << <<(binary_part(Chars, B, 1))/binary>> || <<B>> <= Bin >>;
  82. new_paste_id(Bin, Rem) ->
  83. Next = random:uniform(62) - 1,
  84. new_paste_id(<<Bin/binary, Next>>, Rem - 1).
  85. format_html(Paste, plain) ->
  86. Text = escape_html_chars(read_file(Paste)),
  87. <<"<!DOCTYPE html><html>",
  88. "<head><title>paste</title></head>",
  89. "<body><pre><code>", Text/binary, "</code></pre></body></html>\n">>;
  90. format_html(Paste, Lang) ->
  91. highlight(full_path(Paste), Lang, "html").
  92. format_text(Paste, plain) ->
  93. read_file(Paste);
  94. format_text(Paste, Lang) ->
  95. highlight(full_path(Paste), Lang, "ansi").
  96. highlight(Path, Lang, Type) ->
  97. Path1 = binary_to_list(Path),
  98. Lang1 = binary_to_list(Lang),
  99. os:cmd(["highlight --syntax=", Lang1,
  100. " --doc-title=paste ",
  101. " --out-format=", Type,
  102. " --include-style ", Path1]).
  103. % Escape some HTML characters that might make a fuss
  104. escape_html_chars(Bin) ->
  105. << <<(escape_html_char(B))/binary>> || <<B>> <= Bin >>.
  106. escape_html_char($<) -> <<"&lt;">>;
  107. escape_html_char($>) -> <<"&gt;">>;
  108. escape_html_char($&) -> <<"&amp;">>;
  109. escape_html_char(C) -> <<C>>.