1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2005-2021. 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 22-module(httpd_script_env). 23 24-export([create_env/3]). 25 26-include("httpd.hrl"). 27-include("httpd_internal.hrl"). 28 29%%%========================================================================= 30%%% Internal application API 31%%%========================================================================= 32%%-------------------------------------------------------------------------- 33%% create_env(ScriptType, ModData, ScriptElements) -> [{EnvVariable, Value}] 34%% 35%% ScriptType = cgi | esi 36%% ModData = #mod{} 37%% ScriptElements = [{Element, Value}] 38%% Element = path_info | query_string | entity_body 39%% Value = term() 40%% EnvVariable = string() - cgi | atom() - esi 41%% 42%% Description: Creates a list of cgi/esi environment variables and 43%% there values. 44%%-------------------------------------------------------------------------- 45create_env(ScriptType, ModData, ScriptElements) -> 46 create_basic_elements(ScriptType, ModData) 47 ++ create_http_header_elements(ScriptType, ModData#mod.parsed_header) 48 ++ create_script_elements(ScriptType, ModData, ScriptElements) 49 ++ create_mod_interaction_elements(ScriptType, ModData). 50 51%%%======================================================================== 52%%% Internal functions 53%%%======================================================================== 54 55which_server(#mod{config_db = ConfigDb}) -> 56 httpd_util:lookup(ConfigDb, server, ?SERVER_SOFTWARE). 57 58which_port(#mod{config_db = ConfigDb}) -> 59 httpd_util:lookup(ConfigDb, port, 80). 60 61which_peername(#mod{init_data = #init_data{peername = {_, RemoteAddr}}}) -> 62 RemoteAddr. 63 64which_peercert(#mod{socket_type = {Type, _}, socket = Socket}) when Type == essl; 65 Type == ssl -> 66 case ssl:peercert(Socket) of 67 {ok, Cert} -> 68 Cert; 69 {error, no_peercert} -> 70 no_peercert; 71 _ -> 72 undefined 73 end; 74which_peercert(_) -> %% Not an ssl connection 75 undefined. 76 77 78which_resolve(#mod{init_data = #init_data{resolve = Resolve}}) -> 79 Resolve. 80 81which_name(#mod{config_db = ConfigDB}) -> 82 httpd_util:lookup(ConfigDB, server_name). 83 84which_method(#mod{method = Method}) -> 85 Method. 86 87which_request_uri(#mod{request_uri = RUri}) -> 88 RUri. 89 90create_basic_elements(esi, ModData) -> 91 [{server_software, which_server(ModData)}, 92 {server_name, which_name(ModData)}, 93 {host_name, which_resolve(ModData)}, 94 {gateway_interface, ?GATEWAY_INTERFACE}, 95 {server_protocol, ?SERVER_PROTOCOL}, 96 {server_port, which_port(ModData)}, 97 {request_method, which_method(ModData)}, 98 {remote_addr, which_peername(ModData)}, 99 {peer_cert, which_peercert(ModData)}, 100 {script_name, which_request_uri(ModData)}]; 101 102create_basic_elements(cgi, ModData) -> 103 [{"SERVER_SOFTWARE", which_server(ModData)}, 104 {"SERVER_NAME", which_name(ModData)}, 105 {"HOST_NAME", which_resolve(ModData)}, 106 {"GATEWAY_INTERFACE", ?GATEWAY_INTERFACE}, 107 {"SERVER_PROTOCOL", ?SERVER_PROTOCOL}, 108 {"SERVER_PORT", integer_to_list(which_port(ModData))}, 109 {"REQUEST_METHOD", which_method(ModData)}, 110 {"REMOTE_ADDR", which_peername(ModData)}, 111 {"SCRIPT_NAME", which_request_uri(ModData)}]. 112 113create_http_header_elements(ScriptType, Headers) -> 114 create_http_header_elements(ScriptType, Headers, [], []). 115 116create_http_header_elements(esi, [], Acc, OtherAcc) -> 117 [{http_other, OtherAcc} | Acc]; 118create_http_header_elements(_, [], Acc, _OtherAcc) -> 119 Acc; 120create_http_header_elements(ScriptType, [{Name, [Value | _] = Values } | 121 Headers], Acc, OtherAcc) 122 when is_list(Value) -> 123 try http_env_element(ScriptType, Name, multi_value(Values)) of 124 Element -> 125 create_http_header_elements(ScriptType, Headers, [Element | Acc], 126 OtherAcc) 127 catch 128 _:_ -> 129 create_http_header_elements(ScriptType, Headers, Acc, 130 [{Name, Values} | OtherAcc]) 131 end; 132create_http_header_elements(ScriptType, [{Name, Value} | Headers], Acc, OtherAcc) 133 when is_list(Value) -> 134 try http_env_element(ScriptType, Name, Value) of 135 Element -> 136 create_http_header_elements(ScriptType, Headers, [Element | Acc], 137 OtherAcc) 138 catch 139 _:_ -> 140 create_http_header_elements(ScriptType, Headers, Acc, 141 [{Name, Value} | OtherAcc]) 142 end. 143 144http_env_element(cgi, VarName0, Value) -> 145 VarName = re:replace(VarName0,"-","_", [{return,list}, global]), 146 {"HTTP_"++ http_util:to_upper(VarName), Value}; 147http_env_element(esi, VarName0, Value) -> 148 list_to_existing_atom(VarName0), 149 VarName = re:replace(VarName0,"-","_", [{return,list}, global]), 150 HeaderName = http_util:to_lower(VarName), 151 {list_to_atom("http_"++ HeaderName), Value}. 152 153multi_value([]) -> 154 []; 155multi_value([Value]) -> 156 Value; 157multi_value([Value | Rest]) -> 158 Value ++ ", " ++ multi_value(Rest). 159 160create_script_elements(ScriptType, ModData, ScriptElements) -> 161 lists:flatmap(fun({Element, Data}) -> 162 create_script_elements(ScriptType, 163 Element, 164 Data, ModData) 165 end, ScriptElements). 166 167create_script_elements(esi, query_string, QueryString, _) -> 168 [{query_string, QueryString}]; 169create_script_elements(cgi, query_string, QueryString, _) -> 170 [{"QUERY_STRING", QueryString}]; 171create_script_elements(esi, path_info, PathInfo, ModData) -> 172 Aliases = httpd_util:multi_lookup(ModData#mod.config_db, alias), 173 {_,PathTranslated,_} = 174 mod_alias:real_name(ModData#mod.config_db, PathInfo, 175 Aliases), 176 [{path_info, PathInfo}, 177 {path_translated, PathTranslated}]; 178create_script_elements(cgi, path_info, PathInfo, ModData) -> 179 Aliases = httpd_util:multi_lookup(ModData#mod.config_db, alias), 180 {_,PathTranslated,_} = 181 mod_alias:real_name(ModData#mod.config_db, PathInfo, 182 Aliases), 183 [{"PATH_INFO", PathInfo}, 184 {"PATH_TRANSLATED", PathTranslated}]; 185create_script_elements(esi, entity_body, Body, _) -> 186 [{content_length, integer_to_list(erlang:iolist_size(Body))}]; 187create_script_elements(cgi, entity_body, Body, _) -> 188 [{"CONTENT_LENGTH", integer_to_list(erlang:iolist_size(Body))}]; 189create_script_elements(_, _, _, _) -> 190 []. 191 192create_mod_interaction_elements(_, ModData)-> 193 case proplists:get_value(remote_user, ModData#mod.data) of 194 undefined -> 195 []; 196 RemoteUser -> 197 [{remote_user, RemoteUser}] 198 end. 199