* libs/http: removed protocol.filter, added mimetypes to protocol.mime
[project/luci.git] / libs / httpd / luasrc / httpd / handler / file.lua
index 8028263..4cbfa41 100644 (file)
@@ -30,6 +30,7 @@ function Simple.__init__(self, docroot, dirlist)
        luci.httpd.module.Handler.__init__(self)
        self.docroot = docroot
        self.dirlist = dirlist and true or false
+       self.proto   = luci.http.protocol
        self.mime    = luci.http.protocol.mime
        self.date    = luci.http.protocol.date
        self.cond    = luci.http.protocol.conditionals
@@ -43,7 +44,7 @@ function Simple.getfile(self, uri)
 end
 
 function Simple.handle_get(self, request, sourcein, sinkerr)
-       local file, stat = self:getfile(request.env.PATH_INFO)
+       local file, stat = self:getfile( self.proto.urldecode( request.env.PATH_INFO ) )
 
        if stat then
                if stat.type == "regular" then
@@ -62,16 +63,22 @@ function Simple.handle_get(self, request, sourcein, sinkerr)
                                        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))
+                                                       local f, err = io.open(file)
+
+                                                       if f 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(f)
+                                                       else
+                                                               return self:failure( 403, err:gsub("^.+: ", "") )
+                                                       end
                                                else
                                                        return Response( code, hdrs or { } )
                                                end
@@ -88,6 +95,7 @@ function Simple.handle_get(self, request, sourcein, sinkerr)
                elseif stat.type == "directory" then
 
                        local ruri = request.request_uri:gsub("/$","")
+                       local duri = self.proto.urldecode( ruri )
                        local root = self.docroot:gsub("/$","")
 
                        -- check for index files
@@ -99,7 +107,7 @@ function Simple.handle_get(self, request, sourcein, sinkerr)
                        -- 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
+                                       root .. "/" .. duri .. "/" .. candidate
                                )
 
                                if istat ~= nil and istat.type == "regular" then
@@ -111,36 +119,53 @@ function Simple.handle_get(self, request, sourcein, sinkerr)
 
 
                        local html = string.format(
-                               '<?xml version="1.0" encoding="UTF-8"?>\n' ..
+                               '<?xml version="1.0" encoding="ISO-8859-15"?>\n' ..
                                '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" '  ..
                                        '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n' ..
                                '<html xmlns="http://www.w3.org/1999/xhtml" '                ..
                                        'xml:lang="en" lang="en">\n'                             ..
                                '<head>\n'                                                   ..
-                               '<title>Index of %s/</title>\n'                               ..
-                               '</head><body><h1>Index of %s/</h1><hr /><ul>',
-                                       ruri, ruri
+                               '<title>Index of %s/</title>\n'                              ..
+                               '<style type="text/css"><!--\n'                              ..
+                                       'body { background-color:#FFFFFF; color:#000000 } '      ..
+                                       'li { border-bottom:1px dotted #CCCCCC; padding:3px } '  ..
+                                       'small { font-size:60%%; color:#999999 } '               ..
+                                       'p { margin:0 }'                                         ..
+                               '\n--></style></head><body><h1>Index of %s/</h1><hr /><ul>',
+                                       duri, duri
                        )
 
-                       for i, e in luci.util.vspairs( luci.fs.dir( file ) ) do
+                       local entries = luci.fs.dir( file )
 
-                               if e ~= '.' then
+                       for i, e in luci.util.spairs(
+                               entries, function(a,b)
+                                       if entries[a] == '..' then
+                                               return true
+                                       elseif entries[b] == '..' then
+                                               return false
+                                       else
+                                               return ( entries[a] < entries[b] )
+                                       end
+                               end
+                       ) do
+                               if e ~= '.' and ( e == '..' or e:sub(1,1) ~= '.' ) then
                                        local estat = luci.fs.stat( file .. "/" .. e )
 
                                        if estat.type == "directory" then
                                                html = html .. string.format(
-                                                       '<li><p><a href="%s/%s/">%s/</a> '                         ..
-                                                       '<small>(directory)</small><br />'                              ..
+                                                       '<li><p><a href="%s/%s/">%s/</a> '               ..
+                                                       '<small>(directory)</small><br />'               ..
                                                        '<small>Changed: %s</small></li>',
-                                                               ruri, e, e,
+                                                               ruri, self.proto.urlencode( e ), e,
                                                                self.date.to_http( estat.mtime )
                                                )
                                        else
                                                html = html .. string.format(
-                                                       '<li><p><a href="%s/%s">%s</a> '                         ..
-                                                       '<small>(%s)</small><br />'                              ..
+                                                       '<li><p><a href="%s/%s">%s</a> '                 ..
+                                                       '<small>(%s)</small><br />'                      ..
                                                        '<small>Size: %i Bytes | Changed: %s</small></li>',
-                                                               ruri, e, e, self.mime.to_mime( e ),
+                                                               ruri, self.proto.urlencode( e ), e,
+                                                               self.mime.to_mime( e ),
                                                                estat.size, self.date.to_http( estat.mtime )
                                                )
                                        end
@@ -152,7 +177,7 @@ function Simple.handle_get(self, request, sourcein, sinkerr)
                        return Response(
                                200, {
                                        ["Date"]         = self.date.to_http( os.time() );
-                                       ["Content-Type"] = "text/html";
+                                       ["Content-Type"] = "text/html; charset=ISO-8859-15";
                                }
                        ), ltn12.source.string(html)
                else