X-Git-Url: http://nitlanguage.org diff --git a/lib/nitcorn/file_server.nit b/lib/nitcorn/file_server.nit index 3dadab9..d46d2a4 100644 --- a/lib/nitcorn/file_server.nit +++ b/lib/nitcorn/file_server.nit @@ -42,14 +42,28 @@ end class FileServer super Action - # Root of `self` file system + # Root folder of `self` file system var root: String + init + do + var root = self.root + + # Simplify the root path as each file requested will also be simplified + root = root.simplify_path + + # Make sure the root ends with '/', this makes a difference in the security + # check on each file access. + root = root + "/" + + self.root = root + end + # Error page template for a given `code` - fun error_page(code: Int): Streamable do return new ErrorTemplate(code) + fun error_page(code: Int): Writable do return new ErrorTemplate(code) # Header of each directory page - var header: nullable Streamable = null is writable + var header: nullable Writable = null is writable redef fun answer(request, turi) do @@ -58,17 +72,24 @@ class FileServer var local_file = root.join_path(turi.strip_start_slashes) local_file = local_file.simplify_path - # HACK - if turi == "/" then local_file = root - # Is it reachable? - if local_file.has_prefix(root) then + # + # This make sure that the requested file is within the root folder. + if (local_file + "/").has_prefix(root) then # Does it exists? if local_file.file_exists then - response = new HttpResponse(200) - if local_file.file_stat.is_dir then - # Show index.html instead of the directory listing + # If we target a directory without an ending `/`, + # redirect to the directory ending with `/`. + if not request.uri.is_empty and + request.uri.chars.last != '/' then + response = new HttpResponse(303) + response.header["Location"] = request.uri + "/" + return response + end + + # Show index file instead of the directory listing + # only if `index.html` or `index.htm` is available var index_file = local_file.join_path("index.html") if index_file.file_exists then local_file = index_file @@ -78,20 +99,22 @@ class FileServer end end + response = new HttpResponse(200) if local_file.file_stat.is_dir then # Show the directory listing var title = turi var files = local_file.files var links = new Array[String] - if local_file.length > 1 then - # The extra / is a hack - var path = "/" + (turi + "/..").simplify_path - links.add ".." + if turi.length > 1 then + var path = (request.uri + "/..").simplify_path + links.add ".." end for file in files do - var path = (turi + "/" + file).simplify_path - links.add "{file}" + var local_path = local_file.join_path(file).simplify_path + var web_path = file.simplify_path + if local_path.file_stat.is_dir then web_path = web_path + "/" + links.add "{file}" end var header = self.header @@ -122,7 +145,7 @@ class FileServer response.header["Content-Type"] = media_types["html"].as(not null) else # It's a single file - var file = new IFStream.open(local_file) + var file = new FileReader.open(local_file) response.body = file.read_all var ext = local_file.file_extension