diff options
Diffstat (limited to 'examples/rest_pastebin/src/toppage_handler.erl')
-rw-r--r-- | examples/rest_pastebin/src/toppage_handler.erl | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/examples/rest_pastebin/src/toppage_handler.erl b/examples/rest_pastebin/src/toppage_handler.erl new file mode 100644 index 0000000..758e11d --- /dev/null +++ b/examples/rest_pastebin/src/toppage_handler.erl @@ -0,0 +1,132 @@ +%% Feel free to use, reuse and abuse the code in this file. + +%% @doc Pastebin handler. +-module(toppage_handler). + +%% REST Callbacks +-export([init/3]). +-export([allowed_methods/2]). +-export([content_types_provided/2]). +-export([content_types_accepted/2]). +-export([resource_exists/2]). +-export([post_is_create/2]). +-export([create_path/2]). + +%% Callback Callbacks +-export([create_paste/2]). +-export([paste_html/2]). +-export([paste_text/2]). + +init(_Transport, _Req, []) -> + % For the random number generator: + {X, Y, Z} = now(), + random:seed(X, Y, Z), + {upgrade, protocol, cowboy_rest}. + +allowed_methods(Req, State) -> + {[<<"GET">>, <<"POST">>], Req, State}. + +content_types_provided(Req, State) -> + {[ + {{<<"text">>, <<"plain">>, []}, paste_text}, + {{<<"text">>, <<"html">>, []}, paste_html} + ], Req, State}. + +content_types_accepted(Req, State) -> + {[{{<<"application">>, <<"x-www-form-urlencoded">>, []}, create_paste}], + Req, State}. + +resource_exists(Req, _State) -> + case cowboy_req:binding(paste_id, Req) of + {undefined, Req2} -> + {true, Req2, index}; + {PasteID, Req2} -> + case valid_path(PasteID) and file_exists(PasteID) of + true -> {true, Req2, PasteID}; + false -> {false, Req2, PasteID} + end + end. + +post_is_create(Req, State) -> + {true, Req, State}. + +create_path(Req, State) -> + {<<$/, (new_paste_id())/binary>>, Req, State}. + +create_paste(Req, State) -> + {<<$/, PasteID/binary>>, Req2} = cowboy_req:meta(put_path, Req), + {ok, [{<<"paste">>, Paste}], Req3} = cowboy_req:body_qs(Req2), + ok = file:write_file(full_path(PasteID), Paste), + {true, Req3, State}. + +paste_html(Req, index) -> + {read_file("index.html"), Req, index}; +paste_html(Req, Paste) -> + {Style, Req2} = cowboy_req:qs_val(<<"lang">>, Req, plain), + {format_html(Paste, Style), Req2, Paste}. + +paste_text(Req, index) -> + {read_file("index.txt"), Req, index}; +paste_text(Req, Paste) -> + {Style, Req2} = cowboy_req:qs_val(<<"lang">>, Req, plain), + {format_text(Paste, Style), Req2, Paste}. + +% Private + +read_file(Name) -> + {ok, Binary} = file:read_file(full_path(Name)), + Binary. + +full_path(Name) -> + {ok, Cwd} = file:get_cwd(), + filename:join([Cwd, "priv", Name]). + +file_exists(Name) -> + case file:read_file_info(full_path(Name)) of + {ok, _Info} -> true; + {error, _Reason} -> false + end. + +valid_path(<<>>) -> true; +valid_path(<<$., _T/binary>>) -> false; +valid_path(<<_Char, T/binary>>) -> valid_path(T). + +new_paste_id() -> + Initial = random:uniform(62) - 1, + new_paste_id(<<Initial>>, 7). +new_paste_id(Bin, 0) -> + Chars = <<"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890">>, + << <<(binary_part(Chars, B, 1))/binary>> || <<B>> <= Bin >>; +new_paste_id(Bin, Rem) -> + Next = random:uniform(62) - 1, + new_paste_id(<<Bin/binary, Next>>, Rem - 1). + +format_html(Paste, plain) -> + Text = escape_html_chars(read_file(Paste)), + <<"<!DOCTYPE html><html>", + "<head><title>paste</title></head>", + "<body><pre><code>", Text/binary, "</code></pre></body></html>\n">>; +format_html(Paste, Lang) -> + highlight(full_path(Paste), Lang, "html"). + +format_text(Paste, plain) -> + read_file(Paste); +format_text(Paste, Lang) -> + highlight(full_path(Paste), Lang, "ansi"). + +highlight(Path, Lang, Type) -> + Path1 = binary_to_list(Path), + Lang1 = binary_to_list(Lang), + os:cmd(["highlight --syntax=", Lang1, + " --doc-title=paste ", + " --out-format=", Type, + " --include-style ", Path1]). + +% Escape some HTML characters that might make a fuss +escape_html_chars(Bin) -> + << <<(escape_html_char(B))/binary>> || <<B>> <= Bin >>. + +escape_html_char($<) -> <<"<">>; +escape_html_char($>) -> <<">">>; +escape_html_char($&) -> <<"&">>; +escape_html_char(C) -> <<C>>. |