%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 1997-2009. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. %% %% %CopyrightEnd% %% %% -module(mod_alias). -export([do/1, real_name/3, real_script_name/3, default_index/2, load/2, store/2, path/3]). -include("httpd.hrl"). -define(VMODULE,"ALIAS"). %% do do(Info) -> case proplists:get_value(status, Info#mod.data) of %% A status code has been generated! {_StatusCode, _PhraseArgs, _Reason} -> {proceed,Info#mod.data}; %% No status code has been generated! undefined -> case proplists:get_value(response, Info#mod.data) of %% No response has been generated! undefined -> do_alias(Info); %% A response has been generated or sent! _Response -> {proceed, Info#mod.data} end end. do_alias(Info) -> {ShortPath, Path, AfterPath} = real_name(Info#mod.config_db, Info#mod.request_uri, httpd_util:multi_lookup(Info#mod.config_db,alias)), %% Relocate if a trailing slash is missing else proceed! LastChar = lists:last(ShortPath), case file:read_file_info(ShortPath) of {ok, FileInfo} when FileInfo#file_info.type == directory, LastChar /= $/ -> ServerName = httpd_util:lookup(Info#mod.config_db, server_name), Port = port_string(httpd_util:lookup(Info#mod.config_db,port, 80)), URL = "http://" ++ ServerName ++ Port ++ Info#mod.request_uri ++ "/", ReasonPhrase = httpd_util:reason_phrase(301), Message = httpd_util:message(301, URL, Info#mod.config_db), {proceed, [{response, {301, ["Location: ", URL, "\r\n" "Content-Type: text/html\r\n", "\r\n", "\n\n",ReasonPhrase, "\n\n" "\n

",ReasonPhrase, "

\n", Message, "\n\n\n"]}}| [{real_name, {Path, AfterPath}} | Info#mod.data]]}; _NoFile -> {proceed,[{real_name, {Path, AfterPath}} | Info#mod.data]} end. port_string(80) -> ""; port_string(Port) -> ":"++integer_to_list(Port). %% real_name real_name(ConfigDB, RequestURI, []) -> DocumentRoot = httpd_util:lookup(ConfigDB, document_root, ""), RealName = DocumentRoot ++ RequestURI, {ShortPath, _AfterPath} = httpd_util:split_path(RealName), {Path, AfterPath} = httpd_util:split_path(default_index(ConfigDB, RealName)), {ShortPath, Path, AfterPath}; real_name(ConfigDB, RequestURI, [{FakeName,RealName}|Rest]) -> case inets_regexp:match(RequestURI, "^" ++ FakeName) of {match, _, _} -> {ok, ActualName, _} = inets_regexp:sub(RequestURI, "^" ++ FakeName, RealName), {ShortPath, _AfterPath} = httpd_util:split_path(ActualName), {Path, AfterPath} = httpd_util:split_path(default_index(ConfigDB, ActualName)), {ShortPath, Path, AfterPath}; nomatch -> real_name(ConfigDB,RequestURI,Rest) end. %% real_script_name real_script_name(_ConfigDB, _RequestURI, []) -> not_a_script; real_script_name(ConfigDB, RequestURI, [{FakeName,RealName} | Rest]) -> case inets_regexp:match(RequestURI,"^"++FakeName) of {match,_,_} -> {ok,ActualName,_}=inets_regexp:sub(RequestURI,"^"++FakeName,RealName), httpd_util:split_script_path(default_index(ConfigDB,ActualName)); nomatch -> real_script_name(ConfigDB,RequestURI,Rest) end. %% default_index default_index(ConfigDB, Path) -> case file:read_file_info(Path) of {ok, FileInfo} when FileInfo#file_info.type == directory -> DirectoryIndex = httpd_util:lookup(ConfigDB, directory_index, []), append_index(Path, DirectoryIndex); _ -> Path end. append_index(RealName, []) -> RealName; append_index(RealName, [Index | Rest]) -> case file:read_file_info(filename:join(RealName, Index)) of {error, _Reason} -> append_index(RealName, Rest); _ -> filename:join(RealName, Index) end. %% path path(Data, ConfigDB, RequestURI) -> case proplists:get_value(real_name, Data) of undefined -> DocumentRoot = httpd_util:lookup(ConfigDB, document_root, ""), {Path, _AfterPath} = httpd_util:split_path(DocumentRoot++RequestURI), Path; {Path, _AfterPath} -> Path end. %% %% Configuration %% %% load load("DirectoryIndex " ++ DirectoryIndex, []) -> {ok, DirectoryIndexes} = inets_regexp:split(DirectoryIndex," "), {ok,[], {directory_index, DirectoryIndexes}}; load("Alias " ++ Alias,[]) -> case inets_regexp:split(Alias," ") of {ok, [FakeName, RealName]} -> {ok,[],{alias,{FakeName,RealName}}}; {ok, _} -> {error,?NICE(httpd_conf:clean(Alias)++" is an invalid Alias")} end; load("ScriptAlias " ++ ScriptAlias, []) -> case inets_regexp:split(ScriptAlias, " ") of {ok, [FakeName, RealName]} -> %% Make sure the path always has a trailing slash.. RealName1 = filename:join(filename:split(RealName)), {ok, [], {script_alias, {FakeName, RealName1++"/"}}}; {ok, _} -> {error, ?NICE(httpd_conf:clean(ScriptAlias)++ " is an invalid ScriptAlias")} end. store({directory_index, Value} = Conf, _) when is_list(Value) -> case is_directory_index_list(Value) of true -> {ok, Conf}; false -> {error, {wrong_type, {directory_index, Value}}} end; store({directory_index, Value}, _) -> {error, {wrong_type, {directory_index, Value}}}; store({alias, {Fake, Real}} = Conf, _) when is_list(Fake), is_list(Real) -> {ok, Conf}; store({alias, Value}, _) -> {error, {wrong_type, {alias, Value}}}; store({script_alias, {Fake, Real}} = Conf, _) when is_list(Fake), is_list(Real) -> {ok, Conf}; store({script_alias, Value}, _) -> {error, {wrong_type, {script_alias, Value}}}. is_directory_index_list([]) -> true; is_directory_index_list([Head | Tail]) when is_list(Head) -> is_directory_index_list(Tail); is_directory_index_list(_) -> false.