]> granicus.if.org Git - ejabberd/commitdiff
Normalize HTTP path (thanks to Justin Kirby)
authorBadlop <badlop@process-one.net>
Tue, 25 Jun 2013 08:37:03 +0000 (10:37 +0200)
committerBadlop <badlop@process-one.net>
Tue, 25 Jun 2013 08:37:03 +0000 (10:37 +0200)
src/web/ejabberd_http.erl
src/web/mod_http_fileserver.erl

index 612a544bda35fbe729087258180927a4ef92e3d9..d5abc516cd99f52aea2865438f724eb3c8aca51d 100644 (file)
@@ -372,7 +372,7 @@ process_request(#state{request_method = Method,
        {'EXIT', _} ->
            make_bad_request(State);
        {NPath, Query} ->
-           LPath = [path_decode(NPE) || NPE <- string:tokens(NPath, "/")],
+           LPath = normalize_path([NPE || NPE <- string:tokens(path_decode(NPath), "/")]),
            LQuery = case (catch parse_urlencoded(Query)) of
                         {'EXIT', _Reason} ->
                             [];
@@ -449,7 +449,7 @@ process_request(#state{request_method = Method,
        {'EXIT', _} ->
             make_bad_request(State);
        {NPath, _Query} ->
-           LPath = [path_decode(NPE) || NPE <- string:tokens(NPath, "/")],
+           LPath = normalize_path([NPE || NPE <- string:tokens(path_decode(NPath), "/")]),
            LQuery = case (catch parse_urlencoded(Data)) of
                         {'EXIT', _Reason} ->
                             [];
@@ -1125,3 +1125,14 @@ drop_spaces(YS=[X|XS]) ->
        false ->
            YS
     end.
+
+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]).
index 71a6272083b14ec9a2de908d8247fd047f0fe299..292a460a5dcec7151cc93960ec48919ed764b218 100644 (file)
@@ -303,7 +303,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)
@@ -313,6 +313,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,