--[[ HTTP server implementation for LuCI - file handler (c) 2008 Steven Barth (c) 2008 Freifunk Leipzig / Jo-Philipp Wich Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 $Id$ ]]-- module("luci.httpd.handler.file", package.seeall) require("luci.httpd.module") require("luci.http.protocol.date") require("luci.http.protocol.mime") require("luci.http.protocol.conditionals") require("luci.fs") require("ltn12") Simple = luci.util.class(luci.httpd.module.Handler) Response = luci.httpd.module.Response function Simple.__init__(self, docroot, dirlist) luci.httpd.module.Handler.__init__(self) self.docroot = docroot self.dirlist = dirlist and true or false self.mime = luci.http.protocol.mime self.date = luci.http.protocol.date self.cond = luci.http.protocol.conditionals end function Simple.getfile(self, uri) local file = self.docroot .. uri:gsub("%.%./+", "") local stat = luci.fs.stat(file) return file, stat end function Simple.handle_get(self, request, sourcein, sinkerr) local file, stat = self:getfile(request.env.PATH_INFO) if stat then if stat.type == "regular" then -- Generate Entity Tag local etag = self.cond.mk_etag( stat ) -- Check conditionals local ok, code, hdrs ok, code, hdrs = self.cond.if_modified_since( request, stat ) if ok then ok, code, hdrs = self.cond.if_match( request, stat ) if ok then ok, code, hdrs = self.cond.if_unmodified_since( request, stat ) if ok then ok, code, hdrs = self.cond.if_none_match( request, stat ) if ok then -- Send Response return Response( 200, { ["Date"] = self.date.to_http( os.time() ); ["Last-Modified"] = self.date.to_http( stat.mtime ); ["Content-Type"] = self.mime.to_mime( file ); ["Content-Length"] = stat.size; ["ETag"] = etag; } ), ltn12.source.file(io.open(file)) else return Response( code, hdrs or { } ) end else return Response( code, hdrs or { } ) end else return Response( code, hdrs or { } ) end else return Response( code, hdrs or { } ) end elseif stat.type == "directory" then local ruri = request.request_uri:gsub("/$","") local root = self.docroot:gsub("/$","") -- check for index files local index_candidates = { "index.html", "index.htm", "default.html", "default.htm", "index.txt", "default.txt" } -- try to find an index file and redirect to it for i, candidate in ipairs( index_candidates ) do local istat = luci.fs.stat( root .. "/" .. ruri .. "/" .. candidate ) if istat ~= nil and istat.type == "regular" then return Response( 301, { ["Location"] = ruri .. "/" .. candidate } ), ltn12.source.empty() end end local html = string.format( '\n' .. '\n' .. '\n' .. '\n' .. 'Index of %s/\n' .. '

Index of %s/



' return Response( 200, { ["Date"] = self.date.to_http( os.time() ); ["Content-Type"] = "text/html"; } ), ltn12.source.string(html) else return self:failure(403, "Unable to transmit " .. stat.type .. " " .. file) end else return self:failure(404, "No such file: " .. file) end end function Simple.handle_head(self, ...) local response, sourceout = self:handle_get(...) return response end