%%%============================================================================= %%% @copyright (C) 1999-2014, Erlang Solutions Ltd %%% @author Diana Corbacho %%% @doc %%% @end %%%============================================================================= -module(http_eqc_encoding). -copyright("2014, Erlang Solutions Ltd."). -export([add_content_length/2, add_transfer_encoding/2, body/1]). -export([build_valid_response/4, build_cookie/1, build_expires_date/1, expires_datetime/1]). %%============================================================================== %% API %%============================================================================== add_content_length(Headers, <<>>) -> Headers; add_content_length(Headers, Body) -> ContentLength = list_to_binary(integer_to_list(byte_size(Body))), [{<<"Content-Length">>, ContentLength} | Headers]. body({_, <<$1, _, _>>, _}) -> <<>>; body({_, <<$2,$0,$4>>, _}) -> <<>>; body({_, <<$3,$0,$4>>, _}) -> <<>>; body(_) -> http_eqc_gen:body(). add_transfer_encoding(Headers, <<>>) -> Headers; add_transfer_encoding(Headers, Encoding) -> lists:keystore(<<"Transfer-Encoding">>, 1, remove_transfer_encoding(Headers), {<<"Transfer-Encoding">>, Encoding}). build_valid_response({HttpVersion, StatusCode, Reason}, Headers, Cookies, Body) -> SL = [HttpVersion, sp(), StatusCode, sp(), Reason, crlf()], HS = [[Name, colon(), Value, crlf()] || {Name, Value} <- Headers], CS = [[Name, colon(), build_cookie(Cookie), crlf()] || {Name, Cookie} <- Cookies], [SL, HS ++ CS, crlf(), build_body(Body)]. build_cookie({{K, V}, Avs}) -> CookiePair = [K, eq(), V], CookieAvs = build_cookie_avs(Avs), CookiePair ++ CookieAvs. build_expires_date({rfc1123date, {Wkday, Date1, Time}}) -> Date = build_date(Date1), BTime = build_time(Time), [Wkday, $,, $\s, Date, $\s, BTime, $\s, "GMT"]; build_expires_date({rfc850date, {Weekday, Date2, Time}}) -> Date = build_date(Date2), BTime = build_time(Time), [Weekday, $,, $\s, Date, $\s, BTime, $\s, "GMT"]; build_expires_date({asctimedate, {Wkday, Date3, Time, Year}}) -> BTime = build_time(Time), Date = build_date(Date3), [Wkday, $\s, Date, $\s, BTime, $\s, Year]. expires_datetime({rfc1123date, {_, {date1, {Day, Month, Year}}, {H, M, S}}}) -> {{st_to_int(Year), month(Month), st_to_int(Day)}, {st_to_int(H), st_to_int(M), st_to_int(S)}}; expires_datetime({rfc850date, {_, {date2, {Day, Month, Year}}, {H, M, S}}}) -> {{to_year(Year), month(Month), st_to_int(Day)}, {st_to_int(H), st_to_int(M), st_to_int(S)}}; expires_datetime({asctimedate, {_, {date3, {Day, Month}}, {H, M, S}, Year}}) -> {{st_to_int(Year), month(Month), st_to_int(Day)}, {st_to_int(H), st_to_int(M), st_to_int(S)}}; expires_datetime(undefined) -> undefined. %%============================================================================== %% Internal functions %%============================================================================== remove_transfer_encoding(Headers) -> lists:filter(fun({H, _}) -> H =/= <<"Transfer-Encoding">> end, Headers). build_body(Body) when is_binary(Body) -> Body; build_body(List) -> list_to_binary( io_lib:format("~s0\r\n\r\n", [[io_lib:format("~s\r\n~s\r\n", [erlang:integer_to_list(Nat, 16), Body]) || {Nat, Body} <- List]])). build_cookie_avs(Avs) -> build_cookie_avs(Avs, []). build_cookie_avs([{<<"Expires">> = K, Date} | Rest], Acc) -> V = build_expires_date(Date), build_cookie_avs(Rest, [[semicolon(), sp(), K, eq(), V] | Acc]); build_cookie_avs([{K, V} | Rest], Acc) -> build_cookie_avs(Rest, [[semicolon(), sp(), K, eq(), V] | Acc]); build_cookie_avs([K | Rest], Acc) -> build_cookie_avs(Rest, [[semicolon(), sp(), K] | Acc]); build_cookie_avs([], Acc) -> Acc. build_date({date1, {Day, Month, Year}}) -> [Day, $\s, Month, $\s, Year]; build_date({date2, {Day, Month, Year}}) -> [Day, $-, Month, $-, Year]; build_date({date3, {Day, Month}}) -> [Month, $\s, Day]. build_time({H, M, S}) -> [H, $:, M, $:, S]. colon() -> <<$:>>. semicolon() -> <<$;>>. sp() -> <<$\s>>. crlf() -> <<$\r,$\n>>. eq() -> <<$=>>. months() -> [{"Jan", 1}, {"Feb", 2}, {"Mar", 3}, {"Apr", 4}, {"May", 5}, {"Jun", 6}, {"Jul", 7}, {"Aug", 8}, {"Sep", 9}, {"Oct", 10}, {"Nov", 11}, {"Dec", 12}]. st_to_int(L) -> list_to_integer(L). month(Month) -> proplists:get_value(Month, months()). to_year(Year) when length(Year) == 4 -> st_to_int(Year); to_year(Year) -> IntY = list_to_integer(Year), {Y, _, _} = date(), case (2000 + IntY - Y) > 50 of true -> 1900 + IntY; false -> 2000 + IntY end.