1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20%%
21-module(httpd_esi).
22
23-export([parse_headers/1, handle_headers/1]).
24
25-include_lib("inets/src/inets_app/inets_internal.hrl").
26
27
28%%%=========================================================================
29%%%  Internal application API
30%%%=========================================================================
31
32%%--------------------------------------------------------------------------
33%% parse_headers(Data) -> {Headers, Body}
34%%
35%% Data = string() | io_list()
36%% Headers = string()
37%% Body = io_list()
38%%
39%% Description: Parses <Data> and divides it to a header part and a
40%% body part. Note that it is presumed that <Data> starts with a
41%% string including "\r\n\r\n" if there is any header information
42%% present. The returned headers will not contain the HTTP header body
43%% delimiter \r\n. (All header, header delimiters are kept.)
44%% Ex: ["Content-Type : text/html\r\n Connection : closing \r\n\r\n" |
45%% io_list()] -->  {"Content-Type : text/html\r\n Connection : closing \r\n",
46%% io_list()}
47%%--------------------------------------------------------------------------
48parse_headers(Data) ->
49    parse_headers(Data, []).
50
51%%--------------------------------------------------------------------------
52%% handle_headers(Headers) -> {ok, HTTPHeaders, StatusCode} |
53%%                            {proceed, AbsPath}
54%%	Headers = string()
55%%	HTTPHeaders = [{HeaderField, HeaderValue}]
56%%      HeaderField = string()
57%%      HeaderValue = string()
58%%      StatusCode = integer()
59%%
60%% Description: Transforms the plain HTTP header string data received
61%% from the ESI program into a list of header values and an
62%% appropriate HTTP status code. Note if a location header is present
63%% the return value will be {proceed, AbsPath}
64%%--------------------------------------------------------------------------
65handle_headers("") ->
66    {ok, [], 200};
67handle_headers(Headers) ->
68    NewHeaders = string:tokens(Headers, ?CRLF),
69    handle_headers(NewHeaders, [], 200, true).
70
71%%%========================================================================
72%%% Internal functions
73%%%========================================================================
74parse_headers([], Acc) ->
75    {[], lists:reverse(Acc)};
76parse_headers([?CR, ?LF, ?CR, ?LF], Acc) ->
77    {lists:reverse(Acc) ++ [?CR, ?LF], []};
78parse_headers([?CR, ?LF, ?CR, ?LF | Rest], Acc) ->
79    {lists:reverse(Acc) ++ [?CR, ?LF], Rest};
80parse_headers([Char | Rest], Acc) ->
81    parse_headers(Rest, [Char | Acc]).
82
83handle_headers([], NewHeaders, StatusCode, _) ->
84    {ok, NewHeaders, StatusCode};
85
86handle_headers([Header | Headers], NewHeaders, StatusCode, NoESIStatus) ->
87    {FieldName, FieldValue} = httpd_response:split_header(Header, []),
88    case FieldName of
89	"location" when NoESIStatus == true ->
90            handle_headers(Headers,
91                           [{FieldName, FieldValue} | NewHeaders],
92                           302, NoESIStatus);
93
94	"status" ->
95	    NewStatusCode =
96		case httpd_util:split(FieldValue," ",2) of
97		    {ok,[Code,_]} ->
98			list_to_integer(Code);
99		    _ ->
100			200
101		end,
102	    handle_headers(Headers, NewHeaders, NewStatusCode, false);
103	_ ->
104	    handle_headers(Headers,
105                           [{FieldName, FieldValue}| NewHeaders], StatusCode,
106                           NoESIStatus)
107    end.
108