From b524e79f5508cfa47e692d9e978ac38bd2e7d993 Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 25 Jun 2013 11:26:44 +0200 Subject: [PATCH] Normalize HTTP path (thanks to Justin Kirby) --- src/ejabberd_http.erl | 16 ++++++++++++---- src/mod_http_fileserver.erl | 3 ++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 697aac116..814a563f7 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -366,7 +366,7 @@ process_request(#state{request_method = Method, {'EXIT', _} -> make_bad_request(State); {NPath, Query} -> - LPath = [path_decode(NPE) || NPE <- str:tokens(NPath, <<"/">>)], + LPath = normalize_path([NPE || NPE <- str:tokens(path_decode(NPath), <<"/">>)]), LQuery = case (catch parse_urlencoded(Query)) of {'EXIT', _Reason} -> []; @@ -435,7 +435,7 @@ process_request(#state{request_method = Method, {'EXIT', _} -> make_bad_request(State); {NPath, _Query} -> - LPath = [path_decode(NPE) || NPE <- str:tokens(NPath, <<"/">>)], + LPath = normalize_path([NPE || NPE <- str:tokens(path_decode(NPath), <<"/">>)]), LQuery = case (catch parse_urlencoded(Data)) of {'EXIT', _Reason} -> []; @@ -820,5 +820,13 @@ old_integer_to_hex(I) when I >= 16 -> N = trunc(I / 16), old_integer_to_hex(N) ++ old_integer_to_hex(I rem 16). -%% strip_spaces(String, left) -> -%% drop_spaces(String); +normalize_path(Path) -> + normalize_path(Path, []). + +normalize_path([], Norm) -> lists:reverse(Norm); +normalize_path([".."|Path], Norm) -> + normalize_path(Path, Norm); +normalize_path([_Parent, ".."|Path], Norm) -> + normalize_path(Path, Norm); +normalize_path([Part | Path], Norm) -> + normalize_path(Path, [Part|Norm]). diff --git a/src/mod_http_fileserver.erl b/src/mod_http_fileserver.erl index f16256d4f..fcfa12b59 100644 --- a/src/mod_http_fileserver.erl +++ b/src/mod_http_fileserver.erl @@ -311,7 +311,7 @@ process(LocalPath, Request) -> add_to_log(FileSize, Code, Request), {Code, Headers, Contents} catch - exit:{noproc, _} -> + exit:{noproc, _} -> ?ERROR_MSG("Received an HTTP request with Host ~p, but couldn't find the related " "ejabberd virtual host", [Request#request.host]), ejabberd_web:error(not_found) @@ -321,6 +321,7 @@ serve(LocalPath, DocRoot, DirectoryIndices, CustomHeaders, DefaultContentType, C FileName = filename:join(filename:split(DocRoot) ++ LocalPath), case file:read_file_info(FileName) of {error, enoent} -> ?HTTP_ERR_FILE_NOT_FOUND; + {error, enotdir} -> ?HTTP_ERR_FILE_NOT_FOUND; {error, eacces} -> ?HTTP_ERR_FORBIDDEN; {ok, #file_info{type = directory}} -> serve_index(FileName, DirectoryIndices,