/usr/share/lua/5.1/xavante/filehandler.lua is in xavante 2.3.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | -----------------------------------------------------------------------------
-- Xavante File handler
--
-- Authors: Javier Guerra and Andre Carregal
-- Copyright (c) 2004-2007 Kepler Project
--
-- $Id: filehandler.lua,v 1.26 2009/08/11 01:48:07 mascarenhas Exp $
----------------------------------------------------------------------------
local lfs = require "lfs"
local url = require "socket.url"
local mime = require "xavante.mime"
local enc = require "xavante.encoding"
local xavante = require "xavante"
local httpd = require "xavante.httpd"
xavante.mimetypes = xavante.mimetypes or {}
xavante.encodings = xavante.encodings or {}
-- gets the mimetype from the filename's extension
local function mimefrompath (path)
local _,_,exten = string.find (path, "%.([^.]*)$")
if exten then
return xavante.mimetypes [exten]
else
return nil
end
end
-- gets the encoding from the filename's extension
local function encodingfrompath (path)
local _,_,exten = string.find (path, "%.([^.]*)$")
if exten then
return xavante.encodings [exten]
else
return nil
end
end
-- on partial requests seeks the file to
-- the start of the requested range and returns
-- the number of bytes requested.
-- on full requests returns nil
local function getrange (req, f)
local range = req.headers["range"]
if not range then return nil end
local s,e, r_A, r_B = string.find (range, "(%d*)%s*-%s*(%d*)")
if s and e then
r_A = tonumber (r_A)
r_B = tonumber (r_B)
if r_A then
f:seek ("set", r_A)
if r_B then return r_B + 1 - r_A end
else
if r_B then f:seek ("end", - r_B) end
end
end
return nil
end
-- sends data from the open file f
-- to the response object res
-- sends only numbytes, or until the end of f
-- if numbytes is nil
local function sendfile (f, res, numbytes)
local block
local whole = not numbytes
local left = numbytes
local blocksize = 8192
if not whole then blocksize = math.min (blocksize, left) end
while whole or left > 0 do
block = f:read (blocksize)
if not block then return end
if not whole then
left = left - string.len (block)
blocksize = math.min (blocksize, left)
end
res:send_data (block)
end
end
local function in_base(path)
local l = 0
if path:sub(1, 1) ~= "/" then path = "/" .. path end
for dir in path:gmatch("/([^/]+)") do
if dir == ".." then
l = l - 1
elseif dir ~= "." then
l = l + 1
end
if l < 0 then return false end
end
return true
end
-- main handler
local function filehandler (req, res, baseDir)
if req.cmd_mth ~= "GET" and req.cmd_mth ~= "HEAD" then
return httpd.err_405 (req, res)
end
if not in_base(req.relpath) then
return httpd.err_403 (req, res)
end
local path = baseDir .."/".. req.relpath
res.headers ["Content-Type"] = mimefrompath (path)
res.headers ["Content-Encoding"] = encodingfrompath (path)
local attr = lfs.attributes (path)
if not attr then
return httpd.err_404 (req, res)
end
assert (type(attr) == "table")
if attr.mode == "directory" then
req.parsed_url.path = req.parsed_url.path .. "/"
res.statusline = "HTTP/1.1 301 Moved Permanently"
res.headers["Location"] = url.build (req.parsed_url)
res.content = "redirect"
return res
end
res.headers["Content-Length"] = attr.size
local f = io.open (path, "rb")
if not f then
return httpd.err_404 (req, res)
end
res.headers["last-modified"] = os.date ("!%a, %d %b %Y %H:%M:%S GMT",
attr.modification)
local lms = req.headers["if-modified-since"] or 0
local lm = res.headers["last-modified"] or 1
if lms == lm then
res.headers["Content-Length"] = 0
res.statusline = "HTTP/1.1 304 Not Modified"
res.content = ""
res.chunked = false
res:send_headers()
f:close()
return res
end
if req.cmd_mth == "GET" then
local range_len = getrange (req, f)
if range_len then
res.statusline = "HTTP/1.1 206 Partial Content"
res.headers["Content-Length"] = range_len
end
sendfile (f, res, range_len)
else
res.content = ""
res:send_headers ()
end
f:close ()
return res
end
return function (baseDir)
if type(baseDir) == "table" then baseDir = baseDir.baseDir end
return function (req, res)
return filehandler (req, res, baseDir)
end
end
|